ВходНаше всё Теги codebook 无线电组件 Поиск Опросы Закон Четверг
28 ноября
254366 Топик полностью
fk0, легенда (18.05.2011 20:25, просмотров: 53) ответил vmp на Именно Си или можно C++?
От безысходности можно и C++. Но не представляю как. Задача такова: чтоб в функцию аналогичную printf() в строку формата не подсунули указатель на RAM. Или хотелось бы в runtime отличать (char*) и (char*) указатели приведённые к (const char*). Для -- см. ниже, какую хреновину изобрёл ((C) мой, получение патентов ожидается...): #include <stdio.h> #include <stdarg.h> #include <stdint.h> #include <stddef.h> #include <stdlib.h> #include <string.h> #include <unistd.h> #include <assert.h> #include <errno.h> #include <wchar.h> #include <locale.h> uint_fast8_t ptr_is_const(const void *p) { return 1; } enum e_types { T_ERROR=0, T_INT, T_LONG,T_DOUBLE, #ifndef __NO_LONG_LONG T_LLONG, #endif #ifndef __NO_LONG_DOUBLE_MATH T_LDOUBLE, #endif T_PVOID, T_INTMAX, T_PTRDIFF, T_SIZE, T_PCHAR, T_WCHAR, T_PWCHAR, T_STRERR, T_NCHARS }; static enum e_types parse_type(const char **f) { enum { _none=0, _h, _hh, _l, _ll, _L, _q, _j, _z, _t } mod = 0; while (*++*f!=0) { switch (**f) { /* flag chars, filled width and precision */ case '#': case '-': case '+': case ' ': case '\'': case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': case '*': case '$': case '.': continue; /* length modifiers */ case 'h': switch (mod) { case 0: mod=_h; continue; case _h: mod=_hh; continue; default: return T_ERROR; } case 'l': switch (mod) { case 0: mod=_l; continue; case _l: mod=_ll; continue; default: return T_ERROR; } case 'L': if (mod) return T_ERROR; mod=_L; continue; case 'q': if (mod) return T_ERROR; mod=_q; continue; case 'j': if (mod) return T_ERROR; mod=_j; continue; case 'z': case 'Z': if (mod) return T_ERROR; mod=_z; continue; case 't': if (mod) return T_ERROR; mod=_t; continue; /* type argument */ case 'd': case 'i': case 'o': case 'u': case 'x': case 'X': switch (mod) { case 0: case _h: case _hh: return T_INT; case _l: return T_LONG; #ifndef __NO_LONG_LONG case _ll: case _q: return T_LLONG; #endif case _j: return T_INTMAX; case _z: return T_SIZE; case _t: return T_PTRDIFF; default: return T_ERROR; /* not recognized */ } case 'p': if (!mod) return T_PVOID; else return T_ERROR; case 'e': case 'E': case 'f': case 'F': case 'g': case 'G': case 'a': case 'A': switch (mod) { case 0: return T_DOUBLE; #ifndef __NO_LONG_DOUBLE_MATH case _L: return T_LDOUBLE; #endif default: return T_ERROR; } case 'c': switch (mod) { case 0: return T_INT; case _l: return T_WCHAR; default: return T_ERROR; } case 'C': if (!mod) return T_WCHAR; else return T_ERROR; case 's': switch (mod) { case 0: return T_PCHAR; case _l: return T_PWCHAR; default: return T_ERROR; } case 'S': if (!mod) return T_PWCHAR; else return T_ERROR; case 'n': if (!mod) return T_NCHARS; else return T_ERROR; case 'm': if (!mod) return T_STRERR; else return T_ERROR; default: /* not supported! */ break; } } return T_ERROR; } #define MINBUFSIZE 256 static wchar_t *read_wchar(FILE *ifile) { wchar_t *buf, *nb, *ws; size_t size=MINBUFSIZE; int i; buf=malloc(size); if (buf==NULL) return NULL; ws=buf; do { if ((ws-buf)*sizeof(wchar_t) >= size) { nb=realloc(buf, size+=MINBUFSIZE); if (nb==NULL) { free(buf); return NULL; } buf=nb, size+=MINBUFSIZE; } i=getw(ifile), *ws++=i; } while (i!=EOF && i!=0); if (i!=0) { free(buf); return NULL; } nb=realloc(buf, (ws-buf)*sizeof(wchar_t)); if (nb==NULL) { free(buf); return NULL; } return nb; } static char *read_char(FILE *ifile) { char *buf, *nb, *s; size_t size=MINBUFSIZE; int i; buf=malloc(size); if (buf==NULL) return NULL; s=buf; do { if (s-buf >= size) { nb=realloc(buf, size+=MINBUFSIZE); if (nb==NULL) { free(buf); return NULL; } buf=nb, size+=MINBUFSIZE; } i=getc(ifile), *s++=i; } while (i>0); if (i<0) { free(buf); return NULL; } nb=realloc(buf, s-buf); if (nb==NULL) { free(buf); return NULL; } return nb; } int clog_read(FILE *ifile, FILE *ofile) { const char *fmt, *p; char *afmt; size_t len; enum e_types type; #define PSCALAR(type) do { \ type var; \ fread(&var, sizeof(var), 1, ifile); \ len+=fprintf(ofile, sfmt, var); \ } while(0) /* read format */ fread(&fmt, sizeof(const char*), 1, ifile); if (fmt==NULL) { fmt=afmt=read_char(ifile); if (fmt==NULL) return -1; } else afmt=NULL; while (*fmt) { char *sfmt; size_t slen; if (*fmt!='%') { fputc(*fmt++, ofile), len++; continue; } /* parse format spec. */ type=parse_type((p=fmt, &fmt)); slen=fmt-p+1, sfmt=malloc(slen+1); if (sfmt==NULL) { free(afmt); return -1; } memcpy(sfmt, p, slen), sfmt[slen]=0; switch (type) { case T_INT: PSCALAR(int); break; case T_LONG: PSCALAR(long); break; case T_DOUBLE: PSCALAR(double); break; #ifndef __NO_LONG_LONG case T_LLONG: PSCALAR(long long); break; #endif #ifndef __NO_LONG_DOUBLE_MATH case T_LDOUBLE: PSCALAR(long double); break; #endif case T_PVOID: PSCALAR(const void *); break; case T_INTMAX: PSCALAR(intmax_t); break; case T_PTRDIFF: PSCALAR(ptrdiff_t); break; case T_SIZE: PSCALAR(size_t); break; case T_WCHAR: PSCALAR(wint_t); break; case T_NCHARS: /* skip */ case T_STRERR: { int err; const char *s; fread(&err, sizeof(err), 1, ifile); s=strerror(err); len+=strlen(s); fputs(s, ofile); } break; case T_PCHAR: { char *s=read_char(ifile); if (s==NULL) { free(sfmt), free(afmt); return -1; } len+=fprintf(ofile, sfmt, s); free(s); } break; case T_PWCHAR: { wchar_t *ws=read_wchar(ifile); if (ws==NULL) { free(sfmt), free(afmt); return -1; } len=fprintf(ofile, sfmt, ws); free(ws); } break; default: /* unknown format sequence -- skip... */ break; } free(sfmt); fmt++; } free(afmt); return len; } int clog_file(FILE *file, const char *fmt, ...) { va_list args; size_t len; enum e_types type; #define SCALAR(type) do { \ type var = va_arg(args, type); \ len+=fwrite(&var, sizeof(var), 1, file); \ } while(0) assert(fmt!=NULL); { /* write format first */ const char *p; if (ptr_is_const(fmt)) p=fmt; else p=NULL; len=fwrite(&p, sizeof(p), 1, file); if (p==NULL) len+=fwrite(fmt, strlen(fmt)+1, 1, file); } va_start(args, fmt); while (*fmt) { if (*fmt!='%') { fmt++; continue; } /* parse format spec. */ type=parse_type(&fmt); switch (type) { case T_INT: SCALAR(int); break; case T_LONG: SCALAR(long); break; case T_DOUBLE: SCALAR(double); break; #ifndef __NO_LONG_LONG case T_LLONG: SCALAR(long long); break; #endif #ifndef __NO_LONG_DOUBLE_MATH case T_LDOUBLE: SCALAR(long double); break; #endif case T_PVOID: SCALAR(const void*); break; case T_INTMAX: SCALAR(intmax_t); break; case T_PTRDIFF: SCALAR(ptrdiff_t); break; case T_SIZE: SCALAR(size_t); break; case T_WCHAR: SCALAR(wint_t); break; case T_NCHARS: break; case T_STRERR: len+=fwrite(&errno, sizeof(errno), 1, file); break; case T_PCHAR: { /* zero-terminated string */ const char *s = va_arg(args, const char *); len+=fwrite(s, strlen(s)+1, 1, file); } break; case T_PWCHAR: { const wchar_t *ws = va_arg(args, const wchar_t *); len+=fwrite(ws, sizeof(wchar_t), wcslen(ws)+1, file); } break; default: fprintf(stderr, "bad format spec. %s\n", fmt); return -1; } fmt++; } return len; #undef SCALAR } #if 0 void writelog(int prio, char *fmt, ...) { abort(); } #endif int main(int argc, char *argv[]) { setlocale(LC_ALL, ""); if (argc<2) { clog_file(stdout, "test u=%u s=%s f=%LF ws=%ls\n", 12, "TEST", (long double)0.15, L"русский"); } else { clog_read(stdin, stdout); } return 0; }
[ZX]