Segment *invert_forcer; /* the unswitchable which forces */
} LayTrainState;
+static void lay_train_check_clash(LayTrainState *l, Segment *check,
+ Segment *report) {
+ const char *exi1="", *exi2="";
+ if (check!=report) { exi1= " at "; exi2= check->i->pname; }
+
+ if (seg->tr_updated) {
+ l->ec= safety_problem(l->tra, report, "self-collision%s%s", exi1,exi2);
+ return;
+ }
+ if (seg->owner) {
+ if (seg->owner != l->tra) {
+ l->ec= safety_problem(l->tra, tloc.seg, "collision with %s"
+ "%s%s", seg->owner->pname, exi1,exi2);
+ return;
+ }
+ }
+}
+
+static Segment *interferes(Segment *base) {
+ const SegmentInfo *basei, *interi;
+ SegmentNum intern;
+ Segment *inter;
+
+ basei= base->i;
+ intern= seg->i->interferes;
+
+ if (!SOMEP(intern)) return 0;
+ if (!(segi->interferes_movposcomb_map & (1u << base->movposcomb)))
+ return 0;
+
+ inter= &segments[intern];
+ interi= &info_segments[intern];
+
+ assert(base == &info_segments[interi->interferes]);
+ if (!inter->moving &&
+ !(interi->interferes_movposcomb_map & (1u << inter->movposcomb)))
+ return 0;
+
+ return inter;
+}
+
static void lay_train_pass(LayTrainState *l,
TrackLocation tloc, long advance,
long speed, unsigned backwards,
seg= tloc.seg;
if (check_clash) {
- if (seg->tr_updated) {
- l->ec= safety_problem(l->tra, tloc.seg, "self-collision");
- return;
- }
- if (seg->owner) {
- if (seg->owner != l->tra) {
- l->ec= safety_problem(l->tra, tloc.seg, "collision with %s",
- seg->owner->pname);
- return;
- }
- }
+ lay_train_check_clash(l,seg,seg);
+ inter= interfere_physical(seg);
+ if (inter) lay_train_check_clash(l,inter,seg);
}
-
+
seg->owner= l->tra;
seg->tr_backwards= tloc.backwards ^ backwards;
seg->tr_updated= 1;
# $segs{$seg}{Feats}{$pt}{Posns} ) for Point only
# $segs{$seg}{Feats}{$pt}{BoOb}[] ) for Point only
# $segs{$seg}{Feats}{$pt}{Fixed} position, for Fixed only
+# $segs{$seg}{Inter}{Seg} ) calculated
+# $segs{$seg}{Inter}{Map} ) in writeout
# $segs{$seg}{Num}
# $segs{$seg}{Ends}[$combpos][$end] = [ $node,$side ]
# $segs{$seg}{Dist}[$combpos]
+our (@interferences);
+# $interferences[][] = "$seg/$posre" "/.*" added during parsing if necc.
+
our (%nodes);
# $nodes{$node}[$side]{Seg}
# $nodes{$node}[$side]{End}
sub ditch ($) {
my ($m) = @_;
- print STDERR "ditching $m\n";
+ print STDERR "info: ditching $m\n";
}
sub begin_points () { }
$reversersboardnum[$boob->[0]]= -1;
}
+sub begin_interferences () {
+}
+sub line_interferences () {
+ s/^\s+// or return syntaxerror();
+ my ($is) = [ split /\s+/, $_ ];
+ map { s,$,/.*, unless m,/,; } @$is;
+ return syntaxerror() if grep { !m,^\w+/, } @$is;
+ push @interferences, $is;
+}
+
sub mistake ($) {
my ($m) = @_;
print STDERR "mistake: $m\n in $mode, \`$currentline'\n";
$mistakes++;
}
+sub endmistake ($) {
+ my ($m) = @_;
+ print STDERR "mistake: $m\n";
+ $mistakes++;
+}
+
sub line_endwiring () {
my (@ns,$seg,$subspec,$dist);
my ($segr,@subsegil,$feat,$pos,$featr,$combpos,%featposwant);
m,^\s*segment\s+(\w+\.\d+)\s+(\w+\.\d+)\s+(\w+)(?:/((?:[A-Za-z]+\d+)+)\*\d+)?\s+([0-9.]+)$, or return syntaxerror();
($ns[0],$ns[1],$seg,$subspec,$dist)=($1,$2,$3,$4,$5);
if (!exists $segs{$seg}) {
- ditch("unwired $seg$subspec");
+ ditch("unwired $seg/$subspec");
return;
}
$segr= $segs{$seg};
$featr= $segr->{Feats}{$feat};
if (exists $featr->{Fixed}) {
if ($pos != $featr->{Fixed}) {
- ditch("fixed-elsewise $seg$subspec");
+ ditch("fixed-elsewise $seg/$subspec");
return;
}
} else {
return sprintf("%#5x /* %d.%-2d*/", $objnum, $board, $obj);
} else {
#print "so_boob >$objnum_rr|$$objnum_rr< -\n";
- return " 0 /*none*/ ";
+ return " 0 /*none*/ ";
}
}
sub so_objboob ($$$;$) {
my ($kind,$mkused,$obj, $objnum_rr) = @_;
-# return so_boob($kind,$mkused, defined $obj ? $obj->{BoOb} : undef );
-#print "so_objboob >$objnum_rr|$$objnum_rr<\n";
return so_boob($kind,$mkused,
- defined $obj ? $obj->{BoOb} : undef
- , $objnum_rr
- );
+ defined $obj ? $obj->{BoOb} : undef,
+ $objnum_rr);
}
sub mainread () {
s/\s+$//;
next unless m/\S/;
last if m/^end$/;
- if (m/^(invertible|vanilla|points|fixed|endwiring|boards)$/) {
+ if (m/^(invertible|vanilla|points|fixed|endwiring|boards|interferences)$/) {
$mode= $1;
$invertible= ($mode eq 'invertible');
$mode= 'segment' if $mode =~ m/^(?:vanilla|invertible)$/;
my (@segs,$segn,$seg,$segr,$pt,$ptv, $delim);
my ($comb,$pi,$feat,$featr,$end,$boob);
my ($node,$side,$otherend,$nodeotherside,$otherseg,$otherbackrelus);
+ my ($ourinter,$pcname,$inter,$intother);
o("/* autogenerated - do not edit */\n\n");
@segs=();
for $seg (sort { nummap($a) cmp nummap($b) } keys %segs) {
o("static const SegPosCombInfo spci_${seg}"."[]= {");
$delim='';
+
+ $segr->{Inter}{Map}= 0;
+ $ourinter= $segr->{Inter};
for ($comb=0; $comb < $segr->{Posns}; $comb++) {
$pi='';
foreach $feat (keys %{ $segr->{Feats} }) {
($comb / $featr->{Weight}) % $featr->{Posns});
}
o("$delim\n");
- o(sprintf " { %-8s %4d",
+ o(sprintf " { %-7s%4d",
'"'.$pi.'",',
$segr->{Dist}[$comb]);
for ($end=0; $end<2; $end++) {
- o(", { ");
+ o(", {");
$otherend= $segr->{Ends}[$comb][$end];
defined $otherend or die "$seg $comb $end ?";
($node,$side) = @$otherend;
if (defined $nodeotherside) {
$otherseg= $nodeotherside->{Seg};
$otherbackrelus= $nodeotherside->{End} ^ $end ^ 1;
- o(sprintf "/*%5s.%d %-5s*/ %d,%3d",
+ o(sprintf "/*%4s.%d %-5s*/ %d,%3d",
$node,$side,
($otherbackrelus?'-':' ').$otherseg,
$otherbackrelus,
}
o(sprintf " }");
$delim= ',';
+
+ $pcname= "$seg/$pi";
+ for $inter (@interferences) {
+ next unless grep {
+ if ($pcname =~ m/^$_$/) {
+ s,/.*,/ ?,; 1;
+ } else {
+ 0;
+ }
+ } @$inter;
+ for $intother (@$inter) {
+ $intother =~ m,^(\w+)/, or die "$intother ?";
+ next if $1 eq $seg;
+ exists $segs{$1} or
+ endmistake("unknown segment $1 in interference");
+ if (defined $ourinter->{Seg}) {
+ $1 eq $ourinter->{Seg} or
+ endmistake("unsupported complicated interference ".
+ "involving $seg, $1, $ourinter->{Seg}");
+ } else {
+ $ourinter->{Seg}= $1;
+ }
+ }
+ endmistake("unsupported too-moveable interference")
+ if $comb>7;
+ $ourinter->{Map} |= 1 << $comb;
+ }
}
o("\n};\n");
}
o("\n};\n");
}
+ for $inter (@interferences) {
+ map {
+ warn "warning: unused interference specification $_\n" unless m, ,;
+ } @$inter;
+ }
+
o("const SegmentNum info_nsegments=NUM_SEGMENTS;\n");
o("const SegmentInfo info_segments[NUM_SEGMENTS]= {");
my (@sensemap,$segnum,$sensenum,$i);
foreach $seg (@segs) {
$segr= $segs{$seg};
o("$delim\n");
- o(sprintf " { %-7s %d, %2d,%-9s %3d,%-10s %-6s,%-6s }",
- "\"$seg\",", $segr->{Inv},
+ o(sprintf " { %-6s%d,%2d,%-8s%d,%-9s%-6s,%-7s",
+ "\"$seg\",",$segr->{Inv},
$segr->{FeatCount}, ($segr->{FeatCount} ? "mfi_$seg," : '0,'),
$segr->{Posns}, "spci_$seg,",
so_objboob('sense',1, $segr, \$sensenum),
- so_objboob('reverse',1, $segr->{Inv} ? $segr : undef));
+ so_objboob('reverse',1, $segr->{Inv} ? $segr : undef).',');
+ $ourinter= $segr->{Inter};
+ if (defined $ourinter->{Seg}) {
+ o(sprintf "%2d/*%s*/,0%o", $segs{$ourinter->{Seg}}{Num},
+ $ourinter->{Seg}, $ourinter->{Map});
+ } else {
+ o(" -1");
+ }
+ o(" }");
$delim= ',';
- o("/* sensmap[$sensenum]=$segnum */");
$sensemap[$sensenum]= $segnum++;
}
o("\n};\n");
redaction();
writeout();
writeasm();
+exit 1 if $mistakes;