1/*
2Copyright (C) 1996-1997 Id Software, Inc.
3
4This program is free software; you can redistribute it and/or
5modify it under the terms of the GNU General Public License
6as published by the Free Software Foundation; either version 2
7of the License, or (at your option) any later version.
8
9This program is distributed in the hope that it will be useful,
10but WITHOUT ANY WARRANTY; without even the implied warranty of
11MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
12
13See the GNU General Public License for more details.
14
15You should have received a copy of the GNU General Public License
16along with this program; if not, write to the Free Software
17Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
18
19*/
20//
21// gas to MASM source code converter
22//
23
24#include <stdio.h>
25#include <stdlib.h>
26#include <string.h>
27
28#define MAX_TOKENS			100
29#define MAX_TOKEN_LENGTH	1024
30#define LF					0x0A
31
32typedef enum {NOT_WHITESPACE, WHITESPACE, TOKEN_AVAILABLE, LINE_DONE, FILE_DONE, PARSED_OKAY} tokenstat;
33typedef enum {NOSEG, DATASEG, TEXTSEG} segtype;
34
35int		tokennum;
36int		inline, outline;
37
38char	*token;
39char	tokens[MAX_TOKENS][MAX_TOKEN_LENGTH+1];
40
41segtype	currentseg = NOSEG;
42
43typedef struct {
44	char	*text;
45	char	*emit;
46	int		numtokens;
47	void	(*parsefunc) (void);
48} parsefield;
49
50
51void errorexit (void);
52
53
54//==============================================
55
56typedef struct {
57	char	*text;
58	char	*emit;
59	int		len;
60} regdesc;
61
62regdesc	reglist[] = {
63	{"%eax", "eax", 4},
64	{"%ebx", "ebx", 4},
65	{"%ecx", "ecx", 4},
66	{"%edx", "edx", 4},
67	{"%esi", "esi", 4},
68	{"%edi", "edi", 4},
69	{"%ebp", "ebp", 4},
70	{"%esp", "esp", 4},
71	{"%ax", "ax", 3},
72	{"%bx", "bx", 3},
73	{"%cx", "cx", 3},
74	{"%dx", "dx", 3},
75	{"%si", "si", 3},
76	{"%di", "di", 3},
77	{"%bp", "bp", 3},
78	{"%sp", "sp", 3},
79	{"%al", "al", 3},
80	{"%bl", "bl", 3},
81	{"%cl", "cl", 3},
82	{"%dl", "dl", 3},
83	{"%ah", "ah", 3},
84	{"%bh", "bh", 3},
85	{"%ch", "ch", 3},
86	{"%dh", "dh", 3},
87	{"%st(0)", "st(0)", 6},
88	{"%st(1)", "st(1)", 6},
89	{"%st(2)", "st(2)", 6},
90	{"%st(3)", "st(3)", 6},
91	{"%st(4)", "st(4)", 6},
92	{"%st(5)", "st(5)", 6},
93	{"%st(6)", "st(6)", 6},
94	{"%st(7)", "st(7)", 6},
95};
96
97int	numregs = sizeof (reglist) / sizeof (reglist[0]);
98
99//==============================================
100
101
102void emitanoperand (int tnum, char *type, int notdata)
103{
104	int		i, index, something_outside_parens, regfound;
105	int		parencount;
106	char	*pt;
107	char	temp[MAX_TOKEN_LENGTH+1];
108
109	pt = tokens[tnum];
110
111	if (pt[0] == '%')
112	{
113	// register
114		for (i=0 ; i<numregs ; i++)
115		{
116			if (!strcmpi (pt, reglist[i].text))
117			{
118				printf ("%s", reglist[i].emit);
119				return;
120			}
121		}
122
123		fprintf (stderr, "Error: bad register %s\n", pt);
124		errorexit ();
125	}
126	else if (pt[0] == '$')
127	{
128	// constant
129		if (pt[1] == '(')
130		{
131			if ((pt[2] > '9') || (pt[2] < '0'))
132			{
133				i = 2;
134				printf ("offset ");
135
136				parencount = 1;
137
138				while ((pt[i] != ')') || (parencount > 1))
139				{
140					if (!pt[i])
141					{
142						fprintf (stderr, "mismatched parens");
143						errorexit ();
144					}
145
146					if (pt[i] == ')')
147						parencount--;
148					else if (pt[i] == '(')
149						parencount++;
150
151					printf ("%c", pt[i]);
152					i++;
153				}
154			}
155			else
156			{
157				pt++;
158
159				parencount = 1;
160
161				for (i=1 ; (pt[i] != ')') || (parencount > 1) ; i++)
162				{
163					if (!pt[i])
164					{
165						fprintf (stderr, "mismatched parens");
166						errorexit ();
167					}
168
169					if (pt[i] == ')')
170						parencount--;
171					else if (pt[i] == '(')
172						parencount++;
173				}
174
175				pt[i] = 0;
176
177				if ((pt[1] == '0') && ((pt[2] == 'x') || (pt[2] == 'X')))
178				{
179					printf ("0%sh", &pt[3]);
180				}
181				else
182				{
183					printf ("%s", &pt[1]);
184				}
185 			}
186		}
187		else if ((pt[1] == '0') && ((pt[2] == 'x') || (pt[2] == 'X')))
188		{
189			printf ("0%sh", &pt[3]);
190		}
191		else if ((pt[1] >= '0') && (pt[1] <= '9'))
192		{
193			printf ("%s", &pt[1]);
194		}
195		else
196		{
197			printf ("offset %s", &pt[1]);
198		}
199	}
200	else if (!notdata && ((pt[0] >= '0') && (pt[0] <= '9')))
201	{
202		pt--;
203
204		if ((pt[1] == '0') && ((pt[2] == 'x') || (pt[2] == 'X')))
205		{
206			printf ("0%sh", &pt[3]);
207		}
208		else
209		{
210			printf ("%s", &pt[1]);
211		}
212	}
213	else
214	{
215	// must be a memory location
216		strcpy (temp, type);
217		index = strlen (temp);
218
219		if (notdata)
220			temp[index++] = '[';
221
222		something_outside_parens = 0;
223
224		while (*pt)
225		{
226			if (index > (MAX_TOKEN_LENGTH - 10))
227			{
228				fprintf (stderr, "Error: operand too long %s\n",
229						 tokens[tnum]);
230				errorexit ();
231			}
232
233			if (*pt != ')')
234			{
235				if (*pt == '(')
236				{
237					if (something_outside_parens)
238						temp[index++] = '+';
239				}
240				else if (*pt == '%')
241				{
242					regfound = 0;
243
244					for (i=0 ; i<numregs ; i++)
245					{
246						if (!strnicmp (pt, reglist[i].text,
247							reglist[i].len))
248						{
249							strcpy (&temp[index], reglist[i].emit);
250							index += strlen (reglist[i].emit);
251							pt += strlen (reglist[i].text) - 1;
252							regfound = 1;
253							break;
254						}
255					}
256
257					if (!regfound)
258					{
259						fprintf (stderr, "Error: bad register %s\n", pt);
260						errorexit ();
261					}
262				}
263				else if (*pt == ',')
264				{
265					pt++;
266
267					if ((*pt >= '1') && (*pt <= '8'))
268					{
269						temp[index++] = '*';
270						temp[index++] = *pt;
271					}
272					else if (*pt != ')')
273					{
274						if (temp[index-1] != '+')
275							temp[index++] = '+';
276					}
277				}
278				else
279				{
280					something_outside_parens = 1;
281
282					// handle hexadecimal constants in addresses
283					if ((*pt == '0') &&
284						((*(pt+1) == 'x') || (*(pt+1) == 'X')))
285					{
286						pt += 2;
287
288						do
289						{
290							temp[index++] = *pt++;
291						} while (((*pt >= '0') && (*pt <= '9'))     ||
292								 ((*pt >= 'a') && (*pt <= 'f')) ||
293								 ((*pt >= 'A') && (*pt <= 'F')));
294
295						pt--;
296						temp[index++] = 'h';
297					}
298					else
299					{
300						temp[index++] = *pt;
301					}
302				}
303			}
304
305			pt++;
306		}
307
308		if (notdata)
309			temp[index++] = ']';
310
311		temp[index] = 0;
312		printf ("%s", temp);
313	}
314}
315
316
317void datasegstart (void)
318{
319	if (currentseg == DATASEG)
320		return;
321
322	if (currentseg == TEXTSEG)
323		printf ("_TEXT ENDS\n");
324
325	printf ("_DATA SEGMENT");
326
327	currentseg = DATASEG;
328}
329
330
331void textsegstart (void)
332{
333	if (currentseg == TEXTSEG)
334		return;
335
336	if (currentseg == DATASEG)
337		printf ("_DATA ENDS\n");
338
339	printf ("_TEXT SEGMENT");
340
341	currentseg = TEXTSEG;
342}
343
344
345void emitdata (void)
346{
347	int		i;
348
349	for (i=1 ; i<(tokennum-1) ; i++)
350		printf (" %s,", tokens[i]);
351
352	printf (" %s", tokens[tokennum-1]);
353}
354
355
356void emitonedata (void)
357{
358
359	printf (" %s", tokens[1]);
360}
361
362
363void emitonecalldata (void)
364{
365	int	i, isaddr, len;
366
367	if (tokens[1][0] == '*')
368	{
369		printf (" dword ptr[%s]", &tokens[1][1]);
370	}
371	else
372	{
373		isaddr = 0;
374		len = strlen(tokens[1]);
375
376		for (i=0 ; i<len ; i++)
377		{
378			if (tokens[1][i] == '(')
379			{
380				isaddr = 1;
381				break;
382			}
383		}
384
385		if (!isaddr)
386		{
387			printf (" near ptr %s", tokens[1]);
388		}
389		else
390		{
391			emitanoperand (1, " dword ptr", 1);
392		}
393	}
394}
395
396
397void emitonejumpdata (void)
398{
399	int	i, isaddr, len;
400
401	if (tokens[1][0] == '*')
402	{
403		printf (" dword ptr[%s]", &tokens[1][1]);
404	}
405	else
406	{
407		isaddr = 0;
408		len = strlen(tokens[1]);
409
410		for (i=0 ; i<len ; i++)
411		{
412			if (tokens[1][i] == '(')
413			{
414				isaddr = 1;
415				break;
416			}
417		}
418
419		if (!isaddr)
420		{
421			printf (" %s", tokens[1]);
422		}
423		else
424		{
425			emitanoperand (1, " dword ptr", 1);
426		}
427	}
428}
429
430
431void emitexterndef (void)
432{
433
434	printf (" %s:dword", tokens[1]);
435}
436
437
438void nooperands (void)
439{
440
441}
442
443
444void emitoneoperandl (void)
445{
446
447	printf (" ");
448	emitanoperand (1, "ds:dword ptr", 1);
449}
450
451
452void emitoneoperandb (void)
453{
454
455	printf (" ");
456	emitanoperand (1, "ds:byte ptr", 1);
457}
458
459
460void emitoneoperandw (void)
461{
462
463	printf (" ");
464	emitanoperand (1, "ds:word ptr", 1);
465}
466
467
468void emittwooperandsl (void)
469{
470
471	printf (" ");
472	emitanoperand (2, "ds:dword ptr", 1);
473	printf (",");
474	emitanoperand (1, "ds:dword ptr", 1);
475}
476
477
478void emittwooperandsb (void)
479{
480
481	printf (" ");
482	emitanoperand (2, "ds:byte ptr", 1);
483	printf (",");
484	emitanoperand (1, "ds:byte ptr", 1);
485}
486
487
488void emittwooperandsw (void)
489{
490
491	printf (" ");
492	emitanoperand (2, "ds:word ptr", 1);
493	printf (",");
494	emitanoperand (1, "ds:word ptr", 1);
495}
496
497
498void emit_0_or_1_operandsl (void)
499{
500
501	if (tokennum == 2)
502	{
503		printf (" ");
504		emitanoperand (1, "ds:dword ptr", 1);
505	}
506}
507
508
509void emit_1_or_2_operandsl (void)
510{
511	int		j;
512
513	if (tokennum == 2)
514	{
515		printf (" ");
516		emitanoperand (1, "ds:dword ptr", 1);
517	}
518	else if (tokennum == 3)
519	{
520		printf (" ");
521		emitanoperand (2, "ds:dword ptr", 1);
522		printf (",");
523		emitanoperand (1, "ds:dword ptr", 1);
524	}
525	else
526	{
527
528		fprintf (stderr, "Error: too many operands\n");
529
530		for (j=0 ; j<tokennum ; j++)
531			fprintf (stderr, "%s\n", tokens[j]);
532
533		fprintf (stderr, "\n");
534		errorexit ();
535	}
536}
537
538
539void emit_1_or_2_operandsl_vartext (char *str0, char *str1)
540{
541	int		j;
542
543	if (tokennum == 2)
544	{
545		printf (" %s ", str0);
546		emitanoperand (1, "ds:dword ptr", 1);
547	}
548	else if (tokennum == 3)
549	{
550		if (!strcmpi (tokens[2], "%st(0)"))
551			printf (" %s ", str0);
552		else
553			printf (" %s ", str1);
554
555		emitanoperand (2, "ds:dword ptr", 1);
556		printf (",");
557		emitanoperand (1, "ds:dword ptr", 1);
558	}
559	else
560	{
561
562		fprintf (stderr, "Error: too many operands\n");
563
564		for (j=0 ; j<tokennum ; j++)
565			fprintf (stderr, "%s\n", tokens[j]);
566
567		fprintf (stderr, "\n");
568		errorexit ();
569	}
570}
571
572
573void special_fdivl (void)
574{
575
576	emit_1_or_2_operandsl_vartext ("fdiv", "fdivr");
577}
578
579
580void special_fdivpl (void)
581{
582
583	emit_1_or_2_operandsl_vartext ("fdivp", "fdivrp");
584}
585
586
587void special_fdivrl (void)
588{
589
590	emit_1_or_2_operandsl_vartext ("fdivr", "fdiv");
591}
592
593
594void special_fdivrpl (void)
595{
596
597	emit_1_or_2_operandsl_vartext ("fdivrp", "fdivp");
598}
599
600
601void special_fsubl (void)
602{
603
604	emit_1_or_2_operandsl_vartext ("fsub", "fsubr");
605}
606
607
608void special_fsubpl (void)
609{
610
611	emit_1_or_2_operandsl_vartext ("fsubp", "fsubrp");
612}
613
614
615void special_fsubrl (void)
616{
617
618	emit_1_or_2_operandsl_vartext ("fsubr", "fsub");
619}
620
621
622void special_fsubrpl (void)
623{
624
625	emit_1_or_2_operandsl_vartext ("fsubrp", "fsubp");
626}
627
628
629void emit_multiple_data (void)
630{
631	int		i;
632
633	printf (" ");
634
635	for (i=1 ; i<(tokennum-1) ; i++)
636	{
637		emitanoperand (i, "", 0);
638		printf (", ");
639	}
640
641	emitanoperand (i, "", 0);
642}
643
644
645//==============================================
646
647parsefield	parsedata[] = {
648	{".align", " align", 2, emitonedata},
649	{".byte",  " db", -2, emit_multiple_data},
650	{".data",  "", 1, datasegstart},
651	{".extern"," externdef", 2, emitexterndef},
652	{".globl", " public", -2, emit_multiple_data},
653	{".long",  " dd", -2, emit_multiple_data},
654	{".single"," dd", -2, emit_multiple_data},
655	{".text",  "", 1, textsegstart},
656	{"adcl",   " adc", 3, emittwooperandsl},
657	{"addb",   " add", 3, emittwooperandsb},
658	{"addl",   " add", 3, emittwooperandsl},
659	{"andb",   " and", 3, emittwooperandsb},
660	{"andl",   " and", 3, emittwooperandsl},
661	{"call",   " call", 2, emitonecalldata},
662	{"cmpb",   " cmp", 3, emittwooperandsb},
663	{"cmpl",   " cmp", 3, emittwooperandsl},
664	{"cmpw",   " cmp", 3, emittwooperandsw},
665	{"decl",   " dec", 2, emitoneoperandl},
666	{"decw",   " dec", 2, emitoneoperandw},
667	{"divl",   " div", 2, emitoneoperandl},
668	{"fadd",   " fadd", -2, emit_1_or_2_operandsl},
669	{"faddp",  " faddp", -2, emit_1_or_2_operandsl},
670	{"faddps", " faddp", -2, emit_1_or_2_operandsl},
671	{"fadds",  " fadd", -2, emit_1_or_2_operandsl},
672	{"fcom",   " fcom", 2, emitoneoperandl},
673	{"fcoms",  " fcom", 2, emitoneoperandl},
674	{"fcomp",  " fcomp", 2, emitoneoperandl},
675	{"fcomps", " fcomp", 2, emitoneoperandl},
676	{"fdiv",   "", -2, special_fdivl},
677	{"fdivp",  "", -2, special_fdivpl},
678	{"fdivr",  "", -2, special_fdivrl},
679	{"fdivrp", "", -2, special_fdivrpl},
680	{"fdivrs", "", -2, special_fdivrl},
681	{"fildl",  " fild", 2, emitoneoperandl},
682	{"fistl",  " fist", 2, emitoneoperandl},
683	{"fistpl", " fistp", 2, emitoneoperandl},
684	{"fld",    " fld", 2, emitoneoperandl},
685	{"fldcw",  " fldcw", 2, emitoneoperandw},
686	{"fldenv", " fldenv", 2, emitoneoperandl},
687	{"flds",   " fld", 2, emitoneoperandl},
688	{"fmul",   " fmul", -2, emit_1_or_2_operandsl},
689	{"fmulp",  " fmulp", -2, emit_1_or_2_operandsl},
690	{"fmulps", " fmulp", -2, emit_1_or_2_operandsl},
691	{"fmuls",  " fmul", -2, emit_1_or_2_operandsl},
692	{"fnstcw", " fnstcw", 2, emitoneoperandw},
693	{"fnstenv"," fnstenv", 2, emitoneoperandl},
694	{"fnstsw", " fnstsw", 2, emitoneoperandw},
695	{"fstp",   " fstp", 2, emitoneoperandl},
696	{"fstps",  " fstp", 2, emitoneoperandl},
697	{"fsts",   " fst", 2, emitoneoperandl},
698	{"fsubr",  "", -2, special_fsubrl},
699	{"fsubrp", "", -2, special_fsubrpl},
700	{"fsubrs", "", -2, special_fsubrl},
701	{"fsub",   "", -2, special_fsubl},
702	{"fsubp",  "", -2, special_fsubpl},
703	{"fsubps", "", -2, special_fsubpl},
704	{"fsubs",  "", -2, special_fsubl},
705	{"fxch",   " fxch", 2, emitoneoperandl},
706	{"imull",  " imul", -2, emit_1_or_2_operandsl},
707	{"incl",   " inc", 2, emitoneoperandl},
708	{"ja",     " ja", 2, emitonedata},
709	{"jae",    " jae", 2, emitonedata},
710	{"jb",     " jb", 2, emitonedata},
711	{"jbe",    " jbe", 2, emitonedata},
712	{"jc",     " jc", 2, emitonedata},
713	{"je",     " je", 2, emitonedata},
714	{"jg",     " jg", 2, emitonedata},
715	{"jge",    " jge", 2, emitonedata},
716	{"jl",     " jl", 2, emitonedata},
717	{"jle",    " jle", 2, emitonedata},
718	{"jmp",    " jmp", 2, emitonejumpdata},
719	{"jna",    " jna", 2, emitonedata},
720	{"jnae",   " jnae", 2, emitonedata},
721	{"jnb",    " jnb", 2, emitonedata},
722	{"jnbe",   " jnbe", 2, emitonedata},
723	{"jnc",    " jnc", 2, emitonedata},
724	{"jne",    " jne", 2, emitonedata},
725	{"jng",    " jng", 2, emitonedata},
726	{"jnge",   " jnge", 2, emitonedata},
727	{"jnl",    " jnl", 2, emitonedata},
728	{"jnle",   " jnle", 2, emitonedata},
729	{"jns",    " jns", 2, emitonedata},
730	{"jnz",    " jnz", 2, emitonedata},
731	{"js",     " js", 2, emitonedata},
732	{"jz",     " jz", 2, emitonedata},
733	{"leal",   " lea", 3, emittwooperandsl},
734	{"movb",   " mov", 3, emittwooperandsb},
735	{"movl",   " mov", 3, emittwooperandsl},
736	{"movw",   " mov", 3, emittwooperandsw},
737	{"negl",   " neg", 2, emitoneoperandl},
738	{"orb",    " or", 3, emittwooperandsb},
739	{"orl",    " or", 3, emittwooperandsl},
740	{"popl",   " pop", 2, emitoneoperandl},
741	{"pushl",  " push", 2, emitoneoperandl},
742	{"ret",    " ret", -1, emit_0_or_1_operandsl},
743	{"rorl",   " ror", 3, emittwooperandsl},
744	{"sarl",   " sar", 3, emittwooperandsl},
745	{"sbbl",   " sbb", 3, emittwooperandsl},
746	{"shll",   " shl", 3, emittwooperandsl},
747	{"shrl",   " shr", 3, emittwooperandsl},
748	{"subl",   " sub", 3, emittwooperandsl},
749	{"testb",  " test", 3, emittwooperandsb},
750	{"testl",  " test", 3, emittwooperandsl},
751	{"xorb",   " xor", 3, emittwooperandsb},
752	{"xorl",   " xor", 3, emittwooperandsl},
753};
754
755int	numparse = sizeof (parsedata) / sizeof (parsedata[0]);
756
757//==============================================
758
759void errorexit (void)
760{
761	fprintf (stderr, "In line: %d, out line: %d\n", inline, outline);
762	exit (1);
763}
764
765
766tokenstat whitespace (char c)
767{
768	if (c == '\n')
769		return LINE_DONE;
770
771	if ((c <= ' ') ||
772		(c > 127) ||
773		(c == ','))
774	{
775		return WHITESPACE;
776	}
777
778	return NOT_WHITESPACE;
779}
780
781
782int gettoken (void)
783{
784	char		c;
785	int			count, parencount;
786	tokenstat	stat;
787
788	do
789	{
790		if ((c = getchar ()) == EOF)
791			return FILE_DONE;
792
793		if ((stat = whitespace (c)) == LINE_DONE)
794			return LINE_DONE;
795	} while (stat == WHITESPACE);
796
797	token[0] = c;
798	count = 1;
799
800	if (c == '~')
801	{
802		count--;
803		token[count++] = 'n';
804		token[count++] = 'o';
805		token[count++] = 't';
806		token[count++] = ' ';
807	}
808
809	if (c == '(')
810	{
811		do
812		{
813			if ((c = getchar ()) == EOF)
814			{
815				fprintf (stderr, "EOF in middle of parentheses\n");
816				errorexit ();
817			}
818
819			token[count++] = c;
820
821		} while (c != ')');
822	}
823
824	for ( ;; )
825	{
826		if ((c = getchar ()) == EOF)
827		{
828			token[count] = 0;
829			return TOKEN_AVAILABLE;
830		}
831
832		if (whitespace (c) == LINE_DONE)
833		{
834			if (ungetc (c, stdin) == EOF)
835			{
836				fprintf (stderr, "Couldn't unget character\n");
837				errorexit ();
838			}
839
840			token[count] = 0;
841			return TOKEN_AVAILABLE;
842		}
843
844		if (whitespace (c) == WHITESPACE)
845		{
846			token[count] = 0;
847			return TOKEN_AVAILABLE;
848		}
849
850		if (count >= MAX_TOKEN_LENGTH)
851		{
852			fprintf (stderr, "Error: token too long\n");
853			errorexit ();
854		}
855
856		token[count++] = c;
857
858		if (c == '~')
859		{
860			count--;
861			token[count++] = 'n';
862			token[count++] = 'o';
863			token[count++] = 't';
864			token[count++] = ' ';
865		}
866		else if (c == '(')
867		{
868			parencount = 1;
869
870			do
871			{
872				if ((c = getchar ()) == EOF)
873				{
874					fprintf (stderr, "EOF in middle of parentheses\n");
875					errorexit ();
876				}
877
878				if (c == '(')
879					parencount++;
880				else if (c == ')')
881					parencount--;
882
883				if (c == '~')
884				{
885					token[count++] = 'n';
886					token[count++] = 'o';
887					token[count++] = 't';
888					token[count++] = ' ';
889				}
890				else
891				{
892					token[count++] = c;
893				}
894
895			} while ((c != ')') || (parencount > 0));
896		}
897	}
898}
899
900
901tokenstat parseline (void)
902{
903	tokenstat	stat;
904	int			i, j, firsttoken, labelfound;
905	int			mnemfound;
906
907	firsttoken = 1;
908	tokennum = 0;
909	labelfound = 0;
910
911	for ( ;; )
912	{
913		token = tokens[tokennum];
914		stat = gettoken ();
915
916		switch (stat)
917		{
918		case FILE_DONE:
919			return FILE_DONE;
920
921		case LINE_DONE:
922			if (!firsttoken && tokennum)
923			{
924				mnemfound = 0;
925
926				for (i=0 ; i<numparse; i++)
927				{
928					if (!strcmpi (tokens[0], parsedata[i].text))
929					{
930						if (((parsedata[i].numtokens > 0) &&
931							 (parsedata[i].numtokens != tokennum)) ||
932							((parsedata[i].numtokens < 0) &&
933							 (tokennum < -parsedata[i].numtokens)))
934						{
935							fprintf (stderr, "mismatched number of tokens\n");
936
937							for (j=0 ; j<tokennum ; j++)
938								fprintf (stderr, "%s\n", tokens[j]);
939
940							fprintf (stderr, "\n");
941							errorexit ();
942						}
943
944						printf ("%s", parsedata[i].emit);
945						(*parsedata[i].parsefunc) ();
946
947						mnemfound = 1;
948						break;
949					}
950				}
951
952				if (!mnemfound)
953				{
954					fprintf (stderr, "Error: unknown mnemonic\n");
955
956					for (j=0 ; j<tokennum ; j++)
957						fprintf (stderr, "%s\n", tokens[j]);
958
959					fprintf (stderr, "\n");
960					errorexit ();
961				}
962			}
963
964			if (!firsttoken)
965			{
966				if ((currentseg == DATASEG) && labelfound && !tokennum)
967					printf (":\n");
968				else
969					printf ("\n");
970
971				outline++;
972			}
973			return PARSED_OKAY;
974
975		case TOKEN_AVAILABLE:
976			if (firsttoken)
977			{
978				if (token[strlen(token) - 1] == ':')
979				{
980					labelfound = 1;
981
982					if (currentseg == DATASEG)
983					{
984						token[strlen(token) - 1] = 0;
985						printf ("%s", token);
986					}
987					else if (currentseg == TEXTSEG)
988					{
989						printf ("%s", token);
990					}
991					else
992					{
993						fprintf (stderr, "Error: not in segment block\n");
994						errorexit ();
995					}
996
997					firsttoken = 0;
998					break;
999				}
1000			}
1001
1002			firsttoken = 0;
1003
1004			if (tokennum >= MAX_TOKENS)
1005			{
1006				fprintf (stderr, "Error: too many tokens\n");
1007				exit (0);
1008			}
1009
1010			tokennum++;
1011
1012			break;
1013
1014		default:
1015			fprintf (stderr, "Error: unknown tokenstat %d\n", stat);
1016			exit (0);
1017		}
1018	}
1019}
1020
1021
1022void main (int argc, char **argv)
1023{
1024	tokenstat	stat;
1025
1026	printf (" .386P\n"
1027            " .model FLAT\n");
1028	inline = 1;
1029	outline = 3;
1030
1031	for ( ;; )
1032	{
1033		stat = parseline ();
1034		inline++;
1035
1036		switch (stat)
1037		{
1038		case FILE_DONE:
1039			if (currentseg == TEXTSEG)
1040				printf ("_TEXT ENDS\n");
1041			else if (currentseg == DATASEG)
1042				printf ("_DATA ENDS\n");
1043
1044			printf (" END\n");
1045			exit (0);
1046
1047		case PARSED_OKAY:
1048			break;
1049
1050		default:
1051			fprintf (stderr, "Error: unknown tokenstat %d\n", stat);
1052			exit (0);
1053		}
1054	}
1055}
1056
1057