3 * (C) Copyright Dec 19 1998, Edmond J. Breen.
5 * This code may be copied for personal, non-profit use only.
9 /* This file is broken into 2 parts
10 * the first part defines the interface routines
11 * and the 2nd part adds the interface routine
12 * to EiC's look up tables.
21 #define _POSIX_SOURCE 1
24 #ifndef __EXTENSIONS__
25 #define __EXTENSIONS__
37 extern FILE *popen(const char *, const char *);
38 extern int pclose(FILE *);
53 #include "stdliblocal.h"
61 /* The following code provides for an open FILE cleanup
62 mechanism. EiC will call _ffexit, cleaning up all open
63 FILEs which were opened in the side effects being discarded.
65 static size_t NextFopenEntry = 4;
67 static size_t book1[FOPEN_MAX] = {1,2,3};
68 static FILE * book2[FOPEN_MAX];
70 size_t fopen_NextEntryNum(void) {
71 return NextFopenEntry;
74 /* We assume that eic_fopen() is always closed by eic_fclose()
75 and eic_popen() is aways closed by eic_pclose() so that book[i]
76 being non-zero implies that the associated FILE is still open.
77 This ignores the possibility that a file opened in interpreted
78 code can be closed in compiled code, but such a situation is
79 ill advised in any event.
81 void _ffexit(size_t Entry) {
83 for(i = 0; i < FOPEN_MAX; i += 1) {
84 if(book1[i] >= Entry) {
93 /* INTERFACE FUNCTIONS */
95 int charin_(char **buf)
105 int charback_(int ch, char **buf)
111 int charout_(int c, char **buf)
121 int _eicUprintf(int (*output)(), void *arg, char *fmt, arg_list ap)
123 /* copy of _UPRINTF that works with EiC's run time stack.
124 * Orginally developed from James Hendrix's Small C tools.
126 * (c) Edmond J.Breen (March, 1995).
127 * ALL RIGHTS RESERVED.
129 * Purpose: To perform formatted printing to a function.
130 * It performs a superset of printf type
133 * _UPRINTF RECOGNISES:
136 * plus ! and | (see below).
138 * CONVERSION CHARACTERS:
139 * d, i, o, x, X, u, c, s,
140 * f, e, E, g, G, p, n, %
141 * plus b (see below).
146 * The WIDTH and or the PRECISION can be set indirectly
147 * via * as specified by K&R.
149 * _UPRINTF EXTRA FEATURES.
151 * FLAG WHAT IT SPECIFIES
152 * | Centre justification.
153 * ! Used with floating point numbers.
154 * It specifies, if possible, that the
155 * number will be centred with respect
156 * to the decimal point.
157 * If used with non floating point
158 * numbers or the floating point number
159 * does not contain a decimal point,
160 * the ! flag is equivalent to |.
161 * NEW CONVERSION CHARACTER:
162 * CHARACTER WHAT IT SPECIFIES
163 * b int, unsigned binary notation.
168 static char str[128];
169 char *sptr, lseen,Lseen;
171 int left, right, centre, maxchr,
172 pad, len, width, sign, dprec,
173 mod, prec,dot,gotfloat;
182 } else if(*++fmt =='%') {
183 (*output)(*fmt++,arg);
188 centre = len = right = left = 0;
189 gotfloat = dot = sign = mod = 0;
190 Lseen = lseen = dprec = 0;
191 while(*fmt) { /* collect in any order */
192 if(*fmt == '-') left = 1;
193 else if(*fmt == '0') pad = '0';
194 else if(*fmt == '+') sign = 1;
195 else if(*fmt == '#') mod = 1;
196 else if(*fmt == '|') centre = 1;
197 else if(*fmt == '!') centre = 1, dot = 1;
204 while(isdigit(*fmt)) ++fmt;
205 } else if(*fmt == '*') {
206 width = nextarg(ap,int);
212 maxchr = nextarg(ap,int);
216 while(isdigit(*fmt)) ++fmt;
221 switch(*fmt) { /* check for length modifier*/
222 case 'h': fmt++;break;
223 case 'l': lseen = 1; fmt++;break;
224 case 'L': Lseen = 1; fmt++;break;
228 case 'c': sptr[0] = (char)nextarg(ap,int);
232 if(lseen) ultoa(nextarg(ap,long),sptr,2);
233 else utoa(nextarg(ap,int),sptr,2);
236 case 'd': if(lseen) ltoa(nextarg(ap,long),sptr,10);
237 else itoa(nextarg(ap,int),sptr,10);
240 case 'u': if(lseen) ultoa(nextarg(ap,unsigned long),sptr,10);
241 else utoa(nextarg(ap,unsigned),sptr,10);
244 case 'o': if(mod) *sptr = '0';
245 if(lseen)ltoa(nextarg(ap,long),&sptr[mod],8);
246 else itoa(nextarg(ap,int),&sptr[mod],8);
249 case 's': sptr = nextarg(ap,ptr_t).p; break;
252 *sptr = '0', sptr[1] = *(fmt-1);
255 if(lseen)ultoa(nextarg(ap,long),&sptr[mod],16);
256 else utoa(nextarg(ap,int),&sptr[mod],16);
257 if(*(fmt-1) == 'X') {
259 *sptr = toupper(*sptr);
267 case 'e': case 'E': case 'g': case 'G':
270 char type = *(fmt-1),c;
274 if(maxchr < 0) prec = 6;
275 else prec = maxchr,maxchr = -1;
278 d = nextarg(ap,double);
280 d = nextarg(ap,double);
282 if(type == 'g' || type == 'G') {
285 ex = log10(d < 0? -d:d);
288 if(ex < -4 || ex >= prec)
299 sptr = fftoa(d,str, prec, c,trunc);
302 case 'n': *(int*)nextarg(ap,ptr_t).p = v; continue;
304 ultoa((long)nextarg(ap,ptr_t).p,sptr,16);
306 default: (*output)(*(fmt-1),arg);
308 (*output)(*fmt++,arg);
315 if(!len && sptr) len = strlen(sptr);
316 if(sign) len += (*sptr == '-' ? 0: 1);
318 if(dprec && maxchr >=0) {
326 if(maxchr > -1 && maxchr<len)
336 left = (right = width >> 1) + (width%2);
337 if(dot && gotfloat) {
339 while(sptr[d] && sptr[d] != '.')
343 if(sign && sptr[0] != '-')
345 if(c-d > 0) right = c-d;
347 if(width - right > 0)
348 left = width - right;
359 if(sign && !left && pad == '0') {
366 while(right--) {(*output)(pad,arg); ++v;}
367 if(sign && *sptr != '-') {(*output)('+',arg);len--;++v;}
368 while(len--) {(*output)(*sptr++,arg);++v;}
369 while(left--) {(*output)(pad,arg);++v;}
376 int _eicUscanf(int (*input)(), int (*uget)(),
377 void *arg, const char *fmt, arg_list ap)
381 * (C) May 10 1995 Edmond J.Breen.
382 * ALL RIGHTS RESERVED.
384 * Purpose: To perform formatted reading from a function.
385 * _Uscanf performs a superset of scanf type
388 * _USCANF RECOGNISES:
390 * %[*] [width] [h|l|L] [b|d|i|o|x|X|u|c|s|f|e|E|g|G|p|n|%]
391 * %[*] [width] [scan-set]
393 * CONVERSION CHARACTERS:
394 * d, i, o, x, X, u, c, s
395 * f, e, E, g, G, p, n, %
396 * plus b (see below).
401 * * optional assignment-suppression character
402 * WIDTH optional integer width of field specifier
405 * [...] matches the longest non-emtpy string
406 * of input from the set between the brackects.
407 * [^...] matches the longest non-emtpy string
408 * of input NOT from the set between the brackects.
410 * includes ] as part of the scan-set.
412 * NEW CONVERSION CHARACTER:
413 * CHARACTER WHAT IT SPECIFIES
414 * b int, unsigned binary notation.
416 * STANDARD C AUXILIARY FUNCTIONS REQUIRED
417 * strtol, strtod, strtoul
420 * (1) long double handled as double
421 * (2) error checking could be improved
424 static char field[256], *p;
428 int wast, width,cwidth, ch, base,cnt;
435 while(*fmt != '\0') {
436 if(isspace(*fmt)) { /* match white space */
437 while(*fmt && isspace(*fmt)) ++fmt;
439 while(isspace((ch=(*input)(arg))))
445 if(*fmt != '%') { /* match literal text */
446 while(*fmt && !isspace(*fmt) && *fmt != '%')
447 if((ch=(*input)(arg)) == *fmt)
458 } else if(*fmt == '%') {
464 vptr = nextarg(ap,ptr_t).p;
467 for(width = 0;isdigit(*fmt);fmt++)
468 width = *fmt - '0' + width * 10;
470 width = INT_MAX, cwidth = 1;
474 if(*fmt != 'c' && *fmt != '[' && *fmt != 'n') {
475 /* strip leading white space */
476 while(isspace(ch = (*input)(arg)))
489 case 'h': type = 'h'; ++fmt; break;
490 case 'l': type = 'l'; ++fmt; break;
491 case 'L': type = 'L'; ++fmt; break;
496 case 'c': carg = vptr;
498 *carg = (*input)(arg);
507 if((*carg = (*input)(arg)) == EOF)
522 if(*fmt == '^') {++fmt; type = 0;}
528 while(*p && *p != ']') ++p;
530 if(cwidth == 0) return EOF;
532 while((ch = (*input)(arg)) != EOF)
534 if(memchr(fmt,ch,cwidth)) {
543 if(!memchr(fmt,ch,cwidth)) {
554 case 'e': case 'f': case 'g':
558 if(ch == '-' || ch == '+') {
563 while(width-- && isdigit(ch=(*input)(arg))) {
566 if(ch == '.' && width-- > 0) {
569 while(isdigit(ch=(*input)(arg)) && width--) {
574 if((ch == 'e' || ch == 'E') && width--) {
577 if(ch != '+' && ch != '-' && !isdigit(ch) &&
578 ch != EOF && !isspace(ch)) {
585 if((ch == '+' || ch == '-') && width--) {
590 while(isdigit(ch) && width--) {
600 double d = strtod(field,NULL);
601 if(!type || type == 'h')
602 *(float*)vptr = (float)d;
603 else if(type == 'l' || type == 'L')
618 case 'b': base = 2; break;
623 if(ch == '0') base = 8;
628 case 'o': base = 8; break;
631 case 'p': base = 16; break;
636 while(width-- && !isspace(ch=(*input)(arg)) && ch != EOF) {
649 if(*fmt == 'd' || *fmt == 'i') { /* signed conversion */
650 long lval = strtol(field,&endptr,base);
653 *(short *)vptr =(short) lval;
655 *(long *)vptr = lval;
657 *(int *)vptr = (int) lval;
660 unsigned long ulval = strtoul(field,&endptr,base);
663 *(unsigned short *)vptr =(unsigned short) ulval;
665 *(unsigned long *)vptr = ulval;
667 *(unsigned *)vptr = (unsigned)ulval;
669 if(endptr == field) /* failed */
686 arg_list ap = getargs();
689 v.p.sp = v.p.p = _popen(arg(0,ap,ptr_t).p,arg(1,ap,ptr_t).p);
691 v.p.sp = v.p.p = popen(arg(0,ap,ptr_t).p,arg(1,ap,ptr_t).p);
694 if((FILE *)(v.p.p) != NULL) {
696 for(i=1;i<FOPEN_MAX;i++)
699 book1[i] = NextFopenEntry++;
700 book2[i] = (FILE *)(v.p.p);
702 setEp( v.p, sizeof(FILE) );
712 arg_list ap = getargs();
714 ptr = arg(0,ap,ptr_t).p;
717 v.ival = _pclose(ptr);
719 v.ival = pclose(ptr);
722 for(i=0;i<FOPEN_MAX;i++)
737 val_t _get_stdin(void)
741 * This function exists so that EiC can get the address stdin.
743 v.p.sp = v.p.p = stdin;
744 setEp( v.p, sizeof(*stdin) );
747 val_t _get_stdout(void)
751 * This function exists so that EiC can get the address stdout.
753 v.p.sp = v.p.p = stdout;
754 setEp( v.p, sizeof(*stdout) );
757 val_t _get_stderr(void)
761 * This function exists so that EiC can get the address stderr.
763 v.p.sp = v.p.p = stderr;
764 setEp( v.p, sizeof(*stderr) );
770 val_t eic_ftell(void)
773 v.lval = ftell(arg(0,getargs(),ptr_t).p);
777 val_t eic_fseek(void)
780 v.ival = fseek(arg(0,getargs(),ptr_t).p,
781 arg(1,getargs(),long),
782 arg(2,getargs(),int));
788 val_t eic_printf(void)
791 arg_list ap = getargs();
794 fmt = nextarg(ap,ptr_t).p;
796 v.ival = _eicUprintf(outbyte,stdout,fmt,ap);
798 v.ival = _eicUprintf(fputc,stdout,fmt,ap);
803 val_t eic_fprintf(void)
806 arg_list ap = getargs();
810 fp = nextarg(ap,ptr_t).p;
811 fmt = nextarg(ap,ptr_t).p;
812 v.ival = _eicUprintf(fputc,fp,fmt,ap);
816 val_t eic_vfprintf(void)
819 arg_list ap = getargs();
824 fp = nextarg(ap,ptr_t).p;
825 fmt = nextarg(ap,ptr_t).p;
826 ags = nextarg(ap,arg_list);
827 v.ival = _eicUprintf(fputc,fp,fmt,ags);
831 val_t eic_sprintf(void)
834 arg_list ap = getargs();
836 str = nextarg(ap,ptr_t).p;
837 fmt = nextarg(ap,ptr_t).p;
838 v.ival = _eicUprintf(charout_,&str,fmt,ap);
843 val_t eic_vsprintf(void)
846 arg_list ap = getargs();
851 str = nextarg(ap,ptr_t).p;
852 fmt = nextarg(ap,ptr_t).p;
853 ags = nextarg(ap,arg_list);
854 v.ival = _eicUprintf(charout_,&str,fmt,ags);
859 val_t eic_freopen(void)
862 arg_list ap = getargs();
863 v.p.sp = v.p.p = freopen(arg(0,ap,ptr_t).p,
867 setEp( v.p, sizeof(FILE) );
871 val_t eic_fopen(void)
874 arg_list ap = getargs();
875 v.p.sp = v.p.p = fopen(arg(0,ap,ptr_t).p,
877 if((FILE *)(v.p.p) != NULL) {
879 for(i=1;i<FOPEN_MAX;i++)
882 book1[i] = NextFopenEntry++;
883 book2[i] = (FILE *)(v.p.p);
885 setEp( v.p, sizeof(FILE) );
889 val_t eic_ungetc(void)
892 arg_list ap = getargs();
893 v.ival = ungetc(arg(0,ap,int),
898 val_t eic_fgetc(void)
901 v.ival = fgetc(nextarg(getargs(),ptr_t).p);
904 val_t eic_fclose(void)
910 ptr = nextarg(getargs(),ptr_t).p;
912 for(i=0;i<FOPEN_MAX;i++)
920 v.ival = fclose(ptr);
923 val_t eic_fflush(void)
926 v.ival = fflush(nextarg(getargs(),ptr_t).p);
930 val_t eic_fputc(void)
933 arg_list ap = getargs();
934 v.ival = fputc(arg(0,ap,int),
942 arg_list ap = getargs();
943 v.ival = puts(arg(0,ap,ptr_t).p);
947 val_t eic_fputs(void)
950 arg_list ap = getargs();
951 v.ival = fputs(arg(0,ap,ptr_t).p,
956 val_t eic_fgets(void)
960 arg_list ap = getargs();
966 v.p.p = fgets(v.p.p,n, arg(2,ap,ptr_t).p);
976 n = (char*)v.p.ep - (char*)v.p.sp;
977 v.p.p = fgets(v.p.p,n,stdin);
981 val_t eic_fread(void)
984 arg_list ap = getargs();
985 v.szval = fread(arg(0,ap,ptr_t).p,
992 val_t eic_fwrite(void)
997 v.szval = fwrite(arg(0,ap,ptr_t).p,
1004 val_t eic_fscanf(void)
1007 arg_list ap = getargs();
1008 v.ival = _eicUscanf(fgetc,ungetc,
1010 arg(1,ap,ptr_t).p,ap-2);
1014 val_t eic_feof(void)
1018 v.ival = feof((FILE *)(v.p.p));
1022 val_t eic_ferror(void)
1026 v.ival = ferror((FILE *)(v.p.p));
1030 val_t eic_rewind(void)
1034 rewind((FILE *)(v.p.p));
1038 val_t eic_fsetpos(void)
1041 arg_list ap = getargs();
1042 v.ival = fsetpos(arg(0,ap,ptr_t).p,
1047 val_t eic_fgetpos(void)
1050 arg_list ap = getargs();
1051 v.ival = fgetpos(arg(0,ap,ptr_t).p,
1058 val_t eic_scanf(void)
1061 arg_list ap = getargs();
1062 v.ival = _eicUscanf(fgetc,ungetc,
1064 arg(0,ap,ptr_t).p,ap-1);
1068 val_t eic_sscanf(void)
1072 arg_list ap = getargs();
1073 str = arg(0,ap,ptr_t).p;
1074 v.ival = _eicUscanf(charin_,charback_,
1076 arg(1,ap,ptr_t).p,ap-2);
1080 val_t eic_setvbuf(void)
1083 arg_list ap = getargs();
1084 v.ival = setvbuf(arg(0,ap,ptr_t).p,
1092 val_t eic_tmpnam(void)
1095 v.p.sp = v.p.p = tmpnam(arg(0,getargs(),ptr_t).p);
1096 setEp( v.p, strlen(v.p.p) + 1 );
1099 val_t eic_tmpfile(void)
1102 v.p.sp = v.p.p = tmpfile();
1103 setEp( v.p, strlen(v.p.p) + 1 );
1107 val_t eic_rename(void)
1111 v.ival = rename(arg(0,getargs(),ptr_t).p,
1112 arg(1,getargs(),ptr_t).p);
1114 v.ival = link(arg(0,getargs(),ptr_t).p,
1115 arg(1,getargs(),ptr_t).p);
1117 v.ival = unlink(arg(0,getargs(),ptr_t).p);
1123 val_t eic_clearerr(void)
1126 clearerr((FILE *)(arg(0,getargs(),ptr_t).p));
1130 val_t eic_perror(void)
1133 perror(arg(0,getargs(),ptr_t).p);
1138 /**********************************************************************************/
1140 void module_stdio(void)
1147 /* stdio.h stuff that were macros */
1148 EiC_add_builtinfunc("puts", eic_puts);
1149 EiC_add_builtinfunc("feof", eic_feof);
1150 EiC_add_builtinfunc("ferror", eic_ferror);
1151 EiC_add_builtinfunc("rewind", eic_rewind);
1152 EiC_add_builtinfunc("fsetpos", eic_fsetpos);
1153 EiC_add_builtinfunc("fgetpos", eic_fgetpos);
1156 EiC_add_builtinfunc("_get_stdin",_get_stdin);
1157 EiC_add_builtinfunc("_get_stdout",_get_stdout);
1158 EiC_add_builtinfunc("_get_stderr",_get_stderr);
1159 EiC_add_builtinfunc("ftell", eic_ftell);
1160 EiC_add_builtinfunc("freopen",eic_freopen);
1161 EiC_add_builtinfunc("fopen",eic_fopen);
1162 EiC_add_builtinfunc("printf", eic_printf);
1163 EiC_add_builtinfunc("fprintf", eic_fprintf);
1164 EiC_add_builtinfunc("sprintf", eic_sprintf);
1165 EiC_add_builtinfunc("vfprintf", eic_vfprintf);
1166 EiC_add_builtinfunc("vsprintf", eic_vsprintf);
1167 EiC_add_builtinfunc("ungetc", eic_ungetc);
1168 EiC_add_builtinfunc("fgetc", eic_fgetc);
1169 EiC_add_builtinfunc("fputc", eic_fputc);
1170 EiC_add_builtinfunc("fputs", eic_fputs);
1171 EiC_add_builtinfunc("fgets", eic_fgets);
1172 EiC_add_builtinfunc("gets", eic_gets);
1173 EiC_add_builtinfunc("fread", eic_fread);
1174 EiC_add_builtinfunc("fwrite", eic_fwrite);
1175 EiC_add_builtinfunc("fflush", eic_fflush);
1176 EiC_add_builtinfunc("fclose", eic_fclose);
1177 EiC_add_builtinfunc("fscanf", eic_fscanf);
1178 EiC_add_builtinfunc("sscanf", eic_sscanf);
1179 EiC_add_builtinfunc("scanf", eic_scanf);
1180 EiC_add_builtinfunc("setvbuf", eic_setvbuf);
1181 EiC_add_builtinfunc("tmpnam", eic_tmpnam);
1182 EiC_add_builtinfunc("tmpfile", eic_tmpfile);
1183 EiC_add_builtinfunc("rename",eic_rename);
1184 EiC_add_builtinfunc("fseek", eic_fseek);
1185 EiC_add_builtinfunc("clearerr", eic_clearerr);
1186 EiC_add_builtinfunc("perror", eic_perror);
1190 EiC_add_builtinfunc("popen", eic_popen);
1191 EiC_add_builtinfunc("pclose", eic_pclose);