update credits
[LibreOffice.git] / soltools / mkdepend / parse.c
blob0914fbc57edef2ec19b26e7015d5be62fd083096
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /* $XConsortium: parse.c,v 1.30 94/04/17 20:10:38 gildea Exp $ */
3 /*
5 Copyright (c) 1993, 1994 X Consortium
7 Permission is hereby granted, free of charge, to any person obtaining a copy
8 of this software and associated documentation files (the "Software"), to deal
9 in the Software without restriction, including without limitation the rights
10 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11 copies of the Software, and to permit persons to whom the Software is
12 furnished to do so, subject to the following conditions:
14 The above copyright notice and this permission notice shall be included in
15 all copies or substantial portions of the Software.
17 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20 X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
21 AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
22 CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
24 Except as contained in this notice, the name of the X Consortium shall not be
25 used in advertising or otherwise to promote the sale, use or other dealings
26 in this Software without prior written authorization from the X Consortium.
30 #include "def.h"
31 char *hash_lookup( char *symbol, struct symhash *symbols );
32 void hash_undefine( char *symbol, struct symhash *symbols );
33 int gobble( register struct filepointer *filep, struct inclist *file,
34 struct inclist *file_red, struct symhash *symbols );
35 int deftype ( register char *line, register struct filepointer *filep,
36 register struct inclist *file_red, register struct inclist *file,
37 int parse_it, struct symhash *symbols);
38 int zero_value(register char *exp, register struct filepointer *filep,
39 register struct inclist *file_red, register struct symhash *symbols);
41 extern char *directives[];
42 extern struct symhash *maininclist;
44 int find_includes(struct filepointer *filep, struct inclist *file, struct inclist *file_red, int recursion, boolean failOK, struct IncludesCollection* incCollection, struct symhash *symbols)
46 register char *line;
47 register int type;
48 boolean recfailOK;
50 while ((line = get_line(filep))) {
51 switch(type = deftype(line, filep, file_red, file, TRUE, symbols)) {
52 case IF:
53 doif:
54 type = find_includes(filep, file,
55 file_red, recursion+1, failOK, incCollection, symbols);
56 while ((type == ELIF) || (type == ELIFFALSE) ||
57 (type == ELIFGUESSFALSE))
58 type = gobble(filep, file, file_red, symbols);
59 if (type == ELSE)
60 gobble(filep, file, file_red, symbols);
61 break;
62 case IFFALSE:
63 case IFGUESSFALSE:
64 doiffalse:
65 if (type == IFGUESSFALSE || type == ELIFGUESSFALSE)
66 recfailOK = TRUE;
67 else
68 recfailOK = failOK;
69 type = gobble(filep, file, file_red, symbols);
70 if (type == ELSE)
71 find_includes(filep, file,
72 file_red, recursion+1, recfailOK, incCollection, symbols);
73 else if (type == ELIF)
74 goto doif;
75 else if ((type == ELIFFALSE) || (type == ELIFGUESSFALSE))
76 goto doiffalse;
77 break;
78 case IFDEF:
79 case IFNDEF:
80 if ((type == IFDEF && hash_lookup(line, symbols))
81 || (type == IFNDEF && !hash_lookup(line, symbols))) {
82 debug(1,(type == IFNDEF ?
83 "line %d: %s !def'd in %s via %s%s\n" : "",
84 filep->f_line, line,
85 file->i_file, file_red->i_file, ": doit"));
86 type = find_includes(filep, file,
87 file_red, recursion+1, failOK, incCollection, symbols);
88 while (type == ELIF || type == ELIFFALSE || type == ELIFGUESSFALSE)
89 type = gobble(filep, file, file_red, symbols);
90 if (type == ELSE)
91 gobble(filep, file, file_red, symbols);
93 else {
94 debug(1,(type == IFDEF ?
95 "line %d: %s !def'd in %s via %s%s\n" : "",
96 filep->f_line, line,
97 file->i_file, file_red->i_file, ": gobble"));
98 type = gobble(filep, file, file_red, symbols);
99 if (type == ELSE)
100 find_includes(filep, file,
101 file_red, recursion + 1, failOK, incCollection, symbols);
102 else if (type == ELIF)
103 goto doif;
104 else if (type == ELIFFALSE || type == ELIFGUESSFALSE)
105 goto doiffalse;
107 break;
108 case ELSE:
109 case ELIFFALSE:
110 case ELIFGUESSFALSE:
111 case ELIF:
112 if (!recursion)
113 gobble(filep, file, file_red, symbols);
114 case ENDIF:
115 if (recursion)
116 return(type);
117 case DEFINE:
118 define(line, &symbols);
119 break;
120 case UNDEF:
121 if (!*line) {
122 warning("%s, line %d: incomplete undef == \"%s\"\n",
123 file_red->i_file, filep->f_line, line);
124 break;
126 hash_undefine(line, symbols);
127 break;
128 case INCLUDE:
129 add_include(filep, file, file_red, line, FALSE, failOK, incCollection, symbols);
130 break;
131 case INCLUDEDOT:
132 add_include(filep, file, file_red, line, TRUE, failOK, incCollection, symbols);
133 break;
134 case ERROR:
135 warning("%s: %d: %s\n", file_red->i_file,
136 filep->f_line, line);
137 break;
139 case PRAGMA:
140 case IDENT:
141 case SCCS:
142 case EJECT:
143 break;
144 case -1:
145 warning("%s", file_red->i_file);
146 if (file_red != file)
147 warning1(" (reading %s)", file->i_file);
148 warning1(", line %d: unknown directive == \"%s\"\n",
149 filep->f_line, line);
150 break;
151 case -2:
152 warning("%s", file_red->i_file);
153 if (file_red != file)
154 warning1(" (reading %s)", file->i_file);
155 warning1(", line %d: incomplete include == \"%s\"\n",
156 filep->f_line, line);
157 break;
160 return(-1);
163 int gobble(filep, file, file_red, symbols)
164 register struct filepointer *filep;
165 struct inclist *file, *file_red;
166 struct symhash *symbols;
168 register char *line;
169 register int type;
171 while ((line = get_line(filep))) {
172 switch(type = deftype(line, filep, file_red, file, FALSE, symbols)) {
173 case IF:
174 case IFFALSE:
175 case IFGUESSFALSE:
176 case IFDEF:
177 case IFNDEF:
178 type = gobble(filep, file, file_red, symbols);
179 while ((type == ELIF) || (type == ELIFFALSE) ||
180 (type == ELIFGUESSFALSE))
181 type = gobble(filep, file, file_red, symbols);
182 if (type == ELSE)
183 (void)gobble(filep, file, file_red, symbols);
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 break;
201 case ELIF:
202 case ELIFFALSE:
203 case ELIFGUESSFALSE:
204 return(type);
205 case -1:
206 warning("%s, line %d: unknown directive == \"%s\"\n",
207 file_red->i_file, filep->f_line, line);
208 break;
211 return(-1);
215 * Decide what type of # directive this line is.
217 int deftype (line, filep, file_red, file, parse_it, symbols)
218 register char *line;
219 register struct filepointer *filep;
220 register struct inclist *file_red, *file;
221 int parse_it;
222 struct symhash *symbols;
224 register char *p;
225 char *directive, savechar;
226 register int ret;
229 * Parse the directive...
231 directive=line+1;
232 while (*directive == ' ' || *directive == '\t')
233 directive++;
235 p = directive;
236 while (*p >= 'a' && *p <= 'z')
237 p++;
238 savechar = *p;
239 *p = '\0';
240 ret = match(directive, directives);
241 *p = savechar;
243 /* If we don't recognize this compiler directive or we happen to just
244 * be gobbling up text while waiting for an #endif or #elif or #else
245 * in the case of an #elif we must check the zero_value and return an
246 * ELIF or an ELIFFALSE.
249 if (ret == ELIF && !parse_it)
251 while (*p == ' ' || *p == '\t')
252 p++;
254 * parse an expression.
256 debug(0,("%s, line %d: #elif %s ",
257 file->i_file, filep->f_line, p));
258 ret = zero_value(p, filep, file_red, symbols);
259 if (ret != IF)
261 debug(0,("false...\n"));
262 if (ret == IFFALSE)
263 return(ELIFFALSE);
264 else
265 return(ELIFGUESSFALSE);
267 else
269 debug(0,("true...\n"));
270 return(ELIF);
274 if (ret < 0 || ! parse_it)
275 return(ret);
278 * now decide how to parse the directive, and do it.
280 while (*p == ' ' || *p == '\t')
281 p++;
282 switch (ret) {
283 case IF:
285 * parse an expression.
287 ret = zero_value(p, filep, file_red, symbols);
288 debug(0,("%s, line %d: %s #if %s\n",
289 file->i_file, filep->f_line, ret?"false":"true", p));
290 break;
291 case IFDEF:
292 case IFNDEF:
293 debug(0,("%s, line %d: #%s %s\n",
294 file->i_file, filep->f_line, directives[ret], p));
295 case UNDEF:
297 * separate the name of a single symbol.
299 while (isalnum(*p) || *p == '_')
300 *line++ = *p++;
301 *line = '\0';
302 break;
303 case INCLUDE:
304 debug(2,("%s, line %d: #include %s\n",
305 file->i_file, filep->f_line, p));
307 /* Support ANSI macro substitution */
309 char *sym = hash_lookup(p, symbols);
310 while (sym)
312 p = sym;
313 debug(3,("%s : #includes SYMBOL %s\n",
314 file->i_incstring,
315 sym));
316 /* mark file as having included a 'soft include' */
317 file->i_included_sym = TRUE;
318 sym = hash_lookup(p, symbols);
323 * Separate the name of the include file.
325 while (*p && *p != '"' && *p != '<')
326 p++;
327 if (! *p)
328 return(-2);
329 if (*p++ == '"') {
330 ret = INCLUDEDOT;
331 while (*p && *p != '"')
332 *line++ = *p++;
333 } else
334 while (*p && *p != '>')
335 *line++ = *p++;
336 *line = '\0';
337 break;
338 case DEFINE:
340 * copy the definition back to the beginning of the line.
342 memmove (line, p, strlen(p));
343 break;
344 case ELSE:
345 case ENDIF:
346 case ELIF:
347 case PRAGMA:
348 case ERROR:
349 case IDENT:
350 case SCCS:
351 case EJECT:
352 debug(0,("%s, line %d: #%s\n",
353 file->i_file, filep->f_line, directives[ret]));
355 * nothing to do.
357 break;
359 return(ret);
363 * HACK! - so that we do not have to introduce 'symbols' in each cppsetup.c
364 * function... It's safe, functions from cppsetup.c don't return here.
366 struct symhash *global_symbols = NULL;
368 char * isdefined( symbol )
369 register char *symbol;
371 return hash_lookup( symbol, global_symbols );
375 * Return type based on if the #if expression evaluates to 0
377 int zero_value(exp, filep, file_red, symbols)
378 register char *exp;
379 register struct filepointer *filep;
380 register struct inclist *file_red;
381 register struct symhash *symbols;
383 global_symbols = symbols; /* HACK! see above */
384 if (cppsetup(exp, filep, file_red))
385 return(IFFALSE);
386 else
387 return(IF);
390 void define( def, symbols )
391 char *def;
392 struct symhash **symbols;
394 char *val;
396 /* Separate symbol name and its value */
397 val = def;
398 while (isalnum(*val) || *val == '_')
399 val++;
400 if (*val)
401 *val++ = '\0';
402 while (*val == ' ' || *val == '\t')
403 val++;
405 if (!*val)
406 val = "1";
407 hash_define( def, val, symbols );
410 static int hash( str )
411 register char *str;
413 /* Hash (Kernighan and Ritchie) */
414 register unsigned int hashval = 0;
416 for ( ; *str; str++ )
418 hashval = ( hashval * SYMHASHSEED ) + ( *str );
421 return hashval & ( SYMHASHMEMBERS - 1 );
424 struct symhash *hash_copy( symbols )
425 struct symhash *symbols;
427 int i;
428 struct symhash *newsym;
429 if ( !symbols )
430 return NULL;
432 newsym = (struct symhash *) malloc( sizeof( struct symhash ) );
434 for ( i = 0; i < SYMHASHMEMBERS; ++i )
436 if ( !symbols->s_pairs[ i ] )
437 newsym->s_pairs[ i ] = NULL;
438 else
440 struct pair *it = symbols->s_pairs[ i ];
441 struct pair *nw = newsym->s_pairs[ i ] = (struct pair*) malloc( sizeof( struct pair ) );
442 nw->p_name = it->p_name;
443 nw->p_value = it->p_value;
444 nw->p_next = NULL;
446 while ( it->p_next )
448 nw->p_next = (struct pair*) malloc( sizeof( struct pair ) );
449 it = it->p_next;
450 nw = nw->p_next;
451 nw->p_name = it->p_name;
452 nw->p_value = it->p_value;
453 nw->p_next = NULL;
457 return newsym;
460 void hash_free( symbols )
461 struct symhash *symbols;
463 int i;
465 if ( !symbols )
466 return;
468 for ( i = 0; i < SYMHASHMEMBERS; ++i )
470 struct pair *it = symbols->s_pairs[ i ];
471 struct pair *next;
472 while ( it )
474 next = it->p_next;
475 free( it );
476 it = next;
479 free( symbols->s_pairs );
482 void hash_define( name, val, symbols )
483 char *name, *val;
484 struct symhash **symbols;
486 int hashval;
487 struct pair *it;
489 if ( !symbols )
490 return;
492 /* Make space if it's needed */
493 if ( *symbols == NULL )
495 int i;
497 *symbols = (struct symhash *) malloc( sizeof( struct symhash ) );
498 if ( *symbols == NULL )
499 fatalerr( "malloc()/realloc() failure in insert_defn()\n" );
501 for ( i = 0; i < SYMHASHMEMBERS; ++i )
502 (*symbols)->s_pairs[i] = NULL;
505 hashval = hash( name );
506 it = (*symbols)->s_pairs[ hashval ];
508 /* Replace/insert the symbol */
509 if ( it == NULL )
511 it = (*symbols)->s_pairs[ hashval ] = (struct pair*) malloc( sizeof( struct pair ) );
512 it->p_name = copy( name );
513 it->p_value = copy( val );
514 it->p_next = NULL;
516 else if ( strcmp( it->p_name, name ) == 0 )
518 it->p_value = copy( val );
520 else
522 while ( it->p_next && ( strcmp( it->p_next->p_name, name ) != 0 ) )
524 it = it->p_next;
526 if ( it->p_next )
527 it->p_next->p_name = copy( name );
528 else
530 it->p_next = (struct pair*) malloc( sizeof( struct pair ) );
531 it->p_next->p_name = copy( name );
532 it->p_next->p_value = copy( val );
533 it->p_next->p_next = NULL;
538 char *hash_lookup( symbol, symbols )
539 char *symbol;
540 struct symhash *symbols;
542 struct pair *it;
544 if ( !symbols )
545 return NULL;
547 it = symbols->s_pairs[ hash( symbol ) ];
549 while ( it && ( strcmp( it->p_name, symbol ) != 0 ) )
551 it = it->p_next;
553 if ( it )
554 return it->p_value;
556 return NULL;
559 void hash_undefine( symbol, symbols )
560 char *symbol;
561 struct symhash *symbols;
563 int hashval;
564 struct pair *it;
566 if ( !symbols )
567 return;
569 hashval = hash( symbol );
570 it = symbols->s_pairs[ hashval ];
572 /* Replace/insert the symbol */
573 if ( it == NULL )
574 return;
575 else if ( strcmp( it->p_name, symbol ) == 0 )
577 if ( it->p_next )
579 struct pair *tmp;
580 it->p_name = it->p_next->p_name;
581 it->p_value = it->p_next->p_value;
582 tmp = it->p_next->p_next;
583 free( it->p_next );
584 it->p_next = tmp;
586 else
588 free( it );
589 symbols->s_pairs[ hashval ] = NULL;
592 else
594 while ( it->p_next && ( strcmp( it->p_next->p_name, symbol ) != 0 ) )
596 it = it->p_next;
598 if ( it->p_next )
600 struct pair *tmp = it->p_next;
601 it->p_next = it->p_next->p_next;
602 free( tmp );
607 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */