} 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 ----------*/
* 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
*/
#include "record-i.h"
#include "record-l.h"
+int n_feattargs;
FeaturesTarget *feattargs;
-FeaturesAddr *feataddrs;
+FeaturesAddr *feataddrs_head;
/*---------- input and error handling ----------*/
} \
}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;
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;
}
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;
parse_pass(argv); /* trains!=0: populates data area */
record_tempzone_clear();
speeds_postprocess();
+ features_postprocess();
record_tempzone_freeall();
record_yylex_destroy();
}