From: ian Date: Mon, 21 Apr 2008 00:08:40 +0000 (+0000) Subject: wip new safety - making it compile X-Git-Url: http://www.chiark.greenend.org.uk/ucgi/~ijackson/git?a=commitdiff_plain;h=55db1d1650d1d662683da2c8210d58036f7f5c9e;p=trains.git wip new safety - making it compile --- diff --git a/hostside/commands.c b/hostside/commands.c index 0f7987c..f12362e 100644 --- a/hostside/commands.c +++ b/hostside/commands.c @@ -233,7 +233,7 @@ static int cmd_movfeat(ParseState *ps, const CmdInfo *ci) { MUSTECR( ps_neednoargs(ps) ); if (!ci->xarg) - MUSTECR( safety_checkmovposchange(move) ); + MUSTECR( safety_check_movposchange(move) ); MUSTECR( movpos_change_bysegs(back,move,fwd,ms,0) ); diff --git a/hostside/errorcodes.h.gen b/hostside/errorcodes.h.gen index 5ccde34..b4927f2 100755 --- a/hostside/errorcodes.h.gen +++ b/hostside/errorcodes.h.gen @@ -8,7 +8,7 @@ BufferFull BadCmd NotFound - SignallingProblemPredicted + SignallingPredictedProblem SignallingHorizonReached ); @@ -26,6 +26,9 @@ END } ErrorCode; extern $decl; + +#define ec2str(ec) (errorcodelist[(ec)]) + #define DEFINE_ERRORCODELIST_DATA \\ $decl= { \\ END diff --git a/hostside/persist.c b/hostside/persist.c index 1335bc7..4221eac 100644 --- a/hostside/persist.c +++ b/hostside/persist.c @@ -373,9 +373,9 @@ void persist_entrails_run_converter(void) { if (!tra->pname || !tra->foredetect || !tra->foredetect->i || !tra->foredetect->i->pname) continue; - printf("train %s at %s%s:%d+-%d\n", + printf("train %s at %s%s\n", tra->pname, tra->backwards ? "-" : "", - tra->foredetect->i->pname, tra->maxinto, tra->uncertainty); + tra->foredetect->i->pname); } FOR_SEG { if (seg->i != segi || !segi->pname || diff --git a/hostside/realtime.h b/hostside/realtime.h index 04dafe4..c85b96c 100644 --- a/hostside/realtime.h +++ b/hostside/realtime.h @@ -17,6 +17,7 @@ #include #include #include +#include #include #include diff --git a/hostside/record-i.h b/hostside/record-i.h index 3ef2a42..ff0ba87 100644 --- a/hostside/record-i.h +++ b/hostside/record-i.h @@ -7,10 +7,11 @@ #include "record.h" #include "record-y.h" -void record_train_at(Train *tra, int backw, Segment *seg, int maxi, int unc); +void record_train_at(Train *tra, int backw, Segment *seg); void record_train_is(Train *tra, int addr, int head, int det, int tail); -void record_train_step(Train *tra, int step, double speed, int upw, int downw); -void record_train_step_count(void); +void record_train_step_speed(Train *tra, int step, double speed); +void record_train_stopregime_count(void); +void record_train_stopregime(Train *tra, double speed, int xs, int ts); void record_train_home(Train *tra, int backw, Segment *seg); void record_seg_has(Segment *seg, int backw, Train *tra); void record_seg_at(Segment *seg, const char *movposcomb_pname); diff --git a/hostside/record-y.y b/hostside/record-y.y index e3b588f..25193d3 100644 --- a/hostside/record-y.y +++ b/hostside/record-y.y @@ -44,6 +44,9 @@ line: /* empty */ | TRAIN train IS NUM NUM '+' NUM '+' NUM { if ($2) record_train_is($2,$4,$5,$7,$9); } + | TRAIN train AT backwards seg + { if ($2) record_train_at($2,$4,$5); + } | TRAIN train AT backwards seg ':' NUM '+' '-' NUM { if ($2) record_train_at($2,$4,$5,$7,$10); } diff --git a/hostside/resolve.c b/hostside/resolve.c index 6de6dc7..8f05587 100644 --- a/hostside/resolve.c +++ b/hostside/resolve.c @@ -307,7 +307,6 @@ int resolve_complete(void) { goto x_problems; d->iselem_u= 0; - d->cm_autostop= 0; MovPosComb target= -1; diff --git a/hostside/safety.c b/hostside/safety.c index f787355..6874a01 100644 --- a/hostside/safety.c +++ b/hostside/safety.c @@ -186,11 +186,10 @@ Segment *segments; #define pred_vacated mark2 #define will_polarise mark3 -typedef void PredictionProblemCallback(Train *tra, TrackSegment *seg, - void *pu, const char *message); - typedef struct { + Train *train; unsigned + count_time:1, accelerating:1, walk_compute_polarise:1, /* nose_nextseg still needs to worry */ need_polarise:1, /* when we commit */ @@ -212,7 +211,7 @@ typedef struct { /*---------- prediction problem reporting ----------*/ -static ErrorCode predict_vproblem(PredicUserContext *u, TrackSegment *seg, +static ErrorCode predict_vproblem(PredictUserContext *u, Segment *seg, const char *fmt, va_list al) { int l; char *message; @@ -220,14 +219,15 @@ static ErrorCode predict_vproblem(PredicUserContext *u, TrackSegment *seg, l= vasprintf(&message, fmt, al); if (l <= 0) diem(); if (!u->problem_callback) - safety_panic(u->train, seg, "unexpected problem predicted", - " (context: %s): %s", u->problem_callback_u, message); + safety_panic(u->train, seg, "unexpected problem predicted" + " (context: %s): %s", (char*)u->problem_callback_u, message); else u->problem_callback(u->train, seg, u->problem_callback_u, message); - return EC_ProblemPredicted; + return EC_SignallingPredictedProblem; } -static ErrorCode predict_problem(PredicUserContext *u, TrackSegment *seg, + +static ErrorCode predict_problem(PredictUserContext *u, Segment *seg, const char *fmt, ...) { ErrorCode ec; va_list al; @@ -243,25 +243,28 @@ static int pred_getmovpos(TrackLocation *t, TrackAdvanceContext *c, MovPosComb *use_io) { PredictUserContext *u= c->u; if (t->seg->motion) *use_io= movpos_change_intent(t->seg->motion); - if (*use_io<0) safety_panic(tra,seg, "track route unexpectedly not known"); + if (*use_io<0) safety_panic(u->train, t->seg, + "track route unexpectedly not known"); return 0; } static int pred_trackend(TrackLocation *t, TrackAdvanceContext *c) { - return predict_problem(t,c,"end of track"); + PredictUserContext *u= c->u; + return predict_problem(u, t->seg, "end of track"); } static int pred_trackend_panic(TrackLocation *t, TrackAdvanceContext *c) { PredictUserContext *u= c->u; - return safety_panic(u->train,t->seg,"unexpected end of track"); + safety_panic(u->train,t->seg,"unexpected end of track"); } static int initpresent_nextseg(TrackLocation *t, TrackAdvanceContext *c, MovPosComb *mpc_io, Segment *before) { PredictUserContext *u= c->u; - next->now_present= next->pred_present= next->will_polarise= 1; - next->until= 0; + t->seg->now_present= t->seg->pred_present= t->seg->will_polarise= 1; + t->seg->until= 0; u->noninv_tally[!t->backwards]++; /* ! since going backwards along train */ + return 0; } /*---------- prediction nose advancement ----------*/ @@ -269,14 +272,16 @@ static int initpresent_nextseg(TrackLocation *t, TrackAdvanceContext *c, static int nose_nextseg(TrackLocation *t, TrackAdvanceContext *c, MovPosComb *mpc_io, Segment *before) { PredictUserContext *u= c->u; + Segment *interferer; MovPosComb route_plan; - MovPosChange *route_change; + MovPosChange *route_reservation; TimeInterval max_ms; + ErrorCode ec; /* Is it empty ? */ if (u->train->sigstopping && t->seg->owner != u->train) - return EC_SignalStopHorizonReached; + return EC_SignallingHorizonReached; if (t->seg->owner) { if (t->seg->owner != u->train) @@ -286,7 +291,7 @@ static int nose_nextseg(TrackLocation *t, TrackAdvanceContext *c, if (t->seg->pred_present) return predict_problem(u, t->seg, "will collide with itself!"); - interferer= interferes(c,t->seg); + interferer= segment_interferes(c,t->seg); if (interferer) { if (interferer->owner && interferer->owner != u->train) return predict_problem(u, t->seg, "impeded by %s @%s", @@ -315,7 +320,7 @@ static int nose_nextseg(TrackLocation *t, TrackAdvanceContext *c, /* We already have a plan. */ route_plan= movpos_change_intent(t->seg->motion); if (!u->accelerating) { - *mpc_io= route_plan + *mpc_io= route_plan; goto movement_ok; } } else { @@ -378,7 +383,7 @@ static int tail_nextseg(TrackLocation *t, TrackAdvanceContext *c, static int fdet_nextseg(TrackLocation *t, TrackAdvanceContext *c, MovPosComb *mpc_io, Segment *before) { PredictUserContext *u= c->u; - int advanced; + int advanced, r; /* NB, on entry the movposcomb of the segment we're entering (and * other similar details) may not be known or sufficient because @@ -395,9 +400,9 @@ static int fdet_nextseg(TrackLocation *t, TrackAdvanceContext *c, u->nosec.distance= advanced; r= trackloc_advance(&u->nose,&u->nosec); - if (r==EC_SignalHorizonReached) { + if (r==EC_SignallingHorizonReached) { /* stop our prediction now */ - advanced= was_distance= t->distance= 0; + advanced= u->was_distance= t->remain= 0; r= 0; } @@ -412,7 +417,7 @@ static int fdet_nextseg(TrackLocation *t, TrackAdvanceContext *c, /* Check polarity */ - if (!t->seg->invertible) { + if (!t->seg->i->invertible) { u->noninv_tally[t->backwards]++; if (u->noninv_tally[0] && u->noninv_tally[1]) return predict_problem(u, t->seg, "cannot set track polarity"); @@ -442,14 +447,14 @@ static int fdet_nextseg(TrackLocation *t, TrackAdvanceContext *c, } } if (u->know_best_polarity && - !t->seg->i->invertible + !t->seg->i->invertible && u->noninv_tally[ t->backwards ^ u->train_polarity_inverted ]) { /* incompatible, stop now */ u->walk_compute_polarise= 0; } } if (u->walk_compute_polarise) { - seg->will_polarise= 1; + t->seg->will_polarise= 1; } /* Advance the tail */ @@ -473,21 +478,22 @@ static int fdet_nextseg(TrackLocation *t, TrackAdvanceContext *c, ErrorCode predict_confirm(Train *tra, int accelerate, PredictionProblemCallback *ppc, void *ppcu) { - /* Caller must call this with different situations until it succeeds! */ PredictUserContext u; Segment *foredet; SEG_IV; + ErrorCode ec; FOR_SEG { - seg->now_preset= seg->pred_present= - seg->pred_vacated= seg->choose_invert= 0; + seg->now_present= seg->pred_present= + seg->pred_vacated= seg->will_polarise= 0; } foredet= tra->foredetect; memset(&u,0,sizeof(u)); + u.train= tra; u.accelerating= accelerate; - u.walk_will_polarise= 1; + u.walk_compute_polarise= 1; u.train_polarity_inverted= foredet->seg_inverted ^ foredet->tr_backwards; u.problem_callback= ppc; u.problem_callback_u= ppcu; @@ -503,13 +509,13 @@ ErrorCode predict_confirm(Train *tra, int accelerate, u.tailc.trackend= pred_trackend_panic; u.tailc.u= &u; - r= initpresent_nextseg(&u.tail,&u.tailc,0,0); assert(!r); - r= trackloc_advance(&u.tail,&u.tailc); assert(!r); + ec= initpresent_nextseg(&u.tail,&u.tailc,0,0); assert(!ec); + ec= trackloc_advance(&u.tail,&u.tailc); assert(!ec); trackloc_reverse_exact(&u.tail,0); /* find the train's nose */ - u.nose= fdet; + u.nose= u.fdet; u.nosec.distance= MARGIN_NOSE + (tra->backwards ? tra->tail : tra->head); u.nosec.nextseg= nose_nextseg; u.nosec.getmovpos= pred_getmovpos; @@ -517,8 +523,8 @@ ErrorCode predict_confirm(Train *tra, int accelerate, u.nosec.u= &u; u.count_time= 0; - r= trackloc_advance(&u.nose,&u.nosec); - if (r) goto xproblem; + ec= trackloc_advance(&u.nose,&u.nosec); + if (ec) goto xproblem; /* predict the future */ @@ -530,19 +536,11 @@ ErrorCode predict_confirm(Train *tra, int accelerate, u.tailc.nextseg= tail_nextseg; - r= trackloc_advance(&fdet,&fdetc); - if (r) goto xproblem; + ec= trackloc_advance(&u.fdet,&u.fdetc); + if (ec) goto xproblem; /*----- commit to the plan -----*/ - trackloc_set_maxinto(&u.fdet, foredet, - foredet->tr_backwards); - u.fdetc.distance= INT_MAX; - u.fdetc.nextseg= polarise_nextseg; - u.fdetc.trackend= polarise_trackend; - - r= trackloc_advance(&fdet,&fdetc); - if (u.need_polarise) actual_inversions_start(); @@ -586,11 +584,12 @@ ErrorCode predict_confirm(Train *tra, int accelerate, seg->motion= 0; } } + return ec; } /*========== entrypoints from rest of the program ==========*/ -static void detection_report_problem(Train *tra, TrackSegment *seg, +static void detection_report_problem(Train *tra, Segment *seg, void *pu, const char *message) { logmsg("SignallingProblemPredicted",tra,seg->i, "re detection @%s: %s", tra->foredetect->i->pname, message); @@ -598,6 +597,7 @@ static void detection_report_problem(Train *tra, TrackSegment *seg, void safety_notify_detection(Segment *seg) { Train *tra; + ErrorCode ec; if (seg->det_ignore) return; if (!seg->det_expected) @@ -611,16 +611,15 @@ void safety_notify_detection(Segment *seg) { ec= predict_confirm(tra, 0, detection_report_problem, 0); if (!ec) return; - assert(ec == EC_SignallingProblemPredicted); + assert(ec == EC_SignallingPredictedProblem); tra->sigstopping= 1; - ec= speedmanager_speedchange_request(tra,0, 0,"detection sigstop"); + ec= speedmanager_speedchange_request(tra,0, 0,(char*)"detection sigstop"); /* that calls predict_confirm with our supplied arguments */ assert(!ec); } -ErrorCode safety_checkmovposchange(Segment *seg) { - ErrorCode ec; +ErrorCode safety_check_movposchange(Segment *seg) { if (seg->owner) { oprintf(UPO,"ack SignallingProblemPredicted @%s %s:" " route set for approaching train", diff --git a/hostside/safety.h b/hostside/safety.h index 9386343..e21531b 100644 --- a/hostside/safety.h +++ b/hostside/safety.h @@ -73,7 +73,7 @@ struct Segment { moving:1, /* feature(s) have been told to change */ mark0,mark1,mark2,mark3, /* for temporary private uses */ res_detect:1; /* detection noticed here during resolution */ - MovPosComb movposcomb, /* -1 means not known or moving */ + MovPosComb movposcomb; /* -1 means not known or moving */ MovPosChange *motion; /* if ->moving, owned by movpos, otherwise by safety */ TimeInterval until; /* for use by safety.c */ const SegmentInfo *i; @@ -101,24 +101,26 @@ void safety_panic(Train *tra, Segment *seg, const char *fmt,...) * etc.). */ -void safety_emergencystop(Train*); - /* Callable directly in response to application command. */ +typedef void PredictionProblemCallback(Train *tra, Segment *seg, + void *pu, const char *message); -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(Train* tra, int sense_fixme_define_this_properly); +void safety_setdirection(Train* tra, int backwards); + /* NYI */ void safety_notify_detection(Segment *seg); /* Called by startup.c when new train detection occurs in state Run. */ -ErrorCode safety_checkmovposchange(Segment *seg); +ErrorCode safety_check_movposchange(Segment *seg); /* If this check success, caller may call movpos_change */ +ErrorCode predict_confirm(Train *tra, int accelerate, + PredictionProblemCallback *ppc, void *ppcu); + /* Lower-level interface for speedmanager etc. + * Caller must call this with different situations until it succeeds! + * Caller may pass ppc=0 and ppcu=(char*)"some context" to + * cause safety_panic if it fails. + */ + /*========== movpos.c ==========*/ /* * movpos.c manages the CDU and points and other moveable features. @@ -197,23 +199,15 @@ MovPosComb movpos_change_intent(MovPosChange *chg); * and/or current situation */ -/*========== speedmgr.c ==========*/ +/*========== speed.c ==========*/ -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(Train *tra); -void speedmanager_autostop(Train *tra); - /* These are responsible for calling actual_setspeed. - * - * After speedmanager_autostop, ->speed will have been updated to a - * new desired speed. If it is 0 the train was going slowly and has - * been instructed to stop right now. - */ +ErrorCode speedmanager_speedchange_request(Train *tra, int step, + PredictionProblemCallback *ppc, void *ppcu); + /* ppc and ppcu as for predict_confirm */ void speedmanager_reset_train(Train *tra); +double speedmanager_speed_maxestimate(Train *tra); +double speedmanager_stoppingdistance(Train *tra); /*========== actual.c ==========*/ /* actual.c should only be called from safety.c. @@ -251,20 +245,21 @@ struct TrackLocation { /* transparent, and manipulable by trackloc_... fns */ unsigned backwards:1; /* if 1, into is positive and measured from end */ }; -void trackloc_set_mininto(TrackLocation *tloc, Segment *seg, int backwards); void trackloc_set_maxinto(TrackLocation *tloc, Segment *seg, int backwards); -typedef struct { /* all set by caller, only distance modified by trackloc: */ +typedef struct TrackAdvanceContext { + /* all set by caller, only distance modified by trackloc: */ int distance; /* All event callbacks are optional; if not supplied we pretend * that they were a no-op which returned 0. */ - int nextseg(TrackLocation *t, TrackAdvanceContext *c, - Segment *next, MovPosComb *mpc_io); + int (*nextseg)(TrackLocation *t, struct TrackAdvanceContext *c, + MovPosComb *mpc_io, Segment *before); /* On entry *mpc_io is from next->movposcomb. nextseg may modify * it if it feels like it in which case the modified value will * be used instead. If on 0-return it is still -1, getmovpos is used. * t->remain is not valid on entry and should not be touched. */ - void getmovpos(TrackLocation *t, TrackAdvanceContext *c, MovPosComb *use_io); + int (*getmovpos)(TrackLocation *t, struct TrackAdvanceContext *c, + MovPosComb *use_io); /* Will be called *use_io on entry is * - at the start of trackloc_advance value from segment * - after nextseg value left by nextseg @@ -274,7 +269,7 @@ typedef struct { /* all set by caller, only distance modified by trackloc: */ * -1 in which case advance will return whatever getmovpos did * (even if 0). When called by interfering_segment, non-0 returns * will be treated as an indication that the movposcomb is unknown. */ - int trackend(TrackLocation *t, TrackAdvanceContext *c); + int (*trackend)(TrackLocation *t, struct TrackAdvanceContext *c); /* trackloc_advance stops even if this returns 0. */ void *u; } TrackAdvanceContext; @@ -296,6 +291,10 @@ int trackloc_advance(TrackLocation *t, TrackAdvanceContext *c); * returns non-0, or sometimes 0 if we cannot continue and * the relevant callback is missing or returned 0. */ +int trackloc_reverse_exact(TrackLocation *t, TrackAdvanceContext *c); + /* c is used just as for trackloc_getlink. + * If we can't determine the movposcombs we call abort. */ + /*========== useful macros and declarations ==========*/ /*---------- looping over trains and segments ----------*/ diff --git a/hostside/speed.c b/hostside/speed.c index 516ca74..d67df9c 100644 --- a/hostside/speed.c +++ b/hostside/speed.c @@ -8,7 +8,7 @@ static void xmit(Train *tra) { Nmra n; - enco_nmra_speed126(&n, tra->addr, tra->step, tra->backwards); + enco_nmra_speed126(&n, tra->addr, tra->speed.step, tra->backwards); retransmit_urgent_requeue(&tra->speed.rn, &n); } @@ -18,15 +18,17 @@ static void decel_done(TimeoutEvent *toev) { } static const SpeedRange *stop_info(Train *tra, double speed) { + int i; for (i=0; in_speedregimes; i++) - if (speed <= speedregimes[i].speed) - return &speedregimes[i]; + if (speed <= tra->speedregimes[i].speed) + return &tra->speedregimes[i]; abort(); } static double current_speed(Train *tra, const struct timeval tnow) { - double v1, v2, elapsed; + double v1, v2; double v1sq, v2sq, vtsq; + double left_to_go, ts_v2; if (tra->speed.try_speed >= 0) return tra->speed.try_speed; if (!tra->speed.decel.running) return tra->speed.speed; @@ -39,26 +41,26 @@ static double current_speed(Train *tra, const struct timeval tnow) { return tra->speed.speed= tra->speedcurve[tra->speed.step]; } - v2= tra->speed; + v2= tra->speed.speed; v1= tra->speedcurve[tra->speed.step]; assert(v2 >= v1); - ts_v2= stop_info(v2)->ts; + ts_v2= stop_info(tra,v2)->ts; v1sq= v1*v1; v2sq= v2*v2; vtsq= v1sq + (v2sq-v1sq) * left_to_go / ts_v2; return sqrt(vtsq); } -static double speedmanager_speed_maxestimate(Train *tra) { +double speedmanager_speed_maxestimate(Train *tra) { struct timeval tnow; mgettimeofday(&tnow); return current_speed(tra,tnow) * MARGIN_SPEED; } -static double speedmanager_stoppingdistance(Train *tra) { +double speedmanager_stoppingdistance(Train *tra) { struct timeval tnow; - double vt; + double v, xs; const SpeedRange *regime; mgettimeofday(&tnow); @@ -66,12 +68,12 @@ static double speedmanager_stoppingdistance(Train *tra) { if (v==0) return 0; - regime= stop_info(tra,vt); + regime= stop_info(tra,v); xs= tra->speedregimes[tra->n_speedregimes-1].xs; - v_ts_vcrit= v * regime->ts; if (xs > v_ts_vcrit) xs= v_ts_vcrit; - xs_vcrit= regime->xs; if (xs > xs_vcrit) xs= xs_vcrit; + double v_ts_vcrit= v * regime->ts; if (xs > v_ts_vcrit) xs= v_ts_vcrit; + double xs_vcrit= regime->xs; if (xs > xs_vcrit) xs= xs_vcrit; return xs; } @@ -104,15 +106,15 @@ ErrorCode speedmanager_speedchange_request(Train *tra, int step, if (ec) { tra->speed.try_speed= -1; - ec2= predict_confirm(tra,1, 0,"abandoned acceleration"); + ec2= predict_confirm(tra,1, 0,(char*)"abandoned acceleration"); assert(!ec2); return ec; } - tra->step= step; + tra->speed.step= step; toev_stop(&tra->speed.decel); - tra->speed= vtarg; - tra->try_speed= -1; + tra->speed.speed= vtarg; + tra->speed.try_speed= -1; xmit(tra); return 0; } @@ -126,7 +128,6 @@ void speedmanager_reset_train(Train *tra) { tra->speed.decel.callback= decel_done; tra->speed.speed= 0; tra->speed.try_speed= -1; - tra->decelerating= 0; if (tra->addr < 0) return; diff --git a/hostside/trackloc.c b/hostside/trackloc.c index 1808d37..96c589d 100644 --- a/hostside/trackloc.c +++ b/hostside/trackloc.c @@ -5,23 +5,12 @@ #include "realtime.h" -typedef TrackLocationAdvanceCallbacks Calls; - /*---------- constructors/initialisers ----------*/ -void trackloc_set_mininto(TrackLocation *tloc, Segment *seg, int backwards) { - const SegPosCombInfo *pci; - - tloc->seg= seg; - tloc->backwards= backwards; - pci= trackloc_segposcomb(tloc); - tloc->remain= pci->dist; -} - void trackloc_set_maxinto(TrackLocation *tloc, Segment *seg, int backwards) { tloc->seg= seg; tloc->backwards= backwards; - tloc->into= 0; + tloc->remain= 0; } /*---------- enquirers ----------*/ @@ -31,10 +20,10 @@ int trackloc_getlink(TrackLocation *t, TrackAdvanceContext *c, const SegmentLinkInfo **link_r, MovPosComb mpc) { const SegPosCombInfo *pci; - MovPosComb mpc; + int r; if (mpc<0) - mpc= t->movposcomb; + mpc= t->seg->movposcomb; if (c && c->getmovpos) { r= c->getmovpos(t,c,&mpc); @@ -45,38 +34,42 @@ int trackloc_getlink(TrackLocation *t, TrackAdvanceContext *c, *link_r=0; return 0; } - assert(mpc < seg->i->n_poscombs); - pci= &seg->i->poscombs[seg->movposcomb]; + assert(mpc < t->seg->i->n_poscombs); + pci= &t->seg->i->poscombs[t->seg->movposcomb]; if (*pci_r) *pci_r= pci; - if (*link_r) *link_r= tloc->backwards ? &pci->backwards : &pci->forwards; + if (*link_r) *link_r= &pci->link[t->backwards]; return 0; } /*---------- mutator ----------*/ int trackloc_advance(TrackLocation *t, TrackAdvanceContext *c) { - Segment *next, *save; + Segment *next, *leaving; + SegmentNum nextnum; + const SegPosCombInfo *pci; const SegmentLinkInfo *link; MovPosComb mpc_nego; int leaving_back; + int r; - r= trackloc_getlink(t,c, 0,&link, t->seg.movposcomb); + r= trackloc_getlink(t,c, 0,&link, t->seg->movposcomb); if (r || !link) return r; for (;;) { if (!c->distance) return 0; if (t->remain) { - use= t->remain < *distance ? t->remain : *distance; + int use= t->remain < c->distance ? t->remain : c->distance; t->remain -= use; - *distance -= use; + c->distance -= use; } else { - next= link->next; + nextnum= link->next; - if (!SOMEP(next)) { + if (!SOMEP(nextnum)) { if (c->trackend) return c->trackend(t,c); return 0; } + next= &segments[nextnum]; leaving= t->seg; leaving_back= t->backwards; @@ -85,28 +78,34 @@ int trackloc_advance(TrackLocation *t, TrackAdvanceContext *c) { mpc_nego= next->movposcomb; if (c->nextseg) { - r= calls->nextseg(t,c, &mpc_nego,leaving); + r= c->nextseg(t,c, &mpc_nego,leaving); if (r) return r; } - r= trackloc_getlink(t,c, 0,&link, mpc_nego); + r= trackloc_getlink(t,c, &pci,&link, mpc_nego); if (r || !link) { t->seg=leaving; - t->seg->backwards= leaving_back; + t->backwards= leaving_back; return r; } - t->remain= link->dist; + t->remain= pci->dist; } } } static int interfering_movposcomb(TrackAdvanceContext *c, Segment *seg) { MovPosComb mpc; + int r; - mpc= t->movposcomb; + mpc= seg->movposcomb; if (c && c->getmovpos) { - r= c->getmovpos(t,c,&mpc); + TrackLocation t; + t.seg= seg; + t.backwards= 0; + t.remain= 0; + + r= c->getmovpos(&t,c,&mpc); if (r) return 1; } @@ -131,71 +130,14 @@ Segment *segment_interferes(TrackAdvanceContext *c, Segment *base) { return inter; } -/* ============ OLD CODE ============= */ - - - - -void trackloc_reverse(TrackLocation *tloc); - /* Reverses tloc without changing its actual location. */ - -const SegPosCombInfo *trackloc_segposcomb(const TrackLocation *tloc); -const SegmentLinkInfo *trackloc_segmentlink(const TrackLocation *tloc, - const SegPosCombInfo *pci, - unsigned far); - -xxx long trackloc_remaininseg(const TrackLocation *tloc) { +int trackloc_reverse_exact(TrackLocation *t, TrackAdvanceContext *c) { const SegPosCombInfo *pci; - long segment_len; - - pci= trackloc_segposcomb(tloc); - if (!pci) return -1; - segment_len= pci->dist; - assert(tloc->into <= segment_len); - return segment_len - tloc->into; -} - -xxx long trackloc_remaininseg_poscomb(const SegPosCombInfo *pci) { - segment_len= pci->dist; - assert(tloc->into <= segment_len); - return segment_len - tloc->into; -} - + int r; -void trackloc_reverse_inexact(TrackLocation *tloc) { - tloc->remain= trackloc_segmentlink(tloc) - tloc->remain; - tloc->backwards ^= 1; -} - - -int trackloc_further(TrackLocation *tloc, long *remain_io, Segment *err_r) { - const SegPosCombInfo *pci; - const SegmentLinkInfo *lnki_far; - Segment *nextseg; - long segment_remain; - - - if (*remain_io <= segment_remain) { - tloc->into += *remain_io; - *remain_io= 0; - return 0; - } else { - *remain_io -= segment_remain; - tloc->into += segment_remain; - pci= trackloc_segposcomb(tloc); - - lnki_far= trackloc_segmentlink(tloc, pci, 0); - if (!SOMEP(lnki_far->next)) { *err_r=tloc->seg; return -2; } - - nextseg= &segments[lnki_far->next]; - if (nextseg->movposcomb<0) { *err_r=nextseg; return -1; } - - tloc->seg= nextseg; - tloc->into= 0; - tloc->backwards ^= lnki_far->next_backwards; - return +1; - } + r= trackloc_getlink(t,c,&pci,0,-1); + if (r) return r; + assert(pci); + t->remain= pci->dist - t->remain; + t->backwards ^= 1; + return 0; } - - -