2 * Shell file I/O routines
7 #include "ksh_limval.h"
11 /* flags to shf_emptybuf() */
12 #define EB_READSW 0x01 /* about to switch to reading */
13 #define EB_GROW 0x02 /* grow buffer if necessary (STRING+DYNAMIC) */
16 * Replacement stdio routines. Stdio is too flakey on too many machines
17 * to be useful when you have multiple processes using the same underlying
21 static int shf_fillbuf(struct shf
*);
22 static int shf_emptybuf(struct shf
*, int);
24 /* Open a file. First three args are for open(), last arg is flags for
25 * this package. Returns NULL if file could not be opened, or if a dup
29 shf_open(const char *name
, int oflags
, int mode
, int sflags
)
32 int bsize
= sflags
& SHF_UNBUF
? (sflags
& SHF_RD
? 1 : 0) : SHF_BSIZE
;
35 /* Done before open so if alloca fails, fd won't be lost. */
36 shf
= (struct shf
*) alloc(sizeof(struct shf
) + bsize
, ATEMP
);
38 shf
->buf
= (unsigned char *) &shf
[1];
40 shf
->flags
= SHF_ALLOCS
;
41 /* Rest filled in by reopen. */
43 fd
= open(name
, oflags
, mode
);
45 afree(shf
, shf
->areap
);
48 if ((sflags
& SHF_MAPHI
) && fd
< FDBASE
) {
51 nfd
= fcntl(fd
, F_DUPFD
, FDBASE
);
54 afree(shf
, shf
->areap
);
59 sflags
&= ~SHF_ACCMODE
;
60 sflags
|= (oflags
& O_ACCMODE
) == O_RDONLY
? SHF_RD
:
61 ((oflags
& O_ACCMODE
) == O_WRONLY
? SHF_WR
:
64 return shf_reopen(fd
, sflags
, shf
);
67 /* Set up the shf structure for a file descriptor. Doesn't fail. */
69 shf_fdopen(int fd
, int sflags
, struct shf
*shf
)
71 int bsize
= sflags
& SHF_UNBUF
? (sflags
& SHF_RD
? 1 : 0) : SHF_BSIZE
;
73 /* use fcntl() to figure out correct read/write flags */
74 if (sflags
& SHF_GETFL
) {
75 int flags
= fcntl(fd
, F_GETFL
, 0);
78 /* will get an error on first read/write */
81 switch (flags
& O_ACCMODE
) {
94 if (!(sflags
& (SHF_RD
| SHF_WR
)))
95 internal_errorf(1, "shf_fdopen: missing read/write");
99 shf
->buf
= (unsigned char *) alloc(bsize
, ATEMP
);
100 sflags
|= SHF_ALLOCB
;
102 shf
->buf
= (unsigned char *) 0;
104 shf
= (struct shf
*) alloc(sizeof(struct shf
) + bsize
, ATEMP
);
105 shf
->buf
= (unsigned char *) &shf
[1];
106 sflags
|= SHF_ALLOCS
;
110 shf
->rp
= shf
->wp
= shf
->buf
;
113 shf
->wnleft
= 0; /* force call to shf_emptybuf() */
114 shf
->wbsize
= sflags
& SHF_UNBUF
? 0 : bsize
;
120 #if !defined __amigaos4__ && !defined __AROS__
121 if (sflags
& SHF_CLEXEC
)
122 fcntl(fd
, F_SETFD
, FD_CLOEXEC
);
127 /* Set up an existing shf (and buffer) to use the given fd */
129 shf_reopen(int fd
, int sflags
, struct shf
*shf
)
131 int bsize
= sflags
& SHF_UNBUF
? (sflags
& SHF_RD
? 1 : 0) : SHF_BSIZE
;
133 /* use fcntl() to figure out correct read/write flags */
134 if (sflags
& SHF_GETFL
) {
135 int flags
= fcntl(fd
, F_GETFL
, 0);
138 /* will get an error on first read/write */
141 switch (flags
& O_ACCMODE
) {
142 case O_RDONLY
: sflags
|= SHF_RD
; break;
143 case O_WRONLY
: sflags
|= SHF_WR
; break;
144 case O_RDWR
: sflags
|= SHF_RDWR
; break;
148 if (!(sflags
& (SHF_RD
| SHF_WR
)))
149 internal_errorf(1, "shf_reopen: missing read/write");
150 if (!shf
|| !shf
->buf
|| shf
->bsize
< bsize
)
151 internal_errorf(1, "shf_reopen: bad shf/buf/bsize");
153 /* assumes shf->buf and shf->bsize already set up */
155 shf
->rp
= shf
->wp
= shf
->buf
;
158 shf
->wnleft
= 0; /* force call to shf_emptybuf() */
159 shf
->wbsize
= sflags
& SHF_UNBUF
? 0 : bsize
;
160 shf
->flags
= (shf
->flags
& (SHF_ALLOCS
| SHF_ALLOCB
)) | sflags
;
163 #if !defined __amigaos4__ && !defined __AROS__
164 if (sflags
& SHF_CLEXEC
)
165 fcntl(fd
, F_SETFD
, FD_CLOEXEC
);
170 /* Open a string for reading or writing. If reading, bsize is the number
171 * of bytes that can be read. If writing, bsize is the maximum number of
172 * bytes that can be written. If shf is not null, it is filled in and
173 * returned, if it is null, shf is allocated. If writing and buf is null
174 * and SHF_DYNAMIC is set, the buffer is allocated (if bsize > 0, it is
175 * used for the initial size). Doesn't fail.
176 * When writing, a byte is reserved for a trailing null - see shf_sclose().
179 shf_sopen(char *buf
, int bsize
, int sflags
, struct shf
*shf
)
181 /* can't have a read+write string */
182 if (!(sflags
& (SHF_RD
| SHF_WR
)) ||
183 (sflags
& (SHF_RD
| SHF_WR
)) == (SHF_RD
| SHF_WR
))
184 internal_errorf(1, "shf_sopen: flags 0x%x", sflags
);
187 shf
= (struct shf
*) alloc(sizeof(struct shf
), ATEMP
);
188 sflags
|= SHF_ALLOCS
;
191 if (!buf
&& (sflags
& SHF_WR
) && (sflags
& SHF_DYNAMIC
)) {
194 sflags
|= SHF_ALLOCB
;
195 buf
= alloc(bsize
, shf
->areap
);
198 shf
->buf
= shf
->rp
= shf
->wp
= (unsigned char *) buf
;
201 shf
->wnleft
= bsize
- 1; /* space for a '\0' */
203 shf
->flags
= sflags
| SHF_STRING
;
211 /* Flush and close file descriptor, free the shf structure */
213 shf_close(struct shf
*shf
)
218 ret
= shf_flush(shf
);
220 if(shf
->ispipe
== true)
227 __get_default_file(shf
->fd
,(long *)&f
);
228 NameFromFH(f
,pname
,255);
230 if(close(shf
->fd
) < 0) ret
= EOF
;
240 while((n
= read(shf
->fd
,buffer
,255)) > 0) t
+=n
;
241 if (close(shf
->fd
) < 0) ret
= EOF
;
247 if (close(shf
->fd
) < 0) ret
= EOF
;
250 if (shf
->flags
& SHF_ALLOCS
)
251 afree(shf
, shf
->areap
);
252 else if (shf
->flags
& SHF_ALLOCB
)
253 afree(shf
->buf
, shf
->areap
);
258 /* Flush and close file descriptor, don't free file structure */
260 shf_fdclose(struct shf
*shf
)
265 ret
= shf_flush(shf
);
267 if(shf
->ispipe
== true)
274 __get_default_file(shf
->fd
,(long *)&f
);
275 NameFromFH(f
,pname
,255);
277 if(close(shf
->fd
) < 0) ret
= EOF
;
287 while((n
= read(shf
->fd
,buffer
,255)) > 0) t
+=n
;
288 if (close(shf
->fd
) < 0) ret
= EOF
;
294 if (close(shf
->fd
) < 0) ret
= EOF
;
306 /* Close a string - if it was opened for writing, it is null terminated;
307 * returns a pointer to the string and frees shf if it was allocated
308 * (does not free string if it was allocated).
311 shf_sclose(struct shf
*shf
)
313 unsigned char *s
= shf
->buf
;
316 if (shf
->flags
& SHF_WR
) {
320 if (shf
->flags
& SHF_ALLOCS
)
321 afree(shf
, shf
->areap
);
325 /* Un-read what has been read but not examined, or write what has been
326 * buffered. Returns 0 for success, EOF for (write) error.
329 shf_flush(struct shf
*shf
)
331 if (shf
->flags
& SHF_STRING
)
332 return (shf
->flags
& SHF_WR
) ? EOF
: 0;
335 internal_errorf(1, "shf_flush: no fd");
337 if (shf
->flags
& SHF_ERROR
) {
342 if (shf
->flags
& SHF_READING
) {
343 shf
->flags
&= ~(SHF_EOF
| SHF_READING
);
344 if (shf
->rnleft
> 0) {
345 lseek(shf
->fd
, (off_t
) -shf
->rnleft
, SEEK_CUR
);
350 } else if (shf
->flags
& SHF_WRITING
)
351 return shf_emptybuf(shf
, 0);
356 /* Write out any buffered data. If currently reading, flushes the read
357 * buffer. Returns 0 for success, EOF for (write) error.
360 shf_emptybuf(struct shf
*shf
, int flags
)
364 if (!(shf
->flags
& SHF_STRING
) && shf
->fd
< 0)
365 internal_errorf(1, "shf_emptybuf: no fd");
367 if (shf
->flags
& SHF_ERROR
) {
372 if (shf
->flags
& SHF_READING
) {
373 if (flags
& EB_READSW
) /* doesn't happen */
375 ret
= shf_flush(shf
);
376 shf
->flags
&= ~SHF_READING
;
378 if (shf
->flags
& SHF_STRING
) {
381 /* Note that we assume SHF_ALLOCS is not set if SHF_ALLOCB
382 * is set... (changing the shf pointer could cause problems)
384 if (!(flags
& EB_GROW
) || !(shf
->flags
& SHF_DYNAMIC
) ||
385 !(shf
->flags
& SHF_ALLOCB
))
387 /* allocate more space for buffer */
388 nbuf
= (unsigned char *) aresize(shf
->buf
, shf
->wbsize
* 2,
390 shf
->rp
= nbuf
+ (shf
->rp
- shf
->buf
);
391 shf
->wp
= nbuf
+ (shf
->wp
- shf
->buf
);
392 shf
->rbsize
+= shf
->wbsize
;
393 shf
->wnleft
+= shf
->wbsize
;
397 if (shf
->flags
& SHF_WRITING
) {
398 int ntowrite
= shf
->wp
- shf
->buf
;
399 unsigned char *buf
= shf
->buf
;
402 while (ntowrite
> 0) {
403 n
= write(shf
->fd
, buf
, ntowrite
);
406 && !(shf
->flags
& SHF_INTERRUPT
))
408 shf
->flags
|= SHF_ERROR
;
411 if (buf
!= shf
->buf
) {
412 /* allow a second flush
414 memmove(shf
->buf
, buf
,
416 shf
->wp
= shf
->buf
+ ntowrite
;
423 if (flags
& EB_READSW
) {
426 shf
->flags
&= ~SHF_WRITING
;
431 shf
->wnleft
= shf
->wbsize
;
433 shf
->flags
|= SHF_WRITING
;
438 /* Fill up a read buffer. Returns EOF for a read error, 0 otherwise. */
440 shf_fillbuf(struct shf
*shf
)
442 if (shf
->flags
& SHF_STRING
)
446 internal_errorf(1, "shf_fillbuf: no fd");
448 if (shf
->flags
& (SHF_EOF
| SHF_ERROR
)) {
449 if (shf
->flags
& SHF_ERROR
)
454 if ((shf
->flags
& SHF_WRITING
) && shf_emptybuf(shf
, EB_READSW
) == EOF
)
457 shf
->flags
|= SHF_READING
;
461 shf
->rnleft
= blocking_read(shf
->fd
, (char *) shf
->buf
,
463 if (shf
->rnleft
< 0 && errno
== EINTR
464 && !(shf
->flags
& SHF_INTERRUPT
))
468 if (shf
->rnleft
<= 0) {
469 if (shf
->rnleft
< 0) {
470 shf
->flags
|= SHF_ERROR
;
476 shf
->flags
|= SHF_EOF
;
481 /* Read a buffer from shf. Returns the number of bytes read into buf,
482 * if no bytes were read, returns 0 if end of file was seen, EOF if
483 * a read error occurred.
486 shf_read(char *buf
, int bsize
, struct shf
*shf
)
488 int orig_bsize
= bsize
;
491 if (!(shf
->flags
& SHF_RD
))
492 internal_errorf(1, "shf_read: flags %x", shf
->flags
);
495 internal_errorf(1, "shf_read: bsize %d", bsize
);
499 && (shf_fillbuf(shf
) == EOF
|| shf
->rnleft
== 0))
504 memcpy(buf
, shf
->rp
, ncopy
);
508 shf
->rnleft
-= ncopy
;
510 /* Note: fread(3S) returns 0 for errors - this doesn't */
511 return orig_bsize
== bsize
? (shf_error(shf
) ? EOF
: 0)
512 : orig_bsize
- bsize
;
515 /* Read up to a newline or EOF. The newline is put in buf; buf is always
516 * null terminated. Returns NULL on read error or if nothing was read before
517 * end of file, returns a pointer to the null byte in buf otherwise.
520 shf_getse(char *buf
, int bsize
, struct shf
*shf
)
524 char *orig_buf
= buf
;
526 if (!(shf
->flags
& SHF_RD
))
527 internal_errorf(1, "shf_getse: flags %x", shf
->flags
);
532 --bsize
; /* save room for null */
534 if (shf
->rnleft
== 0) {
535 if (shf_fillbuf(shf
) == EOF
)
537 if (shf
->rnleft
== 0) {
539 return buf
== orig_buf
? NULL
: buf
;
542 end
= (unsigned char *) memchr((char *) shf
->rp
, '\n',
544 ncopy
= end
? end
- shf
->rp
+ 1 : shf
->rnleft
;
547 memcpy(buf
, (char *) shf
->rp
, ncopy
);
549 shf
->rnleft
-= ncopy
;
553 } while (!end
&& bsize
);
558 /* Returns the char read. Returns EOF for error and end of file. */
560 shf_getchar(struct shf
*shf
)
562 if (!(shf
->flags
& SHF_RD
))
563 internal_errorf(1, "shf_getchar: flags %x", shf
->flags
);
565 if (shf
->rnleft
== 0 && (shf_fillbuf(shf
) == EOF
|| shf
->rnleft
== 0))
571 /* Put a character back in the input stream. Returns the character if
572 * successful, EOF if there is no room.
575 shf_ungetc(int c
, struct shf
*shf
)
577 if (!(shf
->flags
& SHF_RD
))
578 internal_errorf(1, "shf_ungetc: flags %x", shf
->flags
);
580 if ((shf
->flags
& SHF_ERROR
) || c
== EOF
581 || (shf
->rp
== shf
->buf
&& shf
->rnleft
))
584 if ((shf
->flags
& SHF_WRITING
) && shf_emptybuf(shf
, EB_READSW
) == EOF
)
587 if (shf
->rp
== shf
->buf
)
588 shf
->rp
= shf
->buf
+ shf
->rbsize
;
589 if (shf
->flags
& SHF_STRING
) {
590 /* Can unget what was read, but not something different - we
591 * don't want to modify a string.
593 if (shf
->rp
[-1] != c
)
595 shf
->flags
&= ~SHF_EOF
;
600 shf
->flags
&= ~SHF_EOF
;
606 /* Write a character. Returns the character if successful, EOF if
607 * the char could not be written.
610 shf_putchar(int c
, struct shf
*shf
)
612 if (!(shf
->flags
& SHF_WR
))
613 internal_errorf(1, "shf_putchar: flags %x", shf
->flags
);
618 if (shf
->flags
& SHF_UNBUF
) {
623 internal_errorf(1, "shf_putchar: no fd");
624 if (shf
->flags
& SHF_ERROR
) {
628 while ((n
= write(shf
->fd
, &cc
, 1)) != 1)
631 && !(shf
->flags
& SHF_INTERRUPT
))
633 shf
->flags
|= SHF_ERROR
;
638 /* Flush deals with strings and sticky errors */
639 if (shf
->wnleft
== 0 && shf_emptybuf(shf
, EB_GROW
) == EOF
)
648 /* Write a string. Returns the length of the string if successful, EOF if
649 * the string could not be written.
652 shf_puts(const char *s
, struct shf
*shf
)
657 return shf_write(s
, strlen(s
), shf
);
660 /* Write a buffer. Returns nbytes if successful, EOF if there is an error. */
662 shf_write(const char *buf
, int nbytes
, struct shf
*shf
)
664 int orig_nbytes
= nbytes
;
668 if (!(shf
->flags
& SHF_WR
))
669 internal_errorf(1, "shf_write: flags %x", shf
->flags
);
672 internal_errorf(1, "shf_write: nbytes %d", nbytes
);
674 /* Don't buffer if buffer is empty and we're writting a large amount. */
675 if ((ncopy
= shf
->wnleft
)
676 && (shf
->wp
!= shf
->buf
|| nbytes
< shf
->wnleft
))
680 memcpy(shf
->wp
, buf
, ncopy
);
684 shf
->wnleft
-= ncopy
;
687 /* Flush deals with strings and sticky errors */
688 if (shf_emptybuf(shf
, EB_GROW
) == EOF
)
690 if (nbytes
> shf
->wbsize
) {
693 ncopy
-= nbytes
% shf
->wbsize
;
696 n
= write(shf
->fd
, buf
, ncopy
);
699 && !(shf
->flags
& SHF_INTERRUPT
))
701 shf
->flags
|= SHF_ERROR
;
704 /* Note: fwrite(3S) returns 0 for
705 * errors - this doesn't */
713 memcpy(shf
->wp
, buf
, nbytes
);
715 shf
->wnleft
-= nbytes
;
723 shf_fprintf(struct shf
*shf
, const char *fmt
, ...)
729 n
= shf_vfprintf(shf
, fmt
, args
);
736 shf_snprintf(char *buf
, int bsize
, const char *fmt
, ...)
742 if (!buf
|| bsize
<= 0)
743 internal_errorf(1, "shf_snprintf: buf %lx, bsize %d",
746 shf_sopen(buf
, bsize
, SHF_WR
, &shf
);
748 n
= shf_vfprintf(&shf
, fmt
, args
);
750 shf_sclose(&shf
); /* null terminates */
755 shf_smprintf(const char *fmt
, ...)
760 shf_sopen((char *) 0, 0, SHF_WR
|SHF_DYNAMIC
, &shf
);
762 shf_vfprintf(&shf
, fmt
, args
);
764 return shf_sclose(&shf
); /* null terminates */
767 #undef FP /* if you want floating point stuff */
770 #define FPBUF_SIZE (DMAXEXP+16)/* this must be >
771 * MAX(DMAXEXP, log10(pow(2, DSIGNIF)))
772 * + ceil(log10(DMAXEXP)) + 8 (I think).
773 * Since this is hard to express as a
774 * constant, just use a large buffer.
778 * What kinda of machine we on? Hopefully the C compiler will optimize
781 * For shorts, we want sign extend for %d but not for %[oxu] - on 16 bit
782 * machines it don't matter. Assumes C compiler has converted shorts to
783 * ints before pushing them.
785 #define POP_INT(f, s, a) \
786 (((f) & FL_LONG) ? va_arg((a), unsigned long) : \
787 (sizeof(int) < sizeof(long) ? ((s) ? \
788 (long) va_arg((a), int) : va_arg((a), unsigned)) : \
789 va_arg((a), unsigned)))
791 #define ABIGNUM 32000 /* big numer that will fit in a short */
792 #define LOG2_10 3.321928094887362347870319429 /* log base 2 of 10 */
794 #define FL_HASH 0x001 /* `#' seen */
795 #define FL_PLUS 0x002 /* `+' seen */
796 #define FL_RIGHT 0x004 /* `-' seen */
797 #define FL_BLANK 0x008 /* ` ' seen */
798 #define FL_SHORT 0x010 /* `h' seen */
799 #define FL_LONG 0x020 /* `l' seen */
800 #define FL_ZERO 0x040 /* `0' seen */
801 #define FL_DOT 0x080 /* '.' seen */
802 #define FL_UPPER 0x100 /* format character was uppercase */
803 #define FL_NUMBER 0x200 /* a number was formated %[douxefg] */
814 return d
- modf(d
, &i
) + (d
< 0 ? -1 : 1);
819 shf_vfprintf(struct shf
*shf
, const char *fmt
, va_list args
)
823 int field
, precision
;
827 /* %#o produces the longest output */
828 char numbuf
[(BITS(long) + 2) / 3 + 1];
829 /* this stuff for dealing with the buffer */
832 /* should be in <math.h>
833 * extern double frexp();
840 char fpbuf
[FPBUF_SIZE
];
846 while ((c
= *fmt
++)) {
853 * This will accept flags/fields in any order - not
854 * just the order specified in printf(3), but this is
855 * the way _doprnt() seems to work (on bsd and sysV).
856 * The only restriction is that the format character must
859 flags
= field
= precision
= 0;
860 for ( ; (c
= *fmt
++) ; ) {
879 if (!(flags
& FL_DOT
))
889 tmp
= va_arg(args
, int);
892 else if ((field
= tmp
) < 0) {
908 while (c
= *fmt
++, digit(c
))
909 tmp
= tmp
* 10 + c
- '0';
911 if (tmp
< 0) /* overflow? */
925 if (!c
) /* nasty format */
928 if (c
>= 'A' && c
<= 'Z') {
934 case 'p': /* pointer */
935 flags
&= ~(FL_LONG
| FL_SHORT
);
936 if (sizeof(char *) > sizeof(int))
937 flags
|= FL_LONG
; /* hope it fits.. */
945 s
= &numbuf
[sizeof(numbuf
)];
946 lnum
= POP_INT(flags
, c
== 'd', args
);
951 lnum
= - (long) lnum
, tmp
= 1;
958 *--s
= lnum
% 10 + '0';
965 else if (flags
& FL_PLUS
)
967 else if (flags
& FL_BLANK
)
974 *--s
= (lnum
& 0x7) + '0';
978 if ((flags
& FL_HASH
) && *s
!= '0')
985 const char *digits
= (flags
& FL_UPPER
) ?
987 : "0123456789abcdef";
989 *--s
= digits
[lnum
& 0xf];
993 if (flags
& FL_HASH
) {
994 *--s
= (flags
& FL_UPPER
) ? 'X' : 'x';
999 len
= &numbuf
[sizeof(numbuf
)] - s
;
1000 if (flags
& FL_DOT
) {
1001 if (precision
> len
) {
1005 precision
= len
; /* no loss */
1017 * This could probably be done better,
1018 * but it seems to work. Note that gcvt()
1019 * is not used, as you cannot tell it to
1020 * not strip the zeros.
1023 if (!(flags
& FL_DOT
))
1024 precision
= 6; /* default */
1026 * Assumes doubles are pushed on
1027 * the stack. If this is not so, then
1028 * FL_LONG/FL_SHORT should be checked.
1030 fpnum
= va_arg(args
, double);
1034 * This is the same as
1035 * expo = ceil(log10(fpnum))
1036 * but doesn't need -lm. This is an
1037 * approximation as expo is rounded up.
1039 (void) frexp(fpnum
, &expo
);
1040 expo
= my_ceil(expo
/ LOG2_10
);
1045 p
= ecvt(fpnum
, precision
+ 1 + expo
,
1048 if (decpt
< -4 || decpt
> precision
)
1052 if (decpt
> 0 && (precision
-= decpt
) < 0)
1057 else if (flags
& FL_PLUS
)
1059 else if (flags
& FL_BLANK
)
1066 /* Overflow check - should
1067 * never have this problem.
1069 if (decpt
> &fpbuf
[sizeof(fpbuf
)] - s
- 8)
1070 decpt
= &fpbuf
[sizeof(fpbuf
)] - s
- 8;
1071 (void) memcpy(s
, p
, decpt
);
1078 /* print the fraction? */
1079 if (precision
> 0) {
1081 /* Overflow check - should
1082 * never have this problem.
1084 if (precision
> &fpbuf
[sizeof(fpbuf
)] - s
- 7)
1085 precision
= &fpbuf
[sizeof(fpbuf
)] - s
- 7;
1086 for (tmp
= decpt
; tmp
++ < 0 &&
1087 precision
> 0 ; precision
--)
1090 if (precision
> tmp
)
1092 /* Overflow check - should
1093 * never have this problem.
1095 if (precision
> &fpbuf
[sizeof(fpbuf
)] - s
- 7)
1096 precision
= &fpbuf
[sizeof(fpbuf
)] - s
- 7;
1097 (void) memcpy(s
, p
, precision
);
1100 * `g' format strips trailing
1101 * zeros after the decimal.
1103 if (c
== 'g' && !(flags
& FL_HASH
)) {
1109 } else if (flags
& FL_HASH
)
1113 *s
++ = (flags
& FL_UPPER
) ? 'E' : 'e';
1120 p
= &numbuf
[sizeof(numbuf
)];
1121 for (tmp
= 0; tmp
< 2 || decpt
; tmp
++) {
1122 *--p
= '0' + decpt
% 10;
1125 tmp
= &numbuf
[sizeof(numbuf
)] - p
;
1126 (void) memcpy(s
, p
, tmp
);
1138 if (!(s
= va_arg(args
, char *)))
1139 s
= strdup("(null %s)");
1145 numbuf
[0] = va_arg(args
, int);
1159 * At this point s should point to a string that is
1160 * to be formatted, and len should be the length of the
1163 if (!(flags
& FL_DOT
) || len
< precision
)
1165 if (field
> precision
) {
1167 if (!(flags
& FL_RIGHT
)) {
1169 /* skip past sign or 0x when padding with 0 */
1170 if ((flags
& FL_ZERO
) && (flags
& FL_NUMBER
)) {
1171 if (*s
== '+' || *s
== '-' || *s
==' ')
1177 } else if (*s
== '0') {
1181 if (--precision
> 0 &&
1192 c
= flags
& FL_ZERO
? '0' : ' ';
1195 for ( ; field
< 0 ; field
++)
1203 if (precision
> 0) {
1204 nwritten
+= precision
;
1205 for ( ; precision
-- > 0 ; s
++)
1210 for ( ; field
> 0 ; --field
)
1215 return shf_error(shf
) ? EOF
: nwritten
;