X-Git-Url: http://www.chiark.greenend.org.uk/ucgi/~yarrgweb/git?p=ypp-sc-tools.db-live.git;a=blobdiff_plain;f=yarrg%2Fcommon.c;h=35b8969811f89cf7a10961dc1b4069638b8de246;hp=f95e585866657f8d8e29c19c7c31b5daeae9c977;hb=683d7344fb6dc8c5b98263e648e46087e5fe91f1;hpb=c68fb80a6bbf7acbcac4b2cb2143f5fea745cd2b;ds=sidebyside diff --git a/yarrg/common.c b/yarrg/common.c index f95e585..35b8969 100644 --- a/yarrg/common.c +++ b/yarrg/common.c @@ -33,6 +33,13 @@ void *mmalloc(size_t sz) { sysassert( r= malloc(sz) ); return r; } +void *mcalloc(size_t sz) { + void *r; + if (!sz) return 0; + sysassert( r= malloc(sz) ); + memset(r, 0, sz); + return r; +} void *mrealloc(void *p, size_t sz) { assert(sz); void *r; @@ -40,129 +47,123 @@ void *mrealloc(void *p, size_t sz) { return r; } +DEFINE_VWRAPPERF(, progress, ) +DEFINE_VWRAPPERF(, progress_log, ) +DEFINE_VWRAPPERF(, progress_spinner, ) +DEFINE_VWRAPPERF(, warning, ) +DEFINE_VWRAPPERF(, fatal, NORET) -FILE *dbfile; -static const char *basepath; /* as passed in by caller */ -static pid_t dbzcat; - -int dbfile_gzopen(const char *basepath_spec) { - assert(!dbfile); - - basepath= basepath_spec; +static int last_progress_len; - char *zpath= masprintf("%s.gz", basepath); - int e= gzopen(zpath, O_RDONLY, &dbfile, &dbzcat, 0); - free(zpath); - if (e) { errno=e; sysassert(errno==ENOENT); return 0; } +static void vprogress_core(int spinner, const char *fmt, va_list al) { + int r; - return 1; -} + if (o_quiet) return; + if (!debug_flags && !isatty(2)) return; + + if (last_progress_len) + putc('\r',stderr); -int dbfile_open(const char *tpath) { - assert(!dbfile); + r= vfprintf(stderr,fmt,al); - basepath= tpath; + if (spinner) { + putc(spinner,stderr); + r++; + } - dbzcat= -1; - dbfile= fopen(tpath,"r"); - if (!dbfile) { sysassert(errno==ENOENT); return 0; } - return 1; -} + if (r < last_progress_len) { + fprintf(stderr,"%*s", last_progress_len - r, ""); + if (!r) putc('\r', stderr); + else while (last_progress_len-- > r) putc('\b',stderr); + } + last_progress_len= r; -void dbfile_close(void) { - gzclose(&dbfile, &dbzcat, basepath); + if (ferror(stderr) || fflush(stderr)) _exit(16); } - -#define dbassertgl(x) ((x) ? (void)0 : dbfile_assertfail(file,line,#x)) - -void dbfile_getsline(char *lbuf, size_t lbufsz, const char *file, int line) { - errno=0; - char *s= fgets(lbuf,lbufsz,dbfile); - sysassert(!ferror(dbfile)); - dbassertgl(!feof(dbfile)); - assert(s); - int l= strlen(lbuf); - dbassertgl(l>0); dbassertgl(lbuf[--l]=='\n'); - lbuf[l]= 0; + +void vprogress(const char *fmt, va_list al) { vprogress_core(0,fmt,al); } +void vprogress_spinner(const char *fmt, va_list al) { + static const char spinchars[]="/-\\"; + static int spinner; + + vprogress_core(spinchars[spinner],fmt,al); + spinner++; + spinner %= (sizeof(spinchars)-1); } -int dbfile_vscanf(const char *fmt, va_list al) { - int r= vfscanf(dbfile,fmt,al); - sysassert(!ferror(dbfile)); - return r; +void vprogress_log(const char *fmt, va_list al) { + if (o_quiet) return; + + progress(""); + vfprintf(stderr,fmt,al); + putc('\n',stderr); + fflush(stderr); } -int dbfile_scanf(const char *fmt, ...) { - va_list al; - va_start(al,fmt); - int r= dbfile_vscanf(fmt,al); - va_end(al); - return r; +void vwarning(const char *fmt, va_list al) { + progress(""); + fputs("Warning: ",stderr); + vfprintf(stderr,fmt,al); + fputs("\n",stderr); + fflush(stderr); } -void dbfile_assertfail(const char *file, int line, const char *m) { - if (dbzcat) - fatal("Error in dictionary file %s.gz:\n" - " Requirement not met at %s:%d:\n" - " %s", - basepath, file,line, m); - else if (dbfile) - fatal("Error in dictionary file %s at byte %ld:\n" - " Requirement not met at %s:%d:\n" - " %s", - basepath,(long)ftell(dbfile), file,line, m); - else - fatal("Semantic error in dictionaries:\n" - " Requirement not met at %s:%d:\n" - " %s", - file,line, m); +void vfatal(const char *fmt, va_list al) { + progress(""); + fputs("\n\nFatal error: ",stderr); + vfprintf(stderr,fmt,al); + fflush(stderr); + fputs("\n\n",stderr); + _exit(4); } -int gzopen(const char *zpath, int oflags, FILE **f_r, pid_t *pid_r, - const char *gziplevel /* 0 for read; may be 0, or "-1" etc. */) { - - int zfd= open(zpath, oflags, 0666); - if (!zfd) return errno; - - int pipefds[2]; - sysassert(! pipe(pipefds) ); +void sysassert_fail(const char *file, int line, const char *what) { + int e= errno; + progress(""); + fprintf(stderr, + "\nfatal operational error:\n" + " unsuccessful execution of: %s\n" + " %s:%d: %s\n\n", + what, file,line, strerror(e)); + _exit(16); +} - int oi,io; const char *cmd; const char *stdiomode; - switch ((oflags & O_ACCMODE)) { - case O_RDONLY: oi=0; io=1; cmd="gunzip"; stdiomode="r"; break; - case O_WRONLY: oi=1; io=0; cmd="gzip"; stdiomode="w"; break; - default: abort(); +void waitpid_check_exitstatus(pid_t pid, const char *what, int sigpipeok) { + pid_t got; + int st; + for (;;) { + got= waitpid(pid, &st, 0); + if (pid==-1) { sysassert(errno==EINTR); continue; } + break; } - - sysassert( (*pid_r=fork()) != -1 ); - if (!*pid_r) { - sysassert( dup2(zfd,oi)==oi ); - sysassert( dup2(pipefds[io],io)==io ); - sysassert(! close(zfd) ); - sysassert(! close(pipefds[0]) ); - sysassert(! close(pipefds[1]) ); - execlp(cmd,cmd,gziplevel,(char*)0); - sysassert(!"execlp gzip/gunzip"); + sysassert( got==pid ); + + if (WIFEXITED(st)) { + if (WEXITSTATUS(st)) + fatal("%s failed with nonzero exit status %d", + what, WEXITSTATUS(st)); + } else if (WIFSIGNALED(st)) { + if (!sigpipeok || WTERMSIG(st) != SIGPIPE) + fatal("%s died due to signal %s%s", what, + strsignal(WTERMSIG(st)), WCOREDUMP(st)?" (core dumped)":""); + } else { + fatal("%s gave strange wait status %d", what, st); } - sysassert(! close(zfd) ); - sysassert(! close(pipefds[io]) ); - sysassert( *f_r= fdopen(pipefds[oi], stdiomode) ); +} - return 0; +char *masprintf(const char *fmt, ...) { + char *r; + va_list al; + va_start(al,fmt); + sysassert( vasprintf(&r,fmt,al) >= 0); + sysassert(r); + va_end(al); + return r; } -void gzclose(FILE **f, pid_t *p, const char *what) { - if (!*f) return; - - sysassert(!ferror(*f)); - sysassert(!fclose(*f)); - - if (*p != -1) { - char *process= masprintf("%s (de)compressor",what); - waitpid_check_exitstatus(*p,process,1); - free(process); - *p= -1; - } +unsigned debug_flags; - *f= 0; +void debug_flush(void) { + sysassert(!ferror(debug)); + sysassert(!fflush(debug)); }