source: rtems/doc/tools/src2html1.4a/Ctags/C.c @ bf09257a

4.104.114.84.95
Last change on this file since bf09257a was 52461c5, checked in by Joel Sherrill <joel.sherrill@…>, on 04/14/98 at 16:03:45

New files

  • Property mode set to 100644
File size: 10.0 KB
Line 
1/*
2 * Copyright (c) 1987 The Regents of the University of California.
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 *    notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 *    notice, this list of conditions and the following disclaimer in the
12 *    documentation and/or other materials provided with the distribution.
13 * 3. All advertising materials mentioning features or use of this software
14 *    must display the following acknowledgement:
15 *      This product includes software developed by the University of
16 *      California, Berkeley and its contributors.
17 * 4. Neither the name of the University nor the names of its contributors
18 *    may be used to endorse or promote products derived from this software
19 *    without specific prior written permission.
20 *
21 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24 * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
25 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31 * SUCH DAMAGE.
32 */
33
34#ifndef lint
35static char sccsid[] = "@(#)C.c 5.5 (Berkeley) 2/26/91";
36#endif /* not lint */
37
38#include <stdio.h>
39#include <string.h>
40#include "ctags.h"
41
42static int func_entry(), str_entry();
43static void hash_entry();
44
45/*
46 * c_entries --
47 *      read .c and .h files and call appropriate routines
48 */
49c_entries()
50{
51        extern int      tflag;          /* -t: create tags for typedefs */
52        register int    c,              /* current character */
53                        level;          /* brace level */
54        register char   *sp;            /* buffer pointer */
55        int     token,                  /* if reading a token */
56                t_def,                  /* if reading a typedef */
57                t_level;                /* typedef's brace level */
58        char    tok[MAXTOKEN];          /* token buffer */
59        int     st;                     /* Symbol type */
60        int     rparen;                 /* State of last rparen */
61
62        lineftell = ftell(inf);
63        sp = tok; token = t_def = NO; t_level = -1; level = 0; lineno = 1;
64        rparen=0;
65        while (GETC(!=,EOF)) {
66        rparen--;
67        switch ((char)c) {
68                /*
69                 * Here's where it DOESN'T handle:
70                 *      foo(a)
71                 *      {
72                 *      #ifdef notdef
73                 *              }
74                 *      #endif
75                 *              if (a)
76                 *                      puts("hello, world");
77                 *      }
78                 */
79                case '{':
80                        ++level;
81                        goto endtok;
82                case '}':
83                        /*
84                         * if level goes below zero, try and fix
85                         * it, even though we've already messed up
86                         */
87                        if (--level < 0)
88                                level = 0;
89                        goto endtok;
90
91                case '\n':
92                        SETLINE;
93                        /*
94                         * the above 3 cases are similar in that they
95                         * are special characters that also end tokens.
96                         */
97endtok:                 if (sp > tok) {
98                                *sp = EOS;
99                                token = YES;
100                                sp = tok;
101                        }
102                        else
103                                token = NO;
104                        continue;
105
106                /* we ignore quoted strings and comments in their entirety */
107                case '"':
108                case '\'':
109                        (void)skip_key(c);
110                        break;
111                /* We ignore everything between [] */
112                case '[':
113                        (void)skip_key(']');
114                        goto storec;
115
116                /*
117                 * comments can be fun; note the state is unchanged after
118                 * return, in case we found:
119                 *      "foo() XX comment XX { int bar; }"
120                 */
121                case '/':
122                        if (GETC(==,'*')) {
123                                skip_comment();
124                                continue;
125                        }
126                        (void)ungetc(c,inf);
127                        c = '/';
128                        goto storec;
129
130                /* hash marks flag #define's. */
131                case '#':
132                        if (sp == tok) {
133                                hash_entry();
134                                break;
135                        }
136                        goto storec;
137
138                /*
139                 * if we have a current token, parenthesis on
140                 * level zero indicates a function.
141                 */
142                case '(':
143                        if (!level && token) {
144                                int     curline;
145
146                                if (sp != tok)
147                                        *sp = EOS;
148                                /*
149                                 * grab the line immediately, we may
150                                 * already be wrong, for example,
151                                 *      foo\n
152                                 *      (arg1,
153                                 */
154                                getline();
155                                curline = lineno;
156                                if (func_entry()) {
157                                        ++level;
158                                        pfnote(tok,curline,SY_FUN);
159                                } else rparen=2;
160                                break;
161                        }
162                        goto storec;
163
164                /*
165                 * semi-colons indicate the end of a typedef; if we find a
166                 * typedef we search for the next semi-colon of the same
167                 * level as the typedef.  Ignoring "structs", they are
168                 * tricky, since you can find:
169                 *
170                 *      "typedef long time_t;"
171                 *      "typedef unsigned int u_int;"
172                 *      "typedef unsigned int u_int [10];"
173                 *
174                 * If looking at a typedef, we save a copy of the last token
175                 * found.  Then, when we find the ';' we take the current
176                 * token if it starts with a valid token name, else we take
177                 * the one we saved.  There's probably some reasonable
178                 * alternative to this...
179                 */
180                case ';':
181                        if (t_def && level == t_level) {
182                                t_def = NO;
183                                getline();
184                                if (sp != tok)
185                                        *sp = EOS;
186                                pfnote(tok,lineno,SY_TYP);
187                                break;
188                        }
189                /*
190                 * Catch global variables by the fact that they end in ; or ,
191                 * and they are at level zero.
192                 */
193                case ',':
194                        if (sp != tok) *sp = EOS;
195                        if (level==0 && rparen!=1) {
196                                pfnote(tok,lineno,SY_VAR);
197                                break;
198                        }
199                        goto storec;
200
201                /*
202                 * store characters until one that can't be part of a token
203                 * comes along; check the current token against certain
204                 * reserved words.
205                 */
206                default:
207storec:                 if (!intoken(c)) {
208                                if (sp == tok)
209                                        break;
210                                *sp = EOS;
211                                if (tflag) {
212                                        /* no typedefs inside typedefs */
213                                        if (!t_def && !bcmp(tok,"typedef",8)) {
214                                                t_def = YES;
215                                                t_level = level;
216                                                break;
217                                        }
218                                        /* catch "typedef struct" */
219                                        if ((!t_def || t_level < level)
220                                            && (!bcmp(tok,"struct",7)
221                                            || !bcmp(tok,"union",6)
222                                            || !bcmp(tok,"enum",5))) {
223                                                /* Get type of symbol */
224                                                st=0;
225                                                switch (*tok) {
226                                                 case 's' : st= SY_STR; break;
227                                                 case 'u' : st= SY_UNI; break;
228                                                 case 'e' : st= SY_ENU; break;
229                                                }
230                                                /*
231                                                 * get line immediately;
232                                                 * may change before '{'
233                                                 */
234                                                getline();
235                                                if (str_entry(c,st))
236                                                        ++level;
237                                                break;
238                                        }
239                                }
240                                sp = tok;
241                        }
242                        else if (sp != tok || begtoken(c)) {
243                                *sp++ = c;
244                                token = YES;
245                        }
246                        continue;
247                }
248                sp = tok;
249                token = NO;
250        }
251}
252
253/*
254 * func_entry --
255 *      handle a function reference
256 */
257static
258func_entry()
259{
260        register int    c;              /* current character */
261
262        /*
263         * we assume that the character after a function's right paren
264         * is a token character if it's a function and a non-token
265         * character if it's a declaration.  Comments don't count...
266         */
267        (void)skip_key((int)')');
268        for (;;) {
269                while (GETC(!=,EOF) && iswhite(c))
270                        if (c == (int)'\n')
271                                SETLINE;
272                if (intoken(c) || c == (int)'{')
273                        break;
274                if (c == (int)'/' && GETC(==,'*'))
275                        skip_comment();
276                else {                          /* don't ever "read" '/' */
277                        (void)ungetc(c,inf);
278                        return(NO);
279                }
280        }
281        if (c != (int)'{')
282                (void)skip_key((int)'{');
283        return(YES);
284}
285
286/*
287 * hash_entry --
288 *      handle a line starting with a '#'
289 */
290static void
291hash_entry()
292{
293        extern int      dflag;          /* -d: non-macro defines */
294        register int    c,              /* character read */
295                        curline;        /* line started on */
296        register char   *sp;            /* buffer pointer */
297        char    tok[MAXTOKEN];          /* storage buffer */
298
299        curline = lineno;
300        for (sp = tok;;) {              /* get next token */
301                if (GETC(==,EOF))
302                        return;
303                if (iswhite(c))
304                        break;
305                *sp++ = c;
306        }
307        *sp = EOS;
308        if (bcmp(tok,"define",6))       /* only interested in #define's */
309                goto skip;
310        for (;;) {                      /* this doesn't handle "#define \n" */
311                if (GETC(==,EOF))
312                        return;
313                if (!iswhite(c))
314                        break;
315        }
316        for (sp = tok;;) {              /* get next token */
317                *sp++ = c;
318                if (GETC(==,EOF))
319                        return;
320                /*
321                 * this is where it DOESN'T handle
322                 * "#define \n"
323                 */
324                if (!intoken(c))
325                        break;
326        }
327        *sp = EOS;
328        if (dflag || c == (int)'(') {   /* only want macros */
329                getline();
330                if (c == (int)'(') pfnote(tok,curline,SY_MAC);
331                else pfnote(tok,curline,SY_DEF);
332        }
333skip:   if (c == (int)'\n') {           /* get rid of rest of define */
334                SETLINE
335                if (*(sp - 1) != '\\')
336                        return;
337        }
338        (void)skip_key((int)'\n');
339}
340
341/*
342 * str_entry --
343 *      handle a struct, union or enum entry
344 */
345static
346str_entry(c,st)
347        register int    c;              /* current character */
348        int     st;                     /* type of symbol */
349{
350        register char   *sp;            /* buffer pointer */
351        int     curline;                /* line started on */
352        char    tok[BUFSIZ];            /* storage buffer */
353
354        curline = lineno;
355        while (iswhite(c))
356                if (GETC(==,EOF))
357                        return(NO);
358        if (c == (int)'{')              /* it was "struct {" */
359                return(YES);
360        for (sp = tok;;) {              /* get next token */
361                *sp++ = c;
362                if (GETC(==,EOF))
363                        return(NO);
364                if (!intoken(c))
365                        break;
366        }
367        switch ((char)c) {
368                case '{':               /* it was "struct foo{" */
369                        --sp;
370                        break;
371                case '\n':              /* it was "struct foo\n" */
372                        SETLINE;
373                        /*FALLTHROUGH*/
374                default:                /* probably "struct foo " */
375                        while (GETC(!=,EOF))
376                                if (!iswhite(c))
377                                        break;
378                        if (c != (int)'{') {
379                                (void)ungetc(c, inf);
380                                return(NO);
381                        }
382        }
383        *sp = EOS;
384        pfnote(tok,curline,st);
385        return(YES);
386}
387
388/*
389 * skip_comment --
390 *      skip over comment
391 */
392skip_comment()
393{
394        register int    c,              /* character read */
395                        star;           /* '*' flag */
396
397        for (star = 0;GETC(!=,EOF);)
398                switch((char)c) {
399                        /* comments don't nest, nor can they be escaped. */
400                        case '*':
401                                star = YES;
402                                break;
403                        case '/':
404                                if (star)
405                                        return;
406                                break;
407                        case '\n':
408                                SETLINE;
409                                /*FALLTHROUGH*/
410                        default:
411                                star = NO;
412                }
413}
414
415/*
416 * skip_key --
417 *      skip to next char "key"
418 */
419skip_key(key)
420        register int    key;
421{
422        register int    c,
423                        skip,
424                        retval;
425
426        for (skip = retval = NO;GETC(!=,EOF);)
427                switch((char)c) {
428                case '\\':              /* a backslash escapes anything */
429                        skip = !skip;   /* we toggle in case it's "\\" */
430                        break;
431                case ';':               /* special case for yacc; if one */
432                case '|':               /* of these chars occurs, we may */
433                        retval = YES;   /* have moved out of the rule */
434                        break;          /* not used by C */
435                case '\n':
436                        SETLINE;
437                        /*FALLTHROUGH*/
438                default:
439                        if (c == key && !skip)
440                                return(retval);
441                        skip = NO;
442                }
443        return(retval);
444}
Note: See TracBrowser for help on using the repository browser.