1 /***************************************
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 ***************************************/
19 #include <sys/types.h>
33 /*+ The default value of the CPP command. +*/
35 #define CPP_COMMAND CXREF_CPP
37 #define CPP_COMMAND "gcc -E -C -dD -dI"
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. +*/
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
)
111 char *root_prefix
=NULL
;
112 char here
[PATH_MAX
+1],there
[PATH_MAX
+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]);
133 cpp_argument_num
=cpp_command_num
;
135 option_incdirs
=(char**)Malloc(8*sizeof(char*));
136 option_incdirs
[0]=MallocString(".");
139 option_odir
=MallocString(".");
141 option_name
=MallocString("cxref");
143 option_files
=(char**)Malloc(8*sizeof(char*));
147 /* Parse the command line options. */
149 if(ParseOptions(argc
-1,&argv
[1],0))
152 /* Parse the options in .cxref in this directory. */
154 if(ParseConfigFile())
157 /* Change directory. */
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);}
172 if(!strcmp(here
,there
))
174 else if(!strcmp(here
,"/"))
176 else if(!strncmp(here
,there
,strlen(here
)))
177 root_prefix
=there
+strlen(here
)+1;
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);
199 cpp_command
[i
]=MallocString(CanonicaliseName(cpp_command
[i
]));
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));
214 cpp_command
[i
]=MallocString(ConcatStrings(2,"-I",CanonicaliseName(cpp_command
[i
]+2)));
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);
231 option_incdirs
[i
]=MallocString(CanonicaliseName(option_incdirs
[i
]));
235 /* Parse the options in .cxref in the root directory. */
238 if(ParseConfigFile())
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
);
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. */
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
);
272 if(!DocumentTheFile(filename
))
275 CrossReference(CurFile
,option_warn
||option_raw
||option_latex
||option_html
||option_rtf
||option_sgml
);
277 if(option_raw
|| option_warn
)
278 WriteWarnRawFile(CurFile
);
280 WriteLatexFile(CurFile
);
282 WriteHTMLFile(CurFile
);
284 WriteRTFFile(CurFile
);
286 WriteSGMLFile(CurFile
);
291 ResetPreProcAnalyser();
293 ResetVariableAnalyser();
294 ResetFunctionAnalyser();
303 CrossReferenceDelete(filename
);
305 WriteLatexFileDelete(filename
);
306 WriteHTMLFileDelete(filename
);
307 WriteRTFFileDelete(filename
);
308 WriteSGMLFileDelete(filename
);
314 /* Create the index */
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
);
331 WriteLatexAppendix(files
,funcs
,vars
,types
);
333 WriteHTMLAppendix(files
,funcs
,vars
,types
);
335 WriteRTFAppendix(files
,funcs
,vars
,types
);
337 WriteSGMLAppendix(files
,funcs
,vars
,types
);
339 DeleteStringList(files
);
340 DeleteStringList2(funcs
);
341 DeleteStringList2(vars
);
342 DeleteStringList2(types
);
354 for(i
=0;i
<cpp_command_num
;i
++)
355 Free(cpp_command
[i
]);
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
]);
367 Free(run_cpp_command
);
369 PrintMemoryStatistics();
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
)
384 " C Cross Referencing & Documenting tool - Version 1.5g\n"
385 " -----------------------------------------------------\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"
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"
401 "Usage: cxref filename [ ... filename] -delete\n"
402 " [-Odirname] [-Nbasename] [-Rdirname]\n"
407 fputs("filename ... : Files to document.\n"
408 "-delete : Delete all references to the named files.\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"
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"
419 "-xref[-*] : Do cross referencing (of specified types).\n"
420 "-warn[-*] : Produce warnings (of comments or cross references).\n"
422 "-index[-*] : Produce a cross reference index (of specified types).\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"
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"
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",
439 fputs("Run cxref with no arguments to get more verbose help\n",
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");
461 while(fgets(data
,256,file
))
463 char *d
=data
+strlen(data
)-1;
468 while(d
>=data
&& (*d
=='\r' || *d
=='\n' || *d
==' '))
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'))
484 while(data
[i
]==' ' || data
[i
]=='\t')
486 lines
[nlines
++]=CopyString(data
);
487 lines
[nlines
++]=CopyString(data
+i
);
489 else if(!strncmp(data
,"-CPP",4) &&
490 (data
[4]==' ' || data
[4]=='\t'))
493 while(data
[i
]==' ' || data
[i
]=='\t')
495 lines
[nlines
++]=CopyString(data
);
496 lines
[nlines
++]=CopyString(data
+i
);
500 lines
[nlines
++]=CopyString(data
);
505 int n_files
=option_nfiles
;
507 if(ParseOptions(nlines
,lines
,1))
509 fprintf(stderr
,"cxref: Error parsing the .cxref file\n");
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
]);
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
)
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
]);
557 if(!strncmp(args
[i
],"-I",2) || !strncmp(args
[i
],"-D",2) || !strncmp(args
[i
],"-U",2))
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
]);
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
]);
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
]);
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
;
595 {fprintf(stderr
,"cxref: The -CPP option requires a following argument.\n");return(1);}
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]);
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
++)
626 run_command
=ConcatStrings(4,run_command
,"-CPP \"",args
[i
],"\"");
630 if(!strncmp(args
[i
],"-O",2))
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
]);
642 option_odir
=MallocString(&args
[i
][2]);
643 run_command
=ConcatStrings(3,run_command
," ",args
[i
]);
647 if(!strncmp(args
[i
],"-N",2))
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
]);
659 option_name
=MallocString(&args
[i
][2]);
660 run_command
=ConcatStrings(3,run_command
," ",args
[i
]);
664 if(!strncmp(args
[i
],"-R",2))
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
]);
676 option_root
=MallocString(&args
[i
][2]);
677 if(*option_root
=='.' && !*(option_root
+1))
679 run_command
=ConcatStrings(3,run_command
," ",args
[i
]);
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))
704 option_xref
=XREF_ALL
;
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;}
716 run_command
=ConcatStrings(3,run_command
," ",args
[i
]);
720 if(!strncmp(args
[i
],"-warn",5))
725 option_warn
=WARN_ALL
;
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;}
735 run_command
=ConcatStrings(3,run_command
," ",args
[i
]);
739 if(!strncmp(args
[i
],"-index",6))
744 option_index
=INDEX_ALL
;
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;}
756 run_command
=ConcatStrings(3,run_command
," ",args
[i
]);
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;}
788 {fprintf(stderr
,"cxref: Unknown option '%s'.\n",args
[i
]);return(1);}
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
]);
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
)
817 while((match
=strstr(match
,"/./")) || !strncmp(match
=name
,"./",2))
819 char *prev
=match
, *next
=match
+2;
820 while((*prev
++=*next
++));
824 while((match
=strstr(match
,"//")))
826 char *prev
=match
, *next
=match
+1;
827 while((*prev
++=*next
++));
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
!='/');
838 if(*prev
=='/')prev
++;
839 while((*prev
++=*next
++));
842 match
=&name
[strlen(name
)-2];
843 if(match
>=name
&& !strcmp(match
,"/."))
846 match
=&name
[strlen(name
)-3];
847 if(match
>=name
&& !strcmp(match
,"/.."))
852 while(match
>name
&& *--match
!='/')
856 #if 1 /* as used in cxref */
858 match
=&name
[strlen(name
)-1];
859 if(match
>name
&& !strcmp(match
,"/"))
863 *name
='.',*(name
+1)=0;
865 #else /* as used in wwwoffle */
867 if(!*name
|| !strncmp(name
,"../",3))
868 *name
='/',*(name
+1)=0;
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
;
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
);
901 {fprintf(stderr
,"cxref: Failed to start the cpp command '%s'\n",cpp_command
[0]);exit(1);}
908 yydebug
=(YYDEBUG
==3);
913 error2
=pclose_execvp(yyin
);
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
)
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 */
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]);
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
)
976 waitpid(popen_pid
,&status
,0);
979 if(WIFEXITED(status
))
980 ret
=WEXITSTATUS(status
);