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

  1.  
  2. /********************************************
  3. print.c
  4. copyright 1992, 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. /* $Log: print.c,v $
  14.  * Revision 5.4.1.2  1993/01/20  12:53:11  mike
  15.  * d_to_l()
  16.  *
  17.  * Revision 5.4.1.1  1993/01/15  03:33:47  mike
  18.  * patch3: safer double to int conversion
  19.  *
  20.  * Revision 5.4  1992/11/29  18:03:11  mike
  21.  * when printing integers, convert doubles to
  22.  * longs so output is the same on 16bit systems as 32bit systems
  23.  *
  24.  * Revision 5.3  1992/08/17  14:23:21  brennan
  25.  * patch2: After parsing, only bi_sprintf() uses string_buff.
  26.  *
  27.  * Revision 5.2  1992/02/24  10:52:16  brennan
  28.  * printf and sprintf() can now have more args than % conversions
  29.  * removed HAVE_PRINTF_HD -- it was too obscure
  30.  *
  31.  * Revision 5.1  91/12/05  07:56:22  brennan
  32.  * 1.1 pre-release
  33.  * 
  34. */
  35.  
  36. #include "mawk.h"
  37. #include "bi_vars.h"
  38. #include "bi_funct.h"
  39. #include "memory.h"
  40. #include "field.h"
  41. #include "scan.h"
  42. #include "files.h"
  43.  
  44. static void  PROTO( print_cell, (CELL *, FILE *) ) ;
  45. static STRING* PROTO( do_printf, (FILE *, char *, unsigned, CELL *) ) ;
  46. static void  PROTO( bad_conversion, (int, char *, char *)) ;
  47.  
  48.  
  49.  
  50. /* this can be moved and enlarged  by -W sprintf=num  */
  51. char *sprintf_buff = string_buff ;
  52. char *sprintf_limit = string_buff + SPRINTF_SZ ;
  53.  
  54. /* Once execute() starts the sprintf code is (belatedly) the only
  55.    code allowed to use string_buff  */
  56.  
  57. static void print_cell(p, fp)
  58.   register CELL *p ;
  59.   register FILE *fp ;
  60.   int len ;
  61.   
  62.   switch( p->type )
  63.   {
  64.     case C_NOINIT : break ;
  65.     case C_MBSTRN :
  66.     case C_STRING :
  67.     case C_STRNUM :
  68.         switch( len = string(p)->len )
  69.         {
  70.           case 0 :  break ;
  71.           case 1 :
  72.                     putc(string(p)->str[0],fp) ;
  73.                     break ;
  74.  
  75.           default :
  76.                     fwrite(string(p)->str, SIZE_T(1), SIZE_T(len), fp) ;
  77.         }
  78.         break ;
  79.  
  80.     case C_DOUBLE :
  81.     {
  82.       long ival = d_to_l(p->dval) ;
  83.  
  84.       /* integers print as "%[l]d" */ 
  85.       if ( (double) ival == p->dval )
  86.             fprintf(fp, INT_FMT, ival) ;
  87.       else
  88.           fprintf(fp, string(OFMT)->str, p->dval) ;
  89.     }
  90.         break ;
  91.  
  92.     default :
  93.         bozo("bad cell passed to print_cell") ;
  94.   }
  95. }
  96.  
  97. /* on entry to bi_print or bi_printf the stack is:
  98.  
  99.    sp[0] = an integer k
  100.        if ( k < 0 )  output is to a file with name in sp[-1]
  101.        { so open file and sp -= 2 }
  102.  
  103.    sp[0] = k >= 0 is the number of print args
  104.    sp[-k]   holds the first argument 
  105. */
  106.  
  107. CELL *bi_print(sp)
  108.   CELL *sp ; /* stack ptr passed in */
  109.   register CELL *p ;
  110.   register int k ;
  111.   FILE *fp ;
  112.  
  113.   k = sp->type ;
  114.   if ( k < 0 )
  115.   { 
  116.     /* k holds redirection */
  117.     if ( (--sp)->type < C_STRING ) cast1_to_s(sp) ;
  118.     fp = (FILE *) file_find( string(sp), k ) ;
  119.     free_STRING(string(sp)) ;
  120.     k = (--sp)->type ;
  121.     /* k now has number of arguments */
  122.   }
  123.   else  fp = stdout ;
  124.  
  125.   if ( k )  
  126.   { 
  127.     p = sp - k ; /* clear k variables off the stack */
  128.     sp = p - 1 ;
  129.     k-- ;
  130.  
  131.     while ( k > 0 ) 
  132.     { 
  133.       print_cell(p,fp) ; print_cell(OFS,fp) ;
  134.       cell_destroy(p) ; 
  135.       p++ ; k-- ;
  136.     }
  137.     
  138.     print_cell(p, fp) ;  cell_destroy(p) ;
  139.   }
  140.   else  
  141.   { /* print $0 */
  142.     sp-- ;
  143.     print_cell( &field[0], fp )  ;
  144.   }
  145.  
  146.   print_cell(ORS , fp) ;
  147.   return sp ;
  148. }
  149.   
  150. /*---------- types and defs for doing printf and sprintf----*/
  151. #define  PF_C        0   /* %c */
  152. #define  PF_S        1   /* %s */
  153. #define  PF_D        2   /* int conversion */
  154. #define  PF_F        3   /* float conversion */
  155.  
  156. /* for switch on number of '*' and type */
  157. #define  AST(num,type)  ((PF_F+1)*(num)+(type))
  158.  
  159. /* some picky ANSI compilers go berserk without this */
  160. #if HAVE_PROTOS
  161. typedef int (*PRINTER)(PTR,char *,...) ;
  162. #else
  163. typedef int (*PRINTER)() ;
  164. #endif
  165.  
  166. /*-------------------------------------------------------*/
  167.  
  168. static void bad_conversion(cnt, who, format)
  169.   int cnt ; 
  170.   char *who , *format ;
  171. {
  172.   rt_error( "improper conversion(number %d) in %s(\"%s\")", 
  173.          cnt, who, format ) ;
  174. }
  175.  
  176. /* the contents of format are preserved,
  177.    caller does CELL cleanup 
  178.  
  179.    This routine does both printf and sprintf (if fp==0)
  180. */
  181. static STRING *do_printf( fp, format, argcnt, cp)
  182.   FILE *fp ;
  183.   char *format ; 
  184.   CELL *cp ;  /* ptr to an array of arguments ( on the eval stack) */
  185.   unsigned argcnt ;  /* number of args on eval stack */
  186.   char  save ;
  187.   char *p ;
  188.   register char *q = format ;
  189.   register char *target ;
  190.   int l_flag , h_flag ;  /* seen %ld or %hd  */
  191.   int ast_cnt ;
  192.   int ast[2] ;
  193.   long lval ;  /* hold integer values */
  194.   int num_conversion = 0 ; /* for error messages */
  195.   char *who ; /*ditto*/
  196.   int pf_type ;  /* conversion type */
  197.   PRINTER printer ; /* pts at fprintf() or sprintf() */
  198.  
  199. #ifdef   SHORT_INTS
  200.   char xbuff[256] ; /* splice in l qualifier here */
  201. #endif
  202.  
  203.   if ( fp == (FILE *) 0 ) /* doing sprintf */
  204.   {
  205.     target = sprintf_buff ;
  206.     printer = (PRINTER) sprintf ;
  207.     who = "sprintf" ;
  208.   }
  209.   else /* doing printf */
  210.   {
  211.     target = (char *) fp ; /* will never change */
  212.     printer = (PRINTER) fprintf ;
  213.     who = "printf" ;
  214.   }
  215.  
  216.   while ( 1 )
  217.   { 
  218.     if ( fp )  /* printf */
  219.     {
  220.       while ( *q != '%' )
  221.     if ( *q == 0 )  return (STRING *) 0 ;
  222.     else
  223.     { putc(*q,fp) ; q++ ; }
  224.     }
  225.     else  /* sprintf */
  226.     {
  227.       while ( *q != '%' )
  228.     if ( *q == 0 )
  229.     {
  230.         if ( target > sprintf_limit ) /* damaged */
  231.         {
  232.           /* hope this works */
  233.           rt_overflow("sprintf buffer",
  234.               sprintf_limit - sprintf_buff) ;
  235.         }
  236.         else  /* really done */
  237.         {
  238.           STRING *retval ;
  239.           int len = target - sprintf_buff ;
  240.  
  241.           retval = new_STRING((char*)0, len) ;
  242.           (void)memcpy(retval->str, sprintf_buff, SIZE_T(len)) ;
  243.           return retval ;
  244.         }
  245.     }
  246.     else  *target++ = *q++ ;
  247.     }
  248.        
  249.  
  250.     /* *q == '%' */
  251.     num_conversion++ ;
  252.   
  253.     if ( * ++q == '%' )   /* %% */
  254.     {
  255.     if ( fp )   putc(*q, fp) ; 
  256.     else *target++ = *q ;
  257.  
  258.     q++ ; continue ;
  259.     }
  260.  
  261.     /* mark the '%' with p */
  262.     p = q-1 ;
  263.  
  264.     /* eat the flags */
  265.     while ( *q == '-' || *q == '+' || *q == ' ' ||
  266.             *q == '#' || *q == '0' )  q++ ;
  267.  
  268.     ast_cnt = 0 ;
  269.     if ( *q == '*' )
  270.     { 
  271.       if ( cp->type != C_DOUBLE ) cast1_to_d(cp) ;
  272.       ast[ast_cnt++] = d_to_i(cp++ ->dval) ;
  273.       argcnt-- ; q++ ;
  274.     }
  275.     else
  276.     while ( scan_code[*(unsigned char *)q] == SC_DIGIT )  q++ ;
  277.     /* width is done */
  278.  
  279.     if ( *q == '.' )  /* have precision */
  280.     { q++ ;
  281.       if ( *q == '*' )
  282.       {
  283.     if ( cp->type != C_DOUBLE ) cast1_to_d(cp) ;
  284.         ast[ast_cnt++] = d_to_i(cp++ ->dval) ;
  285.         argcnt-- ; q++ ;
  286.       }
  287.       else
  288.       while ( scan_code[*(unsigned char*)q] == SC_DIGIT ) q++ ; 
  289.     }
  290.  
  291.     if ( argcnt <= 0 )  
  292.         rt_error("not enough arguments passed to %s(\"%s\")",
  293.           who, format) ;
  294.  
  295.     l_flag = h_flag = 0 ;
  296.  
  297.     if ( *q == 'l' ) { q++ ; l_flag = 1 ; }
  298.     else
  299.     if ( *q == 'h' ) { q++ ; h_flag = 1 ; }
  300.  
  301.     switch( *q++ )
  302.     {
  303.       case 's' :
  304.             if ( l_flag + h_flag ) 
  305.         bad_conversion(num_conversion,who,format) ;
  306.             if ( cp->type < C_STRING ) cast1_to_s(cp) ;
  307.             pf_type = PF_S ;
  308.             break ;
  309.  
  310.       case 'c' :
  311.             if ( l_flag + h_flag )
  312.         bad_conversion(num_conversion,who,format) ;
  313.  
  314.         switch( cp->type )
  315.         {
  316.           case C_NOINIT :
  317.             lval = 0 ;
  318.             break ;
  319.  
  320.           case C_STRNUM :
  321.           case C_DOUBLE :
  322.             lval = (long) d_to_i(cp->dval) ;
  323.             break ;
  324.  
  325.           case  C_STRING :
  326.             lval = string(cp)->str[0] ;
  327.             break ;
  328.  
  329.           case  C_MBSTRN :
  330.             check_strnum(cp) ;
  331.             lval = cp->type == C_STRING ?
  332.             string(cp)->str[0] : (long) d_to_i(cp->dval) ;
  333.             break ;
  334.           
  335.           default :
  336.             bozo("printf %c") ;
  337.         }
  338.  
  339.             pf_type = PF_C ;
  340.         break ;
  341.  
  342.       case 'd' :
  343.       case 'o' :
  344.       case 'x' :
  345.       case 'X' :
  346.       case 'i' :
  347.       case 'u' :
  348.             if ( cp->type != C_DOUBLE ) cast1_to_d(cp) ;
  349.         if ( cp->dval > MAX__LONG ) lval = MAX__LONG ;
  350.         else
  351.         if ( cp->dval > -MAX__LONG ) lval = (long) cp->dval ;
  352.         else lval = -MAX__LONG ;
  353.  
  354.             pf_type = PF_D ;
  355.             break ;
  356.     
  357.       case 'e' :
  358.       case 'g' :
  359.       case 'f' :
  360.       case 'E' :
  361.       case 'G' :
  362.             if ( h_flag + l_flag )
  363.         bad_conversion(num_conversion,who,format) ;
  364.             if ( cp->type != C_DOUBLE ) cast1_to_d(cp) ;
  365.             pf_type = PF_F ;
  366.             break ;
  367.  
  368.       default : bad_conversion(num_conversion,who,format) ;
  369.     }
  370.  
  371.     save = *q ;
  372.     *q = 0 ;
  373.  
  374. #ifdef  SHORT_INTS
  375.     if ( pf_type == PF_D )
  376.     {
  377.       /* need to splice in long modifier */
  378.       strcpy(xbuff, p) ;
  379.  
  380.       if ( l_flag ) /* do nothing */ ;
  381.       else
  382.       {
  383.     int k = q - p ;
  384.  
  385.     if ( h_flag )
  386.     {
  387.       lval = (short) lval ;
  388.       /* replace the 'h' with 'l' (really!) */
  389.       xbuff[k-2] = 'l' ;
  390.       if ( xbuff[k-1] != 'd' && xbuff[k-1] != 'i' ) lval &= 0xffff ;
  391.     }
  392.     else
  393.     {
  394.       /* the usual case */
  395.       xbuff[k] = xbuff[k-1] ;
  396.       xbuff[k-1] = 'l' ;
  397.       xbuff[k+1] = 0 ;
  398.     }
  399.       }
  400.     }
  401. #endif
  402.  
  403.     /* ready to call printf() */
  404.     switch( AST(ast_cnt, pf_type ) )
  405.     {
  406.       case AST(0, PF_C )  :
  407.             (*printer)((PTR) target, p, (int) lval) ;
  408.             break ;
  409.  
  410.       case AST(1, PF_C ) :
  411.             (*printer)((PTR) target, p, ast[0], (int) lval) ;
  412.             break ;
  413.  
  414.       case AST(2, PF_C ) :
  415.             (*printer)((PTR) target, p, ast[0], ast[1], (int)lval) ;
  416.             break ;
  417.  
  418.       case AST(0, PF_S) :
  419.             (*printer)((PTR) target, p, string(cp)->str) ;
  420.             break ;
  421.  
  422.       case AST(1, PF_S) :
  423.             (*printer)((PTR) target, p, ast[0],string(cp)->str) ;
  424.             break ;
  425.  
  426.       case AST(2, PF_S) :
  427.             (*printer)((PTR) target,p,ast[0],ast[1],string(cp)->str) ;
  428.             break ;
  429.  
  430. #ifdef  SHORT_INTS
  431. #define    FMT    xbuff     /* format in xbuff */
  432. #else
  433. #define FMT     p         /* p -> format */
  434. #endif
  435.       case AST(0, PF_D) :
  436.             (*printer)((PTR) target, FMT, lval) ;
  437.             break ;
  438.  
  439.       case AST(1, PF_D) :
  440.             (*printer)((PTR) target, FMT, ast[0], lval) ;
  441.             break ;
  442.  
  443.       case AST(2, PF_D) :
  444.             (*printer)((PTR) target, FMT, ast[0], ast[1], lval) ;
  445.             break ;
  446.  
  447. #undef  FMT
  448.  
  449.  
  450.       case AST(0, PF_F) :
  451.             (*printer)((PTR) target, p,  cp->dval) ;
  452.             break ;
  453.  
  454.       case AST(1, PF_F) :
  455.             (*printer)((PTR) target, p, ast[0],  cp->dval) ;
  456.             break ;
  457.  
  458.       case AST(2, PF_F) :
  459.             (*printer)((PTR) target, p, ast[0], ast[1],  cp->dval) ;
  460.             break ;
  461.     }
  462.     if ( fp == (FILE *) 0 ) while ( *target ) target++ ;
  463.     *q = save ; argcnt-- ; cp++ ;
  464.   }
  465. }
  466.  
  467. CELL *bi_printf(sp)
  468.   register CELL *sp ;
  469. { register int k ;
  470.   register CELL *p ;
  471.   FILE *fp ;
  472.  
  473.   k = sp->type ;
  474.   if ( k  < 0 )
  475.   { 
  476.     /* k has redirection */
  477.     if ( (--sp)->type < C_STRING ) cast1_to_s(sp) ;
  478.     fp = (FILE *) file_find( string(sp), k ) ;
  479.     free_STRING(string(sp)) ;
  480.     k = (--sp)->type ;
  481.     /* k is now number of args including format */
  482.   }
  483.   else  fp = stdout ;
  484.  
  485.   sp -= k ; /* sp points at the format string */
  486.   k-- ;
  487.  
  488.   if ( sp->type < C_STRING )  cast1_to_s(sp) ;
  489.   do_printf(fp, string(sp)->str, k, sp+1) ;
  490.   free_STRING(string(sp)) ;
  491.  
  492.   /* cleanup arguments on eval stack */
  493.   for ( p = sp+1 ; k ; k--, p++ )  cell_destroy(p) ;
  494.   return --sp ;
  495. }
  496.  
  497. CELL *bi_sprintf(sp)
  498.   CELL *sp ;
  499. { CELL *p ;
  500.   int argcnt = sp->type ;
  501.   STRING *sval ;
  502.  
  503.   sp -= argcnt ; /* sp points at the format string */
  504.   argcnt-- ;
  505.  
  506.   if ( sp->type != C_STRING )  cast1_to_s(sp) ;
  507.   sval = do_printf((FILE *)0, string(sp)->str, argcnt, sp+1) ;
  508.   free_STRING(string(sp)) ;
  509.   sp->ptr = (PTR) sval ;
  510.  
  511.   /* cleanup */
  512.   for (p = sp+1 ; argcnt ; argcnt--, p++ )  cell_destroy(p) ;
  513.  
  514.   return sp ;
  515. }
  516.  
  517.  
  518.