chiark / gitweb /
WIP routesearch; debugging is optional; bugfixes fixed the bug in TODO
[ypp-sc-tools.db-test.git] / yarrg / common.c
index cc33235..35b8969 100644 (file)
@@ -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<0) 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));
 }