#define FEATURESADDR_TRANSMITS 4
/* 0..2 are func0to4 func5to8 func9to12 and speed cmd
- * pi.l is 0 if not applicable */
+ * pi.l is 0 if not transmitting */
typedef struct FeaturesAddr {
struct FeaturesAddr *next;
- int addr;
- unsigned current, permitted; /* nmra features */
+ int addr, cbitmap;
RetransmitRelaxedNode rn[FEATURESADDR_TRANSMITS];
} FeaturesAddr;
+typedef struct {
+ 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 */
+} FeaturesTarget;
+
extern int n_trains;
extern Train *trains;
extern Segment *segments;
+extern FeaturesTarget *feattargs;
extern FeaturesAddr *feataddrs;
/*---------- global variables, in realtime.c ----------*/
is { STRT IS; }
at { STRT AT; }
has { STRT HAS; }
-minus { STRT MINUS; }
+inverted { STRT INVERTED; }
step { STRT STEP; }
stops { STRT STOPS; }
home { STRT HOME; }
double dbl;
}
-%token <name> TRAIN FEATURE SEG IS AT HAS MINUS STEP STOPS HOME END
+%token <name> TRAIN FEATURE SEG IS AT HAS INVERTED STEP STOPS HOME END
%token <name> IDENT FEATLETTER
%token <name> NL
%token <num> NUM
{ if ($2) record_seg_at($2,$4);
}
| FEATURE feature IS feataddr NUM
- { if ($4) record_feature_nmrafeat($4,$5);
+ { if ($2) record_feature_nmrafeat($2,$4,$5);
}
| FEATURE feature IS feataddr STEP NUM
- { if ($4) record_feature_motor($4,$6);
+ { if ($2) record_feature_motor($2,$4,$6);
}
backwards: /* empty */ { $$= 0; }
| '-' { $$= 1; }
inverted: /* empty */ { $$= 0; }
- | MINUS { $$= 1; }
+ | INVERTED { $$= 1; }
segments: { cur_train= (void*)-1; }
| backwards seg { record_train_home(cur_train,$1,$2); } segments
ident: TRAIN | SEG
- | IS | AT | HAS | MINUS | STEP | STOPS | HOME
+ | IS | AT | HAS | INVERTED | STEP | STOPS | HOME
| END
| IDENT | FEATLETTER
seg: ident { $$= record_pname2seg($1); }
train: ident { $$= record_pname2train($1); }
-feature: ident ident { record_feature_public($1,$2); }
- | ident MINUS { record_feature_private(); }
+feature: ident FEATLETTER { $$= record_pname2feature($1,$2); }
feataddr: NUM { $$= record_feataddr($1); }
end: END NL
* train <trainpn> stops <step> at <distance> after <milliseconds>
* seg <segpn> has [-]<ownerpn> [inverted]
* seg <segpn> at <movposcomb>
- * feature <trainpn> <featpn>|- is <addr> <nmranum>
- * feature <trainpn> <featpn>|- is <addr> step [-]<nmranum>
+ * feature <trainorfeatpn> <letter> is <addr> <nmranum>
+ * feature <trainorfeatpn> <letter> is <addr> step [-]<nmranum>
*
* speed is floating point in m/s
*/
#include "record-i.h"
#include "record-l.h"
+FeaturesTarget *feattargs;
FeaturesAddr *feataddrs;
-static char *feat_train, *feat_feat;
-
/*---------- input and error handling ----------*/
static const char *filename;
return node;
}
-static void record_feature_freeold(void) {
- free(feat_train);
- free(feat_feat);
-}
+FeaturesFeature *record_pname2feature(const char *name, const char *letter) {
+ FeaturesTarget **search, *node;
+ FeaturesFeature *feat;
+ char *p;
+ int l;
+
+ if (!trains) return 0; /* 2nd pass only */
+ assert(letter[0] && !letter[1]);
-void record_feature_public(const char *name, const char *feat) {
- record_feature_freeold();
- feat_train= mstrdup(name);
- feat_feat= mstrdup(feat);
-}
+ SLIST_FIND_OR_INSERT
+ (feattargs,search,node, !strcmp(name,node->pname), ({
+ node->pname= mstrdup(name);
+ node->featchs= 0;
+ node->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;
-void record_feature_private(void) {
- record_feature_freeold();
- feat_train= feat_feat= 0;
+ return feat;
}
/*---------- zone allocator for strings ----------*/