From: nagorny@rbg.informatik.th-darmstadt.de (alexander nagorny)
Subject: Re: Wie binde ich ein Assemblerprg. in GNU-C ein?
Date: Tue, 15 Dec 1992 15:42:29 GMT
Organization: TU Darmstadt

Hallo,

ich habe dieses einfache Lex-Programm gefunden.

Vieleicht hilft es dir bei der Konvertierung

von einfachen Assembler-Programmen weiter.

Gruss

	Alexander Nagorny

email: nagorny@rbg.informatik.th-darmstadt.de



----------------- Begin of lex program ---------------------------------------
%{
/* cv68.l
 *
 * simple lex program for converting 68K motorola assembler syntax into GNU's
 * GAS syntax. WARNING: It's only a lex program, hence no real syntax analysis
 * of the input text is performed. For that a yacc script would be needed,
 * which, i decided, is too slow, and it's not worth the effort, since most of
 * the asm syntax is simple enough to analyse it with a simple finite state
 * maschine.
 *
 * Be aware that all this is a quick but fairly well working hack!
 *
 * written in 10-12-89 by Kai-Uwe Bloem, I5110401@dbstu1.bitnet
 */

/*
 * states of the FSM.
 */
#define	START	0		/* awaiting a new source line */
#define	LDECL	1		/* label or declaration parsed */
#define	INSTR	2		/* instruction parsed */
#define	OP1	3		/* 1st operand parsed */
#define	OP2	4		/* 2nd operand parsed */
#define	DIREC	10		/* assembler directive line */
#define	COMM	11		/* comment line */

/* strongly simplified grammar:
 *
 * START -> LDECL -> INSTR -> OP1 -> OP2
 *   ^        |        |       |      |
 *   +-- <- --+-- <- --+-- <- -+- <- -+
 */


/*
 * forward declarations
 */
static void p_err();

/*
 * global variables
 */
int state = START;	/* current state */
int lineno = 1;		/* current source line */

/* Opcodes which imply a word length operation (.w) */
char *opcodes[] = {	"add", "clr", "cmp", "neg", "sub", "tst",
			"asl", "asr", "lsl", "lsr", "rol", "ror",
			"and", "eor", "not", "or" , "move", NULL };
			/* Some codes are guaranteed to be missing here... */
%}

delim		[;\n]
wspace		[ \t]+
xnum		"0x"[0-9a-fA-F]+
dnum		"-"?[0-9]+
number		{dnum}|{xnum}
prglabel	[A-Za-z_][A-Za-z0-9_]*
value		{number}|{prglabel}
expr		{value}(("+"|"-"){value})?

dreg		"d"[0-7]
areg		("a"[0-7])|"sp"|"usp"|"pc"
opreg		{dreg}|{areg}|"sr"|"ccr"
opimmd		"#"{expr}
opaddr		{expr}
opreglst	{opreg}("-"{opreg})?("/"{opreg}("-"{opreg})?)*

simploprs	{opreg}|{opimmd}|{opaddr}|{opreglst}
opind		("-("{areg}")")|("("{areg}")+")|("("{areg}")")
opindoff	{expr}"("{areg}(","{opreg}("."[wl])?)?")"

opcode		[a-z]+("."[bwl])?

directive	("."[a-z0-9]+{wspace}[^!;\n]*)|("#"[a-zA-Z][^\n]*)
comment		"!".*
decl		({prglabel}":")|({prglabel}{wspace}*"="{wspace}*{expr})

%%

{wspace}*{opcode} {
	char *s = yytext;
	char **t = opcodes;

	if (state == START || state == LDECL)
	{
		while (*s == ',' || *s == ' ' || *s == '\t')
			fputc(*s++,yyout);
		while (*t != NULL)
		{
			if (!strcmp(*t,s))
			{
				fputs(s,yyout);
				fputc('w',yyout);
				*s = '\0';	/* bogous hack */
				break;
			}
			t++;
		}

		while (*s)
		{
			if (*s != '.')
				fputc(*s,yyout);
			s++;
		}
		state = INSTR;
	}
	else if (state == INSTR || state == OP1)
	{	/* must be a simple value operand... what a crock	*/
		/* (but then, it's just a lex program...)		*/
		fputs( yytext, yyout );
		if (state == INSTR)
			state = OP1;
		else	state = OP2;
	}		
	else	p_err( "unexpected opcode" );
}

((","{wspace}?)|{wspace}){simploprs} {
	if (state == INSTR || state == OP1)
		fputs( yytext, yyout );
	else	p_err( "misplaced operand" );
	if (state == INSTR)
		state = OP1;
	else	state = OP2;
}

((","{wspace}?)|{wspace}){opind} {
	char	*s = yytext;
	int	predecr = 0;

	if (state == INSTR || state == OP1)
	{
		while (*s == ',' || *s == ' ' || *s == '\t')
			fputc(*s++,yyout);
		predecr = *s == '-';
		if (predecr)
			s += 2;
		else	s++;	/* s now points to the address reg */

		fputc(*s++,yyout);	/* register qualifier	*/
		fputc(*s++,yyout);	/* register number	*/
		fputc('@',yyout);	/* indirect qualifier	*/
		if (predecr)		/* decrement/increment	*/
			fputc('-',yyout);
		else if (s[1] == '+')
			fputc('+',yyout);
	}
	else	p_err( "misplaced operand" );
	if (state == INSTR)
		state = OP1;
	else	state = OP2;
}

((","{wspace}?)|{wspace}){opindoff} {
	char	*s = yytext;
	char	*num;

	if (state == INSTR || state == OP1)
	{
		while (*s == ',' || *s == ' ' || *s == '\t')
			fputc(*s++,yyout);
		num = s;
		while (*s != '(') s++;
		*s++ = '\0';			/* skip '(' */

		fputc(*s++,yyout);		/* register qualifier	*/
		fputc(*s++,yyout);		/* register number	*/
		fputc('@',yyout);		/* indirect qualifier	*/
		fputc('(',yyout);		/* offset qualifier	*/
		fputs(num,yyout);		/* offset value		*/
		if (!strncmp(s-2,"pc",2)) {	/* pc-rel is different	*/
			fputs("-.-2",yyout);	/* ... in ACK and GNU	*/
			fprintf(stderr,
				"cv68: line %d, pc-rel. may cause problems\n",
				lineno);
		}
		if (*s++ == ',')		/* distance register	*/
		{
			fputc(',',yyout);
			fputc(*s++,yyout);	/* distance qualifier	*/
			fputc(*s++,yyout);	/* distance number	*/
			if (*s++ == '.')	/* length qualifier	*/
			{
				fputc(':',yyout);
				fputc(*s++,yyout);
			}
		}
		fputc(')',yyout);
	}
	else	p_err( "misplaced operand" );
	if (state == INSTR)
		state = OP1;
	else	state = OP2;
}

{directive} {
	if (!strncmp(yytext,".define",7) || !strncmp(yytext,".extern",7))
	{
		fputs(".globl",yyout);
		fputs(&yytext[7],yyout);
	}
	else if (!strncmp(yytext,".space",6))
	{
		fputs(".skip",yyout);
		fputs(&yytext[6],yyout);
	}
	else if (!strncmp(yytext,".data",5))
	{
		if (yytext[5] == '2')
			fputs(".word",yyout);
		else if (yytext[5] == '4')
			fputs(".long",yyout);
		else if (yytext[5] == '1')
			fputs(".byte",yyout);
		fputs(&yytext[6],yyout);
	}
	else if (!strncmp(yytext,".sect",5))
	{
		char *s = &yytext[5];
		while (*s == ' ' || *s == '\t') s++;
		if (!strncmp(s,".text",5) || !strncmp(s,".data",5))
			fputs(s,yyout);
		else if (!strncmp(s,".bss",4))
		{
			fprintf(stderr,"cv68: line %d, no support for .bss\n",
					lineno);
			fputs(".data	| really .bss, but not in gcc-as...",
					yyout);
		}
		else
		{
			fputc('|',yyout);
			fputs(yytext,yyout);
		}
	}
	else	fputs(yytext,yyout);
}

{comment} {
	fputc('|',yyout);
	fputs(&yytext[1],yyout);
}

{decl} {
	char *s = yytext;

	while(*s && *s != '=')
		fputc(*s++,yyout);
	if (*s && s[-1] != ' ' && s[-1] != '\t')
		fputc(' ',yyout);
	if (*s)
		fputs(s,yyout);
	state = LDECL;
}

{delim} {
	state = START;
	if (yytext[0] == '\n')
		lineno++;
	fputc('\n',yyout);
}

%%

void
p_err(s)
char *s;
{
	fprintf( stderr, "cv68: line %d, %s\n", lineno, s );
	exit(1);
}

main(argc,argv)
int argc;
char *argv[];
{
	int i=0;

	yyout = stdout;
	while(++i < argc)
	{
		if (!strcmp(argv[i],"-v")) {
			printf( "cv68 V1.0, written by KUB\n" );
			continue;
		}
		if (!strcmp(argv[i],"-"))
			yyin = stdin;
		else if ((yyin = fopen(argv[i],"r")) == (FILE *)NULL)
			continue;

		while( yylex() > 0 )
			;
		if (yyin != stdin) fclose(yyin);
	}
}
--------- end of lex program -------------------------------------------------
Newsgroups: de.comp.gnu