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
427 tgl@sss.pgh.pa.us 142 :CBC 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)
427 tgl@sss.pgh.pa.us 178 :UBC 0 : break;
179 : : }
180 : : /* Handle comments. */
427 tgl@sss.pgh.pa.us 181 [ - + ]:CBC 668 : if (in_comment) {
427 tgl@sss.pgh.pa.us 182 [ # # # # ]:UBC 0 : if (lastc == '*' && c == '/')
183 : 0 : in_comment = false;
427 tgl@sss.pgh.pa.us 184 [ - + - - :CBC 668 : } else if (lastc == '/' && c == '*' && !in_slash_comment)
- - ]
427 tgl@sss.pgh.pa.us 185 :UBC 0 : in_comment = true;
427 tgl@sss.pgh.pa.us 186 [ - + ]:CBC 668 : else if (in_slash_comment) {
427 tgl@sss.pgh.pa.us 187 [ # # ]:UBC 0 : if (c == '\n')
188 : 0 : in_slash_comment = false;
427 tgl@sss.pgh.pa.us 189 [ - + - - ]:CBC 668 : } else if (lastc == '/' && c == '/')
427 tgl@sss.pgh.pa.us 190 :UBC 0 : in_slash_comment = true;
191 : : /* Count nested parens properly. */
427 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)
427 tgl@sss.pgh.pa.us 201 :UBC 0 : return false;
427 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". */
427 tgl@sss.pgh.pa.us 212 :UBC 0 : return false;
213 : : }
214 : :
215 : : int
427 tgl@sss.pgh.pa.us 216 :CBC 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
427 tgl@sss.pgh.pa.us 270 :UBC 0 : diag2(1, "Unterminated literal");
271 : : }
272 : : else /* base 10: */
273 : : while (1) {
427 tgl@sss.pgh.pa.us 274 [ + + ]:CBC 60 : if (*buf_ptr == '.') {
275 [ - + ]: 7 : if (seendot)
427 tgl@sss.pgh.pa.us 276 :UBC 0 : break;
277 : : else
427 tgl@sss.pgh.pa.us 278 :CBC 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 {
427 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) {
427 tgl@sss.pgh.pa.us 296 [ - + - - ]:CBC 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])
427 tgl@sss.pgh.pa.us 304 :UBC 0 : *e_token++ = *buf_ptr++;
427 tgl@sss.pgh.pa.us 305 :CBC 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) {
427 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 : : }
427 tgl@sss.pgh.pa.us 323 [ - + - - ]:CBC 1685 : CHECK_SIZE_TOKEN(1);
324 : : /* copy it over */
325 : 1685 : *e_token++ = *buf_ptr++;
326 [ - + ]: 1685 : if (buf_ptr >= buf_end)
427 tgl@sss.pgh.pa.us 327 :UBC 0 : fill_buffer();
328 : : }
427 tgl@sss.pgh.pa.us 329 :CBC 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 ||
427 tgl@sss.pgh.pa.us 432 [ # # ]:UBC 0 : state->last_token == rbrace)) {
427 tgl@sss.pgh.pa.us 433 :CBC 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') {
427 tgl@sss.pgh.pa.us 470 :UBC 0 : diag2(1, "Unterminated literal");
471 : 0 : goto stop_lit;
472 : : }
427 tgl@sss.pgh.pa.us 473 [ - + - - ]:CBC 7 : CHECK_SIZE_TOKEN(2);
474 : 7 : *e_token = *buf_ptr++;
475 [ - + ]: 7 : if (buf_ptr >= buf_end)
427 tgl@sss.pgh.pa.us 476 :UBC 0 : fill_buffer();
427 tgl@sss.pgh.pa.us 477 [ - + ]:CBC 7 : if (*e_token == BACKSLASH) { /* if escape, copy extra char */
427 tgl@sss.pgh.pa.us 478 [ # # ]:UBC 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
427 tgl@sss.pgh.pa.us 487 :CBC 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 : :
427 tgl@sss.pgh.pa.us 510 :UBC 0 : case '?':
511 : 0 : unary_delim = true;
512 : 0 : code = question;
513 : 0 : break;
514 : :
427 tgl@sss.pgh.pa.us 515 :CBC 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 : :
427 tgl@sss.pgh.pa.us 541 :UBC 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 : :
427 tgl@sss.pgh.pa.us 548 :CBC 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 */
427 tgl@sss.pgh.pa.us 565 :UBC 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 : : }
427 tgl@sss.pgh.pa.us 573 [ - + ]:CBC 6 : else if (*buf_ptr == '=')
574 : : /* check for operator += */
427 tgl@sss.pgh.pa.us 575 :UBC 0 : *e_token++ = *buf_ptr++;
427 tgl@sss.pgh.pa.us 576 [ + + ]:CBC 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 == '=') {/* == */
427 tgl@sss.pgh.pa.us 599 :UBC 0 : *e_token++ = '='; /* Flip =+ to += */
600 : 0 : buf_ptr++;
601 : 0 : *e_token = 0;
602 : : }
603 : : #endif
427 tgl@sss.pgh.pa.us 604 :CBC 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)
427 tgl@sss.pgh.pa.us 615 :UBC 0 : fill_buffer();
616 : : }
427 tgl@sss.pgh.pa.us 617 [ - + ]:CBC 4 : if (*buf_ptr == '=')
427 tgl@sss.pgh.pa.us 618 :UBC 0 : *e_token++ = *buf_ptr++;
427 tgl@sss.pgh.pa.us 619 [ - + ]:CBC 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 == '=')
427 tgl@sss.pgh.pa.us 627 :UBC 0 : *e_token++ = *buf_ptr++;
427 tgl@sss.pgh.pa.us 628 :CBC 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)
427 tgl@sss.pgh.pa.us 648 :UBC 0 : fill_buffer();
649 : :
427 tgl@sss.pgh.pa.us 650 :CBC 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 : : */
427 tgl@sss.pgh.pa.us 658 [ # # # # ]:UBC 0 : CHECK_SIZE_TOKEN(1);
659 : 0 : *e_token++ = *buf_ptr;
660 [ # # ]: 0 : if (++buf_ptr >= buf_end)
661 : 0 : fill_buffer();
662 : : }
427 tgl@sss.pgh.pa.us 663 [ + - ]:CBC 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 */
427 tgl@sss.pgh.pa.us 669 :UBC 0 : fill_buffer();
427 tgl@sss.pgh.pa.us 670 :CBC 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)
427 tgl@sss.pgh.pa.us 683 :UBC 0 : err(1, NULL);
427 tgl@sss.pgh.pa.us 684 :CBC 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) {
427 tgl@sss.pgh.pa.us 693 :UBC 0 : typenames = realloc((void *)typenames,
694 : 0 : sizeof(typenames[0]) * (typename_count *= 2));
695 [ # # ]: 0 : if (typenames == NULL)
696 : 0 : err(1, NULL);
697 : : }
427 tgl@sss.pgh.pa.us 698 [ + + ]:CBC 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 */
427 tgl@sss.pgh.pa.us 702 [ # # ]:UBC 0 : if (comparison == 0) /* remove duplicates */
703 : 0 : return;
704 : 0 : typenames[++typename_top] = copy = strdup(key);
705 : : }
706 : : else {
707 : : int p;
708 : :
427 tgl@sss.pgh.pa.us 709 [ - + ]:CBC 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 */
427 tgl@sss.pgh.pa.us 712 :UBC 0 : return;
427 tgl@sss.pgh.pa.us 713 :CBC 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)
427 tgl@sss.pgh.pa.us 719 :UBC 0 : err(1, NULL);
720 : : }
|