fix wrongly interpreted >> in template
[arduino-ctags.git] / asm.c
blob8c1ff2badf69e1021c15dee311200b0dd01ee009
1 /*
2 * $Id: asm.c 536 2007-06-02 06:09:00Z elliotth $
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 vString *keyword = vStringNew ();
133 opKeyword result;
135 vStringCopyToLower (keyword, op);
136 result = (opKeyword) lookupKeyword (vStringValue (keyword), Lang_asm);
137 vStringDelete (keyword);
138 return result;
141 static boolean isInitialSymbolCharacter (int c)
143 return (boolean) (c != '\0' && (isalpha (c) || strchr ("_$", c) != NULL));
146 static boolean isSymbolCharacter (int c)
148 /* '?' character is allowed in AMD 29K family */
149 return (boolean) (c != '\0' && (isalnum (c) || strchr ("_$?", c) != NULL));
152 static boolean readPreProc (const unsigned char *const line)
154 boolean result;
155 const unsigned char *cp = line;
156 vString *name = vStringNew ();
157 while (isSymbolCharacter ((int) *cp))
159 vStringPut (name, *cp);
160 ++cp;
162 vStringTerminate (name);
163 result = (boolean) (strcmp (vStringValue (name), "define") == 0);
164 if (result)
166 while (isspace ((int) *cp))
167 ++cp;
168 vStringClear (name);
169 while (isSymbolCharacter ((int) *cp))
171 vStringPut (name, *cp);
172 ++cp;
174 vStringTerminate (name);
175 makeSimpleTag (name, AsmKinds, K_DEFINE);
177 vStringDelete (name);
178 return result;
181 static AsmKind operatorKind (
182 const vString *const operator,
183 boolean *const found)
185 AsmKind result = K_NONE;
186 const opKeyword kw = analyzeOperator (operator);
187 *found = (boolean) (kw != OP_UNDEFINED);
188 if (*found)
190 result = OpKinds [kw].kind;
191 Assert (OpKinds [kw].keyword == kw);
193 return result;
196 /* We must check for "DB", "DB.L", "DCB.W" (68000)
198 static boolean isDefineOperator (const vString *const operator)
200 const unsigned char *const op =
201 (unsigned char*) vStringValue (operator);
202 const size_t length = vStringLength (operator);
203 const boolean result = (boolean) (length > 0 &&
204 toupper ((int) *op) == 'D' &&
205 (length == 2 ||
206 (length == 4 && (int) op [2] == '.') ||
207 (length == 5 && (int) op [3] == '.')));
208 return result;
211 static void makeAsmTag (
212 const vString *const name,
213 const vString *const operator,
214 const boolean labelCandidate,
215 const boolean nameFollows)
217 if (vStringLength (name) > 0)
219 boolean found;
220 const AsmKind kind = operatorKind (operator, &found);
221 if (found)
223 if (kind != K_NONE)
224 makeSimpleTag (name, AsmKinds, kind);
226 else if (isDefineOperator (operator))
228 if (! nameFollows)
229 makeSimpleTag (name, AsmKinds, K_DEFINE);
231 else if (labelCandidate)
233 operatorKind (name, &found);
234 if (! found)
235 makeSimpleTag (name, AsmKinds, K_LABEL);
240 static const unsigned char *readSymbol (
241 const unsigned char *const start,
242 vString *const sym)
244 const unsigned char *cp = start;
245 vStringClear (sym);
246 if (isInitialSymbolCharacter ((int) *cp))
248 while (isSymbolCharacter ((int) *cp))
250 vStringPut (sym, *cp);
251 ++cp;
253 vStringTerminate (sym);
255 return cp;
258 static const unsigned char *readOperator (
259 const unsigned char *const start,
260 vString *const operator)
262 const unsigned char *cp = start;
263 vStringClear (operator);
264 while (*cp != '\0' && ! isspace ((int) *cp))
266 vStringPut (operator, *cp);
267 ++cp;
269 vStringTerminate (operator);
270 return cp;
273 static void findAsmTags (void)
275 vString *name = vStringNew ();
276 vString *operator = vStringNew ();
277 const unsigned char *line;
278 boolean inCComment = FALSE;
280 while ((line = fileReadLine ()) != NULL)
282 const unsigned char *cp = line;
283 boolean labelCandidate = (boolean) (! isspace ((int) *cp));
284 boolean nameFollows = FALSE;
285 const boolean isComment = (boolean)
286 (*cp != '\0' && strchr (";*@", *cp) != NULL);
288 /* skip comments */
289 if (strncmp ((const char*) cp, "/*", (size_t) 2) == 0)
291 inCComment = TRUE;
292 cp += 2;
294 if (inCComment)
298 if (strncmp ((const char*) cp, "*/", (size_t) 2) == 0)
300 inCComment = FALSE;
301 cp += 2;
302 break;
304 ++cp;
305 } while (*cp != '\0');
307 if (isComment || inCComment)
308 continue;
310 /* read preprocessor defines */
311 if (*cp == '#')
313 ++cp;
314 readPreProc (cp);
315 continue;
318 /* skip white space */
319 while (isspace ((int) *cp))
320 ++cp;
322 /* read symbol */
323 cp = readSymbol (cp, name);
324 if (vStringLength (name) > 0 && *cp == ':')
326 labelCandidate = TRUE;
327 ++cp;
330 if (! isspace ((int) *cp) && *cp != '\0')
331 continue;
333 /* skip white space */
334 while (isspace ((int) *cp))
335 ++cp;
337 /* skip leading dot */
338 #if 0
339 if (*cp == '.')
340 ++cp;
341 #endif
343 cp = readOperator (cp, operator);
345 /* attempt second read of symbol */
346 if (vStringLength (name) == 0)
348 while (isspace ((int) *cp))
349 ++cp;
350 cp = readSymbol (cp, name);
351 nameFollows = TRUE;
353 makeAsmTag (name, operator, labelCandidate, nameFollows);
355 vStringDelete (name);
356 vStringDelete (operator);
359 static void initialize (const langType language)
361 Lang_asm = language;
362 buildAsmKeywordHash ();
365 extern parserDefinition* AsmParser (void)
367 static const char *const extensions [] = {
368 "asm", "ASM", "s", "S", NULL
370 static const char *const patterns [] = {
371 "*.A51",
372 "*.29[kK]",
373 "*.[68][68][kKsSxX]",
374 "*.[xX][68][68]",
375 NULL
377 parserDefinition* def = parserNew ("Asm");
378 def->kinds = AsmKinds;
379 def->kindCount = KIND_COUNT (AsmKinds);
380 def->extensions = extensions;
381 def->patterns = patterns;
382 def->parser = findAsmTags;
383 def->initialize = initialize;
384 return def;
387 /* vi:set tabstop=4 shiftwidth=4: */