!PCBPLOT: Convert PCB .FIN file to Plotter/Laser format
%include "INC:UTIL.IMP"
!?!%const%integer HP7580=1, LASER=2
!?!%const%integer  VARIANT=laser {hp7580
!?!$IF VARIANT = HP7580
%include "INC:MATHS.IMP"
!?!$FINISH
%begin
%string(255) INFILE,OUTFILE

%constinteger UNDEF=-32768
%constinteger FAST=0, SLOW=1
%own%byte    MODE=fast, OPTION=0
%owninteger SCALE=1, SDENOM=1
!?!$IF VARIANT = HP7580
%own%integer DEVSCALE=1, DEVDENOM=1
!?!$FINISH
!?!$IF VARIANT = laser
!?!%own%integer DEVSCALE=3, DEVDENOM=10
!?!$FINISH

!!!!!!!!!!!!!!!!!!   Board and route description   !!!!!!!!!!!!!!!!!

%const%integer MAXPAIRS=8, MAXPADS=6000, MAXSTAGES=50000,
               INSCALE=10
%integer BOARDxdim,BOARDydim,PAIRS,
         PINDIAMETER,VIADIAMETER,TRACKWIDTH,TRACKGAP,
         PINS,VIAS,PADS,STAGES,
         TRACKROOM

%record%format PADF(%short y,x,above,below,code,diameter)
%record%format STAGEF(%short pad,delta)
%record(padf)%array PAD(0:maxpads)
%record(stagef)%array STAGE(0:maxstages)
%integer%array ROUTE(2:maxpairs*2+1)

%string(63) CIRCUITNAME,BOARDNAME

%integer%fn LASTPOS(%string(*)%name s,%integer k)
%integer i=length(s)
  i = i-1 %while i > 0 %and charno(s,i) # k
  %result = i
%end

%integer%fn INTSQRT(%integer v)
%integer i,j
  %result = v %if v <= 1
  j = 0;  i = v
  j = j+1 %and i = i>>1 %until i = 0
  i = 1<<(j>>1);  j = i*i
  %result = i %if j = v
  %if j > v %start
    %cycle
      j = j-i
      %result = i %if j <= v
      i = i-1;  j = j-i
    %repeat
  %else
    %cycle
      j = j+i
      %result = i %if j >= v
      i = i+1;  j = j+i
    %repeat
  %finish
%end

!!!!!!!!!!!!!!!!!!!!!!!!!!   FIN file input   !!!!!!!!!!!!!!!!!!!!!!!

%routine FIND(%integer sym)
!Locate directive letter
%integer k
  read symbol(k) %until k > ' '
  %if k # sym %start
    printstring("Input ");  printsymbol(k)
    printstring(" instead of ");  printsymbol(sym)
    newline
    %stop
  %finish
%end

%routine GET(%integer%name v)
  read(v);  v = v*devscale//devdenom
%end

%routine READ FIN FILE
%const%byte%array PLANE(0:1)='H','V'
%integer i,j,k,p,s,ps=-1
%record(padf)%name pp
%routine IDENTIFY
  %return %if ps = s
  printsymbol(plane(s&1));  write(s>>1,0)
  newline
  ps = s
%end
%routine IDENTIFY PAD(%integer p)
  write(p,1)
  printsymbol('[');  write(pad(p)_x,0)
  printsymbol(',');  write(pad(p)_y,0)
  printsymbol(']')
%end
%routine NOTE(%shortname z)
  %if z&1<<(|j|-1) # 0 %start
    identify
    printstring("Duplicate diversion:")
    write(p,1);  printsymbol('+') %if j > 0
    write(j,0)
    newline
  %finish
  z = z!1<<(|j|-1)
%end
%routine CHECK(%shortname z,%integer k)
  %if z&(z+1)&16_FFFF # 0 %start
    identify
    printstring("Non-dense routing around pad:")
    identify pad(p)
    printsymbol(k)
    k = 1
    %while z # 0 %cycle
      write(k,1) %if z&1 = 0
      z = z>>1;  k = k+1
    %repeat
    printstring(" missing")
    newline
  %finish
  z = 0
%end
%routine READ PAD(%integer p,d)
%integer x,y
  get(x);  skip symbol;  get(y)
  skip symbol %and get(d) %if nextsymbol = ','
  pad(p)_x = x*inscale;  pad(p)_y = y*inscale
  pad(p)_above = 0;  pad(p)_below = 0
  pad(p)_diameter = d
  pad(p)_code = 0
  %if nextsymbol >= 'A' %start      {P,G}
    pad(p)_code = nextsymbol!32
    skip symbol
  %finish
  skip symbol
%end

%on %event 3 %start
  printstring(event_message);  newline
  infile = ""
%finish
  %if infile = "" %start
    prompt("Input file (.FIN assumed): ")
    read(infile);  skip symbol
  %finish
  infile = infile.".fin" %if lastpos(infile,'.') = 0
  open input(1,infile);  select input(1)
  read(circuitname);  read(boardname)
  find('B');  get(boardxdim);  get(boardydim)
  find('L');  read(pairs)
  find('P');  get(pindiameter)
  find('V');  get(viadiameter)
  find('T');  get(trackwidth)
  find('G');  get(trackgap)
!
  find('P');  read(pins)
  %for p = 1,1,pins %cycle
    read pad(p,pindiameter)
  %repeat
  find('V');  read(vias)
  %for p = 1,1,vias %cycle
    read pad(pins+p,viadiameter)
  %repeat
  pads = pins+vias
  stages = 0
  %cycle
    read symbol(k) %until k > ' '
    %exit %unless k = 'V' %or k = 'H'
    read(s)
    s = s+s;  s = s+1 %if k = 'V'
    route(s) = stages+1
    k = nl
    %cycle
      read(p);  p = -p %if k < ' '
      read symbol(k)
      %if p >= 0 %or k # nl %start
        stages = stages+1
        stage(stages)_pad = p
        j = 0
        %if k = '+' %or k = '-' %start
          read(j)
          pp == pad(p)
          %if k = '-' %start
            j = -j
            note(pp_below)
          %else
            note(pp_above)
          %finish
          read symbol(k)
        %finish
        stage(stages)_delta = j
      %finish
    %repeat %until p = 0
    %for p = 1,1,pads %cycle
      check(pad(p)_above,'+')
      check(pad(p)_below,'-')
    %repeat
  %repeat
  close input
%end;  !read fin file

!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!   HP output   !!!!!!!!!!!!!!!!!!!!!!!!!!

!?!$IF VARIANT = hp7580
%constinteger RED=1, GREEN=2, BLUE=3, BLACK=4
%own%integer CURX=-32768, CURY=-32768, OFFX=-32768, OFFY=-32768
%own%integer PENDIA=0, PENDOWN=0
%routine COMMA
  printsymbol(',')
%end
%routine PEN(%integer c)
  printstring("SP");write(c,0);newline
%end
%routine MOVE TO(%integer x,y)
  printstring("PU"); write(x-offx,0)
  printsymbol(','); write(y-offy,0); newline
  curx = x;  cury = y;  pendown = 0
%end
%routine DRAW LINE TO(%integer x,y)
  printstring("PD"); write(x-offx,0)
  printsymbol(','); write(y-offy,0); newline
  curx = x;  cury = y;  pendown = 1
%end
%routine DRAW OUTLINE CIRCLE(%integer r)
  printstring("CI"); write(r,0); newline
  pendown = 1
%end
%routine DRAW SOLID CIRCLE(%integer r)
%integer penrad,n,inc
  penrad = pendia>>1
  r = r-penrad
  %if mode = fast %start
    draw outline circle(r)
  %else
    n = ((r+penrad)//(penrad<<1))+1
    inc = (r+penrad)//n
    %cycle
      draw outline circle(r);  r = r-inc
    %repeat %until r <= 0
  %finish
%end

%routine DRAW ARC TO(%integer x,y,cx,cy,r)
%integer dx,dy,a
%long%real temp
  %return %if x = curx %and y = cury
  dx = x-curx;  dy = y-cury
  temp = sqrt(dx^2+dy^2)/(|r|+|r|)
  temp = 1 %if temp > 1
  temp = -1 %if temp < -1
  a = int(360*arcsin(temp)/3.1415927)
  a = -a %if r < 0             {clockwise if r neg}
  printstring("PD") %and newline %and pendown = 1 %if pendown = 0
  printstring("AA"); write(cx-offx,0)
  printsymbol(','); write(cy-offy,0)
  printsymbol(','); write(a,0); newline
  curx = x;  cury = y
%end

%routine DRAW NUMBER(%integer v)
![nominal numeric output]
  printstring("LB ");write(v,1);printsymbol(3);newline
%end

%routine INITIALISE(%integer first)
  %if first # 0 %start
    offx = boardxdim>>1 %if offx = -32768
    offy = boardydim>>1 %if offy = -32768
    %if mode = slow %start
      printstring("AS1");  newline
      printstring("VS4");  newline
    %finish
  %finish
%end

%routine END OF PHASE
  move to(curx,cury)
%end

%routine TERMINATE
  select output(1)
  printstring("NR"); newline
  select output(0)
%end

%routine SELECT BOARD PEN
  %if mode = fast %then pen(black) %else pen(2)
%end
%routine SELECT GRID PEN
  %if mode = fast %then pen(black) %else pen(1)
%end
%routine SELECT PAD PEN
  %if mode = fast %then pen(black) %else pen(2)
%end
%routine SELECT ALIGNMENT PEN
  %if mode = fast %then pen(black) %else pen(1)
%end
%routine SELECT ROUTE PEN(%integer surface)
  %if mode = fast %start
    %if surface&1 = 0 %then pen(green) %else pen(blue)
  %finish %else pen(2)
%end
%routine SELECT LABEL PEN
  pen(black)
%end

%routine END OF ROUTE
%end

!?!$FINISH

!!!!!!!!!!!!!!!!!!!!!!!!!!!!   Laser output   !!!!!!!!!!!!!!!!!!!!!!!!!

!?!$IF VARIANT = LASER
!?!%include "LASER.INC"
!?!    
!?!%routine SELECT BOARD PEN
!?!  leftpen = pendia//2;  rightpen = pendia-leftpen
!?!%end
!?!%routine SELECT ALIGNMENT PEN
!?!  leftpen = 1;  rightpen = 1
!?!%end
!?!%routine SELECT GRID PEN
!?!  leftpen = 1;  rightpen = 1
!?!%end
!?!%routine SELECT PAD PEN
!?!  select board pen
!?!%end
!?!%routine SELECT ROUTE PEN(%integer surface)
!?!  select board pen
!?!%end
!?!%routine SELECT LABEL PEN
!?!  select board pen
!?!%end
!?!
!?!%routine END OF ROUTE
!?!  newline %and outcol = 0 %if outcol # 0
!?!%end
!?!
!?!$FINISH
!?!
!!!!!!!!!!!!!!!!!!!!!!!   Generic drawing operations   !!!!!!!!!!!!!!!!!

%routine DRAW BOARD(%integer n)
%integer j=0
  select board pen
  %cycle
    move to(j,j)
    move to(j,j)
    draw line to(boardxdim-j,j)
    draw line to(boardxdim-j,boardydim-j)
    draw line to(j,boardydim-j)
    draw line to(j,j)
    j = j+(pendia>>1);  n = n-1
  %repeat %until n <= 0
  end of phase
%end

%routine DRAW GRID
%integer x,y
!?!$IF VARIANT = laser
!?!  select grid pen
!?!  y = 0
!?!  %cycle
!?!    y = y+1000*devscale//devdenom
!?!    %exit %if y >= boardydim
!?!    move to(0,y);  draw line to(boardxdim,y)
!?!  %repeat
!?!  x = 0
!?!  %cycle
!?!    x = x+1000*devscale//devdenom
!?!    %exit %if x >= boardxdim
!?!    move to(x,0);  draw line to(x,boardydim)
!?!  %repeat
!?!  end of phase
!?!$FINISH
%end

%routine MARK HOLE(%integer r)
%integer x=curx,y=cury
  draw outline circle(r)
  move to(x,y+3*r//2)
  draw line to(x,y-3*r//2)
  move to(x+3*r//2,y)
  draw line to(x-3*r//2,y)
  move to(x,y)
%end

%routine DRAW ALIGNMENT MARKS
%integer border=150*devscale//devdenom,
         r1=50*devscale//devdenom, r2=70*devscale//devdenom
  select alignment pen
  move to(boardxdim+border,0)
  mark hole(r1); draw outline circle(r2)
  draw line to(boardxdim+border,boardydim)
  mark hole(r1); draw outline circle(r2)
  move to(boardxdim,boardydim+border)
  mark hole(r1); draw outline circle(r2)
  draw line to(0,boardydim+border)
  mark hole(r1); draw outline circle(r2)
  move to(-border,boardydim)
  mark hole(r1); draw outline circle(r2)
  draw line to(-border,0)
  mark hole(r1); draw outline circle(r2)
  move to(0,-border)
  mark hole(r1); draw outline circle(r2)
  draw line to(boardxdim,-border)
  mark hole(r1); draw outline circle(r2)
  end of phase
%end

%routine DRAW PADS(%integer first,last)
%integer p,rad,inc,n
%record(padf)%name pp
  select pad pen
  %for p = first,1,last %cycle
    pp == pad(p)
    %if pp_diameter <= pindiameter %or pp_code # 0 %start
     {Include hole only if P or G}
      move to(pp_x,pp_y)
      draw solid circle(pp_diameter>>1)
    %finish
  %repeat
  end of phase
%end

%routine DRAW LABELS(%integer first,last)
%integer p
  select label pen
  printstring("CS 10;SS;SI.11,.25");newline
  %for p = first,1,last %cycle
    move to(pad(p)_x,pad(p)_y)
    draw number(p)
  %repeat
%end
%routine DRAW DRILL(%integer first,last)
%integer p,rad,inc,n
  select alignment pen
  %for p = first,1,last %cycle
    rad = (pad(p)_diameter-pendia)>>1
    move to(pad(p)_x,pad(p)_y)
    mark hole(rad)  {; draw solid circle(viadiameter) %if p<=pins
  %repeat
%end
%routine DRAW PG PLANE(%integer plane)
! PLANE = 'g' when drawing Ground and 'p' when drawing Power
! This is a negative plot
%integer p,rad;  %record(padf)%name pp
  select pad pen
  %for p = 1,1,pads %cycle
    pp == pad(p)
    rad = (pp_diameter+trackgap)>>1
    %if pp_diameter > pindiameter %start  {large hole}
      %if pp_code = plane %start         {selected plane}
       {nothing}
      %else %if pp_code # 0              {excluded plane}
       {isolate}
        move to(pp_x,pp_y)
        draw outline circle(rad)
      %else                              {not P or G}
       {leave out altogether}
        move to(pp_x,pp_y)
        draw solid circle(rad)
      %finish
    %else
      %if pp_code = plane %start          {selected plane}
       {draw 4 1/4 arcs for heat insulation}
        move to(pp_x-rad,pp_y-(trackwidth+pendia)>>1)
        draw arc to(pp_x-(trackwidth+pendia)>>1,pp_y-rad,pp_x,pp_y,rad)
        move to(pp_x+(trackwidth+pendia)>>1,pp_y-rad)
        draw arc to(pp_x+rad,pp_y-(trackwidth+pendia)>>1,pp_x,pp_y,rad)
        move to(pp_x+rad,pp_y+(trackwidth+pendia)>>1)
        draw arc to(pp_x+(trackwidth+pendia)>>1,pp_y+rad,pp_x,pp_y,rad)
        move to(pp_x-(trackwidth+pendia)>>1,pp_y+rad)
        draw arc to(pp_x-rad,pp_y+(trackwidth+pendia)>>1,pp_x,pp_y,rad)
      %else
       {isolate}
        move to(pp_x,pp_y)
        draw outline circle(rad)
      %finish
    %finish
  %repeat
%end
%routine DRAW SOLDER RESIST(%integer padmax)
!This is a negative plot
!All pads/holes of all kinds are filled in + protection
![The PADMAX parameter allows exclusion of vias]
%integer p,rad;  %record(padf)%name pp
  select pad pen
  %for p = 1,1,padmax %cycle
    pp == pad(p)
    rad = (pp_diameter+trackgap)>>1
    move to(pp_x,pp_y)
    draw solid circle(rad)
  %repeat
%end

%routine DRAW ROUTE(%integer surface)
%record(stagef)%name r,rr
%record(padf)%name pp1,pp2
%integer p,x,y,x1,y1,d1,x2,y2,d2

%routine CONNECT(%integer X1,Y1,D1,X2,Y2,D2)
%integer x,xx,y,yy,e,d,dd,yy1,yy2,cx1,cy1,dx,dy
!Create route segment from pad centred on X1,Y1
! to pad centred on X2,Y2 at a displacement of
! D1 from the first pad and D2 from the second pad
! If D1 or D2 is non-zero, compute point of tangential
! connection
  cx1 = x1;  cy1 = y1
  -> done %if d1!d2 = 0
  yy1 = y1+d1;  yy2 = y2+d2
  y1 = yy1 %and y2 = yy2 %and -> done %if yy1 = yy2
  y = |d2-d1|
  %if y = 0 %start             {identical radius}
   ! Compute endpoints of line of length R (=D1=D2)
   !  at right angles to DX,DY
    dx = |y2-y1|;  dy = |x2-x1|
    %if dx >= dy %start
      e = 0;  x = |d1|;  y = 0
      d = x*dy                   {D is X*DY-Y*DX}
      %cycle
        dd = d;  xx = x
        e = e-(y*2+1);  y = y+1;  d = d-dx
        %if e+x <= 0 %start
          x = x-1;  e = e+(x*2+1);  d = d-dy
        %finish
      %repeat %until d <= 0
      x = xx %and y = y-1 %if dd <= -d
    %else
      e = 0;  x = 0;  y = |d1|
      d = y*dx                   {D is Y*DX-X*DY}
      %cycle
        dd = d;  xx = y
        e = e-(x*2+1);  x = x+1;  d = d-dy
        %if e+y <= 0 %start
          y = y-1;  e = e+(y*2+1);  d = d-dx
        %finish
      %repeat %until d <= 0
      y = xx %and x = x-1 %if dd <= -d
    %finish
    y = -y %if d1 < 0
    xx = |x2-x1|;  yy = |y2-y1|
    e = intsqrt(xx^^2+yy^^2)
    d{x} = |d1|*yy//e
    e{y} = d1*xx//e               {d1=d2 & yy1#yy2 -> y1#y2}
    xx = x;  yy = y
  %else                                {not identical radius}
    e = 0;  x = 0;  d = -(|yy2-yy1|)*y
    %cycle
      dd = d;  xx = x
      e = e-y;  y = y-1;  e = e-y;  d = d+(|y2-y1|)
      %while e+x <= 0 %cycle
        e = e+x;  x = x+1;  e = e+x;  d = d+(|x2-x1|)
      %repeat
    %repeat %until d >= 0 %or y <= 0
    x = xx %and y = y+1 %if -dd <= d
    xx = x*|d2|//|d2-d1|
    x = x*|d1|//|d2-d1|
    yy = y*d2//|d2-d1|
    y = y*d1//|d2-d1|
  %finish
  %if yy1 < yy2 %start
    x = -x %if d1 > 0
    xx = -xx %if d2 > 0
  %else
    x = -x %if d1 < 0
    xx = -xx %if d2 < 0
  %finish
  %if surface&1 # 0 %start
    x1 = x1-x;  y1 = y1+y
    x2 = x2-xx;  y2 = y2+yy
  %else
    x1 = x1+x;  y1 = y1+y
    x2 = x2+xx;  y2 = y2+yy
  %finish
done:
  %if surface&1 # 0 %start      {vertical}
    draw arc to(y1,x1,cy1,cx1,-d1)
    draw line to(y2,x2)
  %else                         {horizontal}
    draw arc to(x1,y1,cx1,cy1,-d1)
    draw line to(x2,y2)
  %finish
%end
   
  select route pen(surface)
  r == stage(route(surface))
  %while r_pad # 0 %cycle                   {zero pad terminates}
    rr==r[1]
    r == rr %and %continue %if rr_pad <= 0  {neg pad starts new route}
    pp1 == pad(|r_pad|)                     {first pad}
    x1 = pp1_x;  y1 = pp1_y
    move to(x1,y1);  d1 = 0                 {route starts at centre}
    %cycle
      r == r[1]
      %exit %if r_pad <= 0
      pp2 == pad(r_pad)                     {second pad}
      x2 = pp2_x;  y2 = pp2_y
      d2 = r_delta                          {displacement from centre}
      %if d2 # 0 %start
       {convert from N to distance}
        %if d2 > 0 %start
          d2 = (pp2_diameter-trackwidth)>>1+d2*trackroom
        %else
          d2 = -(pp2_diameter-trackwidth)>>1+d2*trackroom
        %finish
      %finish
      %if surface&1 # 0 %then connect(y1,x1,d1,y2,x2,d2) -
      %else connect(x1,y1,d1,x2,y2,d2)
      x1 = x2;  y1 = y2;  d1 = d2
    %repeat
    end of route
  %repeat
  end of phase
%end

%routine PL(%string(255) s)
  printstring(s);  newline
%end

%routine OPEN OUT
%on %event 3 %start
  printstring(event_message);  newline
  outfile = ""
%finish
  %if outfile = "" %start
    prompt("Output file: ");  read(outfile);  skip symbol
  %finish
  open output(1,outfile);  select output(1)
%end

!!!!!!!!!!!!!!!!!!!!!!!!!!!!   Main program   !!!!!!!!!!!!!!!!!!!!!!!!!!!!

%integer SURFACE,OPS,TIMES,PLANE,ERROR,CODE,I

%routine SELECT(%integer letter)
  ops = ops!1<<(letter-'a')
%end

%predicate SELECTED(%integer letter)
  %true %if ops&1<<(letter-'a') # 0
  %false
%end

  define param("INput",infile,pamnodefault)
  define param("OUTput",outfile,pamnodefault+pamnewgroup)
  define int param("SCale (numerator)",scale,0)
  define int param("DENOM (scale denominator)",sdenom,0)
  define int param("Xzero",offx,0)
  define int param("Yzero",offy,0)
  define int param("PENwidth",pendia,0)
!  define enum param("NOYINV,YINV",yinv,0)
!  define enum param("NOXINV,XINV",xinv,0)
  define enum param("FAST,SLOW",mode,0)
  process parameters(cliparam)
  devscale = devscale*scale;  devdenom = devdenom*sdenom

  read fin file
  select input(0)
  trackroom = trackwidth+trackgap
  pendia = trackwidth %if pendia = 0
  pl(" Select by initial letter (* to close)")
  pl("   Outline  Grid  Mark  Pads  Drill  Label  Solder-resist")
  pl("   NP: neg power NG: neg ground")
  pl("   Horizontal1 H2 ...  Vertical1 V2 ...")
  %cycle
    prompt("Selection: ")
    ops = 0;  error = 0
    surface = 0;  times = 0;  plane = 0
    read symbol(code) %until code > ' '
    %exit %if code = '*'
    error = 0
    %cycle
      code = code!32
      %if code = 'g' %or code = 'm' %or code = 'p' -
      %or code = 'd' %or code = 'l' %or code = 's' %start
        select(code)
      %else %if code = 'o'
        select(code)
        read(times) %if '0' <= nextsymbol <= '9'
      %else %if code = 'n'
        %if nextsymbol!32 = 'p' %start
          plane = 'p';  skip symbol
        %else %if nextsymbol = 'g'
          plane = 'g';  skip symbol
        %else
          printstring("Invalid negative code: ")
          printsymbol(nextsymbol) %if nextsymbol >= ' '
          newline
          error = 1
        %finish
      %else %if code = 'h' %or code = 'v'
        i = nextsymbol-'0'
        %if i <= 0 %or i > pairs %start
          printstring("Invalid layer: ")
          printsymbol(nextsymbol) %if nextsymbol >= ' '
          newline
          error = 1
        %else %if surface # 0
          printstring("Only one surface at a time");  newline
          error = 1
        %else
          surface = i+i;  surface = surface+1 %if code = 'v'
          skip symbol
        %finish
      %else
        printstring("Unknown selection: ")
        printsymbol(code);  newline
        error = 1
      %finish
      %exit %if error # 0
      read symbol(code) %until code # ' '
    %repeat %until code < ' '
    %if error # 0 %start
      read symbol(code) %until code < ' '
    %else
      %if outfile # "*" %start                      {first time}
        open out
        outfile = "*"
        initialise(1)
      %else                                    {subsequently}
        select output(1)
        initialise(0)
      %finish
      draw board(times) %if selected('o')
      draw grid %if selected('g')
      draw drill(1,pads) %if selected('d')
      draw solder resist(pads) %if selected('s')
      draw pg plane(plane) %if plane > 0
      draw alignment marks %if selected('m')
      draw labels(1,pads) %if selected('l')
      draw pads(1,pads) %if selected('p')
      draw route(surface) %if surface # 0
      select output(0)
    %finish
  %repeat
  terminate
%end%of%program
