Subversion Repositories Kolibri OS

Rev

Go to most recent revision | Blame | Last modification | View Log | RSS feed

  1. /*
  2. Copyright (C) 1996-1997 Id Software, Inc.
  3.  
  4. This program is free software; you can redistribute it and/or
  5. modify it under the terms of the GNU General Public License
  6. as published by the Free Software Foundation; either version 2
  7. of the License, or (at your option) any later version.
  8.  
  9. This program is distributed in the hope that it will be useful,
  10. but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  
  12.  
  13. See the GNU General Public License for more details.
  14.  
  15. You should have received a copy of the GNU General Public License
  16. along with this program; if not, write to the Free Software
  17. Foundation, 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.  
  32. typedef enum {NOT_WHITESPACE, WHITESPACE, TOKEN_AVAILABLE, LINE_DONE, FILE_DONE, PARSED_OKAY} tokenstat;
  33. typedef enum {NOSEG, DATASEG, TEXTSEG} segtype;
  34.  
  35. int             tokennum;
  36. int             inline, outline;
  37.  
  38. char    *token;
  39. char    tokens[MAX_TOKENS][MAX_TOKEN_LENGTH+1];
  40.  
  41. segtype currentseg = NOSEG;
  42.  
  43. typedef struct {
  44.         char    *text;
  45.         char    *emit;
  46.         int             numtokens;
  47.         void    (*parsefunc) (void);
  48. } parsefield;
  49.  
  50.  
  51. void errorexit (void);
  52.  
  53.  
  54. //==============================================
  55.  
  56. typedef struct {
  57.         char    *text;
  58.         char    *emit;
  59.         int             len;
  60. } regdesc;
  61.  
  62. regdesc 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.  
  97. int     numregs = sizeof (reglist) / sizeof (reglist[0]);
  98.  
  99. //==============================================
  100.  
  101.  
  102. void 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.  
  317. void 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.  
  331. void 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.  
  345. void 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.  
  356. void emitonedata (void)
  357. {
  358.  
  359.         printf (" %s", tokens[1]);
  360. }
  361.  
  362.  
  363. void 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.  
  397. void 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.  
  431. void emitexterndef (void)
  432. {
  433.  
  434.         printf (" %s:dword", tokens[1]);
  435. }
  436.  
  437.  
  438. void nooperands (void)
  439. {
  440.  
  441. }
  442.  
  443.  
  444. void emitoneoperandl (void)
  445. {
  446.  
  447.         printf (" ");
  448.         emitanoperand (1, "ds:dword ptr", 1);
  449. }
  450.  
  451.  
  452. void emitoneoperandb (void)
  453. {
  454.  
  455.         printf (" ");
  456.         emitanoperand (1, "ds:byte ptr", 1);
  457. }
  458.  
  459.  
  460. void emitoneoperandw (void)
  461. {
  462.  
  463.         printf (" ");
  464.         emitanoperand (1, "ds:word ptr", 1);
  465. }
  466.  
  467.  
  468. void 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.  
  478. void 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.  
  488. void 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.  
  498. void 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.  
  509. void 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.  
  539. void 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.  
  573. void special_fdivl (void)
  574. {
  575.  
  576.         emit_1_or_2_operandsl_vartext ("fdiv", "fdivr");
  577. }
  578.  
  579.  
  580. void special_fdivpl (void)
  581. {
  582.  
  583.         emit_1_or_2_operandsl_vartext ("fdivp", "fdivrp");
  584. }
  585.  
  586.  
  587. void special_fdivrl (void)
  588. {
  589.  
  590.         emit_1_or_2_operandsl_vartext ("fdivr", "fdiv");
  591. }
  592.  
  593.  
  594. void special_fdivrpl (void)
  595. {
  596.  
  597.         emit_1_or_2_operandsl_vartext ("fdivrp", "fdivp");
  598. }
  599.  
  600.  
  601. void special_fsubl (void)
  602. {
  603.  
  604.         emit_1_or_2_operandsl_vartext ("fsub", "fsubr");
  605. }
  606.  
  607.  
  608. void special_fsubpl (void)
  609. {
  610.  
  611.         emit_1_or_2_operandsl_vartext ("fsubp", "fsubrp");
  612. }
  613.  
  614.  
  615. void special_fsubrl (void)
  616. {
  617.  
  618.         emit_1_or_2_operandsl_vartext ("fsubr", "fsub");
  619. }
  620.  
  621.  
  622. void special_fsubrpl (void)
  623. {
  624.  
  625.         emit_1_or_2_operandsl_vartext ("fsubrp", "fsubp");
  626. }
  627.  
  628.  
  629. void 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.  
  647. parsefield      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.  
  755. int     numparse = sizeof (parsedata) / sizeof (parsedata[0]);
  756.  
  757. //==============================================
  758.  
  759. void errorexit (void)
  760. {
  761.         fprintf (stderr, "In line: %d, out line: %d\n", inline, outline);
  762.         exit (1);
  763. }
  764.  
  765.  
  766. tokenstat 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.  
  782. int 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.  
  901. tokenstat 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.  
  1022. void 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.