Indentation fix, cleanup.
[AROS.git] / tools / cxref / cxref.c
blobde7083d1cad59f8d09e3d6457de30c22191c2231
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 #ifdef __AROS__
30 #define fork vfork
31 #endif
33 /*+ The default value of the CPP command. +*/
34 #ifdef CXREF_CPP
35 #define CPP_COMMAND CXREF_CPP
36 #else
37 #define CPP_COMMAND "gcc -E -C -dD -dI"
38 #endif
40 /*+ The name of the file to read the configuration from. +*/
41 #define CXREF_CONFIG_FILE ".cxref"
44 static void Usage(int verbose);
45 static int ParseConfigFile(void);
46 static int ParseOptions(int nargs,char **args,int fromfile);
48 static int DocumentTheFile(char* name);
49 static FILE* popen_execvp(char** command);
50 static int pclose_execvp(FILE* f);
52 static char** cpp_command; /*+ The actual cpp command that is built up, adding -D, -U and -I options. +*/
53 static int cpp_command_num=0; /*+ The number of arguments to the cpp command. +*/
54 static int cpp_argument_num=0; /*+ The number of arguments to the -CPP argument. +*/
56 /*+ The command line switch that sets the format of the output, +*/
57 int option_all_comments=0, /*+ use all comments. +*/
58 option_verbatim_comments=0, /*+ insert the comments verbatim into the output. +*/
59 option_block_comments=0, /*+ remove the leading block comment marker. +*/
60 option_no_comments=0, /*+ ignore all comments. +*/
61 option_xref=0, /*+ do cross referencing. +*/
62 option_warn=0, /*+ produce warnings. +*/
63 option_index=0, /*+ produce an index. +*/
64 option_raw=0, /*+ produce raw output. +*/
65 option_latex=0, /*+ produce LaTeX output. +*/
66 option_html=0, /*+ produce HTML output. +*/
67 option_rtf=0, /*+ produce RTF output. +*/
68 option_sgml=0; /*+ produce SGML output. +*/
70 /*+ The option to control the mode of operation. +*/
71 static int option_delete=0;
73 /*+ The command line switch for the output name, +*/
74 char *option_odir=NULL, /*+ the directory to use. +*/
75 *option_name=NULL, /*+ the base part of the name. +*/
76 *option_root=NULL; /*+ the source tree root directory. +*/
78 /*+ The name of the include directories specified on the command line. +*/
79 char **option_incdirs=NULL;
81 /*+ The information about the cxref run, +*/
82 char *run_command=NULL, /*+ the command line options. +*/
83 *run_cpp_command=NULL; /*+ the cpp command and options. +*/
85 /*+ The number of include directories on the command line. +*/
86 int option_nincdirs=0;
88 /*+ The names of the files to process. +*/
89 static char **option_files=NULL;
91 /*+ The number of files to process. +*/
92 static int option_nfiles=0;
94 /*+ The current file that is being processed. +*/
95 File CurFile=NULL;
98 /*++++++++++++++++++++++++++++++++++++++
99 The main function that calls the parser.
101 int main Returns the status, zero for normal termination, else an error.
103 int argc The command line number of arguments.
105 char** argv The actual command line arguments
106 ++++++++++++++++++++++++++++++++++++++*/
108 int main(int argc,char** argv)
110 int i;
111 char *root_prefix=NULL;
112 char here[PATH_MAX+1],there[PATH_MAX+1];
114 if(argc==1)
115 Usage(1);
117 /* Setup the variables. */
119 cpp_command=(char**)Malloc(8*sizeof(char*));
120 cpp_command[cpp_command_num++]=MallocString(CPP_COMMAND);
122 for(i=1;cpp_command[cpp_command_num-1][i];i++)
123 if(cpp_command[cpp_command_num-1][i]==' ')
125 cpp_command[cpp_command_num-1][i]=0;
126 if((cpp_command_num%8)==6)
127 cpp_command=(char**)Realloc(cpp_command,(cpp_command_num+10)*sizeof(char*));
128 cpp_command[cpp_command_num]=MallocString(&cpp_command[cpp_command_num-1][i+1]);
129 cpp_command_num++;
130 i=1;
133 cpp_argument_num=cpp_command_num;
135 option_incdirs=(char**)Malloc(8*sizeof(char*));
136 option_incdirs[0]=MallocString(".");
137 option_nincdirs=1;
139 option_odir=MallocString(".");
141 option_name=MallocString("cxref");
143 option_files=(char**)Malloc(8*sizeof(char*));
145 run_command=argv[0];
147 /* Parse the command line options. */
149 if(ParseOptions(argc-1,&argv[1],0))
150 Usage(0);
152 /* Parse the options in .cxref in this directory. */
154 if(ParseConfigFile())
155 Usage(0);
157 /* Change directory. */
159 if(option_root)
161 if(!getcwd(there,PATH_MAX))
162 {fprintf(stderr,"cxref: Error cannot get current working directory (1).\n");exit(1);}
163 if(chdir(option_root))
164 {fprintf(stderr,"cxref: Error cannot change directory to '%s'.\n",option_root);exit(1);}
167 if(!getcwd(here,PATH_MAX))
168 {fprintf(stderr,"cxref: Error cannot get current working directory (2).\n");exit(1);}
170 if(option_root)
172 if(!strcmp(here,there))
173 root_prefix=".";
174 else if(!strcmp(here,"/"))
175 root_prefix=there+1;
176 else if(!strncmp(here,there,strlen(here)))
177 root_prefix=there+strlen(here)+1;
178 else
179 {fprintf(stderr,"cxref: Error the -R option has not specified a parent directory of the current one.\n");exit(1);}
182 /* Modify the -I options for the new root directory. */
184 for(i=1;i<cpp_command_num;i++)
185 if(cpp_command[i][0]=='-' && cpp_command[i][1]=='I')
187 if(cpp_command[i][2]==0)
189 char *old=cpp_command[++i];
190 if(cpp_command[i][0]!='/' && root_prefix)
191 cpp_command[i]=MallocString(CanonicaliseName(ConcatStrings(3,root_prefix,"/",cpp_command[i])));
192 else if(cpp_command[i][0]=='/' && !strcmp(cpp_command[i],here))
193 cpp_command[i]=MallocString(".");
194 else if(cpp_command[i][0]=='/' && !strcmp(here,"/"))
195 cpp_command[i]=MallocString(cpp_command[i]+1);
196 else if(cpp_command[i][0]=='/' && !strncmp(cpp_command[i],here,strlen(here)))
197 cpp_command[i]=MallocString(cpp_command[i]+strlen(here)+1);
198 else
199 cpp_command[i]=MallocString(CanonicaliseName(cpp_command[i]));
200 Free(old);
202 else
204 char *old=cpp_command[i];
205 if(cpp_command[i][2]!='/' && root_prefix)
206 cpp_command[i]=MallocString(ConcatStrings(2,"-I",CanonicaliseName(ConcatStrings(3,root_prefix,"/",cpp_command[i]+2))));
207 else if(cpp_command[i][2]=='/' && !strcmp(&cpp_command[i][2],here))
208 cpp_command[i]=MallocString("-I.");
209 else if(cpp_command[i][2]=='/' && !strcmp(here,"/"))
210 cpp_command[i]=MallocString(ConcatStrings(2,"-I",cpp_command[i]+2+1));
211 else if(cpp_command[i][2]=='/' && !strncmp(&cpp_command[i][2],here,strlen(here)))
212 cpp_command[i]=MallocString(ConcatStrings(2,"-I",cpp_command[i]+2+strlen(here)+1));
213 else
214 cpp_command[i]=MallocString(ConcatStrings(2,"-I",CanonicaliseName(cpp_command[i]+2)));
215 Free(old);
219 for(i=0;i<option_nincdirs;i++)
221 char *old=option_incdirs[i];
222 if(*option_incdirs[i]!='/' && root_prefix)
223 option_incdirs[i]=MallocString(CanonicaliseName(ConcatStrings(3,root_prefix,"/",option_incdirs[i])));
224 else if(*option_incdirs[i]=='/' && !strcmp(option_incdirs[i],here))
225 option_incdirs[i]=MallocString(".");
226 else if(*option_incdirs[i]=='/' && !strcmp(here,"/"))
227 option_incdirs[i]=MallocString(option_incdirs[i]+strlen(here)+1);
228 else if(*option_incdirs[i]=='/' && !strncmp(option_incdirs[i],here,strlen(here)))
229 option_incdirs[i]=MallocString(option_incdirs[i]+strlen(here)+1);
230 else
231 option_incdirs[i]=MallocString(CanonicaliseName(option_incdirs[i]));
232 Free(old);
235 /* Parse the options in .cxref in the root directory. */
237 if(option_root)
238 if(ParseConfigFile())
239 Usage(0);
241 run_command=MallocString(run_command);
243 run_cpp_command=cpp_command[0];
244 for(i=1;i<cpp_command_num;i++)
245 run_cpp_command=ConcatStrings(3,run_cpp_command," ",cpp_command[i]);
247 run_cpp_command=MallocString(run_cpp_command);
249 TidyMemory();
251 /* Check the options for validity */
253 if(option_warn&WARN_XREF && !option_xref)
254 fprintf(stderr,"cxref: Warning using '-warn-xref' without '-xref'.\n");
256 /* Process each file. */
258 if(option_files)
259 for(i=0;i<option_nfiles;i++)
261 char *filename=CanonicaliseName(root_prefix?ConcatStrings(3,root_prefix,"/",option_files[i]):option_files[i]);
263 if(!strncmp(filename,"../",3) || *filename=='/')
264 fprintf(stderr,"cxref: Error the file %s is outside the cxref root directory.\n",filename);
265 else if(!option_delete)
267 CurFile=NewFile(filename);
269 ResetLexer();
270 ResetParser();
272 if(!DocumentTheFile(filename))
274 if(option_xref)
275 CrossReference(CurFile,option_warn||option_raw||option_latex||option_html||option_rtf||option_sgml);
277 if(option_raw || option_warn)
278 WriteWarnRawFile(CurFile);
279 if(option_latex)
280 WriteLatexFile(CurFile);
281 if(option_html)
282 WriteHTMLFile(CurFile);
283 if(option_rtf)
284 WriteRTFFile(CurFile);
285 if(option_sgml)
286 WriteSGMLFile(CurFile);
289 ResetLexer();
290 ResetParser();
291 ResetPreProcAnalyser();
292 ResetTypeAnalyser();
293 ResetVariableAnalyser();
294 ResetFunctionAnalyser();
296 DeleteComment();
298 DeleteFile(CurFile);
299 CurFile=NULL;
301 else
303 CrossReferenceDelete(filename);
305 WriteLatexFileDelete(filename);
306 WriteHTMLFileDelete(filename);
307 WriteRTFFileDelete(filename);
308 WriteSGMLFileDelete(filename);
311 TidyMemory();
314 /* Create the index */
316 if(option_index)
318 StringList files;
319 StringList2 funcs,vars,types;
321 files=NewStringList();
322 funcs=NewStringList2();
323 vars=NewStringList2();
324 types=NewStringList2();
326 CreateAppendix(files,funcs,vars,types);
328 if(option_raw||option_warn)
329 WriteWarnRawAppendix(files,funcs,vars,types);
330 if(option_latex)
331 WriteLatexAppendix(files,funcs,vars,types);
332 if(option_html)
333 WriteHTMLAppendix(files,funcs,vars,types);
334 if(option_rtf)
335 WriteRTFAppendix(files,funcs,vars,types);
336 if(option_sgml)
337 WriteSGMLAppendix(files,funcs,vars,types);
339 DeleteStringList(files);
340 DeleteStringList2(funcs);
341 DeleteStringList2(vars);
342 DeleteStringList2(types);
344 TidyMemory();
347 /* Tidy up */
349 Free(option_odir);
350 Free(option_name);
351 if(option_root)
352 Free(option_root);
354 for(i=0;i<cpp_command_num;i++)
355 Free(cpp_command[i]);
356 Free(cpp_command);
358 for(i=0;i<option_nincdirs;i++)
359 Free(option_incdirs[i]);
360 Free(option_incdirs);
362 for(i=0;i<option_nfiles;i++)
363 Free(option_files[i]);
364 Free(option_files);
366 Free(run_command);
367 Free(run_cpp_command);
369 PrintMemoryStatistics();
371 return(0);
375 /*++++++++++++++++++++++++++++++++++++++
376 Print out the usage instructions.
378 int verbose If true then output a long version of the information.
379 ++++++++++++++++++++++++++++++++++++++*/
381 static void Usage(int verbose)
383 fputs("\n"
384 " C Cross Referencing & Documenting tool - Version 1.5g\n"
385 " -----------------------------------------------------\n"
386 "\n"
387 "(c) Andrew M. Bishop 1995,96,97,98,99, [ amb@gedanken.demon.co.uk ]\n"
388 " 2000,01,02,03,04 [http://www.gedanken.demon.co.uk/cxref/]\n"
389 "\n"
390 "Usage: cxref filename [ ... filename]\n"
391 " [-Odirname] [-Nbasename] [-Rdirname]\n"
392 " [-all-comments] [-no-comments]\n"
393 " [-verbatim-comments] [-block-comments]\n"
394 " [-xref[-all][-file][-func][-var][-type]]\n"
395 " [-warn[-all][-comment][-xref]]\n"
396 " [-index[-all][-file][-func][-var][-type]]\n"
397 " [-latex209|-latex2e] [-html20|-html32] [-rtf] [-sgml] [-raw]\n"
398 " [-Idirname] [-Ddefine] [-Udefine]\n"
399 " [-CPP cpp_program] [-- cpp_arg [ ... cpp_arg]]\n"
400 "\n"
401 "Usage: cxref filename [ ... filename] -delete\n"
402 " [-Odirname] [-Nbasename] [-Rdirname]\n"
403 "\n",
404 stderr);
406 if(verbose)
407 fputs("filename ... : Files to document.\n"
408 "-delete : Delete all references to the named files.\n"
409 "\n"
410 "-Odirname : The output directory for the documentation.\n"
411 "-Nbasename : The base filename for the output documentation.\n"
412 "-Rdirname : The root directory of the source tree.\n"
413 "\n"
414 "-all-comments : Use all comments.\n"
415 "-verbatim-comments : Insert the comments verbatim in the output.\n"
416 "-block-comments : The comments are in block style.\n"
417 "-no-comments : Ignore all of the comments.\n"
418 "\n"
419 "-xref[-*] : Do cross referencing (of specified types).\n"
420 "-warn[-*] : Produce warnings (of comments or cross references).\n"
421 "\n"
422 "-index[-*] : Produce a cross reference index (of specified types).\n"
423 "\n"
424 "-latex209 | -latex2e : Produce LaTeX output (version 2.09 or 2e - default=2e).\n"
425 "-html20 | -html32 : Produce HTML output (version 2.0 or 3.2 - default=3.2).\n"
426 "-rtf : Produce RTF output (version 1.x).\n"
427 "-sgml : Produce SGML output (for SGML tools version 1.0.x).\n"
428 "-raw : Produce raw output .\n"
429 "\n"
430 "-I*, -D*, -U* : The usual compiler switches.\n"
431 "-CPP cpp_program : The cpp program to use.\n"
432 " : (default '" CPP_COMMAND "')\n"
433 "-- cpp_arg ... : All arguments after the '--' are passed to cpp.\n"
434 "\n"
435 "The file .cxref in the current directory can also contain any of these arguments\n"
436 "one per line, (except for filename and -delete).\n",
437 stderr);
438 else
439 fputs("Run cxref with no arguments to get more verbose help\n",
440 stderr);
442 exit(1);
446 /*++++++++++++++++++++++++++++++++++++++
447 Read in the options from the configuration file.
449 int ParseConfigFile Returns the value returned by ParseOptions().
450 ++++++++++++++++++++++++++++++++++++++*/
452 static int ParseConfigFile(void)
454 FILE *file=fopen(CXREF_CONFIG_FILE,"r");
455 char **lines=NULL;
456 int nlines=0;
457 char data[257];
459 if(file)
461 while(fgets(data,256,file))
463 char *d=data+strlen(data)-1;
465 if(*data=='#')
466 continue;
468 while(d>=data && (*d=='\r' || *d=='\n' || *d==' '))
469 *d--=0;
471 if(d<data)
472 continue;
474 if(!lines)
475 lines=(char**)Malloc(8*sizeof(char*));
476 else if((nlines%8)==7)
477 lines=(char**)Realloc(lines,(nlines+9)*sizeof(char*));
479 if((!strncmp(data,"-I",2) || !strncmp(data,"-D",2) || !strncmp(data,"-U",2) ||
480 !strncmp(data,"-O",2) || !strncmp(data,"-N",2) || !strncmp(data,"-R",2)) &&
481 (data[2]==' ' || data[2]=='\t'))
483 int i=2;
484 while(data[i]==' ' || data[i]=='\t')
485 data[i++]=0;
486 lines[nlines++]=CopyString(data);
487 lines[nlines++]=CopyString(data+i);
489 else if(!strncmp(data,"-CPP",4) &&
490 (data[4]==' ' || data[4]=='\t'))
492 int i=4;
493 while(data[i]==' ' || data[i]=='\t')
494 data[i++]=0;
495 lines[nlines++]=CopyString(data);
496 lines[nlines++]=CopyString(data+i);
498 else
499 if(*data)
500 lines[nlines++]=CopyString(data);
503 if(nlines)
505 int n_files=option_nfiles;
507 if(ParseOptions(nlines,lines,1))
509 fprintf(stderr,"cxref: Error parsing the .cxref file\n");
510 return(1);
513 Free(lines);
515 if(n_files!=option_nfiles)
517 for(;n_files<option_nfiles;n_files++)
518 fprintf(stderr,"cxref: File names '%s' only allowed on command line.\n",option_files[n_files]);
519 return(1);
523 fclose(file);
526 return(0);
530 /*++++++++++++++++++++++++++++++++++++++
531 Parse the options from the command line or from the .cxref file.
533 int ParseOptions Return 1 if there is an error.
535 int nargs The number of arguments.
537 char **args The actual arguments
539 int fromfile A flag indicating that they are read from the .cxref file.
540 ++++++++++++++++++++++++++++++++++++++*/
542 static int ParseOptions(int nargs,char **args,int fromfile)
544 int i,end_of_args=0;
546 for(i=0;i<nargs;i++)
548 if(end_of_args)
550 if((cpp_command_num%8)==6)
551 cpp_command=(char**)Realloc(cpp_command,(cpp_command_num+10)*sizeof(char*));
552 cpp_command[cpp_command_num++]=MallocString(args[i]);
553 run_command=ConcatStrings(3,run_command," ",args[i]);
554 continue;
557 if(!strncmp(args[i],"-I",2) || !strncmp(args[i],"-D",2) || !strncmp(args[i],"-U",2))
559 char *incdir=NULL;
560 if((cpp_command_num%8)==6)
561 cpp_command=(char**)Realloc(cpp_command,(cpp_command_num+10)*sizeof(char*));
562 cpp_command[cpp_command_num++]=MallocString(args[i]);
563 if(args[i][2]==0)
565 if(args[i][1]=='I')
566 incdir=args[i+1];
567 if(i==nargs-1)
568 {fprintf(stderr,"cxref: The -%c option requires a following argument.\n",args[i][1]);return(1);}
569 if((cpp_command_num%8)==6)
570 cpp_command=(char**)Realloc(cpp_command,(cpp_command_num+10)*sizeof(char*));
571 run_command=ConcatStrings(3,run_command," ",args[i]);
572 cpp_command[cpp_command_num++]=MallocString(args[++i]);
574 else
575 if(args[i][1]=='I')
576 incdir=&args[i][2];
578 if(incdir)
580 if((option_nincdirs%8)==0)
581 option_incdirs=(char**)Realloc(option_incdirs,(option_nincdirs+8)*sizeof(char*));
582 option_incdirs[option_nincdirs++]=MallocString(incdir);
585 run_command=ConcatStrings(3,run_command," ",args[i]);
586 continue;
589 if(!strcmp(args[i],"-CPP"))
591 char **old=cpp_command,*command;
592 int j,old_com_num=cpp_command_num,old_arg_num=cpp_argument_num;
594 if(i==nargs-1)
595 {fprintf(stderr,"cxref: The -CPP option requires a following argument.\n");return(1);}
596 command=args[++i];
598 cpp_command_num=0;
599 cpp_command=(char**)Malloc(8*sizeof(char*));
600 cpp_command[cpp_command_num++]=MallocString(command);
602 for(j=1;cpp_command[cpp_command_num-1][j];j++)
603 if(cpp_command[cpp_command_num-1][j]==' ')
605 cpp_command[cpp_command_num-1][j]=0;
606 if((cpp_command_num%8)==6)
607 cpp_command=(char**)Realloc(cpp_command,(cpp_command_num+10)*sizeof(char*));
608 cpp_command[cpp_command_num]=MallocString(&cpp_command[cpp_command_num-1][j+1]);
609 cpp_command_num++;
610 j=1;
613 cpp_argument_num=cpp_command_num;
615 for(j=old_arg_num;j<old_com_num;j++)
617 if((cpp_command_num%8)==6)
618 cpp_command=(char**)Realloc(cpp_command,(cpp_command_num+10)*sizeof(char*));
619 cpp_command[cpp_command_num++]=old[j];
622 for(j=0;j<old_arg_num;j++)
623 Free(old[j]);
624 Free(old);
626 run_command=ConcatStrings(4,run_command,"-CPP \"",args[i],"\"");
627 continue;
630 if(!strncmp(args[i],"-O",2))
632 if(option_odir)
633 Free(option_odir);
634 if(args[i][2]==0)
636 if(i==nargs-1)
637 {fprintf(stderr,"cxref: The -O option requires a following argument.\n");return(1);}
638 run_command=ConcatStrings(3,run_command," ",args[i]);
639 option_odir=MallocString(args[++i]);
641 else
642 option_odir=MallocString(&args[i][2]);
643 run_command=ConcatStrings(3,run_command," ",args[i]);
644 continue;
647 if(!strncmp(args[i],"-N",2))
649 if(option_name)
650 Free(option_name);
651 if(args[i][2]==0)
653 if(i==nargs-1)
654 {fprintf(stderr,"cxref: The -N option requires a following argument.\n");return(1);}
655 run_command=ConcatStrings(3,run_command," ",args[i]);
656 option_name=MallocString(args[++i]);
658 else
659 option_name=MallocString(&args[i][2]);
660 run_command=ConcatStrings(3,run_command," ",args[i]);
661 continue;
664 if(!strncmp(args[i],"-R",2))
666 if(option_root)
667 Free(option_root);
668 if(args[i][2]==0)
670 if(i==nargs-1)
671 {fprintf(stderr,"cxref: The -R option requires a following argument.\n");return(1);}
672 run_command=ConcatStrings(3,run_command," ",args[i]);
673 option_root=MallocString(args[++i]);
675 else
676 option_root=MallocString(&args[i][2]);
677 if(*option_root=='.' && !*(option_root+1))
678 option_root=NULL;
679 run_command=ConcatStrings(3,run_command," ",args[i]);
680 continue;
683 if(!strcmp(args[i],"-delete"))
684 {if(fromfile) {fprintf(stderr,"cxref: The -delete option cannot be used in the .cxref file.\n");return(1);}
685 option_delete=1; run_command=ConcatStrings(3,run_command," ",args[i]); continue;}
687 if(!strcmp(args[i],"-all-comments"))
688 {option_all_comments=1; run_command=ConcatStrings(3,run_command," ",args[i]); continue;}
690 if(!strcmp(args[i],"-verbatim-comments"))
691 {option_verbatim_comments=1; run_command=ConcatStrings(3,run_command," ",args[i]); continue;}
693 if(!strcmp(args[i],"-block-comments"))
694 {option_block_comments=1; run_command=ConcatStrings(3,run_command," ",args[i]); continue;}
696 if(!strcmp(args[i],"-no-comments"))
697 {option_no_comments=1; run_command=ConcatStrings(3,run_command," ",args[i]); continue;}
699 if(!strncmp(args[i],"-xref",5))
701 char* p=&args[i][5];
703 if(!*p)
704 option_xref=XREF_ALL;
705 else
706 while(*p)
708 if(!strncmp(p,"-all" ,4)) {option_xref|=XREF_ALL ; p=&p[4]; continue;}
709 if(!strncmp(p,"-file",5)) {option_xref|=XREF_FILE; p=&p[5]; continue;}
710 if(!strncmp(p,"-func",5)) {option_xref|=XREF_FUNC; p=&p[5]; continue;}
711 if(!strncmp(p,"-var" ,4)) {option_xref|=XREF_VAR ; p=&p[4]; continue;}
712 if(!strncmp(p,"-type",5)) {option_xref|=XREF_TYPE; p=&p[5]; continue;}
713 break;
716 run_command=ConcatStrings(3,run_command," ",args[i]);
717 continue;
720 if(!strncmp(args[i],"-warn",5))
722 char* p=&args[i][5];
724 if(!*p)
725 option_warn=WARN_ALL;
726 else
727 while(*p)
729 if(!strncmp(p,"-all" ,4)) {option_warn|=WARN_ALL ; p=&p[4]; continue;}
730 if(!strncmp(p,"-comment",8)) {option_warn|=WARN_COMMENT; p=&p[8]; continue;}
731 if(!strncmp(p,"-xref" ,5)) {option_warn|=WARN_XREF ; p=&p[5]; continue;}
732 break;
735 run_command=ConcatStrings(3,run_command," ",args[i]);
736 continue;
739 if(!strncmp(args[i],"-index",6))
741 char* p=&args[i][6];
743 if(!*p)
744 option_index=INDEX_ALL;
745 else
746 while(*p)
748 if(!strncmp(p,"-all" ,4)) {option_index|=INDEX_ALL ; p=&p[4]; continue;}
749 if(!strncmp(p,"-file",5)) {option_index|=INDEX_FILE; p=&p[5]; continue;}
750 if(!strncmp(p,"-func",5)) {option_index|=INDEX_FUNC; p=&p[5]; continue;}
751 if(!strncmp(p,"-var" ,4)) {option_index|=INDEX_VAR ; p=&p[4]; continue;}
752 if(!strncmp(p,"-type",5)) {option_index|=INDEX_TYPE; p=&p[5]; continue;}
753 break;
756 run_command=ConcatStrings(3,run_command," ",args[i]);
757 continue;
760 if(!strcmp(args[i],"-raw"))
761 {option_raw=1; run_command=ConcatStrings(3,run_command," ",args[i]); continue;}
763 if(!strcmp(args[i],"-latex209"))
764 {option_latex=1; run_command=ConcatStrings(3,run_command," ",args[i]); continue;}
765 if(!strcmp(args[i],"-latex2e") || !strcmp(args[i],"-latex"))
766 {option_latex=2; run_command=ConcatStrings(3,run_command," ",args[i]); continue;}
768 if(!strncmp(args[i],"-html20",7))
769 {option_html=1; if(!strcmp(args[i]+7,"-src"))option_html+=16;
770 run_command=ConcatStrings(3,run_command," ",args[i]); continue;}
771 if(!strncmp(args[i],"-html32",7))
772 {option_html=2; if(!strcmp(args[i]+7,"-src"))option_html+=16;
773 run_command=ConcatStrings(3,run_command," ",args[i]); continue;}
774 if(!strncmp(args[i],"-html",5))
775 {option_html=2; if(!strcmp(args[i]+5,"-src"))option_html+=16;
776 run_command=ConcatStrings(3,run_command," ",args[i]); continue;}
778 if(!strcmp(args[i],"-rtf"))
779 {option_rtf=1; run_command=ConcatStrings(3,run_command," ",args[i]); continue;}
781 if(!strcmp(args[i],"-sgml"))
782 {option_sgml=1; run_command=ConcatStrings(3,run_command," ",args[i]); continue;}
784 if(!strcmp(args[i],"--"))
785 {end_of_args=1; run_command=ConcatStrings(3,run_command," ",args[i]); continue;}
787 if(args[i][0]=='-')
788 {fprintf(stderr,"cxref: Unknown option '%s'.\n",args[i]);return(1);}
790 if(fromfile)
791 {fprintf(stderr,"cxref: File names '%s' only allowed on command line.\n",args[i]);return(1);}
793 if(option_files && (option_nfiles%8)==0)
794 option_files=(char**)Realloc(option_files,(option_nfiles+8)*sizeof(char*));
795 option_files[option_nfiles++]=MallocString(args[i]);
798 return(0);
802 /*++++++++++++++++++++++++++++++++++++++
803 Canonicalise a file name by removing '/../', '/./' and '//' references.
805 char *CanonicaliseName Returns the argument modified.
807 char *name The original name
809 The same function is used in WWWOFFLE and cxref with changes for files or URLs.
810 ++++++++++++++++++++++++++++++++++++++*/
812 char *CanonicaliseName(char *name)
814 char *match,*name2;
816 match=name;
817 while((match=strstr(match,"/./")) || !strncmp(match=name,"./",2))
819 char *prev=match, *next=match+2;
820 while((*prev++=*next++));
823 match=name;
824 while((match=strstr(match,"//")))
826 char *prev=match, *next=match+1;
827 while((*prev++=*next++));
830 match=name2=name;
831 while((match=strstr(match,"/../")))
833 char *prev=match, *next=match+4;
834 if((prev-name2)==2 && !strncmp(name2,"../",3))
835 {name2+=3;match++;continue;}
836 while(prev>name2 && *--prev!='/');
837 match=prev;
838 if(*prev=='/')prev++;
839 while((*prev++=*next++));
842 match=&name[strlen(name)-2];
843 if(match>=name && !strcmp(match,"/."))
844 *match=0;
846 match=&name[strlen(name)-3];
847 if(match>=name && !strcmp(match,"/.."))
849 if(match==name)
850 *++match=0;
851 else
852 while(match>name && *--match!='/')
853 *match=0;
856 #if 1 /* as used in cxref */
858 match=&name[strlen(name)-1];
859 if(match>name && !strcmp(match,"/"))
860 *match=0;
862 if(!*name)
863 *name='.',*(name+1)=0;
865 #else /* as used in wwwoffle */
867 if(!*name || !strncmp(name,"../",3))
868 *name='/',*(name+1)=0;
870 #endif
872 return(name);
876 /*++++++++++++++++++++++++++++++++++++++
877 Calls CPP for the file to get all of the needed information.
879 int DocumentTheFile Returns 1 in case of error, else 0.
881 char* name The name of the file to document.
883 The CPP is started as a sub-process, (using popen to return a FILE* for lex to use).
884 ++++++++++++++++++++++++++++++++++++++*/
886 static int DocumentTheFile(char* name)
888 struct stat stat_buf;
889 int error1,error2;
890 static int first=1;
892 if(stat(name,&stat_buf)==-1)
893 {fprintf(stderr,"cxref: Cannot access the file '%s'\n",name);return(1);}
895 cpp_command[cpp_command_num ]=name;
896 cpp_command[cpp_command_num+1]=NULL;
898 yyin=popen_execvp(cpp_command);
900 if(!yyin)
901 {fprintf(stderr,"cxref: Failed to start the cpp command '%s'\n",cpp_command[0]);exit(1);}
903 if(!first)
904 yyrestart(yyin);
905 first=0;
907 #if YYDEBUG
908 yydebug=(YYDEBUG==3);
909 #endif
911 error1=yyparse();
913 error2=pclose_execvp(yyin);
915 if(error2)
916 fprintf(stderr,"cxref: The preprocessor exited abnormally on '%s'\n",name);
918 return(error1||error2);
922 /*+ The process id of the pre-processor. +*/
923 static pid_t popen_pid;
925 /*++++++++++++++++++++++++++++++++++++++
926 A popen function that takes a list of arguments not a string.
928 FILE* popen_execvp Returns a file descriptor.
930 char** command The command arguments.
931 ++++++++++++++++++++++++++++++++++++++*/
933 static FILE* popen_execvp(char** command)
935 int fdr[2];
937 if(pipe(fdr)==-1)
938 {fprintf(stderr,"cxref: Can not pipe for the cpp command '%s'.\n",command[0]);exit(1);}
940 if((popen_pid=fork())==-1)
941 {fprintf(stderr,"cxref: Can not fork for the cpp command '%s.\n",command[0]);exit(1);}
943 if(popen_pid) /* The parent */
945 close(fdr[1]);
947 else /* The child */
949 close(1);
950 dup(fdr[1]);
951 close(fdr[1]);
953 close(fdr[0]);
955 execvp(command[0],command);
956 fprintf(stderr,"cxref: Can not execvp for the cpp command '%s', is it on the path?\n",command[0]);
957 exit(1);
960 return(fdopen(fdr[0],"r"));
964 /*++++++++++++++++++++++++++++++++++++++
965 Close the file to the to the preprocessor
967 int pclose_execvp Return the error status.
969 FILE* f The file to close.
970 ++++++++++++++++++++++++++++++++++++++*/
972 static int pclose_execvp(FILE* f)
974 int status,ret;
976 waitpid(popen_pid,&status,0);
977 fclose(f);
979 if(WIFEXITED(status))
980 ret=WEXITSTATUS(status);
981 else
982 ret=-1;
984 return(ret);