home *** CD-ROM | disk | FTP | other *** search
/ io Programmo 72 / IOPROG_72.ISO / soft / Codice / CRobots / Software / CWARS21.ZIP / RCASM.C < prev    next >
Encoding:
C/C++ Source or Header  |  1989-04-26  |  20.1 KB  |  637 lines

  1. /*****************************************************************************
  2.  * REDCODE Assembler ver. 1.1   (C) 1988 Mazoft Software (DK)
  3.  * Format: RCASM <filename(.typ)>
  4.  * Outputs: <filename>.mrs as executeable MARS code
  5.  * "My heaven will be a big heaven - and I will walk through the front door"
  6.  *****************************************************************************/
  7.  
  8. #include <stdio.h>
  9. #include <string.h>
  10. #include <ctype.h>
  11.  
  12. #define FSPLEN 16       /* File Specification maximum name length */
  13. #define OPCODES 12      /* Number of operation codes & pseudo instructions */
  14. #define UNKNOWN 12      /* If recognize() returns UNKNOWN, it's not listed */
  15. #define BADEXP 0x7FFF   /* bad expression */
  16. #define SYMSIZ 0x40     /* default symbol table stack space */
  17. #define MAXPRGSIZ 0x200 /* default maximum redcode program size */
  18. #define IMMEDIATE 0     /* addressing modes (two-bit bitfield) */
  19. #define DIRECT 1
  20. #define INDIRECT 2
  21. #define AUTODECREMENT 3
  22. #define STACKSIZE 0x100 /* evaluator's stack size */
  23. #define MAXERR 16        /* errors before break */
  24.  
  25. #define report(c) {printf(errortext,(c),ipfile,curline,errormsg [(c)]);errno++;opc=UNKNOWN;}
  26. #define hex(i) (i)+((i) > 9 ? '7' : '0')
  27.  
  28. int add ();
  29. int subtract ();
  30. int multiply ();
  31. int divide ();
  32. int goback ();
  33. struct operator *vop ();
  34.  
  35. int stack [STACKSIZE];
  36. char opstk [STACKSIZE];
  37. int stackptr = 0;
  38. int opsptr = 0;
  39. int unary, len;
  40.  
  41. struct operator {            /* structure for operators in expression evaluator */
  42.     int priority;            /* priority */
  43.     char type;            /* character definition */
  44.     int (*handler)();        /* address of handler routine */
  45.     };
  46.  
  47. struct symbol {               /* Symbol Table member consisting of: */
  48.      char name [17];        /* label name */
  49.      unsigned int value;        /* integer value */
  50.      };
  51.  
  52. struct symbol symboltable [SYMSIZ];     /* n symbols allowed */
  53.  
  54. struct operator olist [] = {        /* list of legal operators */
  55.     1, '+', &add,
  56.     1, '-', &subtract,
  57.     2, '*', &multiply,
  58.     2, '/', ÷,
  59.     0, 0, &goback
  60.     };
  61.  
  62. char opcode [16] [4] = {     /* List of REDCODE TLA-opcodes and directives */
  63.     "DAT", "MOV", "ADD", "SUB", "JMP", "JMZ",
  64.     "JMN", "DJN", "CMP", "SPL", "END", "EQU"
  65.      };
  66.  
  67. char *errortext = "Error %d in %s line %d : %s\n";
  68. char *copyright = "Redcode MARS Assembler v. 1.1 - (C) 1988 Maz Spork\n\n";
  69.  
  70. char *errormsg [] = {                /* error messages nos */
  71.      "Line too long",                            /* 0 */
  72.      "Invalid opcode",                            /* 1 */
  73.      "Invalid expression or label not found",        /* 2 */
  74.      "Invalid addressing mode",                    /* 3 */
  75.      "Double definition of label",                    /* 4 */
  76.      "Start indicator misspelled or missing",        /* 5 */
  77.      "Out of stack space",                        /* 6 */
  78.      "Too many errors",                            /* 7 */
  79.      "Too few operands",                            /* 8 */
  80.      "Immediate addressing not allowed here",        /* 9 */
  81.      "Garbled line or too many operands",            /*10 */
  82.     "Equate directive has no label",                /*11 */
  83.      "Heaven sends you no promises"                /*12 */
  84.      };
  85.  
  86. int flag, symbols = 0;     /* flag is reset if first column on line */
  87. unsigned int program [MAXPRGSIZ * 3];
  88.  
  89. main (argc, argv)
  90. int argc;
  91. char **argv;
  92. {
  93.      struct symbol *symbolptr [SYMSIZ], *tempsym;
  94.      FILE *source, *object, *listing;
  95.      char opfile [FSPLEN], ipfile [FSPLEN], lstfile [FSPLEN], operand [64];
  96.      char line [0x100], *charptr, *lineptr, c;
  97.      int pass, curline, errno = 0, i, j, position, lasterr, ok;
  98.      int opc;
  99.      unsigned int mode, value, curloc, wasloc, *progptr;
  100.      unsigned int modes [2], values [2], curop, tmpop;
  101.  
  102.      printf (copyright);     /* Min p0lle */
  103.  
  104.      if (argc < 2) {          /* No parameter supplied? */
  105.           printf ("No source file specified.\n");
  106.           exit (20);
  107.           }
  108.  
  109.      if (strlen (argv [1]) > 12) {     /* Name too long? */
  110.           printf ("Bad source file name %s.\n", argv [1]);
  111.           exit (20);
  112.           }
  113.  
  114.     if (argv [1] [0] == '?') {
  115.         puts ("\nInstruction format:\n");
  116.         puts ("(label) <OPC> (<m><opr>) (<m><opr>) (; comment)\n");
  117.         puts ("\t\"label\" is an optional assembly label");
  118.         puts ("\t\"OPC\" is the opcode or directive (see below)");
  119.         puts ("\t\"m\" is an optional addressing mode (see below)");
  120.         puts ("\t\"opr\" is an operand (label or expression)");
  121.         puts ("\t\";\" treats rest of line as an unassembled comment\n");
  122.         puts ("Redcode instructions:\n");
  123.         puts ("\tDAT b\t\tIllegal opcode, provides data");
  124.           puts ("\tMOV a b\t\tMove data");
  125.         puts ("\tADD a b\t\tAdd a to b, result in b");
  126.         puts ("\tSUB a b\t\tSubtract b from a, result in b");
  127.         puts ("\tJMP a\t\tJump to a");
  128.         puts ("\tJMZ a b\t\tJump to a if b is zero");
  129.         puts ("\tJMN a b\t\tJump to a if b is non-zero");
  130.         puts ("\tDJN a b\t\tDecrement b and jump to a if non-zero");
  131.         puts ("\tSPL b\t\tSpawn child task at location b");
  132.         puts ("\tEQU n\t\tEQUATE directive");
  133.         puts ("\tEND\t\tEND directive\n");
  134.         puts ("Addressing modes:\n");
  135.         puts ("\t$\tDirect addressing\n\t#\tImmediate addressing");
  136.         puts ("\t@\tIndirect addressing\n\t<\tIndirect with pre-decrement");
  137.         exit (0);
  138.         }
  139.  
  140.      for (charptr = argv [1]; *charptr; *charptr++ = toupper (*charptr));
  141.  
  142.      strcpy (opfile, argv [1]);     /* Copy name to obj and lst fsps */
  143.      strcpy (ipfile, argv [1]);
  144.      strcpy (lstfile, argv [1]);
  145.  
  146.      for (charptr = ipfile; *charptr != '.'; charptr++) /* find extension */
  147.           if (!*charptr) strcpy (charptr--, ".RDC");     /* (if any) */
  148.  
  149.      strcpy (opfile+(charptr-ipfile), ".MRS");
  150.      strcpy (lstfile+(charptr-ipfile), ".LST");
  151.  
  152.      if (!(source = fopen (ipfile, "r"))) {
  153.           printf ("Source file \"%s\" not found.\n", ipfile);
  154.           exit (20);
  155.           }
  156.  
  157.      if (!(object = fopen (opfile, "wb"))) {
  158.           printf ("Could not open object file \"%s\".\n", opfile);
  159.           exit (20);
  160.           }
  161.  
  162.      if (!(listing = fopen (lstfile, "w"))) {
  163.           printf ("Could not open assembly listing file \"%s\".\n", lstfile);
  164.           exit (20);
  165.           }
  166.  
  167.      fprintf (listing, copyright);
  168.      fprintf (listing, "line  addr  o A-oper B-oper label   opcode  operands\n\n");
  169.  
  170.      progptr = &program [1];     /* make room for relative start address */
  171.  
  172.      for (pass = 0; errno < MAXERR && pass < 2; pass++) {
  173.           printf ("Pass %d\n", pass + 1);
  174.           rewind (source);     /* start at beginning each pass */
  175.           curloc = 0;
  176.         curline = 1;
  177.  
  178.           while (!feof (source) && errno < MAXERR) {
  179.                if ((i = getline (source, lineptr = line)) > 0xFF) report (0);
  180.                if (i == EOF) break;     /* eof anyway? */
  181.  
  182.                wasloc = curloc;
  183.                lasterr = errno;
  184.  
  185.             values [0] = values [1] = modes [0] = modes [1] = 0;
  186.                curop = flag = ok = 0;
  187.                opc = UNKNOWN;
  188.  
  189.                while (i = getword (lineptr, charptr = operand)) {
  190.                     lineptr += i;
  191.  
  192.                     if (*charptr == ';') break;     /* rest is comment */
  193.  
  194.                     switch (*charptr) {     /* addressing mode */
  195.                          case '$' :
  196.                               mode = DIRECT;
  197.                               charptr++;
  198.                               break;
  199.                          case '#' :
  200.                               mode = IMMEDIATE;
  201.                               charptr++;
  202.                               break;
  203.                          case '@' :
  204.                               mode = INDIRECT;
  205.                               charptr++;
  206.                               break;
  207.                          case '<' :
  208.                               mode = AUTODECREMENT;
  209.                               charptr++;
  210.                               break;
  211.                          default:
  212.                         if (isalnum (*charptr) || *charptr == '+' || *charptr == '-' || *charptr == '!')
  213.                                   mode = DIRECT;
  214.                         else
  215.                             if (!pass) report (3);
  216.                               break;
  217.                          }
  218.  
  219.                     if ((tmpop = recognize (charptr)) == UNKNOWN) {    /* opcode ? */
  220.                          if (pass) {        /* pass 2 */
  221.                               if (flag) {
  222.                                    if ((value = evaluate (charptr, wasloc)) == BADEXP) {
  223.                                         if (opc == UNKNOWN) {
  224.                                      if (!ok) {
  225.                                         report (1);
  226.                                         ok = 1;
  227.                                         }
  228.                                     }
  229.                                 else {
  230.                                     report (2);
  231.                                     printf ("\"%s\" not evaluated.\n", charptr);
  232.                                     }
  233.                                         }
  234.                                    else {
  235.                                         if (curop == 2) {
  236.                                              report (10);
  237.                                     }
  238.                                         else {
  239.                                              modes [curop] = mode;
  240.                                              values [curop++] = value;
  241.                                              }
  242.                                         }
  243.                                    }
  244.                               }
  245.                          else {     /* pass 1 */
  246.                               if (!flag) {     /* pass 1, column 0 */
  247.                                    if (symbols == SYMSIZ) {
  248.                                         report (6);    /* out of space */
  249.                                         symbols--;
  250.                                         }
  251.                             if (evaluate (operand, 0) != BADEXP) {
  252.                                 report (4);
  253.                                 }
  254.                             else {
  255.                                        strncpy (symboltable [symbols].name, operand, 16);
  256.                                 strlwr (symboltable [symbols].name);
  257.                                           symboltable [symbols].name [16] = '\0';
  258.                                           symboltable [symbols].value = curloc;
  259.                                           symbols++;
  260.                                 }
  261.                             } /* flag */
  262.                               } /* pass */
  263.                          } /* known */
  264.                     else {
  265.                     if (ok) {
  266.                         if (!pass) report (10);
  267.                         }
  268.                          else if ((opc = tmpop) < 10) {
  269.                               curloc++;        /* only increment PC if opcode is real */
  270.                               ok = 1;
  271.                               }
  272.                          } /* known/unknown word */
  273.                      } /* while words in line */
  274.  
  275.                if (lasterr != errno) values [0] = values [1] = modes [0] = modes [1] = 0;
  276.  
  277.                if (pass) {     /* tidy the code */
  278.                     position = fprintf (listing, "%4d ", curline);
  279.                     if (opc >= 0 && opc < 10) {     /* if not end directive, or error */
  280.                     putc (' ', listing);
  281.                     position = 2 + itoh (listing, curloc - ok, 4, 2) + itoh (listing, opc, 1, 1);
  282.                          if (!opc || opc == 9) {     /* SPL or DAT */
  283.                               fprintf (listing, "0-0000 ");
  284.                               position += 7;
  285.                               modes [1] = modes [0];
  286.                               values [1] = values [0];
  287.                               modes [0] = values [0] = 0;
  288.                               }
  289.                          else
  290.                               position += itoh (listing, modes [0], 1, 101) + itoh (listing, values [0], 4, 1);
  291.                          if (opc == 4) {
  292.                               fprintf (listing, "0-0000 ");
  293.                               position += 7;
  294.                               }
  295.                          else
  296.                               position += itoh (listing, modes [1], 1, 101) + itoh (listing, values [1], 4, 1);
  297.                     if (opc == 4 || opc == 9 || !opc) {
  298.                         if (!curop) report (8);
  299.                         }
  300.                     else {
  301.                         if (curop < 2) report (8);
  302.                         }
  303.                          if ((((opc && opc < 4) || opc == 10) && !modes [1]) || (opc > 3 && opc < 8 && !modes [0])) report (9);
  304.                          position--;
  305.                          }
  306.                 else if (opc == UNKNOWN) {
  307.                     /* comment line or something */
  308.                     }
  309.                 else {    /* assembly directives */
  310.                     putc ('(', listing);
  311.                     if (opc == 11)    {            /* EQU */
  312.                               for (j = 0; j < symbols && symboltable [j].value != wasloc; j++);
  313.                         symboltable [j].value = values [0];
  314.                         itoh (listing, values [0], 4, 0);
  315.                         }
  316.                     if (opc == 10) {            /* END */
  317.                         fseek (source, 0L, SEEK_END);
  318.                         itoh (listing, 0, 4, 0);
  319.                         }
  320.                     fprintf (listing, ") ");
  321.                     position += 7;
  322.                     }
  323.  
  324.                 if (opc < 10) {
  325.                     *progptr++ = (unsigned) opc + (modes [0] *0x1000) + (modes [1] * 0x100);
  326.                          *progptr++ = values [0];
  327.                          *progptr++ = values [1];
  328.                     }
  329.  
  330.                     spool (line, listing, position + 1);
  331.                     }
  332.             else {
  333.                 if (opc == 11) {
  334.                     if (!symbols || symboltable [symbols - 1].value != wasloc) {
  335.                         report (11);
  336.                         }
  337.                     else strupr (symboltable [symbols - 1].name);
  338.                     }
  339.                 if (opc == 10) fseek (source, 0L, SEEK_END);
  340.                 } /* if pass */
  341.             curline++;
  342.                } /* while lines in file */
  343.           } /* for pass */
  344.  
  345.     if (errno >= MAXERR) {
  346.         report (7);
  347.         }
  348.  
  349.      if ((*program = i = evaluate ("start", 0)) == BADEXP) {
  350.           puts ("Warning: no start indicator, first instruction word assumed");
  351.           *program = 0;    /* assume initial PC to be physical start of code */
  352.           }
  353.  
  354.     if (!curloc) puts ("Warning: no code was assembled - program length is zero");
  355.  
  356.      fprintf (listing, "\n\nCode size     = %4Xh location%c\nStart address = %4Xh relative", curloc, curloc == 1 ? ' ' : 's', *program);
  357.      if (i == BADEXP) fprintf (listing, " (assumed)");     /* if start wasn't specified */
  358.      fprintf (listing, "\nEfficiency    =  %3d%c of stack space used\n", (symbols * 100) / SYMSIZ, '%');
  359.      if (symbols) fprintf (listing, "\nSymbol Table:\n\n");
  360.  
  361.      for (i = 0; i < symbols; i++) symbolptr [i] = &symboltable [i];
  362.      for (i = 0; i < symbols; i++) {          /* alphasort symboltable */
  363.           for (j = 0; j < symbols; j++) {
  364.                if (strcmpi (symbolptr [i]->name, symbolptr [j]->name) < 0) {
  365.                     tempsym = symbolptr [i];     /* swap */
  366.                     symbolptr [i] = symbolptr [j];
  367.                     symbolptr [j] = tempsym;
  368.                     }
  369.                }
  370.           }
  371.  
  372.      for (i = 0; i < symbols; i++) {
  373.           fprintf (listing, "%s", symbolptr [i]->name);
  374.           for (j = 0; j < 17 - strlen (symbolptr [i]->name); j++)
  375.                putc (' ', listing);
  376.           fprintf (listing, "= ");
  377.           itoh (listing, symbolptr [i]->value,4,3);
  378.           putc (i & 1 ? '\n' : ' ', listing);     /* newline or space */
  379.           }
  380.  
  381.      if ((i & 1)) putc ('\n', listing);     /* extra newline if odd end above */
  382.  
  383.     printf ("\n%d line%sassembled : %d error%c\n", curline - 1, curline == 2 ? " " : "s ", errno, errno == 1 ? ' ' : 's');     /* write how many errors detected */
  384.  
  385.     fwrite (program, sizeof (int), curloc * 3 + 1, object);
  386.  
  387.      fclose (source);    /* cloise dem files */
  388.      fclose (object);
  389.      fclose (listing);
  390.      }
  391.  
  392. int recognize (word)     /* Compare an instruction to the opcode list */
  393. char *word;
  394. {
  395.      int i;
  396.  
  397.      for (i = 0; i < OPCODES; i++) if (!strcmpi (word, opcode [i])) break;
  398.      return (i);     /* case insensitive search */
  399.      }
  400.  
  401. int getline (handle, ptr)      /* grab a line of source code */
  402. FILE *handle;
  403. char *ptr;
  404. {
  405.     char c;
  406.      int length = 0;
  407.  
  408.     if (feof (handle)) return (EOF);
  409.  
  410.      do {
  411.           *ptr++ = c = (char) getc (handle);
  412.           } while (++length < 0xFF && c != '\n' && c != ':' && !feof (handle));
  413.  
  414.      *(ptr - 1) = '\0';
  415.     length--;
  416.     c = (char) getc (handle);
  417.     if (feof (handle) && !length) return (EOF);
  418.     ungetc (c, handle);
  419.  
  420.      return (length);
  421.      }
  422.  
  423. int getword (srce, dest)      /* retrieve one word from line of source */
  424. char *srce, *dest;
  425. {
  426.      char c;
  427.     int l1, l2;
  428.  
  429.     l1 = l2 = 0;
  430.      while (*srce == ' ' || *srce == '\t' || *srce == ',') {
  431.           l1++;
  432.           srce++;
  433.           }
  434.  
  435.     flag += l1;
  436.  
  437.      while (*srce && !isspace (*srce) && *srce != ',') {
  438.           *dest++ = *srce++;
  439.           l2++;
  440.           }
  441.  
  442.      *dest = '\0';
  443.     return (l2 ? l1 + l2 : 0);
  444.      }
  445.  
  446. spool (text, handle, pos)      /* spool leading spaces + rest of line */
  447. char *text;
  448. FILE *handle;
  449. int pos;
  450. {
  451.      int i = 0;
  452.  
  453.      for (; pos < 29; pos++) putc ('  ', handle);     /* leading spaces */
  454.  
  455.      while (*text) {
  456.           if (*text == '\t')
  457.                do {
  458.                     putc (' ', handle);
  459.                     i++;
  460.                     } while (i % 8);
  461.           else {
  462.                putc (*text, handle);     /* source text copy */
  463.                i++;
  464.                }
  465.           text++;
  466.           }
  467.  
  468.     putc ('\n', handle);
  469.      }
  470.  
  471. int itoh (stream, value, digits, spaces)      /* fast hex-print + trailing spaces*/
  472. FILE *stream;
  473. unsigned int value, digits, spaces;
  474. {
  475.      int i, j, k;
  476.      char c = ' ';
  477.  
  478.      k = digits + spaces;          /* return length of written string */
  479.  
  480.     while (digits--) putc (hex ((value >> (digits * 4)) & 0xF), stream);
  481.  
  482.      if (spaces > 100) {     /* if 10x is provided, use dashes instead */
  483.           spaces -= 100;
  484.           c = '-';
  485.           }
  486.  
  487.      for (; spaces;  spaces--) putc (c, stream);
  488.      return (k);
  489.      }
  490.  
  491. int power (x, y)      /* x to the power of y as integers, not floating pt */
  492. int x, y;
  493. {
  494.      int r;
  495.  
  496.      for (r = 1; y > 0; y--) r *= x;     /* r mult'd x - y times */
  497.      return (r);
  498.      }
  499.  
  500. /*    EXPRESSION EVALUATOR:
  501.  *    Evaluate integer expression, ascii characters pointed to by string.
  502.  *    offset holds current PC to be subtracted from labels to achieve true
  503.  *    relative addressing.
  504.  */
  505.  
  506. int evaluate (expression, offset)
  507. char *expression;
  508. {
  509.     int f = 0;
  510.  
  511.     while (*expression && !isspace (*expression)) {
  512.         if (f) {
  513.               while (opsptr && priory (*expression) <= priory (opstk [opsptr-1]))
  514.                 push (operate (pop (), opstk [--opsptr], pop ()));
  515.             opstk [opsptr++] = *expression++;
  516.             }
  517.  
  518.         push (getexp (expression, offset));
  519.         expression += len;
  520.         f++;
  521.         }
  522.  
  523.     while (opsptr) push (operate (pop (), opstk [--opsptr], pop()));
  524.     return (pop ());
  525.     }
  526.  
  527. operate (v1, o, v2)
  528. char o;
  529. int v1, v2;
  530. {
  531.     return ((*((vop (o))->handler)) (v1, v2));
  532.     }
  533.  
  534. struct operator *vop (o)        /* returns address of operator struct member */
  535. char o;
  536. {
  537.     struct operator *p = olist;
  538.  
  539.     while (p->type && p->type != o) p++;
  540.     return (p);
  541.     }
  542.  
  543. int priory (v)                /* returns hierachial priority of operator */
  544. char v;
  545. {
  546.     return (vop (v)->priority);
  547.     }
  548.  
  549. push (v)                    /* push v onto evaluator's stack */
  550. int v;
  551. {
  552.     stack [stackptr++] = v;
  553.     return (v);
  554.     }
  555.  
  556. int pop ()                /* returns top value on evaluator's stack */
  557. {
  558.     return (stackptr ? stack [--stackptr] : 0);
  559.     }
  560.  
  561. int add (a, b)
  562. int a, b;
  563. {
  564.     return (a == BADEXP || b == BADEXP ? BADEXP : a + b);
  565.     }
  566.  
  567. int subtract (a, b)
  568. int a, b;
  569. {
  570.     return (a == BADEXP || b == BADEXP ? BADEXP : a - b);
  571.     }
  572.  
  573. int multiply (a, b)
  574. int a, b;
  575. {
  576.     return (a == BADEXP || b == BADEXP ? BADEXP : a * b);
  577.     }
  578.  
  579. int divide (a, b)
  580. {
  581.     return (a == BADEXP || b == BADEXP ? BADEXP : a / b);
  582.     }
  583.  
  584. goback ()        /* used for safety-return pointers */
  585. {
  586.     return (BADEXP);
  587.     }
  588.  
  589. int getexp (source, offset)
  590. char *source;
  591. int offset;
  592. {
  593.     int c, i, n;
  594.     char s [32], *p = s;
  595.  
  596.     unary = 1;        /* assume positive expression */
  597.     len = 0;
  598.     i = -1;
  599.  
  600.     while (i < 0 && !isalnum (c = *source)) {
  601.         if (c == '-') {
  602.             unary *= -1;
  603.             }
  604.         else if (c == '+') {
  605.             unary *= +1;
  606.             }
  607.         else if (c == '!') {
  608.                i = offset;
  609.                }
  610.         else unary = 2;        /* designate error */
  611.           len++;
  612.         source++;
  613.         }
  614.  
  615.     if (i >= 0) return (i);
  616.     if (unary == 2) return (BADEXP);
  617.  
  618.     while (isalnum (*source)) {
  619.         *p++ = *source++;
  620.         len++;
  621.         }
  622.  
  623.     *p = '\0';
  624.  
  625.      if (isalpha (*s)) {    /* labels start with alphabetic char */
  626.         for (i = 0; i < symbols; i++)
  627.             if (!strcmpi (s, symboltable [i].name)) break;
  628.         if (i == symbols)
  629.             return (BADEXP);
  630.         if (isupper (symboltable [i].name[0])) offset = 0;
  631.         return ((symboltable [i].value - offset) * unary);
  632.         }
  633.  
  634.     for (p = s, n = 0; isdigit (*p); p++) n = 10 * n + (int) (*p - '0');
  635.      return (*p ? BADEXP : n * unary);
  636.      }
  637.