home *** CD-ROM | disk | FTP | other *** search
/ The World of Computer Software / World_Of_Computer_Software-02-387-Vol-3of3.iso / m / mawk11as.zip / CAST.C < prev    next >
C/C++ Source or Header  |  1991-12-18  |  9KB  |  402 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.1  91/12/05  07:55:41  brennan
  16.  * 1.1 pre-release
  17.  * 
  18. */
  19.  
  20.  
  21. /*  cast.c  */
  22.  
  23. #include "mawk.h"
  24. #include "field.h"
  25. #include "memory.h"
  26. #include "scan.h"
  27. #include "repl.h"
  28.  
  29. int pow2[NUM_CELL_TYPES] = {1,2,4,8,16,32,64,128,256,512} ;
  30.  
  31. void cast1_to_d( cp )
  32.   register CELL *cp ;
  33. {
  34.   switch( cp->type )
  35.   { case C_NOINIT :  cp->dval = 0.0 ; break ;
  36.  
  37.     case C_DOUBLE :  return ;
  38.  
  39.     case C_MBSTRN :
  40.     case C_STRING :  
  41.           { register STRING *s = (STRING *) cp->ptr  ;
  42.  
  43. #if FPE_TRAPS_ON  /* look for overflow error */
  44.             errno = 0 ;
  45.             cp->dval = strtod(s->str,(char **)0) ;
  46.             if ( errno && cp->dval != 0.0 ) /* ignore underflow */
  47.                 rt_error("overflow converting %s to double", s) ;
  48. #else
  49.             cp->dval = strtod(s->str,(char **)0) ;
  50. #endif
  51.             free_STRING(s) ;
  52.           }
  53.             break ;
  54.  
  55.     case C_STRNUM :  
  56.       /* don't need to convert, but do need to free the STRING part */
  57.             free_STRING( string(cp) ) ;
  58.             break ;
  59.  
  60.  
  61.     default :
  62.             bozo("cast on bad type") ;
  63.   }
  64.   cp->type = C_DOUBLE ;
  65. }
  66.  
  67. void cast2_to_d( cp )
  68.   register CELL *cp ;
  69. { register STRING *s ;
  70.  
  71.   switch( cp->type )
  72.   { case C_NOINIT :  cp->dval = 0.0 ; break ;
  73.  
  74.     case C_DOUBLE :  goto two ;
  75.     case C_STRNUM :  
  76.             free_STRING( string(cp) ) ;
  77.             break ;
  78.  
  79.     case C_MBSTRN :
  80.     case C_STRING :  
  81.             s = (STRING *) cp->ptr ;
  82.  
  83. #if FPE_TRAPS_ON  /* look for overflow error */
  84.             errno = 0 ;
  85.             cp->dval = strtod(s->str,(char **)0) ;
  86.             if ( errno && cp->dval != 0.0 ) /* ignore underflow */
  87.                 rt_error("overflow converting %s to double", s) ;
  88. #else
  89.             cp->dval = strtod(s->str,(char **)0) ;
  90. #endif
  91.             free_STRING(s) ;
  92.             break ;
  93.  
  94.     default :
  95.             bozo("cast on bad type") ;
  96.   }
  97.   cp->type = C_DOUBLE ;
  98.  
  99. two:   cp++ ;
  100.   switch( cp->type )
  101.   { case C_NOINIT :  cp->dval = 0.0 ; break ;
  102.  
  103.     case C_DOUBLE :  return ;
  104.     case C_STRNUM :  
  105.             free_STRING( string(cp) ) ;
  106.             break ;
  107.  
  108.     case C_MBSTRN :
  109.     case C_STRING :  
  110.             s = (STRING *) cp->ptr ;
  111.  
  112. #if FPE_TRAPS_ON  /* look for overflow error */
  113.             errno = 0 ;
  114.             cp->dval = strtod(s->str,(char **)0) ;
  115.             if ( errno && cp->dval != 0.0 ) /* ignore underflow */
  116.                 rt_error("overflow converting %s to double", s) ;
  117. #else
  118.             cp->dval = strtod(s->str,(char **)0) ;
  119. #endif
  120.             free_STRING(s) ;
  121.             break ;
  122.  
  123.     default :
  124.             bozo("cast on bad type") ;
  125.   }
  126.   cp->type = C_DOUBLE ;
  127. }
  128.  
  129. void cast1_to_s( cp )
  130.   register CELL *cp ;
  131. { register int ival ;
  132.  
  133.   switch( cp->type )
  134.   { case C_NOINIT :  
  135.         null_str.ref_cnt++ ;
  136.         cp->ptr = (PTR) &null_str ;
  137.         break ;
  138.  
  139.     case C_DOUBLE  :
  140.     
  141.     if ( (double) (ival = (int) cp->dval) == cp->dval )
  142.         (void) sprintf(string_buff, "%d", ival) ;
  143.     else
  144.             (void) sprintf(string_buff ,
  145.             string(CONVFMT)->str, cp->dval) ;
  146.  
  147.         cp->ptr = (PTR) new_STRING(string_buff) ;
  148.         break ;
  149.  
  150.     case C_STRING :  return ;
  151.  
  152.     case C_MBSTRN :
  153.     case C_STRNUM :  break ;
  154.  
  155.     default :  bozo("bad type on cast") ;
  156.   }
  157.   cp->type = C_STRING ;
  158. }
  159.  
  160. void cast2_to_s( cp )
  161.   register CELL *cp ;
  162. { register int ival ;
  163.  
  164.   switch( cp->type )
  165.   { case C_NOINIT : 
  166.         null_str.ref_cnt++ ;
  167.         cp->ptr = (PTR) &null_str ;
  168.         break ;
  169.  
  170.     case C_DOUBLE  :
  171.     if ( (double) (ival = (int) cp->dval) == cp->dval )
  172.         (void) sprintf(string_buff, "%d", ival) ;
  173.     else
  174.             (void) sprintf(string_buff ,
  175.             string(CONVFMT)->str, cp->dval) ;
  176.  
  177.         cp->ptr = (PTR) new_STRING(string_buff) ;
  178.         break ;
  179.  
  180.     case C_STRING :  goto two ;
  181.  
  182.     case C_MBSTRN :
  183.     case C_STRNUM :  break ;
  184.  
  185.     default :  bozo("bad type on cast") ;
  186.   }
  187.   cp->type = C_STRING ;
  188.  
  189. two:
  190.   cp++ ;
  191.  
  192.   switch( cp->type )
  193.   { case C_NOINIT :  
  194.         null_str.ref_cnt++ ; 
  195.         cp->ptr = (PTR) &null_str ;
  196.         break ;
  197.  
  198.     case C_DOUBLE  :
  199.     if ( (double) (ival = (int) cp->dval) == cp->dval )
  200.         (void) sprintf(string_buff, "%d", ival) ;
  201.     else
  202.             (void) sprintf(string_buff ,
  203.             string(CONVFMT)->str, cp->dval) ;
  204.  
  205.         cp->ptr = (PTR) new_STRING(string_buff) ;
  206.         break ;
  207.  
  208.     case C_STRING :  return ;
  209.  
  210.     case C_MBSTRN :
  211.     case C_STRNUM :  break ;
  212.  
  213.     default :  bozo("bad type on cast") ;
  214.   }
  215.   cp->type = C_STRING ;
  216. }
  217.  
  218. void  cast_to_RE( cp )
  219.   register CELL *cp ;
  220. { register PTR p ;
  221.  
  222.   if ( cp->type < C_STRING )  cast1_to_s(cp) ;
  223.  
  224.   p = re_compile( string(cp) ) ;
  225.   free_STRING( string(cp) ) ;
  226.   cp->type = C_RE ;
  227.   cp->ptr = p ;
  228.  
  229. }
  230.  
  231. void  cast_for_split(cp)
  232.   register CELL *cp ;
  233. {
  234.   static char meta[] = "^$.*+?|[]()" ;
  235.   static char xbuff[] = "\\X" ;
  236.   int c ;
  237.   unsigned len ;
  238.     
  239.   if ( cp->type < C_STRING )  cast1_to_s(cp) ;
  240.  
  241.   if ( (len = string(cp)->len) == 1 )
  242.   {
  243.         if ( (c = string(cp)->str[0]) == ' ' )
  244.         { free_STRING(string(cp)) ;
  245.           cp->type = C_SPACE ; 
  246.           return ; 
  247.         }
  248.         else
  249.         if ( strchr(meta, c) )
  250.         { xbuff[1] = c ;
  251.           free_STRING(string(cp)) ;
  252.           cp->ptr = (PTR) new_STRING(xbuff) ;
  253.         }
  254.   }
  255.   else
  256.   if ( len == 0 ) 
  257.   { free_STRING(string(cp)) ;
  258.     cp->type = C_SNULL ; 
  259.     return ; 
  260.   }
  261.  
  262.   cast_to_RE(cp) ;
  263. }
  264.  
  265. /* input: cp-> a CELL of type C_MBSTRN (maybe strnum)
  266.    test it -- casting it to the appropriate type
  267.    which is C_STRING or C_STRNUM
  268. */
  269.  
  270. void check_strnum( cp )
  271.   CELL *cp ;
  272. { char *test ;
  273.   register unsigned char *s , *q ;
  274.  
  275.   cp->type = C_STRING ; /* assume not C_STRNUM */
  276.   s = (unsigned char *) string(cp)->str ;
  277.   q = s + string(cp)->len ;
  278.   while ( scan_code[*s] == SC_SPACE )  s++ ;
  279.   if ( s == q )  return ;
  280.  
  281.   while ( scan_code[ q[-1] ] == SC_SPACE )  q-- ;
  282.   if ( scan_code[ q[-1] ] != SC_DIGIT &&
  283.        q[-1] != '.' )   return ;
  284.  
  285.   switch ( scan_code[*s] )
  286.   {
  287.     case SC_DIGIT :
  288.     case SC_PLUS  :
  289.     case SC_MINUS :
  290.     case SC_DOT   :
  291.  
  292. #if FPE_TRAPS_ON
  293.              errno = 0 ;
  294.              cp->dval  = strtod((char *)s, &test) ;
  295.              if ( errno && cp->dval != 0.0 )
  296.                 rt_error(
  297.                 "overflow converting %s to double" , s) ;
  298. #else
  299.              cp->dval = strtod((char *)s, &test) ;
  300. #endif
  301.  
  302.              if ((char *) q <= test )  cp->type = C_STRNUM ;
  303.          /*  <= instead of == , for some buggy strtod
  304.          e.g. Apple Unix */
  305.   }
  306. }
  307.  
  308. /* cast a CELL to a replacement cell */
  309.  
  310. void cast_to_REPL( cp )
  311.   register CELL *cp ;
  312. { register STRING *sval ;
  313.  
  314.   if ( cp->type < C_STRING )  cast1_to_s(cp) ;
  315.   sval = (STRING *) cp->ptr ;
  316.  
  317.   (void) cellcpy(cp, repl_compile(sval)) ;
  318.   free_STRING(sval) ;
  319. }
  320.  
  321.  
  322. #if   HAVE_STRTOD==0
  323.  
  324. /* don't use this unless you really don't have strtod() because
  325.    (1) its probably slower than your real strtod()
  326.    (2) atof() may call the real strtod() 
  327. */
  328.  
  329. double strtod(s, endptr)
  330.   char *s , **endptr ;
  331. {
  332.   register unsigned char *p ; 
  333.   int flag ;
  334.   double atof() ;
  335.  
  336.   if ( endptr )
  337.   {
  338.     p = (unsigned char*) s ;
  339.  
  340.     flag = 0 ;
  341.     while ( *p == ' ' || *p == '\t' ) p++ ;
  342.     if ( *p == '-' || *p == '+' ) p++ ;
  343.     while ( scan_code[*p] == SC_DIGIT ) { flag++ ; p++ ; }
  344.     if ( *p == '.' )
  345.     {
  346.       p++ ;
  347.       while ( scan_code[*p] == SC_DIGIT ) { flag++ ; p++ ; }
  348.     }
  349.     /* done with number part */
  350.     if ( flag == 0 )
  351.     { /* no number part */
  352.       *endptr = s ; return 0.0 ; 
  353.     }
  354.     else *endptr = (char *) p ;
  355.  
  356.     /* now look for exponent */
  357.     if ( *p == 'e' || *p == 'E' )
  358.     {
  359.       flag = 0 ;
  360.       p++ ;
  361.       if ( *p == '-' || *p == '+' ) p++ ;
  362.       while ( scan_code[*p] == SC_DIGIT ) { flag++ ; p++ ; }
  363.       if ( flag ) *endptr = (char *) p ;
  364.     }
  365.   }
  366.   return atof(s) ;
  367. }
  368. #endif  /* HAVE_STRTOD==0 */
  369.  
  370. #if   HAVE_FMOD==0
  371.  
  372. #if SW_FP_CHECK   /* this is V7 and XNX23A specific */
  373.  
  374. double  fmod(x, y)
  375.   double x, y ;
  376. { double modf() ;
  377.   double dtmp, ipart ;
  378.  
  379.   clrerr();
  380.   dtmp = x / y;
  381.   fpcheck();
  382.   (void) modf(dtmp, &ipart) ;
  383.   return x - ipart*y ;
  384. }
  385.  
  386. #else
  387.  
  388. double  fmod(x, y)
  389.   double x, y ;
  390. { double modf() ;
  391.   double ipart ;
  392.  
  393.   (void) modf(x/y, &ipart) ;
  394.   return x - ipart*y ;
  395. }
  396.  
  397. #endif
  398. #endif  
  399.  
  400.  
  401.  
  402.