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>
29 /*+ The default value of the CPP command. +*/
31 #define CPP_COMMAND CXREF_CPP
33 #define CPP_COMMAND "gcc -E -C -dD -dI"
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. +*/
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
)
107 char *root_prefix
=NULL
;
108 char here
[PATH_MAX
+1],there
[PATH_MAX
+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]);
129 cpp_argument_num
=cpp_command_num
;
131 option_incdirs
=(char**)Malloc(8*sizeof(char*));
132 option_incdirs
[0]=MallocString(".");
135 option_odir
=MallocString(".");
137 option_name
=MallocString("cxref");
139 option_files
=(char**)Malloc(8*sizeof(char*));
143 /* Parse the command line options. */
145 if(ParseOptions(argc
-1,&argv
[1],0))
148 /* Parse the options in .cxref in this directory. */
150 if(ParseConfigFile())
153 /* Change directory. */
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);}
168 if(!strcmp(here
,there
))
170 else if(!strcmp(here
,"/"))
172 else if(!strncmp(here
,there
,strlen(here
)))
173 root_prefix
=there
+strlen(here
)+1;
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);
195 cpp_command
[i
]=MallocString(CanonicaliseName(cpp_command
[i
]));
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));
210 cpp_command
[i
]=MallocString(ConcatStrings(2,"-I",CanonicaliseName(cpp_command
[i
]+2)));
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);
227 option_incdirs
[i
]=MallocString(CanonicaliseName(option_incdirs
[i
]));
231 /* Parse the options in .cxref in the root directory. */
234 if(ParseConfigFile())
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
);
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. */
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
);
268 if(!DocumentTheFile(filename
))
271 CrossReference(CurFile
,option_warn
||option_raw
||option_latex
||option_html
||option_rtf
||option_sgml
);
273 if(option_raw
|| option_warn
)
274 WriteWarnRawFile(CurFile
);
276 WriteLatexFile(CurFile
);
278 WriteHTMLFile(CurFile
);
280 WriteRTFFile(CurFile
);
282 WriteSGMLFile(CurFile
);
287 ResetPreProcAnalyser();
289 ResetVariableAnalyser();
290 ResetFunctionAnalyser();
299 CrossReferenceDelete(filename
);
301 WriteLatexFileDelete(filename
);
302 WriteHTMLFileDelete(filename
);
303 WriteRTFFileDelete(filename
);
304 WriteSGMLFileDelete(filename
);
310 /* Create the index */
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
);
327 WriteLatexAppendix(files
,funcs
,vars
,types
);
329 WriteHTMLAppendix(files
,funcs
,vars
,types
);
331 WriteRTFAppendix(files
,funcs
,vars
,types
);
333 WriteSGMLAppendix(files
,funcs
,vars
,types
);
335 DeleteStringList(files
);
336 DeleteStringList2(funcs
);
337 DeleteStringList2(vars
);
338 DeleteStringList2(types
);
350 for(i
=0;i
<cpp_command_num
;i
++)
351 Free(cpp_command
[i
]);
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
]);
363 Free(run_cpp_command
);
365 PrintMemoryStatistics();
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
)
380 " C Cross Referencing & Documenting tool - Version 1.5g\n"
381 " -----------------------------------------------------\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"
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"
397 "Usage: cxref filename [ ... filename] -delete\n"
398 " [-Odirname] [-Nbasename] [-Rdirname]\n"
403 fputs("filename ... : Files to document.\n"
404 "-delete : Delete all references to the named files.\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"
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"
415 "-xref[-*] : Do cross referencing (of specified types).\n"
416 "-warn[-*] : Produce warnings (of comments or cross references).\n"
418 "-index[-*] : Produce a cross reference index (of specified types).\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"
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"
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",
435 fputs("Run cxref with no arguments to get more verbose help\n",
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");
457 while(fgets(data
,256,file
))
459 char *d
=data
+strlen(data
)-1;
464 while(d
>=data
&& (*d
=='\r' || *d
=='\n' || *d
==' '))
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'))
480 while(data
[i
]==' ' || data
[i
]=='\t')
482 lines
[nlines
++]=CopyString(data
);
483 lines
[nlines
++]=CopyString(data
+i
);
485 else if(!strncmp(data
,"-CPP",4) &&
486 (data
[4]==' ' || data
[4]=='\t'))
489 while(data
[i
]==' ' || data
[i
]=='\t')
491 lines
[nlines
++]=CopyString(data
);
492 lines
[nlines
++]=CopyString(data
+i
);
496 lines
[nlines
++]=CopyString(data
);
501 int n_files
=option_nfiles
;
503 if(ParseOptions(nlines
,lines
,1))
505 fprintf(stderr
,"cxref: Error parsing the .cxref file\n");
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
]);
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
)
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
]);
553 if(!strncmp(args
[i
],"-I",2) || !strncmp(args
[i
],"-D",2) || !strncmp(args
[i
],"-U",2))
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
]);
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
]);
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
]);
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
;
591 {fprintf(stderr
,"cxref: The -CPP option requires a following argument.\n");return(1);}
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]);
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
++)
622 run_command
=ConcatStrings(4,run_command
,"-CPP \"",args
[i
],"\"");
626 if(!strncmp(args
[i
],"-O",2))
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
]);
638 option_odir
=MallocString(&args
[i
][2]);
639 run_command
=ConcatStrings(3,run_command
," ",args
[i
]);
643 if(!strncmp(args
[i
],"-N",2))
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
]);
655 option_name
=MallocString(&args
[i
][2]);
656 run_command
=ConcatStrings(3,run_command
," ",args
[i
]);
660 if(!strncmp(args
[i
],"-R",2))
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
]);
672 option_root
=MallocString(&args
[i
][2]);
673 if(*option_root
=='.' && !*(option_root
+1))
675 run_command
=ConcatStrings(3,run_command
," ",args
[i
]);
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))
700 option_xref
=XREF_ALL
;
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;}
712 run_command
=ConcatStrings(3,run_command
," ",args
[i
]);
716 if(!strncmp(args
[i
],"-warn",5))
721 option_warn
=WARN_ALL
;
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;}
731 run_command
=ConcatStrings(3,run_command
," ",args
[i
]);
735 if(!strncmp(args
[i
],"-index",6))
740 option_index
=INDEX_ALL
;
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;}
752 run_command
=ConcatStrings(3,run_command
," ",args
[i
]);
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;}
784 {fprintf(stderr
,"cxref: Unknown option '%s'.\n",args
[i
]);return(1);}
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
]);
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
)
813 while((match
=strstr(match
,"/./")) || !strncmp(match
=name
,"./",2))
815 char *prev
=match
, *next
=match
+2;
816 while((*prev
++=*next
++));
820 while((match
=strstr(match
,"//")))
822 char *prev
=match
, *next
=match
+1;
823 while((*prev
++=*next
++));
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
!='/');
834 if(*prev
=='/')prev
++;
835 while((*prev
++=*next
++));
838 match
=&name
[strlen(name
)-2];
839 if(match
>=name
&& !strcmp(match
,"/."))
842 match
=&name
[strlen(name
)-3];
843 if(match
>=name
&& !strcmp(match
,"/.."))
848 while(match
>name
&& *--match
!='/')
852 #if 1 /* as used in cxref */
854 match
=&name
[strlen(name
)-1];
855 if(match
>name
&& !strcmp(match
,"/"))
859 *name
='.',*(name
+1)=0;
861 #else /* as used in wwwoffle */
863 if(!*name
|| !strncmp(name
,"../",3))
864 *name
='/',*(name
+1)=0;
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
;
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
);
897 {fprintf(stderr
,"cxref: Failed to start the cpp command '%s'\n",cpp_command
[0]);exit(1);}
904 yydebug
=(YYDEBUG
==3);
909 error2
=pclose_execvp(yyin
);
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
)
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 */
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]);
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
)
972 waitpid(popen_pid
,&status
,0);
975 if(WIFEXITED(status
))
976 ret
=WEXITSTATUS(status
);