lexi.c revision 1.7 1 1.7 ross /* $NetBSD: lexi.c,v 1.7 1998/08/25 20:59:38 ross 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.7 ross __RCSID("$NetBSD: lexi.c,v 1.7 1998/08/25 20:59:38 ross 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.6 lukem (buf_ptr[0] == '.' && isdigit(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.6 lukem if (isdigit(*buf_ptr) || (buf_ptr[0] == '.' && isdigit(buf_ptr[1]))) {
163 1.6 lukem int seendot = 0, seenexp = 0;
164 1.6 lukem if (*buf_ptr == '0' &&
165 1.6 lukem (buf_ptr[1] == 'x' || buf_ptr[1] == 'X')) {
166 1.6 lukem *e_token++ = *buf_ptr++;
167 1.6 lukem *e_token++ = *buf_ptr++;
168 1.6 lukem while (isxdigit(*buf_ptr)) {
169 1.6 lukem CHECK_SIZE_TOKEN;
170 1.6 lukem *e_token++ = *buf_ptr++;
171 1.6 lukem }
172 1.7 ross } else {
173 1.6 lukem while (1) {
174 1.7 ross if (*buf_ptr == '.') {
175 1.6 lukem if (seendot)
176 1.6 lukem break;
177 1.6 lukem else
178 1.6 lukem seendot++;
179 1.7 ross }
180 1.6 lukem CHECK_SIZE_TOKEN;
181 1.6 lukem *e_token++ = *buf_ptr++;
182 1.7 ross if (!isdigit(*buf_ptr)
183 1.7 ross && *buf_ptr != '.') {
184 1.7 ross if ((*buf_ptr != 'E'
185 1.7 ross && *buf_ptr != 'e') || seenexp)
186 1.6 lukem break;
187 1.6 lukem else {
188 1.6 lukem seenexp++;
189 1.6 lukem seendot++;
190 1.6 lukem CHECK_SIZE_TOKEN;
191 1.6 lukem *e_token++ = *buf_ptr++;
192 1.6 lukem if (*buf_ptr == '+' || *buf_ptr == '-')
193 1.6 lukem *e_token++ = *buf_ptr++;
194 1.6 lukem }
195 1.7 ross }
196 1.6 lukem }
197 1.7 ross }
198 1.6 lukem if (*buf_ptr == 'L' || *buf_ptr == 'l')
199 1.6 lukem *e_token++ = *buf_ptr++;
200 1.6 lukem } else
201 1.6 lukem while (chartype[(int) *buf_ptr] == alphanum) { /* copy it over */
202 1.6 lukem CHECK_SIZE_TOKEN;
203 1.1 cgd *e_token++ = *buf_ptr++;
204 1.6 lukem if (buf_ptr >= buf_end)
205 1.6 lukem fill_buffer();
206 1.1 cgd }
207 1.6 lukem *e_token++ = '\0';
208 1.6 lukem while (*buf_ptr == ' ' || *buf_ptr == '\t') { /* get rid of blanks */
209 1.6 lukem if (++buf_ptr >= buf_end)
210 1.6 lukem fill_buffer();
211 1.1 cgd }
212 1.6 lukem ps.its_a_keyword = false;
213 1.6 lukem ps.sizeof_keyword = false;
214 1.6 lukem if (l_struct) { /* if last token was 'struct', then this token
215 1.1 cgd * should be treated as a declaration */
216 1.6 lukem l_struct = false;
217 1.6 lukem last_code = ident;
218 1.6 lukem ps.last_u_d = true;
219 1.6 lukem return (decl);
220 1.6 lukem }
221 1.6 lukem ps.last_u_d = false; /* Operator after indentifier is
222 1.6 lukem * binary */
223 1.6 lukem last_code = ident; /* Remember that this is the code we
224 1.6 lukem * will return */
225 1.1 cgd
226 1.1 cgd /*
227 1.6 lukem * This loop will check if the token is a keyword.
228 1.6 lukem */
229 1.6 lukem for (p = specials; (j = p->rwd) != 0; p++) {
230 1.6 lukem char *p = s_token; /* point at scanned token */
231 1.6 lukem if (*j++ != *p++ || *j++ != *p++)
232 1.6 lukem continue; /* This test depends on the
233 1.6 lukem * fact that identifiers are
234 1.6 lukem * always at least 1 character
235 1.6 lukem * long (ie. the first two
236 1.6 lukem * bytes of the identifier are
237 1.6 lukem * always meaningful) */
238 1.6 lukem if (p[-1] == 0)
239 1.6 lukem break; /* If its a one-character identifier */
240 1.6 lukem while (*p++ == *j)
241 1.6 lukem if (*j++ == 0)
242 1.6 lukem goto found_keyword; /* I wish that C had a
243 1.6 lukem * multi-level break... */
244 1.6 lukem }
245 1.6 lukem if (p->rwd) { /* we have a keyword */
246 1.6 lukem found_keyword:
247 1.6 lukem ps.its_a_keyword = true;
248 1.6 lukem ps.last_u_d = true;
249 1.6 lukem switch (p->rwcode) {
250 1.6 lukem case 1:/* it is a switch */
251 1.6 lukem return (swstmt);
252 1.6 lukem case 2:/* a case or default */
253 1.6 lukem return (casestmt);
254 1.6 lukem
255 1.6 lukem case 3:/* a "struct" */
256 1.6 lukem if (ps.p_l_follow)
257 1.6 lukem break; /* inside parens: cast */
258 1.6 lukem l_struct = true;
259 1.6 lukem
260 1.6 lukem /*
261 1.6 lukem * Next time around, we will want to know that we have had a
262 1.6 lukem * 'struct'
263 1.6 lukem */
264 1.6 lukem case 4:/* one of the declaration keywords */
265 1.6 lukem if (ps.p_l_follow) {
266 1.6 lukem ps.cast_mask |= 1 << ps.p_l_follow;
267 1.6 lukem break; /* inside parens: cast */
268 1.6 lukem }
269 1.6 lukem last_code = decl;
270 1.6 lukem return (decl);
271 1.6 lukem
272 1.6 lukem case 5:/* if, while, for */
273 1.6 lukem return (sp_paren);
274 1.6 lukem
275 1.6 lukem case 6:/* do, else */
276 1.6 lukem return (sp_nparen);
277 1.6 lukem
278 1.6 lukem case 7:
279 1.6 lukem ps.sizeof_keyword = true;
280 1.6 lukem default: /* all others are treated like any
281 1.6 lukem * other identifier */
282 1.6 lukem return (ident);
283 1.6 lukem } /* end of switch */
284 1.6 lukem } /* end of if (found_it) */
285 1.6 lukem if (*buf_ptr == '(' && ps.tos <= 1 && ps.ind_level == 0) {
286 1.6 lukem char *tp = buf_ptr;
287 1.6 lukem while (tp < buf_end)
288 1.6 lukem if (*tp++ == ')' && (*tp == ';' || *tp == ','))
289 1.6 lukem goto not_proc;
290 1.6 lukem strncpy(ps.procname, token, sizeof ps.procname - 1);
291 1.6 lukem ps.in_parameter_declaration = 1;
292 1.6 lukem rparen_count = 1;
293 1.6 lukem not_proc: ;
294 1.6 lukem }
295 1.6 lukem /*
296 1.6 lukem * The following hack attempts to guess whether or not the current
297 1.6 lukem * token is in fact a declaration keyword -- one that has been
298 1.6 lukem * typedefd
299 1.1 cgd */
300 1.6 lukem if (((*buf_ptr == '*' && buf_ptr[1] != '=') || isalpha(*buf_ptr) || *buf_ptr == '_')
301 1.6 lukem && !ps.p_l_follow
302 1.6 lukem && !ps.block_init
303 1.6 lukem && (ps.last_token == rparen || ps.last_token == semicolon ||
304 1.6 lukem ps.last_token == decl ||
305 1.6 lukem ps.last_token == lbrace || ps.last_token == rbrace)) {
306 1.6 lukem ps.its_a_keyword = true;
307 1.6 lukem ps.last_u_d = true;
308 1.6 lukem last_code = decl;
309 1.6 lukem return decl;
310 1.6 lukem }
311 1.6 lukem if (last_code == decl) /* if this is a declared variable,
312 1.6 lukem * then following sign is unary */
313 1.6 lukem ps.last_u_d = true; /* will make "int a -1" work */
314 1.6 lukem last_code = ident;
315 1.6 lukem return (ident); /* the ident is not in the list */
316 1.6 lukem } /* end of procesing for alpanum character */
317 1.6 lukem /* Scan a non-alphanumeric token */
318 1.6 lukem *e_token++ = *buf_ptr; /* if it is only a one-character token, it is
319 1.6 lukem * moved here */
320 1.6 lukem *e_token = '\0';
321 1.6 lukem if (++buf_ptr >= buf_end)
322 1.6 lukem fill_buffer();
323 1.6 lukem
324 1.6 lukem switch (*token) {
325 1.6 lukem case '\n':
326 1.6 lukem unary_delim = ps.last_u_d;
327 1.6 lukem ps.last_nl = true; /* remember that we just had a newline */
328 1.6 lukem code = (had_eof ? 0 : newline);
329 1.1 cgd
330 1.6 lukem /*
331 1.6 lukem * if data has been exausted, the newline is a dummy, and we should
332 1.6 lukem * return code to stop
333 1.6 lukem */
334 1.6 lukem break;
335 1.1 cgd
336 1.6 lukem case '\'': /* start of quoted character */
337 1.6 lukem case '"': /* start of string */
338 1.6 lukem qchar = *token;
339 1.6 lukem if (troff) {
340 1.6 lukem e_token[-1] = '`';
341 1.6 lukem if (qchar == '"')
342 1.6 lukem *e_token++ = '`';
343 1.6 lukem e_token = chfont(&bodyf, &stringf, e_token);
344 1.6 lukem }
345 1.6 lukem do { /* copy the string */
346 1.6 lukem while (1) { /* move one character or
347 1.6 lukem * [/<char>]<char> */
348 1.6 lukem if (*buf_ptr == '\n') {
349 1.6 lukem printf("%d: Unterminated literal\n", line_no);
350 1.6 lukem goto stop_lit;
351 1.6 lukem }
352 1.6 lukem CHECK_SIZE_TOKEN; /* Only have to do this
353 1.6 lukem * once in this loop,
354 1.6 lukem * since CHECK_SIZE
355 1.6 lukem * guarantees that there
356 1.6 lukem * are at least 5
357 1.6 lukem * entries left */
358 1.6 lukem *e_token = *buf_ptr++;
359 1.6 lukem if (buf_ptr >= buf_end)
360 1.6 lukem fill_buffer();
361 1.6 lukem if (*e_token == BACKSLASH) { /* if escape, copy extra
362 1.6 lukem * char */
363 1.6 lukem if (*buf_ptr == '\n') /* check for escaped
364 1.6 lukem * newline */
365 1.6 lukem ++line_no;
366 1.6 lukem if (troff) {
367 1.6 lukem *++e_token = BACKSLASH;
368 1.6 lukem if (*buf_ptr == BACKSLASH)
369 1.6 lukem *++e_token = BACKSLASH;
370 1.6 lukem }
371 1.6 lukem *++e_token = *buf_ptr++;
372 1.6 lukem ++e_token; /* we must increment
373 1.6 lukem * this again because we
374 1.6 lukem * copied two chars */
375 1.6 lukem if (buf_ptr >= buf_end)
376 1.6 lukem fill_buffer();
377 1.6 lukem } else
378 1.6 lukem break; /* we copied one character */
379 1.6 lukem } /* end of while (1) */
380 1.6 lukem } while (*e_token++ != qchar);
381 1.6 lukem if (troff) {
382 1.6 lukem e_token = chfont(&stringf, &bodyf, e_token - 1);
383 1.6 lukem if (qchar == '"')
384 1.6 lukem *e_token++ = '\'';
385 1.1 cgd }
386 1.1 cgd stop_lit:
387 1.6 lukem code = ident;
388 1.6 lukem break;
389 1.6 lukem
390 1.6 lukem case ('('):
391 1.6 lukem case ('['):
392 1.6 lukem unary_delim = true;
393 1.6 lukem code = lparen;
394 1.6 lukem break;
395 1.6 lukem
396 1.6 lukem case (')'):
397 1.6 lukem case (']'):
398 1.6 lukem code = rparen;
399 1.6 lukem break;
400 1.6 lukem
401 1.6 lukem case '#':
402 1.6 lukem unary_delim = ps.last_u_d;
403 1.6 lukem code = preesc;
404 1.6 lukem break;
405 1.6 lukem
406 1.6 lukem case '?':
407 1.6 lukem unary_delim = true;
408 1.6 lukem code = question;
409 1.6 lukem break;
410 1.6 lukem
411 1.6 lukem case (':'):
412 1.6 lukem code = colon;
413 1.6 lukem unary_delim = true;
414 1.6 lukem break;
415 1.6 lukem
416 1.6 lukem case (';'):
417 1.6 lukem unary_delim = true;
418 1.6 lukem code = semicolon;
419 1.6 lukem break;
420 1.1 cgd
421 1.6 lukem case ('{'):
422 1.6 lukem unary_delim = true;
423 1.1 cgd
424 1.6 lukem /*
425 1.6 lukem * if (ps.in_or_st) ps.block_init = 1;
426 1.6 lukem */
427 1.6 lukem /* ? code = ps.block_init ? lparen : lbrace; */
428 1.6 lukem code = lbrace;
429 1.6 lukem break;
430 1.6 lukem
431 1.6 lukem case ('}'):
432 1.6 lukem unary_delim = true;
433 1.6 lukem /* ? code = ps.block_init ? rparen : rbrace; */
434 1.6 lukem code = rbrace;
435 1.6 lukem break;
436 1.6 lukem
437 1.6 lukem case 014: /* a form feed */
438 1.6 lukem unary_delim = ps.last_u_d;
439 1.6 lukem ps.last_nl = true; /* remember this so we can set
440 1.6 lukem * 'ps.col_1' right */
441 1.6 lukem code = form_feed;
442 1.6 lukem break;
443 1.6 lukem
444 1.6 lukem case (','):
445 1.6 lukem unary_delim = true;
446 1.6 lukem code = comma;
447 1.6 lukem break;
448 1.1 cgd
449 1.6 lukem case '.':
450 1.1 cgd unary_delim = false;
451 1.6 lukem code = period;
452 1.6 lukem break;
453 1.6 lukem
454 1.6 lukem case '-':
455 1.6 lukem case '+': /* check for -, +, --, ++ */
456 1.6 lukem code = (ps.last_u_d ? unary_op : binary_op);
457 1.6 lukem unary_delim = true;
458 1.6 lukem
459 1.6 lukem if (*buf_ptr == token[0]) {
460 1.6 lukem /* check for doubled character */
461 1.6 lukem *e_token++ = *buf_ptr++;
462 1.6 lukem /* buffer overflow will be checked at end of loop */
463 1.6 lukem if (last_code == ident || last_code == rparen) {
464 1.6 lukem code = (ps.last_u_d ? unary_op : postop);
465 1.6 lukem /* check for following ++ or -- */
466 1.6 lukem unary_delim = false;
467 1.6 lukem }
468 1.6 lukem } else
469 1.6 lukem if (*buf_ptr == '=')
470 1.6 lukem /* check for operator += */
471 1.6 lukem *e_token++ = *buf_ptr++;
472 1.6 lukem else
473 1.6 lukem if (*buf_ptr == '>') {
474 1.6 lukem /* check for operator -> */
475 1.6 lukem *e_token++ = *buf_ptr++;
476 1.6 lukem if (!pointer_as_binop) {
477 1.6 lukem unary_delim = false;
478 1.6 lukem code = unary_op;
479 1.6 lukem ps.want_blank = false;
480 1.6 lukem }
481 1.6 lukem }
482 1.6 lukem break; /* buffer overflow will be checked at end of
483 1.1 cgd * switch */
484 1.1 cgd
485 1.6 lukem case '=':
486 1.6 lukem if (ps.in_or_st)
487 1.6 lukem ps.block_init = 1;
488 1.1 cgd #ifdef undef
489 1.6 lukem if (chartype[*buf_ptr] == opchar) { /* we have two char
490 1.6 lukem * assignment */
491 1.6 lukem e_token[-1] = *buf_ptr++;
492 1.6 lukem if ((e_token[-1] == '<' || e_token[-1] == '>') && e_token[-1] == *buf_ptr)
493 1.6 lukem *e_token++ = *buf_ptr++;
494 1.6 lukem *e_token++ = '='; /* Flip =+ to += */
495 1.6 lukem *e_token = 0;
496 1.6 lukem }
497 1.1 cgd #else
498 1.6 lukem if (*buf_ptr == '=') { /* == */
499 1.6 lukem *e_token++ = '='; /* Flip =+ to += */
500 1.6 lukem buf_ptr++;
501 1.6 lukem *e_token = 0;
502 1.6 lukem }
503 1.1 cgd #endif
504 1.6 lukem code = binary_op;
505 1.6 lukem unary_delim = true;
506 1.6 lukem break;
507 1.6 lukem /* can drop thru!!! */
508 1.6 lukem
509 1.6 lukem case '>':
510 1.6 lukem case '<':
511 1.6 lukem case '!': /* ops like <, <<, <=, !=, etc */
512 1.6 lukem if (*buf_ptr == '>' || *buf_ptr == '<' || *buf_ptr == '=') {
513 1.6 lukem *e_token++ = *buf_ptr;
514 1.6 lukem if (++buf_ptr >= buf_end)
515 1.6 lukem fill_buffer();
516 1.6 lukem }
517 1.6 lukem if (*buf_ptr == '=')
518 1.6 lukem *e_token++ = *buf_ptr++;
519 1.6 lukem code = (ps.last_u_d ? unary_op : binary_op);
520 1.6 lukem unary_delim = true;
521 1.6 lukem break;
522 1.6 lukem
523 1.6 lukem default:
524 1.6 lukem if (token[0] == '/' && *buf_ptr == '*') {
525 1.6 lukem /* it is start of comment */
526 1.6 lukem *e_token++ = '*';
527 1.6 lukem
528 1.6 lukem if (++buf_ptr >= buf_end)
529 1.6 lukem fill_buffer();
530 1.6 lukem
531 1.6 lukem code = comment;
532 1.6 lukem unary_delim = ps.last_u_d;
533 1.6 lukem break;
534 1.6 lukem }
535 1.6 lukem while (*(e_token - 1) == *buf_ptr || *buf_ptr == '=') {
536 1.6 lukem /*
537 1.6 lukem * handle ||, &&, etc, and also things as in int *****i
538 1.6 lukem */
539 1.6 lukem *e_token++ = *buf_ptr;
540 1.6 lukem if (++buf_ptr >= buf_end)
541 1.6 lukem fill_buffer();
542 1.6 lukem }
543 1.6 lukem code = (ps.last_u_d ? unary_op : binary_op);
544 1.6 lukem unary_delim = true;
545 1.1 cgd
546 1.1 cgd
547 1.6 lukem } /* end of switch */
548 1.6 lukem if (code != newline) {
549 1.6 lukem l_struct = false;
550 1.6 lukem last_code = code;
551 1.1 cgd }
552 1.6 lukem if (buf_ptr >= buf_end) /* check for input buffer empty */
553 1.1 cgd fill_buffer();
554 1.6 lukem ps.last_u_d = unary_delim;
555 1.6 lukem *e_token = '\0'; /* null terminate the token */
556 1.6 lukem return (code);
557 1.1 cgd }
558 1.1 cgd /*
559 1.1 cgd * Add the given keyword to the keyword table, using val as the keyword type
560 1.1 cgd */
561 1.6 lukem void
562 1.1 cgd addkey(key, val)
563 1.6 lukem char *key;
564 1.6 lukem int val;
565 1.1 cgd {
566 1.6 lukem struct templ *p = specials;
567 1.6 lukem while (p->rwd)
568 1.6 lukem if (p->rwd[0] == key[0] && strcmp(p->rwd, key) == 0)
569 1.6 lukem return;
570 1.6 lukem else
571 1.6 lukem p++;
572 1.6 lukem if (p >= specials + sizeof specials / sizeof specials[0])
573 1.6 lukem return; /* For now, table overflows are silently
574 1.1 cgd * ignored */
575 1.6 lukem p->rwd = key;
576 1.6 lukem p->rwcode = val;
577 1.6 lukem p[1].rwd = 0;
578 1.6 lukem p[1].rwcode = 0;
579 1.1 cgd }
580