chiark / gitweb /
compiles and does little
authorian <ian>
Fri, 22 Oct 2004 19:04:46 +0000 (19:04 +0000)
committerian <ian>
Fri, 22 Oct 2004 19:04:46 +0000 (19:04 +0000)
layout/subseg2display.c

index ebd9e7e1c9aa2050c03208fd0ae93736d3ad719b..ae9a139f752a34c0a74a03c32ca00f71c68f8e5f 100644 (file)
  *   subseg2display encoding.ppm [status-info ...]
  *
  * status-info args are:
- *   <subseg> <alpha> <red> <green> <blue>
+ *   <idchar> <alpha> <red> <green> <blue>
+ *   .. <alpha> <red> <green> <blue>
+ *   <idchar><subseg>
+ *
+ * `..' group is for unspecified segments.
  *
  * <subseg> is
  *   <segnum>               for fixed track
  *   <segnum>.<movfeatpos>  for part of a moveable feature
- * where numbers are in strtoul format, movfeatpos is the
+ * where numbers are in strtoul base=0 format, movfeatpos is the
  * moveable feature and position as in segcmapassign and
- * if <subseg> is `.', spec is for unspecified segments.
  *
  * Resulting pixel is
  *                                               [ red   ]
  *    (alpha * DIRECTION_COLOUR) + ((1-alpha) *  [ green ] )
  *                                               [ blue  ]
- *
- * status.bin has the following format:
- *   16 bits number of segments
- *   2 
  */
 
-int main(int argc, const char *const *argv) {
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <assert.h>
+#include <math.h>
+
+#include <publib.h>
+#include <ppm.h>
+
+/*---------- lookup data structure ----------*/
+
+struct idinfo {
+  double alpha, red, green, blue;
+};
+
+typedef unsigned char id;
+
+struct movperseg {
+  id *lookup;
+  int lookup_a;
+};
+
+#define NCHARS 256
+#define MAXSEGNUM ((1<<10)-1)
+#define MAXMOVFEATPOS ((1<<6)-1)
+
+static struct idinfo idinfo[NCHARS];
+
+static id *fixed;
+static int fixed_a;
+
+static struct movperseg *moveable;
+static int moveable_a;
+
+/*---------- arg parsing helper routines ----------*/
+
+static char **argv;
+
+static void badusage(void) {
+  fprintf(stderr,"bad usage\n");
+  exit(12);
+}
+
+static const char *nextarg(void) {
+  if (!*argv) badusage();
+  return *argv++;
+}
+
+static double doublearg(void) {
+  const char *arg= nextarg();
+  char *ep;
+  double v;
+
+  errno= 0;
+  v= strtod(arg,&ep);
+  if (*ep) badusage();
+  if (errno) badusage();
+  if (!finite(v)) badusage();
+
+  return v;
+}
+
+/*---------- specification args ----------*/
+
+static void idgroupargs(id ix) {
+  struct idinfo *r;
+
+  r= &idinfo[ix];
+
+  r->alpha = doublearg();
+  r->red   = doublearg();
+  r->green = doublearg();
+  r->blue  = doublearg();
+}
+
+static void ensure_somethings(void **ary, int *allocd, int want, size_t item,
+                             void zero(void *data, int count)) {
+  int new_allocd;
+  
+  if (*allocd > want) return;
+  new_allocd= (*allocd+1)*2;
+  *ary= xrealloc(*ary, new_allocd * item);
+  zero((char*)*ary + item * *allocd, new_allocd - *allocd);
+  *allocd= new_allocd;
+}
+
+static void zero_ids(void *data, int count) {
+  memset(data,0, count*sizeof(id));
+}
+
+static void zero_mps(void *data_v, int count) {
+  struct movperseg *data= data_v;
+  for (count /= sizeof(*data);
+       count > 0;
+       count--, data++) {
+    data->lookup= 0;
+    data->lookup_a= 0;
+  }
+}
+
+#define ENSURE_THINGS(sfx,type)                                                \
+  static void ensure_##sfx(type **ary_io, int *allocd, int want) {     \
+    void *ary= *ary_io;                                                        \
+    ensure_somethings(ary,allocd,want,sizeof(**ary_io),zero_##sfx);    \
+    *ary_io= ary;                                                      \
+  }                                                                    \
+  struct eat_semicolon
+
+ENSURE_THINGS(ids,id);
+ENSURE_THINGS(mps,struct movperseg);
+
+static void subsegarg(id ix, const char *arg) {
+  struct idinfo *r;
+  struct movperseg *mps;
+  unsigned long segnum, movfeatpos;
+  char *ep;
+  
+  r= &idinfo[ix];
+
+  errno= 0;
+  segnum= strtoul(arg,&ep,0);
+  if (errno) badusage();
+  if (segnum > MAXSEGNUM) badusage();
+
+  if (!*ep) {
+    ensure_ids(&fixed,&fixed_a,segnum);
+    fixed[segnum]= ix;
+    return;
+  }
+
+  if (*ep != '.') badusage();
+
+  errno= 0;
+  movfeatpos= strtoul(ep+1,&ep,0);
+  if (*ep || errno) badusage();
+  if (movfeatpos > MAXMOVFEATPOS) badusage();
+
+  ensure_mps(&moveable,&moveable_a,segnum);
+  mps= &moveable[ix];
+  ensure_ids(&mps->lookup,&mps->lookup_a, movfeatpos ^ MAXMOVFEATPOS);
+  mps->lookup[movfeatpos ^ MAXMOVFEATPOS]= ix;
+}  
+
+/*---------- actual image processing ----------*/
+
+static int cols, rows, informat;
+static pixval maxval;
+static FILE *encodingfile;
+
+static void badformat(const char *m) {
+  fprintf(stderr,"bad format: %s\n", m);
+  exit(12);
+}
+
+static void process(void) {
+  ppm_readppminit(encodingfile, &cols, &rows, &maxval, &informat);
+  if (maxval != 255) badformat("bad maxval");
+  if (informat != RPPM_FORMAT) badformat("bad format");
+  ppm_writeppminit(stdout, cols, rows, 255, 0);
+}
+
+int main(int argc_spec, char **argv_spec) {
+  const char *arg, *encodingfilename;
+
+  ppm_init(&argc_spec,argv_spec);
+  
+  argv= argv_spec;
+  nextarg();
+  encodingfilename= nextarg();
+  while (*argv) {
+    arg= nextarg();
+    if (!*arg) badusage();
+    if (!arg[1]) idgroupargs(arg[0]);
+    else if (!strcmp(arg,"..")) idgroupargs(0);
+    else subsegarg(arg[0],arg+1);
+  }
+
+  encodingfile= fopen(encodingfilename, "rb");
+  if (!encodingfile) { perror(encodingfilename); exit(8); }
+  process();
+  return 0;
 }