1 /*
   2  * This implementation is based on the UNIX 32V release from 1978
   3  * with permission from Caldera Inc.
   4  *
   5  * Copyright (c) 2011 Joyent, Inc. All rights reserved.
   6  * Copyright (c) 2010 J. Schilling
   7  * All rights reserved.
   8  *
   9  * Redistribution and use in source and binary forms, with or without
  10  * modification, are permitted provided that the following conditions
  11  * are met:
  12  * 1. Redistributions of source code must retain the above copyright
  13  *    notice, this list of conditions and the following disclaimer.
  14  * 2. Redistributions in binary form must reproduce the above copyright
  15  *    notice, this list of conditions and the following disclaimer in the
  16  *    documentation and/or other materials provided with the distribution.
  17  * 3. Neither the name of the copyright holder nor the names of contributors
  18  *    may be used to endorse or promote products derived from this software
  19  *    without specific prior written permission.
  20  *
  21  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTOR(S) ``AS IS'' AND
  22  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  23  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  24  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTOR(S) BE LIABLE
  25  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  26  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  27  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  28  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  29  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  30  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  31  * SUCH DAMAGE.
  32  */
  33 /*
  34  * Copyright(C) Caldera International Inc. 2001-2002. All rights reserved.
  35  *
  36  * Redistribution and use in source and binary forms, with or without
  37  * modification, are permitted provided that the following conditions are
  38  * met:
  39  * 1. Redistributions of source code and documentation must retain the above
  40  *    copyright notice, this list of conditions and the following
  41  *    disclaimer.
  42  *
  43  * 2. Redistributions in binary form must reproduce the above copyright
  44  *    notice, this list of conditions and the following disclaimer in the
  45  *    documentation and/or other materials provided with the distribution.
  46  *
  47  * 3. All advertising materials mentioning features or use of this software
  48  *    must display the following acknowledgement:  This product includes
  49  *    software developed or owned by Caldera International, Inc.
  50  *
  51  * 4. Neither the name of Caldera International, Inc. nor the names of other
  52  *    contributors may be used to endorse or promote products derived from
  53  *    this software without specific prior written permission.
  54  *
  55  * USE OF THE SOFTWARE PROVIDED FOR UNDER THIS LICENSE BY CALDERA
  56  * INTERNATIONAL, INC.  AND CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR
  57  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
  58  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
  59  * DISCLAIMED. IN NO EVENT SHALL CALDERA INTERNATIONAL, INC. BE LIABLE FOR
  60  * ANY DIRECT, INDIRECT INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  61  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  62  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  63  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
  64  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
  65  * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
  66  * POSSIBILITY OF SUCH DAMAGE.
  67  */
  68 
  69 #include "cpp.h"
  70 
  71 /*
  72  * XXX This block should be moved to cpp.h, it is douplicated in cpp.c
  73  */
  74 #define isid(a)  ((fastab+COFF)[(int)a]&IB)
  75 #define IB 1
  76 /*      #if '\377' < 0               it would be nice if this worked properly!!!!! */
  77 #if pdp11 | vax | '\377' < 0
  78 #define COFF 128
  79 #else
  80 #define COFF 0
  81 #endif
  82 
  83 static  long    tobinary(char *, int);
  84 
  85 int
  86 yylex(void)
  87 {
  88         static int ifdef=0;
  89         static char *op2[]={"||",  "&&" , ">>", "<<", ">=", "<=", "!=", "=="};
  90         static int  val2[]={OROR, ANDAND,  RS,   LS,   GE,   LE,   NE,   EQ};
  91         static char *opc="b\bt\tn\nf\fr\r\\\\";
  92         extern char fastab[];
  93         extern char *outp,*inp,*newp; extern int flslvl;
  94         register char savc, *s;
  95         int val;
  96         register char **p2;
  97         struct symtab *sp;
  98 
  99 for (;;) {
 100         newp=skipbl(newp);
 101         if (*inp=='\n') return(stop);   /* end of #if */
 102         savc= *newp; *newp='\0';
 103         for (p2=op2+8; --p2>=op2; )  /* check 2-char ops */
 104                 if (0==strcmp(*p2,inp)) {val=val2[p2-op2]; goto ret;}
 105         s="+-*/%<>&^|?:!~(),";        /* check 1-char ops */
 106         while (*s) if (*s++== *inp) {val= *--s; goto ret;}
 107         if (*inp<='9' && *inp>='0') {/* a number */
 108                 if (*inp=='0') yylval= (inp[1]=='x' || inp[1]=='X') ?
 109                         tobinary(inp+2,16) : tobinary(inp+1,8);
 110                 else yylval=tobinary(inp,10);
 111                 val=number;
 112         } else if (isid(*inp)) {
 113                 if (0==strcmp(inp,"defined")) {ifdef=1; ++flslvl; val=DEFINED;}
 114                 else {
 115                         sp=lookup(inp,-1); if (ifdef!=0) {ifdef=0; --flslvl;}
 116                         yylval= (sp->value==0) ? 0 : 1;
 117                         val=number;
 118                 }
 119         } else  if (*inp=='\'') {/* character constant */
 120                 val=number;
 121                 if (inp[1]=='\\') {/* escaped */
 122                         char c; if (newp[-1]=='\'') newp[-1]='\0';
 123                         s=opc;
 124                         while (*s) if (*s++!=inp[2]) ++s; else {yylval= *s; goto ret;}
 125                         if (inp[2]<='9' && inp[2]>='0') yylval=c=tobinary(inp+2,8);
 126                         else yylval=inp[2];
 127                 } else yylval=inp[1];
 128         } else if (0==strcmp("\\\n",inp)) {*newp=savc; continue;}
 129         else {
 130                 *newp=savc; pperror("Illegal character %c in preprocessor if", *inp);
 131                 continue;
 132         }
 133 ret:
 134         *newp=savc; outp=inp=newp; return(val);
 135 }
 136 }
 137 
 138 static long
 139 tobinary(char *st, int b)
 140 {
 141         char *tmp;
 142         int n;
 143         n = strtoul(st, &tmp, b);
 144         if (*tmp != '\0') {
 145                 if ((strcasecmp(tmp, "L") != 0) &&
 146                     (strcasecmp(tmp, "LL") != 0) &&
 147                     (strcasecmp(tmp, "UL") != 0) &&
 148                     (strcasecmp(tmp, "ULL") != 0))
 149                         pperror("illegal number: %s", st);
 150         }
 151         return(n);
 152 }