!***********************************************************************
!* SOAP80 - IMP80 formatter *
!* Last altered 15/06/83 *
!* *
!* Created by E.N.Gregory, UKC. *
!* All syntax directed sections rewritten by P.D.S., ERCC *
!* using IMP80 syntax version 02. *
!* User interface and parameters revised by J.M.M., ERCC. *
!* *
!***********************************************************************
external routine spec prompt(string (31) s)
!***********************************************************************
!* *
!* Record formats. *
!* *
!***********************************************************************
record format fhdr(integer dataend, datastart, filesize, filetype)
record format chdr(integer conad, filetype, datastart, dataend)
constant integer maxopt= 16,numopt = 3
record format pformat(byte integer array tab(0:20),
(byte integer line, icontin, poscom, movecom, uckey, sepkey, expkey,
lcasnam, spacnam, spacass, spacop, lclist, iblock, istat, seplab,
spcomma or byte integer array optarr(1:maxopt)) or c
byte integer array a(1:21+maxopt))
!***********************************************************************
!* *
!* System routines. *
!* *
!***********************************************************************
system string function spec itos(integer i)
system routine spec connect(string (31) name, integer mode, hole, prot,
record (chdr) name rec, integer name eflag)
system routine spec trim(string (31) file, integer name eflag)
system routine spec setfname(string (31) file)
system string function spec nexttemp
system routine spec sendfile(string (31) file, device, header,
integer copies, form, integer name eflag)
system integer function spec devcode(string (31) name)
system routine spec disconnect(string (31) filename, integer name eflag)
system string function spec failuremessage(integer type)
system routine spec changefilesize(string (31) filename,
integer filesize, integer name eflag)
system routine spec newgen(string (31) filename, newfilename,
integer name eflag)
system routine spec outfile(string (31) filename, integer size, hole,
prot, integer name conad, eflag)
external routine soap80(string (255) s)
integer ptr, dataend, inptr, z, in, obp, eflag, writeaddress, wa0,
filesize, conad, errors, line, erptr, startline, stream, filesizeptr,
ssalt, strdelimiter, str, semicolon, colon, maxptr, maxitem, level,
stop, increm, inlabel, charsin, ersave, inconst, bheading, inline
string (255) outf
string (31) workfile, infile
string (2) percentc
record (pformat) p
record (chdr) rec, rr
record (fhdr) name outrec
constant integer ccsize= 16384
half integer array outbuf(0:ccsize+200)
byte integer array sc(0:ccsize)
constant string (7) array optname(1:maxopt)= "LINE","ICONTIN","POSCOM",
"MOVECOM","UCKEY","SEPKEY","EXPKEY","LCASNAM","SPACNAM","SPACASS","SPACOP",
"LCLIST","IBLOCK","ISTAT","SEPLAB","SPCOMMA"
constant string (39) array optmess(0:1, 1:maxopt)= c
"Line length zero (!!!)","Maximum line length",
"Continued lines not indented","Indentation of continued lines",
"Right hand comments not positioned","Right hand comment position",
"Whole line comments indented normally",
"Whole line comments moved to POSCOM","Keywords output in lower case",
"Keywords output in upper case","Keywords not split","Keywords split",
"%FN, %CONST, %ELSE not expanded",
"%FN, %CONST, (sometimes) %ELSE expanded",
"Case of names controlled by UCKEY", "Case of names left alone",
"Spaces removed from names","Spaces preserved within names",
"No spaces round assignment operators",
"Spaces added round assignment operators","No spaces round operators",
"Spaces added round operators","Constant lists formatted",
"Constant lists left alone","Block not indented w.r.t. block heading",
"Block indented w.r.t. block heading",
"Statements aligned with declarations",
"Statements indented w.r.t. declarations",
"Labels not on lines by themselves","Labels on lines by themselves",
"No space character after commas","Space character after commas"
constant integer charfile= 3; ! Code for a character file.
constant integer underline= 128
constant integer instring= 256,incurly = 512,bpoint = 1024,bpoint2 = 2048
constant integer terminal= 1,file = 2,samefile = 3,device = 4
constant integer true= 255,false = 0; ! Synthetic boolean values.
constant integer nl= 10,dquotes = 34,squotes = 39
constant integer rs= 30; ! RECORD SEPARATOR IS USED AS A DELETED(BY %c) NL
constant integer rem= B'00000001'
constant integer constart= B'00000010'
constant integer quotes= B'00000100'
constant integer endst= B'00001000'
constant integer number= B'00010000'
constant integer letter= B'00100000'
constant byte integer constfirst= B'01000000'
constant integer constcont= B'10000000'
!
constant byte integer array onecase(0:127)=
0,1,2,3,4,5,6,7,8,9,10,11,12,
13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,
35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,
57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,
79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,65,66,67,68,
69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,
123,124,125,126,127
constant byte integer array chartype(0:255)= B'00000001',
B'00000000',
B'00000000',B'00000000',B'00000000',B'00000000',B'00000000',
B'00000000',B'00000000',B'00000000',B'00001000',B'00000000'(22),
B'00000001'{!},B'00000100',B'01000000',B'00000000',B'00000001'{%},
B'00000000',B'00000100',B'00000000',B'00000000',B'00000000',
B'00000000',B'00000000',B'00000000',B'11000000',B'00000000',
B'11010000'(10),
B'00000000',B'00001000',B'01000000',B'01000000',B'01000000',
B'00000000',B'00000000',
B'00100000',B'00100010',B'00100010',B'00100010',B'00100000',
B'00100000',B'00100000',B'00100000',
B'00100000',B'00100000',B'00100010',B'00100000',
B'00100010',B'00100000',B'00100000',B'00100000',B'00100000',
B'00100010',B'00100000',B'00100000',B'00100000',B'00100000'(2),
B'00100010',B'00100000',B'00100000',B'00000000',B'00000000',
B'00000000',B'00000000',B'00000000',B'00000000',
B'00100000',B'00100010'{b},B'00100010',B'00100010',B'00100000'(6),
B'00100010'{k},B'00100000',B'00100010'{m},B'00100000'(4),
B'00100010'{r},B'00100000'(5),B'00100010'{x},B'00100000'(2),
B'00000000',B'00000001'{|},B'00000000',B'00000000',B'00000000',
B'0'(67),
B'00000001'{%C},
B'0'(60)
constant byte integer array keycom(0:7)= '%','C','O','M','M','E','N','T'
constant integer array fstable(1:3)= 4096,16384,65536
!
! Special delimiters noted by SOAP80.
!
constant integer offile= 133,ofprogram = 123,equals = 38,comma = 10,
if = 12,
unless = 15,while = 22,until = 28,else = 227,then = 222,and = 158,or = 162,
const = 204, constant = 195, fn = 96, function = 103
!
constant string (1) snl= "
"
!
constant string (60) array fault(1:4)=
"Statement is too long and could not be compiled.",
"End of file reached before end of program terminator found.",
"%END found, but could not match it to a start of routine.",
"Disaster *** Indentation too near line length limit."
!
!
!
routine spec fail(integer type, action)
routine spec opt(string (255) parm, record (pformat) name p)
!
! Produced by oldps from impalgs_imp80ps04 on 19/01/83
constant byte integer array clett(0:434)= 1,
{1} 43, 1, 45, 1, 40, 1, 41, 1, 42, 1, 44, 2, 201, 198,
{15} 6, 213, 206, 204, 197, 211, 211, 5, 215, 200, 201, 204, 197, 5,
{29} 213, 206, 212, 201, 204, 3, 198, 207, 210, 1, 61, 5, 193, 204,
{43} 201, 193, 211, 7, 201, 206, 212, 197, 199, 197, 210, 4, 210, 197,
{57} 193, 204, 4, 204, 207, 206, 199, 4, 194, 217, 212, 197, 6, 211,
{71} 212, 210, 201, 206, 199, 4, 200, 193, 204, 198, 6, 210, 197, 195,
{85} 207, 210, 196, 7, 210, 207, 213, 212, 201, 206, 197, 2, 198, 206,
{99} 3, 205, 193, 208, 8, 198, 213, 206, 195, 212, 201, 207, 206, 4,
{113} 206, 193, 205, 197, 5, 193, 210, 210, 193, 217, 9, 207, 198, 208,
{127} 210, 207, 199, 210, 193, 205, 6, 207, 198, 198, 201, 204, 197, 6,
{141} 207, 198, 204, 201, 211, 212, 6, 198, 207, 210, 205, 193, 212, 3,
{155} 206, 207, 212, 3, 193, 206, 196, 2, 207, 210, 1, 58, 4, 211,
{169} 208, 197, 195, 3, 207, 215, 206, 8, 197, 216, 212, 197, 210, 206,
{183} 193, 204, 9, 197, 216, 212, 210, 201, 206, 211, 201, 195, 8, 195,
{197} 207, 206, 211, 212, 193, 206, 212, 5, 195, 207, 206, 211, 212, 5,
{211} 197, 214, 197, 206, 212, 5, 211, 212, 193, 210, 212, 4, 212, 200,
{225} 197, 206, 4, 197, 204, 211, 197, 1, 95, 6, 211, 217, 211, 212,
{239} 197, 205, 7, 196, 217, 206, 193, 205, 201, 195, 4, 80, 85, 84,
{253} 95, 5, 67, 78, 79, 80, 95, 2, 204, 61, 1, 60, 1, 62,
{267} 4, 40, 196, 210, 43, 2, 196, 210, 1, 194, 3, 212, 207, 211,
{281} 3, 204, 206, 194, 3, 216, 206, 194, 2, 208, 195, 3, 195, 212,
{295} 194, 2, 45, 62, 6, 210, 197, 212, 213, 210, 206, 6, 210, 197,
{309} 211, 213, 204, 212, 7, 205, 207, 206, 201, 212, 207, 210, 4, 211,
{323} 212, 207, 208, 6, 211, 201, 199, 206, 193, 204, 4, 197, 216, 201,
{337} 212, 8, 195, 207, 206, 212, 201, 206, 213, 197, 6, 198, 201, 206,
{351} 201, 211, 200, 5, 195, 217, 195, 204, 197, 6, 210, 197, 208, 197,
{365} 193, 212, 3, 197, 206, 196, 7, 201, 206, 195, 204, 213, 196, 197,
{379} 5, 194, 197, 199, 201, 206, 2, 207, 206, 6, 211, 215, 201, 212,
{393} 195, 200, 4, 204, 201, 211, 212, 14, 212, 210, 213, 211, 212, 197,
{407} 196, 208, 210, 207, 199, 210, 193, 205, 6, 205, 193, 201, 206, 197,
{421} 208, 7, 195, 207, 206, 212, 210, 207, 204, 4, 40, 42, 41, 58
constant integer array symbol(1300:2167)= 1307,
1303, 0, 1305, 2, 1307, 1000, 1319, 1312, 1001, 1366,
1786, 1315, 1003, 1020, 1319, 4, 1345, 6, 1329, 1323,
1001, 1014, 1325, 1003, 1329, 4, 1329, 6, 1336, 1336,
1010, 1028, 1319, 1011, 1359, 1345, 1343, 1010, 1028, 1319,
1011, 1359, 1345, 8, 1352, 1352, 1010, 1028, 1307, 1011,
1352, 1359, 1357, 1026, 1307, 999, 1359, 1000, 1366, 1364,
1026, 1319, 999, 1366, 1000, 1374, 1372, 4, 1345, 1374,
6, 1374, 1000, 1381, 1379, 10, 1345, 999, 1381, 1000,
1386, 1384, 12, 1386, 15, 1410, 1393, 22, 1010, 1536,
1556, 1011, 1399, 28, 1010, 1536, 1556, 1011, 1410, 34,
1010, 1001, 38, 1345, 10, 1345, 10, 1345, 1011, 1416,
1414, 40, 1013, 1416, 1000, 1423, 1421, 10, 1001, 999,
1423, 1000, 1428, 1426, 46, 1428, 1000, 1436, 1431, 54,
1433, 46, 1436, 59, 54, 1458, 1439, 46, 1441, 54,
1444, 59, 1428, 1447, 64, 1423, 1450, 69, 1689, 1453,
76, 1423, 1458, 81, 4, 1848, 6, 1465, 1461, 88,
1465, 1004, 1436, 1465, 1472, 1468, 96, 1470, 99, 1472,
103, 1488, 1478, 1436, 1493, 1001, 1416, 1484, 1458, 1488,
1001, 1416, 1501, 1488, 112, 1001, 1416, 1493, 1491, 112,
1493, 1000, 1501, 1497, 117, 112, 1499, 112, 1501, 1000,
1511, 1509, 4, 1010, 1472, 1011, 1511, 6, 1511, 1000,
1520, 1518, 1030, 1010, 1472, 1011, 999, 1520, 1000, 1531,
1524, 123, 1016, 1526, 133, 1529, 140, 1018, 1531, 1016,
1536, 1534, 147, 1536, 1000, 1550, 1542, 1345, 1032, 1345,
1550, 1547, 4, 1536, 1556, 6, 1550, 154, 1536, 1556,
1554, 1037, 1345, 1556, 1000, 1567, 1561, 158, 1536, 1567,
1565, 162, 1536, 1574, 1567, 1000, 1574, 1572, 158, 1536,
999, 1574, 1000, 1581, 1579, 162, 1536, 999, 1581, 1000,
1589, 1585, 1033, 1345, 1587, 165, 1589, 1000, 1595, 1593,
167, 1008, 1595, 1015, 1599, 1598, 167, 1599, 1608, 1606,
10, 1345, 165, 1345, 1599, 1608, 1000, 1617, 1613, 1493,
1001, 1416, 1617, 117, 1531, 1617, 1623, 1623, 1001, 1416,
1794, 1623, 1629, 1627, 10, 1617, 1629, 1000, 1646, 1639,
1493, 1595, 1010, 1001, 1410, 1802, 1011, 1646, 1646, 117,
1531, 1595, 1001, 1794, 1668, 1657, 1655, 10, 1010, 1001,
1410, 1802, 1011, 1646, 1657, 1000, 1668, 1660, 172, 1662,
176, 1664, 185, 1666, 195, 1668, 204, 1679, 1677, 38,
1012, 1028, 1319, 1359, 1689, 1679, 1679, 1000, 1689, 1687,
10, 1028, 1319, 1359, 1689, 999, 1689, 1000, 1696, 1694,
4, 1336, 6, 1696, 1000, 1703, 1701, 10, 1329, 999,
1703, 1000, 1708, 1706, 210, 1708, 1000, 1714, 1712, 10,
1345, 1714, 1000, 1727, 1725, 10, 1001, 1416, 4, 1345,
165, 1345, 6, 999, 1727, 1000, 1734, 1732, 28, 1536,
1556, 1734, 1000, 1747, 1737, 1019, 1739, 1006, 1744, 1381,
1536, 1556, 1006, 1747, 1386, 1006, 1761, 1751, 216, 1034,
1755, 222, 216, 1034, 1761, 222, 1010, 2008, 1011, 1767,
1767, 1765, 158, 2008, 1767, 1000, 1773, 1771, 227, 1773,
1773, 1000, 1786, 1777, 216, 1034, 1784, 1381, 1010, 1536,
1556, 1011, 1747, 1786, 2008, 1794, 1792, 232, 1001, 1366,
1786, 1794, 1000, 1802, 1802, 4, 1345, 165, 1345, 1599,
6, 1810, 1808, 38, 1028, 1319, 1359, 1810, 1000, 1819,
1813, 234, 1815, 176, 1817, 241, 1819, 1000, 1830, 1828,
1001, 38, 1345, 10, 1345, 10, 1345, 1830, 1000, 1837,
1835, 10, 1855, 999, 1837, 1000, 1848, 1841, 167, 1001,
1848, 1001, 4, 1855, 1830, 1873, 6, 1855, 1851, 1001,
1855, 1855, 1830, 1873, 1865, 1859, 1436, 1865, 1865, 4,
1855, 1830, 1873, 6, 1873, 1870, 1493, 1001, 1416, 1873,
117, 1617, 1881, 1879, 162, 1855, 1830, 999, 1881, 1000,
1898, 1886, 249, 1002, 1006, 1890, 1022, 1898, 1006, 1896,
254, 1009, 10, 1009, 1006, 1898, 1031, 1912, 1902, 1023,
1912, 1907, 1024, 260, 1951, 1956, 1912, 1025, 1005, 10,
1935, 1935, 1917, 263, 1001, 265, 1919, 1984, 1924, 4,
1984, 1973, 6, 1928, 267, 1984, 6, 1933, 4, 272,
1973, 6, 1935, 275, 1951, 1940, 263, 1001, 265, 1942,
1984, 1947, 4, 272, 1973, 6, 1951, 267, 1005, 6,
1956, 1954, 272, 1956, 1005, 1964, 1962, 10, 1005, 10,
1005, 1964, 1000, 1973, 1968, 0, 1005, 1971, 2, 1005,
1973, 1000, 1979, 1977, 0, 275, 1979, 1000, 1984, 1982,
38, 1984, 1000, 1999, 1989, 1979, 1300, 1003, 1992, 1001,
1964, 1997, 4, 1999, 1964, 6, 1999, 277, 2008, 2002,
281, 2004, 285, 2006, 289, 2008, 292, 2041, 2017, 1010,
1001, 1366, 1786, 1011, 1581, 1761, 2021, 296, 1001, 1366,
2023, 299, 2027, 306, 1033, 1345, 2030, 313, 1761, 2032,
321, 2037, 326, 1703, 1329, 1708, 2039, 333, 2041, 338,
2168, 2048, 1027, 1010, 2008, 1011, 1734, 2050, 1007, 2058,
1381, 1010, 1536, 1556, 1011, 1747, 1006, 2063, 347, 1035,
1767, 1006, 2068, 354, 1029, 1819, 1006, 2073, 360, 1036,
1727, 1006, 2078, 1386, 354, 1029, 1006, 2086, 1004, 1008,
1010, 1436, 1011, 1608, 1006, 2090, 367, 1520, 1006, 2095,
81, 147, 1837, 1006, 2105, 1010, 1810, 1458, 1011, 1589,
1001, 1410, 1501, 1006, 2110, 1657, 1436, 1629, 1006, 2114,
371, 1003, 1038, 2118, 379, 1015, 1006, 2127, 385, 1021,
1703, 1329, 1696, 216, 1034, 1006, 2138, 388, 1001, 1416,
4, 1345, 165, 1345, 6, 1714, 1006, 2142, 395, 1006,
1017, 2148, 227, 1035, 1039, 1034, 1006, 2151, 8, 1881,
2154, 400, 1006, 2158, 415, 1001, 1006, 2162, 422, 1003,
1006, 2166, 1001, 430, 1019, 2168, 1006
constant integer ss= 2041
constant integer comment= 2; ! alt of p<SS> of %comment
constant integer ownalt= 12; ! alt of p<SS> for owns
constant integer eisss= X'00017F00'; ! Flag declarative ss alts
! MAY CHANGE WITH NEW SYNTAX
constant integer array opc(0:127)=
0, M' JCC', M' JAT', M' JAF', 0(4),
M' VAL', M' CYD', M'INCA', M'MODD', M'PRCL', M' J', M' JLK', M'CALL',
M' ADB', M' SBB', M'DEBJ', M' CPB', M' SIG', M' MYB', M' VMY', M'CPIB',
M' LCT', M'MPSR', M'CPSR', M'STCT', M'EXIT', M'ESEX', M' OUT', M' ACT',
M' SL', M'SLSS', M'SLSD', M'SLSQ', M' ST', M'STUH', M'STXN', M'IDLE',
M' SLD', M' SLB', M'TDEC', M'INCT', M' STD', M' STB', M'STLN', M'STSF',
M' L', M' LSS', M' LSD', M' LSQ', M'RRTC', M' LUH', M'RALN', M' ASF',
M'LDRL', M' LDA', M'LDTB', M' LDB', M' LD', M' LB', M' LLN', M' LXN',
M' TCH', M'ANDS', M' ORS', M'NEQS', M'EXPA', M' AND', M' OR', M' NEQ',
M' PK', M' INS', M'SUPK', M' EXP', M'COMA', M' DDV', M'DRDV', M'DMDV',
M'SWEQ', M'SWNE', M' CPS', M' TTR', M' FLT', M' IDV', M'IRDV', M'IMDV',
M' MVL', M' MV', M'CHOV', M' COM', M' FIX', M' RDV', M'RRDV', M'RDVD',
M' UAD', M' USB', M'URSB', M' UCP', M' USH', M' ROT', M' SHS', M' SHZ',
M' DAD', M' DSB', M'DRSB', M' DCP', M' DSH', M' DMY', M'DMYD', M'CBIN',
M' IAD', M' ISB', M'IRSB', M' ICP', M' ISH', M' IMY', M'IMYD', M'CDEC',
M' RAD', M' RSB', M'RRSB', M' RCP', M' RSC', M' RMY', M'RMYD', M' PUT'
routine cnptf
!***********************************************************************
!* Create New Page To File :- This is called when the output file *
!* is full and must be extended to a new page. *
!***********************************************************************
if filesizeptr<3 then c
filesizeptr = filesizeptr+1 and filesize = fstable(filesizeptr) else c
filesize = filesize+fstable(3)
changefilesize(workfile, filesize, eflag)
if eflag=261 start
! V.M. hole is too small for the new file size.
disconnect(workfile, eflag); if eflag#0 then fail(eflag, 5)
changefilesize(workfile, filesize, eflag)
if eflag=0 start
writeaddress = writeaddress-conad
connect(workfile, 3, 0, 0, rr, eflag)
if eflag#0 then fail(eflag, 5)
conad = rr_conad
writeaddress = writeaddress+conad
outrec == record(conad)
finish
finish
if eflag#0 then fail(eflag, 5)
outrec_filesize = filesize; ! Update file size in header.
end
routine transfer(integer from, to)
!***********************************************************************
!* Transfer copies the contents of OUTBUF from FROM to TO into the *
!* output file or channel. *
!***********************************************************************
integer i, ch, last
if stream#terminal start
last = to-from+1+writeaddress-conad
if last>filesize then cnptf
outrec_dataend = last
finish
for i = from, 1, to cycle
ch = outbuf(i)&X'7F'
if ch&127=rs then continue
if ch=nl start
charsin = 0; line = line+1
unless stream=terminal start
write address = write address-1 while c
write address>wa0 and byteinteger(write address-1)=' '
finish
finish else charsin = charsin+1
if stream=terminal then printch(ch) else c
byteinteger(writeaddress) = ch and writeaddress = writeaddress+1
repeat
end
routine outstring(string (40) text)
!***********************************************************************
!* Outstring copies TEXT to the output file or channel. *
!***********************************************************************
integer i, ch, last
if stream#terminal start
last = length(text)+writeaddress-conad
if last>filesize then cnptf
outrec_dataend = last
finish
for i = 1, 1, length(text) cycle
ch = charno(text, i)
if ch=nl then charsin = 0 and line = line+1 else c
charsin = charsin+1
if stream=terminal then printch(ch) else c
byteinteger(writeaddress) = ch and writeaddress = writeaddress+1
repeat
end
routine dupl(integer char, integer times)
!***********************************************************************
!* Dupl copies CHAR, TIMES times to the output file or channel. *
!***********************************************************************
integer i, last
if times<=0 then return
charsin = charsin+times
if stream#terminal start
last = times+writeaddress-conad
if last>filesize then cnptf
outrec_dataend = last
finish
for i = 1, 1, times cycle
if stream=terminal then printch(char) else c
byteinteger(writeaddress) = char and writeaddress = writeaddress+1
repeat
end
routine insert(integer chars, lsflag, rsflag)
!***********************************************************************
!* This will place upto four characters into the OUTBUF buffer this *
!* includes the option of have spaces around the characters. *
!***********************************************************************
if lsflag=true#inconst then outbuf(obp) = ' ' and obp = obp+1
until chars=0 cycle
outbuf(obp) = chars&X'FF'
chars = chars>>8
obp = obp+1
repeat
if rsflag=true#inconst then outbuf(obp) = ' ' and obp = obp+1
end
routine closedown(integer success)
!***********************************************************************
!* Closedown is called when the program is to terminate execution *
!* and is to print a suitable message and to close the output file *
!* if any. *
!***********************************************************************
if success=true start
printstring(itos(line)." lines have been processed".snl)
finish else start
printstring("Soap80 fails :- ".itos(errors))
if errors=1 then printstring(" error.".snl) else c
printstring(" errors.".snl)
finish
! Is there a file to close?
if stream#terminal start
outrec_dataend = writeaddress-conad
trim(workfile, eflag)
disconnect(workfile, eflag)
if stream=samefile start
if errors>0 then c
printstring("Output stored in ".workfile.", since ".infile. c
" contains errors.".snl) else start
newgen(workfile, outf, eflag)
if eflag#0 start
printstring("Attempt to create ".outf." failed because ". c
failuremessage(eflag).snl)
printstring("Output stored in ".workfile.".".snl)
finish
finish
finish else start
if stream=device start
if length(infile)>8 then length(infile) = 8
sendfile(workfile, outf, "Soap80: ".infile, 1, 0, eflag)
if eflag#0 then fail(eflag, 5)
finish
finish
finish
pprofile
stop ; ! Exit from SOAP80.
end
routine punch
!***********************************************************************
!* PUNCH is for tranferring the contents of the OUTBUF array *
!* to the output file or channel, using TRANSFER, OUTSTRING and DUPL.*
!* *
!* PUNCH decides where to break a line if it is too long. *
!***********************************************************************
integer lst, bk, i, ubp, lbp, bbp, tp, inn, ch, curlend
inn = in
inn = inn+1 if 1<<ssalt&eisss=0 and p_istat=true
if ssalt#comment and semicolon=false then dupl(' ', p_tab(inn)-charsin)
if outbuf(obp-1)=';' then semicolon = true else semicolon = false
if semicolon=true and p_line-20<charsin+obp then c
semicolon = false and outbuf(obp-1) = nl
if semicolon=true then outbuf(obp) = ' ' and obp = obp+1
if increm=true start
increm = false
! Is indenting value too near the line length limit?
if p_tab(in+1)+20>p_line then fail(4, 2) else in = in+1
finish
lst = 1
if ssalt=comment start
! Look for RS in comment. If found, output as more than one line.
cycle
if chartype(sc(1))&rem=0 or semicolon=true start
! Comment does not start in column 1.
if semicolon!colon=false and p_movecom=false then c
dupl(' ', p_tab(inn)-charsin) else dupl(' ', p_poscom-charsin)
finish
i = lst
i = i+1 while i<obp and outbuf(i)&127#rs
->final part if i=obp
transfer(lst, i-1)
if outbuf(i-1)&127=',' then outstring(snl) else c
outstring(percentc.snl)
i = i+1 until i=obp or outbuf(i)#' '
lst = i
repeat
finish
cycle
ubp = p_line+lst-charsin-4; ! RHMOST BREAK POINT
lbp = (ubp+lst)//2
bbp = (ubp+3*lst)//4
curlend = 0
! First check for nl in string const or list
for bk = lst, 1, ubp+3 cycle
exit if bk>=obp
ch = outbuf(bk)
if ch&127=nl or (ch&127=rs and ssalt=ownalt and c
p_lclist=true) then ->printpart
repeat
if obp<ubp+3 then exit ; ! 3 FOR " %C"
for bk = ubp, -1, bbp cycle ; ! CHECK FOR PRIMARY BREAK POINTS
if outbuf(bk)&bpoint#0 start
bk = bk+1 while outbuf(bk+1)=' '
->printpart
finish
repeat
for bk = ubp, -1, bbp cycle ; ! CHECK FOR SECONDARY BREAK POINT
if outbuf(bk)&bpoint2#0 start
bk = bk+1 while outbuf(bk+1)=' '
->printpart
finish
repeat
for bk = ubp, -1, bbp cycle
if outbuf(bk)=',' then ->printpart
repeat
if outbuf(ubp)&incurly#0 start ; ! IN A CURLY COMMENT
curlend = 1
for bk = ubp, 1, obp-2 cycle
curlend = 0 and exit if outbuf(bk)&incurly=0
repeat
! curlend indicates whether the curly comment goes to the end of the line.
for bk = ubp, -1, bbp cycle
if outbuf(bk)&incurly=0 then bk = bk-1 and ->printpart
repeat
->final part if curlend=1; ! Overlong curly comment.
for bk = ubp, 1, obp-2 cycle
if outbuf(bk)&incurly=0 then ->printpart
repeat
finish
for bk = ubp+1, -1, lbp cycle
if outbuf(bk)=' ' and outbuf(bk-1)&underline#0 then ->printpart
repeat
if p_spacnam=false start ; ! MUST OMIT IF NAMES ARE SPACED
for bk = ubp+1, -1, lbp cycle
if outbuf(bk)=' ' then ->printpart
repeat
finish
for bk = ubp, -1, lbp cycle
if outbuf(bk)='%' then bk = bk-1 and ->printpart
repeat
for bk = ubp, -1, lbp cycle
if outbuf(bk)='.' or outbuf(bk)=')' then ->printpart
if outbuf(bk)='(' then bk = bk-1 and ->printpart
repeat
if outbuf(ubp)&instring#0 start
! Break point is inside a string.
for bk = ubp, -1, bbp cycle
if outbuf(bk)=',' or outbuf(bk)='.' or outbuf(bk)='=' then c
->printpart
repeat
for i = ubp, -1, lst+3 cycle
if outbuf(i)=dquotes then bk = i-1 and ->printpart
repeat
for i = bk, -1, lst cycle
if outbuf(i)=squotes start
if chartype(outbuf(i-1))&constart=0 then bk = i-1 else c
bk = i-2
->printpart
finish
repeat
! Break string.
printstring("Line:".itos(line)." problem:")
printsymbol(outbuf(i)) for i = lst, 1, ubp
newline
tp = ubp-1
transfer(lst, tp)
outstring(""".".percentc.snl)
dupl(' ', p_tab(inn)+p_icontin)
outstring("""")
lst = tp+1
continue
finish else bk = ubp
printstring("Line:".itos(line)." problem:")
printsymbol(outbuf(i)) for i = lst, 1, ubp
newline
printpart:
i = bk
i = i-1 while outbuf(i)=' ' or outbuf(i)&127=rs
transfer(lst, i)
if i<lst or outbuf(i)&127#nl start ; ! NOT NATURAL BREAK
if outbuf(i)&127#',' and outbuf(bk)#rs!128 and curlend=0 then c
outstring(" ".percentc)
outstring(snl)
dupl(' ', p_tab(inn)+p_icontin) if inconst=false
outstring("%") if c
outbuf(bk+1)&underline#0 and outbuf(bk+1)#rs!128
finish
lst = bk+1
repeat
finalpart:
transfer(lst, obp-1)
obp = 1
end
integer function nextnonsp(integer print)
! If PRINT is True then ' ' or '%' or RS are transferred to the output
! buffer when encountered.
integer ch
cycle
ch = sc(ptr)
if ch='{' start
outbuf(obp) = ' ' and obp = obp+1 if obp>1 and print=false
outbuf(obp) = '{'
obp = obp+1; ptr = ptr+1
cycle
ch = sc(ptr)
outbuf(obp) = ch!incurly
obp = obp+1
ptr = ptr+1
repeat until ch='}'
continue
finish
exit unless ch=' ' or ch='%' or ch&127=rs
if print=true then outbuf(obp) = ch and obp = obp+1
ptr = ptr+1
repeat
result = ch
end
routine getline(integer initptr)
!***********************************************************************
!* GETLINE :- take from the input file and processes the data and *
!* it into the array SC. *
!* *
!* The following processing is done: *
!* 1) All delimiters have 128 added to each character in the word*
!* 2) Lines are joined togther if there is a %c or ',' at the end*
!* of the first line. The newline position is marked by RS. *
!***********************************************************************
constant byte integer array itoi(0:255)= c
32(10),10,32(14),25,26,32(5),
32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,
48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,
64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,
80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,
96,97,98,99,100,101,102,103,104,105,106,107,108,109,
110,111,112,113,114,115,116,117,118,119,
120,121,122,123,124,125,126,32,
26(5),10,26(10),
26(16),
26(14),92,38,
26(11),35,26(4),
26(16),
26(9),35,26(5),94,
26(32)
half integer array scurl, ecurl(1:20)
integer in keyword, char, p, ncurl
own integer strdelimiter
if initptr=1 then startline = inptr
ptr = initptr
cycle
in keyword = false
ncurl = 0
cycle
if ptr>ccsize then fail(1, 1) and exit
if inptr>dataend then fail(2, 1)
char = itoi(byteinteger(inptr))
inptr = inptr+1
if char=nl start
inline = inline+1
sc(ptr) = nl
ptr = ptr+1
exit
finish
if str=true start
sc(ptr) = char; ptr = ptr+1
if char=strdelimiter then str = false
continue
finish
if chartype(char)&endst#0 then c
sc(ptr) = char and ptr = ptr+1 and exit
! Deal with curly bracket comments noting start so as to permit
! continuations of the form ...,{...}.
! Note that any missing closing brace is replaced.
if char='{' start
ncurl = ncurl+1; scurl(ncurl) = ptr
sc(ptr) = char; ptr = ptr+1
cycle
char = itoi(byteinteger(inptr))
if char=nl then char = '}' else inptr = inptr+1
if char='}' then exit
sc(ptr) = char
ptr = ptr+1
repeat
ecurl(ncurl) = ptr
finish
if in keyword=true start
if chartype(char)&letter=0 then in keyword = false else c
sc(ptr) = onecase(char)!underline and ptr = ptr+1 and c
continue
finish
if char='%' then in keyword = true
if char=squotes or char=dquotes start
str = true; strdelimiter = char
finish
sc(ptr) = char
ptr = ptr+1
repeat
if char=nl start ; ! TRAILING SPACES CHECK
ptr = ptr-1 while ptr>2 and sc(ptr-2)=' '
sc(ptr-1) = nl
if str=false start
p = ptr-2
while ncurl>0 and ecurl(ncurl)=p cycle
! Step past curly bracket.
p = scurl(ncurl)-1; ncurl = ncurl-1
p = p-1 while p>0 and sc(p)=' '
repeat
! Now p points at character determining continuation.
if p>0 start
char = sc(p)
if char=',' start
sc(ptr-1) = rs!128
continue
finish
if char='C'+underline start
if p>1 and sc(p-1)='%' then sc(p-1) = ' '
sc(p) = ' '
sc(ptr-1) = rs
continue
finish
if char&127=rs then sc(ptr-1) = rs!128 and continue
finish
finish
finish
exit
repeat
ptr = initptr
end
integer function compare(integer test)
integer i, ch, key, j
for i = 1, 1, clett(test) cycle
ch = nextnonsp(inconst)
if ch#clett(i+test) then result = false
ptr = ptr+1
repeat
if test=offile or test=ofprogram then stop = true
if test=comma then insert(',', false, p_spcomma) and result = true
if test=equals start
if ssalt=ownalt then inconst = p_lclist
! If in own or const declaration and p_lclist is set, then set
! inconst to true. The effect of this is leave the declaration
! unformatted. Inconst is not set earlier as we do not wish the
! leading spaces in the statement to be preserved - i.e. the first
! line of the statement is indented with the rest of the program.
insert('=', p_spacass, p_spacass)
result = true
finish
if p_expkey=true start
test = function if test=fn
test = constant if test=const
finish
if obp=1 or (outbuf(obp-1)&underline=0 and c
outbuf(obp-1)&127#'%') then key = false else key = true
! Current state of outbuf.
for i = 1, 1, clett(test) cycle
ch = clett(test+i)
if ch<underline and key=true start
outbuf(obp) = ' '
obp = obp+1
key = false
finish else if ch>underline start
if key=false start
if obp>1 and '('#outbuf(obp-1)#' ' then c
outbuf(obp) = ' ' and obp = obp+1
outbuf(obp) = '%'
obp = obp+1
key = true
finish else if i=1 and p_sepkey=true then c
outbuf(obp) = ' ' and outbuf(obp+1) = '%' and obp = obp+2
finish
if ch&underline#0 and p_uckey=false and ch#rs!128 then ch = ch!32
outbuf(obp) = ch
obp = obp+1
repeat
if (test=offile or test=ofprogram) and p_sepkey=true start
if test=offile then j = 4 else j = 7
obp = obp+2
outbuf(obp-i) = outbuf(obp-i-2) for i = 1, 1, j
outbuf(obp-j-2) = ' '
outbuf(obp-j-1) = '%'
finish
if test=if or test=unless or test=while or test=until or c
test=else or test=then then outbuf(obp-1) = ch!bpoint
if test=and or test=or then outbuf(obp-1) = ch!bpoint2
result = true
end
integer function check(integer pos)
integer defend, subdefend, subdefstart, res, item, rsptr, z,
strdelimiter, ch, rsobj, alt, i, j
constant string (19) fes="FINISH %ELSE %START"
own integer uci
own integer depth=0
switch bip(999:1039); ! Built-in phrases.
alt = 0
depth = depth+1; ! Depth of recursion in check.
ssalt = 0 if depth=1; ! Initialise ssalt if in top-level call.
rsptr = ptr; rsobj = obp
defend = symbol(pos)
pos = pos+1
while pos<defend cycle
alt = alt+1
if depth=1 start ; ! Outer level - i.e. trying ss alternatives.
ssalt = ssalt+1
inconst = false
finish
subdefend = symbol(pos)
pos = pos+1
res = true
subdefstart = pos
while pos<subdefend cycle
item = symbol(pos)
if 999<=item<1300 then ->bip(item)
if item<999 then res = compare(item)
if item>=1300 then res = check(item)
pos = pos+1
->bypass
bip(999):
pos = subdefstart; ! Star function.
rsptr = ptr; rsobj = obp
->bypass
bip(1000):
depth = depth-1; result = true; ! Zero function.
bip(1001):
! Name
ch = nextnonsp(inconst)
j = ptr; ptr = ptr+1; i = obp
if chartype(ch)&letter=0 then res = false and ->inc
if chartype(ch)&constart#0 and c
nextnonsp(inconst!p_spacnam)=squotes then res = false and ->inc
ptr = j; obp = i; ! AVOID FUNNY SPACING ON 1 LETTER NAMES
j = outbuf(obp-1); ! LAST CHAR OUT
if j>128 or chartype(j)&letter#0 or j=')' then c
outbuf(obp) = ' ' and obp = obp+1
while chartype(ch)&(letter!number)#0 cycle
if chartype(ch)&letter#0 and p_lcasnam=false start
! Letter case in names to be controlled by P_UCKEY.
if p_uckey=true then ch = ch&(¬32) else ch = ch!32
finish
outbuf(obp) = ch; obp = obp+1
j = obp; ! Position after latest character of name.
ptr = ptr+1
ch = nextnonsp(inconst!p_spacnam)
repeat
! Now j gives posn in outbuf after last character of name, and obp
! gives next free posn in outbuf.
if p_spacnam=true and inconst=false and j<obp start
! Throw away bytes after name, apart from curly comments.
i = j
cycle
i = i+1 while i<obp and outbuf(i)&127#'{'
exit if i=obp
if j<i start
outbuf(j) = ' '
cycle
j = j+1
outbuf(j) = outbuf(i)
i = i+1
repeat until outbuf(j)&127='}'
finish else start
j = j+1 until outbuf(j)&127='}'
i = j+1
finish
j = j+1
repeat
obp = j
finish
->inc
bip(1005):
! N - Number.
ch = nextnonsp(inconst)
if chartype(ch)&number=0 then res = false and ->inc
bip(1002):
! Iconst.
bip(1003):
! Const.
ch = nextnonsp(inconst)
ptr = ptr+1
res = false and ->inc unless c
chartype(ch)&(quotes!constfirst)#0 or c
(chartype(ch)&constart#0 and nextnonsp(inconst)=squotes)
if outbuf(obp-1)>128 or chartype(outbuf(obp-1))&letter#0 then c
outbuf(obp) = ' ' and obp = obp+1
if chartype(ch)&constfirst=0 start
if chartype(ch)&constart#0 start
outbuf(obp) = ch; obp = obp+1
strdelimiter = nextnonsp(inconst)
ptr = ptr+1
finish else strdelimiter = ch
outbuf(obp) = strdelimiter; obp = obp+1
cycle
if sc(ptr)=strdelimiter start
outbuf(obp) = strdelimiter!instring
if sc(ptr+1)#strdelimiter then exit
outbuf(obp+1) = strdelimiter!instring
obp = obp+2; ptr = ptr+2
finish else start
ch = sc(ptr)
outbuf(obp) = ch!instring
obp = obp+1; ptr = ptr+1
if ch=nl start
getline(ptr)
finish
finish
repeat
ptr = ptr+1; obp = obp+1
finish else start
ptr = ptr-1
cycle
cycle
exit if chartype(ch)&constcont=0
outbuf(obp) = ch; obp = obp+1
ptr = ptr+1
ch = nextnonsp(inconst)
repeat
if '_'#ch#'@' then exit
if ch='@' then j = number else j = number!letter
! Second part of @ and radix consts
until chartype(ch)&j=0 cycle
outbuf(obp) = ch; obp = obp+1
ptr = ptr+1
ch = nextnonsp(inconst)
repeat
repeat
finish
->inc
bip(1004):! Phrase check extended type
ch = nextnonsp(inconst)
res = false unless c
ch>underline and X'80000000'>>(ch&31)&X'20C83000'#0
->inc
bip(1038):! Include
bip(1006):! S - End statement.
ch = nextnonsp(inconst)
if chartype(ch)&endst=0 then res = false and ->inc
obp = obp-1 while obp>1 and outbuf(obp-1)=' '
outbuf(obp) = ch; obp = obp+1
->inc
bip(1007):! Text - comment string.
ch = nextnonsp(inconst)
if chartype(ch)&rem=0 then res = false and ->inc
if ch&underline#0 and (outbuf(obp-1)&underline=0) then c
outbuf(obp) = '%' and obp = obp+1
outbuf(obp) = ch; obp = obp+1
ptr = ptr+1
if ch='C'+underline start
outbuf(obp-1) = ch!32 if p_uckey=false
for i = 2, 1, 7 cycle
ch = nextnonsp(inconst)
if ch#keycom(i)+underline then res = false and ->inc
if p_uckey=false then ch = ch!32
outbuf(obp) = ch
obp = obp+1
ptr = ptr+1
repeat
finish
str = false
cycle
while sc(ptr)#nl and (str=true or sc(ptr)#';') cycle
ch = sc(ptr)
if ch=squotes or ch=dquotes start
if str=false then c
strdelimiter = ch and str = true else if c
ch=strdelimiter then str = false
finish
if ch&underline#0 and p_uckey=false and ch#rs!128 then c
ch = ch!32
outbuf(obp) = ch; obp = obp+1
ptr = ptr+1
repeat
outbuf(obp) = sc(ptr); obp = obp+1
ptr = ptr+1
exit if outbuf(obp-1)=nl
! Semi-colon terminated input - carry on reading.
getline(1)
repeat
str = false
->inc
bip(1009):! N255 - Test string declaration length.
ch = nextnonsp(inconst)
unless '0'<=ch<='9' then res = false and ->inc
z = 0
while '0'<=ch<='9' cycle
z = z*10+ch-'0'
outbuf(obp) = ch; obp = obp+1
ptr = ptr+1
ch = nextnonsp(inconst)
repeat
if z>255 then res = false
->inc
bip(1012):! Readline?
ch = nextnonsp(inconst)
! Deal with "FRED(1:10) = <nl> .. init vals .." constructions.
if ch=nl start
outbuf(obp) = nl; obp = obp+1
sc(ptr) = rs!128
getline(ptr+1)
finish
->inc
bip(1015):! Down.
level = level+1
bheading = true
if p_iblock=true then increm = true
->inc
bip(1016):! Up.
level = level-1
bheading = true
if p_iblock=true and in>0 then in = in-1
->inc
bip(1019):! Colon - Is previous character a colon ':'?
if sc(ptr-1)#':' then res = false and ->inc
if charsin>0 then outstring(snl)
ch = nextnonsp(inconst)
transfer(1, obp-1)
obp = 1
if p_seplab=true and ch#nl then outstring(snl)
inlabel = true
->inc
bip(1022):! Setnem.
ch = nextnonsp(inconst)
z = M' '
while chartype(ch)&letter#0 cycle
z = z<<8!onecase(ch)
outbuf(obp) = ch; obp = obp+1
ptr = ptr+1
ch = nextnonsp(inconst)
repeat
unless ch='_' and z#M' ' then res = false and ->inc
outbuf(obp) = '_'; obp = obp+1
uci = z
ptr = ptr+1
->inc
bip(1023):! Primform
for i = 7, 1, 127 cycle
->pfnd if opc(i)=uci
repeat
res = false
->inc
pfnd:! Mnemonic found
res = false if 8<=i>>3<=11 and i&7<=3
->inc
bip(1024):! Sectform.
for i = 64, 8, 88 cycle
for j = 0, 1, 3 cycle
if opc(i+j)=uci then ->inc
repeat
repeat
res = false
->inc
bip(1025):! Tertform.
for i = 3, -1, 1 cycle
if opc(i)=uci then ->inc
repeat
res = false
->inc
bip(1026):! Op.
ch = nextnonsp(inconst)
ptr = ptr+1
unless 32<ch<127 and X'80000000'>>(ch&31)&X'4237000A'#0 then c
res = false and ->inc
if ch='&' or ch='+' or ch='-' then c
insert(ch, p_spacop, p_spacop) and ->inc
if ch='*' start
if ch#nextnonsp(inconst) then c
insert('*', p_spacop, p_spacop) and ->inc
ptr = ptr+1; j = ptr
ch = nextnonsp(inconst)
ptr = ptr+1
if M'*'=ch=nextnonsp(inconst) then c
insert(M'****', p_spacop, p_spacop) and ptr = ptr+1 and ->inc
insert(M'**', p_spacop, p_spacop)
ptr = j; ->inc
finish
if ch='/' start
if ch#nextnonsp(inconst) then c
insert('/', p_spacop, p_spacop) and ->inc
insert(M'//', p_spacop, p_spacop)
ptr = ptr+1; ->inc
finish
if ch='!' start
if ch#nextnonsp(inconst) then c
insert('!', p_spacop, p_spacop) and ->inc
insert(M'!!', p_spacop, p_spacop)
ptr = ptr+1; ->inc
finish
if ch='.' then outbuf(obp) = '.' and obp = obp+1 and ->inc
if ch=nextnonsp(inconst)='>' start
insert(M'>>', p_spacop, p_spacop)
ptr = ptr+1
->inc
finish
if ch=nextnonsp(inconst)='<' start
insert(M'<<', p_spacop, p_spacop)
ptr = ptr+1
->inc
finish
if ch='¬' start
if ch#nextnonsp(inconst) then c
insert('¬', p_spacop, p_spacop) and ->inc
insert(M'¬¬', p_spacop, p_spacop)
ptr = ptr+1; ->inc
finish
res = false; ->inc
bip(1027):! Chui.
ch = nextnonsp(inconst)
if chartype(ch)&letter=0 and ch#'-' and c
X'80000000'>>(ch&31)&X'14043000'=0 then res = false
->inc
bip(1028):! +'.
ch = nextnonsp(inconst)
if ch='+' or ch='-' or ch='¬' or ch=X'7E' then c
insert(ch, p_spacop, p_spacop) and ptr = ptr+1
->inc
bip(1031):! Ucwrong (unknown user code format - allow it through).
cycle
ch = nextnonsp(inconst)
outbuf(obp) = ch; obp = obp+1
->inc if chartype(ch)&endst#0
ptr = ptr+1
repeat
bip(1030):! ,'.
ch = nextnonsp(inconst)
res = false if ch=')'
if res=true then insert(',', false, p_spcomma)
if ch=',' then ptr = ptr+1
->inc
bip(1032):! Chcomp.
bip(1037):! Comp2
ch = nextnonsp(inconst)
ptr = ptr+1
unless 32<ch<=92 and X'80000000'>>(ch&31)&X'1004000E'#0 then c
res = false and ->inc
if ch='=' start
if nextnonsp(inconst)=ch then c
ptr = ptr+1 and insert(M'==', p_spacop, p_spacop) and ->inc
insert('=', p_spacop, p_spacop)
->inc
finish
if ch='#' start
if nextnonsp(inconst)=ch then c
ptr = ptr+1 and insert(M'##', p_spacop, p_spacop) and ->inc
insert('#', p_spacop, p_spacop)
->inc
finish
if ch='¬' and nextnonsp(inconst)='=' start
ptr = ptr+1
if nextnonsp(inconst)='=' then c
ptr = ptr+1 and insert(M'==¬', p_spacop, p_spacop) and ->inc
insert(M'=¬', p_spacop, p_spacop)
->inc
finish
if ch='>' start
if nextnonsp(inconst)='=' then c
ptr = ptr+1 and insert(M'=>', p_spacop, p_spacop) and ->inc
insert('>', p_spacop, p_spacop)
->inc
finish
if ch='<' start
if nextnonsp(inconst)='=' then c
ptr = ptr+1 and insert(M'=<', p_spacop, p_spacop) and ->inc
if nextnonsp(inconst)='>' then c
ptr = ptr+1 and insert(M'><', p_spacop, p_spacop) and ->inc
insert('<', p_spacop, p_spacop)
->inc
finish
if ch='-' and nextnonsp(inconst)='>' then c
ptr = ptr+1 and insert(M'>-', p_spacop, p_spacop) and ->inc
res = false
->inc
bip(1033):! Assop.
ch = nextnonsp(inconst)
ptr = ptr+1
if ch='=' start
if nextnonsp(inconst)='=' then c
ptr = ptr+1 and insert(M'==', p_spacass, p_spacass) and ->inc
insert('=', p_spacass, p_spacass)
->inc
finish
if ch='<' and nextnonsp(inconst)='-' then c
ptr = ptr+1 and insert(M'-<', p_spacass, p_spacass) and ->inc
if ch='-' and nextnonsp(inconst)='>' then c
ptr = ptr+1 and insert(M'>-', p_spacass, p_spacass) and ->inc
res = false
bip(1008):! Bighole.
->inc
bip(1010):! Hole.
bip(1011):! Mark.
->inc
bip(1013):! Alias.
ch = nextnonsp(inconst)
ptr = ptr+1
if ch#'"' then res = false and ->inc
outbuf(obp) = ' '; obp = obp+1
outbuf(obp) = '"'; obp = obp+1
cycle
if sc(ptr)='"' start
outbuf(obp) = '"'!instring
if sc(ptr+1)#'"' then exit
outbuf(obp+1) = '"'!instring
obp = obp+2; ptr = ptr+2
finish else start
ch = sc(ptr)
outbuf(obp) = ch!instring
obp = obp+1; ptr = ptr+1
getline(ptr) if ch=nl
finish
repeat
ptr = ptr+1; obp = obp+1
->inc
bip(1014):! Dummyapp.
bip(1017):! Liston.
bip(1018):! List off.
bip(1020):! Note const.
bip(1021):! Trace.
->inc
bip(1039):! Dummy start
if p_expkey=true start ; ! Expand %else to %finish %else %start
obp = obp-4
for i = 1, 1, 19 cycle
j = charno(fes, i)
continue if p_sepkey=false and (j=' ' or j='%')
j = j!32 if p_uckey=false and 'A'<=j<='Z'
outbuf(obp) = j; obp = obp+1
repeat
finish
bip(1029):! Note cycle
bip(1034):! Note start
increm = true; ->inc
bip(1035):! Note finish
bip(1036):! Note repeat
if in>0 then in = in-1; ->inc
inc:
pos = pos+1
bypass:
if res=false start
pos = subdefend
obp = rsobj
if ptr>maxptr then maxptr = ptr and maxitem = item
ptr = rsptr
finish
repeat
if res=true then depth = depth-1 and result = true
repeat
ptr = rsptr; obp = rsobj
depth = depth-1
result = false
end
!***********************************************************************
!* *
!* Main calling routine. *
!* *
!***********************************************************************
opt(s, p); ! Call option setting routine to set parameters.
connect(infile, 0, 0, 0, rec, eflag); ! Open input file.
if eflag#0 then fail(eflag, 5)
if rec_filetype#charfile then setfname(infile) and fail(267, 5)
inptr = rec_conad+rec_datastart; ! Start of data.
dataend = rec_conad+rec_dataend; ! End of data.
! Set output stream, possibilities are:
! Terminal, file, same file or output device.
if outf=".OUT" then stream = terminal else start
if infile=outf then stream = samefile else start
if charno(outf, 1)='.' start
if devcode(outf)<=0 start
! Invalid output device.
setfname(outf)
fail(264, 5)
finish else stream = device
finish else stream = file
finish
finish
! Create tempory output file?
if stream=samefile or stream=device then workfile = "T#".nexttemp else c
workfile = outf
if stream#terminal start
filesizeptr = 1
filesize = fstable(filesizeptr)
outfile(workfile, filesize, 0, 0, conad, eflag)
if eflag#0 then fail(eflag, 5)
outrec == record(conad)
writeaddress = conad+outrec_datastart; wa0 = write address
outrec_filetype = charfile
! Rest of record elements to be fill in at end of indentation.
finish
outbuf(0) = 0; sc(0) = 0
level = 0; obp = 1; in = 0
inline = 1; line = 0 {output line}
errors = 0; erptr = 0; charsin = 0
str = false
stop = false; semicolon = false; increm = false; inlabel = false
ersave = false
if p_uckey=true then percentc = "%C" else percentc = "%c"
cycle
bheading = false
maxptr = 0
! Is there more to analyse in this statement.
colon = inlabel
if inlabel=false then getline(1) else inlabel = false
if check(ss)=false start
printstring(snl."Syntax analysis fails on input line ".itos(inline-1))
printstring(" (output line ".itos(line+1).")".snl)
z = 1
while chartype(sc(z))&endst=0 cycle
if sc(z)&127=rs then newline else printch(sc(z)&127)
z = z+1
repeat
if sc(z)=';' then printch(';')
newline
spaces(maxptr-1); printch('!'); newline
startline = startline+1 while byteinteger(startline)=' '
if stream#terminal start
obp = 1
! Line failed - Input line to output routine.
z = byteinteger(startline)
while chartype(z)&endst=0 cycle
if chartype(z)"es#0 start
strdelimiter = z
outbuf(obp) = strdelimiter; obp = obp+1
startline = startline+1
z = byteinteger(startline)
while z#strdelimiter cycle
outbuf(obp) = z
obp = obp+1; startline = startline+1
z = byteinteger(startline)
repeat
finish
outbuf(obp) = z
obp = obp+1; startline = startline+1
z = byteinteger(startline)
repeat
outbuf(obp) = z; obp = obp+1
punch
finish
str = false
errors = errors+1
finish else start
if inlabel=false then punch
finish
if stop=true start
if errors=0 then closedown(true) else closedown(false)
finish
repeat
! DOES NOT COME THROUGH HERE
routine fail(integer type, action)
if action#5 start
if action&2=0 then c
printstring(snl."*** Error: ") and errors = errors+1 else c
printstring(snl."*** Warning: ")
finish
if action&4=0 start
printstring(fault(type).snl)
printstring("*** In input line ".itos(inline)." (output line ".itos c
(line).")".snl)
finish else printstring("*** Soap80 fails -".failuremessage(type)) c
and stop
if action&1=1 then closedown(false)
end
routine opt(string (255) parm, record (pformat) name p)
!***********************************************************************
!* THIS ROUTINE PROCESSES THE USER OPTION LIST *
!***********************************************************************
routine spec readline
routine spec setline
integer function spec stoi(string name snum)
routine spec ask(integer optno)
integer i, j, temp, flag, prof vsn
string (80) line, option, value, filename
constant integer prog vsn= 3
switch prof(0:prog vsn)
external routine spec read profile(string (11) key, name info,
integer name version, uflag)
external routine spec write profile(string (11) key, name info,
integer name version, uflag)
read profile("Soap80key", p, prof vsn, flag)
if flag>4 start
printstring( c
"Failed to read file SS#PROFILE. Defaults options assumed.".snl)
finish
->prof(prof vsn)
! In the following profile-handling code, we work with array p_a
! (alternative format) rather than the actual option names (p_sepkey
! etc.). This is because the p_a operations remain valid even if the
! record format is subsequently changed.
prof(0):
! Code to set up profile vsn 1 data:
! This consists of 14 options followed by 21 tab values.
p_a(1) = 80; ! line - lines are broken into two if length is greater than 80.
p_a(2) = 3; ! icontin - continuation of line have an addition indentation of 3.
p_a(3) = 41; ! poscom - position for right hand comments.
p_a(4) = true; ! movecom - main comment are indented to POSCOM.
p_a(5) = true; ! uckey - keywords output in upper case.
p_a(6) = false; ! sepkey - adjacent keywords are compounded.
p_a(7) = true; ! lcasnam - case of names left alone.
p_a(8) = true; ! spacnam - spaces are left within names.
p_a(9) = true; ! spacass - spaces are added round assignment operators.
p_a(10) = false; ! spacop - spaces are not added round other operators.
p_a(11) = true; ! lclist - const lists to be left alone.
p_a(12) = true; ! iblock - block contents are indented w.r.t. block heading.
p_a(13) = false; ! istat - statements are aligned with declarations.
p_a(14) = false; ! seplab - Labels and statements may occupy the same line.
! Set default indentation values.
p_a(i+15) = 3*i for i = 0, 1, 10
p_a(i+15) = 5*i-20 for i = 11, 1, 20
prof(1):
! Code to set up profile vsn 2 data:
! This consists of 15 options followed by 21 tab values.
p_a(i) = p_a(i-1) for i = 36, -1, 16; ! Move tab values down to make room.
printstring("**New parameter available: SPCOMMA".snl)
printstring(" Y : One space character inserted after commas.".snl)
printstring( c
" N : No space character inserted after commas (default).".snl.snl)
p_a(15) = false; ! spcomma - default false.
prof(2):
! Code to set up profile vsn 3 data:
! This consists of 21 tab values followed by 16 options.
begin
byte integer array tab(0:20)
tab(i) = p_a(i+16) for i = 0, 1, 20; ! Copy tab values out.
p_a(i+21) = p_a(i) for i = 1, 1, 6; ! Move options down.
! Item _a(28) will be the new parameter (expkey).
p_a(i+22) = p_a(i) for i = 7, 1, 15; ! Move options down.
p_a(i+1) = tab(i) for i = 0, 1, 20; ! Copy tab values back.
end
printstring("**New parameter available: EXPKEY".snl)
printstring( c
" Y : Keywords %FN, %CONST and (sometimes) %ELSE expanded.".snl)
printstring(" N : %FN, %CONST and %ELSE left alone (default).". c
snl.snl)
p_a(28) = false; ! expkey default - false.
! The following two lines should always be just before the final 'prof'
! switch label.
prof vsn = prog vsn
write profile("Soap80key", p, prof vsn, flag)
prof(3):
! Split up parameters and change default values.
if parm->filename.(",").outf start
unless outf->outf.(",").parm then parm = ""
finish else filename = parm and outf = parm and parm = ""
infile = filename
if outf="" then outf = filename
if parm="" then return
temp = charno(parm, length(parm))
if temp#'*' and temp#'?' then parm = parm.",END"
prompt("Soap80: ")
cycle
if parm="" then readline else setline
if line="END" or line=".END" then return
! End of parameter settings.
if line="GO" or line=".GO" then return
! End of parameter settings.
if line="STOP" or line=".STOP" then stop ; ! Abandon Soap80.
if line="SAVE" or line=".SAVE" start
write profile("Soap80key", p, prof vsn, flag)
printstring("Profile file SS#PROFILE created and cherished.".snl) c
if flag=1
finish else if line="?" start
! Print options so far.
printstring( c
"Option name:{current setting}Meaning of current setting".snl)
for i = 1, 1, maxopt cycle
printstring(optname(i))
spaces(7-length(optname(i)))
printstring(":{")
j = p_optarr(i)
if j=false then printsymbol('N') else if j=true then c
printsymbol('Y') else printstring(itos(j))
j = 1 if j>0
printstring("}".optmess(j, i).snl)
repeat
printstring("TAB :{")
for i = 1, 1, 20 cycle
printstring(itos(p_tab(i)))
printsymbol(':') unless i=20
repeat
printsymbol('}')
newline
printstring(" Indenting values".snl)
printstring( c
"SAVE : Save current option settings, for defaults henceforth.
GO or END: Cause SOAP80 to start processing the input.
STOP : Cause SOAP80 to stop immediately.")
newline
finish else start
if line->option.("=").value and value#"" start
flag = 0
for i = 1, 1, maxopt cycle
continue unless option=optname(i)
flag = 1; ! Option identified.
if value="?" start
printstring(optname(i)); spaces(7-length(optname(i)))
printstring(":{")
j = p_optarr(i)
if j=false then printsymbol('N') else if c
j=true then printsymbol('Y') else printstring(itos(j))
j = 1 if j>0
printstring("}".optmess(j, i).snl)
finish else start
if i<=numopt start ; ! Numerical value.
temp = stoi(value)
if option="LINE" and (temp<30 or temp>160) start
printstring( c
"Bad line length - Only from 30 to 160".snl)
exit
finish
temp = -1 if temp>255
if temp=-1 then c
printstring(value." - ".failure message(320)) else c
p_optarr(i) = temp
finish else ask(i)
finish
exit
repeat
continue if flag=1; ! Cycle found option name.
if option="TAB" start
! Set indenting value.
if value="?" start
printstring("TAB :{")
for i = 1, 1, 20 cycle
printstring(itos(p_tab(i)))
printsymbol(':') unless i=20
repeat
printsymbol('}')
newline
printstring(" Indenting values".snl)
finish else start
i = 1
while i<=20 and value#"" cycle
temp = stoi(value)
if temp=-1 then c
printstring(value." - ".failuremessage(320)) and c
exit
p_tab(i) = temp
if length(value)=0 then i = i+1 and exit
if charno(value, 1)#':' start
printstring(value." - ".failuremessage(320))
i = 21
finish else value = substring(value, 2,
length(value))
i = i+1
repeat
! End of indenting value, make up the rest
for j = i, 1, 20 cycle
p_tab(j) = 2*p_tab(j-1)-p_tab(j-2)
if p_tab(j)>p_line then p_tab(j) = p_line
repeat
finish
continue
finish
printstring(option." - ".failuremessage(322))
! Keyword not recognised.
finish else start
printstring(line." - invalid: format should be
'keyword = value' or 'keyword = ?' or '?' or
'SAVE' or 'END' or 'GO' or 'STOP'".snl)
finish
finish
repeat
return
routine readline
!***********************************************************************
!* READLINE creates a line from the input device, converting all *
!* lower case characters to upper case. *
!***********************************************************************
integer ch
cycle
line = ""
cycle
readsymbol(ch); if ch=nl then exit
if ch=' ' then continue
! Convert lower to upper.
line = line.tostring(onecase(ch))
repeat
! Return only if the line has some thing on it.
if length(line)>0 then return
repeat
end
routine setline
!***********************************************************************
!* SETLINE breaks the parameter list into single commands. *
!************************************************************************
unless parm->line.(",").parm start
! Last command in parameter.
if charno(parm, length(parm))='*' then readline else line = parm
parm = ""
finish
end
routine ask(integer i)
!***********************************************************************
!* ASK checks that value starts with Y or N and *
!* assigns True or False accordingly to P_OPTARR(I). *
!***********************************************************************
integer s
s = charno(value, 1)
if s='Y' then p_optarr(i) = true else if s='N' then c
p_optarr(i) = false else printstring("Answer Yes or No or ?".snl)
end
integer function stoi(string name snum)
!***********************************************************************
!* STOI builts up an integer in INUM from the string SNUM, in *
!* doing so characters are deleted from this string. *
!* It is an error if the first character of the string is not a *
!* number. This is signalled by returning -1. *
!***********************************************************************
integer i, inum
unless '0'<=charno(snum, 1)<='9' then result = -1
i = 1; inum = 0
while '0'<=charno(snum, i)<='9' cycle
inum = inum*10+charno(snum, i)-'0'
i = i+1
if i>length(snum) then exit
repeat
if i>=length(snum) then snum = "" else c
snum = substring(snum, i, length(snum))
result = inum
end
end
end
end of file