/********************************************
copyright 1992, 1991. Michael D. Brennan
This is a source file for mawk, an implementation of
the AWK programming language.
Mawk is distributed without warranty under the terms of
the GNU General Public License, version 2, 1991.
********************************************/
* Revision 5.2 92/02/24 10:52:16 brennan
* printf and sprintf() can now have more args than % conversions
* removed HAVE_PRINTF_HD -- it was too obscure
* Revision 5.1 91/12/05 07:56:22 brennan
static void PROTO( print_cell
, (CELL
*, FILE *) ) ;
static STRING
* PROTO( do_printf
, (FILE *, char *, unsigned, CELL
*) ) ;
static void PROTO( bad_conversion
, (int, char *, char *)) ;
/* this can be moved and enlarged by -W sprintf=num */
char *sprintf_buff
= string_buff
;
char *sprintf_limit
= string_buff
+ SPRINTF_SZ
;
static void print_cell(p
, fp
)
switch( len
= string(p
)->len
)
putc(string(p
)->str
[0],fp
) ;
fwrite(string(p
)->str
, SIZE_T(1), SIZE_T(len
), fp
) ;
if ( (double)(len
= (int) p
->dval
) == p
->dval
)
fprintf(fp
, string(OFMT
)->str
, p
->dval
) ;
bozo("bad cell passed to print_cell") ;
/* on entry to bi_print or bi_printf the stack is:
if ( k < 0 ) output is to a file with name in sp[-1]
{ so open file and sp -= 2 }
sp[0] = k >= 0 is the number of print args
sp[-k] holds the first argument
CELL
*sp
; /* stack ptr passed in */
if ( (k
= sp
->type
) < 0 )
{ if ( (--sp
)->type
< C_STRING
) cast1_to_s(sp
) ;
fp
= (FILE *) file_find( string(sp
), k
) ;
free_STRING(string(sp
)) ;
{ p
= sp
- k
; /* clear k variables off the stack */
{ print_cell(p
,fp
) ; print_cell(OFS
,fp
) ;
cell_destroy(p
) ; p
++ ; }
print_cell(p
, fp
) ; cell_destroy(p
) ;
print_cell( &field
[0], fp
) ; }
/*---------- types and defs for doing printf and sprintf----*/
#define PF_D 2 /* int conversion */
#define PF_LD 3 /* long int */
#define PF_F 4 /* float conversion */
/* for switch on number of '*' and type */
#define AST(num,type) (5*(num)+(type))
/* some picky ANSI compilers go berserk without this */
typedef int (*PRINTER
)(PTR
,char *,...) ;
typedef int (*PRINTER
)() ;
/*-------------------------------------------------------*/
static void bad_conversion(cnt
, who
, format
)
rt_error( "improper conversion(number %d) in %s(\"%s\")",
/* the contents of format are preserved,
This routine does both printf and sprintf (if fp==0)
static STRING
*do_printf( fp
, format
, argcnt
, cp
)
CELL
*cp
; /* ptr to an array of arguments ( on the eval stack) */
unsigned argcnt
; /* number of args on eval stack */
register char *q
= format
;
int l_flag
, h_flag
; /* seen %ld or %hd */
int ival
; /* caters to MSDOS */
int num_conversion
= 0 ; /* for error messages */
int pf_type
; /* conversion type */
PRINTER printer
; /* pts at fprintf() or sprintf() */
if ( fp
== (FILE *) 0 ) /* doing sprintf */
printer
= (PRINTER
) sprintf
;
target
= (char *) fp
; /* will never change */
printer
= (PRINTER
) fprintf
;
if ( *q
== 0 ) return (STRING
*) 0 ;
if ( target
> sprintf_limit
) /* damaged */
rt_overflow("sprintf buffer",
sprintf_limit
- sprintf_buff
) ;
int len
= target
- sprintf_buff
;
retval
= new_STRING((char*)0, len
) ;
(void)memcpy(retval
->str
, sprintf_buff
, SIZE_T(len
)) ;
if ( * ++q
== '%' ) /* %% */
/* mark the '%' with p */
while ( *q
== '-' || *q
== '+' || *q
== ' ' ||
*q
== '#' || *q
== '0' ) q
++ ;
if ( cp
->type
!= C_DOUBLE
) cast1_to_d(cp
) ;
ast
[ast_cnt
++] = (int) cp
++ ->dval
;
while ( scan_code
[*(unsigned char *)q
] == SC_DIGIT
) q
++ ;
if ( *q
== '.' ) /* have precision */
if ( cp
->type
!= C_DOUBLE
) cast1_to_d(cp
) ;
ast
[ast_cnt
++] = (int) cp
++ ->dval
;
while ( scan_code
[*(unsigned char*)q
] == SC_DIGIT
) q
++ ;
rt_error("not enough arguments passed to %s(\"%s\")",
if ( *q
== 'l' ) { q
++ ; l_flag
= 1 ; }
if ( *q
== 'h' ) { q
++ ; h_flag
= 1 ; }
bad_conversion(num_conversion
,who
,format
) ;
if ( cp
->type
< C_STRING
) cast1_to_s(cp
) ;
bad_conversion(num_conversion
,who
,format
) ;
ival
= string(cp
)->str
[0] ;
ival
= cp
->type
== C_STRING
?
string(cp
)->str
[0] : (int) cp
->dval
;
if ( cp
->type
!= C_DOUBLE
) cast1_to_d(cp
) ;
if ( h_flag
) lval
&= 0xffff ;
pf_type
= l_flag
? PF_LD
: PF_D
;
bad_conversion(num_conversion
,who
,format
) ;
if ( cp
->type
!= C_DOUBLE
) cast1_to_d(cp
) ;
default : bad_conversion(num_conversion
,who
,format
) ;
/* ready to call printf() */
switch( AST(ast_cnt
, pf_type
) )
(*printer
)((PTR
) target
, p
, ival
) ;
(*printer
)((PTR
) target
, p
, ast
[0], ival
) ;
(*printer
)((PTR
) target
, p
, ast
[0], ast
[1], ival
) ;
(*printer
)((PTR
) target
, p
, string(cp
)->str
) ;
(*printer
)((PTR
) target
, p
, ast
[0],string(cp
)->str
) ;
(*printer
)((PTR
) target
, p
, ast
[0], ast
[1], string(cp
)->str
) ;
(*printer
)((PTR
) target
, p
, (int) lval
) ;
(*printer
)((PTR
) target
, p
, ast
[0], (int) lval
) ;
(*printer
)((PTR
) target
, p
, ast
[0], ast
[1], (int) lval
) ;
(*printer
)((PTR
) target
, p
, lval
) ;
(*printer
)((PTR
) target
, p
, ast
[0], lval
) ;
(*printer
)((PTR
) target
, p
, ast
[0], ast
[1], lval
) ;
(*printer
)((PTR
) target
, p
, cp
->dval
) ;
(*printer
)((PTR
) target
, p
, ast
[0], cp
->dval
) ;
(*printer
)((PTR
) target
, p
, ast
[0], ast
[1], cp
->dval
) ;
if ( fp
== (FILE *) 0 ) while ( *target
) target
++ ;
*q
= save
; argcnt
-- ; cp
++ ;
if ( (k
= sp
->type
) < 0 )
{ if ( (--sp
)->type
< C_STRING
) cast1_to_s(sp
) ;
fp
= (FILE *) file_find( string(sp
), k
) ;
free_STRING(string(sp
)) ;
sp
-= k
-- ; /* sp points at the format string */
if ( sp
->type
< C_STRING
) cast1_to_s(sp
) ;
do_printf(fp
, string(sp
)->str
, k
, sp
+1) ;
free_STRING(string(sp
)) ;
for ( p
= sp
+1 ; k
-- ; p
++ ) cell_destroy(p
) ;
sp
-= argcnt
-- ; /* sp points at the format string */
if ( sp
->type
!= C_STRING
) cast1_to_s(sp
) ;
sval
= do_printf((FILE *)0, string(sp
)->str
, argcnt
, sp
+1) ;
free_STRING(string(sp
)) ;
for ( p
= sp
+1 ; argcnt
-- ; p
++ ) cell_destroy(p
) ;