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
16 #include "general.h" /* must always come first */
30 K_NONE
= -1, K_DEFINE
, K_LABEL
, K_MACRO
, K_TYPE
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
},
84 { "label", OP_LABEL
},
85 { "macro", OP_MACRO
},
86 { ":=", OP_COLON_EQUAL
},
89 { "record", OP_RECORD
},
90 { "sections", OP_SECTIONS
},
92 { "struct", OP_STRUCT
}
95 static const opKind OpKinds
[] = {
96 /* must be ordered same as opKeyword enumeration */
98 { OP_COLON_EQUAL
, K_DEFINE
},
101 { OP_ENDMACRO
, 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]);
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 ();
134 vStringCopyToLower (keyword
, op
);
135 result
= (opKeyword
) lookupKeyword (vStringValue (keyword
), Lang_asm
);
136 vStringDelete (keyword
);
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
)
154 const unsigned char *cp
= line
;
155 vString
*name
= vStringNew ();
156 while (isSymbolCharacter ((int) *cp
))
158 vStringPut (name
, *cp
);
161 vStringTerminate (name
);
162 result
= (boolean
) (strcmp (vStringValue (name
), "define") == 0);
165 while (isspace ((int) *cp
))
168 while (isSymbolCharacter ((int) *cp
))
170 vStringPut (name
, *cp
);
173 vStringTerminate (name
);
174 makeSimpleTag (name
, AsmKinds
, K_DEFINE
);
176 vStringDelete (name
);
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
);
189 result
= OpKinds
[kw
].kind
;
190 Assert (OpKinds
[kw
].keyword
== kw
);
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' &&
205 (length
== 4 && (int) op
[2] == '.') ||
206 (length
== 5 && (int) op
[3] == '.')));
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)
219 const AsmKind kind
= operatorKind (operator, &found
);
223 makeSimpleTag (name
, AsmKinds
, kind
);
225 else if (isDefineOperator (operator))
228 makeSimpleTag (name
, AsmKinds
, K_DEFINE
);
230 else if (labelCandidate
)
232 operatorKind (name
, &found
);
234 makeSimpleTag (name
, AsmKinds
, K_LABEL
);
239 static const unsigned char *readSymbol (
240 const unsigned char *const start
,
243 const unsigned char *cp
= start
;
245 if (isInitialSymbolCharacter ((int) *cp
))
247 while (isSymbolCharacter ((int) *cp
))
249 vStringPut (sym
, *cp
);
252 vStringTerminate (sym
);
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
);
268 vStringTerminate (operator);
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
);
288 if (strncmp ((const char*) cp
, "/*", (size_t) 2) == 0)
297 if (strncmp ((const char*) cp
, "*/", (size_t) 2) == 0)
304 } while (*cp
!= '\0');
306 if (isComment
|| inCComment
)
309 /* read preprocessor defines */
317 /* skip white space */
318 while (isspace ((int) *cp
))
322 cp
= readSymbol (cp
, name
);
323 if (vStringLength (name
) > 0 && *cp
== ':')
325 labelCandidate
= TRUE
;
329 if (! isspace ((int) *cp
) && *cp
!= '\0')
332 /* skip white space */
333 while (isspace ((int) *cp
))
336 /* skip leading dot */
342 cp
= readOperator (cp
, operator);
344 /* attempt second read of symbol */
345 if (vStringLength (name
) == 0)
347 while (isspace ((int) *cp
))
349 cp
= readSymbol (cp
, name
);
352 makeAsmTag (name
, operator, labelCandidate
, nameFollows
);
354 vStringDelete (name
);
355 vStringDelete (operator);
358 static void initialize (const langType 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
[] = {
372 "*.[68][68][kKsSxX]",
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
;
386 /* vi:set tabstop=4 shiftwidth=4: */