home *** CD-ROM | disk | FTP | other *** search
/ Acorn User 11 / AUCD11B.iso / LANGUAGES / WraithSet / AwkStuff / MawkSrc / c / print < prev    next >
Text File  |  1996-09-17  |  13KB  |  581 lines

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