Version 5.4.3.2, tag libreoffice-5.4.3.2
[LibreOffice.git] / soltools / mkdepend / parse.c
blob01d34dcc1c146ae7d1c568c8a2ac11fb7b106ea2
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,
38 struct inclist *file_red, struct inclist *file,
39 int parse_it, struct symhash *symbols);
40 int zero_value(char *exp, struct filepointer *filep,
41 struct inclist *file_red, struct symhash *symbols);
43 extern struct symhash *maininclist;
45 int find_includes(struct filepointer *filep, struct inclist *file, struct inclist *file_red, int recursion, boolean failOK, struct IncludesCollection* incCollection, struct symhash *symbols)
47 char *line;
48 int type;
49 boolean recfailOK;
51 while ((line = get_line(filep))) {
52 switch(type = deftype(line, filep, file_red, file, TRUE, symbols)) {
53 case IF:
54 doif:
55 type = find_includes(filep, file,
56 file_red, recursion+1, failOK, incCollection, symbols);
57 while ((type == ELIF) || (type == ELIFFALSE) ||
58 (type == ELIFGUESSFALSE))
59 type = gobble(filep, file, file_red, symbols);
60 if (type == ELSE)
61 gobble(filep, file, file_red, symbols);
62 break;
63 case IFFALSE:
64 case IFGUESSFALSE:
65 doiffalse:
66 if (type == IFGUESSFALSE || type == ELIFGUESSFALSE)
67 recfailOK = TRUE;
68 else
69 recfailOK = failOK;
70 type = gobble(filep, file, file_red, symbols);
71 if (type == ELSE)
72 find_includes(filep, file,
73 file_red, recursion+1, recfailOK, incCollection, symbols);
74 else if (type == ELIF)
75 goto doif;
76 else if ((type == ELIFFALSE) || (type == ELIFGUESSFALSE))
77 goto doiffalse;
78 break;
79 case IFDEF:
80 case IFNDEF:
81 if ((type == IFDEF && hash_lookup(line, symbols))
82 || (type == IFNDEF && !hash_lookup(line, symbols))) {
83 debug(1,(type == IFNDEF ?
84 "line %d: %s !def'd in %s via %s%s\n" : "",
85 filep->f_line, line,
86 file->i_file, file_red->i_file, ": doit"));
87 type = find_includes(filep, file,
88 file_red, recursion+1, failOK, incCollection, symbols);
89 while (type == ELIF || type == ELIFFALSE || type == ELIFGUESSFALSE)
90 type = gobble(filep, file, file_red, symbols);
91 if (type == ELSE)
92 gobble(filep, file, file_red, symbols);
94 else {
95 debug(1,(type == IFDEF ?
96 "line %d: %s !def'd in %s via %s%s\n" : "",
97 filep->f_line, line,
98 file->i_file, file_red->i_file, ": gobble"));
99 type = gobble(filep, file, file_red, symbols);
100 if (type == ELSE)
101 find_includes(filep, file,
102 file_red, recursion + 1, failOK, incCollection, symbols);
103 else if (type == ELIF)
104 goto doif;
105 else if (type == ELIFFALSE || type == ELIFGUESSFALSE)
106 goto doiffalse;
108 break;
109 case ELSE:
110 case ELIFFALSE:
111 case ELIFGUESSFALSE:
112 case ELIF:
113 if (!recursion)
114 gobble(filep, file, file_red, symbols);
115 /*fall-through*/
116 case ENDIF:
117 if (recursion)
118 return type;
119 /*fall-through*/
120 case DEFINE:
121 define(line, &symbols);
122 break;
123 case UNDEF:
124 if (!*line) {
125 warning("%s, line %d: incomplete undef == \"%s\"\n",
126 file_red->i_file, filep->f_line, line);
127 break;
129 hash_undefine(line, symbols);
130 break;
131 case INCLUDE:
132 add_include(filep, file, file_red, line, FALSE, failOK, incCollection, symbols);
133 break;
134 case INCLUDEDOT:
135 add_include(filep, file, file_red, line, TRUE, failOK, incCollection, symbols);
136 break;
137 case ERROR:
138 warning("%s: %d: %s\n", file_red->i_file,
139 filep->f_line, line);
140 break;
142 case PRAGMA:
143 case IDENT:
144 case SCCS:
145 case EJECT:
146 break;
147 case -1:
148 warning("%s", file_red->i_file);
149 if (file_red != file)
150 warning1(" (reading %s)", file->i_file);
151 warning1(", line %d: unknown directive == \"%s\"\n",
152 filep->f_line, line);
153 break;
154 case -2:
155 warning("%s", file_red->i_file);
156 if (file_red != file)
157 warning1(" (reading %s)", file->i_file);
158 warning1(", line %d: incomplete include == \"%s\"\n",
159 filep->f_line, line);
160 break;
163 return -1;
166 int gobble(struct filepointer *filep,
167 struct inclist *file,
168 struct inclist *file_red,
169 struct symhash *symbols)
171 char *line;
172 int type;
174 while ((line = get_line(filep))) {
175 switch(type = deftype(line, filep, file_red, file, FALSE, symbols)) {
176 case IF:
177 case IFFALSE:
178 case IFGUESSFALSE:
179 case IFDEF:
180 case IFNDEF:
181 type = gobble(filep, file, file_red, symbols);
182 while ((type == ELIF) || (type == ELIFFALSE) ||
183 (type == ELIFGUESSFALSE))
184 type = gobble(filep, file, file_red, symbols);
185 if (type == ELSE)
186 (void)gobble(filep, file, file_red, symbols);
187 break;
188 case ELSE:
189 case ENDIF:
190 debug(0,("%s, line %d: #%s\n",
191 file->i_file, filep->f_line,
192 directives[type]));
193 return type;
194 case DEFINE:
195 case UNDEF:
196 case INCLUDE:
197 case INCLUDEDOT:
198 case PRAGMA:
199 case ERROR:
200 case IDENT:
201 case SCCS:
202 case EJECT:
203 break;
204 case ELIF:
205 case ELIFFALSE:
206 case ELIFGUESSFALSE:
207 return type;
208 case -1:
209 warning("%s, line %d: unknown directive == \"%s\"\n",
210 file_red->i_file, filep->f_line, line);
211 break;
214 return -1;
218 * Decide what type of # directive this line is.
220 int deftype (char *line, struct filepointer *filep, struct inclist *file_red, struct inclist *file, int parse_it, struct symhash *symbols)
222 char *p;
223 char *directive, savechar;
224 int ret;
227 * Parse the directive...
229 directive=line+1;
230 while (*directive == ' ' || *directive == '\t')
231 directive++;
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;
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.
247 if (ret == ELIF && !parse_it)
249 while (*p == ' ' || *p == '\t')
250 p++;
252 * parse an expression.
254 debug(0,("%s, line %d: #elif %s ",
255 file->i_file, filep->f_line, p));
256 ret = zero_value(p, filep, file_red, symbols);
257 if (ret != IF)
259 debug(0,("false...\n"));
260 if (ret == IFFALSE)
261 return ELIFFALSE;
262 else
263 return ELIFGUESSFALSE;
265 else
267 debug(0,("true...\n"));
268 return ELIF;
272 if (ret < 0 || ! parse_it)
273 return ret;
276 * now decide how to parse the directive, and do it.
278 while (*p == ' ' || *p == '\t')
279 p++;
280 switch (ret) {
281 case IF:
283 * parse an expression.
285 ret = zero_value(p, filep, file_red, symbols);
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 //fall-through
294 case UNDEF:
296 * separate the name of a single symbol.
298 while (isalnum((unsigned char)*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));
306 /* Support ANSI macro substitution */
308 char *sym = hash_lookup(p, symbols);
309 while (sym)
311 p = sym;
312 debug(3,("%s : #includes SYMBOL %s\n",
313 file->i_incstring,
314 sym));
315 /* mark file as having included a 'soft include' */
316 file->i_included_sym = TRUE;
317 sym = hash_lookup(p, symbols);
322 * Separate the name of the include file.
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:
339 * copy the definition back to the beginning of the line.
341 memmove (line, p, strlen(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 debug(0,("%s, line %d: #%s\n",
352 file->i_file, filep->f_line, directives[ret]));
354 * nothing to do.
356 break;
358 return ret;
362 * HACK! - so that we do not have to introduce 'symbols' in each cppsetup.c
363 * function... It's safe, functions from cppsetup.c don't return here.
365 static struct symhash *global_symbols = NULL;
367 char * isdefined( char *symbol )
369 return hash_lookup( symbol, global_symbols );
373 * Return type based on if the #if expression evaluates to 0
375 int zero_value(char *exp, struct filepointer *filep, struct inclist *file_red, struct symhash *symbols)
377 global_symbols = symbols; /* HACK! see above */
378 if (cppsetup(exp, filep, file_red))
379 return IFFALSE;
380 else
381 return IF;
384 void define( char *def, struct symhash **symbols )
386 char *val;
388 /* Separate symbol name and its value */
389 val = def;
390 while (isalnum((unsigned char)*val) || *val == '_')
391 val++;
392 if (*val)
393 *val++ = '\0';
394 while (*val == ' ' || *val == '\t')
395 val++;
397 if (!*val)
398 val = "1";
399 hash_define( def, val, symbols );
402 static int hash( char *str )
404 /* Hash (Kernighan and Ritchie) */
405 unsigned int hashval = 0;
407 for ( ; *str; str++ )
409 hashval = ( hashval * SYMHASHSEED ) + ( *str );
412 return hashval & ( SYMHASHMEMBERS - 1 );
415 struct symhash *hash_copy( struct symhash *symbols )
417 int i;
418 struct symhash *newsym;
419 if ( !symbols )
420 return NULL;
422 newsym = (struct symhash *) malloc( sizeof( struct symhash ) );
424 for ( i = 0; i < SYMHASHMEMBERS; ++i )
426 if ( !symbols->s_pairs[ i ] )
427 newsym->s_pairs[ i ] = NULL;
428 else
430 struct pair *it = symbols->s_pairs[ i ];
431 struct pair *nw = newsym->s_pairs[ i ] = (struct pair*) malloc( sizeof( struct pair ) );
432 nw->p_name = it->p_name;
433 nw->p_value = it->p_value;
434 nw->p_next = NULL;
436 while ( it->p_next )
438 nw->p_next = (struct pair*) malloc( sizeof( struct pair ) );
439 it = it->p_next;
440 nw = nw->p_next;
441 nw->p_name = it->p_name;
442 nw->p_value = it->p_value;
443 nw->p_next = NULL;
447 return newsym;
450 void hash_free( struct symhash *symbols )
452 int i;
454 if ( !symbols )
455 return;
457 for ( i = 0; i < SYMHASHMEMBERS; ++i )
459 struct pair *it = symbols->s_pairs[ i ];
460 struct pair *next;
461 while ( it )
463 next = it->p_next;
464 free( it );
465 it = next;
468 free( symbols->s_pairs );
471 void hash_define( char *name, char *val, struct symhash **symbols )
473 int hashval;
474 struct pair *it;
476 if ( !symbols )
477 return;
479 /* Make space if it's needed */
480 if ( *symbols == NULL )
482 int i;
484 *symbols = (struct symhash *) malloc( sizeof( struct symhash ) );
485 if ( *symbols == NULL )
486 fatalerr( "malloc()/realloc() failure in insert_defn()\n" );
488 for ( i = 0; i < SYMHASHMEMBERS; ++i )
489 (*symbols)->s_pairs[i] = NULL;
492 hashval = hash( name );
493 it = (*symbols)->s_pairs[ hashval ];
495 /* Replace/insert the symbol */
496 if ( it == NULL )
498 it = (*symbols)->s_pairs[ hashval ] = (struct pair*) malloc( sizeof( struct pair ) );
499 it->p_name = copy( name );
500 it->p_value = copy( val );
501 it->p_next = NULL;
503 else if ( strcmp( it->p_name, name ) == 0 )
505 it->p_value = copy( val );
507 else
509 while ( it->p_next && ( strcmp( it->p_next->p_name, name ) != 0 ) )
511 it = it->p_next;
513 if ( it->p_next )
514 it->p_next->p_name = copy( name );
515 else
517 it->p_next = (struct pair*) malloc( sizeof( struct pair ) );
518 it->p_next->p_name = copy( name );
519 it->p_next->p_value = copy( val );
520 it->p_next->p_next = NULL;
525 char *hash_lookup( char *symbol, struct symhash *symbols )
527 struct pair *it;
529 if ( !symbols )
530 return NULL;
532 it = symbols->s_pairs[ hash( symbol ) ];
534 while ( it && ( strcmp( it->p_name, symbol ) != 0 ) )
536 it = it->p_next;
538 if ( it )
539 return it->p_value;
541 return NULL;
544 void hash_undefine( char *symbol, struct symhash *symbols )
546 int hashval;
547 struct pair *it;
549 if ( !symbols )
550 return;
552 hashval = hash( symbol );
553 it = symbols->s_pairs[ hashval ];
555 /* Replace/insert the symbol */
556 if ( it == NULL )
557 return;
558 else if ( strcmp( it->p_name, symbol ) == 0 )
560 if ( it->p_next )
562 struct pair *tmp;
563 it->p_name = it->p_next->p_name;
564 it->p_value = it->p_next->p_value;
565 tmp = it->p_next->p_next;
566 free( it->p_next );
567 it->p_next = tmp;
569 else
571 free( it );
572 symbols->s_pairs[ hashval ] = NULL;
575 else
577 while ( it->p_next && ( strcmp( it->p_next->p_name, symbol ) != 0 ) )
579 it = it->p_next;
581 if ( it->p_next )
583 struct pair *tmp = it->p_next;
584 it->p_next = it->p_next->p_next;
585 free( tmp );
590 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */