Version 3.6.0.4, tag libreoffice-3.6.0.4
[LibreOffice.git] / soltools / mkdepend / parse.c
blob939155aa3b83115ab46b9ec5b15da5a28c596d6e
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
74 if (type == ELIF)
75 goto doif;
76 else
77 if ((type == ELIFFALSE) || (type == ELIFGUESSFALSE))
78 goto doiffalse;
79 break;
80 case IFDEF:
81 case IFNDEF:
82 if ((type == IFDEF && hash_lookup(line, symbols))
83 || (type == IFNDEF && !hash_lookup(line, symbols))) {
84 debug(1,(type == IFNDEF ?
85 "line %d: %s !def'd in %s via %s%s\n" : "",
86 filep->f_line, line,
87 file->i_file, file_red->i_file, ": doit"));
88 type = find_includes(filep, file,
89 file_red, recursion+1, failOK, incCollection, symbols);
90 while (type == ELIF || type == ELIFFALSE || type == ELIFGUESSFALSE)
91 type = gobble(filep, file, file_red, symbols);
92 if (type == ELSE)
93 gobble(filep, file, file_red, symbols);
95 else {
96 debug(1,(type == IFDEF ?
97 "line %d: %s !def'd in %s via %s%s\n" : "",
98 filep->f_line, line,
99 file->i_file, file_red->i_file, ": gobble"));
100 type = gobble(filep, file, file_red, symbols);
101 if (type == ELSE)
102 find_includes(filep, file,
103 file_red, recursion + 1, failOK, incCollection, symbols);
104 else if (type == ELIF)
105 goto doif;
106 else if (type == ELIFFALSE || type == ELIFGUESSFALSE)
107 goto doiffalse;
109 break;
110 case ELSE:
111 case ELIFFALSE:
112 case ELIFGUESSFALSE:
113 case ELIF:
114 if (!recursion)
115 gobble(filep, file, file_red, symbols);
116 case ENDIF:
117 if (recursion)
118 return(type);
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(filep, file, file_red, symbols)
166 register struct filepointer *filep;
167 struct inclist *file, *file_red;
168 struct symhash *symbols;
170 register char *line;
171 register 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 (line, filep, file_red, file, parse_it, symbols)
220 register char *line;
221 register struct filepointer *filep;
222 register struct inclist *file_red, *file;
223 int parse_it;
224 struct symhash *symbols;
226 register char *p;
227 char *directive, savechar;
228 register int ret;
231 * Parse the directive...
233 directive=line+1;
234 while (*directive == ' ' || *directive == '\t')
235 directive++;
237 p = directive;
238 while (*p >= 'a' && *p <= 'z')
239 p++;
240 savechar = *p;
241 *p = '\0';
242 ret = match(directive, directives);
243 *p = savechar;
245 /* If we don't recognize this compiler directive or we happen to just
246 * be gobbling up text while waiting for an #endif or #elif or #else
247 * in the case of an #elif we must check the zero_value and return an
248 * ELIF or an ELIFFALSE.
251 if (ret == ELIF && !parse_it)
253 while (*p == ' ' || *p == '\t')
254 p++;
256 * parse an expression.
258 debug(0,("%s, line %d: #elif %s ",
259 file->i_file, filep->f_line, p));
260 ret = zero_value(p, filep, file_red, symbols);
261 if (ret != IF)
263 debug(0,("false...\n"));
264 if (ret == IFFALSE)
265 return(ELIFFALSE);
266 else
267 return(ELIFGUESSFALSE);
269 else
271 debug(0,("true...\n"));
272 return(ELIF);
276 if (ret < 0 || ! parse_it)
277 return(ret);
280 * now decide how to parse the directive, and do it.
282 while (*p == ' ' || *p == '\t')
283 p++;
284 switch (ret) {
285 case IF:
287 * parse an expression.
289 ret = zero_value(p, filep, file_red, symbols);
290 debug(0,("%s, line %d: %s #if %s\n",
291 file->i_file, filep->f_line, ret?"false":"true", p));
292 break;
293 case IFDEF:
294 case IFNDEF:
295 debug(0,("%s, line %d: #%s %s\n",
296 file->i_file, filep->f_line, directives[ret], p));
297 case UNDEF:
299 * separate the name of a single symbol.
301 while (isalnum(*p) || *p == '_')
302 *line++ = *p++;
303 *line = '\0';
304 break;
305 case INCLUDE:
306 debug(2,("%s, line %d: #include %s\n",
307 file->i_file, filep->f_line, p));
309 /* Support ANSI macro substitution */
311 char *sym = hash_lookup(p, symbols);
312 while (sym)
314 p = sym;
315 debug(3,("%s : #includes SYMBOL %s\n",
316 file->i_incstring,
317 sym));
318 /* mark file as having included a 'soft include' */
319 file->i_included_sym = TRUE;
320 sym = hash_lookup(p, symbols);
325 * Separate the name of the include file.
327 while (*p && *p != '"' && *p != '<')
328 p++;
329 if (! *p)
330 return(-2);
331 if (*p++ == '"') {
332 ret = INCLUDEDOT;
333 while (*p && *p != '"')
334 *line++ = *p++;
335 } else
336 while (*p && *p != '>')
337 *line++ = *p++;
338 *line = '\0';
339 break;
340 case DEFINE:
342 * copy the definition back to the beginning of the line.
344 memmove (line, p, strlen(p));
345 break;
346 case ELSE:
347 case ENDIF:
348 case ELIF:
349 case PRAGMA:
350 case ERROR:
351 case IDENT:
352 case SCCS:
353 case EJECT:
354 debug(0,("%s, line %d: #%s\n",
355 file->i_file, filep->f_line, directives[ret]));
357 * nothing to do.
359 break;
361 return(ret);
365 * HACK! - so that we do not have to introduce 'symbols' in each cppsetup.c
366 * function... It's safe, functions from cppsetup.c don't return here.
368 struct symhash *global_symbols = NULL;
370 char * isdefined( symbol )
371 register char *symbol;
373 return hash_lookup( symbol, global_symbols );
377 * Return type based on if the #if expression evaluates to 0
379 int zero_value(exp, filep, file_red, symbols)
380 register char *exp;
381 register struct filepointer *filep;
382 register struct inclist *file_red;
383 register struct symhash *symbols;
385 global_symbols = symbols; /* HACK! see above */
386 if (cppsetup(exp, filep, file_red))
387 return(IFFALSE);
388 else
389 return(IF);
392 void define( def, symbols )
393 char *def;
394 struct symhash **symbols;
396 char *val;
398 /* Separate symbol name and its value */
399 val = def;
400 while (isalnum(*val) || *val == '_')
401 val++;
402 if (*val)
403 *val++ = '\0';
404 while (*val == ' ' || *val == '\t')
405 val++;
407 if (!*val)
408 val = "1";
409 hash_define( def, val, symbols );
412 static int hash( str )
413 register char *str;
415 /* Hash (Kernighan and Ritchie) */
416 register unsigned int hashval = 0;
418 for ( ; *str; str++ )
420 hashval = ( hashval * SYMHASHSEED ) + ( *str );
423 return hashval & ( SYMHASHMEMBERS - 1 );
426 struct symhash *hash_copy( symbols )
427 struct symhash *symbols;
429 int i;
430 struct symhash *newsym;
431 if ( !symbols )
432 return NULL;
434 newsym = (struct symhash *) malloc( sizeof( struct symhash ) );
436 for ( i = 0; i < SYMHASHMEMBERS; ++i )
438 if ( !symbols->s_pairs[ i ] )
439 newsym->s_pairs[ i ] = NULL;
440 else
442 struct pair *it = symbols->s_pairs[ i ];
443 struct pair *nw = newsym->s_pairs[ i ] = (struct pair*) malloc( sizeof( struct pair ) );
444 nw->p_name = it->p_name;
445 nw->p_value = it->p_value;
446 nw->p_next = NULL;
448 while ( it->p_next )
450 nw->p_next = (struct pair*) malloc( sizeof( struct pair ) );
451 it = it->p_next;
452 nw = nw->p_next;
453 nw->p_name = it->p_name;
454 nw->p_value = it->p_value;
455 nw->p_next = NULL;
459 return newsym;
462 void hash_free( symbols )
463 struct symhash *symbols;
465 int i;
467 if ( !symbols )
468 return;
470 for ( i = 0; i < SYMHASHMEMBERS; ++i )
472 struct pair *it = symbols->s_pairs[ i ];
473 struct pair *next;
474 while ( it )
476 next = it->p_next;
477 free( it );
478 it = next;
481 free( symbols->s_pairs );
484 void hash_define( name, val, symbols )
485 char *name, *val;
486 struct symhash **symbols;
488 int hashval;
489 struct pair *it;
491 if ( !symbols )
492 return;
494 /* Make space if it's needed */
495 if ( *symbols == NULL )
497 int i;
499 *symbols = (struct symhash *) malloc( sizeof( struct symhash ) );
500 if ( *symbols == NULL )
501 fatalerr( "malloc()/realloc() failure in insert_defn()\n" );
503 for ( i = 0; i < SYMHASHMEMBERS; ++i )
504 (*symbols)->s_pairs[i] = NULL;
507 hashval = hash( name );
508 it = (*symbols)->s_pairs[ hashval ];
510 /* Replace/insert the symbol */
511 if ( it == NULL )
513 it = (*symbols)->s_pairs[ hashval ] = (struct pair*) malloc( sizeof( struct pair ) );
514 it->p_name = copy( name );
515 it->p_value = copy( val );
516 it->p_next = NULL;
518 else if ( strcmp( it->p_name, name ) == 0 )
520 it->p_value = copy( val );
522 else
524 while ( it->p_next && ( strcmp( it->p_next->p_name, name ) != 0 ) )
526 it = it->p_next;
528 if ( it->p_next )
529 it->p_next->p_name = copy( name );
530 else
532 it->p_next = (struct pair*) malloc( sizeof( struct pair ) );
533 it->p_next->p_name = copy( name );
534 it->p_next->p_value = copy( val );
535 it->p_next->p_next = NULL;
540 char *hash_lookup( symbol, symbols )
541 char *symbol;
542 struct symhash *symbols;
544 struct pair *it;
546 if ( !symbols )
547 return NULL;
549 it = symbols->s_pairs[ hash( symbol ) ];
551 while ( it && ( strcmp( it->p_name, symbol ) != 0 ) )
553 it = it->p_next;
555 if ( it )
556 return it->p_value;
558 return NULL;
561 void hash_undefine( symbol, symbols )
562 char *symbol;
563 struct symhash *symbols;
565 int hashval;
566 struct pair *it;
568 if ( !symbols )
569 return;
571 hashval = hash( symbol );
572 it = symbols->s_pairs[ hashval ];
574 /* Replace/insert the symbol */
575 if ( it == NULL )
576 return;
577 else if ( strcmp( it->p_name, symbol ) == 0 )
579 if ( it->p_next )
581 struct pair *tmp;
582 it->p_name = it->p_next->p_name;
583 it->p_value = it->p_next->p_value;
584 tmp = it->p_next->p_next;
585 free( it->p_next );
586 it->p_next = tmp;
588 else
590 free( it );
591 symbols->s_pairs[ hashval ] = NULL;
594 else
596 while ( it->p_next && ( strcmp( it->p_next->p_name, symbol ) != 0 ) )
598 it = it->p_next;
600 if ( it->p_next )
602 struct pair *tmp = it->p_next;
603 it->p_next = it->p_next->p_next;
604 free( tmp );
609 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */