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
142 4460 : strcmp_type(const void *e1, const void *e2)
143 : {
144 4460 : 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 64 : is_func_definition(char *tp)
161 : {
162 64 : int paren_depth = 0;
163 64 : int in_comment = false;
164 64 : int in_slash_comment = false;
165 64 : int lastc = 0;
166 :
167 : /* We may need to look past the end of the current buffer. */
168 64 : lookahead_reset();
169 1272 : for (;;) {
170 : int c;
171 :
172 : /* Fetch next character. */
173 1336 : if (tp < buf_end)
174 724 : c = *tp++;
175 : else {
176 612 : c = lookahead();
177 612 : if (c == EOF)
178 0 : break;
179 : }
180 : /* Handle comments. */
181 1336 : if (in_comment) {
182 0 : if (lastc == '*' && c == '/')
183 0 : in_comment = false;
184 1336 : } else if (lastc == '/' && c == '*' && !in_slash_comment)
185 0 : in_comment = true;
186 1336 : else if (in_slash_comment) {
187 0 : if (c == '\n')
188 0 : in_slash_comment = false;
189 1336 : } else if (lastc == '/' && c == '/')
190 0 : in_slash_comment = true;
191 : /* Count nested parens properly. */
192 1336 : else if (c == '(')
193 74 : paren_depth++;
194 1262 : else if (c == ')') {
195 74 : paren_depth--;
196 : /*
197 : * If we find unbalanced parens, we must have started inside a
198 : * declaration.
199 : */
200 74 : if (paren_depth < 0)
201 0 : return false;
202 1188 : } else if (paren_depth == 0) {
203 : /* We are outside any parentheses or comments. */
204 198 : if (c == '{')
205 56 : return true;
206 142 : else if (c == ';' || c == ',')
207 8 : return false;
208 : }
209 1272 : lastc = c;
210 : }
211 : /* Hit EOF --- for lack of anything better, assume "not a definition". */
212 0 : return false;
213 : }
214 :
215 : int
216 2642 : 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 2642 : e_token = s_token; /* point to start of place to save token */
224 2642 : unary_delim = false;
225 2642 : 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 2642 : state->last_nl = false;
229 :
230 3536 : while (*buf_ptr == ' ' || *buf_ptr == '\t') { /* get rid of blanks */
231 894 : state->col_1 = false; /* leading blanks imply token is not in column
232 : * 1 */
233 894 : if (++buf_ptr >= buf_end)
234 42 : fill_buffer();
235 : }
236 :
237 : /* Scan an alphanumeric token */
238 2642 : if (chartype[*buf_ptr & 127] == alphanum ||
239 1800 : (buf_ptr[0] == '.' && isdigit((unsigned char)buf_ptr[1]))) {
240 : /*
241 : * we have a character or number
242 : */
243 : struct templ *p;
244 :
245 848 : if (isdigit((unsigned char)*buf_ptr) ||
246 854 : (buf_ptr[0] == '.' && isdigit((unsigned char)buf_ptr[1]))) {
247 106 : int seendot = 0,
248 106 : seenexp = 0,
249 106 : seensfx = 0;
250 :
251 : /*
252 : * base 2, base 8, base 16:
253 : */
254 128 : if (buf_ptr[0] == '0' && buf_ptr[1] != '.') {
255 : int len;
256 :
257 22 : if (buf_ptr[1] == 'b' || buf_ptr[1] == 'B')
258 4 : len = strspn(buf_ptr + 2, "01") + 2;
259 18 : else if (buf_ptr[1] == 'x' || buf_ptr[1] == 'X')
260 4 : len = strspn(buf_ptr + 2, "0123456789ABCDEFabcdef") + 2;
261 : else
262 14 : len = strspn(buf_ptr + 1, "012345678") + 1;
263 22 : if (len > 0) {
264 22 : CHECK_SIZE_TOKEN(len);
265 22 : memcpy(e_token, buf_ptr, len);
266 22 : e_token += len;
267 22 : buf_ptr += len;
268 : }
269 : else
270 0 : diag2(1, "Unterminated literal");
271 : }
272 : else /* base 10: */
273 : while (1) {
274 120 : if (*buf_ptr == '.') {
275 14 : if (seendot)
276 0 : break;
277 : else
278 14 : seendot++;
279 : }
280 120 : CHECK_SIZE_TOKEN(3);
281 120 : *e_token++ = *buf_ptr++;
282 120 : if (!isdigit((unsigned char)*buf_ptr) && *buf_ptr != '.') {
283 84 : if ((*buf_ptr != 'E' && *buf_ptr != 'e') || seenexp)
284 : break;
285 : else {
286 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) {
296 134 : CHECK_SIZE_TOKEN(2);
297 134 : if (!(seensfx & 1) && (*buf_ptr == 'U' || *buf_ptr == 'u')) {
298 12 : *e_token++ = *buf_ptr++;
299 12 : seensfx |= 1;
300 12 : continue;
301 : }
302 122 : if (!(seensfx & 2) && (strchr("fFlL", *buf_ptr) != NULL)) {
303 16 : if (buf_ptr[1] == buf_ptr[0])
304 0 : *e_token++ = *buf_ptr++;
305 16 : *e_token++ = *buf_ptr++;
306 16 : seensfx |= 2;
307 16 : continue;
308 : }
309 106 : break;
310 : }
311 : }
312 : else
313 4112 : while (chartype[*buf_ptr & 127] == alphanum || *buf_ptr == BACKSLASH) {
314 : /* fill_buffer() terminates buffer with newline */
315 3370 : if (*buf_ptr == BACKSLASH) {
316 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 : }
323 3370 : CHECK_SIZE_TOKEN(1);
324 : /* copy it over */
325 3370 : *e_token++ = *buf_ptr++;
326 3370 : if (buf_ptr >= buf_end)
327 0 : fill_buffer();
328 : }
329 848 : *e_token = '\0';
330 :
331 848 : if (s_token[0] == 'L' && s_token[1] == '\0' &&
332 4 : (*buf_ptr == '"' || *buf_ptr == '\''))
333 4 : return (strpfx);
334 :
335 1274 : while (*buf_ptr == ' ' || *buf_ptr == '\t') { /* get rid of blanks */
336 430 : if (++buf_ptr >= buf_end)
337 32 : fill_buffer();
338 : }
339 844 : state->keyword = 0;
340 844 : 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 10 : state->last_u_d = true;
345 10 : return (decl);
346 : }
347 : /*
348 : * Operator after identifier is binary unless last token was 'struct'
349 : */
350 834 : state->last_u_d = (state->last_token == structure);
351 :
352 834 : p = bsearch(s_token,
353 : specials,
354 : sizeof(specials) / sizeof(specials[0]),
355 : sizeof(specials[0]),
356 : strcmp_type);
357 834 : if (p == NULL) { /* not a special keyword... */
358 : char *u;
359 :
360 : /* ... so maybe a type_t or a typedef */
361 502 : if ((auto_typedefs && ((u = strrchr(s_token, '_')) != NULL) &&
362 596 : strcmp(u, "_t") == 0) || (typename_top >= 0 &&
363 94 : bsearch(s_token, typenames, typename_top + 1,
364 : sizeof(typenames[0]), strcmp_type))) {
365 8 : state->keyword = 4; /* a type name */
366 8 : state->last_u_d = true;
367 8 : goto found_typename;
368 : }
369 : } else { /* we have a keyword */
370 332 : state->keyword = p->rwcode;
371 332 : state->last_u_d = true;
372 332 : switch (p->rwcode) {
373 2 : case 7: /* it is a switch */
374 2 : return (swstmt);
375 4 : case 8: /* a case or default */
376 4 : return (casestmt);
377 :
378 : case 3: /* a "struct" */
379 : /* FALLTHROUGH */
380 : case 4: /* one of the declaration keywords */
381 256 : found_typename:
382 256 : if (state->p_l_follow) {
383 : /* inside parens: cast, param list, offsetof or sizeof */
384 94 : state->cast_mask |= (1 << state->p_l_follow) & ~state->not_cast_mask;
385 : }
386 256 : if (state->last_token == period || state->last_token == unary_op) {
387 4 : state->keyword = 0;
388 4 : break;
389 : }
390 252 : if (p != NULL && p->rwcode == 3)
391 36 : return (structure);
392 216 : if (state->p_l_follow)
393 74 : break;
394 142 : return (decl);
395 :
396 24 : case 5: /* if, while, for */
397 24 : return (sp_paren);
398 :
399 14 : case 6: /* do, else */
400 14 : return (sp_nparen);
401 :
402 18 : case 10: /* storage class specifier */
403 18 : return (storage);
404 :
405 12 : case 11: /* typedef */
406 12 : return (type_def);
407 :
408 10 : default: /* all others are treated like any other
409 : * identifier */
410 10 : return (ident);
411 : } /* end of switch */
412 : } /* end of if (found_it) */
413 572 : if (*buf_ptr == '(' && state->tos <= 1 && state->ind_level == 0 &&
414 68 : state->in_parameter_declaration == 0 && state->block_init == 0) {
415 64 : if (is_func_definition(buf_ptr)) {
416 56 : strncpy(state->procname, token, sizeof state->procname - 1);
417 56 : if (state->in_decl)
418 54 : state->in_parameter_declaration = 1;
419 56 : 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 508 : else if (!state->p_l_follow && !state->block_init &&
428 198 : !state->in_stmt &&
429 48 : ((*buf_ptr == '*' && buf_ptr[1] != '=') ||
430 42 : isalpha((unsigned char)*buf_ptr)) &&
431 12 : (state->last_token == semicolon || state->last_token == lbrace ||
432 0 : state->last_token == rbrace)) {
433 12 : state->keyword = 4; /* a type name */
434 12 : state->last_u_d = true;
435 12 : return decl;
436 : }
437 504 : if (state->last_token == decl) /* if this is a declared variable,
438 : * then following sign is unary */
439 76 : state->last_u_d = true; /* will make "int a -1" work */
440 504 : 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 1794 : CHECK_SIZE_TOKEN(3); /* things like "<<=" */
446 1794 : *e_token++ = *buf_ptr; /* if it is only a one-character token, it is
447 : * moved here */
448 1794 : *e_token = '\0';
449 1794 : if (++buf_ptr >= buf_end)
450 598 : fill_buffer();
451 :
452 1794 : switch (*token) {
453 686 : case '\n':
454 686 : unary_delim = state->last_u_d;
455 686 : state->last_nl = true; /* remember that we just had a newline */
456 686 : 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 686 : break;
463 :
464 4 : case '\'': /* start of quoted character */
465 : case '"': /* start of string */
466 4 : qchar = *token;
467 : do { /* copy the string */
468 : while (1) { /* move one character or [/<char>]<char> */
469 14 : if (*buf_ptr == '\n') {
470 0 : diag2(1, "Unterminated literal");
471 0 : goto stop_lit;
472 : }
473 14 : CHECK_SIZE_TOKEN(2);
474 14 : *e_token = *buf_ptr++;
475 14 : if (buf_ptr >= buf_end)
476 0 : fill_buffer();
477 14 : if (*e_token == BACKSLASH) { /* if escape, copy extra char */
478 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
487 14 : break; /* we copied one character */
488 : } /* end of while (1) */
489 14 : } while (*e_token++ != qchar);
490 4 : stop_lit:
491 4 : code = ident;
492 4 : break;
493 :
494 156 : case ('('):
495 : case ('['):
496 156 : unary_delim = true;
497 156 : code = lparen;
498 156 : break;
499 :
500 156 : case (')'):
501 : case (']'):
502 156 : code = rparen;
503 156 : break;
504 :
505 22 : case '#':
506 22 : unary_delim = state->last_u_d;
507 22 : code = preesc;
508 22 : break;
509 :
510 0 : case '?':
511 0 : unary_delim = true;
512 0 : code = question;
513 0 : break;
514 :
515 10 : case (':'):
516 10 : code = colon;
517 10 : unary_delim = true;
518 10 : break;
519 :
520 148 : case (';'):
521 148 : unary_delim = true;
522 148 : code = semicolon;
523 148 : break;
524 :
525 114 : case ('{'):
526 114 : unary_delim = true;
527 :
528 : /*
529 : * if (state->in_or_st) state->block_init = 1;
530 : */
531 : /* ? code = state->block_init ? lparen : lbrace; */
532 114 : code = lbrace;
533 114 : break;
534 :
535 82 : case ('}'):
536 82 : unary_delim = true;
537 : /* ? code = state->block_init ? rparen : rbrace; */
538 82 : code = rbrace;
539 82 : break;
540 :
541 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 :
548 110 : case (','):
549 110 : unary_delim = true;
550 110 : code = comma;
551 110 : break;
552 :
553 8 : case '.':
554 8 : unary_delim = false;
555 8 : code = period;
556 8 : break;
557 :
558 12 : case '-':
559 : case '+': /* check for -, +, --, ++ */
560 12 : code = (state->last_u_d ? unary_op : binary_op);
561 12 : unary_delim = true;
562 :
563 12 : if (*buf_ptr == token[0]) {
564 : /* check for doubled character */
565 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 : }
573 12 : else if (*buf_ptr == '=')
574 : /* check for operator += */
575 0 : *e_token++ = *buf_ptr++;
576 12 : else if (*buf_ptr == '>') {
577 : /* check for operator -> */
578 4 : *e_token++ = *buf_ptr++;
579 4 : unary_delim = false;
580 4 : code = unary_op;
581 4 : state->want_blank = false;
582 : }
583 12 : break; /* buffer overflow will be checked at end of
584 : * switch */
585 :
586 50 : case '=':
587 50 : if (state->in_or_st)
588 44 : 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 50 : if (*buf_ptr == '=') {/* == */
599 0 : *e_token++ = '='; /* Flip =+ to += */
600 0 : buf_ptr++;
601 0 : *e_token = 0;
602 : }
603 : #endif
604 50 : code = binary_op;
605 50 : unary_delim = true;
606 50 : break;
607 : /* can drop thru!!! */
608 :
609 8 : case '>':
610 : case '<':
611 : case '!': /* ops like <, <<, <=, !=, etc */
612 8 : if (*buf_ptr == '>' || *buf_ptr == '<' || *buf_ptr == '=') {
613 8 : *e_token++ = *buf_ptr;
614 8 : if (++buf_ptr >= buf_end)
615 0 : fill_buffer();
616 : }
617 8 : if (*buf_ptr == '=')
618 0 : *e_token++ = *buf_ptr++;
619 8 : code = (state->last_u_d ? unary_op : binary_op);
620 8 : unary_delim = true;
621 8 : break;
622 :
623 92 : case '*':
624 92 : unary_delim = true;
625 92 : if (!state->last_u_d) {
626 12 : if (*buf_ptr == '=')
627 0 : *e_token++ = *buf_ptr++;
628 12 : code = binary_op;
629 12 : break;
630 : }
631 102 : while (*buf_ptr == '*' || isspace((unsigned char)*buf_ptr)) {
632 22 : if (*buf_ptr == '*') {
633 6 : CHECK_SIZE_TOKEN(1);
634 6 : *e_token++ = *buf_ptr;
635 : }
636 22 : if (++buf_ptr >= buf_end)
637 4 : fill_buffer();
638 : }
639 80 : code = unary_op;
640 80 : break;
641 :
642 136 : default:
643 136 : if (token[0] == '/' && *buf_ptr == '*') {
644 : /* it is start of comment */
645 134 : *e_token++ = '*';
646 :
647 134 : if (++buf_ptr >= buf_end)
648 0 : fill_buffer();
649 :
650 134 : code = comment;
651 134 : unary_delim = state->last_u_d;
652 134 : break;
653 : }
654 2 : while (*(e_token - 1) == *buf_ptr || *buf_ptr == '=') {
655 : /*
656 : * handle ||, &&, etc, and also things as in int *****i
657 : */
658 0 : CHECK_SIZE_TOKEN(1);
659 0 : *e_token++ = *buf_ptr;
660 0 : if (++buf_ptr >= buf_end)
661 0 : fill_buffer();
662 : }
663 2 : code = (state->last_u_d ? unary_op : binary_op);
664 2 : unary_delim = true;
665 :
666 :
667 : } /* end of switch */
668 1794 : if (buf_ptr >= buf_end) /* check for input buffer empty */
669 0 : fill_buffer();
670 1794 : state->last_u_d = unary_delim;
671 1794 : CHECK_SIZE_TOKEN(1);
672 1794 : *e_token = '\0'; /* null terminate the token */
673 1794 : return (code);
674 : }
675 :
676 : void
677 38 : alloc_typenames(void)
678 : {
679 :
680 38 : typenames = (const char **)malloc(sizeof(typenames[0]) *
681 38 : (typename_count = 16));
682 38 : if (typenames == NULL)
683 0 : err(1, NULL);
684 38 : }
685 :
686 : void
687 6 : add_typename(const char *key)
688 : {
689 : int comparison;
690 : const char *copy;
691 :
692 6 : if (typename_top + 1 >= typename_count) {
693 0 : typenames = realloc((void *)typenames,
694 0 : sizeof(typenames[0]) * (typename_count *= 2));
695 0 : if (typenames == NULL)
696 0 : err(1, NULL);
697 : }
698 6 : if (typename_top == -1)
699 4 : typenames[++typename_top] = copy = strdup(key);
700 2 : else if ((comparison = strcmp(key, typenames[typename_top])) >= 0) {
701 : /* take advantage of sorted input */
702 0 : if (comparison == 0) /* remove duplicates */
703 0 : return;
704 0 : typenames[++typename_top] = copy = strdup(key);
705 : }
706 : else {
707 : int p;
708 :
709 2 : for (p = 0; (comparison = strcmp(key, typenames[p])) > 0; p++)
710 : /* find place for the new key */;
711 2 : if (comparison == 0) /* remove duplicates */
712 0 : return;
713 2 : memmove(&typenames[p + 1], &typenames[p],
714 2 : sizeof(typenames[0]) * (++typename_top - p));
715 2 : typenames[p] = copy = strdup(key);
716 : }
717 :
718 6 : if (copy == NULL)
719 0 : err(1, NULL);
720 : }
|