home *** CD-ROM | disk | FTP | other *** search
/ Magazyn Amiga 14 / MA_Cover_14.iso / source / c / q1source_amy / qw / gas2masm / gas2masm.c < prev    next >
Encoding:
C/C++ Source or Header  |  1999-12-21  |  19.6 KB  |  1,057 lines

  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.