Changed Asm parser back to C-based parser to eliminate duplicate tags and extend its functionality.

git-svn-id: svn://svn.code.sf.net/p/ctags/code/trunk@150 c5d04d22-be80-434c-894e-aa346cc9e8e8
This commit is contained in:
darren 2002-05-30 02:45:27 +00:00
parent 4555f6c842
commit 78ed7dc79c
6 changed files with 337 additions and 101 deletions

4
NEWS
View File

@ -1,6 +1,8 @@
Current Version: @@VERSION@@
ctags-5.2.4 (Tue May 14 2002)
ctags-5.2.4 (Wed May 29 2002)
* Changed Asm parser to back to C-based parser to remove redundant tags,
and extending its support for more variants [Asm].
* Changed to using _tempnam() to create temporary files on Windows, allowing
"TMP" environment variable to set temporary directory.
* Added support for RISC OS platform, contributed by Andrew Wingate.

View File

@ -15,3 +15,9 @@ PROMPT FCB CR,LF
FCB 0
COLD LDS #STACK
LDAA #$20
; http://www.mekatronix.com/downloads/docs/as11_man.pdf
sym1 EQU 1
sym2: EQU 2
sym3:
sym4: bne sym3

View File

@ -15,6 +15,9 @@ END
myequ EQU 3
myequal = 4
; http://www.xploiter.com/mirrors/asm/asm_3.htm
hllequal := 4
BYTE_BUFFER LABEL BYTE
WORD_BUFFER DW 512 dup (?)

116
Test/moniker.x68 Normal file
View File

@ -0,0 +1,116 @@
* http://www.xrmx.com/solutions/software/68k-fe/samples/moniker.x68
* MONIKER.X68
* Author : Greg Colley
* Date : 29/01/99
* Program Description.
* This will prompt for surname and firstname, and check if its uppercase
* If it is it prints Initial + surname else it repromts.
* This program will only exit when nothing is entered in the surname or
* firstname.
PRTSTR EQU 1 Print string Function
READSTR EQU 2 Read string function
ORG $1000 Start of code location
* Print user prompt for enter the firstname
* =========================================
START MOVEA.L #PROMPT1,A1 Pointer to start of prompt text
MOVE.B #PRTSTR,D0 Set up print string function
MOVE.W #(PROMPT2-PROMPT1),D1 The prompt string length
TRAP #15 Print Prompt
* Get firstname
* =============
MOVEA.L #F_NAME,A1 Pointer to store teh sentance
MOVE.B #READSTR,D0 Set up readstring function
TRAP #15 Get string from KB
MOVE.W D1,D4 Save length of input string to d4
* Check if Return is pressed
CMPI.W #0,D4 Is the length = 0
BEQ QUIT If length = 0 then Quit
* Set up the stuff to check it the entered word is in CAPS
* ========================================================
MOVEA.L #F_NAME,A0 Move the first char to A0
JSR CHECK2 Check if uppercase
CMPI.B #1,D5 See if all the sentance is CAPS
BCS START if it is'nt then re-enter
* Print user prompt for enter the surname
* =======================================
SURNAME MOVEA.L #PROMPT2,A1 Pointer to start of prompt text
MOVE.B #PRTSTR,D0 Set up print string function
MOVE.W #(F_NAME-PROMPT2),D1 The prompt string lenght
TRAP #15 Print Prompt
* Get surname
* ===========
MOVEA.L #S_NAME,A1 Pointer to store the sentance
MOVE.B #READSTR,D0 Set up readstring function
TRAP #15 Get string from KB
MOVE.W D1,D4 Save length on input string
MOVE.W D1,D3 Save length of input string to d3
* Check is Return is pressed
CMPI.W #0,D4 Is the length = 0
BEQ QUIT If length = 0 then Quit
* Set up the stuff to check it the entered word is in CAPS
* ========================================================
MOVEA.L #S_NAME,A0 Move the first char to A0
JSR CHECK2 Check if uppercase
CMPI.B #1,D5 See if all the sentance is CAPS
BCS SURNAME if it is'nt then re-enter
* Move the first char for fname and prints it (Initial Bit)
* =========================================================
INITIAL MOVEA.L #F_NAME,A1 Move the first char to A1
MOVE.B (A1),D1 Move the first char of F_NAME to D1
MOVE.B #6,D0 Set up trap number
TRAP #15 Print the Initial
PRNSURNAME MOVEA.L #S_NAME,A1 Pointer to start of prompt text
MOVE.B #0,D0 Set up print string function
MOVE.W D3,D1 The prompt string lenght
TRAP #15 Print Prompt
QUIT STOP #$2700 Stop the prorgam
* Check if uppercase
* ==================
* This subroutine will return a 1 in, d5 if it's OK or
* return a 0 in d5 if its not ok.
CHECK2 CMPI.B #'A',(A0) Is Char > A ?
BCS RETURNFALSE If no then re-enter
CMP.B #('Z'+1),(A0)+ Check if char is < Z
BCC RETURNFALSE If it is then it must be a cap
SUBI.B #1,D4 Decrease s_name / f_name Length
BNE CHECK2 jump if the sentance is not = 0
RETURNTRUE MOVE.B #1,D5 Moves a one to D5 to make CAPS ture
RTS Jump back to the main program
RETURNFALSE MOVE.B #0,D5 Moves a zero to D5 to make CAPS false
RTS Jump back to the main program
* Var's & Const's
* ===============
PROMPT1 DC.B 'Please enter your firstname (Max 80): '
PROMPT2 DC.B 'Please enter your surname (Max 80): '
F_NAME DS.B 80
S_NAME DS.B 80
DUMMY DS.B 1
END $1000 End of assembley

307
asm.c
View File

@ -20,125 +20,235 @@
#include "parse.h"
#include "read.h"
#include "vstring.h"
#ifdef HAVE_REGCOMP
# ifdef HAVE_SYS_TYPES_H
# include <sys/types.h> /* declare off_t (not known to regex.h on FreeBSD) */
# endif
# include "regex.h"
#endif
/*
* MACROS
* DATA DECLARATIONS
*/
/* '?' character is allowed in AMD 29K family */
#define SYMBOL "[[:alpha:]_$][[:alnum:]_$?]*"
#define EQU "(:?=|(:[[:blank:]]+)?\\.?(equ|set|d[bcdfpqstw][.[:space:]]))"
typedef enum {
K_NONE = -1, K_DEFINE, K_LABEL, K_MACRO, K_TYPE
} AsmKind;
typedef struct {
const char *operator;
AsmKind kind;
} OpType;
/*
* DATA DEFINITIONS
*/
typedef enum {
K_LABEL
} AsmKind;
static kindOption AsmKinds [] = {
{ TRUE, 'l', "label", "labels"}
{ TRUE, 'd', "define", "defines" },
{ TRUE, 'l', "label", "labels" },
{ TRUE, 'm', "macro", "macros" },
{ TRUE, 't', "type", "types" }
};
static const OpType OpTypes [] = {
{ "endm", K_NONE },
{ "endmacro", K_NONE },
{ "endp", K_NONE },
{ "ends", K_NONE },
{ "equ", K_DEFINE },
{ "label", K_LABEL },
{ "macro", K_MACRO },
{ "proc", K_LABEL },
{ "record", K_TYPE },
{ "set", K_DEFINE },
{ "struct", K_TYPE },
{ "=", K_DEFINE },
{ ":=", K_DEFINE }
};
static unsigned int OpTypeCount = sizeof (OpTypes) / sizeof (OpType);
/*
* FUNCTION DEFINITIONS
*/
static void checkLabel (const char *line, const regexMatch *matches,
unsigned int count)
static boolean isInitialSymbolCharacter (int c)
{
#ifdef HAVE_REGCOMP
static regex_t LabelReject;
static boolean compiled = FALSE;
if (! compiled)
{
/* rejects patterns matching other constructs */
compiled = (boolean) (regcomp (&LabelReject, EQU,
REG_EXTENDED|REG_ICASE) == 0);
}
if (compiled && count > 2)
{
const char *match1 = line + matches [1].start;
const char *match2 = line + matches [2].start;
if (regexec (&LabelReject, match2, (size_t) 0, NULL, 0) != 0)
{
vString *name = vStringNew ();
vStringNCopyS (name, match1, matches [1].length);
makeSimpleTag (name, AsmKinds, K_LABEL);
vStringDelete (name);
}
}
#endif
return (boolean) (c != '\0' && (isalpha (c) || strchr ("_$", c) != NULL));
}
/*
* Based upon code samples from http://www.programmersheaven.com/zone5/
*/
static void installAsmRegex (const langType language)
static boolean isSymbolCharacter (int c)
{
/*
* abc =
* abc :=
* abc \.?EQU
* abc \.?SET
* abc \.?D[BCDFPQSTW][. ]
*/
addTagRegex (language,
"^(" SYMBOL ")[[:blank:]]*(" EQU ")",
"\\1", "d,define", "i");
/* gas .equ */
addTagRegex (language,
"^[[:blank:]]*\\.(equ|set)[[:blank:]]+(" SYMBOL ")",
"\\2", "d,define", "i");
/* '?' character is allowed in AMD 29K family */
return (boolean) (c != '\0' && (isalnum (c) || strchr ("_$?", c) != NULL));
}
/*
* abc:
* abc LABEL
*/
addCallbackRegex (language,
"^(" SYMBOL ")[[:blank:]]*(:|[[:blank:]]label[[:space:]])",
"i", checkLabel);
static boolean readPreProc (const unsigned char *const line)
{
boolean result;
const unsigned char *cp = line;
vString *name = vStringNew ();
while (isSymbolCharacter ((int) *cp))
{
vStringPut (name, *cp);
++cp;
}
vStringTerminate (name);
result = (boolean) (strcmp (vStringValue (name), "define") == 0);
if (result)
{
while (isspace ((int) *cp))
++cp;
vStringClear (name);
while (isSymbolCharacter ((int) *cp))
{
vStringPut (name, *cp);
++cp;
}
vStringTerminate (name);
makeSimpleTag (name, AsmKinds, K_DEFINE);
}
vStringDelete (name);
return result;
}
addCallbackRegex (language,
"^(" SYMBOL ")[[:blank:]]+([[:alpha:]].*)$",
"i", checkLabel);
static void makeAsmTag (
const vString *const name,
const vString *const operator,
const boolean initialSymbol,
const boolean hasColon)
{
unsigned int i;
if (vStringLength (name) > 0)
{
boolean found = FALSE;
if (vStringLength (operator) > 0)
{
for (i = 0 ; i < OpTypeCount && !found ; ++i)
{
if (strcasecmp (
vStringValue (operator), OpTypes [i].operator) == 0)
{
if (OpTypes [i].kind != K_NONE)
makeSimpleTag (name, AsmKinds, OpTypes [i].kind);
found = TRUE;
}
}
}
if (!found && initialSymbol)
{
const unsigned char *const op =
(unsigned char*) vStringValue (operator);
if (toupper ((int) *op) == 'D' &&
strchr (". \t", (int) op [2]) != NULL)
{
makeSimpleTag (name, AsmKinds, K_DEFINE);
}
else if (hasColon)
makeSimpleTag (name, AsmKinds, K_LABEL);
else if (vStringLength (operator) > 0)
makeSimpleTag (name, AsmKinds, K_LABEL);
}
}
}
/* MASM proc */
addTagRegex (language,
"^(" SYMBOL ")[[:blank:]]+proc[[:space:]]",
"\\1", "l,label", "i");
/* TASM proc */
addTagRegex (language,
"^proc[[:blank:]]+(" SYMBOL ")",
"\\1", "l,label", "i");
static void findAsmTags (void)
{
vString *name = vStringNew ();
vString *operator = vStringNew ();
const unsigned char *line;
boolean inCComment = FALSE;
/* gas macro */
addTagRegex (language,
"^[[:blank:]]*\\.macro[[:blank:]]*(" SYMBOL ")",
"\\1", "m,macro", "i");
/* MASM macro */
addTagRegex (language,
"^(" SYMBOL ")[[:blank:]]+macro[[:space:]]",
"\\1", "m,macro", "i");
/* TASM macro */
addTagRegex (language,
"^macro[[:blank:]]+(" SYMBOL ")",
"\\1", "m,macro", "i");
while ((line = fileReadLine ()) != NULL)
{
const unsigned char *cp = line;
boolean hasColon = FALSE;
boolean initialSymbol = isInitialSymbolCharacter ((int) *cp);
const boolean isComment = (boolean) (strchr (";*@", *cp) != NULL);
/* MASM structures */
addTagRegex (language,
"^(" SYMBOL ")[[:blank:]]+(struct|record)[[:space:]]",
"\\1", "t,type", "i");
/* TASM structures */
addTagRegex (language,
"^struct[[:blank:]]+(" SYMBOL ")",
"\\1", "t,type", "i");
/* skip comments */
if (strncmp ((const char*) cp, "/*", (size_t) 2) == 0)
{
inCComment = TRUE;
cp += 2;
}
if (inCComment)
{
do
{
if (strncmp ((const char*) cp, "*/", (size_t) 2) == 0)
{
inCComment = FALSE;
cp += 2;
break;
}
++cp;
} while (*cp != '\0');
}
if (isComment || inCComment)
continue;
/* read preprocessor defines */
if (*cp == '#')
{
++cp;
readPreProc (cp);
continue;
}
/* read symbol */
if (initialSymbol)
{
vStringClear (name);
while (isSymbolCharacter ((int) *cp))
{
vStringPut (name, *cp);
++cp;
}
vStringTerminate (name);
if (*cp == ':')
{
hasColon = TRUE;
++cp;
}
else if (! isspace ((int) *cp))
{
vStringClear (name);
initialSymbol = FALSE;
}
}
else if (! isspace ((int) *cp))
continue;
/* skip white space */
while (isspace ((int) *cp))
++cp;
/* skip leading dot */
if (*cp == '.')
++cp;
/* read operator */
vStringClear (operator);
while (*cp != '\0' && ! isspace ((int) *cp))
{
vStringPut (operator, *cp);
++cp;
}
vStringTerminate (operator);
/* attempt second read of symbol */
if (!initialSymbol)
{
while (isspace ((int) *cp))
++cp;
if (isInitialSymbolCharacter ((int) *cp))
{
vStringClear (name);
while (isSymbolCharacter ((int) *cp))
{
vStringPut (name, *cp);
++cp;
}
vStringTerminate (name);
}
}
makeAsmTag (name, operator, initialSymbol, hasColon);
}
vStringDelete (name);
vStringDelete (operator);
}
extern parserDefinition* AsmParser (void)
@ -147,10 +257,10 @@ extern parserDefinition* AsmParser (void)
"asm", "ASM", "s", "S", NULL
};
static const char *const patterns [] = {
"*.A51",
"*.29[kK]",
"*.[68][68][kKsSxX]",
"*.[xX][68][68]",
"*.A5[01]",
NULL
};
parserDefinition* def = parserNew ("Asm");
@ -158,8 +268,7 @@ extern parserDefinition* AsmParser (void)
def->kindCount = KIND_COUNT (AsmKinds);
def->extensions = extensions;
def->patterns = patterns;
def->initialize = installAsmRegex;
def->regex = TRUE;
def->parser = findAsmTags;
return def;
}

View File

@ -62,7 +62,7 @@ names are mapped to languages according to the following default mappings
.RS 4
.TP 9
.B Assembler
*.asm *.ASM *.s *.S
*.asm *.ASM *.[sS] *.A51 *.29[kK] *.[68][68][kKsSxX] *.[xX][68][68]
.TP 9
.B ASP
*.asp *.asa