1 /***************************************
2   $Header: /home/amb/CVS/cxref/src/warn-raw.c,v 1.31 2004-01-24 19:20:25 amb Exp $
3 
4   C Cross Referencing & Documentation tool. Version 1.5f.
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,04 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 
WriteWarnRawFile(File file)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 
WriteWarnRawFilePart(File file)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 
WriteWarnRawInclude(Include inc)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 
WriteWarnRawSubInclude(Include inc,int depth)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 
WriteWarnRawDefine(Define def)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 
WriteWarnRawTypedef(Typedef type)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 
WriteWarnRawStructUnion(StructUnion su,int depth,StructUnion base)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("Warning %16s : Struct/Union component '%s' in '%s' does not have a comment.\n",filename,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 
WriteWarnRawVariable(Variable var)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 
WriteWarnRawFunction(Function func)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",func->incfrom?func->incfrom: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|EXTERNAL) && (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 
WriteWarnRawAppendix(StringList files,StringList2 funcs,StringList2 vars,StringList2 types)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 
CopyOrSkip(char * string,char * type,int * copy,int * skip)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 }
725