DataMuseum.dk

Presents historical artifacts from the history of:

RC4000/8000/9000

This is an automatic "excavation" of a thematic subset of
artifacts from Datamuseum.dk's BitArchive.

See our Wiki for more about RC4000/8000/9000

Excavated with: AutoArchaeologist - Free & Open Source Software.


top - metrics - download

⟦a7d8ab296⟧ TextFile

    Length: 94464 (0x17100)
    Types: TextFile
    Names: »mcltxt      «

Derivation

└─⟦9ccaf6601⟧ Bits:30008165 Bånd med SW8000 kildetekst/release værktøjer
    └─⟦39138f30b⟧ 
        └─⟦this⟧ »mcltxt      « 

TextFile

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◀