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