lexi.c revision 1.8 1 1.8 christos /* $NetBSD: lexi.c,v 1.8 1998/12/19 17:00:08 christos Exp $ */
2 1.3 tls
3 1.1 cgd /*
4 1.5 mrg * Copyright (c) 1980, 1993
5 1.5 mrg * The Regents of the University of California. All rights reserved.
6 1.5 mrg * Copyright (c) 1976 Board of Trustees of the University of Illinois.
7 1.1 cgd * Copyright (c) 1985 Sun Microsystems, Inc.
8 1.1 cgd * All rights reserved.
9 1.1 cgd *
10 1.1 cgd * Redistribution and use in source and binary forms, with or without
11 1.1 cgd * modification, are permitted provided that the following conditions
12 1.1 cgd * are met:
13 1.1 cgd * 1. Redistributions of source code must retain the above copyright
14 1.1 cgd * notice, this list of conditions and the following disclaimer.
15 1.1 cgd * 2. Redistributions in binary form must reproduce the above copyright
16 1.1 cgd * notice, this list of conditions and the following disclaimer in the
17 1.1 cgd * documentation and/or other materials provided with the distribution.
18 1.1 cgd * 3. All advertising materials mentioning features or use of this software
19 1.1 cgd * must display the following acknowledgement:
20 1.1 cgd * This product includes software developed by the University of
21 1.1 cgd * California, Berkeley and its contributors.
22 1.1 cgd * 4. Neither the name of the University nor the names of its contributors
23 1.1 cgd * may be used to endorse or promote products derived from this software
24 1.1 cgd * without specific prior written permission.
25 1.1 cgd *
26 1.1 cgd * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
27 1.1 cgd * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
28 1.1 cgd * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
29 1.1 cgd * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
30 1.1 cgd * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
31 1.1 cgd * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
32 1.1 cgd * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
33 1.1 cgd * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
34 1.1 cgd * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
35 1.1 cgd * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
36 1.1 cgd * SUCH DAMAGE.
37 1.1 cgd */
38 1.1 cgd
39 1.6 lukem #include <sys/cdefs.h>
40 1.1 cgd #ifndef lint
41 1.5 mrg #if 0
42 1.5 mrg static char sccsid[] = "@(#)lexi.c 8.1 (Berkeley) 6/6/93";
43 1.5 mrg #else
44 1.8 christos __RCSID("$NetBSD: lexi.c,v 1.8 1998/12/19 17:00:08 christos Exp $");
45 1.5 mrg #endif
46 1.6 lukem #endif /* not lint */
47 1.1 cgd
48 1.1 cgd /*
49 1.1 cgd * Here we have the token scanner for indent. It scans off one token and puts
50 1.1 cgd * it in the global variable "token". It returns a code, indicating the type
51 1.1 cgd * of token scanned.
52 1.1 cgd */
53 1.1 cgd
54 1.1 cgd #include <stdio.h>
55 1.1 cgd #include <ctype.h>
56 1.1 cgd #include <stdlib.h>
57 1.1 cgd #include <string.h>
58 1.1 cgd #include "indent_globs.h"
59 1.1 cgd #include "indent_codes.h"
60 1.1 cgd
61 1.1 cgd #define alphanum 1
62 1.1 cgd #define opchar 3
63 1.1 cgd
64 1.1 cgd struct templ {
65 1.6 lukem char *rwd;
66 1.6 lukem int rwcode;
67 1.1 cgd };
68 1.1 cgd
69 1.4 agc struct templ specials[1000] =
70 1.1 cgd {
71 1.6 lukem {"switch", 1},
72 1.6 lukem {"case", 2},
73 1.6 lukem {"break", 0},
74 1.6 lukem {"struct", 3},
75 1.6 lukem {"union", 3},
76 1.6 lukem {"enum", 3},
77 1.6 lukem {"default", 2},
78 1.6 lukem {"int", 4},
79 1.6 lukem {"char", 4},
80 1.6 lukem {"float", 4},
81 1.6 lukem {"double", 4},
82 1.6 lukem {"long", 4},
83 1.6 lukem {"short", 4},
84 1.6 lukem {"typdef", 4},
85 1.6 lukem {"unsigned", 4},
86 1.6 lukem {"register", 4},
87 1.6 lukem {"static", 4},
88 1.6 lukem {"global", 4},
89 1.6 lukem {"extern", 4},
90 1.6 lukem {"void", 4},
91 1.6 lukem {"goto", 0},
92 1.6 lukem {"return", 0},
93 1.6 lukem {"if", 5},
94 1.6 lukem {"while", 5},
95 1.6 lukem {"for", 5},
96 1.6 lukem {"else", 6},
97 1.6 lukem {"do", 6},
98 1.6 lukem {"sizeof", 7},
99 1.6 lukem {0, 0}
100 1.1 cgd };
101 1.1 cgd
102 1.6 lukem char chartype[128] =
103 1.1 cgd { /* this is used to facilitate the decision of
104 1.1 cgd * what type (alphanumeric, operator) each
105 1.1 cgd * character is */
106 1.6 lukem 0, 0, 0, 0, 0, 0, 0, 0,
107 1.6 lukem 0, 0, 0, 0, 0, 0, 0, 0,
108 1.6 lukem 0, 0, 0, 0, 0, 0, 0, 0,
109 1.6 lukem 0, 0, 0, 0, 0, 0, 0, 0,
110 1.6 lukem 0, 3, 0, 0, 1, 3, 3, 0,
111 1.6 lukem 0, 0, 3, 3, 0, 3, 0, 3,
112 1.6 lukem 1, 1, 1, 1, 1, 1, 1, 1,
113 1.6 lukem 1, 1, 0, 0, 3, 3, 3, 3,
114 1.6 lukem 0, 1, 1, 1, 1, 1, 1, 1,
115 1.6 lukem 1, 1, 1, 1, 1, 1, 1, 1,
116 1.6 lukem 1, 1, 1, 1, 1, 1, 1, 1,
117 1.6 lukem 1, 1, 1, 0, 0, 0, 3, 1,
118 1.6 lukem 0, 1, 1, 1, 1, 1, 1, 1,
119 1.6 lukem 1, 1, 1, 1, 1, 1, 1, 1,
120 1.6 lukem 1, 1, 1, 1, 1, 1, 1, 1,
121 1.6 lukem 1, 1, 1, 0, 3, 0, 3, 0
122 1.1 cgd };
123 1.1 cgd
124 1.1 cgd
125 1.1 cgd
126 1.1 cgd
127 1.1 cgd int
128 1.1 cgd lexi()
129 1.1 cgd {
130 1.6 lukem int unary_delim; /* this is set to 1 if the current token
131 1.1 cgd *
132 1.1 cgd * forces a following operator to be unary */
133 1.6 lukem static int last_code; /* the last token type returned */
134 1.6 lukem static int l_struct; /* set to 1 if the last token was 'struct' */
135 1.6 lukem int code; /* internal code to be returned */
136 1.6 lukem char qchar; /* the delimiter character for a string */
137 1.6 lukem
138 1.6 lukem e_token = s_token; /* point to start of place to save token */
139 1.6 lukem unary_delim = false;
140 1.6 lukem ps.col_1 = ps.last_nl; /* tell world that this token started in
141 1.1 cgd * column 1 iff the last thing scanned was nl */
142 1.6 lukem ps.last_nl = false;
143 1.1 cgd
144 1.6 lukem while (*buf_ptr == ' ' || *buf_ptr == '\t') { /* get rid of blanks */
145 1.6 lukem ps.col_1 = false; /* leading blanks imply token is not
146 1.6 lukem * in column 1 */
147 1.6 lukem if (++buf_ptr >= buf_end)
148 1.6 lukem fill_buffer();
149 1.6 lukem }
150 1.1 cgd
151 1.6 lukem /* Scan an alphanumeric token */
152 1.6 lukem if (chartype[(int) *buf_ptr] == alphanum ||
153 1.8 christos (buf_ptr[0] == '.' && isdigit((unsigned char)buf_ptr[1]))) {
154 1.6 lukem /*
155 1.6 lukem * we have a character or number
156 1.6 lukem */
157 1.6 lukem char *j; /* used for searching thru list of
158 1.1 cgd *
159 1.1 cgd * reserved words */
160 1.6 lukem struct templ *p;
161 1.1 cgd
162 1.8 christos if (isdigit((unsigned char)*buf_ptr) ||
163 1.8 christos (buf_ptr[0] == '.' && isdigit((unsigned char)buf_ptr[1]))) {
164 1.6 lukem int seendot = 0, seenexp = 0;
165 1.6 lukem if (*buf_ptr == '0' &&
166 1.6 lukem (buf_ptr[1] == 'x' || buf_ptr[1] == 'X')) {
167 1.6 lukem *e_token++ = *buf_ptr++;
168 1.6 lukem *e_token++ = *buf_ptr++;
169 1.8 christos while (isxdigit((unsigned char)*buf_ptr)) {
170 1.6 lukem CHECK_SIZE_TOKEN;
171 1.6 lukem *e_token++ = *buf_ptr++;
172 1.6 lukem }
173 1.7 ross } else {
174 1.6 lukem while (1) {
175 1.7 ross if (*buf_ptr == '.') {
176 1.6 lukem if (seendot)
177 1.6 lukem break;
178 1.6 lukem else
179 1.6 lukem seendot++;
180 1.7 ross }
181 1.6 lukem CHECK_SIZE_TOKEN;
182 1.6 lukem *e_token++ = *buf_ptr++;
183 1.8 christos if (!isdigit((unsigned char)*buf_ptr)
184 1.7 ross && *buf_ptr != '.') {
185 1.7 ross if ((*buf_ptr != 'E'
186 1.7 ross && *buf_ptr != 'e') || seenexp)
187 1.6 lukem break;
188 1.6 lukem else {
189 1.6 lukem seenexp++;
190 1.6 lukem seendot++;
191 1.6 lukem CHECK_SIZE_TOKEN;
192 1.6 lukem *e_token++ = *buf_ptr++;
193 1.6 lukem if (*buf_ptr == '+' || *buf_ptr == '-')
194 1.6 lukem *e_token++ = *buf_ptr++;
195 1.6 lukem }
196 1.7 ross }
197 1.6 lukem }
198 1.7 ross }
199 1.6 lukem if (*buf_ptr == 'L' || *buf_ptr == 'l')
200 1.6 lukem *e_token++ = *buf_ptr++;
201 1.6 lukem } else
202 1.6 lukem while (chartype[(int) *buf_ptr] == alphanum) { /* copy it over */
203 1.6 lukem CHECK_SIZE_TOKEN;
204 1.1 cgd *e_token++ = *buf_ptr++;
205 1.6 lukem if (buf_ptr >= buf_end)
206 1.6 lukem fill_buffer();
207 1.1 cgd }
208 1.6 lukem *e_token++ = '\0';
209 1.6 lukem while (*buf_ptr == ' ' || *buf_ptr == '\t') { /* get rid of blanks */
210 1.6 lukem if (++buf_ptr >= buf_end)
211 1.6 lukem fill_buffer();
212 1.1 cgd }
213 1.6 lukem ps.its_a_keyword = false;
214 1.6 lukem ps.sizeof_keyword = false;
215 1.6 lukem if (l_struct) { /* if last token was 'struct', then this token
216 1.1 cgd * should be treated as a declaration */
217 1.6 lukem l_struct = false;
218 1.6 lukem last_code = ident;
219 1.6 lukem ps.last_u_d = true;
220 1.6 lukem return (decl);
221 1.6 lukem }
222 1.6 lukem ps.last_u_d = false; /* Operator after indentifier is
223 1.6 lukem * binary */
224 1.6 lukem last_code = ident; /* Remember that this is the code we
225 1.6 lukem * will return */
226 1.1 cgd
227 1.1 cgd /*
228 1.6 lukem * This loop will check if the token is a keyword.
229 1.6 lukem */
230 1.6 lukem for (p = specials; (j = p->rwd) != 0; p++) {
231 1.6 lukem char *p = s_token; /* point at scanned token */
232 1.6 lukem if (*j++ != *p++ || *j++ != *p++)
233 1.6 lukem continue; /* This test depends on the
234 1.6 lukem * fact that identifiers are
235 1.6 lukem * always at least 1 character
236 1.6 lukem * long (ie. the first two
237 1.6 lukem * bytes of the identifier are
238 1.6 lukem * always meaningful) */
239 1.6 lukem if (p[-1] == 0)
240 1.6 lukem break; /* If its a one-character identifier */
241 1.6 lukem while (*p++ == *j)
242 1.6 lukem if (*j++ == 0)
243 1.6 lukem goto found_keyword; /* I wish that C had a
244 1.6 lukem * multi-level break... */
245 1.6 lukem }
246 1.6 lukem if (p->rwd) { /* we have a keyword */
247 1.6 lukem found_keyword:
248 1.6 lukem ps.its_a_keyword = true;
249 1.6 lukem ps.last_u_d = true;
250 1.6 lukem switch (p->rwcode) {
251 1.6 lukem case 1:/* it is a switch */
252 1.6 lukem return (swstmt);
253 1.6 lukem case 2:/* a case or default */
254 1.6 lukem return (casestmt);
255 1.6 lukem
256 1.6 lukem case 3:/* a "struct" */
257 1.6 lukem if (ps.p_l_follow)
258 1.6 lukem break; /* inside parens: cast */
259 1.6 lukem l_struct = true;
260 1.6 lukem
261 1.6 lukem /*
262 1.6 lukem * Next time around, we will want to know that we have had a
263 1.6 lukem * 'struct'
264 1.6 lukem */
265 1.6 lukem case 4:/* one of the declaration keywords */
266 1.6 lukem if (ps.p_l_follow) {
267 1.6 lukem ps.cast_mask |= 1 << ps.p_l_follow;
268 1.6 lukem break; /* inside parens: cast */
269 1.6 lukem }
270 1.6 lukem last_code = decl;
271 1.6 lukem return (decl);
272 1.6 lukem
273 1.6 lukem case 5:/* if, while, for */
274 1.6 lukem return (sp_paren);
275 1.6 lukem
276 1.6 lukem case 6:/* do, else */
277 1.6 lukem return (sp_nparen);
278 1.6 lukem
279 1.6 lukem case 7:
280 1.6 lukem ps.sizeof_keyword = true;
281 1.6 lukem default: /* all others are treated like any
282 1.6 lukem * other identifier */
283 1.6 lukem return (ident);
284 1.6 lukem } /* end of switch */
285 1.6 lukem } /* end of if (found_it) */
286 1.6 lukem if (*buf_ptr == '(' && ps.tos <= 1 && ps.ind_level == 0) {
287 1.6 lukem char *tp = buf_ptr;
288 1.6 lukem while (tp < buf_end)
289 1.6 lukem if (*tp++ == ')' && (*tp == ';' || *tp == ','))
290 1.6 lukem goto not_proc;
291 1.6 lukem strncpy(ps.procname, token, sizeof ps.procname - 1);
292 1.6 lukem ps.in_parameter_declaration = 1;
293 1.6 lukem rparen_count = 1;
294 1.6 lukem not_proc: ;
295 1.6 lukem }
296 1.6 lukem /*
297 1.6 lukem * The following hack attempts to guess whether or not the current
298 1.6 lukem * token is in fact a declaration keyword -- one that has been
299 1.6 lukem * typedefd
300 1.1 cgd */
301 1.8 christos if (((*buf_ptr == '*' && buf_ptr[1] != '=') ||
302 1.8 christos isalpha((unsigned char)*buf_ptr) || *buf_ptr == '_')
303 1.6 lukem && !ps.p_l_follow
304 1.6 lukem && !ps.block_init
305 1.6 lukem && (ps.last_token == rparen || ps.last_token == semicolon ||
306 1.6 lukem ps.last_token == decl ||
307 1.6 lukem ps.last_token == lbrace || ps.last_token == rbrace)) {
308 1.6 lukem ps.its_a_keyword = true;
309 1.6 lukem ps.last_u_d = true;
310 1.6 lukem last_code = decl;
311 1.6 lukem return decl;
312 1.6 lukem }
313 1.6 lukem if (last_code == decl) /* if this is a declared variable,
314 1.6 lukem * then following sign is unary */
315 1.6 lukem ps.last_u_d = true; /* will make "int a -1" work */
316 1.6 lukem last_code = ident;
317 1.6 lukem return (ident); /* the ident is not in the list */
318 1.6 lukem } /* end of procesing for alpanum character */
319 1.6 lukem /* Scan a non-alphanumeric token */
320 1.6 lukem *e_token++ = *buf_ptr; /* if it is only a one-character token, it is
321 1.6 lukem * moved here */
322 1.6 lukem *e_token = '\0';
323 1.6 lukem if (++buf_ptr >= buf_end)
324 1.6 lukem fill_buffer();
325 1.6 lukem
326 1.6 lukem switch (*token) {
327 1.6 lukem case '\n':
328 1.6 lukem unary_delim = ps.last_u_d;
329 1.6 lukem ps.last_nl = true; /* remember that we just had a newline */
330 1.6 lukem code = (had_eof ? 0 : newline);
331 1.1 cgd
332 1.6 lukem /*
333 1.6 lukem * if data has been exausted, the newline is a dummy, and we should
334 1.6 lukem * return code to stop
335 1.6 lukem */
336 1.6 lukem break;
337 1.1 cgd
338 1.6 lukem case '\'': /* start of quoted character */
339 1.6 lukem case '"': /* start of string */
340 1.6 lukem qchar = *token;
341 1.6 lukem if (troff) {
342 1.6 lukem e_token[-1] = '`';
343 1.6 lukem if (qchar == '"')
344 1.6 lukem *e_token++ = '`';
345 1.6 lukem e_token = chfont(&bodyf, &stringf, e_token);
346 1.6 lukem }
347 1.6 lukem do { /* copy the string */
348 1.6 lukem while (1) { /* move one character or
349 1.6 lukem * [/<char>]<char> */
350 1.6 lukem if (*buf_ptr == '\n') {
351 1.6 lukem printf("%d: Unterminated literal\n", line_no);
352 1.6 lukem goto stop_lit;
353 1.6 lukem }
354 1.6 lukem CHECK_SIZE_TOKEN; /* Only have to do this
355 1.6 lukem * once in this loop,
356 1.6 lukem * since CHECK_SIZE
357 1.6 lukem * guarantees that there
358 1.6 lukem * are at least 5
359 1.6 lukem * entries left */
360 1.6 lukem *e_token = *buf_ptr++;
361 1.6 lukem if (buf_ptr >= buf_end)
362 1.6 lukem fill_buffer();
363 1.6 lukem if (*e_token == BACKSLASH) { /* if escape, copy extra
364 1.6 lukem * char */
365 1.6 lukem if (*buf_ptr == '\n') /* check for escaped
366 1.6 lukem * newline */
367 1.6 lukem ++line_no;
368 1.6 lukem if (troff) {
369 1.6 lukem *++e_token = BACKSLASH;
370 1.6 lukem if (*buf_ptr == BACKSLASH)
371 1.6 lukem *++e_token = BACKSLASH;
372 1.6 lukem }
373 1.6 lukem *++e_token = *buf_ptr++;
374 1.6 lukem ++e_token; /* we must increment
375 1.6 lukem * this again because we
376 1.6 lukem * copied two chars */
377 1.6 lukem if (buf_ptr >= buf_end)
378 1.6 lukem fill_buffer();
379 1.6 lukem } else
380 1.6 lukem break; /* we copied one character */
381 1.6 lukem } /* end of while (1) */
382 1.6 lukem } while (*e_token++ != qchar);
383 1.6 lukem if (troff) {
384 1.6 lukem e_token = chfont(&stringf, &bodyf, e_token - 1);
385 1.6 lukem if (qchar == '"')
386 1.6 lukem *e_token++ = '\'';
387 1.1 cgd }
388 1.1 cgd stop_lit:
389 1.6 lukem code = ident;
390 1.6 lukem break;
391 1.6 lukem
392 1.6 lukem case ('('):
393 1.6 lukem case ('['):
394 1.6 lukem unary_delim = true;
395 1.6 lukem code = lparen;
396 1.6 lukem break;
397 1.6 lukem
398 1.6 lukem case (')'):
399 1.6 lukem case (']'):
400 1.6 lukem code = rparen;
401 1.6 lukem break;
402 1.6 lukem
403 1.6 lukem case '#':
404 1.6 lukem unary_delim = ps.last_u_d;
405 1.6 lukem code = preesc;
406 1.6 lukem break;
407 1.6 lukem
408 1.6 lukem case '?':
409 1.6 lukem unary_delim = true;
410 1.6 lukem code = question;
411 1.6 lukem break;
412 1.6 lukem
413 1.6 lukem case (':'):
414 1.6 lukem code = colon;
415 1.6 lukem unary_delim = true;
416 1.6 lukem break;
417 1.6 lukem
418 1.6 lukem case (';'):
419 1.6 lukem unary_delim = true;
420 1.6 lukem code = semicolon;
421 1.6 lukem break;
422 1.1 cgd
423 1.6 lukem case ('{'):
424 1.6 lukem unary_delim = true;
425 1.1 cgd
426 1.6 lukem /*
427 1.6 lukem * if (ps.in_or_st) ps.block_init = 1;
428 1.6 lukem */
429 1.6 lukem /* ? code = ps.block_init ? lparen : lbrace; */
430 1.6 lukem code = lbrace;
431 1.6 lukem break;
432 1.6 lukem
433 1.6 lukem case ('}'):
434 1.6 lukem unary_delim = true;
435 1.6 lukem /* ? code = ps.block_init ? rparen : rbrace; */
436 1.6 lukem code = rbrace;
437 1.6 lukem break;
438 1.6 lukem
439 1.6 lukem case 014: /* a form feed */
440 1.6 lukem unary_delim = ps.last_u_d;
441 1.6 lukem ps.last_nl = true; /* remember this so we can set
442 1.6 lukem * 'ps.col_1' right */
443 1.6 lukem code = form_feed;
444 1.6 lukem break;
445 1.6 lukem
446 1.6 lukem case (','):
447 1.6 lukem unary_delim = true;
448 1.6 lukem code = comma;
449 1.6 lukem break;
450 1.1 cgd
451 1.6 lukem case '.':
452 1.1 cgd unary_delim = false;
453 1.6 lukem code = period;
454 1.6 lukem break;
455 1.6 lukem
456 1.6 lukem case '-':
457 1.6 lukem case '+': /* check for -, +, --, ++ */
458 1.6 lukem code = (ps.last_u_d ? unary_op : binary_op);
459 1.6 lukem unary_delim = true;
460 1.6 lukem
461 1.6 lukem if (*buf_ptr == token[0]) {
462 1.6 lukem /* check for doubled character */
463 1.6 lukem *e_token++ = *buf_ptr++;
464 1.6 lukem /* buffer overflow will be checked at end of loop */
465 1.6 lukem if (last_code == ident || last_code == rparen) {
466 1.6 lukem code = (ps.last_u_d ? unary_op : postop);
467 1.6 lukem /* check for following ++ or -- */
468 1.6 lukem unary_delim = false;
469 1.6 lukem }
470 1.6 lukem } else
471 1.6 lukem if (*buf_ptr == '=')
472 1.6 lukem /* check for operator += */
473 1.6 lukem *e_token++ = *buf_ptr++;
474 1.6 lukem else
475 1.6 lukem if (*buf_ptr == '>') {
476 1.6 lukem /* check for operator -> */
477 1.6 lukem *e_token++ = *buf_ptr++;
478 1.6 lukem if (!pointer_as_binop) {
479 1.6 lukem unary_delim = false;
480 1.6 lukem code = unary_op;
481 1.6 lukem ps.want_blank = false;
482 1.6 lukem }
483 1.6 lukem }
484 1.6 lukem break; /* buffer overflow will be checked at end of
485 1.1 cgd * switch */
486 1.1 cgd
487 1.6 lukem case '=':
488 1.6 lukem if (ps.in_or_st)
489 1.6 lukem ps.block_init = 1;
490 1.1 cgd #ifdef undef
491 1.6 lukem if (chartype[*buf_ptr] == opchar) { /* we have two char
492 1.6 lukem * assignment */
493 1.6 lukem e_token[-1] = *buf_ptr++;
494 1.6 lukem if ((e_token[-1] == '<' || e_token[-1] == '>') && e_token[-1] == *buf_ptr)
495 1.6 lukem *e_token++ = *buf_ptr++;
496 1.6 lukem *e_token++ = '='; /* Flip =+ to += */
497 1.6 lukem *e_token = 0;
498 1.6 lukem }
499 1.1 cgd #else
500 1.6 lukem if (*buf_ptr == '=') { /* == */
501 1.6 lukem *e_token++ = '='; /* Flip =+ to += */
502 1.6 lukem buf_ptr++;
503 1.6 lukem *e_token = 0;
504 1.6 lukem }
505 1.1 cgd #endif
506 1.6 lukem code = binary_op;
507 1.6 lukem unary_delim = true;
508 1.6 lukem break;
509 1.6 lukem /* can drop thru!!! */
510 1.6 lukem
511 1.6 lukem case '>':
512 1.6 lukem case '<':
513 1.6 lukem case '!': /* ops like <, <<, <=, !=, etc */
514 1.6 lukem if (*buf_ptr == '>' || *buf_ptr == '<' || *buf_ptr == '=') {
515 1.6 lukem *e_token++ = *buf_ptr;
516 1.6 lukem if (++buf_ptr >= buf_end)
517 1.6 lukem fill_buffer();
518 1.6 lukem }
519 1.6 lukem if (*buf_ptr == '=')
520 1.6 lukem *e_token++ = *buf_ptr++;
521 1.6 lukem code = (ps.last_u_d ? unary_op : binary_op);
522 1.6 lukem unary_delim = true;
523 1.6 lukem break;
524 1.6 lukem
525 1.6 lukem default:
526 1.6 lukem if (token[0] == '/' && *buf_ptr == '*') {
527 1.6 lukem /* it is start of comment */
528 1.6 lukem *e_token++ = '*';
529 1.6 lukem
530 1.6 lukem if (++buf_ptr >= buf_end)
531 1.6 lukem fill_buffer();
532 1.6 lukem
533 1.6 lukem code = comment;
534 1.6 lukem unary_delim = ps.last_u_d;
535 1.6 lukem break;
536 1.6 lukem }
537 1.6 lukem while (*(e_token - 1) == *buf_ptr || *buf_ptr == '=') {
538 1.6 lukem /*
539 1.6 lukem * handle ||, &&, etc, and also things as in int *****i
540 1.6 lukem */
541 1.6 lukem *e_token++ = *buf_ptr;
542 1.6 lukem if (++buf_ptr >= buf_end)
543 1.6 lukem fill_buffer();
544 1.6 lukem }
545 1.6 lukem code = (ps.last_u_d ? unary_op : binary_op);
546 1.6 lukem unary_delim = true;
547 1.1 cgd
548 1.1 cgd
549 1.6 lukem } /* end of switch */
550 1.6 lukem if (code != newline) {
551 1.6 lukem l_struct = false;
552 1.6 lukem last_code = code;
553 1.1 cgd }
554 1.6 lukem if (buf_ptr >= buf_end) /* check for input buffer empty */
555 1.1 cgd fill_buffer();
556 1.6 lukem ps.last_u_d = unary_delim;
557 1.6 lukem *e_token = '\0'; /* null terminate the token */
558 1.6 lukem return (code);
559 1.1 cgd }
560 1.1 cgd /*
561 1.1 cgd * Add the given keyword to the keyword table, using val as the keyword type
562 1.1 cgd */
563 1.6 lukem void
564 1.1 cgd addkey(key, val)
565 1.6 lukem char *key;
566 1.6 lukem int val;
567 1.1 cgd {
568 1.6 lukem struct templ *p = specials;
569 1.6 lukem while (p->rwd)
570 1.6 lukem if (p->rwd[0] == key[0] && strcmp(p->rwd, key) == 0)
571 1.6 lukem return;
572 1.6 lukem else
573 1.6 lukem p++;
574 1.6 lukem if (p >= specials + sizeof specials / sizeof specials[0])
575 1.6 lukem return; /* For now, table overflows are silently
576 1.1 cgd * ignored */
577 1.6 lukem p->rwd = key;
578 1.6 lukem p->rwcode = val;
579 1.6 lukem p[1].rwd = 0;
580 1.6 lukem p[1].rwcode = 0;
581 1.1 cgd }
582