2 * $Id: asm.c 536 2007-06-02 06:09:00Z elliotth $
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 vString
*keyword
= vStringNew ();
135 vStringCopyToLower (keyword
, op
);
136 result
= (opKeyword
) lookupKeyword (vStringValue (keyword
), Lang_asm
);
137 vStringDelete (keyword
);
141 static boolean
isInitialSymbolCharacter (int c
)
143 return (boolean
) (c
!= '\0' && (isalpha (c
) || strchr ("_$", c
) != NULL
));
146 static boolean
isSymbolCharacter (int c
)
148 /* '?' character is allowed in AMD 29K family */
149 return (boolean
) (c
!= '\0' && (isalnum (c
) || strchr ("_$?", c
) != NULL
));
152 static boolean
readPreProc (const unsigned char *const line
)
155 const unsigned char *cp
= line
;
156 vString
*name
= vStringNew ();
157 while (isSymbolCharacter ((int) *cp
))
159 vStringPut (name
, *cp
);
162 vStringTerminate (name
);
163 result
= (boolean
) (strcmp (vStringValue (name
), "define") == 0);
166 while (isspace ((int) *cp
))
169 while (isSymbolCharacter ((int) *cp
))
171 vStringPut (name
, *cp
);
174 vStringTerminate (name
);
175 makeSimpleTag (name
, AsmKinds
, K_DEFINE
);
177 vStringDelete (name
);
181 static AsmKind
operatorKind (
182 const vString
*const operator,
183 boolean
*const found
)
185 AsmKind result
= K_NONE
;
186 const opKeyword kw
= analyzeOperator (operator);
187 *found
= (boolean
) (kw
!= OP_UNDEFINED
);
190 result
= OpKinds
[kw
].kind
;
191 Assert (OpKinds
[kw
].keyword
== kw
);
196 /* We must check for "DB", "DB.L", "DCB.W" (68000)
198 static boolean
isDefineOperator (const vString
*const operator)
200 const unsigned char *const op
=
201 (unsigned char*) vStringValue (operator);
202 const size_t length
= vStringLength (operator);
203 const boolean result
= (boolean
) (length
> 0 &&
204 toupper ((int) *op
) == 'D' &&
206 (length
== 4 && (int) op
[2] == '.') ||
207 (length
== 5 && (int) op
[3] == '.')));
211 static void makeAsmTag (
212 const vString
*const name
,
213 const vString
*const operator,
214 const boolean labelCandidate
,
215 const boolean nameFollows
)
217 if (vStringLength (name
) > 0)
220 const AsmKind kind
= operatorKind (operator, &found
);
224 makeSimpleTag (name
, AsmKinds
, kind
);
226 else if (isDefineOperator (operator))
229 makeSimpleTag (name
, AsmKinds
, K_DEFINE
);
231 else if (labelCandidate
)
233 operatorKind (name
, &found
);
235 makeSimpleTag (name
, AsmKinds
, K_LABEL
);
240 static const unsigned char *readSymbol (
241 const unsigned char *const start
,
244 const unsigned char *cp
= start
;
246 if (isInitialSymbolCharacter ((int) *cp
))
248 while (isSymbolCharacter ((int) *cp
))
250 vStringPut (sym
, *cp
);
253 vStringTerminate (sym
);
258 static const unsigned char *readOperator (
259 const unsigned char *const start
,
260 vString
*const operator)
262 const unsigned char *cp
= start
;
263 vStringClear (operator);
264 while (*cp
!= '\0' && ! isspace ((int) *cp
))
266 vStringPut (operator, *cp
);
269 vStringTerminate (operator);
273 static void findAsmTags (void)
275 vString
*name
= vStringNew ();
276 vString
*operator = vStringNew ();
277 const unsigned char *line
;
278 boolean inCComment
= FALSE
;
280 while ((line
= fileReadLine ()) != NULL
)
282 const unsigned char *cp
= line
;
283 boolean labelCandidate
= (boolean
) (! isspace ((int) *cp
));
284 boolean nameFollows
= FALSE
;
285 const boolean isComment
= (boolean
)
286 (*cp
!= '\0' && strchr (";*@", *cp
) != NULL
);
289 if (strncmp ((const char*) cp
, "/*", (size_t) 2) == 0)
298 if (strncmp ((const char*) cp
, "*/", (size_t) 2) == 0)
305 } while (*cp
!= '\0');
307 if (isComment
|| inCComment
)
310 /* read preprocessor defines */
318 /* skip white space */
319 while (isspace ((int) *cp
))
323 cp
= readSymbol (cp
, name
);
324 if (vStringLength (name
) > 0 && *cp
== ':')
326 labelCandidate
= TRUE
;
330 if (! isspace ((int) *cp
) && *cp
!= '\0')
333 /* skip white space */
334 while (isspace ((int) *cp
))
337 /* skip leading dot */
343 cp
= readOperator (cp
, operator);
345 /* attempt second read of symbol */
346 if (vStringLength (name
) == 0)
348 while (isspace ((int) *cp
))
350 cp
= readSymbol (cp
, name
);
353 makeAsmTag (name
, operator, labelCandidate
, nameFollows
);
355 vStringDelete (name
);
356 vStringDelete (operator);
359 static void initialize (const langType language
)
362 buildAsmKeywordHash ();
365 extern parserDefinition
* AsmParser (void)
367 static const char *const extensions
[] = {
368 "asm", "ASM", "s", "S", NULL
370 static const char *const patterns
[] = {
373 "*.[68][68][kKsSxX]",
377 parserDefinition
* def
= parserNew ("Asm");
378 def
->kinds
= AsmKinds
;
379 def
->kindCount
= KIND_COUNT (AsmKinds
);
380 def
->extensions
= extensions
;
381 def
->patterns
= patterns
;
382 def
->parser
= findAsmTags
;
383 def
->initialize
= initialize
;
387 /* vi:set tabstop=4 shiftwidth=4: */