From: ian Date: Tue, 22 Apr 2008 21:33:08 +0000 (+0000) Subject: new realtime/safety compiles X-Git-Url: http://www.chiark.greenend.org.uk/ucgi/~ijackson/git?a=commitdiff_plain;h=60582b6035fcb91caac397e786828e752ca98e50;p=trains.git new realtime/safety compiles --- diff --git a/hostside/Makefile b/hostside/Makefile index 95873fe..55a6ea6 100644 --- a/hostside/Makefile +++ b/hostside/Makefile @@ -35,7 +35,7 @@ realtime: realtime.o startup.o cdumgr.o safety.o trackloc.o \ utils.o serialio.o parseutils.o auproto-pic.o \ nmra.o encode.o movpos.o \ ../layout/ours.layout-data.o \ - __oop-read-copy.o -loop + __oop-read-copy.o -loop -lm $(LINK) proto-expanded: ../cebpic/README.protocol diff --git a/hostside/commands.c b/hostside/commands.c index f12362e..c17e352 100644 --- a/hostside/commands.c +++ b/hostside/commands.c @@ -27,6 +27,19 @@ struct ManualRetransmitNode { #endif #endif + +static void cmd_ppc(Train *tra, Segment *seg, void *pu, const char *message) { + const CmdInfo *ci= pu; + oprintf(UPO,"ack SignallingPredictedProblem %s %s", ci->name, message); +} + +#define MUSTECRPREDICT(requester) do{ \ + int mustecr__ec= (requester); \ + if (mustecr__ec==EC_SignallingPredictedProblem) return EC_BadCmd; \ + if (mustecr__ec) return mustecr__ec; \ + }while(0) +#define CMDPPC cmd_ppc,(void*)ci + struct NmraParseEncodeCaller { ParseState *ps; unsigned long arg[NMRA_MAX_NARGS]; @@ -206,7 +219,7 @@ static int ps_needtrain(ParseState *ps, Train **tra_r) { } static int cmd_movfeat(ParseState *ps, const CmdInfo *ci) { - Segment *move, *back, *fwd; + Segment *move; const SegmentInfo *movei; long ms; long poscomb; @@ -214,16 +227,16 @@ static int cmd_movfeat(ParseState *ps, const CmdInfo *ci) { MUSTECR( ps_needsegmentperhaps(ps,&move,&movei) ); MUSTECR( ps_needword(ps) ); if (CTYPE(isdigit,*ps->thisword)) { - back= fwd= 0; if (!move) badcmd(ps,"invalid movement specification"); ps_pushbackword(ps); MUSTECR( ps_neednumber(ps,&poscomb,0,movei->n_poscombs, "position number") ); } else { - poscomb= -1; + Segment *back, *fwd; back= move; MUSTECR( ps_needsegment(ps,&move,&movei) ); MUSTECR( ps_needsegmentperhaps(ps,&fwd,0) ); + MUSTECR( movpos_findcomb_bysegs(back,move,fwd,move->movposcomb,&poscomb) ); } ms= INT_MAX; @@ -233,44 +246,25 @@ static int cmd_movfeat(ParseState *ps, const CmdInfo *ci) { MUSTECR( ps_neednoargs(ps) ); if (!ci->xarg) - MUSTECR( safety_check_movposchange(move) ); + MUSTECRPREDICT( safety_check_movposchange(move,CMDPPC) ); - MUSTECR( movpos_change_bysegs(back,move,fwd,ms,0) ); + MUSTECR( movpos_change(move,poscomb,ms,0) ); return 0; } static int cmd_speed(ParseState *ps, const CmdInfo *ci) { - long speed, max; - int curvesz; + long speed; Train *tra; MUSTECR( ps_needtrain(ps,&tra) ); - curvesz= tra->accel.curvesz; - switch (ci->xarg) { - case 0: max=INT_MAX; break; - case 1: max=1000; break; - case 2: max=126; break; - default: abort(); - } - - MUSTECR( ps_neednumber(ps,&speed,0,max,"speed step") ); + MUSTECR( ps_neednumber(ps,&speed,0,126,"speed step") ); MUSTECR( ps_neednoargs(ps) ); - switch (ci->xarg) { - case 0: - break; - case 1: - speed= speed / 1000.0 * tra->accel.curve[curvesz-1].speed; - break; - case 2: - if (speed >= curvesz) speed= curvesz-1; - speed= tra->accel.curve[speed].speed; - break; - } + MUSTECRPREDICT( speedmanager_speedchange_request(tra,speed,CMDPPC) ); - return safety_requestspeed(tra, speed); + return 0; } const CmdInfo toplevel_cmds[]= { @@ -279,8 +273,6 @@ const CmdInfo toplevel_cmds[]= { { "noop", cmd_noop }, { "movfeat", cmd_movfeat }, { "movfeat!", cmd_movfeat, 1 }, - { "speedmms", cmd_speed, 1 }, - { "speedpermil",cmd_speed, 2 }, - { "speed126", cmd_speed, 0 }, + { "speed", cmd_speed }, { 0 } }; diff --git a/hostside/errorcodes.h.gen b/hostside/errorcodes.h.gen index b4927f2..64784a0 100755 --- a/hostside/errorcodes.h.gen +++ b/hostside/errorcodes.h.gen @@ -5,9 +5,9 @@ MovFeatTooLate MovFeatKindsCombination MovFeatReservationInapplicable + MovFeatRouteNotFound BufferFull BadCmd - NotFound SignallingPredictedProblem SignallingHorizonReached ); diff --git a/hostside/movpos.c b/hostside/movpos.c index 5d2235b..4a89d44 100644 --- a/hostside/movpos.c +++ b/hostside/movpos.c @@ -16,7 +16,7 @@ typedef struct KindInfo KindInfo; /* Kind-independent code is responsible for determining * the method, doing a bit of cleanup, and adjusting the flow * slightly. Per-kind code does the actual work and is mostly in - * charge - it is also responsible for updating seg->moving. + * charge - it is also responsible for updating seg->moving and ->motion. */ /* The following states exist for each MovPosChange * at points when control flow passes between kind and indep: @@ -26,7 +26,7 @@ typedef struct KindInfo KindInfo; * C Confirmed motion queued and will occur * D Done motion is complete and callback just needs to be made * E Erroneous indep must call destroy straight away - * seg->moving is in one of the states UC + * seg->moving and ->motion is in one of the states UC */ typedef struct MovPosChange { /* valid in: filled in by and when: */ @@ -38,7 +38,7 @@ typedef struct MovPosChange { /* valid in: filled in by and when: */ } Change; /* `actual' contains the kind's public opinion about the physical * state. It is initialised by indep (just before confirm) from - * move->moving->actual or move->movposcomb as the case may be. It + * move->motion->actual or move->movposcomb as the case may be. It * should be updated by the kind, since it is used by indep for * calculating the number and identities of the features which may * need to change when a new move request is intended to replace an @@ -58,8 +58,8 @@ struct KindInfo { /* indep guarantees that * alloc_motions >= move->i->n_motions on reserve * alloc_motions >= n_motions on confirm - * and that if on entry to reserve move->moving is non-0, - * it is of the same kind + * and that if on entry to reserve move->motion is non-0, + * it move->motion is non-0 and of the same kind */ }; @@ -326,8 +326,9 @@ fprintf(stderr," point confirm\n"); /* state A or R */ pt_dequeue(r); /* states of existing: */ - PointReq *existing= (PointReq*)move->moving; /* U or C */ - if (existing) pt_dequeue(existing); /* U or CA */ + PointReq *existing= + move->moving ? (PointReq*)move->motion : 0; /* U or C */ + if (existing) pt_dequeue(existing); /* U or CA */ /* state A or RA */ memcpy(r->motions, motions, sizeof(r->motions[0])*n_motions); @@ -362,7 +363,8 @@ fprintf(stderr," point confirm\n"); */ if (!ec) { - move->moving= chg; + move->moving= 1; + move->motion= chg; move->movposcomb= -1; pt_check_action(); } @@ -410,11 +412,12 @@ static void pt_check_action(void) { * eg if we are asked to move the */ Segment *move= r->h.move; - assert(move->moving == (Change*)r); + assert(move->moving && move->motion == (Change*)r); pt_queue_remove_index(&pt_confirmed,0); pt_mark_as_allocated(r); /* now state A aka Done */ move->movposcomb= r->h.actual; move->moving= 0; + move->motion= 0; free(r); pt_check_action(); } @@ -430,8 +433,9 @@ void points_all_abandon(void) { for (i=0; ih.move; - assert(move->moving == (Change*)r); + assert(move->motion == (Change*)r); move->moving= 0; + move->motion= 0; move->movposcomb= r->h.actual; free(r); } @@ -506,7 +510,7 @@ static int evaluate_target(Segment *move, MovPosComb target, if (startpoint<0) startpoint= movpos_poscomb_actual(move); - for (feat=0, feati=movei->movfeats, tchanges=0, kind= mfk_none;; + for (feat=0, feati=movei->movfeats, tchanges=0, kind= mfk_none; featn_movfeats; feat++, feati++) { if (!change_needed(feati,target,startpoint)) continue; @@ -529,8 +533,8 @@ ErrorCode movpos_findcomb_bysegs(Segment *back, Segment *move, Segment *fwd, for (tcomb=0, pci=movei->poscombs; tcombn_poscombs; tcomb++, pci++) { - Segment *tback= &segments[pci->backwards.next]; - Segment *tfwd= &segments[pci->forwards .next]; + Segment *tback= &segments[pci->link[1].next]; + Segment *tfwd= &segments[pci->link[0].next]; if (back && !(back==tback || back==tfwd)) continue; if (fwd && !(fwd ==tback || fwd ==tfwd)) continue; @@ -552,8 +556,8 @@ ErrorCode movpos_findcomb_bysegs(Segment *back, Segment *move, Segment *fwd, } if (*chosen_r) *chosen_r= bestcomb; return - tchanges==INT_MAX ? EC_Invalid : - tchanges==INT_MAX-1 ? EC_MovFeatKindsCombination : + bestchanges==INT_MAX ? EC_MovFeatRouteNotFound : + bestchanges==INT_MAX-1 ? EC_MovFeatKindsCombination : 0; } @@ -603,7 +607,7 @@ fprintf(stderr," motion %s %lu kind=%d\n",feati->pname,posn,kind); if (chg) { if (chg->ki != ki || chg->move != move || - chg->intent != intent) + chg->intent != target) return EC_MovFeatReservationInapplicable; } else { chg= mp_allocate(ki,move,n_motions,target); @@ -626,12 +630,11 @@ ErrorCode movpos_reserve(Segment *move, int maxdelay_ms, MovPosChange **res_r, MovPosComb target, MovPosComb startpoint /*as for findcomb*/) { MovFeatKind kind= mfk_none; - const MovFeatInfo *feati; ErrorCode ec; - int feat, nchanges; + int nchanges; nchanges= evaluate_target(move,target,startpoint,&kind); - if (nchanges=-1) return EC_MovFeatKindsCombination; + if (nchanges==-1) return EC_MovFeatKindsCombination; const KindInfo *ki= &methodinfos[kind]; Change *chg= mp_allocate(ki, move, move->i->n_movfeats, target); @@ -652,7 +655,7 @@ void movpos_unreserve(MovPosChange *res) { } MovPosComb movpos_poscomb_actual(Segment *seg) { - return seg->moving ? seg->moving->actual : seg->movposcomb; + return seg->moving ? seg->motion->actual : seg->movposcomb; } MovPosComb movpos_change_intent(MovPosChange *chg) { diff --git a/hostside/persist.c b/hostside/persist.c index 01171e5..d10a3ea 100644 --- a/hostside/persist.c +++ b/hostside/persist.c @@ -362,29 +362,21 @@ static void persist_mapread(void) { mapmem(0, datalen, PROT_READ); } +#define SANE_SEGMENT(seg) + void persist_entrails_run_converter(void) { - TRA_IV; SEG_IV; MovPosComb report; persist_mapread(); - FOR_TRA { - if (!tra->pname || !tra->foredetect || - !tra->foredetect->i || !tra->foredetect->i->pname) - continue; - printf("train %s at %s%s:%d-+%d\n", - tra->pname, tra->backwards ? "-" : "", -fixme tra->backwards is wrong - need to provide both tra->backwards and tr_backwards - tra->foredetect->i->pname, tra->mininto, tra->uncertainty); - } FOR_SEG { if (seg->i != segi || !segi->pname || !seg->owner || !seg->owner->pname) continue; - printf("seg %s has %s%s\n", - segi->pname, seg->tr_backwards ? "-" : "", seg->owner->pname); + printf("seg %s has %s%s\n", segi->pname, + (seg->tr_backwards & seg->owner->backwards) ? "-" : "", + seg->owner->pname); if (segi->n_poscombs>1 && (report= movpos_poscomb_actual(seg)) >=0 && diff --git a/hostside/record-i.h b/hostside/record-i.h index ff0ba87..e876cf7 100644 --- a/hostside/record-i.h +++ b/hostside/record-i.h @@ -7,12 +7,11 @@ #include "record.h" #include "record-y.h" -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_home(Train *tra, int backw, Segment *seg); 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); void record_feature_nmrafeat(FeaturesFeature*, FeaturesAddr*, int num); diff --git a/hostside/record-y.y b/hostside/record-y.y index 984fa9c..964b0cb 100644 --- a/hostside/record-y.y +++ b/hostside/record-y.y @@ -44,12 +44,6 @@ line: /* empty */ | TRAIN train IS NUM NUM '+' NUM '+' NUM { 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 AT backwards seg ':' NUM '+' '-' NUM - { if ($2) record_train_at($2,$4,$5,$7,$10); - } | TRAIN train HOME { cur_train=$2; } segments { } diff --git a/hostside/record.c b/hostside/record.c index b75964b..3dcfe58 100644 --- a/hostside/record.c +++ b/hostside/record.c @@ -184,13 +184,6 @@ void record_train_is(Train *tra, int addr, int head, int det, int tail) { tra->tail= tail; } -void record_train_at(Train *tra, int backw, Segment *seg, int mini, int unc) { - tra->foredetect= seg; - tra->maxinto= maxi; - tra->uncertainty= unc; - tra->backwards= backw; -} - void record_train_home(Train *tra, int backw, Segment *seg) { if (!tra) return; seg->home= tra; @@ -268,7 +261,7 @@ void record_train_stopregime_count(void) { void record_train_stopregime(Train *tra, double from, int xs, int ts) { Train *other; - SpeedRangeEntry *new; + SpeedRange *new; int i; if (rangebufused >= rangebufsz) @@ -310,13 +303,14 @@ void record_train_stopregime(Train *tra, double from, int xs, int ts) { static int speedregime_compare(const void *av, const void *bv) { const SpeedRange *a= av, *b= bv; - if (a->step == b->step) - record_yyerror("multiple speed curve points at same step"); - return a->step - b->step; + if (a->speed == b->speed) + record_yyerror("multiple identical speed regimes"); + return a->speed > b->speed ? 1 : -1; } static void speeds_postprocess(void) { TRA_IV; + int step; FOR_TRA { if (!tra->speedregimes || tra->speedcurve[1]<0) { @@ -365,7 +359,7 @@ static void alloc(void) { SEG_IV; void *mapbase=0; char **trap; - int phase, offset, datalen=0; + int phase, offset, datalen=0, step; #define ALLOC(array,count) \ ((array)= alloc_some(mapbase,&offset,sizeof(*(array)),(count))) @@ -423,7 +417,7 @@ static void alloc(void) { datalen= offset; } - curvebuf= mmalloc(sizeof(*curvebuf) * curvebufsz); + rangebuf= mmalloc(sizeof(*rangebuf) * rangebufsz); } /*---------- entrypoint from main, and its subroutines ----------*/ @@ -449,7 +443,7 @@ static void parse_pass(const char **argv) { } void records_parse(const char **argv) { - parse_pass(argv); /* trains==0: counts trains and curve points. */ + parse_pass(argv); /* trains==0: counts trains and speed ranges. */ alloc(); parse_pass(argv); /* trains!=0: populates data area */ record_tempzone_clear(); diff --git a/hostside/resolve.c b/hostside/resolve.c index 11dad34..35a6539 100644 --- a/hostside/resolve.c +++ b/hostside/resolve.c @@ -320,9 +320,6 @@ int resolve_complete(void) { target= d->movposcomb; } - if (d->owner) - d->until_here= 1e-3; - if (d->i->n_poscombs>1) { d->movposcomb= -1; if (target >= 0) { @@ -340,12 +337,6 @@ int resolve_complete(void) { } } - FOR_TRAIN(t,NOOP,NOOP) { - t->speed= 0; - if (t->resolution == RR_E) - t->backwards= 0; - } - if (problems) { x_problems: oprintf(UPO,"resolution problems %d\n",problems); @@ -371,10 +362,10 @@ static int segdist(Segment *seg) { static int findhead_nextseg(TrackLocation *t, struct TrackAdvanceContext *c, MovPosComb *mpc_io, Segment *before) { FindEndUserContext *u= c->u; - if (t->seg->owner != train) return -1; + if (t->seg->owner != u->train) return -1; if (!t->seg->res_detect) { u->extraspace= 0; return -1; } - u->train->foredetect= seg; + u->train->foredetect= t->seg; t->seg->tr_backwards= t->backwards; t->seg->res_detect= 0; return 0; @@ -382,16 +373,20 @@ static int findhead_nextseg(TrackLocation *t, struct TrackAdvanceContext *c, static int walkback_nextseg(TrackLocation *t, struct TrackAdvanceContext *c, MovPosComb *mpc_io, Segment *before) { - if (t->seg->owner != train) return -1; + FindEndUserContext *u= c->u; + if (t->seg->owner != u->train) return -1; t->seg->tr_backwards= !t->backwards; t->seg->resfin_done= 1; + return 0; } static void resolve_train_finalise(Segment *startpoint) { + SEG_IV; Train *tra; TrackLocation t; TrackAdvanceContext tc; FindEndUserContext u; + int r; assert(startpoint->owner); tra= startpoint->owner; @@ -410,11 +405,10 @@ static void resolve_train_finalise(Segment *startpoint) { u.extraspace= MARGIN_NOSE + tra->head; - r= findhead_nextseg(&t,&c,0,0); assert(!r); + r= findhead_nextseg(&t,&tc,0,0); assert(!r); trackloc_advance(&t,&tc); - tra->foredetect= u->foredetect; - tra->maxinto= segdist(tra->foredetect) - u->extraspace; + tra->maxinto= segdist(tra->foredetect) - u.extraspace; if (tra->maxinto < 0) tra->maxinto= 0; tra->uncertainty= tra->maxinto; @@ -433,8 +427,8 @@ static void resolve_train_finalise(Segment *startpoint) { r= walkback_nextseg(&t,&tc,0,0); assert(!r); trackloc_advance(&t,&tc); - if (u->distance) { - tra->uncertainty -= u->distance; + if (tc.distance) { + tra->uncertainty -= tc.distance; if (tra->uncertainty < 0) safety_panic(tra, t.seg, "resolved train location too small by %d!", -tra->uncertainty); diff --git a/hostside/safety.c b/hostside/safety.c index 1eaf1e2..0501bef 100644 --- a/hostside/safety.c +++ b/hostside/safety.c @@ -252,6 +252,10 @@ typedef struct { int noninv_tally[2]; } PredictUserContext; +static int nose_length(Train *tra) { + return MARGIN_NOSE + (tra->backwards ? tra->tail : tra->head); +} + /*---------- prediction problem reporting ----------*/ static ErrorCode predict_vproblem(PredictUserContext *u, Segment *seg, @@ -323,7 +327,7 @@ static int nose_nextseg(TrackLocation *t, TrackAdvanceContext *c, /* Is it empty ? */ - if (speedmanager_stopping(train) && t->seg->owner != u->train) + if (speedmanager_stopping(u->train) && t->seg->owner != u->train) return EC_SignallingHorizonReached; if (t->seg->owner) { @@ -442,7 +446,7 @@ static int fdet_nextseg(TrackLocation *t, TrackAdvanceContext *c, u->nosec.distance= advanced; r= trackloc_advance(&u->nose,&u->nosec); - if (r == SignallingHorizonReached && + if (r == EC_SignallingHorizonReached && u->was_distance==INT_MAX) { /* Our very first `next segment' lookahead found the end. So we * know that our nose hasn't left this segment because that's what @@ -451,7 +455,7 @@ static int fdet_nextseg(TrackLocation *t, TrackAdvanceContext *c, int adjust= nose_length(u->train); if (adjust > u->train->maxinto) adjust= u->train->maxinto; u->train->maxinto -= adjust; - u->train->uncertainto += adjust; + u->train->uncertainty += adjust; } if (r) return r; @@ -523,10 +527,6 @@ static int fdet_nextseg(TrackLocation *t, TrackAdvanceContext *c, /*---------- prediction entrypoint ----------*/ -static int nose_length(Train *tra) { - return MARGIN_NOSE + (tra->backwards ? tra->tail : tra->head); -} - ErrorCode predict_confirm(Train *tra, int accelerate, PredictionProblemCallback *ppc, void *ppcu) { PredictUserContext u; @@ -653,16 +653,16 @@ static void detection_report_problem(Train *tra, Segment *seg, void safety_notify_detection(Segment *seg) { Train *tra; - TrackLoc tloc; ErrorCode ec; if (seg->det_ignore) return; if (!seg->det_expected) safety_panic(0,seg, "unexpected detection"); + + tra= seg->owner; if (seg->movposcomb < 0) safety_panic(tra,seg, "track route not set and train has arrived"); - tra= seg->owner; tra->foredetect= seg; tra->uncertainty= tra->maxinto= seg->i->poscombs[seg->movposcomb].dist; @@ -677,12 +677,16 @@ void safety_notify_detection(Segment *seg) { assert(!ec); } -ErrorCode safety_check_movposchange(Segment *seg) { +ErrorCode safety_check_movposchange(Segment *seg, + PredictionProblemCallback *ppc, void *ppcu) { + PredictUserContext u; + + u.problem_callback= ppc; + u.problem_callback_u= ppcu; + u.train= seg->owner; + if (seg->owner) { - oprintf(UPO,"ack SignallingProblemPredicted @%s %s:" - " route set for approaching train", - seg->i->pname, seg->owner->pname); - return EC_BadCmd; + return predict_problem(&u,seg, " route set for approaching train"); } return 0; } diff --git a/hostside/safety.h b/hostside/safety.h index 67b3704..4a1ff6c 100644 --- a/hostside/safety.h +++ b/hostside/safety.h @@ -108,7 +108,8 @@ void safety_setdirection(Train* tra, int backwards); void safety_notify_detection(Segment *seg); /* Called by startup.c when new train detection occurs in state Run. */ -ErrorCode safety_check_movposchange(Segment *seg); +ErrorCode safety_check_movposchange(Segment *seg, + PredictionProblemCallback *ppc, void *ppcu); /* If this check success, caller may call movpos_change */ ErrorCode predict_confirm(Train *tra, int accelerate, @@ -206,7 +207,7 @@ ErrorCode speedmanager_speedchange_request(Train *tra, int step, void speedmanager_reset_train(Train *tra); double speedmanager_speed_maxestimate(Train *tra); double speedmanager_stoppingdistance(Train *tra); -int speedmanager_speed_stopping(Train *tra); +int speedmanager_stopping(Train *tra); /*========== actual.c ==========*/ /* actual.c should only be called from safety.c. @@ -297,6 +298,8 @@ int trackloc_advance(TrackLocation *t, TrackAdvanceContext *c); * traversed. */ int trackloc_reverse_exact(TrackLocation *t, TrackAdvanceContext *c); +int trackloc_set_exactinto(TrackLocation *t, TrackAdvanceContext *c, + Segment *seg, int backwards, int into); /* c is used just as for trackloc_getlink. * If we can't determine the movposcombs we call abort. */ diff --git a/hostside/speed.c b/hostside/speed.c index 6b22f25..e0e932b 100644 --- a/hostside/speed.c +++ b/hostside/speed.c @@ -79,7 +79,7 @@ double speedmanager_stoppingdistance(Train *tra) { return xs; } -int speedmanager_speed_stopping(Train *tra) { +int speedmanager_stopping(Train *tra) { return tra->speed.try_speed < 0 && !tra->speed.speed; } diff --git a/hostside/trackloc.c b/hostside/trackloc.c index 5dfdffa..98a6e37 100644 --- a/hostside/trackloc.c +++ b/hostside/trackloc.c @@ -13,6 +13,21 @@ void trackloc_set_maxinto(TrackLocation *tloc, Segment *seg, int backwards) { tloc->remain= 0; } +int trackloc_set_exactinto(TrackLocation *t, TrackAdvanceContext *c, + Segment *seg, int backwards, int into) { + const SegPosCombInfo *pci; + int r; + + r= trackloc_getlink(t,c,&pci,0,-1); + if (r) return r; + assert(pci); + + t->seg= seg; + t->backwards= backwards; + t->remain= pci->dist - into; + return 0; +} + /*---------- enquirers ----------*/ int trackloc_getlink(TrackLocation *t, TrackAdvanceContext *c, @@ -49,7 +64,6 @@ int trackloc_advance(TrackLocation *t, TrackAdvanceContext *c) { const SegPosCombInfo *pci; const SegmentLinkInfo *link; MovPosComb mpc_nego; - int leaving_back; int r; r= trackloc_getlink(t,c, 0,&link, t->seg->movposcomb);