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