~ubuntu-branches/debian/experimental/geany/experimental

« back to all changes in this revision

Viewing changes to tagmanager/asm.c

  • Committer: Bazaar Package Importer
  • Author(s): Damián Viano
  • Date: 2008-05-02 11:37:45 UTC
  • mfrom: (1.2.1 upstream) (3.1.6 hardy)
  • Revision ID: james.westby@ubuntu.com-20080502113745-xzp4g6dmovrpoj17
Tags: 0.14-1
New upstream release (Closes: #478126)

Show diffs side-by-side

added added

removed removed

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