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) );
BufferFull
BadCmd
NotFound
- SignallingProblemPredicted
+ SignallingPredictedProblem
SignallingHorizonReached
);
} ErrorCode;
extern $decl;
+
+#define ec2str(ec) (errorcodelist[(ec)])
+
#define DEFINE_ERRORCODELIST_DATA \\
$decl= { \\
END
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 ||
#include <limits.h>
#include <stddef.h>
#include <ctype.h>
+#include <math.h>
#include <sys/types.h>
#include <sys/time.h>
#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);
| 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);
}
goto x_problems;
d->iselem_u= 0;
- d->cm_autostop= 0;
MovPosComb target= -1;
#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 */
/*---------- 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;
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;
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 ----------*/
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)
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",
/* 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 {
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
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;
}
/* 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");
}
}
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 */
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;
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;
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 */
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();
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);
void safety_notify_detection(Segment *seg) {
Train *tra;
+ ErrorCode ec;
if (seg->det_ignore) return;
if (!seg->det_expected)
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",
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;
* 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.
* 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.
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
* -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;
* 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 ----------*/
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);
}
}
static const SpeedRange *stop_info(Train *tra, double speed) {
+ int i;
for (i=0; i<tra->n_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;
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);
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;
}
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;
}
tra->speed.decel.callback= decel_done;
tra->speed.speed= 0;
tra->speed.try_speed= -1;
- tra->decelerating= 0;
if (tra->addr < 0)
return;
#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 ----------*/
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);
*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;
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;
}
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;
}
-
-
-