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 libraries 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.
49 static int zero_value();
50 static int merge2defines();
52 extern char *directives[];
53 extern struct inclist maininclist;
56 gobble(filep, file, file_red)
57 struct filepointer *filep;
58 struct inclist *file, *file_red;
63 while ((line = our_getline(filep))) {
64 switch(type = deftype(line, filep, file_red, file, FALSE)) {
70 type = gobble(filep, file, file_red);
71 while ((type == ELIF) || (type == ELIFFALSE) ||
72 (type == ELIFGUESSFALSE))
73 type = gobble(filep, file, file_red);
75 (void)gobble(filep, file, file_red);
79 debug(0,("%s, line %d: #%s\n",
80 file->i_file, filep->f_line,
99 warning("%s, line %d: unknown directive == \"%s\"\n",
100 file_red->i_file, filep->f_line, line);
108 * Decide what type of # directive this line is.
110 int deftype (line, filep, file_red, file, parse_it)
112 struct filepointer *filep;
113 struct inclist *file_red, *file;
117 char *directive, savechar, *q;
121 * Parse the directive...
124 while (*directive == ' ' || *directive == '\t')
128 while (*p >= 'a' && *p <= 'z')
132 ret = match(directive, directives);
135 /* If we don't recognize this compiler directive or we happen to just
136 * be gobbling up text while waiting for an #endif or #elif or #else
137 * in the case of an #elif we must check the zero_value and return an
138 * ELIF or an ELIFFALSE.
141 if (ret == ELIF && !parse_it)
143 while (*p == ' ' || *p == '\t')
146 * parse an expression.
148 debug(0,("%s, line %d: #elif %s ",
149 file->i_file, filep->f_line, p));
150 ret = zero_value(p, filep, file_red);
153 debug(0,("false...\n"));
157 return(ELIFGUESSFALSE);
161 debug(0,("true...\n"));
166 if (ret < 0 || ! parse_it)
170 * now decide how to parse the directive, and do it.
172 while (*p == ' ' || *p == '\t')
177 } while (*q == ' ' || *q == '\t');
182 * parse an expression.
184 ret = zero_value(p, filep, file_red);
185 debug(0,("%s, line %d: %s #if %s\n",
186 file->i_file, filep->f_line, ret?"false":"true", p));
190 debug(0,("%s, line %d: #%s %s\n",
191 file->i_file, filep->f_line, directives[ret], p));
194 * separate the name of a single symbol.
196 while (isalnum((int)*p) || *p == '_')
201 debug(2,("%s, line %d: #include %s\n",
202 file->i_file, filep->f_line, p));
204 /* Support ANSI macro substitution */
206 struct symtab **sym = isdefined(p, file_red, NULL);
209 debug(3,("%s : #includes SYMBOL %s = %s\n",
213 /* mark file as having included a 'soft include' */
214 file->i_flags |= INCLUDED_SYM;
215 sym = isdefined(p, file_red, NULL);
220 * Separate the name of the include file.
222 while (*p && *p != '"' && *p != '<')
228 while (*p && *p != '"')
231 while (*p && *p != '>')
237 * copy the definition back to the beginning of the line.
239 memmove (line, p, strlen(p) + 1);
249 debug(0,("%s, line %d: #%s\n",
250 file->i_file, filep->f_line, directives[ret]));
259 struct symtab **fdefined(symbol, file, srcfile)
261 struct inclist *file;
262 struct inclist **srcfile;
267 static int recurse_lvl = 0;
269 if (file->i_flags & DEFCHECKED)
271 file->i_flags |= DEFCHECKED;
272 if ((val = slookup(symbol, file)))
273 debug(1,("%s defined in %s as %s\n",
274 symbol, file->i_file, (*val)->s_value));
275 if (val == NULL && file->i_list)
277 for (ip = file->i_list, i=0; i < file->i_listlen; i++, ip++)
278 if (file->i_merged[i]==FALSE) {
279 val = fdefined(symbol, *ip, srcfile);
280 if ((*ip)->i_flags & FINISHED) {
281 merge2defines(file,*ip);
282 file->i_merged[i]=TRUE;
284 if (val!=NULL) break;
287 else if (val != NULL && srcfile != NULL) *srcfile = file;
289 file->i_flags &= ~DEFCHECKED;
294 struct symtab **isdefined(symbol, file, srcfile)
296 struct inclist *file;
297 struct inclist **srcfile;
301 if ((val = slookup(symbol, &maininclist))) {
302 debug(1,("%s defined on command line\n", symbol));
303 if (srcfile != NULL) *srcfile = &maininclist;
306 if ((val = fdefined(symbol, file, srcfile)))
308 debug(1,("%s not defined in %s\n", symbol, file->i_file));
313 * Return type based on if the #if expression evaluates to 0
316 zero_value(exp, filep, file_red)
318 struct filepointer *filep;
319 struct inclist *file_red;
321 if ((cppsetup(exp, filep, file_red)))
328 define2(name, val, file)
330 struct inclist *file;
332 int first, last, below;
333 struct symtab **sp = NULL, **dest;
336 /* Make space if it's needed */
337 if (file->i_defs == NULL)
339 file->i_defs = (struct symtab **)
340 malloc(sizeof (struct symtab*) * SYMTABINC);
343 else if (!(file->i_ndefs % SYMTABINC))
344 file->i_defs = (struct symtab **)
345 realloc(file->i_defs,
346 sizeof(struct symtab*)*(file->i_ndefs+SYMTABINC));
348 if (file->i_defs == NULL)
349 fatalerr("malloc()/realloc() failure in insert_defn()\n");
352 last = file->i_ndefs - 1;
353 while (last >= first)
355 /* Fast inline binary search */
358 int middle = (first + last) / 2;
360 /* Fast inline strchr() */
362 s2 = file->i_defs[middle]->s_name;
363 while (*s1++ == *s2++)
364 if (s2[-1] == '\0') break;
366 /* If exact match, set sp and break */
369 sp = file->i_defs + middle;
373 /* If name > i_defs[middle] ... */
382 below = last = middle - 1;
386 /* Search is done. If we found an exact match to the symbol name,
387 just replace its s_value */
390 free((*sp)->s_value);
391 (*sp)->s_value = copy(val);
395 sp = file->i_defs + file->i_ndefs++;
396 dest = file->i_defs + below + 1;
402 stab = (struct symtab *) malloc(sizeof (struct symtab));
404 fatalerr("malloc()/realloc() failure in insert_defn()\n");
406 stab->s_name = copy(name);
407 stab->s_value = copy(val);
414 struct inclist *file;
418 /* Separate symbol name and its value */
420 while (isalnum((int)*val) || *val == '_')
424 while (*val == ' ' || *val == '\t')
429 define2(def, val, file);
432 struct symtab **slookup(symbol, file)
434 struct inclist *file;
437 int last = file->i_ndefs - 1;
439 if (file) while (last >= first)
441 /* Fast inline binary search */
444 int middle = (first + last) / 2;
446 /* Fast inline strchr() */
448 s2 = file->i_defs[middle]->s_name;
449 while (*s1++ == *s2++)
450 if (s2[-1] == '\0') break;
452 /* If exact match, we're done */
455 return file->i_defs + middle;
458 /* If symbol > i_defs[middle] ... */
472 int merge2defines(file1, file2)
473 struct inclist *file1;
474 struct inclist *file2;
476 if ((file1!=NULL) && (file2!=NULL))
479 int last1 = file1->i_ndefs - 1;
482 int last2 = file2->i_ndefs - 1;
485 struct symtab** i_defs = NULL;
486 int deflen=file1->i_ndefs+file2->i_ndefs;
490 /* make sure deflen % SYMTABINC == 0 is still true */
491 deflen += (SYMTABINC - deflen % SYMTABINC) % SYMTABINC;
492 i_defs=(struct symtab**)
493 malloc(deflen*sizeof(struct symtab*));
494 if (i_defs==NULL) return 0;
497 while ((last1 >= first1) && (last2 >= first2))
499 char *s1=file1->i_defs[first1]->s_name;
500 char *s2=file2->i_defs[first2]->s_name;
502 if (strcmp(s1,s2) < 0)
503 i_defs[first++]=file1->i_defs[first1++];
504 else if (strcmp(s1,s2) > 0)
505 i_defs[first++]=file2->i_defs[first2++];
508 i_defs[first++]=file2->i_defs[first2++];
512 while (last1 >= first1)
514 i_defs[first++]=file1->i_defs[first1++];
516 while (last2 >= first2)
518 i_defs[first++]=file2->i_defs[first2++];
521 if (file1->i_defs) free(file1->i_defs);
522 file1->i_defs=i_defs;
523 file1->i_ndefs=first;
531 undefine(symbol, file)
533 struct inclist *file;
536 struct inclist *srcfile;
537 while ((ptr = isdefined(symbol, file, &srcfile)) != NULL)
540 for (; ptr < srcfile->i_defs + srcfile->i_ndefs; ptr++)
546 find_includes(filep, file, file_red, recursion, failOK)
547 struct filepointer *filep;
548 struct inclist *file, *file_red;
556 while ((line = our_getline(filep))) {
557 switch(type = deftype(line, filep, file_red, file, TRUE)) {
560 type = find_includes(filep, file,
561 file_red, recursion+1, failOK);
562 while ((type == ELIF) || (type == ELIFFALSE) ||
563 (type == ELIFGUESSFALSE))
564 type = gobble(filep, file, file_red);
566 gobble(filep, file, file_red);
571 if (type == IFGUESSFALSE || type == ELIFGUESSFALSE)
575 type = gobble(filep, file, file_red);
577 find_includes(filep, file,
578 file_red, recursion+1, recfailOK);
583 if ((type == ELIFFALSE) || (type == ELIFGUESSFALSE))
588 if ((type == IFDEF && isdefined(line, file_red, NULL))
589 || (type == IFNDEF && !isdefined(line, file_red, NULL))) {
590 debug(1,(type == IFNDEF ?
591 "line %d: %s !def'd in %s via %s%s\n" : "",
593 file->i_file, file_red->i_file, ": doit"));
594 type = find_includes(filep, file,
595 file_red, recursion+1, failOK);
596 while (type == ELIF || type == ELIFFALSE || type == ELIFGUESSFALSE)
597 type = gobble(filep, file, file_red);
599 gobble(filep, file, file_red);
602 debug(1,(type == IFDEF ?
603 "line %d: %s !def'd in %s via %s%s\n" : "",
605 file->i_file, file_red->i_file, ": gobble"));
606 type = gobble(filep, file, file_red);
608 find_includes(filep, file,
609 file_red, recursion+1, failOK);
610 else if (type == ELIF)
612 else if (type == ELIFFALSE || type == ELIFGUESSFALSE)
621 gobble(filep, file, file_red);
630 warning("%s, line %d: incomplete undef == \"%s\"\n",
631 file_red->i_file, filep->f_line, line);
634 undefine(line, file_red);
637 add_include(filep, file, file_red, line, FALSE, failOK);
640 add_include(filep, file, file_red, line, TRUE, failOK);
643 warning("%s: %d: %s\n", file_red->i_file,
644 filep->f_line, line);
653 warning("%s", file_red->i_file);
654 if (file_red != file)
655 warning1(" (reading %s)", file->i_file);
656 warning1(", line %d: unknown directive == \"%s\"\n",
657 filep->f_line, line);
660 warning("%s", file_red->i_file);
661 if (file_red != file)
662 warning1(" (reading %s)", file->i_file);
663 warning1(", line %d: incomplete include == \"%s\"\n",
664 filep->f_line, line);
668 file->i_flags |= FINISHED;