Replace utils_make_human_readable_str() with g_format_size()
[geany-mirror.git] / ctags / parsers / asm.c
bloba3679499e0a9161b51b804ed49f7efaca2fa910b
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 "cpreprocessor.h"
19 #include "debug.h"
20 #include "entry.h"
21 #include "keyword.h"
22 #include "parse.h"
23 #include "read.h"
24 #include "routines.h"
25 #include "selectors.h"
26 #include "vstring.h"
29 * DATA DECLARATIONS
31 typedef enum {
32 K_PSUEDO_MACRO_END = -2,
33 K_NONE = -1, K_DEFINE, K_LABEL, K_MACRO, K_TYPE,
34 K_SECTION,
35 } AsmKind;
37 typedef enum {
38 OP_UNDEFINED = -1,
39 OP_ALIGN,
40 OP_COLON_EQUAL,
41 OP_END,
42 OP_ENDM,
43 OP_ENDMACRO,
44 OP_ENDP,
45 OP_ENDS,
46 OP_EQU,
47 OP_EQUAL,
48 OP_LABEL,
49 OP_MACRO,
50 OP_PROC,
51 OP_RECORD,
52 OP_SECTIONS,
53 OP_SECTION,
54 OP_SET,
55 OP_STRUCT,
56 OP_LAST
57 } opKeyword;
59 typedef enum {
60 ASM_SECTION_PLACEMENT,
61 } asmSectionRole;
63 typedef struct {
64 opKeyword keyword;
65 AsmKind kind;
66 } opKind;
69 * DATA DEFINITIONS
71 static langType Lang_asm;
73 static roleDefinition asmSectionRoles [] = {
74 { true, "placement", "placement where the assembled code goes" },
77 static kindDefinition AsmKinds [] = {
78 { true, 'd', "define", "defines" },
79 { true, 'l', "label", "labels" },
80 { true, 'm', "macro", "macros" },
81 { true, 't', "type", "types (structs and records)" },
82 { true, 's', "section", "sections",
83 .referenceOnly = true, ATTACH_ROLES(asmSectionRoles)},
86 static const keywordTable AsmKeywords [] = {
87 { "align", OP_ALIGN },
88 { "endmacro", OP_ENDMACRO },
89 { "endm", OP_ENDM },
90 { "end", OP_END },
91 { "endp", OP_ENDP },
92 { "ends", OP_ENDS },
93 { "equ", OP_EQU },
94 { "label", OP_LABEL },
95 { "macro", OP_MACRO },
96 { ":=", OP_COLON_EQUAL },
97 { "=", OP_EQUAL },
98 { "proc", OP_PROC },
99 { "record", OP_RECORD },
100 { "sections", OP_SECTIONS },
102 /* These are used in GNU as. */
103 { "section", OP_SECTION },
104 { "equiv", OP_EQU },
105 { "eqv", OP_EQU },
107 { "set", OP_SET },
108 { "struct", OP_STRUCT }
111 static const opKind OpKinds [] = {
112 /* must be ordered same as opKeyword enumeration */
113 { OP_ALIGN, K_NONE },
114 { OP_COLON_EQUAL, K_DEFINE },
115 { OP_END, K_NONE },
116 { OP_ENDM, K_PSUEDO_MACRO_END },
117 { OP_ENDMACRO, K_NONE },
118 { OP_ENDP, K_NONE },
119 { OP_ENDS, K_NONE },
120 { OP_EQU, K_DEFINE },
121 { OP_EQUAL, K_DEFINE },
122 { OP_LABEL, K_LABEL },
123 { OP_MACRO, K_MACRO },
124 { OP_PROC, K_LABEL },
125 { OP_RECORD, K_TYPE },
126 { OP_SECTIONS, K_NONE },
127 { OP_SECTION, K_SECTION },
128 { OP_SET, K_DEFINE },
129 { OP_STRUCT, K_TYPE }
133 * FUNCTION DEFINITIONS
135 static opKeyword analyzeOperator (const vString *const op)
137 vString *keyword = vStringNew ();
138 opKeyword result;
140 vStringCopyToLower (keyword, op);
141 result = (opKeyword) lookupKeyword (vStringValue (keyword), Lang_asm);
142 vStringDelete (keyword);
143 return result;
146 static bool isInitialSymbolCharacter (int c)
148 return (bool) (c != '\0' && (isalpha (c) || strchr ("_$", c) != NULL));
151 static bool isSymbolCharacter (int c)
153 /* '?' character is allowed in AMD 29K family */
154 return (bool) (c != '\0' && (isalnum (c) || strchr ("_$?", c) != NULL));
157 static AsmKind operatorKind (
158 const vString *const operator,
159 bool *const found)
161 AsmKind result = K_NONE;
162 const opKeyword kw = analyzeOperator (operator);
163 *found = (bool) (kw != OP_UNDEFINED);
164 if (*found)
166 result = OpKinds [kw].kind;
167 Assert (OpKinds [kw].keyword == kw);
169 return result;
172 /* We must check for "DB", "DB.L", "DCB.W" (68000)
174 static bool isDefineOperator (const vString *const operator)
176 const unsigned char *const op =
177 (unsigned char*) vStringValue (operator);
178 const size_t length = vStringLength (operator);
179 const bool result = (bool) (length > 0 &&
180 toupper ((int) *op) == 'D' &&
181 (length == 2 ||
182 (length == 4 && (int) op [2] == '.') ||
183 (length == 5 && (int) op [3] == '.')));
184 return result;
187 static void makeAsmTag (
188 const vString *const name,
189 const vString *const operator,
190 const bool labelCandidate,
191 const bool nameFollows,
192 const bool directive,
193 int *lastMacroCorkIndex)
195 if (vStringLength (name) > 0)
197 bool found;
198 const AsmKind kind = operatorKind (operator, &found);
199 if (found)
201 if (kind > K_NONE)
202 makeSimpleTag (name, kind);
204 else if (isDefineOperator (operator))
206 if (! nameFollows)
207 makeSimpleTag (name, K_DEFINE);
209 else if (labelCandidate)
211 operatorKind (name, &found);
212 if (! found)
213 makeSimpleTag (name, K_LABEL);
215 else if (directive)
217 bool found_dummy;
218 const AsmKind kind_for_directive = operatorKind (name, &found_dummy);
219 tagEntryInfo *macro_tag;
221 switch (kind_for_directive)
223 case K_NONE:
224 break;
225 case K_MACRO:
226 *lastMacroCorkIndex = makeSimpleTag (operator,
227 kind_for_directive);
228 if (*lastMacroCorkIndex != CORK_NIL)
229 registerEntry (*lastMacroCorkIndex);
230 break;
231 case K_PSUEDO_MACRO_END:
232 macro_tag = getEntryInCorkQueue (*lastMacroCorkIndex);
233 if (macro_tag)
234 macro_tag->extensionFields.endLine = getInputLineNumber ();
235 *lastMacroCorkIndex = CORK_NIL;
236 break;
237 case K_SECTION:
238 makeSimpleRefTag (operator,
239 kind_for_directive,
240 ASM_SECTION_PLACEMENT);
241 break;
242 default:
243 makeSimpleTag (operator, kind_for_directive);
249 static const unsigned char *readSymbol (
250 const unsigned char *const start,
251 vString *const sym)
253 const unsigned char *cp = start;
254 vStringClear (sym);
255 if (isInitialSymbolCharacter ((int) *cp))
257 while (isSymbolCharacter ((int) *cp))
259 vStringPut (sym, *cp);
260 ++cp;
263 return cp;
266 static const unsigned char *readOperator (
267 const unsigned char *const start,
268 vString *const operator)
270 const unsigned char *cp = start;
271 vStringClear (operator);
272 while (*cp != '\0' && ! isspace ((int) *cp) && *cp != ',')
274 vStringPut (operator, *cp);
275 ++cp;
277 return cp;
280 static const unsigned char *asmReadLineFromInputFile (void)
282 static vString *line;
283 int c;
285 line = vStringNewOrClear (line);
287 while ((c = cppGetc()) != EOF)
289 if (c == '\n')
290 break;
291 else if (c == STRING_SYMBOL || c == CHAR_SYMBOL)
293 /* We cannot store these values to vString
294 * Store a whitespace as a dummy value for them.
296 vStringPut (line, ' ');
298 else
299 vStringPut (line, c);
302 if ((vStringLength (line) == 0)&& (c == EOF))
303 return NULL;
304 else
305 return (unsigned char *)vStringValue (line);
308 static void findAsmTags (void)
310 vString *name = vStringNew ();
311 vString *operator = vStringNew ();
312 const unsigned char *line;
314 cppInit (false, false, false, false,
315 KIND_GHOST_INDEX, 0, KIND_GHOST_INDEX, KIND_GHOST_INDEX, 0, 0,
316 FIELD_UNKNOWN);
318 int lastMacroCorkIndex = CORK_NIL;
320 while ((line = asmReadLineFromInputFile ()) != NULL)
322 const unsigned char *cp = line;
323 bool labelCandidate = (bool) (! isspace ((int) *cp));
324 bool nameFollows = false;
325 bool directive = false;
326 const bool isComment = (bool)
327 (*cp != '\0' && strchr (";*@", *cp) != NULL);
329 /* skip comments */
330 if (isComment)
331 continue;
333 /* skip white space */
334 while (isspace ((int) *cp))
335 ++cp;
337 /* read symbol */
338 if (*cp == '.')
340 directive = true;
341 labelCandidate = false;
342 ++cp;
345 cp = readSymbol (cp, name);
346 if (vStringLength (name) > 0)
348 if (*cp == ':')
350 labelCandidate = true;
351 ++cp;
353 else if (anyKindEntryInScope (CORK_NIL,
354 vStringValue (name),
355 K_MACRO))
356 labelCandidate = false;
359 if (! isspace ((int) *cp) && *cp != '\0')
360 continue;
362 /* skip white space */
363 while (isspace ((int) *cp))
364 ++cp;
366 /* skip leading dot */
367 #if 0
368 if (*cp == '.')
369 ++cp;
370 #endif
372 cp = readOperator (cp, operator);
374 /* attempt second read of symbol */
375 if (vStringLength (name) == 0)
377 while (isspace ((int) *cp))
378 ++cp;
379 cp = readSymbol (cp, name);
380 nameFollows = true;
382 makeAsmTag (name, operator, labelCandidate, nameFollows, directive,
383 &lastMacroCorkIndex);
386 cppTerminate ();
388 vStringDelete (name);
389 vStringDelete (operator);
392 static void initialize (const langType language)
394 Lang_asm = language;
397 extern parserDefinition* AsmParser (void)
399 static const char *const extensions [] = {
400 "asm", "ASM", "s", "S", NULL
402 static const char *const patterns [] = {
403 "*.A51",
404 "*.29[kK]",
405 "*.[68][68][kKsSxX]",
406 "*.[xX][68][68]",
407 NULL
409 static selectLanguage selectors[] = { selectByArrowOfR,
410 NULL };
412 parserDefinition* def = parserNew ("Asm");
413 def->kindTable = AsmKinds;
414 def->kindCount = ARRAY_SIZE (AsmKinds);
415 def->extensions = extensions;
416 def->patterns = patterns;
417 def->parser = findAsmTags;
418 def->initialize = initialize;
419 def->keywordTable = AsmKeywords;
420 def->keywordCount = ARRAY_SIZE (AsmKeywords);
421 def->selectLanguage = selectors;
422 def->useCork = CORK_QUEUE | CORK_SYMTAB;
423 return def;