Age Owner TLA Line data Source code
1 : /*-
2 : * Copyright (c) 1985 Sun Microsystems, Inc.
3 : * Copyright (c) 1980, 1993
4 : * The Regents of the University of California. All rights reserved.
5 : * All rights reserved.
6 : *
7 : * Redistribution and use in source and binary forms, with or without
8 : * modification, are permitted provided that the following conditions
9 : * are met:
10 : * 1. Redistributions of source code must retain the above copyright
11 : * notice, this list of conditions and the following disclaimer.
12 : * 2. Redistributions in binary form must reproduce the above copyright
13 : * notice, this list of conditions and the following disclaimer in the
14 : * documentation and/or other materials provided with the distribution.
15 : * 3. Neither the name of the University nor the names of its contributors
16 : * may be used to endorse or promote products derived from this software
17 : * without specific prior written permission.
18 : *
19 : * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
20 : * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 : * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 : * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
23 : * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 : * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 : * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 : * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 : * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 : * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 : * SUCH DAMAGE.
30 : */
31 :
32 : #if 0
33 : #ifndef lint
34 : static char sccsid[] = "@(#)lexi.c 8.1 (Berkeley) 6/6/93";
35 : #endif /* not lint */
36 : #endif
37 :
38 : #include "c.h"
39 :
40 : /*
41 : * Here we have the token scanner for indent. It scans off one token and puts
42 : * it in the global variable "token". It returns a code, indicating the type
43 : * of token scanned.
44 : */
45 :
46 : #include <err.h>
47 : #include <stdio.h>
48 : #include <ctype.h>
49 : #include <stdlib.h>
50 : #include <string.h>
51 : #include "indent_globs.h"
52 : #include "indent_codes.h"
53 : #include "indent.h"
54 :
55 : #define alphanum 1
56 : #ifdef undef
57 : #define opchar 3
58 : #endif
59 :
60 : struct templ {
61 : const char *rwd;
62 : int rwcode;
63 : };
64 :
65 : /*
66 : * This table has to be sorted alphabetically, because it'll be used in binary
67 : * search. For the same reason, string must be the first thing in struct templ.
68 : */
69 : struct templ specials[] =
70 : {
71 : {"_Bool", 4},
72 : {"_Complex", 4},
73 : {"_Imaginary", 4},
74 : {"auto", 10},
75 : {"bool", 4},
76 : {"break", 9},
77 : {"case", 8},
78 : {"char", 4},
79 : {"complex", 4},
80 : {"const", 4},
81 : {"continue", 12},
82 : {"default", 8},
83 : {"do", 6},
84 : {"double", 4},
85 : {"else", 6},
86 : {"enum", 3},
87 : {"extern", 10},
88 : {"float", 4},
89 : {"for", 5},
90 : {"global", 4},
91 : {"goto", 9},
92 : {"if", 5},
93 : {"imaginary", 4},
94 : {"inline", 12},
95 : {"int", 4},
96 : {"long", 4},
97 : {"offsetof", 1},
98 : {"register", 10},
99 : {"restrict", 12},
100 : {"return", 9},
101 : {"short", 4},
102 : {"signed", 4},
103 : {"sizeof", 2},
104 : {"static", 10},
105 : {"struct", 3},
106 : {"switch", 7},
107 : {"typedef", 11},
108 : {"union", 3},
109 : {"unsigned", 4},
110 : {"void", 4},
111 : {"volatile", 4},
112 : {"while", 5}
113 : };
114 :
115 : const char **typenames;
116 : int typename_count;
117 : int typename_top = -1;
118 :
119 : char chartype[128] =
120 : { /* this is used to facilitate the decision of
121 : * what type (alphanumeric, operator) each
122 : * character is */
123 : 0, 0, 0, 0, 0, 0, 0, 0,
124 : 0, 0, 0, 0, 0, 0, 0, 0,
125 : 0, 0, 0, 0, 0, 0, 0, 0,
126 : 0, 0, 0, 0, 0, 0, 0, 0,
127 : 0, 3, 0, 0, 1, 3, 3, 0,
128 : 0, 0, 3, 3, 0, 3, 0, 3,
129 : 1, 1, 1, 1, 1, 1, 1, 1,
130 : 1, 1, 0, 0, 3, 3, 3, 3,
131 : 0, 1, 1, 1, 1, 1, 1, 1,
132 : 1, 1, 1, 1, 1, 1, 1, 1,
133 : 1, 1, 1, 1, 1, 1, 1, 1,
134 : 1, 1, 1, 0, 0, 0, 3, 1,
135 : 0, 1, 1, 1, 1, 1, 1, 1,
136 : 1, 1, 1, 1, 1, 1, 1, 1,
137 : 1, 1, 1, 1, 1, 1, 1, 1,
138 : 1, 1, 1, 0, 3, 0, 3, 0
139 : };
140 :
141 : static int
56 tgl 142 GNC 2230 : strcmp_type(const void *e1, const void *e2)
143 : {
144 2230 : return (strcmp(e1, *(const char * const *)e2));
145 : }
146 :
147 : /*
148 : * Decide whether "foo(..." is a function definition or declaration.
149 : *
150 : * At call, we are looking at the '('. Look ahead to find the first
151 : * '{', ';' or ',' that is not within parentheses or comments; then
152 : * it's a definition if we found '{', otherwise a declaration.
153 : * Note that this rule is fooled by K&R-style parameter declarations,
154 : * but telling the difference between those and function attributes
155 : * seems like more trouble than it's worth. This code could also be
156 : * fooled by mismatched parens or apparent comment starts within string
157 : * literals, but that seems unlikely in the context it's used in.
158 : */
159 : static int
160 32 : is_func_definition(char *tp)
161 : {
162 32 : int paren_depth = 0;
163 32 : int in_comment = false;
164 32 : int in_slash_comment = false;
165 32 : int lastc = 0;
166 :
167 : /* We may need to look past the end of the current buffer. */
168 32 : lookahead_reset();
169 636 : for (;;) {
170 : int c;
171 :
172 : /* Fetch next character. */
173 668 : if (tp < buf_end)
174 362 : c = *tp++;
175 : else {
176 306 : c = lookahead();
177 306 : if (c == EOF)
56 tgl 178 UNC 0 : break;
179 : }
180 : /* Handle comments. */
56 tgl 181 GNC 668 : if (in_comment) {
56 tgl 182 UNC 0 : if (lastc == '*' && c == '/')
183 0 : in_comment = false;
56 tgl 184 GNC 668 : } else if (lastc == '/' && c == '*' && !in_slash_comment)
56 tgl 185 UNC 0 : in_comment = true;
56 tgl 186 GNC 668 : else if (in_slash_comment) {
56 tgl 187 UNC 0 : if (c == '\n')
188 0 : in_slash_comment = false;
56 tgl 189 GNC 668 : } else if (lastc == '/' && c == '/')
56 tgl 190 UNC 0 : in_slash_comment = true;
191 : /* Count nested parens properly. */
56 tgl 192 GNC 668 : else if (c == '(')
193 37 : paren_depth++;
194 631 : else if (c == ')') {
195 37 : paren_depth--;
196 : /*
197 : * If we find unbalanced parens, we must have started inside a
198 : * declaration.
199 : */
200 37 : if (paren_depth < 0)
56 tgl 201 UNC 0 : return false;
56 tgl 202 GNC 594 : } else if (paren_depth == 0) {
203 : /* We are outside any parentheses or comments. */
204 99 : if (c == '{')
205 28 : return true;
206 71 : else if (c == ';' || c == ',')
207 4 : return false;
208 : }
209 636 : lastc = c;
210 : }
211 : /* Hit EOF --- for lack of anything better, assume "not a definition". */
56 tgl 212 UNC 0 : return false;
213 : }
214 :
215 : int
56 tgl 216 GNC 1321 : lexi(struct parser_state *state)
217 : {
218 : int unary_delim; /* this is set to 1 if the current token
219 : * forces a following operator to be unary */
220 : int code; /* internal code to be returned */
221 : char qchar; /* the delimiter character for a string */
222 :
223 1321 : e_token = s_token; /* point to start of place to save token */
224 1321 : unary_delim = false;
225 1321 : state->col_1 = state->last_nl; /* tell world that this token started
226 : * in column 1 iff the last thing
227 : * scanned was a newline */
228 1321 : state->last_nl = false;
229 :
230 3089 : while (*buf_ptr == ' ' || *buf_ptr == '\t') { /* get rid of blanks */
231 447 : state->col_1 = false; /* leading blanks imply token is not in column
232 : * 1 */
233 447 : if (++buf_ptr >= buf_end)
234 21 : fill_buffer();
235 : }
236 :
237 : /* Scan an alphanumeric token */
238 1321 : if (chartype[*buf_ptr & 127] == alphanum ||
239 900 : (buf_ptr[0] == '.' && isdigit((unsigned char)buf_ptr[1]))) {
240 : /*
241 : * we have a character or number
242 : */
243 : struct templ *p;
244 :
245 424 : if (isdigit((unsigned char)*buf_ptr) ||
246 427 : (buf_ptr[0] == '.' && isdigit((unsigned char)buf_ptr[1]))) {
247 53 : int seendot = 0,
248 53 : seenexp = 0,
249 53 : seensfx = 0;
250 :
251 : /*
252 : * base 2, base 8, base 16:
253 : */
254 64 : if (buf_ptr[0] == '0' && buf_ptr[1] != '.') {
255 : int len;
256 :
257 11 : if (buf_ptr[1] == 'b' || buf_ptr[1] == 'B')
258 2 : len = strspn(buf_ptr + 2, "01") + 2;
259 9 : else if (buf_ptr[1] == 'x' || buf_ptr[1] == 'X')
260 2 : len = strspn(buf_ptr + 2, "0123456789ABCDEFabcdef") + 2;
261 : else
262 7 : len = strspn(buf_ptr + 1, "012345678") + 1;
263 11 : if (len > 0) {
264 11 : CHECK_SIZE_TOKEN(len);
265 11 : memcpy(e_token, buf_ptr, len);
266 11 : e_token += len;
267 11 : buf_ptr += len;
268 : }
269 : else
56 tgl 270 UNC 0 : diag2(1, "Unterminated literal");
271 : }
272 : else /* base 10: */
273 : while (1) {
56 tgl 274 GNC 60 : if (*buf_ptr == '.') {
275 7 : if (seendot)
56 tgl 276 UNC 0 : break;
277 : else
56 tgl 278 GNC 7 : seendot++;
279 : }
280 60 : CHECK_SIZE_TOKEN(3);
281 60 : *e_token++ = *buf_ptr++;
282 60 : if (!isdigit((unsigned char)*buf_ptr) && *buf_ptr != '.') {
283 42 : if ((*buf_ptr != 'E' && *buf_ptr != 'e') || seenexp)
284 : break;
285 : else {
56 tgl 286 UNC 0 : seenexp++;
287 0 : seendot++;
288 0 : *e_token++ = *buf_ptr++;
289 0 : if (*buf_ptr == '+' || *buf_ptr == '-')
290 0 : *e_token++ = *buf_ptr++;
291 : }
292 : }
293 : }
294 :
295 : while (1) {
56 tgl 296 GNC 67 : CHECK_SIZE_TOKEN(2);
297 67 : if (!(seensfx & 1) && (*buf_ptr == 'U' || *buf_ptr == 'u')) {
298 6 : *e_token++ = *buf_ptr++;
299 6 : seensfx |= 1;
300 6 : continue;
301 : }
302 61 : if (!(seensfx & 2) && (strchr("fFlL", *buf_ptr) != NULL)) {
303 8 : if (buf_ptr[1] == buf_ptr[0])
56 tgl 304 UNC 0 : *e_token++ = *buf_ptr++;
56 tgl 305 GNC 8 : *e_token++ = *buf_ptr++;
306 8 : seensfx |= 2;
307 8 : continue;
308 : }
309 53 : break;
310 : }
311 : }
312 : else
313 2427 : while (chartype[*buf_ptr & 127] == alphanum || *buf_ptr == BACKSLASH) {
314 : /* fill_buffer() terminates buffer with newline */
315 1685 : if (*buf_ptr == BACKSLASH) {
56 tgl 316 UNC 0 : if (*(buf_ptr + 1) == '\n') {
317 0 : buf_ptr += 2;
318 0 : if (buf_ptr >= buf_end)
319 0 : fill_buffer();
320 : } else
321 0 : break;
322 : }
56 tgl 323 GNC 1685 : CHECK_SIZE_TOKEN(1);
324 : /* copy it over */
325 1685 : *e_token++ = *buf_ptr++;
326 1685 : if (buf_ptr >= buf_end)
56 tgl 327 UNC 0 : fill_buffer();
328 : }
56 tgl 329 GNC 424 : *e_token = '\0';
330 :
331 424 : if (s_token[0] == 'L' && s_token[1] == '\0' &&
332 2 : (*buf_ptr == '"' || *buf_ptr == '\''))
333 2 : return (strpfx);
334 :
335 1059 : while (*buf_ptr == ' ' || *buf_ptr == '\t') { /* get rid of blanks */
336 215 : if (++buf_ptr >= buf_end)
337 16 : fill_buffer();
338 : }
339 422 : state->keyword = 0;
340 422 : if (state->last_token == structure && !state->p_l_follow) {
341 : /* if last token was 'struct' and we're not
342 : * in parentheses, then this token
343 : * should be treated as a declaration */
344 5 : state->last_u_d = true;
345 5 : return (decl);
346 : }
347 : /*
348 : * Operator after identifier is binary unless last token was 'struct'
349 : */
350 417 : state->last_u_d = (state->last_token == structure);
351 :
352 417 : p = bsearch(s_token,
353 : specials,
354 : sizeof(specials) / sizeof(specials[0]),
355 : sizeof(specials[0]),
356 : strcmp_type);
357 417 : if (p == NULL) { /* not a special keyword... */
358 : char *u;
359 :
360 : /* ... so maybe a type_t or a typedef */
361 251 : if ((auto_typedefs && ((u = strrchr(s_token, '_')) != NULL) &&
362 298 : strcmp(u, "_t") == 0) || (typename_top >= 0 &&
363 47 : bsearch(s_token, typenames, typename_top + 1,
364 : sizeof(typenames[0]), strcmp_type))) {
365 4 : state->keyword = 4; /* a type name */
366 4 : state->last_u_d = true;
367 4 : goto found_typename;
368 : }
369 : } else { /* we have a keyword */
370 166 : state->keyword = p->rwcode;
371 166 : state->last_u_d = true;
372 166 : switch (p->rwcode) {
373 1 : case 7: /* it is a switch */
374 1 : return (swstmt);
375 2 : case 8: /* a case or default */
376 2 : return (casestmt);
377 :
378 : case 3: /* a "struct" */
379 : /* FALLTHROUGH */
380 : case 4: /* one of the declaration keywords */
381 128 : found_typename:
382 128 : if (state->p_l_follow) {
383 : /* inside parens: cast, param list, offsetof or sizeof */
384 47 : state->cast_mask |= (1 << state->p_l_follow) & ~state->not_cast_mask;
385 : }
386 128 : if (state->last_token == period || state->last_token == unary_op) {
387 2 : state->keyword = 0;
388 2 : break;
389 : }
390 126 : if (p != NULL && p->rwcode == 3)
391 18 : return (structure);
392 108 : if (state->p_l_follow)
393 37 : break;
394 71 : return (decl);
395 :
396 12 : case 5: /* if, while, for */
397 12 : return (sp_paren);
398 :
399 7 : case 6: /* do, else */
400 7 : return (sp_nparen);
401 :
402 9 : case 10: /* storage class specifier */
403 9 : return (storage);
404 :
405 6 : case 11: /* typedef */
406 6 : return (type_def);
407 :
408 5 : default: /* all others are treated like any other
409 : * identifier */
410 5 : return (ident);
411 : } /* end of switch */
412 : } /* end of if (found_it) */
413 286 : if (*buf_ptr == '(' && state->tos <= 1 && state->ind_level == 0 &&
414 34 : state->in_parameter_declaration == 0 && state->block_init == 0) {
415 32 : if (is_func_definition(buf_ptr)) {
416 28 : strncpy(state->procname, token, sizeof state->procname - 1);
417 28 : if (state->in_decl)
418 27 : state->in_parameter_declaration = 1;
419 28 : return (funcname);
420 : }
421 : }
422 : /*
423 : * The following hack attempts to guess whether or not the current
424 : * token is in fact a declaration keyword -- one that has been
425 : * typedefd
426 : */
427 254 : else if (!state->p_l_follow && !state->block_init &&
428 99 : !state->in_stmt &&
429 24 : ((*buf_ptr == '*' && buf_ptr[1] != '=') ||
430 21 : isalpha((unsigned char)*buf_ptr)) &&
431 6 : (state->last_token == semicolon || state->last_token == lbrace ||
56 tgl 432 UNC 0 : state->last_token == rbrace)) {
56 tgl 433 GNC 6 : state->keyword = 4; /* a type name */
434 6 : state->last_u_d = true;
435 6 : return decl;
436 : }
437 252 : if (state->last_token == decl) /* if this is a declared variable,
438 : * then following sign is unary */
439 38 : state->last_u_d = true; /* will make "int a -1" work */
440 252 : return (ident); /* the ident is not in the list */
441 : } /* end of processing for alphanum character */
442 :
443 : /* Scan a non-alphanumeric token */
444 :
445 897 : CHECK_SIZE_TOKEN(3); /* things like "<<=" */
446 897 : *e_token++ = *buf_ptr; /* if it is only a one-character token, it is
447 : * moved here */
448 897 : *e_token = '\0';
449 897 : if (++buf_ptr >= buf_end)
450 299 : fill_buffer();
451 :
452 897 : switch (*token) {
453 343 : case '\n':
454 343 : unary_delim = state->last_u_d;
455 343 : state->last_nl = true; /* remember that we just had a newline */
456 343 : code = (had_eof ? 0 : newline);
457 :
458 : /*
459 : * if data has been exhausted, the newline is a dummy, and we should
460 : * return code to stop
461 : */
462 343 : break;
463 :
464 2 : case '\'': /* start of quoted character */
465 : case '"': /* start of string */
466 2 : qchar = *token;
467 : do { /* copy the string */
468 : while (1) { /* move one character or [/<char>]<char> */
469 7 : if (*buf_ptr == '\n') {
56 tgl 470 UNC 0 : diag2(1, "Unterminated literal");
471 0 : goto stop_lit;
472 : }
56 tgl 473 GNC 7 : CHECK_SIZE_TOKEN(2);
474 7 : *e_token = *buf_ptr++;
475 7 : if (buf_ptr >= buf_end)
56 tgl 476 UNC 0 : fill_buffer();
56 tgl 477 GNC 7 : if (*e_token == BACKSLASH) { /* if escape, copy extra char */
56 tgl 478 UNC 0 : if (*buf_ptr == '\n') /* check for escaped newline */
479 0 : ++line_no;
480 0 : *++e_token = *buf_ptr++;
481 0 : ++e_token; /* we must increment this again because we
482 : * copied two chars */
483 0 : if (buf_ptr >= buf_end)
484 0 : fill_buffer();
485 : }
486 : else
56 tgl 487 GNC 7 : break; /* we copied one character */
488 : } /* end of while (1) */
489 7 : } while (*e_token++ != qchar);
490 2 : stop_lit:
491 2 : code = ident;
492 2 : break;
493 :
494 78 : case ('('):
495 : case ('['):
496 78 : unary_delim = true;
497 78 : code = lparen;
498 78 : break;
499 :
500 78 : case (')'):
501 : case (']'):
502 78 : code = rparen;
503 78 : break;
504 :
505 11 : case '#':
506 11 : unary_delim = state->last_u_d;
507 11 : code = preesc;
508 11 : break;
509 :
56 tgl 510 UNC 0 : case '?':
511 0 : unary_delim = true;
512 0 : code = question;
513 0 : break;
514 :
56 tgl 515 GNC 5 : case (':'):
516 5 : code = colon;
517 5 : unary_delim = true;
518 5 : break;
519 :
520 74 : case (';'):
521 74 : unary_delim = true;
522 74 : code = semicolon;
523 74 : break;
524 :
525 57 : case ('{'):
526 57 : unary_delim = true;
527 :
528 : /*
529 : * if (state->in_or_st) state->block_init = 1;
530 : */
531 : /* ? code = state->block_init ? lparen : lbrace; */
532 57 : code = lbrace;
533 57 : break;
534 :
535 41 : case ('}'):
536 41 : unary_delim = true;
537 : /* ? code = state->block_init ? rparen : rbrace; */
538 41 : code = rbrace;
539 41 : break;
540 :
56 tgl 541 UNC 0 : case 014: /* a form feed */
542 0 : unary_delim = state->last_u_d;
543 0 : state->last_nl = true; /* remember this so we can set 'state->col_1'
544 : * right */
545 0 : code = form_feed;
546 0 : break;
547 :
56 tgl 548 GNC 55 : case (','):
549 55 : unary_delim = true;
550 55 : code = comma;
551 55 : break;
552 :
553 4 : case '.':
554 4 : unary_delim = false;
555 4 : code = period;
556 4 : break;
557 :
558 6 : case '-':
559 : case '+': /* check for -, +, --, ++ */
560 6 : code = (state->last_u_d ? unary_op : binary_op);
561 6 : unary_delim = true;
562 :
563 6 : if (*buf_ptr == token[0]) {
564 : /* check for doubled character */
56 tgl 565 UNC 0 : *e_token++ = *buf_ptr++;
566 : /* buffer overflow will be checked at end of loop */
567 0 : if (state->last_token == ident || state->last_token == rparen) {
568 0 : code = (state->last_u_d ? unary_op : postop);
569 : /* check for following ++ or -- */
570 0 : unary_delim = false;
571 : }
572 : }
56 tgl 573 GNC 6 : else if (*buf_ptr == '=')
574 : /* check for operator += */
56 tgl 575 UNC 0 : *e_token++ = *buf_ptr++;
56 tgl 576 GNC 6 : else if (*buf_ptr == '>') {
577 : /* check for operator -> */
578 2 : *e_token++ = *buf_ptr++;
579 2 : unary_delim = false;
580 2 : code = unary_op;
581 2 : state->want_blank = false;
582 : }
583 6 : break; /* buffer overflow will be checked at end of
584 : * switch */
585 :
586 25 : case '=':
587 25 : if (state->in_or_st)
588 22 : state->block_init = 1;
589 : #ifdef undef
590 : if (chartype[*buf_ptr & 127] == opchar) { /* we have two char assignment */
591 : e_token[-1] = *buf_ptr++;
592 : if ((e_token[-1] == '<' || e_token[-1] == '>') && e_token[-1] == *buf_ptr)
593 : *e_token++ = *buf_ptr++;
594 : *e_token++ = '='; /* Flip =+ to += */
595 : *e_token = 0;
596 : }
597 : #else
598 25 : if (*buf_ptr == '=') {/* == */
56 tgl 599 UNC 0 : *e_token++ = '='; /* Flip =+ to += */
600 0 : buf_ptr++;
601 0 : *e_token = 0;
602 : }
603 : #endif
56 tgl 604 GNC 25 : code = binary_op;
605 25 : unary_delim = true;
606 25 : break;
607 : /* can drop thru!!! */
608 :
609 4 : case '>':
610 : case '<':
611 : case '!': /* ops like <, <<, <=, !=, etc */
612 4 : if (*buf_ptr == '>' || *buf_ptr == '<' || *buf_ptr == '=') {
613 4 : *e_token++ = *buf_ptr;
614 4 : if (++buf_ptr >= buf_end)
56 tgl 615 UNC 0 : fill_buffer();
616 : }
56 tgl 617 GNC 4 : if (*buf_ptr == '=')
56 tgl 618 UNC 0 : *e_token++ = *buf_ptr++;
56 tgl 619 GNC 4 : code = (state->last_u_d ? unary_op : binary_op);
620 4 : unary_delim = true;
621 4 : break;
622 :
623 46 : case '*':
624 46 : unary_delim = true;
625 46 : if (!state->last_u_d) {
626 6 : if (*buf_ptr == '=')
56 tgl 627 UNC 0 : *e_token++ = *buf_ptr++;
56 tgl 628 GNC 6 : code = binary_op;
629 6 : break;
630 : }
631 91 : while (*buf_ptr == '*' || isspace((unsigned char)*buf_ptr)) {
632 11 : if (*buf_ptr == '*') {
633 3 : CHECK_SIZE_TOKEN(1);
634 3 : *e_token++ = *buf_ptr;
635 : }
636 11 : if (++buf_ptr >= buf_end)
637 2 : fill_buffer();
638 : }
639 40 : code = unary_op;
640 40 : break;
641 :
642 68 : default:
643 68 : if (token[0] == '/' && *buf_ptr == '*') {
644 : /* it is start of comment */
645 67 : *e_token++ = '*';
646 :
647 67 : if (++buf_ptr >= buf_end)
56 tgl 648 UNC 0 : fill_buffer();
649 :
56 tgl 650 GNC 67 : code = comment;
651 67 : unary_delim = state->last_u_d;
652 67 : break;
653 : }
654 2 : while (*(e_token - 1) == *buf_ptr || *buf_ptr == '=') {
655 : /*
656 : * handle ||, &&, etc, and also things as in int *****i
657 : */
56 tgl 658 UNC 0 : CHECK_SIZE_TOKEN(1);
659 0 : *e_token++ = *buf_ptr;
660 0 : if (++buf_ptr >= buf_end)
661 0 : fill_buffer();
662 : }
56 tgl 663 GNC 1 : code = (state->last_u_d ? unary_op : binary_op);
664 1 : unary_delim = true;
665 :
666 :
667 : } /* end of switch */
668 897 : if (buf_ptr >= buf_end) /* check for input buffer empty */
56 tgl 669 UNC 0 : fill_buffer();
56 tgl 670 GNC 897 : state->last_u_d = unary_delim;
671 897 : CHECK_SIZE_TOKEN(1);
672 897 : *e_token = '\0'; /* null terminate the token */
673 897 : return (code);
674 : }
675 :
676 : void
677 19 : alloc_typenames(void)
678 : {
679 :
680 19 : typenames = (const char **)malloc(sizeof(typenames[0]) *
681 19 : (typename_count = 16));
682 19 : if (typenames == NULL)
56 tgl 683 UNC 0 : err(1, NULL);
56 tgl 684 GNC 19 : }
685 :
686 : void
687 3 : add_typename(const char *key)
688 : {
689 : int comparison;
690 : const char *copy;
691 :
692 3 : if (typename_top + 1 >= typename_count) {
56 tgl 693 UNC 0 : typenames = realloc((void *)typenames,
694 0 : sizeof(typenames[0]) * (typename_count *= 2));
695 0 : if (typenames == NULL)
696 0 : err(1, NULL);
697 : }
56 tgl 698 GNC 3 : if (typename_top == -1)
699 2 : typenames[++typename_top] = copy = strdup(key);
700 1 : else if ((comparison = strcmp(key, typenames[typename_top])) >= 0) {
701 : /* take advantage of sorted input */
56 tgl 702 UNC 0 : if (comparison == 0) /* remove duplicates */
703 0 : return;
704 0 : typenames[++typename_top] = copy = strdup(key);
705 : }
706 : else {
707 : int p;
708 :
56 tgl 709 GNC 1 : for (p = 0; (comparison = strcmp(key, typenames[p])) > 0; p++)
710 : /* find place for the new key */;
711 1 : if (comparison == 0) /* remove duplicates */
56 tgl 712 UNC 0 : return;
56 tgl 713 GNC 1 : memmove(&typenames[p + 1], &typenames[p],
714 1 : sizeof(typenames[0]) * (++typename_top - p));
715 1 : typenames[p] = copy = strdup(key);
716 : }
717 :
718 3 : if (copy == NULL)
56 tgl 719 UNC 0 : err(1, NULL);
720 : }
|