home *** CD-ROM | disk | FTP | other *** search
/ The World of Computer Software / World_Of_Computer_Software-02-387-Vol-3of3.iso / m / mawk11as.zip / PRINT.C < prev    next >
C/C++ Source or Header  |  1991-12-18  |  11KB  |  454 lines

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