2 * CDE - Common Desktop Environment
4 * Copyright (c) 1993-2012, The Open Group. All rights reserved.
6 * These libraries and programs are free software; you can
7 * redistribute them and/or modify them under the terms of the GNU
8 * Lesser General Public License as published by the Free Software
9 * Foundation; either version 2 of the License, or (at your option)
12 * These libraries and programs are distributed in the hope that
13 * they will be useful, but WITHOUT ANY WARRANTY; without even the
14 * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
15 * PURPOSE. See the GNU Lesser General Public License for more
18 * You should have received a copy of the GNU Lesser General Public
19 * License along with these librararies and programs; if not, write
20 * to the Free Software Foundation, Inc., 51 Franklin Street, Fifth
21 * Floor, Boston, MA 02110-1301 USA
23 /* $TOG: parse.c /main/35 1998/03/25 08:17:55 kaleb $ */
26 Copyright (c) 1993, 1994, 1998 The Open Group
30 The above copyright notice and this permission notice shall be included in
31 all copies or substantial portions of the Software.
33 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
34 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
35 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
36 OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
37 AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
38 CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
40 Except as contained in this notice, the name of The Open Group shall not be
41 used in advertising or otherwise to promote the sale, use or other dealings
42 in this Software without prior written authorization from The Open Group.
48 extern char *directives[];
49 extern struct inclist maininclist;
52 gobble(filep, file, file_red)
53 register struct filepointer *filep;
54 struct inclist *file, *file_red;
59 while (line = our_getline(filep)) {
60 switch(type = deftype(line, filep, file_red, file, FALSE)) {
66 type = gobble(filep, file, file_red);
67 while ((type == ELIF) || (type == ELIFFALSE) ||
68 (type == ELIFGUESSFALSE))
69 type = gobble(filep, file, file_red);
71 (void)gobble(filep, file, file_red);
75 debug(0,("%s, line %d: #%s\n",
76 file->i_file, filep->f_line,
95 warning("%s, line %d: unknown directive == \"%s\"\n",
96 file_red->i_file, filep->f_line, line);
104 * Decide what type of # directive this line is.
106 int deftype (line, filep, file_red, file, parse_it)
108 register struct filepointer *filep;
109 register struct inclist *file_red, *file;
113 char *directive, savechar;
117 * Parse the directive...
120 while (*directive == ' ' || *directive == '\t')
124 while (*p >= 'a' && *p <= 'z')
128 ret = match(directive, directives);
131 /* If we don't recognize this compiler directive or we happen to just
132 * be gobbling up text while waiting for an #endif or #elif or #else
133 * in the case of an #elif we must check the zero_value and return an
134 * ELIF or an ELIFFALSE.
137 if (ret == ELIF && !parse_it)
139 while (*p == ' ' || *p == '\t')
142 * parse an expression.
144 debug(0,("%s, line %d: #elif %s ",
145 file->i_file, filep->f_line, p));
146 ret = zero_value(p, filep, file_red);
149 debug(0,("false...\n"));
153 return(ELIFGUESSFALSE);
157 debug(0,("true...\n"));
162 if (ret < 0 || ! parse_it)
166 * now decide how to parse the directive, and do it.
168 while (*p == ' ' || *p == '\t')
173 * parse an expression.
175 ret = zero_value(p, filep, file_red);
176 debug(0,("%s, line %d: %s #if %s\n",
177 file->i_file, filep->f_line, ret?"false":"true", p));
181 debug(0,("%s, line %d: #%s %s\n",
182 file->i_file, filep->f_line, directives[ret], p));
185 * separate the name of a single symbol.
187 while (isalnum(*p) || *p == '_')
192 debug(2,("%s, line %d: #include %s\n",
193 file->i_file, filep->f_line, p));
195 /* Support ANSI macro substitution */
197 struct symtab **sym = isdefined(p, file_red, NULL);
200 debug(3,("%s : #includes SYMBOL %s = %s\n",
204 /* mark file as having included a 'soft include' */
205 file->i_flags |= INCLUDED_SYM;
206 sym = isdefined(p, file_red, NULL);
211 * Separate the name of the include file.
213 while (*p && *p != '"' && *p != '<')
219 while (*p && *p != '"')
222 while (*p && *p != '>')
228 * copy the definition back to the beginning of the line.
240 debug(0,("%s, line %d: #%s\n",
241 file->i_file, filep->f_line, directives[ret]));
250 struct symtab **fdefined(symbol, file, srcfile)
251 register char *symbol;
252 struct inclist *file;
253 struct inclist **srcfile;
255 register struct inclist **ip;
256 register struct symtab **val;
258 static int recurse_lvl = 0;
260 if (file->i_flags & DEFCHECKED)
262 file->i_flags |= DEFCHECKED;
263 if (val = slookup(symbol, file))
264 debug(1,("%s defined in %s as %s\n",
265 symbol, file->i_file, (*val)->s_value));
266 if (val == NULL && file->i_list)
268 for (ip = file->i_list, i=0; i < file->i_listlen; i++, ip++)
269 if (file->i_merged[i]==FALSE) {
270 val = fdefined(symbol, *ip, srcfile);
271 if ((*ip)->i_flags & FINISHED) {
272 merge2defines(file,*ip);
273 file->i_merged[i]=TRUE;
275 if (val!=NULL) break;
278 else if (val != NULL && srcfile != NULL) *srcfile = file;
280 file->i_flags &= ~DEFCHECKED;
285 struct symtab **isdefined(symbol, file, srcfile)
286 register char *symbol;
287 struct inclist *file;
288 struct inclist **srcfile;
290 register struct symtab **val;
292 if (val = slookup(symbol, &maininclist)) {
293 debug(1,("%s defined on command line\n", symbol));
294 if (srcfile != NULL) *srcfile = &maininclist;
297 if (val = fdefined(symbol, file, srcfile))
299 debug(1,("%s not defined in %s\n", symbol, file->i_file));
304 * Return type based on if the #if expression evaluates to 0
307 zero_value(exp, filep, file_red)
309 register struct filepointer *filep;
310 register struct inclist *file_red;
312 if (cppsetup(exp, filep, file_red))
319 define2(name, val, file)
321 struct inclist *file;
323 int first, last, below;
324 register struct symtab **sp = NULL, **dest;
327 /* Make space if it's needed */
328 if (file->i_defs == NULL)
330 file->i_defs = (struct symtab **)
331 malloc(sizeof (struct symtab*) * SYMTABINC);
334 else if (!(file->i_ndefs % SYMTABINC))
335 file->i_defs = (struct symtab **)
336 realloc(file->i_defs,
337 sizeof(struct symtab*)*(file->i_ndefs+SYMTABINC));
339 if (file->i_defs == NULL)
340 fatalerr("malloc()/realloc() failure in insert_defn()\n");
343 last = file->i_ndefs - 1;
344 while (last >= first)
346 /* Fast inline binary search */
349 register int middle = (first + last) / 2;
351 /* Fast inline strchr() */
353 s2 = file->i_defs[middle]->s_name;
354 while (*s1++ == *s2++)
355 if (s2[-1] == '\0') break;
357 /* If exact match, set sp and break */
360 sp = file->i_defs + middle;
364 /* If name > i_defs[middle] ... */
373 below = last = middle - 1;
377 /* Search is done. If we found an exact match to the symbol name,
378 just replace its s_value */
381 free((*sp)->s_value);
382 (*sp)->s_value = copy(val);
386 sp = file->i_defs + file->i_ndefs++;
387 dest = file->i_defs + below + 1;
393 stab = (struct symtab *) malloc(sizeof (struct symtab));
395 fatalerr("malloc()/realloc() failure in insert_defn()\n");
397 stab->s_name = copy(name);
398 stab->s_value = copy(val);
405 struct inclist *file;
409 /* Separate symbol name and its value */
411 while (isalnum(*val) || *val == '_')
415 while (*val == ' ' || *val == '\t')
420 define2(def, val, file);
423 struct symtab **slookup(symbol, file)
424 register char *symbol;
425 register struct inclist *file;
427 register int first = 0;
428 register int last = file->i_ndefs - 1;
430 if (file) while (last >= first)
432 /* Fast inline binary search */
435 register int middle = (first + last) / 2;
437 /* Fast inline strchr() */
439 s2 = file->i_defs[middle]->s_name;
440 while (*s1++ == *s2++)
441 if (s2[-1] == '\0') break;
443 /* If exact match, we're done */
446 return file->i_defs + middle;
449 /* If symbol > i_defs[middle] ... */
463 int merge2defines(file1, file2)
464 struct inclist *file1;
465 struct inclist *file2;
467 if ((file1!=NULL) && (file2!=NULL))
470 int last1 = file1->i_ndefs - 1;
473 int last2 = file2->i_ndefs - 1;
476 struct symtab** i_defs = NULL;
477 int deflen=file1->i_ndefs+file2->i_ndefs;
481 /* make sure deflen % SYMTABINC == 0 is still true */
482 deflen += (SYMTABINC - deflen % SYMTABINC) % SYMTABINC;
483 i_defs=(struct symtab**)
484 malloc(deflen*sizeof(struct symtab*));
485 if (i_defs==NULL) return 0;
488 while ((last1 >= first1) && (last2 >= first2))
490 char *s1=file1->i_defs[first1]->s_name;
491 char *s2=file2->i_defs[first2]->s_name;
493 if (strcmp(s1,s2) < 0)
494 i_defs[first++]=file1->i_defs[first1++];
495 else if (strcmp(s1,s2) > 0)
496 i_defs[first++]=file2->i_defs[first2++];
499 i_defs[first++]=file2->i_defs[first2++];
503 while (last1 >= first1)
505 i_defs[first++]=file1->i_defs[first1++];
507 while (last2 >= first2)
509 i_defs[first++]=file2->i_defs[first2++];
512 if (file1->i_defs) free(file1->i_defs);
513 file1->i_defs=i_defs;
514 file1->i_ndefs=first;
522 undefine(symbol, file)
524 register struct inclist *file;
526 register struct symtab **ptr;
527 struct inclist *srcfile;
528 while ((ptr = isdefined(symbol, file, &srcfile)) != NULL)
531 for (; ptr < srcfile->i_defs + srcfile->i_ndefs; ptr++)
537 find_includes(filep, file, file_red, recursion, failOK)
538 struct filepointer *filep;
539 struct inclist *file, *file_red;
547 while (line = our_getline(filep)) {
548 switch(type = deftype(line, filep, file_red, file, TRUE)) {
551 type = find_includes(filep, file,
552 file_red, recursion+1, failOK);
553 while ((type == ELIF) || (type == ELIFFALSE) ||
554 (type == ELIFGUESSFALSE))
555 type = gobble(filep, file, file_red);
557 gobble(filep, file, file_red);
562 if (type == IFGUESSFALSE || type == ELIFGUESSFALSE)
566 type = gobble(filep, file, file_red);
568 find_includes(filep, file,
569 file_red, recursion+1, recfailOK);
574 if ((type == ELIFFALSE) || (type == ELIFGUESSFALSE))
579 if ((type == IFDEF && isdefined(line, file_red, NULL))
580 || (type == IFNDEF && !isdefined(line, file_red, NULL))) {
581 debug(1,(type == IFNDEF ?
582 "line %d: %s !def'd in %s via %s%s\n" : "",
584 file->i_file, file_red->i_file, ": doit"));
585 type = find_includes(filep, file,
586 file_red, recursion+1, failOK);
587 while (type == ELIF || type == ELIFFALSE || type == ELIFGUESSFALSE)
588 type = gobble(filep, file, file_red);
590 gobble(filep, file, file_red);
593 debug(1,(type == IFDEF ?
594 "line %d: %s !def'd in %s via %s%s\n" : "",
596 file->i_file, file_red->i_file, ": gobble"));
597 type = gobble(filep, file, file_red);
599 find_includes(filep, file,
600 file_red, recursion+1, failOK);
601 else if (type == ELIF)
603 else if (type == ELIFFALSE || type == ELIFGUESSFALSE)
612 gobble(filep, file, file_red);
621 warning("%s, line %d: incomplete undef == \"%s\"\n",
622 file_red->i_file, filep->f_line, line);
625 undefine(line, file_red);
628 add_include(filep, file, file_red, line, FALSE, failOK);
631 add_include(filep, file, file_red, line, TRUE, failOK);
634 warning("%s: %d: %s\n", file_red->i_file,
635 filep->f_line, line);
644 warning("%s", file_red->i_file);
645 if (file_red != file)
646 warning1(" (reading %s)", file->i_file);
647 warning1(", line %d: unknown directive == \"%s\"\n",
648 filep->f_line, line);
651 warning("%s", file_red->i_file);
652 if (file_red != file)
653 warning1(" (reading %s)", file->i_file);
654 warning1(", line %d: incomplete include == \"%s\"\n",
655 filep->f_line, line);
659 file->i_flags |= FINISHED;