Use non-symlinked VTE libraries on macOS (#1625)
[geany-mirror.git] / ctags / parsers / asm.c
blob8003a2388741407b079562b2530288c23a76bf5a
1 /*
2 * Copyright (c) 2000-2003, Darren Hiebert
4 * This source code is released for free distribution under the terms of the
5 * GNU General Public License version 2 or (at your option) any later version.
7 * This module contains functions for generating tags for assembly language
8 * files.
9 */
12 * INCLUDE FILES
14 #include "general.h" /* must always come first */
16 #include <string.h>
18 #include "debug.h"
19 #include "keyword.h"
20 #include "parse.h"
21 #include "read.h"
22 #include "routines.h"
23 #include "vstring.h"
26 * DATA DECLARATIONS
28 typedef enum {
29 K_NONE = -1, K_DEFINE, K_LABEL, K_MACRO, K_TYPE
30 } AsmKind;
32 typedef enum {
33 OP_UNDEFINED = -1,
34 OP_ALIGN,
35 OP_COLON_EQUAL,
36 OP_END,
37 OP_ENDM,
38 OP_ENDMACRO,
39 OP_ENDP,
40 OP_ENDS,
41 OP_EQU,
42 OP_EQUAL,
43 OP_LABEL,
44 OP_MACRO,
45 OP_PROC,
46 OP_RECORD,
47 OP_SECTIONS,
48 OP_SET,
49 OP_STRUCT,
50 OP_LAST
51 } opKeyword;
53 typedef struct {
54 opKeyword keyword;
55 AsmKind kind;
56 } opKind;
59 * DATA DEFINITIONS
61 static langType Lang_asm;
63 static kindOption AsmKinds [] = {
64 { true, 'd', "define", "defines" },
65 { true, 'l', "label", "labels" },
66 { true, 'm', "macro", "macros" },
67 { true, 't', "type", "types (structs and records)" }
70 static const keywordTable AsmKeywords [] = {
71 { "align", OP_ALIGN },
72 { "endmacro", OP_ENDMACRO },
73 { "endm", OP_ENDM },
74 { "end", OP_END },
75 { "endp", OP_ENDP },
76 { "ends", OP_ENDS },
77 { "equ", OP_EQU },
78 { "label", OP_LABEL },
79 { "macro", OP_MACRO },
80 { ":=", OP_COLON_EQUAL },
81 { "=", OP_EQUAL },
82 { "proc", OP_PROC },
83 { "record", OP_RECORD },
84 { "sections", OP_SECTIONS },
85 { "set", OP_SET },
86 { "struct", OP_STRUCT }
89 static const opKind OpKinds [] = {
90 /* must be ordered same as opKeyword enumeration */
91 { OP_ALIGN, K_NONE },
92 { OP_COLON_EQUAL, K_DEFINE },
93 { OP_END, K_NONE },
94 { OP_ENDM, K_NONE },
95 { OP_ENDMACRO, K_NONE },
96 { OP_ENDP, K_NONE },
97 { OP_ENDS, K_NONE },
98 { OP_EQU, K_DEFINE },
99 { OP_EQUAL, K_DEFINE },
100 { OP_LABEL, K_LABEL },
101 { OP_MACRO, K_MACRO },
102 { OP_PROC, K_LABEL },
103 { OP_RECORD, K_TYPE },
104 { OP_SECTIONS, K_NONE },
105 { OP_SET, K_DEFINE },
106 { OP_STRUCT, K_TYPE }
110 * FUNCTION DEFINITIONS
112 static opKeyword analyzeOperator (const vString *const op)
114 vString *keyword = vStringNew ();
115 opKeyword result;
117 vStringCopyToLower (keyword, op);
118 result = (opKeyword) lookupKeyword (vStringValue (keyword), Lang_asm);
119 vStringDelete (keyword);
120 return result;
123 static bool isInitialSymbolCharacter (int c)
125 return (bool) (c != '\0' && (isalpha (c) || strchr ("_$", c) != NULL));
128 static bool isSymbolCharacter (int c)
130 /* '?' character is allowed in AMD 29K family */
131 return (bool) (c != '\0' && (isalnum (c) || strchr ("_$?", c) != NULL));
134 static bool readPreProc (const unsigned char *const line)
136 bool result;
137 const unsigned char *cp = line;
138 vString *name = vStringNew ();
139 while (isSymbolCharacter ((int) *cp))
141 vStringPut (name, *cp);
142 ++cp;
144 result = (bool) (strcmp (vStringValue (name), "define") == 0);
145 if (result)
147 while (isspace ((int) *cp))
148 ++cp;
149 vStringClear (name);
150 while (isSymbolCharacter ((int) *cp))
152 vStringPut (name, *cp);
153 ++cp;
155 makeSimpleTag (name, AsmKinds, K_DEFINE);
157 vStringDelete (name);
158 return result;
161 static AsmKind operatorKind (
162 const vString *const operator,
163 bool *const found)
165 AsmKind result = K_NONE;
166 const opKeyword kw = analyzeOperator (operator);
167 *found = (bool) (kw != OP_UNDEFINED);
168 if (*found)
170 result = OpKinds [kw].kind;
171 Assert (OpKinds [kw].keyword == kw);
173 return result;
176 /* We must check for "DB", "DB.L", "DCB.W" (68000)
178 static bool isDefineOperator (const vString *const operator)
180 const unsigned char *const op =
181 (unsigned char*) vStringValue (operator);
182 const size_t length = vStringLength (operator);
183 const bool result = (bool) (length > 0 &&
184 toupper ((int) *op) == 'D' &&
185 (length == 2 ||
186 (length == 4 && (int) op [2] == '.') ||
187 (length == 5 && (int) op [3] == '.')));
188 return result;
191 static void makeAsmTag (
192 const vString *const name,
193 const vString *const operator,
194 const bool labelCandidate,
195 const bool nameFollows)
197 if (vStringLength (name) > 0)
199 bool found;
200 const AsmKind kind = operatorKind (operator, &found);
201 if (found)
203 if (kind != K_NONE)
204 makeSimpleTag (name, AsmKinds, kind);
206 else if (isDefineOperator (operator))
208 if (! nameFollows)
209 makeSimpleTag (name, AsmKinds, K_DEFINE);
211 else if (labelCandidate)
213 operatorKind (name, &found);
214 if (! found)
215 makeSimpleTag (name, AsmKinds, K_LABEL);
220 static const unsigned char *readSymbol (
221 const unsigned char *const start,
222 vString *const sym)
224 const unsigned char *cp = start;
225 vStringClear (sym);
226 if (isInitialSymbolCharacter ((int) *cp))
228 while (isSymbolCharacter ((int) *cp))
230 vStringPut (sym, *cp);
231 ++cp;
234 return cp;
237 static const unsigned char *readOperator (
238 const unsigned char *const start,
239 vString *const operator)
241 const unsigned char *cp = start;
242 vStringClear (operator);
243 while (*cp != '\0' && ! isspace ((int) *cp))
245 vStringPut (operator, *cp);
246 ++cp;
248 return cp;
251 static void findAsmTags (void)
253 vString *name = vStringNew ();
254 vString *operator = vStringNew ();
255 const unsigned char *line;
256 bool inCComment = false;
258 while ((line = readLineFromInputFile ()) != NULL)
260 const unsigned char *cp = line;
261 bool labelCandidate = (bool) (! isspace ((int) *cp));
262 bool nameFollows = false;
263 const bool isComment = (bool)
264 (*cp != '\0' && strchr (";*@", *cp) != NULL);
266 /* skip comments */
267 if (strncmp ((const char*) cp, "/*", (size_t) 2) == 0)
269 inCComment = true;
270 cp += 2;
272 if (inCComment)
276 if (strncmp ((const char*) cp, "*/", (size_t) 2) == 0)
278 inCComment = false;
279 cp += 2;
280 break;
282 ++cp;
283 } while (*cp != '\0');
285 if (isComment || inCComment)
286 continue;
288 /* read preprocessor defines */
289 if (*cp == '#')
291 ++cp;
292 readPreProc (cp);
293 continue;
296 /* skip white space */
297 while (isspace ((int) *cp))
298 ++cp;
300 /* read symbol */
301 cp = readSymbol (cp, name);
302 if (vStringLength (name) > 0 && *cp == ':')
304 labelCandidate = true;
305 ++cp;
308 if (! isspace ((int) *cp) && *cp != '\0')
309 continue;
311 /* skip white space */
312 while (isspace ((int) *cp))
313 ++cp;
315 /* skip leading dot */
316 #if 0
317 if (*cp == '.')
318 ++cp;
319 #endif
321 cp = readOperator (cp, operator);
323 /* attempt second read of symbol */
324 if (vStringLength (name) == 0)
326 while (isspace ((int) *cp))
327 ++cp;
328 cp = readSymbol (cp, name);
329 nameFollows = true;
331 makeAsmTag (name, operator, labelCandidate, nameFollows);
333 vStringDelete (name);
334 vStringDelete (operator);
337 static void initialize (const langType language)
339 Lang_asm = language;
342 extern parserDefinition* AsmParser (void)
344 static const char *const extensions [] = {
345 "asm", "ASM", "s", "S", NULL
347 static const char *const patterns [] = {
348 "*.A51",
349 "*.29[kK]",
350 "*.[68][68][kKsSxX]",
351 "*.[xX][68][68]",
352 NULL
354 parserDefinition* def = parserNew ("Asm");
355 def->kinds = AsmKinds;
356 def->kindCount = ARRAY_SIZE (AsmKinds);
357 def->extensions = extensions;
358 def->patterns = patterns;
359 def->parser = findAsmTags;
360 def->initialize = initialize;
361 def->keywordTable = AsmKeywords;
362 def->keywordCount = ARRAY_SIZE (AsmKeywords);
363 return def;