test/pipe.c: Avoid printing hundreds of thousand output lines.
[AROS.git] / tools / cxref / preproc.c
blobc364aa342f9b2eb2d5615cde79a2a1a2f7bfe440
1 /***************************************
2 $Header$
4 C Cross Referencing & Documentation tool. Version 1.5f.
6 Collects the pre-processing instruction stuff.
7 ******************/ /******************
8 Written by Andrew M. Bishop
10 This file Copyright 1995,96,97,99,2000,01,02,03,04 Andrew M. Bishop
11 It may be distributed under the GNU Public License, version 2, or
12 any higher version. See section COPYING of the GNU Public license
13 for conditions under which this file may be redistributed.
14 ***************************************/
16 /*+ Control the output of debugging information for this file. +*/
17 #define DEBUG 0
19 #include <stdlib.h>
20 #include <stdio.h>
21 #include <string.h>
22 #include <unistd.h>
24 #include <limits.h>
25 #include <sys/stat.h>
27 #include "memory.h"
28 #include "datatype.h"
29 #include "parse-yy.h"
30 #include "cxref.h"
32 /*+ The file that is currently being processed. +*/
33 extern File CurFile;
35 /*+ The name of the include directories specified on the command line. +*/
36 extern char **option_incdirs;
38 /*+ The number of include directories on the command line. +*/
39 extern int option_nincdirs;
41 /*+ When in a header file, this is set to 1, to allow most of the stuff to be skipped. +*/
42 int in_header=0;
44 /*+ The current #include we are looking at. +*/
45 static Include cur_inc=NULL;
47 /*+ The current #define we are looking at. +*/
48 static Define cur_def=NULL;
50 /*+ The depth of includes. +*/
51 static int inc_depth=0;
53 /*+ The type of include at this depth. +*/
54 static char *inc_type=NULL;
56 /*+ The name of the include file at this depth. +*/
57 static char **inc_name=NULL;
59 /*+ The working directory. +*/
60 static char *cwd=NULL;
63 static Include NewIncludeType(char *name);
64 static Define NewDefineType(char *name);
67 /*++++++++++++++++++++++++++++++++++++++
68 Function that is called when an included file is seen in the current file.
70 char *name The name of the file from the source code.
71 ++++++++++++++++++++++++++++++++++++++*/
73 void SeenInclude(char *name)
75 #if DEBUG
76 printf("#Preproc.c# #include %s\n",name);
77 #endif
79 if(!inc_type || inc_depth==0 || (inc_depth > 0 && inc_type[inc_depth-1]==LOCAL))
81 Include inc,*t=&CurFile->includes;
82 int inc_scope=(*name=='"')?LOCAL:GLOBAL;
83 int i;
85 name++;
86 name[strlen(name)-1]=0;
88 if(inc_scope==LOCAL && option_nincdirs)
89 for(i=0;i<option_nincdirs;i++)
91 char *newname=CanonicaliseName(ConcatStrings(3,option_incdirs[i],"/",name));
92 struct stat buf;
94 if(!lstat(newname,&buf))
95 {name=newname;break;}
98 for(i=0;i<inc_depth;i++)
100 while(*t && (*t)->next)
101 t=&(*t)->next;
102 t=&(*t)->includes;
105 inc=NewIncludeType(name);
107 inc->comment=MallocString(GetCurrentComment());
108 inc->scope=inc_scope;
110 AddToLinkedList(*t,Include,inc);
112 cur_inc=inc;
114 else
115 cur_inc=NULL;
119 /*++++++++++++++++++++++++++++++++++++++
120 Function that is called when a comment is seen following a #include.
121 ++++++++++++++++++++++++++++++++++++++*/
123 void SeenIncludeComment(void)
125 char* comment=GetCurrentComment();
127 #if DEBUG
128 printf("#Preproc.c# #include trailing comment '%s' for %s\n",comment,cur_inc->name);
129 #endif
131 if(!cur_inc->comment)
132 cur_inc->comment=MallocString(comment);
136 /*++++++++++++++++++++++++++++++++++++++
137 Function that is called when a change in current file is seen.
139 char *SeenFileChange Returns the filename that we are now in.
141 char *name The pathname of the included file as determined by gcc.
143 int flag The flags that GCC leaves in the file
144 ++++++++++++++++++++++++++++++++++++++*/
146 char *SeenFileChange(char *name,int flag)
148 if(!cwd)
150 cwd=(char*)Malloc(PATH_MAX+1);
151 if(!getcwd(cwd,PATH_MAX))
152 cwd[0]=0;
155 /* Special gcc-3.x fake names for built-in #defines. */
157 /* jmj: the fake names differ from locale to locale, but are always bracketed like this */
158 /* old: if(!strcmp(name,"<built-in>") || !strcmp(name,"<command line>"))*/
159 if (*name == '<' && name[strlen(name) - 1] == '>')
161 in_header=1;
162 return(NULL);
164 else if(flag==-1)
166 in_header=0;
167 return(CurFile->name);
170 name=CanonicaliseName(name);
172 if(!strncmp(name,cwd,strlen(cwd)))
173 name=name+strlen(cwd);
175 if(flag&4)
177 if(inc_depth>=2)
178 name=inc_name[inc_depth-2];
179 else
180 name=CurFile->name;
183 #if DEBUG
184 printf("#Preproc.c# FileChange - %s %s (flag=%d)\n",flag&2?"Included ":"Return to",name,flag);
185 #endif
187 /* Store the information. */
189 if(flag&2 && (!inc_type || inc_depth==0 || (inc_depth > 0 && inc_type[inc_depth-1]==LOCAL)))
191 if(!cur_inc)
193 if(flag&8)
194 SeenInclude(ConcatStrings(3,"<",name,">"));
195 else
196 SeenInclude(ConcatStrings(3,"\"",name,"\""));
198 else if(!(flag&8))
200 Free(cur_inc->name);
201 cur_inc->name=MallocString(name);
205 if(flag&2)
207 inc_depth++;
209 if(!inc_type)
211 inc_type=(char*)Malloc(16);
212 inc_name=(char**)Malloc(16*sizeof(char*));
214 else
215 if(!(inc_depth%16))
217 inc_type=(char*)Realloc(inc_type,(unsigned)(inc_depth+16));
218 inc_name=(char**)Realloc(inc_name,(unsigned)(sizeof(char*)*(inc_depth+16)));
221 if(inc_depth>1 && inc_type[inc_depth-2]==GLOBAL)
222 inc_type[inc_depth-1]=GLOBAL;
223 else if (inc_depth > 0)
224 inc_type[inc_depth-1]=cur_inc?cur_inc->scope:(flag&8)?GLOBAL:LOCAL;
226 inc_name[inc_depth-1]=CopyString(name);
228 else
229 inc_depth--;
231 if(inc_type && inc_depth>0)
232 in_header=inc_type[inc_depth-1];
233 else
234 in_header=0;
236 SetCurrentComment(NULL);
238 cur_inc=NULL;
240 return(name);
244 /*++++++++++++++++++++++++++++++++++++++
245 Function that is called when a #define is seen in the current file.
247 char* name The name of the #defined symbol.
248 ++++++++++++++++++++++++++++++++++++++*/
250 void SeenDefine(char* name)
252 Define def;
254 #if DEBUG
255 printf("#Preproc.c# Defined name '%s'\n",name);
256 #endif
258 def=NewDefineType(name);
260 def->comment=MallocString(GetCurrentComment());
262 def->lineno=parse_line;
264 AddToLinkedList(CurFile->defines,Define,def);
266 cur_def=def;
270 /*++++++++++++++++++++++++++++++++++++++
271 Function that is called when a comment is seen in a #define definition.
272 ++++++++++++++++++++++++++++++++++++++*/
274 void SeenDefineComment(void)
276 char* comment=GetCurrentComment();
278 #if DEBUG
279 printf("#Preproc.c# #define inline comment '%s' in %s\n",comment,cur_def->name);
280 #endif
282 if(!cur_def->comment)
283 cur_def->comment=MallocString(comment);
287 /*++++++++++++++++++++++++++++++++++++++
288 Function that is called when a #define value is seen in the current file.
290 char* value The value of the #defined symbol.
291 ++++++++++++++++++++++++++++++++++++++*/
293 void SeenDefineValue(char* value)
295 #if DEBUG
296 printf("#Preproc.c# #define value '%s' for %s\n",value,cur_def->name);
297 #endif
299 cur_def->value=MallocString(value);
303 /*++++++++++++++++++++++++++++++++++++++
304 Function that is called when a #define function argument is seen in the current definition.
306 char* name The argument.
307 ++++++++++++++++++++++++++++++++++++++*/
309 void SeenDefineFunctionArg(char* name)
311 #if DEBUG
312 printf("#Preproc.c# #define Function arg '%s' in %s()\n",name,cur_def->name);
313 #endif
315 AddToStringList2(cur_def->args,name,SplitComment(&cur_def->comment,name),0,0);
319 /*++++++++++++++++++++++++++++++++++++++
320 Function that is called when a comment is seen in a #define function definition.
321 ++++++++++++++++++++++++++++++++++++++*/
323 void SeenDefineFuncArgComment(void)
325 char* comment=GetCurrentComment();
327 #if DEBUG
328 printf("#Preproc.c# #define Function arg comment '%s' in %s()\n",comment,cur_def->name);
329 #endif
331 if(!cur_def->args->s2[cur_def->args->n-1])
332 cur_def->args->s2[cur_def->args->n-1]=MallocString(comment);
336 /*++++++++++++++++++++++++++++++++++++++
337 Tidy up all of the local variables in case of a problem and abnormal parser termination.
338 ++++++++++++++++++++++++++++++++++++++*/
340 void ResetPreProcAnalyser(void)
342 in_header=0;
344 cur_inc=NULL;
345 cur_def=NULL;
347 inc_depth=0;
349 if(inc_type) Free(inc_type);
350 inc_type=NULL;
351 if(inc_name) Free(inc_name);
352 inc_name=NULL;
354 if(cwd) Free(cwd);
355 cwd=NULL;
359 /*++++++++++++++++++++++++++++++++++++++
360 Create a new Include datatype.
362 Include NewIncludeType Return the new Include type.
364 char *name The name of the new include.
365 ++++++++++++++++++++++++++++++++++++++*/
367 static Include NewIncludeType(char *name)
369 Include inc=(Include)Calloc(1,sizeof(struct _Include));
371 inc->name=MallocString(name);
373 return(inc);
377 /*++++++++++++++++++++++++++++++++++++++
378 Delete the specified Include type.
380 Include inc The Include type to be deleted.
381 ++++++++++++++++++++++++++++++++++++++*/
383 void DeleteIncludeType(Include inc)
385 if(inc->comment) Free(inc->comment);
386 if(inc->name) Free(inc->name);
387 if(inc->includes)
389 Include p=inc->includes;
391 Include n=p->next;
392 DeleteIncludeType(p);
393 p=n;
395 while(p);
397 Free(inc);
401 /*++++++++++++++++++++++++++++++++++++++
402 Create a new Define datatype.
404 Define NewDefineType Return the new Define type.
406 char *name The name of the new define.
407 ++++++++++++++++++++++++++++++++++++++*/
409 static Define NewDefineType(char *name)
411 Define def=(Define)Calloc(1,sizeof(struct _Define)); /* clear unused pointers */
413 def->name=MallocString(name);
414 def->args=NewStringList2();
416 return(def);
420 /*++++++++++++++++++++++++++++++++++++++
421 Delete the specified Define type.
423 Define def The Define type to be deleted.
424 ++++++++++++++++++++++++++++++++++++++*/
426 void DeleteDefineType(Define def)
428 if(def->comment) Free(def->comment);
429 if(def->name) Free(def->name);
430 if(def->value) Free(def->value);
431 if(def->args) DeleteStringList2(def->args);
432 Free(def);