⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 asm.c

📁 Exuberant Ctags is a multilanguage reimplementation of the much-underused ctags(1) program and is i
💻 C
字号:
/**   $Id: asm.c,v 1.18 2006/05/30 04:37:11 darren Exp $**   Copyright (c) 2000-2003, Darren Hiebert**   This source code is released for free distribution under the terms of the*   GNU General Public License.**   This module contains functions for generating tags for assembly language*   files.*//**   INCLUDE FILES*/#include "general.h"  /* must always come first */#include <string.h>#include "debug.h"#include "keyword.h"#include "parse.h"#include "read.h"#include "routines.h"#include "vstring.h"/**   DATA DECLARATIONS*/typedef enum {	K_NONE = -1, K_DEFINE, K_LABEL, K_MACRO, K_TYPE} AsmKind;typedef enum {	OP_UNDEFINED = -1,	OP_ALIGN,	OP_COLON_EQUAL,	OP_END,	OP_ENDM,	OP_ENDMACRO,	OP_ENDP,	OP_ENDS,	OP_EQU,	OP_EQUAL,	OP_LABEL,	OP_MACRO,	OP_PROC,	OP_RECORD,	OP_SECTIONS,	OP_SET,	OP_STRUCT,	OP_LAST} opKeyword;typedef struct {	const char *operator;	opKeyword keyword;} asmKeyword;typedef struct {	opKeyword keyword;	AsmKind kind;} opKind;/**   DATA DEFINITIONS*/static langType Lang_asm;static kindOption AsmKinds [] = {	{ TRUE, 'd', "define", "defines" },	{ TRUE, 'l', "label",  "labels"  },	{ TRUE, 'm', "macro",  "macros"  },	{ TRUE, 't', "type",   "types (structs and records)"   }};static const asmKeyword AsmKeywords [] = {	{ "align",    OP_ALIGN       },	{ "endmacro", OP_ENDMACRO    },	{ "endm",     OP_ENDM        },	{ "end",      OP_END         },	{ "endp",     OP_ENDP        },	{ "ends",     OP_ENDS        },	{ "equ",      OP_EQU         },	{ "label",    OP_LABEL       },	{ "macro",    OP_MACRO       },	{ ":=",       OP_COLON_EQUAL },	{ "=",        OP_EQUAL       },	{ "proc",     OP_PROC        },	{ "record",   OP_RECORD      },	{ "sections", OP_SECTIONS    },	{ "set",      OP_SET         },	{ "struct",   OP_STRUCT      }};static const opKind OpKinds [] = {	/* must be ordered same as opKeyword enumeration */	{ OP_ALIGN,       K_NONE   },	{ OP_COLON_EQUAL, K_DEFINE },	{ OP_END,         K_NONE   },	{ OP_ENDM,        K_NONE   },	{ OP_ENDMACRO,    K_NONE   },	{ OP_ENDP,        K_NONE   },	{ OP_ENDS,        K_NONE   },	{ OP_EQU,         K_DEFINE },	{ OP_EQUAL,       K_DEFINE },	{ OP_LABEL,       K_LABEL  },	{ OP_MACRO,       K_MACRO  },	{ OP_PROC,        K_LABEL  },	{ OP_RECORD,      K_TYPE   },	{ OP_SECTIONS,    K_NONE   },	{ OP_SET,         K_DEFINE },	{ OP_STRUCT,      K_TYPE   }};/**   FUNCTION DEFINITIONS*/static void buildAsmKeywordHash (void){	const size_t count = sizeof (AsmKeywords) / sizeof (AsmKeywords [0]);	size_t i;	for (i = 0  ;  i < count  ;  ++i)	{		const asmKeyword* const p = AsmKeywords + i;		addKeyword (p->operator, Lang_asm, (int) p->keyword);	}}static opKeyword analyzeOperator (const vString *const op){	static vString *keyword = NULL;	opKeyword result = OP_UNDEFINED;	if (keyword == NULL)		keyword = vStringNew ();	vStringCopyToLower (keyword, op);	result = (opKeyword) lookupKeyword (vStringValue (keyword), Lang_asm);	return result;}static boolean isInitialSymbolCharacter (int c){	return (boolean) (c != '\0' && (isalpha (c) || strchr ("_$", c) != NULL));}static boolean isSymbolCharacter (int c){	/* '?' character is allowed in AMD 29K family */	return (boolean) (c != '\0' && (isalnum (c) || strchr ("_$?", c) != NULL));}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;}static AsmKind operatorKind (		const vString *const operator,		boolean *const found){	AsmKind result = K_NONE;	const opKeyword kw = analyzeOperator (operator);	*found = (boolean) (kw != OP_UNDEFINED);	if (*found)	{		result = OpKinds [kw].kind;		Assert (OpKinds [kw].keyword == kw);	}	return result;}/*  We must check for "DB", "DB.L", "DCB.W" (68000) */static boolean isDefineOperator (const vString *const operator){	const unsigned char *const op =		(unsigned char*) vStringValue (operator); 	const size_t length = vStringLength (operator);	const boolean result = (boolean) (length > 0  &&		toupper ((int) *op) == 'D'  &&		(length == 2 ||		 (length == 4  &&  (int) op [2] == '.') ||		 (length == 5  &&  (int) op [3] == '.')));	return result;}static void makeAsmTag (		const vString *const name,		const vString *const operator,		const boolean labelCandidate,		const boolean nameFollows){	if (vStringLength (name) > 0)	{		boolean found;		const AsmKind kind = operatorKind (operator, &found);		if (found)		{			if (kind != K_NONE)				makeSimpleTag (name, AsmKinds, kind);		}		else if (isDefineOperator (operator))		{			if (! nameFollows)				makeSimpleTag (name, AsmKinds, K_DEFINE);		}		else if (labelCandidate)		{			operatorKind (name, &found);			if (! found)				makeSimpleTag (name, AsmKinds, K_LABEL);		}	}}static const unsigned char *readSymbol (		const unsigned char *const start,		vString *const sym){	const unsigned char *cp = start;	vStringClear (sym);	if (isInitialSymbolCharacter ((int) *cp))	{		while (isSymbolCharacter ((int) *cp))		{			vStringPut (sym, *cp);			++cp;		}		vStringTerminate (sym);	}	return cp;}static const unsigned char *readOperator (		const unsigned char *const start,		vString *const operator){	const unsigned char *cp = start;	vStringClear (operator);	while (*cp != '\0'  &&  ! isspace ((int) *cp))	{		vStringPut (operator, *cp);		++cp;	}	vStringTerminate (operator);	return cp;}static void findAsmTags (void){	vString *name = vStringNew ();	vString *operator = vStringNew ();	const unsigned char *line;	boolean inCComment = FALSE;	while ((line = fileReadLine ()) != NULL)	{		const unsigned char *cp = line;		boolean labelCandidate = (boolean) (! isspace ((int) *cp));		boolean nameFollows = FALSE;		const boolean isComment = (boolean)				(*cp != '\0' && strchr (";*@", *cp) != NULL);		/* 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;		}		/* skip white space */		while (isspace ((int) *cp))			++cp;		/* read symbol */		cp = readSymbol (cp, name);		if (vStringLength (name) > 0  &&  *cp == ':')		{			labelCandidate = TRUE;			++cp;		}		if (! isspace ((int) *cp)  &&  *cp != '\0')			continue;		/* skip white space */		while (isspace ((int) *cp))			++cp;		/* skip leading dot */#if 0		if (*cp == '.')			++cp;#endif		cp = readOperator (cp, operator);		/* attempt second read of symbol */		if (vStringLength (name) == 0)		{			while (isspace ((int) *cp))				++cp;			cp = readSymbol (cp, name);			nameFollows = TRUE;		}		makeAsmTag (name, operator, labelCandidate, nameFollows);	}	vStringDelete (name);	vStringDelete (operator);}static void initialize (const langType language){	Lang_asm = language;	buildAsmKeywordHash ();}extern parserDefinition* AsmParser (void){	static const char *const extensions [] = {		"asm", "ASM", "s", "S", NULL	};	static const char *const patterns [] = {		"*.A51",		"*.29[kK]",		"*.[68][68][kKsSxX]",		"*.[xX][68][68]",		NULL	};	parserDefinition* def = parserNew ("Asm");	def->kinds      = AsmKinds;	def->kindCount  = KIND_COUNT (AsmKinds);	def->extensions = extensions;	def->patterns   = patterns;	def->parser     = findAsmTags;	def->initialize = initialize;	return def;}/* vi:set tabstop=4 shiftwidth=4: */

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -