Back to home page

darwin3

 
 

    


File indexing completed on 2024-12-17 18:39:59 UTC

view on githubraw file Latest commit c596602b on 2009-04-06 21:17:32 UTC
bf5846c3a1 Ed H*0001 /* $XConsortium: parse.c,v 1.30 94/04/17 20:10:38 gildea Exp $ */
                0002 /*
                0003  * Copyright (c) 1998-2003 Carnegie Mellon University.  All rights reserved.
                0004  *
                0005  * Redistribution and use in source and binary forms, with or without
                0006  * modification, are permitted provided that the following conditions
                0007  * are met:
                0008  *
                0009  * 1. Redistributions of source code must retain the above copyright
                0010  *    notice, this list of conditions and the following disclaimer. 
                0011  *
                0012  * 2. Redistributions in binary form must reproduce the above copyright
                0013  *    notice, this list of conditions and the following disclaimer in
                0014  *    the documentation and/or other materials provided with the
                0015  *    distribution.
                0016  *
                0017  * 3. The name "Carnegie Mellon University" must not be used to
                0018  *    endorse or promote products derived from this software without
                0019  *    prior written permission. For permission or any other legal
                0020  *    details, please contact  
                0021  *      Office of Technology Transfer
                0022  *      Carnegie Mellon University
                0023  *      5000 Forbes Avenue
                0024  *      Pittsburgh, PA  15213-3890
                0025  *      (412) 268-4387, fax: (412) 268-7395
                0026  *      tech-transfer@andrew.cmu.edu
                0027  *
                0028  * 4. Redistributions of any form whatsoever must retain the following
                0029  *    acknowledgment:
                0030  *    "This product includes software developed by Computing Services
                0031  *     at Carnegie Mellon University (http://www.cmu.edu/computing/)."
                0032  *
                0033  * CARNEGIE MELLON UNIVERSITY DISCLAIMS ALL WARRANTIES WITH REGARD TO
                0034  * THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
                0035  * AND FITNESS, IN NO EVENT SHALL CARNEGIE MELLON UNIVERSITY BE LIABLE
                0036  * FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
                0037  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN
                0038  * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
                0039  * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
                0040  *
                0041  */
                0042 
                0043 /*
                0044 
                0045 Copyright (c) 1993, 1994  X Consortium
                0046 
                0047 Permission is hereby granted, free of charge, to any person obtaining a copy
                0048 of this software and associated documentation files (the "Software"), to deal
                0049 in the Software without restriction, including without limitation the rights
                0050 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
                0051 copies of the Software, and to permit persons to whom the Software is
                0052 furnished to do so, subject to the following conditions:
                0053 
                0054 The above copyright notice and this permission notice shall be included in
                0055 all copies or substantial portions of the Software.
                0056 
                0057 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
                0058 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
                0059 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
                0060 X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
                0061 AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
                0062 CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
                0063 
                0064 Except as contained in this notice, the name of the X Consortium shall not be
                0065 used in advertising or otherwise to promote the sale, use or other dealings
                0066 in this Software without prior written authorization from the X Consortium.
                0067 
                0068 */
                0069 
                0070 #include "def.h"
                0071 
                0072 extern char *directives[];
                0073 extern struct inclist   maininclist;
                0074 
                0075 find_includes(filep, file, file_red, recursion, failOK)
                0076     struct filepointer  *filep;
                0077     struct inclist      *file, *file_red;
                0078     int         recursion;
                0079     boolean         failOK;
                0080 {
                0081     register char   *line;
                0082     register int    type;
                0083     boolean recfailOK;
                0084 
c596602bd4 Oliv*0085     while (line = getppline(filep)) {
bf5846c3a1 Ed H*0086         switch(type = deftype(line, filep, file_red, file, TRUE)) {
                0087         case IF:
                0088         doif:
                0089             type = find_includes(filep, file,
                0090                 file_red, recursion+1, failOK);
                0091             while ((type == ELIF) || (type == ELIFFALSE) ||
                0092                    (type == ELIFGUESSFALSE))
                0093                 type = gobble(filep, file, file_red);
                0094             if (type == ELSE)
                0095                 gobble(filep, file, file_red);
                0096             break;
                0097         case IFFALSE:
                0098         case IFGUESSFALSE:
                0099             doiffalse:
                0100             if (type == IFGUESSFALSE || type == ELIFGUESSFALSE)
                0101                 recfailOK = TRUE;
                0102             else
                0103                 recfailOK = failOK;
                0104             type = gobble(filep, file, file_red);
                0105             if (type == ELSE)
                0106                 find_includes(filep, file,
                0107                       file_red, recursion+1, recfailOK);
                0108             else
                0109             if (type == ELIF)
                0110                 goto doif;
                0111             else
                0112             if ((type == ELIFFALSE) || (type == ELIFGUESSFALSE))
                0113                 goto doiffalse;
                0114             break;
                0115         case IFDEF:
                0116         case IFNDEF:
                0117             if ((type == IFDEF && isdefined(line, file_red, NULL))
                0118              || (type == IFNDEF && !isdefined(line, file_red, NULL))) {
                0119                 debug(1,(type == IFNDEF ?
                0120                     "line %d: %s !def'd in %s via %s%s\n" : "",
                0121                     filep->f_line, line,
                0122                     file->i_file, file_red->i_file, ": doit"));
                0123                 type = find_includes(filep, file,
                0124                     file_red, recursion+1, failOK);
                0125                 while (type == ELIF || type == ELIFFALSE || type == ELIFGUESSFALSE)
                0126                     type = gobble(filep, file, file_red);
                0127                 if (type == ELSE)
                0128                     gobble(filep, file, file_red);
                0129             }
                0130             else {
                0131                 debug(1,(type == IFDEF ?
                0132                     "line %d: %s !def'd in %s via %s%s\n" : "",
                0133                     filep->f_line, line,
                0134                     file->i_file, file_red->i_file, ": gobble"));
                0135                 type = gobble(filep, file, file_red);
                0136                 if (type == ELSE)
                0137                     find_includes(filep, file,
                0138                         file_red, recursion+1, failOK);
                0139                 else if (type == ELIF)
                0140                         goto doif;
                0141                 else if (type == ELIFFALSE || type == ELIFGUESSFALSE)
                0142                         goto doiffalse;
                0143             }
                0144             break;
                0145         case ELSE:
                0146         case ELIFFALSE:
                0147         case ELIFGUESSFALSE:
                0148         case ELIF:
                0149             if (!recursion)
                0150                 gobble(filep, file, file_red);
                0151         case ENDIF:
                0152             if (recursion)
                0153                 return(type);
                0154         case DEFINE:
                0155             define(line, file);
                0156             break;
                0157         case UNDEF:
                0158             if (!*line) {
                0159                 warning("%s, line %d: incomplete undef == \"%s\"\n",
                0160                 file_red->i_file, filep->f_line, line);
                0161                 break;
                0162             }
                0163             undefine(line, file_red);
                0164             break;
                0165         case INCLUDE:
                0166             add_include(filep, file, file_red, line, FALSE, failOK);
                0167             break;
                0168         case INCLUDEDOT:
                0169             add_include(filep, file, file_red, line, TRUE, failOK);
                0170             break;
                0171         case ERROR:
                0172                 warning("%s: %d: %s\n", file_red->i_file,
                0173                  filep->f_line, line);
                0174                 break;
                0175             
                0176         case PRAGMA:
                0177         case IDENT:
                0178         case SCCS:
                0179         case EJECT:
                0180             break;
                0181         case -1:
                0182             warning("%s", file_red->i_file);
                0183             if (file_red != file)
                0184                 warning1(" (reading %s)", file->i_file);
                0185             warning1(", line %d: unknown directive == \"%s\"\n",
                0186                  filep->f_line, line);
                0187             break;
                0188         case -2:
                0189             warning("%s", file_red->i_file);
                0190             if (file_red != file)
                0191                 warning1(" (reading %s)", file->i_file);
                0192             warning1(", line %d: incomplete include == \"%s\"\n",
                0193                  filep->f_line, line);
                0194             break;
                0195         }
                0196     }
                0197     return(-1);
                0198 }
                0199 
                0200 gobble(filep, file, file_red)
                0201     register struct filepointer *filep;
                0202     struct inclist      *file, *file_red;
                0203 {
                0204     register char   *line;
                0205     register int    type;
                0206 
c596602bd4 Oliv*0207     while (line = getppline(filep)) {
bf5846c3a1 Ed H*0208         switch(type = deftype(line, filep, file_red, file, FALSE)) {
                0209         case IF:
                0210         case IFFALSE:
                0211         case IFGUESSFALSE:
                0212         case IFDEF:
                0213         case IFNDEF:
                0214             type = gobble(filep, file, file_red);
                0215             while ((type == ELIF) || (type == ELIFFALSE) ||
                0216                    (type == ELIFGUESSFALSE))
                0217                 type = gobble(filep, file, file_red);
                0218             if (type == ELSE)
                0219                     (void)gobble(filep, file, file_red);
                0220             break;
                0221         case ELSE:
                0222         case ENDIF:
                0223             debug(0,("%s, line %d: #%s\n",
                0224                 file->i_file, filep->f_line,
                0225                 directives[type]));
                0226             return(type);
                0227         case DEFINE:
                0228         case UNDEF:
                0229         case INCLUDE:
                0230         case INCLUDEDOT:
                0231         case PRAGMA:
                0232         case ERROR:
                0233         case IDENT:
                0234         case SCCS:
                0235         case EJECT:
                0236             break;
                0237         case ELIF:
                0238         case ELIFFALSE:
                0239         case ELIFGUESSFALSE:
                0240             return(type);
                0241         case -1:
                0242             warning("%s, line %d: unknown directive == \"%s\"\n",
                0243                 file_red->i_file, filep->f_line, line);
                0244             break;
                0245         }
                0246     }
                0247     return(-1);
                0248 }
                0249 
                0250 /*
                0251  * Decide what type of # directive this line is.
                0252  */
                0253 int deftype (line, filep, file_red, file, parse_it)
                0254     register char   *line;
                0255     register struct filepointer *filep;
                0256     register struct inclist *file_red, *file;
                0257     int parse_it;
                0258 {
                0259     register char   *p;
                0260     char    *directive, savechar;
                0261     register int    ret;
                0262 
                0263     /*
                0264      * Parse the directive...
                0265      */
                0266     directive=line+1;
                0267     while (*directive == ' ' || *directive == '\t')
                0268         directive++;
                0269 
                0270     p = directive;
                0271     while (*p >= 'a' && *p <= 'z')
                0272         p++;
                0273     savechar = *p;
                0274     *p = '\0';
                0275     ret = match(directive, directives);
                0276     *p = savechar;
                0277 
                0278     /* If we don't recognize this compiler directive or we happen to just
                0279      * be gobbling up text while waiting for an #endif or #elif or #else
                0280      * in the case of an #elif we must check the zero_value and return an
                0281      * ELIF or an ELIFFALSE.
                0282      */
                0283 
                0284     if (ret == ELIF && !parse_it)
                0285     {
                0286         while (*p == ' ' || *p == '\t')
                0287         p++;
                0288         /*
                0289          * parse an expression.
                0290          */
                0291         debug(0,("%s, line %d: #elif %s ",
                0292            file->i_file, filep->f_line, p));
                0293         ret = zero_value(p, filep, file_red);
                0294         if (ret != IF)
                0295         {
                0296         debug(0,("false...\n"));
                0297         if (ret == IFFALSE)
                0298             return(ELIFFALSE);
                0299         else
                0300             return(ELIFGUESSFALSE);
                0301         }
                0302         else
                0303         {
                0304         debug(0,("true...\n"));
                0305         return(ELIF);
                0306         }
                0307     }
                0308 
                0309     if (ret < 0 || ! parse_it)
                0310         return(ret);
                0311 
                0312     /*
                0313      * now decide how to parse the directive, and do it.
                0314      */
                0315     while (*p == ' ' || *p == '\t')
                0316         p++;
                0317     switch (ret) {
                0318     case IF:
                0319         /*
                0320          * parse an expression.
                0321          */
                0322         ret = zero_value(p, filep, file_red);
                0323         debug(0,("%s, line %d: %s #if %s\n",
                0324              file->i_file, filep->f_line, ret?"false":"true", p));
                0325         break;
                0326     case IFDEF:
                0327     case IFNDEF:
                0328         debug(0,("%s, line %d: #%s %s\n",
                0329             file->i_file, filep->f_line, directives[ret], p));
                0330     case UNDEF:
                0331         /*
                0332          * separate the name of a single symbol.
                0333          */
                0334         while (isalnum(*p) || *p == '_')
                0335             *line++ = *p++;
                0336         *line = '\0';
                0337         break;
                0338     case INCLUDE:
                0339         debug(2,("%s, line %d: #include %s\n",
                0340             file->i_file, filep->f_line, p));
                0341 
                0342         /* Support ANSI macro substitution */
                0343         {
                0344             struct symtab *sym = isdefined(p, file_red, NULL);
                0345             while (sym) {
                0346             p = sym->s_value;
                0347             debug(3,("%s : #includes SYMBOL %s = %s\n",
                0348                    file->i_incstring,
                0349                    sym -> s_name,
                0350                    sym -> s_value));
                0351             /* mark file as having included a 'soft include' */
                0352             file->i_included_sym = TRUE; 
                0353             sym = isdefined(p, file_red, NULL);
                0354             }
                0355         }
                0356 
                0357         /*
                0358          * Separate the name of the include file.
                0359          */
                0360         while (*p && *p != '"' && *p != '<')
                0361             p++;
                0362         if (! *p)
                0363             return(-2);
                0364         if (*p++ == '"') {
                0365             ret = INCLUDEDOT;
                0366             while (*p && *p != '"')
                0367                 *line++ = *p++;
                0368         } else
                0369             while (*p && *p != '>')
                0370                 *line++ = *p++;
                0371         *line = '\0';
                0372         break;
                0373     case DEFINE:
                0374         /*
                0375          * copy the definition back to the beginning of the line.
                0376          */
                0377         strcpy (line, p);
                0378         break;
                0379     case ELSE:
                0380     case ENDIF:
                0381     case ELIF:
                0382     case PRAGMA:
                0383     case ERROR:
                0384     case IDENT:
                0385     case SCCS:
                0386     case EJECT:
                0387         debug(0,("%s, line %d: #%s\n",
                0388             file->i_file, filep->f_line, directives[ret]));
                0389         /*
                0390          * nothing to do.
                0391          */
                0392         break;
                0393     }
                0394     return(ret);
                0395 }
                0396 
                0397 struct symtab *isdefined(symbol, file, srcfile)
                0398     register char   *symbol;
                0399     struct inclist  *file;
                0400     struct inclist  **srcfile;
                0401 {
                0402     register struct symtab  *val;
                0403 
                0404     if (val = slookup(symbol, &maininclist)) {
                0405         debug(1,("%s defined on command line\n", symbol));
                0406         if (srcfile != NULL) *srcfile = &maininclist;
                0407         return(val);
                0408     }
                0409     if (val = fdefined(symbol, file, srcfile))
                0410         return(val);
                0411     debug(1,("%s not defined in %s\n", symbol, file->i_file));
                0412     return(NULL);
                0413 }
                0414 
                0415 struct symtab *fdefined(symbol, file, srcfile)
                0416     register char   *symbol;
                0417     struct inclist  *file;
                0418     struct inclist  **srcfile;
                0419 {
                0420     register struct inclist **ip;
                0421     register struct symtab  *val;
                0422     register int    i;
                0423     static int  recurse_lvl = 0;
                0424 
                0425     if (file->i_defchecked)
                0426         return(NULL);
                0427     file->i_defchecked = TRUE;
                0428     if (val = slookup(symbol, file))
                0429         debug(1,("%s defined in %s as %s\n", symbol, file->i_file, val->s_value));
                0430     if (val == NULL && file->i_list)
                0431         {
                0432         for (ip = file->i_list, i=0; i < file->i_listlen; i++, ip++)
                0433             if (val = fdefined(symbol, *ip, srcfile)) {
                0434                 break;
                0435             }
                0436         }
                0437     else if (val != NULL && srcfile != NULL) *srcfile = file;
                0438     recurse_lvl--;
                0439     file->i_defchecked = FALSE;
                0440 
                0441     return(val);
                0442 }
                0443 
                0444 /*
                0445  * Return type based on if the #if expression evaluates to 0
                0446  */
                0447 zero_value(exp, filep, file_red)
                0448     register char   *exp;
                0449     register struct filepointer *filep;
                0450     register struct inclist *file_red;
                0451 {
                0452     if (cppsetup(exp, filep, file_red))
                0453         return(IFFALSE);
                0454     else
                0455         return(IF);
                0456 }
                0457 
                0458 define(def, file)
                0459     char    *def;
                0460     struct inclist  *file;
                0461 {
                0462     char *val;
                0463 
                0464     /* Separate symbol name and its value */
                0465     val = def;
                0466     while (isalnum(*val) || *val == '_')
                0467     val++;
                0468     if (*val)
                0469     *val++ = '\0';
                0470     while (*val == ' ' || *val == '\t')
                0471     val++;
                0472 
                0473     if (!*val)
                0474     val = "1";
                0475     define2(def, val, file);
                0476 }
                0477 
                0478 define2(name, val, file)
                0479     char    *name, *val;
                0480     struct inclist  *file;
                0481 {
                0482     int first, last, below;
                0483     register struct symtab *sp = NULL, *dest;
                0484 
                0485     /* Make space if it's needed */
                0486     if (file->i_defs == NULL)
                0487     {
                0488     file->i_defs = (struct symtab *)
                0489             malloc(sizeof (struct symtab) * SYMTABINC);
                0490     file->i_deflen = SYMTABINC;
                0491     file->i_ndefs = 0;
                0492     }
                0493     else if (file->i_ndefs == file->i_deflen)
                0494     file->i_defs = (struct symtab *)
                0495             realloc(file->i_defs,
                0496                 sizeof(struct symtab)*(file->i_deflen+=SYMTABINC));
                0497 
                0498     if (file->i_defs == NULL)
                0499     fatalerr("malloc()/realloc() failure in insert_defn()\n");
                0500 
                0501     below = first = 0;
                0502     last = file->i_ndefs - 1;
                0503     while (last >= first)
                0504     {
                0505     /* Fast inline binary search */
                0506     register char *s1;
                0507     register char *s2;
                0508     register int middle = (first + last) / 2;
                0509 
                0510     /* Fast inline strchr() */
                0511     s1 = name;
                0512     s2 = file->i_defs[middle].s_name;
                0513     while (*s1++ == *s2++)
                0514         if (s2[-1] == '\0') break;
                0515 
                0516     /* If exact match, set sp and break */
                0517     if (*--s1 == *--s2) 
                0518     {
                0519         sp = file->i_defs + middle;
                0520         break;
                0521     }
                0522 
                0523     /* If name > i_defs[middle] ... */
                0524     if (*s1 > *s2) 
                0525     {
                0526         below = first;
                0527         first = middle + 1;
                0528     }
                0529     /* else ... */
                0530     else
                0531     {
                0532         below = last = middle - 1;
                0533     }
                0534     }
                0535 
                0536     /* Search is done.  If we found an exact match to the symbol name,
                0537        just replace its s_value */
                0538     if (sp != NULL)
                0539     {
                0540     free(sp->s_value);
                0541     sp->s_value = copy(val);
                0542     return;
                0543     }
                0544 
                0545     sp = file->i_defs + file->i_ndefs++;
                0546     dest = file->i_defs + below + 1;
                0547     while (sp > dest)
                0548     {
                0549     *sp = sp[-1];
                0550     sp--;
                0551     }
                0552     sp->s_name = copy(name);
                0553     sp->s_value = copy(val);
                0554 }
                0555 
                0556 struct symtab *slookup(symbol, file)
                0557     register char   *symbol;
                0558     register struct inclist *file;
                0559 {
                0560     register int first = 0;
                0561     register int last = file->i_ndefs - 1;
                0562 
                0563     if (file) while (last >= first)
                0564     {
                0565         /* Fast inline binary search */
                0566         register char *s1;
                0567         register char *s2;
                0568         register int middle = (first + last) / 2;
                0569 
                0570         /* Fast inline strchr() */
                0571         s1 = symbol;
                0572         s2 = file->i_defs[middle].s_name;
                0573         while (*s1++ == *s2++)
                0574             if (s2[-1] == '\0') break;
                0575 
                0576         /* If exact match, we're done */
                0577         if (*--s1 == *--s2) 
                0578         {
                0579             return file->i_defs + middle;
                0580         }
                0581 
                0582         /* If symbol > i_defs[middle] ... */
                0583         if (*s1 > *s2) 
                0584         {
                0585             first = middle + 1;
                0586         }
                0587         /* else ... */
                0588         else
                0589         {
                0590             last = middle - 1;
                0591         }
                0592     }
                0593     return(NULL);
                0594 }
                0595 
                0596 undefine(symbol, file)
                0597     char    *symbol;
                0598     register struct inclist *file;
                0599 {
                0600     register struct symtab *ptr;
                0601     struct inclist *srcfile;
                0602     while ((ptr = isdefined(symbol, file, &srcfile)) != NULL)
                0603     {
                0604         srcfile->i_ndefs--;
                0605         for (; ptr < srcfile->i_defs + srcfile->i_ndefs; ptr++)
                0606         *ptr = ptr[1];
                0607     }
                0608 }