Ejemplo n.º 1
0
ofs mcxIOappendChunk
(  mcxIO      *xf
,  mcxTing     *dst
,  dim         sz
,  mcxbits     flags cpl__unused
)
   {  unsigned long psz =  getpagesize()
   ;  dim k          =  sz / psz       /* fixme: size checks? */
   ;  dim rem        =  sz % psz
   ;  ofs r          =  1              /* pretend in case k == 0 */
  /*  mcxbool  account = flags & MCX_CHUNK_ACCOUNT ? TRUE : FALSE */
   ;  dim offset     =  dst->len
   ;  char* p

   ;  if (!dst || !xf->fp || !mcxTingEnsure(dst, dst->len + sz))
      return -1
      /* fixme set some (new) errno */

   ;  if (k)
      while (k-- > 0 && (r = read(fileno(xf->fp),  dst->str+dst->len, psz)) > 0)
      dst->len += r     /* careful with unsignedness */

                        /* ^ Note: fileno is POSIX, not c99 */
   ;  if
      (  r > 0
      && rem > 0
      && (r = read(fileno(xf->fp),  dst->str+dst->len, rem)) > 0
      )
      dst->len += r

   ;  dst->str[dst->len] = '\0'
   ;  xf->bc += dst->len - offset

   ;  for (p = dst->str+offset; p<dst->str+dst->len; p++)
      {  if (*p == '\n')
         {  xf->lc++
         ;  xf->lo_ = xf->lo
         ;  xf->lo = 0
      ;  }
         else
         xf->lo++
   ;  }
                           /* fixme; what if k == 0, rem == 0 ? */
      if (!r)                    /* fixme; other possibilities? */
      xf->ateof = 1

   ;  return dst->len
;  }
Ejemplo n.º 2
0
static mcxstatus read_abc
(  mcxIO* xf
,  mcxTing* buf
,  stream_state *iface
,  double* value
)
   {  mcxstatus status  =  mcxIOreadLine(xf, buf, MCX_READLINE_CHOMP)
   ;  mcxTing* xkey     =  mcxTingEmpty(NULL, buf->len)
   ;  mcxTing* ykey     =  mcxTingEmpty(NULL, buf->len)
   ;  mcxbits bits      =  iface->bits

   ;  mcxbool strict    =  bits & MCLXIO_STREAM_STRICT
   ;  mcxbool warn      =  bits & MCLXIO_STREAM_WARN

   ;  mcxbool label_cbits = bits & (MCLXIO_STREAM_CTAB_STRICT | MCLXIO_STREAM_CTAB_RESTRICT)
   ;  mcxbool label_rbits = bits & (MCLXIO_STREAM_RTAB_STRICT | MCLXIO_STREAM_RTAB_RESTRICT)
   ;  mcxbool label_dbits = bits & (MCLXIO_STREAM_WARN | MCLXIO_STREAM_DEBUG)

   ;  const char* printable
   ;  int cv = 0

   ;  iface->statusx =  STATUS_OK
   ;  iface->statusy =  STATUS_OK

   ;  do
      {  int xlen = 0
      ;  int ylen = 0

      ;  if (status)
         break

      ;  printable = mcxStrChrAint(buf->str, isspace, buf->len)
      ;  if (printable && (uchar) printable[0] == '#')
         {  status = mcxIOreadLine(xf, buf, MCX_READLINE_CHOMP)
         ;  continue
      ;  }

         mcxTingEnsure(xkey, buf->len)    /* fixme, bit wasteful */
      ;  mcxTingEnsure(ykey, buf->len)    /* fixme, bit wasteful */

      ;  cv =     strchr(buf->str, '\t')
               ?  sscanf(buf->str, "%[^\t]\t%[^\t]%lf", xkey->str, ykey->str, value)
               :  sscanf(buf->str, "%s%s%lf", xkey->str, ykey->str, value)

      /* WARNING: [xy]key->len have to be set.
       * we first check sscanf return value
      */

      ;  if (cv == 2)
         *value = 1.0

      ;  else if (cv != 3)
         {  if (warn || strict)
            mcxErr
            (  module
            ,  "abc-parser chokes at line %ld [%s]"
            ,  (long) xf->lc
            ,  buf->str
            )
         ;  if (strict)
            {  status = STATUS_FAIL
            ;  break
         ;  }
            status = mcxIOreadLine(xf, buf, MCX_READLINE_CHOMP)
         ;  continue
      ;  }
         else if (!(*value <= FLT_MAX))  /* should catch nan, inf */
         *value = 1.0

      ;  xlen = strlen(xkey->str)
      ;  ylen = strlen(ykey->str)

      ;  xkey->len = xlen
      ;  ykey->len = ylen

      ;     status
         =  iface->statusx
         =  handle_label(&xkey, &(iface->x), iface->map_c, label_cbits | label_dbits, "col")

      ;  if (status == STATUS_FAIL || status == STATUS_IGNORE)
         break

      ;     status
         =  iface->statusy
         =  handle_label(&ykey, &(iface->y), iface->map_r, label_rbits | label_dbits, "row")
      ;  if (status == STATUS_FAIL || status == STATUS_IGNORE)
         break

      ;  status = STATUS_OK     /* Note: status can never be STATUS_NEW */
      ;  break
   ;  }
      while (1)

;if(DEBUG2) fprintf(stderr, "read_abc status %s\n", MCXSTATUS(status))
   ;  if (status == STATUS_NEW)
      mcxErr(module, "read_abc panic, because status == STATUS_NEW")

               /* Below we remove the key from the map if it should be
                * ignored. It will be freed in the block following this one.
               */
   ;  if
      (   iface->statusx == STATUS_NEW
      && (iface->statusy == STATUS_FAIL || iface->statusy == STATUS_IGNORE)
      )
      {  mcxHashSearch(xkey, iface->map_c->map, MCX_DATUM_DELETE)
      ;  iface->map_c->max_seen--
      ;  iface->statusx = STATUS_IGNORE
   ;  }
      else if   /* Impossible (given that we break when iface->statusx) but defensive */
      (   iface->statusy == STATUS_NEW
      && (iface->statusx == STATUS_FAIL || iface->statusx == STATUS_IGNORE)
      )
      {  mcxHashSearch(ykey, iface->map_r->map, MCX_DATUM_DELETE)
      ;  iface->map_r->max_seen--
      ;  iface->statusy = STATUS_IGNORE
   ;  }

         /* NOTE handle_label might have set either to NULL but
          * that's OK.  This is needed because handle_label(&xkey)
          * might succeed and free xkey (because already present in
          * map_c->map); then when handle_label(&ykey) fails we need to
          * clean up.
         */
   ;  if (status)
      {  mcxTingFree(&xkey)   /* kv deleted if iface->statusx == STATUS_NEW */
      ;  mcxTingFree(&ykey)   /* kv deleted if iface->statusy == STATUS_NEW */
   ;  }

      return status
;  }
Ejemplo n.º 3
0
static mclx* process_queries
(  mcxIO* xq
,  mclx* mx
,  mclx* mxtp
,  mcxIO* xfmx
,  mclTab* tab
,  mcxIO* xfout
,  mcxIO* xfpath
,  mcxIO* xfstep
)
   {  mcxTing* line = mcxTingEmpty(NULL, 100)
   ;  mcxTing* sa = mcxTingEmpty(NULL, 100)
   ;  mcxTing* sb = mcxTingEmpty(NULL, 100)
   ;  SSPxy* sspo = mclgSSPxyNew(mx, mxtp)

   ;  mcxIOopen(xq, EXIT_ON_FAIL)

   ;  while (1)
      {  long a = -1, b = -2, ns = 0
      ;  mcxbool query = FALSE
      ;  if (isatty(fileno(xq->fp)))
         fprintf
         (  stdout
         ,  "\n(ready (expect two %s or : directive))\n"
         ,  tab ? "labels" : "graph indices"
         )
      ;  if
         (  STATUS_OK != mcxIOreadLine(xq, line, MCX_READLINE_CHOMP)
            || !strcmp(line->str, ".")
         )
         break

      ;  query = (u8) line->str[0] == ':'

      ;  if (query && (line->len == 1 || isspace((unsigned char) line->str[1])))
         {  fprintf(xfout->fp, "-->\n")
         ;  fprintf(xfout->fp, ":tf <tf-spec>\n")
         ;  fprintf(xfout->fp, ":top <num>\n")
         ;  fprintf(xfout->fp, ":list <node>\n")
         ;  fprintf(xfout->fp, ":clcf <node>\n")
         ;  fprintf(xfout->fp, ":reread>\n")
         ;  fprintf(xfout->fp, "<--\n")
         ;  continue
      ;  }

         mcxTingEnsure(sa, line->len)
      ;  mcxTingEnsure(sb, line->len)

      ;  ns = sscanf(line->str, "%s %s", sa->str, sb->str)
      ;  if (ns == 2)
            sa->len = strlen(sa->str)
         ,  sb->len = strlen(sb->str)
      ;  else
            sa->len = strlen(sa->str)
         ,  sb->len = 0
         ,  sb->str[0] = '\0'

      ;  if (!query && ns != 2)
         {  if (line->len)
            fprintf(stderr, "(error expect two nodes or : directive)\n")
         ;  continue
      ;  }

         if (query)
         {  mx = handle_query(mx, xfmx, sa, sb)
         ;  sspo->mx = mx                 /* fixme improve ownership handling */
         ;  sspo->mxtp = mx
         ;  fprintf(xfout->fp, "%s\n\n", line->str)
         ;  continue                      /* fixme improve flow */
      ;  }
         else if (tab)
         {  mcxKV* kv

         ;  if ((kv = mcxHashSearch(sa, hsh_g, MCX_DATUM_FIND)))
            a = VOID_TO_ULONG kv->val     /* fixme (> 2G labels) */
         ;  else
            {  label_not_found(sa)
            ;  continue
         ;  }

            if ((kv = mcxHashSearch(sb, hsh_g, MCX_DATUM_FIND)))
            b = VOID_TO_ULONG kv->val     /* fixme (> 2G labels) */
         ;  else
            {  label_not_found(sb)
            ;  continue
         ;  }
         }
         else if (mcxStrTol(sa->str, &a, NULL) || mcxStrTol(sb->str, &b, NULL))
         {  fprintf(stderr,  "(error failed-reading-number)\n")
         ;  continue
      ;  }

         if (check_bounds(mx, a))
         continue
      ;  if (check_bounds(mx, b))
         continue

      ;  fprintf
         (  xfout->fp
         ,  "\n(lattice\n"
            "   (anchors %s %s)\n"
         ,  sa->str
         ,  sb->str
         )

      ;  if (0 && a == b)
         {  fprintf
            (  xfout->fp
            ,  "  (path-length 0)\n"
               "(data\n"
            )
      ;  }
         else
         {  mcxstatus thestat = mclgSSPxyQuery(sspo, a, b)
         ;  dim t

         ;  if (thestat)
            fprintf(xfout->fp,  "   (path-length -2)\n(data\n")
         ;  else if (sspo->length < 0)       /* not in same component */
            fprintf(xfout->fp,  "   (path-length -1)\n(data\n")
         ;  else
            {  fprintf
               (  xfout->fp
               ,  "   (path-length %d)\n"
                  "(data\n"
               ,  (int) sspo->length
               )

            ;  if (sspo->length == 1)
               {  if (tab)
                  fprintf(xfout->fp, "((%s %s))\n", sa->str, sb->str)
               ;  else
                  fprintf(xfout->fp, "((%ld %ld))\n", (long) a, (long) b)
            ;  }
               else
               for (t=0; t< N_COLS(sspo->pathmx)-1; t++)
               erdos_link_together(xfout, mx, sspo->pathmx->cols+t, sspo->pathmx->cols+t+1)

            ;  fputs(")\n", xfout->fp)
            ;  fprintf(xfout->fp, "   (anchors %s %s)\n", sa->str, sb->str)
            ;  fprintf(xfout->fp, "   (considered %d)\n", (int) sspo->n_considered)
            ;  fprintf(xfout->fp, "   (participants %d)\n", (int) sspo->n_involved)
            ;  fprintf(xfout->fp, "   (path-length %d)\n", (int) sspo->length)
         ;  }
         }

         fprintf(xfout->fp, ")\n\n")

      ;  if (xfpath)
         mclxWrite(sspo->pathmx, xfpath, MCLXIO_VALUE_NONE, RETURN_ON_FAIL)
      ;  if (xfstep)
         mclxWrite(sspo->stepmx, xfstep, MCLXIO_VALUE_GETENV, RETURN_ON_FAIL)

      ;  mclgSSPxyReset(sspo)
   ;  }
      mcxTingFree(&sa)
   ;  mcxTingFree(&sb)
   ;  mcxTingFree(&line)
   ;  mclgSSPxyFree(&sspo)
   ;  return mx
;  }
Ejemplo n.º 4
0
static dim do_a_file
(  aggr** collectpp
,  const char* fname
,  dim collect_n
)
   {  mcxIO* xf = mcxIOnew(fname, "r")
   ;  mcxTing* buf = mcxTingEmpty(NULL, 100)
   ;  mcxTing* lbl = mcxTingEmpty(NULL, 100)
   ;  mcxstatus status = STATUS_OK
   ;  aggr* collect = *collectpp
   ;  dim ct = 0, collect_alloc = 0

   ;  if (!collect_n)
         collect_alloc = 100
      ,  collect = mcxNAlloc(collect_alloc, sizeof collect[0], NULL, EXIT_ON_FAIL)

   ;  mcxIOopen(xf, EXIT_ON_FAIL)

   ;  while (STATUS_OK == (status = mcxIOreadLine(xf, buf, MCX_READLINE_CHOMP)))
      {  double val
      ;  const char* tabchar = NULL
      ;  mcxbool get_header = collect_g != 'p' && !ct ? TRUE : FALSE

      ;  mcxTingEnsure(lbl, buf->len)

               /* if header_g && !ct && !paste create/check label */
               /* body of this while loop does too many things, refactor */
      ;  if (collect_g == 'p' || get_header)
         {  if (!(tabchar = strchr(buf->str, '\t')))
            mcxDie(1, me, "paste error at line %d file %s (no tab)", (int) xf->lc, fname)
         ;  mcxTingNWrite(lbl, buf->str, tabchar - buf->str)
      ;  }
         else
         {  if (2 != sscanf(buf->str, "%s%lg", lbl->str, &val))
            mcxDie(1, me, "parse error at line %d file %s", (int) xf->lc, fname)
         ;  lbl->len = strlen(lbl->str)
      ;  }

         if (!collect_n)
         {  if (ct >= collect_alloc)
            {  dim collect_realloc = collect_alloc * 1.44
            ;  collect = mcxNRealloc(collect, collect_realloc, collect_alloc, sizeof collect[0], NULL, EXIT_ON_FAIL)
            ;  collect_alloc = collect_realloc
         ;  }
            collect[ct].label = mcxTingStr(lbl)
         ;  collect[ct].val = collect_g == 'p' || get_header ? 0.0 : val
         ;  collect[ct].columns
            =      collect_g == 'p' || get_header
                ?  mcxTingNew(tabchar + (get_header ? 1 : 0))
                :  NULL
      ;  }
         else
         {  if (ct >= collect_n)
            mcxDie(1, me, "additional lines in file %s", fname)
         ;  if (strcmp(collect[ct].label, lbl->str))
            mcxDie
            (  1
            ,  me
            ,  "label conflict %s/%s at line %d in file %s"
            ,  collect[ct].label
            ,  lbl->str
            ,  (int) xf->lc, fname
            )
         ;  if (get_header)            /* only need to check identity */
            {  if (strcmp(tabchar+1, collect[ct].columns->str))
               mcxDie(1, me, "different columns <%s> and <%s>", collect[ct].columns->str, tabchar+1)
         ;  }
            else if (collect_g == 'p')          /* tack it on */
            mcxTingNAppend(collect[ct].columns, tabchar, buf->len - lbl->len)
         ;  else
            collect[ct].val += val 
      ;  }
         ct++
   ;  }

      if (collect_n)
      {  if (ct != collect_n)
         mcxDie(1, me, "not enough lines in file %s", fname)
   ;  }
      else
      {  if (!ct)
         mcxDie(1, me, "empty file(s)")
      ;  *collectpp = collect
   ;  }

      mcxIOfree(&xf)
   ;  return ct
;  }