Age Owner Branch data 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
1203 tgl@sss.pgh.pa.us 142 :CBC 2271 : strcmp_type(const void *e1, const void *e2)
143 : : {
144 : 2271 : 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)
1203 tgl@sss.pgh.pa.us 178 :UBC 0 : break;
179 : : }
180 : : /* Handle comments. */
1203 tgl@sss.pgh.pa.us 181 [ - + ]:CBC 668 : if (in_comment) {
1203 tgl@sss.pgh.pa.us 182 [ # # # # ]:UBC 0 : if (lastc == '*' && c == '/')
183 : 0 : in_comment = false;
1203 tgl@sss.pgh.pa.us 184 [ - + - - :CBC 668 : } else if (lastc == '/' && c == '*' && !in_slash_comment)
- - ]
1203 tgl@sss.pgh.pa.us 185 :UBC 0 : in_comment = true;
1203 tgl@sss.pgh.pa.us 186 [ - + ]:CBC 668 : else if (in_slash_comment) {
1203 tgl@sss.pgh.pa.us 187 [ # # ]:UBC 0 : if (c == '\n')
188 : 0 : in_slash_comment = false;
1203 tgl@sss.pgh.pa.us 189 [ - + - - ]:CBC 668 : } else if (lastc == '/' && c == '/')
1203 tgl@sss.pgh.pa.us 190 :UBC 0 : in_slash_comment = true;
191 : : /* Count nested parens properly. */
1203 tgl@sss.pgh.pa.us 192 [ + + ]:CBC 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)
1203 tgl@sss.pgh.pa.us 201 :UBC 0 : return false;
1203 tgl@sss.pgh.pa.us 202 [ + + ]:CBC 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". */
1203 tgl@sss.pgh.pa.us 212 :UBC 0 : return false;
213 : : }
214 : :
215 : : int
1203 tgl@sss.pgh.pa.us 216 :CBC 1340 : 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 : 1340 : e_token = s_token; /* point to start of place to save token */
224 : 1340 : unary_delim = false;
225 : 1340 : 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 : 1340 : state->last_nl = false;
229 : :
230 [ + + + + ]: 3130 : while (*buf_ptr == ' ' || *buf_ptr == '\t') { /* get rid of blanks */
231 : 450 : state->col_1 = false; /* leading blanks imply token is not in column
232 : : * 1 */
233 [ + + ]: 450 : if (++buf_ptr >= buf_end)
234 : 21 : fill_buffer();
235 : : }
236 : :
237 : : /* Scan an alphanumeric token */
238 [ + + ]: 1340 : if (chartype[*buf_ptr & 127] == alphanum ||
239 [ + + + + ]: 911 : (buf_ptr[0] == '.' && isdigit((unsigned char)buf_ptr[1]))) {
240 : : /*
241 : : * we have a character or number
242 : : */
243 : : struct templ *p;
244 : :
245 [ + + ]: 432 : if (isdigit((unsigned char)*buf_ptr) ||
246 [ + + + - ]: 435 : (buf_ptr[0] == '.' && isdigit((unsigned char)buf_ptr[1]))) {
247 : 55 : int seendot = 0,
248 : 55 : seenexp = 0,
249 : 55 : seensfx = 0;
250 : :
251 : : /*
252 : : * base 2, base 8, base 16:
253 : : */
254 [ + + + + ]: 66 : 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
1203 tgl@sss.pgh.pa.us 270 :UBC 0 : diag2(1, "Unterminated literal");
271 : : }
272 : : else /* base 10: */
273 : : while (1) {
1203 tgl@sss.pgh.pa.us 274 [ + + ]:CBC 62 : if (*buf_ptr == '.') {
275 [ - + ]: 7 : if (seendot)
1203 tgl@sss.pgh.pa.us 276 :UBC 0 : break;
277 : : else
1203 tgl@sss.pgh.pa.us 278 :CBC 7 : seendot++;
279 : : }
280 [ - + - - ]: 62 : CHECK_SIZE_TOKEN(3);
281 : 62 : *e_token++ = *buf_ptr++;
282 [ + + + + ]: 62 : if (!isdigit((unsigned char)*buf_ptr) && *buf_ptr != '.') {
283 [ + - + - : 44 : if ((*buf_ptr != 'E' && *buf_ptr != 'e') || seenexp)
- - ]
284 : : break;
285 : : else {
1203 tgl@sss.pgh.pa.us 286 :UBC 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) {
1203 tgl@sss.pgh.pa.us 296 [ - + - - ]:CBC 69 : CHECK_SIZE_TOKEN(2);
297 [ + + + + : 69 : if (!(seensfx & 1) && (*buf_ptr == 'U' || *buf_ptr == 'u')) {
- + ]
298 : 6 : *e_token++ = *buf_ptr++;
299 : 6 : seensfx |= 1;
300 : 6 : continue;
301 : : }
302 [ + + + + ]: 63 : if (!(seensfx & 2) && (strchr("fFlL", *buf_ptr) != NULL)) {
303 [ - + ]: 8 : if (buf_ptr[1] == buf_ptr[0])
1203 tgl@sss.pgh.pa.us 304 :UBC 0 : *e_token++ = *buf_ptr++;
1203 tgl@sss.pgh.pa.us 305 :CBC 8 : *e_token++ = *buf_ptr++;
306 : 8 : seensfx |= 2;
307 : 8 : continue;
308 : : }
309 : 55 : break;
310 : : }
311 : : }
312 : : else
313 [ + + - + ]: 2457 : while (chartype[*buf_ptr & 127] == alphanum || *buf_ptr == BACKSLASH) {
314 : : /* fill_buffer() terminates buffer with newline */
315 [ - + ]: 1703 : if (*buf_ptr == BACKSLASH) {
1203 tgl@sss.pgh.pa.us 316 [ # # ]:UBC 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 : : }
1203 tgl@sss.pgh.pa.us 323 [ - + - - ]:CBC 1703 : CHECK_SIZE_TOKEN(1);
324 : : /* copy it over */
325 : 1703 : *e_token++ = *buf_ptr++;
326 [ - + ]: 1703 : if (buf_ptr >= buf_end)
1203 tgl@sss.pgh.pa.us 327 :UBC 0 : fill_buffer();
328 : : }
1203 tgl@sss.pgh.pa.us 329 :CBC 432 : *e_token = '\0';
330 : :
331 [ + + + + ]: 432 : if (s_token[0] == 'L' && s_token[1] == '\0' &&
332 [ + + + - ]: 2 : (*buf_ptr == '"' || *buf_ptr == '\''))
333 : 2 : return (strpfx);
334 : :
335 [ + + + + ]: 1081 : while (*buf_ptr == ' ' || *buf_ptr == '\t') { /* get rid of blanks */
336 [ + + ]: 221 : if (++buf_ptr >= buf_end)
337 : 16 : fill_buffer();
338 : : }
339 : 430 : state->keyword = 0;
340 [ + + + + ]: 430 : 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 : 6 : state->last_u_d = true;
345 : 6 : return (decl);
346 : : }
347 : : /*
348 : : * Operator after identifier is binary unless last token was 'struct'
349 : : */
350 : 424 : state->last_u_d = (state->last_token == structure);
351 : :
352 : 424 : p = bsearch(s_token,
353 : : specials,
354 : : sizeof(specials) / sizeof(specials[0]),
355 : : sizeof(specials[0]),
356 : : strcmp_type);
357 [ + + ]: 424 : if (p == NULL) { /* not a special keyword... */
358 : : char *u;
359 : :
360 : : /* ... so maybe a type_t or a typedef */
361 [ - + - - ]: 256 : if ((auto_typedefs && ((u = strrchr(s_token, '_')) != NULL) &&
362 [ - - + + : 303 : 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 */
17 nathan@postgresql.or 366 [ + + + + ]:GNC 4 : if (state->last_token != period && state->last_token != unary_op)
367 : 2 : state->last_u_d = true;
1203 tgl@sss.pgh.pa.us 368 :CBC 4 : goto found_typename;
369 : : }
370 : : } else { /* we have a keyword */
371 : 168 : state->keyword = p->rwcode;
372 : 168 : state->last_u_d = true;
373 [ + + + + : 168 : switch (p->rwcode) {
+ + + + ]
374 : 1 : case 7: /* it is a switch */
375 : 1 : return (swstmt);
376 : 2 : case 8: /* a case or default */
377 : 2 : return (casestmt);
378 : :
379 : : case 3: /* a "struct" */
380 : : /* FALLTHROUGH */
381 : : case 4: /* one of the declaration keywords */
382 : 129 : found_typename:
383 [ + + ]: 129 : if (state->p_l_follow) {
384 : : /* inside parens: cast, param list, offsetof or sizeof */
385 : 47 : state->cast_mask |= (1 << state->p_l_follow) & ~state->not_cast_mask;
386 : : }
387 [ + + + + ]: 129 : if (state->last_token == period || state->last_token == unary_op) {
388 : 2 : state->keyword = 0;
389 : 2 : break;
390 : : }
391 [ + + + + ]: 127 : if (p != NULL && p->rwcode == 3)
392 : 19 : return (structure);
393 [ + + ]: 108 : if (state->p_l_follow)
394 : 37 : break;
395 : 71 : return (decl);
396 : :
397 : 12 : case 5: /* if, while, for */
398 : 12 : return (sp_paren);
399 : :
400 : 7 : case 6: /* do, else */
401 : 7 : return (sp_nparen);
402 : :
403 : 10 : case 10: /* storage class specifier */
404 : 10 : return (storage);
405 : :
406 : 6 : case 11: /* typedef */
407 : 6 : return (type_def);
408 : :
409 : 5 : default: /* all others are treated like any other
410 : : * identifier */
411 : 5 : return (ident);
412 : : } /* end of switch */
413 : : } /* end of if (found_it) */
414 [ + + + + : 291 : if (*buf_ptr == '(' && state->tos <= 1 && state->ind_level == 0 &&
+ - ]
415 [ + + + + ]: 34 : state->in_parameter_declaration == 0 && state->block_init == 0) {
416 [ + + ]: 32 : if (is_func_definition(buf_ptr)) {
417 : 28 : strncpy(state->procname, token, sizeof state->procname - 1);
418 [ + + ]: 28 : if (state->in_decl)
419 : 27 : state->in_parameter_declaration = 1;
420 : 28 : return (funcname);
421 : : }
422 : : }
423 : : /*
424 : : * The following hack attempts to guess whether or not the current
425 : : * token is in fact a declaration keyword -- one that has been
426 : : * typedefd
427 : : */
428 [ + + + + ]: 259 : else if (!state->p_l_follow && !state->block_init &&
429 [ + + ]: 100 : !state->in_stmt &&
430 [ + + - + ]: 24 : ((*buf_ptr == '*' && buf_ptr[1] != '=') ||
431 [ + + ]: 21 : isalpha((unsigned char)*buf_ptr)) &&
432 [ + + - + ]: 6 : (state->last_token == semicolon || state->last_token == lbrace ||
1203 tgl@sss.pgh.pa.us 433 [ # # ]:UBC 0 : state->last_token == rbrace)) {
1203 tgl@sss.pgh.pa.us 434 :CBC 6 : state->keyword = 4; /* a type name */
435 : 6 : state->last_u_d = true;
436 : 6 : return decl;
437 : : }
438 [ + + ]: 257 : if (state->last_token == decl) /* if this is a declared variable,
439 : : * then following sign is unary */
440 : 39 : state->last_u_d = true; /* will make "int a -1" work */
441 : 257 : return (ident); /* the ident is not in the list */
442 : : } /* end of processing for alphanum character */
443 : :
444 : : /* Scan a non-alphanumeric token */
445 : :
446 [ - + - - ]: 908 : CHECK_SIZE_TOKEN(3); /* things like "<<=" */
447 : 908 : *e_token++ = *buf_ptr; /* if it is only a one-character token, it is
448 : : * moved here */
449 : 908 : *e_token = '\0';
450 [ + + ]: 908 : if (++buf_ptr >= buf_end)
451 : 301 : fill_buffer();
452 : :
453 : 908 : switch (*token) {
[ + + + +
+ - + + +
+ - + + +
+ + + + ]
454 : 345 : case '\n':
455 : 345 : unary_delim = state->last_u_d;
456 : 345 : state->last_nl = true; /* remember that we just had a newline */
457 : 345 : code = (had_eof ? 0 : newline);
458 : :
459 : : /*
460 : : * if data has been exhausted, the newline is a dummy, and we should
461 : : * return code to stop
462 : : */
463 : 345 : break;
464 : :
465 : 2 : case '\'': /* start of quoted character */
466 : : case '"': /* start of string */
467 : 2 : qchar = *token;
468 : : do { /* copy the string */
469 : : while (1) { /* move one character or [/<char>]<char> */
470 [ - + ]: 7 : if (*buf_ptr == '\n') {
1203 tgl@sss.pgh.pa.us 471 :UBC 0 : diag2(1, "Unterminated literal");
472 : 0 : goto stop_lit;
473 : : }
1203 tgl@sss.pgh.pa.us 474 [ - + - - ]:CBC 7 : CHECK_SIZE_TOKEN(2);
475 : 7 : *e_token = *buf_ptr++;
476 [ - + ]: 7 : if (buf_ptr >= buf_end)
1203 tgl@sss.pgh.pa.us 477 :UBC 0 : fill_buffer();
1203 tgl@sss.pgh.pa.us 478 [ - + ]:CBC 7 : if (*e_token == BACKSLASH) { /* if escape, copy extra char */
1203 tgl@sss.pgh.pa.us 479 [ # # ]:UBC 0 : if (*buf_ptr == '\n') /* check for escaped newline */
480 : 0 : ++line_no;
481 : 0 : *++e_token = *buf_ptr++;
482 : 0 : ++e_token; /* we must increment this again because we
483 : : * copied two chars */
484 [ # # ]: 0 : if (buf_ptr >= buf_end)
485 : 0 : fill_buffer();
486 : : }
487 : : else
1203 tgl@sss.pgh.pa.us 488 :CBC 7 : break; /* we copied one character */
489 : : } /* end of while (1) */
490 [ + + ]: 7 : } while (*e_token++ != qchar);
491 : 2 : stop_lit:
492 : 2 : code = ident;
493 : 2 : break;
494 : :
495 : 78 : case ('('):
496 : : case ('['):
497 : 78 : unary_delim = true;
498 : 78 : code = lparen;
499 : 78 : break;
500 : :
501 : 78 : case (')'):
502 : : case (']'):
503 : 78 : code = rparen;
504 : 78 : break;
505 : :
506 : 11 : case '#':
507 : 11 : unary_delim = state->last_u_d;
508 : 11 : code = preesc;
509 : 11 : break;
510 : :
1203 tgl@sss.pgh.pa.us 511 :UBC 0 : case '?':
512 : 0 : unary_delim = true;
513 : 0 : code = question;
514 : 0 : break;
515 : :
1203 tgl@sss.pgh.pa.us 516 :CBC 5 : case (':'):
517 : 5 : code = colon;
518 : 5 : unary_delim = true;
519 : 5 : break;
520 : :
521 : 75 : case (';'):
522 : 75 : unary_delim = true;
523 : 75 : code = semicolon;
524 : 75 : break;
525 : :
526 : 58 : case ('{'):
527 : 58 : unary_delim = true;
528 : :
529 : : /*
530 : : * if (state->in_or_st) state->block_init = 1;
531 : : */
532 : : /* ? code = state->block_init ? lparen : lbrace; */
533 : 58 : code = lbrace;
534 : 58 : break;
535 : :
536 : 42 : case ('}'):
537 : 42 : unary_delim = true;
538 : : /* ? code = state->block_init ? rparen : rbrace; */
539 : 42 : code = rbrace;
540 : 42 : break;
541 : :
1203 tgl@sss.pgh.pa.us 542 :UBC 0 : case 014: /* a form feed */
543 : 0 : unary_delim = state->last_u_d;
544 : 0 : state->last_nl = true; /* remember this so we can set 'state->col_1'
545 : : * right */
546 : 0 : code = form_feed;
547 : 0 : break;
548 : :
1203 tgl@sss.pgh.pa.us 549 :CBC 56 : case (','):
550 : 56 : unary_delim = true;
551 : 56 : code = comma;
552 : 56 : break;
553 : :
554 : 6 : case '.':
555 : 6 : unary_delim = false;
556 : 6 : code = period;
557 : 6 : break;
558 : :
559 : 6 : case '-':
560 : : case '+': /* check for -, +, --, ++ */
561 [ - + ]: 6 : code = (state->last_u_d ? unary_op : binary_op);
562 : 6 : unary_delim = true;
563 : :
564 [ - + ]: 6 : if (*buf_ptr == token[0]) {
565 : : /* check for doubled character */
1203 tgl@sss.pgh.pa.us 566 :UBC 0 : *e_token++ = *buf_ptr++;
567 : : /* buffer overflow will be checked at end of loop */
568 [ # # # # ]: 0 : if (state->last_token == ident || state->last_token == rparen) {
569 [ # # ]: 0 : code = (state->last_u_d ? unary_op : postop);
570 : : /* check for following ++ or -- */
571 : 0 : unary_delim = false;
572 : : }
573 : : }
1203 tgl@sss.pgh.pa.us 574 [ - + ]:CBC 6 : else if (*buf_ptr == '=')
575 : : /* check for operator += */
1203 tgl@sss.pgh.pa.us 576 :UBC 0 : *e_token++ = *buf_ptr++;
1203 tgl@sss.pgh.pa.us 577 [ + + ]:CBC 6 : else if (*buf_ptr == '>') {
578 : : /* check for operator -> */
579 : 2 : *e_token++ = *buf_ptr++;
580 : 2 : unary_delim = false;
581 : 2 : code = unary_op;
582 : 2 : state->want_blank = false;
583 : : }
584 : 6 : break; /* buffer overflow will be checked at end of
585 : : * switch */
586 : :
587 : 28 : case '=':
588 [ + + ]: 28 : if (state->in_or_st)
589 : 25 : state->block_init = 1;
590 : : #ifdef undef
591 : : if (chartype[*buf_ptr & 127] == opchar) { /* we have two char assignment */
592 : : e_token[-1] = *buf_ptr++;
593 : : if ((e_token[-1] == '<' || e_token[-1] == '>') && e_token[-1] == *buf_ptr)
594 : : *e_token++ = *buf_ptr++;
595 : : *e_token++ = '='; /* Flip =+ to += */
596 : : *e_token = 0;
597 : : }
598 : : #else
599 [ - + ]: 28 : if (*buf_ptr == '=') {/* == */
1203 tgl@sss.pgh.pa.us 600 :UBC 0 : *e_token++ = '='; /* Flip =+ to += */
601 : 0 : buf_ptr++;
602 : 0 : *e_token = 0;
603 : : }
604 : : #endif
1203 tgl@sss.pgh.pa.us 605 :CBC 28 : code = binary_op;
606 : 28 : unary_delim = true;
607 : 28 : break;
608 : : /* can drop thru!!! */
609 : :
610 : 4 : case '>':
611 : : case '<':
612 : : case '!': /* ops like <, <<, <=, !=, etc */
613 [ + - - + : 4 : if (*buf_ptr == '>' || *buf_ptr == '<' || *buf_ptr == '=') {
- - ]
614 : 4 : *e_token++ = *buf_ptr;
615 [ - + ]: 4 : if (++buf_ptr >= buf_end)
1203 tgl@sss.pgh.pa.us 616 :UBC 0 : fill_buffer();
617 : : }
1203 tgl@sss.pgh.pa.us 618 [ - + ]:CBC 4 : if (*buf_ptr == '=')
1203 tgl@sss.pgh.pa.us 619 :UBC 0 : *e_token++ = *buf_ptr++;
1203 tgl@sss.pgh.pa.us 620 [ - + ]:CBC 4 : code = (state->last_u_d ? unary_op : binary_op);
621 : 4 : unary_delim = true;
622 : 4 : break;
623 : :
624 : 46 : case '*':
625 : 46 : unary_delim = true;
626 [ + + ]: 46 : if (!state->last_u_d) {
627 [ - + ]: 6 : if (*buf_ptr == '=')
1203 tgl@sss.pgh.pa.us 628 :UBC 0 : *e_token++ = *buf_ptr++;
1203 tgl@sss.pgh.pa.us 629 :CBC 6 : code = binary_op;
630 : 6 : break;
631 : : }
632 [ + + + + ]: 91 : while (*buf_ptr == '*' || isspace((unsigned char)*buf_ptr)) {
633 [ + + ]: 11 : if (*buf_ptr == '*') {
634 [ - + - - ]: 3 : CHECK_SIZE_TOKEN(1);
635 : 3 : *e_token++ = *buf_ptr;
636 : : }
637 [ + + ]: 11 : if (++buf_ptr >= buf_end)
638 : 2 : fill_buffer();
639 : : }
640 : 40 : code = unary_op;
641 : 40 : break;
642 : :
643 : 68 : default:
644 [ + + + - ]: 68 : if (token[0] == '/' && *buf_ptr == '*') {
645 : : /* it is start of comment */
646 : 67 : *e_token++ = '*';
647 : :
648 [ - + ]: 67 : if (++buf_ptr >= buf_end)
1203 tgl@sss.pgh.pa.us 649 :UBC 0 : fill_buffer();
650 : :
1203 tgl@sss.pgh.pa.us 651 :CBC 67 : code = comment;
652 : 67 : unary_delim = state->last_u_d;
653 : 67 : break;
654 : : }
655 [ - + - + ]: 2 : while (*(e_token - 1) == *buf_ptr || *buf_ptr == '=') {
656 : : /*
657 : : * handle ||, &&, etc, and also things as in int *****i
658 : : */
1203 tgl@sss.pgh.pa.us 659 [ # # # # ]:UBC 0 : CHECK_SIZE_TOKEN(1);
660 : 0 : *e_token++ = *buf_ptr;
661 [ # # ]: 0 : if (++buf_ptr >= buf_end)
662 : 0 : fill_buffer();
663 : : }
1203 tgl@sss.pgh.pa.us 664 [ + - ]:CBC 1 : code = (state->last_u_d ? unary_op : binary_op);
665 : 1 : unary_delim = true;
666 : :
667 : :
668 : : } /* end of switch */
669 [ - + ]: 908 : if (buf_ptr >= buf_end) /* check for input buffer empty */
1203 tgl@sss.pgh.pa.us 670 :UBC 0 : fill_buffer();
1203 tgl@sss.pgh.pa.us 671 :CBC 908 : state->last_u_d = unary_delim;
672 [ - + - - ]: 908 : CHECK_SIZE_TOKEN(1);
673 : 908 : *e_token = '\0'; /* null terminate the token */
674 : 908 : return (code);
675 : : }
676 : :
677 : : void
678 : 19 : alloc_typenames(void)
679 : : {
680 : :
681 : 19 : typenames = (const char **)malloc(sizeof(typenames[0]) *
682 : 19 : (typename_count = 16));
683 [ - + ]: 19 : if (typenames == NULL)
1203 tgl@sss.pgh.pa.us 684 :UBC 0 : err(1, NULL);
1203 tgl@sss.pgh.pa.us 685 :CBC 19 : }
686 : :
687 : : void
688 : 3 : add_typename(const char *key)
689 : : {
690 : : int comparison;
691 : : const char *copy;
692 : :
693 [ - + ]: 3 : if (typename_top + 1 >= typename_count) {
1203 tgl@sss.pgh.pa.us 694 :UBC 0 : typenames = realloc((void *)typenames,
695 : 0 : sizeof(typenames[0]) * (typename_count *= 2));
696 [ # # ]: 0 : if (typenames == NULL)
697 : 0 : err(1, NULL);
698 : : }
1203 tgl@sss.pgh.pa.us 699 [ + + ]:CBC 3 : if (typename_top == -1)
700 : 2 : typenames[++typename_top] = copy = strdup(key);
701 [ - + ]: 1 : else if ((comparison = strcmp(key, typenames[typename_top])) >= 0) {
702 : : /* take advantage of sorted input */
1203 tgl@sss.pgh.pa.us 703 [ # # ]:UBC 0 : if (comparison == 0) /* remove duplicates */
704 : 0 : return;
705 : 0 : typenames[++typename_top] = copy = strdup(key);
706 : : }
707 : : else {
708 : : int p;
709 : :
1203 tgl@sss.pgh.pa.us 710 [ - + ]:CBC 1 : for (p = 0; (comparison = strcmp(key, typenames[p])) > 0; p++)
711 : : /* find place for the new key */;
712 [ - + ]: 1 : if (comparison == 0) /* remove duplicates */
1203 tgl@sss.pgh.pa.us 713 :UBC 0 : return;
1203 tgl@sss.pgh.pa.us 714 :CBC 1 : memmove(&typenames[p + 1], &typenames[p],
715 : 1 : sizeof(typenames[0]) * (++typename_top - p));
716 : 1 : typenames[p] = copy = strdup(key);
717 : : }
718 : :
719 [ - + ]: 3 : if (copy == NULL)
1203 tgl@sss.pgh.pa.us 720 :UBC 0 : err(1, NULL);
721 : : }
|