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:
parent
4555f6c842
commit
78ed7dc79c
4
NEWS
4
NEWS
|
@ -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.
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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 (?)
|
||||
|
||||
|
|
|
@ -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
307
asm.c
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue