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