include PRIMOS_KEYS include "defines" # p$abi --- integer absolute value subroutine p$abi include creg store (sp) = iabs (store (sp)) return end # p$abr --- real absolute value subroutine p$abr include creg storer (sp) = abs (storer (sp)) return end # p$adi --- integer addition subroutine p$adi include creg sp = sp - 1 store (sp) = store (sp) + store (sp + 1) return end # p$adr --- real addition subroutine p$adr include creg sp = sp - 1 storer (sp) = storer (sp) + storer (sp + 1) return end # p$and --- boolean and subroutine p$and include creg sp = sp - 1 if (store (sp + 1) == 0) store (sp) = 0 return end # p$atn --- arc tangent subroutine p$atn include creg storer (sp) = atan (storer (sp)) return end # p$brd --- binary read - reads num * 2 words from file subroutine p$brd(num) integer num, i, j, fd, nrd, code, filebuf, nr, mapfd, mapsu include creg fd = store (store (sp - 1)) # get device number for file nr = num * 2 # convert to number of 16 bit words if (fd == STDOUT | fd == STDOUT2) call p$bomb ('read on output file.') filebuf = store (sp - 1) + 1 # get starting address of file buffer i = store (sp) # get address of variable for (j = 0; j < num; j = j + 1) # load variable with contents of buffer store (i + j) = store (filebuf + j) call prwf$$ (KREAD, mapfd (mapsu (fd)), loc(store (filebuf)), nr, intl(0), nrd, code) if (code == BEOF) store (filebuf) = EOF # set first loc in file buffer to EOF elif (nrd ~= nr) call p$bomb ('tried to read past end of file.') sp = sp - 1 return end # p$bwr --- binary write - writes num words to file subroutine p$bwr(num) integer num, i, j, fd, nwr, code, filebuf, nw, mapsu, mapfd include creg fd = store (store (sp - 1)) # get device number for file nw = num * 2 # convert to number of 16 bit words if (fd == STDIN | fd == STDIN2) call p$bomb ('write on input file.') filebuf = store (sp - 1) + 1 # get starting address of file buffer i = store (sp) # get address of variable call prwf$$ (KWRIT, mapfd (mapsu (fd)), loc(store (i)), nw, intl(0), nwr, code) for (j = 0; j < num; j = j + 1) # load buffer with contents of variable store (filebuf + j) = store (i + j) if (nw ~= nwr | code ~= 0) call p$bomb ('error in writing to binary file.') sp = sp - 1 return end # p$cfp --- converts a fortran array into a pascal (unpacked) array subroutine p$cfp (size) integer size, i, j, limit, adr include creg adr = store (sp) limit = adr + size - 1 i = int (size / 2) if (size ~= i * 2) { # start at even numbered word store (limit) = rt (store (i + 1), 16) limit = limit - 1 } for (i = limit; i >= adr; i = i - 2) { j = int ((i - adr) / 2) + adr store (i) = rt (store (j), 16) store (i - 1) = rs (store (j), 16) } return end # p$cpf --- converts a pascal (unpacked) array into a fortran array subroutine p$cpf (size) integer size, i, j, limit, adr include creg j = 0 adr = store (sp) limit = adr + size - 1 for (i = adr; i <= int(limit/2) + 1; i = i + 1) { j = j + 2 if (i + j <= limit) { store (i) = ls (store (adr + j + 1), 16) + rt (store (adr + j), 16) } else store (i) = rt (store (i + j), 16) } return end # p$chk --- bounds check subroutine p$chk (lb, ub) longint lb, ub include creg if (store (sp) < lb || store (sp) > ub) { call print (ERROUT, "lb = *l, ub = *l, val = *l*n.", lb, ub, store (sp)) call p$bomb ("value out of range.") } return end # p$chka --- pointer check subroutine p$chka (p, q) longint p, q include creg if (store (sp) < intl (np) || store (sp) > q) { call print (ERROUT, "heap = *i, ptr = *l*n.", np, store (sp)) call p$bomb ("pointer out of range.") } return end # p$chr --- convert integer to character subroutine p$chr include creg store (sp) = store (sp) + 128 return end # p$cls --- close a file subroutine p$cls integer fd, close include creg fd = store (store (sp)) if (fd ~= 0) call close (fd) sp = sp - 1 return end # p$cos --- cosine subroutine p$cos include creg storer (sp) = cos (storer (sp)) return end # p$dat --- calls date subroutine to get data and time subroutine p$dat(code) integer code, string(10), adr, i include creg call date (code, string) adr = store (sp) for (i = 0; i < 8; i = i + 1) store (adr + i) = string (i + 1) sp = sp - 1 return end # p$dec --- decrement subroutine p$dec (p, q) integer p longint q include creg store (sp) = store (sp) - q return end # p$dif --- set difference subroutine p$dif integer i include creg for (i = sp - 8; sp > i; sp = sp - 1) store (sp - 8) = and (store (sp - 8), not (store (sp))) return end # p$dvi --- integer division subroutine p$dvi include creg sp = sp - 1 store (sp) = store (sp) / store (sp + 1) return end # p$dvr --- real division subroutine p$dvr include creg sp = sp - 1 storer (sp) = storer (sp) / storer (sp + 1) return end # p$eln --- end-of-line test subroutine p$eln integer i, fd include creg fd = store (store (sp)) i = store (sp) + 1 store (sp) = rt ((store (i) == NEWLINE | store (i) == EOF), 32) return end # p$ent --- block entry subroutine p$ent (p, q) integer p, q include creg if (p == 1) { sp = mp + q # q = length of data segment if (sp > np) call p$bomb ("stack overflow.") } else { ep = sp + q if (ep > np) # ep = maximum space required on stack call p$bomb ("store overflow.") } return end # p$eof --- end-of-file test subroutine p$eof integer i include creg i = store (sp) + 1 store (sp) = rt ((store (i) == EOF), 32) return end # p$equ --- compare for equality subroutine p$equ (p, q) integer p, q integer i logical bval logical p$comp include creg sp = sp - 1 if (p == 4) { sp = sp - 14 # point to first word of first set bval = .true. for (i = sp + 7; i >= sp & bval; i = i - 1) bval = store (i) == store (i + 8) } elif (p == 5) bval = p$comp (q, EQU) else bval = store (sp) == store (sp + 1) store (sp) = intl (rt (bval, 16)) return end # p$exp --- exponential subroutine p$exp include creg storer (sp) = exp (storer (sp)) return end # p$flo --- integer to real conversion (next-to-top of stack) subroutine p$flo include creg storer (sp - 1) = store (sp - 1) return end # p$flt --- integer to real conversion (top of stack) subroutine p$flt include creg storer (sp) = store (sp) return end # p$fms --- prints final compilation message if any errors subroutine p$fms (message) integer message (MAXLINE) integer q include creg q = store (store (sp)) if (q ~= 0) # there were compilation errors call print (ERROUT, "*4i*p*n.", q, message) sp = sp - 1 return end # p$geq --- compare for greater-than or equal-to relation subroutine p$geq (p, q) integer p, q integer i logical bval logical p$comp include creg sp = sp - 1 if (p == 0) call p$bomb ("illegal address comparison.") elif (p == 2) bval = storer (sp) >= storer (sp + 1) elif (p == 4) { sp = sp - 14 # point to first word of first set bval = .true. for (i = sp + 7; i >= sp & bval; i = i - 1) bval = and (store (i), store (i + 8)) == store (i + 8) } elif (p == 5) bval = p$comp (q, GEQ) else bval = store (sp) >= store (sp + 1) store (sp) = intl (rt (bval, 16)) return end # p$get --- get item from file subroutine p$get integer i, fd integer getch character c include creg i = store (sp) + 1 fd = store (store (sp)) if (fd == STDOUT) call p$bomb ("get on output file.") elif (fd == STDOUT2) call p$bomb ("get on prr file.") else store (i) = getch (c, fd) sp = sp - 1 return end # p$grt --- compare for greater-than subroutine p$grt (p, q) integer p, q logical bval logical p$comp include creg sp = sp - 1 if (p == 0) call p$bomb ("illegal address comparison.") elif (p == 1 | p == 3 | p == 6) bval = store (sp) > store (sp + 1) elif (p == 2) bval = storer (sp) > storer (sp + 1) elif (p == 4) { call p$bomb ("illegal set inclusion.") } else # (p == 5) bval = p$comp (q, GRT) store (sp) = intl (rt (bval, 16)) return end # p$inc --- increment subroutine p$inc (p, q) integer p longint q include creg store (sp) = store (sp) + q return end # p$ind --- indirect load subroutine p$ind (p, q) integer p, q integer i include creg if (p == 4) { sp = sp - 1 i = store (sp) + q store (sp) = store (sp + 1) # copy descriptor call p$ldos (i) } else { i = store (sp) + q store (sp) = store (i) } return end # p$inf --- initialize a file buffer subroutine p$inf include creg store (store (sp)) = 0 sp = sp - 1 return end # p$inn --- set membership test subroutine p$inn integer b, w logical bval include creg include cmasks sp = sp - 8 w = store (sp) / 32 b = mod (store (sp), 32) bval = and (store (sp + w + 1), masks (b + 1)) ~= 0 store (sp) = intl (rt (bval, 16)) return end # p$int --- set intersection subroutine p$int integer i include creg for (i = sp - 8; sp > i; sp = sp - 1) store (sp - 8) = and (store (sp - 8), store (sp)) return end # p$ior --- boolean inclusive or subroutine p$ior include creg sp = sp - 1 if (store (sp + 1) == 1) store (sp) = 1 return end # p$ixa --- generate pointer to array element subroutine p$ixa (q) integer q include creg sp = sp - 1 store (sp) = store (sp) + q * store (sp + 1) return end # p$lao --- load global address subroutine p$lao (q) integer q include creg sp = sp + 1 store (sp) = q return end # p$lca --- load address of constant subroutine p$lca (q) integer q include creg sp = sp + 1 store (sp) = q return end # p$lda --- load address subroutine p$lda (p, q) integer p, q integer p$base include creg sp = sp + 1 store (sp) = p$base (p) + q return end # p$ldc --- load constant subroutine p$ldc (p, q) integer p longint q include creg if (p == 0) { sp = sp + 1 store (sp) = MAXSTORE # load nil } elif (p == 4) call p$ldos (ints (q)) else { sp = sp + 1 store (sp) = q } return end # p$ldo --- load global variable subroutine p$ldo (p, q) integer p, q include creg if (p == 4) call p$ldos (q) else { sp = sp + 1 store (sp) = store (q) } return end # p$ldos --- load set subroutine p$ldos (q) integer q integer i, j, lo, hi include creg lo = rs (store (sp), 8) hi = rt (store (sp), 8) sp = sp - 1 j = q for (i = 0; i < lo; i = i + 1) { sp = sp + 1; store (sp) = 0 } for ( ; i <= hi; i = i + 1) { sp = sp + 1; store (sp) = store (j) j = j + 1 } for ( ; i < 8; i = i + 1) { sp = sp + 1; store (sp) = 0 } return end # p$leq --- compare for less-than or equal-to relation subroutine p$leq (p, q) integer p, q integer i logical bval logical p$comp include creg sp = sp - 1 if (p == 0) call p$bomb ("illegal address comparison.") elif (p == 1 || p == 3 || p == 6) bval = store (sp) <= store (sp + 1) elif (p == 2) bval = storer (sp) <= storer (sp + 1) elif (p == 4) { sp = sp - 14 # point to first word of first set bval = .true. for (i = sp + 7; i >= sp & bval; i = i - 1) bval = and (store (i), store (i + 8)) == store (i) } else # (p == 5) bval = p$comp (q, LEQ) store (sp) = intl (rt (bval, 16)) return end # p$les --- compare for less-than subroutine p$les (p, q) integer p, q logical bval logical p$comp include creg sp = sp - 1 if (p == 0) call p$bomb ("illegal address comparison.") elif (p == 1 || p == 3 || p == 6) bval = store (sp) < store (sp + 1) elif (p == 2) bval = storer (sp) < storer (sp + 1) elif (p == 4) call p$bomb ("illegal set inclusion.") else # (p == 5) bval = p$comp (q, LES) store (sp) = intl (rt (bval, 16)) return end # p$lod --- load variable subroutine p$lod (p, q) integer p, q integer p$base include creg sp = sp + 1 store (sp) = store (p$base (p) + q) return end # p$loda --- load pointer variable subroutine p$loda (p, q) integer p, q integer p$base include creg sp = sp + 1 store (sp) = store (p$base (p) + q) return end # p$lods --- load set variable subroutine p$lods (p, q) integer p, q integer p$base include creg call p$ldos (p$base (p) + q) return end # p$log --- natural logarithm subroutine p$log include creg storer (sp) = alog (storer (sp)) return end # p$mod --- modulus subroutine p$mod include creg sp = sp - 1 store (sp) = mod (store (sp), store (sp + 1)) return end # p$mov --- move subroutine p$mov (q) integer q integer i, i1, i2 include creg i1 = store (sp - 1) i2 = store (sp) sp = sp - 2 # pop pointers for (i = 1; i <= q; i = i + 1) { store (i1) = store (i2) i1 = i1 + 1; i2 = i2 + 1 } return end # p$mpi --- integer multiplication subroutine p$mpi include creg sp = sp - 1 store (sp) = store (sp) * store (sp + 1) return end # p$mpr --- real multiplication subroutine p$mpr include creg sp = sp - 1 storer (sp) = storer (sp) * storer (sp + 1) return end # p$mst --- mark stack subroutine p$mst (p) integer p integer p$base include creg # p is the static level diference between caller and callee. # Store static link, dynamic link and current stack limit; bump sp; # reserve space for function value; size must be # max (intsize, realsize, boolsize, charsize, ptrsize). store (sp + 2) = p$base (p) # static link store (sp + 3) = mp # dynamic link store (sp + 4) = ep # stack limit sp = sp + 5 return end # p$mts --- generate subrange set subroutine p$mts integer lwb, upb, lw, lb, uw, ub, i include creg lwb = store (sp - 1) if (lwb < 0 || lwb > 255) call p$bomb ("mts lower bound out of range.") upb = store (sp) if (upb < 0 || upb > 255) call p$bomb ("mts upper bound out of range.") sp = sp - 2 lw = lwb / 32 lb = mod (lwb, 32) uw = upb / 32 ub = mod (upb, 32) for (i = 0; i < lw; i = i + 1) { sp = sp + 1 store (sp) = 0 } if (lw < uw) { sp = sp + 1 store (sp) = lt (:37777777777, 32 - lb) for (i = lw + 1; i < uw; i = i + 1) { sp = sp + 1 store (sp) = :37777777777 } sp = sp + 1 store (sp) = rt (:37777777777, ub + 1) } else { sp = sp + 1 store (sp) = lt (rt (:37777777777, ub + 1), 32 - lb) } for (i = uw + 1; i < 8; i = i + 1) { sp = sp + 1 store (sp) = 0 } return end # p$neq --- compare for inequality subroutine p$neq (p, q) integer p, q integer i logical bval logical p$comp include creg sp = sp - 1 if (p == 4) { sp = sp - 14 # point to first word of first set bval = .false. for (i = sp + 7; i >= sp & ~bval; i = i - 1) bval = store (i) ~= store (i + 8) } elif (p == 5) bval = p$comp (q, NEQ) else bval = store (sp) ~= store (sp + 1) store (sp) = intl (rt (bval, 16)) return end # p$new --- allocate storage from heap subroutine p$new integer i include creg np = np - store (sp) if (np <= ep) call p$bomb ("heap overflow.") else { i = store (sp - 1) store (i) = np sp = sp - 2 } return end # p$ngi --- integer negation subroutine p$ngi include creg store (sp) = -store (sp) return end # p$ngr --- real negation subroutine p$ngr include creg storer (sp) = -storer (sp) return end # p$not --- boolean not subroutine p$not include creg if (store (sp) == 0) store (sp) = 1 else store (sp) = 0 return end # p$odd --- test for odd subroutine p$odd include creg store (sp) = rt (store (sp), 1) return end # p$ord --- character to integer conversion subroutine p$ord (p) integer p include creg if (p == 6) store (sp) = store (sp) - 128 return end # p$pag --- output a form feed in a test file subroutine p$pag integer fd, i, putch include creg i = store (sp) + 1 fd = store (store (sp)) if (store (i) ~= NEWLINE) call putch (NEWLINE, fd) call putch (FF, fd) call putch (NEWLINE, fd) sp = sp - 1 return end # p$put --- put item into file subroutine p$put integer i, fd, putch include creg i = store (sp) + 1 fd = store (store (sp)) call putch (ints (store (i)), fd) sp = sp - 1 return end # p$rdc --- read character subroutine p$rdc integer i, j, fd integer getch character c include creg j = store (sp) i = store (sp - 1) + 1 fd = store (store (sp - 1)) if (fd == STDIN2) { #STDIN2 is assumed to be terminal input store (i) = getch (c, fd) if (store (i) == NEWLINE) store (j) = ' 'c else store (j) = store (i) } else { if (store (i) == NEWLINE) store (j) = ' 'c else store (j) = store (i) store (i) = getch (c, fd) } sp = sp - 1 return end # p$rdi --- read integer subroutine p$rdi character getch, buffer(12) character c integer i, j, k, fd longint gctol include creg fd = store (store (sp - 1)) i = store (sp - 1) + 1 j = store (sp) if (fd == STDIN2) store (i) = getch (c, fd) else c = store (i) while (store (i) == ' 'c | store (i) == NEWLINE) store (i) = getch (c, fd) buffer (1) = c for (k = 2; k < 12; k = k + 1) if (getch (buffer (k), fd) == EOF || buffer (k) < '0'c || buffer (k) > '9'c) break store (i) = buffer (k) buffer (k) = EOS k = 1 store (j) = gctol (buffer, k, 10) if (buffer (k) ~= EOS) call p$bomb ("illegal character in input.") sp = sp - 1 return end # p$rdr --- read real subroutine p$rdr character getch, buffer (21) character c integer i, j, k, fd real ctor include creg j = store (sp) i = store (sp - 1) + 1 fd = store (store (sp - 1)) c = store (i) while (c == ' 'c | c == NEWLINE) call getch (c, fd) buffer (1) = c for (k = 2; k < 21; k = k + 1) if (getch (buffer (k), fd) == EOF || buffer (k) < '0'c || buffer (k) > '9'c) break if (buffer (k) == '.'c & k < 21) { for (k = k + 1; k < 21; k = k + 1) if (getch (buffer (k), fd) == EOF || buffer (k) < '0'c || buffer (k) > '9'c) break } if (buffer (k) == 'e'c || buffer (k) == 'E'c) { k = k + 1 buffer (k) = getch (c, fd) for (k = k + 1; k < 21; k = k + 1) if (getch (buffer (k), fd) == EOF || buffer (k) < '0'c || buffer (k) > '9'c) break } store (i) = buffer (k) buffer (k) = EOS k = 1 storer (j) = ctor (buffer, k) sp = sp - 1 return end # p$rem --- remove file - removes temporary file subroutine p$rem (q, path) integer path (ARB) character pathname (MAXLINE) integer p, q, remove include creg p = store (sp) if (store (p) ~= 0) { if (q ~= 0) call p$mkpn (q, path, pathname) else call ptoc (path, ';'c, pathname, MAXLINE) call remove (pathname) store (p) = 0 } sp = sp - 1 return end # p$res --- reset file - open file for read only subroutine p$res (flev, num, pathname) integer pathname (ARB) character c, path (MAXLINE) integer p, fd, flev, num, nrd, code, lev, nr integer open, getch, close, mapfd, mapsu include creg p = store (sp) fd = store (p) if (fd ~= 0) call close (fd) if (flev ~= 0) { lev = flev call p$mkpn (lev, pathname, path) } else call ptoc (pathname, ';'c, path, MAXLINE) fd = open (path, READ) store (p) = fd if (fd == ERR) call p$bomb ('file could not be opened for reading.') elif (num == 0) # fill file buffer from ascii file store (p + 1) = getch (c, fd) else { # fill file buffer from binary file nr = num * 2 call prwf$$(KREAD, mapfd (mapsu (fd)), loc (store (p + 1)), nr, intl(0), nrd, code) if (nr ~= nrd || code ~= 0) call p$bomb ('error in reading binary file.') } sp = sp - 1 return end # p$rln --- skip remainder of input record subroutine p$rln integer i, fd integer getch character c include creg i = store (sp) + 1 fd = store (store (sp)) if (store (i) == NEWLINE && fd ~= STDIN2) store (i) = getch (c, fd) else { while (store (i) ~= NEWLINE & store (i) ~= EOF) store (i) = getch (c, fd) if (store (i) ~= EOF & fd ~= STDIN2) store (i) = getch (c, fd) } sp = sp - 1 return end # p$rst --- restore heap pointer subroutine p$rst include creg np = store (sp) sp = sp - 1 return end # p$rwr --- rewrite files - open file for write only subroutine p$rwr (flev, pathname) integer pathname (ARB) character path (MAXLINE) integer p, fd, flev, lev integer create, close include creg p = store (sp) fd = store (p) if (fd ~= 0) call close (fd) if (flev ~= 0) { lev = flev call p$mkpn (lev, pathname, path) } else call ptoc (pathname, ';'c, path, MAXLINE) fd = create (path, WRITE) store (p) = fd if (fd == ERR) call p$bomb ('could not open file for writing.') sp = sp - 1 return end # p$sav --- save heap pointer subroutine p$sav integer i include creg i = store (sp) store (i) = np sp = sp - 1 return end # p$sbi --- integer subtraction subroutine p$sbi include creg sp = sp - 1 store (sp) = store (sp) - store (sp + 1) return end # p$sbr --- real subtraction subroutine p$sbr include creg sp = sp - 1 storer (sp) = storer (sp) - storer (sp + 1) return end # p$sgs --- generate singleton set subroutine p$sgs integer i, w, b include creg include cmasks if (store (sp) < 0 | store (sp) > 255) call p$bomb ("set element out of range.") w = store (sp) / 32 b = mod (store (sp), 32) sp = sp - 1 for (i = 0; i < w; i = i + 1) { sp = sp + 1 store (sp) = 0 } sp = sp + 1 store (sp) = masks (b + 1) for (i = i + 1; i < 8; i = i + 1) { sp = sp + 1 store (sp) = 0 } return end # p$sin --- sine subroutine p$sin include creg storer (sp) = sin (storer (sp)) return end # p$sqi --- integer square subroutine p$sqi include creg store (sp) = store (sp) * store (sp) return end # p$sqr --- real square subroutine p$sqr include creg storer (sp) = storer (sp) * storer (sp) return end # p$sqt --- square root subroutine p$sqt include creg storer (sp) = sqrt (storer (sp)) return end # p$sro --- store into global variable subroutine p$sro (p, q) integer p, q include creg if (p == 4) call p$sros (q) else { store (q) = store (sp) sp = sp - 1 } return end # p$sros --- store into global set variable subroutine p$sros (q) integer q integer i, j, lo, hi include creg i = q j = sp - 8 # point to first word of set lo = j + rs (store (sp), 8) hi = j + rt (store (sp), 8) for ( ; j < lo; j = j + 1) if (store (j) ~= 0) call p$bomb ("set too large.") for (j = hi + 1; j < sp; j = j + 1) if (store (j) ~= 0) call p$bomb ("set too large.") for (j = lo; j <= hi; j = j + 1) { store (i) = store (j) i = i + 1 } sp = sp - 9 # pop set and descriptor return end # p$sto --- store into variable subroutine p$sto (p) integer p, i include creg if (p == 4) { i = store (sp - 9) call p$sros (i) sp = sp - 1 # pop pointer } else { i = store (sp - 1) store (i) = store (sp) sp = sp - 2 } return end # p$stp --- stop subroutine p$stp stop end # p$str --- store into variable subroutine p$str (p, q) integer p, q integer i integer p$base include creg i = p$base (p) + q store (i) = store (sp) sp = sp - 1 return end # p$stra --- store into pointer variable subroutine p$stra (p, q) integer p, q integer i integer p$base include creg i = p$base (p) + q store (i) = store (sp) sp = sp - 1 return end # p$strs --- store into set variable subroutine p$strs (p, q) integer p, q integer p$base include creg call p$sros (p$base (p) + q) return end # p$trc --- real to integer conversion subroutine p$trc include creg store (sp) = storer (sp) return end # p$ujc --- case statement error subroutine p$ujc include creg call p$bomb ("case statement error.") return end # p$uni --- set union subroutine p$uni integer i include creg for (i = sp - 8; sp > i; sp = sp - 1) store (sp - 8) = or (store (sp - 8), store (sp)) return end # p$wln --- write newline subroutine p$wln integer i, fd, putch include creg i = store (sp) + 1 fd = store (store (sp)) call putch (NEWLINE, fd) store (i) = NEWLINE sp = sp - 1 return end # p$wrc --- write character subroutine p$wrc integer bufp, width, fd include creg bufp = store (sp - 2) fd = store (bufp) for (width = store (sp); width > 1; width = width - 1) call putch (' 'c, fd) store (bufp + 1) = store (sp - 1) call putch (ints (store (bufp + 1)), fd) sp = sp - 2 return end # p$wri --- write integer subroutine p$wri integer bufp, fd include creg bufp = store (sp - 2) store (bufp + 1) = store (sp - 1) fd = store (bufp) call print (fd, "*#l.", ints (store (sp)), store (bufp + 1)) sp = sp - 2 return end # p$wrr --- write real subroutine p$wrr include creg integer i, j, k, fd fd = store (store (sp - 3)) i = store (sp - 3) + 1 j = store (sp - 1) k = store (sp) call print (fd, "*#,#r.", j, k, storer (sp - 2)) storer (i) = store (sp - 2) sp = sp - 3 return end # p$wrs --- write string subroutine p$wrs integer fd, i, j, k, l, p integer gchar, putch include creg fd = store (store (sp - 3)) i = store (sp - 3) + 1 l = store (sp - 2) k = store (sp - 1) j = store (sp) if (k > j) for (p = 1; p <= k - j; p = p + 1) call putch (' 'c, fd) else j = k for (p = 0; p < j; ) call putch (gchar (loc (store (l)), p), fd) p = p - 1 store (i) = gchar (loc (store (l)), p) sp = sp - 3 return end # p$base --- follows the static link chain back ld levels and returns # the address of the stack frame origin for that level. integer function p$base (ld) integer ld integer lld, ad include creg ad = mp for (lld = ld; lld > 0; lld = lld - 1) ad = rt (store (ad + 1), 16) p$base = ad return end # p$comp --- compare objects of length q pointed to by store (sp-1) # and store (sp), return YES if holds between them logical function p$comp (length, rel) integer length, rel integer i, l, i1, i2, r longint s1, s2 include creg i1 = store (sp) i2 = store (sp + 1) l = length / 4 # length in words r = mod (length, 4) for (i = 1; i <= l & store (i1) == store (i2); i = i + 1) { i1 = i1 + 1 i2 = i2 + 1 } if (i > l) if (r == 0) i = EQU else { s1 = lt (store (i1), r * 8) s2 = lt (store (i2), r * 8) if (s1 == s2) i = EQU elif (s1 < s2) i = LES else i = GRT } elif (store (i1) > store (i2)) i = GRT else i = LES select (rel) when (1) p$comp = i == EQU # EQU when (2) p$comp = i ~= EQU # NEQ when (3) p$comp = i == EQU | i == GRT # GEQ when (4) p$comp = i == GRT # GRT when (5) p$comp = i == EQU | i == LES # LEQ when (6) p$comp = i == LES # LES return end # p$dbug --- print out contents of current pseudo-stack frame subroutine p$dbug (msg) integer i, j, b, base (3), msg (ARB), putch character c include creg data base /-8, 10, -16/ call print (ERROUT, "*n*p*n*nmp=*i, sp=*i, ep=*i, np=*i*n*n.", msg, mp, sp, ep, np) do b = 1, 3; { call print (ERROUT, "Local stack contents in base *i? .", iabs (base (b))) call t1in (c) call tonl if (c == 'y'c | c == 'Y'c) { j = 0 call tonl for (i = mp; i <= sp; i = i + 1) { call print (ERROUT, "*12,#l.", base (b), store (i)) j = j + 1 if (j >= 6) { j = 0 call putch (NEWLINE, ERROUT) } } if (j > 0) call putch (NEWLINE, ERROUT) } } return end # p$init --- initialize P-code interpreter subroutine p$init(j) integer getch, i, j include creg mp = 0 sp = -1 ep = 5 np = MAXSTK1 store (5) = STDIN store (7) = STDOUT store (9) = STDIN2 store (11) = STDOUT2 if (j == YES) # input file is to be used store (6) = getch (i, STDIN) # note: buffer for keyboard file is not initialized return end # p$mkpn --- take array or record id and make pathname subroutine p$mkpn (lev, pathname, pn) integer i, lev, ind, pathname (ARB) character pn (MAXLINE) integer ptoc, itoc include creg ind = store (sp) i = ptoc (pathname, ';'c, pn, MAXLINE) i = 3 + itoc (lev, pn (3), 3) i = i + itoc (ind, pn (i), 5) pn (i) = EOS return end