bump product version to 5.0.4.1
[LibreOffice.git] / soltools / mkdepend / parse.c
blob01adafbbbd369c04cc64bb6305869eba216464f7
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( struct filepointer *filep, struct inclist *file,
34 struct inclist *file_red, struct symhash *symbols );
35 int deftype ( char *line, struct filepointer *filep,
36 struct inclist *file_red, struct inclist *file,
37 int parse_it, struct symhash *symbols);
38 int zero_value(char *exp, struct filepointer *filep,
39 struct inclist *file_red, 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 char *line;
47 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 /*fall-through*/
115 case ENDIF:
116 if (recursion)
117 return type;
118 /*fall-through*/
119 case DEFINE:
120 define(line, &symbols);
121 break;
122 case UNDEF:
123 if (!*line) {
124 warning("%s, line %d: incomplete undef == \"%s\"\n",
125 file_red->i_file, filep->f_line, line);
126 break;
128 hash_undefine(line, symbols);
129 break;
130 case INCLUDE:
131 add_include(filep, file, file_red, line, FALSE, failOK, incCollection, symbols);
132 break;
133 case INCLUDEDOT:
134 add_include(filep, file, file_red, line, TRUE, failOK, incCollection, symbols);
135 break;
136 case ERROR:
137 warning("%s: %d: %s\n", file_red->i_file,
138 filep->f_line, line);
139 break;
141 case PRAGMA:
142 case IDENT:
143 case SCCS:
144 case EJECT:
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;
162 return -1;
165 int gobble(struct filepointer *filep,
166 struct inclist *file,
167 struct inclist *file_red,
168 struct symhash *symbols)
170 char *line;
171 int type;
173 while ((line = get_line(filep))) {
174 switch(type = deftype(line, filep, file_red, file, FALSE, symbols)) {
175 case IF:
176 case IFFALSE:
177 case IFGUESSFALSE:
178 case IFDEF:
179 case IFNDEF:
180 type = gobble(filep, file, file_red, symbols);
181 while ((type == ELIF) || (type == ELIFFALSE) ||
182 (type == ELIFGUESSFALSE))
183 type = gobble(filep, file, file_red, symbols);
184 if (type == ELSE)
185 (void)gobble(filep, file, file_red, symbols);
186 break;
187 case ELSE:
188 case ENDIF:
189 debug(0,("%s, line %d: #%s\n",
190 file->i_file, filep->f_line,
191 directives[type]));
192 return type;
193 case DEFINE:
194 case UNDEF:
195 case INCLUDE:
196 case INCLUDEDOT:
197 case PRAGMA:
198 case ERROR:
199 case IDENT:
200 case SCCS:
201 case EJECT:
202 break;
203 case ELIF:
204 case ELIFFALSE:
205 case ELIFGUESSFALSE:
206 return type;
207 case -1:
208 warning("%s, line %d: unknown directive == \"%s\"\n",
209 file_red->i_file, filep->f_line, line);
210 break;
213 return -1;
217 * Decide what type of # directive this line is.
219 int deftype (char *line, struct filepointer *filep, struct inclist *file_red, struct inclist *file, int parse_it, struct symhash *symbols)
221 char *p;
222 char *directive, savechar;
223 int ret;
226 * Parse the directive...
228 directive=line+1;
229 while (*directive == ' ' || *directive == '\t')
230 directive++;
232 p = directive;
233 while (*p >= 'a' && *p <= 'z')
234 p++;
235 savechar = *p;
236 *p = '\0';
237 ret = match(directive, directives);
238 *p = savechar;
240 /* If we don't recognize this compiler directive or we happen to just
241 * be gobbling up text while waiting for an #endif or #elif or #else
242 * in the case of an #elif we must check the zero_value and return an
243 * ELIF or an ELIFFALSE.
246 if (ret == ELIF && !parse_it)
248 while (*p == ' ' || *p == '\t')
249 p++;
251 * parse an expression.
253 debug(0,("%s, line %d: #elif %s ",
254 file->i_file, filep->f_line, p));
255 ret = zero_value(p, filep, file_red, symbols);
256 if (ret != IF)
258 debug(0,("false...\n"));
259 if (ret == IFFALSE)
260 return ELIFFALSE;
261 else
262 return ELIFGUESSFALSE;
264 else
266 debug(0,("true...\n"));
267 return ELIF;
271 if (ret < 0 || ! parse_it)
272 return ret;
275 * now decide how to parse the directive, and do it.
277 while (*p == ' ' || *p == '\t')
278 p++;
279 switch (ret) {
280 case IF:
282 * parse an expression.
284 ret = zero_value(p, filep, file_red, symbols);
285 debug(0,("%s, line %d: %s #if %s\n",
286 file->i_file, filep->f_line, ret?"false":"true", p));
287 break;
288 case IFDEF:
289 case IFNDEF:
290 debug(0,("%s, line %d: #%s %s\n",
291 file->i_file, filep->f_line, directives[ret], p));
292 //fall-through
293 case UNDEF:
295 * separate the name of a single symbol.
297 while (isalnum(*p) || *p == '_')
298 *line++ = *p++;
299 *line = '\0';
300 break;
301 case INCLUDE:
302 debug(2,("%s, line %d: #include %s\n",
303 file->i_file, filep->f_line, p));
305 /* Support ANSI macro substitution */
307 char *sym = hash_lookup(p, symbols);
308 while (sym)
310 p = sym;
311 debug(3,("%s : #includes SYMBOL %s\n",
312 file->i_incstring,
313 sym));
314 /* mark file as having included a 'soft include' */
315 file->i_included_sym = TRUE;
316 sym = hash_lookup(p, symbols);
321 * Separate the name of the include file.
323 while (*p && *p != '"' && *p != '<')
324 p++;
325 if (! *p)
326 return -2;
327 if (*p++ == '"') {
328 ret = INCLUDEDOT;
329 while (*p && *p != '"')
330 *line++ = *p++;
331 } else
332 while (*p && *p != '>')
333 *line++ = *p++;
334 *line = '\0';
335 break;
336 case DEFINE:
338 * copy the definition back to the beginning of the line.
340 memmove (line, p, strlen(p));
341 break;
342 case ELSE:
343 case ENDIF:
344 case ELIF:
345 case PRAGMA:
346 case ERROR:
347 case IDENT:
348 case SCCS:
349 case EJECT:
350 debug(0,("%s, line %d: #%s\n",
351 file->i_file, filep->f_line, directives[ret]));
353 * nothing to do.
355 break;
357 return ret;
361 * HACK! - so that we do not have to introduce 'symbols' in each cppsetup.c
362 * function... It's safe, functions from cppsetup.c don't return here.
364 struct symhash *global_symbols = NULL;
366 char * isdefined( char *symbol )
368 return hash_lookup( symbol, global_symbols );
372 * Return type based on if the #if expression evaluates to 0
374 int zero_value(char *exp, struct filepointer *filep, struct inclist *file_red, struct symhash *symbols)
376 global_symbols = symbols; /* HACK! see above */
377 if (cppsetup(exp, filep, file_red))
378 return IFFALSE;
379 else
380 return IF;
383 void define( char *def, struct symhash **symbols )
385 char *val;
387 /* Separate symbol name and its value */
388 val = def;
389 while (isalnum(*val) || *val == '_')
390 val++;
391 if (*val)
392 *val++ = '\0';
393 while (*val == ' ' || *val == '\t')
394 val++;
396 if (!*val)
397 val = "1";
398 hash_define( def, val, symbols );
401 static int hash( char *str )
403 /* Hash (Kernighan and Ritchie) */
404 unsigned int hashval = 0;
406 for ( ; *str; str++ )
408 hashval = ( hashval * SYMHASHSEED ) + ( *str );
411 return hashval & ( SYMHASHMEMBERS - 1 );
414 struct symhash *hash_copy( struct symhash *symbols )
416 int i;
417 struct symhash *newsym;
418 if ( !symbols )
419 return NULL;
421 newsym = (struct symhash *) malloc( sizeof( struct symhash ) );
423 for ( i = 0; i < SYMHASHMEMBERS; ++i )
425 if ( !symbols->s_pairs[ i ] )
426 newsym->s_pairs[ i ] = NULL;
427 else
429 struct pair *it = symbols->s_pairs[ i ];
430 struct pair *nw = newsym->s_pairs[ i ] = (struct pair*) malloc( sizeof( struct pair ) );
431 nw->p_name = it->p_name;
432 nw->p_value = it->p_value;
433 nw->p_next = NULL;
435 while ( it->p_next )
437 nw->p_next = (struct pair*) malloc( sizeof( struct pair ) );
438 it = it->p_next;
439 nw = nw->p_next;
440 nw->p_name = it->p_name;
441 nw->p_value = it->p_value;
442 nw->p_next = NULL;
446 return newsym;
449 void hash_free( struct symhash *symbols )
451 int i;
453 if ( !symbols )
454 return;
456 for ( i = 0; i < SYMHASHMEMBERS; ++i )
458 struct pair *it = symbols->s_pairs[ i ];
459 struct pair *next;
460 while ( it )
462 next = it->p_next;
463 free( it );
464 it = next;
467 free( symbols->s_pairs );
470 void hash_define( char *name, char *val, struct symhash **symbols )
472 int hashval;
473 struct pair *it;
475 if ( !symbols )
476 return;
478 /* Make space if it's needed */
479 if ( *symbols == NULL )
481 int i;
483 *symbols = (struct symhash *) malloc( sizeof( struct symhash ) );
484 if ( *symbols == NULL )
485 fatalerr( "malloc()/realloc() failure in insert_defn()\n" );
487 for ( i = 0; i < SYMHASHMEMBERS; ++i )
488 (*symbols)->s_pairs[i] = NULL;
491 hashval = hash( name );
492 it = (*symbols)->s_pairs[ hashval ];
494 /* Replace/insert the symbol */
495 if ( it == NULL )
497 it = (*symbols)->s_pairs[ hashval ] = (struct pair*) malloc( sizeof( struct pair ) );
498 it->p_name = copy( name );
499 it->p_value = copy( val );
500 it->p_next = NULL;
502 else if ( strcmp( it->p_name, name ) == 0 )
504 it->p_value = copy( val );
506 else
508 while ( it->p_next && ( strcmp( it->p_next->p_name, name ) != 0 ) )
510 it = it->p_next;
512 if ( it->p_next )
513 it->p_next->p_name = copy( name );
514 else
516 it->p_next = (struct pair*) malloc( sizeof( struct pair ) );
517 it->p_next->p_name = copy( name );
518 it->p_next->p_value = copy( val );
519 it->p_next->p_next = NULL;
524 char *hash_lookup( char *symbol, struct symhash *symbols )
526 struct pair *it;
528 if ( !symbols )
529 return NULL;
531 it = symbols->s_pairs[ hash( symbol ) ];
533 while ( it && ( strcmp( it->p_name, symbol ) != 0 ) )
535 it = it->p_next;
537 if ( it )
538 return it->p_value;
540 return NULL;
543 void hash_undefine( char *symbol, struct symhash *symbols )
545 int hashval;
546 struct pair *it;
548 if ( !symbols )
549 return;
551 hashval = hash( symbol );
552 it = symbols->s_pairs[ hashval ];
554 /* Replace/insert the symbol */
555 if ( it == NULL )
556 return;
557 else if ( strcmp( it->p_name, symbol ) == 0 )
559 if ( it->p_next )
561 struct pair *tmp;
562 it->p_name = it->p_next->p_name;
563 it->p_value = it->p_next->p_value;
564 tmp = it->p_next->p_next;
565 free( it->p_next );
566 it->p_next = tmp;
568 else
570 free( it );
571 symbols->s_pairs[ hashval ] = NULL;
574 else
576 while ( it->p_next && ( strcmp( it->p_next->p_name, symbol ) != 0 ) )
578 it = it->p_next;
580 if ( it->p_next )
582 struct pair *tmp = it->p_next;
583 it->p_next = it->p_next->p_next;
584 free( tmp );
589 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */