diff options
author | Lars-Dominik Braun <lars@6xq.net> | 2019-02-04 13:09:03 +0100 |
---|---|---|
committer | Lars-Dominik Braun <lars@6xq.net> | 2019-02-04 13:09:03 +0100 |
commit | 04e68443040c7abad84d66477e98f93bed701760 (patch) | |
tree | 2b6202afae659e773bf6916157d23e83edfa44e3 /system/multiuser | |
download | eumel-src-04e68443040c7abad84d66477e98f93bed701760.tar.gz eumel-src-04e68443040c7abad84d66477e98f93bed701760.tar.bz2 eumel-src-04e68443040c7abad84d66477e98f93bed701760.zip |
Initial import
Diffstat (limited to 'system/multiuser')
26 files changed, 18671 insertions, 0 deletions
diff --git a/system/multiuser/1.7.5/source-disk b/system/multiuser/1.7.5/source-disk new file mode 100644 index 0000000..e24344a --- /dev/null +++ b/system/multiuser/1.7.5/source-disk @@ -0,0 +1,2 @@ +175_src/source-code-1.7.5m_0.img +175_src/source-code-1.7.5m_1.img diff --git a/system/multiuser/1.7.5/src/archive b/system/multiuser/1.7.5/src/archive new file mode 100644 index 0000000..8027b29 --- /dev/null +++ b/system/multiuser/1.7.5/src/archive @@ -0,0 +1,92 @@ +(* ------------------- VERSION 14 06.03.86 ------------------- *) +PACKET archive DEFINES + + archive , + clear , + release , + format , + check , + reserve : + + +LET clear code = 18 , + reserve code = 19 , + free code = 20 , + check read code = 22 , + format code = 23 ; + + +TASK PROC archive : + + task ("ARCHIVE") + +ENDPROC archive ; + +PROC archive (TEXT CONST archive name, TASK CONST task) : + + call (reserve code, archive name, task) + +ENDPROC archive ; + +PROC reserve (TEXT CONST message, TASK CONST task) : + + call (reserve code, message, task) + +END PROC reserve; + +PROC reserve (TASK CONST task) : + + call(reserve code, "", task) + +END PROC reserve; + +PROC archive (TEXT CONST archive name, INT CONST station) : + + call (reserve code, archive name, station/ "ARCHIVE") + +ENDPROC archive ; + +PROC archive (TEXT CONST archive name): + + call (reserve code, archive name, archive) + +ENDPROC archive ; + +PROC release (TASK CONST task) : + + call (free code, "", task) + +ENDPROC release ; + +PROC clear (TASK CONST task) : + + call (clear code, "", task) + +ENDPROC clear ; + +PROC format (TASK CONST task) : + + format (0, task) + +ENDPROC format ; + +PROC format (INT CONST code, TASK CONST task) : + + call (format code , text (code), task) + +ENDPROC format ; + +PROC check (TEXT CONST file name, TASK CONST task) : + + call (check read code, file name, task) + +ENDPROC check ; + +PROC check (THESAURUS CONST nameset, TASK CONST task) : + + do (PROC (TEXT CONST, TASK CONST) check, nameset, task) + +ENDPROC check ; + +ENDPACKET archive ; + diff --git a/system/multiuser/1.7.5/src/archive manager b/system/multiuser/1.7.5/src/archive manager new file mode 100644 index 0000000..c37d2e2 --- /dev/null +++ b/system/multiuser/1.7.5/src/archive manager @@ -0,0 +1,670 @@ +(* ------------------- VERSION 10 vom 17.04.86 ------------------- *) +PACKET archive manager DEFINES (* Autor: J.Liedtke*) + + archive manager , + provide channel : + + + +LET std archive channel = 31 , + + ack = 0 , + nak = 1 , + error nak = 2 , + second phase ack = 5 , + false code = 6 , + + fetch code = 11 , + save code = 12 , + exists code = 13 , + erase code = 14 , + list code = 15 , + all code = 17 , + clear code = 18 , + reserve code = 19 , + free code = 20 , + check read code = 22 , + format code = 23 , + + read error = 92 , + + max files = 200 , + + start of volume = 1000 , + end of volume = 1 , + file header = 3 , + + number of header blocks = 2 , + + quote = """" , + dummy name = "-" , + dummy date = " " , + + + HEADER = STRUCT (TEXT name, date, INT type, TEXT password) ; + + +BOUND STRUCT (TEXT name, pass) VAR msg ; + +INT VAR archive channel := std archive channel ; + +TASK VAR archive owner := niltask , + order task ; +TEXT VAR archive name := "" , write stamp ; + +REAL VAR last access time := 0.0 ; + +BOOL VAR was already write access ; + + +DATASPACE VAR header space := nilspace ; +BOUND HEADER VAR header ; + +TEXT VAR file name := "" ; + +LET invalid = 0 , + read only = 1 , + valid = 2 ; + +LET accept read errors = TRUE , + ignore read errors = FALSE ; + + +INT VAR directory state := invalid ; + +THESAURUS VAR directory ; +INT VAR dir index ; + +INT VAR archive size ; + +INT VAR end of volume block ; +ROW max files INT VAR header block ; +ROW max files TEXT VAR header date ; + + + +PROC provide channel (INT CONST channel) : + + archive channel := channel + +ENDPROC provide channel ; + +PROC archive manager : + + archive manager (archive channel) + +ENDPROC archive manager ; + +PROC archive manager (INT CONST channel) : + + archive channel := channel ; + task password ("-") ; + global manager + (PROC (DATASPACE VAR, INT CONST, INT CONST, TASK CONST) archive manager) + +ENDPROC archive manager ; + +PROC archive manager (DATASPACE VAR ds, INT CONST order, phase, + TASK CONST task) : + + + enable stop ; + order task := task ; + msg := ds ; + SELECT order OF + CASE fetch code : fetch file + CASE save code : save file + CASE exists code : exists file + CASE erase code : erase file + CASE list code : list (ds); manager ok (ds) + CASE all code : deliver directory + CASE clear code, + format code : clear or format + CASE reserve code : reserve + CASE free code : free + CASE check read code : check + OTHERWISE errorstop (name (myself) + ": unbekannter Auftrag") + ENDSELECT . + +deliver directory : + access archive ; + BOUND THESAURUS VAR all names := ds ; + all names := directory ; + WHILE all names CONTAINS dummy name REP + delete (all names, dummy name, dir index) + PER ; + manager ok (ds) . + +clear or format : + IF NOT (order task = archive owner) + THEN errorstop ("Archiv nicht angemeldet") + ELIF phase = 1 + THEN ask for erase all + ELSE directory state := invalid ; + IF order <> clear code + THEN format archive (specification) ; + archive size := archive blocks + FI ; + rewind ; + write header (archive name, text (clock(1),13,1), start of volume); + write end of volume ; + manager ok (ds) + FI . + +ask for erase all : + IF order = format code AND specification > 3 + THEN errorstop ("ungueltiger Format-Code") + FI ; + look at volume header ; + IF header.name <> "" + THEN IF order = clear code + THEN manager question ("Archiv """+header.name+""" loeschen", order task) + ELSE manager question ("Archiv """+header.name+""" formatieren", order task) + FI + ELSE IF order = clear code + THEN manager question ("Archiv initialisieren", order task) + ELSE manager question ("Archiv formatieren", order task) + FI + FI . + +specification : + int (msg.name) . + +reserve : + IF reserve or free permitted + THEN continue archive channel; + disable stop ; + directory state := invalid ; + archive owner := order task ; + archive name := msg.name ; + manager ok (ds) + ELSE errorstop ("Archiv wird von Task """+name(archive owner)+""" benutzt") + FI . + +continue archive channel : + continue channel (archive channel) . + +free : + IF reserve or free permitted + THEN archive owner := niltask ; + break (quiet) ; + manager ok (ds) + ELSE manager message ("Archiv nicht angemeldet", order task) + FI. + +reserve or free permitted : + order task = archive owner OR last access more than five minutes ago + OR archive owner = niltask OR NOT + (exists (archive owner) OR station (archive owner) <> station (myself)) . + +last access more than five minutes ago : + abs (last access time - clock (1)) > 300.0 . + +fetch file : + access archive ; + access file (msg.name) ; + IF no read error remarked + THEN disable stop ; + fetch (ds, accept read errors) ; + IF read error occurred + THEN remark read error + FI ; + enable stop + ELSE fetch (ds, ignore read errors) + FI ; + manager ok (ds) . + +no read error remarked : + pos (file name, " mit Lesefehler") = 0 . + +read error occurred : + is error AND error code = read error . + +remark read error : + dir index := link (directory, file name) ; + REP + file name CAT " mit Lesefehler" ; + UNTIL NOT (directory CONTAINS file name) PER ; + IF LENGTH file name < 100 + THEN rename (directory, dir index, file name) + FI . + +save file : + IF phase = 1 + THEN access archive ; + access file (msg.name) ; + IF file in directory + THEN manager question (""""+file name +""" ueberschreiben", order task) + ELSE send (order task, second phase ack, ds) + FI + ELSE access archive ; + access file (file name) ; + erase ; + save (ds) ; + forget (ds) ; + ds := nilspace ; + manager ok (ds) + FI . + +exists file : + access archive ; + access file (msg.name) ; + IF file in directory + THEN manager ok (ds) + ELSE send (order task, false code, ds) + FI . + +erase file : + access archive ; + access file (msg.name) ; + IF file in directory + THEN IF phase = 1 + THEN manager question (""""+file name+""" loeschen", order task) + ELSE erase ; manager ok (ds) + FI + ELSE manager message ("gibt es nicht", order task) + FI . + +check : + access archive ; + access file (msg.name) ; + IF file in directory + THEN position to file ; + disable stop ; + check read ; + IF is error + THEN clear error; error ("fehlerhaft") + ELSE last access time := clock (1) ; + manager message ("""" + file name + """ ohne Fehler gelesen", order task) + FI + ELSE error ("gibt es nicht") + FI . + +file in directory : dir index > 0 . + +position to file : + seek (header block (dir index) + number of header blocks) . + +ENDPROC archive manager ; + +PROC manager ok (DATASPACE VAR ds) : + + send (order task, ack, ds) ; + last access time := clock (1) . + +ENDPROC manager ok ; + +PROC access archive : + + IF NOT (order task = archive owner) + THEN errorstop ("Archiv nicht angemeldet") + ELIF directory state = invalid + THEN open archive + ELIF last access more than two seconds ago + THEN check volume name ; + new open if somebody changed medium + FI . + +last access more than two seconds ago : + abs (clock (1) - last access time) > 2.0 . + +new open if somebody changed medium : + IF header.date <> write stamp + THEN directory state := invalid ; + access archive + FI . + +open archive : + directory state := invalid ; + check volume name ; + write stamp := header.date ; + was already write access := FALSE ; + read directory ; + make directory valid if no read errors occurred . + +read directory : + directory := empty thesaurus ; + rewind ; + get next header ; + WHILE header.type = file header REP + IF directory CONTAINS header.name + THEN rename (directory, header.name, dummy name) + FI ; + insert (directory, header.name, dir index) ; + header block (dir index) := end of volume block ; + header date (dir index) := header.date ; + get next header ; + PER . + +make directory valid if no read errors occurred : + IF directory state = invalid + THEN directory state := valid + FI . + +ENDPROC access archive ; + +PROC access file (TEXT CONST name) : + + file name := name ; + dir index := link (directory, file name) . + +ENDPROC access file ; + + +PROC check volume name : + + disable stop ; + archive size := archive blocks ; + read volume header ; + IF header.type <> start of volume + THEN simulate header (start of volume, "?????") + ELIF header.name <> archive name + THEN errorstop ("Archiv heisst """ + header.name + """") + FI . + +read volume header : + rewind ; + read header ; + IF is error AND error code = read error + THEN clear error ; + simulate header (start of volume, "?????") + FI . + +ENDPROC check volume name ; + +PROC get next header : + + disable stop ; + skip dataspace ; + IF NOT is error + THEN read header + FI ; + IF is error + THEN clear error ; + directory state := read only ; + search header + FI ; + end of volume block := block number - number of header blocks . + +search header : + INT VAR ds pages ; + search dataspace (ds pages) ; + IF ds pages < 0 + THEN simulate header (end of volume, "") + ELIF NOT is header space + THEN simulate header (file header, "????? " + text (block number)) + FI . + +is header space : + IF ds pages <> 1 + THEN FALSE + ELSE remember position ; + read header ; + IF read error occurred + THEN clear error; back to old position; FALSE + ELIF header format looks ok + THEN TRUE + ELSE back to old position ; FALSE + FI + FI . + +read error occurred : + is error CAND error code = read error . + +header format looks ok : + header.type = file header OR header.type = end of volume . + +remember position : + INT CONST old block nr := block number . + +back to old position : + seek (old block nr) . + +ENDPROC get next header ; + +PROC fetch (DATASPACE VAR ds, BOOL CONST error accept): + + enable stop ; + IF file name <> dummy name + THEN fetch from archive + ELSE error ("Name unzulaessig") + FI . + +fetch from archive : + IF file in directory + THEN position to file ; + read (ds, 30000, error accept) + ELIF directory state = read only + THEN error ("gibt es nicht (oder Lesefehler)") + ELSE error ("gibt es nicht") + FI . + +position to file : + seek (header block (dir index) + number of header blocks) . + +file in directory : dir index > 0 . + +ENDPROC fetch ; + +PROC erase : + + IF directory state = read only + THEN errorstop ("'save'/'erase' wegen Lesefehler verboten") + ELSE update write stamp if first write access ; + erase archive + FI . + +update write stamp if first write access : + IF NOT was already write access + THEN rewind ; + write stamp := text (clock (1), 13, 1) ; + write header (archive name, write stamp, start of volume) ; + was already write access := TRUE + FI . + +erase archive : + IF file in directory + THEN IF is last file of archive + THEN cut off all erased files + ELSE rename to dummy + FI + FI . + +file in directory : dir index > 0 . + +is last file of archive : dir index = highest entry (directory) . + +cut off all erased files : + directory state := invalid ; + REP + delete (directory, dir index) ; + dir index DECR 1 + UNTIL dir index = 0 COR name (directory, dir index) <> dummy name PER ; + behind last valid file ; + write end of volume ; + directory state := valid . + +behind last valid file : + seek (header block (dir index + 1)) ; + end of volume block := block number . + +rename to dummy : + directory state := invalid ; + to file header ; + read header ; + to file header ; + header.name := dummy name ; + header.date := dummy date ; + write (header space) ; + rename (directory, file name, dummy name) ; + header date (dir index) := dummy date ; + directory state := valid . + +to file header : + seek (header block (dir index)) . + +ENDPROC erase ; + +PROC save (DATASPACE VAR ds) : + + IF file name <> dummy name + THEN save to archive + ELSE error ("Name unzulaessig") + FI . + +save to archive : + IF file too large OR highest entry (directory) >= max files + THEN error ( "kann nicht geschrieben werden (Archiv voll)") + ELSE write new file + FI . + +file too large : + end of volume block + ds pages (ds) + 5 > archive size . + +write new file : + seek (end of volume block) ; + disable stop ; + write file (ds) ; + IF is error + THEN seek (end of volume block) + ELSE insert (directory, file name, dir index) ; + remember begin of header block ; + remember date + FI ; + write end of volume . + +remember begin of header block : + header block (dir index) := end of volume block . + +remember date : + header date (dir index) := date . + +ENDPROC save ; + +PROC write file (DATASPACE CONST ds) : + + enable stop ; + write header (file name, date, file header) ; + write (ds) + +ENDPROC write file ; + +PROC write end of volume : + + disable stop ; + end of volume block := block number ; + write header ("", "", end of volume) + +ENDPROC write end of volume ; + +PROC write header (TEXT CONST name, date, INT CONST header type) : + + forget (header space) ; + header space := nilspace ; + header := header space ; + + header.name := subtext (name,1,100) ; + header.date := date ; + header.type := header type ; + + write (header space) + +ENDPROC write header ; + +PROC read header : + + IF archive size > 0 + THEN forget (header space) ; + header space := nilspace ; + read (header space, 1, accept read errors) ; + header := header space + ELSE errorstop ("Lesen unmoeglich (Archiv)") + FI . + +ENDPROC read header ; + +PROC simulate header (INT CONST type, TEXT CONST name) : + + forget (header space) ; + header space := nilspace ; + header := header space ; + header.name := name ; + header.date := "??.??.??" ; + header.type := type ; + header.password := "" + +ENDPROC simulate header ; + +PROC look at volume header : + + rewind ; + archive size := archive blocks ; + forget (header space) ; + header space := nilspace ; + INT VAR return code ; + read block (header space, 1, 1, return code) ; + header := header space ; + disable stop ; + IF return code <> 0 OR + LENGTH header.name < 0 OR LENGTH header.name > 100 OR is error + THEN header.name := "" ; + clear error + FI + +ENDPROC look at volume header ; + +PROC list (DATASPACE VAR ds) : + + access archive ; + open list file ; + INT VAR file number := 0 ; + get (directory, file name, file number) ; + WHILE file number > 0 REP + generate list line ; + get (directory, file name, file number) + PER ; + IF directory state = read only + THEN putline (list file, "Lesefehler: Evtl. fehlen Eintraege") + FI ; + write list head . + +open list file : + forget (ds) ; + ds := nilspace ; + FILE VAR list file := sequential file (output, ds) ; + putline (list file, "") . + +generate list line : + write (list file, header date (file number)) ; + write (list file, text (file blocks DIV 2, 5)) ; + write (list file, " K ") ; + IF file name = dummy name + THEN write (list file, dummy name) + ELSE write (list file, quote) ; + write (list file, file name) ; + write (list file, quote) + FI ; + line (list file) . + +file blocks : + IF file number < highest entry (directory) + THEN header block (file number+1) - header block (file number) + ELSE end of volume block - header block (file number) + FI . + +write list head : (* wk 22.08.85 *) + headline (list file, archive name + + " (" + used + " K belegt von " + text (archive size DIV 2) + " K)") . + +used : text ((end of volume block + 3) DIV 2) . + +ENDPROC list ; + +PROC error (TEXT CONST error msg) : + + errorstop ("""" + file name + """ " + error msg) + +ENDPROC error ; + +ENDPACKET archive manager ; + diff --git a/system/multiuser/1.7.5/src/basic archive b/system/multiuser/1.7.5/src/basic archive new file mode 100644 index 0000000..8235607 --- /dev/null +++ b/system/multiuser/1.7.5/src/basic archive @@ -0,0 +1,401 @@ +(* ------------------- VERSION 11 06.03.86 ------------------- *) +PACKET basic archive DEFINES + + archive blocks , + block number , + check read , + format archive , + read block , + read , + rewind , + search dataspace , + seek , + size , + skip dataspace , + write block , + write : + +INT VAR blocknr := 0 , + rerun := 0 , + page := -1 , + bit word := 1 , + unreadable sequence length := 0 ; +INT CONST all ones :=-1 ; + + +DATASPACE VAR label ds ; + +LET write normal = 0 , + archive version = 1 , + first page stored = 2 , + dr size = 3 , + first bit word = 4 , +(* write deleted data mark = 64 , *) + inconsistent = 90 , + read error = 92 , + label size = 131 ; + +BOUND STRUCT (ALIGN dummy for page1, + (* Page 2 begins: *) + ROW label size INT lab) VAR label; + + +INT PROC block number : + block nr +ENDPROC block number ; + +PROC seek (INT CONST block) : + block nr := block +ENDPROC seek ; + +PROC rewind : + forget (label ds); + label ds := nilspace; + label := label ds; + block nr := 0; + rerun := session +END PROC rewind; + +PROC skip dataspace: + check rerun; + get label; + IF is error + THEN + ELIF olivetti + THEN block nr INCR label.lab (dr size+1) + ELSE block nr INCR label.lab (dr size) + FI +END PROC skip dataspace; + +PROC read (DATASPACE VAR ds): + read (ds, 30000, FALSE) +ENDPROC read ; + +PROC read (DATASPACE VAR ds, INT CONST max pages, BOOL CONST error accept) : + enable stop ; + check rerun; + get label; + init next page; + INT VAR i ; + FOR i FROM 1 UPTO max pages REP + next page; + IF no further page THEN LEAVE read FI; + check storage ; + check rerun ; + read block ; + block nr INCR 1; + PER . + +read block : + disable stop ; + get external block (ds, page, block nr) ; + ignore read error if no errors accepted ; + enable stop . + +ignore read error if no errors accepted : + IF is error CAND error code = read error CAND NOT error accept + THEN clear error + FI . + +check storage : + INT VAR size, used ; + storage (size, used) ; + IF used > size + THEN forget (ds) ; + ds := nilspace ; + errorstop ("Speicherengpass") ; + LEAVE read + FI . + +check rerun : + IF rerun <> session + THEN errorstop ("RERUN beim Archiv-Zugriff") ; + LEAVE read + FI . + +END PROC read; + +PROC check read : + + enable stop ; + get label ; + INT VAR pages, i; + IF olivetti + THEN pages := label.lab (dr size+1) + ELSE pages := label.lab (dr size) + FI ; + FOR i FROM 1 UPTO pages REP + get external block (label ds, 2, block nr) ; + block nr INCR 1 + PER . + +ENDPROC check read ; + +PROC write (DATASPACE CONST ds): + enable stop ; + check rerun; + INT VAR label block nr := block nr; + block nr INCR 1;init label; + INT VAR page := -1,i; + FOR i FROM 1 UPTO ds pages (ds) REP + check rerun ; + page := next ds page(ds,page); + put external block (ds, page, block nr) ; + reset archive bit; + label.lab(dr size) INCR 1; + block nr INCR 1 + PER; + put label. + + + init label: + label.lab(archive version) := 0 ; + label.lab(first page stored) := 0 ; + label.lab(dr size) := 0; + INT VAR j; + FOR j FROM first bit word UPTO label size REP + label.lab (j) := all ones + PER. + + put label: + put external block (label ds, 2, label block nr). + + reset archive bit: + reset bit (label.lab (page DIV 16+first bit word), page MOD 16). + +END PROC write; + +PROC get label: + + enable stop ; + get external block (label ds, 2, block nr) ; + block nr INCR 1; + check label. + +check label: + IF may be z80 format label OR may be old olivetti format label + THEN + ELSE errorstop (inconsistent, "Archiv inkonsistent") + FI. + +may be z80 format label : + z80 archive AND label.lab(dr size) > 0 . + +may be old olivetti format label : + olivetti AND label.lab(first page stored)=0 AND label.lab(dr size+1) > 0 . + +END PROC get label; + +PROC next page: + IF z80 archive + THEN + WHILE labelbits = all ones REP + bitword INCR 1; + IF bitword >= label size THEN + no further page := true; LEAVE next page FI + PER; + INT VAR p := lowest reset (labelbits); + set bit (labelbits, p); + page := 16*(bitword-first bit word)+p + ELSE + WHILE oli bits = 0 REP + bitword INCR 1; + IF bitword >= labelsize-64 THEN + no further page := true; LEAVE next page FI + PER; + p := lowest set (oli bits); + reset bit (olibits, p); + page := 16*(bitword-firstbitword)+p; + FI. + + label bits : label.lab (bitword). + oli bits : label.lab (bitword+1). + +END PROC next page; +. +olivetti : label.lab (archive version) = -1. + +z80 archive : label.lab (archive version) = 0. + +init next page: + BOOL VAR no further page := false; + bitword := first bit word. + +check rerun : + IF rerun <> session + THEN errorstop ("RERUN beim Archiv-Zugriff") + FI . + +PROC get external block (DATASPACE VAR ds, INT CONST page, + INT CONST block nr): + + INT VAR error ; + read block (ds, page, block nr, error) ; + SELECT error OF + CASE 0: read succeeded + CASE 1: error stop ("Lesen unmoeglich (Archiv)") + CASE 2: read failed + CASE 3: error stop ("Archiv-Ueberlauf") + OTHERWISE error stop ("??? (Archiv)") + END SELECT . + +read succeeded : + unreadable sequence length := 0 . + +read failed : + unreadable sequence length INCR 1 ; + IF unreadable sequence length >= 30 + THEN errorstop ("30 unlesbare Bloecke hintereinander") + ELSE error stop (read error, "Lesefehler (Archiv)") + FI . + +END PROC get external block; + +PROC put external block (DATASPACE CONST ds, INT CONST page, + INT CONST block nr): + INT VAR error; + write block (ds, page, write normal, block nr, error) ; + SELECT error OF + CASE 0: + CASE 1: error stop ("Schreiben unmoeglich (Archiv)") + CASE 2: error stop ("Schreibfehler (Archiv)") + CASE 3: error stop ("Archiv-Ueberlauf") + OTHERWISE error stop ("??? (Archiv)") + END SELECT . + +END PROC put external block; + +PROC read block (DATASPACE VAR ds, + INT CONST ds page no, + INT CONST block no, + INT VAR return code) : + read block; + retry if read error. + +read block: + block in (ds, ds page no, 0, block no, return code). + +retry if read error: + INT VAR retry; + FOR retry FROM 1 UPTO 10 WHILE return code = 2 REP + reset to block 0 if fifth try; + read block + PER. + +reset to block 0 if fifth try: + IF retry = 5 + THEN block in (ds, ds page no, 0, 0, return code) + FI. + +END PROC read block; + +PROC write block (DATASPACE CONST ds, + INT CONST ds page no, + INT CONST mode, + INT CONST block no, + INT VAR return code): + write block; + retry if write error. + +write block: + block out (ds, ds page no, mode * 256, block no, return code) . + +retry if write error: + INT VAR retry; + FOR retry FROM 1 UPTO 10 WHILE return code = 2 REP + reset to block 0 if fifth try; + write block + PER. + +reset to block 0 if fifth try: + IF retry = 5 + THEN disable stop; + DATASPACE VAR dummy ds := nilspace; + block in (dummy ds, 2, 0, 0, return code); + forget (dummy ds); + enable stop + FI. + +END PROC write block; + +INT PROC size (INT CONST key) : + + INT VAR return code ; + control (5, key, 0, return code) ; + return code . + +ENDPROC size ; + +INT PROC archive blocks : + size (0) +ENDPROC archive blocks ; + +PROC search dataspace (INT VAR ds pages) : + + disable stop ; + ds pages := -1 ; + INT CONST last block := archive blocks ; + + WHILE block nr < last block REP + IF block is dataspace label + THEN ds pages := pages counted ; + LEAVE search dataspace + FI ; + block nr INCR 1 + UNTIL is error PER . + +block is dataspace label : + look at label block ; + IF is error + THEN IF error code = read error OR error code = inconsistent + THEN clear error + FI ; + FALSE + ELSE count pages ; + pages counted = number of pages as label says + FI . + +look at label block : + INT CONST + old block nr := block nr ; + get label ; + block nr := old block nr. + +count pages : + INT VAR + pages counted := 0 ; + init next page ; + next page ; + WHILE NOT no further page REP + pages counted INCR 1 ; + next page + PER . + +number of pages as label says : label.lab (dr size) . + +ENDPROC search dataspace ; + +PROC format archive (INT CONST format code) : + + IF format is possible + THEN format + ELSE errorstop ("'format' ist hier nicht implementiert") + FI . + +format is possible : + INT VAR return code ; + control (1,0,0, return code) ; + bit (return code, 4) . + +format : + control (7, format code, 0, return code) ; + IF return code = 1 + THEN errorstop ("Formatieren unmoeglich") + ELIF return code > 1 + THEN errorstop ("Schreibfehler (Archiv)") + FI . + +ENDPROC format archive ; + +END PACKET basic archive; + diff --git a/system/multiuser/1.7.5/src/canal b/system/multiuser/1.7.5/src/canal new file mode 100644 index 0000000..ad0baa8 --- /dev/null +++ b/system/multiuser/1.7.5/src/canal @@ -0,0 +1,227 @@ +(* ------------------- VERSION 6 20.05.86 ------------------- *) +PACKET canal DEFINES (* Autor: J.Liedtke *) + + analyze supervisor command : + + + +LET command list = + +"begin:1.12end:3.0break:4.0continue:5.01halt:7.0 +taskinfo:8.0storageinfo:9.0help:10.0 ", + + supervisor command text = + +""6""20""1"ESC ? --> help +"6""21""1"ESC b --> begin ("""") +"6""22""1"ESC c --> continue ("""") +"6""23""1"ESC q --> break +"6""21""50"ESC h --> halt +"6""22""50"ESC s --> storage info +"6""23""50"ESC t --> task info +"6""8""6"gib supervisor kommando :" , + + text type = 4 , + ack = 0 , + error nak = 2 , + begin code = 4 , + end code = 5 , + break code = 6 , + halt code = 8 , + password code = 9 , + continue code = 100 , + + home = ""1"" ; + + +TASK VAR sv ; + +DATASPACE VAR ds ; + +BOUND STRUCT (TEXT tname, tpass, TASK task, PROCA start proc) VAR sv msg ; +BOUND TEXT VAR error msg ; + +INT VAR command index , number of params , reply ; +TEXT VAR param 1, param 2 , task password ; + + + lernsequenz auf taste legen ("b", ""1""8""1""12"begin ("""")"8""8""11"") ; + lernsequenz auf taste legen ("c", ""1""8""1""12"continue ("""")"8""8""11"") ; + lernsequenz auf taste legen ("q", ""1""8""1""12"break"13"") ; + lernsequenz auf taste legen ("h", ""1""8""1""12"halt"13"") ; + lernsequenz auf taste legen ("s", ""1""8""1""12"storage info"13"") ; + lernsequenz auf taste legen ("t", ""1""8""1""12"task info"13"") ; + lernsequenz auf taste legen ("?", ""1""8""1""12"help"13"") ; + +PROC analyze supervisor command : + + disable stop ; + sv := supervisor ; + ds := nilspace ; + REP + command dialogue (TRUE) ; + command pre ; + cry if not enough storage ; + get command (supervisor command text) ; + analyze command (command list, text type, + command index, number of params, + param1, param2) ; + execute command ; + PER . + +command pre : + IF NOT is error + THEN wait for terminal; eumel must advertise + ELSE forget (ds) ; ds := nilspace + FI . + +wait for terminal : + out (home) . + +cry if not enough storage : + INT VAR size, used ; + storage (size, used) ; + IF used > size + THEN out (""7"Speicher Engpass!"13""10"") ; + FI . + +ENDPROC analyze supervisor command ; + +PROC execute command : + + enable stop ; + SELECT command index OF + CASE 1 : begin ("PUBLIC") + CASE 2 : begin (param2) + CASE 3 : end via canal + CASE 4 : break + CASE 5 : quiet + CASE 6 : continue (param1) + CASE 7 : halt + CASE 8 : task info (0); eumel must advertise; quiet + CASE 9 : storage info; quiet + CASE 10 : help; eumel must advertise; quiet + OTHERWISE analyze command error + ENDSELECT ; + IF reply = error nak + THEN error msg := ds ; + errorstop (CONCR (error msg)) + FI . + +end via canal : + IF yes ("Task """ + name (task (channel (myself))) + """ loeschen") + THEN eumel must advertise ; + call (sv, end code, ds, reply) + FI . + +break : + eumel must advertise ; + call (sv, break code, ds, reply) . + +halt : + call (sv, halt code, ds, reply) . + +quiet : + call (sv, ack, ds, reply) . + +analyze command error : + command error ; + IF command index = 0 + THEN errorstop ("kein supervisor kommando") + ELIF number of params = 0 + THEN errorstop ("Taskname fehlt") + ELSE errorstop ("Parameter ueberfluessig") + FI . + +ENDPROC execute command ; + +PROC begin (TEXT CONST father name) : + + IF param1 = "-" + THEN errorstop ("Name ungueltig") + FI ; + sv msg := ds ; + CONCR (sv msg).tname := param1 ; + CONCR (sv msg).tpass := "" ; + call (task (father name), begin code, ds, reply) ; + IF reply = password code + THEN get password ; + sv msg := ds ; + CONCR (sv msg).tpass := task password ; + call (task (father name), begin code, ds, reply) + FI ; + IF reply = ack + THEN continue (param1) + FI . + +get password : + put (" Passwort:") ; + get secret line (task password) . + +ENDPROC begin ; + +PROC continue (TEXT CONST task name) : + + sv msg := ds ; + CONCR (sv msg).tname := task name ; + CONCR (sv msg).tpass := "" ; + call (sv, continue code + channel, ds, reply) ; + IF reply = password code + THEN get password ; + sv msg := ds ; + CONCR (sv msg).tpass := task password ; + call (sv, continue code + channel, ds, reply) + FI . + +get password : + put (" Passwort:") ; + get secret line (task password) . + +ENDPROC continue ; + +PROC help: + + LET page = ""1""4"" + ,bell = ""7"" + ,cr = ""13"" + ,end mark = ""14"" + ,begin mark = ""15"" + ,esc = ""27"" + ; + + REP + out (page) ; + show page ; + UNTIL is quit command PER . + + show page : + putline(begin mark + (31 * ".") + " supervisor help " + (31 * ".") + end mark) ; + putline("Hier finden Sie einige Kommandos, die Ihnen den Einstieg ins System er -") ; + putline("leichtern sollen:") ; + out(""6""05""07"1. Informations-Kommandos") ; + out(""6""07""11"storage info physisch belegten Hintergrundplatz melden") ; + out(""6""08""11"task info Taskbaum zeigen") ; + out(""6""14""07"2. Verbindung zum Supervisor") ; + out(""6""16""11"break Task vom Terminal abkoppeln") ; + out(""6""17""11"begin(""task"") neue Task `task` einrichten") ; + out(""6""18""11"continue(""task"") Task `task` an ein Terminal ankoppeln") ; + out(""6""21""01"Näheres: Benutzerhandbuch, Teil 2, Kap. 2") ; + out(""6""23""05"Wenn Sie den Hilfe-Modus beenden wollen, tippen Sie die Taste `q`. ") ; + out(cr) . + + is quit command : + TEXT VAR char ; + get char (char) ; + IF char = esc + THEN get char (char) + FI; + IF char = "q" COR char = "Q" + THEN true + ELSE out (bell); + FALSE + FI. + +END PROC help ; + +ENDPACKET canal ; + diff --git a/system/multiuser/1.7.5/src/configuration manager b/system/multiuser/1.7.5/src/configuration manager new file mode 100644 index 0000000..5eaea52 --- /dev/null +++ b/system/multiuser/1.7.5/src/configuration manager @@ -0,0 +1,553 @@ +(* ------------------- VERSION 11 02.06.86 ------------------- *) +PACKET configuration manager DEFINES + + configurate , + exec configuration , + setup , + define collector , + configuration manager : + + +LET baudrates = ""1"50"2"75"3"110"4"134.5"5"150"6"300"7"600 +"8"1200"9"1800"10"2400"11"3600"12"4800"13"7200 +"14"9600"15"19200"16"38400"17"", + parities = ""0"no"1"odd"2"even"3"" , + bits per char = ""0"1"1"2"2"3"3"4"4"5"5"6"6"7"7"8"8"" , + stopbits = ""0"1"1"1.5"2"2"3"" , + flow modes = ""0"ohne Protokoll"1"XON/XOFF"2"RTS/CTS +"3""4""5"XON/XOFF - ausgabeseitig"6"RTS/CTS - ausgabeseitig"7""8" +"9"XON/XOFF - eingabeseitig"10"RTS/CTS - eingabeseitig"11"" , + + ok = "j" , + esc = ""27"" , + cr = ""13"" , + right = ""2"" , + + psi = "psi" , + transparent = "transparent" , + + std rate = 14 , + std bits = 22 , + std flow = 0 , + std inbuffer size = 16 , + + device table = 32000 , + + max edit terminal = 15 , + configuration channel = 32 , + + fetch code = 11 , + save code = 12 , + erase code = 14 , + system start interrupt = 100 , + + CONF = STRUCT (TEXT dev type, + INT baud, bits par stop, flow control, inbuffer size) ; + + +BOUND STRUCT (TEXT name, write pass, read pass) VAR msg ; + +BOUND ROW max edit terminal CONF VAR conf ; + +INT VAR channel no ; + +TEXT VAR prelude , last feature , answer , collector := "" ; + + + +BOOL PROC shard permits (INT CONST code, key) : + + INT VAR reply ; + IF key > -128 + THEN control (code, channel no, key, reply) + ELSE control (code, channel no, -maxint-1, reply) + FI ; + reply = 0 . + +ENDPROC shard permits ; + +PROC ask user (TEXT CONST feature, question) : + + last feature := feature ; + put question ; + skip pretyped chars ; + get valid answer . + +put question : + clear line ; + out (prelude) ; + out (feature) ; + out (question) ; + out (" (j/n) ") . + +clear line : + out (cr) ; + 79 TIMESOUT " " ; + out (cr) . + +skip pretyped chars : + REP UNTIL incharety = "" PER . + +get valid answer : + REP + inchar (answer) + UNTIL pos ("jJyYnN"27"", answer) > 0 PER ; + IF answer > ""31"" + THEN out (answer) + FI ; + out (cr) ; + normalize answer . + +normalize answer : + IF pos ("jJyY", answer) > 0 + THEN answer := ok + FI . + +ENDPROC ask user ; + +BOOL PROC yes (TEXT CONST question) : + + ask user ("", question) ; + answer = ok + +ENDPROC yes ; + +PROC chose key (INT VAR old key, INT CONST max key, TEXT CONST key string, + key entity, BOOL PROC (INT CONST) shard permits): + + IF shard permits at least one standard key + THEN try all keys + FI . + +shard permits at least one standard key : + INT VAR key ; + FOR key FROM 0 UPTO max key REP + IF shard permits (key) + THEN LEAVE shard permits at least one standard key WITH TRUE + FI + PER ; + FALSE . + +try all keys : + key := old key ; + REP + examine this key ; + next key + PER . + +examine this key : + IF shard permits (key) CAND key value <> "" + THEN ask user (key value, key entity) ; + IF answer = ok + THEN chose this key + ELIF answer = esc + THEN key := -129 + FI + FI . + +key value : + IF key >= 0 + THEN subtext (key string, key pos + 1, next key pos - 1) + ELSE text (key) + FI . + +key pos : pos (key string, code (key)) . +next key pos : pos (key string, code (key+1)) . + +chose this key : + remember calibration ; + old key := key ; + LEAVE chose key . + +next key : + IF key < max key + THEN key INCR 1 + ELSE key := 0 + FI . + +remember calibration : + prelude CAT last feature ; + prelude CAT ", " . + +ENDPROC chose key ; + +BOOL PROC rate ok (INT CONST key) : + + shard permits (8, key) + +ENDPROC rate ok ; + +BOOL PROC bits ok (INT CONST key) : + + IF key < 0 + THEN shard permits (9, key) + ELSE some standard combination ok + FI . + +some standard combination ok : + INT VAR combined := key ; + REP + IF shard permits (9, combined) + THEN LEAVE bits ok WITH TRUE + FI ; + combined INCR 8 + UNTIL combined > 127 PER ; + FALSE + +ENDPROC bits ok ; + +BOOL PROC parity ok (INT CONST key) : + + INT VAR combined := 8 * key + data bits ; + key >= 0 AND (shard permits (9, combined) OR + shard permits (9, combined + 32) OR + shard permits (9, combined + 64) ) + +ENDPROC parity ok ; + +BOOL PROC stopbits ok (INT CONST key) : + + key >= 0 AND shard permits (9, 32 * key + 8 * parity + data bits) + +ENDPROC stopbits ok ; + +BOOL PROC flow mode ok (INT CONST key) : + + shard permits (6, key) + +ENDPROC flow mode ok ; + + + +INT VAR data bits , + parity , + stop ; + +INT VAR old session := 0 ; + + +TEXT VAR table name, dummy ; + + +PROC configurate : + + new configuration ; + access configuration table ; + show all device types ; + channel no := 1 ; + REP + IF channel hardware exists + THEN try this channel ; + setup this channel + FI ; + channel no INCR 1 + UNTIL channel no > 15 PER ; + prelude := "" ; + IF yes ("Koennen unbenutzte Geraetetypen geloescht werden") + THEN forget unused device tables + FI . + +access configuration table : + IF exists ("configuration") + THEN conf := old ("configuration") + ELSE conf := new ("configuration") ; + initialize configuration + FI . + +initialize configuration : + FOR channel no FROM 1 UPTO max edit terminal REP + conf (channel no) := + CONF:(transparent, std rate, std bits, std flow, std inbuffer size) + PER ; + conf (1).dev type := psi . + +show all device types : + show prelude ; + begin list ; + get list entry (table name, dummy) ; + WHILE table name <> "" REP + IF dataspace is device table + THEN show table name + FI ; + get list entry (table name, dummy) + PER ; + line (2) . + +show prelude : + line (30) ; + outtext (psi, 1, 20) ; + outtext (transparent, 1, 20) . + +dataspace is device table : + type (old (table name)) = device table . + +show table name : + outtext (table name, 1, 20) . + +try this channel : + prelude := "Kanal " ; + ask user ("", text (channel no)) ; + IF answer = ok + THEN prelude CAT text (channel no) + ": " ; + get configuration from user (conf (channel no)) ; + line + FI . + +channel hardware exists : + INT VAR + operators channel := channel ; + INT VAR channel type ; + disable stop ; + continue (channel no) ; + IF is error + THEN IF error message = "kein Kanal" + THEN channel type := 0 + ELSE channel type := inout mask + FI + ELSE get channel type from shard + FI ; + clear error ; + disable stop ; + continue operators channel ; + (channel type AND inout mask) <> 0 . + +get channel type from shard : + control (1, 0, 0, channel type) . + +inout mask : 3 . + +forget unused device tables : + begin list ; + get list entry (table name, dummy) ; + WHILE table name <> "" REP + IF type (old (table name)) = device table + THEN forget if unused + FI ; + get list entry (table name, dummy) + PER . + +forget if unused : + FOR channel no FROM 1 UPTO max edit terminal REP + IF conf (channel no).dev type = table name + THEN LEAVE forget if unused + FI + PER ; + forget (table name, quiet) . + +setup this channel : + operators channel := channel ; + disable stop ; + continue (configuration channel) ; + set up channel (channel no, conf (channel no)) ; + continue operators channel . + +continue operators channel : + continue (operators channel) ; + IF is error + THEN clear error ; + break (quiet) ; + LEAVE configurate + FI ; + enable stop . + +ENDPROC configurate ; + +PROC get configuration from user (CONF VAR conf) : + + get device type ; + get baud rate ; + get bits and parity and stopbits ; + get protocol ; + get buffer size . + + +get device type : + begin list ; + table name := conf.dev type ; + IF NOT is valid device type + THEN next device type + FI ; + REP + IF NOT (table name = transparent AND channel no = 1) + THEN ask user ("", table name) ; + IF answer = ok COR was esc followed by type table name + THEN IF is valid device type + THEN remember device type ; + LEAVE get device type + ELSE out (""7" unbekannter Typ"); pause (20) + FI + FI + FI ; + next device type + PER . + +was esc followed by type table name : + IF answer = esc + THEN 9 TIMESOUT right ; + put ("Typ:") ; + editget (table name) ; + TRUE + ELSE FALSE + FI . + +is valid device type : + table name = psi OR table name = transparent OR + (exists (table name) CAND type (old (table name)) = device table) . + +remember device type : + prelude CAT table name ; + conf.dev type := table name ; + prelude CAT ", " . + +next device type : + IF table name = psi + THEN table name := transparent + ELSE IF table name = transparent + THEN begin list + FI ; + search next device type space + FI . + +search next device type space : + REP + get list entry (table name, dummy) + UNTIL table name = "" COR type (old (table name)) = device table PER; + IF table name = "" + THEN table name := psi + FI . + +get baud rate : + chose key (conf.baud, 16, baudrates, " Baud", PROC rate ok) . + +get bits and parity and stopbits : + data bits := conf.bits par stop MOD 8 ; + parity := (conf.bits par stop DIV 8) MOD 4 ; + stop := (conf.bits par stop DIV 32) MOD 4 ; + chose key (data bits, 7, bits per char, " Bits", PROC bits ok) ; + IF data bits >= 0 + THEN chose key (parity, 2, parities, " parity", PROC parity ok) ; + chose key (stop, 2, stopbits, " Stopbits", PROC stopbits ok); + conf.bits par stop := data bits + 8 * parity + 32 * stop + ELSE conf.bits par stop := data bits + FI . + +get protocol : + chose key (conf.flow control, 10, flow modes, + "", PROC flow mode ok) . + +get buffer size : + IF dev type is transparent + THEN chose buffer size + ELSE conf.inbuffer size := std inbuffer size + FI . + +dev type is transparent : + conf.dev type = "transparent" . + +chose buffer size : + REP + IF conf.inbuffer size = 16 CAND yes ("normaler Puffer") + THEN LEAVE chose buffer size + FI ; + conf.inbuffer size := 512 ; + IF yes ("grosser Puffer") + THEN LEAVE chose buffer size + FI ; + conf.inbuffer size := 16 + PER . + +ENDPROC get configuration from user ; + +PROC exec configuration : + + setup + +ENDPROC exec configuration ; + +PROC setup : + + conf := old ("configuration") ; + continue (configuration channel) ; + FOR channel no FROM 1 UPTO max edit terminal REP + set up channel (channel no, conf (channel no)) + PER ; + set up collector task ; + break but do not forget error message if any . + +set up collector task : + IF collector <> "" CAND collector <> "-" CAND exists task (collector) + THEN define collector (task (collector)) + FI . + +break but do not forget error message if any : + IF is error + THEN dummy := error message ; + clear error ; + break (quiet) ; + errorstop (dummy) + ELSE break (quiet) + FI . + +ENDPROC set up ; + +PROC set up channel (INT CONST channel no, CONF CONST conf) : + + link (channel no, conf.dev type) ; + baudrate (channel no, conf.baud) ; + bits (channel no, conf.bits par stop) ; + flow (channel no, conf.flow control) ; + input buffer size (channel no, conf.inbuffer size) . + +ENDPROC setup channel ; + +PROC configuration manager (DATASPACE VAR ds, INT CONST order, phase, + TASK CONST order task) : + + enable stop ; + IF order <> system start interrupt + THEN font manager + FI ; + IF session <> old session + THEN disable stop ; + set up ; + clear error ; + old session := session ; + set autonom + FI . + + font manager : + IF (order <> save code AND order <> erase code ) OR order task < supervisor + THEN delete password if there is one; + free manager (ds, order, phase, order task) + ELSE errorstop ("kein Zugriffsrecht auf Task """ + name (myself) + """") + FI . + + delete password if there is one : + IF order >= fetch code AND order <= erase code AND phase = 1 + THEN msg := ds; + msg. write pass := ""; + msg. read pass := ""; + FI . + +ENDPROC configuration manager ; + +PROC configuration manager : + + configurate ; + break ; + global manager + (PROC (DATASPACE VAR,INT CONST,INT CONST,TASK CONST) configuration manager) + +ENDPROC configuration manager ; + +PROC define collector (TEXT CONST task table name) : + + collector := task table name ; + IF exists task (collector) + THEN define collector (task (collector)) + FI + +ENDPROC define collector ; + +ENDPACKET configuration manager ; + diff --git a/system/multiuser/1.7.5/src/eumel printer b/system/multiuser/1.7.5/src/eumel printer new file mode 100644 index 0000000..94858b5 --- /dev/null +++ b/system/multiuser/1.7.5/src/eumel printer @@ -0,0 +1,3066 @@ +PACKET eumel printer (* Autor : Rudolf Ruland *) + (* Version : 4 *) + (* Stand : 05.05.86 *) + DEFINES print, + with elan listings, + is elan source, + bottom label for elan listings, + x pos, + y pos, + y offset index, + line type, + material, + pages printed : + + +LET std x wanted = 2.54, + std y wanted = 2.35, + std limit = 16.0, + std pagelength = 25.0, + std linefeed faktor = 1.0, + std material = ""; + +LET blank = " ", + blank code 1 = 33, + geschuetztes blank = ""223"", + keine blankanalyse = 0, + einfach blank = 1, + doppel blank = 2, + + anweisungszeichen = "#", + anweisungszeichen code 1 = 36, + geschuetztes anweisungszeichen = ""222"", + druckerkommando zeichen = "/", + quote = """", + + erweiterungs ausgang = 32767, + blank ausgang = 32766, + anweisungs ausgang = 32765, + d code ausgang = 32764, + max breite = 32763, + + punkt = ".", + + leer = 0, + + kommando token = 0, + text token = 1, + + underline linetype = 1, + underline bit = 0, + bold bit = 1, + italics bit = 2, + modifikations liste = "ubir", + anzahl modifikationen = 4, + + document = 1, + page = 2, + + write text = 1, + write cmd = 2, + carriage return = 3, + move = 4, + draw = 5, + on = 6, + off = 7, + type = 8, + + tag type = 1, + bold type = 2, + number type = 3, + text type = 4, + delimiter type = 6, + eof type = 7; + + +INT CONST null ausgang := -32767-1; + +ROW anzahl modifikationen INT CONST modifikations werte := + ROW anzahl modifikationen INT : (1, 2, 4, 8); + +TEXT CONST anweisungsliste := + "type:1.1on:2.1off:3.1center:4.0right:5.0u:6.0d:7.0e:8.0b:9.0" + + "fillchar:10.1mark:11.2markend:12.0" + + "ub:13.0ue:14.0fb:15.0fe:16.0" + + "block:20.0columns:21.2columnsend:22.0free:23.1limit:24.1linefeed:25.1" + + "material:26.1page:27.01pagelength:29.1start:30.2" + + "table:31.0tableend:32.0clearpos:33.01" + + "lpos:35.1rpos:36.1cpos:37.1dpos:38.2bpos:39.2" + + "textbegin:40.02textend:42.0" + + "indentation:43.1ytab:44.1"; + +LET a type = 1, a block = 20, + a on = 2, a columns = 21, + a off = 3, a columnsend = 22, + a center = 4, a free = 23, + a right = 5, a limit = 24, + a up = 6, a linefeed = 25, + a down = 7, a material = 26, + a end up or down = 8, a page0 = 27, + a bsp = 9, a page1 = 28, + a fill char = 10, a pagelength = 29, + a mark = 11, a start = 30, + a markend = 12, a table = 31, + a ub = 13, a tableend = 32, + a ue = 14, a clearpos0 = 33, + a fb = 15, a clearpos1 = 34, + a fe = 16, a lpos = 35, + a rpos = 36, + a cpos = 37, + a dpos = 38, + a bpos = 39, + a textbegin0 = 40, + a textbegin2 = 41, + a textend = 42, + a indentation = 43, + a y tab = 44; + +INT VAR a xpos, a breite, a font, a modifikationen, + a modifikationen fuer x move, a ypos, aktuelle ypos, + letzter font, letzte modifikationen, + d ypos, d xpos, d font, d modifikationen, + + zeilenpos, alte zeilenpos, zeilen laenge, anzahl zeichen, ausgang, + anzahl einrueck blanks, blankbreite, + einrueckbreite, aktuelle einrueckbreite, alte einrueckbreite, + font durchschuss, fonthoehe, font tiefe, + groesste fonthoehe, aktuelle zeilenhoehe, letzte zeilenhoehe, + blankmodus, alter blankmodus, + token zeiger, erstes token der zeile, + + erstes tab token, tab anfang, anzahl blanks, + d code 1, d pitch, fuell zeichen breite, erstes fuell token, + letztes fuell token, + + x size, y size, x wanted, y wanted, x start, y start, + pagelength, limit, indentation, + left margin, top margin, seitenlaenge, + papierlaenge, papierbreite, + luecke, anzahl spalten, aktuelle spalte, + + verschiebung, rest, neue modifikationen, modifikations modus, pass, + + int param, anweisungs index, anzahl params, index, + + gedruckte seiten; + +BOOL VAR zeile ist absatzzeile, letzte zeile war absatzzeile, + zeile muss geblockt werden, rechts, a block token, offsets, + tabellen modus, block modus, center modus, right modus, + seite ist offen, vor erster seite; + +REAL VAR linefeed faktor, real param; + +TEXT VAR zeile, anweisung, par1, par2, material wert, replacements, + fuell zeichen, d string, font offsets; + +ROW 256 INT VAR zeichenbreiten, replacement tabelle, zeichen zaehler; + +INITFLAG VAR in dieser task := FALSE; + +. zeile ist zu ende : zeilenpos > zeilen laenge + +. zeilen breite : a xpos - left margin + +. neue zeilenhoehe : int (linefeed faktor * real (fonthoehe) + 0.5) + +. naechstes zeichen ist blank : pos (zeile, blank, zeilenpos + 1, zeilenpos + 1) <> 0 + +. naechstes nicht blankes zeichen : pos (zeile, ""33"", ""255"", zeilenpos) + +. in letzter spalte : aktuelle spalte >= anzahl spalten + +. anfangs blankmodus : + INT VAR dummy; + IF center modus OR right modus + THEN dummy + ELIF index zaehler = 0 + THEN blankmodus + ELSE alter blankmodus + FI + +. initialisiere tab variablen : + erstes tab token := token index f + 1; + tab anfang := zeilen breite; + anzahl blanks := 0; +.; + +(******************************************************************) + +LET zeilen nr laenge = 4, + teil einrueckung = 5, + + headline pre = "Zeile **** E L A N EUMEL 1.7.5 **** ", + headline post = " **** "; + +INT VAR zeilen nr, rest auf seite, + max zeichen zeile, max zeichen fuss, layout laenge, layout laenge name, + symbol type, naechster symbol type; + +BOOL VAR vor erstem packet, innerhalb der define liste; + +TEXT VAR bottom label, dateiname, layout blanks, refinement layout zeile; + + +. symbol : fuell zeichen +. naechstes symbol : d string +. elan text : d token. text +.; + +(******************************************************************) +(*** tokenspeicher ***) + +LET max token = 3000, + max ypos = 1000, + + TOKEN = STRUCT (TEXT text, + INT xpos, breite, font, modifikationen, + modifikationen fuer x move, + offset index, naechster token index, + BOOL block token ), + + YPOS = STRUCT (INT ypos, vorheriger ypos index, naechster ypos index, + erster token index, letzter token index ), + + TOKENLISTE = STRUCT (ROW max token TOKEN token liste, + ROW max ypos YPOS ypos liste ); + +DATASPACE VAR ds; + +BOUND TOKENLISTE VAR tokenspeicher; + +TOKEN VAR d token, offset token; + +INT VAR erster ypos index a, letzter ypos index a, + erster ypos index d, letzter ypos index d, + ypos index, ypos index f, ypos index a, ypos index d, + token index, token index f; + +. t : tokenspeicher. token liste (token index) +. tf : tokenspeicher. token liste (token index f) + +. y : tokenspeicher. ypos liste (ypos index) +. yf : tokenspeicher. ypos liste (ypos index f) +. ya : tokenspeicher. ypos liste (ypos index a) +. yd : tokenspeicher. ypos liste (ypos index d) + +. loesche druckspeicher : + erster ypos index d := 0; + ypos index f := 0; + token index f := 0; + +. druckspeicher ist nicht leer : + erster ypos index d <> 0 + +. loesche analysespeicher : + erster ypos index a := 0; + +. analysespeicher ist nicht leer : + erster ypos index a <> 0 +.; + +(******************************************************************) +(*** anweisungsspeicher ***) + +INT VAR anweisungszaehler; +TEXT VAR anweisungs indizes, params1 zeiger, params2 zeiger; +THESAURUS VAR params1, params2; + +PROC loesche anweisungsspeicher : + + anweisungs zaehler := 0; + anweisungs indizes := ""; + params1 zeiger := ""; + params2 zeiger := ""; + params1 := empty thesaurus; + params2 := empty thesaurus; + +END PROC loesche anweisungsspeicher; + +(******************************************************************) +(*** indexspeicher ***) + +INT VAR index zaehler; +TEXT VAR grosse fonts, verschiebungen; + +PROC loesche indexspeicher : + + index zaehler := 0; + grosse fonts := ""; + verschiebungen := ""; + +END PROC loesche indexspeicher; + + +(******************************************************************) +(*** tabellenspeicher ***) + +LET max tabs = 30, + TABELLENEINTRAG = STRUCT (INT tab typ, tab position, tab param); + +TEXT VAR tab liste, fill char; +THESAURUS VAR d strings; +ROW max tabs TABELLENEINTRAG VAR tabspeicher; + +INT VAR tab index; + +. tab typ : tab speicher (tab liste ISUB tab index). tab typ +. tab position : tab speicher (tab liste ISUB tab index). tab position +. tab param : tab speicher (tab liste ISUB tab index). tab param +. anzahl tabs : LENGTH tab liste DIV 2 +.; + +PROC loesche tabellenspeicher : + + fill char := " "; + tabliste := ""; + d strings := empty thesaurus; + FOR tab index FROM 1 UPTO max tabs + REP tab speicher (tab index). tab typ := leer PER; + +END PROC loesche tabellenspeicher; + +(******************************************************************) +(*** markierungsspeicher ***) + +INT VAR mark index l, mark index r, alter mark index l, alter mark index r; + +ROW 4 TOKEN VAR mark token; + +. markierung links : mark index l > 0 +. markierung rechts : mark index r > 0 +.; + +PROC loesche markierung : + + mark index l := 0; + mark index r := 0; + +END PROC loesche markierung; + + +PROC loesche alte markierung : + + alter mark index l := 0; + alter mark index r := 0; + +END PROC loesche alte markierung; + + +PROC initialisiere markierung : + + FOR mark index l FROM 1 UPTO 4 + REP mark token (mark index l). modifikationen fuer x move := 0; + mark token (mark index l). offset index := text token; + mark token (mark index l). block token := FALSE; + mark token (mark index l). naechster token index := 0; + PER; + +END PROC initialisiere markierung; + +(******************************************************************) +(*** durchschuss ***) + +INT VAR durchschuss 1, durchschuss 2, anzahl durchschuss 1, + anzahl durchschuss, zeilen zaehler; + +BOOL VAR wechsel := TRUE; + +INT PROC durchschuss : + + zeilen zaehler INCR 1; + IF zeilen zaehler <= anzahl durchschuss 1 + THEN durchschuss 1 + ELIF zeilen zaehler <= anzahl durchschuss + THEN durchschuss 2 + ELSE 0 + FI + +END PROC durchschuss; + + +PROC neuer durchschuss (INT CONST anzahl, rest) : + + zeilen zaehler := 0; + anzahl durchschuss := anzahl; + IF anzahl > 0 + THEN IF wechsel + THEN durchschuss 1 := rest DIV anzahl durchschuss; + durchschuss 2 := durchschuss 1 + sign (rest); + anzahl durchschuss 1 := anzahl durchschuss - + abs (rest) MOD anzahl durchschuss; + wechsel := FALSE; + ELSE durchschuss 2 := rest DIV anzahl durchschuss; + durchschuss 1 := durchschuss 2 + sign (rest); + anzahl durchschuss 1 := abs (rest) MOD anzahl durchschuss; + wechsel := TRUE; + FI; + ELSE loesche durchschuss + FI; + +END PROC neuer durchschuss; + + +PROC loesche durchschuss : + + durchschuss 1 := 0; + durchschuss 2 := 0; + anzahl durchschuss 1 := 0; + anzahl durchschuss := 0; + zeilen zaehler := 0; + +END PROC loesche durchschuss; + +(****************************************************************) + +PROC initialisierung : + + forget (ds); + ds := nilspace; tokenspeicher := ds; + loesche druckspeicher; + loesche anweisungsspeicher; + loesche indexspeicher; + initialisiere markierung; + right modus := FALSE; + center modus := FALSE; + seite ist offen := FALSE; + pass := 0; + a breite := 0; + a block token := FALSE; + a modifikationen fuer x move := 0; + d code 1 := leer; + erstes fuell token := leer; + IF two bytes + THEN FOR index FROM 1 UPTO 129 REP zeichen zaehler (index) := 1 PER; + FOR index FROM 130 UPTO 160 REP zeichen zaehler (index) := - maxint PER; + FOR index FROM 161 UPTO 224 REP zeichen zaehler (index) := 1 PER; + FOR index FROM 225 UPTO 240 REP zeichen zaehler (index) := - maxint PER; + FOR index FROM 241 UPTO 256 REP zeichen zaehler (index) := 1 PER; + ELSE FOR index FROM 1 UPTO 256 REP zeichen zaehler (index) := 1 PER; + FI; + +END PROC initialisierung; + +(****************************************************************) +(*** print - Kommando ***) + +BOOL VAR elan listings erlaubt; +FILE VAR eingabe; + +with elan listings (TRUE); + +PROC with elan listings (BOOL CONST flag) : + elan listings erlaubt := flag; +END PROC with elan listings; + +BOOL PROC with elan listings : elan listings erlaubt END PROC with elan listings; + + +PROC print (PROC (TEXT VAR) next line, BOOL PROC eof, + PROC (INT CONST, INT VAR, INT VAR) open, + PROC (INT CONST, INT CONST) close, + PROC (INT CONST, TEXT CONST, INT CONST, INT CONST) execute ): + + print (PROC (TEXT VAR) lese zeile, BOOL PROC eof, + PROC (INT CONST, INT VAR, INT VAR) open, + PROC (INT CONST, INT CONST) close, + PROC (INT CONST, TEXT CONST, INT CONST, INT CONST) execute, + FALSE, ""); + +END PROC print; + + +PROC print (FILE VAR file, + PROC (INT CONST, INT VAR, INT VAR) open, + PROC (INT CONST, INT CONST) close, + PROC (INT CONST, TEXT CONST, INT CONST, INT CONST) execute) : + + eingabe := file; + input (eingabe); + print (PROC (TEXT VAR) lese zeile, BOOL PROC eof, + PROC (INT CONST, INT VAR, INT VAR) open, + PROC (INT CONST, INT CONST) close, + PROC (INT CONST, TEXT CONST, INT CONST, INT CONST) execute, + elan listings erlaubt CAND is elan source (eingabe), + headline (eingabe) ); + +END PROC print; + +PROC lese zeile (TEXT VAR zeile) : getline (eingabe, zeile) END PROC lese zeile; + +BOOL PROC eof : eof (eingabe) END PROC eof; + +BOOL PROC is elan source (FILE VAR eingabe) : + +hole erstes symbol; +elan programm tag COR elan programm bold COR kommentar + +. elan programm tag : + symbol type = tag type CAND pos (zeile, ";") > 0 + +. elan programm bold : + symbol type = bold type CAND is elan bold + + . is elan bold : + symbol = "PACKET" COR symbol = "LET" + COR proc oder op (symbol) COR deklaration + + . deklaration : + next symbol (symbol); + symbol = "VAR" OR symbol = "CONST" + +. kommentar : + pos (zeile, "(*") > 0 OR pos (zeile, "{") > 0 + +. + hole erstes symbol : + hole erstes nicht blankes symbol; + scan (zeile); + next symbol (symbol, symbol type); + + . hole erstes nicht blankes symbol : + IF eof (eingabe) THEN LEAVE is elan source WITH FALSE FI; + REP getline (eingabe, zeile); + UNTIL pos (zeile, ""33"",""254"", 1) > 0 OR eof (eingabe) PER; + reset (eingabe); + +END PROC is elan source; + +(****************************************************************) + +bottom label for elan listings (""); + +PROC bottom label for elan listings (TEXT CONST label) : + bottom label := label; +END PROC bottom label for elan listings; + +TEXT PROC bottom label for elan listings : bottom label END PROC bottom label for elan listings; + + +PROC print (PROC (TEXT VAR) next line, BOOL PROC eof, + PROC (INT CONST, INT VAR, INT VAR) open, + PROC (INT CONST, INT CONST) close, + PROC (INT CONST, TEXT CONST, INT CONST, INT CONST) execute, + BOOL CONST elan listing, TEXT CONST file name) : + +disable stop; +gedruckte seiten := 0; +drucke datei (PROC (TEXT VAR) next line, BOOL PROC eof, + PROC (INT CONST, INT VAR, INT VAR) open, + PROC (INT CONST, INT CONST) close, + PROC (INT CONST, TEXT CONST, INT CONST, INT CONST) execute, + elan listing, file name ); +IF is error THEN behandle fehlermeldung FI; + +. behandle fehlermeldung : + par1 := error message; + int param := error line; + clear error; + IF NOT vor erster seite + THEN IF seite ist offen + THEN schliesse seite ab (PROC (INT CONST, INT CONST) close, + PROC (INT CONST, TEXT CONST, INT CONST, INT CONST) execute ) + FI; + clear error; + close (document, 0); + clear error; + FI; + initialisierung; + errorstop (par1 (* + " -> " + text (int param) *) ); + +END PROC print; + +INT PROC x pos : d xpos END PROC x pos; +INT PROC y pos : d ypos END PROC y pos; +INT PROC y offset index : d token. offset index END PROC y offset index; +INT PROC linetype : underline linetype END PROC linetype; +TEXT PROC material : material wert END PROC material; +INT PROC pages printed : gedruckte seiten END PROC pages printed; + +(****************************************************************) + +PROC drucke datei (PROC (TEXT VAR) next line, BOOL PROC eof, + PROC (INT CONST, INT VAR, INT VAR) open, + PROC (INT CONST, INT CONST) close, + PROC (INT CONST, TEXT CONST, INT CONST, INT CONST) execute, + BOOL CONST elan listing, TEXT CONST file name ) : + + +enable stop; +IF elan listing + THEN dateiname := file name; + drucke elan listing; + ELSE drucke text datei; +FI; + +. + drucke text datei : + initialisiere druck; + WHILE NOT eof + REP next line (zeile); + analysiere zeile; + drucke token soweit wie moeglich; + werte anweisungsspeicher aus; + PER; + schliesse druck ab; + +. + initialisiere druck : + IF NOT initialized (in dieser task) + THEN ds := nilspace; + initialisierung + FI; + vor erster seite := TRUE; + tabellen modus := FALSE; + block modus := FALSE; + zeile ist absatzzeile := TRUE; + x wanted := x step conversion (std x wanted); + y wanted := y step conversion (std y wanted); + limit := x step conversion (std limit); + pagelength := y step conversion (std pagelength); + linefeed faktor := std linefeed faktor; + material wert := std material; + indentation := 0; + modifikations modus := maxint; + seitenlaenge := maxint; + papierlaenge := maxint; + left margin := 0; + top margin := 0; + a ypos := top margin; + a font := -1; + a modifikationen := 0; + aktuelle spalte := 1; + anzahl spalten := 1; + stelle neuen font ein (1); + loesche tabellenspeicher; + loesche markierung; + loesche alte markierung; + loesche durchschuss; + +. + schliesse druck ab : + IF NOT vor erster seite + THEN IF seite ist offen + THEN schliesse seite ab (PROC (INT CONST, INT CONST) close, + PROC (INT CONST, TEXT CONST, INT CONST, INT CONST) execute ) + FI; + close (document, 0); + FI; + +. + drucke token soweit wie moeglich : + IF analysespeicher ist nicht leer + THEN letztes token bei gleicher ypos; + IF NOT seite ist offen + THEN eroeffne seite (x wanted, y wanted, + PROC (INT CONST, INT VAR, INT VAR) open); + FI; + gehe zur letzten neuen ypos; + IF seitenlaenge ueberschritten OR papierlaenge ueberschritten + THEN neue seite oder spalte; + analysiere zeile nochmal; + ELSE sortiere neue token ein; + IF in letzter spalte + THEN drucke tokenspeicher (a ypos, + PROC (INT CONST, TEXT CONST, INT CONST, INT CONST) execute); + FI; + FI; + FI; + + . gehe zur letzten neuen ypos : + ypos index a := letzter ypos index a + + . seitenlaenge ueberschritten : + ya. ypos > seitenlaenge + + . papierlaenge ueberschritten : + ya. ypos > papierlaenge + + . neue seite oder spalte : + IF in letzter spalte + THEN schliesse seite ab (PROC (INT CONST, INT CONST) close, + PROC (INT CONST, TEXT CONST, INT CONST, INT CONST) execute); + eroeffne seite (x wanted, aktuelles y wanted, + PROC (INT CONST, INT VAR, INT VAR) open); + ELSE neue spalte; + FI; + + . aktuelles y wanted : + IF seitenlaenge ueberschritten + THEN y wanted + ELSE 0 + FI + + . analysiere zeile nochmal : + setze auf alte werte zurueck; + loesche anweisungsspeicher; + analysiere zeile; + letztes token bei gleicher ypos; + sortiere neue token ein; + + . setze auf alte werte zurueck : + zeile ist absatzzeile := letzte zeile war absatzzeile; + a modifikationen := letzte modifikationen; + stelle neuen font ein (letzter font); + +. + werte anweisungsspeicher aus : + INT VAR index; + FOR index FROM 1 UPTO anweisungszaehler + REP + SELECT anweisungs indizes ISUB index OF + CASE a block : block anweisung + CASE a columns : columns anweisung + CASE a columnsend : columnsend anweisung + CASE a free : free anweisung + CASE a limit : limit anweisung + CASE a linefeed : linefeed anweisung + CASE a material : material anweisung + CASE a page0, a page1 : page anweisung + CASE a pagelength : pagelength anweisung + CASE a start : start anweisung + CASE a table : table anweisung + CASE a tableend : tableend anweisung + CASE a clearpos0 : clearpos0 anweisung + CASE a clearpos1 : clearpos1 anweisung + CASE a lpos, a rpos, a cpos, a dpos + : lpos rpos cpos dpos anweisung + CASE a bpos : bpos anweisung + CASE a fillchar : fillchar anweisung + CASE a textbegin0 : textbegin0 anweisung + CASE a textbegin2 : textbegin2 anweisung + CASE a textend : textend anweisung + CASE a indentation : indentation anweisung + CASE a y tab : y tab anweisung + END SELECT + PER; + loesche anweisungsspeicher; + + . block anweisung : + blockmodus := TRUE; + + . columns anweisung : + IF anzahl spalten = 1 AND int conversion ok (param1) + AND real conversion ok (param2) + THEN anzahl spalten := max (1, int param); + luecke := x step conversion (real param); + FI; + + . columnsend anweisung : + anzahl spalten := 1; + aktuelle spalte := 1; + left margin := x wanted - x start + indentation; + + . free anweisung : + IF real conversion ok (param1) THEN a ypos INCR y step conversion (real param) FI; + + . limit anweisung : + IF real conversion ok (param1) THEN limit := x step conversion (real param) FI; + + . linefeed anweisung : + IF real conversion ok (param1) + THEN linefeed faktor := real param; + letzte zeilenhoehe := neue zeilenhoehe; + FI; + + . material anweisung : + material wert := param1; + + . page anweisung : + IF seite ist offen + THEN IF NOT in letzter spalte + THEN neue spalte + ELSE schliesse seite ab (PROC (INT CONST, INT CONST) close, + PROC (INT CONST, TEXT CONST, INT CONST, INT CONST) execute); + papier laenge := maxint; + FI; + ELSE a ypos := top margin; + papier laenge := maxint; + FI; + + . pagelength anweisung : + IF real conversion ok (param1) + THEN pagelength := y step conversion (real param); + FI; + + . start anweisung : + IF real conversion ok (param1) THEN x wanted := x step conversion (real param) FI; + IF real conversion ok (param2) THEN y wanted := y step conversion (real param) FI; + + . table anweisung : + tabellenmodus := TRUE; + + . tableend anweisung : + tabellenmodus := FALSE; + + . clearpos0 anweisung : + loesche tabellenspeicher; + + . clearpos1 anweisung : + IF real conversion ok (param1) + THEN int param := x step conversion (real param); + FOR tab index FROM 1 UPTO anzahl tabs + REP IF tab position = int param + THEN tab typ := leer; + delete int (tab liste, tab index); + LEAVE clearpos1 anweisung; + FI; + PER; + FI; + + . lpos rpos cpos dpos anweisung : + IF real conversion ok (param1) + THEN neuer tab eintrag (anweisungs indizes ISUB index, param2) FI; + + . bpos anweisung : + IF real conversion ok (param2) CAND real conversion ok (param1) + CAND real (param2) > real param + THEN neuer tab eintrag (a bpos, param2) FI; + + . fillchar anweisung : + fill char := param1; + + . textbegin0 anweisung : + aktuelle einrueckbreite := alte einrueckbreite; + mark index l := alter mark index l; + mark index r := alter mark index r; + loesche alte markierung; + + . textbegin2 anweisung : + aktuelle einrueckbreite := alte einrueckbreite; + mark index l := alter mark index l; + mark index r := alter mark index r; + loesche alte markierung; + neuer durchschuss (int (param1), y step conversion (real (param 2))); + + . textend anweisung : + alte einrueckbreite := aktuelle einrueckbreite; + alter mark index l := mark index l; + alter mark index r := mark index r; + loesche markierung; + loesche durchschuss; + + . indentation anweisung : +(* IF real conversion ok (param1) + THEN int param := x step conversion (real param); + left margin INCR (int param - indentation); + indentation := int param; + FI; + *) + . y tab anweisung : +(* IF real conversion ok (param1) + THEN int param := y step conversion (real param); + IF int param <= seitenlaenge THEN a ypos := int param FI; + FI; + *) + . param1 : + IF (params1 zeiger ISUB index) <> 0 + THEN name (params1, params1 zeiger ISUB index) + ELSE "" + FI + + . param2 : + IF (params2 zeiger ISUB index) <> 0 + THEN name (params2, params2 zeiger ISUB index) + ELSE "" + FI + + +. + drucke elan listing : + initialisiere elan listing; + WHILE NOT eof + REP next line (zeile); + zeilen nr INCR 1; + drucke elan zeile; + PER; + schliesse elan listing ab; + +. + initialisiere elan listing : + open document cmd; + hole elan list font; + initialisiere variablen; + elan fuss und kopf (1, + PROC (INT CONST, INT CONST) close, + PROC (INT CONST, INT VAR, INT VAR) open, + PROC (INT CONST, TEXT CONST, INT CONST, INT CONST) execute); + + . open document cmd : + material wert := ""; + d token. offset index := 1; + erster ypos index d := 0; + vor erster seite := FALSE; + seite ist offen := FALSE; + open (document, x size, y size); + vor erster seite := TRUE; + + . hole elan list font : + d font := max (1, font ("elanlist")); + get replacements (d font, replacements, replacement tabelle); + einrueckbreite := indentation pitch (d font) ; + font hoehe := font lead (d font) + font height (d font) + font depth (d font); + + . initialisiere variablen : + innerhalb der define liste := FALSE; + vor erstem packet := TRUE; + zeilen nr := 0; + y wanted := y size DIV 23; + pagelength := y size - y wanted - y wanted; + x wanted := (min (x size DIV 10, x step conversion (2.54)) + DIV einrueckbreite) * einrueckbreite; + max zeichen zeile := (x size - x wanted - (x wanted DIV 3)) DIV einrueckbreite; + max zeichen fuss := fusszeilenbreite; + layout laenge := min (38, max zeichen zeile DIV 3); + layout laenge name := layout laenge - zeilen nr laenge - 8; + layout blanks := (layout laenge - zeilen nr laenge - 1) * " "; + refinement layout zeile := (layout laenge - 1) * " " ; + refinement layout zeile CAT "|" ; + IF pagelength DIV fonthoehe - 6 < 35 OR max zeichen zeile < 65 + THEN errorstop ("Schreibfeld fuer 'elan listing' zu klein") FI; + + . fusszeilenbreite : + INT CONST dina 4 breite := x step conversion (21.0); + IF x size <= dina 4 breite + THEN (x size - 2 * x wanted) DIV einrueckbreite + ELIF 120 * einrueckbreite <= dina 4 breite - 2 * x wanted + THEN (dina 4 breite - 2 * x wanted) DIV einrueckbreite + ELSE min (120, (x size - 2 * x wanted) DIV einrueckbreite) + FI + +. + schliesse elan listing ab : + elan fuss und kopf (-1, + PROC (INT CONST, INT CONST) close, + PROC (INT CONST, INT VAR, INT VAR) open, + PROC (INT CONST, TEXT CONST, INT CONST, INT CONST) execute); + close (document, 0); + +. + drucke elan zeile : + IF pos (zeile, "#page#") = 1 + THEN IF nicht am seiten anfang THEN seiten wechsel FI; + ELSE bestimme elan layout; + bestimme elan zeile; + gib elan text aus (PROC (INT CONST, TEXT CONST, INT CONST, INT CONST) execute); + seitenwechsel wenn noetig; + FI; + + . nicht am seitenanfang : + rest auf seite < pagelength - 3 * font hoehe + + . seiten wechsel : + elan fuss und kopf (0, + PROC (INT CONST, INT CONST) close, + PROC (INT CONST, INT VAR, INT VAR) open, + PROC (INT CONST, TEXT CONST, INT CONST, INT CONST) execute); + +. + bestimme elan layout : + IF pos (zeile, "P") = 0 AND pos (zeile, ":") = 0 + THEN leeres layout + ELSE analysiere elan zeile + FI; + elan text CAT "|"; + + . leeres layout : + elan text := text (zeilen nr, zeilen nr laenge); + elan text CAT layout blanks; + + . analysiere elan zeile : + scan (zeile); + next symbol (symbol, symbol type); + next symbol (naechstes symbol, naechster symbol type) ; + IF packet anfang THEN packet layout + ELIF innerhalb der define liste THEN leeres layout; pruefe ende der define liste + ELIF proc op anfang THEN proc op layout + ELIF refinement anfang THEN refinement layout + ELSE leeres layout + FI; + + . packet anfang : + symbol = "PACKET" + + . proc op anfang : + IF proc oder op (symbol) + THEN naechster symbol type <> delimiter type + ELIF (symbol <> "END") AND proc oder op (naechstes symbol) + THEN symbol := naechstes symbol; + next symbol (naechstes symbol, naechster symbol type) ; + naechster symbol type <> delimiter type + ELSE FALSE + FI + + . refinement anfang : + symbol type = tag type AND naechstes symbol = ":" + AND NOT innerhalb der define liste + + . packet layout : + IF nicht am seiten anfang AND + (NOT vor erstem packet OR gedruckte seiten > 0) + THEN seiten wechsel FI; + layout (" ", naechstes symbol, "*") ; + vor erstem packet := FALSE ; + innerhalb der define liste := TRUE; + pruefe ende der define liste; + + . pruefe ende der define liste : + IF pos (zeile, ":") <> 0 + THEN scan (zeile); + WHILE innerhalb der define liste + REP next symbol (symbol); + IF symbol = ":" THEN innerhalb der define liste := FALSE FI; + UNTIL symbol = "" PER; + FI; + + . proc op layout : + IF keine vier zeilen mehr + THEN seiten wechsel + ELIF nicht am seitenanfang + THEN cr plus lf (2, PROC (INT CONST, TEXT CONST, INT CONST, INT CONST) execute); + FI ; + layout (" ", naechstes symbol, "."); + + . keine vier zeilen mehr : + rest auf seite <= 8 * font hoehe + + . refinement layout : + IF keine drei zeilen mehr + THEN seiten wechsel + ELIF nicht am seitenanfang + THEN elan text := refinement layout zeile; + gib elan text aus + (PROC (INT CONST, TEXT CONST, INT CONST, INT CONST) execute); + FI ; + layout (" ", symbol, " "); + + . keine drei zeilen mehr : + rest auf seite <= 7 * font hoehe + +. + bestimme elan zeile : + IF zeile ist nicht zu lang + THEN elan text CAT zeile; + ELSE drucke zeile in teilen + FI; + + . zeile ist nicht zu lang : + zeilen laenge := LENGTH zeile; + zeilen laenge <= rest auf zeile + + . rest auf zeile : + max zeichen zeile - LENGTH elan text + + . drucke zeile in teilen : + zeilen pos := 1; + bestimme einrueckung; + WHILE zeile noch nicht ganz gedruckt REP teil layout PER; + + . bestimme einrueckung : + anzahl einrueck blanks := naechstes nicht blankes zeichen - 1; + IF anzahl einrueck blanks > rest auf zeile - 20 + THEN anzahl einrueck blanks := 0 FI; + + . zeile noch nicht ganz gedruckt : + bestimme zeilenteil; + NOT zeile ist zu ende + + . bestimme zeilenteil : + bestimme laenge; + zeilen teil := subtext (zeile, zeilen pos, zeilen pos + laenge - 1); + elan text CAT zeilen teil; + zeilen pos INCR laenge; + + . zeilen teil : par1 + + . bestimme laenge : + INT VAR laenge := zeilen laenge - zeilen pos + 1; + IF laenge > rest auf zeile + THEN laenge := rest auf zeile; + WHILE (zeile SUB (zeilen pos + laenge - 1)) <> " " + REP laenge DECR 1 UNTIL laenge = 0 PER; + IF laenge = 0 THEN laenge := rest auf zeile FI; + FI; + + . teil layout : + gib elan text aus (PROC (INT CONST, TEXT CONST, INT CONST, INT CONST) execute); + elan text := (zeilen nr laenge - 1) * " "; + elan text CAT "+"; + elan text CAT layout blanks; + elan text CAT "|"; + elan text cat blanks (anzahl einrueck blanks + teil einrueckung); + +. + seiten wechsel wenn noetig : + IF keine zeilen mehr AND NOT eof THEN seiten wechsel FI; + + . keine zeilen mehr : + rest auf seite <= 4 * font hoehe + +END PROC drucke datei; + + +BOOL PROC real conversion ok (TEXT CONST param) : + real param := real (param); + last conversion ok AND real param >= 0.0 +END PROC real conversion ok; + + +BOOL PROC int conversion ok (TEXT CONST param) : + int param := int (param); + last conversion ok AND int param >= 0 +END PROC int conversion ok; + + +PROC neuer tab eintrag (INT CONST typ, TEXT CONST param) : + + suche neuen eintrag; + sortiere neue tab position ein; + tab typ := typ; + tab position := neue tab position; + tab param := eventueller parameter; + + . suche neuen eintrag : + INT VAR index := 0; + REP index INCR 1; + IF tab speicher (index). tab typ = leer + THEN LEAVE suche neuen eintrag FI; + UNTIL index = max tabs PER; + LEAVE neuer tab eintrag; + + . sortiere neue tab position ein : + INT VAR neue tab position := x step conversion (real param); + FOR tab index FROM 1 UPTO anzahl tabs + REP IF tab position = neue tab position + THEN LEAVE neuer tab eintrag + ELIF tab position > neue tab position + THEN insert int (tab liste, tab index, index); + LEAVE sortiere neue tab position ein; + FI; + PER; + tab liste CAT index; + tab index := anzahl tabs; + + . eventueller parameter : + INT VAR link; + SELECT typ OF + CASE a dpos : insert (d strings, param, link); link + CASE a bpos : x step conversion (real(param)) + OTHERWISE : 0 + END SELECT + +END PROC neuer tab eintrag; + + +PROC neue spalte : + a ypos := top margin; + left margin INCR (limit + luecke); + aktuelle spalte INCR 1; +END PROC neue spalte ; + + +BOOL PROC proc oder op (TEXT CONST symbol) : + + symbol = "PROC" OR symbol = "PROCEDURE" + OR symbol = "OP" OR symbol = "OPERATOR" + +ENDPROC proc oder op ; + + +PROC layout (TEXT CONST pre, TEXT VAR name, TEXT CONST post) : + +name := subtext (name, 1, layout laenge name) ; +elan text := text (zeilen nr, zeilen nr laenge); +elan text CAT pre; +elan text CAT name; +elan text CAT " "; +generiere strukturiertes layout; + +. generiere strukturiertes layout : + INT VAR index; + FOR index FROM 1 UPTO layout laenge - LENGTH elan text - 1 + REP elan text CAT post PER; + +ENDPROC layout ; + + +PROC elan text cat blanks (INT CONST anzahl) : + + par2 := anzahl * " "; + elan text CAT par2; + +END PROC elan text cat blanks; + + +(***********************************************************************) + +PROC analysiere zeile : + +loesche analysespeicher; +behandle fuehrende blanks; +pruefe ob anweisungszeile; +pruefe ob markierung links; + +IF tabellen modus + THEN analysiere tabellenzeile +ELIF letzte zeile war absatzzeile + THEN analysiere zeile nach absatzzeile + ELSE analysiere zeile nach blockzeile +FI; + +pruefe center und right modus; +pruefe ob tabulation vorliegt; +werte indexspeicher aus; +berechne zeilenhoehe; +pruefe ob markierung rechts; + +. + analysiere zeile nach absatzzeile : + test auf aufzaehlung; + IF zeile muss geblockt werden + THEN analysiere blockzeile nach absatzzeile + ELSE analysiere absatzzeile nach absatzzeile + FI; +. + analysiere zeile nach blockzeile : + IF zeile muss geblockt werden + THEN analysiere blockzeile nach blockzeile + ELSE analysiere absatzzeile nach blockzeile + FI; + + +. + behandle fuehrende blanks : + zeilenpos := 1; + zeilenpos := naechstes nicht blankes zeichen; + IF zeilenpos = 0 + THEN behandle leerzeile; + LEAVE analysiere zeile; + ELSE letzte zeile war absatzzeile := zeile ist absatzzeile; + IF letzte zeile war absatzzeile THEN neue einrueckung FI; + initialisiere analyse; + FI; + + . behandle leerzeile : + a ypos INCR (letzte zeilenhoehe + durchschuss); + zeile ist absatzzeile := LENGTH zeile > 0; + pruefe ob markierung links; + pruefe ob markierung rechts; + + . neue einrueckung : + aktuelle einrueckbreite := einrueckbreite; + + . initialisiere analyse : + zeile ist absatzzeile := (zeile SUB LENGTH zeile) = blank; + zeile muss geblockt werden := block modus AND NOT zeile ist absatzzeile; + erstes token der zeile := token index f + 1; + groesste fonthoehe := fonthoehe; + aktuelle zeilenhoehe := letzte zeilenhoehe; + zeilen laenge := laenge der zeile; + anzahl einrueck blanks := zeilen pos - 1; + anzahl zeichen := anzahl einrueck blanks; + a xpos := left margin + anzahl zeichen * aktuelle einrueckbreite; + a modifikationen fuer x move := 0; + letzter font := a font; + letzte modifikationen := a modifikationen; + IF zeile muss geblockt werden THEN initialisiere tab variablen FI; + + . laenge der zeile : + IF zeile ist absatzzeile + THEN LENGTH zeile - 1 + ELSE LENGTH zeile + FI +. + pruefe ob anweisungszeile : + IF erstes zeichen ist anweisungszeichen + THEN REP analysiere anweisung; + IF zeile ist zu ende THEN LEAVE analysiere zeile FI; + UNTIL zeichen ist kein anweisungs zeichen PER; + FI; + + . erstes zeichen ist anweisungszeichen : + pos (zeile, anweisungszeichen, 1, 1) <> 0 + + . zeichen ist kein anweisungszeichen : + pos (zeile, anweisungszeichen, zeilen pos, zeilen pos) = 0 + +. + pruefe ob markierung links : + IF markierung links + THEN mark token (mark index l). xpos := + left margin - mark token (mark index l). breite; + lege markierungs token an (mark index l); + erstes token der zeile := token index f + 1; + initialisiere tab variablen; + FI; + +. + analysiere tabellenzeile : + anfangs blankmodus := doppel blank; + alte zeilenpos := zeilen pos; + FOR tab index FROM 1 UPTO anzahl tabs + REP lege fuell token an wenn noetig; + initialisiere tab variablen; + SELECT tab typ OF + CASE a lpos : linksbuendige spalte + CASE a rpos : rechtsbuendige spalte + CASE a cpos : zentrierte spalte + CASE a dpos : dezimale spalte + CASE a bpos : geblockte spalte + END SELECT; + berechne fuell token wenn noetig; + tabulation; + PER; + analysiere rest der zeile; + + . lege fuell token an wenn noetig : + IF fill char <> blank + THEN fuellzeichen := fill char; + fuellzeichen breite := string breite (fuellzeichen); + token zeiger := zeilen pos; + erstes fuell token := token index f + 1; + lege text token an; + letztes fuell token := token index f; + a modifikationen fuer x move := a modifikationen + FI; + + . berechne fuell token wenn noetig : + IF erstes fuell token <> leer + THEN IF letztes fuell token <> token index f + THEN berechne fuell token; + ELSE loesche letzte token; + FI; + erstes fuell token := leer + FI; + + . berechne fuell token : + INT VAR anzahl fuellzeichen, fuell breite; + token index := erstes fuell token; + anzahl fuellzeichen := (tab anfang - t. xpos + left margin) + DIV fuellzeichen breite; + rest := (tab anfang - t. xpos + left margin) + MOD fuellzeichen breite; + IF anzahl fuell zeichen > 0 + THEN fuell text := anzahl fuellzeichen * fuellzeichen; + fuell breite := anzahl fuellzeichen * fuellzeichen breite; + FOR token index FROM erstes fuell token UPTO letztes fuell token + REP t. text := fuell text; + t. breite := fuell breite; + IF erstes fuell token <> erstes token der zeile + THEN t. xpos INCR rest DIV 2; + t. modifikationen fuer x move := t. modifikationen; + FI; + PER; + FI; + + . fuell text : par1 + + . loesche letzte token : + FOR token index FROM letztes fuell token DOWNTO erstes fuell token + REP loesche letztes token PER; + + . tabulation : + alte zeilenpos := zeilenpos; + zeilenpos := naechstes nicht blankes zeichen; + IF zeilenpos = 0 + THEN zeilenpos := zeilenlaenge + 1; + LEAVE analysiere tabellenzeile; + FI; + anzahl zeichen INCR zeilenpos - alte zeilenpos; + + . linksbuendige spalte : + a xpos := left margin + tab position; + tab anfang := tab position; + bestimme token bis terminator oder zeilenende; + + . rechtsbuendige spalte : + bestimme token bis terminator oder zeilenende; + schreibe zeile rechtsbuendig (tab position); + + . zentrierte spalte : + bestimme token bis terminator oder zeilenende; + zentriere zeile (tab position); + + . dezimale spalte : + d string := name (d strings, tab param); + d code 1 := code (d string SUB 1) + 1; + d pitch := zeichenbreiten (d code 1); + zeichenbreiten (d code 1) := d code ausgang; + bestimme token bis terminator oder zeilenende; + zeichenbreiten (d code 1) := d pitch; + d code 1 := leer; + schreibe zeile rechtsbuendig (tab position); + IF zeichen ist dezimal zeichen + THEN IF tab position <> zeilen breite + THEN a xpos := left margin + tab position; + tab anfang := tab position; + FI; + bestimme token bis terminator oder zeilenende + FI; + + . zeichen ist dezimal zeichen : + pos (zeile, d string, zeilen pos) = zeilen pos + + . geblockte spalte : + blankmodus := einfach blank; + a xpos := left margin + tab position; + tab anfang := tab position; + REP bestimme token bis terminator oder zeilenende; + IF zeile ist zu ende OR naechstes zeichen ist blank + THEN blocke spalte wenn noetig; + LEAVE geblockte spalte; + ELSE dehnbares blank gefunden; + FI; + PER; + + . blocke spalte wenn noetig : + IF letztes zeichen ist kein geschuetztes blank + THEN blocke zeile (tab param) FI; + blank modus := doppel blank; + + . letztes zeichen ist kein geschuetztes blank : + pos (zeile, geschuetztes blank, zeilen pos - 1, zeilen pos - 1) = 0 + AND NOT within kanji (zeile, zeilen pos - 2) + + . analysiere rest der zeile : + blankmodus := keine blankanalyse; + zeilen pos := alte zeilenpos; + bestimme token bis terminator oder zeilenende; + +. + test auf aufzaehlung : + anfangs blankmodus := einfach blank; + bestimme token bis terminator oder zeilenende; + IF zeile ist zu ende + THEN LEAVE analysiere zeile nach absatzzeile + ELSE aufzaehlung moeglich + FI; + + . aufzaehlung moeglich : + bestimme letztes zeichen; + IF (anzahl zeichen bei aufzaehlung < 2 AND letztes zeichen = "-") + OR (anzahl zeichen bei aufzaehlung < 20 AND letztes zeichen = ":") + OR (anzahl zeichen bei aufzaehlung < 7 + AND pos (".)", letztes zeichen) <> 0) + OR naechstes zeichen ist blank + THEN tabulator position gefunden; + ELIF zeile muss geblockt werden + THEN dehnbares blank gefunden; + FI; + + . bestimme letztes zeichen : + token index := token index f; + WHILE token index >= erstes token der zeile + REP IF token ist text token + THEN letztes zeichen := t. text SUB LENGTH t. text; + LEAVE bestimme letztes zeichen; + FI; + token index DECR 1; + PER; + letztes zeichen := ""; + + . letztes zeichen : par1 + + . anzahl zeichen bei aufzaehlung : + anzahl zeichen - anzahl einrueck blanks + + . token ist text token : + t. offset index >= text token +. + analysiere blockzeile nach absatzzeile : + REP bestimme token bis terminator oder zeilenende; + IF zeile ist zu ende + THEN blocke zeile (limit); + LEAVE analysiere blockzeile nach absatzzeile + ELSE analysiere blank in blockzeile nach absatzzeile + FI; + PER; + + . analysiere blank in blockzeile nach absatzzeile : + IF naechstes zeichen ist blank + THEN tabulator position gefunden; + ELSE dehnbares blank gefunden; + FI; + +. + analysiere absatzzeile nach absatzzeile : + blankmodus := doppel blank; + REP bestimme token bis terminator oder zeilenende; + IF zeile ist zu ende + THEN LEAVE analysiere absatzzeile nach absatzzeile + ELSE tabulator position gefunden + FI; + PER; + +. + analysiere blockzeile nach blockzeile : + anfangs blankmodus := einfach blank; + REP bestimme token bis terminator oder zeilenende; + IF zeile ist zu ende + THEN blocke zeile (limit); + LEAVE analysiere blockzeile nach blockzeile + ELSE dehnbares blank gefunden + FI; + PER; + +. + analysiere absatzzeile nach blockzeile : + anfangs blankmodus := keine blankanalyse; + bestimme token bis terminator oder zeilenende; + +. + dehnbares blank gefunden : + anzahl zeichen INCR 1; + zeilenpos INCR 1; + a xpos INCR blankbreite; + a modifikationen fuer x move := a modifikationen; + IF NOT a block token + THEN anzahl blanks INCR 1; + a block token := TRUE; + FI; +. + tabulator position gefunden : + alte zeilenpos := zeilenpos; + zeilenpos := naechstes nicht blankes zeichen; + IF zeilenpos = 0 + THEN zeilenpos := zeilen laenge + 1; + ELSE IF erstes token der zeile > token index f + THEN token zeiger := zeilen pos; + lege text token an; + FI; + anzahl zeichen INCR (zeilenpos - alte zeilenpos); + a xpos := left margin + anzahl zeichen * aktuelle einrueckbreite; + a modifikationen fuer x move := a modifikationen; + IF zeile muss geblockt werden THEN initialisiere tab variablen FI; + FI; + +. + pruefe center und right modus : + IF center modus THEN zentriere zeile (limit DIV 2) FI; + IF right modus THEN schreibe zeile rechtsbuendig (limit) FI; +. + pruefe ob tabulation vorliegt: + IF analyse speicher ist nicht leer CAND a xpos > tf. xpos + tf. breite + THEN a modifikationen fuer x move := a modifikationen; + token zeiger := zeilen pos; + lege text token an; + FI; +. + werte indexspeicher aus : + INT VAR index; + IF index zaehler > 0 + THEN FOR index FROM index zaehler DOWNTO 1 + REP a ypos DECR (verschiebungen ISUB index) PER; + stelle neuen font ein (grosse fonts ISUB 1); + loesche index speicher; + FI; +. + berechne zeilenhoehe : + verschiebung := aktuelle zeilenhoehe + durchschuss; + a ypos INCR verschiebung; + verschiebe token ypos (verschiebung); + +. + pruefe ob markierung rechts : + IF markierung rechts + THEN mark token (mark index r). xpos := left margin + limit; + lege markierungs token an (mark index r); + FI; + +END PROC analysiere zeile; + + +PROC blocke zeile (INT CONST rechter rand) : + +rest := rechter rand - zeilen breite; +IF rest > 0 AND anzahl blanks > 0 + THEN INT CONST schmaler schritt := rest DIV anzahl blanks, + breiter schritt := schmaler schritt + 1, + anzahl breite schritte := rest MOD anzahl blanks; + IF rechts + THEN blocke token xpos (breiter schritt, schmaler schritt, + anzahl breite schritte); + rechts := FALSE; + ELSE blocke token xpos (schmaler schritt, breiter schritt, + anzahl blanks - anzahl breite schritte); + rechts := TRUE; + FI; + a xpos INCR ( breiter schritt * anzahl breite schritte + + schmaler schritt * (anzahl blanks - anzahl breite schritte) ); +FI; + +END PROC blocke zeile; + + +PROC zentriere zeile (INT CONST zentrier pos) : + +IF erstes tab token <= token index f + THEN verschiebung := zentrier pos - tab anfang - + (zeilen breite - tab anfang) DIV 2; + verschiebe token xpos (verschiebung); + a xpos INCR verschiebung; + tab anfang INCR verschiebung; +FI; +center modus := FALSE; + +END PROC zentriere zeile; + + +PROC schreibe zeile rechtsbuendig (INT CONST rechte pos) : + +IF erstes tab token <= token index f + THEN verschiebung := rechte pos - zeilen breite; + verschiebe token xpos (verschiebung); + a xpos INCR verschiebung; + tab anfang INCR verschiebung; +FI; +right modus := FALSE; + + +END PROC schreibe zeile rechtsbuendig; + + +PROC bestimme token bis terminator oder zeilenende : + +token zeiger := zeilen pos; +REP stranalyze (zeichenbreiten, a breite, max breite, + zeile, zeilen pos, zeilen laenge, + ausgang); + zeilen pos INCR 1; + IF ausgang = blank ausgang + THEN analysiere blank + ELIF ausgang = anweisungs ausgang + THEN anweisung gefunden + ELIF ausgang = d code ausgang + THEN analysiere d string + ELIF ausgang = erweiterungs ausgang + THEN erweiterung gefunden + ELSE terminator oder zeilenende gefunden + FI; +PER; + +. analysiere blank : + IF blankmodus = einfach blank OR + (blankmodus = doppel blank AND naechstes zeichen ist blank) + THEN terminator oder zeilenende gefunden + ELSE a breite INCR blankbreite; + zeilenpos INCR 1; + FI; + +. analysiere d string : + IF pos (zeile, d string, zeilen pos) = zeilen pos + THEN terminator oder zeilenende gefunden + ELSE IF d pitch = maxint + THEN erweiterung gefunden + ELIF d pitch < 0 + THEN a breite INCR (d pitch XOR - maxint - 1); + zeilen pos INCR 2; + ELSE a breite INCR d pitch; + zeilenpos INCR 1; + FI; + FI; + +. erweiterung gefunden : + a breite INCR extended char pitch (a font, zeile SUB zeilen pos, + zeile SUB zeilen pos + 1); + zeilen pos INCR 2; + +. anweisung gefunden : + gegebenfalls neues token gefunden; + analysiere anweisung; + IF zeile ist zu ende + THEN LEAVE bestimme token bis terminator oder zeilenende FI; + token zeiger := zeilenpos; + +. terminator oder zeilenende gefunden : + IF ausgang = null ausgang THEN zeilen laenge DECR 1 FI; + gegebenfalls neues token gefunden; + LEAVE bestimme token bis terminator oder zeilenende; + + . gegebenfalls neues token gefunden : + IF token zeiger < zeilenpos THEN lege text token an FI; + +END PROC bestimme token bis terminator oder zeilen ende; + + +PROC analysiere anweisung : + + bestimme anweisung; + IF anweisung ist kommando + THEN lege kommando token an; + ELSE werte anweisung aus; + FI; + + . anweisungsanfang : token zeiger + + . anweisungsende : zeilen pos - 2 + + . erstes zeichen : par1 + +. bestimme anweisung : + anweisungsanfang := zeilenpos + 1; + zeilen pos := pos (zeile, anweisungszeichen, anweisungsanfang, zeilenlaenge); + IF zeilenpos = 0 + THEN zeilenpos := anweisungsanfang - 1; + replace (zeile, zeilenpos, geschuetztes anweisungszeichen); + LEAVE analysiere anweisung; + FI; + zeilen pos INCR 1; + anweisung := subtext (zeile, anweisungsanfang, anweisungsende); + erstes zeichen := anweisung SUB 1; + +. anweisung ist kommando : + IF erstes zeichen = quote + THEN scan (anweisung); + next symbol (anweisung, symbol type); + next symbol (par2, naechster symbol type); + IF symbol type <> text type OR naechster symbol type <> eof type + THEN LEAVE analysiere anweisung FI; + TRUE + ELIF erstes zeichen = druckerkommando zeichen + THEN delete char (anweisung, 1); + TRUE + ELSE FALSE + FI + +. + werte anweisung aus : + analyze command (anweisungs liste, anweisung, number type, + anweisungs index, anzahl params, par1, par2); + SELECT anweisungs index OF + CASE a type : type anweisung + CASE a on : on anweisung + CASE a off : off anweisung + CASE a ub, a fb : ub fb anweisung + CASE a ue, a fe : ue fe anweisung + CASE a center : center anweisung + CASE a right : right anweisung + CASE a up, a down : index anweisung + CASE a end up or down : end index anweisung + CASE a bsp : bsp anweisung + CASE a fillchar : fillchar anweisung + CASE a mark : mark anweisung + CASE a markend : markend anweisung + OTHERWISE : IF anweisungs index > 0 THEN speichere anweisung FI; + END SELECT; + + . type anweisung : + change all (par1, " ", ""); + stelle neuen font ein (font (par1)); + groesste fonthoehe := max (groesste fonthoehe, fonthoehe); + a modifikationen := 0; + IF nicht innerhalb eines indexes THEN berechne aktuelle zeilenhoehe FI; + + . nicht innerhalb eines indexes : + index zaehler = 0 + + . berechne aktuelle zeilenhoehe : + IF linefeed faktor >= 1.0 + THEN aktuelle zeilenhoehe := max (groesste fonthoehe, + letzte zeilenhoehe); + ELSE aktuelle zeilenhoehe := max (aktuelle zeilenhoehe, + letzte zeilenhoehe); + FI; + + . on anweisung : + par1 := par1 SUB 1; + IF pos (modifikations liste, par1) > 0 + THEN set bit (a modifikationen, pos (modifikations liste, par1) - 1 ); + FI; + + . off anweisung : + par1 := par1 SUB 1; + IF pos (modifikations liste, par1) > 0 + THEN reset bit (a modifikationen, pos (modifikations liste, par1) - 1 ); + FI; + + . ub fb anweisung : + IF anweisungs index = a ub + THEN par1 := "u" + ELSE par1 := "b" + FI; + on anweisung; + + . ue fe anweisung : + IF anweisungs index = a ue + THEN par1 := "u" + ELSE par1 := "b" + FI; + off anweisung; + + . center anweisung : + IF NOT zeile muss geblockt werden AND NOT tabellen modus + AND NOT right modus + THEN center modus := TRUE; + blankmodus := keine blankanalyse; + initialisiere tab variablen; + FI; + + . right anweisung : + IF NOT zeile muss geblockt werden AND NOT tabellen modus + THEN IF center modus THEN zentriere zeile (limit DIV 2) FI; + right modus := TRUE; + blankmodus := keine blankanalyse; + initialisiere tab variablen; + FI; + + . index anweisung : + INT CONST grosser font := a font, grosse fonthoehe := fonthoehe; + INT VAR kleiner font; + IF next smaller font exists (grosser font, kleiner font) + THEN stelle neuen font ein (kleiner font) FI; + IF font hoehe < grosse fonthoehe + THEN berechne verschiebung fuer kleinen font + ELSE berechne verschiebung fuer grossen font + FI; + a ypos INCR verschiebung; + merke grossen font und verschiebung; + + . berechne verschiebung fuer kleinen font : + IF anweisungs index = a down + THEN verschiebung := 15 PROZENT grosse fonthoehe; + ELSE verschiebung := - ( 9 PROZENT grosse fonthoehe ) + - (grosse fonthoehe - fonthoehe); + FI; + + . berechne verschiebung fuer grossen font : + IF anweisungs index = a down + THEN verschiebung := 25 PROZENT fonthoehe; + ELSE verschiebung := - (50 PROZENT fonthoehe); + FI; + + . merke grossen font und verschiebung : + index zaehler INCR 1; + grosse fonts CAT grosser font; + verschiebungen CAT verschiebung; + IF index zaehler = 1 + THEN alter blankmodus := blankmodus; + blankmodus := keine blankanalyse; + FI; + + . end index anweisung : + IF index zaehler > 0 + THEN schalte auf groesseren font zurueck; + FI; + + . schalte auf groesseren font zurueck : + a ypos DECR (verschiebungen ISUB index zaehler); + stelle neuen font ein (grosse fonts ISUB index zaehler); + IF index zaehler = 1 + THEN blankmodus := alter blankmodus; + FI; + index zaehler DECR 1; + verschiebungen := subtext (verschiebungen, 1, 2 * index zaehler); + grosse fonts := subtext (grosse fonts, 1, 2 * index zaehler); + + . bsp anweisung : + INT VAR breite davor, breite dahinter; + IF anweisungs anfang - 2 >= 1 AND anweisungs ende + 2 <= zeilen laenge + THEN IF is kanji esc (zeile SUB anweisungs anfang - 3) + THEN zeichen davor := subtext (zeile, anweisungs anfang - 3, + anweisungs anfang - 2); + ELSE zeichen davor := zeile SUB anweisungs anfang - 2; + FI; + IF is kanji esc (zeile SUB anweisungs ende + 2) + THEN zeichen dahinter := subtext (zeile, anweisungs ende + 2, + anweisungs ende + 3 ); + ELSE zeichen dahinter := zeile SUB anweisungs ende + 2; + FI; + IF pos (" #", zeichen davor) = 0 AND pos (" #", zeichen dahinter) = 0 + THEN breite davor := char pitch (a font, zeichen davor); + breite dahinter := char pitch (a font, zeichen dahinter); + IF breite davor < breite dahinter THEN vertausche zeichen FI; + lege token fuer zeichen dahinter an; + a xpos INCR (breite davor - breite dahinter) DIV 2; + FI; + FI; + + . zeichen davor : par1 + . zeichen dahinter : par2 + + . vertausche zeichen : + change (zeile, anweisungs anfang - 2 - LENGTH zeichen davor + 1, + anweisungs anfang - 2, zeichen dahinter); + change (zeile, anweisungs ende + 2, + anweisungs ende + 2 + LENGTH zeichen dahinter - 1, zeichen davor); + change (tf. text, LENGTH tf. text - LENGTH zeichen davor + 1, + LENGTH tf. text, zeichen dahinter); + tf. breite INCR (breite dahinter - breite davor); + a xpos INCR (breite dahinter - breite davor); + int param := breite davor; + breite davor := breite dahinter; + breite dahinter := int param; + + . lege token fuer zeichen dahinter an : + token zeiger := zeilen pos; + a breite := breite dahinter; + zeilen pos INCR LENGTH zeichen dahinter; + a xpos DECR (breite davor + breite dahinter) DIV 2; + lege text token an; + anzahl zeichen DECR 1; + + . fillchar anweisung : + IF par1 = "" THEN par1 := " " FI; + fill char := par1; + speichere anweisung; + + . mark anweisung : + IF par1 <> "" + THEN mark index l := (alter mark index l MOD 2) + 1; + neue markierung (par1, mark index l); + ELSE mark index l := 0; + FI; + IF par2 <> "" + THEN mark index r := (alter mark index r MOD 2) + 3; + neue markierung (par2, mark index r); + ELSE mark index r := 0; + FI; + + . markend anweisung : + loesche markierung; + + . speichere anweisung : + anweisungs zaehler INCR 1; + anweisungs indizes CAT anweisungs index; + IF par1 <> "" + THEN insert (params1, par1); + params1 zeiger CAT highest entry (params1); + ELSE params1 zeiger CAT 0; + FI; + IF par2 <> "" + THEN insert (params2, par2); + params2 zeiger CAT highest entry (params2); + ELSE params2 zeiger CAT 0; + FI; + +END PROC analysiere anweisung; + + +PROC stelle neuen font ein (INT CONST font nr ) : + + IF font nr <> a font THEN neuer font FI; + + . neuer font : + a font := max (1, font nr); + get font (a font, einrueckbreite, font durchschuss, font hoehe, font tiefe, + zeichenbreiten); + font hoehe INCR (font durchschuss + font tiefe); + letzte zeilenhoehe := neue zeilenhoehe; + blankbreite := zeichenbreiten (blank code 1); + zeichenbreiten (blank code 1) := blank ausgang; + zeichenbreiten (anweisungs zeichen code 1) := anweisungs ausgang; + font offsets := y offsets (a font); + offsets := LENGTH font offsets > 2; + IF d code 1 <> leer + THEN d pitch := zeichenbreiten (d code 1); + zeichenbreiten (d code 1) := d code ausgang; + FI; + +END PROC stelle neuen font ein; + + +INT OP PROZENT (INT CONST prozent, wert) : + + (wert * prozent + 99) DIV 100 + +END OP PROZENT; + + +PROC neue markierung (TEXT CONST text, INT CONST mark index) : + + mark token (mark index). text := text; + mark token (mark index). breite := string breite (text); + mark token (mark index). font := a font; + mark token (mark index). modifikationen := a modifikationen; + +END PROC neue markierung; + + +INT PROC string breite (TEXT CONST string) : + + INT VAR summe := 0, pos := 1; + REP stranalyze (zeichenbreiten, summe, max breite, string, pos, maxint, ausgang); + IF ausgang = erweiterungs ausgang + THEN summe INCR extended char pitch (a font, + string SUB pos+1, string SUB pos+2); + pos INCR 3; + ELIF ausgang = blank ausgang + THEN summe INCR blankbreite; + pos INCR 2; + ELIF ausgang = anweisungs ausgang + THEN summe INCR char pitch (a font, anweisungszeichen); + pos INCR 2; + ELSE LEAVE string breite WITH summe + FI; + PER; + 0 + +END PROC string breite; + +(*******************************************************************) + +PROC lege text token an : + + aktuelle ypos := a ypos + (font offsets ISUB 1); + neuer token index; + uebertrage text token (tf); + IF offsets THEN lege offsets an (font offsets) FI; + stranalyze (zeichen zaehler, anzahl zeichen, max int, + zeile, token zeiger, zeilen pos - 1, ausgang); + a xpos INCR a breite; + a breite := 0; + a modifikationen fuer x move := 0; + a block token := FALSE; + +END PROC lege text token an; + + +PROC uebertrage text token (TOKEN VAR tf) : + + tf. text := subtext (zeile, token zeiger, zeilenpos - 1); + tf. xpos := a xpos; + tf. breite := a breite; + tf. font := a font; + tf. modifikationen := a modifikationen; + tf. modifikationen fuer x move := a modifikationen fuer x move; + tf. offset index := text token; + tf. block token := a block token; + +END PROC uebertrage text token; + + +PROC lege kommando token an : + + aktuelle ypos := a ypos + (font offsets ISUB 1); + neuer token index; + uebertrage kommando token (tf); + a modifikationen fuer x move := 0; + a block token := FALSE; + +END PROC lege kommando token an; + + +PROC uebertrage kommando token (TOKEN VAR tf) : + + tf. text := anweisung; + tf. breite := 0; + tf. xpos := a xpos; + tf. font := a font; + tf. modifikationen := a modifikationen; + tf. modifikationen fuer x move := a modifikationen fuer x move; + tf. offset index := kommando token; + tf. block token := a block token; + +END PROC uebertrage kommando token; + + +PROC lege markierungs token an (INT CONST mark index) : + + aktuelle ypos := a ypos + (mark font offsets ISUB 1); + neuer token index; + tf := mark token (mark index); + IF mark offsets THEN lege offsets an (mark font offsets) FI; + + . mark font offsets : y offsets (mark token (mark index). font) + + . mark offsets : LENGTH mark font offsets > 2 + +END PROC lege markierungs token an; + + +PROC lege offsets an (TEXT CONST offsets) : + + INT CONST anzahl offsets := LENGTH offsets DIV 2; + offset token := tf; + offset token. block token := FALSE; + reset bit (offset token. modifikationen, underline bit); + FOR index FROM 2 UPTO anzahl offsets + REP aktuelle ypos := a ypos + (offsets ISUB index); + neuer token index; + tf := offset token; + tf. offset index := index; + PER; + +END PROC lege offsets an; + + +PROC neuer token index : + +IF erster ypos index a = 0 + THEN erste ypos +ELIF ya. ypos = aktuelle ypos + THEN neues token bei gleicher ypos + ELSE fuege neue ypos ein +FI; + + . erste ypos : + ypos index f INCR 1; + erster ypos index a := ypos index f; + letzter ypos index a := ypos index f; + yf. vorheriger ypos index := 0; + yf. naechster ypos index := 0; + erstes token bei neuer ypos; + + . fuege neue ypos ein : + letztes token bei gleicher ypos; + IF ya. ypos > aktuelle ypos + THEN richtige ypos ist oberhalb + ELSE richtige ypos ist unterhalb + FI; + + . richtige ypos ist oberhalb : + REP ypos index a := ya. vorheriger ypos index; + IF ypos index a = 0 + THEN fuege ypos vor erstem ypos index ein; + LEAVE richtige ypos ist oberhalb; + ELIF ya. ypos = aktuelle ypos + THEN neues token bei neuer ypos; + LEAVE richtige ypos ist oberhalb; + ELIF ya. ypos < aktuelle ypos + THEN fuege ypos nach ypos index ein; + LEAVE richtige ypos ist oberhalb; + FI; + PER; + + . richtige ypos ist unterhalb : + REP ypos index a := ya. naechster ypos index; + IF ypos index a = 0 + THEN fuege ypos nach letztem ypos index ein; + LEAVE richtige ypos ist unterhalb; + ELIF ya. ypos = aktuelle ypos + THEN neues token bei neuer ypos; + LEAVE richtige ypos ist unterhalb; + ELIF ya. ypos > aktuelle ypos + THEN fuege ypos vor ypos index ein; + LEAVE richtige ypos ist unterhalb; + FI; + PER; + + . fuege ypos vor erstem ypos index ein : + ypos index f INCR 1; + yf. vorheriger ypos index := 0; + yf. naechster ypos index := erster ypos index a; + erster ypos index a := ypos index f; + ypos index a := yf. naechster ypos index; + ya. vorheriger ypos index := ypos index f; + erstes token bei neuer ypos; + + . fuege ypos nach ypos index ein : + ypos index f INCR 1; + yf. vorheriger ypos index := ypos index a; + yf. naechster ypos index := ya. naechster ypos index; + ya. naechster ypos index := ypos index f; + ypos index a := yf. naechster ypos index; + ya. vorheriger ypos index := ypos index f; + erstes token bei neuer ypos; + + . fuege ypos vor ypos index ein : + ypos index f INCR 1; + yf. naechster ypos index := ypos index a; + yf. vorheriger ypos index := ya. vorheriger ypos index; + ya. vorheriger ypos index := ypos index f; + ypos index a := yf. vorheriger ypos index; + ya. naechster ypos index := ypos index f; + erstes token bei neuer ypos; + + . fuege ypos nach letztem ypos index ein : + ypos index f INCR 1; + yf. naechster ypos index := 0; + yf. vorheriger ypos index := letzter ypos index a; + letzter ypos index a := ypos index f; + ypos index a := yf. vorheriger ypos index; + ya. naechster ypos index := ypos index f; + erstes token bei neuer ypos; + +END PROC neuer token index; + + +PROC erstes token bei neuer ypos : + token index f INCR 1; + ypos index a := ypos index f; + ya. erster token index := token index f; + ya. ypos := aktuelle ypos; +END PROC erstes token bei neuer ypos; + + +PROC neues token bei neuer ypos : + token index f INCR 1; + ya. ypos := aktuelle ypos; + token index := ya. letzter token index; + t. naechster token index := token index f; +END PROC neues token bei neuer ypos; + + +PROC neues token bei gleicher ypos : + tf. naechster token index := token index f + 1; + token index f INCR 1; +END PROC neues token bei gleicher ypos; + + +PROC letztes token bei gleicher ypos : + tf. naechster token index := 0; + ya. letzter token index := token index f; +END PROC letztes token bei gleicher ypos; + + +PROC loesche letztes token : + + IF token index f = ya. erster token index + THEN loesche ypos + ELSE token index f DECR 1; + FI; + + . loesche ypos : + kette vorgaenger um; + kette nachfolger um; + bestimme letzten ypos index; + + . kette vorgaenger um : + ypos index := ya. vorheriger ypos index; + IF ypos index = 0 + THEN erster ypos index a := ya. naechster ypos index; + ELSE y. naechster ypos index := ya. naechster ypos index; + FI; + + . kette nachfolger um : + ypos index := ya. naechster ypos index; + IF ypos index = 0 + THEN letzter ypos index a := ya. vorheriger ypos index; + ELSE y. vorheriger ypos index := ya. vorheriger ypos index; + FI; + + . bestimme letzten ypos index : + IF ypos index a = ypos index f THEN ypos index f DECR 1 FI; + token index f DECR 1; + ypos index a := letzter ypos index a; + WHILE ypos index a <> 0 + CAND ya. letzter token index <> token index f + REP ypos index a := ya. vorheriger ypos index PER; + +END PROC loesche letztes token; + + +PROC blocke token xpos (INT CONST dehnung 1, dehnung 2, + anzahl dehnungen fuer dehnung 1 ) : + + INT VAR dehnung := 0, anzahl dehnungen := 0; + token index := erstes tab token; + WHILE token index <= token index f + REP erhoehe token xpos bei block token; + t. xpos INCR dehnung; + token index INCR 1; + PER; + + . erhoehe token xpos bei block token : + IF t. block token + THEN IF anzahl dehnungen < anzahl dehnungen fuer dehnung 1 + THEN anzahl dehnungen INCR 1; + dehnung INCR dehnung 1; + ELSE dehnung INCR dehnung 2; + FI; + FI; + +END PROC blocke token xpos; + + +PROC verschiebe token xpos (INT CONST verschiebung) : + + token index := erstes tab token; + WHILE token index <= token index f + REP t. xpos INCR verschiebung; + token index INCR 1; + PER; + +END PROC verschiebe token xpos; + + +PROC verschiebe token ypos (INT CONST verschiebung) : + + ypos index := erster ypos index a; + WHILE ypos index <> 0 + REP y. ypos INCR verschiebung; + ypos index := y. naechster ypos index; + PER; + +END PROC verschiebe token ypos; + + +PROC sortiere neue token ein : + +IF analysespeicher ist nicht leer + THEN IF druckspeicher ist nicht leer + THEN sortiere neue token in sortierte liste ein + ELSE sortierte liste ist leer + FI; +FI; + +. sortierte liste ist leer : + IF erster ypos index a <> 0 + THEN erster ypos index d := erster ypos index a; + letzter ypos index d := letzter ypos index a; + ypos index d := letzter ypos index a; + FI; + +. sortiere neue token in sortierte liste ein : + gehe zum ersten neuen token; + bestimme erste einsortierposition; + WHILE es gibt noch neue token + REP IF ypos index d = 0 + THEN haenge neue token ans ende der sortierten liste + ELIF ya. ypos > yd. ypos + THEN naechste ypos der sortierten liste + ELIF ya. ypos = yd. ypos + THEN neues token auf gleicher ypos + ELSE neue token vor ypos + FI; + PER; + + . gehe zum ersten neuen token : + ypos index a := erster ypos index a; + + . bestimme erste einsortierposition : + WHILE ypos index d <> 0 CAND ya. ypos < yd. ypos + REP ypos index d := yd. vorheriger ypos index PER; + IF ypos index d = 0 THEN erste neue token vor listen anfang FI; + + . erste neue token vor listen anfang : + ypos index d := erster ypos index d; + erster ypos index d := erster ypos index a; + REP ypos index a := ya. naechster ypos index; + IF ypos index a = 0 + THEN verkette letztes ya mit yd; + LEAVE sortiere neue token in sortierte liste ein + ELIF ya. ypos = yd. ypos + THEN verkette ya mit yd; + LEAVE erste neue token vor listen anfang + ELIF ya. ypos > yd. ypos + THEN verkette vorheriges ya mit yd; + ypos index d := yd. naechster ypos index; + LEAVE erste neue token vor listen anfang + FI; + PER; + + . es gibt noch neue token : + ypos index a <> 0 + + . haenge neue token ans ende der sortierten liste : + ypos index d := letzter ypos index d; + yd. naechster ypos index := ypos index a; + ya. vorheriger ypos index := ypos index d; + letzter ypos index d := letzter ypos index a; + ypos index d := letzter ypos index a; + ypos index a := 0; + + . naechste ypos der sortierten liste : + ypos index d := yd. naechster ypos index; + + . neues token auf gleicher ypos : + token index := yd. letzter token index; + t . naechster token index := ya. erster token index; + yd. letzter token index := ya. letzter token index; + ypos index a := ya. naechster ypos index; + ypos index d := yd. naechster ypos index; + IF ypos index d = 0 THEN ypos index d := letzter ypos index d FI; + + . neue token vor ypos : + verkette ya mit vorherigem yd; + REP ypos index a := ya. naechster ypos index; + IF ypos index a = 0 + THEN verkette letztes ya mit yd; + LEAVE sortiere neue token in sortierte liste ein + ELIF ya. ypos = yd. ypos + THEN verkette ya mit yd; + LEAVE neue token vor ypos + ELIF ya. ypos > yd. ypos + THEN verkette vorheriges ya mit yd; + ypos index d := yd. naechster ypos index; + LEAVE neue token vor ypos + FI; + PER; + + +. verkette ya mit vorherigem yd : + index := ypos index d; + ypos index d := yd. vorheriger ypos index; + yd. naechster ypos index := ypos index a; + ya. vorheriger ypos index := ypos index d; + ypos index d := index; + +. verkette letztes ya mit yd : + ypos index a := letzter ypos index a; + yd. vorheriger ypos index := ypos index a; + ya. naechster ypos index := ypos index d; + ypos index a := 0; + +. verkette vorheriges ya mit yd : + index := ypos index a; + ypos index a := ya. vorheriger ypos index; + yd. vorheriger ypos index := ypos index a; + ya. naechster ypos index := ypos index d; + ypos index a := index; + +. verkette ya mit yd : + verkette vorheriges ya mit yd; + neues token auf gleicher ypos; + +END PROC sortiere neue token ein; + +(***************************************************************) + +PROC drucke tokenspeicher + (INT CONST max ypos, + PROC (INT CONST, TEXT CONST, INT CONST, INT CONST) execute) : + +IF druckspeicher ist nicht leer + THEN gehe zur ersten ypos; + WHILE yd. ypos <= max ypos + REP drucke token bei ypos; + gehe zur naechsten ypos; + PER; + loesche gedruckte token; +FI; + +. gehe zur ersten ypos : + ypos index d := erster ypos index d; + +. drucke token bei ypos : + IF yd. ypos >= - y start + THEN druck durchgang; + IF bold pass THEN fett durchgang FI; + IF underline pass THEN unterstreich durchgang FI; + FI; + + . bold pass : bit (pass, bold bit) + + . underline pass : bit (pass, underline bit) + +. gehe zur naechsten ypos : + IF ypos index d = letzter ypos index d + THEN loesche druckspeicher; + LEAVE drucke tokenspeicher; + FI; + ypos index d := yd. naechster ypos index; + +. loesche gedruckte token : + erster ypos index d := ypos index d; + yd. vorheriger ypos index := 0; + +. + druck durchgang : + verschiebung := yd. ypos - d ypos; + y move (PROC (INT CONST, TEXT CONST, INT CONST, INT CONST) execute); + gehe zum ersten token dieser ypos; + REP drucke token UNTIL kein token mehr vorhanden PER; + gib cr aus; + + . drucke token : + IF NOT token passt in zeile THEN berechne token teil FI; + font wechsel wenn noetig; + x move mit modifikations ueberpruefung; + IF token ist text token + THEN gib text token aus + (PROC (INT CONST, TEXT CONST, INT CONST, INT CONST) execute); + ELSE gib kommando token aus + FI; + + . gib kommando token aus : + execute (write cmd, d token. text, 1, LENGTH d token. text) + + . berechne token teil : + INT CONST fuenf punkte := 5 * char pitch (d token. font, punkt); + INT VAR token pos, token breite, anzahl punkte, zeichen laenge, zeichen breite; + IF d token. xpos < - x start + AND d token. xpos + d token. breite > - x start + THEN berechne token teil von links + ELIF d token. xpos < papierbreite + AND d token. xpos + d token. breite > papierbreite + THEN berechne token teil nach rechts + ELSE LEAVE drucke token + FI; + + . berechne token teil von links : + rest := min (x size, d token. xpos + d token. breite + x start); + d token. xpos := - x start; + IF rest <= fuenf punkte + THEN anzahl punkte := rest DIV char pitch (d token. font, punkt); + d token. text := anzahl punkte * punkt; + d token. breite := anzahl punkte * char pitch (d token. font, punkt); + ELSE token pos := LENGTH d token. text + 1; + token breite := fuenf punkte; + berechne token teil breite von hinten; + change (d token. text, 1, token pos - 1, 5 * punkt); + d token. breite := token breite; + FI; + + . berechne token teil breite von hinten : + WHILE naechstes zeichen passt noch davor + REP token breite INCR zeichen breite; + token pos DECR zeichen laenge; + PER; + + . naechstes zeichen passt noch davor : + IF within kanji (d token. text, token pos - 1) + THEN zeichen laenge := 2 + ELSE zeichen laenge := 1 + FI; + zeichen breite := char pitch (d token. font, + subtext (d token. text, token pos - zeichen laenge, token pos - 1)); + token breite + zeichen breite < rest + + . berechne token teil nach rechts : + rest := papier breite - d token. xpos; + IF rest <= fuenf punkte + THEN anzahl punkte := rest DIV char pitch (d token. font, punkt); + d token. text := anzahl punkte * punkt; + d token. breite := anzahl punkte * char pitch (d token. font, punkt); + ELSE token pos := 0; + token breite := fuenf punkte; + berechne token teil breite von vorne; + change (d token. text, token pos + 1, LENGTH d token. text, 5 * punkt); + d token. breite := token breite; + FI; + + . berechne token teil breite von vorne : + WHILE naechstes zeichen passt noch dahinter + REP token breite INCR zeichen breite; + token pos INCR zeichen laenge; + PER; + + . naechstes zeichen passt noch dahinter : + IF is kanji esc (d token. text SUB token pos + 1) + THEN zeichen laenge := 2 + ELSE zeichen laenge := 1 + FI; + zeichen breite := char pitch (d token. font, + subtext (d token. text, token pos + 1, token pos + zeichen laenge)); + token breite + zeichen breite < rest + +. + fett durchgang : + reset bit (pass, bold bit); + gehe zum ersten token dieser ypos; + REP gib token nochmal aus UNTIL kein token mehr vorhanden PER; + schalte modifikationen aus wenn noetig; + gib cr aus; + + . gib token nochmal aus : + INT CONST min verschiebung := bold offset (d token. font); + d token. xpos INCR min verschiebung; + IF bit (d token. modifikationen, bold bit) AND + token passt in zeile AND token ist text token + THEN verschiebung := d token. xpos - d xpos; + font wechsel wenn noetig; + schalte italics ein wenn noetig; + x move wenn noetig; + gib text token aus (PROC (INT CONST, TEXT CONST, INT CONST, INT CONST) execute); + FI; + d token. xpos DECR min verschiebung; + + . schalte italics ein wenn noetig : + IF bit (d token. modifikationen, italics bit) + THEN neue modifikationen := modifikations werte (italics bit + 1); + schalte modifikationen ein wenn noetig; + ELSE schalte modifikationen aus wenn noetig; + FI; + +. + unterstreich durchgang : + INT VAR l xpos := 0; + reset bit (pass, underline bit); + schalte modifikationen aus wenn noetig; + gehe zum ersten token dieser ypos; + REP unterstreiche token UNTIL kein token mehr vorhanden PER; + gib cr aus; + + . unterstreiche token : + IF token muss unterstrichen werden AND + token passt in zeile AND token ist text token + THEN font wechsel wenn noetig; + berechne x move laenge; + x move wenn noetig; + berechne unterstreich laenge; + unterstreiche; + FI; + l xpos := d token. xpos + d token. breite; + + . token muss unterstrichen werden : + bit (d token. modifikationen, underline bit) OR + bit (d token. modifikationen fuer x move, underline bit) + + . berechne x move laenge : + IF bit (d token. modifikationen fuer x move, underline bit) + THEN verschiebung := l xpos - d xpos + ELSE verschiebung := d token. xpos - d xpos + FI; + + . berechne unterstreich laenge : + INT VAR unterstreich verschiebung; + IF bit (d token. modifikationen, underline bit) + THEN unterstreich verschiebung := d token. xpos + + d token. breite - d xpos + ELSE unterstreich verschiebung := d token. xpos - d xpos + FI; + + +. gehe zum ersten token dieser ypos : + token index := yd. erster token index; + d token := t; + +. kein token mehr vorhanden : + token index := d token. naechster token index; + IF token index = 0 + THEN TRUE + ELSE d token := t; + FALSE + FI + +. token ist text token : + d token. offset index >= text token + +. token passt in zeile : + d token. xpos >= - x start AND + d token. xpos + d token. breite <= papier breite + +. font wechsel wenn noetig : + IF d token. font <> d font + THEN font wechsel (PROC (INT CONST, TEXT CONST, INT CONST, INT CONST) execute) FI; + +. schalte modifikationen ein wenn noetig : + IF d modifikationen <> neue modifikationen + THEN schalte modifikationen ein (PROC (INT CONST, TEXT CONST, INT CONST, INT CONST) execute) FI; + +. schalte modifikationen aus wenn noetig : + IF d modifikationen <> 0 + THEN schalte modifikationen aus (PROC (INT CONST, TEXT CONST, INT CONST, INT CONST) execute) FI; + +. x move wenn noetig : + IF verschiebung <> 0 + THEN x move (PROC (INT CONST, TEXT CONST, INT CONST, INT CONST) execute) FI; + +. gib cr aus : + execute (carriage return, "", d xpos, 0); + d xpos := 0; + +. + x move mit modifikations ueberpruefung : + verschiebung := d token. xpos - d xpos; + IF verschiebung <> 0 + THEN neue modifikationen := d token. modifikationen fuer x move; + schalte modifikationen ein wenn noetig; + x move (PROC (INT CONST, TEXT CONST, INT CONST, INT CONST) execute); + FI; + neue modifikationen := d token. modifikationen; + schalte modifikationen ein wenn noetig; + +. + unterstreiche : + IF unterstreich verschiebung > 0 + THEN disable stop; + d xpos INCR unterstreich verschiebung; + execute (draw, "", unterstreich verschiebung, 0); + IF is error + THEN unterstreiche nach cr; + FI; + enable stop; + FI; + + . unterstreiche nach cr : + clear error; + d xpos DECR unterstreich verschiebung; + verschiebung := d xpos; + gib cr aus; + x move (PROC (INT CONST, TEXT CONST, INT CONST, INT CONST) execute); + d xpos INCR unterstreich verschiebung; + execute (draw, "", unterstreich verschiebung, 0); + IF is error + THEN clear error; + d xpos DECR unterstreich verschiebung; + gib cr aus; + LEAVE unterstreich durchgang; + FI; + +END PROC drucke tokenspeicher; + +PROC y move (PROC (INT CONST, TEXT CONST, INT CONST, INT CONST) execute) : + + IF verschiebung <> 0 + THEN disable stop; + d ypos INCR verschiebung; + execute (move, "", 0, verschiebung); + IF is error + THEN clear error; + d ypos DECR verschiebung; + verschiebung := 0; + FI; + enable stop; + FI; + +END PROC y move; + + +PROC x move (PROC (INT CONST, TEXT CONST, INT CONST, INT CONST) execute) : + + disable stop; + d xpos INCR verschiebung; + execute (move, "", verschiebung, 0); + IF is error + THEN fuehre x move nach cr aus + FI; + + . fuehre x move nach cr aus : + clear error; + schalte modifikationen aus wenn noetig; + gib cr aus; + IF d xpos <> 0 + THEN execute (move, "", d xpos, 0); + IF is error + THEN clear error; + d xpos := 0; + FI + FI; + schalte modifikationen ein wenn noetig; + + . gib cr aus : + execute (carriage return, "", d xpos - verschiebung, 0); + + . schalte modifikationen aus wenn noetig : + neue modifikationen := d modifikationen; + IF d modifikationen <> 0 + THEN schalte modifikationen aus + (PROC (INT CONST, TEXT CONST, INT CONST, INT CONST) execute); + FI; + + . schalte modifikationen ein wenn noetig : + IF d modifikationen <> neue modifikationen + THEN schalte modifikationen ein + (PROC (INT CONST, TEXT CONST, INT CONST, INT CONST) execute); + FI; + +END PROC x move; + + +PROC schalte modifikationen ein + (PROC (INT CONST, TEXT CONST, INT CONST, INT CONST) execute) : + + disable stop; + INT VAR index; + IF d modifikationen <> 0 + THEN schalte modifikationen aus + (PROC (INT CONST, TEXT CONST, INT CONST, INT CONST) execute); + FI; + d modifikationen := neue modifikationen; + FOR index FROM 1 UPTO anzahl modifikationen + REP IF bit (d modifikationen, modifikations bit) + THEN modifikation muss eingeschaltet werden + FI; + PER; + + . modifikations bit : index - 1 + + . modifikation muss eingeschaltet werden : + IF bit (modifikations modus, modifikations bit) + THEN execute (on, "", modifikations werte (index), 0); + IF is error + THEN clear error; + reset bit (modifikations modus, modifikations bit); + set bit (pass, modifikations bit); + FI; + ELSE set bit (pass, modifikations bit); + FI; + +END PROC schalte modifikationen ein; + + +PROC schalte modifikationen aus + (PROC (INT CONST, TEXT CONST, INT CONST, INT CONST) execute) : + + disable stop; + INT VAR index; + FOR index FROM 1 UPTO anzahl modifikationen + REP IF bit (d modifikationen, modifikations bit) + THEN modifikation muss ausgeschaltet werden + FI; + PER; + d modifikationen := 0; + + . modifikations bit : index - 1 + + . modifikation muss ausgeschaltet werden : + IF bit (modifikations modus, modifikations bit) + THEN execute (off, "", modifikations werte (index), 0); + IF is error THEN clear error FI; + FI; + +END PROC schalte modifikationen aus; + + +PROC font wechsel + (PROC (INT CONST, TEXT CONST, INT CONST, INT CONST) execute) : + + disable stop; + d font := d token. font; + get replacements (d font, replacements, replacement tabelle); + execute (type, "", d font, 0); + IF is error THEN font wechsel nach cr FI; + enable stop; + + . font wechsel nach cr : + clear error; + verschiebung := d xpos; + gib cr aus; + execute (type, "", d font, 0); + IF NOT is error + THEN schalte modifikationen aus + (PROC (INT CONST, TEXT CONST, INT CONST, INT CONST) execute); + x move + (PROC (INT CONST, TEXT CONST, INT CONST, INT CONST) execute); + FI; + + . gib cr aus : + execute (carriage return, "", d xpos, 0); + d xpos := 0; + +END PROC font wechsel; + + +PROC gib text token aus + (PROC (INT CONST, TEXT CONST, INT CONST, INT CONST) execute) : + + INT CONST token laenge := LENGTH d token. text; + INT VAR token pos := 1, alte token pos, summe := 0; + IF token laenge > 0 + THEN REP alte token pos := token pos; + stranalyze (replacement tabelle, summe, 0, + d token. text, token pos, token laenge, + ausgang); + IF ausgang = 0 + THEN gib token rest aus; + ELSE gib token teil aus; + gib ersatzdarstellung aus; + FI; + PER; + FI; + + . gib token rest aus : + IF token laenge >= alte token pos + THEN execute (write text, d token. text, alte token pos, token laenge) FI; + d xpos INCR d token. breite; + LEAVE gib text token aus; + + . gib token teil aus : + IF token pos >= alte token pos + THEN execute (write text, d token. text, alte token pos, token pos) FI; + + . gib ersatzdarstellung aus : + IF ausgang = maxint + THEN ersatzdarstellung := extended replacement (d token. font, + d token. text SUB token pos + 1, d token. text SUB token pos + 2); + execute (write text, ersatzdarstellung, 1, LENGTH ersatzdarstellung); + tokenpos INCR 3; + ELSE IF ausgang < 0 + THEN ausgang := ausgang XOR (-32767-1); + token pos INCR 1; + FI; + execute (write text, replacements, ausgang + 1, ausgang + code (replacements SUB ausgang)); + token pos INCR 2; + FI; + + . ersatzdarstellung : par1 + +END PROC gib text token aus; + + +PROC schliesse seite ab (PROC (INT CONST, INT CONST) close, + PROC (INT CONST, TEXT CONST, INT CONST, INT CONST) execute) : + +enable stop; +gebe restliche token aus; +seiten ende kommando; + +. gebe restliche token aus : + IF erster ypos index d <> 0 + THEN drucke tokenspeicher (maxint, + PROC (INT CONST, TEXT CONST, INT CONST, INT CONST) execute); + FI; + rest := papier laenge - d ypos; + +. seiten ende kommando : + seite ist offen := FALSE; + a ypos := top margin; + aktuelle spalte := 1; + close (page, rest); + +END PROC schliesse seite ab; + + +PROC eroeffne seite (INT CONST x wanted, y wanted, + PROC (INT CONST, INT VAR, INT VAR) open ) : + +IF vor erster seite THEN eroeffne druck FI; +seiten anfang kommando; +initialisiere neue seite; + +. eroeffne druck : + open (document, x size, y size); + vor erster seite := FALSE; + d font := -1; + d modifikationen := 0; + +. seiten anfang kommando : + x start := x wanted; + y start := y wanted; + open (page, x start, y start); + gedruckte seiten INCR 1; + seite ist offen := TRUE; + +. initialisiere neue seite : + INT CONST dif left margin := x wanted - x start - left margin + indentation, + dif top margin := y wanted - y start - top margin; + IF dif left margin <> 0 + THEN erstes tab token := 1; + verschiebe token xpos (dif left margin); + a xpos INCR dif left margin; + left margin INCR dif left margin; + FI; + IF dif top margin <> 0 + THEN verschiebe token ypos (dif top margin); + a ypos INCR dif top margin; + top margin INCR dif top margin; + FI; + d xpos := 0; + d ypos := 0; + IF seitenlaenge <= papierlaenge + THEN seitenlaenge := top margin + pagelength; + ELSE seitenlaenge DECR papierlaenge; + FI; + papierlaenge := y size - y start; + papierbreite := x size - x start; + +END PROC eroeffne seite; + +(****************************************************************) + +PROC elan fuss und kopf (INT CONST fuss oder kopf, + PROC (INT CONST, INT CONST) close, + PROC (INT CONST, INT VAR, INT VAR) open, + PROC (INT CONST, TEXT CONST, INT CONST, INT CONST) execute) : + +IF fuss oder kopf <= 0 THEN elan fuss FI; +IF fuss oder kopf >= 0 THEN elan kopf FI; + +. + elan fuss : + y move zur fusszeile; + drucke elan fuss; + close page cmd; + +. y move zur fusszeile : + execute (carriage return, "", d xpos, 0); + d xpos := 0; + verschiebung := rest auf seite - font hoehe; + y move (PROC (INT CONST, TEXT CONST, INT CONST, INT CONST) execute); + +. drucke elan fuss : + IF bottom label = "" + THEN seiten nr := "" + ELSE seiten nr := bottom label; + seiten nr CAT "/"; + FI; + seiten nr CAT text (gedruckte seiten); + elan text := seiten nr; + elan text CAT " "; + elan text cat blanks ((max zeichen fuss - LENGTH dateiname) DIV 2 - LENGTH elan text); + elan text CAT dateiname; + elan text cat blanks (max zeichen fuss - LENGTH seiten nr - LENGTH elan text - 3); + elan text CAT " "; + elan text CAT seiten nr; + IF LENGTH elan text > max zeichen zeile + THEN elan text := subtext (elan text, 1, max zeichen zeile) FI; + gib elan text aus (PROC (INT CONST, TEXT CONST, INT CONST, INT CONST) execute); + + . seiten nr : par1 + +. close page cmd : + close (page, papierlaenge - d ypos); + seite ist offen := FALSE; + +. + elan kopf : + open page cmd ; + y move zur kopfzeile; + drucke elan kopf; + +. open page cmd : + x start := x wanted; + y start := y wanted; + open (page, x start, y start); + IF fuss oder kopf = 1 THEN execute (type, "", d font, 0) FI; + gedruckte seiten INCR 1; + seite ist offen := TRUE; + top margin := y wanted - y start; + left margin := x wanted - x start; + rest auf seite := pagelength; + papierlaenge := y size - y start; + d ypos := 0; + d xpos := 0; + +. y move zur kopf zeile : + verschiebung := top margin; + y move (PROC (INT CONST, TEXT CONST, INT CONST, INT CONST) execute); + IF verschiebung = 0 THEN rest auf seite INCR top margin FI; + +. drucke elan kopf : + elan text := headline pre; + elan text CAT date; + elan text CAT headline post; + elan text CAT datei name; + IF LENGTH elan text > max zeichen zeile + THEN elan text := subtext (elan text, 1, max zeichen zeile) FI; + gib elan text aus (PROC (INT CONST, TEXT CONST, INT CONST, INT CONST) execute); + cr plus lf (2, PROC (INT CONST, TEXT CONST, INT CONST, INT CONST) execute); + +ENDPROC elan fuss und kopf; + + +PROC gib elan text aus (PROC (INT CONST, TEXT CONST, INT CONST, INT CONST) execute) : + +cr plus lf (1, PROC (INT CONST, TEXT CONST, INT CONST, INT CONST) execute); +linker rand wenn noetig; +d token. breite := LENGTH elan text * einrueckbreite; +gib text token aus (PROC (INT CONST, TEXT CONST, INT CONST, INT CONST) execute); + +. linker rand wenn noetig : + IF left margin > 0 + THEN disable stop; + d xpos := left margin; + execute (move, "", left margin, 0); + IF is error + THEN clear error; + d xpos := 0; + FI; + enable stop; + FI; + +END PROC gib elan text aus; + + +PROC cr plus lf (INT CONST anzahl, + PROC (INT CONST, TEXT CONST, INT CONST, INT CONST) execute) : + +gib cr aus; +gib lf aus; +rest auf seite DECR verschiebung; + +. gib cr aus : + execute (carriage return, "", d xpos, 0); + d xpos := 0; + +. gib lf aus : + verschiebung := anzahl * font hoehe; + y move (PROC (INT CONST, TEXT CONST, INT CONST, INT CONST) execute); + +END PROC cr plus lf ; + + +END PACKET eumel printer; + diff --git a/system/multiuser/1.7.5/src/font store b/system/multiuser/1.7.5/src/font store new file mode 100644 index 0000000..ebb6a62 --- /dev/null +++ b/system/multiuser/1.7.5/src/font store @@ -0,0 +1,695 @@ +PACKET font store (* Autor : Rudolf Ruland *) + (* Stand : 18.02.86 *) + DEFINES font table, + list font tables, + list fonts, + + x step conversion, + y step conversion, + on string, + off string, + + font, + font exists, + next larger font exists, + next smaller font exists, + font lead, + font height, + font depth, + indentation pitch, + char pitch, + extended char pitch, + replacement, + extended replacement, + font string, + y offsets, + bold offset, + get font, + get replacements : + + +LET font task = "configurator"; + +LET ack = 0, + fetch code = 11, + all code = 17, + + underline = 1, + bold = 2, + italics = 4, + reverse = 8, + + first font = 1, + max fonts = 50, + max extensions = 120, + font table type = 3009, + + FONTTABLE = STRUCT ( + + THESAURUS font names, + + TEXT replacements, font name links, + extension chars, extension indexes, + + ROW 4 TEXT on strings, off strings, + + REAL x unit, y unit, + + ROW 256 INT replacements table, + + INT last font, last extension + + ROW max fonts STRUCT ( + TEXT font string, font name indexes, replacements, + extension chars, extension indexes, y offsets, + ROW 256 INT pitch table, replacements table, + INT indentation pitch, font lead, font height, font depth, + next larger font, next smaller font, bold offset ) fonts , + + ROW max extensions STRUCT ( + TEXT replacements, + ROW 256 INT pitch table, replacements table, + INT std pitch ) extensions , + + ); + +INT VAR font nr, help, reply, list index, last font, + index, char code 1, link nr, font store replacements length; + +TEXT VAR fo table := "", old font table, font name links, buffer; + +THESAURUS VAR font tables, font names; + +INITFLAG VAR in this task := FALSE, + init font ds := FALSE, + init ds := FALSE; + +BOUND FONTTABLE VAR font store; + +BOUND STRUCT (TEXT name, write pass, read pass) VAR msg; + +BOUND THESAURUS VAR all msg; + +BOUND TEXT VAR error msg; + +DATASPACE VAR font ds, ds; + +(*****************************************************************) + +PROC font table (TEXT CONST new font table) : + + disable stop; + get font table (new font table); + in this task := NOT (font table = "" OR type (font ds) <> font table type); + +END PROC font table; + + +PROC get font table (TEXT CONST new font table) : + + enable stop; + buffer := new font table; + change all (buffer, " ", ""); + IF exists (buffer) CAND type (old (buffer)) = font table type + THEN get font table from own task + ELIF exists task (font task) + THEN get font table from font task + ELSE errorstop ("Fonttabelle """ + buffer + """ gibt es nicht") + FI; + + . get font table from own task : + IF NOT initialized (init ds) THEN ds := nilspace FI; + forget (ds); ds := old (buffer); + new font store; + + . get font table from font task : + fetch font table (buffer); + IF type (ds) <> font table type + THEN forget (ds); + errorstop ("Fonttabelle """ + buffer + """ gibt es nicht") + FI; + new font store; + + . new font store : + disable stop; + IF NOT initialized (init font ds) THEN font ds := nilspace FI; + forget (font ds); + font ds := ds; + forget (ds); + font store := font ds; + fo table := buffer; + font names := font store. font names; + font name links := font store. font name links; + last font := font store. last font; + font store replacements length := LENGTH font store. replacements; + +END PROC get font table; + + +TEXT PROC font table : + + fo table + +END PROC font table; + + +PROC list font tables : + + enable stop; + font tables := empty thesaurus; + font tables in own task; + font tables in font task; + note font tables; + note edit; + + . font tables in own task : + list index := 0; + REP get (all, buffer, list index); + IF buffer = "" THEN LEAVE font tables in own task FI; + IF type (old (buffer)) = font table type + AND NOT (font tables CONTAINS buffer) + THEN insert (font tables, buffer) FI; + PER; + + . font tables in font task : + all file names from font task; + THESAURUS CONST names := all msg; + list index := 0; + REP get (names, buffer, list index); + IF buffer = "" + THEN forget (ds); + LEAVE font tables in font task + FI; + fetch font table (buffer); + IF type (ds) = font table type + AND NOT (font tables CONTAINS buffer) + THEN insert (font tables, buffer) FI; + PER; + + . note font tables : + list index := 0; + REP get (font tables, buffer, list index); + IF buffer = "" + THEN LEAVE note font tables; + ELSE note (buffer); note line; + FI; + PER; + +END PROC list font tables; + + +PROC list fonts (TEXT CONST name): + + initialize if necessary; + disable stop; + old font table := font table; + font table (name); + list fonts; + font table (old font table); + +END PROC list fonts; + + +PROC list fonts : + + enable stop; + initialize if necessary; + note font table; + FOR font nr FROM first font UPTO last font REP note font PER; + note edit; + +. note font table : + note ("FONTTABELLE : """); note (font table); note (""";"); noteline; + note (" x einheit = "); note (text (font store. x unit)); note (";"); noteline; + note (" y einheit = "); note (text (font store. y unit)); note (";"); noteline; + +. note font : + cout (font nr); + noteline; + note (" FONT : "); note font names; note (";"); noteline; + note (" einrueckbreite = "); note (text(font. indentation pitch)); note (";"); noteline; + note (" durchschuss = "); note (text(font. font lead)); note (";"); noteline; + note (" fonthoehe = "); note (text(font. font height)); note (";"); noteline; + note (" fonttiefe = "); note (text(font. font depth)); note (";"); noteline; + note (" groesserer font = """); note (next larger); note (""";"); noteline; + note (" kleinerer font = """); note (next smaller); note (""";"); noteline; + + . font : font store. fonts (font nr) + . next larger : name (font store. font names, font. next larger font) + . next smaller : name (font store. font names, font. next smaller font) + + . note font names : + INT VAR index; + note (""""); + note (name (font names, font. font name indexes ISUB 1)); + note (""""); + FOR index FROM 2 UPTO LENGTH font. font name indexes DIV 2 + REP note (", """); + note (name (font names, font. font name indexes ISUB index)); + note (""""); + PER; + +END PROC list fonts; + + +INT PROC x step conversion (REAL CONST cm) : + + initialize if necessary; + IF cm >= 0.0 + THEN int (cm * font store. x unit + 0.5 ) + ELSE int (cm * font store. x unit - 0.5 ) + FI + +END PROC x step conversion; + + +REAL PROC x step conversion (INT CONST steps) : + + initialize if necessary; + real (steps) / font store. x unit + +END PROC x step conversion; + + +INT PROC y step conversion (REAL CONST cm) : + + initialize if necessary; + IF cm >= 0.0 + THEN int (cm * font store. y unit + 0.5 ) + ELSE int (cm * font store. y unit - 0.5 ) + FI + +END PROC y step conversion; + + +REAL PROC y step conversion (INT CONST steps) : + + initialize if necessary; + real (steps) / font store. y unit + +END PROC y step conversion; + + +TEXT PROC on string (INT CONST modification) : + + initialize if necessary; + SELECT modification OF + CASE underline : font store. on strings (1) + CASE bold : font store. on strings (2) + CASE italics : font store. on strings (3) + CASE reverse : font store. on strings (4) + OTHERWISE : errorstop ("unzulaessige Modifikation"); "" + END SELECT + +END PROC on string; + + +TEXT PROC off string (INT CONST modification) : + + initialize if necessary; + SELECT modification OF + CASE underline : font store. off strings (1) + CASE bold : font store. off strings (2) + CASE italics : font store. off strings (3) + CASE reverse : font store. off strings (4) + OTHERWISE : errorstop ("unzulaessige Modifikation"); "" + END SELECT + +END PROC off string; + + +INT PROC font (TEXT CONST font name) : + + initialize if necessary; + buffer := font name; + change all (buffer, " ", ""); + INT CONST link nr := link (font names, buffer) + IF link nr <> 0 + THEN font name links ISUB link nr + ELSE 0 + FI + +END PROC font; + + +TEXT PROC font (INT CONST font number) : + + initialize if necessary; + IF font number >= first font AND font number <= last font + THEN name (font names, fonts. font name indexes ISUB 1) + ELSE "" + FI + + . fonts : font store. fonts (font number) + +END PROC font; + + +BOOL PROC font exists (TEXT CONST font name) : + + font (font name) <> 0 + +END PROC font exists; + + +BOOL PROC next larger font exists(INT CONST font number, + INT VAR next larger font) : + + initialize if necessary; + IF font number >= first font AND font number <= last font + THEN next larger font := fonts. next larger font; + IF next larger font <> 0 + THEN next larger font := font name links ISUB next larger font; + next larger font <> 0 + ELSE FALSE + FI + ELSE errorstop ("Font " + text (font number) + " gibt es nicht"); + FALSE + FI + + . fonts : font store. fonts (font number) + +END PROC next larger font exists; + + +BOOL PROC next smaller font exists (INT CONST font number, + INT VAR next smaller font) : + + initialize if necessary; + IF font number >= first font AND font number <= last font + THEN next smaller font := fonts. next smaller font; + IF next smaller font <> 0 + THEN next smaller font := font name links ISUB next smaller font; + next smaller font <> 0 + ELSE FALSE + FI + ELSE errorstop ("Font " + text (font number) + " gibt es nicht"); + FALSE + FI + + . fonts : font store. fonts (font number) + +END PROC next smaller font exists; + + +INT PROC font lead (INT CONST font number) : + + initialize if necessary; + IF font number >= first font AND font number <= last font + THEN fonts. font lead + ELSE errorstop ("Font " + text (font number) + " gibt es nicht"); 0 + FI + + . fonts : font store. fonts (font number) + +END PROC font lead; + + +INT PROC font height (INT CONST font number) : + + initialize if necessary; + IF font number >= first font AND font number <= last font + THEN fonts. font height + ELSE errorstop ("Font " + text (font number) + " gibt es nicht"); 0 + FI + + . fonts : font store. fonts (font number) + +END PROC font height; + + +INT PROC font depth (INT CONST font number) : + + initialize if necessary; + IF font number >= first font AND font number <= last font + THEN fonts. font depth + ELSE errorstop ("Font " + text (font number) + " gibt es nicht"); 0 + FI + + . fonts : font store. fonts (font number) + +END PROC font depth; + + +INT PROC indentation pitch (INT CONST font number) : + + initialize if necessary; + IF font number >= first font AND font number <= last font + THEN fonts. indentation pitch + ELSE errorstop ("Font " + text (font number) + " gibt es nicht"); 0 + FI + + . fonts : font store. fonts (font number) + +END PROC indentation pitch; + + +INT PROC char pitch (INT CONST font number, + TEXT CONST char ) : + + initialize if necessary; + IF font number >= first font AND font number <= last font + THEN INT CONST pitch := font. pitch table (code (char SUB 1) + 1); + IF pitch = maxint + THEN extended char pitch (font number, char SUB 1, char SUB 2) + ELIF pitch < 0 + THEN pitch XOR (-maxint-1) + ELSE pitch + FI + ELSE errorstop ("Font " + text (font number) + " gibt es nicht"); 0 + FI + + . font : font store. fonts (font number) + +END PROC char pitch; + + +INT PROC extended char pitch (INT CONST font number, + TEXT CONST esc char, char) : + + initialize if necessary; + IF font number >= first font AND font number <= last font + THEN extension. pitch table (code (char) + 1) + ELSE errorstop ("Font " + text (font number) + " gibt es nicht"); 0 + FI + + . font : font store. fonts (font number) + + . extension : font store. extensions (extension number) + + . extension number : + INT CONST index := pos (font. extension chars, esc char); + IF index = 0 + THEN errorstop ("""" + esc char + char + """ hat keine Erweiterung") FI; + font. extension indexes ISUB index + +END PROC extended char pitch; + + +TEXT PROC replacement (INT CONST font number, + TEXT CONST char ) : + + initialize if necessary; + IF font number >= first font AND font number <= last font + THEN link nr := font. replacements table (code (char SUB 1) + 1); + IF link nr = maxint + THEN extended replacement (font number, char SUB 1, char SUB 2) + ELSE process font replacement + FI + ELSE errorstop ("Font " + text (font number) + " gibt es nicht"); "" + FI + + . font : font store. fonts (font number) + + . process font replacement : + IF link nr < 0 THEN link nr := link nr XOR (-maxint-1) FI; + IF link nr = 0 + THEN char + ELIF link nr > font store replacements length + THEN link nr DECR font store replacements length; + replacement text (font. replacements) + ELSE replacement text (font store. replacements) + FI + +END PROC replacement; + + +TEXT PROC extended replacement (INT CONST font number, + TEXT CONST esc char, char ) : + + initialize if necessary; + IF font number >= first font AND font number <= last font + THEN process extension replacement + ELSE errorstop ("Font " + text (font number) + " gibt es nicht"); "" + FI + + . process extension replacement : + determine extension link nr; + IF link nr = 0 + THEN char + ELIF link nr > font store extension replacements length + THEN link nr DECR font store extension replacements length; + replacement text (font extension. replacements) + ELSE replacement text (font store extension. replacements) + FI + + . determine extension link nr : + INT CONST index 1 := pos (font. extension chars, esc char); + INT CONST index 2 := pos (font store. extension chars, esc char); + IF index 1 <> 0 + THEN link nr := font extension. replacements table (code (char) + 1); + ELIF index 2 <> 0 + THEN link nr := font store extension. replacements table (code (char) + 1); + ELSE errorstop ("""" + esc char + char + """ hat keine Erweiterung") + FI; + + . font extension : font store. extensions (font extension number) + + . font extension number : font. extension indexes ISUB index 1 + + . font : font store. fonts (font number) + + . font store extension : font store. extensions (font store extension number) + + . font store extension number : font store. extension indexes ISUB index 2 + + . font store extension replacements length : + IF index 2 = 0 + THEN 0 + ELSE LENGTH font store extension. replacements + FI + +END PROC extended replacement; + + +TEXT PROC replacement text (TEXT CONST replacements) : + + buffer := subtext (replacements, link nr + 1, + link nr + code (replacements SUB link nr)); + buffer + +END PROC replacement text; + + +TEXT PROC font string (INT CONST font number) : + + initialize if necessary; + IF font number >= first font AND font number <= last font + THEN fonts. font string + ELSE errorstop ("Font " + text (font number) + " gibt es nicht"); "" + FI + + . fonts : font store. fonts (font number) + +END PROC font string; + + +TEXT PROC y offsets (INT CONST font number) : + + initialize if necessary; + IF font number >= first font AND font number <= last font + THEN fonts. y offsets + ELSE errorstop ("Font " + text (font number) + " gibt es nicht"); "" + FI + + . fonts : font store. fonts (font number) + +END PROC y offsets; + + +INT PROC bold offset (INT CONST font number) : + + initialize if necessary; + IF font number >= first font AND font number <= last font + THEN fonts. bold offset + ELSE errorstop ("Font " + text (font number) + " gibt es nicht"); 0 + FI + + . fonts : font store. fonts (font number) + +END PROC bold offset; + + +PROC get font (INT CONST font number, + INT VAR indentation pitch, font lead, font height, font depth, + ROW 256 INT VAR pitch table ) : + + initialize if necessary; + IF font number >= first font AND font number <= last font + THEN indentation pitch := fonts. indentation pitch; + pitch table := fonts. pitch table; + font lead := fonts. font lead; + font height := fonts. font height; + font depth := fonts. font depth; + ELSE errorstop ("Font " + text (font number) + " gibt es nicht"); + FI; + + . fonts : font store. fonts (font number) + +END PROC get font; + + +PROC get replacements (INT CONST font number, + TEXT VAR replacements, + ROW 256 INT VAR replacements table) : + + initialize if necessary; + IF font number >= first font AND font number <= last font + THEN replacements := font store. replacements; + replacements CAT fonts. replacements; + replacements table := fonts. replacements table; + ELSE errorstop ("Font " + text (font number) + " gibt es nicht"); + FI; + + . fonts : font store. fonts (font number) + +END PROC get replacements; + + +PROC initialize if necessary : + + IF NOT initialized (in this task) + THEN IF font table = "" + THEN in this task := FALSE; + errorstop ("Fonttabelle noch nicht eingestellt"); + ELSE font table (font table); + FI; + FI; + +END PROC initialize if necessary; + + +PROC fetch font table (TEXT CONST font table name) : + + enable stop; + IF NOT initialized (init ds) THEN ds := nilspace FI; + forget (ds); ds := nilspace; + msg := ds; + msg. name := font table name; + msg. write pass := ""; + msg. read pass := ""; + call (task (font task), fetch code, ds, reply); + IF reply <> ack + THEN errorstop ("Fonttabelle """ + font table name + """ gibt es nicht") + FI; + +END PROC fetch font table; + + +PROC all file names from font task : + + enable stop; + IF NOT initialized (init ds) THEN ds := nilspace FI; + forget (ds); ds := nilspace; + call (task (font task), all code, ds, reply); + IF reply <> ack + THEN error msg := ds; + errorstop (error msg); + ELSE all msg := ds + FI; + +END PROC all file names from font task; + + +END PACKET font store; + diff --git a/system/multiuser/1.7.5/src/global manager b/system/multiuser/1.7.5/src/global manager new file mode 100644 index 0000000..b3d64cc --- /dev/null +++ b/system/multiuser/1.7.5/src/global manager @@ -0,0 +1,683 @@ +(* ------------------- VERSION 19 16.05.86 ------------------- *) +PACKET global manager DEFINES (* Autor: J.Liedtke *) + + ALL , + begin password , + call , + continue channel , + erase , + exists , + fetch , + free global manager , + free manager , + global manager , + list , + manager message , + manager question , + save , + std manager : + + +LET ack = 0 , + nak = 1 , + error nak = 2 , + message ack = 3 , + question ack = 4 , + second phase ack = 5 , + false code = 6 , + + begin code = 4 , + password code = 9 , + fetch code = 11 , + save code = 12 , + exists code = 13 , + erase code = 14 , + list code = 15 , + all code = 17 , + free code = 20 , + continue code = 100, + + + error pre = ""7""13""10""5"FEHLER : " , + cr lf = ""13""10"" ; + +INT VAR reply , order , last order, phase number ; + +DATASPACE VAR ds := nilspace ; + +BOUND STRUCT (TEXT name, write pass, read pass) VAR msg ; +BOUND TEXT VAR reply msg ; +BOUND THESAURUS VAR thesaurus msg ; + +TASK VAR order task, last order task ; + +FILE VAR list file ; + +TEXT VAR error message buffer := "" + ,record + ,received name + ,create son password := "" + ,save file name + ,save write password + ,save read password + ; + + +PROC fetch (TEXT CONST file name) : + + fetch (file name, father) + +ENDPROC fetch ; + +PROC fetch (TEXT CONST file name, TASK CONST manager) : + + enable stop ; + last param (file name) ; + IF NOT exists (file name) + THEN call (fetch code, file name, manager) + ELIF overwrite permitted + THEN call (fetch code, file name, manager) ; + forget (file name, quiet) + ELSE LEAVE fetch + FI ; + IF reply = ack + THEN disable stop ; + copy (ds, file name) ; + forget (ds) + ELSE forget (ds) ; + errorstop ("Task """ + name (manager) + """antwortet nicht mit ack") + FI . + +overwrite permitted : + say ("eigene Datei """) ; + say (file name) ; + yes (""" ueberschreiben") . + +ENDPROC fetch ; + +PROC fetch (DATASPACE VAR dest, TEXT CONST file name, TASK CONST manager) : + + disable stop ; + call (fetch code, file name, manager) ; + dest := ds ; + forget (ds) + +ENDPROC fetch ; + + +PROC save : + + save (last param) + +ENDPROC save ; + +PROC save (TEXT CONST file name) : + + save (file name, father) + +ENDPROC save ; + +PROC save (TEXT CONST file name, TASK CONST manager) : + + last param (file name) ; + call (save code, file name, old (file name), manager) ; + forget (ds) + +ENDPROC save ; + +PROC save (DATASPACE CONST source, TEXT CONST file name, TASK CONST manager): + + call (save code, file name, source, manager) ; + forget (ds) + +ENDPROC save ; + + +BOOL PROC exists (TEXT CONST file name, TASK CONST manager) : + + call (exists code, file name, manager) ; + forget (ds) ; + reply = ack . + +ENDPROC exists ; + + +PROC erase : + + erase (last param) + +ENDPROC erase ; + +PROC erase (TEXT CONST file name) : + + erase (file name, father) + +ENDPROC erase ; + +PROC erase (TEXT CONST file name, TASK CONST manager) : + + call (erase code, file name, manager) ; + forget (ds) + +ENDPROC erase ; + + +PROC list (TASK CONST manager) : + + IF manager = myself + THEN list + ELSE list from manager + FI . + +list from manager : + call (list code, "", manager) ; + IF reply = ack + THEN DATASPACE VAR save ds := ds ; + forget (ds) ; + list file := sequential file (modify, save ds) ; + insert station and name of task in headline if possible ; + show (list file) ; + forget (save ds) + ELSE forget (ds) + FI . + +insert station and name of task in headline if possible : + IF headline (list file) = "" + THEN headline (list file, station number if there is one + + " Task : " + name (manager)) + FI . + +station number if there is one : + IF station (manager) > 0 + THEN "Station : " + text (station (manager)) + ELSE "" + FI . + +ENDPROC list ; + +PROC list (FILE VAR f, TASK CONST manager) : + + IF manager = myself + THEN list (f) + ELSE list from manager + FI . + +list from manager : + call (list code, "", manager) ; + IF reply = ack + THEN DATASPACE VAR save ds := ds ; + forget (ds) ; + list file := sequential file (input, save ds) ; + copy attributes (list file, f) ; + insert station and name of task in headline if possible ; + REP + getline (list file, record) ; + putline (f, record) + UNTIL eof (list file) PER ; + forget (save ds) + ELSE forget (ds) + FI . + +insert station and name of task in headline if possible : + IF headline (list file) = "" + THEN headline (list file, station number if there is one + + " Task : " + name (manager)) + FI . + +station number if there is one : + IF station (manager) > 0 + THEN "Station : " + text (station (manager)) + ELSE "" + FI . + +ENDPROC list ; + +THESAURUS OP ALL (TASK CONST manager) : + + THESAURUS VAR result ; + IF manager = myself + THEN result := all + ELSE get all from manager + FI ; + result . + +get all from manager : + call (all code, "", manager) ; + IF reply = ack + THEN get result thesaurus + ELSE result := empty thesaurus + FI . + +get result thesaurus : + thesaurus msg := ds ; + result := CONCR (thesaurus msg) ; + forget (ds) . + +ENDOP ALL ; + + +PROC call (INT CONST op code, TEXT CONST file name, TASK CONST manager) : + + DATASPACE VAR dummy space ; + call (op code, file name, dummy space, manager) + +ENDPROC call ; + +PROC call (INT CONST op code, TEXT CONST file name, + DATASPACE CONST save space, TASK CONST manager) : + + enable stop ; + send first order first time ; + send second order if required first time ; + WHILE order restart required REP + pause (10) ; + send first order (op code, file name, manager) ; + send second order if required + PER ; + error or message if required . + +send first order first time : + send first order (op code, file name, manager) ; + WHILE order restart required REP + pause (10) ; + send first order (op code, file name, manager) + PER . + +send second order if required first time : + IF reply = question ack + THEN reply msg := ds ; + IF NOT yes (reply msg) + THEN LEAVE call + ELSE send second order (op code, file name, save space, manager) + FI + ELIF reply = second phase ack + THEN send second order (op code, file name, save space, manager) + FI . + +send second order if required : + IF reply = second phase ack OR reply = question ack + THEN send second order (op code, file name, save space, manager) + FI . + +error or message if required : + IF reply = message ack + THEN reply msg := ds ; + say (reply msg) ; + say (cr lf) + ELIF reply = error nak + THEN reply msg := ds ; + errorstop (reply msg) + FI . + +order restart required : reply = nak . + +ENDPROC call ; + +PROC send first order (INT CONST op code, TEXT CONST file name, + TASK CONST manager) : + + forget (ds) ; + ds := nilspace ; + msg := ds ; + msg.name := file name ; + msg.write pass := write password ; + msg.read pass := read password ; + call (manager, op code, ds, reply) ; + IF reply < 0 + THEN errorstop ("Task nicht vorhanden") + FI . + +ENDPROC send first order ; + +PROC send second order (INT CONST op code, TEXT CONST file name, + DATASPACE CONST save space, TASK CONST manager) : + + IF op code = save code + THEN send save space + ELSE send first order (second phase ack, file name, manager) + FI . + +send save space : + forget (ds) ; + ds := save space ; + call (manager, second phase ack, ds, reply) . + +ENDPROC send second order ; + + +PROC global manager : + + global manager + (PROC (DATASPACE VAR, INT CONST, INT CONST, TASK CONST) std manager) + +ENDPROC global manager ; + +PROC free global manager : + + global manager + (PROC (DATASPACE VAR, INT CONST, INT CONST, TASK CONST) free manager) + +ENDPROC free global manager ; + + +PROC global manager (PROC (DATASPACE VAR, + INT CONST, INT CONST, TASK CONST) manager) : + + DATASPACE VAR local ds := nilspace ; + break ; + set autonom ; + disable stop ; + command dialogue (FALSE) ; + remember heap size ; + last order task := niltask ; + REP + forget (local ds) ; + wait (local ds, order, order task) ; + IF order <> second phase ack + THEN prepare first phase ; + manager (local ds, order, phase number, order task) + ELIF order task = last order task + THEN prepare second phase ; + manager (local ds, order, phase number, order task) + ELSE send nak + FI ; + send error if necessary ; + collect heap garbage if necessary + PER . + +prepare first phase : + phase number := 1 ; + last order := order ; + last order task := order task . + +prepare second phase : + phase number INCR 1 ; + order := last order . + +send nak : + forget (local ds) ; + local ds := nilspace ; + send (order task, nak, local ds) . + +send error if necessary : + IF is error + THEN forget (local ds) ; + local ds := nilspace ; + reply msg := local ds ; + CONCR (reply msg) := error message ; + clear error ; + send (order task, error nak, local ds) + FI . + +remember heap size : + INT VAR old heap size := heap size . + +collect heap garbage if necessary : + IF heap size > old heap size + 8 + THEN collect heap garbage ; + old heap size := heap size + FI . + +ENDPROC global manager ; + +PROC std manager (DATASPACE VAR ds, + INT CONST order, phase, TASK CONST order task) : + + IF order task < myself OR order = begin code OR order task = supervisor + THEN free manager (ds, order, phase, order task) + ELSE errorstop ("kein Zugriffsrecht auf Task """ + name (myself) + """") + FI . + +ENDPROC std manager ; + +PROC free manager (DATASPACE VAR ds, + INT CONST order, phase, TASK CONST order task): + + enable stop ; + IF order > continue code AND + order task = supervisor THEN y maintenance + ELIF order = begin code THEN y begin + ELSE file manager order + FI . + +file manager order : + get message text if there is one ; + SELECT order OF + CASE fetch code : y fetch + CASE save code : y save + CASE exists code : y exists + CASE erase code : y erase + CASE list code : y list + CASE all code : y all + OTHERWISE errorstop ("falscher Auftrag fuer Task """+name(myself)+"""") + ENDSELECT . + +get message text if there is one : + IF order >= fetch code AND order <= erase code AND phase = 1 + THEN msg := ds ; + received name := msg.name + FI . + +y begin : + BOUND STRUCT (TEXT tname, tpass, TASK task, PROCA start proc) VAR sv msg := ds ; + IF create son password = sv msg.tpass AND create son password <> "-" + THEN create son task + ELIF sv msg.tpass = "" + THEN ask for password + ELSE errorstop ("Passwort falsch") + FI . + +create son task : + begin (ds, PROC std begin, reply) ; + send (order task, reply, ds) . + +ask for password : + send (order task, password code, ds) . + + +y fetch : + IF read permission (received name, msg.read pass) + THEN forget (ds) ; + ds := old (received name) ; + send (order task, ack, ds) + ELSE errorstop ("Passwort falsch") + FI . + +y erase : + msg := ds ; + received name := msg.name ; + IF NOT exists (received name) + THEN manager message ("""" + received name + """ existiert nicht", order task) + ELIF phase = 1 + THEN manager question ("""" + received name + """ loeschen", order task) + ELIF write permission (received name, msg.write pass) + THEN forget (received name, quiet) ; + send (order task, ack, ds) + ELSE errorstop ("Passwort falsch") + FI . + +y save : + IF phase = 1 + THEN y save pre + ELSE y save post + FI . + +y save pre : + IF write permission (received name, msg.write pass) + THEN save file name := received name ; + save write password := msg.write pass ; + save read password := msg.read pass ; + IF exists (received name) + THEN manager question + ("""" + received name + """ ueberschreiben", order task) + ELSE send (order task, second phase ack, ds) + FI + ELSE errorstop ("Passwort falsch") + FI . + +y save post : + forget (save file name, quiet) ; + copy (ds, save file name) ; + enter password (save file name, save write password, save read password) ; + forget (ds) ; + ds := nilspace ; + send (order task, ack, ds) ; + cover tracks of save passwords . + +cover tracks of save passwords : + replace (save write password, 1, LENGTH save write password * " ") ; + replace (save read password, 1, LENGTH save read password * " ") . + +y exists : + IF exists (received name) + THEN send (order task, ack, ds) + ELSE send (order task, false code, ds) + FI . + +y list : + forget (ds) ; + ds := nilspace ; + list file := sequential file (output, ds) ; + list (list file) ; + send (order task, ack, ds) . + +y all : + BOUND THESAURUS VAR all names := ds ; + all names := all ; + send (order task, ack, ds) . + +y maintenance : + disable stop ; + call (supervisor, order, ds, reply) ; + forget (ds) ; + IF reply = ack + THEN put error message if there is one ; + REP + command dialogue (TRUE) ; + get command ("maintenance :") ; + reset editor ; + do command + UNTIL NOT on line PER ; + command dialogue (FALSE) ; + break ; + set autonom ; + save error message if there is one + FI ; + enable stop . + +put error message if there is one : + IF error message buffer <> "" + THEN out (error pre) ; + out (error message buffer) ; + out (cr lf) ; + error message buffer := "" + FI . + +reset editor : + WHILE aktueller editor > 0 REP + quit + PER ; + clear error . + +save error message if there is one : + IF is error + THEN error message buffer := error message ; + clear error + FI . + +ENDPROC free manager ; + +PROC manager message (TEXT CONST message) : + + forget (ds) ; + ds := nilspace ; + reply msg := ds ; + reply msg := message ; + send (order task, message ack, ds) + +ENDPROC manager message ; + +PROC manager question (TEXT CONST question) : + + forget (ds) ; + ds := nilspace ; + reply msg := ds ; + reply msg := question ; + send (order task, question ack, ds) + +ENDPROC manager question ; + +PROC manager message (TEXT CONST message, TASK CONST receiver) : + + forget (ds) ; + ds := nilspace ; + reply msg := ds ; + reply msg := message ; + send (receiver, message ack, ds) + +ENDPROC manager message ; + +PROC manager question (TEXT CONST question, TASK CONST receiver) : + + forget (ds) ; + ds := nilspace ; + reply msg := ds ; + reply msg := question ; + send (receiver, question ack, ds) + +ENDPROC manager question ; + +PROC std begin : + + do ("monitor") + +ENDPROC std begin ; + +PROC begin password (TEXT CONST password) : + + cover tracks of old create son password ; + create son password := password ; + say (""3""13""5"") ; + cover tracks . + +cover tracks of old create son password : + replace (create son password, 1, LENGTH create son password * " ") . + +ENDPROC begin password ; + + +PROC continue channel (INT CONST channel number) : + + TASK CONST channel owner := task (channel number) ; + IF i am not channel owner + THEN IF NOT is niltask (channel owner) + THEN ask channel owner to release the channel ; + IF channel owner does not release channel + THEN errorstop ("Task """ + name (channel owner) + + """ gibt Kanal " + + text (channel number) + + " nicht frei") + FI + FI ; + continue (channel number) + FI . + +i am not channel owner : + channel <> channel number . + +ask channel owner to release the channel : + forget (ds) ; + ds := nilspace ; + pingpong (channel owner, free code, ds, reply) . + +channel owner does not release channel : + (reply <> ack) AND task exists . + +task exists : + reply <> -1 . + +ENDPROC continue channel ; + + +END PACKET global manager ; + diff --git a/system/multiuser/1.7.5/src/indexer b/system/multiuser/1.7.5/src/indexer new file mode 100644 index 0000000..e60110a --- /dev/null +++ b/system/multiuser/1.7.5/src/indexer @@ -0,0 +1,1142 @@ +(* ------------------- VERSION 59 vom 21.02.86 -------------------- *) +PACKET index program DEFINES outline, + index, + index merge: + +(* Programm zur Behandlung von Indizes aus Druckdateien + Autor: Rainer Hahn + Stand: 1.7.1 (Febr. 1984) + 1.7.4 (Maerz 1985) 'outline' +*) + +LET escape = ""27"", + blank = " ", + trenn k = ""220"", + trennzeichen = ""221"", + minuszeichen = ""45"", + kommando zeichen = "#", + trenner = " ...", + ziffernanfang = "... ", + ziffern = "1234567890", + ib0 = 1, + ib1 = 2, + ib2 = 3, + ie0 = 4, + ie1 = 5, + ie2 = 6, + max indizes = 10, (* !!Anzahl möglichetr Indizes *) + punkt grenze = 50, + leer = 0, + fuellend = 1, + nicht angekoppelt = 2; + +INT VAR seiten nr, + zeilen nr, + erste fehler zeilennr, + zeilen seit index begin, + von, + komm anf, + komm ende, + kommando index, + index nr, + inhalt nr, + anz params, + anz zwischenspeicher, + y richtung; + +BOOL VAR outline modus, + inhaltsverzeichnis offen; + +TEXT VAR dummy, + dummy2, + fehlerdummy, + einrueckung, + akt zeile, + zweite zeile, + akt index, + zweiter index, + zeile, + kommando, + datei name, + kommando liste :: "ib:1.012ie:4.012", + par1, + par2; + +FILE VAR eingabe file, + ausgabe file; + +ROW max indizes FILE VAR f; + +ROW max indizes TEXT VAR zwischenspeicher; + +LET SAMMLER = STRUCT (TEXT index text, + TEXT seitennummer zusatz, + INT zustand); + +ROW max indizes SAMMLER VAR sammler; + +(******************************* outline-Routine **********************) + +PROC outline: + outline (last param) +END PROC outline; + +PROC outline (TEXT CONST eingabe datei): + outline modus := TRUE; + disable stop; + do outline (eingabe datei); + IF is error + THEN put error; + clear error + FI; + enable stop; + IF anything noted + THEN to line (eingabe file, erste fehler zeilennr); + note edit (eingabe file) + ELSE to line (eingabe file, 1); + last param (eingabe datei + ".outline") + FI; + line +END PROC outline; + +PROC do outline (TEXT CONST eingabe datei): + enable stop; + IF exists (eingabe datei) + THEN initialisiere bildschirm; + deaktiviere sammler; + anfrage auf inhaltsverzeichnis; + einrichten fuer zeilennummer ausgabe; + richte dateien ein; + verarbeite datei; + ELSE errorstop ("Datei nicht vorhanden") + FI; + cursor (1, y richtung + 1). + +initialisiere bildschirm: + eingabe file := sequential file (modify, eingabe datei); + page; + put ("OUTLINE"); put ("( für"); put (lines (eingabe file)); put ("Zeilen):"); + put (eingabe datei); + put ("->"); out (eingabe datei); out (".outline"); + cursor (1, 3). + +anfrage auf inhaltsverzeichnis: + put ("Bitte Index-Nr. für Inhaltsverzeichnis:"); + dummy := "9"; + REP + editget (dummy); + inhalt nr := int (dummy); + IF last conversion ok AND inhalt nr > 0 AND inhalt nr < 10 + THEN LEAVE anfrage auf inhaltsverzeichnis + ELSE line; put ("Nr. zwischen 0 und 9, bitte nochmal:") + FI + END REP. + +einrichten fuer zeilennummer ausgabe: + line (2); + INT VAR x; + get cursor (x, y richtung). + +richte dateien ein: + inhaltsverzeichnis offen := FALSE; + anz zwischenspeicher := 0; + einrueckung := ""; + erste fehler zeilennr := 0; + ggf ueberschreibe anfrage (eingabe datei + ".outline"); + ausgabe file := sequential file (output, eingabe datei + ".outline"); + to line (eingabe file, 1); + col (eingabe file, 1). + +verarbeite datei: + REP + suche naechste zeile mit kommandozeichen; + IF pattern found + THEN verarbeite ggf index kommandos + FI; + IF line no (eingabe file) = lines (eingabe file) + THEN LEAVE verarbeite datei + ELSE down (eingabe file); + col (eingabe file, 1) + FI + END REP. + +verarbeite ggf index kommandos: + komm anf := col (eingabe file); + von := komm anf; + REP + WHILE komm anf <> 0 REP + komplettiere alle fuellenden sammler (von, komm anf - 1); + entschluessele kommando; + von := komm ende + 1; + setze kommando um + END REP; + IF alle sammler leer + THEN LEAVE verarbeite ggf index kommandos + ELSE fuelle sammler mit restzeile und lese naechste zeile + FI + UNTIL line no (eingabe file) = lines (eingabe file) END REP. + +setze kommando um: + SELECT kommando index OF + CASE ib0, ib1, ib2: + zeilen seit index begin := 0; + IF anz params = 0 + THEN index nr := 1 + ELSE index nr := int (par1) + FI; + index anfang; + CASE ie0, ie1, ie2: + IF anz params = 0 + THEN index nr := 1 + ELSE index nr := int (par1) + FI; + index ende; + OTHERWISE + END SELECT. + +index anfang: + IF gueltiger index + THEN fange neuen index an + ELSE fehler (18, par1) + FI. + +fange neuen index an: + IF sammler fuellend (index nr) + THEN fehler (20, text (index nr)) + ELIF index ist inhaltsverzeichnis + THEN stelle einrueckung fest; + sammler [index nr] . index text := einrueckung; + einrueckung CAT " "; + inhaltsverzeichnis offen := TRUE + ELIF index ist hauptindex + THEN sammler [index nr] . index text := einrueckung; + ELSE sammler [index nr] . index text := einrueckung; + sammler [index nr] . index text CAT text (index nr); + sammler [index nr] . index text CAT " --> " + FI; + sammler [index nr] . zustand := fuellend. + +stelle einrueckung fest: + einrueckung := ""; + INT VAR punkt pos :: pos (zeile, "."); + WHILE punkt pos <> 0 REP + einrueckung CAT " "; + punkt pos := pos (zeile, ".", punkt pos + 1) + END REP. + +index ende: + IF gueltiger index + THEN IF sammler fuellend (index nr) + THEN IF kommando index = ie2 + THEN sammler [index nr] . index text CAT par2; + FI; + leere sammler in outline datei (index nr) + ELSE fehler (21, text (index nr)) + FI + ELSE fehler (18, text (index nr)) + FI; + sammler [index nr] . zustand := leer. + +index ist inhaltsverzeichnis: + index nr = inhalt nr. + +index ist hauptindex: + index nr = 1. +END PROC do outline; + +PROC leere sammler in outline datei (INT CONST nr): + IF index ist inhaltsverzeichnis + THEN line (ausgabe file); + putline (ausgabe file, sammler [nr] . index text); + inhaltsverzeichnis offen := FALSE; + leere zwischenspeicher + ELIF inhaltsverzeichnis offen + THEN fuelle zwischenspeicher + ELSE putline (ausgabe file, sammler [nr] . index text) + FI; + sammler [nr] . zustand := leer. + +index ist inhaltsverzeichnis: + nr = inhalt nr. + +leere zwischenspeicher: + INT VAR i; + FOR i FROM 1 UPTO anz zwischenspeicher REP + putline (ausgabe file, zwischenspeicher [i]) + END REP; + anz zwischenspeicher := 0. + +fuelle zwischenspeicher: + anz zwischenspeicher INCR 1; + IF anz zwischenspeicher <= max indizes + THEN zwischenspeicher [anz zwischenspeicher] := sammler [nr] . index text + FI. +END PROC leere sammler in outline datei; + +(********************* Utility Routinen *****************************) + +PROC ggf ueberschreibe anfrage (TEXT CONST d): + yrichtung INCR 1; + cursor (1, yrichtung); + IF exists (d) + THEN IF yes (d + " überschreiben") + THEN forget (d, quiet) + ELSE put ("wird angefügt") + FI + FI; + IF outline modus + THEN line + ELSE cursor (7, 3) + FI +END PROC ggf ueberschreibe anfrage; + +BOOL PROC gueltiger index: + last conversion ok AND index nr > 0 AND index nr <= max indizes +END PROC gueltiger index; + +PROC suche naechste zeile mit kommandozeichen: + TEXT VAR steuerzeichen :: incharety; + IF steuerzeichen = escape + THEN errorstop ("Abbruch durch ESC") + FI; + downety (eingabe file, "#", lines (eingabe file)); + read record (eingabe file, zeile); + zeilen nr := line no (eingabe file); + cout (zeilen nr); +END PROC suche naechste zeile mit kommandozeichen; + +PROC entschluessele kommando: + komm ende := pos (zeile, kommando zeichen, komm anf + 1); + IF komm ende <> 0 + THEN hole kommando text; + TEXT CONST kommando anfangs zeichen :: kommando SUB 1; + IF pos ("-/"":*", kommando anfangs zeichen) = 0 + THEN analysiere kommando + FI; + komm anf := pos (zeile, kommando zeichen, komm ende + 1); + ELSE fehler (2, ""); + komm anf := 0; + LEAVE entschluessele kommando + END IF. + +hole kommando text: + kommando := subtext (zeile, komm anf + 1, komm ende - 1). + +analysiere kommando: + kommando index := 0; + analyze command (kommando liste, kommando, 3, + kommando index, anz params, par1, par2); + disable stop; + command error; + IF is error + THEN dummy := error message; + clear error; + dummy CAT " -> "; + dummy CAT kommando; + fehler (22, dummy); + enable stop; + komm anf := 0; + kommando index := 0; + LEAVE entschluessele kommando + END IF; + enable stop +END PROC entschluessele kommando; + +PROC fuelle sammler mit restzeile und lese naechste zeile: + restzeile auffuellen; + naechste zeile und zaehlen; + zeilen seit index begin INCR 1; + von := pos (zeile, ""33"", ""255"", 1); + komm anf := pos (zeile, kommando zeichen, von); + IF zeilen seit index begin > 10 (* !!Anzahl Zeilen!! *) + THEN index aufnahme stoppen; + fehler (17, ""); + LEAVE fuelle sammler mit restzeile und lese naechste zeile + ELIF seitenbegrenzung + THEN index aufnahme stoppen; + fehler (7, ""); + END IF. + +restzeile auffuellen: + IF silbentrennung + THEN IF durch silbentrennung gewandeltes k + THEN replace (zeile, length (zeile) - 1, "c") + FI; + komplettiere alle fuellenden sammler (von, length (zeile) - 1) + ELIF bindestrich + THEN komplettiere alle fuellenden sammler (von, length (zeile)); + ELSE komplettiere alle fuellenden sammler (von, length (zeile)); + zeile := " "; + komplettiere alle fuellenden sammler (1, 1) + END IF. + +silbentrennung: + (zeile SUB length (zeile)) = trennzeichen. + +durch silbentrennung gewandeltes k: + (zeile SUB length (zeile) - 1) = trenn k. + +bindestrich: + (zeile SUB length (zeile)) = minuszeichen AND + (zeile SUB length (zeile) - 1) <> blank. +END PROC fuelle sammler mit restzeile und lese naechste zeile; + +(**************************** index routine *************************) + +PROC index: + index (last param) +END PROC index; + +PROC index (TEXT CONST eingabe datei): + outline modus := FALSE; + last param (eingabe datei); + disable stop; + suche indizes (eingabe datei); + IF is error + THEN put error; + clear error; + FI; + enable stop; + nachbehandlung. + +nachbehandlung: + IF anything noted + THEN to line (eingabe file, erste fehler zeilennr); + note edit (eingabe file) + ELSE to line (eingabe file, 1) + FI; + line. +END PROC index; + +(************************** eigentliche index routine *****************) + +PROC suche indizes (TEXT CONST eingabe datei): + enable stop; + IF exists (eingabe datei) + THEN IF pos (eingabe datei, ".p") = 0 + THEN errorstop ("Datei ist keine Druckdatei") + FI; + eingabe file := sequential file (modify, eingabe datei); + datei name := eingabe datei; + erste fehler zeilennr := 0; + initialisiere bildschirm; + deaktiviere sammler; + verarbeite datei; + sortiere die index dateien; + ELSE errorstop ("Datei existiert nicht") + END IF. + +initialisiere bildschirm: + page; + put ("INDEX"); put ("(für"); put (lines (eingabe file)); put ("Zeilen):"); + put (eingabe datei); + cursor (1, 3); + out ("Zeile: "); + out ("Seite:"); + y richtung := 4; + cursor (7, 3). + +verarbeite datei: + lese bis erste seitenbegrenzung; + WHILE NOT eof (eingabe file) REP + lese bis naechste seitenbegrenzung; + setze seiten nr; + gehe auf erste textzeile zurueck; + verarbeite indizes dieser seite + END REP. + +lese bis erste seitenbegrenzung: + to line (eingabe file, 1); + col (eingabe file, 1); + read record (eingabe file, zeile); + zeilen nr := 1; + cout (1); + REP + IF eof (eingabe file) + THEN errorstop ("Datei ist keine Druckdatei") + ELIF seitenbegrenzung + THEN LEAVE lese bis erste seitenbegrenzung + ELSE naechste zeile und zaehlen + END IF + END REP. + +lese bis naechste seitenbegrenzung: + IF line no (eingabe file) >= lines (eingabe file) + THEN LEAVE verarbeite datei + ELSE down (eingabe file) + FI; + INT VAR erste textzeile := line no (eingabe file); + down (eingabe file, "#page##----", lines (eingabe file)); + IF pattern found + THEN read record (eingabe file, zeile) + ELSE LEAVE verarbeite datei + FI. + +gehe auf erste textzeile zurueck: + to line (eingabe file, erste textzeile); + read record (eingabe file, zeile); + zeilennr := lineno (eingabe file); + cout (zeilennr). + +verarbeite indizes dieser seite: + REP + suche naechste zeile mit kommandozeichen; + IF seitenbegrenzung + THEN LEAVE verarbeite indizes dieser seite + FI; + verarbeite index kommandos der naechsten zeilen; + IF seitenbegrenzung + THEN LEAVE verarbeite indizes dieser seite + FI; + down (eingabe file); + col (eingabe file, 1) + END REP. + +verarbeite index kommandos der naechsten zeilen: + komm anf := col (eingabe file); + von := komm anf; + REP + WHILE komm anf <> 0 REP + komplettiere alle fuellenden sammler (von, komm anf - 1); + entschluessele kommando; + von := komm ende + 1; + setze kommando um + END REP; + IF alle sammler leer + THEN LEAVE verarbeite index kommandos der naechsten zeilen + ELSE fuelle sammler mit restzeile und lese naechste zeile + END IF + UNTIL seitenbegrenzung ENDREP; + fehler (7, ""). + +setze kommando um: +SELECT kommando index OF +CASE ib0, ib1, ib2: + zeilen seit index begin := 0; + IF anz params = 0 + THEN index nr := 1 + ELSE index nr := int (par1) + FI; + index anfang; +CASE ie0, ie1, ie2: + IF anz params = 0 + THEN index nr := 1 + ELSE index nr := int (par1) + FI; + index ende; +OTHERWISE +ENDSELECT. + +index anfang: + IF gueltiger index + THEN fange neuen index an + ELSE fehler (18, par1) + END IF. + +fange neuen index an: + IF sammler fuellend (index nr) + THEN fehler (20, text (index nr)) + ELSE fuelle sammler mit (index nr, ""); + IF anz params = 2 + THEN zusatz an seitennummer (index nr, par2) + ELSE zusatz an seitennummer (index nr, "") + END IF + END IF. + +index ende: + IF gueltiger index + THEN schreibe fuellenden sammler + ELSE fehler (18, text (index nr)) + END IF. + +schreibe fuellenden sammler: + IF sammler fuellend (index nr) + THEN IF anz params = 2 + THEN fuelle sammler mit (index nr, par2) + ENDIF; + schreibe sammler (index nr); + ELSE fehler (21, text (index nr)) + END IF. +END PROC suche indizes; + +(********************* Service Routinen ************************) + +BOOL PROC seitenbegrenzung: + subtext (zeile, 2, 5) = "page" AND subtext (zeile, 8, 12) = "-----" +END PROC seitenbegrenzung; + +PROC setze seiten nr: + seiten nr := int (subtext (zeile, ziffern anfang, ziffernende)); + cursor (20, 3); + put (seiten nr); + cursor (7, 3). + +ziffern anfang: + pos (zeile, "0", "9", 10). + +ziffern ende: + pos (zeile, " ", ziffern anfang) - 1 +END PROC setze seiten nr; + +PROC naechste zeile und zaehlen: + zeilen nr INCR 1; + cout (zeilen nr); + naechste zeile +END PROC naechste zeile und zaehlen; + +PROC naechste zeile: + down (eingabe file); + read record (eingabe file, zeile); + col (eingabe file, 1) +END PROC naechste zeile; + +(**************************** Fehler - Routine *********************) + +PROC fehler (INT CONST nr, TEXT CONST addition): + IF erste fehler zeilennr = 0 + THEN erste fehler zeilennr := zeilen nr + FI; + yrichtung INCR 1; + IF yrichtung > 23 + THEN yrichtung := 23; + FI; + cursor (1, yrichtung); + fehler melden; + fehlermeldung auf terminal ausgeben; + IF outline modus + THEN line + ELSE cursor (7, 3) + FI. + +fehler melden: + report text processing error (nr, zeilen nr, fehlerdummy, addition). + +fehlermeldung auf terminal ausgeben: + out (fehlerdummy); +END PROC fehler; + +PROC warnung (INT CONST nr, TEXT CONST addition): + IF erste fehler zeilennr = 0 + THEN erste fehler zeilennr := zeilen nr + FI; + yrichtung INCR 1; + IF yrichtung > 23 + THEN yrichtung := 23; + FI; + cursor (1, yrichtung); + fehler melden; + meldung auf terminal ausgeben; + IF outline modus + THEN line + ELSE cursor (7, 3) + FI. + +fehler melden: + report text processing warning (nr, zeilen nr, fehlerdummy, addition). + +meldung auf terminal ausgeben: + out (fehlerdummy); +END PROC warnung; + +(************************** Sammler-Dienste **************************) + +PROC index aufnahme stoppen: + zeile := "INDEX FEHLER"; + komplettiere alle fuellenden sammler (1, length (zeile)); + schreibe alle sammler; + read record (eingabe file, zeile) +END PROC index aufnahme stoppen; + +PROC deaktiviere sammler: + INT VAR i; + FOR i FROM 1 UPTO max indizes REP + sammler [i] . zustand := nicht angekoppelt + END REP +END PROC deaktiviere sammler; + +BOOL PROC sammler fuellend (INT CONST nr): + sammler [nr] . zustand = fuellend +END PROC sammler fuellend; + +BOOL PROC sammler angekoppelt (INT CONST nr): + NOT (sammler [nr] . zustand = nicht angekoppelt) +END PROC sammler angekoppelt; + +BOOL PROC alle sammler leer: + INT VAR i; + FOR i FROM 1 UPTO max indizes REP + IF sammler [i] . zustand = fuellend + THEN LEAVE alle sammler leer WITH FALSE + END IF + END REP; + TRUE +END PROC alle sammler leer; + +PROC komplettiere alle fuellenden sammler (INT CONST von pos, bis pos): + INT VAR i; + IF von pos > bis pos + THEN LEAVE komplettiere alle fuellenden sammler + FI; + dummy := subtext (zeile, von pos, bis pos); + FOR i FROM 1 UPTO max indizes REP + IF sammler [i] . zustand = fuellend + THEN sammler [i] . index text CAT dummy; + FI + END REP; +END PROC komplettiere alle fuellenden sammler; + +PROC fuelle sammler mit (INT CONST nr, TEXT CONST dazu): + IF sammler [nr] . zustand = nicht angekoppelt + THEN ankoppeln; + sammler [nr] . index text := dazu + ELIF sammler [nr] . zustand = leer + THEN sammler [nr] . index text := dazu + ELIF sammler fuellend (nr) + THEN sammler [nr] . index text CAT dazu + END IF; + sammler [nr] . zustand := fuellend. + +ankoppeln: + yrichtung INCR 1; + cursor (1, yrichtung); + put ("Indizes"); + put (nr); + put ("gehen in Datei:"); + dummy := datei name; + IF subtext (dummy, length (dummy) - 1) = ".p" + THEN replace (dummy, length (dummy) - 1, ".i") + ELSE dummy CAT ".i"; + END IF; + dummy CAT text (nr); + out (dummy); + ggf ueberschreibe anfrage (dummy); + f [nr] := sequential file (output, dummy); + copy attributes (eingabe file, f[nr]); + cursor (7, 3) +END PROC fuelle sammler mit; + +PROC zusatz an seitennummer (INT CONST nr, TEXT CONST zus text): + sammler [nr] . seitennummer zusatz := zus text +END PROC zusatz an seitennummer; + +PROC schreibe sammler (INT CONST nr): + entferne leading blanks; + IF outline modus + THEN leere sammler in outline datei (nr) + ELSE fuege punkte an; + fuege seiten nr an; + fuege zusatz an seitennummer an; + fuege absatzzeichen an; + leere sammler + FI. + +entferne leading blanks: + WHILE (aufgesammelter text SUB 1) = blank REP + delete char (aufgesammelter text, 1) + END REP. + +fuege punkte an: + aufgesammelter text CAT trenner; + IF length (aufgesammelter text) < punkt grenze + THEN dummy := (punkt grenze - length (aufgesammelter text)) * "."; + aufgesammelter text CAT dummy + END IF; + aufgesammelter text CAT " ". + +fuege seiten nr an: + aufgesammelter text CAT text (seiten nr). + +fuege zusatz an seitennummer an: + aufgesammelter text CAT sammler [nr]. seitennummer zusatz. + +fuege absatzzeichen an: + aufgesammelter text CAT blank. + +leere sammler: + putline (f [nr], aufgesammelter text); + sammler [nr] . zustand := leer. + +aufgesammelter text: + sammler [nr] . index text +END PROC schreibe sammler; + +PROC schreibe alle sammler: + INT VAR i; + FOR i FROM 1 UPTO max indizes REP + IF sammler fuellend (i) + THEN schreibe sammler (i) + END IF + END REP +END PROC schreibe alle sammler; + +(**************** Sortieren und Indizes zusammenfuehren ***************) + +PROC sortiere die index dateien: +INT VAR i; + FOR i FROM 1 UPTO max indizes REP + IF index datei erstellt + THEN sortiere diese datei + END IF + END REP. + +index datei erstellt: + sammler angekoppelt (i). + +sortiere diese datei: + y richtung INCR 1; + cursor (1, yrichtung); + dummy := datei name; + IF subtext (dummy, length (dummy) - 1) = ".p" + THEN replace (dummy, length (dummy) - 1, ".i") + ELSE dummy CAT ".i"; + END IF; + dummy CAT text (i); + put (dummy); + IF yes ("sortieren") + THEN lex sort (dummy); + eintraege zusammenziehen (dummy) + END IF; +END PROC sortiere die index dateien; + +PROC eintraege zusammenziehen (TEXT CONST fname): + FILE VAR sorted file :: sequential file (modify, fname); + INT VAR i :: 1; + to line (sorted file, 1); + read record (sorted file, akt zeile); + akt index := subtext (akt zeile, 1, pos (akt zeile, trenner) - 1); + down (sorted file); + WHILE NOT eof (sorted file) REP + read record (sorted file, zweite zeile); + zweiter index := subtext (zweitezeile, 1, pos (zweitezeile, trenner)-1); + i INCR 1; + cout (i); + IF akt index LEXEQUAL zweiter index + THEN fuege seitennummern von zweite in akt zeile ein + ELSE akt zeile := zweite zeile; + akt index := zweiter index + FI; + down (sorted file) + END REP; + to line (sorted file, 1). + +fuege seitennummern von zweite in akt zeile ein: + hole seitennummer der zweiten zeile; + fuege in akt zeile ein; + delete record (sorted file); + up (sorted file); + write record (sorted file, akt zeile). + +hole seitennummer der zweiten zeile: + INT VAR von := pos (zweite zeile, ziffernanfang) + length (ziffernanfang), + bis := von; + WHILE pos (ziffern, zweite zeile SUB bis) <> 0 REP + bis INCR 1 + END REP; + bis DECR 1; + INT VAR zweite nummer := int( subtext (zweite zeile, von, bis)); + TEXT VAR zweiter nummern text := + subtext (zweite zeile, von, length (zweite zeile) - 1). + +fuege in akt zeile ein: + suche einfuege position in akt zeile; + fuege ein. + +suche einfuege position in akt zeile: + INT VAR einfuege pos := + pos (akt zeile, ziffernanfang) + length (ziffernanfang); + von := einfuege pos; + REP + hole neue nummer; + UNTIL am ende der zeile END REP. + +am ende der zeile: + von >= length (akt zeile). + +hole neue nummer: + bis := von; + WHILE pos (ziffern, akt zeile SUB bis) <> 0 REP + bis INCR 1 + END REP; + bis DECR 1; + IF bis < von + THEN bis := von + FI; + INT VAR neue nummer := int (subtext (akt zeile, von, bis)); + IF zweite nummer = neue nummer + THEN fuege ggf zweiten nummern text mit textanhang ein + ELIF zweite nummer > neue nummer + THEN einfuege pos := von; + von := pos (akt zeile, ", ", bis) + 2; + IF von <= 2 + THEN von := length (akt zeile) + FI + ELSE einfuege pos := von; + LEAVE suche einfuege position in akt zeile + FI. + +fuege ggf zweiten nummern text mit textanhang ein: + bis := pos (akt zeile, ", ", von); + IF bis <= 0 + THEN bis := length (akt zeile); + FI; + IF die beiden nummern sind mit textanhang gleich + THEN LEAVE fuege in akt zeile ein + ELSE einfuege pos := von; + LEAVE suche einfuege position in akt zeile + FI. + +die beiden nummern sind mit textanhang gleich: + zweiter nummern text = subtext (akt zeile, von, bis - 1). + +fuege ein: + IF am ende der zeile + THEN change (akt zeile, length (akt zeile), length (akt zeile), ", "); + akt zeile CAT (zweiter nummern text + " ") + ELSE zweiter nummern text CAT ", "; + change + (akt zeile, einfuege pos, einfuege pos -1, zweiter nummern text); + FI. +END PROC eintraege zusammenziehen; + +(*********************** merge routine *********************) + +PROC index merge (TEXT CONST i1, i2): + disable stop; + indizes zusammenziehen (i1, i2); + IF is error + THEN put error; + clear error; + ELSE last param (i2) + FI; + enable stop; + line. +END PROC index merge; + +PROC indizes zusammenziehen (TEXT CONST i1, i2): + enable stop; + ueberschrift schreiben; + dateien assoziieren; + i1 vor i2 einfuegen; + sortieren; + forget (i1). + +dateien assoziieren: + IF exists (i1) + THEN eingabe file := sequential file (modify, i1) + ELSE errorstop (i1 + "existiert nicht") + END IF; + IF exists (i2) + THEN f[2] := sequential file (modify, i2) + ELSE errorstop (i2 + "existiert nicht") + END IF. + +ueberschrift schreiben: + page; + put ("INDEX MERGE:"); put (i1); put ("-->"); put (i2); + cursor (1, 3); + yrichtung := 3. + +i1 vor i2 einfuegen: + to first record (eingabe file); + to first record (f [2]); + zeilen nr := 0; + WHILE NOT eof (eingabe file) REP + zeilennr INCR 1; + cout (zeilennr); + read record (eingabe file, zeile); + insert record (f [2]); + write record (f[2], zeile); + down (f[2]); + down (eingabe file); + END REP. + +sortieren: + y richtung INCR 1; + cursor (1, yrichtung); + put (i2); + IF yes ("sortieren") + THEN lex sort (i2); + eintraege zusammenziehen (i2) + END IF +END PROC indizes zusammenziehen; +END PACKET index program; + +PACKET columns DEFINES col put, col get, col lineform, col autoform: + +INT VAR ende pos, + anfangs pos; + +FILE VAR file, spaltenfile; + +TEXT VAR dummy, + spalte, + zeile; + +LET geschuetztes blank = ""223"", + blank = " "; + +BOOL VAR spalte loeschen; + +DATASPACE VAR local space := nilspace; + +PROC col lineform: + spalte loeschen := TRUE; + columns put; + file := sequential file (modify, local space); + lineform (spaltenfile); + col get +END PROC col lineform; + +PROC col autoform: + spalte loeschen := TRUE; + columns put; + file := sequential file (modify, local space); + autoform (spaltenfile); + col get +END PROC col autoform; + +PROC col put: + spalte loeschen := yes ("Spalte löschen"); + columns put +END PROC col put; + +PROC columns put: + IF aktueller editor > 0 AND mark + THEN editor bereich bearbeiten + ELSE errorstop ("col put arbeitet nur auf markierten Bereich im Editor") + FI. + +editor bereich bearbeiten: + file := editfile; + anfangs pos einholen; + ende pos einholen; + INT VAR letzte zeile := line no (file), + erste zeile := mark line no (file); + to line (file, erste zeile); + col (file, 1); + spalten put; + to line (file, erste zeile); + col (file, anfangs pos); + mark (false); + ueberschrift neu. + +anfangs pos einholen: + anfangs pos := mark col (file). + +ende pos einholen: + ende pos := col (file) - 1; + IF ende pos < anfangs pos + THEN errorstop ("Markierungsende muß rechts vom -anfang sein") + FI. + +spalten put: + spaltendatei einrichten; + satznr neu; + WHILE line no (file) <= letzte zeile REP + satznr zeigen; + read record (file, zeile); + spalte herausholen; + spalte schreiben; + down (file) + END REP. + +spaltendatei einrichten: + forget (local space); + local space := nilspace; + spaltenfile := sequential file (output, local space). + +spalte herausholen: + spalte := subtext (zeile, anfangs pos, ende pos); + IF spalte loeschen + THEN change (zeile, anfangs pos, ende pos, ""); + write record (file, zeile) + FI; + WHILE length (spalte) > 1 AND (spalte SUB length (spalte)) = blank REP + delete char (spalte, length (spalte)) + END REP; + IF spaltenende ist geschuetztes blank + THEN delete char (spalte, length (spalte)); + spalte CAT " " + FI. + +spalte schreiben: + putline (spaltenfile, spalte). + +spaltenende ist geschuetztes blank: + (spalte SUB length (spalte)) = geschuetztes blank. +END PROC columns put; + +PROC col get: + IF aktueller editor > 0 + THEN editor bereich bearbeiten + ELSE errorstop ("col put kann nur im Editor aufgerufen werden") + FI; + columns get; + alles neu. + +editor bereich bearbeiten: + file := editfile; + spaltenfile := sequential file (input, local space). + +columns get: + anfangs pos := col (file) - 1; + spaltenbreite feststellen; + col (file, 1); + satznr neu; + WHILE NOT eof (spaltenfile) REP + satznr zeigen; + getline (spaltenfile, spalte); + read record (file, zeile); + spalte ggf verbreitern; + zeile ggf verbreitern; + spalte in zeile einfuegen; + zeile schreiben; + down (file); + IF eof (file) + THEN errorstop ("Spalte hat zu viele Zeilen für die Datei") + FI + END REP. + +zeile ggf verbreitern: + WHILE length (zeile) < anfangs pos REP + zeile CAT blank + END REP. + +spaltenbreite feststellen: + INT VAR anz spaltenzeichen :: 0; + WHILE NOT eof (spaltenfile) REP + getline (spaltenfile, spalte); + IF length (spalte) > anz spaltenzeichen + THEN anz spaltenzeichen := length (spalte) + FI + END REP; + spaltenfile := sequential file (input, local space). + +spalte ggf verbreitern: + IF (spalte SUB length (spalte)) = blank + THEN delete char (spalte, length (spalte)); + spalte CAT geschuetztes blank + FI; + IF anzufuegende spalte soll nicht ans zeilenende + THEN spalte verbreitern + FI. + +anzufuegende spalte soll nicht ans zeilenende: + anfangs pos <= length (zeile). + +spalte verbreitern: + WHILE length (spalte) < anz spaltenzeichen REP + spalte CAT blank + END REP. + +spalte in zeile einfuegen: + dummy := subtext (zeile, 1, anfangs pos); + dummy CAT spalte; + dummy CAT subtext (zeile, anfangs pos + 1); + zeile := dummy. + +zeile schreiben: + write record (file, zeile). +END PROC col get; +END PACKET columns; + diff --git a/system/multiuser/1.7.5/src/konfigurieren b/system/multiuser/1.7.5/src/konfigurieren new file mode 100644 index 0000000..016fef2 --- /dev/null +++ b/system/multiuser/1.7.5/src/konfigurieren @@ -0,0 +1,254 @@ +(* ------------------- VERSION 4 22.04.86 ------------------- *) +PACKET konfigurieren DEFINES (* Autor: D.Heinrichs *) + + + + ansi cursor, + baudrate , + bits , + cursor logic , + elbit cursor , + enter incode , + enter outcode , + flow , + input buffer size , + link , + new configuration , + new type , + ysize : + +LET max dtype nr = 5, (* maximum number of active device tables *) + device table = 32000, + ack = 0 ; + + +INT VAR next outstring, + next instring; + +BOUND STRUCT (ALIGN space, (* umsetzcodetabelle *) + ROW 128 INT outcodes, + ROW 64 INT outstrings, + ROW 64 INT instrings) VAR x; + + +ROW max dtype nr DATASPACE VAR device code table; + +THESAURUS VAR dtypes ; + + +PROC new configuration : + + dtypes := empty thesaurus ; + INT VAR i ; + insert (dtypes, "psi", i) ; + insert (dtypes, "transparent", i) ; + FOR i FROM 1 UPTO max dtype nr REP + forget (device code table (i)) + PER . + +ENDPROC new configuration ; + + +PROC block out (DATASPACE CONST ds, INT CONST page, code): + INT VAR err; + block out (ds,page,0,code,err); + announce error (err) +END PROC block out; + +PROC announce error (INT CONST err): + SELECT err OF + CASE 0: + CASE 1: errorstop ("unbekanntes Terminalkommando") + CASE 2: errorstop ("Nummer der Terminal-Typ-Tabelle falsch") + CASE 3: errorstop ("falsche Terminalnummer") + OTHERWISE errorstop ("blockout: unzulaessiger Kanal") + ENDSELECT +END PROC announce error; + +PROC flow (INT CONST nr, INT CONST dtype): + control (6, dtype, nr) +END PROC flow; + +PROC ysize (INT CONST channel ,new size, INT VAR old size) : + control (11, channel, new size, old size) +ENDPROC ysize ; + +PROC input buffer size (INT CONST nr,size): + INT VAR err; + control (2,nr,size,err) +END PROC input buffer size; + +PROC baudrate (INT CONST nr, rate) : + control (8, rate, nr) +ENDPROC baudrate ; + +PROC bits (INT CONST channel, number, parity) : + bits (channel, number-1 + 8*parity) +ENDPROC bits ; + +PROC bits (INT CONST channel, key) : + control (9, key, channel) +ENDPROC bits ; + +PROC control (INT CONST function, key, channel) : + + INT VAR err ; + IF key > -128 AND key < 127 + THEN control (function, channel, key, err) + ELIF key = -128 + THEN control (function, channel, -maxint-1, err) + FI + +ENDPROC control ; + + +PROC new type (TEXT CONST dtype): + x := new (dtype); + type (old (dtype), device table); + next outstring := 4; + next instring := 0; + INT VAR i; + (* Defaults, damit trmpret den cursor mitfuehrt: *) + FOR i FROM 1 UPTO 6 REP + enter outcode (i,i) + PER; + enter outcode (8,8); + enter outcode (10,10); + enter outcode (13,13); + enter outcode (14,126); + enter outcode (15,126); +END PROC new type; + +INT PROC activate dtype (TEXT CONST dtype): + + INT VAR i := link (dtypes, dtype); + IF (exists (dtype) CAND type (old (dtype)) = device table) + THEN IF i <= 0 + THEN insert (dtypes, dtype, i); + FI; + forget(device code table (i-2)); + device code table (i-2) := old (dtype) + FI; + IF i > max dtype nr +2 (* 5 neue Typen erlaubt *) + THEN delete (dtypes,i); + error stop ("Anzahl Terminaltypen > "+text (i));0 + ELIF i <= 0 + THEN error stop ("Unbekannter Terminaltyp" + dtype); 0 + ELSE i + FI. + +END PROC activate dtype; + +PROC link (INT CONST nr, TEXT CONST dtype): + + INT VAR lst nr := activate dtype (dtype)-3; + IF lst nr < 0 + THEN lst nr INCR 256 (* fuer std terminal und std device *) + ELSE blockout (device code table(lst nr+1), 2, lst nr); + FI; + INT VAR err := 0; + control (1,nr,lst nr,err) ; + announce error(err) + +END PROC link; + + +PROC enter outcode (INT CONST eumel code, ziel code): + + IF ziel code < 128 + THEN simple entry (eumel code, ziel code) + ELSE enter outcode (eumel code, 0, code (ziel code)) + FI . + +ENDPROC enter outcode ; + +PROC simple entry (INT CONST eumel code, ziel code) : + + INT CONST position := eumel code DIV 2 +1, + teil := eumel code - 2*position + 2; + TEXT VAR h :=" "; + replace (h,1,out word); + replace (h,1+teil,code (ziel code)); + out word := (h ISUB 1). + + out word: x.outcodes (position). + +END PROC simple entry ; + +PROC enter outcode (INT CONST eumel code, wartezeit, + TEXT CONST sequenz): + + INT VAR i; + simple entry (eumel code, next outstring + 128); + enter part (x.outstrings, next outstring, wartezeit); + FOR i FROM 1 UPTO length (sequenz) REP + enter part (x.outstrings, next outstring + i, code (sequenzSUBi)) + PER; + next outstring INCR length (sequenz)+2; + abschluss. + + abschluss: + enter part (x.outstrings, next outstring-1, 0) +END PROC enter outcode; + +PROC enter outcode (INT CONST eumelcode, TEXT CONST wert): + enter outcode (eumelcode,code(wert)) +END PROC enter outcode; + +PROC enter part (ROW 64 INT VAR a,INT CONST index, wert): + INT CONST position := index DIV 2 +1, + teil := index - 2*position + 2; + IF position > 64 THEN errorstop ("Ueberlauf der Terminaltyptabelle") FI; + TEXT VAR h :=" "; + replace (h,1,out word); + replace (h,1+teil,code (wert)); + out word := (h ISUB 1). + + out word: a (position). +END PROC enter part; + + +PROC enter incode (INT CONST elan code, TEXT CONST sequenz): + IF elan code > 254 OR elan code < 0 THEN errorstop ("kein Eingabecode") + ELSE + INT VAR i; + enter part (x.instrings, next instring, elan code); + FOR i FROM 1 UPTO length (sequenz) REP + enter part (x.instrings, next instring + i, code (sequenzSUBi)) + PER; + next instring INCR length (sequenz)+2; + + FI + +END PROC enter incode; + +PROC cursor logic (INT CONST dist, TEXT CONST pre, mid, post): + + cursor logic (dist,255,pre,mid,post) + +END PROC cursor logic; + +PROC ansi cursor (TEXT CONST pre, mid, post): + + cursor logic (0, 1, pre, mid, post) + +END PROC ansi cursor; + +PROC cursor logic (INT CONST dist, modus, TEXT CONST pre, mid, post): + + enter part (x.outstrings,2,dist); + enter part (x.outstrings,3,dist); + enter part (x.outstrings,0,modus); + enter part (x.outstrings,1,modus); + enter outcode (6,0,pre+""0"y"+mid+""0"x"+post+""0"") + +END PROC cursor logic; + +PROC elbit cursor: + cursor logic (0,""27"","",""); + enter part (x.outstrings,0,2); + enter part (x.outstrings,1,255); +END PROC elbit cursor; + +ENDPACKET konfigurieren; + diff --git a/system/multiuser/1.7.5/src/liner b/system/multiuser/1.7.5/src/liner new file mode 100644 index 0000000..bc1f41d --- /dev/null +++ b/system/multiuser/1.7.5/src/liner @@ -0,0 +1,3079 @@ +(* ------------------- VERSION 406 vom 28.05.86 ----(1.7.5)------------- *) +PACKET liner DEFINES line form, + autoform, + hyphenation width, + additional commands: + +(* Programm zur Zeilenformatierung mit unterschiedlichen Schriftypen + Autor: Rainer Hahn + Stand: 1.7.1 Febr. 1984 + 1.7.3 Juli 1984 + 1.7.4 Juni 1985 + 1.7.5 ab Okt. 1985 + *) + +(********************* form deklarationen ********************) + +TEXT VAR zeichen, + aufzaehlungszeichen, + par 1, + par 2, + kommando, + command store, + zielreferenzen, + herkunftsreferenzen, + aktuelle referenz, + alter schriftname, + dummy, + fehlerdummy, + footdummy, + scan symbol, + font table name :: "", + trennwort, + trennwort ohne komm, + wort1, + wort1 ohne komm, + wort2, + font nr speicher, + modifikations speicher, + mod zeilennr speicher, + index speicher, + ind zeilennr speicher, + counter numbering store, + counter reference store, + trennsymbol, + puffer, + neue zeile, + zeile, + einrueckung zweite zeile, + aktuelle blanks, + alte blanks, + zusaetzliche commands :: "", + kommando liste; + +INT CONST rueckwaerts :: -1, + esc char ohne zweites byte ausgang :: - maxint - 1; + +INT VAR anz tabs, + mitzuzaehlende zeichen, + anz blanks freihalten, + kommando index, + scan type, + font nr :: 1, + blankbreite fuer diesen schrifttyp, + aktuelle pitch zeilenlaenge, + eingestellte indentation pitch, + einrueckbreite, + zeilenbreite, + trennbreite in prozent :: 7, + trennbreite, + max trennlaenge, + max trenn laenge ohne komm, + zeichenwert ausgang, + formelbreite, + formelanfang, + zeilennr, + wortanfang, + wortende, + erste fehler zeilennr, + macro kommando ende, + von, + pufferlaenge, + zeichenpos, + zeichenpos bereits verarbeitet; + +BOOL VAR ask type and limit, + format file in situ, + lineform mode, + macro works, + kommandos speichern, + letzter puffer war absatz, + in d und e verarbeitung, + in tabelle, + in foot uebertrag, + in foot; + +LET hop = ""1"", + rechts = ""2"", + cl eol = ""5"", + links = ""8"", + return = ""13"", + begin mark = ""15"", + end mark = ""14"", + escape = ""27"", + trennzeichen = ""221"", + trenn k = ""220"", + blank = " ", + bindestrich = "-", + buchstaben = + "abcdefghijklmnopqrstuvwxyzüäößABCDEFGHIJKLMNOPQRSTUVWXYZÄÜö", + kommando zeichen = "#", + max tabs = 30, + extended char ausgang = 32767, + blank ausgang = 32766, + kommando ausgang = 32765, + such ausgang = 32764, + zeilenende ausgang = 0, + vorwaerts = 1, + type1 = 1, + linefeed = 3, + limit = 4, + free = 5, + page command0= 6, + page command1= 7, + on = 8, + off = 9, + page nr = 10, + pagelength = 11, + start = 12, + foot = 13, + end = 14, + head = 15, + headeven = 16, + headodd = 17, + bottom = 18, + bottomeven = 19, + bottomodd = 20, + block = 21, + material = 22, + columns = 23, + columnsend = 24, + ib0 = 25, + ib1 = 26, + ib2 = 27, + ie0 = 28, + ie1 = 29, + ie2 = 30, + topage = 31, + goalpage = 32, + count0 = 33, + count1 = 34, + setcount = 35, + value0 = 36, + value1 = 37, + table = 38, + table end = 39, + r pos = 40, + l pos = 41, + c pos = 42, + d pos = 43, + b pos = 44, + clear pos0 = 45, + clear pos1 = 46, + right = 47, + center = 48, + skip = 49, + skip end = 50, + u command = 51, + d command = 52, + e command = 53, + head on = 54, + head off = 55, + bottom on = 56, + bottom off = 57, + count per page=58, + fillchar = 59, + mark command = 60, + mark end = 61, + pageblock = 62, + bsp = 63, + counter1 = 64, + counter2 = 65, + setcounter = 66, + putcounter0 = 67, + putcounter1 = 68, + storecounter = 69, + ub = 70, + ue = 71, + fb = 72, + fe = 73; + +REAL VAR limit in cm :: 16.0, + fehler wert :: -1.0; + +FILE VAR eingabe, + ausgabe, + file; + +FRANGE VAR alter bereich; + +DATASPACE VAR ds; + +ROW 256 INT VAR pitch table; +ROW max tabs TEXT VAR tab zeichen; +ROW max tabs ROW 3 INT VAR tabs; +(* 1. Eintrag: Position + 2. Eintrag: Art + 3. Eintrag: Bis-Position +*) + +(************************** liner state-Routinen **********************) + +TYPE LINERSTATE = + STRUCT (INT position, from, + BOOL in macro, + TEXT buffer line, next line, + old blanks, actual blanks, + new line); + +LINERSTATE VAR before macro state, + before foot state; + +PROC get liner state (LINERSTATE VAR l): + l . position := zeichenpos; + l . from := von; + l . in macro := macro works; + l . buffer line := puffer; + l . next line := zeile; + l . old blanks := alte blanks; + l . actualblanks:= aktuelle blanks; + l . new line := neue zeile; +END PROC get liner state; + +PROC put liner state (LINERSTATE CONST l): + zeichenpos := l . position; + von := l . from; + macro works := l . in macro; + puffer := l . buffer line ; + zeile := l . next line ; + alte blanks := l . old blanks; + aktuelle blanks := l . actual blanks; + neue zeile := l . new line ; + pufferlaenge := length (puffer); +END PROC put liner state; + +(*********************** Utility Routinen **************************) + +PROC delete int (TEXT VAR resultat, INT CONST delete pos) : + change (resultat, delete pos * 2 - 1, delete pos * 2, "") +END PROC delete int; + +OP CAT (TEXT VAR resultat, INT CONST zahl) : + resultat CAT " "; + replace (resultat, LENGTH resultat DIV 2, zahl); +END OP CAT; + +PROC conversion (REAL VAR cm, INT VAR pitches): + disable stop; + INT VAR i :: x step conversion (cm); + IF is error + THEN dummy := error message; + clear error; + dummy CAT " -> "; + dummy CAT text (cm); + fehler (38, dummy); + cm := fehler wert + ELIF i < 0 + THEN fehler (38, "negativ"); + cm := fehler wert + ELSE pitches := i + FI; + enable stop +END PROC conversion; + +(************************** Fehlermeldungen **********************) + +PROC fehler (INT CONST nr, TEXT CONST addition): + fehler melden; + meldung auf terminal ausgeben und ggf zeilennummer merken. + +fehler melden: + report text processing error (nr, zeilen nr, fehlerdummy, addition). +END PROC fehler; + +PROC warnung (INT CONST nr, TEXT CONST addition): + warnung melden; + meldung auf terminal ausgeben und ggf zeilennummer merken. + +warnung melden: + report text processing warning (nr, zeilennr, fehlerdummy, addition). +END PROC warnung; + +PROC meldung auf terminal ausgeben und ggf zeilennummer merken: + IF online + THEN line ; + out (fehlerdummy); + line ; + FI; + IF erste fehler zeilennr = 0 + THEN erste fehler zeilennr := zeilennr + FI +END PROC meldung auf terminal ausgeben und ggf zeilennummer merken; + +(*********************** Macro-Bearbeitung ***********************) + +PROC fuehre initialisierung fuer macro aus: + get liner state (before macro state); + get macro line (puffer); + pufferlaenge := length (puffer); + get macro line (zeile); + zeichenpos := 1; + von := 1; + macro works := TRUE. +END PROC fuehre initialisierung fuer macro aus; + +PROC macro end command: + kommando := subtext (kommando, 2); + scan (kommando); + next symbol (scan symbol, scan type); + IF NOT macro works + THEN fehler (40, kommando); + LEAVE macro end command + ELIF scan symbol <> "macroend" + THEN fehler (33, kommando) + ELSE put liner state (before macro state); + FI +END PROC macro end command; + +(************************** Schrifttyp einstellen *********************) + +PROC stelle font ein: + IF alter schriftname = par1 + THEN IF zeilen nr > 2 + THEN warnung (8, par1) + ELSE LEAVE stelle font ein + FI + ELIF font exists (par1) + THEN font nr := font (par1); + ELSE fehler (1, par1); + par1 := font (1); + font nr := 1 + FI; + alter schriftname := par1; + hole font und stelle trennbreite ein +END PROC stelle font ein; + +PROC hole font: + INT VAR x; (* height Werte *) + get font (font nr, eingestellte indentation pitch, x, x, x, pitch table); + pitch table [code (kommandozeichen) + 1] := kommando ausgang; + blankbreite fuer diesen schrifttyp := pitch table [code (blank) + 1] +END PROC hole font; + +PROC hole font und stelle trennbreite ein: + hole font; + trennbreite setzen +END PROC hole font und stelle trennbreite ein; + +PROC trennbreite setzen: + trennbreite := berechnete trennbreite. + +berechnete trennbreite: + INT VAR eingestellte trennbreite; + conversion (limit in cm, eingestellte trennbreite); + eingestellte trennbreite := eingestellte trennbreite + DIV 100 * trennbreite in prozent; + IF eingestellte trennbreite <= zweimal blankbreite + THEN zweimal blankbreite + ELSE eingestellte trennbreite + FI. + +zweimal blankbreite: + 2 * eingestellte indentation pitch. +END PROC trennbreite setzen; + +PROC hyphenation width (INT CONST prozente): + IF prozente < 4 OR prozente > 20 + THEN putline ("Fehler: Einstellbare Trennbreite zwischen 4 und 20%") + ELSE trennbreite in prozent := prozente + FI +END PROC hyphenation width; + +(************************** kommando verarbeitung ****************) + +PROC additional commands (TEXT CONST k): + zusaetzliche commands := k +END PROC additional commands; + +TEXT PROC additional commands: + zusaetzliche commands +END PROC additional commands; + +BOOL PROC hinter dem kommando steht nix (INT CONST komm ende): + komm ende = pufferlaenge OR absatz hinter dem kommando. + +absatz hinter dem kommando: + komm ende + 1 = pufferlaenge AND puffer hat absatz. +END PROC hinter dem kommando steht nix; + +PROC verarbeite kommando und neue zeile auffuellen: + neue zeile auffuellen (von, zeichenpos - 1); + von := zeichenpos; + verarbeite kommando; + neue zeile auffuellen (von, zeichenpos - 1); + von := zeichenpos +END PROC verarbeite kommando und neue zeile auffuellen; + +PROC speichere kommando: + command store CAT "#"; + command store CAT kommando; + command store CAT "#" +END PROC speichere kommando; + +PROC execute stored commands: + IF length (command store) <> 0 + THEN kommandos speichern := FALSE; + dummy := puffer; + INT VAR zpos := zeichenpos; + zeichenpos := 1; + puffer := command store; + pufferlaenge := length (puffer); + execute commands; + puffer := dummy; + pufferlaenge := length (puffer); + zeichenpos := zpos; + command store := ""; + FI; + kommandos speichern := TRUE. + +execute commands: + WHILE zeichenpos < pufferlaenge REP + verarbeite kommando + END REP. +END PROC execute stored commands; + +PROC verarbeite kommando: +INT VAR anz params, + intparam, + kommando ende; +REAL VAR realparam; + zeichenpos INCR 1; + kommando ende := pos (puffer, kommando zeichen, zeichenpos); + IF kommando ende <> 0 + THEN kommando oder kommentar kommando verarbeiten; + zeichenpos := kommando ende + 1 + ELSE fehler (2, "") + FI. + +kommando oder kommentar kommando verarbeiten: + kommando := subtext (puffer, zeichenpos, kommando ende - 1); + TEXT CONST erstes kommandozeichen :: (kommando SUB 1); + IF pos ("-/"":*", erstes kommandozeichen) = 0 + THEN scanne kommando und fuehre es aus + ELSE restliche kommandos + FI. + +restliche kommandos: + IF erstes kommandozeichen = "-" OR erstes kommandozeichen = "/" + THEN + ELIF erstes kommandozeichen = """" + THEN scan (kommando); + next symbol (scan symbol, scan type); + INT VAR scan type2; + next symbol (scan symbol, scan type2); + IF scan type <> 4 OR scan type2 <> 7 + THEN fehler (58, kommando) + FI + ELIF erstes kommandozeichen = "*" + THEN zeichenpos := kommando ende + 1; + macroend command; + LEAVE verarbeite kommando + ELIF erstes kommandozeichen = ":" + THEN disable stop; + delete char (kommando, 1); + INT CONST line no before do := line no (eingabe); + do (kommando); + to line (eingabe, line no before do); + IF is error + THEN dummy := error message; + clear error; + dummy CAT " -> "; + dummy CAT kommando; + fehler (9, dummy) + FI; + enable stop + FI. + +scanne kommando und fuehre es aus: + analyze command (kommando liste, kommando, 3, + kommando index, anz params, par1, par2); + disable stop ; + command error ; + IF is error + THEN dummy := error message; + clear error; + dummy CAT " -> "; + dummy CAT kommando; + fehler (22, dummy); + enable stop; + LEAVE scanne kommando und fuehre es aus + FI; + enable stop; + setze kommando um. + +setze kommando um: + SELECT kommando index OF + +CASE type1: + stelle font ein; + modifikations speicher := ""; + mod zeilennr speicher := "" + +CASE limit: + realparam := real (par1); + IF kommandos speichern + THEN speichere kommando + ELIF last conversion ok AND pos (par1, ".") <> 0 + THEN IF realparam = 0.0 + THEN fehler (37, "") + ELSE conversion (realparam, aktuelle pitch zeilenlaenge); + IF realparam <> fehlerwert + THEN limit in cm := realparam; + trennbreite setzen + FI + FI + ELSE fehler (4, par1); + FI + +CASE on, ub, fb: + TEXT VAR mod zeichen; + IF kommando index = ub + THEN mod zeichen := "u" + ELIF kommando index = fb + THEN mod zeichen := "b" + ELSE mod zeichen := (par1 SUB 1); + FI; + INT VAR position :: pos (modifikations speicher, mod zeichen); + IF position <> 0 + THEN dummy := mod zeichen + " in Zeile "; + dummy CAT text (mod zeilennr speicher ISUB position); + fehler (54, dummy); + replace (mod zeilennr speicher, position, zeilennr); + ELSE modifikations speicher CAT mod zeichen; + mod zeilennr speicher CAT zeilennr + FI + +CASE off, fe, ue: + IF kommando index = ue + THEN mod zeichen := "u" + ELIF kommando index = fe + THEN mod zeichen := "b" + ELSE mod zeichen := (par1 SUB 1); + FI; + position := pos (modifikations speicher, mod zeichen); + IF position = 0 + THEN fehler (55, mod zeichen) + ELSE delete char (modifikations speicher, position); + delete int (mod zeilennr speicher, position) + FI + +CASE pagenr, pagelength, start, block, material, setcount, right, center, + linefeed: + +CASE head, headodd, headeven, bottom, bottomodd, bottomeven, end, free, + page command0, page command1, columns, columnsend: + IF NOT hinter dem kommando steht nix (kommando ende) + THEN fehler (19, kommando) + ELIF kommando ende = pufferlaenge + THEN IF (neue zeile SUB length (neue zeile)) = blank + THEN delete char (neue zeile, length (neue zeile)) + FI; + puffer CAT blank; + pufferlaenge := length (puffer) + FI; + in foot := FALSE + +CASE foot: + IF in foot uebertrag + THEN zeilenbreite := aktuelle pitch zeilenlaenge + 1 + ELIF in foot + THEN fehler (3, "") + ELSE fuelle ggf zeile vor foot auf (kommando ende) + FI + +CASE ib0, ib1, ib2: + TEXT VAR ind zeichen; + IF kommando index = ib0 + THEN ind zeichen:= "1" + ELSE ind zeichen := par1 + FI; + position := pos (index speicher, ind zeichen); + IF position <> 0 + THEN dummy := ind zeichen + " in Zeile "; + dummy CAT text (ind zeilennr speicher ISUB position); + fehler (56, dummy); + replace (ind zeilennr speicher, position, zeilennr) + ELSE index speicher CAT ind zeichen; + ind zeilennr speicher CAT zeilennr + FI + +CASE ie0, ie1, ie2: + IF kommando index = ie0 + THEN ind zeichen := "1" + ELSE ind zeichen := par1 + FI; + position := pos (index speicher, ind zeichen); + IF position = 0 + THEN fehler (57, ind zeichen) + ELSE delete char (index speicher, position); + delete int (ind zeilennr speicher, position) + FI + +CASE topage, count1: + herkunftsreferenzen speichern; + zeilenbreite um blankbreite erhoehen (3) + +CASE count0: + zeilenbreite um blankbreite erhoehen (3) + +CASE value0, value1: + IF anz params <> 0 + THEN zielreferenzen speichern ohne warnung + FI; + zeilenbreite um blankbreite erhoehen (3) + +CASE goalpage: + zielreferenzen speichern + +CASE table: + IF in tabelle + THEN fehler (41, "") + ELSE IF hinter dem kommando steht nix (kommando ende) + THEN zeichenpos := pufferlaenge; + neue zeile auffuellen und ausgabe bei zeilenende + ELSE neue zeile auffuellen (von, kommando ende); + puffer := subtext (puffer, kommandoende + 1); + schreibe und initialisiere neue zeile + FI; + verarbeite tabelle; + LEAVE verarbeite kommando + FI + +CASE table end: + IF NOT in tabelle + THEN fehler (59, "") + FI + +CASE r pos: + IF kommandos speichern + THEN speichere kommando + ELSE tabulatorposition eintragen (r pos) + FI + +CASE l pos: + IF kommandos speichern + THEN speichere kommando + ELSE tabulatorposition eintragen (l pos) + FI + +CASE c pos: + IF kommandos speichern + THEN speichere kommando + ELSE tabulatorposition eintragen (c pos) + FI + +CASE d pos: + IF kommandos speichern + THEN speichere kommando + ELSE tabulatorposition eintragen (d pos) + FI + +CASE b pos: + IF kommandos speichern + THEN speichere kommando + ELSE tabulatorposition eintragen (b pos) + FI + +CASE clear pos0: + IF kommandos speichern + THEN speichere kommando + ELSE anz tabs := 0; + FI + +CASE clear pos1: + IF kommandos speichern + THEN speichere kommando + ELSE tabulatorposition loeschen + FI + +CASE skip: + IF hinter dem kommando steht nix (kommando ende) + THEN neue zeile auffuellen und ausgabe bei zeilenende + ELSE neue zeile auffuellen (von, kommandoende); + puffer := subtext (puffer, kommandoende + 1); + schreibe und initialisiere neue zeile + FI; + skip zeilen verarbeiten; + kommando ende := zeichenpos; + +CASE skip end: + +CASE u command, d command: + INT VAR next smaller font; + speichere font nr; + IF next smaller font exists (font nr, next smaller font) + THEN font nr := next smaller font + FI; + hole font und stelle trennbreite ein; + IF NOT in d und e verarbeitung + THEN verarbeite index und exponenten; + LEAVE verarbeite kommando + FI + +CASE e command: + entspeichere font nr + +CASE head on, head off, bottom on, bottom off, count per page, fillchar, + mark command, markend, pageblock: + +CASE bsp: + zeichenpos DECR 2; + IF kommandoende = length (puffer) OR + (puffer SUB kommandoende + 1) = kommandozeichen OR + zeichenpos < 1 OR + (puffer SUB zeichenpos) = kommandozeichen + THEN fehler (28, ""); + LEAVE setze kommando um + FI; + begin of this char (puffer, zeichenpos); + kommandoende INCR 1; + INT VAR diese breite :: breite (puffer, zeichenpos), + naechste breite :: breite (puffer, kommandoende); + IF in d und e verarbeitung + THEN formelbreite DECR diese breite; + formelbreite INCR max (diese breite, naechste breite) + ELSE zeilenbreite DECR diese breite; + zeilenbreite INCR max (diese breite, naechste breite) + FI; + zeichenpos := kommandoende; + char pos move (vorwaerts); + LEAVE verarbeite kommando + +CASE counter1, counter2: + dummy := "#"; + dummy CAT par1; + dummy CAT "#"; + IF pos (counter numbering store, dummy) = 0 + THEN fehler (34, par1); + FI; + IF kommando index = counter1 + THEN par2 := "0" + FI; + anz blanks freihalten := 3 + 2 * int (par2); + zeilenbreite um blankbreite erhoehen (anz blanks freihalten) + +CASE set counter: + dummy := "#"; + dummy CAT par1; + dummy CAT "#"; + IF pos (counter numbering store, dummy) = 0 + THEN counter numbering store CAT dummy + ELSE warnung (15, par1) + FI + +CASE put counter0: + zeilenbreite um blankbreite erhoehen (anz blanks freihalten) + +CASE put counter1: + dummy := "#"; + dummy CAT par1; + dummy CAT "#"; + INT VAR begin pos :: pos (counter reference store, dummy); + IF begin pos = 0 + THEN counter reference store CAT "u"; + counter reference store CAT dummy + ELIF (counter reference store SUB begin pos - 1) <> "u" + THEN insert char (counter reference store,"u", max (begin pos, 1)) + FI; + zeilenbreite um blankbreite erhoehen (5) + +CASE store counter: + dummy := "#"; + dummy CAT par1; + dummy CAT "#"; + begin pos := pos (counter reference store, dummy); + IF begin pos <> 0 + THEN IF (counter reference store SUB begin pos - 1) = "i" OR + (counter reference store SUB begin pos - 2) = "i" + THEN fehler (35, par1) + ELIF (counter reference store SUB begin pos - 1) = "u" + THEN insert char (counter reference store, "i", + max (begin pos - 1, 1)) + ELSE insert char (counter reference store, "i", + max (begin pos, 1)) + FI + ELSE counter reference store CAT "i"; + counter reference store CAT dummy + FI + +OTHERWISE + IF macro command and then process parameters (kommando) + THEN IF macro works + THEN fehler (15, kommando) + ELSE zeichenpos := kommando ende + 1; + neue zeile auffuellen (von, zeichenpos - 1); + von := zeichenpos; + fuehre initialisierung fuer macro aus; + LEAVE verarbeite kommando + FI + ELIF zusaetzliche commands <> "" + THEN analyze command (zusaetzliche commands, kommando, 3, + kommando index, anz params, par1, par2); + IF kommando index = 0 + THEN fehler (8, kommando) + FI + ELSE fehler (8, kommando) + FI; +END SELECT. +END PROC verarbeite kommando; + +(************************* Indizes und Exponenten **********************) + +PROC zeilenbreite um blankbreite erhoehen (INT CONST anz): + INT CONST blankbreite mal anz :: anz * eingestellte indentation pitch; + IF in d und e verarbeitung + THEN formelbreite INCR blankbreite mal anz + ELSE zeilenbreite INCR blankbreite mal anz + FI; + mitzuzaehlende zeichen INCR anz +END PROC zeilenbreite um blankbreite erhoehen; + +PROC speichere font nr: + IF index oder exponent anfang + THEN suche wortanfang in neuer zeile; + zeilenbreite DECR formelbreite + FI; + font nr speicher CAT " "; + font nr speicher CAT text (font nr). + +index oder exponent anfang: + font nr speicher = "". + +suche wortanfang in neuer zeile: + auf das letzte zeichen stellen; + WHILE NOT wortanfang vor formel REP + formelbreite INCR breite (neue zeile, formelanfang); + IF formelanfang = 1 + THEN LEAVE suche wortanfang in neuer zeile + FI; + char pos move (neue zeile, formelanfang, rueckwaerts); + END REP; + char pos move (neue zeile, formelanfang, vorwaerts). + +wortanfang vor formel: + pos (" #", neue zeile SUB formelanfang) <> 0. + +auf das letzte zeichen stellen: + formelanfang := length (neue zeile); + formelbreite := 0; + IF formelanfang > 0 + THEN begin of this char (neue zeile, formelanfang); + ELSE formelanfang := 1; + LEAVE suche wortanfang in neuer zeile + FI +END PROC speichere font nr; + +PROC verarbeite index und exponenten: + in d und e verarbeitung := TRUE; + zeichenpos := pos (puffer, kommandozeichen, zeichenpos) + 1; + INT VAR altes zeichenpos := zeichenpos; + verarbeite index oder exponenten zeichen; + fehler (52, ""); + entspeichere font nr. + +verarbeite index oder exponenten zeichen: + REP + stranalyze (pitch table, formelbreite, + aktuelle pitch zeilenlaenge - zeilenbreite, + puffer, zeichenpos, pufferlaenge, zeichenwert ausgang); + IF zeichenwert ausgang = kommando ausgang + THEN verarbeite zeichen vor kommando; + verarbeite kommando und neue zeile auffuellen; + IF NOT in d und e verarbeitung + THEN zeilenbreite INCR formelbreite; + LEAVE verarbeite index und exponenten + FI; + altes zeichenpos := zeichenpos + ELIF zeichenwert ausgang = extended char ausgang + THEN char pos move (vorwaerts); + zeilenbreite INCR breite (puffer, zeichenpos); + char pos move (vorwaerts) + ELIF zeichenpos >= pufferlaenge + AND formelbreite + zeilenbreite < aktuelle pitch zeilenlaenge + THEN LEAVE verarbeite index oder exponenten zeichen + ELIF formelanfang <= 1 + THEN fehler (53, ""); + formelbreite := 0; + ELIF zeichenwert ausgang = esc char ohne zweites byte ausgang + THEN fehler (23, ""); + LEAVE verarbeite index oder exponenten zeichen + ELSE schreibe neue zeile vor formelanfang + FI + END REP. + +verarbeite zeichen vor kommando: + mitzuzaehlende zeichen INCR + number chars (puffer, altes zeichenpos, zeichenpos); + IF (puffer SUB zeichenpos) <> blank + THEN aufzaehlungszeichen := (puffer SUB zeichenpos) + FI; + char pos move (vorwaerts). + +schreibe neue zeile vor formelanfang: + dummy := subtext (neue zeile, formelanfang); + neue zeile := subtext (neue zeile, 1, formelanfang - 1); + loesche nachfolgende blanks; + schreibe und initialisiere neue zeile; + neue zeile CAT dummy; + formelanfang := 1; + char pos move (vorwaerts) +END PROC verarbeite index und exponenten; + +PROC entspeichere font nr: + INT VAR index := length (font nr speicher); + IF index <= 1 + THEN fehler (51, "") + ELSE suche nr anfang; + entspeichere; + FI. + +suche nr anfang: + WHILE (font nr speicher SUB index) <> " " AND index <> 0 REP + index DECR 1 + END REP. + +entspeichere: + font nr := int (subtext (font nr speicher, index + 1)); + IF index <= 1 + THEN font nr speicher := ""; + in d und e verarbeitung := FALSE + ELSE font nr speicher := subtext (font nr speicher, 1, index - 1) + FI; + hole font und stelle trennbreite ein +END PROC entspeichere font nr; + +(*************************** skip zeilen ****************************) + +PROC skip zeilen verarbeiten: + REP + IF dateiende + THEN errorstop ("Dateiende während skip-Anweisung") + ELIF skip ende kommando + THEN LEAVE skip zeilen verarbeiten + FI; + neue zeile auffuellen und ausgabe bei zeilenende + END REP. + +dateiende: + pufferlaenge = 0. + +skip ende kommando: + TEXT VAR kliste :: "skipend:1.0", k; + INT VAR k anf :: pos (puffer, kommandozeichen), + kende, anz params, kindex; + WHILE noch ein kommando vorhanden REP + kindex := 0; + analysiere das kommando + END REP; + FALSE. + +noch ein kommando vorhanden: + kanf <> 0. + +analysiere das kommando: + kende := pos (puffer, kommandozeichen, kanf + 1); + IF kende = 0 + THEN fehler (2, ""); + LEAVE skip ende kommando WITH FALSE + FI; + k := subtext (puffer, kanf + 1, kende - 1); + analyze command (kliste, k, 3, kindex, anz params, par1, par2); + IF kindex = 1 + THEN zeichenpos := kende; + LEAVE skip ende kommando WITH TRUE + FI; + kanf := pos (puffer, kommandozeichen, kende + 1). +END PROC skip zeilen verarbeiten; + +(**************** sonderbehandlung von zeilen vor foot *******************) + +PROC fuelle ggf zeile vor foot auf (INT VAR com ende): + IF foot am zeilenende ohne absatz AND NOT macro works + THEN letzter puffer war absatz := TRUE; + IF text vor foot AND NOT zeile hat richtige laenge + THEN INT VAR foot zeilennr := line no (eingabe); + INT CONST x1 := com ende; + in foot uebertrag := TRUE; + get liner state (before foot state); + formatiere diese zeile; + to line (eingabe, foot zeilennr); + footdummy := neue zeile; + put liner state (before foot state); + neue zeile := footdummy; + com ende := x1; + in foot uebertrag := FALSE + FI + ELIF NOT hinter dem kommando steht nix (com ende) + THEN fehler (19, kommando); + LEAVE fuelle ggf zeile vor foot auf + FI; + in foot := TRUE. + +foot am zeilenende ohne absatz: + com ende = pufferlaenge. + +text vor foot: + pos (neue zeile, ""33"", ""255"", 1) <> 0. + +formatiere diese zeile: + foot anweisung entfernen; + lese eingabe datei bis end kommando; + zeile nach end in zeile; + formatiere; + schreibe die veraenderte zeile nach end. + +foot anweisung entfernen: + zeichenpos := com ende; + ueberspringe das kommando (puffer, zeichenpos, rueckwaerts); + zeichenpos DECR 1; + puffer := subtext (puffer, 1, zeichenpos); + WHILE NOT within kanji (puffer, zeichenpos) AND + (puffer SUB zeichenpos) = blank AND foot stand nicht am zeilenanfang + REP + zeilenbreite DECR breite (blank); + delete char (puffer, zeichenpos); + delete char (neue zeile, length (neue zeile)); + zeichenpos DECR 1 + END REP; + pufferlaenge := length (puffer). + +foot stand nicht am zeilenanfang: + zeichenpos > 0. + +lese eingabe datei bis end kommando: + TEXT VAR kliste :: "end:1.0"; + dummy := zeile; + WHILE NOT foot ende kommando REP + IF eof (eingabe) + THEN LEAVE formatiere diese zeile + FI; + read record (eingabe, dummy); + down (eingabe); + ENDREP; + INT CONST zeile nach end := line no (eingabe); + IF NOT end kommando steht am zeilenende + THEN LEAVE formatiere diese zeile + FI. + +end kommando steht am zeilenende: + k ende = length (dummy) OR k ende + 1 = length (dummy). + +foot ende kommando: + INT VAR k anf, k ende :: 0, anz params, k index; + WHILE noch ein kommando vorhanden REP + k ende := pos (dummy, kommandozeichen, k anf + 1); + IF k ende = 0 + THEN LEAVE foot ende kommando WITH FALSE + ELSE kommando := subtext (dummy, k anf + 1, k ende - 1); + FI; + analyze command (kliste, kommando, 3, kindex, anz params, par1, par2); + IF k index = 1 + THEN LEAVE foot ende kommando WITH TRUE + FI; + END REP; + FALSE. + +noch ein kommando vorhanden: + k anf := pos (dummy, kommandozeichen, k ende + 1); + k anf <> 0. + +zeile nach end in zeile: + read record (eingabe, zeile); + INT VAR text anf := pos (zeile, ""33"", ""255"", 1); + IF zeile nach end ist leerzeile + THEN LEAVE formatiere diese zeile + ELSE IF text anf > 1 + THEN aktuelle blanks := subtext (zeile, 1, text anf - 1); + zeile := subtext (zeile, text anf) + FI; + FI. + +zeile nach end ist leerzeile: + text anf <= 0. + +formatiere: + IF foot stand nicht am zeilenanfang + THEN verarbeite letztes zeichen von puffer + ELSE puffer CAT zeile; + pufferlaenge := length (puffer) + FI; + REP + stranalyze (pitch table, zeilenbreite, aktuelle pitch zeilenlaenge, + puffer, zeichenpos, pufferlaenge, zeichenwert ausgang); + IF zeichenwert ausgang = kommando ausgang + THEN zeichenpos INCR 1; + neue zeile auffuellen (von, zeichenpos - 1); + von := zeichenpos; + INT VAR ende der neuen zeile := length (neue zeile), + zpos davor := zeichenpos; + verarbeite kommando; + neue zeile auffuellen (von, zeichenpos - 1); + von := zeichenpos; + IF kommando index = foot + THEN behandlung der zeile vor foot; + LEAVE formatiere + ELIF zeichenpos >= pufferlaenge + OR zeilenbreite > aktuelle pitch zeilenlaenge + THEN ende einer neuen zeile; + LEAVE formatiere + FI + ELIF zeichenwert ausgang = extended char ausgang + THEN char pos move (vorwaerts); + zeilenbreite INCR breite (puffer, zeichenpos); + char pos move (vorwaerts) + ELIF zeichenwert ausgang = zeilenende ausgang + OR zeichenwert ausgang = esc char ohne zweites byte ausgang + THEN up (eingabe); + delete record (eingabe); + neue zeile auffuellen; + IF zeichenwert ausgang = esc char ohne zweites byte ausgang + THEN fehler (23, "") + FI; + LEAVE formatiere diese zeile + ELSE ende einer neuen zeile; + LEAVE formatiere + FI + END REP. + +behandlung der zeile vor foot: + neue zeile := subtext (neue zeile, 1, ende der neuen zeile); + zeichenpos := zpos davor. + +schreibe die veraenderte zeile nach end: + to line (eingabe, zeile nach end); + dummy := (text anf - 1) * blank; + dummy CAT subtext (puffer, zeichenpos); + IF format file in situ + THEN insert record (eingabe) + FI; + write record (eingabe, dummy). +END PROC fuelle ggf zeile vor foot auf; + +(*************** Tabulator- und Tabellen verarbeitung ******************) + +PROC tabulatorposition eintragen (INT CONST tab type): + ROW 3 INT VAR akt tab pos; + IF anz tabs >= max tabs + THEN fehler (32, "") + ELIF tab in cm umwandeln (par1, tab pos in pitches) + THEN IF tab type = b pos AND tab in cm umwandeln (par2, bis tab) + THEN + ELSE bis tab := 0 + FI; + TEXT VAR zentrierzeichen; + IF tab type = d pos + THEN zentrierzeichen := par2 + ELSE zentrierzeichen := "" + FI; + tabs sortiert eintragen + FI. + +tabs sortiert eintragen: + INT VAR i; + type tab := tab type; + FOR i FROM 1 UPTO anz tabs REP + IF tab pos in pitches = tabs [i] [1] + THEN fehler (42, par1); + LEAVE tabulatorposition eintragen + ELIF tabs [i] [1] > tab pos in pitches + THEN vertauschen + FI; + IF ueberschneidende bpos + THEN fehler (12, text (xstepconversion (tab pos in pitches))) + FI; + END REP; + anz tabs INCR 1; + tabs [anz tabs] := akt tab pos; + tab zeichen [anz tabs] := zentrierzeichen. + +ueberschneidende bpos: + tabs [i] [2] = bpos AND naechste anfang pos liegt in diesem bpos bereich. + +naechste anfang pos liegt in diesem bpos bereich: + tab pos in pitches <= tabs [i] [3]. + +vertauschen: + ROW 3 INT CONST hilf1 :: tabs [i]; + TEXT CONST thilf :: tab zeichen [i]; + tabs [i] := akt tab pos; + tab zeichen [i] := zentrierzeichen; + akt tab pos := hilf1; + zentrierzeichen := thilf. + +tab pos in pitches: + akt tab pos [1]. + +type tab: + akt tab pos [2]. + +bis tab: + akt tab pos [3]. +END PROC tabulatorposition eintragen; + +BOOL PROC tab in cm umwandeln (TEXT CONST text wert, INT VAR f breite): + REAL VAR cm := real (text wert); + IF last conversion ok AND pos (text wert, ".") <> 0 + THEN umwandeln + ELSE fehler (4, par1); + TRUE + FI. + +umwandeln: + conversion (cm, f breite); + IF f breite > aktuelle pitch zeilenlaenge + THEN fehler (39, par1) + ELIF cm = fehlerwert + THEN + ELSE LEAVE tab in cm umwandeln WITH TRUE + FI; + FALSE +END PROC tab in cm umwandeln; + +PROC cm angabe der druckposition in dummy (INT CONST nr): + dummy := text (x step conversion (tabs [nr] [1])); + IF (dummy SUB length (dummy)) = "." + THEN dummy CAT "0" + FI; + dummy CAT " cm" +END PROC cm angabe der druckposition in dummy; + +PROC tabulator position loeschen: + INT VAR tab pos in pitches; + IF tab in cm umwandeln (par1, tab pos in pitches) + THEN versuche zu loeschen + FI. + +versuche zu loeschen: + INT VAR i; + FOR i FROM 1 UPTO anz tabs REP + IF tab pos in pitches = tabs [i] [1] + THEN verschiebe eintraege nach unten; + LEAVE tabulator position loeschen + FI + END REP; + fehler (43, par1). + +verschiebe eintraege nach unten: + INT VAR k; + FOR k FROM i UPTO anz tabs - 1 REP + tabs [k] := tabs [k + 1]; + tab zeichen [k] := tab zeichen [k + 1]; + END REP; + anz tabs DECR 1. +END PROC tabulatorposition loeschen; + +PROC verarbeite tabelle: + in tabelle := TRUE; + pitch table auf blank ausgang setzen; + verarbeite tabellenzeilen; + pitch table auf blank setzen; + IF suchausgang gesetzt + THEN pitch table [pos tab zeichen in pitch table] := + breite erstes dezimalzeichen; + suchausgang gesetzt := FALSE; + FI; + in tabelle := FALSE. + +verarbeite tabellenzeilen: + WHILE pufferlaenge <> 0 REP + ueberpruefe tabellenzeile; + zeichenpos := pufferlaenge; + neue zeile auffuellen und ausgabe bei zeilenende + END REP; + puffer := " "; + pufferlaenge := 1; + zeichenpos := 1; + fehler (49, ""). + +ueberpruefe tabellenzeile: +(* Achtung: Zeilenbreite ist Spaltenbreite; + tab zeilen breite ist Summe der Spalten und Positionen *) + INT VAR tab zeilen breite :: 0, + tab no :: 1; + WHILE noch tab positionen OR only command line (puffer) REP + positioniere auf naechste spalte; + errechne spaltenbreite; + IF anz tabs > 0 + THEN ueberpruefe ob es passt; + FI; + tab no INCR 1 + END REP; + IF tabellenzeile breiter als limit + THEN warnung (10, "") + ELIF noch mehr spaltentexte AND anz tabs <> 0 + THEN warnung (11, subtext (puffer, zeichenpos)) + FI. + +noch tab positionen: + tab no <= anz tabs. + +positioniere auf naechste spalte: + zeichenpos := pos (puffer, ""33"", ""255"", zeichenpos); + IF leerzeile oder rest der zeile ist leer + THEN IF NOT only command line (puffer) AND pufferlaenge > 1 + THEN warnung (14, "") + FI; + LEAVE ueberpruefe tabellenzeile + FI. + +leerzeile oder rest der zeile ist leer: + zeichenpos <= 0. + +errechne spaltenbreite: + zeilenbreite := 0; + BOOL VAR suchausgang gesetzt :: FALSE; + IF diese position ist dezimal pos + THEN setze dezimalzeichen auf suchausgang + FI; + REP + stranalyze (pitch table, zeilenbreite, aktuelle pitch zeilenlaenge, + puffer, zeichenpos, pufferlaenge, zeichenwert ausgang); + zeichenpos INCR 1; + IF zeichenwert ausgang = blank ausgang + THEN behandele dieses blank + ELIF zeichenwert ausgang = kommando ausgang + THEN verarbeite das kommando + ELIF zeichenwert ausgang = extended char ausgang + THEN char pos move (vorwaerts); + zeilenbreite INCR breite (puffer, zeichenpos); + char pos move (vorwaerts) + ELIF zeichenwert ausgang = such ausgang + THEN verarbeite ersten teil der dezimal zentrierung + ELIF zeichenwert ausgang = esc char ohne zweites byte ausgang + THEN fehler (23, ""); + LEAVE ueberpruefe tabellenzeile + ELIF zeilenbreite + zeichenwert ausgang > aktuelle pitch zeilenlaenge + THEN fehler (36, ""); + LEAVE ueberpruefe tabellenzeile + ELSE tabellenzeile ohne absatz + FI + END REP. + +diese position ist dezimal pos: + tabs [tab no] [2] = dpos. + +setze dezimalzeichen auf suchausgang: + INT CONST pos tab zeichen in pitch table :: + code (tab zeichen [tab no] SUB 1) + 1; + INT VAR breite erstes dezimalzeichen :=breite (tab zeichen [tab no] SUB 1), + breite excl dezimalzeichen := 0; + suchausgang gesetzt := TRUE; + pitch table [pos tab zeichen in pitch table] := such ausgang. + +verarbeite ersten teil der dezimal zentrierung: + IF pos (puffer, tab zeichen [tab no], zeichenpos) = zeichenpos + THEN pitch table [pos tab zeichen in pitch table] := + breite erstes dezimalzeichen; + suchausgang gesetzt := FALSE; + breite excl dezimalzeichen := zeilenbreite + FI; + zeilenbreite INCR breite (puffer SUB zeichenpos); + zeichenpos INCR 1. + +behandele dieses blank: + IF doppelblank OR absatz + THEN LEAVE errechne spaltenbreite + ELSE zeilenbreite INCR blankbreite fuer diesen schrifttyp; + zeichenpos INCR 1 + FI. + +doppelblank: + (puffer SUB zeichenpos + 1) = blank. + +verarbeite das kommando: + pitch table auf blank setzen; + verarbeite kommando und neue zeile auffuellen; + pitch table auf blank ausgang setzen; + IF kommando index = table end + THEN LEAVE verarbeite tabellenzeilen + ELIF suchausgang gesetzt AND + pitch table [pos tab zeichen in pitch table] <> suchausgang + THEN pitch table [pos tab zeichen in pitch table] := suchausgang + FI. + +tabellenzeile ohne absatz: + IF zeilenende eines macros + THEN zeile in puffer und zeile lesen; + zeichenpos := pos (puffer, ""33"", ""255"", zeichenpos); + ELSE LEAVE errechne spaltenbreite + FI. + +zeilenende eines macros: + zeichenwert ausgang = zeilenende ausgang AND macro works. + +ueberpruefe ob es passt: + INT CONST akt tab pos :: tabs [tab no] [1]; + IF vorherige spalte ueberschreibt tabulator position + THEN cm angabe der druckposition in dummy (tab no - 1); + fehler (44, dummy); + tab zeilenbreite := akt tab pos + ELIF only command line (puffer) + THEN + ELSE ueberpruefe nach art des tabulators + FI. + +ueberpruefe nach art des tabulators: + IF tabs [tab no] [2] = r pos + THEN nach links schreibend + ELIF tabs [tab no] [2] = l pos + THEN nach rechts schreibend + ELIF tabs [tab no] [2] = b pos + THEN nach rechts blockend schreibend + ELIF tabs [tab no] [2] = c pos + THEN zentrierend + ELSE zentrierend um zeichen + FI. + +vorherige spalte ueberschreibt tabulator position: + tab zeilenbreite > akt tab pos. + +nach links schreibend: + IF tab zeilenbreite + zeilenbreite > akt tab pos + THEN cm angabe der druckposition in dummy (tab no); + fehler (45, dummy); + FI; + tab zeilenbreite := akt tab pos. + +nach rechts schreibend: + tab zeilenbreite := akt tab pos + zeilenbreite. + +nach rechts blockend schreibend: + IF akt tab pos + zeilenbreite > tabs [tab no] [3] + THEN cm angabe der druckposition in dummy (tab no); + fehler (48, dummy) + FI; + tab zeilenbreite := tabs [tab no] [3]. + +zentrierend: + IF tab zeilenbreite + (zeilenbreite DIV 2) > akt tab pos + THEN cm angabe der druckposition in dummy (tab no); + fehler (46, dummy) + FI; + tab zeilenbreite := akt tab pos + (zeilenbreite DIV 2). + +zentrierend um zeichen: + IF breite excl dezimalzeichen = 0 + THEN cm angabe der druckposition in dummy (tab no); + fehler (50, dummy) + ELIF tab zeilenbreite + breite excl dezimalzeichen > akt tab pos + THEN cm angabe der druckposition in dummy (tab no); + fehler (47, dummy) + FI; + IF suchausgang gesetzt + THEN pitch table [pos tab zeichen in pitch table] := + breite erstes dezimalzeichen; + suchausgang gesetzt := FALSE; + FI; + tab zeilenbreite := akt tab pos + + (zeilenbreite - breite excl dezimalzeichen). + +tabellenzeile breiter als limit: + tab zeilenbreite > aktuelle pitch zeilenlaenge + einrueckbreite. + +noch mehr spaltentexte: + pos (puffer, ""33"", ""255"", zeichenpos) <> 0. +END PROC verarbeite tabelle; + +(*********************** referenzen ueberpruefen **********************) + +PROC aktuelle referenz erstellen: + aktuelle referenz := "#"; + aktuelle referenz CAT par1; + aktuelle referenz CAT "#"; +END PROC aktuelle referenz erstellen; + +PROC zielreferenzen speichern ohne warnung: + aktuelle referenz erstellen; + IF pos (zielreferenzen, aktuelle referenz) = 0 + THEN delete char (aktuelle referenz, 1); + zielreferenzen CAT aktuelle referenz + FI +END PROC zielreferenzen speichern ohne warnung; + +PROC zielreferenzen speichern: + aktuelle referenz erstellen; + IF pos (zielreferenzen, aktuelle referenz) <> 0 + THEN warnung (9, par1) + ELSE delete char (aktuelle referenz, 1); + zielreferenzen CAT aktuelle referenz + FI +END PROC zielreferenzen speichern; + +PROC herkunftsreferenzen speichern: + aktuelle referenz erstellen; + IF pos (herkunftsreferenzen, aktuelle referenz) = 0 + THEN delete char (aktuelle referenz, 1); + herkunftsreferenzen CAT aktuelle referenz + FI +END PROC herkunftsreferenzen speichern; + +PROC referenzen ueberpruefen: + ueberpruefe zielreferenzen; + ueberpruefe restliche herkunftsreferenzen. + +ueberpruefe zielreferenzen: + REP + hole naechste zielreferenz; + IF pos (herkunfts referenzen, aktuelle referenz) = 0 + THEN change all (aktuelle referenz,"#", ""); + warnung (3, aktuelle referenz) + ELSE delete char (aktuelle referenz, length (aktuelle referenz)); + change (herkunftsreferenzen, aktuelle referenz, ""); + FI + END REP. + +hole naechste zielreferenz: + IF length (zielreferenzen) > 1 + THEN aktuelle referenz := + subtext (zielreferenzen, 1, pos (zielreferenzen, "#", 2)); + zielreferenzen := + subtext (zielreferenzen, pos (zielreferenzen, "#", 2)) + ELSE LEAVE ueberpruefe zielreferenzen + FI. + +ueberpruefe restliche herkunftsreferenzen: + WHILE length (herkunftsreferenzen) > 1 REP + aktuelle referenz := + subtext (herkunftsreferenzen, 1, pos (herkunftsreferenzen, "#", 2) - 1); + change (herkunftsreferenzen, aktuelle referenz, ""); + delete char (aktuelle referenz, 1); + warnung (4, aktuelle referenz) + END REP. +END PROC referenzen ueberpruefen; + +(*************************** Utilities *******************************) + +INT PROC breite (TEXT CONST z): + INT VAR b; + IF z = "" + THEN display and pause (1) + ELIF z = kommandozeichen + THEN display and pause (2); b := 1 + ELSE b := pitch table [code (z) + 1] + FI; + IF zeilenbreite > maxint - b + THEN display and pause (3); b := 1 + FI; + b. +END PROC breite; + +INT PROC breite (TEXT CONST ein text, INT CONST zpos): + TEXT CONST z :: ein text SUB zpos; + INT VAR zeichen breite; + IF z = "" + THEN display and pause (4); zeichen breite := 1 + ELIF z = kommandozeichen + THEN display and pause (6); zeichen breite := 1 + ELSE zeichen breite := pitch table [code (z) + 1] + FI; + IF zeichen breite = extended char ausgang + THEN zeichen breite := extended char pitch (font nr, + ein text SUB zpos, ein text SUB zpos + 1) + FI; + zeichen breite +END PROC breite; + +PROC char pos move (INT CONST richtung): + char pos move (zeichenpos, richtung) +END PROC char pos move; + +PROC char pos move (INT VAR zpos, INT CONST richtung): + char pos move (puffer, zpos, richtung) +END PROC char pos move; + +BOOL PROC absatz: + zeichenpos = pufferlaenge AND puffer hat absatz +END PROC absatz; + +BOOL PROC puffer hat absatz: + NOT within kanji (puffer, pufferlaenge) AND + (puffer SUB pufferlaenge) = blank +END PROC puffer hat absatz; + +PROC pitch table auf blank ausgang setzen: + IF pitch table [code (blank) + 1] <> blank ausgang + THEN blank breite fuer diesen schrifttyp := breite (blank); + pitch table [code (blank) + 1] := blank ausgang + FI +END PROC pitch table auf blank ausgang setzen; + +PROC pitch table auf blank setzen: + pitch table [code (blank) + 1] := blank breite fuer diesen schrifttyp +END PROC pitch table auf blank setzen; + +(*PROC zustands test (TEXT CONST anf): +line ;put(anf); +line ;put("zeilenbreite, aktuelle pitch zeilenlaenge:"); + put(zeilenbreite);put(aktuelle pitch zeilenlaenge); +line ;put("zeichenpos, pufferlaenge, ausgang, zeichen:"); +put(zeichenpos);put(pufferlaenge); +IF zeichenwert ausgang = blank ausgang + THEN put ("blank") +ELIF zeichenwert ausgang = kommando ausgang + THEN put ("kommando") +ELIF zeichenwert ausgang = such ausgang + THEN put ("such") +ELIF zeichenwert ausgang = zeilenende ausgang + THEN put ("zeilenende") + ELSE put(zeichenwert ausgang); +FI; put ("ausgang"); +out(">");out(puffer SUB zeichenpos);out("<"); +line ;out("puffer >"); +IF length (puffer) > 65 + THEN outsubtext (puffer, 1, 65); + line ; outsubtext (puffer, 66) + ELSE out(puffer); +FI; +out("<"); +line ;out("zeile >"); +IF length (zeile) > 65 + THEN outsubtext (zeile, 1, 65); + line ; outsubtext (zeile, 66) + ELSE out (zeile); +FI; +out("<"); +line ;out("neue zeile >"); +IF length (neue zeile) > 65 + THEN outsubtext (neue zeile, 1, 65); + line ; outsubtext (neue zeile, 66) + ELSE out(neue zeile); +FI; +out("<"); +line ; +END PROC zustands test;*) + +(*************************** eigentliche form routine ********************) + +PROC zeilen form (TEXT CONST datei): + enable stop; + form initialisieren (datei); + formiere absatzweise; + letzte neue zeile ausgeben. + +formiere absatzweise: + REP + letzter puffer war absatz := FALSE; + einrueckbreite := eingestellte indentation pitch; + IF einfacher absatz nach absatz + THEN gebe einfachen absatz aus + ELSE verarbeite abschnitt nach absatz + FI + UNTIL pufferlaenge = 0 END REP. + +einfacher absatz nach absatz: + absatz. + +gebe einfachen absatz aus: + neue zeile := blank; + ausgabe bei zeilenende. + +verarbeite abschnitt nach absatz: + berechne erste zeile nach absatz; + IF NOT letzter puffer war absatz + THEN formiere + FI. + +formiere: + INT VAR letzte zeilennr; + REP + stranalyze (pitch table, zeilenbreite, aktuelle pitch zeilenlaenge, + puffer, zeichenpos, pufferlaenge, zeichenwert ausgang); + IF zeichenwert ausgang = kommando ausgang + THEN zeichenpos INCR 1; + verarbeite kommando und neue zeile auffuellen; + IF letzter puffer war absatz + THEN ausgabe bei zeilenende; + LEAVE verarbeite abschnitt nach absatz + ELIF zeichenpos > pufferlaenge OR absatz + THEN letzte zeilennr := zeilennr; + verarbeite letztes zeichen von puffer; + IF neue zeile ausgeloest + THEN LEAVE verarbeite abschnitt nach absatz + ELSE letzter puffer war absatz := FALSE + FI + FI + ELIF zeichenwert ausgang = extended char ausgang + THEN char pos move (vorwaerts); + zeilenbreite INCR breite (puffer, zeichenpos); + char pos move (vorwaerts) + ELIF zeichenwert ausgang = zeilenende ausgang + OR zeichenwert ausgang = esc char ohne zweites byte ausgang + THEN letzte zeilennr := zeilennr; + verarbeite letztes zeichen von puffer; + IF zeichenwert ausgang = esc char ohne zweites byte ausgang + THEN fehler (23, "") + FI; + IF neue zeile ausgeloest + THEN LEAVE verarbeite abschnitt nach absatz + ELSE letzter puffer war absatz := FALSE + FI + ELSE ende einer neuen zeile + FI; + UNTIL pufferlaenge = 0 END REP. + +neue zeile ausgeloest: + letzte zeilennr < zeilennr. +END PROC zeilen form; + +PROC berechne erste zeile nach absatz: + INT CONST anz einrueckungszeichen :: zeilenbreite DIV einrueckbreite; + INT VAR anz zeichen fuer einzeilige einrueckung :: 0, + anz zeichen :: 0, + schlepper zeichenpos :: 1, + letzte zeilennr; + BOOL CONST puffer hatte anfangs absatz :: puffer hat absatz; + BOOL VAR noch kein blank gewesen :: TRUE; + pitch table auf blank ausgang setzen; + berechne erste zeile; + pitch table auf blank setzen. + +berechne erste zeile: + REP + stranalyze (pitch table, zeilenbreite, aktuelle pitch zeilenlaenge, + puffer, zeichenpos, pufferlaenge, zeichenwert ausgang); + IF zeichenwert ausgang = blank ausgang + THEN verarbeite text + ELIF zeichenwert ausgang = extended char ausgang + THEN char pos move (vorwaerts); + zeilenbreite INCR breite (puffer, zeichenpos); + char pos move (vorwaerts) + ELIF zeichenwert ausgang = kommando ausgang + THEN verarbeite dieses kommando + ELIF zeichenwert ausgang = zeilenende ausgang + OR zeichenwert ausgang = esc char ohne zweites byte ausgang + THEN behandele zu kurze zeile + ELSE behandele zu lange zeile + FI + END REP. + +verarbeite dieses kommando: + textzeichen mitzaehlen; + IF pos (" #", (puffer SUB zeichenpos)) = 0 + THEN aufzaehlungszeichen := (puffer SUB zeichenpos) + FI; + char pos move (vorwaerts); + mitzuzaehlende zeichen := 0; + pitch table auf blank setzen; + verarbeite kommando und neue zeile auffuellen; + pitch table auf blank ausgang setzen; + IF letzter puffer war absatz + THEN neue zeile auffuellen und ausgabe bei zeilenende; + LEAVE berechne erste zeile + ELIF zeichenpos > pufferlaenge OR absatz + THEN letzte zeilennr := zeilennr; + verarbeite letztes zeichen von puffer; + IF neue zeile ausgeloest + THEN LEAVE berechne erste zeile + ELSE letzter puffer war absatz := FALSE + FI + ELIF anweisung erlaubt keine aufzaehlung + THEN LEAVE berechne erste zeile + FI; + anz zeichen INCR mitzuzaehlende zeichen; + schlepper zeichenpos := zeichenpos. + +neue zeile ausgeloest: + letzte zeilennr < zeilennr. + +anweisung erlaubt keine aufzaehlung: + kommando index = center OR kommando index = right. + +verarbeite text: + char pos move (vorwaerts); + IF absatz + THEN verarbeite letztes zeichen von puffer; + LEAVE berechne erste zeile + ELIF zeilenbreite + blankbreite fuer diesen schrifttyp > + aktuelle pitch zeilenlaenge + THEN behandele zu lange zeile + ELIF mehrfaches blank + THEN positionierung mit doppelblank + ELIF noch kein blank gewesen AND + anz zeichen + + number chars (puffer, schlepper zeichenpos, zeichenpos) <= 20 + THEN ggf aufzaehlung aufnehmen + ELSE zeilenbreite INCR blankbreite fuer diesen schrifttyp + FI; + noch kein blank gewesen := FALSE; + zeichenpos INCR 1. + +mehrfaches blank: + (puffer SUB zeichenpos + 1) = blank. + +positionierung mit doppelblank: + WHILE NOT within kanji (puffer, zeichenpos + 1) AND + (puffer SUB zeichenpos + 1) = blank REP + zeichenpos INCR 1 + END REP; + textzeichen mitzaehlen; + pruefe auf ueberschreibung + (zeilenbreite, anz zeichen + anz einrueckungszeichen). + +ggf aufzaehlung aufnehmen: + IF NOT within kanji (puffer, zeichenpos - 1) AND + (puffer SUB zeichenpos - 1) <> kommandozeichen + THEN aufzaehlungszeichen := (puffer SUB zeichenpos - 1); + FI; + textzeichen mitzaehlen; + IF aufzaehlungszeichen = ":" + OR (aufzaehlungszeichen = "-" AND anz zeichen <= 2) + OR (anz zeichen <= 7 AND ( aufzaehlungszeichen = ")" + OR aufzaehlungszeichen = ".")) + THEN anz zeichen fuer einzeilige einrueckung := anz zeichen; + pruefe auf ueberschreibung + (zeilenbreite, anz zeichen + anz einrueckungszeichen) + ELSE zeilenbreite INCR blankbreite fuer diesen schrifttyp + FI. + +textzeichen mitzaehlen: + anz zeichen INCR number chars (puffer, schlepper zeichenpos, zeichenpos); + IF is kanji esc (puffer SUB zeichenpos) + THEN schlepper zeichenpos := zeichenpos + 2 + ELSE schlepper zeichenpos := zeichenpos + 1 + FI. + +behandele zu kurze zeile: + textzeichen mitzaehlen; + IF zeichenwert ausgang = esc char ohne zweites byte ausgang + THEN fehler (23, ""); + neue zeile auffuellen; + schreibe und initialisiere neue zeile; + zeichenpos := 1; + LEAVE berechne erste zeile + FI; + letzte zeilennr := zeilennr; + verarbeite letztes zeichen von puffer; + IF neue zeile ausgeloest + THEN LEAVE berechne erste zeile + FI; + schlepper zeichenpos := 1. + +behandele zu lange zeile: + pitch table auf blank setzen; + IF zeilenende bei erstem zeichen + THEN loesche nachfolgende blanks; + schreibe und initialisiere neue zeile; + zeichenpos := 1; + LEAVE berechne erste zeile + ELIF (puffer SUB zeichenpos) = kommandozeichen + THEN zeichenpos INCR 1 + ELSE zeilenbreite DECR breite (puffer, zeichenpos) + FI; + IF puffer hatte anfangs absatz + THEN einrueckung gemaess pufferanfang + FI; + LEAVE berechne erste zeile. + +zeilenende bei erstem zeichen: + zeichenpos < 1. + +einrueckung gemaess pufferanfang: +alte blanks := +(anz einrueckungszeichen + anz zeichen fuer einzeilige einrueckung) * blank. +END PROC berechne erste zeile nach absatz; + +PROC pruefe auf ueberschreibung (INT CONST aufzaehlungsbreite, + anz aufzaehlungszeichen): + IF ueberschreibung + THEN fehlende blanks errechnen; + INT VAR aufzaehlungsende :: zeichenpos - 1; + WHILE (puffer SUB aufzaehlungsende) = blank REP + aufzaehlungsende DECR 1 + END REP; + dummy := ">"; + dummy CAT subtext (puffer, + aufzaehlungsende - 15, aufzaehlungsende); + dummy CAT "< Fehlende Blanks: "; + dummy CAT text (anz fehlende blanks); + warnung (12, dummy) + FI; + zeilenbreite := anz aufzaehlungszeichen * einrueckbreite. + +ueberschreibung: + INT CONST anz zeichen mal einrueckbreite :: + anz aufzaehlungszeichen * einrueckbreite, + min zwischenraum :: (einrueckbreite DIV 4); + aufzaehlungsbreite + min zwischenraum > anz zeichen mal einrueckbreite. + +fehlende blanks errechnen: + INT VAR anz fehlende blanks :: + (aufzaehlungsbreite + min zwischenraum + - anz zeichen mal einrueckbreite + einrueckbreite - 1) + DIV einrueckbreite. +END PROC pruefe auf ueberschreibung; + +(********************** eingabe routinen **************************) + +PROC zeile lesen: + alte blanks := aktuelle blanks; + hole zeile; + behandele einrueckung. + +hole zeile: + IF macro works + THEN get macro line (zeile); + ELIF eof (eingabe) + THEN zeile := ""; + LEAVE zeile lesen + ELSE lesen + FI; + IF zeile = "" + THEN zeile := blank + ELIF (zeile SUB length (zeile) - 1) = blank + THEN ggf ueberfluessige leerzeichen am ende entfernen + FI. + +lesen: + IF format file in situ + THEN read record (eingabe, zeile); + delete record (eingabe) + ELSE read record (eingabe, zeile); + down (eingabe) + FI. + +ggf ueberfluessige leerzeichen am ende entfernen: + WHILE NOT within kanji (zeile, length (zeile) - 1) AND + subtext (zeile, length (zeile) - 1) = " " REP + delete char (zeile, length (zeile)) + END REP. + +behandele einrueckung: + aktuelle blanks := ""; + IF zeile <> blank + THEN INT VAR einrueckung := pos (zeile, ""33"", ""255"", 1); + IF einrueckung > 1 + THEN aktuelle blanks := subtext (zeile, 1, einrueckung - 1); + zeile := subtext (zeile, einrueckung) + FI + FI +END PROC zeile lesen; + +PROC zeile in puffer und zeile lesen: + puffer := zeile; + zeichenpos := 1; + von := 1; + zeile lesen; + pufferlaenge := length (puffer); + ggf absatz an puffer anfuegen; +END PROC zeile in puffer und zeile lesen; + +PROC ggf absatz an puffer anfuegen: + IF (zeile ist nur absatz AND NOT puffer hat absatz) + OR (NOT puffer hat absatz AND only command line (puffer) + AND only command line (zeile)) + THEN puffer CAT blank; + pufferlaenge := length (puffer) + ELIF puffer ist nur absatz AND (zeile SUB length (zeile)) <> " " AND + only command line (zeile) + THEN zeile CAT " " + FI. + +puffer ist nur absatz: + puffer = blank. + +zeile ist nur absatz: + zeile = blank. +END PROC ggf absatz an puffer anfuegen; + +(****************** routinen fuer zeilenende behandlung ***********) + +PROC verarbeite letztes zeichen von puffer: + zeichenpos := length (puffer); + begin of this char (puffer, zeichenpos); + zeichen := puffer SUB zeichenpos; + IF trennung vorhanden + THEN IF zeile hat richtige laenge + THEN neue zeile auffuellen und ausgabe bei zeilenende + ELSE getrennte zeilen zusammenziehen + FI + ELSE neue zeile auffuellen; + IF absatz + THEN letzter puffer war absatz := TRUE; + IF letztes kommando war macro AND macro hat absatz getaetigt + THEN zeile in puffer und zeile lesen; + initialisiere neue zeile; + ELSE ausgabe bei zeilenende; + FI + ELSE neue zeile ggf weiterfuehren + FI + FI. + +neue zeile ggf weiterfuehren: + IF macro end in dieser oder naechster zeile + THEN + ELIF zeile = "" + THEN schreibe und initialisiere neue zeile; + letzter puffer war absatz := TRUE + ELIF zeilenbreite + blank breite fuer diesen schrifttyp > + aktuelle pitch zeilenlaenge + THEN loesche nachfolgende blanks; + schreibe und initialisiere neue zeile + ELIF in neuer zeile steht etwas + THEN neue zeile CAT blank; + zeilenbreite INCR blank breite fuer diesen schrifttyp + FI; + zeile in puffer und zeile lesen. + +macro end in dieser oder naechster zeile: + macro works AND (pos (puffer, "#*") <> 0 OR pos (zeile, "#*") <> 0). + +in neuer zeile steht etwas: + pos (neue zeile, ""33"", ""255"", 1) <> 0. + +letztes kommando war macro: + pos (kommando, "macro") <> 0. + +macro hat absatz getaetigt: + NOT in neuer zeile steht etwas. +END PROC verarbeite letztes zeichen von puffer; + +PROC getrennte zeilen zusammenziehen: + zeichen := puffer SUB pufferlaenge; + IF NOT within kanji (puffer, pufferlaenge) AND zeichen = trennzeichen + THEN zeilenbreite DECR breite (trennzeichen); + delete char (puffer, pufferlaenge); + pufferlaenge := length (puffer); + IF ((puffer SUB pufferlaenge) = trenn k) AND ((zeile SUB 1) = "k") + THEN replace (puffer, pufferlaenge, "c"); + zeilenbreite DECR breite ("k"); + zeilenbreite INCR breite ("c"); + FI; + zeichenpos := pufferlaenge + 1 + FI; + puffer CAT zeile; + zeile lesen; + pufferlaenge := length (puffer); + ggf absatz an puffer anfuegen; +END PROC getrennte zeilen zusammenziehen; + +BOOL PROC trennung vorhanden: + IF within kanji (puffer, pufferlaenge) + THEN LEAVE trennung vorhanden WITH FALSE + FI; + zeichen := puffer SUB pufferlaenge; + zeichen = trennzeichen OR wort mit bindestrich. + +wort mit bindestrich: + zeichen = bindestrich AND kein leerzeichen davor + AND NOT naechstes wort ist konjunktion AND kein loser gedankenstrich. + +kein leerzeichen davor: + NOT within kanji (puffer, pufferlaenge - 1) AND + (puffer SUB pufferlaenge - 1) <> blank. + +naechstes wort ist konjunktion: + pos (zeile, "und") = 1 + OR pos (zeile, "oder") = 1 + OR pos (zeile, "bzw") = 1 + OR pos (zeile, "sowie") = 1. + +kein loser gedankenstrich: + pufferlaenge > 1. +END PROC trennung vorhanden; + +BOOL PROC zeile hat richtige laenge: + zeilenbreite > aktuelle pitch zeilenlaenge - trennbreite +END PROC zeile hat richtige laenge; + +(*********************** ausgabe routinen *******************) + +PROC ende einer neuen zeile: + IF zeichenpos > 0 + THEN begin of this char (puffer, zeichenpos); + FI; + zeichen := puffer SUB zeichenpos; + zeichenpos bereits verarbeitet := 0; + IF naechstes zeichen ist absatz + THEN zeichenpos := pufferlaenge; + verarbeite letztes zeichen von puffer; + LEAVE ende einer neuen zeile + ELIF zeichen = blank + THEN neue zeile auffuellen (von, zeichenpos - 1); + zeichenpos := pos (puffer, ""33"", ""255"", zeichenpos); + von := zeichenpos; + ELIF nach zeichenpos beginnt ein neues wort + THEN neue zeile auffuellen (von, zeichenpos); + zeichenpos := pos (puffer, ""33"", ""255"", zeichenpos + 1); + von := zeichenpos + ELIF letzter puffer passte genau + THEN (* erstes zeichen des neuen puffers > zeilenbreite *) + zeichenpos := 1; + von := 1 + ELSE zeichenpos bereits verarbeitet := zeichenpos; + trennung eventuell vornehmen; + IF erstes wort auf der absatzzeile laesst sich nicht trennen + THEN alte blanks := aktuelle blanks + FI + FI; + loesche nachfolgende blanks; + IF NOT in foot uebertrag + THEN schreibe und initialisiere neue zeile; + zeilenbreite und zeichenpos auf das bereits verarbeitete + zeichen setzen; + FI. + +erstes wort auf der absatzzeile laesst sich nicht trennen: + pos (neue zeile, ""33"", ""255"", 1) = 0 AND (*keine buchstaben*) + length (neue zeile) > 1 AND (*einrueckung*) + (neue zeile SUB length (neue zeile)) = blank. (* Absatz *) + +naechstes zeichen ist absatz: + zeichenpos + 1 = pufferlaenge AND puffer hat absatz. + +nach zeichenpos beginnt ein neues wort: + (pufferlaenge > zeichenpos + 2) AND (puffer SUB zeichenpos + 1) = blank. + +letzter puffer passte genau: + zeichenpos <= 0. + +zeilenbreite und zeichenpos auf das bereits verarbeitete zeichen setzen: + IF zeichenpos bereits verarbeitet <> 0 + THEN INT VAR bis := zeichenpos, einfuege pos := bis; + zeilenbreite um die bereits verarbeiteten zeichen erhoehen; + zeichenpos := zeichenpos bereits verarbeitet; + IF einfuege pos > 1 + THEN insert char (puffer, blank, einfuege pos); + pufferlaenge := length (puffer); + von := einfuege pos + 1; + char pos move (vorwaerts) + FI; + char pos move (vorwaerts); + FI. + +zeilenbreite um die bereits verarbeiteten zeichen erhoehen: + zeichenpos := zeichenpos bereits verarbeitet; + WHILE (puffer SUB bis) = kommandozeichen REP + bis := pos (puffer, kommandozeichen, bis + 1) + 1 + END REP; + begin of this char (puffer, zeichenpos); + WHILE zeichenpos >= bis REP + IF (puffer SUB zeichenpos) = kommandozeichen + THEN ueberspringe das kommando (puffer, zeichenpos, rueckwaerts) + ELSE zeilenbreite INCR breite (puffer, zeichenpos); + FI; + IF zeichenpos <= 1 + THEN LEAVE zeilenbreite um die bereits verarbeiteten zeichen erhoehen + FI; + char pos move (rueckwaerts) + END REP. +END PROC ende einer neuen zeile; + +PROC loesche nachfolgende blanks: + WHILE NOT within kanji (neue zeile, length (neue zeile)) AND + (neue zeile SUB length (neue zeile)) = blank REP + delete char (neue zeile, length (neue zeile)) + END REP +END PROC loesche nachfolgende blanks; + +PROC neue zeile auffuellen: + dummy := subtext (puffer, von); + neue zeile CAT dummy +END PROC neue zeile auffuellen; + +PROC neue zeile auffuellen (INT CONST from, to): + dummy := subtext (puffer, from, to); + neue zeile CAT dummy +END PROC neue zeile auffuellen; + +PROC schreibe neue zeile: + IF macro works + THEN IF alte neue zeile einschliesslich macro ist auszugeben + THEN schreibe textteil einschliesslich macro; + FI + ELSE schreibe; + pruefe auf abbruch + FI. + +alte neue zeile: + before macro state . new line. + +alter puffer: + before macro state . buffer line. + +alte neue zeile einschliesslich macro ist auszugeben: + INT VAR text anf :: pos (alte neue zeile, ""33"", ""255"", 1); + text anf <> 0. + +schreibe textteil einschliesslich macro: + dummy := neue zeile; + neue zeile := alte neue zeile; + IF macro hatte absatz danach + THEN neue zeile CAT " " + ELSE zeilennr INCR 1 + FI; + schreibe; + neue zeile := dummy; + alte neue zeile := subtext (alte neue zeile, 1, text anf - 1). + +macro hatte absatz danach: + length (alter puffer) - 1 = length (alte neue zeile) AND + (alter puffer SUB length (alter puffer)) = " ". + +pruefe auf abbruch: + IF incharety = escape + THEN errorstop ("Abbruch mit ESC") + FI. +END PROC schreibe neue zeile; + +PROC schreibe: + IF format file in situ + THEN insert record (eingabe); + write record (eingabe, neue zeile); + down (eingabe) + ELSE insert record (ausgabe); + write record (ausgabe, neue zeile); + down (ausgabe); + speicher ueberlauf + FI; + execute stored commands; + IF (neue zeile SUB length (neue zeile)) = blank + THEN einrueckbreite := eingestellte indentation pitch + FI. + +speicher ueberlauf: + INT VAR size, used; + storage (size, used); + IF used > size + THEN errorstop ("Speicherengpaß") + FI. +END PROC schreibe; + +PROC schreibe und initialisiere neue zeile: + schreibe neue zeile; + initialisiere neue zeile +END PROC schreibe und initialisiere neue zeile; + +PROC ausgabe bei zeilenende: + schreibe und initialisiere neue zeile; + zeile in puffer und zeile lesen +END PROC ausgabe bei zeilenende; + +PROC neue zeile auffuellen und ausgabe bei zeilenende: + neue zeile auffuellen; + schreibe und initialisiere neue zeile; + zeile in puffer und zeile lesen +END PROC neue zeile auffuellen und ausgabe bei zeilenende; + +PROC initialisiere neue zeile: + einrueckung in die neue zeile; + zeilennummer mitzaehlen. + +einrueckung in die neue zeile: + IF zeichenpos < pufferlaenge AND + (puffer hat absatz OR foot ohne absatz am zeilenende) + THEN neue zeile := alte blanks + ELSE neue zeile := aktuelle blanks + FI; + zeilenbreite := length (neue zeile) * einrueckbreite; + IF zeilenbreite +trennbreite +einrueckbreite >= aktuelle pitch zeilenlaenge + THEN fehler (10, ""); + zeilenbreite := 0; + FI. + +foot ohne absatz am zeilenende: + pos (puffer, "#foot#") > 1 AND pos (puffer, "#foot#") = length (puffer) -5. + +zeilennummer mitzaehlen: + IF NOT macro works + THEN zeilennr INCR 1; + cout (zeilennr); + FI. +END PROC initialisiere neue zeile; + +PROC letzte neue zeile ausgeben: + IF pos (neue zeile, ""33"", ""255"", 1) <> 0 + THEN schreibe neue zeile + FI; + offene modifikationen ausgeben; + offene indizes ausgeben; + IF aktueller editor < 1 + THEN referenzen ueberpruefen; + offene counter referenzen ausgeben; + FI. + +offene modifikationen ausgeben: + WHILE length (modifikations speicher) <> 0 REP + dummy := (modifikations speicher SUB 1); + delete char (modifikations speicher, 1); + dummy CAT " in Zeile "; + dummy CAT text (mod zeilennr speicher ISUB 1); + delete int (mod zeilennr speicher, 1); + warnung (5, dummy) + END REP. + +offene indizes ausgeben: + WHILE length (index speicher) <> 0 REP + dummy := (index speicher SUB 1); + delete char (index speicher, 1); + dummy CAT " in Zeile "; + dummy CAT text (ind zeilennr speicher ISUB 1); + delete int (ind zeilennr speicher, 1); + warnung (6, dummy) + END REP. + +offene counter referenzen ausgeben: + INT VAR begin pos := pos (counter reference store, "#"); + WHILE begin pos > 0 REP + INT VAR end pos := pos (counter reference store, "#", begin pos + 1); + IF (counter reference store SUB begin pos - 1) <> "u" + THEN fehler (60, subtext (counter reference store, begin pos + 1, + end pos - 1)) + ELIF (counter reference store SUB begin pos - 2) <> "i" + THEN fehler (61, subtext (counter reference store, begin pos + 1, + end pos - 1)) + FI; + begin pos := pos (counter reference store, "#", end pos + 1) + END REP. +END PROC letzte neue zeile ausgeben; + +(*********************** silbentrenn routinen *******************) + +INT PROC position von (TEXT CONST such zeichen, INT CONST richtung, + INT VAR anz zeich, breite der z): + INT VAR index :: zeichenpos; + TEXT VAR akt z; + anz zeich := 0; + breite der z := 0; + WHILE index > 1 AND index < pufferlaenge REP + akt z := puffer SUB index; + IF akt z = such zeichen + THEN LEAVE position von WITH index + ELIF akt z = kommandozeichen + THEN ueberspringe das kommando (puffer, index, richtung); + IF nur ein kommandozeichen gefunden + THEN gehe nur bis erstes kommandozeichen + ELIF index <= 1 OR index >= pufferlaenge + THEN LEAVE position von WITH index + FI + ELSE anz zeich INCR 1; + breite der z INCR breite (puffer, index) + FI; + char pos move (index, richtung) + END REP; + anz zeich INCR 1; + breite der z INCR breite (puffer, index); + index. + +nur ein kommandozeichen gefunden: + (puffer SUB index) <> kommandozeichen. + +gehe nur bis erstes kommandozeichen: + index := zeichenpos; anz zeich := 0; breite der z := 0; + WHILE (puffer SUB index) <> kommandozeichen REP + anz zeich INCR 1; + breite der z INCR breite (puffer, index); + char pos move (index, richtung) + END REP; + IF richtung <> rueckwaerts + THEN index DECR 1 + FI; + LEAVE position von WITH index. +END PROC position von; + +PROC ueberspringe das kommando (TEXT CONST t, INT VAR i, INT CONST richtung): + REP + i INCR richtung; + IF within kanji (t, i) + THEN i INCR richtung + FI + UNTIL (t SUB i) = kommandozeichen OR i <= 1 OR i >= length (t) END REP. +END PROC ueberspringe das kommando; + +PROC trennung eventuell vornehmen: +INT VAR xwort1, ywort1, + anz zeichen davor, + breite davor; + IF macro works + THEN fehler (6, "") + FI; + trennsymbol := trennzeichen; + wortanfang := position von + (blank, rueckwaerts, anz zeichen davor, breite davor); + bereite neue zeile bis wortanfang auf; + IF trennung sinnvoll + THEN versuche zu trennen + ELSE zeichenpos := wortanfang + FI. + +bereite neue zeile bis wortanfang auf: + IF wortanfang > 1 + THEN wortanfang INCR 1 + FI; + IF von > wortanfang + THEN eliminiere zeichen in neuer zeile bis wortanfang + ELSE neue zeile auffuellen (von, wortanfang - 1) + FI; + von := wortanfang. + +eliminiere zeichen in neuer zeile bis wortanfang: + INT VAR y :: length (neue zeile); + begin of this char (neue zeile, y); + WHILE y >= 1 REP + IF (neue zeile SUB y) = kommandozeichen + THEN ueberspringe das kommando (neue zeile, y, rueckwaerts) + FI; + char pos move (neue zeile, y, rueckwaerts) + UNTIL (neue zeile SUB y) = blank END REP; + neue zeile := subtext (neue zeile, 1, y). + +trennung sinnvoll: + anz zeichen davor > 2 AND breite davor > trennbreite. + +versuche zu trennen: + INT CONST k := zeichenpos; + naechste zeile ggf heranziehen; + zeichenpos := k; + wortteile holen; + trenn (trennwort ohne komm, wort1 ohne komm, trennsymbol, + max trennlaenge ohne komm); + wort1 mit komm ermitteln; + IF lineform mode + THEN wort2 := subtext (trennwort, length (wort1) + 1, max trennlaenge); + display vorherige zeile bis wortanfang; + schreibe nicht trennbaren teil des trennwortes; + schreibe zeile nach trennwort; + skip input; + interaktive worttrennung + FI; + neue zeile mit trennwort versehen; + IF wort1 <> "" AND NOT lineform mode + THEN note (zeilen nr); note (": "); + note (trennwort); + note (" --> "); + note (wort1); note (trennsymbol); + wort2 := subtext (trennwort, length (wort1) + 1); + note (wort2); + note line + FI. + +wortteile holen: + zeichenpos durch trennzeichenbreite verschieben; + wort1 := subtext (puffer, wortanfang, zeichenpos); + max trennlaenge := length (wort1); + wortende ermitteln; + wort2 := subtext (puffer, zeichenpos, wortende); + trennwort := subtext (puffer, wortanfang, wortende); + trennwort ohne komm ermitteln; + wort1 ohne komm := subtext (trennwort ohne komm, 1, anz zeichen davor); + max trenn laenge ohne komm := anz zeichen davor. + +trennwort ohne komm ermitteln: + trennwort ohne komm := trennwort; + WHILE pos (trennwort ohne komm, kommando zeichen) <> 0 REP + INT CONST komm anf := pos (trennwort ohne komm, kommando zeichen), + komm ende:= pos (trennwort ohne komm, kommando zeichen, + komm anf + 1); + IF komm ende = 0 + THEN LEAVE trennwort ohne komm ermitteln + FI; + dummy := subtext (trennwort ohne komm, komm ende + 1); + trennwort ohne komm := subtext (trennwort ohne komm, 1, komm anf - 1); + trennwort ohne komm CAT dummy; + END REP. + +wort1 mit komm ermitteln: + IF length (wort1 ohne komm) = 0 + THEN wort1 := ""; + LEAVE wort1 mit komm ermitteln + FI; + INT VAR index ohne := 0, + index mit := 0; + REP + index ohne INCR 1; + index mit INCR 1; + WHILE (wort1 SUB index mit) = kommando zeichen REP + index mit := pos (wort1, kommando zeichen, index mit + 1) + 1 + END REP; + UNTIL index ohne >= length (wort1 ohne komm) END REP; + wort1 := subtext (wort1, 1, index mit). + +zeichenpos durch trennzeichenbreite verschieben: + REP + zeichen := puffer SUB zeichenpos; + IF zeichen = kommandozeichen + THEN ueberspringe das kommando (puffer, zeichenpos, rueckwaerts); + char pos move (rueckwaerts) + ELIF zeichenpos < wortanfang + 1 + THEN zeichenpos := wortanfang; + LEAVE trennung eventuell vornehmen + ELSE zeilenbreite DECR breite (puffer, zeichenpos); + anz zeichen davor DECR 1; + char pos move (rueckwaerts); + IF zeilenbreite+breite(trennzeichen) <= aktuellepitchzeilenlaenge + AND (puffer SUB zeichenpos) <> kommandozeichen + THEN LEAVE zeichenpos durch trennzeichenbreite verschieben + FI + FI; + END REP. + +wortende ermitteln: + INT VAR x1, x2; + wortende := position von (blank, 1, x1, x2); + IF pufferlaenge > wortende + THEN wortende DECR 1 + FI. + +display vorherige zeile bis wortanfang: + dummy := neue zeile; + dummy CAT subtext (puffer, von, wortanfang - 2); + line ; + outsubtext (dummy, length (dummy) - 78). + +schreibe nicht trennbaren teil des trennwortes: + line ; + get cursor (xwort1, ywort1); + IF length (trennwort) < 70 + THEN cursor (max trennlaenge + 4, ywort1); + outsubtext (trennwort, max trennlaenge + 1) + FI. + +schreibe zeile nach trennwort: + dummy := subtext (puffer, wortende + 1); + get cursor (trennwort endepos, ywort1); + IF length (trennwort) >= 70 + THEN + ELIF length (dummy) > 75 - trennwort ende pos + THEN outsubtext (dummy, 1, 75 - trennwort endepos); + ELSE out (dummy); + IF (dummy SUB length (dummy)) = blank + THEN cursor (78, ywort1); + out (begin mark); + out (end mark) + FI + FI. + +trennwort endepos: + xwort1. + +interaktive worttrennung: + REP + out (return); + schreibe erstes wort; + get cursor (xwort1, ywort1); + schreibe trennung; + schreibe zweites wort; + schreibe rest bei zu langem trennwort; + cursor (xwort1, ywort1); + hole steuerzeichen und veraendere worte + END REP. + +schreibe erstes wort: + out (begin mark); + IF length (trennwort) < 70 + THEN out (wort1) + ELSE outsubtext (wort1, length (wort1) - 60) + FI. + +schreibe trennung: + IF ck vorhanden + THEN out (links); out ("k"); + FI; + out (trennsymbol). + +schreibe zweites wort: + IF length (trennwort) < 70 + THEN out (wort2) + ELSE outsubtext (wort2, 1, 70 - xwort1); + FI; + out (end mark). + +schreibe rest bei zu langem trennwort: + IF length (trennwort) >= 70 + THEN INT VAR xakt pos; + out (cl eol); + get cursor (xakt pos, ywort1); + outsubtext (trennwort, max trennlaenge + 1, + max trennlaenge + 1 + (78 - xakt pos)) + FI. + +ck vorhanden: + (wort1 SUB length (wort1)) = "c" AND + (trennwort SUB (length (wort1) + 1)) = "k". + +hole steuerzeichen und veraendere worte: +TEXT VAR steuerzeichen; + inchar (steuerzeichen); + IF steuerzeichen = links + THEN nach links + ELIF steuerzeichen = rechts + THEN nach rechts + ELIF steuerzeichen = hop + THEN sprung + ELIF steuerzeichen = return + THEN line ; + LEAVE interaktive worttrennung + ELIF steuerzeichen = escape + THEN errorstop ("Abbruch mit ESC") + ELIF code (steuerzeichen) < 32 + THEN + ELSE trennsymbol := steuerzeichen; + LEAVE hole steuerzeichen und veraendere worte + FI; + IF wort1 = "" + OR (wort1 SUB length (wort1)) = bindestrich + THEN trennsymbol := blank + ELSE trennsymbol := trennzeichen + FI. + +nach links: +TEXT VAR ein zeichen; +INT VAR position; + IF length (wort1) <> 0 + THEN position := length (wort1); + IF (wort1 SUB position) = kommando zeichen + THEN ueberspringe das kommando (wort1, position, rueckwaerts); + FI; + position DECR 1; + wort1 := subtext (trennwort, 1, position); + wort2 := subtext (trennwort, position + 1, max trennlaenge); + IF rechtes teilwort mit bindestrich + THEN ein zeichen := (wort1 SUB length (wort1)); + delete char (wort1, length (wort1)); + insert char (wort2, ein zeichen, 1) + FI + FI. + +nach rechts: + IF length (wort1) < max trennlaenge + THEN position := length (wort1) + 1; + IF (trennwort SUB position) = kommando zeichen + THEN ueberspringe das kommando (trennwort, position, +1); + FI; + wort1 := subtext (trennwort, 1, position); + wort2 := subtext (trennwort, position + 1, max trennlaenge); + IF rechtes teilwort mit bindestrich + THEN wort1 CAT bindestrich; + delete char (wort2, 1) + FI + FI. + +rechtes teilwort mit bindestrich: + (wort2 SUB 1) = bindestrich AND + pos (buchstaben, wort1 SUB length (wort1)) <> 0. + +sprung: + inchar(steuerzeichen); + IF steuerzeichen = rechts + THEN wort1 := subtext (trennwort, 1, max trennlaenge); + wort2 := "" + ELIF steuerzeichen = links + THEN wort1 := ""; + wort2 := subtext (trennwort, 1, max trennlaenge) + FI. + +neue zeile mit trennwort versehen: + IF wort1 = "" + THEN keine trennung + ELSE zeichenpos := wortanfang + length (wort1); + mit trennsymbol trennen; + von := zeichenpos + FI. + +keine trennung: + IF wort ist zu lang fuer limit + THEN warnung (7, trennwort); + neue zeile CAT trennwort; + zeichenpos := wortende + 1; + zeichenpos bereits verarbeitet := 0; + von := zeichenpos + ELSE loesche nachfolgende blanks; + zeichenpos := wortanfang + FI. + +wort ist zu lang fuer limit: + length (alte blanks) * einrueckbreite + breite davor + trennbreite + >= aktuelle pitch zeilenlaenge. + +mit trennsymbol trennen: + IF (wort1 SUB length (wort1)) = "c" AND + (trennwort SUB (length (wort1) + 1)) = "k" + THEN replace (wort1, length (wort1), trenn k) + FI; + neue zeile CAT wort1; + IF trennsymbol <> blank + THEN neue zeile CAT trennsymbol + FI. +END PROC trennung eventuell vornehmen; + +PROC naechste zeile ggf heranziehen: + IF puffer hat absatz + OR puffer hat noch mindestens zwei woerter + OR zeile hat eine foot anweisung + OR in foot uebertrag + THEN LEAVE naechste zeile ggf heranziehen + ELIF trennung vorhanden + THEN IF zeichenpos < pufferlaenge + THEN zeilenbreite INCR breite (trennzeichen) + FI; + getrennte zeilen zusammenziehen; + LEAVE naechste zeile ggf heranziehen + FI; + puffer CAT blank; + puffer CAT zeile; + zeile lesen; + pufferlaenge := length (puffer); + ggf absatz an puffer anfuegen. + +puffer hat noch mindestens zwei woerter: + INT VAR anz :: 0, i :: zeichenpos; + WHILE pos (puffer, " ", i) > 0 REP + anz INCR 1; + i := pos (puffer, " ", i) + 1 + END REP; + anz > 1. + +zeile hat eine foot anweisung: + pos (puffer, "#foot") <> 0. +END PROC naechste zeile ggf heranziehen; + +(******************** initialisierungs routine *******************) + +PROC form initialisieren (TEXT CONST datei): + kommando liste := +"type:1.1linefeed:3.1limit:4.1free:5.1page:6.01on:8.1off:9.1pagenr:10.2 +pagelength:11.1start:12.2foot:13.0end:14.0head:15.0headeven:16.0 +headodd:17.0bottom:18.0bottomeven:19.0bottomodd:20.0block:21.0"; + kommando liste CAT +"material:22.1columns:23.2columnsend:24.0ib:25.012ie:28.012topage:31.1 +goalpage:32.1count:33.01setcount:35.1value:36.01table:38.0tableend:39.0 +rpos:40.1lpos:41.1cpos:42.1dpos:43.2bpos:44.2clearpos:45.01right:47.0"; + kommando liste CAT +"center:48.0skip:49.0skipend:50.0u:51.0d:52.0e:53.0headon:54.0headoff:55.0 +bottomon:56.0bottomoff:57.0countperpage:58.0fillchar:59.1mark:60.2 +markend:61.0pageblock:62.0b:63.0counter:64.12setcounter:66.2putcounter:67.01 +storecounter:69.1"; + kommando liste CAT +"ub:70.0ue:71.0fb:72.0fe:73.0"; + line ; + erste fehlerzeilennr := 0; + anz tabs := 0; + zeilennr := 0; + zeilenbreite := 0; + anz blanks freihalten := 3; + herkunftsreferenzen := "#"; + zielreferenzen := "#"; + aktuelle blanks := ""; + font nr speicher := ""; + modifikationsspeicher := ""; + mod zeilennr speicher := ""; + index speicher := ""; + ind zeilennr speicher := ""; + counter numbering store := ""; + counter reference store := ""; + command store := ""; + kommando := ""; + neue zeile := ""; + zeile := ""; + puffer := " "; + macro works := FALSE; + in tabelle := FALSE; + in d und e verarbeitung := FALSE; + kommandos speichern := TRUE; + in foot := FALSE; + in foot uebertrag := FALSE; + test ob font table vorhanden; + bildschirm initialisieren; + zeile lesen; + zeile in puffer und zeile lesen; + einrueckung zweite zeile := "xxx"; + limit und type ggf anfragen; + einrueckbreite := eingestellte indentation pitch ; + initialisiere neue zeile; + IF einrueckung zweite zeile <> "xxx" + THEN aktuelle blanks := einrueckung zweite zeile + FI. + +test ob font table vorhanden: + INT VAR xxx :: x step conversion (0.0). + +bildschirm initialisieren: + IF online + THEN init + FI. + +init: + page; + IF lineform mode + THEN put ("LINEFORM") + ELSE put ("AUTOFORM") + FI; + put ("(für"); put (lines (eingabe)); put ("Zeilen):"); + put (datei); + cursor (1, 3). +END PROC form initialisieren; + +PROC limit und type ggf anfragen: + conversion (limit in cm, aktuelle pitch zeilenlaenge); + IF ask type and limit + THEN type und limit setzen + ELSE alter schriftname := kein vorhandener schriftname; + stelle font ein + FI; + REAL VAR x :: limit in cm; + conversion (x, aktuelle pitch zeilenlaenge); + IF x = fehler wert + THEN limit in cm := 16.0; + conversion (limit in cm, aktuelle pitch zeilenlaenge) + ELSE limit in cm := x + FI; + trennbreite setzen. + +type und limit setzen: + LET type text = "#type (""", + limit text = "#limit (", + kommando ende text = ")#", + kein vorhandener schriftname = "#####"; + IF type und limit anweisungen nicht vorhanden + THEN type und limit fragen + ELSE hole font; + alter schriftname := kein vorhandener schriftname + FI. + +type und limit fragen: + type anfragen; + type in neue zeile; + limit anfragen; + limit in neue zeile; + IF NOT format file in situ + THEN schreibe neue zeile; + zeilen nr INCR 1 + FI; + IF NOT puffer hat absatz + THEN einrueckung zweite zeile := aktuelle blanks; + aktuelle blanks := alte blanks;(* Einrueckung fuer die erste zeile*) + FI; + line. + +type und limit anweisungen nicht vorhanden: + (pos (puffer, type text) <> 1 OR pos (puffer, "limit") < 12). + +type anfragen: + put ("Bitte Schrifttyp :"); + IF font table name = font table + THEN dummy := font (font nr); + ELSE dummy := font (1); + font table name := font table + FI; + REP + editget (dummy); + IF font exists (dummy) + THEN alter schriftname := dummy; + font nr := font (dummy); + hole font; + LEAVE type anfragen + ELSE line ; + put ("ERROR: unbekannter Schrifttyp"); + line (2); + put ("Schrifttyp bitte nochmal:") + FI + END REP. + +type in neue zeile: + neue zeile := type text; + neue zeile CAT dummy; + neue zeile CAT """"; + neue zeile CAT kommando ende text. + +limit anfragen: + line ; + put ("Zeilenbreite (in cm):"); + dummy := text (limit in cm); + REP + editget (dummy); + limit in cm := real (dummy); + IF last conversion ok AND pos (dummy, ".") <> 0 + THEN LEAVE limit anfragen + ELSE line ; + put ("ERROR: Falsche Angabe"); + line (2); + put ("Zeilenbreite (in cm) bitte nochmal:"); + FI + END REP. + +limit in neue zeile: + neue zeile CAT limit text; + neue zeile CAT dummy; + neue zeile CAT kommando ende text; + neue zeile CAT " ". +END PROC limit und type ggf anfragen; + +PROC start form (TEXT CONST datei): + IF NOT format file in situ + THEN last param (datei); + FI; + disable stop; + dateien assoziieren; + zeilen form (datei); + IF is error + THEN fehlerbehandlung + ELSE datei neu nach alt kopieren + FI; + zwischendatei loeschen; + enable stop; + col (eingabe, 1); + IF aktueller editor > 0 + THEN set range (file, alter bereich) + FI; + IF anything noted + THEN IF aktueller editor = 0 + THEN to line (eingabe, erste fehler zeilen nr); + ELSE alles neu + FI; + note edit (eingabe) + ELIF NOT format file in situ + THEN to line (eingabe, 1) + FI. + +dateien assoziieren: + IF format file in situ + THEN + ELIF exists (datei) + THEN IF subtext (datei, length (datei) - 1) = ".p" + THEN errorstop + ("'.p'-Datei kann nicht mit lineform bearbeitet werden") + FI; + eingabe := sequential file (modify, datei); + ausgabe datei einrichten + ELSE errorstop ("Datei existiert nicht") + FI; + to line (eingabe, 1); + col (eingabe, 1). + +ausgabe datei einrichten: + ds := nilspace; + ausgabe := sequential file (modify, ds); + to line (ausgabe, 1); + copy attributes (eingabe, ausgabe). + +fehlerbehandlung: + put error; + clear error; + font nr := 1; + font table name := ""; + limit in cm := 16.0; + IF format file in situ + THEN insert record (eingabe); + write record (eingabe, neue zeile); + down (eingabe); + insert record (eingabe); + write record (eingabe, puffer); + down (eingabe); + insert record (eingabe); + write record (eingabe, zeile) + FI. + +datei neu nach alt kopieren: + IF NOT format file in situ + THEN forget (datei, quiet); + copy (ds, datei); + eingabe := sequential file (modify, datei) + FI. + +zwischendatei loeschen: + IF NOT format file in situ + THEN forget (ds) + FI. +END PROC start form; + +(************** line/autoform fuer benannte Dateien ******************) + +PROC lineform: + IF aktueller editor > 0 + THEN IF mark + THEN editor bereich bearbeiten + ELSE errorstop ("kein markierter Bereich") + FI + ELSE lineform (last param) + FI. + +editor bereich bearbeiten: + disable stop; + file := editfile; + set marked range (file, alter bereich); + lineform (file); + enable stop; +END PROC lineform; + +PROC lineform (TEXT CONST datei): + ask type and limit := TRUE; + lineform mode := TRUE; + format file in situ := FALSE; + start form (datei) +END PROC lineform; + +PROC autoform: + IF aktueller editor > 0 + THEN IF mark + THEN editor bereich bearbeiten + ELSE errorstop ("kein markierter Bereich") + FI + ELSE auto form (last param) + FI. + +editor bereich bearbeiten: + disable stop; + file := editfile; + set marked range (file, alter bereich); + autoform (file); + enable stop +END PROC autoform; + +PROC autoform (TEXT CONST datei): + ask type and limit := TRUE; + lineform mode := FALSE; + format file in situ := FALSE; + start form (datei) +END PROC autoform; + +(******************** line/autoform fuer files ************************) + +PROC lineform (FILE VAR f): + enable stop; + eingabe := f; + format file in situ := TRUE; + ask type and limit := TRUE; + lineform mode := TRUE; + start form (""); +END PROC lineform; + +PROC autoform (FILE VAR f): + enable stop; + eingabe := f; + format file in situ := TRUE; + ask type and limit := TRUE; + lineform mode := FALSE; + start form (""); +END PROC autoform; + +PROC lineform (FILE VAR f, TEXT CONST type name, REAL CONST file limit): + eingabe := f; + format file in situ := TRUE; + lineform mode := TRUE; + ask type and limit := FALSE; + par1 := type name; + limit in cm := file limit; + start form (""); +END PROC lineform; + +PROC autoform (FILE VAR f, TEXT CONST type name, REAL CONST file limit): + eingabe := f; + format file in situ := TRUE; + lineform mode := FALSE; + ask type and limit := FALSE; + par1 := type name; + limit in cm := file limit; + start form (""); +END PROC autoform; +END PACKET liner; +(* +REP + copy("lfehler","zz"); + IF yes ("autoform") + THEN autoform ("zz") + ELSE lineform ("zz") + FI; + edit("zz"); + forget("zz") +UNTIL yes ("ENDE") ENDREP; +*) + diff --git a/system/multiuser/1.7.5/src/macro store b/system/multiuser/1.7.5/src/macro store new file mode 100644 index 0000000..dc13a1b --- /dev/null +++ b/system/multiuser/1.7.5/src/macro store @@ -0,0 +1,298 @@ +(* ------------------- VERSION 13 vom 28.05.86 -------------------- *) +PACKET macro store DEFINES macro command and then process parameters, + get macro line, + number macro lines, + load macros, + list macros: + +(* Programm zur Behandlung von Textkosemtik-Macros + Autor: Rainer Hahn + Stand: 1.7.1 (Febr. 1984) +*) + +INITFLAG VAR this packet :: FALSE; + +DATASPACE VAR ds; + +BOUND MACROTABLE VAR macro table; + +FILE VAR f; + +LET MACROTABLE = STRUCT (ROW max macros TEXT replacement store, + ROW max macro zeilen TEXT macro zeilen, + ROW max macros TEXT macro namen, + ROW max macros INT anz parameter, + ROW max macros INT macro start); + + +LET tag = 1, + number = 3, + delimiter = 6, + end of scan = 7, + max macro zeilen = 1000, + max macros = 200; + +INT VAR index aktuelle macro zeile, + type, + anz zeilen in macro, + anz macro zeilen, + anz macros :: 0; + +TEXT VAR symbol, + fehlertext, + dummy, + kommando, + zeile; + +BOOL VAR with parameters, + macro end gewesen; + +PROC init macros: + IF NOT initialized (this packet) + THEN ds := nilspace; + macro table := ds; + macros leeren + FI. + +macros leeren: + anz macro zeilen := 0; + anz macros := 0. +END PROC init macros; + +PROC load macros (TEXT CONST fname): + init macros; + line; + IF exists (fname) + THEN f := sequential file (input, fname); + forget (ds); + ds := nilspace; + macro table := ds; + macros einlesen + ELSE errorstop ("Datei existiert nicht") + FI. + +macros einlesen: + macro end gewesen := TRUE; + anz macros := 0; + anz macro zeilen := 0; + WHILE NOT eof (f) REP + anz macro zeilen INCR 1; + IF anz macro zeilen > max macro zeilen + THEN errorstop ("Zu viele Zeilen (max.1000)") + FI; + cout (anz macro zeilen); + getline (f, zeile); + IF zeile = "" + THEN zeile := " " + ELIF pos (zeile, "#*") > 0 + THEN macro name oder end vermerken + FI; + IF macro end gewesen AND zeile = " " + THEN anz macro zeilen DECR 1 + ELSE macro table . macro zeilen [anz macro zeilen] := zeile + FI + END REP; + anz macro zeilen INCR 1; + macro table . macro zeilen [anz macro zeilen] := " "; + IF anz macros = 0 + THEN putline ("Macros geleert") + FI. + +macro name oder end vermerken: + INT CONST komm anfang :: pos (zeile, "#*") + 2, + komm ende :: pos (zeile, "#", komm anfang); + IF komm anfang <> 3 OR hinter dem kommando steht noch was + THEN errorstop ("Macro-Anweisung steht nicht alleine auf der Zeile"); + FI; + kommando := subtext (zeile, komm anfang, komm ende -1); + scan (kommando); + next symbol (symbol, type); + IF type = tag + THEN macro namen aufnehmen + ELSE errorstop ("kein Macroname nach #*") + FI; + next symbol (symbol, type); + IF type >= end of scan + THEN macro table . anz parameter [anz macros] := 0; + LEAVE macro name oder end vermerken + ELIF symbol = "(" + THEN parameter aufsammeln; + ELSE errorstop ("keine ( nach Macro-Name") + FI. + +macro namen aufnehmen: + IF symbol = "macroend" + THEN put ("mit"); put (macro table . anz parameter [anz macros]); + put ("Parameter(n) geladen"); + macro end gewesen := TRUE; + line; + LEAVE macro name oder end vermerken + ELIF NOT macro end gewesen + THEN errorstop ("macro end fehlt") + ELSE macro end gewesen := FALSE; + anz macros INCR 1; + IF anz macros > max macros + THEN errorstop ("Zu viele Macros (max. 200") + FI; + macro table . macro namen [anz macros] := symbol; + macro table . macro start [anz macros] := anz macro zeilen; + line; + put (symbol); + FI. + +hinter dem kommando steht noch was: + NOT (komm ende = length (zeile) COR + (komm ende + 1 = length (zeile) AND (zeile SUB komm ende + 1) = " ")). + +parameter aufsammeln: + INT VAR parameter number :: 1; + next symbol (symbol, type); + WHILE symbol = "$" REP + next symbol (symbol, type); + IF type = number CAND int (symbol) = parameter number + THEN IF parameter number > 9 + THEN errorstop ("Anzahl Parameter > 9") + FI; + macro table . anz parameter [anz macros] := parameter number; + parameter number INCR 1; + ELSE errorstop ("Parameter-Nummer inkorrekt: " + symbol) + FI; + next symbol (symbol, type); + IF symbol = ")" + THEN LEAVE parameter aufsammeln + ELIF symbol = "," + THEN next symbol (symbol, type) + ELSE errorstop (", oder ) erwartet:" + symbol) + FI + END REP; + errorstop ("Parameterliste inkorrekt bei" + symbol). +END PROC load macros; + +PROC load macros: + load macros (last param) +END PROC load macros; + +PROC list macros: + init macros; + note (""); + INT VAR i := 1; + WHILE i <= anz macro zeilen REP + cout (i); + note (macro table . macro zeilen [i]); + note line; + i INCR 1 + END REP; + note edit +END PROC list macros; + +BOOL PROC macro exists (TEXT CONST name, INT VAR anz params): + INT VAR i; + FOR i FROM 1 UPTO anz macros REP + IF macro table . macro namen [i] = name + THEN anz params := macro table . anz parameter [i]; + index aktuelle macro zeile := macro table . macro start [i] + 1; + berechne anzahl zeilen in macro; + IF anz params = 0 + THEN with parameters := FALSE + ELSE with parameters := TRUE; + lade macro in replacement store; + index aktuelle macro zeile := 1; + FI; + LEAVE macro exists WITH TRUE + FI + END REP; + FALSE. + +berechne anzahl zeilen in macro: + IF i = anz macros + THEN anz zeilen in macro := + anz macro zeilen - index aktuelle macro zeile; + ELSE anz zeilen in macro := + macro table . macro start [i + 1] - index aktuelle macro zeile + FI. + +lade macro in replacement store: + INT VAR k; + FOR k FROM 1 UPTO anz zeilen in macro REP + macro table . replacement store [k] := + macro table . macro zeilen [index aktuelle macro zeile +k-1] + END REP. +END PROC macro exists; + +PROC replace macro parameter (INT CONST number, TEXT CONST param): + TEXT VAR param text := "$" + text (number); + INT VAR k; + FOR k FROM 1 UPTO anz zeilen in macro - 1 REP + change all (macro table . replacement store [k], param text, param); + END REP +END PROC replace macro parameter; + +BOOL PROC macro command and then process parameters (TEXT VAR komm): + init macros; + LET tag = 1; + scan (komm); + next symbol (symbol, type); + IF type = tag + THEN untersuche ob deklariertes macro + ELSE FALSE + FI. + +untersuche ob deklariertes macro: + INT VAR anz macro params; + IF macro exists (symbol, anz macro params) + THEN fehlertext := "in Makro: "; fehlertext CAT symbol; + IF anz macro params > 0 + THEN macro parameter ersetzen + FI; + TRUE + ELSE FALSE + FI. + +macro parameter ersetzen: + next symbol (symbol, type); + IF symbol = "(" + THEN ersetze + ELSE report text processing error (34, 0, dummy, symbol + fehlertext); + LEAVE macro command and then process parameters WITH FALSE + FI. + +ersetze: + LET text type = 4, + end of scan = 7; + INT VAR number parameter :: 1; + REP + next symbol (symbol, type); + IF type = texttype + THEN replace macro parameter (number parameter, symbol); + ELSE report text processing error (35, 0, dummy, fehlertext + symbol); + LEAVE macro command and then process parameters WITH FALSE + FI; + number parameter INCR 1; + IF number parameter > anz macro params + THEN LEAVE macro command and then process parameters WITH TRUE + FI; + next symbol (symbol, type); + IF symbol <> "," OR type >= end of scan + THEN report text processing error (36, 0, dummy, fehlertext + symbol); + LEAVE macro command and then process parameters WITH FALSE + FI + END REP. +END PROC macro command and then process parameters; + +PROC get macro line (TEXT VAR macro zeile): + IF index aktuelle macro zeile > anz zeilen in macro + THEN macro zeile := "#### " + ELIF with parameters + THEN macro zeile := + macro table . replacement store [index aktuelle macro zeile] + ELSE macro zeile := + macro table . macro zeilen [index aktuelle macro zeile] + FI; + index aktuelle macro zeile INCR 1; +END PROC get macro line; + +INT PROC number macro lines: + anz zeilen in macro +END PROC number macro lines; +END PACKET macro store; + diff --git a/system/multiuser/1.7.5/src/multi user monitor b/system/multiuser/1.7.5/src/multi user monitor new file mode 100644 index 0000000..dd3051e --- /dev/null +++ b/system/multiuser/1.7.5/src/multi user monitor @@ -0,0 +1,93 @@ +(* ------------------- VERSION 2 16.05.86 ------------------- *) +PACKET multi user monitor DEFINES (* Autor: J.Liedtke *) + + monitor : + + +LET command list = + +"edit:1.01run:4.01runagain:6.0insert:7.01forget:9.01rename:11.2copy:12.2 +list:13.0storageinfo:14.0taskinfo:15.0 +fetch:16.1save:17.01break:19.0saveall:20.0 " ; + +LET text param type = 4 ; + + +INT VAR command index , number of params , previous heap size ; +TEXT VAR param 1, param 2 ; + + + lernsequenz auf taste legen ("q", ""1""8""1""12"break"13"") ; + lernsequenz auf taste legen ("e", ""1""8""1""12"edit"13"") ; + + +PROC monitor : + + disable stop ; + previous heap size := heap size ; + REP + command dialogue (TRUE) ; + sysin ("") ; + sysout ("") ; + cry if not enough storage ; + get command ("gib kommando :") ; + reset editor ; + analyze command (command list, text param type, + command index, number of params, param1, param2) ; + execute command ; + collect heap garbage if necessary + PER . + +collect heap garbage if necessary : + IF heap size > previous heap size + 10 + THEN collect heap garbage ; + previous heap size := heap size + FI . + +cry if not enough storage : + INT VAR size, used ; + storage (size, used) ; + IF used > size + THEN out (""7"Speicher Engpass! Dateien loeschen!"13""10"") + FI . + +reset editor : + WHILE aktueller editor > 0 REP + quit + PER ; + clear error . + +ENDPROC monitor ; + +PROC execute command : + + enable stop ; + SELECT command index OF + CASE 1 : edit + CASE 2 : edit (param1) + CASE 3 : (* war frueher paralleleditor *) + CASE 4 : run + CASE 5 : run (param1) + CASE 6 : run again + CASE 7 : insert + CASE 8 : insert (param1) + CASE 9 : forget + CASE 10: forget (param1) + CASE 11: rename (param1, param2) + CASE 12: copy (param1, param2) + CASE 13: list + CASE 14: storage info + CASE 15: task info + CASE 16: fetch (param1) + CASE 17: save + CASE 18: save (param1) + CASE 19: break + CASE 20: save all + + OTHERWISE do command + ENDSELECT . + +ENDPROC execute command ; + +ENDPACKET multi user monitor ; + diff --git a/system/multiuser/1.7.5/src/nameset b/system/multiuser/1.7.5/src/nameset new file mode 100644 index 0000000..8ea4359 --- /dev/null +++ b/system/multiuser/1.7.5/src/nameset @@ -0,0 +1,355 @@ +(* ------------------- VERSION 3 17.03.86 ------------------- *) +PACKET name set DEFINES (* Autor: J.Liedtke *) + + ALL , + SOME , + LIKE , + + , + - , + / , + do , + FILLBY , + remainder , + + fetch , + save , + fetch all , + save all , + forget , + erase , + insert , + edit : + + +LET cr lf = ""13""10"" ; + +TEXT VAR name ; +DATASPACE VAR edit space ; + +THESAURUS VAR remaining thesaurus := empty thesaurus ; + + +THESAURUS OP + (THESAURUS CONST left, right) : + + THESAURUS VAR union := left ; + INT VAR index := 0 ; + get (right, name, index) ; + WHILE name <> "" REP + IF NOT (union CONTAINS name) + THEN insert (union, name) + FI ; + get (right, name, index) + PER ; + union . + +ENDOP + ; + +THESAURUS OP + (THESAURUS CONST left, TEXT CONST right) : + + THESAURUS VAR union := left ; + IF NOT (union CONTAINS right) + THEN insert (union, right) + FI ; + union . + +ENDOP + ; + +THESAURUS OP - (THESAURUS CONST left, right) : + + THESAURUS VAR difference := empty thesaurus ; + INT VAR index := 0 ; + get (left, name, index) ; + WHILE name <> "" REP + IF NOT (right CONTAINS name) + THEN insert (difference, name) + FI ; + get (left, name, index) + PER ; + difference . + +ENDOP - ; + +THESAURUS OP - (THESAURUS CONST left, TEXT CONST right) : + + THESAURUS VAR difference := left ; + INT VAR index ; + delete (difference, right, index) ; + difference . + +ENDOP - ; + +THESAURUS OP / (THESAURUS CONST left, right) : + + THESAURUS VAR intersection := empty thesaurus ; + INT VAR index := 0 ; + get (left, name, index) ; + WHILE name <> "" REP + IF right CONTAINS name + THEN insert (intersection, name) + FI ; + get (left, name, index) + PER ; + intersection . + +ENDOP / ; + +THESAURUS OP ALL (TEXT CONST file name) : + + FILE VAR file := sequential file (input, file name) ; + THESAURUS VAR thesaurus := empty thesaurus ; + thesaurus FILLBY file ; + thesaurus . + +ENDOP ALL ; + +THESAURUS OP SOME (THESAURUS CONST thesaurus) : + + copy thesaurus into file ; + edit file ; + copy file into thesaurus . + +copy thesaurus into file : + forget (edit space) ; + edit space := nilspace ; + FILE VAR file := sequential file (output, edit space) ; + file FILLBY thesaurus . + +edit file : + modify (file) ; + edit (file) . + +copy file into thesaurus : + THESAURUS VAR result := empty thesaurus ; + input (file) ; + result FILLBY file ; + forget (edit space) ; + result . + +ENDOP SOME ; + +THESAURUS OP SOME (TASK CONST task) : + + SOME ALL task + +ENDOP SOME ; + +THESAURUS OP SOME (TEXT CONST file name) : + + SOME ALL file name + +ENDOP SOME ; + +THESAURUS OP LIKE (THESAURUS CONST thesaurus, TEXT CONST pattern) : + + THESAURUS VAR result:= empty thesaurus ; + INT VAR index:= 0 ; + REP get (thesaurus, name, index) ; + IF name = "" + THEN LEAVE LIKE WITH result + ELIF name LIKE pattern + THEN insert (result, name) + FI + PER ; + result . + +ENDOP LIKE ; + +THESAURUS PROC remainder : + + remaining thesaurus + +ENDPROC remainder ; + +PROC do (PROC (TEXT CONST) operate, THESAURUS CONST thesaurus) : + + INT VAR index := 0 , operation number := 0 ; + TEXT VAR name ; + + remaining thesaurus := empty thesaurus ; + disable stop ; + work off thesaurus ; + fill leftover with remainder . + +work off thesaurus : + REP + get (thesaurus, name, index) ; + IF name = "" + THEN LEAVE work off thesaurus + FI ; + operation number INCR 1 ; + cout (operation number) ; + execute (PROC (TEXT CONST) operate, name) + UNTIL is error ENDREP . + +fill leftover with remainder : + WHILE name <> "" REP + insert (remaining thesaurus, name) ; + get (thesaurus, name, index) + PER . + +ENDPROC do ; + +PROC execute (PROC (TEXT CONST) operate, TEXT CONST name) : + + enable stop ; + operate (name) + +ENDPROC execute ; + +PROC do (PROC (TEXT CONST, TASK CONST) operate, THESAURUS CONST thesaurus, + TASK CONST task) : + + INT VAR index := 0 , operation number := 0 ; + TEXT VAR name ; + + remaining thesaurus := empty thesaurus ; + disable stop ; + work off thesaurus ; + fill leftover with remainder . + +work off thesaurus : + REP + get (thesaurus, name, index) ; + IF name = "" + THEN LEAVE work off thesaurus + FI ; + operation number INCR 1 ; + cout (operation number) ; + execute (PROC (TEXT CONST, TASK CONST) operate, name, task) + UNTIL is error ENDREP . + +fill leftover with remainder : + WHILE name <> "" REP + insert (remaining thesaurus, name) ; + get (thesaurus, name, index) + PER . + +ENDPROC do ; + +PROC execute (PROC (TEXT CONST, TASK CONST) operate, + TEXT CONST name, TASK CONST task) : + + enable stop ; + operate (name, task) + +ENDPROC execute ; + +OP FILLBY (THESAURUS VAR thesaurus, FILE VAR file) : + + WHILE NOT eof (file) REP + getline (file, name) ; + delete trailing blanks ; + IF name <> "" CAND NOT (thesaurus CONTAINS name) + THEN insert (thesaurus, name) + FI + PER . + +delete trailing blanks : + WHILE (name SUB LENGTH name) = " " REP + name := subtext (name, 1, LENGTH name - 1) + PER . + +ENDOP FILLBY ; + +OP FILLBY (FILE VAR file, THESAURUS CONST thesaurus) : + + INT VAR index := 0 ; + REP + get (thesaurus, name, index) ; + IF name = "" + THEN LEAVE FILLBY + FI ; + putline (file, name) + PER . + +ENDOP FILLBY ; + +OP FILLBY (TEXT CONST file name, THESAURUS CONST thesaurus) : + + FILE VAR f := sequential file (output, file name) ; + f FILLBY thesaurus + +ENDOP FILLBY ; + + + +PROC fetch (THESAURUS CONST nameset) : + + do (PROC (TEXT CONST) fetch, nameset) + +ENDPROC fetch ; + +PROC fetch (THESAURUS CONST nameset, TASK CONST task) : + + do (PROC (TEXT CONST, TASK CONST) fetch, nameset, task) + +ENDPROC fetch ; + +PROC save (THESAURUS CONST nameset) : + + do (PROC (TEXT CONST) save, nameset) + +ENDPROC save ; + +PROC save (THESAURUS CONST nameset, TASK CONST task) : + + do (PROC (TEXT CONST, TASK CONST) save, nameset, task) + +ENDPROC save ; + +PROC fetch all : + + fetch all (father) + +ENDPROC fetch all ; + +PROC fetch all (TASK CONST manager) : + + fetch (ALL manager, manager) + +ENDPROC fetch all ; + +PROC save all : + + save all (father) + +ENDPROC save all ; + +PROC save all (TASK CONST manager) : + + save (ALL myself, manager) + +ENDPROC save all ; + +PROC forget (THESAURUS CONST nameset) : + + do (PROC (TEXT CONST) forget, nameset) + +ENDPROC forget ; + +PROC erase (THESAURUS CONST nameset) : + + do (PROC (TEXT CONST) erase, nameset) + +ENDPROC erase ; + +PROC erase (THESAURUS CONST nameset, TASK CONST task) : + + do (PROC (TEXT CONST, TASK CONST) erase, nameset, task) + +ENDPROC erase ; + +PROC insert (THESAURUS CONST nameset) : + + do (PROC (TEXT CONST) insert, nameset) + +ENDPROC insert ; + +PROC edit (THESAURUS CONST nameset) : + + do (PROC (TEXT CONST) edit, nameset) + +ENDPROC edit ; + +ENDPACKET name set ; + diff --git a/system/multiuser/1.7.5/src/pager b/system/multiuser/1.7.5/src/pager new file mode 100644 index 0000000..35189a4 --- /dev/null +++ b/system/multiuser/1.7.5/src/pager @@ -0,0 +1,2451 @@ +(*-------------------- VERSION 197 vom 05.05.86 -------(1.7.5)------ *) +PACKET seiten formatieren DEFINES pageform, + auto pageform, + number empty lines before foot, + first head, + last bottom: + +(* Programm zur interaktiven Formatierung von Seiten, Fussnoten, Kopf- und + Fusszeilen, Seitennummern usw. + Autor: Rainer Hahn + *) + +(***************** Deklarationen fuer pageform ************) + +LET type1 = 1, + linefeed = 3, + limit = 4, + free = 5, + page command0= 6, + page command1= 7, + pagenr = 8, + pagelength = 9, + foot = 10, + end = 11, + head = 12, + headeven = 13, + headodd = 14, + bottom = 15, + bottomeven = 16, + bottomodd = 17, + columns = 18, + columnsend = 19, + topage = 20, + goalpage = 21, + count0 = 22, + count1 = 23, + setcount = 24, + value0 = 25, + value1 = 26, + on = 27, + off = 28, + head on = 29, + head off = 30, + bottom on = 31, + bottom off = 32, + count per page=33, + foot contd = 34, + table = 35, + table end = 36, + r pos = 37, + l pos = 38, + c pos = 39, + d pos = 40, + b pos = 41, + clearpos0 = 42, + clearpos1 = 43, + fillchar = 44, + pageblock = 45, + counter1 = 46, + counter2 = 47, + counter store= 48, + countervalue0= 49, + countervalue1= 50, + set counter = 51, + u = 52, + d = 53, + e = 54, + fehler index = 100, + hop = ""1"", + upchar = ""3"", + cl eop = ""4"", + cl eol = ""5"", + downchar = ""10"", + rub in = ""11"", + rub out = ""12"", + return = ""13"", + end mark = ""14"", + begin mark = ""15"", + begin end mark = ""15""14"", + esc = ""27"", + blank = " ", + kommando zeichen = "#", + kopf = 1, + kopf gerade = 2, + fuss = 3, + fuss gerade = 4, + kopf ungerade = 5, + fuss ungerade = 6, + foot note = 7, + dina4 limit = "16.0", + dina4 pagelength = 25.0, + pos seitengrenze = 17, + zeilen nach oben = 13, + zeilen nach unten = 6, + max foot zeilen = 120, + max zeilen zahl = 15, + max refers = 300, + max anz seitenzeichen = 3; + +BOOL VAR interaktiv, + bereich aufnehmen, + zeile noch nicht verarbeitet, + es war ein linefeed in der zeile, + mindestens ein topage gewesen, + insert first head :: TRUE, + insert last bottom :: TRUE, + pageblock on, + ausgeschalteter head, + ausgeschalteter bottom, + count seitenzaehlung, + file works, + in tabelle, + in nullter seite, + letzte textzeile war mit absatz, + letztes seitenende war mit absatz, + letztes seitenende war in tabelle; + +INT VAR kommando anfangs pos, + kommando ende pos, + kommando index, + number blank lines before foot :: 1, + in index oder exponent, + durchgang, + nummer erste seite, + nummer letzte seite, + laufende spaltennr, + anz refers, + counter, + anz spalten, + anz zeilen nach oben, + anz vertauschte zeilen, + font nr, + type zeilenvorschub, + berechneter zeilenvorschub, + max zeilenvorschub, + max type zeilenvorschub, + textbegin zeilennr, + anz textzeilen, + text laenge vor columns, + bereichshoehe, + aktuelle seitenlaenge, + eingestellte seitenlaenge; + +REAL VAR real eingestellter zeilenvorschub, + realparam; + +TEXT VAR kommando, + par1, par2, + macro line, + vor macro, + nach macro, + dummy, + fehlerdummy, + modifikation, + modifikations speicher, + kommando seitenspeicher, + dec value, + counter numbering store, + counter reference store, + letzte kommandoleiste, + kommando speicher, + tab pos speicher, + bereich kommando speicher, + seitenzeichen, + name druck datei, + name eingabe datei, + zeile, + eingestellter typ, + eingestelltes limit; + +TEXT VAR kommando liste :: +"type:1.1linefeed:3.1limit:4.1free:5.1page:6.01pagenr:8.2pagelength:9.1 +foot:10.0end:11.0head:12.0headeven:13.0headodd:14.0bottom:15.0bottomeven:16.0 +bottomodd:17.0columns:18.2columnsend:19.0topage:20.1goalpage:21.1count:22.01 +setcount:24.1"; + +kommando liste CAT +"value:25.01on:27.1off:28.1headon:29.0headoff:30.0bottomon:31.0bottomoff:32.0 +countperpage:33.0footcontinued:34.0table:35.0tableend:36.0rpos:37.1lpos:38.1 +cpos:39.1dpos:40.2bpos:41.2clearpos:42.01fillchar:44.1pageblock:45.0"; + +kommando liste CAT +"counter:46.12storecounter:48.1putcounter:49.01setcounter:51.2u:52.0d:53.0 +e:54.0"; + +FILE VAR eingabe, + ausgabe; + +ROW 6 ROW max zeilenzahl TEXT VAR kopf fuss zeilen; + +ROW max foot zeilen TEXT VAR foot zeilen; + +ROW max foot zeilen BOOL VAR kommandos vorhanden; + +ROW 7 INT VAR anz kopf oder fuss zeilen, + kopf oder fuss laenge; + +ROW max anz seitenzeichen INT VAR laufende seitennr; + +BOUND ROW max refers REFER VAR refer sammler; + +LET REFER = STRUCT (TEXT kennzeichen, INT nummer, BOOL referenced); + +DATASPACE VAR ds; + +(********************* Einstell-Prozeduren ***************************) + +PROC first head (BOOL CONST was): + insert first head := was +END PROC first head; + +PROC last bottom (BOOL CONST was): + insert last bottom := was +END PROC last bottom; + +PROC number empty lines before foot (INT CONST n): + IF n >= 0 AND n < 10 + THEN number blank lines before foot := n + ELSE errorstop ("nur einstellbar zwischen 0 und 9") + FI +END PROC number empty lines before foot; + +(************************** Fehlermeldungen **********************) + +PROC fehler (INT CONST nr, TEXT CONST addition): + IF durchgang = 1 OR + kommando index = goalpage OR kommandoindex = count0 OR + kommando index = count1 OR kommando index = value1 OR + kommando index = topage OR kommando index = pagelength OR + kommando index = counterstoreOR kommando index = counter1 OR + kommando index = counter2 OR kommando index = countervalue1 + THEN fehler melden; + fehlermeldung auf terminal ausgeben + FI. + +fehler melden: + report text processing error (nr, line no (ausgabe), fehlerdummy, addition). + +fehlermeldung auf terminal ausgeben: + IF interaktiv + THEN cursor(1,2); out(cleop); + ELSE line + FI; + out (fehlerdummy); + line. +END PROC fehler; + +PROC warnung (INT CONST nr, TEXT CONST addition): + IF durchgang = 1 OR + kommando index = goalpage OR kommandoindex = count0 OR + kommando index = count1 OR kommando index = value1 OR + kommando index = topage OR kommando index = set counter + THEN fehler melden; + meldung auf terminal ausgeben + FI. + +fehler melden: + report text processing warning (nr, line no (ausgabe), fehlerdummy, addition). + +meldung auf terminal ausgeben: + IF interaktiv + THEN cursor(1,2); out(cleop); + ELSE line + FI; + out (fehlerdummy); + line. +END PROC warnung; + +(*************************** Globale Dateibehandlung **************) + +PROC datei assoziieren: + IF exists (name eingabe datei) + THEN ausgabe datei einrichten + ELSE errorstop (name eingabe datei + " existiert nicht") + FI. + +ausgabe datei einrichten: + IF name eingabe datei = name druck datei + THEN errorstop ("Name Eingabedatei = Name Ausgabedatei") + ELIF subtext (name eingabe datei, length (name eingabe datei) - 1) = ".p" + THEN errorstop ("Druckdatei kann nicht nochmal formatiert werden") + ELSE eingabe := sequential file (input, name eingabe datei); + copy (name eingabedatei, name druck datei); + ausgabe := sequential file (modify, name druck datei); + copy attributes (eingabe, ausgabe); + headline (ausgabe, name druck datei); + FI +END PROC datei assoziieren; + +PROC record einfuegen (TEXT CONST rec): + insert record (ausgabe); + write record (ausgabe, rec); + down (ausgabe); +END PROC record einfuegen; + +(******************** Kopf- oder Fusszeilen aufnehmen *************) + +PROC fussnote aufnehmen: + bereich aufnehmen := TRUE; + IF keine zeichen ausser blank nach dem kommando + THEN aufnehmen (footnote) + ELSE fehler (19, kommando) + FI; + in index oder exponent := 0; + bereich aufnehmen := FALSE +END PROC fussnote aufnehmen; + +PROC aufnehmen (INT CONST was): + kommando zustand vor bereich speichern; + aktuelle zeile ggf mitzaehlen; + aufnehmen initialisieren; + kopf oder fuss zeilen aufnehmen. + +kommando zustand vor bereich speichern: + kommandos in dummy speichern; + bereich kommando speicher := dummy. + +aktuelle zeile ggf mitzaehlen: +INT VAR einleitungs kommando anfang :: kommando anfangs pos; + IF kommando anfangs pos > 1 + THEN IF NOT only command line (zeile) + THEN aktuelle seitenlaenge INCR max zeilenvorschub + FI; + read record (ausgabe, zeile) + FI. + +aufnehmen initialisieren: + IF was = foot note + THEN initialisierung fuer fussnoten + ELSE anz kopf oder fuss zeilen [was] := 1; + kommandos in dummy speichern; + kopf fuss zeilen [was] [1] := dummy; + kopf oder fuss laenge [was] := 0; + FI; + bereichshoehe := kopf oder fusslaenge [was]. + +initialisierung fuer fussnoten: + INT CONST fussnotenlaenge vorher :: kopf oder fuss laenge [footnote], + anz fusszeilen vorher :: anz kopf oder fusszeilen [footnote]; + anz kopf oder fuss zeilen [footnote] INCR 1; + kommandos in dummy speichern; + kommandoleiste in fussnote speichern; (* davor *) + IF anz kopf oder fuss zeilen [footnote] = 1 + THEN unterstreichungsstrich + FI. + +kommandoleiste in fussnote speichern: + foot zeilen [anz kopf oder fuss zeilen [footnote]] := dummy; + kommandos vorhanden [anz kopf oder fuss zeilen [footnote]]:= TRUE. + +unterstreichungsstrich: + FOR i FROM 2 UPTO max foot zeilen REP + kommandos vorhanden [i] := FALSE + ENDREP; + FOR i FROM 1 UPTO number blank lines before foot REP + foot zeilen [i + 1] := " " + END REP; + foot zeilen [number blank lines before foot + 2] := + "#on(""underline"")#               #off(""underline"")# "; + kopf oder fuss laenge [footnote] := + (number blank lines before foot + 1) * berechneter zeilenvorschub; + anz kopf oder fuss zeilen [footnote] := number blank lines before foot + 2. + +kopf oder fuss zeilen aufnehmen: +INT VAR anzahl :: 1; + REP + naechste zeile lesen; + cout (line no (ausgabe)); + IF mindestens ein kommando vorhanden + THEN kommandos von kopf oder fuss verarbeiten + FI; + in index oder exponent := 0; + zeile aufnehmen; + anzahl INCR 1 + UNTIL eof (ausgabe) END REP; + errorstop ("end fehlt bei Dateiende"). + +kommandos von kopf oder fuss verarbeiten: + max zeilenvorschub := berechneter zeilenvorschub; + max type zeilenvorschub := type zeilenvorschub; + kommando anfangs pos := pos (zeile, kommando zeichen); + WHILE kommando anfangs pos <> 0 REP + verarbeite kommando; + kommandos von kopf oder fuss pruefen; + kommando anfangs pos := + pos (zeile, kommando zeichen, kommando ende pos + 1) + END REP. + +kommandos von kopf oder fuss pruefen: + IF kommandoindex = end + THEN aufnehmen beenden + ELIF kommando index = free + THEN IF y step conversion (realparam) >= eingestellte seitenlaenge + THEN fehler (24, text (realparam)) + ELSE kopf oder fusslaenge [was] INCR y step conversion (realparam) + FI + ELIF seitenende + THEN INT VAR xx := durchgang; + durchgang := 1; + fehler (25, ""); + durchgang := xx; + zeile zurueck lesen; + kommando index := end; + LEAVE aufnehmen + ELIF kommando index = fehler index + THEN LEAVE aufnehmen + ELIF kommando index > free AND kommando index < to page + THEN fehler (11, kommando); + kommando index := fehler index; + LEAVE aufnehmen + FI. + +aufnehmen beenden: + IF kommando anfangs pos > 1 + THEN IF absatzzeile + THEN zeile := subtext (zeile, 1, kommando anfangs pos -1); + zeile CAT blank; + ELSE zeile := subtext (zeile, 1, kommando anfangs pos -1); + FI; + zeile aufnehmen + FI; + IF NOT (durchgang = 1 AND was = footnote) + THEN die aufgenommenen zeilen in druckdatei loeschen + FI; + LEAVE aufnehmen. + +die aufgenommenen zeilen in druckdatei loeschen: + INT VAR i; + delete record (ausgabe); + FOR i FROM 1 UPTO anzahl - 1 REP + up (ausgabe); + delete record (ausgabe) + END REP; + zeile zurueck lesen; + letztes kommando dieser zeile loeschen; + ggf kommandoleiste generieren. + +letztes kommando dieser zeile loeschen: + IF einleitungs kommando anfang = 1 + THEN delete record (ausgabe); + IF line no (ausgabe) = 1 + THEN zeile noch nicht verarbeitet := TRUE + ELSE zeile zurueck lesen + FI + ELSE dummy := subtext (zeile, 1, einleitungs kommando anfang - 1); + IF absatz zeile + THEN dummy CAT blank; + ELIF (dummy SUB length (dummy)) = " " + THEN delete char (dummy, length (dummy)) + FI; + write record (ausgabe, dummy) + FI. + +ggf kommandoleiste generieren: + kommandos in dummy speichern; + IF was = footnote + THEN anz kopf oder fusszeilen [footnote] INCR 1; + kommandoleiste in fussnote speichern (* danach *) + FI; + IF dummy <> bereich kommando speicher + THEN down (ausgabe); + record einfuegen (dummy); + up (ausgabe, 2); + FI. + +zeile aufnehmen: + zeile speichern (was, anzahl); + IF erreichte seitenlaenge > eingestellte seitenlaenge + THEN bereich aufnehmen := FALSE; + IF kommando index = end + THEN seitenende nach geteilter fussnote + ELSE seitenende vor der fussnote + FI; + kommando index := end; + LEAVE aufnehmen + FI. + +seitenende nach geteilter fussnote: + kopf oder fuss laenge [footnote] DECR max zeilenvorschub; + anz kopf oder fuss zeilen [footnote] DECR 1; + seitenende einbringen und zurueck. + +seitenende vor der fussnote: + kopf oder fuss laenge [footnote] := fussnotenlaenge vorher; + anz kopf oder fuss zeilen [footnote] := anz fusszeilen vorher; + ende einer seite. +END PROC aufnehmen; + +PROC zeile speichern (INT CONST was, anzahl): + zeile mitzaehlen; + IF was = footnote + THEN fussnote aufnehmen + ELIF anz kopf oder fuss zeilen [was] > max zeilenzahl + THEN errorstop ("Zu viele 'head' oder 'bottom' Zeilen"); + ELSE kopf fuss zeilen [was] [anz kopf oder fuss zeilen [was]] := zeile + FI. + +zeile mitzaehlen: + anz kopf oder fuss zeilen [was] INCR 1; + IF NOT only command line (zeile) + THEN IF mindestens ein kommando vorhanden + THEN kopf oder fuss laenge [was] INCR max zeilenvorschub; + bereichshoehe INCR max zeilenvorschub + ELSE kopf oder fuss laenge [was] INCR berechneter zeilenvorschub; + bereichshoehe INCR berechneter zeilenvorschub + FI; + IF bereichshoehe >= eingestellte seitenlaenge + THEN errorstop + ("head, bottom oder footzeilen > Seitenlänge (end vergessen?)") + FI + FI; + IF es war ein linefeed in der zeile + THEN berechne zeilenvorschub; + es war ein linefeed in der zeile := FALSE + FI; + IF erreichte seitenlaenge > eingestellte seitenlaenge + THEN fussnotenumbruch pruefung + FI. + +fussnote aufnehmen: + IF anz kopf oder fuss zeilen [footnote] > max footzeilen + THEN errorstop ("Zu viele Fußnotenzeilen") + ELIF bereichshoehe > eingestellte seitenlaenge - seitenlaenge fester teil + - (eingestellte seitenlaenge DIV 100 * 15) + THEN errorstop ("Fußnote > 85% der Seitenlänge (end vergessen?)") + ELSE foot zeilen [anz kopf oder fuss zeilen [footnote]] := zeile + FI. + +fussnotenumbruch pruefung: + IF fussnotenumbruch moeglich + THEN ggf fussnote aufbrechen + ELSE lese rueckwaerts um (anzahl); + IF only command line (zeile) + THEN lese rueckwaerts um (1) + FI + FI. + +fussnotenumbruch moeglich: + was = footnote AND anzahl > 2. + +ggf fussnote aufbrechen: + up (ausgabe); + IF interaktiv + THEN fussnotenumbruch anfrage; + line (2) + FI; + anweisungen fuer umbruch einfuegen. + +fussnotenumbruch anfrage: + schreibe titelzeile ("Weiterführen der Fußnote auf nächster Seite (j/n)?"); + line (2); + schreibe bildschirm; + cursor (53, 1); + skip input; + REP + TEXT VAR steuerzeichen; + inchar (steuerzeichen); + IF steuerzeichen = "n" + THEN lese rueckwaerts um (anzahl - 1); + IF only command line (zeile) + THEN lese rueckwaerts um (1) + FI; + LEAVE ggf fussnote aufbrechen + ELIF steuerzeichen = "j" OR steuerzeichen = return + THEN LEAVE fussnotenumbruch anfrage + ELIF steuerzeichen = esc + THEN errorstop ("Abbruch durch ESC") + FI + END REP. + +anweisungen fuer umbruch einfuegen: + record einfuegen ("#end#"); + record einfuegen ("#foot continued#"); + kommandos in dummy speichern; + record einfuegen (dummy); + record einfuegen ("Forts. von letzter Seite: "); + lese rueckwaerts um (3); + kommando index := end. +END PROC zeile speichern; + +PROC lese rueckwaerts um (INT CONST anzahl): + to line (ausgabe, line no (ausgabe) - anzahl); + read record (ausgabe, zeile) +END PROC lese rueckwaerts um; + +PROC schreibe kopf oder fuss (INT CONST was): + IF was = footnote + THEN fussnoten generieren + ELIF laufende spaltennr < 2 + THEN kopf oder fuss zeilen generieren + FI. + +kopf oder fusszeilen generieren: +INT VAR i :: 1; +BOOL VAR in generierter zeile war kommando :: FALSE; + ggf anfangs kommandos generieren; + FOR i FROM 2 UPTO anz kopf oder fuss zeilen [was] REP + dummy := kopf fuss zeilen [was] [i]; + IF NOT in generierter zeile war kommando + THEN in generierter zeile war kommando := + pos (dummy, kommandozeichen) <> 0 + FI; + fuege seitennr ein; + record einfuegen (dummy) + END REP; + ggf ende kommandos generieren. + +ggf anfangs kommandos generieren: + kommandos in dummy speichern; + IF dummy <> kopf fuss zeilen [was] [1] + THEN record einfuegen (kopf fuss zeilen [was] [1]) + FI. + +ggf ende kommandos generieren: + kommandos in dummy speichern; + IF dummy <> kopf fuss zeilen [was] [1] OR + in generierter zeile war kommando + THEN record einfuegen (dummy) + FI. + +fuege seitennr ein: +INT VAR k; + change all (dummy, + (seitenzeichen SUB 1) + (seitenzeichen SUB 1), + text (laufende seitennr [1] +1)); + FOR k FROM 1 UPTO length (seitenzeichen) REP + change all (dummy, seitenzeichen SUB k, text (laufende seitennr [k])); + END REP. + +fussnoten generieren: + kommandos in dummy speichern; + letzte kommandoleiste := dummy; + i := 1; + WHILE i < anz kopf oder fusszeilen [footnote] REP + IF kommandos vorhanden [i] + THEN IF letzte kommandoleiste <> footzeilen [i] + THEN record einfuegen (footzeilen [i]); + letzte kommandoleiste := footzeilen [i] + FI + ELSE record einfuegen (footzeilen [i]) + FI; + i INCR 1 + END REP; + IF footzeilen [i] <> dummy + THEN record einfuegen (dummy) + FI +END PROC schreibe kopf oder fuss; + +PROC fussnoten loeschen: + kopf oder fuss laenge [footnote] := 0; + anz kopf oder fuss zeilen [footnote] := 0 +END PROC fussnoten loeschen; + +PROC schreibe ggf fuss: + record einfuegen ("#text end#"); + ggf tabellenende generieren; + letztes seitenende war mit absatz := letzte textzeile war mit absatz; + IF erreichte seitenlaenge <> eingestellte seitenlaenge + THEN schreibe freien platz + FI; + IF kopf oder fuss laenge [footnote] > 0 + THEN ggf tabellenende generieren; + schreibe kopf oder fuss (footnote); + fussnoten loeschen + FI; + IF (NOT insert last bottom AND laufende seitennr [1] = nummer letzte seite) + OR ausgeschalteter bottom + THEN + ELSE schreibe mal fussbereich + FI. + +schreibe mal fussbereich: + IF kopf oder fuss laenge [fuss] > 0 + THEN schreibe kopf oder fuss (fuss) + ELIF kopf oder fuss laenge [fuss gerade] > 0 AND + (laufende seitennr [1] MOD 2 = 0) + THEN schreibe kopf oder fuss (fuss gerade) + ELIF kopf oder fuss laenge [fuss ungerade] > 0 AND + (laufende seitennr [1] MOD 2 <> 0) + THEN schreibe kopf oder fuss (fuss ungerade) + FI. + +ggf tabellenende generieren: + IF tab pos speicher <> "" + THEN record einfuegen ("#clear pos# ") + FI; + IF in tabelle + THEN record einfuegen ("#table end# "); + letztes seitenende war in tabelle := TRUE; + in tabelle := FALSE + FI. + +schreibe freien platz: + IF pageblock on + THEN schreibe ggf stauchung oder streckungs anweisung + ELSE schreibe free (eingestellte seitenlaenge - erreichte seitenlaenge) + FI. + +schreibe ggf stauchung oder streckungs anweisung: + IF interaktiv AND seitenluecke > fuenf prozent der seitenlaenge + THEN cursor (1, 2); + dummy := begin mark; + dummy CAT "Soll die Seite beim Druck gestreckt werden ("; + dummy CAT text (ystepconversion (seitenluecke)); + dummy CAT " cm)"; + dummy CAT end mark; + IF no (dummy) + THEN cursor (1, 2); + out (cl eol); + schreibe free + (eingestellte seitenlaenge - erreichte seitenlaenge); + line; + LEAVE schreibe ggf stauchung oder streckungs anweisung + FI; + cursor (1, 2); + out (cl eol); + line + FI; + INT VAR i :: lineno (ausgabe); + to line (ausgabe, textbegin zeilennr); + dummy := "#textbegin ("; + dummy CAT text (anz textzeilen); + dummy CAT ", """; + dummy CAT text (ystepconversion (seitenluecke)); + dummy CAT """)#"; + read record (ausgabe, zeile); + IF (zeile SUB length (zeile)) = blank + THEN dummy CAT blank + FI; + write record (ausgabe, dummy); + to line (ausgabe, i). + +seitenluecke: + eingestellte seitenlaenge - erreichte seitenlaenge. + +fuenf prozent der seitenlaenge: + ((eingestellte seitenlaenge + 99) DIV 100) * 5. +END PROC schreibe ggf fuss; + +(**************************** kommando speicherung *****************) + +PROC grenzmarkierung in dummy speichern: + dummy := "#page##"; + dummy CAT (3 * "-----------"); + dummy CAT " Ende der Seite "; + IF in nullter seite + THEN dummy CAT "0 " + ELSE dummy CAT (text (laufende seitennr [1]) + blank) + FI; + IF anz spalten > 1 + THEN dummy CAT "und Spalte "; + dummy CAT (text (laufende spaltennr) + blank) + ELSE dummy CAT "-----------" + FI; + dummy CAT kommando zeichen +END PROC grenzmarkierung in dummy speichern; + +PROC kommandos in dummy speichern: + type speichern; + dummy CAT modifikation; + limit speichern; + linefeed mit absatzblank speichern. + +type speichern: + dummy := "#type("""; + dummy CAT eingestellter typ; + dummy CAT """)#". + +limit speichern: + dummy CAT "#limit("; + dummy CAT eingestelltes limit; + dummy CAT ")#". + +linefeed mit absatzblank speichern: + dummy CAT "#linefeed(0"; + dummy CAT text (real eingestellter zeilenvorschub); + dummy CAT ")# ". +END PROC kommandos in dummy speichern; + +PROC kommandos aufheben: + kommandos in dummy speichern; + kommando speicher := dummy +END PROC kommandos aufheben; + +PROC kommandos wiederherstellen: + zeile := kommando speicher; + kommandos verarbeiten; + berechneter zeilenvorschub := + int (real (type zeilenvorschub) * real eingestellter zeilenvorschub + 0.5); + max zeilenvorschub := berechneter zeilenvorschub; + max type zeilenvorschub := type zeilenvorschub +END PROC kommandos wiederherstellen; + +(**************************** headzeilen einfuegen ************************) + +PROC schreibe ggf kopf: + IF (NOT insert first head AND laufende seiten nr [1] = nummer erste seite) + OR ausgeschalteter head + THEN + ELSE schreibe mal + FI; + ggf tabellenanfang generieren; + text begin anweisung generieren. + +schreibe mal: + IF kopf oder fuss laenge [kopf] > 0 + THEN schreibe kopf oder fuss (kopf); + aktuelle seitenlaenge INCR kopf oder fuss laenge [kopf] + ELIF kopf oder fuss laenge [kopf gerade] > 0 + AND (laufende seitennr [1] MOD 2 = 0) + THEN schreibe kopf oder fuss (kopf gerade); + aktuelle seitenlaenge INCR kopf oder fuss laenge [kopf gerade] + ELIF kopf oder fuss laenge [kopf ungerade] > 0 + AND (laufende seitennr [1] MOD 2 <> 0) + THEN schreibe kopf oder fuss (kopf ungerade); + aktuelle seitenlaenge INCR kopf oder fuss laenge [kopf ungerade] + FI. + +ggf tabellenanfang generieren: + IF tab pos speicher <> "" + THEN record einfuegen ("#clearpos#"); + record einfuegen (tab pos speicher) + FI; + IF letztes seitenende war in tabelle + THEN record einfuegen ("#table# "); + letztes seitenende war in tabelle := FALSE; + in tabelle := TRUE + FI. + +text begin anweisung generieren: + dummy := "#text begin#"; + IF letztes seitenende war mit absatz + THEN dummy CAT " " + FI; + record einfuegen (dummy); + textbegin zeilennr := line no (ausgabe) - 1. +END PROC schreibe ggf kopf; + +PROC erhoehe seiten und spaltennr: + IF anz spalten > 1 + THEN erhoehe spaltennummer + FI; + IF NOT in nullter seite + THEN erhoehe seitennummer + FI. + +erhoehe spaltennummer: + laufende spaltennr INCR 1; + IF laufende spaltennr > anz spalten + THEN laufende spaltennr := 1; + text laenge vor columns := 0 + ELSE LEAVE erhoehe seiten und spaltennr + FI. + +erhoehe seitennummer: + INT VAR i; + FOR i FROM 1 UPTO length (seitenzeichen) REP + laufende seitennr [i] INCR 1 + END REP +END PROC erhoehe seiten und spaltennr; + +PROC seitennummer setzen (INT CONST akt nummer): + IF pos (seitenzeichen, par1) = 0 + THEN IF length (seitenzeichen) >= max anz seitenzeichen + THEN fehler (16, ""); + LEAVE seitennummer setzen + FI; + seitenzeichen CAT par1 + FI; + laufende seitennr [pos (seitenzeichen, par1)] := akt nummer. +END PROC seitennummer setzen; + +PROC kommando seitenspeicher fuellen: + kommando seitenspeicher CAT "#"; + kommando seitenspeicher CAT kommando; + kommando seitenspeicher CAT "#" +END PROC kommando seitenspeicher fuellen; + +(************************** kommandos verarbeiten ********************) + +PROC verarbeite kommando: +INT VAR anz params, intparam; + kommando ende pos := + pos (zeile, kommando zeichen, kommando anfangs pos + 1); + IF kommando ende pos <> 0 + THEN kommando oder kommentar kommando verarbeiten + ELSE fehler (2, + subtext (zeile, kommandoanfangspos, kommandoanfangspos+9)+"..."); + zeile CAT kommando zeichen; + write record (ausgabe, zeile); + kommando ende pos := length (zeile) + FI. + +kommando oder kommentar kommando verarbeiten: + IF pos ("-/"":", zeile SUB kommando anfangs pos + 1) = 0 + THEN kommando := + subtext (zeile, kommando anfangs pos + 1, kommando ende pos - 1); + scanne kommando; + setze kommando um + ELSE kommando index := 0 + FI. + +scanne kommando: + analyze command (kommandoliste, kommando, 3, + kommando index, anz params, par1, par2); + disable stop; + command error; + IF is error + THEN dummy := error message; + clear error; + dummy CAT " -> "; + dummy CAT kommando; + fehler (22, dummy); + enable stop; + LEAVE verarbeite kommando + FI; + enable stop. + +setze kommando um: + IF durchgang = 3 AND kommando index <> value1 AND kommando index <> to page + AND kommando index <> counter value1 + THEN LEAVE verarbeite kommando + FI; + SELECT kommando index OF + +CASE type1: + modifikation := ""; + IF in index oder exponent > 0 + THEN LEAVE setze kommando um + ELIF font exists (par1) + THEN font nr := font (par1); + eingestellter typ := par1; + type zeilenvorschub := + font height (fontnr) + font lead (fontnr) + font depth (fontnr); + IF type zeilenvorschub > max type zeilenvorschub + THEN max type zeilenvorschub := type zeilenvorschub + FI + ELSE fehler (1, par1) + FI; + berechne zeilenvorschub + +CASE linefeed: + realparam := real (par1); + IF last conversion ok AND pos (par1, ".") <> 0 + THEN real eingestellter zeilenvorschub := realparam; + es war ein linefeed in der zeile := TRUE + ELSE fehler (4, par1) + FI + +CASE limit: + eingestelltes limit := par1 + +CASE free: + realparam := real (par1); + IF last conversion ok AND pos (par1, ".") <> 0 + THEN IF keine zeichen ausser blank nach dem kommando + THEN free kommando ausfuehren + ELSE fehler (19, kommando); + FI + ELSE fehler (4, par1) + FI + +CASE page command0: + IF keine zeichen ausser blank nach dem kommando + THEN page behandlung; + schreibe titelzeile + ELSE fehler (19, kommando) + FI + +CASE page command1: + IF keine zeichen ausser blank nach dem kommando + THEN INT VAR seitennummer mit page := int (par1); + page behandlung; + laufende spaltennr := 1; + text laenge vor columns := 0; + IF seitennummer mit page <= 0 + THEN fehler (27, "page (" + text (seitennummer mit page) + ")") + ELSE laufende seitennr [1] := seitennummer mit page + FI + ELSE fehler (19, kommando) + FI + +CASE pagenr: + IF in nullter seite OR durchgang = 4 + THEN intparam := int (par2); + IF length (par1) <> 1 + THEN fehler (14, "") + ELIF NOT last conversion ok + THEN fehler (5, kommando) + ELIF intparam <= 0 + THEN fehler (27, kommando) + ELSE seitennummer setzen (intparam) + FI + ELIF durchgang = 2 + THEN kommando seitenspeicher fuellen + FI + +CASE pagelength: + realparam := real (par1); + IF last conversion ok AND pos (par1, ".") <> 0 + THEN IF in nullter seite OR durchgang = 4 + THEN eingestellte seitenlaenge := y step conversion (realparam) + ELIF durchgang = 2 + THEN kommando seitenspeicher fuellen + FI + ELSE fehler (4, kommando) + FI + +CASE foot, foot contd: + fussnote aufnehmen + +CASE end: + IF NOT bereich aufnehmen + THEN fehler (31, "") + FI; + bereich aufnehmen := FALSE; + kommando index := end; + IF NOT keine zeichen ausser blank nach dem kommando + THEN fehler (19, kommando) + FI + +CASE head: + bereich aufnehmen := TRUE; + IF keine zeichen ausser blank nach dem kommando + THEN kopf oder fuss laenge [kopf ungerade] := 0; + kopf oder fuss laenge [kopf gerade] := 0; + aufnehmen (kopf) + ELSE fehler (19, kommando) + FI; + bereich aufnehmen := FALSE + +CASE headeven: + bereich aufnehmen := TRUE; + IF keine zeichen ausser blank nach dem kommando + THEN kopf oder fuss laenge [kopf] := 0; + aufnehmen (kopf gerade) + ELSE fehler (19, kommando) + FI; + bereich aufnehmen := FALSE + +CASE headodd: + bereich aufnehmen := TRUE; + IF keine zeichen ausser blank nach dem kommando + THEN kopf oder fuss laenge [kopf] := 0; + aufnehmen (kopf ungerade) + ELSE fehler (19, kommando) + FI; + bereich aufnehmen := FALSE + +CASE bottom: + bereich aufnehmen := TRUE; + IF keine zeichen ausser blank nach dem kommando + THEN kopf oder fuss laenge [fuss ungerade] := 0; + kopf oder fuss laenge [fuss gerade] := 0; + aufnehmen (fuss) + ELSE fehler (19, kommando) + FI; + bereich aufnehmen := FALSE + +CASE bottomeven: + bereich aufnehmen := TRUE; + IF keine zeichen ausser blank nach dem kommando + THEN kopf oder fuss laenge [fuss] := 0; + aufnehmen (fuss gerade) + ELSE fehler (19, kommando) + FI; + bereich aufnehmen := FALSE + +CASE bottomodd: + bereich aufnehmen := TRUE; + IF keine zeichen ausser blank nach dem kommando + THEN kopf oder fuss laenge [fuss] := 0; + aufnehmen (fuss ungerade) + ELSE fehler (19, kommando) + FI; + bereich aufnehmen := FALSE + +CASE columns: + IF anz spalten > 1 + THEN fehler (29, "") + ELSE anz spalten := int (par1); + laufende spalten nr := 1; + IF anz spalten < 2 + THEN fehler (26, ""); + anz spalten := 2 + FI; + text laenge vor columns := + aktuelle seitenlaenge + kopf oder fuss laenge [footnote] + FI + +CASE columnsend: + IF durchgang = 1 + THEN delete record (ausgabe); + IF NOT nur dateiende danach + THEN seitenende einbringen und zurueck; + record einfuegen ("#columnsend#"); + text laenge vor columns := 0; + laufende spaltennr := 1; + anz spalten := 1; + kommando index := page command0; + down (ausgabe) + FI + FI + +CASE topage: + IF durchgang > 1 + THEN ggf gespeicherte nummer einsetzen (par1); + mindestens ein topage gewesen := TRUE + FI + +CASE goalpage: + IF durchgang > 1 + THEN nummer und kennzeichen speichern (laufende seitennr[1], par1) + FI + +CASE count0, count1: + IF durchgang > 1 + THEN counter INCR 1; + change (zeile, + kommando anfangs pos, kommando ende pos, text(counter)); + kommando ende pos := kommando anfangs pos; + write record (ausgabe, zeile); + IF anz params = 1 + THEN nummer und kennzeichen speichern (counter, par1) + FI + FI + +CASE setcount: + intparam := int (par1); + IF last conversion ok AND intparam >= 0 + THEN counter := intparam - 1 + ELSE fehler (30, par1) + FI + +CASE value0: + IF durchgang > 1 + THEN change (zeile, kommando anfangs pos, kommando ende pos, + text (counter)); + write record (ausgabe, zeile); + kommando ende pos := kommando anfangs pos + FI + +CASE value1: + IF durchgang > 1 + THEN ggf gespeicherte nummer einsetzen (par1) + FI + +CASE on: + change all (par1, " ", ""); + par1 := (par1 SUB 1); + modifikation CAT "#on(""" + par1 + """)#" + +CASE off: + change all (par1, " ", ""); + par1 := (par1 SUB 1); + changeall (modifikation, "#on(""" + par1 + """)#", ""); + +CASE head on: ausgeschalteter head := FALSE +CASE head off: ausgeschalteter head := TRUE + +CASE bottom on: ausgeschalteter bottom := FALSE +CASE bottom off: ausgeschalteter bottom := TRUE + +CASE count per page: count seitenzaehlung := TRUE + +CASE table: + IF durchgang > 1 + THEN in tabelle := TRUE + FI + +CASE table end: + IF durchgang > 1 + THEN in tabelle := FALSE + FI + +CASE r pos, l pos, c pos, d pos, b pos, clearpos1, fillchar: + IF durchgang > 1 + THEN tab pos speicher CAT "#"; + tab pos speicher CAT kommando; + tab pos speicher CAT "#" + FI + +CASE clearpos0: + IF durchgang > 1 + THEN tab pos speicher := "" + FI + +CASE pageblock : pageblock on := TRUE + +CASE counter1, counter2: + IF durchgang > 1 + THEN process counter + FI + +CASE set counter: + IF durchgang > 1 + THEN process set counter + FI + +CASE counter store: + IF durchgang > 1 + THEN process counter store + FI + +CASE counter value0: + IF durchgang > 1 + THEN write dec value into file + FI + +CASE counter value1: + IF durchgang > 1 + THEN process counter value + FI + +CASE u, d: + in index oder exponent INCR 1 + +CASE e: + in index oder exponent DECR 1 + +OTHERWISE + kommando index := 0; + IF macro command and then process parameters (kommando) + THEN ersetze macro + FI +END SELECT. + +nur dateiende danach: + INT VAR diese zeile :: line no (ausgabe); + WHILE NOT eof (ausgabe) REP + read record (ausgabe, zeile); + IF length (zeile) > 1 + THEN to line (ausgabe, diese zeile); + read record (ausgabe, zeile); + LEAVE nur dateiende danach WITH FALSE + FI; + down (ausgabe) + END REP; + to line (ausgabe, diese zeile); + read record (ausgabe, zeile); + TRUE. +END PROC verarbeite kommando; + +(************************ Makro-Ersetzung **************************) + +PROC ersetze macro: + INT VAR erste zeile :: line no (ausgabe); + hole texte um macro herum; + fuege macro zeilen ein; + fuege text nach macro an; + positioniere zurueck. + +hole texte um macro herum: + vor macro := subtext (zeile, 1, kommando anfangs pos - 1); + nach macro := subtext (zeile, kommando ende pos + 1). + +fuege macro zeilen ein: + INT VAR anz :: 1; + WHILE anz < number macro lines REP + get macro line (macro line); + IF anz = 1 + THEN vor macro CAT macro line ; + write record (ausgabe, vor macro); + ELSE down (ausgabe); + insert record (ausgabe); + write record (ausgabe, macro line) + FI; + anz INCR 1 + END REP. + +fuege text nach macro an: + read record (ausgabe, zeile); + IF length (nach macro) <> 0 + THEN zeile CAT nach macro + ELIF (zeile SUB length (zeile)) <> blank AND number macro lines > 2 + THEN delete record (ausgabe); + read record (ausgabe, dummy); + zeile CAT dummy + FI; + IF subtext (zeile, length (zeile) - 1, length (zeile)) = " " + THEN delete char (zeile, length (zeile)) + FI; + write record (ausgabe, zeile). + +positioniere zurueck: + to line (ausgabe, erste zeile); + read record (ausgabe, zeile); + IF in nullter seite + THEN zeile noch nicht verarbeitet := TRUE + FI; + kommando ende pos := kommando anfangs pos - 1. +END PROC ersetze macro; + +(************************ Zeilenvorschub-Berechnung ****************) + +PROC berechne zeilenvorschub: + berechneter zeilenvorschub := + int (real (type zeilenvorschub) * real eingestellter zeilenvorschub + 0.5); + IF real eingestellter zeilenvorschub >= 1.0 + THEN max zeilenvorschub := max + (int (real (max type zeilenvorschub)*real eingestellter zeilenvorschub + 0.5), + berechneter zeilenvorschub) + ELIF berechneter zeilenvorschub > max zeilenvorschub + THEN max zeilenvorschub := berechneter zeilenvorschub + FI +END PROC berechne zeilenvorschub; + +(**************************** counter processing **********************) + +PROC process counter: + dummy := "#"; + dummy CAT par1; + dummy CAT "#"; + IF pos (counter numbering store, dummy) = 0 + THEN fehler (34, par1); + LEAVE process counter + FI; + get dec value (counter numbering store); + IF kommando index = counter2 + THEN resize dec value to needed points + FI; + IF dec value was just initialized + THEN dec value := subtext (dec value, 2) + ELIF kommando index = counter1 + THEN digit value := int (dec value); + digit value INCR 1; + dec value := text (digit value) + ELSE incr counter value + FI; + write dec value into file; + replace value in numbering store (dec value). + +resize dec value to needed points: + INT VAR needed points :: int (par2), + begin of last digit :: 1; + WHILE needed points > 0 REP + IF next point pos = 0 + THEN IF needed points = 1 + THEN dec value CAT ".0" + ELSE dec value CAT ".1" + FI; + begin of last digit := length (dec value) + ELSE begin of last digit := next point pos + 1 + FI; + needed points DECR 1 + END REP; + INT VAR end of last digit := next point pos - 1; + IF end of last digit < 0 + THEN end of last digit := length (dec value) + FI; + dec value := subtext (dec value, 1, end of last digit). + +next point pos: + pos (dec value, ".", begin of last digit). + +dec value was just initialized: + (dec value SUB 1) = "i". + +incr counter value: + INT VAR digit value :: int ( + subtext (dec value, begin of last digit, end of last digit)); + digit value INCR 1; + change (dec value, begin of last digit, end of last digit, + text (digit value)). +END PROC process counter; + +PROC process set counter: + dummy := "#"; + dummy CAT par1; + dummy CAT "#"; + IF pos (counter numbering store, dummy) <> 0 + THEN warnung (15, par1); + replace value in numbering store (par2); + INT VAR begin pos :: pos (counter numbering store, dummy) + 1; + begin pos := pos (counter numbering store, "#", beginpos) + 1; + insert char (counter numbering store, "i", begin pos) + ELSE counter numbering store CAT dummy; + counter numbering store CAT "i"; + counter numbering store CAT par2 + FI. +END PROC process set counter; + +PROC process counter store: + IF pos (counter reference store, par1) <> 0 + THEN fehler (35, par1) + ELSE store it + FI. + +store it: + counter reference store CAT "#"; + counter reference store CAT par1; + counter reference store CAT "#"; + counter reference store CAT dec value +END PROC process counter store; + +PROC process counter value: + dummy := "#"; + dummy CAT par1; + dummy CAT "#"; + IF pos (counter reference store, dummy) <> 0 + THEN get dec value (counter reference store); + write dec value into file + ELIF durchgang = 3 + THEN fehler (61, par1) + FI. +END PROC process counter value; + +PROC replace value in numbering store (TEXT CONST val): + INT VAR begin pos :: pos (counter numbering store, dummy) + 1; + begin pos := pos (counter numbering store, "#", begin pos) + 1; + INT VAR end pos := pos (counter numbering store, "#", begin pos)-1; + IF end pos <= 0 + THEN end pos := length (counter numbering store) + FI; + change (counter numbering store, begin pos, end pos, val) +END PROC replace value in numbering store; + +PROC write dec value into file: + change (zeile, kommando anfangs pos, kommando ende pos, dec value); + kommando ende pos := kommando anfangs pos; + write record (ausgabe, zeile) +END PROC write dec value into file; + +PROC get dec value (TEXT CONST store): + INT VAR value begin :: pos (store, dummy); + value begin := pos (store, "#", value begin + 1) + 1; + INT VAR value end :: pos (store, "#", value begin)-1; + IF value end < 0 + THEN value end := length (store) + FI; + dec value := subtext (store, value begin, value end). +END PROC get dec value; + +(************************** Zaehler routinen ('refer') ***************) + +PROC nummer und kennzeichen speichern (INT CONST number, TEXT VAR kennung): + ueberpruefe auf bereits vorhandenes kennzeichen; + anz refers INCR 1; + IF anz refers > max refers + THEN errorstop ("Anzahl Referenzen zu gross") + FI; + refer sammler [anz refers] . kennzeichen := kennung; + refer sammler [anz refers] . nummer := number; + refer sammler [anz refers] . referenced := FALSE. + +ueberpruefe auf bereits vorhandenes kennzeichen: + INT VAR i; + FOR i FROM 1 UPTO anz refers REP + IF refer sammler [i] . kennzeichen = kennung + THEN warnung (9, kennung); + LEAVE nummer und kennzeichen speichern + FI + END REP. +END PROC nummer und kennzeichen speichern; + +PROC ggf gespeicherte nummer einsetzen (TEXT VAR kennung): + IF kennzeichen vorhanden + THEN change (zeile, kommando anfangs pos, kommando ende pos, textnummer); + refer sammler [i] . referenced := TRUE; + kommando ende pos := kommando anfangs pos; + write record (ausgabe, zeile) + ELIF durchgang = 3 + THEN warnung (4, kennung) + FI. + +textnummer: + text (refer sammler [i] . nummer). + +kennzeichen vorhanden: +INT VAR i; + FOR i FROM 1 UPTO anz refers REP + IF refer sammler [i] . kennzeichen = kennung + THEN LEAVE kennzeichen vorhanden WITH TRUE + FI + END REP; + FALSE. +END PROC ggf gespeicherte nummer einsetzen; + +(************************** free-Kommando *****************************) + +PROC free kommando ausfuehren: +INT CONST wert in y steps :: y step conversion (realparam); + IF bereich aufnehmen + THEN + ELIF wert in y steps>=eingestellte seitenlaenge - seitenlaenge fester teil + THEN fehler (13, "") + ELIF erreichte seitenlaenge + wert in y steps > eingestellte seitenlaenge + THEN ende einer seite; + kommando index := fehler index + ELSE aktuelle seitenlaenge INCR wert in y steps + FI +END PROC free kommando ausfuehren; + +(*************************** page-Kommando ******************************) + +PROC page behandlung: +TEXT VAR steuerzeichen; + page kommando entfernen; + IF aktuelle seitenlaenge <= 0 + THEN IF line no (ausgabe) = 1 + THEN zeile noch nicht verarbeitet := TRUE + ELSE up (ausgabe) + FI; + LEAVE page behandlung + FI; + IF interaktiv + THEN initialisiere bildschirm fuer page; + mit page interaktiv formatieren; + schreibe titelzeile; + FI; + BOOL CONST hilf :: pageblock on; + pageblock on := FALSE; + seitenende einbringen und zurueck; + pageblock on := hilf; + kommando index := page command0. + +page kommando entfernen: + IF kommando anfangs pos = 1 + THEN delete record (ausgabe); + IF line no (ausgabe) = 1 + THEN zeile noch nicht verarbeitet := TRUE + FI + ELSE zeile := subtext (zeile, 1, kommando anfangs pos - 1); + write record (ausgabe, zeile); + IF NOT only command line (zeile) + THEN aktuelle seitenlaenge INCR max zeilenvorschub + FI; + down (ausgabe) + FI. + +initialisiere bildschirm fuer page: + schreibe titelzeile + ("#page# bestaetigen: RETURN / loeschen: HOP RUBOUT / Abbruch: ESC"); + line ; out (cleol); + put ("#page# nach"); + put (y step conversion (erreichte seitenlaenge)); put ("cm"); + schreibe bildschirm; + out (hop). + +mit page interaktiv formatieren: + REP + inchar (steuerzeichen); + IF steuerzeichen = return + THEN zeilenmitteilung loeschen; + LEAVE mit page interaktiv formatieren + ELIF steuerzeichen = rubout + THEN weitermachen + ELIF steuerzeichen = esc + THEN errorstop ("Abbruch mit ESC") + FI + END REP. + +weitermachen: + zeilenmitteilung loeschen; + up (ausgabe); + LEAVE page behandlung. + +zeilenmitteilung loeschen: + cursor (1, 2); out (cleol); line. +END PROC page behandlung; + +PROC seite nochmal durchgehen: + zurueck bis seitenende; + kommandos wiederherstellen; + down (ausgabe); + IF count seitenzaehlung + THEN counter := 0 + FI; + schreibe ggf kopf; + read record (ausgabe, zeile); + seitenlaenge initialisieren; + fussnoten loeschen; + bis seitenende lesen und kommandos verarbeiten; + schreibe ggf fuss; + initialisieren fuer neue seite. + +bis seitenende lesen und kommandos verarbeiten: + durchgang := 2; + zeilen und kommandos verarbeiten; + durchgang := 1. + +zeilen und kommandos verarbeiten: + anz textzeilen := 0; + WHILE NOT seitenende REP + IF mindestens ein kommando vorhanden + THEN IF NOT only command line (zeile) + THEN anz textzeilen INCR 1 + FI; + kommandos verarbeiten und ggf zeile mitzaehlen; + ELSE aktuelle seitenlaenge INCR berechneter zeilenvorschub; + anz textzeilen INCR 1 + FI; + naechste zeile lesen + END REP. + +initialisieren fuer neue seite: + kommandos aufheben; + fussnoten loeschen; + erhoehe seiten und spaltennr; + seitenlaenge initialisieren +END PROC seite nochmal durchgehen; + +PROC seitenlaenge initialisieren: + IF anz spalten > 1 AND laufende spaltennr > 1 + THEN aktuelle seitenlaenge := text laenge vor columns + ELSE aktuelle seitenlaenge := 0; + verarbeite seitenkommandos + FI. + +verarbeite seitenkommandos: + IF kommando seitenspeicher <> "" + THEN zeile := kommando seitenspeicher; + kommando seitenspeicher := ""; + INT CONST xx := durchgang; + durchgang := 4; + kommandos verarbeiten; + durchgang := xx + FI. +END PROC seitenlaenge initialisieren; + +PROC zurueck bis seitenende: + up (ausgabe, "#page##---", line no (ausgabe)); + IF anz spalten > 1 AND laufende spaltennr > 1 + THEN down (ausgabe); + schreibe free (text laenge vor columns + head laenge); + up (ausgabe) + FI; + read record (ausgabe, zeile); + cout (line no (ausgabe)); +END PROC zurueck bis seitenende; + +BOOL PROC seitenende: + pos (zeile, "#page#") = 1 AND pos (zeile, "-----", 8) = 8 +END PROC seitenende; + +(**************************** eigentliche seitenform-routine *********) + +PROC seiten form: + enable stop; + datei assoziieren; + page form initialisieren; + to line (ausgabe, 1); + read record (ausgabe, zeile); + in nullter seite := TRUE; + nullte seite verarbeiten; + nullte seitengrenze einfuegen; + in nullter seite := FALSE; + formieren. + +nullte seite verarbeiten: + aktuelle seitenlaenge := 0; + WHILE only command line (zeile) REP + IF seitenende + THEN errorstop ("Bitte Originaldatei bearbeiten (keine Druckdatei)") + FI; + kommandos verarbeiten; + IF es war ein free kommando OR tabellen kommando + THEN LEAVE nullte seite verarbeiten + ELIF es war ein linefeed in der zeile + THEN berechne zeilenvorschub; + es war ein linefeed in der zeile := FALSE; + naechste zeile lesen + ELIF zeile noch nicht verarbeitet + THEN read record (ausgabe, zeile); + zeile noch nicht verarbeitet := FALSE + ELSE naechste zeile lesen + FI; + cout (line no (ausgabe)) + ENDREP. + +es war ein free kommando: + aktuelle seitenlaenge <> 0. + +tabellen kommando: + kommando index >= 35 AND kommando index <= 44. + +nullte seitengrenze einfuegen: + laufende spaltennr := 0; + grenzmarkierung in dummy speichern; + record einfuegen (dummy); + read record (ausgabe, zeile); + kommandos aufheben; + aktuelle seitenlaenge := 0; + erhoehe seiten und spaltennr; + nummer erste seite := laufende seiten nr [1]. + +formieren: + REP + cout (line no (ausgabe)); + IF mindestens ein kommando vorhanden + THEN kommandos verarbeiten und ggf zeile mitzaehlen + ELSE aktuelle seitenlaenge INCR berechneter zeilenvorschub; + FI; + IF erreichte seitenlaenge > eingestellte seitenlaenge + THEN ende einer seite + FI; + IF eof (ausgabe) + THEN eof behandlung; + LEAVE formieren + ELSE down (ausgabe); + IF eof (ausgabe) + THEN eof behandlung; + LEAVE formieren + ELSE read record (ausgabe, zeile) + FI + FI + END REP. +END PROC seiten form; + +PROC eof behandlung: + grenzmarkierung in dummy speichern; + insert record (ausgabe); + write record (ausgabe, dummy); + nummer letzte seite := laufende seiten nr [1]; + pageblock on := FALSE; + seite nochmal durchgehen; + IF anz refers <> 0 OR mindestens ein topage gewesen + OR counter reference store <> "" + THEN ausgabe datei nochmals durchgehen; + offene referenzen pruefen + FI. + +ausgabe datei nochmals durchgehen: + to line (ausgabe, 1); col (ausgabe, 1); + durchgang := 3; + REP + down (ausgabe, "#", lines (ausgabe)); + IF pattern found + THEN read record (ausgabe, zeile); + cout (line no (ausgabe)); + kommandos verarbeiten; + IF eof (ausgabe) + THEN LEAVE ausgabe datei nochmals durchgehen + ELSE down (ausgabe); col (ausgabe, 1) + FI + ELSE LEAVE ausgabe datei nochmals durchgehen + FI + END REP. + +offene referenzen pruefen: + INT VAR i; + FOR i FROM 1 UPTO anz refers REP + IF NOT refer sammler [i] . referenced + THEN report text processing warning + (3, 0, fehlerdummy, CONCR(refersammler) [i] . kennzeichen) + FI + END REP. +END PROC eof behandlung; + +(************************** kommando verarbeitung **********) + +BOOL PROC mindestens ein kommando vorhanden: + pos (zeile, kommando zeichen) <> 0. +END PROC mindestens ein kommando vorhanden; + +PROC kommandos verarbeiten: + kommando anfangs pos := pos (zeile, kommando zeichen); + WHILE kommando anfangs pos <> 0 REP + verarbeite kommando; + IF kommando index = end OR kommando index = page command0 + OR kommando index = page command1 OR kommando index = fehler index + THEN LEAVE kommandos verarbeiten + ELSE kommando anfangs pos := + pos (zeile, kommando zeichen, kommando ende pos + 1) + FI + END REP. +END PROC kommandos verarbeiten; + +PROC kommandos verarbeiten und ggf zeile mitzaehlen: + max zeilenvorschub := berechneter zeilenvorschub; + max type zeilenvorschub := type zeilenvorschub; + kommandos verarbeiten; + in index oder exponent := 0; + zeile zur seitenlaenge ggf addieren; + IF es war ein linefeed in der zeile + THEN berechne zeilenvorschub; + es war ein linefeed in der zeile := FALSE + FI. + +zeile zur seitenlaenge ggf addieren: + IF only command line (zeile) OR + kommando index = end OR kommando index = page command0 OR + kommando index = page command1 OR kommando index = fehler index + THEN + ELSE aktuelle seitenlaenge INCR max zeilenvorschub; + FI. +END PROC kommandos verarbeiten und ggf zeile mitzaehlen; + +BOOL PROC keine zeichen ausser blank nach dem kommando: + IF kommando anfangs pos > 1 AND + pos (zeile, ""33"", ""255"", 1) = kommando anfangs pos + THEN warnung (13, kommando) + FI; + kommando ende pos = length (zeile) OR + pos (zeile, ""33"", ""254"", kommando ende pos + 1) = 0 +END PROC keine zeichen ausser blank nach dem kommando; + +BOOL PROC absatz zeile: + (zeile SUB length (zeile)) = blank +END PROC absatz zeile; + +(********************** routinen fuers seitenende *************) + +INT PROC erreichte seitenlaenge: + aktuelle seitenlaenge + kopf oder fuss laenge [footnote] + + seitenlaenge fester teil +END PROC erreichte seitenlaenge; + +INT PROC seitenlaenge fester teil: + head laenge + bottom laenge. + +bottom laenge: + IF (NOT insert last bottom AND laufende seitennr [1] = nummer letzte seite) + OR ausgeschalteter bottom + THEN 0 + ELSE kopf oder fuss laenge [fuss] + + bottom laenge fuer gerade oder ungerade seiten + FI. + +bottom laenge fuer gerade oder ungerade seiten: + IF laufende seitennr [1] MOD 2 = 0 + THEN kopf oder fuss laenge [fuss gerade] + ELSE kopf oder fuss laenge [fuss ungerade] + FI. +END PROC seitenlaenge fester teil; + +INT PROC head laenge: + IF (NOT insert first head AND laufende seitennr [1] = nummer erste seite) + OR ausgeschalteter head + THEN 0 + ELSE kopf oder fuss laenge [kopf] + + head laenge fuer gerade oder ungerade seiten + FI. + +head laenge fuer gerade oder ungerade seiten: + IF laufende seitennr [1] MOD 2 = 0 + THEN kopf oder fuss laenge [koπ3Πφ&η6φζ� + ELSE kopf oder fuss laenge [kopf ungerade] + FI. +END PROC head laenge; + +PROC ende einer seite: + IF interaktiv + THEN seitenende ggf verschieben + ELSE seitenende fuer autopageform ggf verschieben + FI; + seitenende einbringen und zurueck. + +seitenende ggf verschieben: + BOOL VAR veraenderungen in der seite :: FALSE; + formatiere ueber bildschirm (veraenderungen in der seite); + schreibe titelzeile; + IF veraenderungen in der seite + THEN zum seitenanfang zur erneuten bearbeitung; + LEAVE ende einer seite + FI. + +seitenende fuer autopageform ggf verschieben: +INT VAR i, hier :: line no (ausgabe); + FOR i FROM 1 UPTO 4 REP + zeile zurueck lesen; + IF absatz zeile OR line no (ausgabe) <= 2 + THEN ggf um leerzeilen nach oben lesen; + naechste zeile lesen; + LEAVE seitenende fuer autopageform ggf verschieben + FI + END REP; + to line (ausgabe, hier); + read record (ausgabe, zeile); + IF pageblock on + THEN FOR i FROM 1 UPTO 4 REP + IF absatz zeile OR eof (ausgabe) OR pos (zeile, "#foot") <> 0 + OR pos (zeile, "#free") <> 0 + THEN naechste zeile lesen; + LEAVE seitenende fuer autopageform ggf verschieben + FI; + naechste zeile lesen + END REP; + to line (ausgabe, hier); + read record (ausgabe, zeile) + FI. + +ggf um leerzeilen nach oben lesen: + INT VAR ii := i; + WHILE zeile = " " AND pageblock on AND ii <= 4 REP + IF line no (ausgabe) <= 2 + THEN LEAVE ggf um leerzeilen nach oben lesen + FI; + zeile zurueck lesen; + ii INCR 1 + END REP. +END PROC ende einer seite; + +PROC seitenende einbringen und zurueck: + letzte textzeile war mit absatz := letzte zeile; + down (ausgabe); + grenzmarkierung in dummy speichern; + record einfuegen (dummy); + up (ausgabe); + seite nochmal durchgehen. + +letzte zeile: + up (ausgabe); + read record (ausgabe, zeile); + absatz zeile. +END PROC seitenende einbringen und zurueck; + +PROC zum seitenanfang zur erneuten bearbeitung: + zurueck bis seitenende; + durchgang := 1; + aktuelle seitenlaenge := 0; + fussnoten loeschen; + kommandos wiederherstellen +END PROC zum seitenanfang zur erneuten bearbeitung; + +(********************** positionierungs routinen ************) + +PROC naechste zeile lesen: + down (ausgabe); + read record (ausgabe, zeile) +END PROC naechste zeile lesen; + +PROC zeile zurueck lesen: + up (ausgabe); + read record (ausgabe, zeile); +END PROC zeile zurueck lesen; + +(***************** seitenende interaktiv positionieren **********) + +PROC formatiere ueber bildschirm (BOOL VAR veraenderungen): + veraenderungen := FALSE; + anz zeilen nach oben := 0; + erste bildschirmzeile schreiben; + schreibe bildschirm; + REP + positioniere lfd satz nach steuerzeichen und ggf schirm schreiben + END REP. + +positioniere lfd satz nach steuerzeichen und ggf schirm schreiben: +TEXT VAR steuerzeichen; + inchar (steuerzeichen); + IF steuerzeichen = upchar + THEN nach oben; + IF fussnoten ende + THEN ueberspringe fussnote nach oben; + schreibe bildschirm + FI + ELIF steuerzeichen = downchar + THEN IF fussnoten anfang + THEN ueberspringe fussnote nach unten; + schreibe bildschirm + ELSE nach unten; + IF fussnoten anfang + THEN ueberspringe fussnote nach unten; + schreibe bildschirm + FI + FI + ELIF steuerzeichen = hop + THEN sprung oder leerzeilen veraenderung; + schreibe bildschirm; + ELIF steuerzeichen = return + THEN IF anz zeilen nach oben < 0 + THEN down (ausgabe); + read record (ausgabe, zeile) + FI; + IF zeile = "" OR zeile = " " + THEN leerzeilen vor neuer seite loeschen + FI; + LEAVE formatiere ueber bildschirm + ELIF steuerzeichen = esc + THEN errorstop ("Abbruch mit ESC") + FI. + +fussnoten anfang: + pos (zeile, "#foot") <> 0 AND anz zeilen nach oben > 0. + +fussnoten ende: + pos (zeile, "#end") <> 0. + +nach oben: + IF anz zeilen nach oben < 0 + THEN nach oben unterhalb der seitengrenze + ELIF eine zeile nach oben war moeglich + THEN IF fussnoten ende + THEN ueberspringe fussnote nach oben; + schreibe bildschirm + ELIF anz vertauschte zeilen < zeilen nach oben + THEN out (upchar); raus; out (upchar); + schreibe seitenbegrenzung auf bildschirm; + anz vertauschte zeilen INCR 1 + ELSE schreibe bildschirm + FI + FI. + +nach oben unterhalb der seitengrenze: + IF anz zeilen nach oben = -1 + THEN cursor (1, pos seitengrenze); out (cl eop); + schreibe seitenbegrenzung auf bildschirm; + cursor (1, pos seitengrenze); + schreibe untere zeilen; + anz zeilen nach oben := 0 + ELSE INT VAR bildschirmzeile unterhalb :: + pos seitengrenze + abs (anz zeilen nach oben) + 1; + cursor (1, bildschirmzeile unterhalb); + out (cl eol); + outsubtext (zeile, 1, 76); + anz zeilen nach oben INCR 1; + bildschirmzeile unterhalb DECR 1; + cursor (1, bildschirmzeile unterhalb); + schreibe seitenbegrenzung auf bildschirm; + zeile zurueck lesen; + cursor (1, pos seitengrenze) + FI. + +nach unten: + IF anz zeilen nach oben < -4 + THEN + ELIF anz zeilen nach oben < 1 + THEN ggf nach unten formatieren + ELIF anz vertauschte zeilen > 0 + THEN out (upchar); raus; line ; + schreibe seitenbegrenzung auf bildschirm; + eine zeile nach unten wenn moeglich; + anz vertauschte zeilen DECR 1 + ELSE eine zeile nach unten wenn moeglich; + IF fussnoten anfang + THEN ueberspringe fussnote nach unten; + FI; + schreibe bildschirm + FI. + +ggf nach unten formatieren: + IF pageblock on + THEN zeile nach unten ueber seitengrenze; + cursor (1, pos seitengrenze); + FI. + +zeile nach unten ueber seitengrenze: + IF eof (ausgabe) OR page oder free oder foot anweisung + THEN LEAVE zeile nach unten ueber seitengrenze + ELSE naechste zeile lesen; + IF eof (ausgabe) OR page oder free oder foot anweisung + THEN zeile zurueck lesen; + LEAVE zeile nach unten ueber seitengrenze + FI; + zeile zurueck lesen + FI; + IF anz zeilen nach oben = 0 + THEN out (cl eol); + out (begin mark); + out ("Über Seitenende hinaus (Stauchung): UP/DOWN"); + out (end mark); + cursor (1, pos seitengrenze + 1); + schreibe untere zeilen; + ELSE naechste zeile lesen; + FI; + cursor (1, pos seitengrenze + abs (anz zeilen nach oben) + 1); + out (cl eol); + outsubtext (zeile, 1, 76); + anz zeilen nach oben DECR 1; + cursor (1, pos seitengrenze + abs (anz zeilen nach oben) + 1); + schreibe seitenbegrenzung auf bildschirm. + +page oder free oder foot anweisung: + pos (zeile, "#page") <> 0 OR pos (zeile, "#free") <> 0 + OR pos (zeile, "#foot") <> 0. + +sprung oder leerzeilen veraenderung: + INT VAR i :: 0; + REP + inchar (steuerzeichen); + IF steuerzeichen = upchar + THEN sprung nach oben + ELIF steuerzeichen = downchar + THEN sprung nach unten + ELIF steuerzeichen = rub out + THEN zeile loeschen; + ELIF steuerzeichen = rub in + THEN leerzeilen einfuegen; + FI + END REP. + +sprung nach oben: + WHILE eine zeile nach oben war moeglich REP + i INCR 1; + IF fussnoten ende + THEN ueberspringe fussnote nach oben; + LEAVE sprung oder leerzeilen veraenderung + FI + UNTIL i >= zeilen nach oben END REP; + LEAVE sprung oder leerzeilen veraenderung. + +sprung nach unten: + WHILE i < zeilen nach oben REP + IF fussnoten anfang + THEN ueberspringe fussnote nach unten; + LEAVE sprung oder leerzeilen veraenderung + ELSE eine zeile nach unten wenn moeglich; + i INCR 1; + FI; + IF fussnoten anfang + THEN ueberspringe fussnote nach unten; + LEAVE sprung oder leerzeilen veraenderung + FI + END REP; + LEAVE sprung oder leerzeilen veraenderung. + +zeile loeschen: + veraenderungen := TRUE; + up (ausgabe); + read record (ausgabe, zeile); + IF seiten ende + THEN down (ausgabe); + ELSE delete record (ausgabe); + FI; + LEAVE formatiere ueber bildschirm. + +leerzeilen einfuegen: + veraenderungen := TRUE; + out (cl eop); + REP + inchar (steuerzeichen); + IF steuerzeichen = return + THEN insert record (ausgabe); + zeile := " "; + write record (ausgabe, zeile); + out (upchar); + raus; + line + ELIF steuerzeichen = rubin + THEN LEAVE formatiere ueber bildschirm + FI + END REP. +END PROC formatiere ueber bildschirm; + +PROC leerzeilen vor neuer seite loeschen: + WHILE zeile = "" OR zeile = " " REP + delete record (ausgabe); + IF eof (ausgabe) + THEN LEAVE leerzeilen vor neuer seite loeschen + ELSE read record (ausgabe, zeile) + FI + END REP. +END PROC leerzeilen vor neuer seite loeschen; + +PROC ueberspringe fussnote nach oben: + WHILE eine zeile nach oben war moeglich REP + IF fussnoten anfang + THEN IF eine zeile nach oben war moeglich + THEN + FI; + LEAVE ueberspringe fussnote nach oben + FI + END REP. + +fussnoten anfang: + pos (zeile, "#foot#") <> 0. +END PROC ueberspringe fussnote nach oben; + +PROC ueberspringe fussnote nach unten: + REP + eine zeile nach unten wenn moeglich; + IF fussnoten ende + THEN eine zeile nach unten wenn moeglich; + LEAVE ueberspringe fussnote nach unten + FI + END REP. + +fussnoten ende: + pos (zeile, "#end#") <> 0. +END PROC ueberspringe fussnote nach unten; + +PROC schreibe free (INT CONST wert): +REAL CONST wert in y steps :: y step conversion (wert); + dummy := "#free("; + IF wert in y steps < 1.0 + THEN dummy CAT "0"; + FI; + dummy CAT text (wert in y steps); + dummy CAT ")#"; + record einfuegen (dummy); +END PROC schreibe free; + +BOOL PROC eine zeile nach oben war moeglich: + IF line no (ausgabe) = 1 + THEN FALSE + ELSE zeile zurueck lesen; + IF seitenende OR columns kommando in dieser zeile + THEN naechste zeile lesen; + FALSE + ELSE anz zeilen nach oben INCR 1; + TRUE + FI + FI. + +columns kommando in dieser zeile: + anz spalten > 1 AND pos (zeile, "#columns") <> 0. +END PROC eine zeile nach oben war moeglich; + +PROC eine zeile nach unten wenn moeglich: + IF anz zeilen nach oben > 0 + THEN naechste zeile lesen; + anz zeilen nach oben DECR 1 + FI +END PROC eine zeile nach unten wenn moeglich; + +PROC erste bildschirmzeile schreiben: + IF anz spalten > 1 + THEN dummy := "Spalten" + ELSE dummy := "Seiten" + FI; + dummy CAT "ende verschieben: UP, DOWN / bestaetigen: RETURN / Abbruch: ESC"; + schreibe titelzeile (dummy). +END PROC erste bildschirmzeile schreiben; + +PROC schreibe bildschirm: + anz vertauschte zeilen := 0; + cursor (1, 3); + out (cl eop); + gehe zurueck; + wieder nach vorne und zeilen ausgeben; + cursor (1, pos seitengrenze); + schreibe seitenbegrenzung auf bildschirm; + cursor (1, pos seitengrenze); + schreibe untere zeilen. + +gehe zurueck: + INT VAR hier :: line no (ausgabe) -1; + to line (ausgabe, hier - zeilen nach oben + 1); + INT VAR anz read zeilen :: hier - line no (ausgabe) + 2. + + wieder nach vorne und zeilen ausgeben: + IF line no (ausgabe) = 1 + THEN ggf leerzeilen auf bildschirm schreiben; + FI; + WHILE line no (ausgabe) <= hier REP + read record (ausgabe, zeile); + raus; + down (ausgabe); + END REP; + read record (ausgabe, zeile). + +ggf leerzeilen auf bildschirm schreiben: + IF zeilen nach oben - anz read zeilen >= 0 + THEN INT VAR i; + FOR i FROM 1 UPTO zeilen nach oben - anz read zeilen REP + line ; out (cl eol); out(" ") + END REP; + line ; out (cl eol); + out ("<< DATEI ANFANG >>"); out (return) + FI. +END PROC schreibe bildschirm; + +PROC schreibe untere zeilen: + gehe weiter und gebe zeilen aus; + gehe wieder zurueck; + skip input; + cursor (1, pos seitengrenze). + +gehe weiter und gebe zeilen aus: +INT VAR anz read zeilen :: 0, + i :: line no (ausgabe); + WHILE anz read zeilen < zeilen nach unten REP + IF eof (ausgabe) + THEN line ; out (cleol); out ("<< DATEI ENDE >>"); + LEAVE gehe weiter und gebe zeilen aus + FI; + raus; + naechste zeile lesen; + anz read zeilen INCR 1 + END REP. + +gehe wieder zurueck: + to line (ausgabe, i); + read record (ausgabe, zeile). +END PROC schreibe untere zeilen; + +(***************** schreib-routinen fuer den bildschirm ************) + +PROC schreibe seitenbegrenzung auf bildschirm: + out (cl eol); out (begin mark); + grenzmarkierung in dummy speichern; + out (dummy); + out (end mark); + out (return) +END PROC schreibe seitenbegrenzung auf bildschirm; + +PROC raus: +INT VAR xzeile, yspalte; + line ; out (cl eol); + outsubtext (zeile, 1, 76); + IF absatz zeile + THEN get cursor (yspalte, xzeile); + cursor (77, xzeile); + out (begin end mark) + FI; + out (return) +END PROC raus; + +PROC schreibe titelzeile: + IF online + THEN schreibe + FI. + +schreibe: + out (hop); out (cleol); + put ("PAGEFORM"); put ("(für"); put (lines (ausgabe)); put ("Zeilen):"); + put (name eingabe datei); + put ("->"); + put (name druck datei); + cursor (1, 3). +END PROC schreibe titelzeile; + +PROC schreibe titelzeile (TEXT CONST t): + IF online + THEN schreibe + FI. + +schreibe: + out (hop); out (cl eol); + out (begin mark); + out (t); + out (end mark) +END PROC schreibe titelzeile; + +(************************** initialisierungs-routine ************) + +PROC page form initialisieren: +BOOL VAR exists; +INT VAR i; + letzte textzeile war mit absatz := TRUE; + letztes seitenende war mit absatz := TRUE; + pageblock on := FALSE; + zeile noch nicht verarbeitet := FALSE; + bereich aufnehmen := FALSE; + count seitenzaehlung := FALSE; + ausgeschalteter head := FALSE; + ausgeschalteter bottom := FALSE; + in tabelle := FALSE; + es war ein linefeed in der zeile := FALSE; + letztes seitenende war in tabelle := FALSE; + mindestens ein topage gewesen := FALSE; + in index oder exponent := 0; + anz refers := 0; + kommando index := 0; + counter := 0; + laufende seitennr [1] := 1; + durchgang := 1; + anz spalten := 1; + modifikation := ""; + tab pos speicher := ""; + kommando seitenspeicher := ""; + counter numbering store := ""; + counter reference store := ""; + dec value := ""; + seitenzeichen := "%"; + eingestelltes limit := dina4 limit; + IF NOT file works + THEN font nr := 1; + eingestellter typ := font (1); + type zeilenvorschub := + font height (1) + font lead (1) + font depth (1); + eingestellte seitenlaenge := y step conversion (dina4 pagelength); + real eingestellter zeilenvorschub := 1.0 + FI; + berechneter zeilenvorschub := + int (real (type zeilenvorschub) * real eingestellter zeilenvorschub + 0.5); + max zeilenvorschub := berechneter zeilenvorschub; + max type zeilenvorschub := type zeilenvorschub; + FOR i FROM 1 UPTO 7 REP + kopf oder fuss laenge [i] := 0; + anz kopf oder fuss zeilen [i] := 0 + END REP; + IF online + THEN page + FI; + IF command dialogue + THEN interaktiv := TRUE; + ELSE interaktiv := FALSE; + FI; + IF online + THEN page + FI; + schreibe titelzeile +END PROC page form initialisieren; + +PROC central pagefo9ü̈NSγJr+�Cβ+̂γ��{s�β�KrΓλγb�#Τκ�ZK�� + name eingabe datei := input; + name druck datei := druck; + IF exists (druck) + THEN forget (druck, quiet) + FI; + disable stop; + ds := nilspace; + refer sammler := ds; + seiten form; + forget(ds); + IF is error + THEN put error; + clear error; + last param (name eingabe datei) + ELSE last param (name druck datei) + FI; + enable stop; + IF anything noted + THEN note edit (ausgabe) + FI. +END PROC central pageform routine; + +PROC pageform (TEXT CONST input, druck): + file works := FALSE; + central pageform routine (input, druck). +END PROC pageform; + +PROC pageform (TEXT CONST input): + file works := FALSE; + central pageform routine (input, input + ".p"). +END PROC pageform; + +PROC pageform: + file works := FALSE; + pageform (last param) +END PROC pageform; + +PROC pageform (TEXT CONST input, REAL CONST lf, seitenlaenge): + file works := TRUE; + eingestellte seitenlaenge := y step conversion (seitenlaenge); + real eingestellter zeilenvorschub := lf; + central pageform routine (input, input + ".p") +END PROC pageform; + +PROC autopageform: + autopageform (last param) +END PROC autopageform; + +PROC autopageform (TEXT CONST input): + command dialogue (false); + pageform (input); + command dialogue (true) +END PROC autopageform; +END PACKET seiten formatieren; +(* +REP + IF yes ("autopageform") + THEN autopageform ("pfehler") + ELSE pageform ("pfehler") + FI; + edit("pfehler.p"); +UNTIL yes ("ENDE") ENDREP; +*) + diff --git a/system/multiuser/1.7.5/src/print cmd b/system/multiuser/1.7.5/src/print cmd new file mode 100644 index 0000000..1fcb475 --- /dev/null +++ b/system/multiuser/1.7.5/src/print cmd @@ -0,0 +1,29 @@ + +PACKET print cmd DEFINES print, printer : + +PROC print : + + print (last param) + +ENDPROC print ; + +PROC print (TEXT CONST file name) : + + save (file name, task ("PRINTER")) ; + +ENDPROC print ; + +PROC print (THESAURUS CONST nameset) : + + do (PROC (TEXT CONST) print, nameset) + +ENDPROC print ; + +TASK PROC printer : + + task ("PRINTER") + +ENDPROC printer ; + +ENDPACKET print cmd ; + diff --git a/system/multiuser/1.7.5/src/priv ops b/system/multiuser/1.7.5/src/priv ops new file mode 100644 index 0000000..a92ee76 --- /dev/null +++ b/system/multiuser/1.7.5/src/priv ops @@ -0,0 +1,268 @@ +(* ------------------- VERSION 10 22.04.86 ------------------- *) +PACKET privileged operations DEFINES (* Autor: J.Liedtke *) + + block , + calendar , + collect garbage blocks , + define collector , + fixpoint , + info password , + prio , + save system , + send , + set clock , + set date , + shutup , + unblock : + +LET prio field = 6 , + cr = ""13"" , + archive channel = 31 , + + ack = 0 , + + garbage collect code = 1 , + fixpoint code = 2 , + shutup code = 4 , + shutup and save code = 12 , + reserve code = 19 , + release code = 20 ; + + + +INT PROC prio (TASK CONST task) : + pcb (task, prio field) +ENDPROC prio ; + +PROC prio (TASK CONST task, INT CONST new prio) : + pcb (task, prio field, new prio) +ENDPROC prio ; + +TEXT VAR date text ; + +PROC collect garbage blocks : + + system operation (garbage collect code) + +ENDPROC collect garbage blocks ; + +PROC fixpoint : + + system operation (fixpoint code) + +ENDPROC fixpoint ; + +PROC info password (TEXT CONST old info password, new info password) : + + INT VAR error code ; + IF online + THEN say (""3""5""10"") + FI ; + IF LENGTH new info password < 10 + THEN infopw (old info password + cr, new info pw, error code) ; + IF error code = 0 + THEN shutup + ELSE errorstop ("Falsches Info-Passwort") + FI + ELSE errorstop ("Passwort zu lang (max. 9 Zeichen)") + FI ; + cover tracks . + +new info pw : + IF new info password = "-" + THEN "-" + 9 * "0" + ELSE new info password + "cr" + FI . + +ENDPROC info password ; + +PROC shutup : + + system operation (shutup code) ; + IF command dialogue + THEN wait for configurator ; + page ; + set date + FI + +ENDPROC shutup ; + +PROC save system : + + INT VAR reply ; + TASK VAR channel owner ; + enable stop ; + reserve archive channel ; + IF yes ("Leere Floppy eingelegt") + THEN + reserve archive channel ; + system operation (shutup and save code) ; + release archive channel ; + IF command dialogue + THEN wait for configurator ; + page ; + set date + FI + FI ; + release archive channel . + +reserve archive channel : + channel owner := task (archive channel) ; + IF NOT is niltask (channel owner) + THEN ask channel owner to reserve the channel ; + IF channel owner does not reserve channel + THEN errorstop ("Task """ + name (channel owner) + + """ gibt Kanal " + + text (archive channel) + + " nicht frei") + FI + FI . + +ask channel owner to reserve the channel : + forget (ds) ; + ds := nilspace ; + pingpong (channel owner, reserve code, ds, reply) . + +channel owner does not reserve channel : + (reply <> ack) AND task exists . + +task exists : + reply <> -1 . + +release archive channel : + forget (ds) ; + ds := nilspace ; + pingpong (channel owner, release code, ds, reply) . + +ENDPROC save system ; + +PROC system operation (INT CONST code) : + + INT VAR size, used ; + storage (size, used) ; + IF used <= size + THEN sys op (code) + ELSE errorstop ("Speicherengpass") + FI + +ENDPROC system operation ; + +DATASPACE VAR ds := nilspace ; + +PROC wait for configurator : + + INT VAR i , receipt ; + FOR i FROM 1 UPTO 20 WHILE configurator exists REP + pause (30) ; + forget (ds) ; + ds := nilspace ; + ping pong (configurator, ack, ds, receipt) + UNTIL receipt >= 0 PER . + +configurator exists : + disable stop ; + TASK VAR configurator := task ("configurator") ; + clear error ; + NOT is niltask (configurator) . + +ENDPROC wait for configurator ; + +BOOL VAR hardware clock ok ; +REAL VAR now ; + +PROC set date : + + hardware clock ok := TRUE ; + try to get date and time from hardware ; + IF NOT hardware clock ok + THEN get date and time from user + FI ; + define date and time . + +try to get date and time from hardware : + disable stop ; + REAL VAR previous now ; + now := 0.0 ; + INT VAR try ; + FOR try FROM 1 UPTO 3 WHILE hardware clock ok REP + previous now := now ; + now := date (hardwares today) + time (hardwares time) + UNTIL now = previous now OR is error PER ; + clear error ; + enable stop . + +get date and time from user : + line (2) ; + put (" Bitte geben Sie das heutige Datum ein :") ; + date text := date ; + TEXT VAR exit char ; + editget (date text, cr, "", exit char) ; + now := date (date text) ; + line ; + put (" und die aktuelle Uhrzeit :") ; + date text := time of day ; + editget (date text, cr, "", exit char) ; + now INCR time (date text) ; + IF NOT last conversion ok + THEN errorstop ("Falsche Zeitangabe") + FI . + +hardwares today : calendar (3) + "." + calendar (4) + "." + calendar (5) . + +hardwares time : calendar (2) + ":" + calendar (1) . + +define date and time : + set clock (now) . + +ENDPROC set date ; + +TEXT PROC calendar (INT CONST index) : + + INT VAR bcd ; + control (10, index, 0, bcd) ; + IF bcd < 0 + THEN hardware clock ok := FALSE ; "" + ELSE text (low digit + 10 * high digit) + FI . + +low digit : bcd AND 15 . + +high digit: (bcd AND (15*256)) DIV 256 . + +ENDPROC calendar ; + +PROC infopw (TEXT CONST old, new, INT VAR error code) : + EXTERNAL 81 +ENDPROC infopw ; + +PROC sys op (INT CONST code) : + EXTERNAL 90 +ENDPROC sys op ; + +PROC set clock (REAL CONST time) : + EXTERNAL 103 +ENDPROC set clock ; + +PROC pcb (TASK CONST task, INT CONST field, value) : + EXTERNAL 105 +ENDPROC pcb ; + +PROC unblock (TASK CONST task) : + EXTERNAL 108 +ENDPROC unblock ; + +PROC block (TASK CONST task) : + EXTERNAL 109 +ENDPROC block ; + +PROC send (TASK CONST from, to, INT CONST order, DATASPACE VAR ds, + INT VAR receipt) : + EXTERNAL 127 +ENDPROC send ; + +PROC define collector (TASK CONST task) : + EXTERNAL 128 +ENDPROC define collector ; + +ENDPACKET privileged operations ; + diff --git a/system/multiuser/1.7.5/src/silbentrennung b/system/multiuser/1.7.5/src/silbentrennung new file mode 100644 index 0000000..dfbdf75 --- /dev/null +++ b/system/multiuser/1.7.5/src/silbentrennung @@ -0,0 +1,1166 @@ +(* ------------------- VERSION 170 vom 30.09.85 -------------------- *) +PACKET silbentrennung DEFINES + trenn, + schreibe trennvektor, + ist ausnahme wort, + lade ausnahmen, + entlade ausnahmen: + +(* Programm zur Silbentrennung + Autor: Klaus-Uwe Koschnick / Rainer Hahn + Stand: 1.7.1 (Febr. 1984) + 1.7.4 (Mai 1984) (Ausnahme-Woerterbuch, Verbesserungen) +*) + +(*--------------------- Ausnahme Woerterbuch -----------------------*) + +DATASPACE VAR ds1 :: nilspace; + +FILE VAR f; + +LET name table length = 1024, + max hash chars = 5; + +INT VAR anz worte :: 0, + hash index; + +INITFLAG VAR this packet :: FALSE; + +TEXT VAR dummy, + name ohne trennstellen, + trennstellen, + blanked name; + +BOUND ROW name table length TEXT VAR name table; + +PROC init packet: + IF NOT initialized (this packet) + THEN anz worte := 0 + FI +END PROC init packet; + +PROC init name table: + forget (ds1); + ds1 := nilspace; + name table := ds1; + INT VAR i; + FOR i FROM 1 UPTO name table length REP + cout (i); + name table [i] := "" + END REP; + anz worte := 0. +END PROC init name table; + +PROC lade ausnahmen: + lade ausnahmen (last param) +END PROC lade ausnahmen; + +PROC lade ausnahmen (TEXT CONST filename): + IF exists (filename) + THEN lade + ELSE errorstop ("Datei nicht vorhanden") + FI. + +lade: + init packet; + IF anz worte > 0 + THEN IF yes ("überschreiben") + THEN init nametable + ELIF no ("anfügen") + THEN LEAVE lade ausnahmen + FI + ELSE init nametable + FI; + line (2); + f := sequential file (input, file name); + WHILE NOT eof (f) REP + get (f, dummy); + IF subtext (dummy, 1, 2) = "(*" + THEN ueberlese kommentar + ELSE lade wort (* Vor.: Worte ohne Blanks *) + FI + END REP. + +ueberlese kommentar: + WHILE NOT eof (f) AND pos (dummy, "*)") = 0 REP + get (f, dummy); + END REP. + +lade wort: + line ; + anz worte INCR 1; + put (anz worte); + stelle namen ohne trennstellen her; + put (name ohne trennstellen); + blanked name := " "; + name ohne trennstellen CAT " "; + blanked name CAT name ohne trennstellen; + hash; + IF pos (name table [hash index], blanked name) > 0 + THEN put ("(bereits geladen)") + ELSE insert char (name ohne trennstellen, " ", 1); + name ohne trennstellen CAT trennstellen; + name table [hash index] CAT name ohne trennstellen; + FI. + +stelle namen ohne trennstellen her: + INT VAR number; + name ohne trennstellen := dummy; + trennstellen := ""; + WHILE pos (name ohne trennstellen, "-") > 0 REP + number := pos (name ohne trennstellen, "-"); + delete char (name ohne trennstellen, number); + trennstellen CAT text (number - 1); + trennstellen CAT " " + END REP. +END PROC lade ausnahmen; + +PROC entlade ausnahmen (TEXT CONST file name): + init packet; + IF exists (file name) + THEN errorstop ("Datei existiert bereits") + ELSE unload + FI. + +unload: + f := sequential file (output, file name); + INT VAR i; + FOR i FROM 1 UPTO name table length REP + cout (i); + IF name table [i] <> "" + THEN putline (f, name table [i]) + FI + END REP. +END PROC entlade ausnahmen; + +BOOL PROC ist ausnahme wort (TEXT CONST word, + INT CONST maximum, INT VAR trenn position): + init packet; + IF anz worte > 0 + THEN blanked name fuer hash bilden; + hash; + IF pos (name table [hash index], blanked name) > 0 + THEN trennstelle suchen + FI + FI; + FALSE. + +blanked name fuer hash bilden: + blanked name := " "; + IF maximum <= max hash chars + THEN eliminiere ggf satzzeichen hinter dem wort; + blanked name CAT + subtext (word, 1, min (max hash chars, wortlaenge)) + ELSE blanked name CAT subtext (word, 1, maximum); + FI. + +eliminiere ggf satzzeichen hinter dem wort: + INT VAR wort laenge := length (word); + WHILE letztes zeichen ist kein buchstabe REP + wort laenge DECR 1; + IF wort laenge <= 2 + THEN LEAVE ist ausnahme wort WITH FALSE + FI + END REP. + +letztes zeichen ist kein buchstabe: + TEXT CONST letztes zeichen :: (word SUB wortlaenge); + NOT (letztes zeichen >= "A" AND letztes zeichen <= "Z" OR + letztes zeichen >= "a" AND letztes zeichen <= "z" OR + letztes zeichen >= "Ä" AND letztes zeichen <= "k" OR + letztes zeichen = "ß"). + +trennstelle suchen: + index der ersten ziffer suchen; + INT VAR neue ziffer := 0; + trenn position := 0; + ziffern holen. + +index der ersten ziffer suchen: + dummy := name table [hash index]; + INT VAR ziffern index := pos (dummy, blanked name); + ziffern index := pos (dummy, " ", ziffern index + 1) + 1. + +ziffern holen: + WHILE ist ziffer REP + hole neue ziffer; + IF gefundene ziffer ist ausserhalb des trennbereichs + THEN LEAVE ist ausnahme wort WITH TRUE + FI; + trenn position := neue ziffer + END REP; + LEAVE ist ausnahme wort WITH TRUE. + +ist ziffer: + ziffern index < length (dummy) AND +((dummy SUB ziffern index + 1) = " " OR (dummy SUB ziffern index + 2) = " "). + +hole neue ziffer: + INT VAR ende position :: pos (dummy, " ", ziffern index); + neue ziffer := int (subtext (dummy, ziffern index, ende position - 1)); + ziffern index := ende position + 1. + +gefundene ziffer ist ausserhalb des trennbereichs: + neue ziffer > maximum. +END PROC ist ausnahme wort; + +PROC hash: + INT VAR i; + hash index := code (blanked name SUB 2); + FOR i FROM 3 UPTO min (length (blanked name), max hash chars) REP + hash index INCR hash index; + hash index INCR code (blanked name SUB i); + decrementiere hash index + END REP. + +decrementiere hash index: + WHILE hash index > name table length REP + hash index DECR 1023 + END REP. +END PROC hash; + +(*-------------- eigentlicher Trenn-Algorithmus --------------*) + +LET zeichenkette n = "-/", + regelmaessig = " bl br chl chr dr fl fr gl gr kl kn kr pf ph pl pr + sp st schl schm schn schr schw th tr zw ", + vokal string = "aeiouyäöü", + buchstaben = + "abcdefghijklmnopqrstuvwxyzäöüßABCDEFGHIJKLMNOPQRSTUVWXYZÄÖÜ", + grosse buchstaben = "ABCDEFGHIJKLMNOPQRSTUVWXYZ", + trennstrich = ""221"", + cv a = 97 , cv b = 98 , cv c = 99 , cv d = 100, cv e = 101, + cv f = 102, cv g = 103, cv i = 105, cv k = 107, + cv l = 108, cv m = 109, cv n = 110, cv o = 111, + cv p = 112, cv r = 114, cv s = 115, cv t = 116, + cv u = 117, cv w = 119, cv x = 120, cv y = 121, + cv ae = 217 , cv oe = 218 , cv ue = 219 , cv sz = 251, + weder h noch ch = 0 , + buchstabe h = 1 , + zeichenfolge ch = 2 ; + +INT CONST minus one :: - 1; + +INT VAR i, grenze, absolute grenze, sonderzeichen trennpos, + zeichen vor teilwort, teilwort laenge, a pos, e pos, + a pos minus 2, a pos minus 1, a pos plus 1, a pos plus 2, + e pos minus 1; + +ROW 50 INT VAR vektor ; + +TEXT VAR wort, + teilwort, + kons gr, + search, + zeichen; + +BOOL VAR trennstelle gefunden ; + +PROC trenn (TEXT CONST word, TEXT VAR part1, trennsymbol, INT CONST maximum): + IF ist ausnahme wort (word, maximum, position) + THEN ausnahme wort behandlung; + LEAVE trenn + FI; + INT VAR laenge :: length (word) ; + IF laenge < 4 + THEN trennung nicht moeglich + ELSE wort := word ; + grenze := min (50, maximum) ; + absolute grenze := min (laenge, grenze + 5) ; + trennung versuchen + FI . + +ausnahme wort behandlung: + IF position <= 0 + THEN trennung nicht moeglich + ELSE part1 := subtext (word, 1, position); + IF pos (zeichenkette n, word SUB position + 1) > 0 + THEN trennsymbol := " " + ELSE trennsymbol := trennstrich + FI + FI. + +trennung nicht moeglich : + part 1 := ""; + trennsymbol := " ". + +trennung versuchen : + erstelle trennvektor ; + IF sonderzeichen trennpos > 0 + THEN part 1 := subtext (word, 1, sonderzeichen trennpos) ; + trennsymbol := " " + ELSE bestimme trennposition ; + IF position = 0 + THEN trennung nicht moeglich + ELSE part 1 := subtext (wort, 1, position) ; + trennsymbol := trennstrich + FI + FI . + +bestimme trennposition : + INT VAR position ; + FOR position FROM grenze DOWNTO 1 REP + IF vektor [position] = 1 + THEN LEAVE bestimme trennposition + FI + END REP ; + position := 0 +END PROC trenn ; + +BOOL PROC buchstabe (INT CONST posi) : + pos (buchstaben, wort SUB posi) > 0 OR spezialcode. + +spezialcode: + INT CONST z code :: code (wort SUB posi) ; + (zcode > 96 AND zcode < 123). +END PROC buchstabe ; + +OP SPERRE (INT CONST element) : + INT CONST w element :: zeichen vor teilwort + element ; + IF w element > 0 AND w element <= grenze + THEN vektor [w element] := minus one + FI +END OP SPERRE ; + +OP SETZE (INT CONST element) : + INT CONST w element :: zeichen vor teilwort + element; + IF w element > 0 AND w element <= grenze AND vektor [w element] <> minus one + THEN vektor [w element] := 1 ; + trennstelle gefunden := TRUE + FI +END OP SETZE ; + +BOOL PROC vorletzter buchstabe oderkeine trennung oder sperre gesetzt + (INT CONST akt buchstabenpos): + vorletzter buchstabe (akt buchstabenpos) + OR NOT trennung oder sperre gesetzt (akt buchstabenpos). +END PROC vorletzter buchstabe oderkeine trennung oder sperre gesetzt; + +BOOL PROC vorletzter buchstabe (INT CONST akt buchstabenpos): + akt buchstabenpos = absolute grenze - 1 +END PROC vorletzter buchstabe; + +BOOL PROC trennung oder sperre gesetzt (INT CONST element): + INT CONST w element :: zeichen vor teilwort + element; + IF w element > 1 AND w element < teilwort laenge + THEN vektor [w element] = 1 OR gesperrt + ELSE TRUE + FI. + +gesperrt: + IF w element >= length (wort) - 1 + THEN TRUE + ELSE vektor [w element] = minus one + FI. +END PROC trennung oder sperre gesetzt; + +PROC sperren und setzen (INT CONST element) : + INT CONST w element :: zeichen vor teilwort + element ; + vektor [w element - 1] := minus one; + vektor [w element] := 1 +END PROC sperren und setzen ; + +TEXT PROC string (INT CONST anf pos, end pos) : + subtext (teilwort, maximum, minimum). + +maximum: + IF anf pos > 1 + THEN anf pos + ELSE 1 + FI. + +minimum: + IF teilwort laenge < end pos + THEN teilwort laenge + ELSE end pos + FI. +END PROC string ; + +BOOL PROC silbenanfang vor (INT CONST akt buchstabenpos): + zwei silber (akt buchstabenpos - 2) OR drei silber (akt buchstabenpos - 3) +END PROC silbenanfang vor; + +BOOL PROC silbenanfang nach (INT CONST akt buchstabenpos): + zwei silber (akt buchstabenpos + 1) OR drei silber (akt buchstabenpos + 1) +END PROC silbenanfang nach; + +BOOL PROC zwei silber (INT CONST akt buchstabenpos): + TEXT VAR zweier :: string (akt buchstabenpos, akt buchstabenpos + 1); + length (zweier) = 2 AND + pos ("ab an ar be er ge in um un zu re", zweier) > 0 +END PROC zwei silber; + +BOOL PROC drei silber (INT CONST akt buchstabenpos): + TEXT VAR dreier :: string (akt buchstabenpos, akt buchstabenpos + 2); + length (dreier) = 3 AND + pos ("auf aus bei ein end ent mit", dreier) > 0 +END PROC drei silber; + +BOOL PROC reg (INT CONST st pos) : + INT CONST code one :: code (teilwort SUB st pos) , + code two :: code (teilwort SUB st pos + 1) ; + pos (regelmaessig, konsonanten) > 0 . + +konsonanten : + search := " " ; + IF code one = cv c + THEN search CAT string (st pos, st pos + 2) + ELIF code one = cv s AND code two = cv c + THEN search CAT string (st pos, st pos + 3) + ELSE search CAT string (st pos, st pos + 1) + FI ; + search CAT " " ; + search +END PROC reg ; + +INT PROC grenz position (INT CONST start pos, richtung): + INT VAR posit :: start pos ; + REP + posit INCR richtung + UNTIL sonderzeichen oder position unzulaessig END REP; + posit - richtung. + +sonderzeichen oder position unzulaessig: + posit = 0 AND posit > absolute grenze OR ist kein buchstabe. + +ist kein buchstabe: + pos (buchstaben, wort SUB posit) = 0 AND kein spezialcode. + +kein spezialcode: + INT CONST z code :: code (wort SUB posit) ; + (zcode < 97 OR zcode > 121). +END PROC grenz position ; + +PROC schreibe trennvektor (TEXT CONST ttt): +line ; put (ttt); INT VAR ii; +FOR ii FROM 1 UPTO length (wort) REP put(vektor [ii]) PER +END PROC schreibe trennvektor; + +PROC erstelle trennvektor : +INT VAR akt pos, anfang teilwort, ende teilwort, anzahl, + zuletzt, tr pos, ind, code 1, code 2, code 3, + rechts von a pos, z code, posit; +BOOL VAR sonderzeichen modus, + aktueller buchstabe ist vokal, + vorsilbe oder nachsilbe; + + sonderzeichen trennpos := 0 ; + trennstelle gefunden := FALSE ; + initialisiere trennvektor ; + akt pos := grenze ; + IF buchstabe (akt pos) + THEN zuerst teilwort + ELSE zuerst sonderzeichenblock + FI; + WHILE akt pos > 0 REP + IF sonderzeichen modus + THEN behandle sonderzeichenblock + ELSE suche trennstellen in teilwort + FI + END REP. + +initialisiere trennvektor : + FOR i FROM 1 UPTO grenze REP vektor [i] := 0 END REP . + +zuerst teilwort: + ende teilwort := grenz position (akt pos, 1) ; + sonderzeichen modus := FALSE . + +zuerst sonderzeichenblock: + sonderzeichen modus := TRUE . + +behandle sonderzeichenblock: + WHILE sonderzeichen modus REP + IF buchstabe (akt pos) + THEN sonderzeichen modus := FALSE + ELSE zeichen := wort SUB akt pos ; + IF pos (zeichenkette n, zeichen) <> 0 + THEN sonderzeichen trennpos := akt pos ; + LEAVE erstelle trennvektor + FI ; + akt pos DECR 1 ; + IF akt pos = 0 + THEN LEAVE erstelle trennvektor + FI + FI + END REP; + ende teilwort := akt pos . + +suche trennstellen in teilwort: + bestimme anfang von teilwort ; + IF teilwort lang genug + THEN teilwort ausbauen und wandeln ; + SPERRE 1 ; SPERRE (teilwort laenge - 1) ; + vorsilben untersuchen ; + nachsilben untersuchen ; + vorsilbe oder nachsilbe := trennstelle gefunden ; + trennstelle gefunden := FALSE ; + weitere trennstellen suchen ; + IF vorsilbe oder nachsilbe + THEN LEAVE erstelle trennvektor + FI + FI ; + akt pos := anfang teilwort - 1 ; + sonderzeichen modus := TRUE . + +bestimme anfang von teilwort: + anfang teilwort := grenz position (ende teilwort, minus one) . + +teilwort lang genug: + teilwort laenge := ende teilwort - anfang teilwort + 1 ; + teilwort laenge > 3 . + +teilwort ausbauen und wandeln: + teilwort := subtext (wort, anfang teilwort, ende teilwort); + zeichen vor teilwort := anfang teilwort - 1 ; + IF pos (grosse buchstaben, teilwort SUB 1) > 0 + THEN replace (teilwort, 1, code (code (teilwort SUB 1) + 32)) + FI . + (* Es ist nicht notwendig, gross geschriebene Umlaute am + Wortanfang zu wandeln! *) + +weitere trennstellen suchen: + e pos := teilwort laenge ; + aktueller buchstabe ist vokal := letzter buchstabe ist vokal ; + WHILE e pos > 1 REP + anzahl := 0 ; + a pos := e pos ; + IF aktueller buchstabe ist vokal + THEN behandle vokalgruppe + ELSE behandle konsonantengruppe + FI ; + IF trennstelle gefunden + THEN LEAVE erstelle trennvektor + FI ; + e pos := a pos - 1 ; + END REP . + +letzter buchstabe ist vokal: + pos (vokal string,teilwort SUB e pos) > 0 . + +behandle vokalgruppe: + vokalgruppe lokalisieren ; + IF a pos > 1 AND e pos < teilwort laenge + THEN a pos plus 1 := a pos + 1 ; + a pos plus 2 := a pos + 2 ; + IF anzahl = 2 + THEN vokal 2 + ELIF anzahl > 2 + THEN vokal 3 + ELSE vokal 1 + FI + FI . + +vokalgruppe lokalisieren: + zuletzt := 0 ; + WHILE aktueller buchstabe ist vokal REP + zeichen := teilwort SUB a pos ; + IF pos (vokal string,zeichen) > 0 + THEN z code := code(zeichen) ; + IF zuletzt <> cv e + OR (z code <> cv a AND z code <> cv o AND z code <> cv u) + THEN anzahl INCR 1 + FI ; + IF a pos > 1 + THEN a pos DECR 1 ; + zuletzt := z code + ELSE aktueller buchstabe ist vokal := FALSE + FI + ELSE a pos INCR 1 ; + aktueller buchstabe ist vokal := FALSE + FI + END REP . + +behandle konsonantengruppe: + konsonantengruppe lokalisieren ; + IF a pos > 1 AND e pos < teilwort laenge + THEN a pos minus 2 := a pos - 2 ; + a pos minus 1 := a pos - 1 ; + a pos plus 1 := a pos + 1 ; + a pos plus 2 := a pos + 2 ; + e pos minus 1 := e pos - 1 ; + SELECT anzahl OF + CASE 1 : konsonant 1 + CASE 2 : konsonant 2 + OTHERWISE : konsonant 3 + END SELECT + FI . + +konsonantengruppe lokalisieren: + rechts von a pos := weder h noch ch ; + REP + zeichen := teilwort SUB a pos ; + IF pos (vokal string, zeichen) = 0 + THEN anzahl INCR 1 ; + IF zeichen = "h" + THEN rechts von a pos := buchstabe h + ELIF zeichen = "c" AND rechts von a pos = buchstabe h + THEN anzahl DECR 1 ; + rechts von a pos := zeichenfolge ch + ELIF zeichen = "s" AND rechts von a pos = zeichenfolge ch + THEN anzahl DECR 1 ; + rechts von a pos := weder h noch ch + ELSE rechts von a pos := weder h noch ch + FI ; + IF a pos > 1 + THEN a pos DECR 1 + ELSE aktueller buchstabe ist vokal := TRUE + FI + ELSE a pos INCR 1 ; + aktueller buchstabe ist vokal := TRUE + FI + UNTIL aktueller buchstabe ist vokal END REP . + +vorsilben untersuchen: + code 2 := code (teilwort SUB 2); + code 3 := code (teilwort SUB 3); + IF ch vierer silbe + THEN sperren und setzen (4) + ELSE restliche vorsilben + FI. + +ch vierer silbe: + string (2, 4) = "ach" OR string (2, 4) = "och" OR string (2, 4) = "uch". + +restliche vorsilben: + ind := pos ("abdefghimnrstuvwüu", teilwort SUB 1); +SELECT ind OF +CASE1(*a*): IF drei silber (1) + THEN sperren und setzen (3) + ELIF code 2 = cv b (*ab*) + THEN IF string(3,5) = "end" (*abend*) + THEN SPERRE 2; sperren und setzen (5) + ELIF string(3,4) = "er" (*aber*) + THEN sperren und setzen (4) + ELSE sperren und setzen (2) + FI + ELIF code 2 = cv n AND string(3,5) <> "alo" (*analo*) + THEN SETZE 2 + FI +CASE2(*b*): IF code 2 = cv e (* be *) + THEN IF (teilwort SUB 3) = "h" (* be-handeln usw *) + OR (teilwort SUB 3) = "a" (* beamter *) + THEN sperren und setzen (2) + ELIF string (3, 4) = "ob" (* beobachten *) + THEN SETZE 2; sperren und setzen (4) + FI + ELIF string (2, 3) = "au" (* bauer usw *) + THEN sperren und setzen (3) + FI +CASE3(*d*): IF (code 3 = cv s AND (code 2 = cv i OR code 2 = cv e)) + OR string (2, 3) = "ar" (* dis, des, dar*) + THEN sperren und setzen (3) + ELIF string (2, 4) = "enk" (* denk.. *) + THEN sperren und setzen (4) + ELIF string(2,5) = "urch" (*durch*) + THEN SPERRE 3 ; SETZE 5 + FI +CASE4(*e*): IF code 2 = cv r AND code 3 <> cv n AND code 3 <> cv d + AND string (3, 4) <> "ro" (* er, aber nicht: ern, erd, erro *) + THEN SETZE 2 + ELIF code 2 = cv x (* ex *) + THEN SETZE 2 + ELIF (code 2 = cv m AND code 3 = cv p AND (teilwort SUB 4) = "f") + OR (code 2 = cv n AND code 3 = cv t) (* empf, ent *) + THEN sperren und setzen (3) + FI +CASE5(*f*): +CASE6(*g*): IF string (2, 5) = "egen" (* gegen *) + THEN sperren und setzen (5) + ELIF string (2, 6) = "leich" (* gleich *) + THEN IF vorletzter buchstabe (5) + THEN SPERRE 6 + ELIF vorletzter buchstabe (6) + THEN sperren und setzen (4) + ELSE sperren und setzen (6) + FI + ELIF zwei silber (1) + THEN SETZE 2 + FI +CASE7(*h*): IF string (2, 3) = "in" OR string (2, 3) = "er" (* hin, her *) + THEN sperren und setzen (3) + FI +CASE8(*i*): IF code 2 = cv n (* in *) + THEN IF string (3, 5) = "ter" (* inter *) + THEN sperren und setzen (5) + ELIF subtext (teilwort, 1, 5) = "insbe" + THEN sperren und setzen (3) + ELSE sperren und setzen (2) + FI; + FI +CASE9(*m*): IF string (2, 3) = "ög" AND teilwort laenge > 5 (* mög *) + THEN sperren und setzen (3); + FI +CASE10(*n*): IF string (2, 4) = "ach" AND teilwort laenge >= 7 + AND (teilwort SUB 5) <> "t" (* nach, aber nicht: nacht *) + THEN SETZE 4 + ELIF string (2, 6) = "ieder" (* nieder *) + THEN sperren und setzen (6) + ELIF string (2, 5) = "icht" (* nicht *) + THEN sperren und setzen (5) + ELIF string (2, 3) = "eu" (* neu *) + THEN sperren und setzen (3); + IF dreisilber (4) + THEN sperren und setzen (6) + FI + ELIF string (2, 5) = "iste" + THEN sperren und setzen (2) + FI +CASE11(*r*): IF code 2 = cv e (* re *) + THEN IF silbenanfang nach (4) (* Realeinkommen *) + THEN sperren und setzen (4) + ELSE sperren und setzen (2) + FI + FI +CASE12(*s*): IF string (2, 6) = "elbst" (* selbst *) + THEN sperren und setzen (6); SPERRE 4 + FI +CASE13(*t*): IF string (2, 3) = "at" (* tat *) + THEN sperren und setzen (3) + ELIF string (2, 5) = "rans" (* trans *) + THEN sperren und setzen (5) + ELIF string (2, 4) = "heo" (* theo *) + THEN sperren und setzen (4) + FI +CASE14(*u*): IF code 2 = cv m (* um *) + THEN SETZE 2 + ELIF code 2 = cv n (* un *) + THEN IF code 3 = cv i (* uni *) + THEN sperren und setzen (3) + ELSE sperren und setzen (2); + IF string (3, 5) = "ter" (* unter *) + THEN sperren und setzen (5) + FI + FI + FI +CASE15(*v*): IF string (2, 3) = "or" OR string (2, 3) = "on" OR + string (2, 3) = "er" (* vor, von, ver *) + THEN sperren und setzen (3) + FI +CASE16(*w*): IF code 2 = cv e AND code 3 = cv g (* weg *) + THEN sperren und setzen (3) + ELIF code 2 = cv i (* wi *) + THEN IF string(3,5) = "der" (* wider *) + THEN sperren und setzen (5) + ELIF string(3,6) = "eder" (* weder *) + THEN sperren und setzen (6) + FI + FI +CASE17(*ü*): IF string (2, 4) = "ber" (* über *) + THEN sperren und setzen (4) + FI +CASE18(*z*): IF code 2 = cv u (*zu*) + THEN sperren und setzen (2); + IF drei silber (3) (* zuein *) + THEN sperren und setzen (5) + FI + FI +END SELECT. + +nachsilben untersuchen: + IF (teilwort SUB teilwort laenge) = "t" + THEN IF (string (teilwort laenge - 3,teilwort laenge) = "heit" + AND (teilwort SUB teilwort laenge - 4) <> "c") + OR string (teilwort laenge - 3, teilwort laenge -1) = "kei" + THEN sperren und setzen (teilwort laenge - 4) + FI + ELIF string (teilwort laenge - 2, teilwort laenge) = "tag" + THEN sperren und setzen (teilwort laenge - 3) + ELIF string (teilwort laenge - 3, teilwort laenge) = "tags" + THEN sperren und setzen (teilwort laenge - 4) + FI. + +vokal 1: + IF string (a pos, a pos plus 2) = "uel" + THEN SETZE a pos + FI. + +vokal 2 : + ind := pos (vokal string, teilwort SUB a pos); + code 2 := code (teilwort SUB a pos plus 1); +SELECT ind OF +CASE1(*a*): IF code 2 = cv a OR code 2 = cv i OR code 2 = cv y (*aa,ai,ay*) + THEN + ELIF code 2 = cv u + THEN silbe au behandlung + ELSE SETZE a pos + FI +CASE2(*e*): IF code 2 = cv u AND (teilwort SUB a pos plus 2) = "e" (*eue*) + THEN SETZE a pos plus 1 + ELIF code 2 = cv o OR code 2 = cv ae OR code 2 = cv ue + OR code 2 = cv oe (*eo, eä, eü, eö *) + THEN SETZE a pos + FI +CASE3(*i*): IF code 2 <> cv e AND code 2 <> cv o (* i, aber nicht: ie, io *) + THEN SETZE a pos + FI +CASE4(*o*): IF code 2 = cv o OR code 2 = cv u (* oo, ou *) + THEN + ELIF code 2 = cv e (* oe *) + THEN SETZE a pos plus 1 + ELSE SETZE a pos + FI +CASE5(*u*): IF (teilwort SUB a pos - 1) = "q" (* qu *) + THEN + ELIF code 2 = cv e (* ue *) + THEN SETZE a pos plus 1 + ELSE SETZE a pos + FI +CASE7(*y*): IF code 2 <> cv u (* yu *) + THEN SETZE a pos + FI +OTHERWISE (*äöü*): SETZE a pos +END SELECT. + +silbe au behandlung: + IF (teilwort SUB a pos + 2) = "e" (* aue, wie in dau-ernd *) + THEN SETZE a pos plus 1 + ELIF a pos > 2 AND trennung oder sperre gesetzt (a pos + 2) AND + ((teilwort SUB a pos + 2) = "f" OR (teilwort SUB a pos + 2) = "s") + (* aus- oder auf-Mittelsilben *) + THEN SETZE (a pos - 1) + FI. + +vokal 3 : + IF string (a pos, a pos plus 2) <> "eau" + AND string (a pos plus 1, a pos+3) <> "eau" + THEN IF e pos - a pos = anzahl - 1 + THEN SETZE a pos plus 1 + ELSE code 1 := code(teilwort SUB a pos) ; + tr pos := a pos plus 1 ; + IF (code 1 = cv a OR code 1 = cv o OR code 1 = cv u) + AND (teilwort SUB a pos plus 1) = "e" + THEN tr pos INCR 1 + FI; + code 2 := code (teilwort SUB tr pos) ; + IF (code 2 = cv a OR code 2 = cv o OR code 2 = cv u) + AND (teilwort SUB tr pos + 1) = "e" + THEN tr pos INCR 1 + FI ; + SETZE tr pos + FI + FI . + +konsonant 1 : + ind := pos ("bcklmnrstß", teilwort SUB a pos); +SELECT ind OF +CASE1(*b*): IF string (a pos minus 1, a pos plus 2) = "über" + THEN SETZE a pos minus 2 + ELIF silbenanfang nach (a pos) + AND NOT trennung oder sperre gesetzt (a pos minus 1) + THEN SETZE a pos + ELIF vorletzter buchstabe oderkeine trennung oder sperre gesetzt + (a pos) + THEN SETZE a pos minus 1 + FI; +CASE2(* c oder ch *): + IF ((teilwort SUB a pos plus 1) = "h" + AND (silbenanfang nach (a pos plus 1) + OR string (a pos, a pos + 3) = "chen")) + OR (teilwort SUB a pos plus 1) <> "h" + THEN SETZE a pos minus 1 + ELSE SETZE a pos plus 1 + FI +CASE3(*k*): IF string (a pos minus 2, a pos minus 1) = "ti" (* tik *) + AND silbenanfang nach (a pos) + THEN SETZE a pos + ELSE SETZE a pos minus 1 + FI +CASE4(*l*): IF string (a pos - 3, a pos plus 1) = "reali" + THEN SETZE a pos plus 1 + ELIF string (a pos minus 1, a pos plus 1) = "aly" + THEN SETZE a pos minus 1 + ELIF string (a pos minus 2, a pos minus 1) = "ta" (*..tal..*) + OR string (a pos minus 2, a pos minus 1) = "na" (*..nal..*) + OR string (a pos minus 2, a pos minus 1) = "ia" (*..ial..*) + THEN SETZE a pos + ELSE SETZE a pos minus 1 + FI +CASE5(*m*): IF string (a pos minus 2, a pos minus 1) = "to" (* ..tom..*) + THEN SETZE a pos + ELSE SETZE a pos minus 1 + FI +CASE6(*n*): IF string (a pos - 4, a pos minus 1) = "gege" + OR string (a pos - 4, a pos minus 1) = "nebe" (*gegen, neben*) + THEN SETZE (a pos - 3) ; SETZE a pos + ELIF string (a pos minus 1, a pos plus 1) = "ini" + THEN + ELIF NOT silbenanfang vor (a pos) + AND ((teilwort SUB a pos minus 1) = "e" (* en *) + OR (teilwort SUB a pos minus 1) = "u") (* un *) + AND (silbenanfang nach (a pos) + OR string (a pos plus 1, a pos plus 2) = "ob") + THEN SETZE a pos + ELIF string (a pos minus 2, a pos plus 1) = "eina" + THEN SETZE a pos + ELSE SETZE a pos minus 1 + FI +CASE7(*r*): IF string (a pos minus 2, a pos minus 1) = "tu" (*..tur..*) + THEN IF string (a pos plus 1, a pos plus 2) = "el" + OR (string (a pos plus 1, a pos plus 2) = "en" + AND string (a pos minus 1, apos +3) <> "ent") + (* turel OR <>turentwick*) + THEN SETZE a pos minus 1 + ELSE SETZE a pos + FI + ELIF string (a pos minus 2, a pos minus 1) = "ve" (*..ver..*) + OR string (a pos minus 2, a pos minus 1) = "vo" (*..vor..*) + THEN SETZE a pos + ELIF string (a pos minus 2, a pos minus 1) = "te" (* ter *) + THEN IF dreisilber (a pos plus 1) + OR string (a pos plus 1, a pos plus 1) = "a" (*tera*) + OR string (a pos - 3, a pos minus 2) <> "zt" (*zter*) + THEN SETZE a pos + ELSE SETZE a pos minus 1 + FI + ELIF (teilwort SUB a pos minus 1) = "e" (* er*) + AND silbenanfang nach (a pos) + AND string (a pos plus 1, a pos + 3) <> "ung" (*erung*) + AND string (a pos plus 1, a pos plus 2) <> "er" (*erer*) + THEN SETZE a pos + ELIF vorletzter buchstabe oderkeine trennung oder sperre gesetzt + (a pos) + THEN SETZE a pos minus 1 + FI +CASE8(*s*): IF string (a pos minus 2, a pos minus 1) = "de" (* des *) + OR string (a pos minus 2, a pos minus 1) = "xi" (* ..xis *) + THEN SETZE a pos + ELIF string (a pos minus 2, a pos minus 1) = "ni" (* nis *) + AND silbenanfang nach (a pos) + THEN SETZE a pos + ELIF vorletzter buchstabe oderkeine trennung oder sperre gesetzt + (a pos) + THEN SETZE apos minus 1 + FI +CASE9(*t*): IF string (a pos plus 1, a pos + 3) = "ion" (* tion *) + THEN SETZE a pos minus 1 + ELIF string (a pos plus 1, a pos + 3) <> "ier" (* imitieren *) + AND (string (a pos minus 2, a pos minus 1) = "mi"(*...mit..*) + OR string (a pos minus 2, a pos minus 1) = "va"(*privat..*) + OR string (a pos minus 2, a pos minus 1) = "fi"(*profit..*) + OR string (a pos - 3, a pos minus 1) = "zei")(*..zeit..*) + THEN SETZE a pos + ELSE SETZE a pos minus 1 + FI +CASE10(*ß*): IF string (a pos, a pos plus 2) = "ßen" + OR vorletzter buchstabe (a pos) + THEN SETZE a pos minus 1 + ELSE SETZE a pos + FI +OTHERWISE: IF vorletzter buchstabe oderkeine trennung oder sperre gesetzt + (a pos) + THEN SETZE a pos minus 1 + FI +END SELECT. + +konsonant 2 : + kons gr := string (a pos, e pos); + IF a pos > 2 AND trennung oder sperre gesetzt (a pos minus 1) + THEN + ELIF ausnahme fuer zwei konsonanten + THEN SETZE a pos + ELIF kons gr = "ts" + THEN IF NOT trennung oder sperre gesetzt (a pos) + (* für <> Tatsache, tatsächlich *) + THEN SETZE e pos + FI + ELIF kons gr = "tz" + THEN IF (teilwort SUB a pos plus 2) = "e" (* ..tze.. *) + OR (teilwort SUB a pos plus 2) = "u" (* ..tzu.. *) + THEN SETZE a pos + ELSE SETZE a pos plus 1 + FI + ELIF string (a pos, a pos plus 1) = "ch"(* ch zaehlt als 1 Buchstabe *) + THEN SETZE a pos plus 1 (* darum keine Abfrage mit kons gr *) + ELIF (kons gr = "dt" OR kons gr = "kt") + AND silbenanfang nach (e pos) + THEN SETZE e pos + ELIF kons gr = "ns" AND + (string (a pos - 2, a pos - 1) = "io" (* ..ions *) + OR (string (a pos minus 1, a pos) ="en" (*..ens..*) + AND (teilwort SUB a pos minus 2) <> "t")) (* aber nicht ..tensiv*) + THEN SETZE e pos + ELIF string (a pos minus 2, a pos plus 1) = "nach" + THEN IF (teilwort SUB a pos plus 2) <> "t" + THEN SETZE a pos plus 1 + FI + ELIF string (e pos, e pos + 3) = "lich" + THEN IF string (a pos minus 2, a pos) = "mög" + THEN SETZE a pos + ELIF pos ("hg", teilwort SUB e pos minus 1) > 0 + THEN SPERRE e pos minus 1 + ELSE SETZE e pos minus 1 + FI; + ELIF (reg (a pos) AND NOT trennung oder sperre gesetzt (a pos)) + OR (kons gr = "sp" AND silbenanfang vor (a pos)) + THEN SETZE a pos minus 1 + ELIF string (a pos, a pos plus 2) = "sch" + THEN SETZE a pos plus 2 + ELSE SETZE a pos + FI. + +ausnahme fuer zwei konsonanten: + string (a pos minus 2, a pos) = "nis" AND a pos > 1 + (*..nis.., aber nicht nisten *) + OR string (a pos minus 2, a pos plus 1) = "rafr" (* strafrecht *) + OR string (a pos - 4, a pos) = "undes" (* Bundes *) + OR string (a pos minus 1, a pos + 3) = "unter" + OR silbenanfang vor (e pos). + +konsonant 3 : + code 1 := code (teilwort SUB a pos); + code 2 := code (teilwort SUB a pos plus 1); + code 3 := code (teilwort SUB a pos plus 2); + IF NOT (ausnahme 1 OR ausnahme 2 OR ausnahme 3 OR ausnahme 4) + THEN suche regelmaessige konsonantenverbindung + FI. + +ausnahme 1 : + ind := pos ("cfgklnprt", code (code 1)); + SELECT ind OF +CASE1(*c*): IF code 2 = cv k (* ck *) + THEN SETZE a pos plus 1 + ELIF string (a pos, a pos + 3) = "chts" + (* Rechts.., Gesichts.., .. machts..*) + THEN SETZE (a pos + 3) + ELIF string (a pos plus 1, a pos + 5) = "hstag" (* Reichstag *) + OR (string (a pos, a pos plus 2) = "chs" AND (* ..chs.. *) + string (a pos plus 2, a pos +3) <> "st") + THEN SETZE a pos plus 2 + ELSE LEAVE ausnahme 1 WITH FALSE + FI; + TRUE +CASE2(*f*): IF code 2 = cv f (*ff*) + THEN IF code 3 = cv s + THEN SETZE a pos plus 2 (* ffs *) + ELSE SETZE a pos plus 1 + FI + ELIF string (a pos minus 1, a pos plus 1) = "aft" (*..aft..*) + THEN IF (teilwort SUB a pos plus 2) = "s" + THEN SETZE a pos plus 2 + ELSE SETZE a pos plus 1 + FI + ELSE LEAVE ausnahme 1 WITH FALSE + FI; + TRUE +CASE3(*g*): IF string (a pos minus 2, a pos minus 1) = "ag" (* ags *) + THEN SETZE a pos plus 1 + ELSE LEAVE ausnahme 1 WITH FALSE + FI; + TRUE +CASE4(*k*): IF string (a pos, a pos plus 1) = "kt" + AND silbenanfang nach (a pos plus 1) + THEN SETZE a pos plus 1 + ELSE LEAVE ausnahme 1 WITH FALSE + FI; + TRUE +CASE5(*l*): IF code 2 = cv d OR code 2 = cv g OR code 2 = cv k (*ld, lg, lk*) + THEN SETZE a pos plus 1 + ELIF string (a pos, a pos + 4) = "ltspr" (* Anwaltsprogramm *) + THEN SETZE (a pos + 2) + ELSE LEAVE ausnahme 1 WITH FALSE + FI; + TRUE +CASE6(*n*): IF string (a pos - 2, a pos) = "ein" + THEN SETZE a pos + ELIF code 2 = cv d (* nd *) + THEN IF code 3 = cv s (* nds, wie in ...stands... *) + THEN SETZE a pos plus 2 + ELSE SETZE a pos plus 1 + FI + ELIF code 2 = cv g (* ng *) + THEN IF code 3 = cv s (* ..ngs.. *) + THEN SETZE a pos plus 2 + ELIF code 3 = cv r (* ..ngr.. *) + THEN SETZE a pos + ELIF code 3 = cv l (* ungleich *) + THEN + ELSE SETZE a pos plus 1 + FI + ELIF string (a pos - 3, a pos plus 1) = "trans" + OR string (a pos - 3, a pos plus 1) = "tions" (*tionsplan*) + THEN SETZE a pos plus 1 + ELIF string (a pos plus 1, a pos + 6) = "ftsper" (*ftsperspek*) + THEN SETZE (a pos + 3) + ELSE LEAVE ausnahme 1 WITH FALSE + FI; + TRUE +CASE7(*p*): IF code 2 = cv p (* pp *) + OR (code 2 = cv f AND code 3 = cv t) (* pft *) + THEN SETZE a pos plus 1; TRUE + ELSE FALSE + FI +CASE8(*r*): IF string (a pos plus 1, a pos + 4) = "tner" (* rtner *) + THEN SETZE a pos plus 1 + ELIF trennung oder sperre gesetzt (a pos) + THEN + ELSE LEAVE ausnahme 1 WITH FALSE + FI; + TRUE +CASE9(*t*): IF string (a pos plus 1, a pos plus 2) = "st" (*tst*) + THEN SETZE a pos + ELIF string (a pos plus 1, a pos plus 2) = "zt" + (* letzt.. *) + THEN IF (teilwort SUB a pos + 3) = "e" (*letzte..*) + THEN SETZE a pos plus 1 + ELSE SETZE a pos plus 2 + FI + ELIF string (apos - 2, a pos plus 1) = "eits" + (* ..heits.., ..keits.., ..beits.. *) + OR string (a pos plus 1, a pos plus 1)= "z" (*tz*) + THEN SETZE a pos plus 1 + ELSE LEAVE ausnahme 1 WITH FALSE + FI; + TRUE +OTHERWISE: FALSE +END SELECT. + +ausnahme 2 : + IF e pos - a pos = 2 + THEN FALSE + ELIF code 2 = cv p AND string (a pos plus 2, a pos + 3) = "ft" (* pft *) + THEN SETZE a pos plus 2; TRUE + ELSE FALSE + FI . + +ausnahme 3 : + IF code 1 = cv s + THEN IF code 2 = cv t AND code 3 <> cv r (* st, aber nicht: str *) + AND pos (vokal string, teilwort SUB a pos plus 2) = 0 + THEN SETZE a pos plus 1 ; TRUE + ELSE FALSE + FI + ELIF code 2 = cv s + THEN IF code 3 = cv t AND (teilwort SUB a pos + 3) <> "r" + AND pos (vokal string, teilwort SUB (a pos + 3)) = 0 + THEN SETZE a pos plus 2; TRUE + ELSE FALSE + FI + ELSE FALSE + FI . + +ausnahme 4 : + IF string (e pos, e pos + 3) = "lich" + THEN IF pos ("hg", teilwort SUB e pos minus 1) > 0 + THEN SPERRE e pos minus 1 + ELSE SETZE e pos minus 1 + FI; + TRUE + ELSE FALSE + FI . + +suche regelmaessige konsonantenverbindung : + FOR posit FROM a pos UPTO e pos minus 1 REP + IF reg (posit) + THEN SETZE (posit - 1); LEAVE konsonant 3 + FI + END REP ; + IF (teilwort SUB e pos) <> "h" OR (teilwort SUB e pos minus 1) <> "c" + THEN SETZE e pos minus 1 + ELIF (teilwort SUB e pos - 2) <> "s" + THEN SETZE (e pos - 2) + ELSE SETZE (e pos - 3) + FI +END PROC erstelle trennvektor ; +END PACKET silbentrennung; + diff --git a/system/multiuser/1.7.5/src/spool manager b/system/multiuser/1.7.5/src/spool manager new file mode 100644 index 0000000..ac0295a --- /dev/null +++ b/system/multiuser/1.7.5/src/spool manager @@ -0,0 +1,887 @@ +PACKET spool manager DEFINES (* Autor: J. Liedtke *) + (* R. Nolting *) + (* R. Ruland *) + (* Stand: 25.04.86 *) + + spool manager , + + server channel , + spool duty, + station only, + spool control task : + +LET que size = 101 , + + ack = 0 , + nak = 1 , + error nak = 2 , + message ack = 3 , + question ack = 4 , + second phase ack = 5 , + + fetch code = 11 , + save code = 12 , + file save code old = 13 , + erase code = 14 , + list code = 15 , + all code = 17 , + param fetch code = 21 , + file save code = 22 , + entry line code = 23 , + killer code = 24 , + first code = 25 , + start code = 26 , + stop code = 27 , + halt code = 28 , + wait for halt code = 29 , + + continue code = 100 , + + file type = 1003 ; + +LET begin char = ""0"", + end char = ""1""; + +LET PARAMS = STRUCT (TEXT name, userid, password, sendername, INT station), + ENTRY = STRUCT (PARAMS ds params, TEXT entry line, DATASPACE space); + +ROW que size ENTRY VAR que ; + +PARAMS CONST empty params := PARAMS : ("", "", "", "", -1); + +PARAMS VAR save params, file save params; + +ENTRY VAR fetch entry; + +FILE VAR file; + +INT VAR order, last order, phase, reply, old heap size, first, last, list index, + begin pos, end pos, order task station, sp channel, counter; + +TEXT VAR order task name, buffer, sp duty, start time; + +BOOL VAR server is waiting, stop command pending, stat only, valid fetch entry; + +TASK VAR order task, last order task, server, calling parent, task in control; + +INITFLAG VAR in this task := FALSE; + +DATASPACE VAR ds; + +BOUND STRUCT (TEXT name, userid, password) VAR msg; +BOUND STRUCT (TEXT entry line, INT index) VAR control msg; +BOUND PARAMS VAR fetch msg; +BOUND THESAURUS VAR all msg; +BOUND TEXT VAR error msg ; + + +. first entry : que (first) +. list entry : que (list index) +. last entry : que (last) + +. que is empty : first = last +. que is full : first = next (last) +.; + +sp channel := 0; +sp duty := ""; +stat only := FALSE; +task in control := myself; + +PROC server channel (INT CONST channel nr) : + IF channel nr <= 0 OR channel nr >= 33 + THEN errorstop ("falsche Kanalangabe") FI; + sp channel := channel nr; +END PROC server channel; + +INT PROC server channel : + sp channel +END PROC server channel; + + +PROC station only (BOOL CONST flag) : + stat only := flag +END PROC station only; + +BOOL PROC station only : + stat only +END PROC station only; + + +PROC spool duty (TEXT CONST duty) : + sp duty := duty; +END PROC spool duty; + +TEXT PROC spool duty : + sp duty +END PROC spool duty; + + +PROC spool control task (TASK CONST task id): + task in control := task id; +END PROC spool control task; + +TASK PROC spool control task : + task in control +END PROC spool control task; + + +PROC spool manager (PROC server start) : + + spool manager (PROC server start, TRUE) + +END PROC spool manager; + + +PROC spool manager (PROC server start, BOOL CONST with start) : + + set autonom ; + break ; + disable stop ; + initialize spool manager ; + REP forget (ds) ; + wait (ds, order, order task) ; + IF order <> second phase ack + THEN prepare first phase ; + spool (PROC server start); + ELIF order task = last order task + THEN prepare second phase ; + spool (PROC server start); + ELSE send nak + FI ; + send error if necessary ; + collect heap garbage if necessary + PER + + . initialize spool manager : + initialize if necessary; + stop; + erase fetch entry; + IF with start THEN start (PROC server start) FI; + + . initialize if necessary : + IF NOT initialized (in this task) + THEN FOR list index FROM 1 UPTO que size + REP list entry. space := nilspace PER; + fetch entry. space := nilspace; + ds := nilspace; + last order task := niltask; + server := niltask; + calling parent := niltask; + server is waiting := FALSE; + stop command pending := FALSE; + old heap size := 0; + clear spool; + FI; + + . prepare first phase : + IF order = save code OR order = erase code OR order = stop code + THEN phase := 1 ; + last order := order ; + last order task := order task ; + FI; + + . prepare second phase : + phase INCR 1 ; + order := last order + + . send nak : + forget (ds) ; + ds := nilspace ; + send (order task, nak, ds); + + . send error if necessary : + IF is error + THEN forget (ds) ; + ds := nilspace ; + error msg := ds ; + CONCR (error msg) := error message; + clear error; + send (order task, error nak, ds) + FI; + + . collect heap garbage if necessary : + IF heap size > old heap size + 2 + THEN collect heap garbage; + old heap size := heap size; + FI; + +END PROC spool manager; + + +PROC spool (PROC server start): + + command dialogue (FALSE); + enable stop; + IF station only CAND station (ordertask) <> station (myself) + THEN errorstop ("kein Zugriffsrecht auf Task " + text (station(myself)) + + "/""" + name(myself) + """") + FI; + + SELECT order OF + + CASE fetch code : out of que + CASE param fetch code : send fetch params + CASE save code : new que entry + CASE file save code, file save code old : + new file que entry + CASE erase code : erase que entry + CASE list code : send spool list + CASE all code : send owners ds names + + OTHERWISE : + + IF order >= continue code AND order task = supervisor + THEN forget (ds); + spool command (PROC server start) + + ELIF spool control allowed by order task + THEN SELECT order OF + CASE entry line code : send next entry line + CASE killer code : kill entry + CASE first code : make to first + CASE start code : start server + CASE stop code : stop server + CASE halt code : halt server + CASE wait for halt code : wait for halt + OTHERWISE : errorstop ("falscher Auftrag fuer Task """ + + name(myself) + """") + END SELECT + + ELSE errorstop ("falscher Auftrag fuer Task """ + + name(myself) + """") + FI; + END SELECT; + + +. spool control allowed by order task : + (order task = spool control task OR order task < spool control task + OR spool control task = supervisor) + AND station (order task) = station (myself) +. + out of que : + IF NOT (order task = server) + THEN errorstop ("keine Servertask") + ELIF stop command pending + THEN forget (ds); + stop; + erase fetch entry; + ELIF que is empty + THEN forget (ds) ; + erase fetch entry; + server is waiting := TRUE; + ELSE send first entry; + FI; + +. + send fetch params : + IF order task = server + THEN send params + ELSE errorstop ("keine Servertask") + FI; + + . send params : + forget(ds); ds := nilspace; fetch msg := ds; + fetch msg := fetch entry. ds params; + send (order task, ack, ds); + +. + new que entry : + IF phase = 1 + THEN prepare into que + ELSE into que + FI; + +. + prepare into que : + msg := ds ; + save params. name := msg.name; + save params. userid := msg.userid; + save params. password := msg.password; + save params. sendername := name (order task); + save params. station := station (order task); + forget (ds); ds := nilspace; + send (order task, second phase ack, ds); + +. + new file que entry : + IF type (ds) <> file type + THEN errorstop ("Datenraum hat falschen Typ"); + ELSE get file params; + into que; + FI; + + . get file params : + file := sequential file (input, ds); + end pos := 0; + next headline information (file save params. name); + next headline information (file save params. userid); + next headline information (file save params. password); + next headline information (file save params. sendername); + next headline information (buffer); + file save params. station := int (buffer); + IF NOT last conversion ok + THEN file save params. station := station (order task) FI; + IF file save params. sendername = "" + THEN file save params. sendername := name (order task) FI; + IF file save params. name = "" + THEN IF headline (file) <> "" + THEN file save params. name := headline (file); + ELSE errorstop ("Name unzulaessig") + FI; + ELSE headline (file, file save params. name); + FI; + +. + erase que entry : + msg := ds ; + order task name := name (order task); + order task station := station (order task); + IF phase = 1 + THEN ask for erase + ELSE erase entry from order task + FI; + + . ask for erase : + to first que entry; + WHILE next que entry found + REP IF is entry from order task (msg. name) + THEN manager question ("""" + msg.name + """ loeschen"); + LEAVE erase que entry + FI; + PER ; + manager message ("""" + msg.name + """ existiert nicht"); + + . erase entry from order task : + IF is entry from order task (msg. name) + THEN delete que entry; + LEAVE erase que entry + ELSE to first que entry; + WHILE next que entry found + REP IF is entry from order task (msg. name) + THEN delete que entry; + LEAVE erase que entry + FI ; + PER ; + manager message ("""" + msg.name + """ existiert nicht"); + FI; + + . delete que entry : + erase entry (list index) ; + send ack; + +. + send owners ds names: + order task name := name (order task); + order task station := station (order task); + forget (ds); ds := nilspace; all msg := ds; + all msg := empty thesaurus; + to first que entry; + WHILE next que entry found + REP IF is entry from order task ("") + THEN insert (all msg, list entry. ds params. name) + FI; + PER; + send (order task, ack, ds) + +. + send spool list : + list spool; + send (order task, ack, ds); + +. + send next entry line : + control msg := ds; + get next entry line (control msg. entry line, control msg. index); + send (order task, ack, ds); + +. + kill entry : + control msg := ds; + list index := control msg. index; + IF is valid que entry (list index) + THEN erase entry (list index) + FI; + send (order task, ack, ds); + +. + make to first : + control msg := ds; + list index := control msg. index; + IF is valid que entry (list index) + THEN new first (list entry); + erase entry (list index); + FI; + send (order task, ack, ds); + +. + start server : + IF exists (server) THEN errorstop ("Spool muß zuerst gestoppt werden") FI; + start (PROC server start); + IF server channel <= 0 OR server channel >= 33 + THEN manager message ("WARNUNG : Serverkanal nicht eingestellt"); + ELSE send ack + FI; + +. + stop server: + IF phase = 1 + THEN stop; + IF valid fetch entry + THEN valid fetch entry := FALSE; + manager question (""13""10"" + + fetch entry. entry line + " neu eintragen"); + ELSE erase fetch entry; + send ack; + FI; + ELSE IF fetch entry. entry line <> "" THEN new first (fetch entry) FI; + erase fetch entry; + send ack; + FI; + +. + halt server : + stop command pending := TRUE; + IF NOT exists (server) OR server is waiting + THEN stop; + erase fetch entry; + FI; + send ack; + +. + wait for halt : + IF exists (calling parent) + THEN errorstop ("Task """ + name (calling parent) + """ wartet schon auf halt") + ELSE calling parent := order task; + stop command pending := TRUE; + forget (ds); + IF NOT exists (server) OR server is waiting + THEN stop; + erase fetch entry; + FI; + FI; + +END PROC spool; + + +PROC send first entry : + + forget (ds); ds := first entry. space; + send (server, ack, ds, reply) ; + IF reply = ack + THEN server is waiting := FALSE; + start time := time of day; + start time CAT " am "; + start time CAT date; + erase fetch entry; + fetch entry := first entry; + erase entry (first); + valid fetch entry := TRUE; + ELSE forget (ds); + FI; + +END PROC send first entry; + + +PROC into que : + + IF que is full + THEN errorstop ("Spool ist voll") + ELSE make new entry; + send ack; + awake server if necessary + FI; + + . make new entry : + IF order = save code + THEN last entry. ds params := save params; + save params := empty params; + ELSE last entry. ds params := file save params; + file save params := empty params; + FI; + last entry. space := ds; + counter INCR 1; + build entry line; + last := next (last) ; + + . build entry line : + IF LENGTH last entry. ds params. sender name > 16 + THEN buffer := subtext (last entry. ds params. sender name, 1, 13); + buffer CAT "..."""; + ELSE buffer := last entry. ds params. sender name; + buffer CAT """"; + buffer := text (buffer, 17); + FI; + last entry. entry line := text (last entry. ds params. station, 2); + last entry. entry line CAT "/"""; + last entry. entry line CAT buffer; + last entry. entry line CAT " : """ ; + last entry. entry line CAT last entry. ds params. name; + last entry. entry line CAT """ (" ; + last entry. entry line CAT text (storage (last entry. space)); + last entry. entry line CAT " K)"; + + . awake server if necessary : + IF server is waiting THEN send first entry FI; + +END PROC into que; + + +PROC list spool : + + forget (ds); ds := nilspace; + file := sequential file (output, ds) ; + max line length (file, 1000); + headline(file, text (station(myself)) + "/""" + name (myself) + """"); + put spool duty; + put current job; + put spool que; + + . put spool duty : + IF spool duty <> "" + THEN write (file, "Aufgabe: "); + write (file, spool duty ); + line (file, 2); + FI; + + . put current job : + IF valid fetch entry AND exists (server) + THEN write (file, "In Bearbeitung seit "); + write (file, start time); + write (file, ":"); + line (file, 2); + putline (file, fetch entry. entry line); + IF stop command pending + THEN putline (file, "Spool wird nach diesem Auftrag deaktiviert"); + FI; + line (file); + ELSE write (file, "kein Auftrag in Bearbeitung"); + IF NOT exists (server) + THEN write (file, ", da Spool deaktiviert"); + ELIF que is empty + THEN write (file, ", da Warteschlange leer"); + LEAVE list spool; + FI; + line (file, 2); + FI; + + . put spool que : + IF que is empty + THEN putline (file, "Warteschlange ist leer"); + ELSE write (file, "Warteschlange ("); + write (file, text (counter)); + write (file, " Auftraege):"); + line (file, 2); + to first que entry ; + WHILE next que entry found + REP putline (file, list entry. entry line) PER; + FI; + +END PROC list spool ; + + +PROC clear spool : + + first := 1; + last := 1; + counter := 0; + FOR list index FROM 1 UPTO que size + REP list entry. ds params := empty params; + list entry. entry line := ""; + forget (list entry. space) + PER; + +END PROC clear spool; + +(*********************************************************************) +(* Hilfsprozeduren zum Spoolmanager *) + +BOOL PROC is valid que entry (INT CONST index) : + + que (index). entry line <> "" + +END PROC is valid que entry; + + +INT PROC next (INT CONST index) : + + IF index < que size + THEN index + 1 + ELSE 1 + FI + +END PROC next; + + +PROC to first que entry : + + list index := first - 1; + +ENDPROC to first que entry ; + + +BOOL PROC next que entry found : + + list index := next (list index); + WHILE is not last que entry + REP IF is valid que entry (list index) + THEN LEAVE next que entry found WITH TRUE FI; + list index := next (list index); + PER; + FALSE + + . is not last que entry : + list index <> last + +ENDPROC next que entry found ; + + +PROC get next entry line (TEXT VAR entry line, INT VAR index) : + + IF index = 0 + THEN list index := first - 1 + ELSE list index := index + FI; + IF next que entry found + THEN entry line := list entry. entry line; + index := list index; + ELSE entry line := ""; + index := 0; + FI; + +END PROC get next entry line; + + +PROC new first (ENTRY VAR new first entry) : + + IF que is full + THEN errorstop ("Spool ist voll") + ELSE first DECR 1 ; + IF first = 0 THEN first := que size FI; + first entry := new first entry; + counter INCR 1; + FI; + +END PROC new first; + + +PROC erase entry (INT CONST index) : + + entry. ds params := empty params; + entry. entry line := ""; + forget (entry.space) ; + counter DECR 1; + IF index = first + THEN inc first + FI ; + + . entry : que (index) + + . inc first : + REP first := next (first) + UNTIL que is empty OR is valid que entry (first) PER + +END PROC erase entry; + + +PROC erase fetch entry : + + fetch entry. ds params := empty params; + fetch entry. entry line := ""; + forget (fetch entry. space); + valid fetch entry := FALSE; + +END PROC erase fetch entry; + + +BOOL PROC is entry from order task (TEXT CONST file name) : + + correct order task CAND correct filename + + . correct order task : + order task name = list entry. ds params. sendername + AND order task station = list entry. ds params. station + + . correct file name : + file name = "" OR file name = list entry. ds params. name + +END PROC is entry from order task; + + +PROC start (PROC server start): + + begin (PROC server start, server); + +END PROC start; + + +PROC stop : + + stop server; + send calling parent reply if necessary; + + . stop server: + IF exists (server) THEN end (server) FI; + server := niltask; + server is waiting := FALSE; + stop command pending := FALSE; + + . send calling parent reply if necessary : + IF exists (calling parent) + THEN forget (ds); ds := nilspace; + send (calling parent, ack, ds); + calling parent := niltask; + FI; + +END PROC stop; + + +PROC next headline information (TEXT VAR t): + + begin pos := pos (headline (file), begin char, end pos + 1); + IF begin pos = 0 + THEN begin pos := LENGTH headline (file) + 1; + t := ""; + ELSE end pos := pos (headline (file), end char, begin pos + 1); + IF end pos = 0 + THEN end pos := LENGTH headline (file) + 1; + t := ""; + ELSE t := subtext (headline (file), begin pos+1, end pos-1) + FI + FI + +END PROC next headline information; + + +PROC send ack : + + forget (ds); ds := nilspace; + send (order task, ack, ds) + +END PROC send ack; + + +PROC manager question (TEXT CONST question) : + + forget (ds); ds := nilspace; error msg := ds ; + error msg := question ; + send (order task, question ack, ds) + +ENDPROC manager question ; + + +PROC manager message (TEXT CONST message) : + + forget (ds); ds := nilspace; error msg := ds ; + error msg := message ; + send (order task, message ack, ds) + +ENDPROC manager message ; + +(*********************************************************************) +(* Spool - Kommandos *) + +INT VAR command index , params ; +TEXT VAR command line, param 1, param 2 ; + +LET spool command list = +"break:1.0start:2.01stop:4.0halt:5.0first:6.0killer:7.0listspool:8.0 +clearspool:9.0spoolcontrolby:10.1"; + +PROC spool command (PROC server start) : + + enable stop ; + continue (order - continue code) ; + disable stop ; + REP command dialogue (TRUE) ; + get command ("gib Spool-Kommando:", command line); + analyze command (spool command list, command line, 3, command index, + params, param1, param2); + execute command (PROC server start); + UNTIL NOT online PER; + command dialogue (FALSE); + break (quiet); + set autonom; + +END PROC spool command; + + +PROC execute command (PROC server start) : + + enable stop; + SELECT command index OF + CASE 1 : break + CASE 2 : start server + CASE 3 : start server with new channel + CASE 4 : stop server + CASE 5 : halt server + CASE 6 : first cmd + CASE 7 : killer cmd + CASE 8 : show spool list + CASE 9 : clear spool + CASE 10 : spool control task (task (param1)) + OTHERWISE do (command line) + END SELECT; + + . start server : + IF server channel <= 0 OR server channel >= 33 + THEN line; + putline ("WARNUNG : Serverkanal nicht eingestellt"); + FI; + stop server; + start (PROC server start); + + . start server with new channel: + INT VAR i := int (param1); + IF last conversion ok + THEN server channel (i); + start server; + ELSE errorstop ("falsche Kanalangabe") + FI; + + . stop server : + disable stop; + stop; + IF valid fetch entry CAND + yes (""13""10"" + fetch entry. entry line + " neu eintragen") + THEN new first (fetch entry) FI; + erase fetch entry; + enable stop; + + . halt server : + stop command pending := TRUE; + IF NOT exists (server) OR server is waiting + THEN stop server; + erase fetch entry; + FI; + + . first cmd : + line ; + to first que entry ; + WHILE next que entry found + REP say (list entry. entry line) ; + IF yes (" als erstes") + THEN new first (list entry); + erase entry (list index); + LEAVE first cmd + FI ; + PER; + + . killer cmd : + line ; + to first que entry ; + WHILE next que entry found + REP say (list entry. entry line) ; + IF yes (" loeschen") THEN erase entry (list index) FI ; + PER; + + . show spool list : + list spool; + disable stop; + show (file); + forget (ds); + +ENDPROC execute command ; + +ENDPACKET spool manager; + diff --git a/system/multiuser/1.7.5/src/supervisor b/system/multiuser/1.7.5/src/supervisor new file mode 100644 index 0000000..00874b2 --- /dev/null +++ b/system/multiuser/1.7.5/src/supervisor @@ -0,0 +1,774 @@ +(* ------------------- VERSION 19 03.06.86 ------------------- *) +PACKET supervisor : (* Autor: J.Liedtke *) + + + + +LET ack = 0 , + nak = 1 , + error nak = 2 , + + system catalogue code = 3 , + begin code = 4 , + end code = 5 , + break code = 6 , + rename code = 7 , + halt code = 8 , + password code = 9 , + family password code = 40 , + set autonom code = 41 , + reset autonom code = 42 , + define canal code = 43 , + go back to old canal code = 44 , + task of channel code = 45 , + canal of channel code = 46 , + set automatic startup code = 47 , + reset automatic startup code = 48 , + + continue code low = 100 , + continue code high = 132 , + + system start code = 100 , + define station code = 32000 , + max station no = 127 , + + nil = 0 , + + number of tasks = 125 , + + number of channels = 32 , + highest terminal channel = 16 , + highest user channel = 24 , + highest system channel = 32 , + configurator channel = 32 , + + shutup and save code = 12 , + + channel field = 4 , + fromid field = 11 , + nilchannel = 0 ; + + + +TASK VAR order task ; +INT VAR order code , + channel nr , + channel index ; + +DATASPACE VAR ds ; + +BOUND STRUCT (TEXT tname, tpass, TASK task, PROCA start proc) VAR msg ; +BOUND TEXT VAR error msg ; + +REAL VAR last rename time := 0.0 ; + + +TEXT VAR actual password, supply password ; + + +ROW highest terminal channel TASK VAR canal ; + +ROW number of channels TASK VAR connected task ; + +FOR channel index FROM 1 UPTO highest terminal channel REP + canal (channel index) := niltask ; +PER ; +FOR channel index FROM 1 UPTO number of channels REP + connected task (channel index) := niltask +PER ; + + +ROW number of tasks BOOL VAR autonom flag ; +ROW number of tasks BOOL VAR automatic startup flag ; +ROW number of tasks TEXT VAR task password ; + +task password (1) := "-" ; +task password (2) := "-" ; + +set clock (date ("09.06.86")) ; + +TASK VAR dummy task ; +command dialogue (TRUE) ; + +ke ; (* maintenance ke *) + +create son (myself, "SYSUR", dummy task, proca (PROC sysur)) ; + +PROC sysur : + + disable stop ; + begin ("ARCHIVE", PROC archive manager, dummy task) ; + begin ("OPERATOR", PROC monitor, dummy task) ; + begin ("conf", PROC configurator, dummy task) ; + system manager + +ENDPROC sysur ; + +PROC configurator : + + page ; + REP UNTIL yes("Archiv 'dev' eingelegt") PER; + archive ("dev") ; + fetch all (archive) ; + release (archive) ; + REP UNTIL yes ("save system") PER ; + command dialogue (FALSE) ; + save system ; + command dialogue (TRUE) ; + rename myself ("configurator") ; + disable stop ; + REP + configuration manager ; + clear error + PER + +ENDPROC configurator ; + + +erase last bootstrap source dataspace ; +channel (myself, 1) ; +command dialogue (TRUE) ; +IF yes("Leere Floppy eingelegt") + THEN channel (myself, nilchannel) ; + command dialogue (FALSE) ; + sys op (shutup and save code) + ELSE channel (myself, nilchannel) ; + command dialogue (FALSE) +FI ; +supervisor ; + + +PROC supervisor : + + disable stop ; + INT VAR old session := session ; + REP + wait (ds, order code, order task) ; + IF is niltask (order task) + THEN interrupt + ELIF station (order task) = station (myself) + THEN order from task + FI + PER . + +interrupt : + IF order code = 0 + THEN IF old session <> session + THEN disconnect all terminal tasks ; + old session := session + FI ; + system start interrupt + ELSE supervisor interrupt (canal (order code), order code, + connected task (order code)) + FI . + +disconnect all terminal tasks : + INT VAR i ; + FOR i FROM 1 UPTO highest terminal channel REP + TASK VAR id := connected task (i) ; + IF NOT (is niltask (id) COR automatic startup flag (index (id)) + COR is niltask (canal (i))) + THEN break task + FI + PER . + +break task : + IF task direct connected to channel + THEN channel (id, nilchannel) ; + connected task (i) := niltask + ELSE disconnect if at terminal but overloaded by canal + FI . + +task direct connected to channel : + pcb (id, channel field) <> nilchannel . + +disconnect if at terminal but overloaded by canal : + connected task (i) := niltask . + +order from task : + channel index := channel (order task) ; + IF is command analyzer task + THEN order from command analyzer (connected task (channel index)) + ELSE order from user task + FI ; + IF is error + THEN send back error message + FI . + +is command analyzer task : + channel index <> nilchannel + CAND channel index <= highest terminal channel + CAND order task = canal (channel index) . + +send back error message : + forget (ds) ; + ds := nilspace ; + error msg := ds ; + CONCR (error msg) := error message ; + clear error ; + send (order task, error nak, ds) . + +ENDPROC supervisor ; + +PROC supervisor interrupt (TASK VAR command analyzer, INT CONST channel nr, + TASK VAR terminal task) : + + IF NOT is niltask (terminal task) + THEN channel (terminal task, nilchannel) + FI ; + create command analyzer if necessary ; + IF already at terminal + THEN halt process (command analyzer) + ELSE send acknowledge + FI ; + channel (command analyzer, channel nr) ; + activate (command analyzer) . + +create command analyzer if necessary : + IF is niltask (command analyzer) + THEN create son (myself, "-", command analyzer, proca (PROC analyze supervisor command)) + FI . + +send acknowledge : + forget (ds) ; + ds := nilspace ; + send (command analyzer, ack, ds) . + +already at terminal : channel (command analyzer) = channel nr . + +ENDPROC supervisor interrupt ; + +PROC order from command analyzer (TASK VAR terminal task) : + +enable stop ; +IF is continue THEN sv cmd continue +ELIF order code = system catalogue code THEN task info cmd +ELIF order code = task of channel code THEN sv cmd task of channel +ELSE SELECT order code OF CASE ack : + CASE end code : sv cmd end + CASE break code : sv cmd break + CASE halt code : sv cmd halt + OTHERWISE errorstop ("falscher Auftrag fuer Task ""SUPERVISOR""") + END SELECT ; + channel (command analyzer, nilchannel) +FI ; + +forget (ds) ; +IF NOT is niltask (terminal task) AND order code <> system catalogue code + THEN channel (order task, nilchannel) ; + channel (terminal task, channel index) ; + activate (terminal task) +FI . + +sv cmd task of channel : + msg := ds ; + msg.task := terminal task ; + send (order task,ack, ds) ; + LEAVE order from command analyzer . + +sv cmd end : + IF NOT is niltask (terminal task) + THEN delete task (terminal task) ; + terminal task := niltask + FI . + +sv cmd break : + terminal task := niltask . + +sv cmd continue : + sv cmd break ; + continue cmd by canal . + +sv cmd halt : + IF is niltask (terminal task) + THEN errorstop ("keine Task angekoppelt") + ELSE halt process (terminal task) + FI . + +is continue : + order code > continue code low AND order code <= continue code high . + +command analyzer : canal (channel index) . + +ENDPROC order from command analyzer ; + +PROC order from user task : + + enable stop ; + SELECT order code OF + CASE nak, error nak : + CASE system catalogue code : task info cmd + CASE begin code : user begin cmd + CASE end code : user end cmd + CASE break code : user break cmd + CASE rename code : user rename cmd + CASE password code : password cmd + CASE family password code : family password cmd + CASE set autonom code : set autonom cmd + CASE reset autonom code : reset autonom cmd + CASE define canal code : define new canal + CASE go back to old canal code : go back to old canal + CASE task of channel code : task of channel + CASE canal of channel code : canal of channel + CASE set automatic startup code : set automatic startup cmd + CASE reset automatic startup code : reset automatic startup cmd + OTHERWISE IF is continue + THEN user continue cmd + ELIF is define station + THEN define new station + ELSE errorstop ("falscher Auftrag fuer Task ""SUPERVISOR""") + FI + ENDSELECT . + +user begin cmd : + msg := ds ; + create son (order task, new task name, new task, new start proc) ; + send (order task, ack, ds) . + +user end cmd : + msg := ds ; + TASK VAR to be erased := CONCR (msg).task ; + IF task end permitted + THEN delete task (to be erased) + ELSE errorstop ("'end' unzulaessig") + FI ; + IF exists (order task) + THEN send (order task, ack, ds) + ELSE forget (ds) + FI . + +task end permitted : + ( (task is dead AND system catalogue contains entry) OR exists (to be erased)) + CAND ( to be erased = order task + COR to be erased < order task + COR (order task < myself AND NOT (order task < to be erased)) ) . + +task is dead : + status (to be erased) > 6 . + +system catalogue contains entry : + task in catalogue (to be erased, index (to be erased)) . + +user rename cmd : + IF last rename was long ago + THEN msg := ds ; + name (order task, CONCR (msg).tname) ; + update entry in connected task array ; + send (order task, ack, ds) ; + remember rename time + ELSE send (order task, nak, ds) + FI . + +update entry in connected task array : + IF channel (order task) <> nilchannel + THEN connected task (channel (order task)) := order task + FI . + +remember rename time : + last rename time := clock (1) . + +last rename was long ago : abs (clock (1) - last rename time) > 20.0 . + +user break cmd : + break order task ; + send (order task, ack, ds) . + +break order task : + IF task direct connected to channel + THEN channel (order task, nilchannel) ; + terminal task := niltask + ELSE disconnect if at terminal but overloaded by canal + FI . + +task direct connected to channel : channel index <> nilchannel . + +terminal task : connected task (channel index) . + +disconnect if at terminal but overloaded by canal : + INT VAR i ; + FOR i FROM 1 UPTO highest terminal channel REP + IF connected task (i) = order task + THEN connected task (i) := niltask ; + LEAVE disconnect if at terminal but overloaded by canal + FI + PER . + +user continue cmd : + INT CONST dest channel := order code - continue code low ; + IF dest channel <= highest user channel OR order task < myself + THEN IF NOT channel really existing + THEN errorstop ("kein Kanal") + ELIF dest channel is free OR task is already at dest channel + THEN break order task ; + continue (order task, dest channel) ; + autonom flag (index (order task)) := FALSE ; + send (order task, ack, ds) + ELSE errorstop ("Kanal belegt") + FI + ELSE errorstop ("ungueltiger Kanal") + FI . + +channel really existing : + channel type (dest channel) <> 0 OR dest channel = configurator channel . + +dest channel is free : + (is niltask (connected task (dest channel)) OR channel (connected task (dest channel)) = nilchannel) + AND no canal active . + +no canal active : + dest channel > highest terminal channel COR + is niltask (canal (dest channel)) COR + channel (canal (dest channel)) = nilchannel . + +task is already at dest channel : + channel index = dest channel . + + +password cmd : + msg := ds ; + task password (index (order task)) := new task password ; + forget (ds) ; + ds := nilspace ; + send (order task, ack, ds) . + +family password cmd : + msg := ds ; + actual password := new task password ; + supply password := task password (index (order task)) ; + change pw of all sons where necessary (son (order task)) ; + task password (index (order task)) := actual password ; + forget (ds) ; + ds := nilspace ; + send (order task, ack, ds) . + +set autonom cmd : + autonom flag (index (order task)) := TRUE ; + send (order task, ack, ds) . + +reset autonom cmd : + autonom flag (index (order task)) := FALSE ; + send (order task, ack, ds) . + +define new canal : + IF order task < myself AND + channel index > 0 AND channel index <= highest terminal channel CAND + is niltask (canal (channel index)) + THEN canal (channel index) := order task ; + connected task (channel index) := niltask ; + send (order task, ack, ds) + ELSE errorstop ("falscher Auftrag fuer Task ""SUPERVISOR""") + FI . + +go back to old canal : + IF order task < myself AND + channel index > 0 AND channel index <= highest terminal channel + THEN IF NOT is niltask (canal (channel index)) + THEN delete task (canal (channel index)) + FI ; + send (order task, ack, ds) + ELSE errorstop ("falscher Auftrag fuer Task ""SUPERVISOR""") + FI . + +task of channel : + msg := ds ; + channel nr := int (msg.tname) ; + msg.task := channel task ; + send (order task, ack, ds). + +channel task : + IF channel nr <= highest terminal channel + THEN IF no command analyzer active + THEN connected task (channel nr) + ELSE canal (channel nr) + FI + ELSE connected task (channel nr) + FI . + +no command analyzer active : + channel (canal (channel nr)) = nilchannel . + +canal of channel : + msg := ds ; + channel nr := int (msg.tname) ; + msg.task := canal (channel nr) ; + send (order task, ack, ds). + +set automatic startup cmd : + automatic startup flag (index (order task)) := TRUE ; + send (order task, ack, ds) . + +reset automatic startup cmd : + automatic startup flag (index (order task)) := FALSE ; + send (order task, ack, ds) . + +is continue : + order code > continue code low AND order code <= continue code high . + +new task name : CONCR (msg).tname . + +new task : CONCR (msg).task . + +new task password : subtext (CONCR (msg).tpass, 1, 100) . + +new start proc : CONCR (msg).start proc . + +is define station : + order code >= define station code AND order task < myself AND + order code <= define station code + max station no . + +ENDPROC order from user task ; + +PROC continue cmd by canal : + + access task name and password ; + check password if necessary ; + continue or send continue request ; + channel (order task, nilchannel) . + +access task name and password : + msg := ds ; + TASK CONST user task := task (CONCR (msg).tname) ; + INT CONST task index := index (user task) ; + actual password := task password (task index) ; + supply password := CONCR (msg).tpass . + +check password if necessary : + IF actual password <> "" + THEN IF supply password = "" + THEN ask for password ; + LEAVE continue cmd by canal + ELIF actual password <> supply password OR actual password = "-" + THEN errorstop ("Passwort falsch") + FI + FI . +ask for password : + send (order task, password code, ds) . + +continue or send continue request : + IF autonom flag (task index) + THEN send continue request to user task + ELSE continue (user task, order code - continue code low) + FI . + +send continue request to user task : + INT VAR request count , quit ; + FOR request count FROM 1 UPTO 10 REP + send (user task, order code, ds, quit) ; + IF quit = ack + THEN LEAVE send continue request to user task + FI ; + pause (3) + PER ; + errorstop ("Task antwortet nicht") . + +ENDPROC continue cmd by canal ; + +PROC continue (TASK CONST id, INT CONST channel nr) : + + IF NOT is niltask (id) CAND channel (id) <> channel nr + THEN check whether not linked to another channel ; + channel (id, channel nr) ; + connected task (channel nr) := id ; + prio (id, 0) ; + activate (id) + FI . + +check whether not linked to another channel : + INT VAR i ; + FOR i FROM 1 UPTO number of channels REP + IF connected task (i) = id + THEN errorstop ("bereits an Kanal " + text (i) ) ; + LEAVE continue + FI + PER . + +ENDPROC continue ; + +PROC task info cmd : + + forget (ds) ; + ds := sys cat ; + send (order task, ack, ds) . + +ENDPROC task info cmd ; + +PROC delete task (TASK CONST superfluous) : + + delete all sons of superfluous ; + delete superfluous itself . + +delete superfluous itself : + update cpu time of father ; + erase process (superfluous) ; + delete (superfluous) ; + erase terminal connection remark . + +update cpu time of father : + TASK CONST father task := father (superfluous) ; + IF NOT is niltask (father task) + THEN disable stop ; + REAL CONST father time := clock (father task) + clock (superfluous); + IF is error + THEN clear error + ELSE set clock (father task, father time) + FI ; + enable stop + FI . + +erase terminal connection remark : + INT VAR i ; + FOR i FROM 1 UPTO number of channels REP + IF connected task (i) = superfluous + THEN connected task (i) := niltask ; + LEAVE erase terminal connection remark + FI + PER ; + FOR i FROM 1 UPTO highest terminal channel REP + IF canal (i) = superfluous + THEN canal (i) := niltask ; + LEAVE erase terminal connection remark + FI + PER . + +delete all sons of superfluous : + TASK VAR son task ; + REP + son task := son (superfluous) ; + IF is niltask (son task) + THEN LEAVE delete all sons of superfluous + FI ; + delete task (son task) + PER . + +ENDPROC delete task ; + +PROC create son (TASK CONST father, TEXT CONST task name, TASK VAR new task, PROCA CONST start) : + + entry (father, task name, new task) ; + autonom flag (index (new task)) := FALSE ; + automatic startup flag (index (new task)) := TRUE ; + task password (index (new task)) := "" ; + create (father, new task, privilege, start) . + +privilege : + IF new task < myself + THEN 1 + ELSE 0 + FI . + +ENDPROC create son ; + + +PROC system start interrupt : + + IF exists task ("configurator") + THEN send system start message + FI . + +send system start message : + ds := nilspace ; + INT VAR request count, quit ; + FOR request count FROM 1 UPTO 10 REP + send (task ("configurator"), system start code, ds, quit) ; + IF quit = ack + THEN LEAVE send system start message + FI ; + pause (3) + PER ; + forget (ds) . + +ENDPROC system start interrupt ; + +PROC define new station : + + INT CONST station := order code - define station code ; + INT VAR i ; + FOR i FROM 1 UPTO highest terminal channel REP + IF NOT is niltask (canal (i)) + THEN delete task (canal (i)) + FI + PER ; + define station (station) ; + FOR i FROM 1 UPTO number of channels REP + update (connected task (i)) + PER ; + forget (ds) . + +ENDPROC define new station ; + +PROC change pw of all sons where necessary (TASK CONST first son) : + + TASK VAR actual task := first son ; + WHILE NOT is niltask (actual task) REP + change pw ; + change pw of all sons where necessary (son (actual task)); + actual task := brother (actual task) + PER. + + change pw : + IF task password (index (actual task)) = supply password + OR + task password (index (actual task)) = "" + THEN task password (index (actual task)) := actual password + FI. + +END PROC change pw of all sons where necessary ; + +(******************* basic supervisor operations **********************) + + +PROC channel (TASK CONST id, INT CONST channel nr) : + pcb (id, channel field, channel nr) +ENDPROC channel ; + +INT PROC channel type (INT CONST channel nr) : + disable stop ; + channel (myself, channel nr) ; + INT VAR type ; + control (1, 0, 0, type) ; + channel (myself, nilchannel) ; + type +ENDPROC channel type ; + +PROC erase last bootstrap source dataspace : + + disable stop ; + errorstop ("") ; + clear error + +ENDPROC erase last bootstrap source dataspace ; + +PROC set clock (TASK CONST id, REAL CONST clock value) : + EXTERNAL 82 +ENDPROC set clock ; + +PROC sys op (INT CONST code) : + EXTERNAL 90 +END PROC sys op ; + +PROC create (TASK CONST father, son, INT CONST priv, PROCA CONST start) : + EXTERNAL 95 +ENDPROC create ; + +PROC pcb (TASK CONST id, INT CONST field, value) : + EXTERNAL 105 +ENDPROC pcb ; + +PROC activate (TASK CONST id) : + EXTERNAL 108 +ENDPROC activate ; + +PROC deactivate (TASK CONST id) : + EXTERNAL 109 +ENDPROC deactivate ; + +PROC halt process (TASK CONST id) : + EXTERNAL 110 +ENDPROC halt process ; + +PROC erase process (TASK CONST id) : + EXTERNAL 112 +ENDPROC erase process ; + +ENDPACKET supervisor ; + diff --git a/system/multiuser/1.7.5/src/sysgen off b/system/multiuser/1.7.5/src/sysgen off new file mode 100644 index 0000000..9cb999b --- /dev/null +++ b/system/multiuser/1.7.5/src/sysgen off @@ -0,0 +1,9 @@ +ke ; (* maintenance ke *) + +PROC sysgen off (INT CONST mode, INT VAR a,b,c,d,e,f,g,h,i,j,k) : + EXTERNAL 256 +ENDPROC sysgen off ; + +INT VAR x := 0 ; +sysgen off (3,x,x,x,x,x,x,x,x,x,x,x) ; + diff --git a/system/multiuser/1.7.5/src/system info b/system/multiuser/1.7.5/src/system info new file mode 100644 index 0000000..c29dfc2 --- /dev/null +++ b/system/multiuser/1.7.5/src/system info @@ -0,0 +1,342 @@ + +PACKET system info DEFINES (* Autor: J.Liedtke *) + (* Stand: 10.09.84 *) + task info , + task status , + storage info , + help : + + +LET supervisor mode = 0 , + simple mode = 1 , + status mode = 2 , + storage mode = 3 , + + ack = 0 , + + channel field = 4 , + prio field = 6 , + + cr lf = ""13""10"" , + cr = ""13"" , + page = ""1""4"" , + begin mark= ""15"" , + end mark = ""14"" , + bell = ""7"" , + esc = ""27"" ; + + + +TEXT VAR task name , record ; +DATASPACE VAR ds := nilspace ; + + +PROC task info : + + task info (simple mode) + +ENDPROC task info ; + +PROC task info (INT CONST mode) : + + open list file ; + task info (mode, list file) ; + show task info . + +open list file : + forget (ds) ; + ds := nilspace ; + FILE VAR list file := sequential file (output, ds) . + +show task info : + IF mode <> supervisor mode + THEN show (list file) + ELSE open editor (list file, FALSE) ; + edit (groesster editor, "q", PROC (TEXT CONST) no orders) + FI . + +ENDPROC task info ; + +PROC task info (INT CONST mode, FILE VAR list file) : + + access catalogue ; + IF mode > simple mode + THEN generate head + FI ; + list tree (list file, supervisor,0, mode) . + +generate head : + put (list file, date) ; + put (list file, " ") ; + put (list file, time of day) ; + put (list file, " ") ; + IF mode = storage mode + THEN put (list file, "K ") + FI ; + put (list file, " CPU PRIO CHAN STATUS") ; + line (list file) . + +ENDPROC task info ; + +PROC task info (INT CONST level, fremdstation): + IF fremdstation = station (myself) + THEN task info (level) + ELSE + disable stop; + DATASPACE VAR x:= nilspace; + BOUND INT VAR l := x; l := level; + call (collector, 256+fremdstation, x, rtn); + INT VAR rtn; + IF rtn = ack + THEN FILE VAR ti:= sequential file (modify, x) ; + show (ti) + ELSE forget (x) ; + errorstop ("Station " + text (fremdstation) + " antwortet nicht") + FI ; + forget (x) + FI +END PROC task info; + +PROC no orders (TEXT CONST ed kommando taste) : + + IF ed kommando taste = "q" + THEN quit + ELSE out (""7"") + FI + +ENDPROC no orders ; + +PROC list tree (FILE VAR list file, + TASK CONST first son, INT CONST depth, mode) : + + enable stop ; + TASK VAR actual task := first son ; + WHILE NOT is niltask (actual task) REP + list actual task ; + list tree (list file, son (actual task), depth+1, mode) ; + actual task := brother (actual task) + PER . + +list actual task : + record := "" ; + generate layout and task name ; + IF mode > simple mode + THEN tab to info position ; + show storage if wanted ; + record CAT cpu time of (actual task) ; + record CAT prio of actual task ; + record CAT channel of actual task ; + record CAT " " ; + record CAT status of (actual task) + FI ; + putline (list file, record) . + +generate layout and task name : + INT VAR i ; + FOR i FROM 1 UPTO depth REP + record CAT " " + PER ; + task name := name (actual task) ; + record CAT task name . + +tab to info position : + record := subtext (record, 1, 40) ; + FOR i FROM LENGTH record + 1 UPTO 40 REP + record CAT "." + PER ; + record CAT " " . + +show storage if wanted : + IF mode = storage mode + THEN record CAT text (storage (actual task), 5) ; + record CAT " " + FI . + +prio of actual task : + text (pcb (actual task, prio field),4) . + +channel of actual task : + INT CONST channel := pcb (actual task, channel field) ; + IF channel = 0 + THEN " -" + ELSE text (channel,4) + FI . + +ENDPROC list tree ; + +TEXT PROC cpu time of (TASK CONST actual task) : + + disable stop ; + TEXT VAR result := subtext (time (clock (actual task), 12), 1, 10) ; + IF is error + THEN clear error ; + result := 10 * "*" + FI ; + result + +ENDPROC cpu time of ; + +TEXT PROC status of (TASK CONST actual task) : + + SELECT status (actual task) OF + CASE 0 : "-busy-" + CASE 1 : "i/o" + CASE 2 : "wait" + CASE 4 : "busy-blocked" + CASE 5 : "i/o -blocked" + CASE 6 : "wait-blocked" + OTHERWISE "--dead--" + END SELECT . + +ENDPROC status of ; + +PROC task status : + + task status (myself) + +ENDPROC task status ; + +PROC task status (TEXT CONST task name) : + + task status (task (task name)) + +ENDPROC task status ; + +PROC task status (TASK CONST actual task) : + + IF exists (actual task) + THEN put status of task + ELSE errorstop ("Task nicht vorhanden") + FI . + +put status of task : + line ; + put (date); put (time of day) ; + put (" TASK:") ; + put (name (actual task)) ; + line (2) ; + put ("Speicher:"); put (storage (actual task)); putline ("K"); + put ("CPU-Zeit:"); put (cpu time of (actual task)) ; line; + put ("Zustand :"); write (status of (actual task)); + put (", (prio"); + write (text (pcb (actual task, prio field))); + put ("), Kanal") ; + IF channel (actual task) = 0 + THEN put ("-") + ELSE put (channel (actual task)) + FI ; + line . + +ENDPROC task status ; + +PROC storage info : + + INT VAR size, used ; + storage (size, used) ; + out (""13""10" ") ; + put (used) ; + put ("K von") ; + put (size plus reserve) ; + putline ("K sind belegt!") . + +size plus reserve : + int (real (size + 24) * 64.0 / 63.0 ) . + +ENDPROC storage info ; + + +PROC help : + + IF NOT exists ("help") + THEN get help file + FI ; + FILE VAR f := sequential file (modify, "help") ; + help (f) . + +get help file : + TEXT VAR old std param := std ; + IF exists ("help", father) + THEN fetch ("help") + ELSE fetch ("help", public) + FI ; + last param (old std param) . + +ENDPROC help ; + +PROC help (FILE VAR help file) : + + initialize help command ; + REP + out (page) ; + to paragraph ; + show paragraph ; + get show command + UNTIL is quit command PER . + +initialize help command : + TEXT VAR + help command := getcharety ; + IF help command = "" + THEN help command := "0" + FI . + +to paragraph : + col (help file, 1) ; + to line (help file, 1) ; + downety (help file, "#" + help command + "#") ; + IF eof (help file) + THEN to line (help file, 1) ; + out (bell) + FI . + +show paragraph : + show headline ; + WHILE NOT end of help subfile REP + show help line + PER ; + show bottom line . + +show headline : + out (begin mark) ; + INT CONST dots := (x size - len (help file) - 5) DIV 2 ; + dots TIMESOUT "." ; + exec (PROC show line, help file, 4) ; + dots TIMESOUT "." ; + out (end mark) ; + down (help file) . + +show help line : + out (cr lf) ; + exec (PROC show line, help file, 1) ; + down (help file) . + +show bottom line : + cursor (5, y size) ; + exec (PROC show line, help file, 3) ; + out (cr) . + +get show command : + TEXT VAR char ; + get char (char) ; + IF char = esc + THEN get char (char) + FI ; + IF char >= " " + THEN help command := char + ELSE out (bell) + FI . + +end of help subfile : pos (help file,"##",1) <> 0 OR eof (help file) . + +is quit command : help command = "q" OR help command = "Q" . + +ENDPROC help ; + +PROC show line (TEXT CONST line, INT CONST from) : + + outsubtext (line, from, x size - from) + +ENDPROC show line ; + +ENDPACKET system info ; + diff --git a/system/multiuser/1.7.5/src/system manager b/system/multiuser/1.7.5/src/system manager new file mode 100644 index 0000000..5406ff0 --- /dev/null +++ b/system/multiuser/1.7.5/src/system manager @@ -0,0 +1,117 @@ +(* ------------------- VERSION 4 vom 31.01.86 ------------------- *) +PACKET system manager DEFINES (* F. Klapper *) + system manager , + generate shutup manager , + put log : + +LET ack = 0 , + error nak = 2 , + fetch code = 11 , + list code = 15 , + all code = 17 , + log code = 21 , + eszet = ""251"" , + log file name = "logbuch"; + +DATASPACE VAR ds; + +BOUND STRUCT (TEXT name, write pass, read pass) VAR msg ; +BOUND TEXT VAR log message, + error msg; + +INT VAR reply; + +TEXT VAR xname; + +FILE VAR log file; + +PROC system manager: + lernsequenz auf taste legen ("s", eszet) ; + global manager + (PROC (DATASPACE VAR, INT CONST, INT CONST, TASK CONST) sys manager) + +END PROC system manager; + +PROC sys manager (DATASPACE VAR ds, INT CONST order, phase, + TASK CONST order task): + enable stop; + SELECT order OF + CASE log code : y put log + CASE list code : y list + CASE all code : y all + CASE fetch code : y fetch + OTHERWISE std manager (ds, order, phase, order task) + END SELECT. + +y fetch : + msg := ds; + xname := msg.name; + IF read permission (xname, msg.read pass) + THEN forget (ds) ; + ds := old (xname) ; + send (order task, ack, ds) + ELSE errorstop ("Passwort falsch") + FI . + +y list : + forget (ds) ; + ds := nilspace ; + FILE VAR list file := sequential file (output, ds) ; + list (list file) ; + send (order task, ack, ds) . + +y all : + forget (ds); + ds := nilspace; + BOUND THESAURUS VAR all names := ds ; + all names := all ; + send (order task, ack, ds) . + +y put log : + log file := sequential file (output, log file name) ; + IF lines (log file) < 4000 + THEN max line length (log file,1000); + put (log file, date) ; + put (log file, time of day) ; + put (log file, text (name (order task), 8)); + log message := ds ; + put (log file, CONCR (log message)) ; + FI ; + send (order task, ack, ds) . + +END PROC sys manager; + +PROC put log (TEXT CONST message) : + enable stop; + forget (ds) ; + ds := nilspace ; + log message := ds ; + CONCR (log message) := message ; + call (task("SYSUR"), log code, ds, reply) . + +ENDPROC put log ; + +PROC generate shutup manager : + + TASK VAR son ; + begin ("shutup", PROC shutup manager, son) + +ENDPROC generate shutup manager ; + +PROC shutup manager : + disable stop ; + task password ("") ; + command dialogue (TRUE) ; + REP + break ; + line ; + IF yes ("shutup") + THEN clear error ; + shutup + FI + PER + +ENDPROC shutup manager ; + +ENDPACKET system manager ; + diff --git a/system/multiuser/1.7.5/src/tasks b/system/multiuser/1.7.5/src/tasks new file mode 100644 index 0000000..276011e --- /dev/null +++ b/system/multiuser/1.7.5/src/tasks @@ -0,0 +1,978 @@ +(* ------------------- VERSION 9 vom 09.06.86 ------------------- *) +PACKET tasks DEFINES (* Autor: J.Liedtke *) + + TASK , + PROCA , + := , + = , + < , + / , + niltask , + is niltask , + exists , + exists task , + supervisor , + myself , + public , + proca , + collector , + access , + name , + task , + canal , + dataspaces , + index , + station , + update , + father , + son , + brother , + next active , + access catalogue , + family password , + task in catalogue , + entry , + delete , + define station , + + pcb , + status , + channel , + clock , + storage , + callee , + + send , + wait , + call , + pingpong , + collected destination , + + begin , + end , + break , + continue , + rename myself , + task password , + set autonom , + reset autonom , + set automatic startup , + reset automatic startup , + + sys cat : + + + +LET nil = 0 , + + max version = 30000 , + max task = 125 , + max station no = 127 , + sv no = 1 , + + hex ff = 255 , + hex 7f00 = 32512 , + + collected dest field 1 = 2 , + collected dest field 2 = 3 , + channel field = 4 , + myself no field = 9 , + myself version field = 10 , + callee no field = 11 , + callee version field = 12 , + + highest terminal channel = 16 , + number of channels = 32 , + + wait state = 2 , + + ack = 0 , + nak = 1 , + error nak = 2 , + system catalogue code = 3 , + begin code = 4 , + end code = 5 , + break code = 6 , + rename code = 7 , + password code = 9 , + family password code = 40 , + set autonom code = 41 , + reset autonom code = 42 , + task of channel code = 45 , + canal of channel code = 46 , + set automatic startup code = 47 , + reset automatic startup code = 48 , + + continue code = 100, + define station code = 32000, + + lowest ds number = 4 , + highest ds number = 255 ; + + +TYPE TASK = STRUCT (INT no, version) , + PROCA = STRUCT (INT a, b) ; + +OP := (PROCA VAR right, PROCA CONST left) : + CONCR (right) := CONCR (left) +ENDOP := ; + +PROCA PROC proca (PROC p) : + + push (0, PROC p) ; + pop + +ENDPROC proca ; + +PROC push (INT CONST dummy, PROC p) : ENDPROC push ; + +PROCA PROC pop : + PROCA VAR res; + res +ENDPROC pop ; + +TASK CONST niltask := TASK: (0,0) , + collector := TASK: (-1,0) ; + +TASK PROC supervisor : + + TASK: (my station id + sv no, 0) . + +my station id : pcb (myself no field) AND hex 7f00 . + +ENDPROC supervisor ; + +TASK VAR father task ; + +INITFLAG VAR catalogue known := FALSE , father known := FALSE ; + + + +LET TASKVECTOR = STRUCT (INT version, father, son, brother) ; + + +DATASPACE VAR catalogue space , sv space ; + +BOUND STRUCT (THESAURUS dir, + ROW max task TASKVECTOR link) VAR system catalogue ; + initialize catalogue ; + +BOUND STRUCT (TEXT tname, tpass, TASK task, PROCA start proc) VAR sv msg ; + + +PROC initialize catalogue : + + catalogue space := nilspace ; + system catalogue := catalogue space ; + system catalogue.dir := empty thesaurus ; + + insert (system catalogue.dir, "SUPERVISOR") ; + insert (system catalogue.dir, "UR") ; + system catalogue.link (1) := TASKVECTOR:(0,0,0,2) ; + system catalogue.link (2) := TASKVECTOR:(0,0,0,0) . + +ENDPROC initialize catalogue ; + +DATASPACE PROC sys cat : + catalogue space +ENDPROC sys cat ; + + +TASK PROC myself : + + TASK: (pcb (myself no field), pcb (myself version field)) + +ENDPROC myself ; + + +OP := (TASK VAR dest, TASK CONST source): + + CONCR (dest) := CONCR (source) + +ENDOP := ; + +BOOL OP = (TASK CONST left, right) : + + left.no = right.no AND left.version = right.version + +ENDOP = ; + +BOOL PROC is niltask (TASK CONST t) : + + t.no = 0 + +ENDPROC is niltask ; + +BOOL OP < (TASK CONST left, right) : + + IF both of my station + THEN access (left) ; + access (right) ; + ( index (left) > 0 CAND index (left) <= max task ) + CAND + ( father (left) = right COR father (left) < right ) + ELSE FALSE + FI . + +both of my station : + station (left) = station (right) AND station (right) = station (myself) . + +ENDOP < ; + +BOOL PROC exists (TASK CONST task) : + + EXTERNAL 123 + +ENDPROC exists ; + +BOOL PROC exists task (TEXT CONST name) : + + task id (name).no <> 0 + +ENDPROC exists task ; + +TEXT PROC name (TASK CONST task) : + + IF is task of other station + THEN external name (task) + ELSE + access (task) ; + INT CONST task no := index (task) ; + IF task in catalogue (task ,task no) + THEN name (system catalogue.dir, task no) + ELSE "" + FI + FI. + +is task of other station : + (task.no AND hex 7f00) <> (pcb (myself no field) AND hex 7f00) . + +ENDPROC name ; + +BOOL PROC task in catalogue (TASK CONST task, INT CONST task no) : + + access catalogue ; + task no >= 1 CAND task no <= max task CAND + task.version = system catalogue.link (task no).version . + +ENDPROC task in catalogue ; + +PROC access (TASK CONST task) : + + INT CONST task no := task.no AND hex ff ; + IF task no < 1 OR task no > max task + THEN + ELIF is task of other station + THEN errorstop ("TASK anderer Station") + ELIF actual task id not in catalogue COR NOT exists (task) + THEN access catalogue + FI . + +actual task id not in catalogue : + NOT initialized (catalogue known) COR + ( task no > 0 CAND catalogue version <> task.version ) . + +catalogue version : system catalogue.link (task no).version . + +is task of other station : + (task.no AND hex 7f00) <> (pcb (myself no field) AND hex 7f00) . + +ENDPROC access ; + +TASK PROC task (TEXT CONST task name) : + + TASK CONST id := task id (task name) ; + IF id.no = 0 + THEN errorstop (""""+task name+""" gibt es nicht") + FI ; + id + +ENDPROC task ; + +TASK PROC task id (TEXT CONST task name) : + + IF task name = "-" OR task name = "" + THEN errorstop ("Taskname unzulaessig") + FI ; + IF NOT initialized (catalogue known) + THEN access catalogue + FI ; + + TASK VAR + id := task id (link (system catalogue.dir, task name)) ; + IF NOT exists (id) + THEN access catalogue ; + id := task id (link (system catalogue.dir, task name)) ; + FI ; + id . + +ENDPROC task id ; + +TASK OP / (TEXT CONST task name) : + + task (task name) + +ENDOP / ; + +INT PROC index (TASK CONST task) : + + IF NOT initialized (catalogue known) + THEN access catalogue + FI ; + task.no AND hex ff + +ENDPROC index ; + +INT PROC station (TASK CONST task) : + + task.no DIV 256 + +ENDPROC station ; + +PROC update (TASK VAR task) : + + IF task.no <> nil + THEN task.no := (task.no AND hex ff) + new station number + FI . + +new station number : (pcb (myself no field) AND hex 7f00) . + +ENDPROC update ; + + +TASK PROC public : + + task ("PUBLIC") + +ENDPROC public ; + +TASK PROC father : + + IF NOT initialized (father known) COR station or rename changed father id + THEN access catalogue ; + father task := father (myself) + FI ; + father task . + +station or rename changed father id : + NOT exists (father task) . + +ENDPROC father ; + +INT VAR task no ; + +TASK PROC father (TASK CONST task) : + + task no := index (task) ; + task id (system catalogue.link (task no).father) . + +ENDPROC father ; + +TASK PROC son (TASK CONST task) : + + task no := index (task) ; + IF task no = nil + THEN supervisor + ELSE task id (system catalogue.link (task no).son) + FI . + +ENDPROC son ; + +TASK PROC brother (TASK CONST task) : + + task no := index (task) ; + task id (system catalogue.link (task no).brother) . + +ENDPROC brother ; + +PROC next active (TASK VAR task) : + + next active task index (task.no) ; + IF task.no > 0 + THEN task.version := pcb (task, myself version field) + ELSE task.version := 0 + FI + +ENDPROC next active ; + +PROC next active task index (INT CONST no) : + + EXTERNAL 118 + +ENDPROC next active task index ; + +TASK PROC task id (INT CONST task nr) : + + INT VAR task index := task nr AND hex ff ; + TASK VAR result ; + result.no := task index ; + IF task index = nil + THEN result.version := 0 + ELSE result.version := system catalogue.link (task index).version ; + result.no INCR my station id + FI ; + result . + +my station id : pcb (myself no field) AND hex 7f00 . + +ENDPROC task id ; + +PROC access catalogue : + + IF this is not supervisor + THEN get catalogue from supervisor + FI . + +this is not supervisor : + (pcb (myself no field) AND hex ff) <> sv no . + +get catalogue from supervisor : + INT VAR dummy reply ; + forget (catalogue space) ; + catalogue space := nilspace ; + call (supervisor, system catalogue code, catalogue space, dummy reply) ; + system catalogue := catalogue space . + +ENDPROC access catalogue ; + + +PROC entry (TASK CONST father task, TEXT CONST task name, + TASK VAR son task) : + + IF task name <> "-" CAND (system catalogue.dir CONTAINS task name) + THEN errorstop (""""+task name+""" existiert bereits") + ELIF is niltask (father task) + THEN errorstop ("Vatertask existiert nicht") + ELSE entry task + FI . + +entry task : + INT VAR son task nr ; + INT CONST father task nr := index (father task) ; + insert (system catalogue.dir, task name, son task nr) ; + IF son task nr = nil OR son task nr > max task + THEN delete (system catalogue.dir, son task nr) ; + son task := niltask ; + errorstop ("zu viele Tasks") + ELSE insert task (father task, father vec, son task, son vec, son tasknr) + FI . + +father vec : system catalogue.link (father task nr) . + +son vec : system catalogue.link (son task nr) . + +ENDPROC entry ; + +PROC insert task (TASK CONST father task, TASKVECTOR VAR father vec, + TASK VAR son task, TASKVECTOR VAR son vec, INT CONST nr) : + + initialize version number if son vec is first time used ; + increment version (son vec) ; + son task.no := my station id + nr ; + son task.version := son vec.version ; + link into task tree . + +initialize version number if son vec is first time used : + IF son vec.version < 0 + THEN son vec.version := 0 + FI . + +link into task tree : + son vec.son := nil ; + son vec.brother := father vec.son ; + son vec.father := index (father task) ; + father vec.son := son task.no . + +my station id : pcb (myself no field) AND hex 7f00 . + +END PROC insert task ; + + +PROC delete (TASK CONST superfluous) : + + INT CONST superfluous nr := index (superfluous) ; + delete (system catalogue.dir, superfluous nr) ; + delete superfluous task ; + increment version (superfluous vec) . + +delete superfluous task : + INT CONST successor of superfluous := superfluous vec.brother ; + TASK VAR + last := father (superfluous) , + actual := son (last) ; + IF actual = superfluous + THEN delete first son of last + ELSE search previous brother of superfluous ; + delete from brother chain + FI . + +delete first son of last : + last vec.son := successor of superfluous . + +search previous brother of superfluous : + REP + last := actual ; + actual := brother (actual) + UNTIL actual = superfluous PER . + +delete from brother chain : + last vec.brother := successor of superfluous . + +last vec : system catalogue.link (index (last)) . + +superfluous vec : system catalogue.link (superfluous nr) . + +ENDPROC delete ; + + +PROC name (TASK VAR task, TEXT CONST new name) : + + INT CONST task no := index (task) ; + IF (system catalogue.dir CONTAINS new name) AND (new name <> "-") + AND (name (task) <> new name) + THEN errorstop (""""+new name+""" existiert bereits") + ELSE rename (system catalogue.dir, task no, new name) ; + increment version (system catalogue.link (task no)) ; + IF this is supervisor + THEN update task version in pcb and task variable + FI + FI . + +this is supervisor : (pcb (myself no field) AND hex ff) = sv no . + +update task version in pcb and task variable : + INT CONST new version := system catalogue.link (task no).version ; + write pcb (task, myself version field, new version) ; + task.version := new version . + +ENDPROC name ; + + +PROC increment version (TASKVECTOR VAR task vec) : + + task vec.version := task vec.version MOD max version + 1 + +ENDPROC increment version ; + + +INT PROC pcb (TASK CONST id, INT CONST field) : + + EXTERNAL 104 + +ENDPROC pcb ; + +INT PROC status (TASK CONST id) : + + EXTERNAL 107 + +ENDPROC status ; + +INT PROC channel (TASK CONST id) : + + pcb (id, channel field) + +ENDPROC channel ; + +REAL PROC clock (TASK CONST id) : + + EXTERNAL 106 + +ENDPROC clock ; + +INT PROC storage (TASK CONST id) : + + INT VAR ds number, storage sum := 0, ds size; + FOR ds number FROM lowest ds number UPTO highest ds number REP + ds size := pages (ds number, id) ; + IF ds size > 0 + THEN storage sum INCR ((ds size + 1) DIV 2) + FI + PER ; + storage sum + +ENDPROC storage ; + +INT PROC pages (INT CONST ds number, TASK CONST id) : + + EXTERNAL 88 + +ENDPROC pages ; + +TASK PROC callee (TASK CONST from) : + + IF status (from) = wait state + THEN TASK:(pcb (from, callee no field), pcb (from, callee version field)) + ELSE niltask + FI + +ENDPROC callee ; + + +PROC send (TASK CONST dest, INT CONST send code, DATASPACE VAR ds, + INT VAR quit) : + EXTERNAL 113 + +ENDPROC send ; + +PROC send (TASK CONST dest, INT CONST send code, DATASPACE VAR ds) : + + INT VAR dummy quit ; + send (dest, send code, ds, dummy quit) ; + forget (ds) + +ENDPROC send ; + +PROC wait (DATASPACE VAR ds, INT VAR receive code, TASK VAR source) : + + EXTERNAL 114 + +ENDPROC wait ; + +PROC call (TASK CONST dest, INT CONST order code, DATASPACE VAR ds, + INT VAR reply code) : + EXTERNAL 115 + +ENDPROC call ; + +PROC pingpong (TASK CONST dest, INT CONST order code, DATASPACE VAR ds, + INT VAR reply code) : + EXTERNAL 122 + +ENDPROC pingpong ; + +TASK PROC collected destination : + + TASK: (pcb (collected dest field 1), pcb (collected dest field 2)) + +ENDPROC collected destination ; + + +PROC begin (PROC start, TASK VAR new task) : + + begin ("-", PROC start, new task) + +ENDPROC begin ; + +PROC begin (TEXT CONST son name, PROC start, TASK VAR new task) : + + enable stop ; + forget (sv space) ; + sv space := nilspace ; + sv msg := sv space ; + CONCR (sv msg).tname := son name ; + CONCR (sv msg).start proc := proca (PROC start) ; + supervisor call (begin code) ; + sv msg := sv space ; + new task := CONCR (sv msg).task . + +ENDPROC begin ; + +PROC begin (DATASPACE VAR ds, PROC start, INT VAR reply) : + + sv msg := ds ; + sv msg.start proc := proca (PROC start) ; + call (supervisor, begin code, ds, reply) + +ENDPROC begin ; + +PROC end : + + command dialogue (TRUE) ; + say ("task """) ; + say (name (myself)) ; + IF yes (""" loeschen") + THEN eumel must advertise ; + end (myself) + FI + +ENDPROC end ; + +PROC end (TASK CONST id) : + + forget (sv space) ; + sv space := nilspace ; + sv msg := sv space ; + CONCR (sv msg).task := id ; + supervisor call (end code) + +ENDPROC end ; + +PROC break (QUIET CONST quiet) : + + simple supervisor call (break code) + +ENDPROC break ; + +PROC break : + + eumel must advertise ; + simple supervisor call (break code) + +ENDPROC break ; + +PROC continue (INT CONST channel nr) : + + simple supervisor call (continue code + channel nr) + +ENDPROC continue ; + +PROC rename myself (TEXT CONST new name) : + + forget (sv space) ; + sv space := nilspace ; + sv msg := sv space ; + CONCR (sv msg).tname := new name ; + supervisor call (rename code) . + +ENDPROC rename myself ; + + +PROC simple supervisor call (INT CONST code) : + + forget (sv space) ; + sv space := nilspace ; + supervisor call (code) + +ENDPROC simple supervisor call ; + +PROC supervisor call (INT CONST code) : + + INT VAR answer ; + call (supervisor, code, sv space, answer) ; + WHILE answer = nak REP + pause (20) ; + call (supervisor, code, sv space, answer) + PER ; + IF answer = error nak + THEN BOUND TEXT VAR error message := sv space ; + errorstop (CONCR (error message)) + FI + +ENDPROC supervisor call ; + +PROC task password (TEXT CONST password) : + + IF online + THEN say (""3""5""10"") + FI ; + forget (sv space) ; + sv space := nilspace ; + sv msg := sv space ; + CONCR (sv msg).tpass := password ; + supervisor call (password code) ; + cover tracks . + +ENDPROC task password ; + +PROC set autonom : + + simple supervisor call (set autonom code) + +ENDPROC set autonom ; + +PROC reset autonom : + + simple supervisor call (reset autonom code) + +ENDPROC reset autonom ; + +PROC set automatic startup : + simple supervisor call (set automatic startup code) +ENDPROC set automatic startup ; + +PROC reset automatic startup : + simple supervisor call (reset automatic startup code) +ENDPROC reset automatic startup ; + +PROC define station (INT CONST station number) : + + IF this is supervisor + THEN update all tasks + ELIF i am privileged + THEN IF station number is valid + THEN send define station message + ELSE errorstop ("ungueltige Stationsnummer (0 - 127)") + FI + ELSE errorstop ("falscher Auftrag fuer Task ""SUPERVISOR""") + FI . + +update all tasks : + start at supervisor ; + REP + get next task ; + IF no more task found + THEN update station number of supervisor ; + LEAVE update all tasks + FI ; + update station number of actual task + PER . + +i am privileged : + myself < supervisor . + +station number is valid : + station number >= 0 AND station number <= max station no . + +start at supervisor : + TEXT VAR name ; + INT VAR index := sv no . + +get next task : + get (system catalogue.dir, name, index) . + +no more task found : index = 0 . + +update station number of actual task : + write pcb (task id (index), myself no field, station number * 256 + index). + +update station number of supervisor : + write pcb (supervisor, myself no field, station number * 256 + sv no) . + +send define station message : + forget (sv space) ; + sv space := nilspace ; + INT VAR receipt ; + REP + send (supervisor, define station code+station number, sv space, receipt) + UNTIL receipt = ack PER . + +this is supervisor : + (pcb (myself no field) AND hex ff) = sv no . + +ENDPROC define station ; + + +TASK OP / (INT CONST station number, TEXT CONST task name) : + + IF station number = station (myself) + THEN task (task name) + ELSE get task id from other station + FI . + +get task id from other station : + enable stop ; + forget (sv space) ; + sv space := nilspace ; + BOUND TEXT VAR name message := sv space ; + name message := task name ; + INT VAR reply ; + call (collector, station number, sv space, reply) ; + IF reply = ack + THEN BOUND TASK VAR result := sv space ; + CONCR (result) + ELIF reply = error nak + THEN name message := sv space; + disable stop; + errorstop (name message) ; + forget (sv space) ; + niltask + ELSE forget (sv space); + errorstop ("Collector-Task fehlt") ; + niltask + FI + +ENDOP / ; + + +TASK OP / (INT CONST station number, TASK CONST tsk): + + station number / name (tsk) + +END OP / ; + + +TEXT PROC external name (TASK CONST tsk): + + IF tsk = nil task + THEN + "" + ELIF tsk = collector + THEN + "** collector **" + ELSE + name via net + FI. + +name via net: + enable stop ; + forget (sv space); + sv space := nil space; + BOUND TASK VAR task message := sv space; + task message := tsk; + INT VAR reply; + call (collector, 256, sv space, reply); + BOUND TEXT VAR result := sv space; + CONCR (result). + +END PROC external name; + +PROC write pcb (TASK CONST task, INT CONST field, value) : + EXTERNAL 105 +ENDPROC write pcb ; + +TASK PROC task (INT CONST channel number) : + + IF channel number < 1 OR channel number > 32 + THEN errorstop ("ungueltige Kanalnummer") + FI ; + forget (sv space) ; + sv space := nilspace ; + sv msg := sv space ; + sv msg.tname := text (channel number) ; + supervisor call (task of channel code) ; + sv msg := sv space ; + sv msg.task + +END PROC task; + +TASK PROC canal (INT CONST channel number) : + + IF channel number < 1 OR channel number > highest terminal channel + THEN errorstop ("ungueltige Kanalnummer") + FI ; + forget (sv space); + sv space := nilspace ; + sv msg := sv space ; + sv msg.tname := text (channel number) ; + supervisor call (canal of channel code) ; + sv msg := sv space ; + sv msg.task + +END PROC canal ; + +PROC family password (TEXT CONST password) : + + IF online + THEN say (""3""5""10"") + FI ; + forget (sv space) ; + sv space := nilspace ; + sv msg := sv space ; + sv msg.tpass := password ; + supervisor call (family password code) ; + cover tracks . + +ENDPROC family password ; + +INT PROC dataspaces (TASK CONST task) : + + INT VAR ds number, spaces := 0 ; + FOR ds number FROM lowest ds number UPTO highest ds number REP + IF pages (ds number, index (task)) >= 0 + THEN spaces INCR 1 + FI + PER ; + spaces + +ENDPROC dataspaces ; + +INT PROC dataspaces : + dataspaces (myself) +ENDPROC dataspaces ; + +INT PROC pages (INT CONST ds number, INT CONST task no) : + EXTERNAL 88 +ENDPROC pages ; + +ENDPACKET tasks ; + diff --git a/system/multiuser/1.7.5/src/ur start b/system/multiuser/1.7.5/src/ur start new file mode 100644 index 0000000..efbf8c1 --- /dev/null +++ b/system/multiuser/1.7.5/src/ur start @@ -0,0 +1,40 @@ +(* ------------------- VERSION 2 06.03.86 ------------------- *) +PROC begin process (TASK CONST father, son, INT CONST priv, PROCA CONST start) : + EXTERNAL 95 +ENDPROC begin process ; + +PROC ur : + TASK VAR dummy ; + begin ("PUBLIC", PROC public manager, dummy) ; + global manager (PROC ur manager) +ENDPROC ur ; + +PROC public manager : + + page ; + REP UNTIL yes("Archiv 'help' eingelegt") PER; + archive ("help") ; + fetch ("help", archive) ; + release (archive) ; + free global manager + +ENDPROC public manager ; + +PROC ur manager (DATASPACE VAR ds, INT CONST order, phase, + TASK CONST order task) : + + LET begin code = 4 ; + enable stop ; + IF order = begin code + THEN std manager (ds, order, phase, order task) + ELSE errorstop ("falscher Auftrag fuer Task ""UR""") + FI + +ENDPROC ur manager ; + +check on ; +command dialogue (TRUE) ; +begin process (supervisor, task ("UR"), 0, proca (PROC ur)) ; +command dialogue (FALSE) ; +check off; + |