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 */
18 #include "cpreprocessor.h"
25 #include "selectors.h"
32 K_PSUEDO_MACRO_END
= -2,
33 K_NONE
= -1, K_DEFINE
, K_LABEL
, K_MACRO
, K_TYPE
,
60 ASM_SECTION_PLACEMENT
,
71 static langType Lang_asm
;
73 static roleDefinition asmSectionRoles
[] = {
74 { true, "placement", "placement where the assembled code goes" },
77 static kindDefinition AsmKinds
[] = {
78 { true, 'd', "define", "defines" },
79 { true, 'l', "label", "labels" },
80 { true, 'm', "macro", "macros" },
81 { true, 't', "type", "types (structs and records)" },
82 { true, 's', "section", "sections",
83 .referenceOnly
= true, ATTACH_ROLES(asmSectionRoles
)},
86 static const keywordTable AsmKeywords
[] = {
87 { "align", OP_ALIGN
},
88 { "endmacro", OP_ENDMACRO
},
94 { "label", OP_LABEL
},
95 { "macro", OP_MACRO
},
96 { ":=", OP_COLON_EQUAL
},
99 { "record", OP_RECORD
},
100 { "sections", OP_SECTIONS
},
102 /* These are used in GNU as. */
103 { "section", OP_SECTION
},
108 { "struct", OP_STRUCT
}
111 static const opKind OpKinds
[] = {
112 /* must be ordered same as opKeyword enumeration */
113 { OP_ALIGN
, K_NONE
},
114 { OP_COLON_EQUAL
, K_DEFINE
},
116 { OP_ENDM
, K_PSUEDO_MACRO_END
},
117 { OP_ENDMACRO
, K_NONE
},
120 { OP_EQU
, K_DEFINE
},
121 { OP_EQUAL
, K_DEFINE
},
122 { OP_LABEL
, K_LABEL
},
123 { OP_MACRO
, K_MACRO
},
124 { OP_PROC
, K_LABEL
},
125 { OP_RECORD
, K_TYPE
},
126 { OP_SECTIONS
, K_NONE
},
127 { OP_SECTION
, K_SECTION
},
128 { OP_SET
, K_DEFINE
},
129 { OP_STRUCT
, K_TYPE
}
133 * FUNCTION DEFINITIONS
135 static opKeyword
analyzeOperator (const vString
*const op
)
137 vString
*keyword
= vStringNew ();
140 vStringCopyToLower (keyword
, op
);
141 result
= (opKeyword
) lookupKeyword (vStringValue (keyword
), Lang_asm
);
142 vStringDelete (keyword
);
146 static bool isInitialSymbolCharacter (int c
)
148 return (bool) (c
!= '\0' && (isalpha (c
) || strchr ("_$", c
) != NULL
));
151 static bool isSymbolCharacter (int c
)
153 /* '?' character is allowed in AMD 29K family */
154 return (bool) (c
!= '\0' && (isalnum (c
) || strchr ("_$?", c
) != NULL
));
157 static AsmKind
operatorKind (
158 const vString
*const operator,
161 AsmKind result
= K_NONE
;
162 const opKeyword kw
= analyzeOperator (operator);
163 *found
= (bool) (kw
!= OP_UNDEFINED
);
166 result
= OpKinds
[kw
].kind
;
167 Assert (OpKinds
[kw
].keyword
== kw
);
172 /* We must check for "DB", "DB.L", "DCB.W" (68000)
174 static bool isDefineOperator (const vString
*const operator)
176 const unsigned char *const op
=
177 (unsigned char*) vStringValue (operator);
178 const size_t length
= vStringLength (operator);
179 const bool result
= (bool) (length
> 0 &&
180 toupper ((int) *op
) == 'D' &&
182 (length
== 4 && (int) op
[2] == '.') ||
183 (length
== 5 && (int) op
[3] == '.')));
187 static void makeAsmTag (
188 const vString
*const name
,
189 const vString
*const operator,
190 const bool labelCandidate
,
191 const bool nameFollows
,
192 const bool directive
,
193 int *lastMacroCorkIndex
)
195 if (vStringLength (name
) > 0)
198 const AsmKind kind
= operatorKind (operator, &found
);
202 makeSimpleTag (name
, kind
);
204 else if (isDefineOperator (operator))
207 makeSimpleTag (name
, K_DEFINE
);
209 else if (labelCandidate
)
211 operatorKind (name
, &found
);
213 makeSimpleTag (name
, K_LABEL
);
218 const AsmKind kind_for_directive
= operatorKind (name
, &found_dummy
);
219 tagEntryInfo
*macro_tag
;
221 switch (kind_for_directive
)
226 *lastMacroCorkIndex
= makeSimpleTag (operator,
228 if (*lastMacroCorkIndex
!= CORK_NIL
)
229 registerEntry (*lastMacroCorkIndex
);
231 case K_PSUEDO_MACRO_END
:
232 macro_tag
= getEntryInCorkQueue (*lastMacroCorkIndex
);
234 macro_tag
->extensionFields
.endLine
= getInputLineNumber ();
235 *lastMacroCorkIndex
= CORK_NIL
;
238 makeSimpleRefTag (operator,
240 ASM_SECTION_PLACEMENT
);
243 makeSimpleTag (operator, kind_for_directive
);
249 static const unsigned char *readSymbol (
250 const unsigned char *const start
,
253 const unsigned char *cp
= start
;
255 if (isInitialSymbolCharacter ((int) *cp
))
257 while (isSymbolCharacter ((int) *cp
))
259 vStringPut (sym
, *cp
);
266 static const unsigned char *readOperator (
267 const unsigned char *const start
,
268 vString
*const operator)
270 const unsigned char *cp
= start
;
271 vStringClear (operator);
272 while (*cp
!= '\0' && ! isspace ((int) *cp
) && *cp
!= ',')
274 vStringPut (operator, *cp
);
280 static const unsigned char *asmReadLineFromInputFile (void)
282 static vString
*line
;
285 line
= vStringNewOrClear (line
);
287 while ((c
= cppGetc()) != EOF
)
291 else if (c
== STRING_SYMBOL
|| c
== CHAR_SYMBOL
)
293 /* We cannot store these values to vString
294 * Store a whitespace as a dummy value for them.
296 vStringPut (line
, ' ');
299 vStringPut (line
, c
);
302 if ((vStringLength (line
) == 0)&& (c
== EOF
))
305 return (unsigned char *)vStringValue (line
);
308 static void findAsmTags (void)
310 vString
*name
= vStringNew ();
311 vString
*operator = vStringNew ();
312 const unsigned char *line
;
314 cppInit (false, false, false, false,
315 KIND_GHOST_INDEX
, 0, KIND_GHOST_INDEX
, KIND_GHOST_INDEX
, 0, 0,
318 int lastMacroCorkIndex
= CORK_NIL
;
320 while ((line
= asmReadLineFromInputFile ()) != NULL
)
322 const unsigned char *cp
= line
;
323 bool labelCandidate
= (bool) (! isspace ((int) *cp
));
324 bool nameFollows
= false;
325 bool directive
= false;
326 const bool isComment
= (bool)
327 (*cp
!= '\0' && strchr (";*@", *cp
) != NULL
);
333 /* skip white space */
334 while (isspace ((int) *cp
))
341 labelCandidate
= false;
345 cp
= readSymbol (cp
, name
);
346 if (vStringLength (name
) > 0)
350 labelCandidate
= true;
353 else if (anyKindEntryInScope (CORK_NIL
,
356 labelCandidate
= false;
359 if (! isspace ((int) *cp
) && *cp
!= '\0')
362 /* skip white space */
363 while (isspace ((int) *cp
))
366 /* skip leading dot */
372 cp
= readOperator (cp
, operator);
374 /* attempt second read of symbol */
375 if (vStringLength (name
) == 0)
377 while (isspace ((int) *cp
))
379 cp
= readSymbol (cp
, name
);
382 makeAsmTag (name
, operator, labelCandidate
, nameFollows
, directive
,
383 &lastMacroCorkIndex
);
388 vStringDelete (name
);
389 vStringDelete (operator);
392 static void initialize (const langType language
)
397 extern parserDefinition
* AsmParser (void)
399 static const char *const extensions
[] = {
400 "asm", "ASM", "s", "S", NULL
402 static const char *const patterns
[] = {
405 "*.[68][68][kKsSxX]",
409 static selectLanguage selectors
[] = { selectByArrowOfR
,
412 parserDefinition
* def
= parserNew ("Asm");
413 def
->kindTable
= AsmKinds
;
414 def
->kindCount
= ARRAY_SIZE (AsmKinds
);
415 def
->extensions
= extensions
;
416 def
->patterns
= patterns
;
417 def
->parser
= findAsmTags
;
418 def
->initialize
= initialize
;
419 def
->keywordTable
= AsmKeywords
;
420 def
->keywordCount
= ARRAY_SIZE (AsmKeywords
);
421 def
->selectLanguage
= selectors
;
422 def
->useCork
= CORK_QUEUE
| CORK_SYMTAB
;