From b668ac0180e5a6cef96280fd77b0dc3a44fcdd5e Mon Sep 17 00:00:00 2001 From: ian Date: Sun, 10 Sep 2006 18:37:11 +0000 Subject: [PATCH] giant reorg abolishes TrainNum most of the time; working on making it build --- hostside/.cvsignore | 2 +- hostside/Makefile | 6 +- hostside/actual.c | 12 +- hostside/common.h | 3 + hostside/dummy-trains.c | 2 + hostside/main.c | 4 - hostside/realtime.c | 64 +++++----- hostside/realtime.h | 18 ++- hostside/record-l.l | 24 ++-- hostside/record-y.y | 51 ++++---- hostside/record.c | 255 ++++++++++++++++++++++++++++++++++++++++ hostside/record.h | 27 +++++ hostside/rtmacros.h | 13 -- hostside/safety.c | 134 ++++++++++----------- hostside/safety.h | 89 ++++++++------ hostside/speed.c | 82 ++++++------- hostside/startup.c | 2 +- hostside/trackloc.c | 12 +- hostside/utils.c | 4 + layout/data2safety | 5 +- layout/layout-data.h | 36 ++---- 21 files changed, 557 insertions(+), 288 deletions(-) create mode 100644 hostside/record.h delete mode 100644 hostside/rtmacros.h diff --git a/hostside/.cvsignore b/hostside/.cvsignore index 62750d5..82443ed 100644 --- a/hostside/.cvsignore +++ b/hostside/.cvsignore @@ -11,5 +11,5 @@ gui-plan-bot selectors.h errorcodes.h retransmit-table.h -record-l.c +record-l.[ch] record-y.[ch] diff --git a/hostside/Makefile b/hostside/Makefile index a718672..caca325 100644 --- a/hostside/Makefile +++ b/hostside/Makefile @@ -17,6 +17,8 @@ hostside-old: serialio.o nmra.o main.o encode.o utils.o BESSAR=bessar:things/trains-bessar/hostside/. +SPECIAL_CFLAGS_record-l= $(FLEXCFLAGS) + on-bessar: $(TARGETS) RSYNC_RSH=fsh rsync $(TARGETS) $(BESSAR) @@ -24,9 +26,11 @@ on-bessar: $(TARGETS) RSYNC_RSH=fsh rsync $^ $(BESSAR) realtime: realtime.o startup.o cdumgr.o safety.o trackloc.o \ - actual.o dummy-trains.o \ + speed.o actual.o retransmit.o \ cmdinput.o obc.o eventhelp.o \ + record.o record-l.o record-y.o \ utils.o serialio.o parseutils.o auproto-pic.o \ + nmra.o encode.o \ ../layout/ours.layout-data.o \ __oop-read-copy.o -loop $(LINK) diff --git a/hostside/actual.c b/hostside/actual.c index ef86d3a..21eef04 100644 --- a/hostside/actual.c +++ b/hostside/actual.c @@ -7,9 +7,6 @@ static PicInsn polarityinsn= { { 0x90 }, 0 }; -#define SEG \ - const SegmentInfo *segi= &info_segments[segn]; - #define OPONBIT_BYTE (polarityinsn.d[bytenum]) #define OPONBIT(body) do{ \ BoardObject bo; \ @@ -25,8 +22,7 @@ static PicInsn polarityinsn= { { 0x90 }, 0 }; { body } \ }while(0) -int picinsn_polarity_testbit(const PicInsn *pi, SegmentNum segn) { - SEG; +int picinsn_polarity_testbit(const PicInsn *pi, const SegmentInfo *segi) { OPONBIT({ return !!(OPONBIT_BYTE & bitv); }); @@ -36,10 +32,8 @@ void actual_inversions_start(void) { polarityinsn.l= (info_maxreverse + 4 + 6) / 7; } -void actual_inversions_segment(SegmentNum segn) { - SEG; - State *s= &safety_state; - const SegmentState *seg= &s->segments[segn]; +void actual_inversions_segment(Segment *seg) { + const SegmentInfo *segi= seg->i; OPONBIT({ Byte *insnbyte= &OPONBIT_BYTE; diff --git a/hostside/common.h b/hostside/common.h index 83754b3..b44acbd 100644 --- a/hostside/common.h +++ b/hostside/common.h @@ -97,10 +97,13 @@ void die_vprintf_hook(const char *fmt, va_list al) __attribute__((format(printf,1,0))); void *mmalloc(size_t sz); +void *mrealloc(void *old, size_t sz); char *mstrdupl(const char *s, int l); char *mstrdup(const char *s); void mgettimeofday(struct timeval *tv); +void badusage(const char *why); + #define massert(x) ((x) ? (void)0 : diem()) /*---------- from serialio.c ----------*/ diff --git a/hostside/dummy-trains.c b/hostside/dummy-trains.c index 86bd7c1..f03295a 100644 --- a/hostside/dummy-trains.c +++ b/hostside/dummy-trains.c @@ -1,6 +1,8 @@ /* */ +FIXME this should go in a config file + #include "realtime.h" #define NOTA_TRAIN { 0,0,0,0, "internal-error-not-a-train" } diff --git a/hostside/main.c b/hostside/main.c index 6ea07ec..1a8ffbd 100644 --- a/hostside/main.c +++ b/hostside/main.c @@ -30,10 +30,6 @@ static Nmra buf; void die_hook(void) { } void die_vprintf_hook(const char *fmt, va_list al) { } -static void badusage(const char *why) { - fprintf(stderr,"bad usage: %s\n",why); exit(8); -} - static void pahex(const char **argv) { const char *data_string; char hbuf[3], *ep; diff --git a/hostside/realtime.c b/hostside/realtime.c index cb8274c..629b515 100644 --- a/hostside/realtime.c +++ b/hostside/realtime.c @@ -10,7 +10,7 @@ const char *progname= "realtime"; CommandInput cmdi; -static const char *device; +static const char *device= "/dev/ttya0"; /*---------- general event handling ----------*/ @@ -40,48 +40,48 @@ static void *read_exception(oop_source *evts, int fd, /*---------- logging etc. ----------*/ -static char *transegn2suffixstring(TrainNum tran, SegmentNum segn) { - /* Either arg may be NOTA(...), in which case it's not included. +static char *transegn2suffixstring(Train *tra, Segment *seg) { + /* Either arg may be 0, in which case it's not included. * Result string will be empty, or start with ": " * Result string is from malloc. * Never fails. */ - const char *tra, *seg; + const char *trapn, *segpn; char *s; int r; - seg= SOMEP(segn) ? info_segments[segn].pname : 0; - tra= SOMEP(tran) ? info_trains[tran].pname : 0; + segpn= seg ? seg->i->pname : 0; + trapn= tra ? tra->pname : 0; r= asprintf(&s, "%s%s%s%s%s", - seg||tra ? ":" : "", - seg ? " @" : "", - seg ? seg : "", - tra ? " " : "", - tra ? tra : ""); - if (r<0) diee("vasprintf failed in transegn2suffixstring " - "tran=%lu segn=%lu", (unsigned long)tran, (unsigned long)segn); + segpn||trapn ? ":" : "", + segpn ? " @" : "", + segpn ? segpn : "", + trapn ? " " : "", + trapn ? trapn : ""); + if (r<0) diee("vasprintf failed in transegn2suffixstring"); return s; } -void vlogmsg(ErrorCode ec, TrainNum tran, SegmentNum segn, +void vlogmsg(ErrorCode ec, Train *tra, const SegmentInfo *segi, const char *fmt, va_list al) { oprintf(UPO, "message %s ", ec ? errorcodelist[ec] : "info"); ovprintf(UPO,fmt,al); - if (SOMEP(segn) || SOMEP(tran)) oprintf(UPO, ":"); - if (SOMEP(segn)) oprintf(UPO, " @%s", info_segments[segn].pname); - if (SOMEP(tran)) oprintf(UPO, " %s", info_trains[tran].pname); + if (segi || tra) oprintf(UPO, ":"); + if (segi) oprintf(UPO, " @%s", segi->pname); + if (tra) oprintf(UPO, " %s", tra->pname); oprintf(UPO, "\n"); } -void logmsg(ErrorCode ec, TrainNum tran, SegmentNum segn,const char *fmt,...) { +void logmsg(ErrorCode ec, Train *tra, const SegmentInfo *segi, + const char *fmt,...) { va_list al; va_start(al,fmt); - vlogmsg(ec,tran,segn,fmt,al); + vlogmsg(ec,tra,segi,fmt,al); va_end(al); } -void safety_vpanic(TrainNum tran, SegmentNum segn,const char *fmt,va_list al) { +void safety_vpanic(Train *tra, Segment *seg,const char *fmt,va_list al) { char *msg, *where; PicInsn piob; @@ -91,20 +91,20 @@ void safety_vpanic(TrainNum tran, SegmentNum segn,const char *fmt,va_list al) { if (vasprintf(&msg,fmt,al) < 0) diee("vasprintf failed in safety_vpanic fmt=\"%s\"", fmt); - where= transegn2suffixstring(tran,segn); + where= transegn2suffixstring(tra,seg); die("fatal safety problem: %s%s", msg, where); } -void safety_panic(TrainNum tran, SegmentNum segn, const char *fmt, ...) { +void safety_panic(Train *tra, Segment *seg, const char *fmt, ...) { va_list al; va_start(al,fmt); - safety_panic(tran, segn, fmt, al); + safety_panic(tra, seg, fmt, al); } -ErrorCode safety_problem(TrainNum tran, SegmentNum segn, const char *fmt,...) { +ErrorCode safety_problem(Train *tra, Segment *seg, const char *fmt,...) { va_list al; va_start(al,fmt); - vlogmsg(EC_Safety, tran, segn, fmt, al); + vlogmsg(EC_Safety, tra, seg?seg->i:0, fmt, al); va_end(al); return EC_Safety; } @@ -199,7 +199,7 @@ void serial_transmit(const PicInsn *pi) { segn < info_nsegments; segn++, segi++) { if (!segi->invertible) continue; - if (!picinsn_polarity_testbit(pi,segn)) continue; + if (!picinsn_polarity_testbit(pi,segi)) continue; oprintf(UPO,"%s%s", delim, segi->pname); delim= ","; } @@ -224,10 +224,18 @@ void serial_transmit(const PicInsn *pi) { int main(int argc, const char **argv) { oop_source_sys *sys_events; + const char *arg; int r; - device= argv[1]; - if (!device) device= "/dev/ttya0"; + while ((arg=*++argv) && *arg=='-') { + arg++; + switch (*arg++) { + case 's': device= arg; break; + default: badusage("unknown option"); + } + } + + records_parse(argv); sys_events= oop_sys_new(); if (!sys_events) diee("oop_sys_new"); events= oop_sys_source(sys_events); massert(events); diff --git a/hostside/realtime.h b/hostside/realtime.h index c18118d..197efc6 100644 --- a/hostside/realtime.h +++ b/hostside/realtime.h @@ -6,7 +6,6 @@ #define REALTIME_H #include "daemons.h" -#include "safety.h" #include "auproto-pic.h" #include "dliste.h" @@ -15,10 +14,17 @@ #include #include #include +#include +#include #include #include +#include "../layout/layout-data.h" + +typedef struct Segment Segment; +typedef struct Train Train; + /*---------- from retransmit.c ----------*/ typedef struct RetransmitRelaxedNode RetransmitRelaxedNode; @@ -74,6 +80,10 @@ void serial_moredata(PicInsn *buf); extern StartupState sta_state; +/*---------- from/for record.c ----------*/ + +void records_parse(const char **argv); + /*---------- from/for realtime.c ----------*/ void oupicio(const char *dirn, const PicInsnInfo *pii, int objnum); @@ -83,7 +93,7 @@ void serial_transmit(const PicInsn *pi); /*---------- from actual.c ----------*/ -int picinsn_polarity_testbit(const PicInsn *pi, SegmentNum segn); +int picinsn_polarity_testbit(const PicInsn *pi, const SegmentInfo *segi); /* this belongs in {au,skel}proto-pic.[ch] really but it's * more convenient here. */ @@ -91,4 +101,8 @@ int picinsn_polarity_testbit(const PicInsn *pi, SegmentNum segn); void abandon_run(void); + +#include "safety.h" + + #endif /*REALTIME_H*/ diff --git a/hostside/record-l.l b/hostside/record-l.l index 4a61e8d..20f845b 100644 --- a/hostside/record-l.l +++ b/hostside/record-l.l @@ -1,24 +1,22 @@ /* -*- fundamental -*- */ %{ -#include "y.tab.h" +#include "record.h" %} %option warn %option batch %option noyywrap - -%option bison-locations -%option bison-bridge +%option yylineno +%option prefix="record_yy" +%option header-file="record-l.h" %{ -#define STR yylval->str= xstrdup(yytext); return +#define STR record_yylval.name= record_tempzone_strdup(yytext); return %} %% -max-trains { yylval->str= 0; return MAXTRAINS; } - train { STR TRAIN; } seg { STR SEG; } is { STR IS; } @@ -27,15 +25,15 @@ has { STR HAS; } step { STR STEP; } end { STR END; } -[A-Za-z0-9_]+ { STR IDENT; } +[A-Za-z][A-Za-z0-9_]+ { STR IDENT; } -[0-9]{0,5} { yylval->num= strtoul(yytext,0,10); return NUM; } -[0-9]{6} { badrecord("number too long"); } +[0-9]{0,5} { record_yylval.num= strtoul(yytext,0,10); return NUM; } +[0-9]{6} { record_yyerror("number too long"); } -[-+:=~$/] { yylval->str= 0; return yytext[0]; } +[-+:=~/] { record_yylval.name= 0; return yytext[0]; } -\#.*\n|\ { yylval->str= 0; return NL; } +\#.*\n|\n { record_yylval.name= 0; return NL; } [ \t] { } -. { badrecord("lexically invalid input"); } +. { record_yyerror("lexically invalid input"); } diff --git a/hostside/record-y.y b/hostside/record-y.y index 3f8f769..5ba3d1c 100644 --- a/hostside/record-y.y +++ b/hostside/record-y.y @@ -1,55 +1,60 @@ /* -*- fundamental -*- */ %{ -#include "realtime.h" +#include "record.h" +#include "record-l.h" %} %union { - char *name; + const char *name; Train *train; Segment *seg; int num; } %token TRAIN SEG IS AT HAS STEP END IDENT -%token MAXTRAINS NL +%token NL %token NUM %type ident %type train -%type seg -%type sign +%type seg +%type backwards %defines +%error-verbose +%name-prefix="record_yy" %% file: end - | line NL file + | line NL { record_tempzone_clear(); } file line: /* empty */ - | MAXTRAINS NUM - { record_max_trains($2); } - | TRAIN train AT sign SEG ':' NUM '+' '-' NUM - { record_train_at($2,$4,$5,$7,$10); } | TRAIN train IS NUM NUM '+' NUM '+' NUM - { record_train_is($2,$4,$5,$7,$9); } + { if ($2) record_train_is($2,$4,$5,$7,$9); + } + | TRAIN train AT backwards seg ':' NUM '+' '-' NUM + { if ($2) record_train_at($2,$4,$5,$7,$10); + } | TRAIN train STEP NUM '=' NUM NUM '/' NUM - { record_train_step($2,$4,$6,$7,$9); } - | SEG seg HAS sign train - { record_seg_has($2,$4,$5); } - | SEG seg HAS '$' - { record_seg_has($2,0,0); } - | SEG seg AT NUM - { record_seg_at($2,$4); } - -sign: /* empty */ { return 1; } - | '-' { return -1; } + { if (!trains) record_train_step_count(); + else if ($2) record_train_step($2,$4,$6,$7,$9); + } + | SEG seg HAS backwards train + { if ($2 && $5) record_seg_has($2,$4,$5); + } + | SEG seg AT ident + { if ($2) record_seg_at($2,$4); + } + +backwards: /* empty */ { return 0; } + | '-' { return 1; } ident: IDENT | TRAIN | SEG | IS | AT | STEP | END -seg: ident { $$= pname2seg($1); } -train: ident { $$= pname2train($1); } +seg: ident { $$= record_pname2seg($1); } +train: ident { $$= record_pname2train($1); } end: END NL diff --git a/hostside/record.c b/hostside/record.c index 429cee2..1f357af 100644 --- a/hostside/record.c +++ b/hostside/record.c @@ -11,3 +11,258 @@ * seg at */ +#include + +#include "record.h" +#include "record-l.h" + +/*---------- input and error handling ----------*/ + +static const char *filename; + +void record_yyerror(const char *m) { + die("config: %s:%d: %s\n", filename, record_yylineno, m); +} + +/*---------- pname lookup (also handles train counting) ----------*/ + +static char **train_pnames; + +Train *record_pname2train(const char *pname) { + int tran; + char **trap; + + for (tran=0, trap=train_pnames; tranpname, pname)) + return segments + i; + + return 0; /* silently discard data for segments no longer in the layout */ +} + +/*---------- zone allocator for strings ----------*/ + +typedef struct TempZoneBlock TempZoneBlock; +struct TempZoneBlock { + TempZoneBlock *next; /* for deallocation */ + char buf[1]; +}; + +static TempZoneBlock *tempzones_head; +static char *tempzone_ptr; +static int tempzone_remain, tempzone_head_len; + +char *record_tempzone_strdup(const char *s) { + int l; + char *r; + + l= strlen(s) + 1; + if (l > tempzone_remain) { + TempZoneBlock *new; + assert(l < INT_MAX/20); + tempzone_head_len= tempzone_remain= l*10 + 65536; + new= mmalloc(sizeof(new) + tempzone_remain); + tempzone_ptr= (char*)new + sizeof(new); + new->next= tempzones_head; + tempzones_head= new; + } + r= tempzone_ptr; + tempzone_remain -= l; + tempzone_ptr += l; + memcpy(r,s,l); + return r; +} + +void record_tempzone_clear(void) { + TempZoneBlock *clear, *clear_next; + if (!tempzones_head) return; + + clear= tempzones_head->next; + while (clear) { clear_next= clear->next; free(clear); clear= clear_next; } + tempzones_head->next= 0; + tempzone_remain= tempzone_head_len; + tempzone_ptr= tempzones_head->buf; +} + +/*---------- semantic actions ----------*/ +/* + * These are all called only during the second pass, when trains is non-0. + * Also, all Train* and Segment* arguments are known to be non-0. + */ + +void record_train_is(Train *tra, int addr, int head, int det, int tail) { + tra->addr= addr; + tra->head= head; + tra->detectable= det; + tra->tail= tail; +} + +void record_train_at(Train *tra, int backw, Segment *seg, int maxi, int unc) { + tra->foredetect= seg; + tra->maxinto= maxi; + tra->uncertainty= unc; + tra->backwards= backw; +} + +void record_seg_has(Segment *seg, int backw, Train *tra) { + seg->owner= tra; + seg->tr_backwards= backw; +} + +void record_seg_at(Segment *seg, const char *movposcombpname) { + const SegPosCombInfo *spci; + int i; + + for (i=0, spci=seg->i->poscombs; + ii->n_poscombs; + i++, spci++) + if (!strcmp(spci->pname, movposcombpname)) + goto found; + return; + +found: + seg->movposcomb= i; +} + +/*---------- speed curves ----------*/ + +static SpeedCurveEntry *curvebuf; +static int curvebufsz, curvebufused; + +void record_train_step_count(void) { + curvebufsz++; +} + +void record_train_step(Train *tra, int step, int speed, int upw, int downw) { + Train *other; + SpeedCurveEntry *new; + int i; + + if (curvebufused >= curvebufsz) record_yyerror("more speed points on 2nd pass!"); + + if (!tra->accel.curve) { + tra->accel.curve= curvebuf + curvebufused; + } + + /* Make room for an extra speed step point for this train, + * by moving all of the other trains up. First move the data: */ + memmove(tra->accel.curve + tra->accel.curvesz + 1, + tra->accel.curve + tra->accel.curvesz, + (char*)(curvebuf + curvebufused) + - (char*)(tra->accel.curve + tra->accel.curvesz)); + /* Then adjust everyone's pointers: */ + for (i=0, other=trains; + iaccel.curve && + other->accel.curve >= tra->accel.curve) + other->accel.curve++; + /* ... that whole thing is O(n^2) if the speed points aren't sorted + * by train; we hope they are, in which case we are always adding + * to the last train in the list and there is then no data to copy, + * which makes it O(n*t) where n is the number of speed points and + * t is the number of trains. If we cared we could optimise away + * the loop in the common case where this train is right at the end + * but a special case seems like asking for a bug when we do have + * out of order speed points. */ + + new= &tra->accel.curve[tra->accel.curvesz++]; + curvebufsz++; + + new->step= step; + new->speed= speed; + new->upwait= upw; + new->downwait= downw; +} + +static int speedcurveentry_compare(const void *av, const void *bv) { + const SpeedCurveEntry *a= av, *b= bv; + if (a->step == b->step) + record_yyerror("multiple speed curve points at same step"); + return a->step - b->step; +} + +static void sort_curves(void) { + int i; + Train *tra; + + for (i=0, tra=trains; + iaccel.curve) { + if (tra->accel.curvesz < 2) + die("config: speed curve too short for %s", tra->pname); + qsort(tra->accel.curve, tra->accel.curvesz, + sizeof(*tra->accel.curve), speedcurveentry_compare); + if (tra->accel.curve[0].step || tra->accel.curve[0].speed) + die("config: speed curve missing zero point for %s", tra->pname); + } + } +} + +/*---------- entrypoint from main, and its subroutines ----------*/ + +static void alloc(void) { + Train *tra; Segment *seg; const SegmentInfo *segi; + char **trap; + int i; + + segments= mmap(0, sizeof(*segments)*NUM_SEGMENTS + sizeof(*trains)*n_trains, + PROT_READ|PROT_WRITE, MAP_SHARED|MAP_ANONYMOUS, -1,0); + if (!segments) diee("mmap for shared region"); + + for (i=0, seg=segments, segi=info_segments; + imovposcomb= -1; + seg->i= segi; + } + + trains= (void*)(segments + NUM_SEGMENTS); + for (i=0, tra=trains, trap=train_pnames; + ipname= *trap; + tra->addr= -1; + tra->head= -1; + } + + curvebuf= mmalloc(sizeof(*curvebuf) * curvebufsz); +} + +static void parse_pass(const char **argv) { + FILE *f; + + while ((filename= *argv++)) { + f= fopen(filename,"r"); + if (!f) diee("config: cannot open input file: %s", filename); + record_yyrestart(f); + record_yyparse(); + } +} + +void records_parse(const char **argv) { + parse_pass(argv); /* trains==0: counts trains and curve points. */ + alloc(); + parse_pass(argv); /* trains!=0: populates data area */ + record_tempzone_clear(); + sort_curves(); +} diff --git a/hostside/record.h b/hostside/record.h new file mode 100644 index 0000000..366bd29 --- /dev/null +++ b/hostside/record.h @@ -0,0 +1,27 @@ +/* + */ + +#ifndef RECORD_H +#define RECORD_H + +#include "realtime.h" +#include "record-y.h" + +void record_train_at(Train *tra, int backw, Segment *seg, int maxi, int unc); +void record_train_is(Train *tra, int addr, int head, int det, int tail); +void record_train_step(Train *tra, int step, int speed, int upw, int downw); +void record_train_step_count(void); +void record_seg_has(Segment *seg, int backw, Train *tra); +void record_seg_at(Segment *seg, const char *movposcomb_pname); + +Train *record_pname2train(const char *pname); +Segment *record_pname2seg(const char *pname); +char *record_tempzone_strdup(const char *s); +void record_yyerror(const char *m); +void record_tempzone_clear(void); + +int record_yyparse(void); +int record_yylex(void); +extern int record_yylineno; + +#endif /*RECORD_H*/ diff --git a/hostside/rtmacros.h b/hostside/rtmacros.h deleted file mode 100644 index 45d88be..0000000 --- a/hostside/rtmacros.h +++ /dev/null @@ -1,13 +0,0 @@ -/* - * macros which help some files in the realtime daemon - */ - -#ifndef RTMACROS_H -#define RTMACROS_H - -#define S State *s= &safety_state -#define TRA TrainState *tra= &s->trains[tran] -#define TRAI const TrainInfo *trai= &info_trains[tran]; -#define SEG SegmentState *seg= &s->segments[segn] - -#endif /*RTMACROS_H*/ diff --git a/hostside/safety.c b/hostside/safety.c index 3e069ac..179f0e4 100644 --- a/hostside/safety.c +++ b/hostside/safety.c @@ -8,18 +8,20 @@ #include "realtime.h" -State safety_state; +int n_trains; +Train *trains; +Segment *segments; -static void seg_clear_stale(SegmentState *seg) { +static void seg_clear_stale(Segment *seg) { if (!seg->tr_updated) { - seg->owned= 0; + seg->owner= 0; seg->until_here= seg->until_detect= 0; } } typedef struct { /* constant inputs */ - TrainNum tran; + Train *tra; /* modified in place by lay_train_pass: */ ErrorCode ec; int invert_count[2]; /* count of (switchable) segments, @@ -27,71 +29,64 @@ typedef struct { * iff train is backwards (ie, train not inverted) * invert_count[1]: train is inverted * set to -1 if any unswitchable is the other way */ - SegmentNum invert_forcer; /* the unswitchable which forces */ + Segment *invert_forcer; /* the unswitchable which forces */ } LayTrainState; static void lay_train_pass(LayTrainState *l, TrackLocation tloc, long advance, long speed, unsigned backwards, unsigned check_clash) { - S; - SegmentNum segn; - SegmentState *seg; - const SegmentInfo *segi; + Segment *seg; long overall, remain, dist_until, time_until; int *invert_likehere, train_inverted_here; - TrainState *tra= &s->trains[l->tran]; + Train *tra= l->tra; if (l->ec) return; - segn= tra->foredetect; - seg= &s->segments[segn]; + seg= tra->foredetect; remain= overall= advance + speed * SPEED_CLEAR_MULT; for (;;) { - segn= tloc.segn; - seg= &s->segments[segn]; - segi= &info_segments[segn]; + seg= tloc.seg; if (check_clash) { if (seg->tr_updated) { - l->ec= safety_problem(l->tran, tloc.segn, "self-collision"); + l->ec= safety_problem(l->tra, tloc.seg, "self-collision"); return; } - if (seg->owned) { - if (seg->owner != l->tran) { - l->ec= safety_problem(l->tran, tloc.segn, "collision with %s", - info_trains[seg->owner].pname); + if (seg->owner) { + if (seg->owner != l->tra) { + l->ec= safety_problem(l->tra, tloc.seg, "collision with %s", + seg->owner->pname); return; } seg_clear_stale(seg); } } - seg->owned= 1; + seg->owner= l->tra; seg->tr_backwards= tloc.backwards ^ backwards; seg->tr_updated= 1; - seg->owner= l->tran; train_inverted_here= seg->seg_inverted ^ seg->tr_backwards; invert_likehere= &l->invert_count[train_inverted_here]; - if (segi->invertible) { + if (seg->i->invertible) { if (*invert_likehere >= 0) (*invert_likehere)++; } else { if (*invert_likehere < 0) { - l->ec= safety_problem(l->tran, NOTA(Segment), "train requires" + l->ec= safety_problem(l->tra,0, "train requires" " noninvertible segments with opposite polarity:" - " @%s, @%s", segi->pname, - info_segments[l->invert_forcer].pname); + " @%s, @%s", seg->i->pname, + l->invert_forcer->i->pname); return; } assert(!seg->seg_inverted); (*invert_likehere)++; l->invert_count[!train_inverted_here]= -1; - l->invert_forcer= segn; + l->invert_forcer= seg; } dist_until= (overall - remain) - advance; @@ -104,9 +99,8 @@ static void lay_train_pass(LayTrainState *l, } static void lay_train_inversions(LayTrainState *l) { - S; SegmentNum segn; - SegmentState *seg; + Segment *seg; const SegmentInfo *segi; int train_be_inverted, seg_be_inverted; @@ -117,28 +111,27 @@ static void lay_train_inversions(LayTrainState *l) { actual_inversions_start(); - for (segn=0, seg=s->segments, segi=info_segments; + for (segn=0, seg=segments, segi=info_segments; segn <= NUM_SEGMENTS; - segn++, seg++) { + segn++, seg++, segi++) { if (!seg->tr_updated) continue; - assert(seg->owner == l->tran); + assert(seg->owner == l->tra); seg_be_inverted= train_be_inverted ^ seg->tr_backwards; assert(!(seg_be_inverted && !segi->invertible)); seg->seg_inverted= seg_be_inverted; - actual_inversions_segment(segn); + actual_inversions_segment(seg); } actual_inversions_done(); } static void lay_train_done(LayTrainState *l) { - S; SegmentNum segn; - SegmentState *seg; + Segment *seg; - for (segn=0, seg=s->segments; + for (segn=0, seg=segments; segn <= NUM_SEGMENTS; segn++, seg++) { - if (seg->owner == l->tran) { + if (seg->owner == l->tra) { if (!seg->tr_updated) seg_clear_stale(seg); seg->tr_updated= 0; } @@ -147,22 +140,19 @@ static void lay_train_done(LayTrainState *l) { } } -static ErrorCode lay_train(TrainNum tran, long added_slop) { - S; TRA; TRAI; - SegmentNum segn; - SegmentState *seg; +static ErrorCode lay_train(Train *tra, long added_slop) { + Segment *seg; TrackLocation tloc; long head, headslop, tail, taildet; LayTrainState l; - segn= tra->foredetect; - seg= &s->segments[segn]; + seg= tra->foredetect; - tloc.segn= segn; + tloc.seg= seg; tloc.into= tra->maxinto; tloc.backwards= seg->tr_backwards ^ tra->backwards; - l.tran= tran; + l.tra= tra; l.ec= 0; l.invert_count[0]= l.invert_count[1]= 0; @@ -198,30 +188,28 @@ static ErrorCode lay_train(TrainNum tran, long added_slop) { return l.ec; } -void safety_notify_detection(SegmentNum segn) { - S; SEG; - TrainNum tran= seg->owner; - TRA; +void safety_notify_detection(Segment *seg) { + Train *tra= seg->owner; ErrorCode ec; TrackLocation tloc; - if (!seg->owned) - safety_panic(NOTA(Train), segn, "unexpected detection"); + if (!seg->owner) + safety_panic(0,seg, "unexpected detection"); if (!seg->until_detect) return; - tloc.segn= segn; + tloc.seg= seg; tloc.into= 0; tloc.backwards= seg->tr_backwards; - tra->foredetect= segn; + tra->foredetect= seg; tra->maxinto= trackloc_remaininseg(&tloc); if (seg->cm_autostop) { seg->cm_autostop= 0; if (!tra->estopping) { - speedmanager_autostop(tran); + speedmanager_autostop(tra); if (!tra->speed && tra->maxinto > AUTOSTOP_UNCERTAINTY) /* At some point we may need to allow more slop when the * next segment is points than when this is the last segment @@ -232,51 +220,51 @@ void safety_notify_detection(SegmentNum segn) { tra->uncertainty= tra->maxinto; if (!tra->estopping) { - ec= lay_train(tran, 0); + ec= lay_train(tra, 0); if (ec) { - logmsg(ec, tran, segn, "emergency stop"); - safety_emergencystop(tran); + logmsg(ec,tra,seg->i, "emergency stop"); + safety_emergencystop(tra); } } } -void safety_emergencystop(TrainNum tran) { - S; TRA; +void safety_emergencystop(Train *tra) { ErrorCode ec; if (tra->estopping) return; - ec= lay_train(tran, ESTOP_UNCERTAINTY); - if (ec) safety_panic(tran, NOTA(Segment), "emergency stop forbidden!"); - speedmanager_emergencystop(tran); + ec= lay_train(tra, ESTOP_UNCERTAINTY); + if (ec) safety_panic(tra,0, "emergency stop forbidden!"); + speedmanager_emergencystop(tra); } -ErrorCode safety_requestspeed(TrainNum tran, long newspeed) { - S; TRA; +ErrorCode safety_requestspeed(Train *tra, long newspeed) { long oldspeed; ErrorCode ec; oldspeed= tra->speed; tra->speed= newspeed; - ec= lay_train(tran, 0); + ec= lay_train(tra, 0); if (ec) { + ErrorCode revert_ec; + if (oldspeed && oldspeed < newspeed) { - logmsg(ec, tran, NOTA(Segment), "countermanded acceleration" + logmsg(ec,tra,0, "countermanded acceleration" " from %ld to %ld", oldspeed, newspeed); } else if (oldspeed) { - safety_panic(tran, NOTA(Segment), "deceleration forbidden!" + safety_panic(tra,0, "deceleration forbidden!" " (from %ld to %ld", oldspeed, newspeed); } else { - logmsg(ec, tran, NOTA(Segment), "countermanded motion start"); + logmsg(ec,tra,0, "countermanded motion start"); } oprintf(UPO, "countermanded %s %ld %ld\n", - info_trains[tran].pname, oldspeed, newspeed); - ec= lay_train(tran, 0); - if (ec) - safety_panic(tran, NOTA(Segment), "countermanding" + tra->pname, oldspeed, newspeed); + revert_ec= lay_train(tra, 0); + if (revert_ec) + safety_panic(tra,0, "countermanding" " speed change insufficient!"); - return; } + return ec; } diff --git a/hostside/safety.h b/hostside/safety.h index 2cb34c3..d741131 100644 --- a/hostside/safety.h +++ b/hostside/safety.h @@ -27,65 +27,73 @@ typedef short TimeInterval; /*ms*/ /*========== state of the layout ==========*/ typedef struct { - fixme init location; - fixme call init_fixed_train; + int step; + long speed; + TimeInterval upwait, downwait; /* between this insn and next one */ +} SpeedCurveEntry; + +struct Train { + /* Configuration (excluding speed curve): */ + char *pname; int addr; Distance head, detectable, tail; + + /* Location: */ Segment *foredetect; /* train's detectable part is at most maxinto */ Distance maxinto, uncertainty; /* into foredetect but train may be */ unsigned /* uncertainty less far advanced */ backwards:1, /* train is moving backwards wrt its own front and back */ + + /* Speed: */ estopping:1; /* set and cleared by speed.c */ Speed speed; /* when accelerating/decelerating, is maximum at this moment */ - + struct { - const SpeedCurveEntry *curve; - int curvesz; int target; /* index into curve */ int commanded; /* when ac-/decel, eq last value xmitted */ TimeoutEvent more; RetransmitUrgentNode rn; + + /* Configuration for acceleration: */ + SpeedCurveEntry *curve; + int curvesz; } accel; -} TrainState; +}; -typedef struct { +struct Segment { + Train *owner; /* or 0 */ unsigned - owned:1, /* this track segment is reserved for a train */ tr_backwards:1, /* train's motion is (would be) backwards wrt track */ movfeat_moving:1, /* feature(s) have been told to change to movposcomb */ cm_autostop:1, /* train should stop on detection */ seg_inverted:1, /* polarity is inverted */ tr_updated:1; /* for use by safety.c:lay_train etc.; otherwise 0 */ - TimeInterval until_here, /* ) nonnegative; */ /* ) always valid but */ - until_detect; /* ) 0 if already */ /* ) only meaningful */ - TrainNum owner; /* ) iff owned */ + TimeInterval until_here, /* ) nonnegative; */ /* ) always valid but */ + until_detect; /* ) 0 if already */ /* ) meaningful iff owner */ MovPosComb movposcomb; - /*polarity?*/ -} SegmentState; - -typedef struct { - TrainState trains[NUM_TRAINS]; - SegmentState segments[NUM_SEGMENTS]; -} State; + const SegmentInfo *i; +}; -extern State safety_state; +extern int n_trains; +extern Train *trains; +extern Segment *segments; /*========== embed.c ==========*/ /* surrounds the algorithms and machinery in a program: logging, error * handling, arg parsing, etc. */ -void vlogmsg(ErrorCode ec, TrainNum tran, SegmentNum segn, +void vlogmsg(ErrorCode ec, Train *tra, const SegmentInfo *segi, const char *fmt, va_list al) __attribute__((format(printf,4,0))); -void logmsg(ErrorCode ec, TrainNum tran, SegmentNum segn, +void logmsg(ErrorCode ec, Train *tra, const SegmentInfo *segi, const char *fmt, ...) __attribute__((format(printf,4,5))); -void safety_vpanic(TrainNum tran, SegmentNum segn, const char *fmt, va_list al) +void safety_vpanic(Train *tra, Segment *seg, const char *fmt, va_list al) __attribute__((format(printf,3,0),noreturn)); -void safety_panic(TrainNum tran, SegmentNum segn, const char *fmt,...) +void safety_panic(Train *tra, Segment *seg, const char *fmt,...) __attribute__((format(printf,3,4),noreturn)); -ErrorCode safety_problem(TrainNum tran, SegmentNum segn, const char *fmt, ...) +ErrorCode safety_problem(Train *tra, Segment *seg, const char *fmt, ...) __attribute__((format(printf,3,4))); /* simple wrapper around vlogmsg; implies and returns EC_Safety */ @@ -96,28 +104,30 @@ ErrorCode safety_problem(TrainNum tran, SegmentNum segn, const char *fmt, ...) * etc.). */ -void safety_emergencystop(TrainNum); +void safety_emergencystop(Train*); /* Callable directly in response to application command. */ -ErrorCode safety_requestspeed(TrainNum tran, long newspeed); +ErrorCode safety_requestspeed(Train* tra, long newspeed); /* To be called only by the speed manager, thus indirectly from * user request. Any error will have been logged. On success, * ->speed has been updated. Speed manager is responsible for * calling actual_setspeed. */ -void safety_setdirection(TrainNum tran, int sense_fixme_define_this_properly); +void safety_setdirection(Train* tra, int sense_fixme_define_this_properly); -void safety_notify_detection(SegmentNum segn); +void safety_notify_detection(Segment *seg); /* Called by startup.c when new train detection occurs in state Run. */ /*========== speedmgr.c ==========*/ -void speedmanager_speedchange_request(TrainNum tran, Speed speed); - /* Callable directly in response to application command. */ +void speedmanager_speedchange_request(Train *tra, long speed); + /* Callable directly in response to application command. + * speed may be LONG_MAX to mean maximum permitted. + */ -void speedmanager_emergencystop(TrainNum tran); -void speedmanager_autostop(TrainNum tran); +void speedmanager_emergencystop(Train *tra); +void speedmanager_autostop(Train *tra); /* These are responsible for calling actual_setspeed. * * After speedmanager_autostop, ->speed will have been updated to a @@ -125,6 +135,8 @@ void speedmanager_autostop(TrainNum tran); * been instructed to stop right now. */ +void speedmanager_reset_train(Train *tra); + /*========== actual.c ==========*/ /* actual.c should only be called from safety.c. * It is responsible for communicating with the PICs, including @@ -135,11 +147,11 @@ void speedmanager_autostop(TrainNum tran); * will then call an actual_... function to notify the change. */ -void actual_setspeed(TrainNum tran); -void actual_emergencystop(TrainNum tran); +void actual_setspeed(Train *tra); +void actual_emergencystop(Train *tra); void actual_inversions_start(void); -void actual_inversions_segment(SegmentNum); +void actual_inversions_segment(Segment *seg); void actual_inversions_done(void); /* safety.c will call these in this order: first start, then segment * for 0 or more segments (whose s.segments[segn].seg_inverted may @@ -156,7 +168,7 @@ void actual_inversions_done(void); typedef struct TrackLocation TrackLocation; struct TrackLocation { /* transparent, and manipulable by trackloc_... fns */ - SegmentNum segn; /* current segment */ + Segment *seg; /* current segment */ long into; /* distance from start of segment */ unsigned backwards:1; /* if 1, into is positive and measured from end */ }; @@ -193,8 +205,9 @@ const SegmentLinkInfo *trackloc_segmentlink(const TrackLocation *tloc, #define CLEAR_FORESIGHT_TIME 500 /*ms*/ #define AUTOSTOP_MAXSPEED ((50 * SPEED_UNIT)/1000) /* 50 mm/s */ -#define AUTOSTOP_UNCERTAINTY 20 -#define ESTOP_UNCERTAINTY 300 +#define AUTOSTOP_UNCERTAINTY 20 /*mm*/ +#define ESTOP_UNCERTAINTY 300 /*mm*/ +#define ESTOP_DEADTIME 2000 /*ms*/ #define SPEED_CLEAR_MULT SPEED_CALC_DIST(1,CLEAR_FORESIGHT_TIME,UP) diff --git a/hostside/speed.c b/hostside/speed.c index dea39f0..8f5a88d 100644 --- a/hostside/speed.c +++ b/hostside/speed.c @@ -4,15 +4,14 @@ */ #include "realtime.h" +#include "nmra.h" -typedef struct { - SpeedStep step; - Speed speed; - TimeInterval upwait, downwait; /* between this insn and next one */ -} SpeedCurveEntry; +static void changereq_internal(Train *tra, int newcommanded, int inautostop); +static void accel_more(TimeoutEvent *toev); -void reset_train(Train *tra) { +void speedmanager_reset_train(Train *tra) { Nmra n; + ErrorCode ec; tra->estopping= 0; tra->speed= 0; @@ -20,34 +19,22 @@ void reset_train(Train *tra) { toev_init(&tra->accel.more); enco_nmra_speed126(&n, tra->addr, 0, tra->backwards); retransmit_urgent_queue_relaxed(&tra->accel.rn, &n); - ec= safety_requestspeed(tran, 0); + ec= safety_requestspeed(tra, 0); if (ec) safety_panic(tra, 0, "position reset impossible!"); } -void init_fixed_train(Train *tra, const TrainInfo *trai) { - /* does not init location (ie foredetect, maxinto, uncertainty, backwards); - * at least backwards must already be valid */ - tra->addr= trai->addr; - tra->head= trai->head; - tra->detectable= trai->detectable; - tra->tail= trai->tail; - tra->accel.curve= trai->curve; - tra->accel.curvesz= trai->curvesz; - reset_train(tra); -} - -void xmit_speed(Train *tra) { +static void xmit_speed(Train *tra) { Nmra n; enco_nmra_speed126(&n, tra->addr, - tra->curve[tra->accel.commanded].step, + tra->accel.curve[tra->accel.commanded].step, tra->backwards); retransmit_urgent_requeue(&tra->accel.rn, &n); } -void speedmanager_autostop(TrainNum tran) { +void speedmanager_autostop(Train *tra) { if (tra->speed < AUTOSTOP_MAXSPEED) { - toev_stop(&tra->speedadjust); + toev_stop(&tra->accel.more); tra->accel.commanded= tra->accel.target= tra->speed= 0; xmit_speed(tra); } else { @@ -58,14 +45,14 @@ void speedmanager_autostop(TrainNum tran) { static void estop_done(TimeoutEvent *toev) { Train *tra= (void*)((char*)toev - offsetof(Train, accel.more)); retransmit_urgent_cancel(&tra->accel.rn); - reset_train(tra); + speedmanager_reset_train(tra); } void speedmanager_emergencystop(Train *tra) { Nmra n; tra->estopping= 1; - toev_stop(&tra->speedadjust); - enco_nmra_estop(&n, tra->addr); + toev_stop(&tra->accel.more); + enco_nmra_estop1(&n, tra->addr); retransmit_urgent_requeue(&tra->accel.rn, &n); toev_stop(&tra->accel.more); @@ -74,29 +61,23 @@ void speedmanager_emergencystop(Train *tra) { toev_start(&tra->accel.more); } -static void accel_more(TimeoutEvent *toev) { - Train *tra= (void*)((char*)toev - offsetof(Train, accel.more)); - adjust_next(tra, 0); -} - static void adjust_next(Train *tra, int inautostop) { - int newold, xmit; long newspeed; if (tra->accel.target > tra->accel.commanded) { tra->accel.commanded++; - tra->accel.more.duration= tra->curve[tra->accel.commanded].upwait; - newspeed= tra->curve[tra->accel.commanded].speed; + tra->accel.more.duration= tra->accel.curve[tra->accel.commanded].upwait; + newspeed= tra->accel.curve[tra->accel.commanded].speed; } else if (tra->accel.target < tra->accel.commanded) { - newspeed= tra->curve[tra->accel.commanded].speed; + newspeed= tra->accel.curve[tra->accel.commanded].speed; tra->accel.commanded--; - tra->accel.more.duration= tra->curve[tra->accel.commanded].downwait; + tra->accel.more.duration= tra->accel.curve[tra->accel.commanded].downwait; } else { return; } if (!inautostop) { - ec= safety_requestspeed(tra, newspeed); + ErrorCode ec= safety_requestspeed(tra, newspeed); if (ec) { assert(newspeed > tra->speed); assert(tra->accel.target >= tra->accel.commanded); @@ -114,10 +95,15 @@ static void adjust_next(Train *tra, int inautostop) { xmit_speed(tra); } -int changereq_internal(Train *tra, int newcommanded, int inautostop) { +static void accel_more(TimeoutEvent *toev) { + Train *tra= (void*)((char*)toev - offsetof(Train, accel.more)); + adjust_next(tra, 0); +} + +static void changereq_internal(Train *tra, int newcommanded, int inautostop) { int reverse, newold; - if (!speedadjust->running) { + if (!tra->accel.more.running) { assert(tra->accel.commanded == tra->accel.target); adjust_next(tra, 0); } else { @@ -134,24 +120,24 @@ int changereq_internal(Train *tra, int newcommanded, int inautostop) { if (reverse) { /* switch from accel to decel or vice versa */ - toev_stop(&tra->speedadjust); + toev_stop(&tra->accel.more); tra->accel.commanded= newold; adjust_next(tra, 0); } } } -void speedmanager_speedchange_request(TrainNum tran, Speed speed) { +void speedmanager_speedchange_request(Train *tra, long speed) { changereq_internal(tra, speed, 0); - int a, b, found; - const SpeedCurveEntry *curve; + int a, b, try, found; + const SpeedCurveEntry *curve= tra->accel.curve; if (tra->estopping) { logmsg(EC_Invalid, tra, 0, "speed request ignored during emergency stop"); return; } - for (a=0, b=trai->nsteps; + for (a=0, b=tra->accel.curvesz; a < b; ) { try= (a + b) >> 2; @@ -168,10 +154,10 @@ void speedmanager_speedchange_request(TrainNum tran, Speed speed) { */ found= a>1 ? a-1 : speed ? 1 : 0; - if (curve[found].speed < speed && !NOTA(speed)) - logmsg(EC_Invalid, tran, NOTA(SegmentNum), - "requested speed %l excessive; capping at %l", - (long)speed, (long)curve[found].speed); + if (curve[found].speed < speed && speed != INT_MAX) + logmsg(EC_Invalid, tra,0, + "requested speed %ld excessive; capping at %ld", + speed, curve[found].speed); changereq_internal(tra, found, 0); } diff --git a/hostside/startup.c b/hostside/startup.c index 9f8a0fe..a580280 100644 --- a/hostside/startup.c +++ b/hostside/startup.c @@ -192,7 +192,7 @@ void on_pic_detect1(const PicInsnInfo *pii, const PicInsn *pi, int segn) { info_segments[segn].pname); return; } - safety_notify_detection(segn); + safety_notify_detection(&segments[segn]); } /*---------- fixme move these to where they want to go ----------*/ diff --git a/hostside/trackloc.c b/hostside/trackloc.c index 4a17714..0818c6b 100644 --- a/hostside/trackloc.c +++ b/hostside/trackloc.c @@ -3,15 +3,13 @@ #include -#include "safety.h" +#include "realtime.h" const SegPosCombInfo *trackloc_segposcomb(const TrackLocation *tloc) { - State *s= &safety_state; - SegmentState *seg= &s->segments[tloc->segn]; - const SegmentInfo *segi= &info_segments[tloc->segn]; + Segment *seg= tloc->seg; - assert(seg->movposcomb < segi->n_poscombs); - return &segi->poscombs[seg->movposcomb]; + assert(seg->movposcomb < seg->i->n_poscombs); + return &seg->i->poscombs[seg->movposcomb]; } const SegmentLinkInfo *trackloc_segmentlink(const TrackLocation *tloc, @@ -44,7 +42,7 @@ void trackloc_further(TrackLocation *tloc, long *remain_io) { pci= trackloc_segposcomb(tloc); lnki_far= trackloc_segmentlink(tloc, pci, 1); *remain_io -= segment_remain; - tloc->segn= lnki_far->next; + tloc->seg= &segments[lnki_far->next]; tloc->into= 0; tloc->backwards ^= lnki_far->next_backwards; } diff --git a/hostside/utils.c b/hostside/utils.c index 3b5e307..ce4bee9 100644 --- a/hostside/utils.c +++ b/hostside/utils.c @@ -34,6 +34,10 @@ void vdie(const char *fmt, int ev, va_list al) { exit(12); } +void badusage(const char *why) { + fprintf(stderr,"%s: bad usage: %s\n",progname,why); exit(8); +} + void die(const char *fmt, ...) { va_list al; va_start(al,fmt); vdie(fmt,0,al); } void diee(const char *fmt, ...) diff --git a/layout/data2safety b/layout/data2safety index c6037ca..0bd5708 100755 --- a/layout/data2safety +++ b/layout/data2safety @@ -403,7 +403,6 @@ sub writeout () { push @segs, $seg; } o(sprintf - "#define NUM_TRAINS 1000000\n". "#define NUM_SEGMENTS %s\n\n". "#include \"layout-data.h\"\n\n", scalar @segs); @@ -422,7 +421,7 @@ sub writeout () { } o("$delim\n"); o(sprintf " { %-8s %4d", - '"'.$seg.(length $pi ? '/' : '').$pi.'",', + '"'.$pi.'",', $segr->{Dist}[$comb]); for ($end=0; $end<2; $end++) { o(", { "); @@ -470,7 +469,7 @@ sub writeout () { $ptv= $segr->{Feats}{$pt}; next if exists $ptv->{Fixed}; o("$delim\n"); - o(" { \"$seg/$pt\", mfk_".lc($ptv->{Kind}).",". + o(" { \"$pt\", mfk_".lc($ptv->{Kind}).",". " $ptv->{Posns}, $ptv->{Weight}, mfbo_${seg}_$pt }"); $delim=','; } diff --git a/layout/layout-data.h b/layout/layout-data.h index 98796c6..4bb569a 100644 --- a/layout/layout-data.h +++ b/layout/layout-data.h @@ -14,16 +14,13 @@ /*========== basic types etc. ==========*/ -typedef unsigned short TrainNum; -typedef unsigned short SegmentNum; -typedef unsigned short MovPosComb; -typedef unsigned short BoardObject; - -typedef unsigned char Small; - -typedef short Distance; -typedef char Speed; - /* for units, see safety.h */ +typedef int TrainNum; +typedef int SegmentNum; +typedef long MovPosComb; +typedef long Speed; +typedef int BoardObject; +typedef int Small; +typedef int Distance; typedef enum { mfk_none, @@ -61,27 +58,18 @@ typedef struct { BoardObject sense, invert; } SegmentInfo; -typedef struct { - Speed maxspeed; - Distance tail, detectable, head; - const char *pname; -} TrainInfo; - -/* These data arrays have no sentinel members. Use the info_nfoobars - * constants. Alternatively, it is legal to sed out everything from +/* This data array has no sentinel member. Use the info_nsegments + * constant. Alternatively, it is legal to sed out everything from * .layout-data.c from the first #include onwards, and - * this will give definitions of NUM_SEGMENTS and NUM_TRAINS. + * this will give a definition of NUM_SEGMENTS. */ extern const SegmentNum info_nsegments; extern const SegmentInfo info_segments[]; -extern const TrainNum info_nsegments; -extern const TrainInfo info_trains[]; - extern const BoardObject info_maxreverse; /* max. reverse + 1 */ -#define NOTA(x) (~(x##Num)0) -#define SOMEP(x) (!!~(x)) +#define NOTA(x) (-1) +#define SOMEP(x) ((x) >= 0) #endif /*LAYOUT_DATA_H*/ -- 2.30.2