diff options
author | Joseph Hunkeler <jhunkeler@gmail.com> | 2015-07-08 20:46:52 -0400 |
---|---|---|
committer | Joseph Hunkeler <jhunkeler@gmail.com> | 2015-07-08 20:46:52 -0400 |
commit | fa080de7afc95aa1c19a6e6fc0e0708ced2eadc4 (patch) | |
tree | bdda434976bc09c864f2e4fa6f16ba1952b1e555 /sys/libc/printf.c | |
download | iraf-linux-fa080de7afc95aa1c19a6e6fc0e0708ced2eadc4.tar.gz |
Initial commit
Diffstat (limited to 'sys/libc/printf.c')
-rw-r--r-- | sys/libc/printf.c | 245 |
1 files changed, 245 insertions, 0 deletions
diff --git a/sys/libc/printf.c b/sys/libc/printf.c new file mode 100644 index 00000000..03b155bb --- /dev/null +++ b/sys/libc/printf.c @@ -0,0 +1,245 @@ +/* Copyright(c) 1986 Association of Universities for Research in Astronomy Inc. +*/ + +#define import_spp +#define import_libc +#define import_xnames +#define import_stdio +#define import_ctype +#define import_stdarg +#include <iraf.h> + + +/* PRINTF -- Emulation of the UNIX printf facilities with the IRAF FMTIO +** interface as the backend. All features of the UNIX printf are supported +** without modification. Additional format codes are supported in conformance +** with the IRAF printf, e.g., hms format, variable radix, tabstops, etc., +** but these are upward compatible with standard UNIX usage. +*/ + +#define SZ_FMTSPEC 25 /* max size single format spec */ +#define SZ_OBUF SZ_COMMAND /* sz intermediate buffer */ +#define MAX_PREC 4 /* max "*" deferred args */ +#define NOARG (-1) /* % spec with no data value */ + + +/* PRINTF -- Formatted print to the standard output. +*/ +void +printf (char *format, ...) +{ + va_list argp; + void u_doprnt(); + + va_start (argp, format); + u_doprnt (format, &argp, stdout); + va_end (argp); +} + + +/* FPRINTF -- Formatted print to a file. +*/ +void +fprintf (FILE *fp, char *format, ...) +{ + va_list argp; + void u_doprnt(); + + va_start (argp, format); + u_doprnt (format, &argp, fp); + va_end (argp); +} + + +/* U_DOPRNT -- Process the format to the output file, taking arguments from +** the list pointed to by argp as % format specs are encountered in the input. +** The main point of this routine is to handle the variable number of arguments. +** The actual encoding is all handled by the IRAF FPRINF and PARG calls. +** N.B. we assume chars are stacked as ints, and floats are stacked as doubles. +*/ +void +u_doprnt ( + char *format, /* "%w.dC" etc. format spec */ + va_list *argp, /* pointer to first value arg */ + FILE *fp /* output file */ +) +{ + register int ch; /* next format char reference */ + XCHAR formspec[SZ_FMTSPEC]; /* copy of single format spec */ + XCHAR *fsp; /* pointer into formspec */ + int done, dotseen; /* one when at end of a format */ + int varprec; /* runtime precision is used */ + int prec[MAX_PREC]; /* values of prec args */ + + void u_doarg (); + + + while ( (ch = *format++) ) { + if (ch == '%') { + fsp = formspec; + *fsp++ = ch; + varprec = 0; + dotseen = 0; + done = 0; + + while (!done) { + ch = *fsp++ = *format++; + + switch (ch) { + case EOS: + --format; + done++; + break; + + case 'l': + /* arg size modifier; ignored for now */ + fsp--; + break; + + case '*': + prec[varprec++] = va_arg ((*argp), int); + break; + + case '.': + dotseen++; + break; + + case 'r': /* nonstandard UNIX */ + if ((ch = *fsp++ = *format++) == '*') { + int radix; + int radchar; + + radix = va_arg ((*argp), int); + if (radix < 0) + radchar = 'A'; + else if (radix > 9) + radchar = radix - 10 + 'A'; + else + radchar = todigit (radix); + *(fsp-1) = radchar; + } else if (ch == EOS) { + --format; + break; + } + /* fall through */ + + case 'b': /* nonstandard UNIX */ + case 'c': + case 'd': + case 'o': + case 'x': + case 'u': + *fsp = EOS; + u_doarg (fp, formspec, &argp, prec, varprec, TY_INT); + done++; + break; + + case 'E': /* ANSI emulation */ + *(fsp-1) = 'e'; + goto rval; + case 'G': /* ANSI emulation */ + *(fsp-1) = 'g'; + goto rval; + + case 'z': /* nonstandard UNIX */ + case 'h': /* nonstandard UNIX */ + case 'H': /* nonstandard UNIX */ + case 'm': /* nonstandard UNIX */ + case 'M': /* nonstandard UNIX */ + case 'e': + case 'f': + case 'g': + /* If no precision was specified, default to 14 digits + * for %[efgz] and 3 digits for %[hm]. + */ +rval: if (!dotseen) { + *(fsp-1) = '.'; + if (ch == 'h' || ch == 'm' || + ch == 'H' || ch == 'M') { + *fsp++ = '3'; + } else { + *fsp++ = '1'; + *fsp++ = '4'; + } + *fsp++ = ch; + } + + *fsp = XEOS; + u_doarg (fp, formspec, &argp, prec, varprec, TY_DOUBLE); + done++; + break; + + case 's': + *fsp = EOS; + u_doarg (fp, formspec, &argp, prec, varprec, TY_CHAR); + done++; + break; + + case 't': /* nonstandard UNIX */ + case 'w': /* nonstandard UNIX */ + *fsp = EOS; + u_doarg (fp, formspec, &argp, prec, varprec, NOARG); + done++; + break; + + case '%': + putc (ch, fp); + done++; + break; + } + } + + } else + putc (ch, fp); + } +} + + +/* U_DOARG -- Encode a single argument acording to the simplified format +** specification given by formspec. This is the interface to the IRAF +** formatted output procedures. +*/ +void +u_doarg (fp, formspec, argp, prec, varprec, dtype) +FILE *fp; /* output file */ +XCHAR *formspec; /* format string */ +va_list **argp; /* pointer to data value */ +int prec[]; /* varprec args, if any */ +int varprec; /* number of varprec args */ +int dtype; /* datatype of data value */ +{ + register int p; + XCHAR sbuf[SZ_OBUF+1]; + XINT fd = fileno (fp); + XINT ival; + XDOUBLE dval; + char *cptr; + + + /* Pass format string and any variable precision arguments. + */ + FPRINTF (&fd, formspec); + for (p=0; p < varprec; p++) { + ival = prec[p]; + PARGI (&ival); + } + + /* Pass the data value to be encoded, bump argument pointer by the + * size of the data object. If there is no data value the case + * is a no-op. + */ + switch (dtype) { + case TY_INT: + ival = va_arg ((**argp), int); + PARGI (&ival); + break; + case TY_DOUBLE: + dval = va_arg ((**argp), double); + PARGD (&dval); + break; + case TY_CHAR: + cptr = va_arg ((**argp), char *); + PARGSTR (c_strupk (cptr, sbuf, SZ_OBUF)); + break; + } +} |