0,0 → 1,1056 |
/* |
Copyright (C) 1996-1997 Id Software, Inc. |
|
This program is free software; you can redistribute it and/or |
modify it under the terms of the GNU General Public License |
as published by the Free Software Foundation; either version 2 |
of the License, or (at your option) any later version. |
|
This program is distributed in the hope that it will be useful, |
but WITHOUT ANY WARRANTY; without even the implied warranty of |
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. |
|
See the GNU General Public License for more details. |
|
You should have received a copy of the GNU General Public License |
along with this program; if not, write to the Free Software |
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. |
|
*/ |
// |
// gas to MASM source code converter |
// |
|
#include <stdio.h> |
#include <stdlib.h> |
#include <string.h> |
|
#define MAX_TOKENS 100 |
#define MAX_TOKEN_LENGTH 1024 |
#define LF 0x0A |
|
typedef enum {NOT_WHITESPACE, WHITESPACE, TOKEN_AVAILABLE, LINE_DONE, FILE_DONE, PARSED_OKAY} tokenstat; |
typedef enum {NOSEG, DATASEG, TEXTSEG} segtype; |
|
int tokennum; |
int inline, outline; |
|
char *token; |
char tokens[MAX_TOKENS][MAX_TOKEN_LENGTH+1]; |
|
segtype currentseg = NOSEG; |
|
typedef struct { |
char *text; |
char *emit; |
int numtokens; |
void (*parsefunc) (void); |
} parsefield; |
|
|
void errorexit (void); |
|
|
//============================================== |
|
typedef struct { |
char *text; |
char *emit; |
int len; |
} regdesc; |
|
regdesc reglist[] = { |
{"%eax", "eax", 4}, |
{"%ebx", "ebx", 4}, |
{"%ecx", "ecx", 4}, |
{"%edx", "edx", 4}, |
{"%esi", "esi", 4}, |
{"%edi", "edi", 4}, |
{"%ebp", "ebp", 4}, |
{"%esp", "esp", 4}, |
{"%ax", "ax", 3}, |
{"%bx", "bx", 3}, |
{"%cx", "cx", 3}, |
{"%dx", "dx", 3}, |
{"%si", "si", 3}, |
{"%di", "di", 3}, |
{"%bp", "bp", 3}, |
{"%sp", "sp", 3}, |
{"%al", "al", 3}, |
{"%bl", "bl", 3}, |
{"%cl", "cl", 3}, |
{"%dl", "dl", 3}, |
{"%ah", "ah", 3}, |
{"%bh", "bh", 3}, |
{"%ch", "ch", 3}, |
{"%dh", "dh", 3}, |
{"%st(0)", "st(0)", 6}, |
{"%st(1)", "st(1)", 6}, |
{"%st(2)", "st(2)", 6}, |
{"%st(3)", "st(3)", 6}, |
{"%st(4)", "st(4)", 6}, |
{"%st(5)", "st(5)", 6}, |
{"%st(6)", "st(6)", 6}, |
{"%st(7)", "st(7)", 6}, |
}; |
|
int numregs = sizeof (reglist) / sizeof (reglist[0]); |
|
//============================================== |
|
|
void emitanoperand (int tnum, char *type, int notdata) |
{ |
int i, index, something_outside_parens, regfound; |
int parencount; |
char *pt; |
char temp[MAX_TOKEN_LENGTH+1]; |
|
pt = tokens[tnum]; |
|
if (pt[0] == '%') |
{ |
// register |
for (i=0 ; i<numregs ; i++) |
{ |
if (!strcmpi (pt, reglist[i].text)) |
{ |
printf ("%s", reglist[i].emit); |
return; |
} |
} |
|
fprintf (stderr, "Error: bad register %s\n", pt); |
errorexit (); |
} |
else if (pt[0] == '$') |
{ |
// constant |
if (pt[1] == '(') |
{ |
if ((pt[2] > '9') || (pt[2] < '0')) |
{ |
i = 2; |
printf ("offset "); |
|
parencount = 1; |
|
while ((pt[i] != ')') || (parencount > 1)) |
{ |
if (!pt[i]) |
{ |
fprintf (stderr, "mismatched parens"); |
errorexit (); |
} |
|
if (pt[i] == ')') |
parencount--; |
else if (pt[i] == '(') |
parencount++; |
|
printf ("%c", pt[i]); |
i++; |
} |
} |
else |
{ |
pt++; |
|
parencount = 1; |
|
for (i=1 ; (pt[i] != ')') || (parencount > 1) ; i++) |
{ |
if (!pt[i]) |
{ |
fprintf (stderr, "mismatched parens"); |
errorexit (); |
} |
|
if (pt[i] == ')') |
parencount--; |
else if (pt[i] == '(') |
parencount++; |
} |
|
pt[i] = 0; |
|
if ((pt[1] == '0') && ((pt[2] == 'x') || (pt[2] == 'X'))) |
{ |
printf ("0%sh", &pt[3]); |
} |
else |
{ |
printf ("%s", &pt[1]); |
} |
} |
} |
else if ((pt[1] == '0') && ((pt[2] == 'x') || (pt[2] == 'X'))) |
{ |
printf ("0%sh", &pt[3]); |
} |
else if ((pt[1] >= '0') && (pt[1] <= '9')) |
{ |
printf ("%s", &pt[1]); |
} |
else |
{ |
printf ("offset %s", &pt[1]); |
} |
} |
else if (!notdata && ((pt[0] >= '0') && (pt[0] <= '9'))) |
{ |
pt--; |
|
if ((pt[1] == '0') && ((pt[2] == 'x') || (pt[2] == 'X'))) |
{ |
printf ("0%sh", &pt[3]); |
} |
else |
{ |
printf ("%s", &pt[1]); |
} |
} |
else |
{ |
// must be a memory location |
strcpy (temp, type); |
index = strlen (temp); |
|
if (notdata) |
temp[index++] = '['; |
|
something_outside_parens = 0; |
|
while (*pt) |
{ |
if (index > (MAX_TOKEN_LENGTH - 10)) |
{ |
fprintf (stderr, "Error: operand too long %s\n", |
tokens[tnum]); |
errorexit (); |
} |
|
if (*pt != ')') |
{ |
if (*pt == '(') |
{ |
if (something_outside_parens) |
temp[index++] = '+'; |
} |
else if (*pt == '%') |
{ |
regfound = 0; |
|
for (i=0 ; i<numregs ; i++) |
{ |
if (!strnicmp (pt, reglist[i].text, |
reglist[i].len)) |
{ |
strcpy (&temp[index], reglist[i].emit); |
index += strlen (reglist[i].emit); |
pt += strlen (reglist[i].text) - 1; |
regfound = 1; |
break; |
} |
} |
|
if (!regfound) |
{ |
fprintf (stderr, "Error: bad register %s\n", pt); |
errorexit (); |
} |
} |
else if (*pt == ',') |
{ |
pt++; |
|
if ((*pt >= '1') && (*pt <= '8')) |
{ |
temp[index++] = '*'; |
temp[index++] = *pt; |
} |
else if (*pt != ')') |
{ |
if (temp[index-1] != '+') |
temp[index++] = '+'; |
} |
} |
else |
{ |
something_outside_parens = 1; |
|
// handle hexadecimal constants in addresses |
if ((*pt == '0') && |
((*(pt+1) == 'x') || (*(pt+1) == 'X'))) |
{ |
pt += 2; |
|
do |
{ |
temp[index++] = *pt++; |
} while (((*pt >= '0') && (*pt <= '9')) || |
((*pt >= 'a') && (*pt <= 'f')) || |
((*pt >= 'A') && (*pt <= 'F'))); |
|
pt--; |
temp[index++] = 'h'; |
} |
else |
{ |
temp[index++] = *pt; |
} |
} |
} |
|
pt++; |
} |
|
if (notdata) |
temp[index++] = ']'; |
|
temp[index] = 0; |
printf ("%s", temp); |
} |
} |
|
|
void datasegstart (void) |
{ |
if (currentseg == DATASEG) |
return; |
|
if (currentseg == TEXTSEG) |
printf ("_TEXT ENDS\n"); |
|
printf ("_DATA SEGMENT"); |
|
currentseg = DATASEG; |
} |
|
|
void textsegstart (void) |
{ |
if (currentseg == TEXTSEG) |
return; |
|
if (currentseg == DATASEG) |
printf ("_DATA ENDS\n"); |
|
printf ("_TEXT SEGMENT"); |
|
currentseg = TEXTSEG; |
} |
|
|
void emitdata (void) |
{ |
int i; |
|
for (i=1 ; i<(tokennum-1) ; i++) |
printf (" %s,", tokens[i]); |
|
printf (" %s", tokens[tokennum-1]); |
} |
|
|
void emitonedata (void) |
{ |
|
printf (" %s", tokens[1]); |
} |
|
|
void emitonecalldata (void) |
{ |
int i, isaddr, len; |
|
if (tokens[1][0] == '*') |
{ |
printf (" dword ptr[%s]", &tokens[1][1]); |
} |
else |
{ |
isaddr = 0; |
len = strlen(tokens[1]); |
|
for (i=0 ; i<len ; i++) |
{ |
if (tokens[1][i] == '(') |
{ |
isaddr = 1; |
break; |
} |
} |
|
if (!isaddr) |
{ |
printf (" near ptr %s", tokens[1]); |
} |
else |
{ |
emitanoperand (1, " dword ptr", 1); |
} |
} |
} |
|
|
void emitonejumpdata (void) |
{ |
int i, isaddr, len; |
|
if (tokens[1][0] == '*') |
{ |
printf (" dword ptr[%s]", &tokens[1][1]); |
} |
else |
{ |
isaddr = 0; |
len = strlen(tokens[1]); |
|
for (i=0 ; i<len ; i++) |
{ |
if (tokens[1][i] == '(') |
{ |
isaddr = 1; |
break; |
} |
} |
|
if (!isaddr) |
{ |
printf (" %s", tokens[1]); |
} |
else |
{ |
emitanoperand (1, " dword ptr", 1); |
} |
} |
} |
|
|
void emitexterndef (void) |
{ |
|
printf (" %s:dword", tokens[1]); |
} |
|
|
void nooperands (void) |
{ |
|
} |
|
|
void emitoneoperandl (void) |
{ |
|
printf (" "); |
emitanoperand (1, "ds:dword ptr", 1); |
} |
|
|
void emitoneoperandb (void) |
{ |
|
printf (" "); |
emitanoperand (1, "ds:byte ptr", 1); |
} |
|
|
void emitoneoperandw (void) |
{ |
|
printf (" "); |
emitanoperand (1, "ds:word ptr", 1); |
} |
|
|
void emittwooperandsl (void) |
{ |
|
printf (" "); |
emitanoperand (2, "ds:dword ptr", 1); |
printf (","); |
emitanoperand (1, "ds:dword ptr", 1); |
} |
|
|
void emittwooperandsb (void) |
{ |
|
printf (" "); |
emitanoperand (2, "ds:byte ptr", 1); |
printf (","); |
emitanoperand (1, "ds:byte ptr", 1); |
} |
|
|
void emittwooperandsw (void) |
{ |
|
printf (" "); |
emitanoperand (2, "ds:word ptr", 1); |
printf (","); |
emitanoperand (1, "ds:word ptr", 1); |
} |
|
|
void emit_0_or_1_operandsl (void) |
{ |
|
if (tokennum == 2) |
{ |
printf (" "); |
emitanoperand (1, "ds:dword ptr", 1); |
} |
} |
|
|
void emit_1_or_2_operandsl (void) |
{ |
int j; |
|
if (tokennum == 2) |
{ |
printf (" "); |
emitanoperand (1, "ds:dword ptr", 1); |
} |
else if (tokennum == 3) |
{ |
printf (" "); |
emitanoperand (2, "ds:dword ptr", 1); |
printf (","); |
emitanoperand (1, "ds:dword ptr", 1); |
} |
else |
{ |
|
fprintf (stderr, "Error: too many operands\n"); |
|
for (j=0 ; j<tokennum ; j++) |
fprintf (stderr, "%s\n", tokens[j]); |
|
fprintf (stderr, "\n"); |
errorexit (); |
} |
} |
|
|
void emit_1_or_2_operandsl_vartext (char *str0, char *str1) |
{ |
int j; |
|
if (tokennum == 2) |
{ |
printf (" %s ", str0); |
emitanoperand (1, "ds:dword ptr", 1); |
} |
else if (tokennum == 3) |
{ |
if (!strcmpi (tokens[2], "%st(0)")) |
printf (" %s ", str0); |
else |
printf (" %s ", str1); |
|
emitanoperand (2, "ds:dword ptr", 1); |
printf (","); |
emitanoperand (1, "ds:dword ptr", 1); |
} |
else |
{ |
|
fprintf (stderr, "Error: too many operands\n"); |
|
for (j=0 ; j<tokennum ; j++) |
fprintf (stderr, "%s\n", tokens[j]); |
|
fprintf (stderr, "\n"); |
errorexit (); |
} |
} |
|
|
void special_fdivl (void) |
{ |
|
emit_1_or_2_operandsl_vartext ("fdiv", "fdivr"); |
} |
|
|
void special_fdivpl (void) |
{ |
|
emit_1_or_2_operandsl_vartext ("fdivp", "fdivrp"); |
} |
|
|
void special_fdivrl (void) |
{ |
|
emit_1_or_2_operandsl_vartext ("fdivr", "fdiv"); |
} |
|
|
void special_fdivrpl (void) |
{ |
|
emit_1_or_2_operandsl_vartext ("fdivrp", "fdivp"); |
} |
|
|
void special_fsubl (void) |
{ |
|
emit_1_or_2_operandsl_vartext ("fsub", "fsubr"); |
} |
|
|
void special_fsubpl (void) |
{ |
|
emit_1_or_2_operandsl_vartext ("fsubp", "fsubrp"); |
} |
|
|
void special_fsubrl (void) |
{ |
|
emit_1_or_2_operandsl_vartext ("fsubr", "fsub"); |
} |
|
|
void special_fsubrpl (void) |
{ |
|
emit_1_or_2_operandsl_vartext ("fsubrp", "fsubp"); |
} |
|
|
void emit_multiple_data (void) |
{ |
int i; |
|
printf (" "); |
|
for (i=1 ; i<(tokennum-1) ; i++) |
{ |
emitanoperand (i, "", 0); |
printf (", "); |
} |
|
emitanoperand (i, "", 0); |
} |
|
|
//============================================== |
|
parsefield parsedata[] = { |
{".align", " align", 2, emitonedata}, |
{".byte", " db", -2, emit_multiple_data}, |
{".data", "", 1, datasegstart}, |
{".extern"," externdef", 2, emitexterndef}, |
{".globl", " public", -2, emit_multiple_data}, |
{".long", " dd", -2, emit_multiple_data}, |
{".single"," dd", -2, emit_multiple_data}, |
{".text", "", 1, textsegstart}, |
{"adcl", " adc", 3, emittwooperandsl}, |
{"addb", " add", 3, emittwooperandsb}, |
{"addl", " add", 3, emittwooperandsl}, |
{"andb", " and", 3, emittwooperandsb}, |
{"andl", " and", 3, emittwooperandsl}, |
{"call", " call", 2, emitonecalldata}, |
{"cmpb", " cmp", 3, emittwooperandsb}, |
{"cmpl", " cmp", 3, emittwooperandsl}, |
{"cmpw", " cmp", 3, emittwooperandsw}, |
{"decl", " dec", 2, emitoneoperandl}, |
{"decw", " dec", 2, emitoneoperandw}, |
{"divl", " div", 2, emitoneoperandl}, |
{"fadd", " fadd", -2, emit_1_or_2_operandsl}, |
{"faddp", " faddp", -2, emit_1_or_2_operandsl}, |
{"faddps", " faddp", -2, emit_1_or_2_operandsl}, |
{"fadds", " fadd", -2, emit_1_or_2_operandsl}, |
{"fcom", " fcom", 2, emitoneoperandl}, |
{"fcoms", " fcom", 2, emitoneoperandl}, |
{"fcomp", " fcomp", 2, emitoneoperandl}, |
{"fcomps", " fcomp", 2, emitoneoperandl}, |
{"fdiv", "", -2, special_fdivl}, |
{"fdivp", "", -2, special_fdivpl}, |
{"fdivr", "", -2, special_fdivrl}, |
{"fdivrp", "", -2, special_fdivrpl}, |
{"fdivrs", "", -2, special_fdivrl}, |
{"fildl", " fild", 2, emitoneoperandl}, |
{"fistl", " fist", 2, emitoneoperandl}, |
{"fistpl", " fistp", 2, emitoneoperandl}, |
{"fld", " fld", 2, emitoneoperandl}, |
{"fldcw", " fldcw", 2, emitoneoperandw}, |
{"fldenv", " fldenv", 2, emitoneoperandl}, |
{"flds", " fld", 2, emitoneoperandl}, |
{"fmul", " fmul", -2, emit_1_or_2_operandsl}, |
{"fmulp", " fmulp", -2, emit_1_or_2_operandsl}, |
{"fmulps", " fmulp", -2, emit_1_or_2_operandsl}, |
{"fmuls", " fmul", -2, emit_1_or_2_operandsl}, |
{"fnstcw", " fnstcw", 2, emitoneoperandw}, |
{"fnstenv"," fnstenv", 2, emitoneoperandl}, |
{"fnstsw", " fnstsw", 2, emitoneoperandw}, |
{"fstp", " fstp", 2, emitoneoperandl}, |
{"fstps", " fstp", 2, emitoneoperandl}, |
{"fsts", " fst", 2, emitoneoperandl}, |
{"fsubr", "", -2, special_fsubrl}, |
{"fsubrp", "", -2, special_fsubrpl}, |
{"fsubrs", "", -2, special_fsubrl}, |
{"fsub", "", -2, special_fsubl}, |
{"fsubp", "", -2, special_fsubpl}, |
{"fsubps", "", -2, special_fsubpl}, |
{"fsubs", "", -2, special_fsubl}, |
{"fxch", " fxch", 2, emitoneoperandl}, |
{"imull", " imul", -2, emit_1_or_2_operandsl}, |
{"incl", " inc", 2, emitoneoperandl}, |
{"ja", " ja", 2, emitonedata}, |
{"jae", " jae", 2, emitonedata}, |
{"jb", " jb", 2, emitonedata}, |
{"jbe", " jbe", 2, emitonedata}, |
{"jc", " jc", 2, emitonedata}, |
{"je", " je", 2, emitonedata}, |
{"jg", " jg", 2, emitonedata}, |
{"jge", " jge", 2, emitonedata}, |
{"jl", " jl", 2, emitonedata}, |
{"jle", " jle", 2, emitonedata}, |
{"jmp", " jmp", 2, emitonejumpdata}, |
{"jna", " jna", 2, emitonedata}, |
{"jnae", " jnae", 2, emitonedata}, |
{"jnb", " jnb", 2, emitonedata}, |
{"jnbe", " jnbe", 2, emitonedata}, |
{"jnc", " jnc", 2, emitonedata}, |
{"jne", " jne", 2, emitonedata}, |
{"jng", " jng", 2, emitonedata}, |
{"jnge", " jnge", 2, emitonedata}, |
{"jnl", " jnl", 2, emitonedata}, |
{"jnle", " jnle", 2, emitonedata}, |
{"jns", " jns", 2, emitonedata}, |
{"jnz", " jnz", 2, emitonedata}, |
{"js", " js", 2, emitonedata}, |
{"jz", " jz", 2, emitonedata}, |
{"leal", " lea", 3, emittwooperandsl}, |
{"movb", " mov", 3, emittwooperandsb}, |
{"movl", " mov", 3, emittwooperandsl}, |
{"movw", " mov", 3, emittwooperandsw}, |
{"negl", " neg", 2, emitoneoperandl}, |
{"orb", " or", 3, emittwooperandsb}, |
{"orl", " or", 3, emittwooperandsl}, |
{"popl", " pop", 2, emitoneoperandl}, |
{"pushl", " push", 2, emitoneoperandl}, |
{"ret", " ret", -1, emit_0_or_1_operandsl}, |
{"rorl", " ror", 3, emittwooperandsl}, |
{"sarl", " sar", 3, emittwooperandsl}, |
{"sbbl", " sbb", 3, emittwooperandsl}, |
{"shll", " shl", 3, emittwooperandsl}, |
{"shrl", " shr", 3, emittwooperandsl}, |
{"subl", " sub", 3, emittwooperandsl}, |
{"testb", " test", 3, emittwooperandsb}, |
{"testl", " test", 3, emittwooperandsl}, |
{"xorb", " xor", 3, emittwooperandsb}, |
{"xorl", " xor", 3, emittwooperandsl}, |
}; |
|
int numparse = sizeof (parsedata) / sizeof (parsedata[0]); |
|
//============================================== |
|
void errorexit (void) |
{ |
fprintf (stderr, "In line: %d, out line: %d\n", inline, outline); |
exit (1); |
} |
|
|
tokenstat whitespace (char c) |
{ |
if (c == '\n') |
return LINE_DONE; |
|
if ((c <= ' ') || |
(c > 127) || |
(c == ',')) |
{ |
return WHITESPACE; |
} |
|
return NOT_WHITESPACE; |
} |
|
|
int gettoken (void) |
{ |
char c; |
int count, parencount; |
tokenstat stat; |
|
do |
{ |
if ((c = getchar ()) == EOF) |
return FILE_DONE; |
|
if ((stat = whitespace (c)) == LINE_DONE) |
return LINE_DONE; |
} while (stat == WHITESPACE); |
|
token[0] = c; |
count = 1; |
|
if (c == '~') |
{ |
count--; |
token[count++] = 'n'; |
token[count++] = 'o'; |
token[count++] = 't'; |
token[count++] = ' '; |
} |
|
if (c == '(') |
{ |
do |
{ |
if ((c = getchar ()) == EOF) |
{ |
fprintf (stderr, "EOF in middle of parentheses\n"); |
errorexit (); |
} |
|
token[count++] = c; |
|
} while (c != ')'); |
} |
|
for ( ;; ) |
{ |
if ((c = getchar ()) == EOF) |
{ |
token[count] = 0; |
return TOKEN_AVAILABLE; |
} |
|
if (whitespace (c) == LINE_DONE) |
{ |
if (ungetc (c, stdin) == EOF) |
{ |
fprintf (stderr, "Couldn't unget character\n"); |
errorexit (); |
} |
|
token[count] = 0; |
return TOKEN_AVAILABLE; |
} |
|
if (whitespace (c) == WHITESPACE) |
{ |
token[count] = 0; |
return TOKEN_AVAILABLE; |
} |
|
if (count >= MAX_TOKEN_LENGTH) |
{ |
fprintf (stderr, "Error: token too long\n"); |
errorexit (); |
} |
|
token[count++] = c; |
|
if (c == '~') |
{ |
count--; |
token[count++] = 'n'; |
token[count++] = 'o'; |
token[count++] = 't'; |
token[count++] = ' '; |
} |
else if (c == '(') |
{ |
parencount = 1; |
|
do |
{ |
if ((c = getchar ()) == EOF) |
{ |
fprintf (stderr, "EOF in middle of parentheses\n"); |
errorexit (); |
} |
|
if (c == '(') |
parencount++; |
else if (c == ')') |
parencount--; |
|
if (c == '~') |
{ |
token[count++] = 'n'; |
token[count++] = 'o'; |
token[count++] = 't'; |
token[count++] = ' '; |
} |
else |
{ |
token[count++] = c; |
} |
|
} while ((c != ')') || (parencount > 0)); |
} |
} |
} |
|
|
tokenstat parseline (void) |
{ |
tokenstat stat; |
int i, j, firsttoken, labelfound; |
int mnemfound; |
|
firsttoken = 1; |
tokennum = 0; |
labelfound = 0; |
|
for ( ;; ) |
{ |
token = tokens[tokennum]; |
stat = gettoken (); |
|
switch (stat) |
{ |
case FILE_DONE: |
return FILE_DONE; |
|
case LINE_DONE: |
if (!firsttoken && tokennum) |
{ |
mnemfound = 0; |
|
for (i=0 ; i<numparse; i++) |
{ |
if (!strcmpi (tokens[0], parsedata[i].text)) |
{ |
if (((parsedata[i].numtokens > 0) && |
(parsedata[i].numtokens != tokennum)) || |
((parsedata[i].numtokens < 0) && |
(tokennum < -parsedata[i].numtokens))) |
{ |
fprintf (stderr, "mismatched number of tokens\n"); |
|
for (j=0 ; j<tokennum ; j++) |
fprintf (stderr, "%s\n", tokens[j]); |
|
fprintf (stderr, "\n"); |
errorexit (); |
} |
|
printf ("%s", parsedata[i].emit); |
(*parsedata[i].parsefunc) (); |
|
mnemfound = 1; |
break; |
} |
} |
|
if (!mnemfound) |
{ |
fprintf (stderr, "Error: unknown mnemonic\n"); |
|
for (j=0 ; j<tokennum ; j++) |
fprintf (stderr, "%s\n", tokens[j]); |
|
fprintf (stderr, "\n"); |
errorexit (); |
} |
} |
|
if (!firsttoken) |
{ |
if ((currentseg == DATASEG) && labelfound && !tokennum) |
printf (":\n"); |
else |
printf ("\n"); |
|
outline++; |
} |
return PARSED_OKAY; |
|
case TOKEN_AVAILABLE: |
if (firsttoken) |
{ |
if (token[strlen(token) - 1] == ':') |
{ |
labelfound = 1; |
|
if (currentseg == DATASEG) |
{ |
token[strlen(token) - 1] = 0; |
printf ("%s", token); |
} |
else if (currentseg == TEXTSEG) |
{ |
printf ("%s", token); |
} |
else |
{ |
fprintf (stderr, "Error: not in segment block\n"); |
errorexit (); |
} |
|
firsttoken = 0; |
break; |
} |
} |
|
firsttoken = 0; |
|
if (tokennum >= MAX_TOKENS) |
{ |
fprintf (stderr, "Error: too many tokens\n"); |
exit (0); |
} |
|
tokennum++; |
|
break; |
|
default: |
fprintf (stderr, "Error: unknown tokenstat %d\n", stat); |
exit (0); |
} |
} |
} |
|
|
void main (int argc, char **argv) |
{ |
tokenstat stat; |
|
printf (" .386P\n" |
" .model FLAT\n"); |
inline = 1; |
outline = 3; |
|
for ( ;; ) |
{ |
stat = parseline (); |
inline++; |
|
switch (stat) |
{ |
case FILE_DONE: |
if (currentseg == TEXTSEG) |
printf ("_TEXT ENDS\n"); |
else if (currentseg == DATASEG) |
printf ("_DATA ENDS\n"); |
|
printf (" END\n"); |
exit (0); |
|
case PARSED_OKAY: |
break; |
|
default: |
fprintf (stderr, "Error: unknown tokenstat %d\n", stat); |
exit (0); |
} |
} |
} |
|