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
14 #include "general.h" /* must always come first */
29 K_NONE
= -1, K_DEFINE
, K_LABEL
, K_MACRO
, K_TYPE
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
},
78 { "label", OP_LABEL
},
79 { "macro", OP_MACRO
},
80 { ":=", OP_COLON_EQUAL
},
83 { "record", OP_RECORD
},
84 { "sections", OP_SECTIONS
},
86 { "struct", OP_STRUCT
}
89 static const opKind OpKinds
[] = {
90 /* must be ordered same as opKeyword enumeration */
92 { OP_COLON_EQUAL
, K_DEFINE
},
95 { OP_ENDMACRO
, K_NONE
},
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 ();
117 vStringCopyToLower (keyword
, op
);
118 result
= (opKeyword
) lookupKeyword (vStringValue (keyword
), Lang_asm
);
119 vStringDelete (keyword
);
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
)
137 const unsigned char *cp
= line
;
138 vString
*name
= vStringNew ();
139 while (isSymbolCharacter ((int) *cp
))
141 vStringPut (name
, *cp
);
144 result
= (bool) (strcmp (vStringValue (name
), "define") == 0);
147 while (isspace ((int) *cp
))
150 while (isSymbolCharacter ((int) *cp
))
152 vStringPut (name
, *cp
);
155 makeSimpleTag (name
, AsmKinds
, K_DEFINE
);
157 vStringDelete (name
);
161 static AsmKind
operatorKind (
162 const vString
*const operator,
165 AsmKind result
= K_NONE
;
166 const opKeyword kw
= analyzeOperator (operator);
167 *found
= (bool) (kw
!= OP_UNDEFINED
);
170 result
= OpKinds
[kw
].kind
;
171 Assert (OpKinds
[kw
].keyword
== kw
);
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' &&
186 (length
== 4 && (int) op
[2] == '.') ||
187 (length
== 5 && (int) op
[3] == '.')));
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)
200 const AsmKind kind
= operatorKind (operator, &found
);
204 makeSimpleTag (name
, AsmKinds
, kind
);
206 else if (isDefineOperator (operator))
209 makeSimpleTag (name
, AsmKinds
, K_DEFINE
);
211 else if (labelCandidate
)
213 operatorKind (name
, &found
);
215 makeSimpleTag (name
, AsmKinds
, K_LABEL
);
220 static const unsigned char *readSymbol (
221 const unsigned char *const start
,
224 const unsigned char *cp
= start
;
226 if (isInitialSymbolCharacter ((int) *cp
))
228 while (isSymbolCharacter ((int) *cp
))
230 vStringPut (sym
, *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
);
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
);
267 if (strncmp ((const char*) cp
, "/*", (size_t) 2) == 0)
276 if (strncmp ((const char*) cp
, "*/", (size_t) 2) == 0)
283 } while (*cp
!= '\0');
285 if (isComment
|| inCComment
)
288 /* read preprocessor defines */
296 /* skip white space */
297 while (isspace ((int) *cp
))
301 cp
= readSymbol (cp
, name
);
302 if (vStringLength (name
) > 0 && *cp
== ':')
304 labelCandidate
= true;
308 if (! isspace ((int) *cp
) && *cp
!= '\0')
311 /* skip white space */
312 while (isspace ((int) *cp
))
315 /* skip leading dot */
321 cp
= readOperator (cp
, operator);
323 /* attempt second read of symbol */
324 if (vStringLength (name
) == 0)
326 while (isspace ((int) *cp
))
328 cp
= readSymbol (cp
, name
);
331 makeAsmTag (name
, operator, labelCandidate
, nameFollows
);
333 vStringDelete (name
);
334 vStringDelete (operator);
337 static void initialize (const langType language
)
342 extern parserDefinition
* AsmParser (void)
344 static const char *const extensions
[] = {
345 "asm", "ASM", "s", "S", NULL
347 static const char *const patterns
[] = {
350 "*.[68][68][kKsSxX]",
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
);