home *** CD-ROM | disk | FTP | other *** search
/ ARM Club 1 / ARM_CLUB_CD.iso / contents / apps / print / progs / gscript / !GS / c / ISCAN < prev    next >
Encoding:
Text File  |  1991-10-26  |  20.1 KB  |  718 lines

  1. /* Copyright (C) 1989, 1990, 1991 Aladdin Enterprises.  All rights reserved.
  2.    Distributed by Free Software Foundation, Inc.
  3.  
  4. This file is part of Ghostscript.
  5.  
  6. Ghostscript is distributed in the hope that it will be useful, but
  7. WITHOUT ANY WARRANTY.  No author or distributor accepts responsibility
  8. to anyone for the consequences of using it or for whether it serves any
  9. particular purpose or works at all, unless he says so in writing.  Refer
  10. to the Ghostscript General Public License for full details.
  11.  
  12. Everyone is granted permission to copy, modify and redistribute
  13. Ghostscript, but only under the conditions described in the Ghostscript
  14. General Public License.  A copy of this license is supposed to have been
  15. given to you along with Ghostscript so you can know your rights and
  16. responsibilities.  It should be in a file named COPYING.  Among other
  17. things, the copyright notice and this notice must be preserved on all
  18. copies.  */
  19.  
  20. /* iscan.c */
  21. /* Token scanner for Ghostscript interpreter */
  22. #include <ctype.h>
  23. #include "memory_.h"
  24. #include "ghost.h"
  25. #include "arch.h"
  26. #include "alloc.h"
  27. #include "dict.h"            /* for //name lookup */
  28. #include "errors.h"
  29. #include "iutil.h"
  30. #include "name.h"
  31. #include "ostack.h"            /* for accumulating proc bodies */
  32. #include "packed.h"
  33. #include "store.h"
  34. #include "stream.h"
  35. #include "scanchar.h"
  36.  
  37. /* Array packing flag */
  38. ref array_packing;
  39.  
  40. /* Indicate whether to suppress \ handling in strings. */
  41. int scan_from_string = 0;        /* 1 in old level 1, 0 in Level 2 */
  42.  
  43. /* Forward references */
  44. private    int    scan_hex_string(P2(stream *, ref *)),
  45.         scan_int(P5(stream _ss *, int, int, long *, double *)),
  46.         scan_string(P3(stream *, int, ref *));
  47. int    scan_number(P2(stream _ss *, ref *));
  48.  
  49. /* Import the dictionary stack for //name lookup */
  50. extern ref *dsp;
  51.  
  52. /* Define the character scanning table (see scanchar.h). */
  53. byte scan_char_array[257];
  54.  
  55. /* A structure for dynamically growable objects */
  56. typedef struct dynamic_area_s {
  57.     byte *base;
  58.     byte *next;
  59.     uint num_elts;
  60.     uint elt_size;
  61.     int is_dynamic;            /* false if using fixed buffer */
  62.     byte *limit;
  63. } dynamic_area;
  64.  
  65. /* Begin a dynamic object. */
  66. /* dynamic_begin returns the value of alloc_dynamic, which may be 0: */
  67. /* the invoker of dynamic_begin must test the value against 0. */
  68. #define dynamic_begin(pda, dnum, desize)\
  69.     ((pda)->base = alloc_dynamic((pda)->num_elts = (dnum),\
  70.                      (pda)->elt_size = (desize), "scanner"),\
  71.      (pda)->limit = (pda)->base + (dnum) * (desize),\
  72.      (pda)->is_dynamic = 1,\
  73.      (pda)->next = (pda)->base)
  74.  
  75. /* Grow a dynamic object */
  76. private int
  77. dynamic_grow(register dynamic_area *pda)
  78. {    uint num = pda->num_elts;
  79.     uint size = num * pda->elt_size;
  80.     uint new_num;
  81.     uint pos = pda->next - pda->base;
  82.     size = (size < 10 ? 20 : size >= (max_uint >> 1) ? max_uint : size << 1);
  83.     new_num = size / pda->elt_size;
  84.     if ( pda->is_dynamic )
  85.        {    pda->base = alloc_grow(pda->base, num, new_num, pda->elt_size, "scanner");
  86.         if ( pda->base == 0 ) return 0;
  87.         pda->num_elts = new_num;
  88.         pda->limit = pda->base + size;
  89.        }
  90.     else
  91.        {    byte *base = pda->base;
  92.         uint old_size = size;
  93.         if ( !dynamic_begin(pda, new_num, pda->elt_size) ) return 0;
  94.         memcpy(pda->base, base, old_size);
  95.         pda->is_dynamic = 1;
  96.        }
  97.     pda->next = pda->base + pos;
  98.     return 1;
  99. }
  100.  
  101. /* Get rid of an unwanted dynamic object */
  102. #define dynamic_free(pda)\
  103.   if ( (pda)->is_dynamic )\
  104.     alloc_free((char *)((pda)->base), (pda)->num_elts, (pda)->elt_size, "scanner")
  105.  
  106. /* Initialize the scanner. */
  107. void
  108. scan_init()
  109. {    /* Initialize decoder array */
  110.     register byte _ds *decoder = scan_char_decoder;
  111.     static char stop_chars[] = "()<>[]{}/%";
  112.     static char space_chars[] = " \f\t\n\r";
  113.     decoder[-1] = ctype_eof;
  114.     memset(decoder, ctype_name, 256);
  115.        {    register char _ds *p;
  116.         for ( p = space_chars; *p; p++ )
  117.           decoder[*p] = ctype_space;
  118.         decoder[char_NULL] = decoder[char_VT] =
  119.           decoder[char_DOS_EOF] = ctype_space;
  120.         for ( p = stop_chars; *p; p++ )
  121.           decoder[*p] = ctype_other;
  122.        }
  123.        {    register int i;
  124.         for ( i = 0; i < 10; i++ )
  125.           decoder['0' + i] = i;
  126.         for ( i = 0; i < max_radix - 10; i++ )
  127.           decoder['A' + i] = decoder['a' + i] = i + 10;
  128.        }
  129.     /* Other initialization */
  130.     make_false(&array_packing);
  131. }
  132.  
  133. /* Read a token from a stream. */
  134. /* Return 1 for end-of-stream, 0 if a token was read, */
  135. /* or a (negative) error code. */
  136. /* If the token required a terminating character (i.e., was a name or */
  137. /* number) and the next character was whitespace, read and discard */
  138. /* that character: see the description of the 'token' operator on */
  139. /* p. 232 of the Red Book. */
  140. /* from_string indicates reading from a string vs. a file, */
  141. /* because \ escapes are not recognized in the former case. */
  142. /* (See the footnote on p. 23 of the Red Book.) */
  143. int
  144. scan_token(register stream *s, int from_string, ref *pref)
  145. {    ref *myref = pref;
  146.     dynamic_area proc_da;    /* (not actually dynamic) */
  147.     int pstack = 0;        /* offset from proc_da.base */
  148.     int retcode = 0;
  149.     register int c;
  150.     int name_type;            /* number of /'s preceding */
  151.     int try_number;
  152.     byte s1[1];
  153.     register byte _ds *decoder = scan_char_decoder;
  154.     /* Only old P*stScr*pt interpreters use from_string.... */
  155.     from_string &= scan_from_string;
  156. top:    c = sgetc(s);
  157. #ifdef DEBUG
  158. if ( gs_debug['s'] )
  159.     fprintf(gs_debug_out, (c >= 32 && c <= 126 ? "`%c'" : "`%03o'"), c);
  160. #endif
  161.     switch ( c )
  162.        {
  163.     case ' ': case '\f': case '\t': case '\n': case '\r':
  164.     case char_NULL: case char_VT: case char_DOS_EOF:
  165.         goto top;
  166.     case '[':
  167.     case ']':
  168.         s1[0] = (byte)c;
  169.         name_ref(s1, 1, myref, 1);
  170.         r_set_attrs(myref, a_executable);
  171.         break;
  172.     case '<':
  173.         retcode = scan_hex_string(s, myref);
  174.         break;
  175.     case '(':
  176.         retcode = scan_string(s, from_string, myref);
  177.         break;
  178.     case '{':
  179.         if ( pstack == 0 )
  180.            {    /* Use the operand stack to accumulate procedures. */
  181.             myref = osp + 1;
  182.             proc_da.base = (byte *)myref;
  183.             proc_da.limit = (byte *)(ostop + 1);
  184.             proc_da.is_dynamic = 0;
  185.             proc_da.elt_size = sizeof(ref);
  186.             proc_da.num_elts = ostop - osp;
  187.            }
  188.         if ( proc_da.limit - (byte *)myref < 2 * sizeof(ref) )
  189.           return e_limitcheck; /* ****** SHOULD GROW OSTACK ****** */
  190.         r_set_size(myref, pstack);
  191.         myref++;
  192.         pstack = (byte *)myref - proc_da.base;
  193.         goto top;
  194.     case '>':
  195.     case ')':
  196.         retcode = e_syntaxerror;
  197.         break;
  198.     case '}':
  199.         if ( pstack == 0 )
  200.            {    retcode = e_syntaxerror;
  201.             break;    
  202.            }
  203.            {    ref *ref0 = (ref *)(proc_da.base + pstack);
  204.             uint size = myref - ref0;
  205.             ref *aref;
  206.             myref = ref0 - 1;
  207.             pstack = r_size(myref);
  208.             if ( pstack == 0 ) myref = pref;
  209.             if ( array_packing.value.index )
  210.                {    retcode = make_packed_array(ref0, size, myref,
  211.                                 "scanner(packed)");
  212.                 if ( retcode < 0 ) return retcode;
  213.                 r_set_attrs(myref, a_executable);
  214.                }
  215.             else
  216.               {    aref = alloc_refs(size, "scanner(proc)");
  217.                 if ( aref == 0 ) return e_VMerror;
  218.                 refcpy_to_new(aref, ref0, size);
  219.                 make_tasv_new(myref, t_array, a_executable + a_all, size, refs, aref);
  220.               }
  221.            }
  222.         break;
  223.     case '/':
  224.         c = sgetc(s);
  225.         if ( c == '/' )
  226.            {    name_type = 2;
  227.             c = sgetc(s);
  228.            }
  229.         else
  230.             name_type = 1;
  231.         try_number = 0;
  232.         switch ( decoder[c] )
  233.            {
  234.         case ctype_name:
  235.         default:
  236.             goto do_name;
  237.         case ctype_eof:
  238.             /* Empty name: bizarre but legitimate. */
  239.             name_ref((byte *)0, 0, myref, 1);
  240.             goto have_name;
  241.         case ctype_other:
  242.             switch ( c )
  243.                {
  244.             case '[':    /* only special as first character */
  245.             case ']':    /* ditto */
  246.                 s1[0] = (byte)c;
  247.                 name_ref(s1, 1, myref, 1);
  248.                 goto have_name;
  249.             default:
  250.                 /* Empty name: bizarre but legitimate. */
  251.                 name_ref((byte *)0, 0, myref, 1);
  252.                 sputback(s);
  253.                 goto have_name;
  254.                }
  255.         case ctype_space:
  256.             /* Empty name: bizarre but legitimate. */
  257.             name_ref((byte *)0, 0, myref, 1);
  258.             /* Check for \r\n */
  259.             if ( c == '\r' && (c = sgetc(s)) != '\n' && c != EOFC )
  260.                 sputback(s);
  261.             goto have_name;
  262.            }
  263.         /* NOTREACHED */
  264.     case '%':
  265.        {    int c1;
  266.         do { c = sgetc(s); }
  267.         while ( c != '\f' && c != '\n' && c != '\r' && c != EOFC );
  268.         if ( c == '\r' && (c1 = sgetc(s)) != '\n' && c1 != EOFC )
  269.             sputback(s);
  270.         if ( c != EOFC ) goto top;
  271.        }    /* falls through */
  272.     case EOFC:
  273.         retcode = (pstack != 0 ? e_syntaxerror : 1);
  274.         break;
  275.     /* Handle separately the names that might be a number */
  276.     case '0': case '1': case '2': case '3': case '4':
  277.     case '5': case '6': case '7': case '8': case '9':
  278.     case '.': case '+': case '-':
  279.         try_number = 1;
  280.         name_type = 0;
  281.         goto do_name;
  282.     /* Check for a binary object */
  283.     default:            /* ****** NYI ****** */
  284.     /* Handle the common cases (letters and _) explicitly, */
  285.     /* rather than going through the default test. */
  286.     case 'a': case 'b': case 'c': case 'd': case 'e': case 'f':
  287.     case 'g': case 'h': case 'i': case 'j': case 'k': case 'l': case 'm':
  288.     case 'n': case 'o': case 'p': case 'q': case 'r': case 's':
  289.     case 't': case 'u': case 'v': case 'w': case 'x': case 'y': case 'z':
  290.     case 'A': case 'B': case 'C': case 'D': case 'E': case 'F':
  291.     case 'G': case 'H': case 'I': case 'J': case 'K': case 'L': case 'M':
  292.     case 'N': case 'O': case 'P': case 'Q': case 'R': case 'S':
  293.     case 'T': case 'U': case 'V': case 'W': case 'X': case 'Y': case 'Z':
  294.     case '_':
  295.         try_number = 0;
  296.         name_type = 0;
  297.         /* Common code for scanning a name. */
  298.         /* try_number and name_type are already set. */
  299.         /* We know c has ctype_name or is a digit. */
  300. do_name:
  301.        {    dynamic_area da;
  302.         /* Try to scan entirely within the stream buffer. */
  303.         /* We stop 1 character early, so we don't switch buffers */
  304.         /* looking ahead if the name is terminated by \r\n. */
  305.         register byte *ptr = sbufptr(s);
  306.         byte *end = sbufend(s) - 1;
  307.         da.base = ptr - 1;
  308.         da.is_dynamic = 0;
  309.         do
  310.            {    if ( ptr >= end )
  311.                {    ssetbufptr(s, ptr);
  312.                 /* Initialize the dynamic area. */
  313.                 /* We have to do this before the next */
  314.                 /* sgetc, which will overwrite the buffer. */
  315.                 da.next = da.limit = ptr;
  316.                 da.num_elts = ptr - da.base;
  317.                 da.elt_size = 1;
  318.                 if ( !dynamic_grow(&da) ) return e_VMerror;
  319.                 ptr = da.next;
  320.                 goto dyn_name;
  321.                }
  322.             c = *ptr++;
  323.            }
  324.         while ( decoder[c] <= ctype_name );    /* digit or name */
  325.         /* Name ended within the buffer. */
  326.         ssetbufptr(s, ptr);
  327.         ptr--;
  328.         goto nx;
  329.         /* Name overran buffer. */
  330. dyn_name:    while ( decoder[c = sgetc(s)] <= ctype_name )
  331.           {    if ( ptr == da.limit )
  332.                {    da.next = ptr;
  333.                 if ( !dynamic_grow(&da) )
  334.                   return e_VMerror;
  335.                 ptr = da.next;
  336.                }
  337.             *ptr++ = c;
  338.            }
  339. nx:        switch ( decoder[c] )
  340.           {
  341.           case ctype_other:
  342.             sputback(s);
  343.           case ctype_space:
  344.             /* Check for \r\n */
  345.             if ( c == '\r' && (c = sgetc(s)) != '\n' && c != EOFC )
  346.                 sputback(s);
  347.           case ctype_eof: ;
  348.           }
  349.         /* Check for a number */
  350.         if ( try_number )
  351.            {    stream nst;
  352.             sread_string(&nst, da.base, (uint)(ptr - da.base));
  353.             retcode = scan_number(&nst, myref);
  354.             if ( retcode != e_syntaxerror )
  355.                {    dynamic_free(&da);
  356.                 goto have_name;    /* might be e_limitcheck */
  357.                }
  358.            }
  359.         retcode = name_ref(da.base, (uint)(ptr - da.base), myref, 1);
  360.         dynamic_free(&da);
  361.        }
  362.         /* Done scanning.  Check for preceding /'s. */
  363. have_name:    if ( retcode < 0 ) return retcode;
  364.         switch ( name_type )
  365.            {
  366.         case 0:            /* ordinary executable name */
  367.             if ( r_type(myref) == t_name )    /* i.e., not a number */
  368.               r_set_attrs(myref, a_executable);
  369.         case 1:            /* quoted name */
  370.             break;
  371.         case 2:            /* immediate lookup */
  372.            {    ref *pvalue;
  373.             if ( dict_lookup(dstack, dsp, myref, &pvalue) <= 0 )
  374.                 return e_undefined;
  375.             ref_assign_new(myref, pvalue);
  376.            }
  377.            }
  378.        }
  379.     /* If we are the top level, return the object, otherwise keep going */
  380.     if ( pstack == 0 || retcode < 0 )
  381.       return retcode;
  382.     if ( proc_da.limit - (byte *)myref < 2 * sizeof(ref) )
  383.       return e_limitcheck; /* ****** SHOULD GROW OSTACK ****** */
  384.     myref++;
  385.     goto top;
  386. }
  387.  
  388. /* The internal scanning procedures return 0 on success, */
  389. /* or a (negative) error code on failure. */
  390.  
  391. /* Procedure to scan a number.  This is also called by cvi and cvr. */
  392. int
  393. scan_number(register stream _ss *s, ref *pref)
  394. {    /* Powers of 10 up to 6 can be represented accurately as */
  395.     /* a single-precision float. */
  396. #define num_powers_10 6
  397.     static float powers_10[num_powers_10+1] =
  398.        {    1e0, 1e1, 1e2, 1e3, 1e4, 1e5, 1e6    };
  399.     static double neg_powers_10[num_powers_10+1] =
  400.        {    1e0, 1e-1, 1e-2, 1e-3, 1e-4, 1e-5, 1e-6    };
  401.     int sign = 0;
  402.     long ival;
  403.     double dval;
  404.     int exp10 = 0;
  405.     int code;
  406.     register int c;
  407.     switch ( c = sgetc(s) )
  408.        {
  409.     case '+': sign = 1; c = sgetc(s); break;
  410.     case '-': sign = -1; c = sgetc(s); break;
  411.        }
  412.     if ( !isdigit(c) )
  413.        {    if ( c != '.' ) return e_syntaxerror;
  414.         c = sgetc(s);
  415.         if ( !isdigit(c) ) return e_syntaxerror;
  416.         ival = 0;
  417.         goto fi;
  418.        }
  419.     sputback(s);
  420.     if ( (code = scan_int(s, 10, 0, &ival, &dval)) != 0 )
  421.        {    if ( code < 0 ) return code;    /* e_syntaxerror */
  422.         /* Code == 1, i.e., the integer overflowed. */
  423.         switch ( c = sgetc(s) )
  424.            {
  425.         default: return e_syntaxerror;    /* not terminated properly */
  426.         case '.': c = sgetc(s); goto fd;
  427.         case 'e': case 'E': goto fsd;
  428.         case EOFC:        /* return a float */
  429.             make_real_new(pref, (float)(sign < 0 ? -dval : dval));
  430.             return 0;
  431.            }
  432.        }
  433.     switch ( c = sgetc(s) )
  434.        {
  435.     default: return e_syntaxerror;    /* not terminated properly */
  436.     case '.': c = sgetc(s); goto fi;
  437.     case 'e': case 'E': goto fsi;
  438.     case '#':
  439.         if ( sign || ival < min_radix || ival > max_radix )
  440.             return e_syntaxerror;
  441.         code = scan_int(s, (int)ival, 1, &ival, NULL);
  442.         if ( code ) return code;
  443.         if ( sgetc(s) != EOFC ) return e_syntaxerror;
  444.     case EOFC: ;
  445.        }
  446.     /* Return an integer */
  447.     make_int_new(pref, (sign < 0 ? -ival : ival));
  448.     return 0;
  449.     /* Handle a real.  We just saw the decimal point. */
  450.     /* Enter here if we are still accumulating an integer in ival. */
  451. fi:    while ( isdigit(c) )
  452.        {    /* Check for overflowing ival */
  453.         if ( ival >= (max_ulong >> 1) / 10 - 1 )
  454.            {    dval = ival;
  455.             goto fd;
  456.            }
  457.         ival = ival * 10 + (c - '0');
  458.         c = sgetc(s);
  459.         exp10--;
  460.        }
  461. fsi:    if ( sign < 0 ) ival = -ival;
  462.     /* Take a shortcut for the common case */
  463.     if ( !(c == 'e' || c == 'E' || exp10 < -num_powers_10) )
  464.        {    make_real_new(pref, (float)(ival * neg_powers_10[-exp10]));
  465.         return 0;
  466.        }
  467.     dval = ival;
  468.     goto fe;
  469.     /* Now we are accumulating a double in dval. */
  470. fd:    while ( isdigit(c) )
  471.        {    dval = dval * 10 + (c - '0');
  472.         c = sgetc(s);
  473.         exp10--;
  474.        }
  475. fsd:    if ( sign < 0 ) dval = -dval;
  476. fe:    /* dval contains the value, negated if necessary */
  477.     if ( c == 'e' || c == 'E' )
  478.        {    /* Check for a following exponent. */
  479.         int esign = 0;
  480.         long eexp;
  481.         switch ( c = sgetc(s) )
  482.            {
  483.         case '+': break;
  484.         case '-': esign = 1; break;
  485.         default: sputback(s);
  486.            }
  487.         code = scan_int(s, 10, 0, &eexp, NULL);
  488.         if ( code < 0 ) return code;
  489.         if ( code > 0 || eexp > 999 )
  490.             return e_limitcheck;    /* semi-arbitrary */
  491.         if ( esign )
  492.             exp10 -= (int)eexp;
  493.         else
  494.             exp10 += (int)eexp;
  495.         c = sgetc(s);
  496.        }
  497.     if ( c != EOFC ) return e_syntaxerror;
  498.     /* Compute dval * 10^exp10. */
  499.     if ( exp10 > 0 )
  500.        {    while ( exp10 > num_powers_10 )
  501.             dval *= powers_10[num_powers_10],
  502.             exp10 -= num_powers_10;
  503.         if ( exp10 > 0 )
  504.             dval *= powers_10[exp10];
  505.        }
  506.     else if ( exp10 < 0 )
  507.        {    while ( exp10 < -num_powers_10 )
  508.             dval /= powers_10[num_powers_10],
  509.             exp10 += num_powers_10;
  510.         if ( exp10 < 0 )
  511.             dval /= powers_10[-exp10];
  512.        }
  513.     make_real_new(pref, (float)dval);
  514.     return 0;
  515. }
  516. /* Internal subroutine to scan an integer. */
  517. /* Return 0, e_limitcheck, or e_syntaxerror. */
  518. /* (The only syntax error is no digits encountered.) */
  519. /* Put back the terminating character. */
  520. /* If nosign is true, the integer is scanned as unsigned; */
  521. /* overflowing a ulong returns e_limitcheck.  If nosign is false, */
  522. /* the integer is scanned as signed; if the integer won't fit in a long, */
  523. /* then: */
  524. /*   if pdval == NULL, return e_limitcheck; */
  525. /*   if pdval != NULL, return 1 and store a double value in *pdval. */
  526. private int
  527. scan_int(register stream _ss *s, int radix, int nosign,
  528.   long *pval, double *pdval)
  529. {    uint ival = 0, imax, irem;
  530. #if arch_ints_are_short
  531.     ulong lval, lmax;
  532.     uint lrem;
  533. #else
  534. #  define lval ival            /* for overflowing into double */
  535. #endif
  536.     double dval;
  537.     register int c, d;
  538.     register byte _ds *decoder = scan_char_decoder;
  539.     /* Avoid the long divisions when radix = 10 */
  540. #define set_max(vmax, vrem, big)\
  541.   if ( radix == 10 )    vmax = (big) / 10, vrem = (big) % 10;\
  542.   else            vmax = (big) / radix, vrem = (big) % radix
  543.     set_max(imax, irem, max_uint);
  544. #define convert_digit_fails(c, d)\
  545.   (d = decoder[c]) >= radix
  546.     while ( 1 )
  547.        {    c = sgetc(s);
  548.         if ( convert_digit_fails(c, d) )
  549.            {    if ( c != EOFC ) sputback(s);
  550.             if ( (int)ival < 0 && !nosign )
  551.                {    d = ival % radix;
  552.                 ival /= radix;
  553.                 break;
  554.                }
  555.             *pval = ival;
  556.             return 0;
  557.            }
  558.         if ( ival >= imax && (ival > imax || d > irem) )
  559.             break;        /* overflow */
  560.         ival = ival * radix + d;
  561.        }
  562. #if arch_ints_are_short
  563.     /* Short integer overflowed.  Accumulate in a long. */
  564.     lval = (ulong)ival * radix + d;
  565.     set_max(lmax, lrem, max_ulong);
  566.     while ( 1 )
  567.        {    c = sgetc(s);
  568.         if ( convert_digit_fails(c, d) )
  569.            {    if ( c != EOFC ) sputback(s);
  570.             if ( (long)lval < 0 && !nosign )
  571.                {    d = lval % radix;
  572.                 lval /= radix;
  573.                 break;
  574.                }
  575.             *pval = lval;
  576.             return 0;
  577.            }
  578.         if ( lval >= lmax && (lval > lmax || d > lrem) )
  579.             break;        /* overflow */
  580.         lval = lval * radix + d;
  581.        }
  582. #endif
  583.     /* Integer overflowed.  Accumulate the result as a double. */
  584.     if ( pdval == NULL ) return e_limitcheck;
  585.     dval = (double)lval * radix + d;
  586.     while ( 1 )
  587.        {    c = sgetc(s);
  588.         if ( convert_digit_fails(c, d) )
  589.            {    if ( c != EOFC ) sputback(s);
  590.             *pdval = dval;
  591.             return 1;
  592.            }
  593.         dval = dval * radix + d;
  594.        }
  595.     /* Control doesn't get here */
  596. }
  597.  
  598. /* Make a string */
  599. private int
  600. mk_string(ref *pref, dynamic_area *pda)
  601. {    uint size = pda->next - pda->base;
  602.     byte *body = alloc_shrink(pda->base, pda->num_elts, size, 1, "scanner(string)");
  603.     if ( body == 0 ) return e_VMerror;
  604.     make_tasv_new(pref, t_string, a_all, size, bytes, body);
  605.     return 0;
  606. }
  607.  
  608. /* Internal procedure to scan a string. */
  609. private int
  610. scan_string(register stream *s, int from_string, ref *pref)
  611. {    dynamic_area da;
  612.     register int c;
  613.     register byte *ptr = dynamic_begin(&da, 100, 1);
  614.     int plevel = 0;
  615.     if ( ptr == 0 ) return e_VMerror;
  616. top:    while ( 1 )
  617.        {    switch ( (c = sgetc(s)) )
  618.            {
  619.         case EOFC:
  620.             return e_syntaxerror;
  621.         case '\\':
  622.             if ( from_string ) break;
  623.             switch ( (c = sgetc(s)) )
  624.                {
  625.             case 'n': c = '\n'; break;
  626.             case 'r': c = '\r'; break;
  627.             case 't': c = '\t'; break;
  628.             case 'b': c = '\b'; break;
  629.             case 'f': c = '\f'; break;
  630.             case '\r':    /* ignore, check for following \n */
  631.                 c = sgetc(s);
  632.                 if ( c != '\n' && c != EOFC )
  633.                     sputback(s);
  634.                 goto top;
  635.             case '\n': goto top;    /* ignore */
  636.             case '0': case '1': case '2': case '3':
  637.             case '4': case '5': case '6': case '7':
  638.                {    int d = sgetc(s);
  639.                 c -= '0';
  640.                 if ( d >= '0' && d <= '7' )
  641.                    {    c = (c << 3) + d - '0';
  642.                     d = sgetc(s);
  643.                     if ( d >= '0' && d <= '7' )
  644.                        {    c = (c << 3) + d - '0';
  645.                         break;
  646.                        }
  647.                    }
  648.                 if ( d == EOFC ) return e_syntaxerror;
  649.                 sputback(s);
  650.                }
  651.                 break;
  652.             default: ;    /* ignore the \ */
  653.                }
  654.             break;
  655.         case '(':
  656.             plevel++; break;
  657.         case ')':
  658.             if ( --plevel < 0 ) goto out; break;
  659.         case '\r':        /* convert to \n */
  660.             c = sgetc(s);
  661.             if ( c != '\n' && c != EOFC )
  662.                 sputback(s);
  663.             c = '\n';
  664.            }
  665.         if ( ptr == da.limit )
  666.            {    da.next = ptr;
  667.             if ( !dynamic_grow(&da) )
  668.               return e_VMerror;
  669.             ptr = da.next;
  670.            }
  671.         *ptr++ = c;
  672.        }
  673. out:    da.next = ptr;
  674.     return mk_string(pref, &da);
  675. }
  676.  
  677. /* Internal procedure to scan a hex string. */
  678. private int
  679. scan_hex_string(stream *s, ref *pref)
  680. {    dynamic_area da;
  681.     int c1, c2, val1, val2;
  682.     byte *ptr = dynamic_begin(&da, 100, 1);
  683.     register byte _ds *decoder = scan_char_decoder;
  684.     if ( ptr == 0 ) return e_VMerror;
  685. l1:    do
  686.        {    c1 = sgetc(s);
  687.         if ( (val1 = decoder[c1]) < 0x10 )
  688.            {    do
  689.                {    c2 = sgetc(s);
  690.                 if ( (val2 = decoder[c2]) < 0x10 )
  691.                    {    if ( ptr == da.limit )
  692.                        {    da.next = ptr;
  693.                         if ( !dynamic_grow(&da) )
  694.                           return e_VMerror;
  695.                         ptr = da.next;
  696.                        }
  697.                     *ptr++ = (val1 << 4) + val2;
  698.                     goto l1;
  699.                    }
  700.                }
  701.             while ( val2 == ctype_space );
  702.             if ( c2 != '>' ) return e_syntaxerror;
  703.             if ( ptr == da.limit )
  704.                {    da.next = ptr;
  705.                 if ( !dynamic_grow(&da) )
  706.                   return e_VMerror;
  707.                 ptr = da.next;
  708.                }
  709.             *ptr++ = val1 << 4;    /* no 2nd char */
  710.             goto lx;
  711.            }
  712.        }
  713.     while ( val1 == ctype_space );
  714.     if ( c1 != '>' ) return e_syntaxerror;
  715. lx:    da.next = ptr;
  716.     return mk_string(pref, &da);
  717. }
  718.