r5123 | ntrel | 2010-08-10 17:12:24 +0100 (Tue, 10 Aug 2010) | 4 lines
[geany-mirror.git] / tagmanager / asm.c
blobf1dc39bc90efad26711c78bfd45143d9d04f304c
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 "keyword.h"
21 #include "parse.h"
22 #include "read.h"
23 #include "main.h"
24 #include "vstring.h"
27 * DATA DECLARATIONS
29 typedef enum {
30 K_NONE = -1, K_DEFINE, K_LABEL, K_MACRO, K_TYPE
31 } AsmKind;
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;
54 typedef struct {
55 const char *operator;
56 opKeyword keyword;
57 } asmKeyword;
59 typedef struct {
60 opKeyword keyword;
61 AsmKind kind;
62 } opKind;
65 * DATA DEFINITIONS
67 static langType Lang_asm;
69 static kindOption AsmKinds [] = {
70 { TRUE, 'd', "macro", "defines" },
71 { TRUE, 'l', "namespace", "labels" },
72 { TRUE, 'm', "function", "macros" },
73 { TRUE, 't', "struct", "types (structs and records)" }
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 }
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 }
116 * FUNCTION DEFINITIONS
118 static void buildAsmKeywordHash (void)
120 const size_t count = sizeof (AsmKeywords) / sizeof (AsmKeywords [0]);
121 size_t i;
122 for (i = 0 ; i < count ; ++i)
124 const asmKeyword* const p = AsmKeywords + i;
125 addKeyword (p->operator, Lang_asm, (int) p->keyword);
129 static opKeyword analyzeOperator (const vString *const op)
131 vString *keyword = vStringNew ();
132 opKeyword result;
134 vStringCopyToLower (keyword, op);
135 result = (opKeyword) lookupKeyword (vStringValue (keyword), Lang_asm);
136 vStringDelete (keyword);
137 return result;
140 static boolean isInitialSymbolCharacter (int c)
142 return (boolean) (c != '\0' && (isalpha (c) || strchr ("_$", c) != NULL));
145 static boolean isSymbolCharacter (int c)
147 /* '?' character is allowed in AMD 29K family */
148 return (boolean) (c != '\0' && (isalnum (c) || strchr ("_$?", c) != NULL));
151 static boolean readPreProc (const unsigned char *const line)
153 boolean result;
154 const unsigned char *cp = line;
155 vString *name = vStringNew ();
156 while (isSymbolCharacter ((int) *cp))
158 vStringPut (name, *cp);
159 ++cp;
161 vStringTerminate (name);
162 result = (boolean) (strcmp (vStringValue (name), "define") == 0);
163 if (result)
165 while (isspace ((int) *cp))
166 ++cp;
167 vStringClear (name);
168 while (isSymbolCharacter ((int) *cp))
170 vStringPut (name, *cp);
171 ++cp;
173 vStringTerminate (name);
174 makeSimpleTag (name, AsmKinds, K_DEFINE);
176 vStringDelete (name);
177 return result;
180 static AsmKind operatorKind (
181 const vString *const operator,
182 boolean *const found)
184 AsmKind result = K_NONE;
185 const opKeyword kw = analyzeOperator (operator);
186 *found = (boolean) (kw != OP_UNDEFINED);
187 if (*found)
189 result = OpKinds [kw].kind;
190 Assert (OpKinds [kw].keyword == kw);
192 return result;
195 /* We must check for "DB", "DB.L", "DCB.W" (68000)
197 static boolean isDefineOperator (const vString *const operator)
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;
210 static void makeAsmTag (
211 const vString *const name,
212 const vString *const operator,
213 const boolean labelCandidate,
214 const boolean nameFollows)
216 if (vStringLength (name) > 0)
218 boolean found;
219 const AsmKind kind = operatorKind (operator, &found);
220 if (found)
222 if (kind != K_NONE)
223 makeSimpleTag (name, AsmKinds, kind);
225 else if (isDefineOperator (operator))
227 if (! nameFollows)
228 makeSimpleTag (name, AsmKinds, K_DEFINE);
230 else if (labelCandidate)
232 operatorKind (name, &found);
233 if (! found)
234 makeSimpleTag (name, AsmKinds, K_LABEL);
239 static const unsigned char *readSymbol (
240 const unsigned char *const start,
241 vString *const sym)
243 const unsigned char *cp = start;
244 vStringClear (sym);
245 if (isInitialSymbolCharacter ((int) *cp))
247 while (isSymbolCharacter ((int) *cp))
249 vStringPut (sym, *cp);
250 ++cp;
252 vStringTerminate (sym);
254 return cp;
257 static const unsigned char *readOperator (
258 const unsigned char *const start,
259 vString *const operator)
261 const unsigned char *cp = start;
262 vStringClear (operator);
263 while (*cp != '\0' && ! isspace ((int) *cp))
265 vStringPut (operator, *cp);
266 ++cp;
268 vStringTerminate (operator);
269 return cp;
272 static void findAsmTags (void)
274 vString *name = vStringNew ();
275 vString *operator = vStringNew ();
276 const unsigned char *line;
277 boolean inCComment = FALSE;
279 while ((line = fileReadLine ()) != NULL)
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);
287 /* skip comments */
288 if (strncmp ((const char*) cp, "/*", (size_t) 2) == 0)
290 inCComment = TRUE;
291 cp += 2;
293 if (inCComment)
297 if (strncmp ((const char*) cp, "*/", (size_t) 2) == 0)
299 inCComment = FALSE;
300 cp += 2;
301 break;
303 ++cp;
304 } while (*cp != '\0');
306 if (isComment || inCComment)
307 continue;
309 /* read preprocessor defines */
310 if (*cp == '#')
312 ++cp;
313 readPreProc (cp);
314 continue;
317 /* skip white space */
318 while (isspace ((int) *cp))
319 ++cp;
321 /* read symbol */
322 cp = readSymbol (cp, name);
323 if (vStringLength (name) > 0 && *cp == ':')
325 labelCandidate = TRUE;
326 ++cp;
329 if (! isspace ((int) *cp) && *cp != '\0')
330 continue;
332 /* skip white space */
333 while (isspace ((int) *cp))
334 ++cp;
336 /* skip leading dot */
337 #if 0
338 if (*cp == '.')
339 ++cp;
340 #endif
342 cp = readOperator (cp, operator);
344 /* attempt second read of symbol */
345 if (vStringLength (name) == 0)
347 while (isspace ((int) *cp))
348 ++cp;
349 cp = readSymbol (cp, name);
350 nameFollows = TRUE;
352 makeAsmTag (name, operator, labelCandidate, nameFollows);
354 vStringDelete (name);
355 vStringDelete (operator);
358 static void initialize (const langType language)
360 Lang_asm = language;
361 buildAsmKeywordHash ();
364 extern parserDefinition* AsmParser (void)
366 static const char *const extensions [] = {
367 "asm", "ASM", "s", "S", NULL
369 static const char *const patterns [] = {
370 "*.A51",
371 "*.29[kK]",
372 "*.[68][68][kKsSxX]",
373 "*.[xX][68][68]",
374 NULL
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;
386 /* vi:set tabstop=4 shiftwidth=4: */