File: | src/usr.bin/ctags/C.c |
Warning: | line 422, column 17 The left operand of '!=' is a garbage value |
Press '?' to see keyboard shortcuts
Keyboard shortcuts:
1 | /* $OpenBSD: C.c,v 1.15 2014/12/08 03:58:56 jsg Exp $ */ | |||
2 | /* $NetBSD: C.c,v 1.3 1995/03/26 20:14:02 glass Exp $ */ | |||
3 | ||||
4 | /* | |||
5 | * Copyright (c) 1987, 1993, 1994 | |||
6 | * The Regents of the University of California. All rights reserved. | |||
7 | * | |||
8 | * Redistribution and use in source and binary forms, with or without | |||
9 | * modification, are permitted provided that the following conditions | |||
10 | * are met: | |||
11 | * 1. Redistributions of source code must retain the above copyright | |||
12 | * notice, this list of conditions and the following disclaimer. | |||
13 | * 2. Redistributions in binary form must reproduce the above copyright | |||
14 | * notice, this list of conditions and the following disclaimer in the | |||
15 | * documentation and/or other materials provided with the distribution. | |||
16 | * 3. Neither the name of the University nor the names of its contributors | |||
17 | * may be used to endorse or promote products derived from this software | |||
18 | * without specific prior written permission. | |||
19 | * | |||
20 | * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND | |||
21 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | |||
22 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | |||
23 | * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE | |||
24 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL | |||
25 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS | |||
26 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) | |||
27 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT | |||
28 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY | |||
29 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF | |||
30 | * SUCH DAMAGE. | |||
31 | */ | |||
32 | ||||
33 | #include <limits.h> | |||
34 | #include <stdio.h> | |||
35 | #include <string.h> | |||
36 | ||||
37 | #include "ctags.h" | |||
38 | ||||
39 | static int func_entry(void); | |||
40 | static void hash_entry(void); | |||
41 | static void skip_string(int); | |||
42 | static int str_entry(int); | |||
43 | ||||
44 | /* | |||
45 | * c_entries -- | |||
46 | * read .c and .h files and call appropriate routines | |||
47 | */ | |||
48 | void | |||
49 | c_entries(void) | |||
50 | { | |||
51 | int c; /* current character */ | |||
52 | int level; /* brace level */ | |||
53 | int token; /* if reading a token */ | |||
54 | int t_def; /* if reading a typedef */ | |||
55 | int t_level; /* typedef's brace level */ | |||
56 | char *sp; /* buffer pointer */ | |||
57 | char tok[MAXTOKEN250]; /* token buffer */ | |||
58 | ||||
59 | lineftell = ftell(inf); | |||
60 | sp = tok; token = t_def = NO0; t_level = -1; level = 0; lineno = 1; | |||
61 | while (GETC(!=, EOF)((c = (!__isthreaded ? (--(inf)->_r < 0 ? __srget(inf) : (int)(*(inf)->_p++)) : (getc)(inf))) != (int)(-1))) { | |||
| ||||
62 | switch (c) { | |||
63 | /* | |||
64 | * Here's where it DOESN'T handle: { | |||
65 | * foo(a) | |||
66 | * { | |||
67 | * #ifdef notdef | |||
68 | * } | |||
69 | * #endif | |||
70 | * if (a) | |||
71 | * puts("hello, world"); | |||
72 | * } | |||
73 | */ | |||
74 | case '{': | |||
75 | ++level; | |||
76 | goto endtok; | |||
77 | case '}': | |||
78 | /* | |||
79 | * if level goes below zero, try and fix | |||
80 | * it, even though we've already messed up | |||
81 | */ | |||
82 | if (--level < 0) | |||
83 | level = 0; | |||
84 | goto endtok; | |||
85 | ||||
86 | case '\n': | |||
87 | SETLINE{++lineno;lineftell = ftell(inf);}; | |||
88 | /* | |||
89 | * the above 3 cases are similar in that they | |||
90 | * are special characters that also end tokens. | |||
91 | */ | |||
92 | endtok: if (sp > tok) { | |||
93 | *sp = EOS'\0'; | |||
94 | token = YES1; | |||
95 | sp = tok; | |||
96 | } | |||
97 | else | |||
98 | token = NO0; | |||
99 | continue; | |||
100 | ||||
101 | /* | |||
102 | * We ignore quoted strings and character constants | |||
103 | * completely. | |||
104 | */ | |||
105 | case '"': | |||
106 | case '\'': | |||
107 | (void)skip_string(c); | |||
108 | break; | |||
109 | ||||
110 | /* | |||
111 | * comments can be fun; note the state is unchanged after | |||
112 | * return, in case we found: | |||
113 | * "foo() XX comment XX { int bar; }" | |||
114 | */ | |||
115 | case '/': | |||
116 | if (GETC(==, '*')((c = (!__isthreaded ? (--(inf)->_r < 0 ? __srget(inf) : (int)(*(inf)->_p++)) : (getc)(inf))) == (int)'*')) { | |||
117 | skip_comment(c); | |||
118 | continue; | |||
119 | } else if (c == '/') { | |||
120 | skip_comment(c); | |||
121 | continue; | |||
122 | } | |||
123 | (void)ungetc(c, inf); | |||
124 | c = '/'; | |||
125 | goto storec; | |||
126 | ||||
127 | /* hash marks flag #define's. */ | |||
128 | case '#': | |||
129 | if (sp
| |||
130 | hash_entry(); | |||
131 | break; | |||
132 | } | |||
133 | goto storec; | |||
134 | ||||
135 | /* | |||
136 | * if we have a current token, parenthesis on | |||
137 | * level zero indicates a function. | |||
138 | */ | |||
139 | case '(': | |||
140 | do { | |||
141 | if (GETC(==, EOF)((c = (!__isthreaded ? (--(inf)->_r < 0 ? __srget(inf) : (int)(*(inf)->_p++)) : (getc)(inf))) == (int)(-1))) | |||
142 | return; | |||
143 | } while (iswhite(c)(_wht[(unsigned)c])); | |||
144 | if (c == '*') | |||
145 | break; | |||
146 | else | |||
147 | ungetc(c, inf); | |||
148 | if (!level && token) { | |||
149 | int curline; | |||
150 | ||||
151 | if (sp != tok) | |||
152 | *sp = EOS'\0'; | |||
153 | /* | |||
154 | * grab the line immediately, we may | |||
155 | * already be wrong, for example, | |||
156 | * foo\n | |||
157 | * (arg1, | |||
158 | */ | |||
159 | get_line(); | |||
160 | curline = lineno; | |||
161 | if (func_entry()) { | |||
162 | ++level; | |||
163 | pfnote(tok, curline); | |||
164 | } | |||
165 | break; | |||
166 | } | |||
167 | goto storec; | |||
168 | ||||
169 | /* | |||
170 | * semi-colons indicate the end of a typedef; if we find a | |||
171 | * typedef we search for the next semi-colon of the same | |||
172 | * level as the typedef. Ignoring "structs", they are | |||
173 | * tricky, since you can find: | |||
174 | * | |||
175 | * "typedef int time_t;" | |||
176 | * "typedef unsigned int u_int;" | |||
177 | * "typedef unsigned int u_int [10];" | |||
178 | * | |||
179 | * If looking at a typedef, we save a copy of the last token | |||
180 | * found. Then, when we find the ';' we take the current | |||
181 | * token if it starts with a valid token name, else we take | |||
182 | * the one we saved. There's probably some reasonable | |||
183 | * alternative to this... | |||
184 | */ | |||
185 | case ';': | |||
186 | if (t_def && level == t_level) { | |||
187 | t_def = NO0; | |||
188 | get_line(); | |||
189 | if (sp != tok) | |||
190 | *sp = EOS'\0'; | |||
191 | pfnote(tok, lineno); | |||
192 | break; | |||
193 | } | |||
194 | goto storec; | |||
195 | ||||
196 | /* | |||
197 | * store characters until one that can't be part of a token | |||
198 | * comes along; check the current token against certain | |||
199 | * reserved words. | |||
200 | */ | |||
201 | default: | |||
202 | /* | |||
203 | * to treat following function. | |||
204 | * func (arg) { | |||
205 | * .... | |||
206 | * } | |||
207 | */ | |||
208 | if (c == ' ' || c == '\t') { | |||
209 | int save = c; | |||
210 | while (GETC(!=, EOF)((c = (!__isthreaded ? (--(inf)->_r < 0 ? __srget(inf) : (int)(*(inf)->_p++)) : (getc)(inf))) != (int)(-1)) && (c == ' ' || c == '\t')) | |||
211 | ; | |||
212 | if (c == EOF(-1)) | |||
213 | return; | |||
214 | (void)ungetc(c, inf); | |||
215 | c = save; | |||
216 | } | |||
217 | storec: if (!intoken(c)(_itk[(unsigned)c])) { | |||
218 | if (sp == tok) | |||
219 | break; | |||
220 | *sp = EOS'\0'; | |||
221 | /* no typedefs inside typedefs */ | |||
222 | if (!t_def && | |||
223 | !memcmp(tok, "typedef",8)) { | |||
224 | t_def = YES1; | |||
225 | t_level = level; | |||
226 | break; | |||
227 | } | |||
228 | /* catch "typedef struct" */ | |||
229 | if ((!t_def || t_level < level) | |||
230 | && (!memcmp(tok, "struct", 7) | |||
231 | || !memcmp(tok, "union", 6) | |||
232 | || !memcmp(tok, "enum", 5))) { | |||
233 | /* | |||
234 | * get line immediately; | |||
235 | * may change before '{' | |||
236 | */ | |||
237 | get_line(); | |||
238 | if (str_entry(c)) | |||
239 | ++level; | |||
240 | break; | |||
241 | /* } */ | |||
242 | } | |||
243 | sp = tok; | |||
244 | } | |||
245 | else if (sp != tok || begtoken(c)(_btk[(unsigned)c])) { | |||
246 | /* hell... truncate it */ | |||
247 | if (sp == tok + sizeof tok - 1) | |||
248 | *sp = EOS'\0'; | |||
249 | else | |||
250 | *sp++ = c; | |||
251 | token = YES1; | |||
252 | } | |||
253 | continue; | |||
254 | } | |||
255 | ||||
256 | sp = tok; | |||
257 | token = NO0; | |||
258 | } | |||
259 | } | |||
260 | ||||
261 | /* | |||
262 | * func_entry -- | |||
263 | * handle a function reference | |||
264 | */ | |||
265 | static int | |||
266 | func_entry(void) | |||
267 | { | |||
268 | int c; /* current character */ | |||
269 | int level = 0; /* for matching '()' */ | |||
270 | static char attribute[] = "__attribute__"; | |||
271 | char maybe_attribute[sizeof attribute + 1]; | |||
272 | char *anext; | |||
273 | ||||
274 | /* | |||
275 | * Find the end of the assumed function declaration. | |||
276 | * Note that ANSI C functions can have type definitions so keep | |||
277 | * track of the parentheses nesting level. | |||
278 | */ | |||
279 | while (GETC(!=, EOF)((c = (!__isthreaded ? (--(inf)->_r < 0 ? __srget(inf) : (int)(*(inf)->_p++)) : (getc)(inf))) != (int)(-1))) { | |||
280 | switch (c) { | |||
281 | case '\'': | |||
282 | case '"': | |||
283 | /* skip strings and character constants */ | |||
284 | skip_string(c); | |||
285 | break; | |||
286 | case '/': | |||
287 | /* skip comments */ | |||
288 | if (GETC(==, '*')((c = (!__isthreaded ? (--(inf)->_r < 0 ? __srget(inf) : (int)(*(inf)->_p++)) : (getc)(inf))) == (int)'*')) | |||
289 | skip_comment(c); | |||
290 | else if (c == '/') | |||
291 | skip_comment(c); | |||
292 | break; | |||
293 | case '(': | |||
294 | level++; | |||
295 | break; | |||
296 | case ')': | |||
297 | if (level == 0) | |||
298 | goto fnd; | |||
299 | level--; | |||
300 | break; | |||
301 | case '\n': | |||
302 | SETLINE{++lineno;lineftell = ftell(inf);}; | |||
303 | } | |||
304 | } | |||
305 | return (NO0); | |||
306 | fnd: | |||
307 | /* | |||
308 | * we assume that the character after a function's right paren | |||
309 | * is a token character if it's a function and a non-token | |||
310 | * character if it's a declaration. Comments don't count... | |||
311 | */ | |||
312 | for (anext = maybe_attribute;;) { | |||
313 | while (GETC(!=, EOF)((c = (!__isthreaded ? (--(inf)->_r < 0 ? __srget(inf) : (int)(*(inf)->_p++)) : (getc)(inf))) != (int)(-1)) && iswhite(c)(_wht[(unsigned)c])) | |||
314 | if (c == '\n') | |||
315 | SETLINE{++lineno;lineftell = ftell(inf);}; | |||
316 | if (c == EOF(-1)) | |||
317 | return NO0; | |||
318 | /* | |||
319 | * Recognize the GNU __attribute__ extension, which would | |||
320 | * otherwise make the heuristic test DTWT | |||
321 | */ | |||
322 | if (anext == maybe_attribute) { | |||
323 | if (intoken(c)(_itk[(unsigned)c])) { | |||
324 | *anext++ = c; | |||
325 | continue; | |||
326 | } | |||
327 | } else { | |||
328 | if (intoken(c)(_itk[(unsigned)c])) { | |||
329 | if (anext - maybe_attribute < (int)(sizeof attribute - 1)) | |||
330 | *anext++ = c; | |||
331 | else | |||
332 | break; | |||
333 | continue; | |||
334 | } else { | |||
335 | *anext++ = '\0'; | |||
336 | if (strcmp(maybe_attribute, attribute) == 0) { | |||
337 | (void)ungetc(c, inf); | |||
338 | return NO0; | |||
339 | } | |||
340 | break; | |||
341 | } | |||
342 | } | |||
343 | if (intoken(c)(_itk[(unsigned)c]) || c == '{') | |||
344 | break; | |||
345 | if (c == '/' && GETC(==, '*')((c = (!__isthreaded ? (--(inf)->_r < 0 ? __srget(inf) : (int)(*(inf)->_p++)) : (getc)(inf))) == (int)'*')) | |||
346 | skip_comment(c); | |||
347 | else if (c == '/') | |||
348 | skip_comment(c); | |||
349 | else { /* don't ever "read" '/' */ | |||
350 | (void)ungetc(c, inf); | |||
351 | return (NO0); | |||
352 | } | |||
353 | } | |||
354 | if (c != '{') | |||
355 | (void)skip_key('{'); | |||
356 | return (YES1); | |||
357 | } | |||
358 | ||||
359 | /* | |||
360 | * hash_entry -- | |||
361 | * handle a line starting with a '#' | |||
362 | */ | |||
363 | static void | |||
364 | hash_entry(void) | |||
365 | { | |||
366 | int c; /* character read */ | |||
367 | int curline; /* line started on */ | |||
368 | char *sp; /* buffer pointer */ | |||
369 | char tok[MAXTOKEN250]; /* storage buffer */ | |||
370 | ||||
371 | /* | |||
372 | * to treat following macro. | |||
373 | * # macro(arg) .... | |||
374 | */ | |||
375 | while (GETC(!=, EOF)((c = (!__isthreaded ? (--(inf)->_r < 0 ? __srget(inf) : (int)(*(inf)->_p++)) : (getc)(inf))) != (int)(-1)) && (c == ' ' || c == '\t')) | |||
376 | ; | |||
377 | (void)ungetc(c, inf); | |||
378 | ||||
379 | curline = lineno; | |||
380 | for (sp = tok;;) { /* get next token */ | |||
381 | if (GETC(==, EOF)((c = (!__isthreaded ? (--(inf)->_r < 0 ? __srget(inf) : (int)(*(inf)->_p++)) : (getc)(inf))) == (int)(-1))) | |||
382 | return; | |||
383 | if (iswhite(c)(_wht[(unsigned)c])) | |||
384 | break; | |||
385 | /* hell... truncate it */ | |||
386 | if (sp == tok + sizeof tok - 1) | |||
387 | *sp = EOS'\0'; | |||
388 | else | |||
389 | *sp++ = c; | |||
390 | } | |||
391 | *sp = EOS'\0'; | |||
392 | if (memcmp(tok, "define", 6)) /* only interested in #define's */ | |||
393 | goto skip; | |||
394 | for (;;) { /* this doesn't handle "#define \n" */ | |||
395 | if (GETC(==, EOF)((c = (!__isthreaded ? (--(inf)->_r < 0 ? __srget(inf) : (int)(*(inf)->_p++)) : (getc)(inf))) == (int)(-1))) | |||
396 | return; | |||
397 | if (!iswhite(c)(_wht[(unsigned)c])) | |||
398 | break; | |||
399 | } | |||
400 | for (sp = tok;;) { /* get next token */ | |||
401 | /* hell... truncate it */ | |||
402 | if (sp == tok + sizeof tok - 1) | |||
403 | *sp = EOS'\0'; | |||
404 | else | |||
405 | *sp++ = c; | |||
406 | if (GETC(==, EOF)((c = (!__isthreaded ? (--(inf)->_r < 0 ? __srget(inf) : (int)(*(inf)->_p++)) : (getc)(inf))) == (int)(-1))) | |||
407 | return; | |||
408 | /* | |||
409 | * this is where it DOESN'T handle | |||
410 | * "#define \n" | |||
411 | */ | |||
412 | if (!intoken(c)(_itk[(unsigned)c])) | |||
413 | break; | |||
414 | } | |||
415 | *sp = EOS'\0'; | |||
416 | if (dflag || c == '(') { /* only want macros */ | |||
417 | get_line(); | |||
418 | pfnote(tok, curline); | |||
419 | } | |||
420 | skip: if (c == '\n') { /* get rid of rest of define */ | |||
421 | SETLINE{++lineno;lineftell = ftell(inf);} | |||
422 | if (*(sp - 1) != '\\') | |||
| ||||
423 | return; | |||
424 | } | |||
425 | (void)skip_key('\n'); | |||
426 | } | |||
427 | ||||
428 | /* | |||
429 | * str_entry -- | |||
430 | * handle a struct, union or enum entry | |||
431 | */ | |||
432 | static int | |||
433 | str_entry(int c) | |||
434 | { | |||
435 | int curline; /* line started on */ | |||
436 | char *sp; /* buffer pointer */ | |||
437 | char tok[LINE_MAX2048]; /* storage buffer */ | |||
438 | ||||
439 | curline = lineno; | |||
440 | while (iswhite(c)(_wht[(unsigned)c])) | |||
441 | if (GETC(==, EOF)((c = (!__isthreaded ? (--(inf)->_r < 0 ? __srget(inf) : (int)(*(inf)->_p++)) : (getc)(inf))) == (int)(-1))) | |||
442 | return (NO0); | |||
443 | if (c == '{') /* it was "struct {" */ | |||
444 | return (YES1); | |||
445 | for (sp = tok;;) { /* get next token */ | |||
446 | /* hell... truncate it */ | |||
447 | if (sp == tok + sizeof tok - 1) | |||
448 | *sp = EOS'\0'; | |||
449 | else | |||
450 | *sp++ = c; | |||
451 | if (GETC(==, EOF)((c = (!__isthreaded ? (--(inf)->_r < 0 ? __srget(inf) : (int)(*(inf)->_p++)) : (getc)(inf))) == (int)(-1))) | |||
452 | return (NO0); | |||
453 | if (!intoken(c)(_itk[(unsigned)c])) | |||
454 | break; | |||
455 | } | |||
456 | switch (c) { | |||
457 | case '{': /* it was "struct foo{" */ | |||
458 | --sp; | |||
459 | break; | |||
460 | case '\n': /* it was "struct foo\n" */ | |||
461 | SETLINE{++lineno;lineftell = ftell(inf);}; | |||
462 | /*FALLTHROUGH*/ | |||
463 | default: /* probably "struct foo " */ | |||
464 | while (GETC(!=, EOF)((c = (!__isthreaded ? (--(inf)->_r < 0 ? __srget(inf) : (int)(*(inf)->_p++)) : (getc)(inf))) != (int)(-1))) | |||
465 | if (!iswhite(c)(_wht[(unsigned)c])) | |||
466 | break; | |||
467 | if (c != '{') { | |||
468 | (void)ungetc(c, inf); | |||
469 | return (NO0); | |||
470 | } | |||
471 | } | |||
472 | *sp = EOS'\0'; | |||
473 | pfnote(tok, curline); | |||
474 | return (YES1); | |||
475 | } | |||
476 | ||||
477 | /* | |||
478 | * skip_comment -- | |||
479 | * skip over comment | |||
480 | */ | |||
481 | void | |||
482 | skip_comment(int commenttype) | |||
483 | { | |||
484 | int c; /* character read */ | |||
485 | int star; /* '*' flag */ | |||
486 | ||||
487 | for (star = 0; GETC(!=, EOF)((c = (!__isthreaded ? (--(inf)->_r < 0 ? __srget(inf) : (int)(*(inf)->_p++)) : (getc)(inf))) != (int)(-1));) | |||
488 | switch(c) { | |||
489 | /* comments don't nest, nor can they be escaped. */ | |||
490 | case '*': | |||
491 | star = YES1; | |||
492 | break; | |||
493 | case '/': | |||
494 | if (commenttype == '*' && star) | |||
495 | return; | |||
496 | break; | |||
497 | case '\n': | |||
498 | if (commenttype == '/') { | |||
499 | /* We don't really parse C, so sometimes it | |||
500 | * is necessary to see the newline | |||
501 | */ | |||
502 | ungetc(c, inf); | |||
503 | return; | |||
504 | } | |||
505 | SETLINE{++lineno;lineftell = ftell(inf);}; | |||
506 | /*FALLTHROUGH*/ | |||
507 | default: | |||
508 | star = NO0; | |||
509 | break; | |||
510 | } | |||
511 | } | |||
512 | ||||
513 | /* | |||
514 | * skip_string -- | |||
515 | * skip to the end of a string or character constant. | |||
516 | */ | |||
517 | static void | |||
518 | skip_string(int key) | |||
519 | { | |||
520 | int c, | |||
521 | skip; | |||
522 | ||||
523 | for (skip = NO0; GETC(!=, EOF)((c = (!__isthreaded ? (--(inf)->_r < 0 ? __srget(inf) : (int)(*(inf)->_p++)) : (getc)(inf))) != (int)(-1)); ) | |||
524 | switch (c) { | |||
525 | case '\\': /* a backslash escapes anything */ | |||
526 | skip = !skip; /* we toggle in case it's "\\" */ | |||
527 | break; | |||
528 | case '\n': | |||
529 | SETLINE{++lineno;lineftell = ftell(inf);}; | |||
530 | /*FALLTHROUGH*/ | |||
531 | default: | |||
532 | if (c == key && !skip) | |||
533 | return; | |||
534 | skip = NO0; | |||
535 | } | |||
536 | } | |||
537 | ||||
538 | /* | |||
539 | * skip_key -- | |||
540 | * skip to next char "key" | |||
541 | */ | |||
542 | int | |||
543 | skip_key(int key) | |||
544 | { | |||
545 | int c, | |||
546 | skip, | |||
547 | retval; | |||
548 | ||||
549 | for (skip = retval = NO0; GETC(!=, EOF)((c = (!__isthreaded ? (--(inf)->_r < 0 ? __srget(inf) : (int)(*(inf)->_p++)) : (getc)(inf))) != (int)(-1));) | |||
550 | switch(c) { | |||
551 | case '\\': /* a backslash escapes anything */ | |||
552 | skip = !skip; /* we toggle in case it's "\\" */ | |||
553 | break; | |||
554 | case ';': /* special case for yacc; if one */ | |||
555 | case '|': /* of these chars occurs, we may */ | |||
556 | retval = YES1; /* have moved out of the rule */ | |||
557 | break; /* not used by C */ | |||
558 | case '\'': | |||
559 | case '"': | |||
560 | /* skip strings and character constants */ | |||
561 | skip_string(c); | |||
562 | break; | |||
563 | case '/': | |||
564 | /* skip comments */ | |||
565 | if (GETC(==, '*')((c = (!__isthreaded ? (--(inf)->_r < 0 ? __srget(inf) : (int)(*(inf)->_p++)) : (getc)(inf))) == (int)'*')) { | |||
566 | skip_comment(c); | |||
567 | break; | |||
568 | } else if (c == '/') { | |||
569 | skip_comment(c); | |||
570 | break; | |||
571 | } | |||
572 | (void)ungetc(c, inf); | |||
573 | c = '/'; | |||
574 | goto norm; | |||
575 | case '\n': | |||
576 | SETLINE{++lineno;lineftell = ftell(inf);}; | |||
577 | /*FALLTHROUGH*/ | |||
578 | default: | |||
579 | norm: | |||
580 | if (c == key && !skip) | |||
581 | return (retval); | |||
582 | skip = NO0; | |||
583 | } | |||
584 | return (retval); | |||
585 | } |