chiark / gitweb /
features are named rather than lettered; define the features
authorian <ian>
Thu, 26 Jun 2008 15:52:14 +0000 (15:52 +0000)
committerian <ian>
Thu, 26 Jun 2008 15:52:14 +0000 (15:52 +0000)
hostside/homes.record
hostside/realtime.h
hostside/record-l.l
hostside/record-y.y
hostside/record.c

index 12420bec922a4b53cf2d35f2c86d973d61276739..05275b9063736515c09d2c02bc562d97615ccbac 100644 (file)
@@ -1,3 +1,17 @@
 train santafe home -X8
 train shinkansen home -X7 -X9 -X11 -A5 -A6
+
+feature shinkansen head                is 1 5
+feature shinkansen head-red    is 1 6
+feature shinkansen tail                is 1 7
+feature shinkansen tail-red    is 1 8
+
+feature santafe head           is 2 5
+feature santafe tail           is 2 6
+
+feature bavarian head          is 4 5
+feature bavarian tail          is 4 6
+
+feature hoover motor           is 5 step 60
+
 end
index bd67a7a92b43c6d3ac4ccc26c79c3586295ceeed..419f1436fa6814cca9621ecd2861b70b8e8741e8 100644 (file)
@@ -80,24 +80,25 @@ typedef struct FeaturesAddr {
 } FeaturesAddr;
 
 typedef struct {
+  char *pname; /* first, for pname1st_compar */
   FeaturesAddr *a;
   int bitval; /* may have no or several bits set */
   int speedstep; /* -ve means backwards; 0 means not to use motor for feat */
 } FeaturesFeature;
 
 typedef struct FeaturesTarget {
-  struct FeaturesTarget *next;
-  char *pname;
-  char *featchs; /* null-terminated */
-  FeaturesFeature **feats; /* same order as featchs */
+  char *pname; /* first, for pname1st_compar */
+  int n_feats;
+  FeaturesFeature *feats;
 } FeaturesTarget;
 
 extern int n_trains;
 extern Train *trains;
 extern Segment *segments;
 
+extern int n_feattargs;
 extern FeaturesTarget *feattargs;
-extern FeaturesAddr *feataddrs;
+extern FeaturesAddr *feataddrs_head;
 
 /*---------- global variables, in realtime.c ----------*/
 
index c514a098ad660078ecb399dee81c6b63c0eafee8..053a0e80cc5022440285eb7c1b1a9a451a2a930b 100644 (file)
@@ -31,7 +31,6 @@ end           { STRT END; }
  /* new keywords must be added to %token<name> and ident: in record-y.y */
 
 [A-Za-z][A-Za-z0-9_]+  { STRT IDENT; }
-[a-z]          { STRT FEATLETTER; }
 
 [0-9]{0,8}     { record_yylval.num= strtoul(yytext,0,10); return NUM; }
 [0-9]{9}       { record_yyerror("number too long"); }
index 8ddbe8ba73d658a5ea3d3b0c74ac4bb849c0a89f..5042851e35f2e2f3f4d290a071b387491df809ad 100644 (file)
@@ -18,7 +18,7 @@ static Train *cur_train;
 }
 
 %token <name>  TRAIN FEATURE SEG  IS AT HAS INVERTED STEP STOPS HOME  END
-%token <name>  IDENT FEATLETTER
+%token <name>  IDENT
 %token <name>  NL
 %token <num>   NUM
 %token <dbl>   DBL
@@ -79,14 +79,14 @@ segments:   { cur_train= (void*)-1; }
 ident:         TRAIN | SEG
        |       IS | AT | HAS | INVERTED | STEP | STOPS | HOME
        |       END
-       |       IDENT | FEATLETTER
+       |       IDENT
 
 dbl:           DBL
        |       NUM { $$= $1 }
 
 seg:           ident { $$= record_pname2seg($1); }
 train:         ident { $$= record_pname2train($1); }
-feature:       ident FEATLETTER { $$= record_pname2feature($1,$2); }
+feature:       ident ident { $$= record_pname2feature($1,$2); }
 feataddr:      NUM { $$= record_feataddr($1); }
 
 end:           END NL
index f22d5b0c04571ab3d0633014c25655df44b3e266..dedd6637a5c32346414caaeada6b556dfa5f08e6 100644 (file)
@@ -10,8 +10,8 @@
  *  train <trainpn> stops <step> at <distance> after <milliseconds>
  *  seg <segpn> has [-]<ownerpn> [inverted]
  *  seg <segpn> at <movposcomb>
- *  feature <trainorfeatpn> <letter> is <addr> <nmranum>
- *  feature <trainorfeatpn> <letter> is <addr> step [-]<nmranum>
+ *  feature <trainorfeatpn> <featpn> is <addr> <nmranum>
+ *  feature <trainorfeatpn> <featpn> is <addr> step [-]<nmranum>
  *
  * speed is floating point in m/s
  */
@@ -21,8 +21,9 @@
 #include "record-i.h"
 #include "record-l.h"
 
+int n_feattargs;
 FeaturesTarget *feattargs;
-FeaturesAddr *feataddrs;
+FeaturesAddr *feataddrs_head;
 
 /*---------- input and error handling ----------*/
 
@@ -75,13 +76,25 @@ Segment *record_pname2seg(const char *pname) {
     }                                                          \
   }while(0)
 
+#define ARY_FIND_OR_APPEND(things,n_things,i,entry,found,fillin) do{   \
+    for ((i)=0, (entry)=(things);                                      \
+        (i)<(n_things) && !(found);                                    \
+        (i)++, (entry)++);                                             \
+    if ((i) >= (n_things)) {                                           \
+      (n_things)++;                                                    \
+      (things)= mrealloc((things), sizeof(*things) * (n_things));      \
+      entry= &(things)[(i)];                                           \
+      fillin;                                                          \
+    }                                                                  \
+  }while(0)
+
 FeaturesAddr *record_feataddr(int num) {
   FeaturesAddr **search, *node;
   
   if (num<1 || num>0x3ff) record_yyerror("feature address out of range");
 
   SLIST_FIND_OR_INSERT
-    (feataddrs,search,node, node->addr == num, ({
+    (feataddrs_head,search,node, node->addr == num, ({
       int i;
       node->next= 0;
       node->addr= num;
@@ -92,38 +105,26 @@ FeaturesAddr *record_feataddr(int num) {
   return node;
 }
 
-FeaturesFeature *record_pname2feature(const char *name, const char *letter) {
-  FeaturesTarget **search, *node;
+FeaturesFeature *record_pname2feature(const char *targpn, const char *featpn) {
+  int i;
+  FeaturesTarget *targ;
   FeaturesFeature *feat;
-  char *p;
-  int l;
-  
   if (!trains) return 0; /* 2nd pass only */
-  assert(letter[0] && !letter[1]);
 
-  SLIST_FIND_OR_INSERT
-    (feattargs,search,node, !strcmp(name,node->pname), ({
-      node->pname= mstrdup(name);
-      node->featchs= 0;
-      node->feats= 0;
+  ARY_FIND_OR_APPEND
+    (feattargs,n_feattargs,i,targ, !strcmp(targ->pname, targpn), ({
+      targ->pname= mstrdup(targpn);
+      targ->n_feats= 0;
+      targ->feats= 0;
     }));
 
-  l= node->featchs ? strlen(node->featchs) : 0;
-  if (l) {
-    p= strchr(node->featchs, letter[0]);
-    if (p) return node->feats[p - node->featchs];
-  }
-
-  node->featchs= mrealloc(node->featchs,l+2);
-  node->featchs[l]= letter[0];
-  node->featchs[l+1]= 0;
-
-  node->feats= mrealloc(node->feats, (l+1)*sizeof(*node->feats));
-  node->feats[l]= feat= mmalloc(sizeof(*feat));
-
-  feat->a= 0;
-  feat->bitval= 0;
-  feat->speedstep= 0;
+  ARY_FIND_OR_APPEND
+    (targ->feats,targ->n_feats,i,feat, !strcmp(feat->pname, featpn), ({
+      feat->pname= mstrdup(featpn);
+      feat->a= 0;
+      feat->bitval= 0;
+      feat->speedstep= 0;
+    }));
 
   return feat;
 }
@@ -260,6 +261,24 @@ void record_feature_motor(FeaturesFeature *feat, FeaturesAddr *addr,
   feat->speedstep= speed;
 }
 
+static int pname1st_compar(const void *av, const void *bv) {
+  const char *const *a= av;
+  const char *const *b= bv;
+  return strcmp(*a,*b);
+}
+
+static void features_postprocess(void) {
+  int i;
+  FeaturesTarget *targ;
+  
+  qsort(feattargs, n_feattargs, sizeof(*feattargs), pname1st_compar);
+
+  for (i=0, targ=feattargs;
+       i<n_feattargs;
+       i++, targ++)
+    qsort(targ->feats, targ->n_feats, sizeof(*targ->feats), pname1st_compar);
+}
+
 /*---------- speed curves ----------*/
 
 static SpeedRange *rangebuf;
@@ -470,6 +489,7 @@ void records_parse(const char **argv) {
   parse_pass(argv); /* trains!=0: populates data area */
   record_tempzone_clear();
   speeds_postprocess();
+  features_postprocess();
   record_tempzone_freeall();
   record_yylex_destroy();
 }