1    | /***************************************
2    |   $Header: /home/amb/cxref/RCS/warn-raw.c 1.28 2001/01/06 13:05:13 amb Exp $
3    | 
4    |   C Cross Referencing & Documentation tool. Version 1.5c.
5    | 
6    |   Writes the raw information and / or warnings out.
7    |   ******************/ /******************
8    |   Written by Andrew M. Bishop
9    | 
10   |   This file Copyright 1995,96,97,99,2001 Andrew M. Bishop
11   |   It may be distributed under the GNU Public License, version 2, or
12   |   any higher version.  See section COPYING of the GNU Public license
13   |   for conditions under which this file may be redistributed.
14   |   ***************************************/
15   | 
16   | #include <stdlib.h>
17   | #include <stdio.h>
18   | #include <string.h>
19   | 
20   | #include "datatype.h"
21   | #include "cxref.h"
22   | #include "memory.h"
23   | 
24   | static void WriteWarnRawFilePart(File file);
25   | static void WriteWarnRawInclude(Include inc);
26   | static void WriteWarnRawSubInclude(Include inc,int depth);
27   | static void WriteWarnRawDefine(Define def);
28   | static void WriteWarnRawTypedef(Typedef type);
29   | static void WriteWarnRawStructUnion(StructUnion su, int depth,StructUnion base);
30   | static void WriteWarnRawVariable(Variable var);
31   | static void WriteWarnRawFunction(Function func);
32   | 
33   | /*+ Output option. +*/
34   | extern int option_warn,option_raw,option_xref,option_index;
35   | 
36   | /*+ The name of the current file. +*/
37   | static char* filename=NULL;
38   | 
39   | /*++++++++++++++++++++++++++++++++++++++
40   |   Write the raw / warning output for a complete File structure and all components.
41   | 
42   |   File file The File structure to output.
43   |   ++++++++++++++++++++++++++++++++++++++*/
44   | 
45   | void WriteWarnRawFile(File file)
46   | {
47   |  Include   inc =file->includes;
48   |  Define    def =file->defines;
49   |  Typedef   type=file->typedefs;
50   |  Variable  var=file->variables;
51   |  Function  func=file->functions;
52   | 
53   |  filename=file->name;
54   | 
55   |  /*+ The file structure is broken into its components and they are each written out. +*/
56   | 
57   |  if(option_raw)
58   |     printf("----------------------------------------\n");
59   | 
60   |  WriteWarnRawFilePart(file);
61   | 
62   |  while(inc)
63   |    {
64   |     WriteWarnRawInclude(inc);
65   |     inc=inc->next;
66   |    }
67   | 
68   |  while(def)
69   |    {
70   |     WriteWarnRawDefine(def);
71   |     def=def->next;
72   |    }
73   | 
74   |  while(type)
75   |    {
76   |     WriteWarnRawTypedef(type);
77   |     type=type->next;
78   |    }
79   | 
80   |  while(var)
81   |    {
82   |     WriteWarnRawVariable(var);
83   |     var=var->next;
84   |    }
85   | 
86   |  while(func)
87   |    {
88   |     WriteWarnRawFunction(func);
89   |     func=func->next;
90   |    }
91   | 
92   |  if(option_raw)
93   |     printf("----------------------------------------\n\n");
94   | }
95   | 
96   | 
97   | /*++++++++++++++++++++++++++++++++++++++
98   |   Write a File structure out.
99   | 
100  |   File file The File structure to output.
101  |   ++++++++++++++++++++++++++++++++++++++*/
102  | 
103  | static void WriteWarnRawFilePart(File file)
104  | {
105  |  int i;
106  | 
107  |  if(option_raw)
108  |     printf("FILE : '%s'\n",file->name);
109  | 
110  |  if(file->comment && option_raw)
111  |     printf("<<<\n%s\n>>>\n",file->comment);
112  | 
113  |  if(option_warn&WARN_COMMENT && !file->comment)
114  |     printf("Warning %16s : File does not have a comment.\n",filename);
115  | 
116  |  if(option_xref&XREF_FILE)
117  |    {
118  |     if(option_raw)
119  |        for(i=0;i<file->inc_in->n;i++)
120  |           printf("Included in %s\n",file->inc_in->s[i]);
121  | 
122  |     if(option_warn&WARN_XREF)
123  |       {
124  |        int len=strlen(file->name)-2;
125  |        if(!file->inc_in->n && !strcmp(&file->name[len],".h"))
126  |           printf("Warning %16s : Header file %s is not included in any files.\n",filename,file->name);
127  |        if( file->inc_in->n && !strcmp(&file->name[len],".c"))
128  |           printf("Warning %16s : Source file %s is included in another file.\n",filename,file->name);
129  |       }
130  |    }
131  | 
132  |  if(option_xref&XREF_FUNC)
133  |     for(i=0;i<file->f_refs->n;i++)
134  |       {
135  |        if(option_raw)
136  |          {
137  |           if(file->f_refs->s2[i])
138  |              printf("References Function %s : %s\n",file->f_refs->s1[i],file->f_refs->s2[i]);
139  |           else
140  |              printf("References Function %s\n",file->f_refs->s1[i]);
141  |          }
142  |        if(option_warn&WARN_XREF && !file->f_refs->s2[i])
143  |           printf("Warning %16s : File references function %s() whose definition is unknown.\n",filename,file->f_refs->s1[i]);
144  |       }
145  | 
146  |  if(option_xref&XREF_VAR)
147  |     for(i=0;i<file->v_refs->n;i++)
148  |       {
149  |        if(option_raw)
150  |          {
151  |           if(file->v_refs->s2[i])
152  |              printf("References Variable %s : %s\n",file->v_refs->s1[i],file->v_refs->s2[i]);
153  |           else
154  |              printf("References Variable %s\n",file->v_refs->s1[i]);
155  |          }
156  |        if(option_warn&WARN_XREF && !file->v_refs->s2[i])
157  |           printf("Warning %16s : File references variable %s whose definition is unknown.\n",filename,file->v_refs->s1[i]);
158  |       }
159  | }
160  | 
161  | 
162  | /*++++++++++++++++++++++++++++++++++++++
163  |   Write an Include structure out.
164  | 
165  |   Include inc The Include structure to output.
166  |   ++++++++++++++++++++++++++++++++++++++*/
167  | 
168  | static void WriteWarnRawInclude(Include inc)
169  | {
170  |  if(option_raw)
171  |     printf("\nINCLUDES : '%s' [%s file]\n",inc->name,(inc->scope==GLOBAL?"System":"Local"));
172  | 
173  |  if(inc->comment && option_raw)
174  |     printf("<<<\n%s\n>>>\n",inc->comment);
175  |  if(option_warn&WARN_COMMENT && !inc->comment)
176  |     printf("Warning %16s : #Include %s does not have a comment.\n",filename,inc->name);
177  | 
178  |  if(option_raw && inc->includes)
179  |     WriteWarnRawSubInclude(inc->includes,1);
180  | }
181  | 
182  | 
183  | /*++++++++++++++++++++++++++++++++++++++
184  |   Write an Sub-Include structure out.
185  | 
186  |   Include inc The Include structure to output.
187  | 
188  |   int depth The depth of the include hierarchy.
189  |   ++++++++++++++++++++++++++++++++++++++*/
190  | 
191  | static void WriteWarnRawSubInclude(Include inc,int depth)
192  | {
193  |  int i;
194  | 
195  |  while(inc)
196  |    {
197  |     for(i=0;i<depth;i++) printf("   ");
198  |     printf("INCLUDES : '%s' [%s file]\n",inc->name,(inc->scope==GLOBAL?"System":"Local"));
199  | 
200  |     if(inc->includes)
201  |        WriteWarnRawSubInclude(inc->includes,depth+1);
202  | 
203  |     inc=inc->next;
204  |    }
205  | }
206  | 
207  | 
208  | /*++++++++++++++++++++++++++++++++++++++
209  |   Write a Define structure out.
210  | 
211  |   Define def The Define structure to output.
212  |   ++++++++++++++++++++++++++++++++++++++*/
213  | 
214  | static void WriteWarnRawDefine(Define def)
215  | {
216  |  int i;
217  | 
218  |  if(option_raw)
219  |    {
220  |     printf("\nDEFINES : '%s' ",def->name);
221  | 
222  |     if(def->value)
223  |        printf("= %s",def->value);
224  | 
225  |     if(def->args->n)
226  |       {
227  |        printf("(");
228  |        for(i=0;i<def->args->n;i++)
229  |           printf(i?",%s":"%s",def->args->s1[i]);
230  |        printf(")");
231  |       }
232  | 
233  |     printf("\n");
234  |    }
235  | 
236  |  if(def->comment && option_raw)
237  |     printf("<<<\n%s\n>>>\n",def->comment);
238  |  if(option_warn&WARN_COMMENT && !def->comment)
239  |     printf("Warning %16s : #Define %s does not have a comment.\n",filename,def->name);
240  | 
241  |  if(option_raw)
242  |     printf("Defined: %s:%d\n",filename,def->lineno);
243  | 
244  |  for(i=0;i<def->args->n;i++)
245  |    {
246  |     if(option_raw)
247  |       {
248  |        if(def->args->s2[i])
249  |           printf("Arguments: %s <<<%s>>>\n",def->args->s1[i],def->args->s2[i]);
250  |        else
251  |           printf("Arguments: %s\n",def->args->s1[i]);
252  |       }
253  |     if(option_warn&WARN_COMMENT && !def->args->s2[i])
254  |        printf("Warning %16s : #Define %s has an argument %s with no comment.\n",filename,def->name,def->args->s1[i]);
255  |    }
256  | }
257  | 
258  | 
259  | /*++++++++++++++++++++++++++++++++++++++
260  |   Write a Typedef structure out.
261  | 
262  |   Typedef type The Typedef structure to output.
263  |   ++++++++++++++++++++++++++++++++++++++*/
264  | 
265  | static void WriteWarnRawTypedef(Typedef type)
266  | {
267  |  if(option_raw)
268  |    {
269  |     if(type->type)
270  |        printf("\nTYPEDEF : '%s'\n",type->name);
271  |     else
272  |        printf("\nTYPE : '%s'\n",type->name);
273  |    }
274  | 
275  |  if(type->comment && option_raw)
276  |     printf("<<<\n%s\n>>>\n",type->comment);
277  |  if(option_warn&WARN_COMMENT && !type->comment)
278  |     printf("Warning %16s : Type %s does not have a comment.\n",filename,type->name);
279  | 
280  |  if(option_raw)
281  |     printf("Defined: %s:%d\n",filename,type->lineno);
282  | 
283  |  if(option_raw)
284  |     if(type->type)
285  |        printf("Type: %s\n",type->type);
286  | 
287  |  if(option_raw)
288  |     if(type->typexref)
289  |        printf("See: %s %s\n",type->typexref->type?"Typedef":"Type",type->typexref->name);
290  | 
291  |  if(type->sutype)
292  |     WriteWarnRawStructUnion(type->sutype,0,type->sutype);
293  | }
294  | 
295  | 
296  | /*++++++++++++++++++++++++++++++++++++++
297  |   Write a structure / union / enum out.
298  | 
299  |   StructUnion su The structure / union / enum to write.
300  | 
301  |   int depth The depth within the structure.
302  | 
303  |   StructUnion base The base struct union that this one is part of.
304  |   ++++++++++++++++++++++++++++++++++++++*/
305  | 
306  | static void WriteWarnRawStructUnion(StructUnion su, int depth,StructUnion base)
307  | {
308  |  int i;
309  |  char* splitsu=NULL;
310  | 
311  |  if(option_warn&WARN_COMMENT && depth && !su->comment)
312  |     printf("Struct/Union component %s in %s does not have a comment.\n",su->name,base->name);
313  | 
314  |  splitsu=strstr(su->name,"{...}");
315  |  if(splitsu) splitsu[-1]=0;
316  | 
317  |  if(option_raw)
318  |    {
319  |     for(i=0;i<depth;i++) printf("   ");
320  |     if(depth && su->comment && !su->comps)
321  |        printf("%s; <<<%s>>>\n",su->name,su->comment);
322  |     else if(!depth || su->comps)
323  |        printf("%s\n",su->name);
324  |     else
325  |        printf("%s;\n",su->name);
326  |    }
327  | 
328  |  if(!depth || su->comps)
329  |    {
330  |     if(option_raw)
331  |       {
332  |        for(i=0;i<depth;i++) printf("   ");
333  |        printf("  {\n");
334  |       }
335  |     for(i=0;i<su->n_comp;i++)
336  |        WriteWarnRawStructUnion(su->comps[i],depth+1,base);
337  |     if(option_raw)
338  |       {
339  |        for(i=0;i<depth;i++) printf("   ");
340  |        printf("  }\n");
341  |        if(splitsu)
342  |          {
343  |           for(i=0;i<depth;i++) printf("   ");
344  |           if(depth && su->comment)
345  |              printf("%s; <<<%s>>>\n",splitsu[5]?&splitsu[6]:"",su->comment);
346  |           else
347  |              printf("%s;\n",splitsu[5]?&splitsu[6]:"");
348  |          }
349  |       }
350  |    }
351  | 
352  |  if(splitsu) splitsu[-1]=' ';
353  | }
354  | 
355  | 
356  | /*++++++++++++++++++++++++++++++++++++++
357  |   Write a Variable structure out.
358  | 
359  |   Variable var The Variable structure to output.
360  |   ++++++++++++++++++++++++++++++++++++++*/
361  | 
362  | static void WriteWarnRawVariable(Variable var)
363  | {
364  |  int i;
365  | 
366  |  if(option_raw)
367  |    {
368  |     int done=0;
369  | 
370  |     printf("\nVARIABLE : %s [",var->name);
371  |     if(var->scope&LOCAL)    done=printf("Local");
372  |     if(var->scope&GLOBAL)   done=printf("Global");
373  |     if(var->scope&EXTERNAL) done=printf("%sExternal",done?" and ":"");
374  |     if(var->scope&EXTERN_H) done=printf("%sExternal from header file",done?" and ":"");
375  |     if(var->scope&EXTERN_F)      printf("%sExternal within function",done?" and ":"");
376  |     printf("]\n");
377  | 
378  |     if(var->comment)
379  |        printf("<<<\n%s\n>>>\n",var->comment);
380  |    }
381  | 
382  |  if(option_warn&WARN_COMMENT && !var->comment && (var->scope&(GLOBAL|LOCAL|EXTERNAL|EXTERN_F) || option_raw))
383  |     printf("Warning %16s : Variable %s does not have a comment.\n",filename,var->name);
384  | 
385  |  if(option_raw)
386  |     printf("Defined: %s:%d\n",var->incfrom?var->incfrom:filename,var->lineno);
387  | 
388  |  if(option_raw)
389  |     printf("Type: %s\n",var->type);
390  | 
391  |  if(option_raw && var->incfrom)
392  |     printf("Included from: %s\n",var->incfrom);
393  | 
394  |  if(option_xref&XREF_VAR)
395  |    {
396  |     if(option_raw)
397  |       {
398  |        if(var->scope&(EXTERNAL|EXTERN_F) && var->defined)
399  |           printf("Declared global in '%s'\n",var->defined);
400  | 
401  |        if(var->scope&(GLOBAL|LOCAL))
402  |          {
403  |           for(i=0;i<var->visible->n;i++)
404  |              if(var->visible->s1[i][0]=='$' && !var->visible->s1[i][1])
405  |                 printf("Visible in %s\n",var->visible->s2[i]);
406  |              else
407  |                 printf("Visible in %s : %s\n",var->visible->s1[i],var->visible->s2[i]);
408  | 
409  |           for(i=0;i<var->used->n;i++)
410  |              if(var->used->s1[i][0]=='$' && !var->used->s1[i][1])
411  |                 printf("Used in %s\n",var->used->s2[i]);
412  |              else
413  |                 printf("Used in %s : %s\n",var->used->s1[i],var->used->s2[i]);
414  |          }
415  |       }
416  | 
417  |     if(option_warn&WARN_XREF)
418  |       {
419  |        if(var->scope&(EXTERNAL|EXTERN_F) && !var->defined)
420  |           printf("Warning %16s : Variable %s has an unknown global definition.\n",filename,var->name);
421  | 
422  |        if(var->scope&(GLOBAL|LOCAL|EXTERNAL|EXTERN_F) && !var->used->n)
423  |           printf("Warning %16s : Variable %s is not used anywhere.\n",filename,var->name);
424  | 
425  |        if(var->scope&(GLOBAL|EXTERNAL|EXTERN_F) && var->used->n)
426  |          {
427  |           int is_used_elsewhere=0,is_used_here=0;
428  |           for(i=0;i<var->used->n;i++)
429  |              if(!strcmp(filename,var->used->s2[i]))
430  |                 is_used_here=1;
431  |              else
432  |                 is_used_elsewhere=1;
433  |           if(!is_used_elsewhere)
434  |              printf("Warning %16s : Variable %s is %s but only used in this file.\n",filename,var->name,var->scope&GLOBAL?"global":"extern");
435  |           if(!is_used_here)
436  |              printf("Warning %16s : Variable %s is %s but not used in this file.\n",filename,var->name,var->scope&GLOBAL?"global":"extern");
437  |          }
438  |       }
439  |    }
440  | }
441  | 
442  | 
443  | /*++++++++++++++++++++++++++++++++++++++
444  |   Write a Function structure out.
445  | 
446  |   Function func The Function structure to output.
447  |   ++++++++++++++++++++++++++++++++++++++*/
448  | 
449  | static void WriteWarnRawFunction(Function func)
450  | {
451  |  int i;
452  | 
453  |  if(option_raw)
454  |    {
455  |     int done=0;
456  | 
457  |     printf("\nFUNCTION : %s [",func->name);
458  |     if(func->scope&LOCAL)    done=printf("Local");
459  |     if(func->scope&GLOBAL)   done=printf("Global");
460  |     if(func->scope&EXTERNAL) done=printf("External");
461  |     if(func->scope&INLINED)       printf("%sInline",done?" and ":"");
462  |     printf("]\n");
463  | 
464  |     if(func->comment)
465  |        printf("<<<\n%s\n>>>\n",func->comment);
466  |    }
467  | 
468  |  if(option_warn&WARN_COMMENT && !func->comment)
469  |     printf("Warning %16s : Function %s() does not have a comment.\n",filename,func->name);
470  | 
471  |  if(option_raw)
472  |     printf("Defined: %s:%d\n",filename,func->lineno);
473  | 
474  |  if(option_xref&XREF_FUNC)
475  |    {
476  |     if(func->protofile && option_raw)
477  |        printf("Prototyped in %s\n",func->protofile);
478  |     if(option_warn&WARN_XREF && !func->protofile)
479  |        printf("Warning %16s : Function %s() is not prototyped.\n",filename,func->name);
480  |    }
481  | 
482  |  if(option_raw)
483  |    {
484  |     if(func->cret)
485  |        printf("Type: %s <<<%s>>>\n",func->type,func->cret);
486  |     else
487  |        printf("Type: %s\n",func->type);
488  |    }
489  |  if(option_warn&WARN_COMMENT && !func->cret && strncmp("void ",func->type,5))
490  |     printf("Warning %16s : Function %s() has a return value with no comment.\n",filename,func->name);
491  | 
492  |  for(i=0;i<func->args->n;i++)
493  |    {
494  |     if(option_raw)
495  |       {
496  |        if(func->args->s2[i])
497  |           printf("Arguments: %s <<<%s>>>\n",func->args->s1[i],func->args->s2[i]);
498  |        else
499  |           printf("Arguments: %s\n",func->args->s1[i]);
500  |       }
501  |     if(option_warn&WARN_COMMENT && !func->args->s2[i] && strcmp("void",func->args->s1[i]))
502  |        printf("Warning %16s : Function %s() has an argument %s with no comment.\n",filename,func->name,func->args->s1[i]);
503  |    }
504  | 
505  |  if(option_raw && func->incfrom)
506  |     printf("Included from: %s\n",func->incfrom);
507  | 
508  |  if(option_xref&XREF_FUNC)
509  |    {
510  |     for(i=0;i<func->calls->n;i++)
511  |       {
512  |        if(option_raw)
513  |          {
514  |           if(func->calls->s2[i])
515  |              printf("Calls %s : %s\n",func->calls->s1[i],func->calls->s2[i]);
516  |           else
517  |              printf("Calls %s\n",func->calls->s1[i]);
518  |          }
519  | #if 0 /* Too verbose */
520  |        if(option_warn&WARN_XREF && !func->calls->s2[i])
521  |           printf("Warning %16s : Function %s() calls function %s() whose definition is unknown.\n",filename,func->name,func->calls->s1[i]);
522  | #endif
523  |       }
524  | 
525  |     if(option_raw)
526  |        for(i=0;i<func->called->n;i++)
527  |           printf("Called from %s : %s\n",func->called->s1[i],func->called->s2[i]);
528  | 
529  |     if(option_raw)
530  |        for(i=0;i<func->used->n;i++)
531  |          {
532  |           if(func->used->s1[i][0]=='$' && !func->used->s1[i][1])
533  |              printf("Used in %s\n",func->used->s2[i]);
534  |           else
535  |              printf("Used in %s : %s\n",func->used->s1[i],func->used->s2[i]);
536  |          }
537  | 
538  |     for(i=0;i<func->f_refs->n;i++)
539  |       {
540  |        if(option_raw)
541  |          {
542  |           if(func->f_refs->s2[i])
543  |              printf("References Function %s : %s\n",func->f_refs->s1[i],func->f_refs->s2[i]);
544  |           else
545  |              printf("References Function %s\n",func->f_refs->s1[i]);
546  |          }
547  |        if(option_warn&WARN_XREF && !func->f_refs->s2[i])
548  |           printf("Warning %16s : Function %s() references function %s() whose definition is unknown.\n",filename,func->name,func->f_refs->s1[i]);
549  |       }
550  |    }
551  | 
552  |  if(option_xref&XREF_VAR)
553  |     for(i=0;i<func->v_refs->n;i++)
554  |       {
555  |        if(option_raw)
556  |          {
557  |           if(func->v_refs->s2[i])
558  |              printf("References Variable %s : %s\n",func->v_refs->s1[i],func->v_refs->s2[i]);
559  |           else
560  |              printf("References Variable %s\n",func->v_refs->s1[i]);
561  |          }
562  |        if(option_warn&WARN_XREF && !func->v_refs->s2[i])
563  |           printf("Warning %16s : Function %s() references variable %s whose definition is unknown.\n",filename,func->name,func->v_refs->s1[i]);
564  |       }
565  | 
566  | 
567  |  if(option_warn&WARN_XREF)
568  |    {
569  |     if(!func->used->n && !func->called->n)
570  |        printf("Warning %16s : Function %s() is not used anywhere.\n",filename,func->name);
571  | 
572  |     if(func->scope&GLOBAL && (func->called->n || func->used->n))
573  |       {
574  |        int is_used_elsewhere=0;
575  |        for(i=0;i<func->called->n;i++)
576  |           if(strcmp(func->called->s2[i],filename))
577  |             {is_used_elsewhere=1;break;}
578  |        for(i=0;i<func->used->n;i++)
579  |           if(strcmp(func->used->s2[i],filename))
580  |             {is_used_elsewhere=1;break;}
581  |        if(!is_used_elsewhere)
582  |           printf("Warning %16s : Function %s() is global but is only used in this file.\n",filename,func->name);
583  |       }
584  |    }
585  | }
586  | 
587  | 
588  | /*++++++++++++++++++++++++++++++++++++++
589  |   Write out a raw version of the appendix.
590  | 
591  |   StringList files The list of files to write.
592  | 
593  |   StringList2 funcs The list of functions to write.
594  | 
595  |   StringList2 vars The list of variables to write.
596  | 
597  |   StringList2 types The list of types to write.
598  |   ++++++++++++++++++++++++++++++++++++++*/
599  | 
600  | void WriteWarnRawAppendix(StringList files,StringList2 funcs,StringList2 vars,StringList2 types)
601  | {
602  |  int i;
603  | 
604  |  /* Write out the appendix of files. */
605  | 
606  |  if(option_index&INDEX_FILE)
607  |    {
608  |     if(files->n)
609  |       {
610  |        printf("\nAppendix - Files\n\n");
611  |        for(i=0;i<files->n;i++)
612  |           printf("%s\n",files->s[i]);
613  |       }
614  |     else
615  |        if(option_warn&WARN_XREF)
616  |           printf("Warning Index : No global files to index.\n");
617  |    }
618  | 
619  |  /* Write out the appendix of functions. */
620  | 
621  |  if(option_index&INDEX_FUNC)
622  |    {
623  |     if(funcs->n)
624  |       {
625  |        printf("\nAppendix - Global Functions\n\n");
626  |        for(i=0;i<funcs->n;i++)
627  |           printf("%s : %s\n",funcs->s1[i],funcs->s2[i]);
628  |       }
629  |     else
630  |        if(option_warn&WARN_XREF)
631  |           printf("Warning Index : No global functions to index.\n");
632  |    }
633  | 
634  |  /* Write out the appendix of variables. */
635  | 
636  |  if(option_index&INDEX_VAR)
637  |    {
638  |     if(vars->n)
639  |       {
640  |        printf("\nAppendix - Global Variables\n\n");
641  |        for(i=0;i<vars->n;i++)
642  |           printf("%s : %s\n",vars->s1[i],vars->s2[i]);
643  |       }
644  |     else
645  |        if(option_warn&WARN_XREF)
646  |           printf("Warning Index : No global variables to index.\n");
647  |    }
648  | 
649  |  /* Write out the appendix of types. */
650  | 
651  |  if(option_index&INDEX_TYPE)
652  |    {
653  |     if(types->n)
654  |       {
655  |        printf("\nAppendix - Defined Types\n\n");
656  |        for(i=0;i<types->n;i++)
657  |           printf("%s : %s\n",types->s1[i],types->s2[i]);
658  |       }
659  |     else
660  |        if(option_warn&WARN_XREF)
661  |           printf("Warning Index : No types to index.\n");
662  |    }
663  | }
664  | 
665  | 
666  | /*++++++++++++++++++++++++++++++++++++++
667  |   Decide if to copy or skip the next line.
668  | 
669  |   int CopyOrSkip Returns the number of characters to skip.
670  | 
671  |   char *string The string that starts the next line.
672  | 
673  |   char *type The type of file we are outputing.
674  | 
675  |   int *copy Returns true if we are to copy the line verbatim.
676  | 
677  |   int *skip Returns true if we are to skip the line.
678  |   ++++++++++++++++++++++++++++++++++++++*/
679  | 
680  | int CopyOrSkip(char *string,char *type,int *copy,int *skip)
681  | {
682  |  char *p=string;
683  |  int s=0;
684  | 
685  |  if(*p=='\n')
686  |     p++;
687  |  while(*p==' ' || *p=='\t')
688  |     p++;
689  | 
690  |  *copy=*skip=0;
691  | 
692  |  switch(*type)
693  |     {
694  |     case 'h': /* html */
695  |      if(!strncmp(p,"+html+",s=6) || !strncmp(p,"-latex-",s=7) || !strncmp(p,"-sgml-",s=6) || !strncmp(p,"-rtf-",s=5))
696  |         *copy=1;
697  |      if(!strncmp(p,"-html-",s=6) || !strncmp(p,"+latex+",s=7) || !strncmp(p,"+sgml+",s=6) || !strncmp(p,"+rtf+",s=5) || !strncmp(p,"+none+",s=6))
698  |         *skip=1;
699  |      break;
700  |     case 'l': /* latex */
701  |      if(!strncmp(p,"-html-",s=6) || !strncmp(p,"+latex+",s=7) || !strncmp(p,"-sgml-",s=6) || !strncmp(p,"-rtf-",s=5))
702  |         *copy=1;
703  |      if(!strncmp(p,"+html+",s=6) || !strncmp(p,"-latex-",s=7) || !strncmp(p,"+sgml+",s=6) || !strncmp(p,"+rtf+",s=5) || !strncmp(p,"+none+",s=6))
704  |         *skip=1;
705  |      break;
706  |     case 's': /* sgml */
707  |      if(!strncmp(p,"-html-",s=6) || !strncmp(p,"-latex-",s=7) || !strncmp(p,"+sgml+",s=6) || !strncmp(p,"-rtf-",s=5))
708  |         *copy=1;
709  |      if(!strncmp(p,"+html+",s=6) || !strncmp(p,"+latex+",s=7) || !strncmp(p,"-sgml-",s=6) || !strncmp(p,"+rtf+",s=5) || !strncmp(p,"+none+",s=6))
710  |         *skip=1;
711  |      break;
712  |     case 'r': /* rtf */
713  |      if(!strncmp(p,"-html-",s=6) || !strncmp(p,"-latex-",s=7) || !strncmp(p,"-sgml-",s=6) || !strncmp(p,"+rtf+",s=5))
714  |         *copy=1;
715  |      if(!strncmp(p,"+html+",s=6) || !strncmp(p,"+latex+",s=7) || !strncmp(p,"+sgml+",s=6) || !strncmp(p,"-rtf-",s=5) || !strncmp(p,"+none+",s=6))
716  |         *skip=1;
717  |      break;
718  |     }
719  | 
720  |  if(*copy)
721  |     return(p-string+s);
722  |  else
723  |     return(0);
724  | }