home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 11 Util / 11-Util.zip / MAWK113.ZIP / mawk113 / cast.c < prev    next >
C/C++ Source or Header  |  1993-01-22  |  10KB  |  448 lines

  1.  
  2. /********************************************
  3. cast.c
  4. copyright 1991, Michael D. Brennan
  5.  
  6. This is a source file for mawk, an implementation of
  7. the AWK programming language.
  8.  
  9. Mawk is distributed without warranty under the terms of
  10. the GNU General Public License, version 2, 1991.
  11. ********************************************/
  12.  
  13.  
  14. /*   $Log: cast.c,v $
  15.  * Revision 5.3.1.4  1993/01/22  15:05:19  mike
  16.  * pow2->mpow2 for linux
  17.  *
  18.  * Revision 5.3.1.3  1993/01/22  14:18:33  mike
  19.  * const for strtod and ansi picky compilers
  20.  *
  21.  * Revision 5.3.1.2  1993/01/20  12:53:06  mike
  22.  * d_to_l()
  23.  *
  24.  * Revision 5.3.1.1  1993/01/15  03:33:37  mike
  25.  * patch3: safer double to int conversion
  26.  *
  27.  * Revision 5.3  1992/11/28  23:48:42  mike
  28.  * For internal conversion numeric->string, when testing
  29.  * if integer, use longs instead of ints so 16 and 32 bit
  30.  * systems behave the same
  31.  *
  32.  * Revision 5.2  1992/08/17  14:19:45  brennan
  33.  * patch2: After parsing, only bi_sprintf() uses string_buff.
  34.  *
  35.  * Revision 5.1  1991/12/05  07:55:41  brennan
  36.  * 1.1 pre-release
  37.  *
  38. */
  39.  
  40.  
  41. /*  cast.c  */
  42.  
  43. #include "mawk.h"
  44. #include "field.h"
  45. #include "memory.h"
  46. #include "scan.h"
  47. #include "repl.h"
  48.  
  49. int mpow2[NUM_CELL_TYPES] = {1,2,4,8,16,32,64,128,256,512} ;
  50.  
  51. void cast1_to_d( cp )
  52.   register CELL *cp ;
  53. {
  54.   switch( cp->type )
  55.   { case C_NOINIT :  cp->dval = 0.0 ; break ;
  56.  
  57.     case C_DOUBLE :  return ;
  58.  
  59.     case C_MBSTRN :
  60.     case C_STRING :  
  61.           { register STRING *s = (STRING *) cp->ptr  ;
  62.  
  63. #if FPE_TRAPS_ON  /* look for overflow error */
  64.             errno = 0 ;
  65.             cp->dval = strtod(s->str,(char **)0) ;
  66.             if ( errno && cp->dval != 0.0 ) /* ignore underflow */
  67.                 rt_error("overflow converting %s to double", s) ;
  68. #else
  69.             cp->dval = strtod(s->str,(char **)0) ;
  70. #endif
  71.             free_STRING(s) ;
  72.           }
  73.             break ;
  74.  
  75.     case C_STRNUM :  
  76.       /* don't need to convert, but do need to free the STRING part */
  77.             free_STRING( string(cp) ) ;
  78.             break ;
  79.  
  80.  
  81.     default :
  82.             bozo("cast on bad type") ;
  83.   }
  84.   cp->type = C_DOUBLE ;
  85. }
  86.  
  87. void cast2_to_d( cp )
  88.   register CELL *cp ;
  89. { register STRING *s ;
  90.  
  91.   switch( cp->type )
  92.   { case C_NOINIT :  cp->dval = 0.0 ; break ;
  93.  
  94.     case C_DOUBLE :  goto two ;
  95.     case C_STRNUM :  
  96.             free_STRING( string(cp) ) ;
  97.             break ;
  98.  
  99.     case C_MBSTRN :
  100.     case C_STRING :  
  101.             s = (STRING *) cp->ptr ;
  102.  
  103. #if FPE_TRAPS_ON  /* look for overflow error */
  104.             errno = 0 ;
  105.             cp->dval = strtod(s->str,(char **)0) ;
  106.             if ( errno && cp->dval != 0.0 ) /* ignore underflow */
  107.                 rt_error("overflow converting %s to double", s) ;
  108. #else
  109.             cp->dval = strtod(s->str,(char **)0) ;
  110. #endif
  111.             free_STRING(s) ;
  112.             break ;
  113.  
  114.     default :
  115.             bozo("cast on bad type") ;
  116.   }
  117.   cp->type = C_DOUBLE ;
  118.  
  119. two:   cp++ ;
  120.   switch( cp->type )
  121.   { case C_NOINIT :  cp->dval = 0.0 ; break ;
  122.  
  123.     case C_DOUBLE :  return ;
  124.     case C_STRNUM :  
  125.             free_STRING( string(cp) ) ;
  126.             break ;
  127.  
  128.     case C_MBSTRN :
  129.     case C_STRING :  
  130.             s = (STRING *) cp->ptr ;
  131.  
  132. #if FPE_TRAPS_ON  /* look for overflow error */
  133.             errno = 0 ;
  134.             cp->dval = strtod(s->str,(char **)0) ;
  135.             if ( errno && cp->dval != 0.0 ) /* ignore underflow */
  136.                 rt_error("overflow converting %s to double", s) ;
  137. #else
  138.             cp->dval = strtod(s->str,(char **)0) ;
  139. #endif
  140.             free_STRING(s) ;
  141.             break ;
  142.  
  143.     default :
  144.             bozo("cast on bad type") ;
  145.   }
  146.   cp->type = C_DOUBLE ;
  147. }
  148.  
  149. void cast1_to_s( cp )
  150.   register CELL *cp ;
  151.   register long lval ;
  152.   char xbuff[260] ;
  153.  
  154.   switch( cp->type )
  155.   { case C_NOINIT :  
  156.         null_str.ref_cnt++ ;
  157.         cp->ptr = (PTR) &null_str ;
  158.         break ;
  159.  
  160.     case C_DOUBLE  :
  161.     
  162.     lval = d_to_l(cp->dval) ;
  163.     if ( lval == cp->dval )
  164.         (void) sprintf(xbuff, INT_FMT, lval) ;
  165.     else
  166.             (void) sprintf(xbuff , string(CONVFMT)->str, cp->dval) ;
  167.  
  168.         cp->ptr = (PTR) new_STRING(xbuff) ;
  169.         break ;
  170.  
  171.     case C_STRING :  return ;
  172.  
  173.     case C_MBSTRN :
  174.     case C_STRNUM :  break ;
  175.  
  176.     default :  bozo("bad type on cast") ;
  177.   }
  178.   cp->type = C_STRING ;
  179. }
  180.  
  181. void cast2_to_s( cp )
  182.   register CELL *cp ;
  183.   register long lval ;
  184.   char xbuff[260] ;
  185.  
  186.   switch( cp->type )
  187.   { case C_NOINIT : 
  188.         null_str.ref_cnt++ ;
  189.         cp->ptr = (PTR) &null_str ;
  190.         break ;
  191.  
  192.     case C_DOUBLE  :
  193.  
  194.     lval = d_to_l(cp->dval) ;
  195.     if ( lval == cp->dval )
  196.         (void) sprintf(xbuff, INT_FMT, lval) ;
  197.     else
  198.             (void) sprintf(xbuff , string(CONVFMT)->str, cp->dval) ;
  199.  
  200.         cp->ptr = (PTR) new_STRING(xbuff) ;
  201.         break ;
  202.  
  203.     case C_STRING :  goto two ;
  204.  
  205.     case C_MBSTRN :
  206.     case C_STRNUM :  break ;
  207.  
  208.     default :  bozo("bad type on cast") ;
  209.   }
  210.   cp->type = C_STRING ;
  211.  
  212. two:
  213.   cp++ ;
  214.  
  215.   switch( cp->type )
  216.   { case C_NOINIT :  
  217.         null_str.ref_cnt++ ; 
  218.         cp->ptr = (PTR) &null_str ;
  219.         break ;
  220.  
  221.     case C_DOUBLE  :
  222.  
  223.     lval = d_to_l(cp->dval) ;
  224.     if ( lval == cp->dval )
  225.         (void) sprintf(xbuff, INT_FMT, lval) ;
  226.     else
  227.             (void) sprintf(xbuff , string(CONVFMT)->str, cp->dval) ;
  228.  
  229.         cp->ptr = (PTR) new_STRING(xbuff) ;
  230.         break ;
  231.  
  232.     case C_STRING :  return ;
  233.  
  234.     case C_MBSTRN :
  235.     case C_STRNUM :  break ;
  236.  
  237.     default :  bozo("bad type on cast") ;
  238.   }
  239.   cp->type = C_STRING ;
  240. }
  241.  
  242. void  cast_to_RE( cp )
  243.   register CELL *cp ;
  244. { register PTR p ;
  245.  
  246.   if ( cp->type < C_STRING )  cast1_to_s(cp) ;
  247.  
  248.   p = re_compile( string(cp) ) ;
  249.   free_STRING( string(cp) ) ;
  250.   cp->type = C_RE ;
  251.   cp->ptr = p ;
  252.  
  253. }
  254.  
  255. void  cast_for_split(cp)
  256.   register CELL *cp ;
  257. {
  258.   static char meta[] = "^$.*+?|[]()" ;
  259.   static char xbuff[] = "\\X" ;
  260.   int c ;
  261.   unsigned len ;
  262.     
  263.   if ( cp->type < C_STRING )  cast1_to_s(cp) ;
  264.  
  265.   if ( (len = string(cp)->len) == 1 )
  266.   {
  267.         if ( (c = string(cp)->str[0]) == ' ' )
  268.         { free_STRING(string(cp)) ;
  269.           cp->type = C_SPACE ; 
  270.           return ; 
  271.         }
  272.         else
  273.         if ( strchr(meta, c) )
  274.         { xbuff[1] = c ;
  275.           free_STRING(string(cp)) ;
  276.           cp->ptr = (PTR) new_STRING(xbuff) ;
  277.         }
  278.   }
  279.   else
  280.   if ( len == 0 ) 
  281.   { free_STRING(string(cp)) ;
  282.     cp->type = C_SNULL ; 
  283.     return ; 
  284.   }
  285.  
  286.   cast_to_RE(cp) ;
  287. }
  288.  
  289. /* input: cp-> a CELL of type C_MBSTRN (maybe strnum)
  290.    test it -- casting it to the appropriate type
  291.    which is C_STRING or C_STRNUM
  292. */
  293.  
  294. void check_strnum( cp )
  295.   CELL *cp ;
  296. { char *test ;
  297.   register unsigned char *s , *q ;
  298.  
  299.   cp->type = C_STRING ; /* assume not C_STRNUM */
  300.   s = (unsigned char *) string(cp)->str ;
  301.   q = s + string(cp)->len ;
  302.   while ( scan_code[*s] == SC_SPACE )  s++ ;
  303.   if ( s == q )  return ;
  304.  
  305.   while ( scan_code[ q[-1] ] == SC_SPACE )  q-- ;
  306.   if ( scan_code[ q[-1] ] != SC_DIGIT &&
  307.        q[-1] != '.' )   return ;
  308.  
  309.   switch ( scan_code[*s] )
  310.   {
  311.     case SC_DIGIT :
  312.     case SC_PLUS  :
  313.     case SC_MINUS :
  314.     case SC_DOT   :
  315.  
  316. #if FPE_TRAPS_ON
  317.              errno = 0 ;
  318.              cp->dval  = strtod((char *)s, &test) ;
  319.              if ( errno && cp->dval != 0.0 )
  320.                 rt_error(
  321.                 "overflow converting %s to double" , s) ;
  322. #else
  323.              cp->dval = strtod((char *)s, &test) ;
  324. #endif
  325.  
  326.              if ((char *) q <= test )  cp->type = C_STRNUM ;
  327.          /*  <= instead of == , for some buggy strtod
  328.          e.g. Apple Unix */
  329.   }
  330. }
  331.  
  332. /* cast a CELL to a replacement cell */
  333.  
  334. void cast_to_REPL( cp )
  335.   register CELL *cp ;
  336. { register STRING *sval ;
  337.  
  338.   if ( cp->type < C_STRING )  cast1_to_s(cp) ;
  339.   sval = (STRING *) cp->ptr ;
  340.  
  341.   (void) cellcpy(cp, repl_compile(sval)) ;
  342.   free_STRING(sval) ;
  343. }
  344.  
  345.  
  346. /* convert a double to long (this is not as simple as a
  347.    cast because the results are undefined if it won't fit).
  348.    Truncate large values to +MAX__LONG or -MAX__LONG
  349.    Send nans to -MAX__LONG
  350. */
  351.  
  352. long
  353. d_to_l(d)
  354.   double d ;
  355. {
  356.   if ( d >= MAX__LONG )  return MAX__LONG ;
  357.   if ( d >  -MAX__LONG ) return (int) d ;
  358.   return -MAX__LONG ;
  359. }
  360.  
  361. #if   HAVE_STRTOD==0
  362.  
  363. /* don't use this unless you really don't have strtod() because
  364.    (1) its probably slower than your real strtod()
  365.    (2) atof() may call the real strtod() 
  366. */
  367.  
  368. #if __STDC__ == 0
  369. #define const
  370. #endif
  371.  
  372. double strtod(s, endptr)
  373.   const char *s ;
  374.   char  **endptr ;
  375. {
  376.   register unsigned char *p ; 
  377.   int flag ;
  378.   double atof() ;
  379.  
  380.   if ( endptr )
  381.   {
  382.     p = (unsigned char*) s ;
  383.  
  384.     flag = 0 ;
  385.     while ( *p == ' ' || *p == '\t' ) p++ ;
  386.     if ( *p == '-' || *p == '+' ) p++ ;
  387.     while ( scan_code[*p] == SC_DIGIT ) { flag++ ; p++ ; }
  388.     if ( *p == '.' )
  389.     {
  390.       p++ ;
  391.       while ( scan_code[*p] == SC_DIGIT ) { flag++ ; p++ ; }
  392.     }
  393.     /* done with number part */
  394.     if ( flag == 0 )
  395.     { /* no number part */
  396.       *endptr = s ; return 0.0 ; 
  397.     }
  398.     else *endptr = (char *) p ;
  399.  
  400.     /* now look for exponent */
  401.     if ( *p == 'e' || *p == 'E' )
  402.     {
  403.       flag = 0 ;
  404.       p++ ;
  405.       if ( *p == '-' || *p == '+' ) p++ ;
  406.       while ( scan_code[*p] == SC_DIGIT ) { flag++ ; p++ ; }
  407.       if ( flag ) *endptr = (char *) p ;
  408.     }
  409.   }
  410.   return atof(s) ;
  411. }
  412. #endif  /* HAVE_STRTOD==0 */
  413.  
  414. #if   HAVE_FMOD==0
  415.  
  416. #if SW_FP_CHECK   /* this is V7 and XNX23A specific */
  417.  
  418. double  fmod(x, y)
  419.   double x, y ;
  420. { double modf() ;
  421.   double dtmp, ipart ;
  422.  
  423.   clrerr();
  424.   dtmp = x / y;
  425.   fpcheck();
  426.   (void) modf(dtmp, &ipart) ;
  427.   return x - ipart*y ;
  428. }
  429.  
  430. #else
  431.  
  432. double  fmod(x, y)
  433.   double x, y ;
  434. { double modf() ;
  435.   double ipart ;
  436.  
  437.   (void) modf(x/y, &ipart) ;
  438.   return x - ipart*y ;
  439. }
  440.  
  441. #endif
  442. #endif  
  443.  
  444.  
  445.  
  446.