int main() { int _fgetc(FILE *fp); int _fputc(int c, FILE *fp); int _fprintf(FILE *fp, const char *s, ...); _fprintf(stdout, "Shit yeah!\n"); _fprintf(stdout, "Hello %s World!\n", "man, WHAT'S Up"); _fprintf(stdout, "Yo %s, hello.\n", "dog"); _fprintf(stdout, "Hello, Dog.\n"); _fprintf(stdout, "Hello %d times.\n", 5067397); _fprintf(stdout, "%c:%c:%c:%c\n", 65 & 0xf0 << 1, 65 & 0xf0 >> 4, 65 | 0x0f << 2, 0x41 << 2 ^ ~11); return 0; }
size_t printf(const char* fstr, ...) { size_t ret = 0; va_list args; va_start(args, fstr); ret = _fprintf(STDOUT, fstr, args); va_end(args); return (ret); }
size_t fprintf(int fd, const char* fstr, ...) { size_t ret = 0; va_list args; va_start(args, fstr); ret = _fprintf(fd, fstr, args); va_end(args); return (ret); }
int _fprintf(FILE *fp, const char *s, ...) { va_list args; int res; int c,i; c = 0; va_start(args, s); for(c = 0; c < strlen(s); ++c) { if(s[c] == '%') { char *p; int j,k; ++c; switch(s[c]) { case 's': for(p = va_arg(args, char *), i = 0; i < strlen(p); ++i) _fputc(p[i], fp); p = NULL; break; case 'd': j = va_arg(args, int); if((p = p_itoc(j)) == NULL) { _fprintf(stderr, "Error: could not convert number to string.\n"); continue; } p = p_rnum(p); while(*p != 0) _fputc(*p++, stdout); break; case 'c': k = va_arg(args, int); _fputc(k, stdout); break; default: _fprintf(stderr, "%d: needs an argument.\n", c); } continue; } else if(s[c] == '\\') {
static void ssuperrprintf(va_list a) { /* This routine behaves like printf but also recognises escape chars of * the form $<char> and acts upon them. It writes its output to * stderr, and if listing-file!= NULL also to a buffer associated with * the listing file. */ for (;;) { #define no_arg_type 0 #define int_arg_type 2 #define ptr_arg_type 4 #define no_qualifier 0 #define long_qualifier 8 #define star_qualifier 16 /* indirection for field width (yuk) */ int arg_type = no_arg_type, w; void *pnt; long l_int; int ch; char v[80+12]; /* Buffer for segment of the format string */ int n = 0; /* 0..91 */ /* Characters are moved to the buffer up as far as a $ or % escape */ while ((ch = fetch_string_char()) != 0 && ch != '$' && n != 80 && /* also break at char 80... */ ch != '%') v[n++] = ch; if (ch == '%') { /* It is assumed here that there will never be more than 11 characters in */ /* an escape sequence (e.g. %-20.20l#x has 10 chars in it and seems a */ /* bit excessive. The limit is because of overflow in the buffer v[] */ v[n++] = ch; for (;;) { ch = fetch_string_char(); if (n == 91) syserr(syserr_bad_fmt_dir); v[n++] = ch; switch (safe_tolower(ch)) { case 'l': arg_type |= long_qualifier; continue; case '*': arg_type |= star_qualifier; continue; /* Note that 'h' indicates that an int should be treated as a */ /* short value, but the va_arg() call still fetches an int. */ default: continue; case '%': break; case 'c': case 'd': case 'i': case 'o': case 'u': case 'x': arg_type |= int_arg_type; break; case 'p': case 's': arg_type |= ptr_arg_type; break; case 'e': case 'f': case 'g': /* disallow floating point here */ case 'n': case 0: syserr(syserr_bad_fmt_dir); } break; } ch = fetch_string_char(); } v[n] = 0; /* terminate format string */ if (listingstream != NULL) check_error_buffer(); switch (arg_type) { default: case no_arg_type: #ifndef NO_LISTING_OUTPUT if (listingstream != NULL) errsavep += (_sprintf(&errsaves[errsavep], v), strlen(&errsaves[errsavep])); #endif _fprintf(stderr, v); break; case ptr_arg_type: pnt = va_arg(a, void *); #ifndef NO_LISTING_OUTPUT if (listingstream != NULL) errsavep += (_sprintf(&errsaves[errsavep], v, pnt), strlen(&errsaves[errsavep])); #endif _fprintf(stderr, v, pnt); break; /* At present I am only supporting '*' qualifiers for use with string */ /* printing (i.e. %.*s) - at the time of writing this code there is just */ /* one such format in errors.h - I might like to get rid of it by */ /* achieving the same result some other way so that this extra mess here */ /* wrt format decoding could be discarded. ACN */ case ptr_arg_type + star_qualifier: w = va_arg(a, int); pnt = va_arg(a, void *); #ifndef NO_LISTING_OUTPUT if (listingstream != NULL) errsavep += (_sprintf(&errsaves[errsavep], v, w, pnt), strlen(&errsaves[errsavep])); #endif _fprintf(stderr, v, w, pnt); break; case int_arg_type + long_qualifier: l_int = va_arg(a, long); #ifndef NO_LISTING_OUTPUT if (listingstream != NULL) errsavep += (_sprintf(&errsaves[errsavep], v, l_int), strlen(&errsaves[errsavep])); #endif _fprintf(stderr, v, l_int); break; case int_arg_type: w = va_arg(a, int); #ifndef NO_LISTING_OUTPUT if (listingstream != NULL) errsavep += (_sprintf(&errsaves[errsavep], v, w), strlen(&errsaves[errsavep])); #endif _fprintf(stderr, v, w); break; } if (ch == 0) { #ifdef CPLUSPLUS if (syserr_behaviour==3) abort(); #endif return; /* Message now complete */ } if (ch != '$') unfetch_string_char(ch); else switch (ch = fetch_string_char()) { case 0: return; case 's': qprints(sym_name_table[va_arg(a,AEop) & 255]); break; case 'l': /* current lexeme */ switch (curlex.sym & 255) { case s_integer: errprintf("'%ld'", (long)curlex.a1.i); break; case s_floatcon: errprintf("'%s'", curlex.a1.fc->floatstr); break; case s_identifier: errprintf("'%s'", symname_(curlex.a1.sv)); break; case s_string: { char e[80]; escstring(e, 20, curlex.a1.s, curlex.a2.len); errprintf("'\"%s\"'", e); } break; default: qprints(sym_name_table[curlex.sym & 255]); break; } break; case 'r': { Symstr *r = va_arg(a, Symstr *); if (r==0 || h0_(r) != s_identifier) { if (r == 0) errprintf("<missing>"); else errprintf("<oddity>"); } else errprintf("'%s'", symname_(r)); } break; case 'b': /* ordinary binder, but works for tag binder too. */ { Binder *b = va_arg(a, Binder *); errprintf("'%s'", b ? symname_(bindsym_(b)) : "<nullbinder>"); } break; case 'c': /* tag binder -- this will simplify many err msgs. */ { TagBinder *b = va_arg(a,TagBinder *); errprintf("'%s %s'", sym_name_table[tagbindsort(b)], symname_(tagbindsym_(b))); } break; case 'e': { Expr *e = va_arg(a,Expr *); while (h0_(e) == s_invisible) e = arg1_(e); if (h0_(e) == s_binder) errprintf("'%s'", symname_(bindsym_(((Binder *)e)))); else if (h0_(e) == s_string) { char s[80]; StringSegList *z = ((String *)e)->strseg; escstring(s, 60, z->strsegbase, z->strseglen); errprintf("'\"%s\"'", s); } /* improve the next line -- I wonder what the best heuristic is. */ /* Note that any routines MUST eventually call errprintf, if you */ /* ever aspire to have listing output as well as stderr. */ else errprintf("<expr>"); } break; case 't': qprints(xtype_name(va_arg(a,TypeExpr *))); break; case 'm': errprintf("'%s'", xstg_name(va_arg(a,SET_BITMAP))); break; default: errprintf("$%c", (int)ch); /* really an error */ break; } } }