feisty meow concerns codebase  2.140
parse.cpp
Go to the documentation of this file.
1 /* $XConsortium: parse.c,v 1.30 94/04/17 20:10:38 gildea Exp $ */
2 /*
3 
4 Copyright (c) 1993, 1994 X Consortium
5 
6 Permission is hereby granted, free of charge, to any person obtaining a copy
7 of this software and associated documentation files (the "Software"), to deal
8 in the Software without restriction, including without limitation the rights
9 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 copies of the Software, and to permit persons to whom the Software is
11 furnished to do so, subject to the following conditions:
12 
13 The above copyright notice and this permission notice shall be included in
14 all copies or substantial portions of the Software.
15 
16 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
20 AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
21 CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
22 
23 Except as contained in this notice, the name of the X Consortium shall not be
24 used in advertising or otherwise to promote the sale, use or other dealings
25 in this Software without prior written authorization from the X Consortium.
26 
27 */
28 
29 #ifdef __WIN32__
30  #pragma warning(disable : 4996)
31 #endif
32 
33 #include "def.h"
34 
35 #include <string.h>
36 
37 extern const char *directives[];
38 extern inclist maininclist;
39 
40 int find_includes(struct filepointer *filep, inclist *file, inclist *file_red, int recursion, bool failOK)
41 {
42  register char *line;
43  register int type;
44  bool recfailOK;
45 
46  while ((line = getline(filep))) {
47  switch(type = deftype(line, filep, file_red, file, true)) {
48  case IF:
49  doif:
50  type = find_includes(filep, file,
51  file_red, recursion+1, failOK);
52  while ((type == ELIF) || (type == ELIFFALSE) ||
53  (type == ELIFGUESSFALSE))
54  type = gobble(filep, file, file_red);
55  if (type == ELSE)
56  gobble(filep, file, file_red);
57  break;
58  case IFFALSE:
59  case IFGUESSFALSE:
60  doiffalse:
61  if (type == IFGUESSFALSE || type == ELIFGUESSFALSE)
62  recfailOK = true;
63  else
64  recfailOK = failOK;
65  type = gobble(filep, file, file_red);
66  if (type == ELSE)
67  find_includes(filep, file,
68  file_red, recursion+1, recfailOK);
69  else
70  if (type == ELIF)
71  goto doif;
72  else
73  if ((type == ELIFFALSE) || (type == ELIFGUESSFALSE))
74  goto doiffalse;
75  break;
76  case IFDEF:
77  case IFNDEF:
78  if ((type == IFDEF && isdefined(line, file_red, NULL))
79  || (type == IFNDEF && !isdefined(line, file_red, NULL))) {
80  debug(1,(type == IFNDEF ?
81  "line %d: %s !def'd in %s via %s%s\n" : "",
82  filep->f_line, line,
83  file->i_file, file_red->i_file, ": doit"));
84  type = find_includes(filep, file,
85  file_red, recursion+1, failOK);
86  while (type == ELIF || type == ELIFFALSE || type == ELIFGUESSFALSE)
87  type = gobble(filep, file, file_red);
88  if (type == ELSE)
89  gobble(filep, file, file_red);
90  }
91  else {
92  debug(1,(type == IFDEF ?
93  "line %d: %s !def'd in %s via %s%s\n" : "",
94  filep->f_line, line,
95  file->i_file, file_red->i_file, ": gobble"));
96  type = gobble(filep, file, file_red);
97  if (type == ELSE)
98  find_includes(filep, file,
99  file_red, recursion+1, failOK);
100  else if (type == ELIF)
101  goto doif;
102  else if (type == ELIFFALSE || type == ELIFGUESSFALSE)
103  goto doiffalse;
104  }
105  break;
106  case ELSE:
107  case ELIFFALSE:
108  case ELIFGUESSFALSE:
109  case ELIF:
110  if (!recursion)
111  gobble(filep, file, file_red);
112  //hmmm: is this right?
113  /* no break */
114  case ENDIF:
115  if (recursion)
116  return(type);
117  break;
118  case DEFINE:
119  define(line, file);
120  break;
121  case UNDEF:
122  if (!*line) {
123  warning("%s, line %d: incomplete undef == \"%s\"\n",
124  file_red->i_file, filep->f_line, line);
125  break;
126  }
127  undefine(line, file_red);
128  break;
129  case INCLUDE:
130  add_include(filep, file, file_red, line, false, failOK);
131  break;
132  case INCLUDEDOT:
133  add_include(filep, file, file_red, line, true, failOK);
134  break;
135  case ERROR:
136  warning("%s: %d: %s\n", file_red->i_file,
137  filep->f_line, line);
138  break;
139 
140  case PRAGMA:
141  case IDENT:
142  case SCCS:
143  case EJECT:
144  case IMPORT:
145  break;
146  case -1:
147  warning("%s", file_red->i_file);
148  if (file_red != file)
149  warning1(" (reading %s)", file->i_file);
150  warning1(", line %d: unknown directive == \"%s\"\n",
151  filep->f_line, line);
152  break;
153  case -2:
154  warning("%s", file_red->i_file);
155  if (file_red != file)
156  warning1(" (reading %s)", file->i_file);
157  warning1(", line %d: incomplete include == \"%s\"\n",
158  filep->f_line, line);
159  break;
160  }
161  }
162  return(-1);
163 }
164 
165 int gobble(register struct filepointer *filep, inclist *file,
166  inclist *file_red)
167 {
168  register char *line;
169  register int type;
170 
171  while ((line = getline(filep))) {
172  switch(type = deftype(line, filep, file_red, file, false)) {
173  case IF:
174  case IFFALSE:
175  case IFGUESSFALSE:
176  case IFDEF:
177  case IFNDEF:
178  type = gobble(filep, file, file_red);
179  while ((type == ELIF) || (type == ELIFFALSE) ||
180  (type == ELIFGUESSFALSE))
181  type = gobble(filep, file, file_red);
182  if (type == ELSE)
183  (void)gobble(filep, file, file_red);
184  break;
185  case ELSE:
186  case ENDIF:
187  debug(0,("%s, line %d: #%s\n",
188  file->i_file, filep->f_line,
189  directives[type]));
190  return(type);
191  case DEFINE:
192  case UNDEF:
193  case INCLUDE:
194  case INCLUDEDOT:
195  case PRAGMA:
196  case ERROR:
197  case IDENT:
198  case SCCS:
199  case EJECT:
200  case IMPORT:
201  break;
202  case ELIF:
203  case ELIFFALSE:
204  case ELIFGUESSFALSE:
205  return(type);
206  case -1:
207  warning("%s, line %d: unknown directive == \"%s\"\n",
208  file_red->i_file, filep->f_line, line);
209  break;
210  }
211  }
212  return(-1);
213 }
214 
215 /*
216  * Decide what type of # directive this line is.
217  */
218 int deftype(register char *line, register struct filepointer *filep,
219  register inclist *file_red, register inclist *file,
220  int parse_it)
221 {
222  register char *p;
223  char *directive, savechar;
224  register int ret;
225 
226  /*
227  * Parse the directive...
228  */
229  directive=line+1;
230  while (*directive == ' ' || *directive == '\t')
231  directive++;
232 
233  p = directive;
234  while (*p >= 'a' && *p <= 'z')
235  p++;
236  savechar = *p;
237  *p = '\0';
238  ret = match(directive, directives);
239  *p = savechar;
240 
241  /* If we don't recognize this compiler directive or we happen to just
242  * be gobbling up text while waiting for an #endif or #elif or #else
243  * in the case of an #elif we must check the zero_value and return an
244  * ELIF or an ELIFFALSE.
245  */
246 
247  if (ret == ELIF && !parse_it)
248  {
249  while (*p == ' ' || *p == '\t')
250  p++;
251  /*
252  * parse an expression.
253  */
254  debug(0,("%s, line %d: #elif %s ",
255  file->i_file, filep->f_line, p));
256  ret = zero_value(p, filep, file_red);
257  if (ret != IF)
258  {
259  debug(0,("false...\n"));
260  if (ret == IFFALSE)
261  return(ELIFFALSE);
262  else
263  return(ELIFGUESSFALSE);
264  }
265  else
266  {
267  debug(0,("true...\n"));
268  return(ELIF);
269  }
270  }
271 
272  if (ret < 0 || ! parse_it)
273  return(ret);
274 
275  /*
276  * now decide how to parse the directive, and do it.
277  */
278  while (*p == ' ' || *p == '\t')
279  p++;
280  switch (ret) {
281  case IF:
282  /*
283  * parse an expression.
284  */
285  ret = zero_value(p, filep, file_red);
286  debug(0,("%s, line %d: %s #if %s\n",
287  file->i_file, filep->f_line, ret?"false":"true", p));
288  break;
289  case IFDEF:
290  case IFNDEF:
291  debug(0,("%s, line %d: #%s %s\n",
292  file->i_file, filep->f_line, directives[ret], p));
293  //hmmm: no break here either?
294  case UNDEF:
295  /*
296  * separate the name of a single symbol.
297  */
298  while (isalnum(*p) || *p == '_')
299  *line++ = *p++;
300  *line = '\0';
301  break;
302  case INCLUDE:
303  debug(2,("%s, line %d: #include %s\n",
304  file->i_file, filep->f_line, p));
305 
306  /* Support ANSI macro substitution */
307  {
308  struct symtab *sym = isdefined(p, file_red, NULL);
309  while (sym) {
310  p = sym->s_value;
311  debug(3,("%s : #includes SYMBOL %s = %s\n",
312  file->i_incstring,
313  sym -> s_name,
314  sym -> s_value));
315  /* mark file as having included a 'soft include' */
316  file->i_included_sym = true;
317  sym = isdefined(p, file_red, NULL);
318  }
319  }
320 
321  /*
322  * Separate the name of the include file.
323  */
324  while (*p && *p != '"' && *p != '<')
325  p++;
326  if (! *p)
327  return(-2);
328  if (*p++ == '"') {
329  ret = INCLUDEDOT;
330  while (*p && *p != '"')
331  *line++ = *p++;
332  } else
333  while (*p && *p != '>')
334  *line++ = *p++;
335  *line = '\0';
336  break;
337  case DEFINE:
338  /*
339  * copy the definition back to the beginning of the line.
340  */
341  strcpy (line, p);
342  break;
343  case ELSE:
344  case ENDIF:
345  case ELIF:
346  case PRAGMA:
347  case ERROR:
348  case IDENT:
349  case SCCS:
350  case EJECT:
351  case IMPORT:
352  debug(0,("%s, line %d: #%s\n",
353  file->i_file, filep->f_line, directives[ret]));
354  /*
355  * nothing to do.
356  */
357  break;
358  }
359  return(ret);
360 }
361 
362 symtab *isdefined(register char *symbol, inclist *file,
363  inclist **srcfile)
364 {
365  register struct symtab *val;
366 
367  if ((val = slookup(symbol, &maininclist))) {
368  debug(1,("%s defined on command line\n", symbol));
369  if (srcfile != NULL) *srcfile = &maininclist;
370  return(val);
371  }
372  if ((val = fdefined(symbol, file, srcfile)))
373  return(val);
374  debug(1,("%s not defined in %s\n", symbol, file->i_file));
375  return(NULL);
376 }
377 
378 struct symtab *fdefined(register char *symbol, inclist *file, inclist **srcfile)
379 {
380  register inclist **ip;
381  register struct symtab *val;
382  register int i;
383  static int recurse_lvl = 0;
384 
385  if (file->i_defchecked)
386  return(NULL);
387  file->i_defchecked = true;
388  if ((val = slookup(symbol, file)))
389  debug(1,("%s defined in %s as %s\n", symbol, file->i_file, val->s_value));
390  if (val == NULL && file->i_list)
391  {
392  for (ip = file->i_list, i=0; i < file->i_listlen; i++, ip++)
393  if ((val = fdefined(symbol, *ip, srcfile))) {
394  break;
395  }
396  }
397  else if (val != NULL && srcfile != NULL) *srcfile = file;
398  recurse_lvl--;
399  file->i_defchecked = false;
400 
401  return(val);
402 }
403 
404 /*
405  * Return type based on if the #if expression evaluates to 0
406  */
407 int zero_value(register char *exp, register struct filepointer *filep,
408  register inclist *file_red)
409 {
410  if (cppsetup(exp, filep, file_red))
411  return(IFFALSE);
412  else
413  return(IF);
414 }
415 
416 void define(char *def, inclist *file)
417 {
418  char *val;
419 
420  /* Separate symbol name and its value */
421  val = def;
422  while (isalnum(*val) || *val == '_')
423  val++;
424  if (*val)
425  *val++ = '\0';
426  while (*val == ' ' || *val == '\t')
427  val++;
428 
429  if (!*val)
430  val = (char *)"1";
431  define2(def, val, file);
432 }
433 
434 void define2(char *name, char *val, inclist *file)
435 {
436  int first, last, below;
437  register struct symtab *sp = NULL, *dest;
438 
439  /* Make space if it's needed */
440  if (file->i_defs == NULL)
441  {
442  file->i_defs = (struct symtab *)
443  malloc(sizeof (struct symtab) * SYMTABINC);
444  file->i_deflen = SYMTABINC;
445  file->i_ndefs = 0;
446  }
447  else if (file->i_ndefs == file->i_deflen)
448  file->i_defs = (struct symtab *)
449  realloc(file->i_defs,
450  sizeof(struct symtab)*(file->i_deflen+=SYMTABINC));
451 
452  if (file->i_defs == NULL)
453  fatalerr("malloc()/realloc() failure in insert_defn()\n");
454 
455  below = first = 0;
456  last = file->i_ndefs - 1;
457  while (last >= first)
458  {
459  /* Fast inline binary search */
460  register char *s1;
461  register char *s2;
462  register int middle = (first + last) / 2;
463 
464  /* Fast inline strchr() */
465  s1 = name;
466  s2 = file->i_defs[middle].s_name;
467  while (*s1++ == *s2++)
468  if (s2[-1] == '\0') break;
469 
470  /* If exact match, set sp and break */
471  if (*--s1 == *--s2)
472  {
473  sp = file->i_defs + middle;
474  break;
475  }
476 
477  /* If name > i_defs[middle] ... */
478  if (*s1 > *s2)
479  {
480  below = first;
481  first = middle + 1;
482  }
483  /* else ... */
484  else
485  {
486  below = last = middle - 1;
487  }
488  }
489 
490  /* Search is done. If we found an exact match to the symbol name,
491  just replace its s_value */
492  if (sp != NULL)
493  {
494  free(sp->s_value);
495  sp->s_value = copy(val);
496  return;
497  }
498 
499  sp = file->i_defs + file->i_ndefs++;
500  dest = file->i_defs + below + 1;
501  while (sp > dest)
502  {
503  *sp = sp[-1];
504  sp--;
505  }
506  sp->s_name = copy(name);
507  sp->s_value = copy(val);
508 }
509 
510 struct symtab *slookup(register char *symbol, register inclist *file)
511 {
512  register int first = 0;
513  register int last = file->i_ndefs - 1;
514 
515  if (file) while (last >= first)
516  {
517  /* Fast inline binary search */
518  register char *s1;
519  register char *s2;
520  register int middle = (first + last) / 2;
521 
522  /* Fast inline strchr() */
523  s1 = symbol;
524  s2 = file->i_defs[middle].s_name;
525  while (*s1++ == *s2++)
526  if (s2[-1] == '\0') break;
527 
528  /* If exact match, we're done */
529  if (*--s1 == *--s2)
530  {
531  return file->i_defs + middle;
532  }
533 
534  /* If symbol > i_defs[middle] ... */
535  if (*s1 > *s2)
536  {
537  first = middle + 1;
538  }
539  /* else ... */
540  else
541  {
542  last = middle - 1;
543  }
544  }
545  return(NULL);
546 }
547 
548 void undefine(char *symbol, register inclist *file)
549 {
550  register struct symtab *ptr;
551  inclist *srcfile;
552  while ((ptr = isdefined(symbol, file, &srcfile)) != NULL)
553  {
554  srcfile->i_ndefs--;
555  for (; ptr < srcfile->i_defs + srcfile->i_ndefs; ptr++)
556  *ptr = ptr[1];
557  }
558 }
int cppsetup(register char *line, register struct filepointer *filep, register inclist *inc)
Definition: cppsetup.cpp:207
#define IDENT
Definition: def.h:65
#define ELSE
Definition: def.h:57
#define INCLUDEDOT
Definition: def.h:73
char * getline(register filepointer *filep)
#define IFFALSE
Definition: def.h:71
#define INCLUDE
Definition: def.h:61
#define IFGUESSFALSE
Definition: def.h:74
#define debug(level, arg)
define DEBUG
Definition: def.h:93
void add_include(filepointer *filep, inclist *file, inclist *file_red, char *include, bool dot, bool failOK)
Definition: pr.cpp:44
#define IFDEF
Definition: def.h:55
#define EJECT
Definition: def.h:68
#define IMPORT
Definition: def.h:69
int match(register const char *str, register const char **list)
Definition: makedep.cpp:562
#define ERROR
Definition: def.h:64
#define SCCS
Definition: def.h:66
#define SYMTABINC
Definition: def.h:51
#define ELIFFALSE
Definition: def.h:72
#define PRAGMA
Definition: def.h:63
#define ELIF
Definition: def.h:67
#define ELIFGUESSFALSE
Definition: def.h:75
#define UNDEF
Definition: def.h:60
#define IF
Definition: def.h:54
char * copy(register char *str)
Definition: makedep.cpp:554
#define DEFINE
Definition: def.h:59
#define IFNDEF
Definition: def.h:56
#define ENDIF
Definition: def.h:58
void warning1(const char *msg, x1, x2, x3, x4, x5, x6, x7, x8, x9)
Definition: makedep.cpp:790
void fatalerr(char *msg, x1, x2, x3, x4, x5, x6, x7, x8, x9)
Definition: makedep.cpp:749
void warning(const char *msg, x1, x2, x3, x4, x5, x6, x7, x8, x9)
Definition: makedep.cpp:770
symtab * isdefined(register char *symbol, inclist *file, inclist **srcfile)
Definition: parse.cpp:362
int zero_value(register char *exp, register struct filepointer *filep, register inclist *file_red)
Definition: parse.cpp:407
int find_includes(struct filepointer *filep, inclist *file, inclist *file_red, int recursion, bool failOK)
Definition: parse.cpp:40
const char * directives[]
Definition: makedep.cpp:76
int gobble(register struct filepointer *filep, inclist *file, inclist *file_red)
Definition: parse.cpp:165
inclist maininclist
Definition: makedep.cpp:100
void define2(char *name, char *val, inclist *file)
Definition: parse.cpp:434
void undefine(char *symbol, register inclist *file)
Definition: parse.cpp:548
struct symtab * fdefined(register char *symbol, inclist *file, inclist **srcfile)
Definition: parse.cpp:378
void define(char *def, inclist *file)
Definition: parse.cpp:416
int deftype(register char *line, register struct filepointer *filep, register inclist *file_red, register inclist *file, int parse_it)
Definition: parse.cpp:218
struct symtab * slookup(register char *symbol, register inclist *file)
Definition: parse.cpp:510
long f_line
Definition: def.h:122
Definition: def.h:101
bool i_defchecked
Definition: def.h:109
int i_deflen
Definition: def.h:108
bool i_included_sym
Definition: def.h:113
symtab * i_defs
Definition: def.h:106
int i_ndefs
Definition: def.h:107
char * i_incstring
Definition: def.h:102
char * i_file
Definition: def.h:103
inclist ** i_list
Definition: def.h:104
Definition: def.h:96
char * s_value
Definition: def.h:98
char * s_name
Definition: def.h:97