~ubuntu-branches/ubuntu/lucid/codelite/lucid

« back to all changes in this revision

Viewing changes to sdk/codelite_indexer/libctags/asm.c

  • Committer: Bazaar Package Importer
  • Author(s): Chow Loong Jin
  • Date: 2009-02-10 02:27:55 UTC
  • mfrom: (1.1.1 upstream)
  • Revision ID: james.westby@ubuntu.com-20090210022755-m5692nfc1t5uf1w9
Tags: 1.0.2759+dfsg-0ubuntu1
* New upstream release (LP: #327216).
* debian/patches/series, debian/patches/00_fix-ia64-build.patch:
  + Dropped, applied upstream already.
* debian/patches/02_fix-desktop.patch,
  debian/patches/03_fix-sh.patch:
  + Refreshed to patch cleanly.
* debian/rules:
  + Make get-orig-source honour UPSTREAM_VERSION if set.
* debian/ctags-le.1,
  debian/codelite_indexer.1,
  debian/codelite.manpages:
  + Dropped ctags-le manpage, since ctags-le was replaced by
    codelite_indexer.
  + Added codelite_indexer manpage.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
*   $Id: asm.c,v 1.18 2006/05/30 04:37:11 darren Exp $
 
3
*
 
4
*   Copyright (c) 2000-2003, Darren Hiebert
 
5
*
 
6
*   This source code is released for free distribution under the terms of the
 
7
*   GNU General Public License.
 
8
*
 
9
*   This module contains functions for generating tags for assembly language
 
10
*   files.
 
11
*/
 
12
 
 
13
/*
 
14
*   INCLUDE FILES
 
15
*/
 
16
#include "general.h"  /* must always come first */
 
17
 
 
18
#include <string.h>
 
19
 
 
20
#include "debug.h"
 
21
#include "keyword.h"
 
22
#include "parse.h"
 
23
#include "read.h"
 
24
#include "routines.h"
 
25
#include "vstring.h"
 
26
 
 
27
/*
 
28
*   DATA DECLARATIONS
 
29
*/
 
30
typedef enum {
 
31
        K_NONE = -1, K_DEFINE, K_LABEL, K_MACRO, K_TYPE
 
32
} AsmKind;
 
33
 
 
34
typedef enum {
 
35
        OP_UNDEFINED = -1,
 
36
        OP_ALIGN,
 
37
        OP_COLON_EQUAL,
 
38
        OP_END,
 
39
        OP_ENDM,
 
40
        OP_ENDMACRO,
 
41
        OP_ENDP,
 
42
        OP_ENDS,
 
43
        OP_EQU,
 
44
        OP_EQUAL,
 
45
        OP_LABEL,
 
46
        OP_MACRO,
 
47
        OP_PROC,
 
48
        OP_RECORD,
 
49
        OP_SECTIONS,
 
50
        OP_SET,
 
51
        OP_STRUCT,
 
52
        OP_LAST
 
53
} opKeyword;
 
54
 
 
55
typedef struct {
 
56
        const char *_operator;
 
57
        opKeyword keyword;
 
58
} asmKeyword;
 
59
 
 
60
typedef struct {
 
61
        opKeyword keyword;
 
62
        AsmKind kind;
 
63
} opKind;
 
64
 
 
65
/*
 
66
*   DATA DEFINITIONS
 
67
*/
 
68
static langType Lang_asm;
 
69
 
 
70
static kindOption AsmKinds [] = {
 
71
        { TRUE, 'd', "define", "defines" },
 
72
        { TRUE, 'l', "label",  "labels"  },
 
73
        { TRUE, 'm', "macro",  "macros"  },
 
74
        { TRUE, 't', "type",   "types (structs and records)"   }
 
75
};
 
76
 
 
77
static const asmKeyword AsmKeywords [] = {
 
78
        { "align",    OP_ALIGN       },
 
79
        { "endmacro", OP_ENDMACRO    },
 
80
        { "endm",     OP_ENDM        },
 
81
        { "end",      OP_END         },
 
82
        { "endp",     OP_ENDP        },
 
83
        { "ends",     OP_ENDS        },
 
84
        { "equ",      OP_EQU         },
 
85
        { "label",    OP_LABEL       },
 
86
        { "macro",    OP_MACRO       },
 
87
        { ":=",       OP_COLON_EQUAL },
 
88
        { "=",        OP_EQUAL       },
 
89
        { "proc",     OP_PROC        },
 
90
        { "record",   OP_RECORD      },
 
91
        { "sections", OP_SECTIONS    },
 
92
        { "set",      OP_SET         },
 
93
        { "struct",   OP_STRUCT      }
 
94
};
 
95
 
 
96
static const opKind OpKinds [] = {
 
97
        /* must be ordered same as opKeyword enumeration */
 
98
        { OP_ALIGN,       K_NONE   },
 
99
        { OP_COLON_EQUAL, K_DEFINE },
 
100
        { OP_END,         K_NONE   },
 
101
        { OP_ENDM,        K_NONE   },
 
102
        { OP_ENDMACRO,    K_NONE   },
 
103
        { OP_ENDP,        K_NONE   },
 
104
        { OP_ENDS,        K_NONE   },
 
105
        { OP_EQU,         K_DEFINE },
 
106
        { OP_EQUAL,       K_DEFINE },
 
107
        { OP_LABEL,       K_LABEL  },
 
108
        { OP_MACRO,       K_MACRO  },
 
109
        { OP_PROC,        K_LABEL  },
 
110
        { OP_RECORD,      K_TYPE   },
 
111
        { OP_SECTIONS,    K_NONE   },
 
112
        { OP_SET,         K_DEFINE },
 
113
        { OP_STRUCT,      K_TYPE   }
 
114
};
 
115
 
 
116
/*
 
117
*   FUNCTION DEFINITIONS
 
118
*/
 
119
static void buildAsmKeywordHash (void)
 
120
{
 
121
        const size_t count = sizeof (AsmKeywords) / sizeof (AsmKeywords [0]);
 
122
        size_t i;
 
123
        for (i = 0  ;  i < count  ;  ++i)
 
124
        {
 
125
                const asmKeyword* const p = AsmKeywords + i;
 
126
                addKeyword (p->_operator, Lang_asm, (int) p->keyword);
 
127
        }
 
128
}
 
129
 
 
130
static opKeyword analyzeOperator (const vString *const op)
 
131
{
 
132
        static vString *keyword = NULL;
 
133
        opKeyword result = OP_UNDEFINED;
 
134
 
 
135
        if (keyword == NULL)
 
136
                keyword = vStringNew ();
 
137
        vStringCopyToLower (keyword, op);
 
138
        result = (opKeyword) lookupKeyword (vStringValue (keyword), Lang_asm);
 
139
        return result;
 
140
}
 
141
 
 
142
static boolean isInitialSymbolCharacter (int c)
 
143
{
 
144
        return (boolean) (c != '\0' && (isalpha (c) || strchr ("_$", c) != NULL));
 
145
}
 
146
 
 
147
static boolean isSymbolCharacter (int c)
 
148
{
 
149
        /* '?' character is allowed in AMD 29K family */
 
150
        return (boolean) (c != '\0' && (isalnum (c) || strchr ("_$?", c) != NULL));
 
151
}
 
152
 
 
153
static boolean readPreProc (const unsigned char *const line)
 
154
{
 
155
        boolean result;
 
156
        const unsigned char *cp = line;
 
157
        vString *name = vStringNew ();
 
158
        while (isSymbolCharacter ((int) *cp))
 
159
        {
 
160
                vStringPut (name, *cp);
 
161
                ++cp;
 
162
        }
 
163
        vStringTerminate (name);
 
164
        result = (boolean) (strcmp (vStringValue (name), "define") == 0);
 
165
        if (result)
 
166
        {
 
167
                while (isspace ((int) *cp))
 
168
                        ++cp;
 
169
                vStringClear (name);
 
170
                while (isSymbolCharacter ((int) *cp))
 
171
                {
 
172
                        vStringPut (name, *cp);
 
173
                        ++cp;
 
174
                }
 
175
                vStringTerminate (name);
 
176
                makeSimpleTag (name, AsmKinds, K_DEFINE);
 
177
        }
 
178
        vStringDelete (name);
 
179
        return result;
 
180
}
 
181
 
 
182
static AsmKind operatorKind (
 
183
                const vString *const _operator,
 
184
                boolean *const found)
 
185
{
 
186
        AsmKind result = K_NONE;
 
187
        const opKeyword kw = analyzeOperator (_operator);
 
188
        *found = (boolean) (kw != OP_UNDEFINED);
 
189
        if (*found)
 
190
        {
 
191
                result = OpKinds [kw].kind;
 
192
                Assert (OpKinds [kw].keyword == kw);
 
193
        }
 
194
        return result;
 
195
}
 
196
 
 
197
/*  We must check for "DB", "DB.L", "DCB.W" (68000)
 
198
 */
 
199
static boolean isDefineOperator (const vString *const _operator)
 
200
{
 
201
        const unsigned char *const op =
 
202
                (unsigned char*) vStringValue (_operator);
 
203
        const size_t length = vStringLength (_operator);
 
204
        const boolean result = (boolean) (length > 0  &&
 
205
                toupper ((int) *op) == 'D'  &&
 
206
                (length == 2 ||
 
207
                 (length == 4  &&  (int) op [2] == '.') ||
 
208
                 (length == 5  &&  (int) op [3] == '.')));
 
209
        return result;
 
210
}
 
211
 
 
212
static void makeAsmTag (
 
213
                const vString *const name,
 
214
                const vString *const _operator,
 
215
                const boolean labelCandidate,
 
216
                const boolean nameFollows)
 
217
{
 
218
        if (vStringLength (name) > 0)
 
219
        {
 
220
                boolean found;
 
221
                const AsmKind kind = operatorKind (_operator, &found);
 
222
                if (found)
 
223
                {
 
224
                        if (kind != K_NONE)
 
225
                                makeSimpleTag (name, AsmKinds, kind);
 
226
                }
 
227
                else if (isDefineOperator (_operator))
 
228
                {
 
229
                        if (! nameFollows)
 
230
                                makeSimpleTag (name, AsmKinds, K_DEFINE);
 
231
                }
 
232
                else if (labelCandidate)
 
233
                {
 
234
                        operatorKind (name, &found);
 
235
                        if (! found)
 
236
                                makeSimpleTag (name, AsmKinds, K_LABEL);
 
237
                }
 
238
        }
 
239
}
 
240
 
 
241
static const unsigned char *readSymbol (
 
242
                const unsigned char *const start,
 
243
                vString *const sym)
 
244
{
 
245
        const unsigned char *cp = start;
 
246
        vStringClear (sym);
 
247
        if (isInitialSymbolCharacter ((int) *cp))
 
248
        {
 
249
                while (isSymbolCharacter ((int) *cp))
 
250
                {
 
251
                        vStringPut (sym, *cp);
 
252
                        ++cp;
 
253
                }
 
254
                vStringTerminate (sym);
 
255
        }
 
256
        return cp;
 
257
}
 
258
 
 
259
static const unsigned char *readOperator (
 
260
                const unsigned char *const start,
 
261
                vString *const _operator)
 
262
{
 
263
        const unsigned char *cp = start;
 
264
        vStringClear (_operator);
 
265
        while (*cp != '\0'  &&  ! isspace ((int) *cp))
 
266
        {
 
267
                vStringPut (_operator, *cp);
 
268
                ++cp;
 
269
        }
 
270
        vStringTerminate (_operator);
 
271
        return cp;
 
272
}
 
273
 
 
274
static void findAsmTags (void)
 
275
{
 
276
        vString *name = vStringNew ();
 
277
        vString *_operator = vStringNew ();
 
278
        const unsigned char *line;
 
279
        boolean inCComment = FALSE;
 
280
 
 
281
        while ((line = fileReadLine ()) != NULL)
 
282
        {
 
283
                const unsigned char *cp = line;
 
284
                boolean labelCandidate = (boolean) (! isspace ((int) *cp));
 
285
                boolean nameFollows = FALSE;
 
286
                const boolean isComment = (boolean)
 
287
                                (*cp != '\0' && strchr (";*@", *cp) != NULL);
 
288
 
 
289
                /* skip comments */
 
290
                if (strncmp ((const char*) cp, "/*", (size_t) 2) == 0)
 
291
                {
 
292
                        inCComment = TRUE;
 
293
                        cp += 2;
 
294
                }
 
295
                if (inCComment)
 
296
                {
 
297
                        do
 
298
                        {
 
299
                                if (strncmp ((const char*) cp, "*/", (size_t) 2) == 0)
 
300
                                {
 
301
                                        inCComment = FALSE;
 
302
                                        cp += 2;
 
303
                                        break;
 
304
                                }
 
305
                                ++cp;
 
306
                        } while (*cp != '\0');
 
307
                }
 
308
                if (isComment || inCComment)
 
309
                        continue;
 
310
 
 
311
                /* read preprocessor defines */
 
312
                if (*cp == '#')
 
313
                {
 
314
                        ++cp;
 
315
                        readPreProc (cp);
 
316
                        continue;
 
317
                }
 
318
 
 
319
                /* skip white space */
 
320
                while (isspace ((int) *cp))
 
321
                        ++cp;
 
322
 
 
323
                /* read symbol */
 
324
                cp = readSymbol (cp, name);
 
325
                if (vStringLength (name) > 0  &&  *cp == ':')
 
326
                {
 
327
                        labelCandidate = TRUE;
 
328
                        ++cp;
 
329
                }
 
330
 
 
331
                if (! isspace ((int) *cp)  &&  *cp != '\0')
 
332
                        continue;
 
333
 
 
334
                /* skip white space */
 
335
                while (isspace ((int) *cp))
 
336
                        ++cp;
 
337
 
 
338
                /* skip leading dot */
 
339
#if 0
 
340
                if (*cp == '.')
 
341
                        ++cp;
 
342
#endif
 
343
 
 
344
                cp = readOperator (cp, _operator);
 
345
 
 
346
                /* attempt second read of symbol */
 
347
                if (vStringLength (name) == 0)
 
348
                {
 
349
                        while (isspace ((int) *cp))
 
350
                                ++cp;
 
351
                        cp = readSymbol (cp, name);
 
352
                        nameFollows = TRUE;
 
353
                }
 
354
                makeAsmTag (name, _operator, labelCandidate, nameFollows);
 
355
        }
 
356
        vStringDelete (name);
 
357
        vStringDelete (_operator);
 
358
}
 
359
 
 
360
static void initialize (const langType language)
 
361
{
 
362
        Lang_asm = language;
 
363
        buildAsmKeywordHash ();
 
364
}
 
365
 
 
366
extern parserDefinition* AsmParser (void)
 
367
{
 
368
        static const char *const extensions [] = {
 
369
                "asm", "ASM", "s", "S", NULL
 
370
        };
 
371
        static const char *const patterns [] = {
 
372
                "*.A51",
 
373
                "*.29[kK]",
 
374
                "*.[68][68][kKsSxX]",
 
375
                "*.[xX][68][68]",
 
376
                NULL
 
377
        };
 
378
        parserDefinition* def = parserNew ("Asm");
 
379
        def->kinds      = AsmKinds;
 
380
        def->kindCount  = KIND_COUNT (AsmKinds);
 
381
        def->extensions = extensions;
 
382
        def->patterns   = patterns;
 
383
        def->parser     = findAsmTags;
 
384
        def->initialize = initialize;
 
385
        return def;
 
386
}
 
387
 
 
388
/* vi:set tabstop=4 shiftwidth=4: */