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.
7 * This module contains functions for generating tags for assembly language
14 #include "general.h" /* must always come first */
28 K_NONE
= -1, K_DEFINE
, K_LABEL
, K_MACRO
, K_TYPE
65 static langType Lang_asm
;
67 static kindOption AsmKinds
[] = {
68 { TRUE
, 'd', "macro", "defines" },
69 { TRUE
, 'l', "namespace", "labels" },
70 { TRUE
, 'm', "function", "macros" },
71 { TRUE
, 't', "struct", "types (structs and records)" }
74 static const asmKeyword AsmKeywords
[] = {
75 { "align", OP_ALIGN
},
76 { "endmacro", OP_ENDMACRO
},
82 { "label", OP_LABEL
},
83 { "macro", OP_MACRO
},
84 { ":=", OP_COLON_EQUAL
},
87 { "record", OP_RECORD
},
88 { "sections", OP_SECTIONS
},
90 { "struct", OP_STRUCT
}
93 static const opKind OpKinds
[] = {
94 /* must be ordered same as opKeyword enumeration */
96 { OP_COLON_EQUAL
, K_DEFINE
},
99 { OP_ENDMACRO
, K_NONE
},
102 { OP_EQU
, K_DEFINE
},
103 { OP_EQUAL
, K_DEFINE
},
104 { OP_LABEL
, K_LABEL
},
105 { OP_MACRO
, K_MACRO
},
106 { OP_PROC
, K_LABEL
},
107 { OP_RECORD
, K_TYPE
},
108 { OP_SECTIONS
, K_NONE
},
109 { OP_SET
, K_DEFINE
},
110 { OP_STRUCT
, K_TYPE
}
114 * FUNCTION DEFINITIONS
116 static void buildAsmKeywordHash (void)
118 const size_t count
= sizeof (AsmKeywords
) / sizeof (AsmKeywords
[0]);
120 for (i
= 0 ; i
< count
; ++i
)
122 const asmKeyword
* const p
= AsmKeywords
+ i
;
123 addKeyword (p
->operator, Lang_asm
, (int) p
->keyword
);
127 static opKeyword
analyzeOperator (const vString
*const op
)
129 vString
*keyword
= vStringNew ();
132 vStringCopyToLower (keyword
, op
);
133 result
= (opKeyword
) lookupKeyword (vStringValue (keyword
), Lang_asm
);
134 vStringDelete (keyword
);
138 static boolean
isInitialSymbolCharacter (int c
)
140 return (boolean
) (c
!= '\0' && (isalpha (c
) || strchr ("_$", c
) != NULL
));
143 static boolean
isSymbolCharacter (int c
)
145 /* '?' character is allowed in AMD 29K family */
146 return (boolean
) (c
!= '\0' && (isalnum (c
) || strchr ("_$?", c
) != NULL
));
149 static boolean
readPreProc (const unsigned char *const line
)
152 const unsigned char *cp
= line
;
153 vString
*name
= vStringNew ();
154 while (isSymbolCharacter ((int) *cp
))
156 vStringPut (name
, *cp
);
159 vStringTerminate (name
);
160 result
= (boolean
) (strcmp (vStringValue (name
), "define") == 0);
163 while (isspace ((int) *cp
))
166 while (isSymbolCharacter ((int) *cp
))
168 vStringPut (name
, *cp
);
171 vStringTerminate (name
);
172 makeSimpleTag (name
, AsmKinds
, K_DEFINE
);
174 vStringDelete (name
);
178 static AsmKind
operatorKind (
179 const vString
*const operator,
180 boolean
*const found
)
182 AsmKind result
= K_NONE
;
183 const opKeyword kw
= analyzeOperator (operator);
184 *found
= (boolean
) (kw
!= OP_UNDEFINED
);
187 result
= OpKinds
[kw
].kind
;
188 Assert (OpKinds
[kw
].keyword
== kw
);
193 /* We must check for "DB", "DB.L", "DCB.W" (68000)
195 static boolean
isDefineOperator (const vString
*const operator)
197 const unsigned char *const op
=
198 (unsigned char*) vStringValue (operator);
199 const size_t length
= vStringLength (operator);
200 const boolean result
= (boolean
) (length
> 0 &&
201 toupper ((int) *op
) == 'D' &&
203 (length
== 4 && (int) op
[2] == '.') ||
204 (length
== 5 && (int) op
[3] == '.')));
208 static void makeAsmTag (
209 const vString
*const name
,
210 const vString
*const operator,
211 const boolean labelCandidate
,
212 const boolean nameFollows
)
214 if (vStringLength (name
) > 0)
217 const AsmKind kind
= operatorKind (operator, &found
);
221 makeSimpleTag (name
, AsmKinds
, kind
);
223 else if (isDefineOperator (operator))
226 makeSimpleTag (name
, AsmKinds
, K_DEFINE
);
228 else if (labelCandidate
)
230 operatorKind (name
, &found
);
232 makeSimpleTag (name
, AsmKinds
, K_LABEL
);
237 static const unsigned char *readSymbol (
238 const unsigned char *const start
,
241 const unsigned char *cp
= start
;
243 if (isInitialSymbolCharacter ((int) *cp
))
245 while (isSymbolCharacter ((int) *cp
))
247 vStringPut (sym
, *cp
);
250 vStringTerminate (sym
);
255 static const unsigned char *readOperator (
256 const unsigned char *const start
,
257 vString
*const operator)
259 const unsigned char *cp
= start
;
260 vStringClear (operator);
261 while (*cp
!= '\0' && ! isspace ((int) *cp
))
263 vStringPut (operator, *cp
);
266 vStringTerminate (operator);
270 static void findAsmTags (void)
272 vString
*name
= vStringNew ();
273 vString
*operator = vStringNew ();
274 const unsigned char *line
;
275 boolean inCComment
= FALSE
;
277 while ((line
= fileReadLine ()) != NULL
)
279 const unsigned char *cp
= line
;
280 boolean labelCandidate
= (boolean
) (! isspace ((int) *cp
));
281 boolean nameFollows
= FALSE
;
282 const boolean isComment
= (boolean
)
283 (*cp
!= '\0' && strchr (";*@", *cp
) != NULL
);
286 if (strncmp ((const char*) cp
, "/*", (size_t) 2) == 0)
295 if (strncmp ((const char*) cp
, "*/", (size_t) 2) == 0)
302 } while (*cp
!= '\0');
304 if (isComment
|| inCComment
)
307 /* read preprocessor defines */
315 /* skip white space */
316 while (isspace ((int) *cp
))
320 cp
= readSymbol (cp
, name
);
321 if (vStringLength (name
) > 0 && *cp
== ':')
323 labelCandidate
= TRUE
;
327 if (! isspace ((int) *cp
) && *cp
!= '\0')
330 /* skip white space */
331 while (isspace ((int) *cp
))
334 /* skip leading dot */
340 cp
= readOperator (cp
, operator);
342 /* attempt second read of symbol */
343 if (vStringLength (name
) == 0)
345 while (isspace ((int) *cp
))
347 cp
= readSymbol (cp
, name
);
350 makeAsmTag (name
, operator, labelCandidate
, nameFollows
);
352 vStringDelete (name
);
353 vStringDelete (operator);
356 static void initialize (const langType language
)
359 buildAsmKeywordHash ();
362 extern parserDefinition
* AsmParser (void)
364 static const char *const extensions
[] = {
365 "asm", "ASM", "s", "S", NULL
367 static const char *const patterns
[] = {
370 "*.[68][68][kKsSxX]",
374 parserDefinition
* def
= parserNew ("Asm");
375 def
->kinds
= AsmKinds
;
376 def
->kindCount
= KIND_COUNT (AsmKinds
);
377 def
->extensions
= extensions
;
378 def
->patterns
= patterns
;
379 def
->parser
= findAsmTags
;
380 def
->initialize
= initialize
;
384 /* vi:set tabstop=4 shiftwidth=4: */