~ubuntu-branches/ubuntu/utopic/exuberant-ctags/utopic

« back to all changes in this revision

Viewing changes to beta.c

  • Committer: Bazaar Package Importer
  • Author(s): Colin Watson
  • Date: 2004-03-30 11:56:40 UTC
  • Revision ID: james.westby@ubuntu.com-20040330115640-0u2eq56u65zf53il
Tags: upstream-5.5.4
Import upstream version 5.5.4

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
*   $Id: beta.c,v 1.6 2003/02/23 17:37:48 darren Exp $
 
3
*
 
4
*   Copyright (c) 1999-2000, Mj�lner Informatics
 
5
*
 
6
*   Written by Erik Corry <corry@mjolner.dk>
 
7
*
 
8
*   This source code is released for free distribution under the terms of the
 
9
*   GNU General Public License.
 
10
*
 
11
*   This module contains functions for generating tags for BETA language
 
12
*   files.
 
13
*/
 
14
 
 
15
/*
 
16
*   INCLUDE FILES
 
17
*/
 
18
#include "general.h"    /* must always come first */
 
19
 
 
20
#include <string.h>
 
21
 
 
22
#include "entry.h"
 
23
#include "parse.h"
 
24
#include "read.h"
 
25
#include "routines.h"
 
26
#include "vstring.h"
 
27
 
 
28
/*
 
29
*   MACROS
 
30
*/
 
31
#define isbident(c) (identarray [(unsigned char) (c)])
 
32
 
 
33
/*
 
34
*   DATA DEFINITIONS
 
35
*/
 
36
typedef enum {
 
37
    K_FRAGMENT, K_PATTERN, K_SLOT, K_VIRTUAL
 
38
} betaKind;
 
39
 
 
40
static kindOption BetaKinds [] = {
 
41
    { TRUE,  'f', "fragment", "fragment definitions"},
 
42
    { FALSE, 'p', "pattern",  "all patterns"},
 
43
    { TRUE,  's', "slot",     "slots (fragment uses)"},
 
44
    { TRUE,  'v', "virtual",  "patterns (virtual or rebound)"}
 
45
};
 
46
 
 
47
/* [A-Z_a-z0-9] */
 
48
static const char identarray [256] = {
 
49
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  /* 0-15  */
 
50
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  /* 16-31 */
 
51
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  /* 32-47    !"#$%&'()*+'-./ */
 
52
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0,  /* 48-63   0123456789:;<=>? */
 
53
0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,  /* 64-79   @ABCDEFGHIJKLMNO */
 
54
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 1,  /* 80-95   PQRSTUVWXYZ [\]^_ */
 
55
0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,  /* 96-111  `abcdefghijklmno */
 
56
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0,  /* 112-127  pqrstuvwxyz{|}~ */
 
57
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  /* 128-  */
 
58
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
 
59
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
 
60
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
 
61
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
 
62
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
 
63
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
 
64
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; /* -255  */
 
65
 
 
66
/*
 
67
*   FUNCTION DEFINITIONS
 
68
*/
 
69
 
 
70
static void makeBetaTag (const char* const name, const betaKind kind)
 
71
{
 
72
    if (BetaKinds [kind].enabled)
 
73
    {
 
74
        tagEntryInfo e;
 
75
        initTagEntry (&e, name);
 
76
 
 
77
        e.kindName = BetaKinds [kind].name;
 
78
        e.kind     = BetaKinds [kind].letter;
 
79
 
 
80
        makeTagEntry (&e);
 
81
    }
 
82
}
 
83
 
 
84
static void findBetaTags (void)
 
85
{
 
86
    vString *line = vStringNew ();
 
87
    boolean incomment = FALSE;
 
88
    boolean inquote = FALSE;
 
89
    boolean dovirtuals = BetaKinds [K_VIRTUAL].enabled;
 
90
    boolean dopatterns = BetaKinds [K_PATTERN].enabled;
 
91
 
 
92
    do
 
93
    {
 
94
        boolean foundfragmenthere = FALSE;
 
95
        /* find fragment definition (line that starts and ends with --) */
 
96
        int last;
 
97
        int first;
 
98
        int c;
 
99
 
 
100
        vStringClear (line);
 
101
 
 
102
        while ((c = fileGetc ()) != EOF && c != '\n' && c != '\r')
 
103
            vStringPut (line, c);
 
104
 
 
105
        vStringTerminate (line);
 
106
 
 
107
        last = vStringLength (line) - 1;
 
108
        first = 0;
 
109
        /* skip white space at start and end of line */
 
110
        while (last && isspace ((int) vStringChar (line, last))) last--;
 
111
        while (first < last && isspace ((int) vStringChar (line, first))) first++;
 
112
        /* if line still has a reasonable length and ... */
 
113
        if (last - first > 4 &&
 
114
           (vStringChar (line, first)     == '-' && 
 
115
            vStringChar (line, first + 1) == '-' && 
 
116
            vStringChar (line, last)      == '-' && 
 
117
            vStringChar (line, last - 1)  == '-'))
 
118
        {
 
119
            if (!incomment && !inquote)
 
120
            {
 
121
                foundfragmenthere = TRUE;
 
122
                /* skip past -- and whitespace.  Also skip back past 'dopart'
 
123
                   or 'attributes' to the :.  We have to do this because there
 
124
                   is no sensible way to include whitespace in a ctags token
 
125
                   so the conventional space after the ':' would mess us up */
 
126
                last -= 2;
 
127
                first += 2;
 
128
                while (last && vStringChar (line, last) != ':') last--;
 
129
                while (last && (isspace ((int) vStringChar (line, last-1)))) last--;
 
130
                while (first < last &&
 
131
                       (isspace ((int) vStringChar (line, first)) ||
 
132
                        vStringChar (line, first) == '-'))
 
133
                    first++;
 
134
                /* If there's anything left it is a fragment title */
 
135
                if (first < last - 1)
 
136
                {
 
137
                    vStringChar (line, last) = 0;
 
138
                    if (strcasecmp ("LIB", vStringValue (line) + first) &&
 
139
                        strcasecmp ("PROGRAM", vStringValue (line) + first))
 
140
                    {
 
141
                        makeBetaTag (vStringValue (line) + first, K_FRAGMENT);
 
142
                    }
 
143
                }
 
144
            }
 
145
        } else {
 
146
            int pos = 0;
 
147
            int len = vStringLength (line);
 
148
            if (inquote) goto stringtext;
 
149
            if (incomment) goto commenttext;
 
150
        programtext:
 
151
            for ( ; pos < len; pos++)
 
152
            {
 
153
                if (vStringChar (line, pos) == '\'')
 
154
                {
 
155
                    pos++;
 
156
                    inquote = TRUE;
 
157
                    goto stringtext;
 
158
                }
 
159
                if (vStringChar (line, pos) == '{')
 
160
                {
 
161
                    pos++;
 
162
                    incomment = TRUE;
 
163
                    goto commenttext;
 
164
                }
 
165
                if (vStringChar (line, pos) == '(' && pos < len - 1 &&
 
166
                    vStringChar (line, pos+1) == '*')
 
167
                {
 
168
                    pos +=2;
 
169
                    incomment = TRUE;
 
170
                    goto commenttext;
 
171
                }
 
172
                /*
 
173
                 * SLOT definition looks like this: 
 
174
                 * <<SLOT nameofslot: dopart>> 
 
175
                 * or
 
176
                 * <<SLOT nameofslot: descriptor>> 
 
177
                 */
 
178
                if (!foundfragmenthere &&
 
179
                    vStringChar (line, pos) == '<' &&
 
180
                    pos+1 < len &&
 
181
                    vStringChar (line, pos+1) == '<' &&
 
182
                    strstr (vStringValue (line) + pos, ">>"))
 
183
                {
 
184
                    /* Found slot name, get start and end */
 
185
                    int eoname;
 
186
                    char c2;
 
187
                    pos += 2; /* skip past << */
 
188
                    /* skip past space before SLOT */
 
189
                    while (pos < len && isspace ((int) vStringChar (line, pos)))
 
190
                        pos++;
 
191
                    /* skip past SLOT */
 
192
                    if (pos+4 <= len &&
 
193
                        !strncasecmp (vStringValue(line) + pos, "SLOT", (size_t)4))
 
194
                        pos += 4;
 
195
                    /* skip past space after SLOT */
 
196
                    while (pos < len &&
 
197
                           isspace ((int) vStringChar (line, pos)))
 
198
                        pos++;
 
199
                    eoname = pos;
 
200
                    /* skip to end of name */
 
201
                    while (eoname < len &&
 
202
                           (c2 = vStringChar (line, eoname)) != '>' &&
 
203
                           c2 != ':' &&
 
204
                           !isspace ((int) c2))
 
205
                        eoname++;
 
206
                    if (eoname < len)
 
207
                    {
 
208
                        vStringChar (line, eoname) = 0;
 
209
                        if (strcasecmp ("LIB", vStringValue (line) + pos) &&
 
210
                            strcasecmp ("PROGRAM", vStringValue (line) + pos) &&
 
211
                            strcasecmp ("SLOT", vStringValue (line) + pos))
 
212
                        {
 
213
                            makeBetaTag (vStringValue (line) + pos, K_SLOT);
 
214
                        }
 
215
                    }
 
216
                    if (eoname+1 < len) {
 
217
                       pos = eoname + 1;
 
218
                    } else {
 
219
                       pos = len;
 
220
                       continue;
 
221
                    }
 
222
                }
 
223
                /* Only patterns that are virtual, extensions of virtuals or
 
224
                 * final bindings are normally included so as not to overload
 
225
                 * totally.
 
226
                 * That means one of the forms name:: name:< or name::<
 
227
                 */
 
228
                if (!foundfragmenthere &&
 
229
                    vStringChar (line, pos) == ':' &&
 
230
                    (dopatterns ||
 
231
                     (dovirtuals &&
 
232
                      (vStringChar (line, pos+1) == ':' ||
 
233
                       vStringChar (line, pos+1) == '<')
 
234
                     )
 
235
                    )
 
236
                   )
 
237
                {
 
238
                    /* Found pattern name, get start and end */
 
239
                    int eoname = pos;
 
240
                    int soname;
 
241
                    while (eoname && isspace ((int) vStringChar (line, eoname-1)))
 
242
                        eoname--;
 
243
                foundanothername:
 
244
                    /* terminate right after name */
 
245
                    vStringChar (line, eoname) = 0;
 
246
                    soname = eoname;
 
247
                    while (soname &&
 
248
                        isbident (vStringChar (line, soname-1)))
 
249
                    {
 
250
                        soname--;
 
251
                    }
 
252
                    if (soname != eoname)
 
253
                    {
 
254
                        makeBetaTag (vStringValue (line) + soname, K_PATTERN);
 
255
                        /* scan back past white space */
 
256
                        while (soname &&
 
257
                                isspace ((int) vStringChar (line, soname-1)))
 
258
                            soname--;
 
259
                        if (soname && vStringChar (line, soname-1) == ',')
 
260
                        {
 
261
                            /* we found a new pattern name before comma */
 
262
                            eoname = soname;
 
263
                            goto foundanothername;
 
264
                        }
 
265
                    }
 
266
                }
 
267
            }
 
268
            goto endofline;
 
269
        commenttext:
 
270
            for ( ; pos < len; pos++)
 
271
            {
 
272
                if (vStringChar (line, pos) == '*' && pos < len - 1 &&
 
273
                    vStringChar (line, pos+1) == ')')
 
274
                {
 
275
                    pos += 2;
 
276
                    incomment = FALSE;
 
277
                    goto programtext;
 
278
                }
 
279
                if (vStringChar (line, pos) == '}')
 
280
                {
 
281
                    pos++;
 
282
                    incomment = FALSE;
 
283
                    goto programtext;
 
284
                }
 
285
            }
 
286
            goto endofline;
 
287
        stringtext:
 
288
            for ( ; pos < len; pos++)
 
289
            {
 
290
                if (vStringChar (line, pos) == '\\')
 
291
                {
 
292
                    if (pos < len - 1) pos++;
 
293
                }
 
294
                else if (vStringChar (line, pos) == '\'')
 
295
                {
 
296
                    pos++;
 
297
                    /* support obsolete '' syntax */
 
298
                    if (pos < len && vStringChar (line, pos) == '\'')
 
299
                    {
 
300
                        continue;
 
301
                    }
 
302
                    inquote = FALSE;
 
303
                    goto programtext;
 
304
                }
 
305
            }
 
306
        }
 
307
        endofline:
 
308
        inquote = FALSE;  /* This shouldn't really make a difference */
 
309
    } while (!feof (File.fp));
 
310
}
 
311
 
 
312
extern parserDefinition* BetaParser (void)
 
313
{
 
314
    static const char *const extensions [] = { "bet", NULL };
 
315
    parserDefinition* def = parserNew ("BETA");
 
316
    def->kinds      = BetaKinds;
 
317
    def->kindCount  = KIND_COUNT (BetaKinds);
 
318
    def->extensions = extensions;
 
319
    def->parser     = findBetaTags;
 
320
    return def;
 
321
}
 
322
 
 
323
/* vi:set tabstop=8 shiftwidth=4: */