mirror of
https://github.com/SEPPDROID/DR-DOS-OpenDOS.git
synced 2025-10-25 01:14:23 +00:00
Upload
This commit is contained in:
560
COMMAND/PRINTF.C
Normal file
560
COMMAND/PRINTF.C
Normal file
@@ -0,0 +1,560 @@
|
||||
/*
|
||||
; File : $Workfile: PRINTF.C$
|
||||
;
|
||||
; Description :
|
||||
;
|
||||
; Original Author : DIGITAL RESEARCH
|
||||
;
|
||||
; Last Edited By : $CALDERA$
|
||||
;
|
||||
;-----------------------------------------------------------------------;
|
||||
; Copyright Work of Caldera, Inc. All Rights Reserved.
|
||||
;
|
||||
; THIS WORK IS A COPYRIGHT WORK AND CONTAINS CONFIDENTIAL,
|
||||
; PROPRIETARY AND TRADE SECRET INFORMATION OF CALDERA, INC.
|
||||
; ACCESS TO THIS WORK IS RESTRICTED TO (I) CALDERA, INC. EMPLOYEES
|
||||
; WHO HAVE A NEED TO KNOW TO PERFORM TASKS WITHIN THE SCOPE OF
|
||||
; THEIR ASSIGNMENTS AND (II) ENTITIES OTHER THAN CALDERA, INC. WHO
|
||||
; HAVE ACCEPTED THE CALDERA OPENDOS SOURCE LICENSE OR OTHER CALDERA LICENSE
|
||||
; AGREEMENTS. EXCEPT UNDER THE EXPRESS TERMS OF THE CALDERA LICENSE
|
||||
; AGREEMENT NO PART OF THIS WORK MAY BE USED, PRACTICED, PERFORMED,
|
||||
; COPIED, DISTRIBUTED, REVISED, MODIFIED, TRANSLATED, ABRIDGED,
|
||||
; CONDENSED, EXPANDED, COLLECTED, COMPILED, LINKED, RECAST,
|
||||
; TRANSFORMED OR ADAPTED WITHOUT THE PRIOR WRITTEN CONSENT OF
|
||||
; CALDERA, INC. ANY USE OR EXPLOITATION OF THIS WORK WITHOUT
|
||||
; AUTHORIZATION COULD SUBJECT THE PERPETRATOR TO CRIMINAL AND
|
||||
; CIVIL LIABILITY.
|
||||
;-----------------------------------------------------------------------;
|
||||
;
|
||||
; *** Current Edit History ***
|
||||
; *** End of Current Edit History ***
|
||||
;
|
||||
; $Log$
|
||||
;
|
||||
; ENDLOG
|
||||
*/
|
||||
|
||||
/*
|
||||
* 26 Apr 88 Modify the Long conversion routine to display all 10
|
||||
* digits of a 32 bit integer when displayed in decimal
|
||||
* 27 May 88 Added string undefs.
|
||||
* 1? Jun 88 Support for CODE relative messages using the FARPTR routine.
|
||||
* 05 Jun 89 Add EPRINTF routine to display messages on STDERR
|
||||
* 30 Oct 89 dispense with digits & uc_digits in resident portion
|
||||
* 8 Nov 89 Replaced ASCII calculation with to_dec(), etc. as used
|
||||
* in APPALIB printf module. Much faster (eg dir /l 10% faster).
|
||||
* 8 Jan 90 Added parameter order indexing option.
|
||||
* 6-Mar-90 Watcom C v 7.0
|
||||
* 26-Mar-90 Make _printf CDECL again, otherwise arg processing screws up
|
||||
* 23-May-90 increase printf buffers from 128 to 130
|
||||
* 02-Dec-90 Re-work, to flush buffer on \n to allow large input strings
|
||||
* 28-May-91 local buffer is now on the stack instead of static. Reduces
|
||||
* resident size by 128 bytes.
|
||||
* 29-Jul-91 Buffer is now a far one, so output redirection to a file works
|
||||
* on a NOVELL drive when we are in seg FFFF.
|
||||
*/
|
||||
|
||||
#include "defines.h"
|
||||
#include <string.h>
|
||||
|
||||
#if defined(MWC) && defined(strlen)
|
||||
#undef strcmp /* These are defined as macros in string.h */
|
||||
#undef strcpy /* which are expaneded in line under */
|
||||
#undef strlen /* Metaware C. These undefs avoid this. */
|
||||
#endif
|
||||
|
||||
#include <portab.h>
|
||||
#include "command.h"
|
||||
#include "dosif.h"
|
||||
#include "global.h"
|
||||
|
||||
#define PRINTF -1
|
||||
#define EPRINTF -2
|
||||
#define SPRINTF -3
|
||||
|
||||
EXTERN VOID c_write (BYTE *, WORD);
|
||||
EXTERN BYTE FAR * CDECL farptr (BYTE *);
|
||||
EXTERN BOOLEAN isdigit (BYTE);
|
||||
EXTERN BOOLEAN err_flag;
|
||||
|
||||
/* forward references */
|
||||
MLOCAL UWORD CDECL _printf (BYTE *, UWORD *, UWORD);
|
||||
MLOCAL VOID arg_ptrs (BYTE FAR *, UWORD *, UWORD **);
|
||||
MLOCAL BYTE FAR * arg_siz (BYTE FAR *, UBYTE *);
|
||||
MLOCAL BYTE FAR * arg_num (BYTE FAR *, UWORD *);
|
||||
MLOCAL BYTE * to_hex (ULONG, BYTE *, BYTE);
|
||||
MLOCAL BYTE * to_dec (ULONG, BYTE *);
|
||||
MLOCAL BYTE * to_udec (ULONG, BYTE *);
|
||||
|
||||
#define UPPER_CASE ('A'-10)
|
||||
#define LOWER_CASE ('a'-10)
|
||||
|
||||
#define MAX_ARG_NUM 10 /* max args with order indxs */
|
||||
|
||||
MLOCAL BYTE FAR *buff = NULLPTR;
|
||||
|
||||
/*GLOBAL BYTE str[130];*/
|
||||
MLOCAL BYTE FAR *str;
|
||||
|
||||
GLOBAL WORD CDECL printf(fmt,args)
|
||||
BYTE *fmt;
|
||||
UWORD args;
|
||||
{
|
||||
UWORD totlen,len;
|
||||
/*BYTE local_buff[130];*/
|
||||
UWORD bufsize;
|
||||
|
||||
/*str = (BYTE FAR *) local_buff;*/
|
||||
str = gp_far_buff;
|
||||
|
||||
buff = str; /* use local buffer for printing */
|
||||
totlen = _printf (fmt,&args,PRINTF); /* build up output string */
|
||||
len=(UWORD) buff - (UWORD) str;
|
||||
if(len) /* if anything in the buffer */
|
||||
far_write(err_flag ? STDERR:STDOUT, str, len);
|
||||
/* then flush it */
|
||||
|
||||
return totlen+len; /* Return the String Length */
|
||||
|
||||
}
|
||||
|
||||
GLOBAL WORD CDECL eprintf(fmt,args)
|
||||
BYTE *fmt;
|
||||
UWORD args;
|
||||
{
|
||||
UWORD totlen, len;
|
||||
BYTE local_buff[130];
|
||||
|
||||
str = (BYTE FAR *) local_buff;
|
||||
|
||||
buff = str; /* use local buffer for printing */
|
||||
err_flag = TRUE;
|
||||
totlen = _printf (fmt,&args,EPRINTF); /* build up output string */
|
||||
len = buff-str;
|
||||
if(len) { /* if anything in the buffer */
|
||||
far_write(STDERR,str,len);
|
||||
}
|
||||
err_flag = FALSE;
|
||||
|
||||
return totlen+len; /* Return the String Length */
|
||||
|
||||
}
|
||||
|
||||
GLOBAL WORD CDECL fprintf(handle, fmt, args)
|
||||
UWORD handle;
|
||||
BYTE *fmt;
|
||||
UWORD args;
|
||||
{
|
||||
UWORD totlen,len;
|
||||
UWORD bufsize;
|
||||
|
||||
str = gp_far_buff;
|
||||
|
||||
buff = str; /* use local buffer for printing */
|
||||
totlen =_printf (fmt,&args,handle); /* build up output string */
|
||||
len = (UWORD) buff - (UWORD) str;
|
||||
if(len) /* if anything in the buffer */
|
||||
far_write(handle, str, len); /* then flush it */
|
||||
|
||||
return totlen+len; /* Return the String Length */
|
||||
|
||||
}
|
||||
|
||||
GLOBAL WORD CDECL sprintf(strg, fmt, args)
|
||||
BYTE *strg;
|
||||
BYTE *fmt;
|
||||
UWORD args;
|
||||
{
|
||||
buff = (BYTE FAR *) strg; /* Point buffer at String */
|
||||
return _printf (fmt,&args,SPRINTF); /* Generate the String */
|
||||
}
|
||||
|
||||
MLOCAL UWORD CDECL _printf(fmt_near, args, type)
|
||||
BYTE *fmt_near;
|
||||
UWORD *args;
|
||||
UWORD type;
|
||||
{
|
||||
BYTE FAR *fmt;
|
||||
WORD rjust; /* if string/number is right justified */
|
||||
WORD maxwidth, width;
|
||||
BOOLEAN long_arg; /* true if next argument is long */
|
||||
ULONG value;
|
||||
UWORD uvalue;
|
||||
WORD i, k;
|
||||
BYTE FAR *cp;
|
||||
BYTE c, filler;
|
||||
BYTE s[40], *sp;
|
||||
LONG *lp;
|
||||
UWORD *arg_list[MAX_ARG_NUM];
|
||||
UWORD arg_idx;
|
||||
UWORD totlen=0;
|
||||
|
||||
fmt = farptr(fmt_near); /* get full address of format string */
|
||||
arg_ptrs(fmt, args, arg_list); /* init table of argument addresses */
|
||||
|
||||
while ((c = *fmt++) != 0) /* scan format string */
|
||||
{
|
||||
if (c == '%') { /* formatting code found */
|
||||
s[14] = 0;
|
||||
rjust = YES;
|
||||
filler = ' ';
|
||||
maxwidth = 0x7fff;
|
||||
|
||||
fmt = arg_num(fmt, &arg_idx); /* get argument index */
|
||||
if (arg_idx < MAX_ARG_NUM) { /* valid index? */
|
||||
fmt++; /* yes - skip '%' */
|
||||
args = arg_list[arg_idx]; /* lookup address of arg */
|
||||
}
|
||||
|
||||
if ((c = *fmt) == '-') { /* string is left justified */
|
||||
rjust = NO; /* ... not right justified */
|
||||
c = *fmt++; /* get the next character */
|
||||
}
|
||||
|
||||
if (c == '0') /* if leading zeroes desired */
|
||||
filler = '0'; /* use '0' instead of ' ' */
|
||||
|
||||
if (*fmt == '*') { /* if formatting width is parameter */
|
||||
/* then get it from parameters */
|
||||
width = (WORD)*args++;
|
||||
fmt++; /* skip the asterisk */
|
||||
c = *fmt++; /* get next character */
|
||||
}
|
||||
else /* get full width */
|
||||
for (width = 0; (c = *fmt++) >= '0' && c <= '9'; )
|
||||
width = width*10 + c - '0';
|
||||
|
||||
if (c == '.') { /* if decimal places specified */
|
||||
if (*fmt == '*') { /* if width is a parameter */
|
||||
maxwidth = (WORD)*args++;
|
||||
fmt++; /* skip the asterisk */
|
||||
c = *fmt++; /* get next character */
|
||||
}
|
||||
else /* get decimal places */
|
||||
for (maxwidth = 0; (c = *fmt++) >= '0' && c <= '9' ;)
|
||||
maxwidth = maxwidth*10 + c - '0';
|
||||
}
|
||||
|
||||
/* "%ld", "%lu", "lx" specified */
|
||||
long_arg = (c == 'l'); /* is the argument supplied long? */
|
||||
if (long_arg) /* if long argument */
|
||||
c = *fmt++; /* then skip the 'l' character */
|
||||
|
||||
switch (c) {
|
||||
case 'd': /* signed argument */
|
||||
if (!long_arg)
|
||||
value = (WORD) *args++;
|
||||
else {
|
||||
lp = (LONG *) args;
|
||||
value = *lp++;
|
||||
args = (UWORD *) lp;
|
||||
}
|
||||
break;
|
||||
|
||||
case 'u': /* unsigned argument */
|
||||
case 'x':
|
||||
case 'X':
|
||||
if (!long_arg)
|
||||
value = (UWORD) *args++;
|
||||
else {
|
||||
lp = (LONG *) args;
|
||||
value = (ULONG) *lp++;
|
||||
args = (UWORD *) lp;
|
||||
}
|
||||
break;
|
||||
|
||||
default: /* "%s", "%c" */
|
||||
uvalue = (UWORD) *args++; /* get string address of char */
|
||||
}
|
||||
|
||||
|
||||
switch (c) { /* now convert to ASCII */
|
||||
case 'd': /* signed decimal */
|
||||
sp = to_dec(value, s+14);
|
||||
break;
|
||||
|
||||
case 'u': /* unsigned decimal */
|
||||
sp = to_udec(value, s+14);
|
||||
break;
|
||||
|
||||
case 'x': /* unsigned hexadecimal, lower case */
|
||||
sp = to_hex(value, s+14, LOWER_CASE);
|
||||
break;
|
||||
|
||||
case 'X': /* unsigned hexadecimal, upper case */
|
||||
sp = to_hex(value, s+14, UPPER_CASE);
|
||||
break;
|
||||
|
||||
case 's': /* string -- could be far */
|
||||
cp = farptr((BYTE *)uvalue);
|
||||
for (i=0; cp[i] != '\0'; i++)
|
||||
;
|
||||
goto havelen;
|
||||
|
||||
case 'c':
|
||||
c = uvalue;
|
||||
/* drop into "default:" */
|
||||
default: /* normal characters */
|
||||
sp = s+13;
|
||||
*sp = c;
|
||||
break;
|
||||
}
|
||||
|
||||
i = (s+14) - sp; /* work out length of string */
|
||||
cp = (BYTE FAR *) sp; /* convert to FAR pointer */
|
||||
|
||||
havelen:
|
||||
if (i > maxwidth)
|
||||
i = maxwidth;
|
||||
|
||||
if (rjust) {
|
||||
while (width-- > i)
|
||||
*buff++ = filler;
|
||||
}
|
||||
|
||||
for (k = 0; *cp && k < maxwidth; ++k) {
|
||||
if (*cp == '\n')
|
||||
*buff++ = '\r';
|
||||
*buff++ = *cp++;
|
||||
}
|
||||
|
||||
if (!rjust) { /* if right justified */
|
||||
while (width-- > i)
|
||||
*buff++ = ' ';
|
||||
}
|
||||
}
|
||||
else if (c == '\n') { /* expand newline to CR,LF then flush the buffer */
|
||||
*buff++ = '\r';
|
||||
*buff++ = '\n';
|
||||
if (type!=SPRINTF) {
|
||||
/* Flush the buffer */
|
||||
*buff = '\0'; /* terminate the string */
|
||||
switch (type) {
|
||||
case PRINTF:
|
||||
far_write(err_flag ? STDERR:STDOUT,str,
|
||||
(UWORD) buff - (UWORD) str);
|
||||
break;
|
||||
case EPRINTF:
|
||||
far_write(STDERR, str, buff-str);
|
||||
break;
|
||||
default:
|
||||
far_write(type, str, buff-str);
|
||||
break;
|
||||
} /*ENDSWITCH*/
|
||||
totlen+=buff-str;
|
||||
buff=str;
|
||||
}
|
||||
}
|
||||
else
|
||||
*buff++ = c;
|
||||
}
|
||||
*buff = '\0'; /* terminate the string */
|
||||
return totlen+=buff-str;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* Initialise the table of pointers to all arguments (ptr_list).
|
||||
The ptr_list table will not be filled in unless the format
|
||||
string (fmt) contains parameter order indexes. */
|
||||
|
||||
MLOCAL VOID arg_ptrs(fmt, args, ptr_list)
|
||||
REG BYTE FAR *fmt; /* ASCIIZ format string */
|
||||
UWORD *args; /* pointer to first argument */
|
||||
UWORD *ptr_list[]; /* list of pointers to all arguments */
|
||||
{
|
||||
UWORD arg_cnt; /* running count of parameters found */
|
||||
UWORD num;
|
||||
UBYTE size_list[MAX_ARG_NUM]; /* number bytes in each argument */
|
||||
UWORD i;
|
||||
|
||||
|
||||
/* Read through format string to determine the size of each argument. */
|
||||
for (arg_cnt = 0; ; )
|
||||
{
|
||||
while (*fmt && *fmt != '%') /* find the next parameter */
|
||||
fmt++;
|
||||
|
||||
if (!*fmt) /* patameter found? */
|
||||
break; /* no - exit loop */
|
||||
fmt++; /* skip '%' */
|
||||
|
||||
if (*fmt == '%') /* "%%" escape for percent? */
|
||||
{
|
||||
fmt++; /* yes - skip second '%' */
|
||||
continue; /* and look for next parameter */
|
||||
}
|
||||
|
||||
fmt = arg_num(fmt, &num); /* get this argument's index */
|
||||
if (num >= MAX_ARG_NUM) /* arg index present and valid? */
|
||||
break; /* no - go no further */
|
||||
|
||||
/* record this argument's size */
|
||||
fmt = arg_siz(fmt, &size_list[num]);
|
||||
arg_cnt++; /* one more argument found */
|
||||
}
|
||||
|
||||
|
||||
/* Loop once for each argument found in format string, filling in
|
||||
the offset for that argument in the size_list table. */
|
||||
for (i = 0; i < arg_cnt; i++)
|
||||
{
|
||||
ptr_list[i] = args; /* record the address of arg */
|
||||
args += (UWORD)(size_list[i]); /* update ptr by size of arg */
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* Determine the size in bytes (siz) of the argument that corresponds to the
|
||||
given format string (fmt). Return a pointer to the character following
|
||||
the last in the format string. For example...
|
||||
|
||||
fmt siz
|
||||
%d 2
|
||||
%ld 4
|
||||
%*d 4
|
||||
*/
|
||||
|
||||
MLOCAL BYTE FAR * arg_siz(fmt, siz)
|
||||
REG BYTE FAR *fmt; /* printf argument format string */
|
||||
UBYTE *siz; /* returned argument size, in bytes */
|
||||
{
|
||||
|
||||
*siz = 0; /* argument size not yet known */
|
||||
|
||||
if (*fmt != '%')
|
||||
return fmt; /* format string must begin with '%' */
|
||||
fmt++; /* skip '%' */
|
||||
|
||||
if (*fmt == '#') /* ignore various formatting ctrls */
|
||||
fmt++;
|
||||
if (*fmt == '-')
|
||||
fmt++;
|
||||
if (*fmt == '0')
|
||||
fmt++;
|
||||
|
||||
if (*fmt == '*')
|
||||
{ /* width argument also on stack */
|
||||
*siz += sizeof(WORD); /* width argument is a WORD */
|
||||
fmt++;
|
||||
}
|
||||
else /* ignore any static width control */
|
||||
while (*fmt >= '0' && *fmt <= '9')
|
||||
fmt++;
|
||||
|
||||
if (*fmt == '.')
|
||||
{
|
||||
fmt++;
|
||||
if (*fmt == '*')
|
||||
{ /* 2nd width argument on stack */
|
||||
*siz += sizeof(WORD);
|
||||
fmt++;
|
||||
}
|
||||
else /* ignore any static width control */
|
||||
while (*fmt >= '0' && *fmt <= '9')
|
||||
fmt++;
|
||||
}
|
||||
|
||||
if (*fmt == 'l')
|
||||
{
|
||||
*siz += sizeof(LONG);
|
||||
fmt++;
|
||||
}
|
||||
else
|
||||
*siz += sizeof(WORD); /* assume sizeof(WORD)==sizeof(BYTE *) */
|
||||
|
||||
return ++fmt; /* skip final char: 'd', 's', etc. */
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* Determine the index number (num) of the argument given by the format
|
||||
string (fmt). If the format string does not have a valid index number
|
||||
num is set to MAX_ARG_NUM. Return a pointer to the character following
|
||||
the last in the index number. For example...
|
||||
|
||||
fmt num returned pointer to...
|
||||
3%4d 3 '%'
|
||||
4d MAX_ARG_NUM '4'
|
||||
% MAX_ARG_NUM '%'
|
||||
*/
|
||||
|
||||
MLOCAL BYTE FAR * arg_num(fmt, num)
|
||||
BYTE FAR *fmt;
|
||||
UWORD *num;
|
||||
{
|
||||
REG BYTE FAR *cp;
|
||||
REG UWORD n;
|
||||
|
||||
|
||||
*num = MAX_ARG_NUM; /* argument index not yet known */
|
||||
|
||||
cp = fmt;
|
||||
if (!isdigit(*cp)) /* at least one digit expected */
|
||||
return fmt;
|
||||
/* extract index number */
|
||||
for (n = 0; *cp >= '0' && *cp <= '9'; cp++)
|
||||
n = n * 10 + *cp - '0';
|
||||
|
||||
if (*cp != '%')
|
||||
return fmt; /* number must be terminated by '%' */
|
||||
|
||||
*num = n; /* record the index number */
|
||||
return cp; /* return pointer to last '%' */
|
||||
}
|
||||
|
||||
|
||||
|
||||
MLOCAL BYTE * to_hex(n, s, hex_base)
|
||||
ULONG n;
|
||||
BYTE *s;
|
||||
BYTE hex_base; /* 'a'-10 for lowercase, 'A'-10 uppercase */
|
||||
{
|
||||
REG UBYTE i;
|
||||
|
||||
do
|
||||
{
|
||||
i = (UBYTE)n & 0x0F;
|
||||
*--s = (i > 9) ? (hex_base + i) : ('0' + i);
|
||||
n >>= 4;
|
||||
}
|
||||
while (n != 0);
|
||||
|
||||
return s;
|
||||
}
|
||||
|
||||
|
||||
|
||||
MLOCAL BYTE * to_dec(n, s)
|
||||
ULONG n;
|
||||
BYTE *s;
|
||||
{
|
||||
if ((LONG)n < 0)
|
||||
{
|
||||
s = to_udec(0 - (LONG)n, s);
|
||||
*--s = '-'; /* preceed number with sign */
|
||||
return s;
|
||||
}
|
||||
else
|
||||
return to_udec(n, s);
|
||||
}
|
||||
|
||||
|
||||
|
||||
MLOCAL BYTE * to_udec(n, s)
|
||||
ULONG n;
|
||||
BYTE *s;
|
||||
{
|
||||
do
|
||||
{
|
||||
*--s = '0' + (n % 10);
|
||||
n /= 10;
|
||||
}
|
||||
while (n != 0);
|
||||
|
||||
return s;
|
||||
}
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user