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 */
31 K_NONE
= -1, K_DEFINE
, K_LABEL
, K_MACRO
, K_TYPE
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
},
85 { "label", OP_LABEL
},
86 { "macro", OP_MACRO
},
87 { ":=", OP_COLON_EQUAL
},
90 { "record", OP_RECORD
},
91 { "sections", OP_SECTIONS
},
93 { "struct", OP_STRUCT
}
96 static const opKind OpKinds
[] = {
97 /* must be ordered same as opKeyword enumeration */
99 { OP_COLON_EQUAL
, K_DEFINE
},
102 { OP_ENDMACRO
, 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]);
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 static vString
*keyword
= NULL
;
133 opKeyword result
= OP_UNDEFINED
;
136 keyword
= vStringNew ();
137 vStringCopyToLower (keyword
, op
);
138 result
= (opKeyword
) lookupKeyword (vStringValue (keyword
), Lang_asm
);
142 static boolean
isInitialSymbolCharacter (int c
)
144 return (boolean
) (c
!= '\0' && (isalpha (c
) || strchr ("_$", c
) != NULL
));
147 static boolean
isSymbolCharacter (int c
)
149 /* '?' character is allowed in AMD 29K family */
150 return (boolean
) (c
!= '\0' && (isalnum (c
) || strchr ("_$?", c
) != NULL
));
153 static boolean
readPreProc (const unsigned char *const line
)
156 const unsigned char *cp
= line
;
157 vString
*name
= vStringNew ();
158 while (isSymbolCharacter ((int) *cp
))
160 vStringPut (name
, *cp
);
163 vStringTerminate (name
);
164 result
= (boolean
) (strcmp (vStringValue (name
), "define") == 0);
167 while (isspace ((int) *cp
))
170 while (isSymbolCharacter ((int) *cp
))
172 vStringPut (name
, *cp
);
175 vStringTerminate (name
);
176 makeSimpleTag (name
, AsmKinds
, K_DEFINE
);
178 vStringDelete (name
);
182 static AsmKind
operatorKind (
183 const vString
*const operator,
184 boolean
*const found
)
186 AsmKind result
= K_NONE
;
187 const opKeyword kw
= analyzeOperator (operator);
188 *found
= (boolean
) (kw
!= OP_UNDEFINED
);
191 result
= OpKinds
[kw
].kind
;
192 Assert (OpKinds
[kw
].keyword
== kw
);
197 /* We must check for "DB", "DB.L", "DCB.W" (68000)
199 static boolean
isDefineOperator (const vString
*const operator)
201 const unsigned char *const op
=
202 (unsigned char*) vStringValue (operator);
203 const size_t length
= vStringLength (operator);
204 const boolean result
= (boolean
) (length
> 0 &&
205 toupper ((int) *op
) == 'D' &&
207 (length
== 4 && (int) op
[2] == '.') ||
208 (length
== 5 && (int) op
[3] == '.')));
212 static void makeAsmTag (
213 const vString
*const name
,
214 const vString
*const operator,
215 const boolean labelCandidate
,
216 const boolean nameFollows
)
218 if (vStringLength (name
) > 0)
221 const AsmKind kind
= operatorKind (operator, &found
);
225 makeSimpleTag (name
, AsmKinds
, kind
);
227 else if (isDefineOperator (operator))
230 makeSimpleTag (name
, AsmKinds
, K_DEFINE
);
232 else if (labelCandidate
)
234 operatorKind (name
, &found
);
236 makeSimpleTag (name
, AsmKinds
, K_LABEL
);
241 static const unsigned char *readSymbol (
242 const unsigned char *const start
,
245 const unsigned char *cp
= start
;
247 if (isInitialSymbolCharacter ((int) *cp
))
249 while (isSymbolCharacter ((int) *cp
))
251 vStringPut (sym
, *cp
);
254 vStringTerminate (sym
);
259 static const unsigned char *readOperator (
260 const unsigned char *const start
,
261 vString
*const operator)
263 const unsigned char *cp
= start
;
264 vStringClear (operator);
265 while (*cp
!= '\0' && ! isspace ((int) *cp
))
267 vStringPut (operator, *cp
);
270 vStringTerminate (operator);
274 static void findAsmTags (void)
276 vString
*name
= vStringNew ();
277 vString
*operator = vStringNew ();
278 const unsigned char *line
;
279 boolean inCComment
= FALSE
;
281 while ((line
= fileReadLine ()) != NULL
)
283 const unsigned char *cp
= line
;
284 boolean labelCandidate
= (boolean
) (! isspace ((int) *cp
));
285 boolean nameFollows
= FALSE
;
286 const boolean isComment
= (boolean
)
287 (*cp
!= '\0' && strchr (";*@", *cp
) != NULL
);
290 if (strncmp ((const char*) cp
, "/*", (size_t) 2) == 0)
299 if (strncmp ((const char*) cp
, "*/", (size_t) 2) == 0)
306 } while (*cp
!= '\0');
308 if (isComment
|| inCComment
)
311 /* read preprocessor defines */
319 /* skip white space */
320 while (isspace ((int) *cp
))
324 cp
= readSymbol (cp
, name
);
325 if (vStringLength (name
) > 0 && *cp
== ':')
327 labelCandidate
= TRUE
;
331 if (! isspace ((int) *cp
) && *cp
!= '\0')
334 /* skip white space */
335 while (isspace ((int) *cp
))
338 /* skip leading dot */
344 cp
= readOperator (cp
, operator);
346 /* attempt second read of symbol */
347 if (vStringLength (name
) == 0)
349 while (isspace ((int) *cp
))
351 cp
= readSymbol (cp
, name
);
354 makeAsmTag (name
, operator, labelCandidate
, nameFollows
);
356 vStringDelete (name
);
357 vStringDelete (operator);
360 static void initialize (const langType language
)
363 buildAsmKeywordHash ();
366 extern parserDefinition
* AsmParser (void)
368 static const char *const extensions
[] = {
369 "asm", "ASM", "s", "S", NULL
371 static const char *const patterns
[] = {
374 "*.[68][68][kKsSxX]",
378 parserDefinition
* def
= parserNew ("Asm");
379 def
->kinds
= AsmKinds
;
380 def
->kindCount
= KIND_COUNT (AsmKinds
);
381 def
->extensions
= extensions
;
382 def
->patterns
= patterns
;
383 def
->parser
= findAsmTags
;
384 def
->initialize
= initialize
;
388 /* vi:set tabstop=4 shiftwidth=4: */