2008-02-13 Johannes Schmid <jhs@gnome.org>
[anjuta-git-plugin.git] / tagmanager / asm.c
blob9aae1204f640ad03eb7bcec80471d7e6b3d72a10
1 /*
2 * $Id$
4 * Copyright (c) 2000-2003, Darren Hiebert
6 * This source code is released for free distribution under the terms of the
7 * GNU General Public License.
9 * This module contains functions for generating tags for assembly language
10 * files.
14 * INCLUDE FILES
16 #include "general.h" /* must always come first */
18 #include <string.h>
20 #include "debug.h"
21 #include "keyword.h"
22 #include "parse.h"
23 #include "read.h"
24 #include "routines.h"
25 #include "vstring.h"
28 * DATA DECLARATIONS
30 typedef enum {
31 K_NONE = -1, K_DEFINE, K_LABEL, K_MACRO, K_TYPE
32 } AsmKind;
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;
55 typedef struct {
56 const char *operator;
57 opKeyword keyword;
58 } asmKeyword;
60 typedef struct {
61 opKeyword keyword;
62 AsmKind kind;
63 } opKind;
66 * DATA DEFINITIONS
68 static langType Lang_asm;
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)" }
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 }
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 }
117 * FUNCTION DEFINITIONS
119 static void buildAsmKeywordHash (void)
121 const size_t count = sizeof (AsmKeywords) / sizeof (AsmKeywords [0]);
122 size_t i;
123 for (i = 0 ; i < count ; ++i)
125 const asmKeyword* const p = AsmKeywords + i;
126 addKeyword (p->operator, Lang_asm, (int) p->keyword);
130 static opKeyword analyzeOperator (const vString *const op)
132 static vString *keyword = NULL;
133 opKeyword result = OP_UNDEFINED;
135 if (keyword == NULL)
136 keyword = vStringNew ();
137 vStringCopyToLower (keyword, op);
138 result = (opKeyword) lookupKeyword (vStringValue (keyword), Lang_asm);
139 return result;
142 static boolean isInitialSymbolCharacter (int c)
144 return (boolean) (c != '\0' && (isalpha (c) || strchr ("_$", c) != NULL));
147 static boolean isSymbolCharacter (int c)
149 /* '?' character is allowed in AMD 29K family */
150 return (boolean) (c != '\0' && (isalnum (c) || strchr ("_$?", c) != NULL));
153 static boolean readPreProc (const unsigned char *const line)
155 boolean result;
156 const unsigned char *cp = line;
157 vString *name = vStringNew ();
158 while (isSymbolCharacter ((int) *cp))
160 vStringPut (name, *cp);
161 ++cp;
163 vStringTerminate (name);
164 result = (boolean) (strcmp (vStringValue (name), "define") == 0);
165 if (result)
167 while (isspace ((int) *cp))
168 ++cp;
169 vStringClear (name);
170 while (isSymbolCharacter ((int) *cp))
172 vStringPut (name, *cp);
173 ++cp;
175 vStringTerminate (name);
176 makeSimpleTag (name, AsmKinds, K_DEFINE);
178 vStringDelete (name);
179 return result;
182 static AsmKind operatorKind (
183 const vString *const operator,
184 boolean *const found)
186 AsmKind result = K_NONE;
187 const opKeyword kw = analyzeOperator (operator);
188 *found = (boolean) (kw != OP_UNDEFINED);
189 if (*found)
191 result = OpKinds [kw].kind;
192 Assert (OpKinds [kw].keyword == kw);
194 return result;
197 /* We must check for "DB", "DB.L", "DCB.W" (68000)
199 static boolean isDefineOperator (const vString *const operator)
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;
212 static void makeAsmTag (
213 const vString *const name,
214 const vString *const operator,
215 const boolean labelCandidate,
216 const boolean nameFollows)
218 if (vStringLength (name) > 0)
220 boolean found;
221 const AsmKind kind = operatorKind (operator, &found);
222 if (found)
224 if (kind != K_NONE)
225 makeSimpleTag (name, AsmKinds, kind);
227 else if (isDefineOperator (operator))
229 if (! nameFollows)
230 makeSimpleTag (name, AsmKinds, K_DEFINE);
232 else if (labelCandidate)
234 operatorKind (name, &found);
235 if (! found)
236 makeSimpleTag (name, AsmKinds, K_LABEL);
241 static const unsigned char *readSymbol (
242 const unsigned char *const start,
243 vString *const sym)
245 const unsigned char *cp = start;
246 vStringClear (sym);
247 if (isInitialSymbolCharacter ((int) *cp))
249 while (isSymbolCharacter ((int) *cp))
251 vStringPut (sym, *cp);
252 ++cp;
254 vStringTerminate (sym);
256 return cp;
259 static const unsigned char *readOperator (
260 const unsigned char *const start,
261 vString *const operator)
263 const unsigned char *cp = start;
264 vStringClear (operator);
265 while (*cp != '\0' && ! isspace ((int) *cp))
267 vStringPut (operator, *cp);
268 ++cp;
270 vStringTerminate (operator);
271 return cp;
274 static void findAsmTags (void)
276 vString *name = vStringNew ();
277 vString *operator = vStringNew ();
278 const unsigned char *line;
279 boolean inCComment = FALSE;
281 while ((line = fileReadLine ()) != NULL)
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);
289 /* skip comments */
290 if (strncmp ((const char*) cp, "/*", (size_t) 2) == 0)
292 inCComment = TRUE;
293 cp += 2;
295 if (inCComment)
299 if (strncmp ((const char*) cp, "*/", (size_t) 2) == 0)
301 inCComment = FALSE;
302 cp += 2;
303 break;
305 ++cp;
306 } while (*cp != '\0');
308 if (isComment || inCComment)
309 continue;
311 /* read preprocessor defines */
312 if (*cp == '#')
314 ++cp;
315 readPreProc (cp);
316 continue;
319 /* skip white space */
320 while (isspace ((int) *cp))
321 ++cp;
323 /* read symbol */
324 cp = readSymbol (cp, name);
325 if (vStringLength (name) > 0 && *cp == ':')
327 labelCandidate = TRUE;
328 ++cp;
331 if (! isspace ((int) *cp) && *cp != '\0')
332 continue;
334 /* skip white space */
335 while (isspace ((int) *cp))
336 ++cp;
338 /* skip leading dot */
339 #if 0
340 if (*cp == '.')
341 ++cp;
342 #endif
344 cp = readOperator (cp, operator);
346 /* attempt second read of symbol */
347 if (vStringLength (name) == 0)
349 while (isspace ((int) *cp))
350 ++cp;
351 cp = readSymbol (cp, name);
352 nameFollows = TRUE;
354 makeAsmTag (name, operator, labelCandidate, nameFollows);
356 vStringDelete (name);
357 vStringDelete (operator);
360 static void initialize (const langType language)
362 Lang_asm = language;
363 buildAsmKeywordHash ();
366 extern parserDefinition* AsmParser (void)
368 static const char *const extensions [] = {
369 "asm", "ASM", "s", "S", NULL
371 static const char *const patterns [] = {
372 "*.A51",
373 "*.29[kK]",
374 "*.[68][68][kKsSxX]",
375 "*.[xX][68][68]",
376 NULL
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;
388 /* vi:set tabstop=4 shiftwidth=4: */