Version 6.1.0.2, tag libreoffice-6.1.0.2
[LibreOffice.git] / soltools / mkdepend / parse.c
blob8aa05547bbe785a257a56fe4cef09658fd009096
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 <ctype.h>
32 #include "def.h"
33 char *hash_lookup( char *symbol, struct symhash *symbols );
34 void hash_undefine( char *symbol, struct symhash *symbols );
35 int gobble( struct filepointer *filep, struct inclist *file,
36 struct inclist *file_red, struct symhash *symbols );
37 int deftype ( char *line, struct filepointer *filep, struct inclist *file,
38 int parse_it, struct symhash *symbols);
39 int zero_value(char const *exp, struct symhash *symbols);
41 extern struct symhash *maininclist;
43 int find_includes(struct filepointer *filep, struct inclist *file, struct inclist *file_red, int recursion, boolean failOK, struct IncludesCollection* incCollection, struct symhash *symbols)
45 char *line;
46 int type;
47 boolean recfailOK;
49 while ((line = get_line(filep))) {
50 switch(type = deftype(line, filep, file, TRUE, symbols)) {
51 case IF:
52 doif:
53 type = find_includes(filep, file,
54 file_red, recursion+1, failOK, incCollection, symbols);
55 while ((type == ELIF) || (type == ELIFFALSE) ||
56 (type == ELIFGUESSFALSE))
57 type = gobble(filep, file, file_red, symbols);
58 if (type == ELSE)
59 gobble(filep, file, file_red, symbols);
60 break;
61 case IFFALSE:
62 case IFGUESSFALSE:
63 doiffalse:
64 if (type == IFGUESSFALSE || type == ELIFGUESSFALSE)
65 recfailOK = TRUE;
66 else
67 recfailOK = failOK;
68 type = gobble(filep, file, file_red, symbols);
69 if (type == ELSE)
70 find_includes(filep, file,
71 file_red, recursion+1, recfailOK, incCollection, symbols);
72 else if (type == ELIF)
73 goto doif;
74 else if ((type == ELIFFALSE) || (type == ELIFGUESSFALSE))
75 goto doiffalse;
76 break;
77 case IFDEF:
78 case IFNDEF:
79 if ((type == IFDEF && hash_lookup(line, symbols))
80 || (type == IFNDEF && !hash_lookup(line, symbols))) {
81 debug(1,(type == IFNDEF ?
82 "line %d: %s !def'd in %s via %s%s\n" : "",
83 filep->f_line, line,
84 file->i_file, file_red->i_file, ": doit"));
85 type = find_includes(filep, file,
86 file_red, recursion+1, failOK, incCollection, symbols);
87 while (type == ELIF || type == ELIFFALSE || type == ELIFGUESSFALSE)
88 type = gobble(filep, file, file_red, symbols);
89 if (type == ELSE)
90 gobble(filep, file, file_red, symbols);
92 else {
93 debug(1,(type == IFDEF ?
94 "line %d: %s !def'd in %s via %s%s\n" : "",
95 filep->f_line, line,
96 file->i_file, file_red->i_file, ": gobble"));
97 type = gobble(filep, file, file_red, symbols);
98 if (type == ELSE)
99 find_includes(filep, file,
100 file_red, recursion + 1, failOK, incCollection, symbols);
101 else if (type == ELIF)
102 goto doif;
103 else if (type == ELIFFALSE || type == ELIFGUESSFALSE)
104 goto doiffalse;
106 break;
107 case ELSE:
108 case ELIFFALSE:
109 case ELIFGUESSFALSE:
110 case ELIF:
111 if (!recursion)
112 gobble(filep, file, file_red, symbols);
113 /*fall-through*/
114 case ENDIF:
115 if (recursion)
116 return type;
117 /*fall-through*/
118 case DEFINE:
119 define(line, &symbols);
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;
127 hash_undefine(line, symbols);
128 break;
129 case INCLUDE:
130 add_include(filep, file, file_red, line, FALSE, failOK, incCollection, symbols);
131 break;
132 case INCLUDEDOT:
133 add_include(filep, file, file_red, line, TRUE, failOK, incCollection, symbols);
134 break;
135 case ERROR:
136 warning("%s: %d: %s\n", file_red->i_file,
137 filep->f_line, line);
138 break;
140 case PRAGMA:
141 case IDENT:
142 case SCCS:
143 case EJECT:
144 break;
145 case -1:
146 warning("%s", file_red->i_file);
147 if (file_red != file)
148 warning1(" (reading %s)", file->i_file);
149 warning1(", line %d: unknown directive == \"%s\"\n",
150 filep->f_line, line);
151 break;
152 case -2:
153 warning("%s", file_red->i_file);
154 if (file_red != file)
155 warning1(" (reading %s)", file->i_file);
156 warning1(", line %d: incomplete include == \"%s\"\n",
157 filep->f_line, line);
158 break;
161 return -1;
164 int gobble(struct filepointer *filep,
165 struct inclist *file,
166 struct inclist *file_red,
167 struct symhash *symbols)
169 char *line;
170 int type;
172 while ((line = get_line(filep))) {
173 switch(type = deftype(line, filep, file, FALSE, symbols)) {
174 case IF:
175 case IFFALSE:
176 case IFGUESSFALSE:
177 case IFDEF:
178 case IFNDEF:
179 type = gobble(filep, file, file_red, symbols);
180 while ((type == ELIF) || (type == ELIFFALSE) ||
181 (type == ELIFGUESSFALSE))
182 type = gobble(filep, file, file_red, symbols);
183 if (type == ELSE)
184 (void)gobble(filep, file, file_red, symbols);
185 break;
186 case ELSE:
187 case ENDIF:
188 debug(0,("%s, line %d: #%s\n",
189 file->i_file, filep->f_line,
190 directives[type]));
191 return type;
192 case DEFINE:
193 case UNDEF:
194 case INCLUDE:
195 case INCLUDEDOT:
196 case PRAGMA:
197 case ERROR:
198 case IDENT:
199 case SCCS:
200 case EJECT:
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;
212 return -1;
216 * Decide what type of # directive this line is.
218 int deftype (char *line, struct filepointer *filep, struct inclist *file, int parse_it, struct symhash *symbols)
220 char *p;
221 char *directive, savechar;
222 int ret;
223 (void)filep;
225 * Parse the directive...
227 directive=line+1;
228 while (*directive == ' ' || *directive == '\t')
229 directive++;
231 p = directive;
232 while (*p >= 'a' && *p <= 'z')
233 p++;
234 savechar = *p;
235 *p = '\0';
236 ret = match(directive, directives);
237 *p = savechar;
239 /* If we don't recognize this compiler directive or we happen to just
240 * be gobbling up text while waiting for an #endif or #elif or #else
241 * in the case of an #elif we must check the zero_value and return an
242 * ELIF or an ELIFFALSE.
245 if (ret == ELIF && !parse_it)
247 while (*p == ' ' || *p == '\t')
248 p++;
250 * parse an expression.
252 debug(0,("%s, line %d: #elif %s ",
253 file->i_file, filep->f_line, p));
254 ret = zero_value(p, symbols);
255 if (ret != IF)
257 debug(0,("false...\n"));
258 if (ret == IFFALSE)
259 return ELIFFALSE;
260 else
261 return ELIFGUESSFALSE;
263 else
265 debug(0,("true...\n"));
266 return ELIF;
270 if (ret < 0 || ! parse_it)
271 return ret;
274 * now decide how to parse the directive, and do it.
276 while (*p == ' ' || *p == '\t')
277 p++;
278 switch (ret) {
279 case IF:
281 * parse an expression.
283 ret = zero_value(p, symbols);
284 debug(0,("%s, line %d: %s #if %s\n",
285 file->i_file, filep->f_line, ret?"false":"true", p));
286 break;
287 case IFDEF:
288 case IFNDEF:
289 debug(0,("%s, line %d: #%s %s\n",
290 file->i_file, filep->f_line, directives[ret], p));
291 //fall-through
292 case UNDEF:
294 * separate the name of a single symbol.
296 while (isalnum((unsigned char)*p) || *p == '_')
297 *line++ = *p++;
298 *line = '\0';
299 break;
300 case INCLUDE:
301 debug(2,("%s, line %d: #include %s\n",
302 file->i_file, filep->f_line, p));
304 /* Support ANSI macro substitution */
306 char *sym = hash_lookup(p, symbols);
307 while (sym)
309 p = sym;
310 debug(3,("%s : #includes SYMBOL %s\n",
311 file->i_incstring,
312 sym));
313 /* mark file as having included a 'soft include' */
314 file->i_included_sym = TRUE;
315 sym = hash_lookup(p, symbols);
320 * Separate the name of the include file.
322 while (*p && *p != '"' && *p != '<')
323 p++;
324 if (! *p)
325 return -2;
326 if (*p++ == '"') {
327 ret = INCLUDEDOT;
328 while (*p && *p != '"')
329 *line++ = *p++;
330 } else
331 while (*p && *p != '>')
332 *line++ = *p++;
333 *line = '\0';
334 break;
335 case DEFINE:
337 * copy the definition back to the beginning of the line.
339 memmove (line, p, strlen(p));
340 break;
341 case ELSE:
342 case ENDIF:
343 case ELIF:
344 case PRAGMA:
345 case ERROR:
346 case IDENT:
347 case SCCS:
348 case EJECT:
349 debug(0,("%s, line %d: #%s\n",
350 file->i_file, filep->f_line, directives[ret]));
352 * nothing to do.
354 break;
356 return ret;
360 * HACK! - so that we do not have to introduce 'symbols' in each cppsetup.c
361 * function... It's safe, functions from cppsetup.c don't return here.
363 static struct symhash *global_symbols = NULL;
365 char * isdefined( char *symbol )
367 return hash_lookup( symbol, global_symbols );
371 * Return type based on if the #if expression evaluates to 0
373 int zero_value(char const *exp, struct symhash *symbols)
375 global_symbols = symbols; /* HACK! see above */
376 if (cppsetup(exp))
377 return IFFALSE;
378 else
379 return IF;
382 void define( char *def, struct symhash **symbols )
384 char *val;
386 /* Separate symbol name and its value */
387 val = def;
388 while (isalnum((unsigned char)*val) || *val == '_')
389 val++;
390 if (*val)
391 *val++ = '\0';
392 while (*val == ' ' || *val == '\t')
393 val++;
395 if (!*val)
396 val = "1";
397 hash_define( def, val, symbols );
400 static int hash( char *str )
402 /* Hash (Kernighan and Ritchie) */
403 unsigned int hashval = 0;
405 for ( ; *str; str++ )
407 hashval = ( hashval * SYMHASHSEED ) + ( *str );
410 return hashval & ( SYMHASHMEMBERS - 1 );
413 struct symhash *hash_copy( struct symhash *symbols )
415 int i;
416 struct symhash *newsym;
417 if ( !symbols )
418 return NULL;
420 newsym = (struct symhash *) malloc( sizeof( struct symhash ) );
422 for ( i = 0; i < SYMHASHMEMBERS; ++i )
424 if ( !symbols->s_pairs[ i ] )
425 newsym->s_pairs[ i ] = NULL;
426 else
428 struct pair *it = symbols->s_pairs[ i ];
429 struct pair *nw = newsym->s_pairs[ i ] = (struct pair*) malloc( sizeof( struct pair ) );
430 nw->p_name = it->p_name;
431 nw->p_value = it->p_value;
432 nw->p_next = NULL;
434 while ( it->p_next )
436 nw->p_next = (struct pair*) malloc( sizeof( struct pair ) );
437 it = it->p_next;
438 nw = nw->p_next;
439 nw->p_name = it->p_name;
440 nw->p_value = it->p_value;
441 nw->p_next = NULL;
445 return newsym;
448 void hash_free( struct symhash *symbols )
450 int i;
452 if ( !symbols )
453 return;
455 for ( i = 0; i < SYMHASHMEMBERS; ++i )
457 struct pair *it = symbols->s_pairs[ i ];
458 struct pair *next;
459 while ( it )
461 next = it->p_next;
462 free( it );
463 it = next;
466 free( symbols->s_pairs );
469 void hash_define( char *name, char const *val, struct symhash **symbols )
471 int hashval;
472 struct pair *it;
474 if ( !symbols )
475 return;
477 /* Make space if it's needed */
478 if ( *symbols == NULL )
480 int i;
482 *symbols = (struct symhash *) malloc( sizeof( struct symhash ) );
483 if ( *symbols == NULL )
484 fatalerr( "malloc()/realloc() failure in insert_defn()\n" );
486 for ( i = 0; i < SYMHASHMEMBERS; ++i )
487 (*symbols)->s_pairs[i] = NULL;
490 hashval = hash( name );
491 it = (*symbols)->s_pairs[ hashval ];
493 /* Replace/insert the symbol */
494 if ( it == NULL )
496 it = (*symbols)->s_pairs[ hashval ] = (struct pair*) malloc( sizeof( struct pair ) );
497 it->p_name = copy( name );
498 it->p_value = copy( val );
499 it->p_next = NULL;
501 else if ( strcmp( it->p_name, name ) == 0 )
503 it->p_value = copy( val );
505 else
507 while ( it->p_next && ( strcmp( it->p_next->p_name, name ) != 0 ) )
509 it = it->p_next;
511 if ( it->p_next )
512 it->p_next->p_name = copy( name );
513 else
515 it->p_next = (struct pair*) malloc( sizeof( struct pair ) );
516 it->p_next->p_name = copy( name );
517 it->p_next->p_value = copy( val );
518 it->p_next->p_next = NULL;
523 char *hash_lookup( char *symbol, struct symhash *symbols )
525 struct pair *it;
527 if ( !symbols )
528 return NULL;
530 it = symbols->s_pairs[ hash( symbol ) ];
532 while ( it && ( strcmp( it->p_name, symbol ) != 0 ) )
534 it = it->p_next;
536 if ( it )
537 return it->p_value;
539 return NULL;
542 void hash_undefine( char *symbol, struct symhash *symbols )
544 int hashval;
545 struct pair *it;
547 if ( !symbols )
548 return;
550 hashval = hash( symbol );
551 it = symbols->s_pairs[ hashval ];
553 /* Replace/insert the symbol */
554 if ( it == NULL )
555 return;
556 else if ( strcmp( it->p_name, symbol ) == 0 )
558 if ( it->p_next )
560 struct pair *tmp;
561 it->p_name = it->p_next->p_name;
562 it->p_value = it->p_next->p_value;
563 tmp = it->p_next->p_next;
564 free( it->p_next );
565 it->p_next = tmp;
567 else
569 free( it );
570 symbols->s_pairs[ hashval ] = NULL;
573 else
575 while ( it->p_next && ( strcmp( it->p_next->p_name, symbol ) != 0 ) )
577 it = it->p_next;
579 if ( it->p_next )
581 struct pair *tmp = it->p_next;
582 it->p_next = it->p_next->p_next;
583 free( tmp );
588 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */