!Graham Toal - last working version of SKIMPA 10/02/81 11.57 external string (127) fn spec cliparam external integer fn spec outstream external routine spec resetinput const string (1) snl = " " external integer spec faults routine do(string (127) text) !?%EXTERNALROUTINESPEC M6809 !! For invoking assembler after successful compilation... ! system(text) printstring(text); newline end external integer array a(1 : 500) ! initialisation for i/o routines external byte integer array named(1 : 1024) = c 10, 'R', 'E', 'A', 'D', 'S', 'Y', 'M', 'B', 'O', 'L', 10, 'N', 'E', 'X', 'T', 'S', 'Y', 'M', 'B', 'O', 'L', 10, 'S', 'K', 'I', 'P', 'S', 'Y', 'M', 'B', 'O', 'L', 11, 'P', 'R', 'I', 'N', 'T', 'S', 'Y', 'M', 'B', 'O', 'L', 5, 'S', 'P', 'A', 'C', 'E', 6, 'S', 'P', 'A', 'C', 'E', 'S', 7, 'N', 'E', 'W', 'L', 'I', 'N', 'E', 8, 'N', 'E', 'W', 'L', 'I', 'N', 'E', 'S', 7, 'N', 'E', 'W', 'P', 'A', 'G', 'E', 4, 'R', 'E', 'A', 'D', 5, 'W', 'R', 'I', 'T', 'E', 0(930) external integer array namedlink(0 : 255) = 0, 76, 0(12), 89, 0(54), 84, 0(118), 52, 0(11), 1, 12, 23, 34, 0(4), 67, 0(23), 46, 0(5), 59, 0(17) external integer array taglink(0 : 255) = 0, 13, 0(12), 16, 0(54), 14, 0(118), 8, 0(11), 1, 3, 4, 5, 0(4), 11, 0(23), 7, 0(5), 10, 0(17) external integer array tag(1 : 512) = 16_40100001, 16_11010002, 16_41000002, 16_40000003, 16_40100004, 16_01010002, 16_40000005, 16_40100006, 16_01010002, 16_40000007, 16_40100008, 16_01010002, 16_40000009, 16_4010000A, 16_11010002, 16_4020000B, 16_01010002, 16_01010003, 0(494) external integer array link(1 : 512) = 2, 0, 0, 0, 6, 0, 0, 9, 0, 0, 12, 0, 0, 15, 0, 17, 18, 0, 0(494) external integer namedp = 95 external integer tagasl = 19 external integer expropt = 0 external integer condopt = 0 external integer tagsopt = 0 external integer traceopt = 0 external integer checkopt = 0 external integer infoopt = 0 !----------------------------------------------------------------------- external routine spec statement(integer statementp) external string (255) fn spec strint(integer n, p) external routine spec fault(string (63) mess) external routine spec dump(string (7) opn, reg, base, integer disp) external string (255) fn spec name(integer ident) !----------------------------------------------------------------------- external routine skimp string (63) s, param routine spec readps routine spec readstatement routine spec rpsym(integer name l) integer fn spec findk(string (*) name k) integer fn spec compare(integer p) record format kdf(byte integer l, n, a, b) record (kdf) array kd(1 : 255) string (15) array pn(256 : 319) integer array pp(256 : 319) integer array ps(1 : 512) integer array t, tt(1 : 256) integer tp, ap, ttp, i, j, psflag string (63) file, options, option, as own integer lexopt = 0 own integer analopt = 0 own integer codeopt = 1 own integer listopt = 1 own integer assmopt = 0 own integer shift = 32 own string (63) assopt = "" s = cliparam if s -> ("/") . options then start unless options -> options . (" ") . file then file = "" cycle unless options -> option . ("/") . options then c option = options and options = "" if option -> ("NO") . option then i = 0 else i = 1 if option = "LEX" then lexopt = i and continue c else if option = "ANAL" then analopt = i and continue c else if option = "EXPR" then expropt = i and continue c else if option = "COND" then condopt = i and continue c else if option = "TAGS" then tagsopt = i and continue else start if option -> ("OPT=") . assopt then assmopt = i and continue c else if option = "TRACE" then traceopt = i and continue c else if option = "CHECK" then checkopt = i and continue c else if option = "LIST" then listopt = i and continue c else if option = "CODE" then codeopt = i and continue c else if option = "INFO" then infoopt = i and continue finish printstring(option . " OPTION ? ") stop repeat until options = "" finish else file = s on event 9, 13 start closeinput closeoutput printstring("FILE NOT FOUND - OR SOME OTHER ERROR!" . snl) ;! %if event_event = 9 stop if file = "" or codeopt = listopt = 0 or faults > 0 param = "" if codeopt = 0 then param = param . "/NOOBJECT" if listopt = 1 then param = param . "/LIST" do("ass68 " . file . " " . param) stop finish readps if file = "" then openoutput(1, "/dev/stdout") else openoutput(1, file . ".asm") selectoutput(1) printstring(" NAM " . file . snl) if file # "" printstring(" OPT " . assopt . snl) if assmopt = 1 printstring(" * File: " . file . " * Options: ") if lexopt = 1 then printstring("/LEX ") if analopt = 1 then printstring("/ANAL ") if expropt = 1 then printstring("/EXPR ") if condopt = 1 then printstring("/COND ") if tagsopt = 1 then printstring("/TAGS ") if infoopt = 1 then printstring("/INFO ") if traceopt = 1 then printstring("/TRACE ") if checkopt = 1 then printstring("/CHECK ") if listopt = 0 then printstring("/NOLIST ") if codeopt = 0 then printstring("/NOCODE ") if assmopt = 1 then printstring("/OPT=" . assopt) newline if psflag # 0 then fault("PHRASE STRUCTURE FAULTY") and stop if file = "" then openinput(1, "/dev/stdout") else openinput(1, file . ".imp") selectinput(1) ! set up tags available space list for i = tagasl, 1, 511 cycle link(i) = i + 1 repeat ! PRINTSTRING(" NAM ".FILE.SNL) %IF FILE#"" ! PRINTSTRING(" OPT ".ASSOPT.SNL) %IF ASSMOPT=1 cycle ! for each statement readstatement ttp = tp - 1 tp = 1 ap = 1 if compare(259) = 0 or tp # ttp then fault("SYNTAX ?") else start !**FRIG** above for printtext... if analopt = 1 then start newline j = 0 for i = 1, 1, ap - 1 cycle ! print analysis record if a(i) < 0 then as = " (" . strint(i, 1) . "/" . pn(a(i) << 1 >> 17) . ")" c and printstring(as) and j = j + length(as) and a(i) = a(i) & 16_FFFF write(a(i), 4) j = j + 5 if j > 60 then newline and j = 0 repeat newlines(2) finish else start for i = 1, 1, ap - 1 cycle ! remove phrase numbers if a(i) < 0 then a(i) = a(i) & 16_FFFF repeat finish statement(1) ! generate code for statement finish repeat !----------------------------------------------------------------------- routine readps ! read phrase structure from file 'SKIMPPS' and reduce it string (31) array ka(1 : 128) integer array kna(1 : 128) string (31) k integer kap, kdasl, kn, i, l, psp, pnp, alt integer name np routine spec insert(string (15) k) routine spec extract(integer i, string (15) k) routine spec assign(integer i) integer fn spec newkd routine spec returnkd(integer i) routine spec returnlist(integer i) integer fn spec phrase routine spec literal routine spec keyword openinput(2, "skimpps.new") selectinput(2) if infoopt = 1 then openoutput(2, "skimpps.lis") else openoutput(2, "/dev/null") selectoutput(2) printstring(" PHRASE STRUCTURE ") ! scan file to build keyword dictionary kap = 1 cycle rpsym(l) if l = '$' then exit if l = '"' then start k = "" cycle rpsym(l) if l = '"' then exit if 'A' <= l <= 'Z' then k = k . tostring(l) repeat ka(kap) = k kap = kap + 1 finish repeat for i = 1, 1, 26 cycle kd(i) = 0 repeat for i = 27, 1, 254 cycle kd(i)_b = i + 1 repeat kdasl = 27 i = 1 insert(ka(i)) and i = i + 1 until i = kap kn = 128 for i = 1, 1, 26 cycle if kd(i)_l # 0 then assign(i) repeat kap = 1 for i = 1, 1, 26 cycle if kd(i)_l # 0 then extract(i, "") repeat printstring(" KEYWORDS ") for i = 1, 1, kap - 1 cycle printstring(strint(kna(i), 3) . " " . ka(i) . " ") repeat ! reread file and reduce phrase structure resetinput pn(256) = "NAME" pp(256) = 0 pn(257) = "CONST" pp(257) = 0 pn(258) = "STRING" pp(258) = 0 pnp = 259 psp = 1 cycle ! for each phrase definition readsymbol(l) if l = '$' then exit if l = '<' then start ! start of phrase definition pp(phrase) = psp cycle ! for each alternative alt = psp np == ps(psp + 1) np = 0 ! number of phrases psp = psp + 2 cycle ! for each item readsymbol(l) if l = '<' then ps(psp) = phrase and psp = psp + 1 and np = np + 1 if l = '''' then literal if l = '"' then keyword if l = ',' or l = ';' then exit repeat ps(alt) = psp if l = ';' then exit repeat ps(psp) = 0 psp = psp + 1 finish repeat psflag = 0 for i = 259, 1, pnp - 1 cycle if pp(i) = 0 then fault("<" . pn(i) . "> NOT DEFINED") and psflag = 1 repeat printstring(" PHRASES ") for i = 256, 1, pnp - 1 cycle printstring(strint(i, 3) . strint(pp(i), 6) . " " . pn(i) . " ") repeat printstring(" REDUCED PHRASE STRUCTURE ") for i = 1, 1, psp - 1 cycle if (i - 1) & 15 = 0 then printstring(" " . strint(i, 3) . " ") write(ps(i), 3) repeat newlines(2) return !----------------------------------------------------------------------- routine insert(string (15) k) ! search for and insert keyword into dictionary integer i, j, l l = charno(k, 1) k -> (tostring(l)) . k i = l - 'A' + 1 if kd(i)_l # 0 then start search: if k = "" then start if kd(i)_a # 0 then extract(kd(i)_a, "") c and returnlist(kd(i)_a) and kd(i)_a = 0 return finish if kd(i)_a = 0 then insert(k) and return l = charno(k, 1) k -> (tostring(l)) . k i = kd(i)_a cycle if kd(i)_l = l then -> search if kd(i)_b = 0 then exit i = kd(i)_b repeat j = i i = newkd kd(j)_b = i finish ! insert remainder of letters cycle kd(i)_l = l if k = "" then return l = charno(k, 1) k -> (tostring(l)) . k j = i i = newkd kd(j)_a = i repeat end !----------------------------------------------------------------------- routine extract(integer i, string (15) k) string (15) kk if i = 0 then return kk = k . tostring(kd(i)_l) if kd(i)_a = 0 then ka(kap) = kk and kna(kap) = kd(i)_n c and kap = kap + 1 else extract(kd(i)_a, kk) extract(kd(i)_b, k) end !----------------------------------------------------------------------- routine assign(integer i) if i = 0 then return if kd(i)_a = 0 then kd(i)_n = kn and kn = kn + 1 else assign(kd(i)_a) assign(kd(i)_b) end !----------------------------------------------------------------------- integer fn newkd integer i if kdasl = 0 then printstring("KD ASL EMPTY") and stop i = kdasl kdasl = kd(i)_b kd(i) = 0 result = i end !----------------------------------------------------------------------- routine returnkd(integer i) kd(i)_b = kdasl kdasl = i end !----------------------------------------------------------------------- routine returnlist(integer i) if i = 0 then return returnlist(kd(i)_a) returnlist(kd(i)_b) returnkd(i) end !----------------------------------------------------------------------- integer fn phrase string (15) p integer i, l p = "" cycle readsymbol(l) if l = '>' then exit else p = p . tostring(l) repeat for i = 256, 1, pnp - 1 cycle if pn(i) = p then result = i repeat pn(pnp) = p pp(pnp) = 0 pnp = pnp + 1 result = pnp - 1 end !----------------------------------------------------------------------- routine literal integer l cycle readsymbol(l) if l = '''' then return else ps(psp) = l and psp = psp + 1 repeat end !----------------------------------------------------------------------- routine keyword string (31) k integer l k = "" cycle readsymbol(l) if l = '"' then exit if 'A' <= l <= 'Z' then k = k . tostring(l) repeat ps(psp) = findk(k) and psp = psp + 1 until k = "" end end !----------------------------------------------------------------------- routine readstatement routine spec store(integer l) routine spec keyword routine spec name routine spec const routine spec stringconst integer i, l, ksh, ttp, ttpp ! line reconstruct phase newlines(2) ttp = 1 ksh = 0 cycle ! for each character rpsym(l) if l = '%' then ksh = 128 else start unless 'A' <= l <= 'Z' then ksh = 0 if l # ' ' then start ! discard spaces if l = '!' and ttp = 1 then start rpsym(l) until l = ';' or l = nl ! discard comments finish else start store(l) if l = '"' then start shift = 0 rpsym(l) and store(l) until l = '"' shift = 32 finish else start if l = '''' then start shift = 0 rpsym(l) and store(l) until l = '''' shift = 32 finish else start if l = ';' or l = nl then start if ttp = 2 then ttp = 1 else start if l = ';' then newline and exit if tt(ttp - 2) = 'C' + 128 then ttp = ttp - 2 else exit finish finish finish finish finish finish finish repeat ! lexical phase tp = 1 ttpp = 1 cycle ! for each lexical item i = tt(ttpp) if i >= 128 then keyword else start if 'A' <= i <= 'Z' then name else start if i = '"' then stringconst else start if '0' <= i <= '9' or i = '''' or i = '$' then c const else t(tp) = i and tp = tp + 1 and ttpp = ttpp + 1 finish finish finish repeat until ttpp = ttp if lexopt = 1 then start newline for ttpp = 1, 1, tp - 2 cycle write(t(ttpp), 4) if ttpp & 16_F = 0 then newline repeat newline finish return !----------------------------------------------------------------------- routine store(integer l) if ttp > 256 then fault("STATEMENT TOO LONG") and stop tt(ttp) = l + ksh ttp = ttp + 1 end !----------------------------------------------------------------------- routine keyword string (255) k integer i k = "" while tt(ttpp) > 128 then k = k . tostring(tt(ttpp) - 128) and ttpp = ttpp + 1 i = findk(k) and t(tp) = i and tp = tp + 1 until k = "" or i = 0 end !----------------------------------------------------------------------- routine name string (*) name sname integer i, l, hash sname == string(addr(named(namedp))) hash = 0 sname = "" l = tt(ttpp) cycle if namedp + length(sname) >= 1022 then fault("NAME DICTIONARY FULL") and stop if length(sname) = 255 then fault("NAME TOO LONG") and stop sname = sname . tostring(l) hash = hash << 8 ! l ttpp = ttpp + 1 l = tt(ttpp) repeat until l < '0' or '9' < l < 'A' or l > 'Z' hash = hash - hash // 251 * 251 i = hash cycle ! scan dictionary if namedlink(i) = 0 then namedlink(i) = namedp c and namedp = namedp + length(sname) + 1 and exit ! insert name if sname = string(addr(named(namedlink(i)))) then exit i = (i + 1) & 255 if i = hash then fault("NAME DICTIONARY FULL") and stop repeat t(tp) = 256 ! <name> t(tp + 1) = i ! ident tp = tp + 2 end !----------------------------------------------------------------------- routine const integer l, value, flag, count, maxby10, maxld value = 0 flag = 0 if tt(ttpp) = '$' then start cycle ttpp = ttpp + 1 exit unless '0' <= tt(ttpp) <= '9' or 'A' <= tt(ttpp) <= 'F' if tt(ttpp) < 'A' then value = value << 4 ! (tt(ttpp) - '0') c else value = value << 4 ! (tt(ttpp) - 'A' + 10) flag = 1 and exit if value > 16_FFFF repeat finish else start if tt(ttpp) = '''' then start count = 0 cycle ttpp = ttpp + 1 if tt(ttpp) = '''' then start ttpp = ttpp + 1 if tt(ttpp) # '''' then exit finish value = value << 8 ! tt(ttpp) count = count + 1 repeat unless count <= 2 then flag = 1 ! Only one char per word on M6809 finish else start maxby10 = 16_7FFF // 10 maxld = 16_7FFF - maxby10 * 10 + '0' ! Bug fixed. l = tt(ttpp) cycle if value > maxby10 or (value = maxby10 and l > maxld) c then flag = 1 else value = value * 10 + l - '0' ttpp = ttpp + 1 l = tt(ttpp) repeat until l < '0' or l > '9' finish finish t(tp) = 257 ! <const> if flag # 0 then fault("CONSTANT INVALID") and value = 0 t(tp + 1) = value tp = tp + 2 end !----------------------------------------------------------------------- routine stringconst t(tp) = 258 ! <STRING> if tt(ttpp) # '"' then start fault("INVALID STRING") t(tp + 1) = 16_80 return finish cycle tp = tp + 1 ! Skip the first quote ttpp = ttpp + 1 if tt(ttpp) = '"' then start if tt(ttpp + 1) = '"' then ttpp = ttpp + 1 c and t(tp) = '"' and continue t(tp) = 16_80 tp = tp + 1 ttpp = ttpp + 1 return finish t(tp) = tt(ttpp) repeat end end !----------------------------------------------------------------------- routine rpsym(integer name l) own integer flag = 1 readsymbol(l) if flag = 1 and outstream = 1 then printstring("* ") and flag = 0 printsymbol(l) if outstream = 1 and l = ';' and shift # 0 then newline if outstream = 1 and (l = nl or (l = ';' and shift # 0)) then flag = 1 if 'a' <= l <= 'z' then l = l !! shift end !----------------------------------------------------------------------- integer fn findk(string (*) name k) ! look keyword up in dictionary integer i, l l = charno(k, 1) k -> (tostring(l)) . k i = l - 'A' + 1 if kd(i)_l = 0 then result = 0 search: if k = "" or kd(i)_a = 0 then result = kd(i)_n l = charno(k, 1) k -> (tostring(l)) . k i = kd(i)_a cycle if kd(i)_l = l then -> search if kd(i)_b = 0 then result = 0 i = kd(i)_b repeat end !----------------------------------------------------------------------- integer fn compare(integer p) integer app, tpp, alt, altend, psp, psi a(ap) = p << 16 ! 16_80000001 ! phrase number & alternative 1 if p <= 257 then start ! <name> or <const> if p = t(tp) then start ! success a(ap + 1) = t(tp + 1) ap = ap + 2 tp = tp + 2 result = 1 finish else result = 0 finish if p = 258 then start if t(tp) # p then result = 0 alt = 1 a(ap + alt) = t(tp + alt) and alt = alt + 1 until t(tp + alt) = 16_80 a(ap + alt) = 16_80 ap = ap + alt + 1 tp = tp + alt + 1 result = 1 finish tpp = tp ! preserve text pointer app = ap ! preserve analysis record pointer psp = pp(p) ! start of phrase definition cycle ! for each alternative alt = ap + 1 altend = ps(psp) ap = alt + ps(psp + 1) ! leave gap for forward pointers if ap > 255 then fault("ANALYSIS RECORD TOO LONG") and stop psp = psp + 2 cycle ! for each item if psp = altend then result = 1 ! success psi = ps(psp) if psi >= 256 then start ! phrase a(alt) = ap ! forward pointer if compare(psi) = 0 then exit alt = alt + 1 finish else start ! literal or keyword if psi # t(tp) then exit tp = tp + 1 finish psp = psp + 1 repeat if ps(altend) = 0 then result = 0 ! failure psp = altend tp = tpp ! backtrack text pointer ap = app ! backtrack analysis record pointer a(ap) = a(ap) + 1 ! next alternative number repeat end end of program