|
DataMuseum.dkPresents historical artifacts from the history of: RC4000/8000/9000 |
This is an automatic "excavation" of a thematic subset of
See our Wiki for more about RC4000/8000/9000 Excavated with: AutoArchaeologist - Free & Open Source Software. |
top - metrics - download
Length: 94464 (0x17100) Types: TextFile Names: »mcltxt «
└─⟦9ccaf6601⟧ Bits:30008165 Bånd med SW8000 kildetekst/release værktøjer └─⟦39138f30b⟧ └─⟦this⟧ »mcltxt «
begin <**************************************************************> <* MCL compiler source text for Terminal Access System *> <* *> <* Compiles MCL source text to cmcl format code *> <* Produce all code in core before writing it to file *> <* *> <* Henning Godske 870506 *> <* A/S Regnecentralen *> <* *> <* Compiler call: <result>=algol <source> connect.no *> <**************************************************************> <**************************************************************> <* Revision history *> <* *> <* 87.05.06 MCL compiler release 1.0 *> <**************************************************************> <*--------------------------------------*> <* Constans used global *> <*--------------------------------------*> integer max_var, <* Max. numbers of var's *> max_string, <* Max. numbers of chars. in text *> max_code, <* Max. code address *> keywords; <* Number of keywords *> array pn(1:2); <* Program name *> integer i; <* work *> <* Reserve 50 segments for algol to run in, *> <* use rest for code array *> max_code:=((system(2,i,pn)//512)-50)*512; keywords:=40; max_var:=25; max_string:=80; begin <*---------------------------*> <* Globale scanner variables *> <*---------------------------*> integer array newintable(0:255); integer item; integer last_item; integer token_type, line_number, token_number_val, token_string_length, token_number; boolean token_var_sub; long array item_val(0:200); integer array item_kind(0:200); long array token_text(1:200); long array symbol_text(1:keywords); integer array symbol_val(1:keywords); zone source_text(256,2,stderror); <*----------------------------*> <* Globale compiler variables *> <*----------------------------*> boolean list_source, <* list.yes *> show_warning, <* warning.yes *> show_test, <* test.yes *> show_code, <* code.yes *> use_note, <* note.yes *> make_code, <* Produce code *> make_cmcl, <* make result file *> warnings; integer array tail(1:10); real array cmcl_file,source_file(1:2); integer next_free, <* Next free address in code *> while_start, <* Current while block start *> att_start, <* Current att or inc block start *> s_line, <* Source line number *> ii; <* work *> real rr; <* work *> boolean in_attention, in_include; integer array field op; boolean array code(0:max_code); <* Code array with index in hw *> zone cmcl_code(256,2,stderror); <*------------------------------------------------*> <* Token constants used global. Set in init_scan *> <*------------------------------------------------*> integer t_end_file, t_case, t_otherwise, t_endselect, t_else, t_endif, t_point, t_text, t_endmenu, t_endwhile, t_endattention, t_endinclude, t_select, t_while, t_menu, t_attention, t_include, t_at, t_write, t_nl, t_erase, t_read, t_get, t_let, t_send, t_if, t_execute, t_note, t_direct, t_loop, t_exit, t_output, t_convert, t_echo, t_of, t_do, t_then, t_equal, t_not, t_on, t_off, t_int_start, t_int_end, t_unknown, t_number, t_string, t_errstring, t_var, t_and, t_or; procedure init_error(nr); <*----------------------------------------------------------------*> <* Write initial error and stop *> <*----------------------------------------------------------------*> integer nr; begin integer i; i:=1; write(out,<:***:>,string pn(increase(i))); if nr<1 or nr>7 then nr:=8; <* Max. init error number used + 1 *> write(out,<: :>,case nr of (<:No source file specified:>, <:Parameter:>, <:Source file not found:>, <:Process too small:>, <:Source file not a text file:>, <:Can't create result file:>, <:Can't use result file:>, <:Undefined error:>),<:<10>:>); make_code:=false; goto stop; end; procedure init_compiler; <*----------------------------------------------------------------*> <* Read FP parameters and init. global variables *> <*----------------------------------------------------------------*> begin real array ra(1:2); integer sy,i,j; trapmode:=1 shift 10; errorbits:=0; warnings:=false; list_source:=use_note:=false; show_warning:=make_cmcl:=true; show_code:=show_test:=false; zero_code; <* nulstil kode område *> make_code:=true; next_free:=while_start:=0; in_attention:=in_include:=false; if max_code<512 then init_error(4); if (system(4,1,ra) shift (-12))=6 then begin system(4,0,ra); make_cmcl:=true; for j:=1,2 do cmcl_file(j):=ra(j); i:=2; end else begin make_cmcl:=false; i:=1; end; if system(4,i,ra)<>(4 shift 12 + 10) then <* error in source specification *> init_error(1); for j:=1,2 do source_file(j):=ra(j); i:=i+1; sy:=system(4,i,ra); while sy<>0 do begin if ra(1) = real <:test:> then begin i:=i+1; if system(4,i,ra)<>(8 shift 12 + 10) then <* error in yes/no spec. *> init_error(2); if ra(1) = real <:yes:> then show_test:=true else begin if ra(1) = real <:no:> then show_test:=false else init_error(2); end; end; if ra(1) = real <:code:> then begin i:=i+1; if system(4,i,ra)<>(8 shift 12 + 10) then <* error in yes/no spec. *> init_error(2); if ra(1) = real <:yes:> then show_code:=true else begin if ra(1) = real <:no:> then show_code:=false else init_error(2); end; end; if ra(1) = real <:list:> then begin i:=i+1; if system(4,i,ra)<>(8 shift 12 + 10) then <* error in yes/no spec. *> init_error(2); if ra(1) = real <:yes:> then list_source:=true else begin if ra(1) = real <:no:> then list_source:=false else init_error(2); end; end; if ra(1) = real <:note:> then begin i:=i+1; if system(4,i,ra)<>(8 shift 12 + 10) then <* error in yes/no spec. *> init_error(2); if ra(1) = real <:yes:> then use_note:=true else begin if ra(1) = real <:no:> then use_note:=false else init_error(2); end; end; if ra(1) = real <:warni:> add 'n' then begin i:=i+1; if system(4,i,ra)<>(8 shift 12 + 10) then <* error in yes/no spec. *> init_error(2); if ra(1) = real <:yes:> then show_warning:=true else begin if ra(1) = real <:no:> then show_warning:=false else init_error(2); end; end; i:=i+1; sy:=system(4,i,ra); end; end; procedure init_scan; <*----------------------------------------------------------------*> <* Init. intable and keyword table used by scanner *> <*----------------------------------------------------------------*> begin integer i; item_val(0):=0; item_kind(0):=0; <* Init intable *> <* Kind: *> <* 1 : Illegal number *> <* 2 : Number *> <* 3 - *> <* 4 - *> <* 5 - *> <* 6 : Keyword *> <* 7 : Delimiter *> <* 8 : End line (EM, NL, FF) *> <* 9 : Text start char: < *> <* 10 : Text stop char: > *> <* 11 : Char. in text or comment (--) *> <* 12 : & or ^ or _ in text *> <* 13 : Alfa in text or comment *> <* 14 : Interval start char: ( *> <* 15 : Interval stop char: ) *> <* 16 : Symbol ! *> <* 17 : Synbol = *> <* 18 : Illegal character *> <* *> for i:=1 step 1 until 256 do newintable(i-1):= (case i of <* Kind *> ( 0, <* nul *> 18, <* soh *> 18, <* stx *> 18, <* etx *> 18, <* eot *> 18, <* enq *> 18, <* ack *> 18, <* bel *> 18, <* bs *> 18, <* ht *> 8, <* nl *> 18, <* vt *> 8, <* ff *> 0, <* cr *> 18, <* so *> 18, <* si *> 18, <* dle *> 18, <* dc1 *> 18, <* dc2 *> 18, <* dc3 *> 18, <* dc4 *> 18, <* nak *> 18, <* syn *> 18, <* etb *> 18, <* can *> 8, <* em *> 18, <* sub *> 18, <* esc *> 18, <* fs *> 18, <* gs *> 18, <* rs *> 18, <* us *> 7, <* *> 16, <* ! *> 18, <* " *> 18, <* # *> 18, <* $ *> 18, <* % *> 18, <* & *> 18, <* ' *> 14, <* ( *> 15, <* ) *> 18, <* * *> 18, <* + *> 18, <* , *> 1, <* - *> 18, <* . *> 18, <* / *> 2, <* 0 *> 2, <* 1 *> 2, <* 2 *> 2, <* 3 *> 2, <* 4 *> 2, <* 5 *> 2, <* 6 *> 2, <* 7 *> 2, <* 8 *> 2, <* 9 *> 18, <* : *> 18, <* ; *> 1, <* < *> 17, <* = *> 10, <* > *> 18, <* ? *> 18, <* @ *> 6, <* A *> 6, <* B *> 6, <* C *> 6, <* D *> 6, <* E *> 6, <* F *> 6, <* G *> 6, <* H *> 6, <* I *> 6, <* J *> 6, <* K *> 6, <* L *> 6, <* M *> 6, <* N *> 6, <* O *> 6, <* P *> 6, <* Q *> 6, <* R *> 6, <* S *> 6, <* T *> 6, <* U *> 6, <* V *> 6, <* W *> 6, <* X *> 6, <* Y *> 6, <* Z *> 6, <* Æ *> 6, <* Ø *> 6, <* Å *> 18, <* ^ *> 18, <* _ *> 18, <* ` *> 6, <* a *> 6, <* b *> 6, <* c *> 6, <* d *> 6, <* e *> 6, <* f *> 6, <* g *> 6, <* h *> 6, <* i *> 6, <* j *> 6, <* k *> 6, <* l *> 6, <* m *> 6, <* n *> 6, <* o *> 6, <* p *> 6, <* q *> 6, <* r *> 6, <* s *> 6, <* t *> 6, <* u *> 6, <* v *> 6, <* w *> 6, <* x *> 6, <* y *> 6, <* z *> 6, <* æ *> 6, <* ø *> 6, <* å *> 18, <* ü *> 18, <* del *> <*-------------------*> 0, <* nul *> 0, <* soh *> 0, <* stx *> 0, <* etx *> 0, <* eot *> 0, <* enq *> 0, <* ack *> 0, <* bel *> 0, <* bs *> 0, <* ht *> 8, <* nl *> 0, <* vt *> 8, <* ff *> 0, <* cr *> 0, <* so *> 0, <* si *> 0, <* dle *> 0, <* dc1 *> 0, <* dc2 *> 0, <* dc3 *> 0, <* dc4 *> 0, <* nak *> 0, <* syn *> 0, <* etb *> 0, <* can *> 8, <* em *> 0, <* sub *> 0, <* esc *> 0, <* fs *> 0, <* gs *> 0, <* rs *> 0, <* us *> 11, <* *> 11, <* ! *> 11, <* " *> 11, <* # *> 11, <* $ *> 11, <* % *> 12, <* & *> 11, <* ' *> 11, <* ( *> 11, <* ) *> 11, <* * *> 11, <* + *> 11, <* , *> 11, <* - *> 11, <* . *> 11, <* / *> 11, <* 0 *> 11, <* 1 *> 11, <* 2 *> 11, <* 3 *> 11, <* 4 *> 11, <* 5 *> 11, <* 6 *> 11, <* 7 *> 11, <* 8 *> 11, <* 9 *> 11, <* : *> 11, <* ; *> 9, <* < *> 11, <* = *> 1, <* > *> 11, <* ? *> 11, <* @ *> 13, <* A *> 13, <* B *> 13, <* C *> 13, <* D *> 13, <* E *> 13, <* F *> 13, <* G *> 13, <* H *> 13, <* I *> 13, <* J *> 13, <* K *> 13, <* L *> 13, <* M *> 13, <* N *> 13, <* O *> 13, <* P *> 13, <* Q *> 13, <* R *> 13, <* S *> 13, <* T *> 13, <* U *> 13, <* V *> 13, <* W *> 13, <* X *> 13, <* Y *> 13, <* Z *> 13, <* Æ *> 13, <* Ø *> 13, <* Å *> 12, <* ^ *> 8, <* _ *> 11, <* ` *> 13, <* a *> 13, <* b *> 13, <* c *> 13, <* d *> 13, <* e *> 13, <* f *> 13, <* g *> 13, <* h *> 13, <* i *> 13, <* j *> 13, <* k *> 13, <* l *> 13, <* m *> 13, <* n *> 13, <* o *> 13, <* p *> 13, <* q *> 13, <* r *> 13, <* s *> 13, <* t *> 13, <* u *> 13, <* v *> 13, <* w *> 13, <* x *> 13, <* y *> 13, <* z *> 13, <* æ *> 13, <* ø *> 13, <* å *> 11, <* ü *> 0 ))<* del *> shift 12 + (case i of <* Value *> ( 0, <* nul *> 0, <* soh *> 0, <* stx *> 0, <* etx *> 0, <* eot *> 0, <* enq *> 0, <* ack *> 0, <* bel *> 0, <* bs *> 0, <* ht *> 10, <* nl *> 0, <* vt *> 12, <* ff *> 0, <* cr *> 0, <* so *> 0, <* si *> 0, <* dle *> 0, <* dc1 *> 0, <* dc2 *> 0, <* dc3 *> 0, <* dc4 *> 0, <* nak *> 0, <* syn *> 0, <* etb *> 0, <* can *> 25, <* em *> 0, <* sub *> 0, <* esc *> 0, <* fs *> 0, <* gs *> 0, <* rs *> 0, <* us *> 32, <* *> 33, <* ! *> 34, <* " *> 35, <* # *> 36, <* $ *> 37, <* % *> 38, <* & *> 39, <* ' *> 40, <* ( *> 41, <* ) *> 42, <* * *> 43, <* + *> 44, <* , *> 128, <* - *> 46, <* . *> 47, <* / *> 48, <* 0 *> 49, <* 1 *> 50, <* 2 *> 51, <* 3 *> 52, <* 4 *> 53, <* 5 *> 54, <* 6 *> 55, <* 7 *> 56, <* 8 *> 57, <* 9 *> 58, <* : *> 59, <* ; *> 128, <* < *> 61, <* = *> 62, <* > *> 63, <* ? *> 64, <* @ *> 65, <* A *> 66, <* B *> 67, <* C *> 68, <* D *> 69, <* E *> 70, <* F *> 71, <* G *> 72, <* H *> 73, <* I *> 74, <* J *> 75, <* K *> 76, <* L *> 77, <* M *> 78, <* N *> 79, <* O *> 80, <* P *> 81, <* Q *> 82, <* R *> 83, <* S *> 84, <* T *> 85, <* U *> 86, <* V *> 87, <* W *> 88, <* X *> 89, <* Y *> 90, <* Z *> 91, <* Æ *> 92, <* Ø *> 93, <* Å *> 94, <* ^ *> 95, <* _ *> 96, <* ` *> 65, <* a *> 66, <* b *> 67, <* c *> 68, <* d *> 69, <* e *> 70, <* f *> 71, <* g *> 72, <* h *> 73, <* i *> 74, <* j *> 75, <* k *> 76, <* l *> 77, <* m *> 78, <* n *> 79, <* o *> 80, <* p *> 81, <* q *> 82, <* r *> 83, <* s *> 84, <* t *> 85, <* u *> 86, <* v *> 87, <* w *> 88, <* x *> 89, <* y *> 90, <* z *> 91, <* æ *> 92, <* ø *> 93, <* å *> 126, <* ü *> 0, <* del *> <*-------------------*> 0, <* nul *> 0, <* soh *> 0, <* stx *> 0, <* etx *> 0, <* eot *> 0, <* enq *> 0, <* ack *> 0, <* bel *> 0, <* bs *> 0, <* ht *> 10, <* nl *> 0, <* vt *> 12, <* ff *> 0, <* cr *> 0, <* so *> 0, <* si *> 0, <* dle *> 0, <* dc1 *> 0, <* dc2 *> 0, <* dc3 *> 0, <* dc4 *> 0, <* nak *> 0, <* syn *> 0, <* etb *> 0, <* can *> 25, <* em *> 0, <* sub *> 0, <* esc *> 0, <* fs *> 0, <* gs *> 0, <* rs *> 0, <* us *> 32, <* *> 33, <* ! *> 34, <* " *> 35, <* # *> 36, <* $ *> 37, <* % *> 38, <* & *> 39, <* ' *> 40, <* ( *> 41, <* ) *> 42, <* * *> 43, <* + *> 44, <* , *> 45, <* - *> 46, <* . *> 47, <* / *> 48, <* 0 *> 49, <* 1 *> 50, <* 2 *> 51, <* 3 *> 52, <* 4 *> 53, <* 5 *> 54, <* 6 *> 55, <* 7 *> 56, <* 8 *> 57, <* 9 *> 58, <* : *> 59, <* ; *> 60, <* < *> 61, <* = *> 0, <* > *> 63, <* ? *> 64, <* @ *> 65, <* A *> 66, <* B *> 67, <* C *> 68, <* D *> 69, <* E *> 70, <* F *> 71, <* G *> 72, <* H *> 73, <* I *> 74, <* J *> 75, <* K *> 76, <* L *> 77, <* M *> 78, <* N *> 79, <* O *> 80, <* P *> 81, <* Q *> 82, <* R *> 83, <* S *> 84, <* T *> 85, <* U *> 86, <* V *> 87, <* W *> 88, <* X *> 89, <* Y *> 90, <* Z *> 91, <* Æ *> 92, <* Ø *> 93, <* Å *> 94, <* ^ *> 95, <* _ *> 96, <* ` *> 97, <* a *> 98, <* b *> 99, <* c *> 100, <* d *> 101, <* e *> 102, <* f *> 103, <* g *> 104, <* h *> 105, <* i *> 106, <* j *> 107, <* k *> 108, <* l *> 109, <* m *> 110, <* n *> 111, <* o *> 112, <* p *> 113, <* q *> 114, <* r *> 115, <* s *> 116, <* t *> 117, <* u *> 118, <* v *> 119, <* w *> 120, <* x *> 121, <* y *> 122, <* z *> 123, <* æ *> 124, <* ø *> 125, <* å *> 126, <* ü *> 0 ))<* del *> extract 12; intable(newintable); t_end_file :=00; t_case :=01; t_otherwise :=02; t_endselect :=03; t_else :=04; t_endif :=05; t_point :=06; t_text :=07; t_endmenu :=08; t_endwhile :=09; t_endattention :=10; t_endinclude :=11; t_select :=12; t_while :=13; t_menu :=14; t_attention :=15; t_include :=16; t_at :=17; t_write :=18; t_nl :=19; t_erase :=20; t_read :=21; t_get :=22; t_let :=23; t_send :=24; t_if :=25; t_execute :=26; t_note :=27; t_direct :=28; t_loop :=29; t_exit :=30; t_output :=31; t_convert :=32; t_echo :=33; t_of :=34; t_do :=35; t_then :=36; t_equal :=37; t_not :=38; t_on :=39; t_off :=40; t_int_start :=41; t_int_end :=42; t_unknown :=43; t_number :=44; t_string :=45; t_errstring :=46; t_var :=47; t_and :=48; t_or :=49; <* Keywords for mcl *> <* Bemærk alfabetisk opstilling *> for i:=1 step 1 until keywords do begin symbol_text(i):= case i of ( long <:AND:>, long <:AT:>, long <:ATTEN:> add 'T', long <:CASE:>, long <:CONVE:> add 'R', long <:DIREC:> add 'T', long <:DO:>, long <:ECHO:>, long <:ELSE:>, long <:ENDAT:> add 'T', long <:ENDIF:>, long <:ENDIN:> add 'C', long <:ENDME:> add 'N', long <:ENDSE:> add 'L', long <:ENDWH:> add 'I', long <:ERASE:>, long <:EXECU:> add 'T', long <:EXIT:>, long <:GET:>, long <:IF:>, long <:INCLU:> add 'D', long <:LET:>, long <:LOOP:>, long <:MENU:>, long <:NL:>, long <:NOTE:>, long <:OF:>, long <:OFF:>, long <:ON:>, long <:OR:>, long <:OTHER:> add 'W', long <:OUTPU:> add 'T', long <:POINT:>, long <:READ:>, long <:SELEC:> add 'T', long <:SEND:>, long <:TEXT:>, long <:THEN:>, long <:WHILE:>, long <:WRITE:> ); <* Token values for keywords *> symbol_val(i):= case i of (t_and, t_at, t_attention, t_case, t_convert, t_direct, t_do, t_echo, t_else, t_endattention, t_endif, t_endinclude, t_endmenu, t_endselect, t_endwhile, t_erase, t_execute, t_exit, t_get, t_if, t_include, t_let, t_loop, t_menu, t_nl, t_note, t_of, t_off, t_on, t_or, t_otherwise, t_output, t_point, t_read, t_select, t_send, t_text, t_then, t_while, t_write); end; end; procedure warning(nr); <*----------------------------------------------------------------*> <* Write warning on current output *> <*----------------------------------------------------------------*> value nr; integer nr; begin if show_warning then begin if list_source then write(out,<:<10>***warning :>) else write(out,<:<10>:>,<<dddd >,line_number,<:: warning :>); if nr<1 or nr>4 then nr:=5; <* Max. warning number used + 1 *> write(out,<< dd>,token_number,<:. :>,case nr of (<:no link:>, <:too many menu lines:>, <:illegal character:>, <:constant string with interval:>, <:undefined warning:>)); end; warnings:=true; end; procedure mcl_error(nr); <*----------------------------------------------------------------*> <* Write error on current output *> <*----------------------------------------------------------------*> value nr; integer nr; begin if list_source then write(out,<:<10>***error :>) else write(out,<:<10>:>,<<dddd >,line_number,<:: error :>); if nr<1 or nr>12 then nr:=12; <* Max. error number used + 1 *> write(out,<< dd>,token_number,<:. :>,case nr of (<:no selectable menu text lines:>, <:string size:>, <:non constant string:>, <:empty string:>, <:illegal number:>, <:column > 79:>, <:line > 24:>, <:line = 0:>, <:already in attention or include:>, <:point not unique:>, <:source line too long:>, <:undefined error:>)); make_code:=false; end; procedure comp_error(nr); <*----------------------------------------------------------------*> <* Called when error in this program is detected *> <* Write error and goto stop *> <*----------------------------------------------------------------*> integer nr; begin ii:=1; write(out,<:<10>***internal :>,nr,<:<10>:>); goto stop; end; procedure syntax_error(nr); <*----------------------------------------------------------------*> <* writes syntax error on current output *> <* signals that no usefull code is produced *> <*----------------------------------------------------------------*> value nr; integer nr; begin if list_source then write(out,<< dddd>,<:<10>***syntax :>) else write(out,<:<10>:>,<<dddd >,line_number,<:: syntax :>); if nr<1 or nr>23 then nr:=24; <* Max. error number used + 1 *> write(out,<< dd>,token_number,<:. :>,case nr of (<:error in string:>, <:unknown keyword:>, <:number missing:>, <:interval error:>, <:) missing:>, <:variabel missing:>, <:OF missing:>, <:CASE expected:>, <:ENDSELECT expected:>, <:= missing:>, <:DO missing:>, <:ENDWHILE expected:>, <:POINT expected:>, <:too many points:>, <:ENDMENU expected:>, <:ENDATTENTION expected:>, <:ENDINCLUDE expected:>, <:sentence expected:>, <:THEN missing:>, <:ENDIF expected:>, <:ON or OFF missing:>, <:structure:>, <:illegal variable:>, <:undefined error:>)); make_code:=false; end; procedure syntax_scan(nr); <*----------------------------------------------------------------*> <* write syntax error and scans to next sentence *> <*----------------------------------------------------------------*> value nr; integer nr; begin syntax_error(nr); while token_type>t_echo do begin next_token; if token_type=t_errstring then syntax_error(1); if token_type=t_unknown then syntax_error(2); end; end; procedure write_headline; <*----------------------------------------------------------------*> <* Write form-feed and headline on current output *> <*----------------------------------------------------------------*> begin integer i; real array on(1:2); system(6,i,on); i:=1; write(out,<:<12><10>:>,string on(increase(i)),<: :>); i:=1; write(out,<:mcl d.:>,<<zddddd>,systime(5,0,rr),<:.:>,rr); i:=1; write(out,<: source file: :>,string source_file(increase(i)),<:<10>:>); end; procedure get_new_line; <*----------------------------------------------------------------*> <* Read next line from source and list this line *> <* on current output if LIST.YES *> <*----------------------------------------------------------------*> begin integer ch; tableindex:=0; last_item:=read_all(source_text,item_val,item_kind,1); while item_val(last_item)=95 do begin item_kind(last_item):=12; if table_index=128 then begin last_item:=last_item+1; read_char(source_text,ch); item_kind(last_item):=13; item_val(last_item):=ch; table_index:=128; end; last_item:=read_all(source_text,item_val,item_kind,last_item+1)+last_item; end; item:=0; token_number:=0; if -,(item_kind(1)=8 and item_val(1)=25) then begin line_number:=line_number+1; if list_source then begin <* Write line *> long array field key_word; integer i; write(out,<:<10>:>,<<dddd>,line_number,<: : :>); for i:=1 step 1 until abs last_item do if (item_kind(i)>8) or (item_kind(i)=7) then begin if (item_kind(i)=12) and (item_val(i)<>95) and (item_val(i-1)<>95) and (item_kind(i+1)=13) and (item_val(i+1)>96) then item_val(i+1):=item_val(i+1)-32; outchar(out,item_val(i) extract 24); end else if item_kind(i)=6 then begin key_word:=(i-1)*4; write(out,item_val.key_word); while item_kind(i+1)=6 do i:=i+1; end else if item_kind(i)<3 then write(out,<<d>,item_val(i)) else if (item_kind(i)=8) and item_val(i)=12 then write_headline; end; if last_item<0 then begin while readchar(source_text,ch)<>8 do; last_item:=-last_item; end; end; end; procedure next_item; <*----------------------------------------------------------------*> <* Get next item from line read from source *> <*----------------------------------------------------------------*> begin if item=0 then item:=1 else if item_kind(item)=8 then begin if item_val(item)<>25 then begin get_new_line; item:=1; end; end else if item=last_item then begin item_kind(item):=8; item_val(item):=10; mcl_error(11); end else item:=item+1; end; procedure next_token; <*----------------------------------------------------------------*> <* Get next token value evaluated from *> <* reading one or more items *> <*----------------------------------------------------------------*> begin integer index,low_index,high_index, i,text_ch,ch; next_token_start: next_item; case item_kind(item) of begin <* 1 Illegal number *> comp_error(1); <* 2 Number *> begin token_number_val:=item_val(item); token_type:=t_number; end; <* 3 *> comp_error(2); <* 4 *> comp_error(3); <* 5 *> comp_error(4); <* 6 keyword *> begin if (item_val(item) shift 8)=0 then begin <* 1 char. then VARIABLE *> token_type:=t_var; token_number_val:=(item_val(item) shift (-40))-65; if token_number_val>31 then token_number_val:=token_number_val-32; if token_number_val>max_var then syntax_error(23); end else begin <* Keyword *> index:=keywords//2; low_index:=1; high_index:=keywords; <* Use binary search to find value *> while item_val(item)<>symbol_text(index) do begin if low_index>=high_index then begin <* error keyword not found *> token_type:=t_unknown; goto key_word_end; end; if item_val(item) < symbol_text(index) then high_index:=index-1 else low_index:=index+1; index:=(high_index-low_index)//2+low_index; if index<1 or index>keywords then comp_error(5); end; token_type:=symbol_val(index); key_word_end: while item_kind(item+1)=6 do next_item; end; end; <* 7 Delimiter *> goto next_token_start; <* 8 End line *> if item_val(item)=25 then token_type:=t_end_file else goto next_token_start; <* 9 Text start < *> begin boolean string_error; string_error:=false; <* init token text *> for i:=1 step 1 until 15 do token_text(i):=0; token_var_sub:=false; next_item; text_ch:=1; if (item_kind(item)<9) or (item_kind(item)>13) then begin string_error:=true; goto string_end; end; while (item_kind(item)<>10) do begin if (item_kind(item)<9) or (item_kind(item)>13) then begin string_error:=true; goto string_end; end; if item_kind(item)=12 then begin if item_val(item)=94 then begin next_item; ch:=item_val(item) extract 5; if (item_kind(item)<11) or (item_kind(item)>13) or (ch=0) then begin string_error:=true; goto string_end; end; end else if item_val(item)=95 then begin next_item; ch:=item_val(item); if item_kind(item)=8 then begin string_error:=true; goto string_end; end; if item_kind(item)=10 then table_index:=128; end else begin next_item; if item_kind(item)<>13 then begin string_error:=true; ch:=0; end else begin ch:=item_val(item)+63; if ch>159 then ch:=ch-32; token_var_sub:=true; if ch-128>max_var then syntax_error(23); end; end; end else ch:=item_val(item); token_text((text_ch-1)//6+1):= token_text((text_ch-1)//6+1) shift 8 + ch extract 8; if text_ch<82 then text_ch:=text_ch+1; next_item; end; <* Insert in string *> string_end: token_string_length:=text_ch-1; i:=token_string_length mod 6; if i<>0 then token_text((token_string_length)//6+1):= token_text((token_string_length)//6+1) shift ((6-i)*8); if string_error then token_type:=t_errstring else token_type:=t_string; end; <* 10 Illegal char. > *> begin warning(3); goto next_token_start; end; <* 11 Comment -- *> begin next_item; if item_kind(item)<>11 then warning(3); next_item; while (item_kind(item)<>8) do next_item; if item_val(item)=25 then begin token_type:=t_end_file; goto next_token_end; end; goto next_token_start; end; <* 12 & in text *> comp_error(7); <* 13 Alfa in text *> comp_error(8); <* 14 Int start ( *> token_type:=t_int_start; <* 15 Int stop ) *> token_type:=t_int_end; <* 16 != *> begin next_item; if item_kind(item)<>17 then syntax_error(10); token_type:=t_not; end; <* 17 = *> token_type:=t_equal; <* 18 Illegal char. *> begin warning(3); goto next_token_start; end; end; next_token_end: token_number:=token_number+1; end; <* Next token *> procedure zero_code; <*----------------------------------------------------------------*> <* insert zero's in hole code area *> <*----------------------------------------------------------------*> begin long array field laf; integer i; laf:=0; code(0):=false; for i:=1 step 1 until max_code//4 do code.laf(i):=0; end; integer procedure set_op(opcode_nr,code_length); <*----------------------------------------------------------------*> <* Set OP to current opcode start, *> <* insert opcode nr and s_line, code_length is number *> <* of half word that shall be free in the same segment. *> <* If it's not posible in current segment start in *> <* next segment *> <*----------------------------------------------------------------*> value opcode_nr,code_length; integer opcode_nr,code_length; begin integer length_to_limit; length_to_limit:=512-(next_free mod 512); if length_to_limit<code_length then op:=next_free+length_to_limit-1 else op:=next_free-1; next_free:=op+code_length+1; if next_free>=max_code then init_error(4); code.op(1):=opcode_nr shift 12 +(s_line extract 12); set_op:=next_free; end; integer procedure find_string_address(string_length); <*----------------------------------------------------------------*> <* Find room to insert string_length hw's in the same *> <* segment starting at next_free *> <*----------------------------------------------------------------*> value string_length; integer string_length; begin integer length_to_limit,i; length_to_limit:=512-(next_free mod 512); if string_length>length_to_limit then i:=next_free+length_to_limit else i:=next_free; find_string_address:=i; end; procedure insert_jump(addr,jump); <*----------------------------------------------------------------*> <* Insert a jump op-code *> <*----------------------------------------------------------------*> value jump; integer field addr; integer jump; begin integer field next_addr; while addr<>0 do begin next_addr:=code.addr; code.addr:=jump; addr:=next_addr; end; end; procedure make_bool(f_addr,t_addr); <*----------------------------------------------------------------*> <* Producer kode for bool-exp *> <* returner peger til false og true *> <* adresse felterne i koden *> <*----------------------------------------------------------------*> integer field f_addr,t_addr; begin integer array left_string,right_string (1:max_string//3+5); boolean equal; if -,make_string(left_string) then begin syntax_scan(1); goto end_bool; end; equal:=false; if token_type=t_equal then equal:=true else if token_type<>t_not then syntax_error(10); next_token; if -,make_string(right_string) then begin syntax_scan(1); goto end_bool; end; <* make bool-exp *> if (left_string(2) shift (-12)=1) and (right_string(2) shift (-12)=5) and (right_string(3) extract 12 <=3) then begin set_op(3,10); code.op(4):=(left_string(2) extract 12) shift 12 + (right_string(3) extract 12); code.op(5):=right_string(4); end else if (right_string(2) shift (-12)=1) and (left_string(2) shift (-12)=5) and (left_string(3) extract 12 <=3) then begin set_op(3,10); code.op(4):=(right_string(2) extract 12) shift 12 + (left_string(3) extract 12); code.op(5):=left_string(4); end else if right_string(2) shift (-12)=0 and left_string(2) shift (-12)=1 then begin set_op(3,10); code.op(4):=left_string(2) shift 12; code.op(5):=0; end else if left_string(2) shift (-12)=0 and right_string(2) shift (-12)=1 then begin set_op(3,10); code.op(4):=right_string(2) shift 12; code.op(5):=0; end else begin set_op(2,8+left_string(1)); insert_string(left_string,op+9); code.op(4):=find_string_address(right_string(1)); insert_string(right_string,code.op(4)); end; if equal then begin f_addr:=op+6; t_addr:=op+4; <* true jump *> end else begin t_addr:=op+6; <* false jump *> f_addr:=op+4; end; end_bool: end; procedure make_bool_exp(end_token_type,error_nr,f_addr,t_addr); <*----------------------------------------------------------------*> <* Producer kode for bool-exp ink. AND / OR *> <* returner peger til false og true *> <* adresse felterne i koden *> <*----------------------------------------------------------------*> integer end_token_type,error_nr; integer field f_addr,t_addr; begin integer prev_addr; make_bool(f_addr,t_addr); while token_type=t_and or token_type=t_or do begin if token_type=t_and then begin insert_jump(t_addr,next_free); prev_addr:=f_addr; next_token; make_bool(f_addr,t_addr); code.f_addr:=prev_addr; end else if token_type=t_or then begin insert_jump(f_addr,next_free); prev_addr:=t_addr; next_token; make_bool(f_addr,t_addr); code.t_addr:=prev_addr; end end; if token_type=end_token_type then next_token else syntax_scan(error_nr); end; boolean procedure make_string(st); <*----------------------------------------------------------------*> <* Find type of string and insert this in string array *> <* String array format: *> <* st(1) : Length of used string array exc. this element *> <* in half words. *> <* st(2) : String type in same format as cmcl code. *> <* st(3) : Text start (first word = HW < 12 + chars.) *> <*----------------------------------------------------------------*> integer array st; begin boolean interval,ok; integer first_char,num_of_char,var_ref,i; make_string:=true; ok:=true; for ii:=system(3,i,st) step 1 until i do st(ii):=0; if token_type<t_string or token_type>t_var then begin ok:=false; goto make_string_end; end; if token_type=t_string then <* Text string *> begin long array la(1:max_string//6+3); integer i,ts_length; boolean tvs; ts_length:=token_string_length; tvs:=token_var_sub; if ts_length>max_string then begin mcl_error(2); ts_length:=max_string; end; for i:=1 step 1 until max_string//6+2 do la(i):=token_text(i); next_token; interval:=false; if token_type=t_int_start then begin <* Interval *> if -,tvs then warning(4); next_token; if token_type<>t_number then begin ok:=false; syntax_error(3); goto make_string_end; end; first_char:=token_number_val; if first_char<1 then begin first_char:=1; syntax_error(4); end; if first_char>max_string+20 then begin first_char:=max_string; syntax_error(4); end; next_token; if token_type<>t_number then begin ok:=false; syntax_error(3); goto make_string_end; end; num_of_char:=token_number_val; if num_of_char<1 then begin syntax_error(4); num_of_char:=1; end; next_token; if token_type<>t_int_end then begin ok:=false; syntax_error(5); goto make_string_end; end; next_token; interval:=true; end; if (ts_length=0) or (interval and -,tvs and (ts_length < first_char)) then begin <* Null string *> st(1):=2; st(2):=0; end else begin if -,(interval or tvs) then begin <* Constant string *> st(1):=4+((ts_length+2)//3*2); st(2):=5 shift 12; st(3):=(st(1)-2) shift 12 + ts_length; for i:=1 step 1 until (st(1)-2)//4 do begin st(2*i+2):=la(i) shift (-24); st(2*i+3):=la(i) extract 24; end; end; if tvs and -,interval then begin <* Text with varsub *> st(1):=4+((ts_length+2)//3*2); st(2):=3 shift 12; st(3):=(st(1)-2) shift 12 + ts_length; for i:=1 step 1 until (st(1)-2)//4 do begin st(2*i+2):=la(i) shift (-24); st(2*i+3):=la(i) extract 24; end; end; if tvs and interval then begin st(1):=6+((ts_length+2)//3*2); st(2):=4 shift 12; st(3):=first_char shift 12 + num_of_char; st(4):=(st(1)-4) shift 12 + ts_length; for i:=1 step 1 until (st(1)-4)//4 do begin st(2*i+3):=la(i) shift (-24); st(2*i+4):=la(i) extract 24; end; end; if interval and -,tvs then begin <* Constant string with interval !!!!! *> integer new_length,sti,li,ch,index; new_length:=if (ts_length-first_char+1)>=num_of_char then num_of_char else ts_length-first_char+1; sti:=0; <* move new_length characters from la to st *> <* starting at character first_char in la *> for li:=first_char-1 step 1 until first_char+new_length-2 do begin <* find character li+1 in la *> ch:=(la(li//6+1) shift (-8*(5-(li mod 6)))) extract 8; index:=sti//3+4; <* insert character in st at sti+1 *> st(index):=st(index) + (ch shift (8*(2-(sti mod 3)))); sti:=sti+1; end; st(1):=4+((new_length+2)//3*2); st(2):=5 shift 12; st(3):=(st(1)-2) shift 12 + new_length; end; end; end <* Text string *> else begin <* Variable or illegal string *> var_ref:=token_number_val; if token_type=t_errstring then syntax_error(1); next_token; if token_type=t_int_start then begin <* Interval *> next_token; if token_type<>t_number then begin ok:=false; syntax_error(3); goto make_string_end; end; first_char:=token_number_val; if first_char<1 then begin first_char:=1; syntax_error(4); end; if first_char>max_string+20 then begin first_char:=max_string; syntax_error(4); end; next_token; if token_type<>t_number then begin ok:=false; syntax_error(3); goto make_string_end; end; num_of_char:=token_number_val; if num_of_char<1 then begin syntax_error(4); num_of_char:=1; end; if num_of_char>max_string+20 then begin syntax_error(4); num_of_char:=max_string; end; next_token; if token_type<>t_int_end then begin ok:=false; syntax_error(5); goto make_string_end; end; next_token; st(1):=4; st(2):=2 shift 12 + var_ref; st(3):=first_char shift 12 + num_of_char; end else begin <* No interval *> st(1):=2; st(2):= 1 shift 12 + var_ref; end; end; make_string_end: if -,ok then begin st(1):=2; st(2):=0; <* Empty string *> make_string:=false; while token_type=t_int_end or token_type=t_number do next_token; end; end; boolean procedure make_const_string(cst,point); <*----------------------------------------------------------------*> <* Find constant string and insert this in const *> <* string array. *> <* const string array format: *> <* cst(1) : Number of char in text. *> <* cst(2) : First char. in text. Converted to capital letter *> <* cst(3) : Start of text *> <*----------------------------------------------------------------*> integer array cst; boolean point; begin integer i,j; for i:=system(3,j,cst) step 1 until j do cst(i):=0; if token_type=t_errstring then begin syntax_error(1); cst(1):=cst(2):=cst(3):=0; end else if token_type<>t_string then begin make_const_string:=false; cst(1):=cst(2):=cst(3):=0; end else begin make_const_string:=true; if token_var_sub then mcl_error(3); <* Not constant *> if token_string_length=0 then cst(1):=cst(2):=cst(3):=0 else begin if token_string_length>max_string then begin mcl_error(2); token_string_length:=max_string; end; cst(1):=token_string_length; cst(2):=token_text(1) shift (-40); for i:=1 step 1 until cst(1)//6+1 do begin cst(2*i+1):=token_text(i) shift (-24); cst(2*i+2):=token_text(i) extract 24; end; end; if cst(2)>='a' and cst(2)<='å' then cst(2):=cst(2)-32; if token_string_length=0 and point then mcl_error(4); next_token; end; end; integer procedure insert_string(st,addr); <*----------------------------------------------------------------*> <* Insert st (string) in code at address addr *> <* Return next unused address in next_free *> <*----------------------------------------------------------------*> value addr; integer array st; integer addr; begin integer i; integer array field p; p:=addr-1; for i:=2 step 1 until st(1)//2+1 do code.p(i-1):=st(i); insert_string:=next_free:=addr+st(1); end; procedure select; <*----------------------------------------------------------------*> <* Produce code for SELECT *> <* Structure of produced kode: *> <* -- bool exp -- ___ true address -- * !----false address ! * ! -------------- ! * ! <--! * ! Action * First CASE ! * ! ---- jump ---- * ! address ---! * ! -------------- ! __* !--> ! --* ! * More cases ! * -------------- ! --* otherwise ! action ! -------------- ! <--! *> <*----------------------------------------------------------------*> begin integer f_jump_hold_addr, t_jump_hold_addr, jump_hold_addr, string_start; integer field i; integer var_ref; integer array case_string(1:max_string//3+5); f_jump_hold_addr:=jump_hold_addr:=0; if token_type<>t_var then begin syntax_scan(6); goto case_start; end; var_ref:=token_number_val; next_token; if token_type<>t_of then begin syntax_scan(7); goto case_start; end; next_token; if token_type<>t_case then syntax_scan(8); case_start: while token_type=t_case do <* case *> begin s_line:=line_number; next_token; if f_jump_hold_addr<>0 then begin <* Indsæt adresse på ny bool-exp start i forrige bool-exp *> i:=f_jump_hold_addr; code.i:=next_free; end; if -,make_string(case_string) then syntax_scan(1); <* Indsæt bool-exp ud fra var_ref og case_string *> if (case_string(2) shift (-12)=5) and (case_string(3) extract 12<=3) then begin set_op(3,10); code.op(4):=var_ref shift 12 +(case_string(3) extract 12); code.op(5):=case_string(4); end else if (case_string(2) shift (-12)=0) then begin set_op(3,10); code.op(4):=var_ref shift 12; code.op(5):=0; end else begin set_op(2,10); code.op(5):=1 shift 12 + var_ref; string_start:=find_string_address(case_string(1)); code.op(4):=string_start; insert_string(case_string,string_start); end; code.op(2):=next_free; f_jump_hold_addr:=op+6; action; s_line:=line_number; <* Indsæt JUMP code efter action *> set_op(1,4); code.op(2):=jump_hold_addr; jump_hold_addr:=op+4; end; if token_type=t_otherwise then begin <* otherwise *> <* Indsæt adresse på otherwise i sidste bool-exp *> if make_code then begin i:=f_jump_hold_addr; code.i:=next_free; end; next_token; action; end else if make_code then begin <* fjern sidste jump *> next_free:=next_free-4; jump_hold_addr:=code.op(2); code.op(1):=code.op(2):=0; <* Indsæt adresse på endselect i sidste bool-exp *> i:=f_jump_hold_addr; code.i:=next_free; end; <*Indsæt baglens i jump_hold_adr addressen på første sætning efter select *> if make_code then while jump_hold_addr<>0 do begin i:=jump_hold_addr; jump_hold_addr:=code.i; code.i:=next_free; end; if token_type<>t_endselect then syntax_error(9) else next_token; <* find first token after SELECT *> select_end: end; <* select *> procedure while_sentence; <*----------------------------------------------------------------*> <* Produce code for WHILE *> <* Structure of produced kode *> <* -- bool exp -- <-------! true address -- ! !----false address ! ! ! -------------- ! ! ! <--! ! ! action ! ! ! ! ---- jump ---- ! ! address --------- ! -------------- !--> *> <*----------------------------------------------------------------*> begin integer prev_while_start; integer field f_jump_hold_addr,t_jump_hold_addr; boolean equal; prev_while_start:=while_start; while_start:=next_free; make_bool_exp(t_do,11,f_jump_hold_addr,t_jump_hold_addr); if make_code then insert_jump(t_jump_hold_addr,next_free); first_action: action; s_line:=line_number; <* Insert jump code to while start *> set_op(1,4); code.op(2):=while_start; if make_code then insert_jump(f_jump_hold_addr,next_free); while_start:=prev_while_start; if token_type<>t_endwhile then begin syntax_error(12); end else next_token; end; procedure menu; <*----------------------------------------------------------------*> <* Produce code for MENU *> <*----------------------------------------------------------------*> begin integer field end_hold_addr,i; integer col,line,num_of_point,menu_text_index, ch_index,text_length,ncol; integer array menu_text(1:640),point_table(1:3*25); integer array field entry,menu_op; integer array menu_line(1:max_string//3+5); boolean first_text,ctrls; boolean array unique(0:127); procedure next_line; <* Insert NL in menu text *> begin if menu_line(2)>31 then begin line:=line+1; if line>24 then warning(2); pack_char(10); end; end; procedure pack_char(ch); <* Insert a character in menu text *> value ch; integer ch; begin menu_text(menu_text_index):=menu_text(menu_text_index)+ (ch shift (8*ch_index)); ch_index:=ch_index-1; if ch_index=-1 then begin menu_text_index:=menu_text_index+1; if menu_text_index>640 then comp_error(9); ch_index:=2; end; end; procedure pack_const_string(cst); <* Indsert string in cst in menu text *> integer array cst; begin integer i,cst_text_index,cst_ch_index; cst_text_index:=0; cst_ch_index:=-2; for i:=1 step 1 until cst(1) do begin pack_char((cst(3+cst_text_index) shift (cst_ch_index*8)) extract 8); cst_ch_index:=cst_ch_index+1; if cst_ch_index=1 then begin cst_text_index:=cst_text_index+1; cst_ch_index:=-2; end; end; end; if token_type<>t_number then begin syntax_error(3); col:=line:=-1; goto point_start; end; col:=token_number_val; if col>79 then begin mcl_error(6); col:=79; end; next_token; if token_type<>t_number then begin syntax_error(3); col:=line:=-1; goto point_start; end; line:=token_number_val; if line>24 then begin mcl_error(7); line:=1; end; next_token; if -,make_const_string(menu_line,false) then begin syntax_error(1); line:=col:=-1; end; set_op(22,8); code.op(2):=line shift 12; point_start: if token_type>t_endinclude then begin if col<>-1 then syntax_error(13); menu_line(1):=menu_line(2):=1; while token_type>t_endinclude do next_token; end; menu_op:=op; <* Rem. menu code pos. *> menu_text_index:=1; for i:=1 step 1 until 640 do menu_text(i):=0; ch_index:=2; end_hold_addr:=0; num_of_point:=0; if menu_line(1)>0 and menu_line(2)>31 then begin <* Write headline centred in 80 char. *> for i:=1 step 1 until (80-menu_line(1))//2 do pack_char(32); pack_const_string(menu_line); end; line:=line+1; for ii:=0 step 1 until 127 do unique(ii):=false; ctrls:=true; while token_type=t_point or token_type=t_text do begin <* POINT and TEXT *> if token_type=t_text then begin <* TEXT *> next_token; if token_type=t_at then begin next_token; if token_type<>t_number then syntax_scan(3) else begin ncol:=token_number_val; if ncol>79 then begin mcl_error(6); ncol:=1; end; end; next_token; end else ncol:=col; if -,make_const_string(menu_line,false) then syntax_scan(1); next_line; if menu_line(1)>0 and menu_line(2)>31 then begin <* Insert text at collum ncol *> for i:=1 step 1 until ncol do pack_char(32); pack_const_string(menu_line); end; if menu_line(1)=0 then begin menu_line(2):=32; next_line; end; end else begin <* POINT *> integer entry_type; num_of_point:=num_of_point+1; if num_of_point>25 then begin num_of_point:=1; syntax_error(14); end; entry:=(num_of_point-1)*6; next_token; <* if token_type=t_at then begin next_token; if token_type<>t_number then syntax_scan(3) else begin ncol:=token_number_val; if ncol>79 then begin mcl_error(6); ncol:=1; end; end; next_token; end else *> ncol:=col; if -,make_const_string(menu_line,true) then syntax_scan(1); if unique(menu_line(2)) then mcl_error(10); unique(menu_line(2)):=true; point_table.entry(2):=ncol shift 12 + line; next_line; if menu_line(1)>0 and menu_line(2)>31 then begin <*Insert text at collum ncol *> for i:=1 step 1 until ncol do pack_char(32); pack_const_string(menu_line); ctrls:=false; <* Printeble menu point used *> end; <* Find entry type bits *> entry_type:=0; if num_of_point=1 then entry_type:=1; <* Top bit *> if menu_line(2)<32 then entry_type:=entry_type+8; <* Ctlr char bit *> point_table.entry(1):=menu_line(2) shift 12 + entry_type; point_table.entry(3):=next_free; <* Action address *> action; s_line:=line_number; set_op(1,4); <* Insert jump to end-menu after action code *> code.op(2):=end_hold_addr; end_hold_addr:=op+4; end; if token_type>t_endinclude then begin syntax_error(15); while token_type>t_endinclude do next_token; end; end; <* point and text *> <* Indsert bottom bit in last entry *> if num_of_point>0 then begin entry:=6*(num_of_point-1); point_table.entry(1):=point_table.entry(1)+2; end else mcl_error(1); if ctrls then <* Only controls are used in points *> mcl_error(1); <* Insert last menu line in all ctrl point *> for entry:=0 step 6 until 6*(num_of_point-1) do if (point_table.entry(1) shift (-12))<32 then point_table.entry(2):=col shift 12 + line; <* Find menu text length *> text_length:=3*(menu_text_index-1)+(2-ch_index); first_text:=true; menu_text_index:=0; while text_length>0 do begin <* Insert menu text entries *> integer room; room:=512-(next_free mod 512); if (room<20) and (((text_length//3)*2+4)>room) then begin <* No room for text; min. 30 char in one text-entry *> next_free:=next_free+room; room:=512; end; if first_text then code.menu_op(4):=next_free; <* Insert address of first text *> entry:=next_free-1; <* Entry in code *> first_text:=false; if ((text_length//3)*2+4)<room then begin <* Last text entry *> code.entry(1):=0; code.entry(2):=((text_length+2)//3+1)*2 shift 12 + text_length; end else begin code.entry(1):=next_free+room; <* Next text start *> code.entry(2):=(room-2) shift 12 + ((room-4)//2)*3; end; for i:=1 step 1 until (code.entry(2) shift (-12))//2 do code.entry(2+i):=menu_text(i+menu_text_index); next_free:=next_free+(code.entry(2) shift (-12))+2; text_length:=text_length-code.entry(2) extract 12; menu_text_index:=menu_text_index+(code.entry(2) extract 12)//3; end; <* Find room for point table (max. 150 hw) *> entry:=find_string_address(6*num_of_point)-1; code.menu_op(3):=entry+1; <* Insert address of first point *> for i:=1 step 1 until 3*num_of_point do code.entry(i):=point_table(i); next_free:=entry+1+6*num_of_point; code.menu_op(2):=code.menu_op(2)+num_of_point; <* indsæt i end_hold_jump *> if make_code then while end_hold_addr<>0 do begin i:=end_hold_addr; end_hold_addr:=code.i; code.i:=next_free; end; if token_type<>t_endmenu then syntax_error(15) else next_token; end; <* menu *> procedure attention; <*----------------------------------------------------------------*> <* Produce code for ATTENTION *> <*----------------------------------------------------------------*> begin integer field end_att_hold_addr; integer array proc_string(1:max_string//3+5); if in_attention or in_include then mcl_error(9); in_attention:=true; att_start:=next_free; if -,make_string(proc_string) then begin syntax_scan(1); goto first_action; end; set_op(4,10+proc_string(1)); insert_string(proc_string,op+9); code.op(2):=next_free; if token_type<>t_var then begin syntax_scan(6); goto first_action; end; code.op(4):=token_number_val shift 12; end_att_hold_addr:=op+6; next_token; first_action: action; if make_code then code.end_att_hold_addr:=next_free; s_line:=line_number; set_op(5,2); in_attention:=false; if token_type<>t_endattention then syntax_error(16) else next_token; end; procedure include; <*----------------------------------------------------------------*> <* Produce code for INCLUDE *> <*----------------------------------------------------------------*> begin integer field end_inc_hold_addr; integer array proc_string,pool_string,local_string(1:max_string//3+5); integer bufs; if in_attention or in_include then mcl_error(9); in_include:=true; att_start:=next_free; if -,make_string(pool_string) then begin syntax_scan(1); goto first_action; end; if -,make_string(proc_string) then begin syntax_scan(1); goto first_action; end; if -,make_string(local_string) then begin syntax_scan(1); goto first_action; end; set_op(6,16+local_string(1)); insert_string(local_string,op+15); code.op(6):=find_string_address(pool_string(1)); insert_string(pool_string,code.op(6)); code.op(7):=find_string_address(proc_string(1)); insert_string(proc_string,code.op(7)); code.op(2):=next_free; if token_type<>t_number then begin syntax_scan(3); goto first_action; end; bufs:=token_number_val; if bufs>1 then mcl_error(5); next_token; if token_type<>t_number then begin syntax_scan(3); goto first_action; end; code.op(5):=bufs shift 12 + token_number_val; next_token; if token_type<>t_var then begin syntax_scan(6); goto first_action; end; code.op(4):=token_number_val shift 12; end_inc_hold_addr:=op+6; next_token; first_action: action; if make_code then code.end_inc_hold_addr:=next_free; s_line:=line_number; set_op(7,2); in_include:=false; if token_type<>t_endinclude then syntax_error(17) else next_token; end; procedure at; <*----------------------------------------------------------------*> <* Produce code for AT *> <*----------------------------------------------------------------*> begin integer col,line; if token_type<>t_number then syntax_scan(3) else begin col:=token_number_val; if col>79 then begin mcl_error(6); col:=79; end; next_token; if token_type=t_number then begin line:=token_number_val; if line>24 then begin mcl_error(7); line:=24; end; next_token; end else begin line:=-1; if token_type>t_echo then syntax_scan(18); end; set_op(8,4); code.op(2):=col shift 12 + (line extract 12); end; end; procedure write_sentence; <*----------------------------------------------------------------*> <* Produce code for WRITE *> <*----------------------------------------------------------------*> begin integer array write_string(1:max_string//3+5); if -,make_string(write_string) then syntax_scan(1) else if write_string(2) shift (-12) <> 0 then begin <* Non empty string *> set_op(9,6+write_string(1)); insert_string(write_string,op+5); code.op(2):=next_free; end; end; procedure nl; <*----------------------------------------------------------------*> <* Produce code for NL *> <*----------------------------------------------------------------*> begin set_op(10,2); end; procedure erase; <*----------------------------------------------------------------*> <* Produce code for ERASE *> <*----------------------------------------------------------------*> begin set_op(23,2); end; procedure read_sentence; <*----------------------------------------------------------------*> <* Produce code for READ *> <*----------------------------------------------------------------*> begin integer array read_string(1:max_string//3+5); integer char_to_read; if -,make_string(read_string) then syntax_scan(1) else if token_type<>t_number then char_to_read:=-1 else begin char_to_read:=token_number_val; if char_to_read>max_string or char_to_read<1 then begin mcl_error(5); char_to_read:=1; end; next_token; end; if token_type<>t_var then syntax_scan(6) else begin if read_string(2) shift (-12) <> 0 then begin <* Non empty string *> set_op(9,6+read_string(1)); insert_string(read_string,op+5); code.op(2):=next_free; end; set_op(11,4); code.op(2):=char_to_read shift 12 + token_number_val; next_token; end; end; procedure get; <*----------------------------------------------------------------*> <* Produce code for GET *> <*----------------------------------------------------------------*> begin integer char_to_get; if -,(in_attention or in_include) then warning(1); if token_type<>t_number then syntax_scan(3) else begin char_to_get:=token_number_val; if char_to_get>max_string or char_to_get<1 then mcl_error(5); next_token; if token_type<>t_var then syntax_scan(6) else begin set_op(12,4); code.op(2):=char_to_get shift 12 + token_number_val; next_token; end; end; end; procedure let; <*----------------------------------------------------------------*> <* Produce code for LET *> <*----------------------------------------------------------------*> begin integer var_ref; integer array let_string(1:max_string//3+5); if token_type<>t_var then syntax_scan(6) else begin var_ref:=token_number_val; next_token; if token_type<>t_equal then syntax_scan(10) else begin next_token; if -,make_string(let_string) then syntax_scan(1) else begin set_op(13,8+let_string(1)); insert_string(let_string,op+7); code.op(2):=next_free; code.op(3):=var_ref shift 12; end; end; end; end; procedure send; <*----------------------------------------------------------------*> <* Produce code for SEND *> <*----------------------------------------------------------------*> begin integer array send_string(1:max_string//3+5); if -,(in_attention or in_include) then warning(1); if -,make_string(send_string) then syntax_scan(1) else begin set_op(14,6+send_string(1)); insert_string(send_string,op+5); code.op(2):=next_free; end; end; procedure if_sentence; <*----------------------------------------------------------------*> <* Produce code for IF *> <* Structure of produced kode for IF THEN ELSE *> <* -- bool exp -- true address -- !----false address ! ! -------------- ! ! <--! ! action ! ! ---- jump ---- ! address ---! ! -------------- ! !--> else ! action ! -------------- ! <--! Structure of produced kode for IF THEN -- bool exp -- true address -- !----false address ! ! -------------- ! ! <--! ! action ! ! -------------- !--> *> <*----------------------------------------------------------------*> begin integer field f_jump_hold_addr,t_jump_hold_addr; boolean equal; make_bool_exp(t_then,19,f_jump_hold_addr,t_jump_hold_addr); if make_code then insert_jump(t_jump_hold_addr,next_free); first_action: action; s_line:=line_number; if token_type=t_else then begin set_op(1,4); if make_code then insert_jump(f_jump_hold_addr,next_free); f_jump_hold_addr:=op+3; next_token; action; end; if make_code then insert_jump(f_jump_hold_addr,next_free); if token_type<>t_endif then begin syntax_error(20); end else next_token; end; procedure execute; <*----------------------------------------------------------------*> <* Produce code for EXECUTE *> <*----------------------------------------------------------------*> begin integer array execute_string(1:max_string//3+5); if -,make_string(execute_string) then syntax_scan(1) else begin set_op(15,8+execute_string(1)); insert_string(execute_string,op+7); code.op(2):=next_free; if token_type<>t_var then syntax_scan(6) else begin code.op(3):=token_number_val shift 12; next_token; end; end; end; procedure note; <*----------------------------------------------------------------*> <* Produce code for NOTE *> <*----------------------------------------------------------------*> begin integer array note_string(1:max_string//3+5); if -,make_string(note_string) then syntax_scan(1) else if use_note then begin set_op(9,6+note_string(1)); insert_string(note_string,op+5); code.op(2):=next_free; set_op(10,2); end; end; procedure direct; <*----------------------------------------------------------------*> <* Produce code for DIRECT *> <*----------------------------------------------------------------*> begin if -,(in_attention or in_include) then warning(1); if token_type<>t_var then syntax_scan(6) else begin set_op(16,4); code.op(2):=token_number_val shift 12; next_token; end; end; procedure loop; <*----------------------------------------------------------------*> <* Produce code for LOOP *> <*----------------------------------------------------------------*> begin if in_attention and (while_start<att_start) then set_op(5,2); if in_include and (while_start<att_start) then set_op(5,2); set_op(1,4); code.op(2):=while_start; end; procedure exit; <*----------------------------------------------------------------*> <* Produce code for EXIT *> <*----------------------------------------------------------------*> begin integer array exit_string(1:max_string//3+5); if in_attention then set_op(5,2); if in_include then set_op(7,2); if -,make_string(exit_string) then syntax_scan(1); set_op(17,2+exit_string(1)); insert_string(exit_string,op+3); end; procedure output; <*----------------------------------------------------------------*> <* Produce code for OUTPUT *> <*----------------------------------------------------------------*> begin if token_type=t_on then begin next_token; set_op(18,2); end else if token_type=t_off then begin next_token; set_op(19,2); end else syntax_scan(21); end; procedure echo; <*----------------------------------------------------------------*> <* Produce code for ECHO *> <*----------------------------------------------------------------*> begin if token_type=t_on then begin next_token; set_op(20,2); end else if token_type=t_off then begin next_token; set_op(21,2); end else syntax_scan(21); end; procedure convert; <*----------------------------------------------------------------*> <* Produce code for CONVERT *> <*----------------------------------------------------------------*> begin if token_type<>t_var then syntax_scan(6) else begin set_op(24,4); code.op(2):=token_number_val shift 12; next_token; end; end; procedure action; <*----------------------------------------------------------------*> <* Call procedures to produce code for the *> <* sentence in a action, return if next keyword *> <* is a 'action-end' *> <*----------------------------------------------------------------*> begin integer tt; while token_type>t_endinclude do begin if (token_type>=t_select) and (token_type<=t_echo) then begin tt:=token_type-t_endinclude; s_line:=line_number; next_token; case tt of begin select; while_sentence; menu; attention; include; at; write_sentence; nl; erase; read_sentence; get; let; send; if_sentence; execute; note; direct; loop; exit; output; convert; echo end; end; if token_type>t_echo then begin <* Error, not a sentence start *> if token_type=t_unknown then <* Unknown keyword *> begin next_token; syntax_scan(2); end else syntax_scan(18); end; end; <* Other = end action *> end; integer procedure list_string(addr); <*----------------------------------------------------------------*> <* Used by list-code. List string format *> <* starting at address addr *> <*----------------------------------------------------------------*> value addr; integer addr; begin integer type; integer field i; write(out,<:<10>:>,<<dddddd>,addr,<:+ :>); i:=addr+1; type:=code.i shift (-12); if type<0 or type>5 then write(out,<:***String error:>,type) else begin case type+1 of begin <* 0 *> begin write(out,<: Empty string:>); list_string:=addr+2; end; <* 1 *> begin write(out,<: Variable :>); outchar(out,(code.i extract 12)+65); list_string:=addr+2; end; <* 2 *> begin write(out,<: Variable with interval :>); w_h(i,true); w_h(i+1,false); w_h(i+2,false); list_string:=addr+4; end; <* 3 *> begin write(out,<: Text with var.sub :>); list_string:=list_text(addr+2); end; <* 4 *> begin write(out,<: Text with var.sub and interval :>); w_h(i+1,false); w_h(i+2,false); list_string:=list_text(addr+4); end; <* 5 *> begin write(out,<: Constant text :>); list_string:=list_text(addr+2); end; end; end; end; integer procedure list_text(addr); <*----------------------------------------------------------------*> <* Used by code-list. List text starting at addr *> <*----------------------------------------------------------------*> value addr; integer addr; begin integer array field iaf; integer field inx; integer i,j,ch; inx:=addr+1; write(out,<:<10>:>,<<dddddd>,addr,<:+ Text:>,<< d>, code.inx shift (-12), code.inx extract 12); iaf:=inx; write(out,<: <60>:>); for i:=1 step 1 until (code.inx shift (-12))//2 do for j:=-16 step 8 until 0 do begin ch:=(code.iaf(i) shift j) extract 8; if ch<32 then begin if ch=0 then goto text_end; write(out,<:^:>); ch:=ch+64; end; if ch>127 then begin write(out,<:&:>); ch:=ch-63; end; outchar(out,ch); end; text_end: write(out,<:<62>:>); list_text:=addr+(code.inx shift (-12)); end; procedure w_addr(addr,text); integer field addr; string text; begin write(out,<:<10>:>,<<dddddd>,addr,<:+ :>, text,<< d>,code.addr); end; procedure w_h(addr,var); boolean field addr; boolean var; begin write(out,<:<10>:>,<<dddddd>,addr,<:+ :>); if var then begin write(out,<:Variable :>); outchar(out,(code.addr extract 12)+65); end else write(out,<< d>,code.addr extract 12); end; procedure code_list(op_addr,stop_addr); <*----------------------------------------------------------------*> <* List code formats from address op_addr *> <* until address stop_addr *> <*----------------------------------------------------------------*> value stop_addr; integer op_addr,stop_addr; begin integer op_code; while op_addr<stop_addr do begin op:=op_addr-1; op_code:=code.op(1) shift (-12); if op_code<0 or op_code>24 then begin write(out,<:<10>:>,<<dddddd>,op_addr, <: ***error in op code :>,op_code); while op_code<0 or op_code>24 do begin op_addr:=op_addr+2; op:=op_addr-1; op_code:=code.op(1) shift (-12); write(out,<< d>,op_code); end; end; write(out,<:<10>:>,<<dddddd>,op_addr,<:::>, <<dddd >,code.op(1) extract 12, case op_code+1 of (<:New segment:>, <:Jump:>, <:Bool-exp:>, <:Red-bool-exp:>, <:Attention:>, <:Endattention:>, <:Include:>, <:Endinclude:>, <:At:>, <:Write:>, <:Nl:>, <:Read:>, <:Get:>, <:Let:>, <:Send:>, <:Execute:>, <:Direct:>, <:Exit:>, <:Output-on:>, <:Output-off:>, <:Echo-on:>, <:Echo-off:>, <:Menu:>, <:Erase:>, <:Convert:>)); case op_code+1 of begin <* 0 *> begin op_addr:=(op_addr shift (-9)+1) shift 9; end; <* 1 *> begin op_addr:=op_addr+4; w_addr(op+3,<:addr::>); end; <* 2 *> begin op_addr:=if code.op(2)<code.op(3) then code.op(2) else code.op(3); w_addr(op+3,<:equal addr::>); w_addr(op+5,<:not equal addr::>); w_addr(op+7,<:right s addr::>); list_string(op+9); list_string(code.op(4)); end; <* 3 *> begin op_addr:=if code.op(2)<code.op(3) then code.op(2) else code.op(3); w_addr(op+3,<:equal addr::>); w_addr(op+5,<:not equal addr::>); w_h(op+7,true); w_h(op+8,false); write(out,<: :>); for ii:=-16 step 8 until -24+8*(code.op(4) extract 12) do outchar(out,code.op(5) shift ii); end; <* 4 *> begin op_addr:=code.op(2); w_addr(op+3,<:next op.:>); w_addr(op+5,<:end att addr::>); w_h(op+7,true); list_string(op+9); end; <* 5 *> begin op_addr:=op_addr+2; end; <* 6 *> begin op_addr:=code.op(2); w_addr(op+3,<:next op.:>); w_addr(op+5,<:end inc addr::>); w_h(op+7,true); w_h(op+9,false); w_h(op+10,false); w_addr(op+11,<:pool s addr::>); w_addr(op+13,<:proc s addr::>); list_string(op+15); list_string(code.op(6)); list_string(code.op(7)); end; <* 7 *> begin op_addr:=op_addr+2; end; <* 8 *> begin op_addr:=op_addr+4; w_h(op+3,false); w_h(op+4,false); end; <* 9 *> begin op_addr:=code.op(2); w_addr(op+3,<:next op.:>); list_string(op+5); end; <* 10 *> begin op_addr:=op_addr+2; end; <* 11 *> begin op_addr:=op_addr+4; w_h(op+3,false); w_h(op+4,true); end; <* 12 *> begin op_addr:=op_addr+4; w_h(op+3,false); w_h(op+4,true); end; <* 13 *> begin op_addr:=code.op(2); w_addr(op+3,<:next op.:>); w_h(op+5,true); list_string(op+7); end; <* 14 *> begin op_addr:=code.op(2); w_addr(op+3,<:next op.:>); list_string(op+5); end; <* 15 *> begin op_addr:=code.op(2); w_addr(op+3,<:next op.:>); w_h(op+5,true); list_string(op+7); end; <* 16 *> begin op_addr:=op_addr+4; w_h(op+3,true); end; <* 17 *> begin op_addr:=list_string(op+3); end; <* 18 *> begin op_addr:=op_addr+2; end; <* 19 *> begin op_addr:=op_addr+2; end; <* 20 *> begin op_addr:=op_addr+2; end; <* 21 *> begin op_addr:=op_addr+2; end; <* 22 *> begin integer next_text,point_table,num_of_point,point; long array field laf; integer field i; integer pch; op_addr:=op_addr+8; w_h(op+3,false); w_h(op+4,false); num_of_point:=code.op(2) extract 12; w_addr(op+5,<:first point:>); w_addr(op+7,<:menu text:>); next_text:=code.op(4); point_table:=code.op(3); code_list(op_addr,code.op(4)); while next_text<>0 do begin write(out,<:<10>:>,<<dddddd>,next_text,<:+ Menu text:>); op:=next_text-1; next_text:=code.op(1); if next_text>0 then w_addr(op+1,<:next text:>); write(out,<< d>,code.op(2) shift (-12), code.op(2) extract 12); laf:=op+4; write(out,<:<10>--------Menu-text-start---<10>:>,code.laf, <:<10>--------Menu-text-end-----<10>:>); end; for op:=point_table-1 step 6 until (num_of_point-1)*6+point_table-1 do begin write(out,<:<10>:>,<<dddddd>,op+1,<:+ Point :>); pch:=code.op(1) shift (-12); if pch < 32 then begin pch:=pch+64; write(out,<:^:>); end else write(out,<: :>); outchar(out,pch); write(out,<: :>); for ii:=-11 step 1 until 0 do write(out,<<d>,(code.op(1) shift ii) extract 1); w_h(op+3,false); w_h(op+4,false); w_addr(op+5,<:action:>); end; op_addr:=point_table+6*num_of_point; end; <* 23 *> begin op_addr:=op_addr+2; end; <* 24 *> begin op_addr:=op_addr+4; w_h(op+3,true); end; end; end; end; trap(traped); init_compiler; if list_source then write_headline; init_scan; open(source_text,4,source_file,0); if monitor(42,source_text,ii,tail)<>0 then init_error(3); if tail(9)<>0 then init_error(5); line_number:=0; get_new_line; next_token; while token_type<>t_end_file do begin action; if token_type<>t_end_file then begin syntax_error(22); while (token_type<t_select or token_type>t_echo) and token_type<>t_end_file do next_token; end; end; if false then traped: comp_error(alarmcause extract 24); stop: <* Insert exit at end *> s_line:=line_number; set_op(17,10); <* Default exit text *> code.op(2):=5 shift 12; code.op(3):=6 shift 12 + 5; code.op(4):= long <:exi:> shift (-24) extract 24; code.op(5):= long <:t :> shift (-24) extract 24; if show_code and make_code then begin write_headline; write(out,<:<10>Code list::>); code_list(0,next_free); end; if make_code and make_cmcl then begin real array field raf; open(cmcl_code,4,cmcl_file,0); monitor(42,cmcl_code,ii,tail); tail(1):=(next_free//512)+1; tail(6):=systime(7,0,rr); tail(9):=29 shift 12; <* Contents key 29 *> tail(10):=next_free; <* Size of code in hw's *> if monitor(44,cmcl_code,ii,tail)<>0 then begin for ii:=2,3,4,5,7,8 do tail(ii):=0; if monitor(40,cmcl_code,ii,tail)<>0 then init_error(6); end; for raf:=-1 step 512 until next_free-2 do begin outrec6(cmcl_code,512); tofrom(cmcl_code,code.raf,512); end; close(cmcl_code,true); end; write(out,<:<10>mcl end :>); if make_code then write(out,<: code:>,<< d>,next_free,<:<10>:>) else write(out,<: no code generated<10>:>); if warnings then errorbits:=1 shift 1; if -,make_code then errorbits:=3; end; end; <* program *> ▶EOF◀