Autodoc corrections.
[cake.git] / tools / cxref / cxref.c
bloba5bededabafd681156e510fd7e64d3e7fb7d181c
1 /***************************************
2 $Header$
4 C Cross Referencing & Documentation tool. Version 1.5g.
5 ******************/ /******************
6 Written by Andrew M. Bishop
8 This file Copyright 1995,96,97,98,99,2000,01,02,03,04 Andrew M. Bishop
9 It may be distributed under the GNU Public License, version 2, or
10 any higher version. See section COPYING of the GNU Public license
11 for conditions under which this file may be redistributed.
12 ***************************************/
14 #include <stdio.h>
15 #include <stdlib.h>
16 #include <string.h>
18 #include <limits.h>
19 #include <sys/types.h>
20 #include <sys/wait.h>
21 #include <sys/stat.h>
22 #include <unistd.h>
24 #include "parse-yy.h"
25 #include "memory.h"
26 #include "datatype.h"
27 #include "cxref.h"
29 /*+ The default value of the CPP command. +*/
30 #ifdef CXREF_CPP
31 #define CPP_COMMAND CXREF_CPP
32 #else
33 #define CPP_COMMAND "gcc -E -C -dD -dI"
34 #endif
36 /*+ The name of the file to read the configuration from. +*/
37 #define CXREF_CONFIG_FILE ".cxref"
40 static void Usage(int verbose);
41 static int ParseConfigFile(void);
42 static int ParseOptions(int nargs,char **args,int fromfile);
44 static int DocumentTheFile(char* name);
45 static FILE* popen_execvp(char** command);
46 static int pclose_execvp(FILE* f);
48 static char** cpp_command; /*+ The actual cpp command that is built up, adding -D, -U and -I options. +*/
49 static int cpp_command_num=0; /*+ The number of arguments to the cpp command. +*/
50 static int cpp_argument_num=0; /*+ The number of arguments to the -CPP argument. +*/
52 /*+ The command line switch that sets the format of the output, +*/
53 int option_all_comments=0, /*+ use all comments. +*/
54 option_verbatim_comments=0, /*+ insert the comments verbatim into the output. +*/
55 option_block_comments=0, /*+ remove the leading block comment marker. +*/
56 option_no_comments=0, /*+ ignore all comments. +*/
57 option_xref=0, /*+ do cross referencing. +*/
58 option_warn=0, /*+ produce warnings. +*/
59 option_index=0, /*+ produce an index. +*/
60 option_raw=0, /*+ produce raw output. +*/
61 option_latex=0, /*+ produce LaTeX output. +*/
62 option_html=0, /*+ produce HTML output. +*/
63 option_rtf=0, /*+ produce RTF output. +*/
64 option_sgml=0; /*+ produce SGML output. +*/
66 /*+ The option to control the mode of operation. +*/
67 static int option_delete=0;
69 /*+ The command line switch for the output name, +*/
70 char *option_odir=NULL, /*+ the directory to use. +*/
71 *option_name=NULL, /*+ the base part of the name. +*/
72 *option_root=NULL; /*+ the source tree root directory. +*/
74 /*+ The name of the include directories specified on the command line. +*/
75 char **option_incdirs=NULL;
77 /*+ The information about the cxref run, +*/
78 char *run_command=NULL, /*+ the command line options. +*/
79 *run_cpp_command=NULL; /*+ the cpp command and options. +*/
81 /*+ The number of include directories on the command line. +*/
82 int option_nincdirs=0;
84 /*+ The names of the files to process. +*/
85 static char **option_files=NULL;
87 /*+ The number of files to process. +*/
88 static int option_nfiles=0;
90 /*+ The current file that is being processed. +*/
91 File CurFile=NULL;
94 /*++++++++++++++++++++++++++++++++++++++
95 The main function that calls the parser.
97 int main Returns the status, zero for normal termination, else an error.
99 int argc The command line number of arguments.
101 char** argv The actual command line arguments
102 ++++++++++++++++++++++++++++++++++++++*/
104 int main(int argc,char** argv)
106 int i;
107 char *root_prefix=NULL;
108 char here[PATH_MAX+1],there[PATH_MAX+1];
110 if(argc==1)
111 Usage(1);
113 /* Setup the variables. */
115 cpp_command=(char**)Malloc(8*sizeof(char*));
116 cpp_command[cpp_command_num++]=MallocString(CPP_COMMAND);
118 for(i=1;cpp_command[cpp_command_num-1][i];i++)
119 if(cpp_command[cpp_command_num-1][i]==' ')
121 cpp_command[cpp_command_num-1][i]=0;
122 if((cpp_command_num%8)==6)
123 cpp_command=(char**)Realloc(cpp_command,(cpp_command_num+10)*sizeof(char*));
124 cpp_command[cpp_command_num]=MallocString(&cpp_command[cpp_command_num-1][i+1]);
125 cpp_command_num++;
126 i=1;
129 cpp_argument_num=cpp_command_num;
131 option_incdirs=(char**)Malloc(8*sizeof(char*));
132 option_incdirs[0]=MallocString(".");
133 option_nincdirs=1;
135 option_odir=MallocString(".");
137 option_name=MallocString("cxref");
139 option_files=(char**)Malloc(8*sizeof(char*));
141 run_command=argv[0];
143 /* Parse the command line options. */
145 if(ParseOptions(argc-1,&argv[1],0))
146 Usage(0);
148 /* Parse the options in .cxref in this directory. */
150 if(ParseConfigFile())
151 Usage(0);
153 /* Change directory. */
155 if(option_root)
157 if(!getcwd(there,PATH_MAX))
158 {fprintf(stderr,"cxref: Error cannot get current working directory (1).\n");exit(1);}
159 if(chdir(option_root))
160 {fprintf(stderr,"cxref: Error cannot change directory to '%s'.\n",option_root);exit(1);}
163 if(!getcwd(here,PATH_MAX))
164 {fprintf(stderr,"cxref: Error cannot get current working directory (2).\n");exit(1);}
166 if(option_root)
168 if(!strcmp(here,there))
169 root_prefix=".";
170 else if(!strcmp(here,"/"))
171 root_prefix=there+1;
172 else if(!strncmp(here,there,strlen(here)))
173 root_prefix=there+strlen(here)+1;
174 else
175 {fprintf(stderr,"cxref: Error the -R option has not specified a parent directory of the current one.\n");exit(1);}
178 /* Modify the -I options for the new root directory. */
180 for(i=1;i<cpp_command_num;i++)
181 if(cpp_command[i][0]=='-' && cpp_command[i][1]=='I')
183 if(cpp_command[i][2]==0)
185 char *old=cpp_command[++i];
186 if(cpp_command[i][0]!='/' && root_prefix)
187 cpp_command[i]=MallocString(CanonicaliseName(ConcatStrings(3,root_prefix,"/",cpp_command[i])));
188 else if(cpp_command[i][0]=='/' && !strcmp(cpp_command[i],here))
189 cpp_command[i]=MallocString(".");
190 else if(cpp_command[i][0]=='/' && !strcmp(here,"/"))
191 cpp_command[i]=MallocString(cpp_command[i]+1);
192 else if(cpp_command[i][0]=='/' && !strncmp(cpp_command[i],here,strlen(here)))
193 cpp_command[i]=MallocString(cpp_command[i]+strlen(here)+1);
194 else
195 cpp_command[i]=MallocString(CanonicaliseName(cpp_command[i]));
196 Free(old);
198 else
200 char *old=cpp_command[i];
201 if(cpp_command[i][2]!='/' && root_prefix)
202 cpp_command[i]=MallocString(ConcatStrings(2,"-I",CanonicaliseName(ConcatStrings(3,root_prefix,"/",cpp_command[i]+2))));
203 else if(cpp_command[i][2]=='/' && !strcmp(&cpp_command[i][2],here))
204 cpp_command[i]=MallocString("-I.");
205 else if(cpp_command[i][2]=='/' && !strcmp(here,"/"))
206 cpp_command[i]=MallocString(ConcatStrings(2,"-I",cpp_command[i]+2+1));
207 else if(cpp_command[i][2]=='/' && !strncmp(&cpp_command[i][2],here,strlen(here)))
208 cpp_command[i]=MallocString(ConcatStrings(2,"-I",cpp_command[i]+2+strlen(here)+1));
209 else
210 cpp_command[i]=MallocString(ConcatStrings(2,"-I",CanonicaliseName(cpp_command[i]+2)));
211 Free(old);
215 for(i=0;i<option_nincdirs;i++)
217 char *old=option_incdirs[i];
218 if(*option_incdirs[i]!='/' && root_prefix)
219 option_incdirs[i]=MallocString(CanonicaliseName(ConcatStrings(3,root_prefix,"/",option_incdirs[i])));
220 else if(*option_incdirs[i]=='/' && !strcmp(option_incdirs[i],here))
221 option_incdirs[i]=MallocString(".");
222 else if(*option_incdirs[i]=='/' && !strcmp(here,"/"))
223 option_incdirs[i]=MallocString(option_incdirs[i]+strlen(here)+1);
224 else if(*option_incdirs[i]=='/' && !strncmp(option_incdirs[i],here,strlen(here)))
225 option_incdirs[i]=MallocString(option_incdirs[i]+strlen(here)+1);
226 else
227 option_incdirs[i]=MallocString(CanonicaliseName(option_incdirs[i]));
228 Free(old);
231 /* Parse the options in .cxref in the root directory. */
233 if(option_root)
234 if(ParseConfigFile())
235 Usage(0);
237 run_command=MallocString(run_command);
239 run_cpp_command=cpp_command[0];
240 for(i=1;i<cpp_command_num;i++)
241 run_cpp_command=ConcatStrings(3,run_cpp_command," ",cpp_command[i]);
243 run_cpp_command=MallocString(run_cpp_command);
245 TidyMemory();
247 /* Check the options for validity */
249 if(option_warn&WARN_XREF && !option_xref)
250 fprintf(stderr,"cxref: Warning using '-warn-xref' without '-xref'.\n");
252 /* Process each file. */
254 if(option_files)
255 for(i=0;i<option_nfiles;i++)
257 char *filename=CanonicaliseName(root_prefix?ConcatStrings(3,root_prefix,"/",option_files[i]):option_files[i]);
259 if(!strncmp(filename,"../",3) || *filename=='/')
260 fprintf(stderr,"cxref: Error the file %s is outside the cxref root directory.\n",filename);
261 else if(!option_delete)
263 CurFile=NewFile(filename);
265 ResetLexer();
266 ResetParser();
268 if(!DocumentTheFile(filename))
270 if(option_xref)
271 CrossReference(CurFile,option_warn||option_raw||option_latex||option_html||option_rtf||option_sgml);
273 if(option_raw || option_warn)
274 WriteWarnRawFile(CurFile);
275 if(option_latex)
276 WriteLatexFile(CurFile);
277 if(option_html)
278 WriteHTMLFile(CurFile);
279 if(option_rtf)
280 WriteRTFFile(CurFile);
281 if(option_sgml)
282 WriteSGMLFile(CurFile);
285 ResetLexer();
286 ResetParser();
287 ResetPreProcAnalyser();
288 ResetTypeAnalyser();
289 ResetVariableAnalyser();
290 ResetFunctionAnalyser();
292 DeleteComment();
294 DeleteFile(CurFile);
295 CurFile=NULL;
297 else
299 CrossReferenceDelete(filename);
301 WriteLatexFileDelete(filename);
302 WriteHTMLFileDelete(filename);
303 WriteRTFFileDelete(filename);
304 WriteSGMLFileDelete(filename);
307 TidyMemory();
310 /* Create the index */
312 if(option_index)
314 StringList files;
315 StringList2 funcs,vars,types;
317 files=NewStringList();
318 funcs=NewStringList2();
319 vars=NewStringList2();
320 types=NewStringList2();
322 CreateAppendix(files,funcs,vars,types);
324 if(option_raw||option_warn)
325 WriteWarnRawAppendix(files,funcs,vars,types);
326 if(option_latex)
327 WriteLatexAppendix(files,funcs,vars,types);
328 if(option_html)
329 WriteHTMLAppendix(files,funcs,vars,types);
330 if(option_rtf)
331 WriteRTFAppendix(files,funcs,vars,types);
332 if(option_sgml)
333 WriteSGMLAppendix(files,funcs,vars,types);
335 DeleteStringList(files);
336 DeleteStringList2(funcs);
337 DeleteStringList2(vars);
338 DeleteStringList2(types);
340 TidyMemory();
343 /* Tidy up */
345 Free(option_odir);
346 Free(option_name);
347 if(option_root)
348 Free(option_root);
350 for(i=0;i<cpp_command_num;i++)
351 Free(cpp_command[i]);
352 Free(cpp_command);
354 for(i=0;i<option_nincdirs;i++)
355 Free(option_incdirs[i]);
356 Free(option_incdirs);
358 for(i=0;i<option_nfiles;i++)
359 Free(option_files[i]);
360 Free(option_files);
362 Free(run_command);
363 Free(run_cpp_command);
365 PrintMemoryStatistics();
367 return(0);
371 /*++++++++++++++++++++++++++++++++++++++
372 Print out the usage instructions.
374 int verbose If true then output a long version of the information.
375 ++++++++++++++++++++++++++++++++++++++*/
377 static void Usage(int verbose)
379 fputs("\n"
380 " C Cross Referencing & Documenting tool - Version 1.5g\n"
381 " -----------------------------------------------------\n"
382 "\n"
383 "(c) Andrew M. Bishop 1995,96,97,98,99, [ amb@gedanken.demon.co.uk ]\n"
384 " 2000,01,02,03,04 [http://www.gedanken.demon.co.uk/cxref/]\n"
385 "\n"
386 "Usage: cxref filename [ ... filename]\n"
387 " [-Odirname] [-Nbasename] [-Rdirname]\n"
388 " [-all-comments] [-no-comments]\n"
389 " [-verbatim-comments] [-block-comments]\n"
390 " [-xref[-all][-file][-func][-var][-type]]\n"
391 " [-warn[-all][-comment][-xref]]\n"
392 " [-index[-all][-file][-func][-var][-type]]\n"
393 " [-latex209|-latex2e] [-html20|-html32] [-rtf] [-sgml] [-raw]\n"
394 " [-Idirname] [-Ddefine] [-Udefine]\n"
395 " [-CPP cpp_program] [-- cpp_arg [ ... cpp_arg]]\n"
396 "\n"
397 "Usage: cxref filename [ ... filename] -delete\n"
398 " [-Odirname] [-Nbasename] [-Rdirname]\n"
399 "\n",
400 stderr);
402 if(verbose)
403 fputs("filename ... : Files to document.\n"
404 "-delete : Delete all references to the named files.\n"
405 "\n"
406 "-Odirname : The output directory for the documentation.\n"
407 "-Nbasename : The base filename for the output documentation.\n"
408 "-Rdirname : The root directory of the source tree.\n"
409 "\n"
410 "-all-comments : Use all comments.\n"
411 "-verbatim-comments : Insert the comments verbatim in the output.\n"
412 "-block-comments : The comments are in block style.\n"
413 "-no-comments : Ignore all of the comments.\n"
414 "\n"
415 "-xref[-*] : Do cross referencing (of specified types).\n"
416 "-warn[-*] : Produce warnings (of comments or cross references).\n"
417 "\n"
418 "-index[-*] : Produce a cross reference index (of specified types).\n"
419 "\n"
420 "-latex209 | -latex2e : Produce LaTeX output (version 2.09 or 2e - default=2e).\n"
421 "-html20 | -html32 : Produce HTML output (version 2.0 or 3.2 - default=3.2).\n"
422 "-rtf : Produce RTF output (version 1.x).\n"
423 "-sgml : Produce SGML output (for SGML tools version 1.0.x).\n"
424 "-raw : Produce raw output .\n"
425 "\n"
426 "-I*, -D*, -U* : The usual compiler switches.\n"
427 "-CPP cpp_program : The cpp program to use.\n"
428 " : (default '" CPP_COMMAND "')\n"
429 "-- cpp_arg ... : All arguments after the '--' are passed to cpp.\n"
430 "\n"
431 "The file .cxref in the current directory can also contain any of these arguments\n"
432 "one per line, (except for filename and -delete).\n",
433 stderr);
434 else
435 fputs("Run cxref with no arguments to get more verbose help\n",
436 stderr);
438 exit(1);
442 /*++++++++++++++++++++++++++++++++++++++
443 Read in the options from the configuration file.
445 int ParseConfigFile Returns the value returned by ParseOptions().
446 ++++++++++++++++++++++++++++++++++++++*/
448 static int ParseConfigFile(void)
450 FILE *file=fopen(CXREF_CONFIG_FILE,"r");
451 char **lines=NULL;
452 int nlines=0;
453 char data[257];
455 if(file)
457 while(fgets(data,256,file))
459 char *d=data+strlen(data)-1;
461 if(*data=='#')
462 continue;
464 while(d>=data && (*d=='\r' || *d=='\n' || *d==' '))
465 *d--=0;
467 if(d<data)
468 continue;
470 if(!lines)
471 lines=(char**)Malloc(8*sizeof(char*));
472 else if((nlines%8)==7)
473 lines=(char**)Realloc(lines,(nlines+9)*sizeof(char*));
475 if((!strncmp(data,"-I",2) || !strncmp(data,"-D",2) || !strncmp(data,"-U",2) ||
476 !strncmp(data,"-O",2) || !strncmp(data,"-N",2) || !strncmp(data,"-R",2)) &&
477 (data[2]==' ' || data[2]=='\t'))
479 int i=2;
480 while(data[i]==' ' || data[i]=='\t')
481 data[i++]=0;
482 lines[nlines++]=CopyString(data);
483 lines[nlines++]=CopyString(data+i);
485 else if(!strncmp(data,"-CPP",4) &&
486 (data[4]==' ' || data[4]=='\t'))
488 int i=4;
489 while(data[i]==' ' || data[i]=='\t')
490 data[i++]=0;
491 lines[nlines++]=CopyString(data);
492 lines[nlines++]=CopyString(data+i);
494 else
495 if(*data)
496 lines[nlines++]=CopyString(data);
499 if(nlines)
501 int n_files=option_nfiles;
503 if(ParseOptions(nlines,lines,1))
505 fprintf(stderr,"cxref: Error parsing the .cxref file\n");
506 return(1);
509 Free(lines);
511 if(n_files!=option_nfiles)
513 for(;n_files<option_nfiles;n_files++)
514 fprintf(stderr,"cxref: File names '%s' only allowed on command line.\n",option_files[n_files]);
515 return(1);
519 fclose(file);
522 return(0);
526 /*++++++++++++++++++++++++++++++++++++++
527 Parse the options from the command line or from the .cxref file.
529 int ParseOptions Return 1 if there is an error.
531 int nargs The number of arguments.
533 char **args The actual arguments
535 int fromfile A flag indicating that they are read from the .cxref file.
536 ++++++++++++++++++++++++++++++++++++++*/
538 static int ParseOptions(int nargs,char **args,int fromfile)
540 int i,end_of_args=0;
542 for(i=0;i<nargs;i++)
544 if(end_of_args)
546 if((cpp_command_num%8)==6)
547 cpp_command=(char**)Realloc(cpp_command,(cpp_command_num+10)*sizeof(char*));
548 cpp_command[cpp_command_num++]=MallocString(args[i]);
549 run_command=ConcatStrings(3,run_command," ",args[i]);
550 continue;
553 if(!strncmp(args[i],"-I",2) || !strncmp(args[i],"-D",2) || !strncmp(args[i],"-U",2))
555 char *incdir=NULL;
556 if((cpp_command_num%8)==6)
557 cpp_command=(char**)Realloc(cpp_command,(cpp_command_num+10)*sizeof(char*));
558 cpp_command[cpp_command_num++]=MallocString(args[i]);
559 if(args[i][2]==0)
561 if(args[i][1]=='I')
562 incdir=args[i+1];
563 if(i==nargs-1)
564 {fprintf(stderr,"cxref: The -%c option requires a following argument.\n",args[i][1]);return(1);}
565 if((cpp_command_num%8)==6)
566 cpp_command=(char**)Realloc(cpp_command,(cpp_command_num+10)*sizeof(char*));
567 run_command=ConcatStrings(3,run_command," ",args[i]);
568 cpp_command[cpp_command_num++]=MallocString(args[++i]);
570 else
571 if(args[i][1]=='I')
572 incdir=&args[i][2];
574 if(incdir)
576 if((option_nincdirs%8)==0)
577 option_incdirs=(char**)Realloc(option_incdirs,(option_nincdirs+8)*sizeof(char*));
578 option_incdirs[option_nincdirs++]=MallocString(incdir);
581 run_command=ConcatStrings(3,run_command," ",args[i]);
582 continue;
585 if(!strcmp(args[i],"-CPP"))
587 char **old=cpp_command,*command;
588 int j,old_com_num=cpp_command_num,old_arg_num=cpp_argument_num;
590 if(i==nargs-1)
591 {fprintf(stderr,"cxref: The -CPP option requires a following argument.\n");return(1);}
592 command=args[++i];
594 cpp_command_num=0;
595 cpp_command=(char**)Malloc(8*sizeof(char*));
596 cpp_command[cpp_command_num++]=MallocString(command);
598 for(j=1;cpp_command[cpp_command_num-1][j];j++)
599 if(cpp_command[cpp_command_num-1][j]==' ')
601 cpp_command[cpp_command_num-1][j]=0;
602 if((cpp_command_num%8)==6)
603 cpp_command=(char**)Realloc(cpp_command,(cpp_command_num+10)*sizeof(char*));
604 cpp_command[cpp_command_num]=MallocString(&cpp_command[cpp_command_num-1][j+1]);
605 cpp_command_num++;
606 j=1;
609 cpp_argument_num=cpp_command_num;
611 for(j=old_arg_num;j<old_com_num;j++)
613 if((cpp_command_num%8)==6)
614 cpp_command=(char**)Realloc(cpp_command,(cpp_command_num+10)*sizeof(char*));
615 cpp_command[cpp_command_num++]=old[j];
618 for(j=0;j<old_arg_num;j++)
619 Free(old[j]);
620 Free(old);
622 run_command=ConcatStrings(4,run_command,"-CPP \"",args[i],"\"");
623 continue;
626 if(!strncmp(args[i],"-O",2))
628 if(option_odir)
629 Free(option_odir);
630 if(args[i][2]==0)
632 if(i==nargs-1)
633 {fprintf(stderr,"cxref: The -O option requires a following argument.\n");return(1);}
634 run_command=ConcatStrings(3,run_command," ",args[i]);
635 option_odir=MallocString(args[++i]);
637 else
638 option_odir=MallocString(&args[i][2]);
639 run_command=ConcatStrings(3,run_command," ",args[i]);
640 continue;
643 if(!strncmp(args[i],"-N",2))
645 if(option_name)
646 Free(option_name);
647 if(args[i][2]==0)
649 if(i==nargs-1)
650 {fprintf(stderr,"cxref: The -N option requires a following argument.\n");return(1);}
651 run_command=ConcatStrings(3,run_command," ",args[i]);
652 option_name=MallocString(args[++i]);
654 else
655 option_name=MallocString(&args[i][2]);
656 run_command=ConcatStrings(3,run_command," ",args[i]);
657 continue;
660 if(!strncmp(args[i],"-R",2))
662 if(option_root)
663 Free(option_root);
664 if(args[i][2]==0)
666 if(i==nargs-1)
667 {fprintf(stderr,"cxref: The -R option requires a following argument.\n");return(1);}
668 run_command=ConcatStrings(3,run_command," ",args[i]);
669 option_root=MallocString(args[++i]);
671 else
672 option_root=MallocString(&args[i][2]);
673 if(*option_root=='.' && !*(option_root+1))
674 option_root=NULL;
675 run_command=ConcatStrings(3,run_command," ",args[i]);
676 continue;
679 if(!strcmp(args[i],"-delete"))
680 {if(fromfile) {fprintf(stderr,"cxref: The -delete option cannot be used in the .cxref file.\n");return(1);}
681 option_delete=1; run_command=ConcatStrings(3,run_command," ",args[i]); continue;}
683 if(!strcmp(args[i],"-all-comments"))
684 {option_all_comments=1; run_command=ConcatStrings(3,run_command," ",args[i]); continue;}
686 if(!strcmp(args[i],"-verbatim-comments"))
687 {option_verbatim_comments=1; run_command=ConcatStrings(3,run_command," ",args[i]); continue;}
689 if(!strcmp(args[i],"-block-comments"))
690 {option_block_comments=1; run_command=ConcatStrings(3,run_command," ",args[i]); continue;}
692 if(!strcmp(args[i],"-no-comments"))
693 {option_no_comments=1; run_command=ConcatStrings(3,run_command," ",args[i]); continue;}
695 if(!strncmp(args[i],"-xref",5))
697 char* p=&args[i][5];
699 if(!*p)
700 option_xref=XREF_ALL;
701 else
702 while(*p)
704 if(!strncmp(p,"-all" ,4)) {option_xref|=XREF_ALL ; p=&p[4]; continue;}
705 if(!strncmp(p,"-file",5)) {option_xref|=XREF_FILE; p=&p[5]; continue;}
706 if(!strncmp(p,"-func",5)) {option_xref|=XREF_FUNC; p=&p[5]; continue;}
707 if(!strncmp(p,"-var" ,4)) {option_xref|=XREF_VAR ; p=&p[4]; continue;}
708 if(!strncmp(p,"-type",5)) {option_xref|=XREF_TYPE; p=&p[5]; continue;}
709 break;
712 run_command=ConcatStrings(3,run_command," ",args[i]);
713 continue;
716 if(!strncmp(args[i],"-warn",5))
718 char* p=&args[i][5];
720 if(!*p)
721 option_warn=WARN_ALL;
722 else
723 while(*p)
725 if(!strncmp(p,"-all" ,4)) {option_warn|=WARN_ALL ; p=&p[4]; continue;}
726 if(!strncmp(p,"-comment",8)) {option_warn|=WARN_COMMENT; p=&p[8]; continue;}
727 if(!strncmp(p,"-xref" ,5)) {option_warn|=WARN_XREF ; p=&p[5]; continue;}
728 break;
731 run_command=ConcatStrings(3,run_command," ",args[i]);
732 continue;
735 if(!strncmp(args[i],"-index",6))
737 char* p=&args[i][6];
739 if(!*p)
740 option_index=INDEX_ALL;
741 else
742 while(*p)
744 if(!strncmp(p,"-all" ,4)) {option_index|=INDEX_ALL ; p=&p[4]; continue;}
745 if(!strncmp(p,"-file",5)) {option_index|=INDEX_FILE; p=&p[5]; continue;}
746 if(!strncmp(p,"-func",5)) {option_index|=INDEX_FUNC; p=&p[5]; continue;}
747 if(!strncmp(p,"-var" ,4)) {option_index|=INDEX_VAR ; p=&p[4]; continue;}
748 if(!strncmp(p,"-type",5)) {option_index|=INDEX_TYPE; p=&p[5]; continue;}
749 break;
752 run_command=ConcatStrings(3,run_command," ",args[i]);
753 continue;
756 if(!strcmp(args[i],"-raw"))
757 {option_raw=1; run_command=ConcatStrings(3,run_command," ",args[i]); continue;}
759 if(!strcmp(args[i],"-latex209"))
760 {option_latex=1; run_command=ConcatStrings(3,run_command," ",args[i]); continue;}
761 if(!strcmp(args[i],"-latex2e") || !strcmp(args[i],"-latex"))
762 {option_latex=2; run_command=ConcatStrings(3,run_command," ",args[i]); continue;}
764 if(!strncmp(args[i],"-html20",7))
765 {option_html=1; if(!strcmp(args[i]+7,"-src"))option_html+=16;
766 run_command=ConcatStrings(3,run_command," ",args[i]); continue;}
767 if(!strncmp(args[i],"-html32",7))
768 {option_html=2; if(!strcmp(args[i]+7,"-src"))option_html+=16;
769 run_command=ConcatStrings(3,run_command," ",args[i]); continue;}
770 if(!strncmp(args[i],"-html",5))
771 {option_html=2; if(!strcmp(args[i]+5,"-src"))option_html+=16;
772 run_command=ConcatStrings(3,run_command," ",args[i]); continue;}
774 if(!strcmp(args[i],"-rtf"))
775 {option_rtf=1; run_command=ConcatStrings(3,run_command," ",args[i]); continue;}
777 if(!strcmp(args[i],"-sgml"))
778 {option_sgml=1; run_command=ConcatStrings(3,run_command," ",args[i]); continue;}
780 if(!strcmp(args[i],"--"))
781 {end_of_args=1; run_command=ConcatStrings(3,run_command," ",args[i]); continue;}
783 if(args[i][0]=='-')
784 {fprintf(stderr,"cxref: Unknown option '%s'.\n",args[i]);return(1);}
786 if(fromfile)
787 {fprintf(stderr,"cxref: File names '%s' only allowed on command line.\n",args[i]);return(1);}
789 if(option_files && (option_nfiles%8)==0)
790 option_files=(char**)Realloc(option_files,(option_nfiles+8)*sizeof(char*));
791 option_files[option_nfiles++]=MallocString(args[i]);
794 return(0);
798 /*++++++++++++++++++++++++++++++++++++++
799 Canonicalise a file name by removing '/../', '/./' and '//' references.
801 char *CanonicaliseName Returns the argument modified.
803 char *name The original name
805 The same function is used in WWWOFFLE and cxref with changes for files or URLs.
806 ++++++++++++++++++++++++++++++++++++++*/
808 char *CanonicaliseName(char *name)
810 char *match,*name2;
812 match=name;
813 while((match=strstr(match,"/./")) || !strncmp(match=name,"./",2))
815 char *prev=match, *next=match+2;
816 while((*prev++=*next++));
819 match=name;
820 while((match=strstr(match,"//")))
822 char *prev=match, *next=match+1;
823 while((*prev++=*next++));
826 match=name2=name;
827 while((match=strstr(match,"/../")))
829 char *prev=match, *next=match+4;
830 if((prev-name2)==2 && !strncmp(name2,"../",3))
831 {name2+=3;match++;continue;}
832 while(prev>name2 && *--prev!='/');
833 match=prev;
834 if(*prev=='/')prev++;
835 while((*prev++=*next++));
838 match=&name[strlen(name)-2];
839 if(match>=name && !strcmp(match,"/."))
840 *match=0;
842 match=&name[strlen(name)-3];
843 if(match>=name && !strcmp(match,"/.."))
845 if(match==name)
846 *++match=0;
847 else
848 while(match>name && *--match!='/')
849 *match=0;
852 #if 1 /* as used in cxref */
854 match=&name[strlen(name)-1];
855 if(match>name && !strcmp(match,"/"))
856 *match=0;
858 if(!*name)
859 *name='.',*(name+1)=0;
861 #else /* as used in wwwoffle */
863 if(!*name || !strncmp(name,"../",3))
864 *name='/',*(name+1)=0;
866 #endif
868 return(name);
872 /*++++++++++++++++++++++++++++++++++++++
873 Calls CPP for the file to get all of the needed information.
875 int DocumentTheFile Returns 1 in case of error, else 0.
877 char* name The name of the file to document.
879 The CPP is started as a sub-process, (using popen to return a FILE* for lex to use).
880 ++++++++++++++++++++++++++++++++++++++*/
882 static int DocumentTheFile(char* name)
884 struct stat stat_buf;
885 int error1,error2;
886 static int first=1;
888 if(stat(name,&stat_buf)==-1)
889 {fprintf(stderr,"cxref: Cannot access the file '%s'\n",name);return(1);}
891 cpp_command[cpp_command_num ]=name;
892 cpp_command[cpp_command_num+1]=NULL;
894 yyin=popen_execvp(cpp_command);
896 if(!yyin)
897 {fprintf(stderr,"cxref: Failed to start the cpp command '%s'\n",cpp_command[0]);exit(1);}
899 if(!first)
900 yyrestart(yyin);
901 first=0;
903 #if YYDEBUG
904 yydebug=(YYDEBUG==3);
905 #endif
907 error1=yyparse();
909 error2=pclose_execvp(yyin);
911 if(error2)
912 fprintf(stderr,"cxref: The preprocessor exited abnormally on '%s'\n",name);
914 return(error1||error2);
918 /*+ The process id of the pre-processor. +*/
919 static pid_t popen_pid;
921 /*++++++++++++++++++++++++++++++++++++++
922 A popen function that takes a list of arguments not a string.
924 FILE* popen_execvp Returns a file descriptor.
926 char** command The command arguments.
927 ++++++++++++++++++++++++++++++++++++++*/
929 static FILE* popen_execvp(char** command)
931 int fdr[2];
933 if(pipe(fdr)==-1)
934 {fprintf(stderr,"cxref: Can not pipe for the cpp command '%s'.\n",command[0]);exit(1);}
936 if((popen_pid=fork())==-1)
937 {fprintf(stderr,"cxref: Can not fork for the cpp command '%s.\n",command[0]);exit(1);}
939 if(popen_pid) /* The parent */
941 close(fdr[1]);
943 else /* The child */
945 close(1);
946 dup(fdr[1]);
947 close(fdr[1]);
949 close(fdr[0]);
951 execvp(command[0],command);
952 fprintf(stderr,"cxref: Can not execvp for the cpp command '%s', is it on the path?\n",command[0]);
953 exit(1);
956 return(fdopen(fdr[0],"r"));
960 /*++++++++++++++++++++++++++++++++++++++
961 Close the file to the to the preprocessor
963 int pclose_execvp Return the error status.
965 FILE* f The file to close.
966 ++++++++++++++++++++++++++++++++++++++*/
968 static int pclose_execvp(FILE* f)
970 int status,ret;
972 waitpid(popen_pid,&status,0);
973 fclose(f);
975 if(WIFEXITED(status))
976 ret=WEXITSTATUS(status);
977 else
978 ret=-1;
980 return(ret);