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 int 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 int
139 tobinary(st, b)
140 char *st;
141 int b;
142 {
143 int n, c, t;
144 char *s;
145 n=0;
146 s=st;
147 while ((c = *s++) != '\0') {
148 switch(c) {
149 case '0': case '1': case '2': case '3': case '4':
150 case '5': case '6': case '7': case '8': case '9':
151 t = c-'0'; break;
152 case 'a': case 'b': case 'c': case 'd': case 'e': case 'f':
153 t = c-'a'; if (b>10) break;
154 case 'A': case 'B': case 'C': case 'D': case 'E': case 'F':
155 t = c - 'A'; if (b>10) break;
156 default:
157 t = -1;
158 if ( c=='l' || c=='L') if (*s=='\0') break;
159 pperror("Illegal number %s", st);
160 }
161 if (t<0) break;
162 n = n*b+t;
163 }
164 return(n);
165 }