Personal tools
You are here: Home Projects SETL LITTLE Source code LEX: Lexical scan phase.
Document Actions

LEX: Lexical scan phase.

by Paul McJones last modified 2021-03-17 18:40

LEX: Lexical scan phase.

1 .=member intro
       2 $     !$&'()*+,-./0123456789:;<=>abcdefghijklmnopqrstuvwxyz^_
       3 $    the above line contains, in order of ascii codes, the 56
       4 $    characters of the little language, starting in column 7.
       5$
       6$
       7$  $$          $$$$$$$$$$  $$$$$$$$$$  $$$$$$$$$$  $$          $$$$$$$$$
       8$  $$          $$$$$$$$$$  $$$$$$$$$$  $$$$$$$$$$  $$          $$$$$$$$$
       9$  $$              $$          $$          $$      $$          $$
      10$  $$              $$          $$          $$      $$          $$
      11$  $$              $$          $$          $$      $$          $$$$$$
      12$  $$              $$          $$          $$      $$          $$$$$$
      13$  $$              $$          $$          $$      $$          $$
      14$  $$              $$          $$          $$      $$          $$
      15$  $$$$$$$$$$  $$$$$$$$$$      $$          $$      $$$$$$$$$$  $$$$$$$$$
      16$  $$$$$$$$$$  $$$$$$$$$$      $$          $$      $$$$$$$$$$  $$$$$$$$$
      17$
      18$
      19$              $$          $$$$$$$$$$  $$      $$
      20$              $$          $$$$$$$$$$   $$    $$
      21$              $$          $$            $$  $$
      22$              $$          $$             $$$$
      23$              $$          $$$$$$          $$
      24$              $$          $$$$$$         $$$$
      25$              $$          $$            $$  $$
      26$              $$          $$           $$    $$
      27$              $$$$$$$$$$  $$$$$$$$$$  $$      $$
      28$              $$$$$$$$$$  $$$$$$$$$$  $$      $$
      29$
      30$
      31$
      32$
      33$
      34 $    this software is part of the little programming system.
      35 $             address queries and comments to
      36 $
      37 $                      little project
      38 $              department of computer science
      39 $                   new york university
      40 $        courant institute of mathematical sciences
      41 $                    251 mercer street
      42 $                   new york,  ny  10012
      43 $
      44 $    this is the first phase of the little compiler.  it performs
      45 $    the lexical scan, and is known as 'lex'.
      46 $
      47 $    the principal authors of the little compiler are
      48 $    robert abes, edith deak, richard kenner, david shields
      49 $    and aaron stein.
      50 $
      51 $
      52 $    the following is a list of the routines in the scanner -
      53
      54
      55 $
      56 $ name          description
      57 $ ---------------------------------------------------------------   c
      58 $ start         contains size statements for global variables
      59 $ lexini        initialisation routine
      60 $ setlit        define literal strings.
      61 $ inslit        insert literals in hash table.
      62 $ lexdo         driver for scanner
      63 $ nextw         top scanner routine, emits tokens to parser
      64 $ dfabsrb       absorbs macro definitions
      65 $ mcexpnd       expands macros
      66 $ trulex        builds tokens from input characters
      67 $ charinr       adds character to token
      68 $ givecr        gets next card from input stream
      69 $ hash          adds token to symbol table (ha)
      70 $ fivdec        converts integer to 5 right adjusted characters
      71 $ ibigr         compare symbols for cross-ref.
      72 $ detect        detects suspicious variables
      73 $ pflshr        control routine for puncher
      74 $ pncr          punches out token
      75 $ ermsg         lists error messages
      76 $ ertlist       list recent tokens if error detected
      77 $ toklr         list characters in token.
      78 $ ltoflo        report table overflow.
      79 $ lexexit       exit routine for scanner
      80
      81
      82 $    m a c r o   g l o s s a r y .
      83 $
      84 $    alphabetic (c)  =  1 if c is alphabetic character, else 0
      85 $    astkget (l)  = astk(l)  (astk is packed array)
      86 $    astklim  =  length of macro argumet stack astk
      87 $    astkput (v)  =  add v as new top of astk  (astk is packed)
      88 $    astkset (l,c)  =  astk(l)=v;  (astk is packed array)
      89 $    bintok  =  code for binary token, e.g., '100b'
      90 $    buildz (h,n,t)  = build token with index n. t is type. h ha-index
      91 $    cab  =  ha-field for conditional assembly bit
      92 $    charin (c)  =  add c to current token  (cf. trulex)
      93 $    charl (c)  =  print character c
      94 $    countup (i,l,m)  =  add 1 to i; quit if exceeds l. m is message
      95 $    cpstr - characters in short token record
      96 $    cpw  =  characters per word
      97 $    cs  =  character size in bits
      98 $    dectok  =  code for integer token, e.g., '100'
      99 $    endl  =  end current print line, start new one
     100 $    ertoksave (h)  =  add ha-index h to lisf t orecent tokens seen
     101 $    geter (a,l)  =  return a(l)  (a is packed array)
     102 $    getfromkeep(char) = get character from buffer
     103 $    getrefsym (s,w)  = get sds string for token, w is cross ref wd.
     104 $    getsym (s,h)  =  get sds string for token with ha-index h
     105 $    givec (c)  = get next character from input, put in c
     106 $    givecstr (c) = get next character, when inside string
     107 $    hamax  =  dims of hash table, or ha.  (must be prime)
     108 $    hashin (i)  =  add token to ha, set i to ha-index
     109 $    hashtokorg  =  origin for sds input string hashtok used in hash
     110 $    hasz  =  size of ha-entry in bits
     111 $    icdsig = card marking card image record on token file
     112 $    intl (i)  =  print integer i in five columns
     114 $    intlp(n,c) = output integer in c columns
     115 $    iscachar (c)  =  1 if c is one of '. + -' (conditional asm.)
     116 $    isublim  =  max. no. of routines for cross-reference
     117 $    isymc (h,i)  =  i-th character of token with ha-index h
     118 $    keepc(char) = character backup macro, limit is keeplimit
     119 $    lettercode (c) = ordinal of c if alphabetic, else 0. a=1,b=2,etc.
     120 $    leldefault = default lexical error limit.
     121 $    lexlen  =  ha-field giving token length in characters
     122 $    lextyp  =  ha-field giving lexical type
     123 $    namesmax  =  dims of 'names' array; max. no. of words for name str
     124 $    listarglim  =  dims of listarg in nextw, same as max. macro args
     125 $    macdef (t)  =  auxiliary for defining macros in macros
     126 $    macdrop (m)  =  drop macro with ha-index m
     127 $    macorg  =  ha-field giving mtab index of macro def. (0 if not macr
     128 $    macstate - ha field, 'is name currently a macro'
     129 $    mactlim  =  max. no. of entries for macro def table mtab
     130 $    maxtoklen  =  max. length of token in characters
     131 $    maxlinesz  =  number of characters in output line
     132 $    mccd = last column of input card that scanner processes
     133 $    mflshr (h)  =  punch out token with ha-index h
     134 $    mstklim  =  max. no entries in mstk for macro expansion
     135 $    mtset (l,w)  =  set l-th entry of mtab to w (mtab is packed)
     136 $    mtabsize  =  size in bits of macro def table entry
     137 $    mtlim - max. no. of entries in macro definition table
     138 $    nameptr  =  ha-field giving index in 'names' of name of token
     139 $    nametok  =  code for name-type token, e.g., 'little'
     140 $    namptrb  =  length of nameptr field
     141 $    nchars  =  no. of characters in system character set
     142 $    no  =  1 (used for readability)
     143 $    numbugtoks  =  no. of lexical debugging tokens (cf. trulex)
     144 $    nuses  =  ha-field giving number of times token used
     145 $    octaltok  =  code for octal-type token, e.g. '100b'
     146 $    octl (w)  =  print word in octal form
     147 $    optok  =  code for period delimiter operator token, eg., '.and.'
     148 $    ps  =  pointer size in bits (maximum subscript value)
     149 $    ms  =  size of macro definition item
     150 $    q3 (a,b,c)  =  auxiliary for defining macros inside macros
     151 $    readbio (t,a,n)  =  binary read n words into array a from tape t
     152 $    readio (t,a,n)  =  coded read n words into array a from tape t
     153 $    reslim  =  max. no of tokens in nextw backup buffer
     154 $    rztok  =  code for right alinng, zero-fill token, e.g., 4rabcd.
     155 $    sds (n)  =  size need for sds string of n characters
     156 $    sdspack (a,n)  = add n characters as start of current token
     157 $    sdstl  =  size in bits needed to hold 20 chars of token in sds foo
     158 $    sdstok  =  code for self-defining-string token, e.g. ' 'string' '.
     159 $    seter (a,v,w)  =  set a(w) = v  (a is packed array)
     160 $    skipl (n)  =  skip forward n spaces on print line
     161 $    slen  =  length (in characters) field of self-defining-string
     162 $    sorg  =  origin field for self-defining-string
     163 $    spectok  =  code for special-type token, e.g., '('
     164 $    stringtok  =  generic code for string type token
     165 $    suspi  =  level of usage below which variable becomes suspicious
     166 $    tabl (n)  =  tab print file to column n
     167 $    textl (s)  =  print string s
     168 $    tintl (s,i)  =  print label s, then integer i
     169 $    tokch (p,c)  = set p-th char of hash input to char. c
     170 $    tokl (h)  =  print token with ha-index h
     171 $    tokout (hdr, ara, lo)  add hdr, ara(1)...ara(lo) to token file
     172 $    tokout1 (w)  =  add word w to token fiel buffer
     173 $    tokpack (pak,unp,n)  =  pac n chars of ara unp into array pak
     174 $    tokrbuflim  =  no. of entries in token buffer tokrbuf
     175 $    tokrcard  =  code for card-image record in token file
     176 $    tokreof  =  code for end-file record on token flei
     177 $    tokrtyp  =  field in token record giving lexical type
     178 $    tokrval  =  field in token record giving first few chars of token
     179 $    torklen  =  field in token record giving token length in chars.
     180 $    ws  =  word size in bits
     181 $    yes  =  1 (used for readability)
     182 $
       1 .=member chars
       2 /*   little character set and ascii representation
       3
       4       !$&'()*+,-./0123456789:;<=>abcdefghijklmnopqrstuvwxyz^_
       5      the above line contains, in order of ascii codes, the 56
       6      characters of the little language, starting in column 7.
       7
       8      the little language requires 56 distinct characters.
       9      these include the 26 upper case letters, the 10 digits,
      10      and the following special characters:
      11
      12        blank
      13      = equal sign, assignment symbol
      14      + plus
      15      - minus
      16      * times, asterisk
      17      / divide, slash
      18      ( left parenthesis
      19      ) right parenthesis
      20      , comma
      21      . period, point
      22      ; semicolon
      23      : colon
      24      $ dollar sign, comment character
      25      ^ not
      26      & and
      27      ! or
      28      < less than
      29      > greater than
      30      ' apostrophe, string delimiter
      31      _ underline, break character
      32
      33      the following table gives the standard ascii encoding
      34      for the little character set.
      35
      36        little character    ascii  ascii  ascii    ascii character
      37                            (hex)  (oct)  (dec)
      38
      39        space                  20     40     32    space
      40      ! or                     21     41     33    exclamation mark
      41      $ dollar sign            24     44     36    dollar sign
      42      & and                    26     46     38    ampersand
      43      ' apostrophe             27     47     39    apostrophe
      44      ( left parenthesis       28     50     40    left parenthesis
      45      ) right parenthesis      29     51     41    right parenthesis
      46      * asterisk               2a     52     42    asterisk
      47      + plus                   2b     53     43    plus
      48      , comma                  2c     54     44    comma
      49      - minus                  2d     55     45    minus
      50      . period                 2e     56     46    period
      51      / slash                  2f     57     47    slant
      52      0 digit 0                30     60     48    digit 0
      53      1 digit 1                31     61     49    digit 1
      54      2 digit 2                32     62     50    digit 2
      55      3 digit 3                33     63     51    digit 3
      56      4 digit 4                34     64     52    digit 4
      57      5 digit 5                35     65     53    digit 5
      58      6 digit 6                36     66     54    digit 6
      59      7 digit 7                37     67     55    digit 7
      60      8 digit 8                38     70     56    digit 8
      61      9 digit 9                39     71     57    digit 9
      62      : colon                  3a     72     58    colon
      63      ; semicolon              3b     73     59    semicolon
      64      < less than              3c     74     60    less than
      65      = equals                 3d     75     61    equals
      66      > greater than           3e     76     62    greater than
      67      a letter a               41    101     65    letter a
      68      b letter b               42    102     66    letter b
      69      c letter c               43    103     67    letter c
      70      d letter d               44    104     68    letter d
      71      e letter e               45    105     69    letter e
      72      f letter f               46    106     70    letter f
      73      g letter g               47    107     71    letter g
      74      h letter h               48    110     72    letter h
      75      i letter i               49    111     73    letter i
      76      j letter j               4a    112     74    letter j
      77      k letter k               4b    113     75    letter k
      78      l letter l               4c    114     76    letter l
      79      m letter m               4d    115     77    letter m
      80      n letter n               4e    116     78    letter n
      81      o letter o               4f    117     79    letter o
      82      p letter p               50    120     80    letter p
      83      q letter q               51    121     81    letter q
      84      r letter r               52    122     82    letter r
      85      s letter s               53    123     83    letter s
      86      t letter t               54    124     84    letter t
      87      u letter u               55    125     85    letter u
      88      v letter v               56    126     86    letter v
      89      w letter w               57    127     87    letter w
      90      x letter x               58    130     88    letter x
      91      y letter y               59    131     89    letter y
      92      z letter z               5a    132     90    letter z
      93      ^ not                    5e    136     94    circumflex
      94      _ underline              5f    137     95    underline
      95
      96 */
      97
       1 .=member mods
       2 $    all changes are to insert self-description at -- mods.2 --
utsa   1
utsa   2 $    utsa      d. shields          29-nov-81           level 81333
utsa   3 $
utsa   4 $    support s47: amdahl uts (universal timesharing system).
utsa   5 $    this implementation runs on s37 architecture using an operating
utsa   6 $    system very close to unix (v7), and uses the ascii character set.
utsa   7
ldsa   1
ldsa   2 $    ldsa      d. shields          20-nov-81           level 81324
ldsa   3 $
ldsa   4 $    increase ha dimension yet again. for s32 unix, it is great help
ldsa   5 $    to be able to compile stlcod by appending text needed from stllib.
ldsa   6 $    this required change in cross-reference fields, so ref needs
ldsa   7 $    updating also.
ldsa   8 $    deck affected - macros
ldsa   9
hab    1
hab    2 $    hab       d. shields          01-oct-81           level 81274
hab    3 $
hab    4 $    increase ha dimension so can do full compilation of setl lib v21.
hab    5 $    new value (3929) cannot be increased without redoing table
hab    6 $    layouts due to field sizes of 12 bits.
hab    7 $    deck affected - macros
hab    8
dsz    1
dsz    2 $    dsz       d. shields          21-sep-81           level 81264
dsz    3 $
dsz    4 $    1.  make default for suspicious variables list 'susp=0/0' so
dsz    5 $        this list generated only if 'susp=1' specified.
dsz    6 $    2.  do not include 'name with prior usage being designated as
dsz    7 $        macro' warnings in warning count.
dsz    8 $    3.  add error message text for a case where '**' missing.
dsz    9 $    decks affected - lexini, ermsg
dsz   10
dsy    1
dsy    2 $    dsy       d. shields          17-jun-81           level 81168
dsy    3 $
dsy    4 $    1.  extend iset option to allow several names separated by
dsy    5 $        plus signs.
dsy    6 $    2.  fix error (fr157) in that illformed conditional assembly
dsy    7 $        names were not detected.
dsy    8 $    decks affected - lexini, lexca, cainit (new)
dsy    9
nama   1
nama   2 $    nama      d. shields          28-apr-81           level 81118
nama   3 $
nama   4 $    increase dimension of names array for s10, s32 and s37 to permit
nama   5 $    full compilation of setl lib, v2.20.
nama   6
dsx    1
dsx    2 $    dsx       d. shields          12-nov-80           level 80317
dsx    3 $
dsx    4 $    for unix, initially define (set) symbol 'unix'. this avoids having
dsx    5 $    to specify 'iset=unix' for compilations in unix environment.
dsx    6 $    deck affected - lexini.
dsx    7
dsw    1
dsw    2 $    dsw       d. shields          21-jul-80           level 80203
dsw    3 $
dsw    4 $    correct problems in case folding.
dsw    5 $    enable trace options for unix checkout.
dsw    6 $    decks affected - macros, trulex, lexdir.
dsw    7
dsv    1
dsv    2 $    dsv       d. shields          10-jul-80           level 80192
dsv    3 $
dsv    4 $    1.  fix problem (fr135) in setting of termination code.
dsv    5 $        now issue code 0 if no warnings or errors, code 4 if warnings
dsv    6 $        and no errors, code 8 if any errors detected.
dsv    7 $    2.  add possibility of running with lower-case as primary case
dsv    8 $        used within the compiler. this obtained by setting -mcl-.
dsv    9 $    3.  do not generate 'no errors detected' message.
dsv   10 $    4.  add conditional symbol -unix- for the unix operating system.
dsv   11 $        use iset=unix to obtain unix variant.
dsv   12 $        want listing terse, make lcp=0 and lcs=0 the defaults.
dsv   13 $        for initial checkout, delete special env code (bskp, etc.).
dsv   14 $
dsv   15 $    decks affected - macros, lexini, trulex, lexexit.
dsv   16
dsu    1
dsu    2 $    dsu       d. shields          10-jan-80           level 80010
dsu    3 $
dsu    4 $    1.  extend dimension of names and macro arrays to permit
dsu    5 $        full compilation of setl lib phase.
dsu    6 $        this requires changing ha field definitions.
dsu    7 $    2.  redefine format of cross-reference file to permit input
dsu    8 $        file to have more than 32767 lines.
dsu    9 $    decks affected - macros, start.
dsu   10
dst    1
dst    2 $    dst       d. shields          03-jan-80           level 80003
dst    3 $
dst    4 $    1.  increase dimension of ha and macro table.
dst    5 $    2.  fix bug in list resume option
dst    6 $    decks affected - macros, start.
dst    7
dss    1
dss    2 $    dss       d. shields          04-dec-79           level 79338
dss    3 $
dss    4 $    if lower case supported, convert first character of
dss    5 $    source line to upper case as appropriate (fr2.3.128).
dss    6 $    deck affected - macros
dss    7
dsr    1
dsr    2 $    dsr       d. shields          19-nov-79           level 79323
dsr    3 $
dsr    4 $    1.  rewind token file for s66 only.
dsr    5 $    2.  use getapp (new lib procedure provided by mod dsc) to
dsr    6 $        obtain and list actual parameter string specified by user.
dsr    7 $    3.  delete code to read term= parameter and possibly open
dsr    8 $        terminal file, as this now done by lib (mod dsc).
dsr    9 $    decks affected - macros, lexini.
dsr   10
dsq    1
dsq    2 $    dsq       d. shields          02-aug-79           level 79214
dsq    3 $
dsq    4 $    1. convert to use string search primitives (provided by lib
dsq    5 $        level 79200) to support mixed-case source. case significant
dsq    6 $        only within character string constants.
dsq    7 $    2.  modify code to list line to provide tab character if
dsq    8 $        available so as to maintain alignment of source using tabs.
dsq    9 $    3.  add program parameter  'upd=0/1' such that upd=1 indicates
dsq   10 $        that lines in input file have upd sequence information in the
dsq   11 $        first eight columns.
dsq   12 $    4.  for s10, issue standard characters at start of error
dsq   13 $        and warning messages sent to terminal.
dsq   14 $    decks affected - macros, start, and principally trulex.
dsq   15
mgfa   1
mgfa   2 $    mgfa      m.g. ford           05-jul-79           level 79186
mgfa   3 $
mgfa   4 $    this mod performs some s10-only changes, to improve dec-10
mgfa   5 $    compatibility slightly. it requires associated mods in all
mgfa   6 $    other programs which are part of the little suite.
mgfa   7 $    1.  revamp default filenames.
mgfa   8 $    2.  have terminal open by default ('term=tty:/').
mgfa   9 $    3.  change from sixbit to 9-bit ascii (cs=9).
mgfa  10 $    decks affected - macros,lexini.
mgfa  11
dsp    1 $ dsp (79052) - adjust dimension of names for s10.
dso    1
dso    2 $    dso       d. shields          21 dec 78           level 78355
dso    3 $
dso    4 $    1.  fix error (fr.23.71) in that not all calls to -ermsg-
dso    5 $        specified three arguments.
dso    6 $    2.  delete trace code for s10, as bootstrap complete.
dso    7 $    decks affected - macros, those referencing -ermsg-.
dso    8
vax    1
vax    2 $    vax       d. shields          21 nov  78          level 78325
vax    3 $              r. kenner
vax    4 $
vax    5 $    add configuration values for s32: dec vax-11/780.
vax    6 $    decks affected - macros, start, lexini.
vax    7
dsn    1
dsn    2 $    dsn       d. shields          25 sep 78           level 78268
dsn    3 $
dsn    4 $    1.  increase macro table length for setl use.
dsn    5 $    2.  add code for resident s10 compiler.
dsn    6 $    decks affected - macros, start, lexini.
dsn    7
       3
       4 $    chars     d. shields          30 may 78           level 78150
       5 $
       6 $    include deck chars to describe character set to assist in
       7 $    correct translation of source text for new machines.
       8 $    correct error in use of cdc character set so that apostrophe
       9 $    represented by cdc display code 3b'70' (up arrow).
      10 $    decks affected - all (source resequenced).
      11
      12 $    rbkh      r. kenner           01 mar 78           level 78060
      13 $              d. shields
      14 $
      15 $    1.  increase dimension of names for s37.
      16 $    2.  correct size error in lexdir.
      17 $    3.  avoid sending line twice just after  .=list input
      18 $    decks affected - macros, lexdir, givecr.
      19
      20
      21 $    rbkg      r. kenner           04 jan 78           level 78004
      22 $
      23 $    1.  correct some errors in s37 conditional code.
      24 $    2.  permit use of s-type tokens, which are delimited with
      25 $        code s, as in '3sabc'.  s-tokens are machine-dependent, and
      26 $        are for use on machines such as s10 and s11 with a 'system-
      27 $        format' string.
      28 $    3.  change 'subr start' to 'prog start' for s37 since no
      29 $        overlaying of phases occurs.
      30 $    4.  fix code mostly in -lexca- which handles work-to-do on a
      31 $        card since the gen 'fix' on taking .not. of a constant makes
      32 $        it incorrect as written.  (the problem is that ^(^1b'100') is
      33 $        ^(1b'11') which yields 1b'0', not the 1b'100' that
      34 $        might be expected.)
      35 $    5.  slightly clean up exit code in -lexexit- when no token file
      36 $        is specified.
      37 $    6.  correct bug in processing of -zzy- tokens in open text.
      38 $    decks affected - macros, start, lexini, lexdo, trulex, givecr,
      39 $                     lexca, lexdir, pflshr, lexexit
      40
      41
      42 $    dsm       d. shields          08 dec 77           level 77342
      43 $
      44 $    correct error in real constants with negative exponent.
      45 $    deck affected - trulex.
      46
      47
      48 $    rbkf      r. kenner           27 oct 77           77300
      49 $
      50 $    this mod improves the handling of programs with a lot of
      51 $    comment lines by not sending lines to gen unless the gen
      52 $    list option is on or the lines contain tokens.  in order
      53 $    for gen to keep the line numbers correct, the number of
      54 $    cards that a particular card represents is sent in the
      55 $    -toklc- field of the token for the card.
      56 $    this mod requires mod rbkk in gen.
      57 $    decks affected - start, lexdo, givecr, hash, lexexit
      58
      59
      60 $    rbkee     r. kenner           07 oct 77           77280
      61 $
      62 $    this mod corrects some errors in mod rbke.  the most important
      63 $    error was one in the routine -hash-.
      64 $    decks affected - macros, start, setlit, nextw, trulex, hash,
      65 $                     pflshr, ermsg
      66
      67
      68 $    rbke      r. kenner           07 sep 77           77250
      69 $
      70 $    this is mostly an internal cleanup mod.  the following are the
      71 $    major areas of change.
      72 $    1.  conditional code is added for s10 (dec system/10).
      73 $    2.  lexical punch code has been rewritten to bring it more
      74 $        up to date, clean it up, and clean up the format of
      75 $        the punched output.
      76 $    3.  -nextw-, -defabsrb-, and -mcexpand- are now only called
      77 $        when they are actually needed.  in most cases, most
      78 $        of the work is now done in -lexdo-.
      79 $    4.  error messages are now more informative and, in most
      80 $        cases, errors do not pass 'junk' to gen.
      81 $    5.  -astk- overflow is now not fatal but aborts macro
      82 $        expansion.
      83 $    6.  table definitions for s37 have been changed.
      84 $    7.  the dimension of the -ha- is now larger than the
      85 $        prime used to allow the first few clashes to be
      86 $        put in a separate area.  also, some tests have been
      87 $        reordered.
      88 $    decks affected - all (source has been resequenced)
      89
      90
      91 $    dsl       d. shields          26 jul 77           level 77206.
      92 $
      93 $    add program parameter 'termlex=0/1' to permit termination of
      94 $    compilation at end of lexical scan.
      95 $    decks affected - start, lexini, lexexit.
      96
      97
      98 $    dsk       d. shields          20 may 77           level 77140.
      99 $
     100 $    reported bug - macro '+* stk(a,b) = ; **' expands incorrectly.
     101 $    cause - special case code for one symbol macros did not check
     102 $        to see if macro had arguments.
     103 $    moral - special cases need special care.
     104 $    deck affected - defabs.
     105
     106
     107 $    dsjj      d. shields          05 may 77            level 77125.
     108 $
     109 $    reported bug - warning message for macro redefinition given twice.
     110 $    fix - remove duplicated code (introduced by mod dsj).
     111 $    deck affected - defabs.
     112
     113
     114 $    dsj       d. shields          08 april 1977       level 77098.
     115 $
     116 $    1.  improve diagnostic message if mstk overflow.
     117 $    2.  accept '.=member' directives in primary input file.
     118 $    3.  detect 'immediate', or one symbol macros, and use the macorg
     119 $        field to expand the macro, thus saving space in mtab.
     120 $        add the ha field 'macimm' which is on if macro is immediate.
     121 $        (suggested by art grand.)
     122 $    4.  increase dimension of mtab.
     123 $    decks affected - nextw, defabs, lexdir.
     124
     125
     126 $    dsi       d. shields          03 february 1977    level 77034.
     127 $
     128 $    1.  redefine origin of zzy and zzz symbols to be zero so first
     129 $        generated symbol or integer has index one.
     130 $    2.  use different counters for zzy and zzz symbols.
     131 $    3.  list active zzy counter values at end of scan.
     132 $    4.  increase length of macro table to permit compilation of new
     133 $        setl library.
     134 $    decks affected - macros, start, defabs, buildz, macexp,
     135 $        lexdir and lexexit.
     136
     137
     138 $    dsh       d. shields          31 january 1977     level 77031.
     139 $
     140 $    1.  adapt lex for s66 to support both 63 and 64 character sets.
     141 $        do this by accepting both 3b'63' and 3b'00' as valid forms of
     142 $        the 'colon' character in little.  implement by hashing these
     143 $        values in absolute form to initialize in imtoktab and setting
     144 $        literal codes of both entries to 70, the literal code for
     145 $        'colon'.
     146 $        code must be changed if literal code of colon changed.
     147 $        this change applies to s66 only - all code conditional.
     148 $    2.  repair error in trulex, which was not detecting real constants
     149 $        beginning with decimal point.
     150 $    3.  abort scan if input file empty.
     151 $    decks affected - lexini, trulex, lexexit.
     152
     153
     154 $    dsg       d. shields          07 january 1977     level 77007.
     155 $
     156 $    1.  repair error in -list- directive, as 'list input' was not
     157 $        recognized due to size introduced in prior mod.
     158 $    2.  define -zzy- counters to be one-origin, not zero origin.
     159 $    3.  at request of setl group, install directive to reset
     160 $        -zzy- counters.  the directive ' .=zzyorg' has as
     161 $        parameter a list of characters indicating the counters
     162 $        to be reset to one.  for example,
     163 $            .=zzyorg csr
     164 $        resets the counters zzyc, zzys and zzyr.
     165 $    4.  change keyword -debug- to -monitor-.
     166 $
     167 $    remaining changes adapt lex to new language level and library.
     168 $    trulex has been rewritten, and some source cleanup done.
     169 $
     170 $    5.  use -getipp- and -getspp- to obtain program parameters at
     171 $        execution time.
     172 $    6.  use new sio for io for token, punch and reference files.
     173 $    7.  keep macro argument count, which was ha field -macargs-, as
     174 $        first entry in macro text table -mtab-.
     175 $    8.  revise hash algorithm to use algorithm 'c' of knuth
     176 $        (see comments in procedure -insglor- in -gen-).
     177 $    9.  pad -names- entries with blanks, not binary zeros.
     178 $   10.  recode trulex to support only new language level.
     179 $        salient points are as follows:
     180 $        1.  drop support of token types -d-, -h-, -z-, -l- and -b-.
     181 $        2.  assign -q- tokens lexical type -stringtok-, as q tokens
     182 $            are just another way of writing character strings.
     183 $        3.  avoid use of finite state automaton to drive scan.
     184 $            large number of special actions makes straight code
     185 $            clearer and more efficient.
     186 $        4.  distinguish two cases of 'get next character' primitive.
     187 $            use -givec(c)- to get character via procedure call.
     188 $            use -giveq(c)- to get character via inline code.
     189 $        5.  implement -givecstr- primitive as procedure cal.
     190 $        6.  code for -ieof- end of file option retained, but is
     191 $            probably incorrect if enabled.
     192 $
     193 $    source has been resequenced.
     194 $
     195 $    decks affected - all.
     196
     197
     198 $    dsf       d. shields          20 november 76      level 76325.
     199 $
     200 $    convert to use new -sio.  drop use of following routines:
     201 $        opnpun, putpun, clspun, opntok, puttok, clstok.
     202 $    decks affected: macros, start, lexini, pncr, lexexit.
     203
     204
     205 $    rbkd      r. kenner           1 november 76       level 76306
     206 $
     207 $    fix bug in macro processor causing stores into the zero word
     208 $    of -astk-.
     209 $    deck affected - nextw
     210
     211
     212 $    dse       d. shields          8 oct 76            level 76282.
     213 $
     214 $    add literals:  read  write  prog  .seq.  .sne.
     215 $    literal codes   93     94    95     96     97  .
     216 $    deck affected - inslit.
     217
     218
     219 $    rbkc      r. kenner           29 july 76          level 76211
     220 $
     221 $    1.  fix bug causing compilation error if -oldtoks- is set.
     222 $    2.  fix bug in -lexca-.
     223 $    3.  change -slen- macro to use .len.
     224
     225 $    rbkb      r. kenner           21 july 76          level 76203
     226 $
     227 $    1.  add conditional option 'oldtoks' to allow usage of old-style
     228 $        tokens.  in this mode, an error message will be given for
     229 $        each such token.  if 'oldtoks' is not set, usage of old-style
     230 $        tokens is not allowed.
     231 $    2.  add literal codes for 'limit', 'debug', and 'rewind'.
     232 $    3.  improve error message content and format.
     233 $    4.  change parameter used to specify an initial inclusion
     234 $        member to 'imem' (it was -incl-).
     235 $    5.  support 'term' parameter.  it specifies a file name to
     236 $    receive copy of error messages.
     237 $    6.  add -ejectl- and -stitlr- calls to improve formatting of
     238 $        output listing.
     239 $    7.  extend listing control by rewriting -givecr- and
     240 $        adding -lexca- to handle condition processing.  -lexca-
     241 $        replaces some code previously in -givecr- and is called
     242 $        by -givecr-.  changes at the user level are:
     243 $        1.  the list parameter -sinput- has been changed to
     244 $            -linput- and the corresponding letter in the 'list'
     245 $            compilation parameter is now 'l' instead of 's'.
     246 $        2.  the following parameters have been added to the -list-
     247 $            directive:
     248 $                    autotitle          instructs -gen- to use the
     249 $                                       -subr- or -fnct- statement as
     250 $                                       a subtitle and use 'title'
     251 $                                       directives as main title.
     252 $                    skip               instructs -gen- to list lines
     253 $                                       of text skipped by conditional
     254 $                                       processing.
     255 $                    qualifiers         instructs -gen- to list the
     256 $                                       conditional qualifiers.
     257 $                    directive          instructs -lex- and -gen- to
     258 $                                       list the directive on which
     259 $                                       this parameter appears.
     260 $            note that 'no' may preceed each of these to negate the
     261 $            effect and that each may be indicated in the compiler
     262 $            'list' parameter by its first letter.
     263 $            also, 'dir'/'nodir' may appear on 'punch'.
     264 $        3.  default is  .=list noaut,nolin,noinp,nocod,ref,noski,noqua
     265 $
     266
     267
     268 $    dsd       d. shields          28 june 76          level 76180.
     269 $
     270 $    revise listing control.
     271 $        lines with ' .=' in columns 1 through 3 are directives.
     272 $
     273 $        the ' .=title' directive sets the listing title.  the
     274 $        directive contains a quoted string which is the title text.
     275 $        the first title directive defines the main title which appears
     276 $        on the top of each page; remaining directives set the subtitle
     277 $        and cause a page eject.
     278 $
     279 $        the ' .=eject' directive begins a new page of listing.
     280 $        an optional integer parameter may be supplied, in which case
     281 $        a new page is begun only if less than the indicated number of
     282 $        lines remain on the current listing page.
     283 $
     284 $        the ' .=list' and ' .=punch' directives control listing and
     285 $        macro 'punch' control, respectively.
     286 $        each of these directives may contain a list of parameters,
     287 $        separated by commas.
     288 $        an option is disabled by putting the letters 'no' in front.
     289 $        only the first three characters of the parameter code are
     290 $        examined.
     291 $
     292 $        the parameters for the punch directive are 'define', to
     293 $        punch macro definitions and 'expand' to punch expanded text.
     294 $
     295 $        the parameters for the list directive are as follows:
     296 $            code - list generated code.
     297 $            input - list source input in parse (gen) phase.
     298 $            ref - collect references if cross reference feature on.
     299 $            sinput - list source input in scanner (lex) phase.
     300 $
     301 $        all options are off by default except for 'ref'.
     302 $
     303 $        a stack is kept of the most recent twenty or so list
     304 $        directives. the parameter 'resume' may be used to restore
     305 $        list control to that established by the previous list directiv
     306 $
     307 $        the list directives may be initialized by the control card
     308 $        option 'list' which accepts a list of character codes.
     309 $
     310 $            c   enable 'code' option.
     311 $            d   enable 'define' option for punch.
     312 $            e   enable 'expand' option for punch.
     313 $            i   enable 'input' option.
     314 $            s   enable 'sinput' option.
     315 $            0   ignore list directives in input.
     316 $
     317 $        if 'list' alone occurs, 'list=i' is implied.
     318 $
     319 $    include feature for remote text.
     320 $
     321 $        directives of the form ' .=include  name' indicate that
     322 $        the line in the text is to be replaced by member 'name' of
     323 $        a text library.  the compiler option 'ilib' may be used to
     324 $        name a member to be included before the input file is read,
     325 $        thus permitting inclusion of a standard text prelude.
     326 $
     327 $        inclusion processing is contained in the new library routines
     328 $        'opninc', 'getinc' and 'clsinc' which are similar to the
     329 $        routines 'opninp', 'getinp' and 'clsinp' previously used to
     330 $        read the input file.
     331 $
     332 $    environment symbol '.compdate.' for compilation date.
     333 $
     334 $        an instance of the symbol .compdate. is replaced by a
     335 $        character string of length 30 which gives the date of
     336 $        compilation.  the format is that returned by the 'lctime'
     337 $        library primitive.
     338 $
     339 $    use of new library listing features.
     340 $
     341 $        this version of lex uses the extended version of the standard
     342 $        print routines which recognizes pages and permits page titles.
     343 $
     344 $    decks affected = all.
     345
     346
     347 $    rbka      r. kenner           24 may 76           level 76147.
     348 $              d. shields
     349 $
     350 $    1.  use ps for ws whenever possible (better on s37).
     351 $    2.  allow 'iset' option to set initial conditional name;
     352 $        for example, 'iset=tr' corresponds to insertion of card
     353 $        ' .+set tr' before start of input.
     354 $    3.  generate initial set for symbol 'snn' where nn is target
     355 $        machine as determined by 'tm' option.
     356
     357
     358 $    cra       d. shields          04 may 76               level 76125
     359 $
     360 $    cross-reference processing is now done as follows.
     361 $    the individual routine reference list is no longer available, as
     362 $    global map obtained by compiling routines of interest provides
     363 $    essentially the same information.
     364
     365 $    the lexical phase writes two files.  the reference file contains
     366 $    a list of ha indexes and line numbers.  the ha file defines the
     367 $    ha and includes a count of the total number of references, etc.
     368 $    the gen phase writes a third file which indicates the subroutine
     369 $    boundaries.
     370 $
     371 $    the reference list is generated by a separate program, 'ref',
     372 $    which reads in the files, sorts the ha and reference list,
     373 $    eliminates duplicate references and formats the listing.
     374 $
     375 $    reference file 1 contains a list of references, each defined by
     376 $    three fields:
     377 $    1.  line number
     378 $    2.  ha index of symbol.
     379 $    3.  flag set if name currently is macro.
     380 $    the list is terminated with a zero entry.
     381 $
     382 $    structure of reference file 2 is as follows:
     383 $    each entry is word-size.
     384 $    1.  total number of references.
     385 $    2.  last line number.
     386 $    3.  ha dimension.
     387 $    4.  number of words required to store names in ha.
     388 $    there follow a variable number of entires defining the ha,
     389 $    as follows:
     390 $        1.  ha index.
     391 $        2.  length of name.
     392 $        3.  name, packed cpw characters per entry, and
     393 $            right adjusted.
     394 $
     395 $    every ha entry referred to in the reference list must be
     396 $    specified.
     397 $    the list is terminated by an entry of 0.
     398 $
     399 $    the files are written using -sio- with fixed-length records.  the
     400 $    record length is a parameter, -crbuffmax-, whose value must agree
     401 $    with that used in -gen- and -ref-.
     402 $
     403 $    the files are identified internally by number.  the parameter
     404 $    'rf' gives a file name skeleton from which the name is generated
     405 $    by replacing the last numeric character by the appropriate numeric
     406 $    character.  the library routine -crfnam- performs this task.
     407
     408 $    the suspicious variables function is now realized by internal
     409 $    sort of ha.
     410 $    routines affected - macros, start, hash, detect, lexexit.
     411 $    routines deleted - maklinz, mastlis, purger, sorter, mem.
     412 $    the source has been resequenced.
     413
     414
     415 $    dsc       d. shields          19 april 1976       level 76110
     416 $
     417 $    support revised form of bit string constants.  this form consists
     418 $    of a 'width' specifier of 1,2,3 or 4 followed by 'b' and then
     419 $    immediately followed by a quoted string containing blanks and bit
     420 $    values.  the width indicates the number of bits defined by each
     421 $    nonblank character.  the characters 'a', 'b', 'c', 'd', 'e' and
     422 $    'f' are used for width 4 in the usual hexadecimal sense.
     423 $    for example, the integer 13 is equivalent to each of the following
     424 $    bit constants:  1b'1101'  2b'31'  3b'15'  4b'd' .
     425 $    the 'b' and 'l' format bit constants will soon be dropped.
     426 $    decks affected - macros, lexini, trulex, lexexit, ermsg.
     427
     428
     429 $    dsb       d. shields          14 april 76         level 76105
     430 $
     431 $    1.  use .ws., .ps., etc. for machine parameters.
     432 $    2.  be more consistent in use of tokch.
     433 $    3.  correct errors in generation of 'zzz' type tokens.
     434 $    4.  replace 'goby' statements with indexed 'go to'.
     435 $    decks affected - macros, lexini.
     436
     437
     438 $    dsa       d. shields          25 march 1976       76085
     439 $
     440 $    continue work on system/370 version, as follows.
     441 $    1.  eliminate uses of eqsds, .s. and .e.
     442 $    2.  use lctime to obtain time and date.
     443 $    3.  change name countupr to ltoflo.
     444 $    4.  initialize some previously unitialized variables.
     445 $    5.  change fivdec to return array of chars, not string.
     446 $
     447$     the source has been resequenced.
     448
     449
     450 $    ldsy      d. shields          20 january 1976     level 76020
     451 $
     452 $    1.  allow up to 31 arguments in macros.
     453 $        (this has required change in litcod field position.)
     454 $    2.  eliminate 'no list dollar' option.
     455 $    3.  add options 'lcp' and 'lcs' to allow selection of
     456 $        listing of parameters and statistics.
     457 $        'lcp=0' suppresses parameter listing.
     458 $        'lcs=0' supresses statistics listing.
     459 $    4.  add option 'lel' to permit selection of maximum allowed
     460 $        number of errors.
     461 $    5.  change format of parameter listing.
     462 $    decks affected - start, lexini, givec, lexexit, ermsg.
     463
     464
     465  $   ldsx      d. shields          01 january 1976     level 76001
     466 $
     467 $    change literal codes to correspond to level 76001 of gen.
     468 $    fix error in purger, so duplicate entries eliminated.
     469 $    decks affected - setlit, purger
     470
     471
     472 $    ldsw      d. shields          06 november 1975    level 75310
     473 $
     474 $    1.  if a name used as a macro within a routine, insert '+*' on
     475 $        first line of reference list for each routine.
     476 $    2.  do not collect references to 'subr' or 'fnct'.
     477 $    decks affected - macros, hash, maklinz
     478
     479
     480 $    ldsv             d. shields         27 october 1975
     481 $
     482 $    eliminate literal codes for io keywords no longer used:
     483 $          17'readb'  18'read'  19'writb 20'write  22'endfile'
     484 $    and define new literal codes as follows:
     485 $          17'elseif'  18'in'  19'.sds. 20'.voapart.'
     486 $    (code 22 thus not used now).
     487 $    the level is now 75300.
     488 $    deck affected - setlit
     489
     490
     491 $    ldsu          d. shields         15 september 1975
     492 $
     493 $    reported bug - not all subroutine boundaries seen by cross-ref opt
     494 $    fix - fine tune the automaton in hash to detect case when routine
     495 $    ends in 'end' followed by literals followed by 'end subr/fnct'.
     496 $    deck affected - hash
     497 $    the level is now 75258.
     498
     499
     500 $    ldst          d. shields       7 july 75
     501 $
     502 $    the line numbers in the 'complete' cross-reference map
     503 $    (xra=1) are now given relative to the start of the routine.
     504 $    the level is now 75188.
     505 $    decks affected - purger, mastlis, maklinz
     506
     507
     508 $    ldss       d. shields        2 july 75
     509 $
     510 $    reported bug - routine boundaries not seen during cross-
     511 $    reference listing generation.
     512 $    fix - -hash- was not passing tokens 'subr' 'fnct' and 'end'
     513 $    to cross reference code.
     514 $
     515 $    the 'tally' option is now expressed as separate options
     516 $    'tallytokens', 'tallycomments' and (new) 'tallyhash', which
     517 $    measures symbol table access.
     518 $    deck affected - hash
     519 $    the level is now 75183.
     520
     521 $    ldsr          d. shields         4 june 75
     522 $
     523 $    this ident simplifies some of the initializations, particularly
     524 $    for the literals.  new literals
     525 $        .ws.  .ps.  .cs.  .sl.  .so.
     526 $    have been added, in anticipation of 'machine parameter' option.
     527 $    the level is now 75155.
     528 $    decks affected - lexini, setlit
     529
     530
     531 $    ldsq         d. shields      30 may 75
     532 $
     533 $    this correction changes the handling of file names to use
     534 $    sds format names instead of machine dependent z-format
     535 $    previously used.
     536 $    file names of up to -filenamelen- chars (currently 20) are
     537 $    allowed.  default names are given by macros which may be
     538 $    adjusted to fit different systems.
     539 $    control card parameters are now obtained using
     540 $    library routine -reados-.
     541 $    the format of error messages has been changed.
     542 $    decks affected - macros,lexini,ermsg(resequenced
     543 $    the level is now 75150
     544
     545
     546 $    nmchar       d. shields       23 may 75
     547 $
     548 $    this correction extends the language to include n-type tokens.
     549 $    n-type tokens are used to define names and are similar in format
     550 $    to the -r-, -h-, -z-, and -d- tokens, except the letter -n- is
     551 $    used.  n-type tokens permit the use of non-standard characters
     552 $    in names; possible uses include protection of library
     553 $    names to avoid conflict with user names.  for example,
     554 $    'call 3nio.(a,b)' is a call to routine with name 'io.'.
     555 $    the level is now 75143.
     556 $    decks affected - lexini, trulex
     557
     558
     559 $    ldsp             d. shields           9 april 75
     560 $
     561 $    reported bug - string 'zzzz' processed as though were name.
     562 $    fix - restrict test for zzz-zzy type tokens to names.
     563 $    the level is now 75099.
     564 $    decks affected - nextw, dfabsrb
     565
     566
     567 $    astkmsg       d. shields      31 march 75
     568 $
     569 $    this correction provides improved diagnostic support if
     570 $    macro argument has unbalanced parenthesies.  previously,
     571 $    the scanner continued search over input until -astk- overflow
     572 $    occurred, causing fatal termination.  the resulting messages
     573 $    were confusing to users and provided little help, as error
     574 $    actually occurred several hundred tokens before point of overflow.
     575 $    the new scheme is as follows - when we start to collect a macro
     576 $    argument, we save current line number; during argument collection
     577 $    we watch for argument overflow, so that we can indicate most likel
     578 $    source of problem.
     579 $    the level is now 75090.
     580 $    decks affected - macros (astkput only), nextw, ermsg.
     581
     582
     583 $    litcod        e deak              23 feb 75
     584 $
     585 $    all keywords and literals are given literal codes.
     586 $    a litcod field is set in the ha for them (lexini). the
     587 $    literal code is passed to gen in tokhdr in new field tokrlc.
     588 $    the mapping of literals onto litcodes must be identical in gen
     589 $    and lex.
     590 $    decks affected are macros, hash, detect, genini
     591
     592 $
     593 $    ldso        d. shields       6 march 75
     594 $
     595 $    reported bug - unexpected instance of '/ *' within
     596 $        pl1 comment observed.
     597 $    fix - trulex had incorrect test for termination of pl1
     598 $    style comment if even number of * preceded terminal /.
     599 $    the level is now 75065.
     600 $    deck affected - trulex
     601 $
     602
     603 $    ldsn         d. shields       18 february 75
     604 $
     605 $    to dimensions of -ha- and -names- have been increased to permit
     606 $    compilation of -gen- which supports new i/o features.
     607 $    the level is now 75049.
     608
     609 $    ldsm          d. shields          6 november 74
     610 $
     611 $    reported bug - sequence '1. else' converted to '1. lelse'.
     612 $    fix - error in detection and backup of real constants
     613 $    fixed in trulex.
     614 $    reported bug - punch routines punch '1b' as '21b'.
     615 $    fix - octal tokens were being handled as though
     616 $    they were strings by -pncr-.  test of token type fixed.
     617 $    the initialization of actab has been adjusted so that names
     618 $    always collected in separate loop, and comment just following
     619 $    definition of actab in trulex has been brought up to date.
     620 $    the level is now 74310.
     621 $    decks affected - lexini, trulex, pncr.
     622
     623 $    ldsl          d shields           6 november 74
     624 $
     625 $    this correction modifies definition of real constants so that
     626 $    blanks only allowed inside such constants if they occur between
     627 $    two numeric characters.  the previous definition, while satis-
     628 $    factory for little, caused problems in new setl front end.
     629 $    the macros -addtotok-, -retbuf- and -abuf- are no longer needed,
     630 $    and so have been eliminated, as have variables
     631 $    numflag and expflag within trulex
     632 $    decks affected - macros, trulex
     633
     634
     635 $    ldsk          d shields           7 october 74
     636 $    this correction makes a few changes to ease system/370 bootstrap
     637 $    -  time and date now expressed by functions -timestr- and
     638 $        -datestr- which return array of characters (8)
     639 $    -  control card parameters and file names changed to not exceed
     640 $        four characters in length
     641 $    -  default for -detect- option changed to -no- for 370 to
     642 $        avoid use of random/access routnes in initial bootstrap
     643 $    deck affected - macros, start, lexini
     644 $    the level is now 74280
     645
     646 $
     647 $    ldsj             d. shields       13 august 74
     648 $
     649 $    this correction set
     650 $    1.  fixes two errors in trulex in detection of real constants
     651 $        (bug reported and fixed by d. mirante).
     652 $    2.  reduces mtab size to 8000 from 12000.
     653 $    3.  corrects countup macro (quitting one entry too soon).
     654 $        last line listed if abort via countup.
     655 $    4.  dayfile message suppressed if no errors.
     656 $    the level is now 74225
     657 $    decks affected - macros,trulex, users of -countup- macro
     658 $
     659
     660 $    ldsi          d shields      29 july 74
     661 $
     662 $    this correction fixes an error in macro-processor, slightly
     663 $    recodes  a test which inadvertently was calling off-line
     664 $    multi-word routines.
     665 $    - the error in detect causing  only last line to be listed
     666 $        has been fixed.
     667 $    decks affected - macros, nextw, detect
     668 $    the level is now 74210
     669
     670 $    ldsh         d. shields        18 july 74
     671 $
     672 $    this correction fixes error in trulex in handling of blanks
     673 $    inside numerical constants.
     674 $    the level number is now 74199
     675 $    deck affected - trulex
     676
       1 .=member macros
       2
       3      $   conditional assembly options.
       4
       5
dsq   16      $   select lc if lower-case characters available.
dsq   17
dsv   17 .+set mc  $ assume mixed-case characters available.
dsv   18
dsv   19 $    if mixed-case available, default primary case is upper.
dsv   20 $    obtain lower primary case by defining mcl.
dsq   19
       6      $   select mp to include little macroprocessor.
       7 .+set mp
       8
       9      $   select ca to include conditional assembly feature.
      10 .+set ca
      11
      12      $   select cr to include cross-reference function.
      13 .+set  cr
      14
      15      $   following options used to collect performance statistics.
      16      $   select tallycomments to count number and type of comments.
      17 .+set  tallycomments
      18
      19      $   select tallytokens to count number of tokens sent to parser.
      20 $-set tallytokens
      21
      22      $   select tallyhash to monitor hash table probes.
      23 .+set  tallyhash
      24
      25      $   select ht to include code supporting .hatr. and .nohatr.
      26      $   ha trace tokens.
      27 $-set ht
      28
      29      $   select ct to include code supporting .chtr. and .nochtr.
      30      $   character trace tokens.
      31 $-set  ct
      32
      33      $   select mt to include code supporting .mactr. and .nomactr.
      34 $-set  mt
      35
      36      $   select mtgc to include empty entry at start of each macro
      37      $   definition to permit macro garbage collection.  as garbage
      38      $   collector not expected soon, text usually not included.
      39 .-set  mtgc
      40      $   select bub if scanner runs together with parser which requires
      41      $   token back-up (bub stands for b-ack u-p b-uffer).  do not
      42      $   select if scanner runs as separate parse phase or job step.
      43 .-set  bub
      44
      45      $   select sdspack_env if special library code provided to do
      46      $   token pack into hashtok.
dsn    8 .+s10.
dsn    9 .+set  movea_env
dsn   11 .+set  sdspack_env
dsn   16 ..s10
      47 .+s66.
      48 .+set  sdspack_env
dsv   21 .-set mc  $ s66 upper-case only
      49 ..s66
utsb   1
utsb   2 .+s32.
utsb   3 .+set s32v  $ assume vms.
utsb   4 ..s32
utsb   5
utsb   6 .+s32u.
utsb   7 .+s32.
utsb   8 .-set s32v  $ do not want vms.
utsb   9 .+set s32u  $ want unix os.
utsb  10 ..s32
utsb  11 .+set mcl   $ want primary case to be lower.
utsb  12 ..s32u
utsc   1
utsb  14 .+s32.
vaxb   1 .+set sdspack_env,bskp_env,movea_env
vax   11 ..s32
      50 .+s37.
      51 .+set sdspack_env,bskp_env,movea_env
      52 ..s37
utsa   8 .+s47.
utsa   9 .+set mcl  $ primary case is lower
utsa  10 .-set sdspack_env,bskp_env,movea_env
utsa  11 ..s47
      53
      54      +*  scannerlevel =  $ julian date of last scanner change
ldsa  10           'lex(81324)'  $ 20-nov-81
      56      **
      57
      58
utsb  15 .+s32u.
dsv   24 $    configure for unix, set primary case lower.
dsv   25 .+set mcl
dsv   26 $    for initial checkout, delete efficiency env options.
dsv   27 .-set sdspack_env,bskp_env,movea_env
utsb  16 ..s32u
      59
      60
      61
      62      +*  ws = .ws. **  $ machine word size in bits.
      63
      64      +*  ps = .ps. **  $ machine pointer (address) size in bits.
      65
      66      +*  cs = .cs. **  $ character size in bits.
      67
      68      +*  slen = .len. **  $ length field of self-defining string (sds)
      69
      70      +*  sorg = .f. .sl.+1, .so., **  $ origin field of sds.
      71
      72      +*  sds(n) = .sds. (n) **  $ size of n-character sds.
      73
      74      +*  cpw = (ws/cs) **  $ no. of characters in machine word
      75
dsv   29 .+mc.
dsv   30 .+mcl.   $ if mixed-case to be lower
dsv   31      +*  ctpc(x) = ctlc(x) **  $ primary case is lower.
dsv   32      +*  stpc(x) = stlc(x) **  $ primary case is lower.
dsv   33 .-mcl.
dsv   34      +*  ctpc(x) = ctuc(x) **  $ primary case is upper.
dsv   35      +*  stpc(x) = stuc(x) **  $ primary case is upper.
dsv   36 ..mcl
dsv   37 ..mc
      82      +*  ms = $ size of macro definition item (must divide ws)
      83 .+s66    15
vax   14 .+s32    16
      84 .+s37    16
utsa  12 .+s47    16
habb   1 .+s10    18
      86          **
      87
      88      +*  wpc =   $ number of words per card
      89 .+s66    9 $ read 9 words (90 columns) for cdc 6600
vax   15 .+s32    20  $ assume 80 columns in input card
      90 .+s37    20  $ assume 80 columns in input card
utsa  13 .+s47    20  $ assume 80 columns in input card
mgfa  14 .+s10    20  $ assume 80 columns in input card.
      92          **
      93
      94      +*  filenamelen =  20 ** $ maximum file name length in chars
vaxc   1 .+s32    +*  filenamelen =  64 ** $ maximum file name length in chars
utsa  14 .+s47    +*  filenamelen =  64 ** $ maximum file name length in chars
      95
      96      +*  tokenfile = 3 **  $ token file number.
      97
dsr   12 $    getapp_len is length of actual parameter string (cf. lexini).
dsr   13          +*  getapp_len = 128  **
dsr   14 .+s32    +*  getapp_len = 240 **
utsa  15 .+s47    +*  getapp_len = 240 **
      98
      99      +*  punchfile = 6 **  $ punch file number.
     100
     101      +*  crfile = 5 **  $ cross reference file number.
     102
     103 .+cr.
     104      $   fields of cross-reference entry.
dsu   12      +*  cref_line  = .f. 01, 16, **  $ line number of reference.
ldsa  11      +*  cref_ha    = .f. 17, 14, **  $ ha index of item.
ldsa  12      +*  cref_macro = .f. 31, 01, **  $ 'is name currently macro'.
     108
     109      +*  crbuffmax = 256 **
     110
     111      +*  crefput(i) =
     112          crbuffptr = crbuffptr + 1;
     113          crbuff(crbuffptr) = i;
     114          if  crbuffptr = crbuffmax  then
     115              call wtrwsio(crfile, iorc, crbuff, 1, crbuffmax);
     116              crbuffptr = 0;
     117              end if;
     118          **
     119 ..cr
     120      +*  lstimelen = 30 **  $ length of lstime time representation.
     121      +*  mccd = 72 **  $ rightmost column of input processed
     122      +*  numbugtoks = 9 **   $ number of special period delim toks
     123      +*  listarglim = 31 **  $ max. no. of macro arguments.
     124          $ arguments, is dimension is array listarg in routine nextw
     125      +*  namesmax =          $ dimension of names array.
ldsa  13 .+s32    12000
ldsa  14 .+s37    12000
utsa  16 .+s47    12000
ldsa  15 .+s66    5000
ldsa  16 .+s10    12000
     129          **
     130
     131      +*  mtlim =  $ max. number of entries in mtab, macro def. table.
dsu   19          10000
     133          **
     134
     135      +*  mstklim = 100 ** $ limit of mstk.
     136
     137      +*  lsvtkz = 15 **  $ dims of -lsvtk-, must be 2**k-1
     138
     139
     140 .+bub    +*  reslim = 20 **  $ limit on reserved token stack in nextw
     141
     142      +*  maxtoklen = 127 **  $ max. token length in characters
     143      +*  hashtokorg = $ origin for hashtok string, fixed always
     144          (1 + .sds. (maxtoklen+cpw)) **
     145
     146      +*  listprevmax = 10 **   $ depth of listing status saved.
     147
     148      +*  tokrbuflim = 256 **  $ no of entries in token buffer
     149
     150      +*  hasz = $ size of ha in bits
dsu   20 .+s66    120
vax   17 .+s32    64
     152 .+s37    64
utsa  17 .+s47    64
     153 .+s10    72
     154      **
     155
     156 $        note that the dimension of the ha must be a prime
     157 $    selection of primes is machine dependent and is discussed in
     158 $    'the art of computer programming', d. e. knuth, vol 3.
     159 $    pp 508-509.
     160 $    in brief, condition is to find p such that
     161 $    r exp k is not congruent to a modulo p, where
     162 $    r is radix of character set (64 for 6600),
     163 $    k and a are small integers.
     164 $    not that if r exp k is congruent to a mod p, then
     165 $    hash of 'ab' is close to sume of hash 'a' and hash 'b'.
     166
     167 $    suggested values for s66 are: 4073, 3613, 3329, 2969.
     168
ldsa  17 .+s66   +* haprime = 3929 ** $ keep old value for s66
ldsa  18 .-s66  +* haprime = 4507 **
     170
     171      +*  hadim = (haprime + haprime/25) **  $ leave space at top.
     172
     173      +*  suspi=2 **  $  nuses threshhold used by detect
     174
     175
     176      +*  sdstl  =  $ macro giving needed size for std token string
     177          (.sds. 20) **
     178
     179 $      macros for token types assigned by scanner
     180
     181      +*  nametok = 1         **  $  name
     182      +*  spectok = 2         **  $  special, eg  () + -
     183      +*  optok  = 3          **  $  period delimited operator, eg  =
     184      +*  dectok = 4          **  $  decimal integer, eg  100
     185      +*  sstok = 5 **    $ 'special' string token
     186      +*  stringtok = 6       **  $  constant string, eg  'message'
     187      +*  bittok = 8 **       $ bit string
     188      +*  rztok = 12 **       $ r-type token, right zero fill
     189      +*  realtok = 14 **          $ real constant
     190
     191      +*  cpstr = $ characters per short token record
     192 .+s66    6
vax   18 .+s32    1
     193 .+s37    1
utsa  18 .+s47    1
mgfa  16 .+s10    1
     195          **
     196
     197      +*  listcontroltok = 27 **  $ .=list directives.
     198      +*  listejecttok   = 28 **  $ .=eject directive.
     199      +*  listtitletok   = 29 **  $ .=title directive.
     200      +*  tokrcard = 30 **    $ tyoen-record code for card image
     201      +*  tokreof = 31 **     $  token file code for end-of-file
     202 .-s66.   $ new values.
     203      +*  tokrtyp = .f. 1, 8, **  $ token-record code for lexical type
     204      +*  tokrlen = .f. 9, 8, **   $  toeen-record code for no of chars
     205      +*  tokrlc = .f. 17, 8, **  $ token literal code
     206 .+s66.  $ old values for now.
     207      +*  tokrtyp = .f. 1, 5, **
     208      +*  tokrlen = .f. 7, 7, **
     209      +*  tokrlc = .f. 14, 9, **
     210 ..s66
     211      +*  tokrval =  $ value part of header word (first few token chars)
     212 $    (holds cpstr characters)
     213          .f. ws+1 - cpstr*cs, cpstr*cs, **
     214
     215 $    the following macros define characters used to identify
     216 $    the various character string constants.
     217      $   ha fields are as follows:
     218
     219      $   nameptr - start of name in names array.
     220      $   lextyp - token lexical type, one of nametok, bintok, etc.
     221      $   lexlen - token length in characters.
     222      $   litcod - literal code if literal.
     223      $   nuses - number of token occurrences.
     224      $   macorg - start of macro definition in mtab.
     225      $   cab - conditional assembly state of name.
     226      $   halink - ha index of next entry in hash chain.
     227
     228
ldsa  19 .+s66.
ldsa  20      +*  lextyp     = .f. 01, 04, **  $ lexical type.
ldsa  21      +*  lexlen     = .f. 05, 07, **  $ lexical length.
ldsa  22      +*  litcod     = .f. 12, 07, **  $ literal code number.
ldsa  23 .+ca +*  cab        = .f. 19, 01, **  $ conditional assembly bit.
ldsa  24      +*  nameptr    = .f. 20, 13, **  $ names index.
ldsa  25 .+mp +*  macorg     = .f. 61, 14, **  $ macro origin.
ldsa  26      +*  nuses      = .f. 46, 02, **  $ number of uses.
ldsa  27      +*  halink     = .f. 75, 13, **  $ link for hash chain.
ldsa  28 .+mp +*  macimm     = .f. 60, 01, **  $ 'is this immediate macro'.
ldsa  29 ..s66
ldsa  30 .+s32.
ldsa  31 .+ca +*  cab     = .f.  1,  1, **
ldsa  32 .+mp +*  macimm  = .f. 49,  1, **
ldsa  33      +*  nameptr = .f.  2, 14, **
ldsa  34      +*  lextyp  = .f. 16,  4, **
haba   1 .+mp +*  macorg  = .f. 50, 14, **
ldsa  36      +*  lexlen  = .f. 33,  7, **
ldsa  37      +*  litcod  = .f. 40,  7, **
ldsa  38      +*  nuses   = .f. 47,  2, **
ldsa  39      +*  halink  = .f. 20, 13, **
ldsa  40 ..s32
ldsa  41 .+s37.
ldsa  42 .+ca +*  cab     = .f.  1,  1, **
ldsa  43 .+mp +*  macimm  = .f. 49,  1, **
ldsa  44      +*  nameptr = .f.  2, 14, **
ldsa  45      +*  lextyp  = .f. 16,  4, **
haba   2 .+mp +*  macorg  = .f. 50, 14, **
ldsa  47      +*  lexlen  = .f. 33,  7, **
ldsa  48      +*  litcod  = .f. 40,  7, **
ldsa  49      +*  nuses   = .f. 47,  2, **
ldsa  50      +*  halink  = .f. 20, 13, **
ldsa  51 ..s37
utsa  19 .+s47.
utsa  20 .+ca +*  cab     = .f.  1,  1, **
utsa  21 .+mp +*  macimm  = .f. 49,  1, **
utsa  22      +*  nameptr = .f.  2, 14, **
utsa  23      +*  lextyp  = .f. 16,  4, **
haba   3 .+mp +*  macorg  = .f. 50, 14, **
utsa  25      +*  lexlen  = .f. 33,  7, **
utsa  26      +*  litcod  = .f. 40,  7, **
utsa  27      +*  nuses   = .f. 47,  2, **
utsa  28      +*  halink  = .f. 20, 13, **
utsa  29 ..s47
ldsa  52 .+s10.
ldsa  53      +*  nameptr = .f.  1, 18, **
ldsa  54 .+mp +*  macorg  = .f. 19, 18, **
ldsa  55      +*  lexlen  = .f. 37,  7, **
ldsa  56      +*  nuses   = .f. 44,  2, **
ldsa  57 .+ca +*  cab     = .f. 46,  1, **
ldsa  58      +*  litcod  = .f. 47,  7, **
ldsa  59      +*  lextyp  = .f. 54,  4, **
ldsa  60 .+mp +*  macimm  = .f. 58,  1, **
ldsa  61      +*  halink  = .f. 59, 13, **
ldsa  62 ..s10
     262
     263
     264
     265      $   io access codes.
     266      +*  access_put = 3 **
     267      +*  access_write = 6 **
     268
     269
     270 $        macros for output
     271
     272 $    routines called by these macros are in little run-time
     273 $    library.
     274 $    macros are to appear where statement may appear; semicolon indicat
     275 $    end of statement supplied by macro expansion.
     276
     277      +*  charl(c) = call charlr(c); **  $ output character
     278      +*  intl(i) = call intlr(i); **  $ output integer (5 digits)
     279      +*  intlp(n,c) = call intlpr(n,c); **  $ output integer in c colum
     280      +*  textl(s) = call textlr(s); **  $ output quoted string
     281      +*  tintl(s,i) = call tintlr(s,i); **  $ output text and integer
     282      +*  tabl(p) = call contlpr(4,p); **  $ tab to column p
     283      +*  skipl(i) = call contlpr(3, i);  **  $ skip forward i columns
     284      +*  octl(i) = call octlr(i);**  $ output octal word
     285      +*  tokl(i) = call toklr(i); **  $ list token given hash
     286      +*  endl = call endlr;**  $ end line
     287      +*  listl(n) = call contlpr(26, n); **  $ set listing flag
     288      +*  terml(n) = call contlpr(27, n); **  $ set terminal flag
     289      +*  ejectl = call contlpr(5,0); **  $ eject to new page.
     290      $   ejectlp(n) - eject new page if less than n lines left on
     291      $   current page.
     292      +*  ejectlp(n) = call contlpr(5,n); **
     293      $   macros to define macros within macros.
     294      +*  q3(a,b,c) = a b c **
     295      +*  macdef(text) = q3(+,*text*,*) **
     296      +*  macdrop(mname) = macdef(mname=) **    $  easy way to drop macr
     297
     298          $   these macros for -yes- and-no- aid readability of
     299          $   expressions involving logical variables
     300
     301      +*  yes = 1 **
     302      +*  no = 0 **
     303
     304      +*  error_notice   = '*****error**** ' **
     305      +*  system_notice  = '*system error* ' **
     306      +*  warning_notice = '****warning*** ' **
     307
dsq   23 .+s10.  $ s10 wants special characters at start of error
dsq   24          $ and warning lines.
dsq   25      +*  warn_s10 = charl(37)  **  $ per cent for warnings.
dsq   26      +*  error_s10 = charl(63) **  $ question mark for errors.
dsq   27 ..s10
dsq   28
     308      +*  hashin(i) = call hash; i = haptr; **  $ hash and get code
     309
     310
     311 $         table top increment macro
     312
     313      +*  countup(index,limit,ermsg) =
     314          index = index+1;
     315          if  (index > limit) call ltoflo(index,limit,ermsg); **
     316
     317      +*  ertoksave(iwd) =  $ macro to save token hash code
     318          lsvtk(lsvtkp+1) = iwd;  $ add to buffer
     319          lsvtkp = (lsvtkp+1).a.lsvtkz;  $ add 1 to buffer pointer (pow2
     320          lsvtk(lsvtkp+1) = 0;  $ mark end
     321          **
     322
dsq   29      $   codes for standard string sets.
dsq   30
dsq   31      +*  ss_blank =   1 **
dsq   32      $   ss_separ matches blank and other characters (such as tab and
dsq   33      $   form feed for ascii environments) which are by convention
dsq   34      $   considered equivalent to blanks.
dsq   35      +*  ss_separ =   2 **
dsq   36      +*  ss_digit =   4 **  $ digits.
dsq   37      +*  ss_ucltr =   8 **  $ upper case letters a..z
dsq   38      +*  ss_lcltr =  16 **  $ lower case letters a..z
dsq   39      +*  ss_break =  32 **  $ underline, break '_'
dsq   40
dsq   41      $   additional string sets.
dsq   42
dsq   43      +*  ss_conda =  64 **  $ string set for conditional assembly chara
dsq   44
dsq   45      $   imtoks is string of single-character (immediate) tokens. these
dsq   46      $   tokens are found efficiently by trulex without hashing.
dsq   47
dsq   48      +*  imtoks = '(),;=+-*:
^!&' **
dsq   49      +*  num_imtoks = 14 **
dsq   50 .+s66.
dsq   51      $   on s66 imtoks must be variable so can deal correctly with
dsq   52      $   both 63 and 64 character sets.
dsq   53      macdrop(imtoks)
dsq   54      +*  num_imtoks = 15 **
dsq   55 ..s66
dsq   56
dsq   57      +*  ss_immed = 128 **  $ string set for immediate token chars.
dsq   58
dsq   59      $   macros for character type (used principally by trulex).
dsq   60
dsq   61      +*  alphabetic(c) = anyc(c, ss_ucltr ! ss_lcltr ! ss_break ) **
dsq   62      +*  numeric(c) = anyc(c, ss_digit) **
dsq   63      +*  alphameric(c) = anyc(c, ss_ucltr ! ss_lcltr ! ss_break !
dsq   64          ss_digit) **
dsq   65 .+ca +*  iscachar(c) = anyc(c, ss_conda) ** $ conditional assembly.
dsq   66      $   lettercode macro maps letters in a..z_ to ordinal position and
dsq   67      $   other characters to zero. this macro used mainly to process
dsq   68      $   zzy- and zzz- symbols in macro definitions.
dsq   69      +*  lettercode(c) = ((brkc('abcdefghijklmnopqrstuvwxyz_', 1, c)
dsq   70          >= 0) * (1 + brkc('abcdefghijklmnopqrstuvwxyz_', 1, c)) ) **
dsq   71
dsq   72      $   isblank is macro to test if character is blank or equivalent
dsq   73      $   separator. blank is assumed to be only separator in upper-case
dsq   74      $   only systems (true for s37 and s66).
dsq   75
dsv   38 .-mc +*  isblank(c) = (c=1r ) **
dsv   39 .+mc +*  isblank(c) = anyc(c, ss_separ) **  $ separators.
dsq   78                                $ separators.
     330      +*  tally(i) = i = i+1; **   $ used to count things
     331      +*  digofchar(c) = $ decimal value of decimal character
     332          (c-1r0)
     333          **
     334      +*  charofdig(d) = $ character for decimal digit
     335          (d+1r0)
     336          **
     337
     338      +*  blankword =  $ machine word of blanks (cf. macro givec)
vax   30 .+s32    4r
     339 .+s37    4r
utsa  30 .+s47    4r
     340 .+s66    10r
mgfa  17 .+s10    4r
     342          **
     343
dsq   79      $   cc_tab is code for tab character if available,
dsq   80      $   or is code for blank.
dsq   81      +*  cc_tab =
dsq   82 .+s10    9
dsq   83 .+s11    9
dsq   84 .+s32    9
dsq   85 .+s37    1r
utsc   2 .+s47    9
dsq   86 .+s66    1r
dsq   87          **
dsq   88
     344
     347
     348 $            isymc(wd,j) - gets j-th char in token with ha-index wd
     349      +*  isymc(wd, j) = (.f. ws+1-cs - cs*mod((j)-1, cpw), cs,
     350              names(nameptr ha(wd) + (j-1)/cpw)) **
     351
     352
     353      +*  tokch(p, c) =  $ set first character in hashtok
     354          .f. hashtokorg -cs*(p), cs, hashtok = c;  **
     355
     356      +*  sdspack(ara,count) =  $ copy char per elm array into hashtok
     357 .-sdspack_env.
     358          size  zzza(ps);
     359          do  zzza = 1 to count;  $ loop doing each character.
     360              tokch(zzza, ara(zzza));
     361              end do;
     362          slen hashtok = count;
     363 .+sdspack_env.    $ if special code in library used.
     364          call 7nspak$li(hashtok, ara, count);
     365 ..sdspack_env
     366          **
     367
     368
     369
     370      +*  getsym(sym, hap)  = $ macro to get name as string given hash
     371          size zzza(ps);  zzza=nameptr ha(hap);  $ position word 1 of na
dsn   19 .+s10.
dsn   20 $    move characters from names into global buffer
dsn   21 $    (technique exploiting dec-10 blt byte-move ops would be helpful)
mgfa  18      .f. 5*ws+1, ws, sym = names(zzza);
mgfa  19      .f. 4*ws+1, ws, sym = names(zzza + 1);
mgfa  20      .f. 3*ws+1, ws, sym = names(zzza + 2);
mgfa  21      .f. 2*ws+1, ws, sym = names(zzza + 3);
mgfa  22      .f. 1*ws+1, ws, sym = names(zzza + 4);
dsn   26 ..s10
     372 .+s66.     $ macro is machine dependent
     373      .f. 121, 60, sym = names(zzza);   $ first part of token
     374      .f. 61, 60, sym = names(zzza+1);  $ next ten chars
     375 ..s66
vax   31 .+s32.
vax   32 $    move characters from names into global buffer
vax   33      .f. 5*ws+1, ws, sym = names(zzza);
vax   34      .f. 4*ws+1, ws, sym = names(zzza + 1);
vax   35      .f. 3*ws+1, ws, sym = names(zzza + 2);
vax   36      .f. 2*ws+1, ws, sym = names(zzza + 3);
vax   37      .f. 1*ws+1, ws, sym = names(zzza + 4);
vax   38 ..s32
     376 .+s37.
     377 $    move characters from names into global buffer
     378 $    (technique exploiting system/370 byte-move ops would be helpful)
     379      .f. 5*ws+1, ws, sym = names(zzza);
     380      .f. 4*ws+1, ws, sym = names(zzza + 1);
     381      .f. 3*ws+1, ws, sym = names(zzza + 2);
     382      .f. 2*ws+1, ws, sym = names(zzza + 3);
     383      .f. 1*ws+1, ws, sym = names(zzza + 4);
     384 ..s37
utsa  32 .+s47.
utsa  33 $    move characters from names into global buffer
utsa  34 $    (technique exploiting system/370 byte-move ops would be helpful)
utsa  35      .f. 5*ws+1, ws, sym = names(zzza);
utsa  36      .f. 4*ws+1, ws, sym = names(zzza + 1);
utsa  37      .f. 3*ws+1, ws, sym = names(zzza + 2);
utsa  38      .f. 2*ws+1, ws, sym = names(zzza + 3);
utsa  39      .f. 1*ws+1, ws, sym = names(zzza + 4);
utsa  40 ..s47
     385      size zzzl(ps);  $ for length of token
     386      zzzl = lexlen ha(hap); if  (zzzl>20) zzzl=20;
     387      slen sym = zzzl; sorg sym = sdstl+1;
     388          **
     389 $    macros used by trulex, the basic lexical scanner
     390
     391      +* keeplimit = 10 **
     392
     393
     394      +* keepc(char) =     $ macro to save char in buffer
     395 .+ct     countup(keepindex, keeplimit, 'keep');
     396 .-ct     keepindex = keepindex + 1;
     397          keep(keepindex) = char ;  **
     398
     399
     400      +* getfromkeep(char) =     $ get char from buffer
     401          char = keep(keepindex);
     402          keepindex = keepindex - 1;  **
     403 +*   givec_text(c) =  $ macro to get character
     404      if  keepindex  then  $ if prior token kept.
     405          getfromkeep(c);
     406      elseif  nowc > mccd  then  $ if new card must be read.
     407          call givecr(c);  $ read next card.
dsv   40 .+mc     c = ctpc(c);  $ fold first char in line.
     408      else
     409          if  nc10 = 1 then  $ if new word needed
     410              nowdp = nowdp + 1;  nowd = iwds(nowdp);
     411              nc10 = ws + 1;
     412              if  nowd = blankword  then  $ if blanks, take only one.
     413 .+tallytokens    tally(tallyblank)
     414                  nc10 = 1;
     415                  nowc = nowc + cpw;  $ advance to next word.
     416                  c = 1r ;
     417                  go to zzza;
     418                  end if;
     419              end if;
     420          nc10 = nc10 - cs;   $ advance to next character.
dsv   41 .+mc     c = ctpc((.f. nc10, cs, nowd));
dsv   42 .-mc     c = .f. nc10, cs, nowd;
dsq   91          nowc = nowc + 1;
     422          end if;
     423   /zzza/
     424 .+ct.
     425     if  chartrace  then  $ if tracing characters.
     426          textl(' ct=<')  charl(c) textl('> ')
     427          end if;
     428 ..ct
     429      **
     430
     431      +*  giveq(c) = givec_text(c); **  $ get character inline.
     432      +*  givec(c) = call givecp(c); **  $ get character offline.
     433
     434      +*  giveqnk(c) =   $ get character when not in -keep-.
     435      if  nowc > mccd  then  $ if new card must be read.
     436          call givecr(c);  $ read next card.
dsw   15 .+mc     c = ctpc(c);  $ convert to primary case.
     437      else
     438          if  nc10 = 1 then  $ if new word needed
     439              nowdp = nowdp + 1;  nowd = iwds(nowdp);
     440              nc10 = ws + 1;
     441              if  nowd = blankword  then  $ if blanks, take only one.
     442 .+tallytokens    tally(tallyblank)
     443                  nc10 = 1;
     444                  nowc = nowc + cpw;  $ advance to next word.
     445                  c = 1r ;
     446                  go to zzza;
     447                  end if;
     448              end if;
     449          nc10 = nc10 - cs;   $ advance to next character.
dsv   43 .+mc     c = ctpc((.f. nc10, cs, nowd));
dsv   44 .-mc     c = .f. nc10, cs, nowd;
dsq   94          nowc = nowc + 1;
     451          end if;
     452   /zzza/
     453 .+ct.
     454     if  chartrace  then  $ if tracing characters.
     455          textl(' ct=<')  charl(c) textl('> ')
     456          end if;
     457 ..ct ;
     458      **
     459      +*  givecstr(ic) =  $ get character when inside char. string
     460          call givesp(ic); **
     461
     462      +*  charin(c) =  $ add -c- to token buffer
     463          tokptr = tokptr + 1; $ advance index
     464          tok(tokptr) = c;    $ store in token array.
     465          if  tokptr > maxtoklen  then  $ check if in range
dso   10              call ermsg(10, maxtoklen, 0);  $ give error.
     467              tokptr = maxtoklen/2 + 1;  $ set to shorter token.
     468              end if;
     469          **
     470
     471 $     macro to set macro-table value
     472 .+mp.
     473      +*  seter(intoarr,value,loc) =
     474          .f. ws+1-ms - ms*mod((loc)-1, ws/ms), ms,
     475              intoarr(1 + ((loc)-1)/(ws/ms)) = value; **
     476      +*  mtset(loc,iwd) = seter(mtab,iwd,loc) **
     477
     478      +*  geter(fromarr,loc)=
     479          .f. ws+1-ms - ms*mod((loc)-1, ws/ms), ms,
     480              fromarr(1 + (loc-1)/(ws/ms)) **
     481 $     macro to get parcel from macro dictionary
     482      +*  mtget(j)=geter(mtab,j) **
     483
     484 $        macro for load into ms-bit packed vector
     485      +*  astklim = 100 **     $ dimension of -astk-
     486      +*  astkget(l) = astk(l);  **     $ gets -l- entry in astk
     487      +*  astkset(l,v) = astk(l) = v;**$ set -l-th entry in astk to v
     488
     489 $    macro to pass token to puncher routine, with check for zero arg
     490
     491      +*  mflshr(iwd) = call pflshr(iwd); **
     492
     493      +*  mcexpnd(i) =    $ get token from -mcexpand-.
     494          until  iwd;   $ loop until got non-zero token.
     495              if  keepwd then   $ see if a token was kept.
     496                  iwd = keepwd;  keepwd = 0;  $ get it if so.
     497                  quit until;   $ show got token.
     498
     499              elseif  mstkpt = 0 then   $ can call -trulex- directly.
     500                  call trulex;  $ just get token.
     501 .+tallytokens    tally(tallytrue);  $ count true tokens.
     502 .+mt.
     503                  if  mactrace then  $ if tracing macros.
     504                      textl('trulex <') tokl(iwd) textl('>') endl
     505                      end if;
     506 ..mt
     507
     508                  ertoksave(iwd);  $ save token for token list.
     509                  quit until;  $ show got token.
     510
     511              else   $ we are in a macro expansion.
     512                  call mcexpand;   $ call routine to get from macros.
     513                  end if;
     514              end until;
     515
     516          i = iwd;   $ set result token.
     517 .+mt.
     518          if  mactrace then  $ if tracing macros.
     519              textl('macexp <') tokl(iwd) textl('>') endl
     520              end if;
     521 ..mt
     522          **
     523 ..mp
     524
     525      +*  dfabsrb(i) =   $ get token from -defabsrb-.
     526 .+mp.
     527          until  iwd;  $ loop until got a token.
     528              mcexpnd(iwd);  $ first get from -mcexpand-.
     529              if  iwd = ihpl ! iwd = ihst then  $ macro start, end.
     530                  call defabsrb;   $ call routine if it is.
     531                  end if;
     532              end until;
     533
     534 .+mt.
     535          if  mactrace then  $ if tracing macros.
     536              textl('defabsrb <') tokl(iwd) textl('>') endl
     537              end if;
     538 ..mt
     539
     540 .-mp     call trulex;  $ get token if no macros.
     541
     542          i = iwd;  $ copy to output.
     543          **
     544
     545
     546 ..mp
     547 $  macros for writing token file for generator phase
     548
     549      +*  tokout1(wd) =  $ output one word token to token file
     550          tokrbufp = tokrbufp + 1; tokrbuf(tokrbufp) = wd;
     551          if  tokrbufp >=  tokrbuflim  then  $ flush buffer if full
     552              call wtrwsio(tokenfile, iorc, tokrbuf, 1, tokrbufp);
     553              tokrbufp = 0;
     554              end if;
     555          **
     556
     557      +*  tokout(hdrwd, ara, lo) =  $ output token descriptor
     558      size  zzzw(ps);  $ no of words to output
     559      size  zzzi(ps);   $ do loop index.
     560      tokout1(hdrwd);
     561      zzzw = (tokrlen hdrwd -1)/cpw + 1;
     562      if  tokrbufp+zzzw >= tokrbuflim then  $ flush buffer if full.
     563          do  zzzi = 1 to zzzw;
     564              tokout1(ara(zzzi+lo-1));
     565              end do;
     566      else
     567 .+movea_env.
     568          call 7nmova$li(tokrbuf, tokrbufp+1, ara, lo, zzzw);  $ move
     569 .-movea_env.
     570          do  zzzi = 1 to zzzw;  $ just copy into buffer.
     571              tokrbuf(tokrbufp+zzzi) = ara(lo-1+zzzi);  $ copy one word.
     572              end do;
     573 ..movea_env
     574          tokrbufp = tokrbufp+zzzw;
     575          end if;  **
     576
       1 .=member start
dsn   27 .+s10  prog start;
vax   39 .+s32  prog start;
dsn   28 .+s37  prog start;
utsa  41 .+s47  prog start;
dsn   29 .+s66  subr start;
       4 $    all global variables are defined in this routine.
       5 $    the routine lexini is called to perform needed initializations
       6 $    and then lexdo, the driver for the scanner, is called.
       7 .+s66    nameset blank;      $  keep in blank common on s66.
       8      size  astk(ps); dims astk(astklim);  $ stack for macro arguments
       9 .+s66    end nameset blank;
      10      size  astkpt(ps); data astkpt=0; $ top of macro arg. list
      11      size  bugtoks(ps);  dims bugtoks(numbugtoks);
      12      size  caname(cs); dims caname(mccd-3);  $ ca name
      13      size  cardlisted(1);  $ flag set when card listed
      14      size  cardsent(1);  data cardsent = yes;  $ 'card sent to gen'
      15      size  col3char(cs);  $ column 3 of card
      16      size  canamel(ps);  $ length of -caname-
      17      size  cardskip (1); data cardskip=0; $ card'skip flag
      19      size  chartrace(ps);  $ char trace flag
      20      size  countzzy(ps); dims countzzy(27); data countzzy = 0(27);
      21      size  countzzz(ps); dims countzzz(27); data countzzz = 0(27);
      22 .+cr.
      23      size  crfilename(sds(filenamelen));  $ name of reference file.
      24      size  crfileparm(sds(filenamelen));  $ skeleton for ref. file name
      25      size  crbuffptr(ps);  data crbuffptr = 0;
      26 .+s66    nameset blank;      $  keep in blank common on s66.
      27      size  crbuff(ws);  dims crbuff(crbuffmax);
      28 .+s66    end nameset blank;
      29      size  creftot(ps);  data creftot = 0;  $ total number of refs.
      30 ..cr
      31      size  dodetect(1);    $ on to list suspicious variables.
      32      size  errecho(1);  data errecho = no;  $ for error echo of input c
      33      size  exitcode(1); data exitcode = yes;  $ exit code for -lexexit-
      34      size  fivdecara(cs);  dims fivdecara(5); $ fivdec result.
      35 .+cr size  crefent(ws);  $ cross reference entry.
      36      size  haptr(ps);        $ index of current ha entry.
      37 .+s66    nameset blank;      $  keep in blank common on s66.
      38      size  ha(hasz);dims ha(hadim); $ symbol table.
      39 .+s66    end nameset blank;
      40      size  hafree(ps);  data hafree = hadim+1;  $ free pointer for hash
      41      size  hashca(ps);  $ hash-code of -caname-
      42 .+ca size  hashcaset(ps); $ hash code of -set-
      43      size  hashlen(ps);  $  length in chars of token to hash
      44      size  hashtok(hashtokorg-1); data hashtok=0; $ global hash input s
      45      size  hashtrace(ps);  $ hashtrace flag
      46      size  hashtyp(ps);  $ lexical typeof hashed token
      47      size  hashwords(ps);  $ no of words in hashed token
      48      size  haused(ps); data haused=0; $ no of ha-words full
      49      size  icdno(ps); data icdno=0; $ no. of cards read
      50      size  icdlast(ps); data icdlast = 0;  $ last card no. sent to gen.
      51      size  ihcm(ps);  $ hash-index of symbol ',' (comma)
      52      size  ihcompdate(ps);  $ ha index of compilation date.
      53      size  iheq(ps);  $  hash pointer for symbol -=-
      54      size  ihlp(ps);  $ hash-index of symbol '(' (left paren)
      55      size  ihpl(ps);  $ hash-index of symbol '+' (plus)
      56      size  ihpr(ps);
      57      size  ihrp(ps);  $ hash-index of symbol ')' (right paren)
      58      size  ihsemi(ps);  $ hash-code of semicolon
      59      size  ihsl(ps);  $ hash-code of slash /
      60      size  ihst(ps);  $ hash-index of symbol '*' (star)
dsq   95      size  imtoktab(ps);  dims  imtoktab(num_imtoks);
dsq   96 .+s66.
dsq   97      $   imtoks is variable so can deal with 63 and 64 sets.
dsq   98      $   see lexini for details.
dsq   99      size  imtoks(.sds. num_imtoks);
dsq  100      data  imtoks = '(),;=+-*
^!&::' ;
dsq  101 ..s66
      62      size  initializing(1); data initializing=yes;
      63          $ -initializing- on while we are initializing the scanner.
      64      size  initloc(ps);  $ used to save -prevloc-
      65 .+cr   size  isonxrf(ps);  data isonxrf = no;  $ on when doing xref
      66      size  iorc(ps);  $ return code from io operation.
      67      size  iwd(ps);  $  ha-index
      68      size  iwds(ws); dims iwds(wpc); $ input card image
      69      size  keep(cs);  dims keep(keeplimit);$ character buffer for givec
      70      size  keepindex(ps);      data keepindex = 0;    $ index into keep
      71      size  keepwd(ps);  data keepwd=0;  $ one-token buffer
      72      size  lastwd(ps);   $ index of last non-blank word on card.
      73      size  lcp_opt(1); data lcp_opt=yes; $ on to list parameters.
      74      size  lcs_opt(1); data lcs_opt=yes; $ on to list statistics.
      75      size  lelvalue(ps);  $ error limit.
      78      size  lexdotrace(ps); data lexdotrace = 0; $ lexdo tok list
      79      size  listapt(ps); data listapt=0; $ no. of args in current macro
      80      size  listarg(ps);  dims listarg(listarglim);
      81      $   listignore is set when .=list directives are to be ignored.
      82      size  listignore(1); data listignore = no;
      83
      84      $   listprev is list of prior list control status entries.
      85      size  listprev(ps);  dims listprev(listprevmax);
      86      size  listprevptr(ps);  data listprevptr = 1;
      87      size  listnow(ps);      $ current list status word.
      88      size  listnew(ps);      $ new list status word.
      89      size  listvals(ps);  $ array of list parameters
      90      +*  list_code        =  1 **  $ list generated code in -asm-
      91      +*  list_input       =  2 **  $ list input in -gen-
      92      +*  list_autotitle   =  3 **  $ auto titling in -gen-
      93      +*  list_skip        =  4 **  $ list skipped cards
      94      +*  list_qualifiers  =  5 **  $ list conditional qualifiers
      95      +*  list_linput      =  6 **  $ list input in -lex-
      96      +*  list_references  =  7 **  $ collect references
      97      +*  list_definitions =  8 **  $ punch macro definitions
      98      +*  list_expansions  =  9 **  $ punch expanded text
      99      +*  list_resume      = 10 **  $ pop listing stack
     100      +*  list_directive   = 11 **  $ list current list directive
     101
     102      +*  listinginput   = .f. list_linput,     1, listnow **
     103      +*  collectingrefs = .f. list_references, 1, listnow **
     104      +*  listingen = .f. list_input, 1, listnow **
     105
     106      +*  numlistparms = 11 **  $ number of listing options
     107      dims  listvals(numlistparms);
     108
     109      $   definitions of fields of -listvals-
     110      +*  listval_tf = .f. 1, 1, **  $ output data to token file
     111      +*  listval_ll = .f. 2, 1, **  $ causes directive to list in -lex-
     112      +*  listval_gl = .f. 3, 1, **  $ causes directive to list in -gen-
     113      +*  listval_df = .f. 4, 1, **  $ default initial value
     114
     115      $   array of characters used in 'list' parameter
     116      size  listchars(cs); dims listchars(numlistparms);
     117
     118      +*  setlist(val, char, tf, ll, gl, df) =  $ macro to set option
     119          listchars(val) = char:
     120          listvals(val) = 8*df + 4*gl + 2*ll + tf **
     121
     122      data    $ initialize list control arrays
     123
     124 $                    value          ic   tf   ll   gl   df
     125          setlist(list_code,        1rc, yes, yes, yes,  no):
     126          setlist(list_input,       1ri, yes, yes, no,   no):
     127          setlist(list_autotitle,   1ra, yes, yes, yes,  no):
     128          setlist(list_skip,        1rs, no,  yes, yes,  no):
     129          setlist(list_qualifiers,  1rq, no,  yes, yes,  no):
     130          setlist(list_linput,      1rl, no,  no,  yes,  no):
     131          setlist(list_references,  1rr, no,  yes, yes, yes):
     132          setlist(list_definitions, 1rd, no,  yes, yes,  no):
     133          setlist(list_expansions,  1re, no,  yes, yes,  no):
     134          setlist(list_resume,      0,   no,  no,  no,   no):
     135          setlist(list_directive,   0,   no,  no,  no,   no);
     136
     137      macdrop(setlist)
     138      size  lsvtk(ps); dims lsvtk(lsvtkz+1); data lsvtk = 0(lsvtkz+1);
     139      size  lsvtkp(ps); data lsvtkp=0; $ current entry in lsvtk
dst   11 .+mdc.
     140      size  mdclist(ps);  data mdclist=no;  $ on to list mach. dep. cnst
dst   12 ..mdc
     141      size  mstk(ws); dims mstk(mstklim);  $ macro expansion control
     142 .+mp. $ variables used in mcacroprocessor
     143      size  mactrace(1);  data mactrace=no;  $ on for macro trace
     144      size  mname(ps);  $ ha index of macro name.
     145      size  mstkpt(ps); data mstkpt=0; $ top of macro control stack
     146      size  mtptr(ps); data mtptr=0; $ top of macro def. table
     147 .+s66    nameset blank;      $  keep in blank common on s66.
     148      size  mtab(ws); dims mtab(mtlim/(ws/ms)); $ macro table
     149 .+s66    end nameset blank;
     150 ..mp
     151 .+s66    nameset blank;      $  keep in blank common on s66.
     152      size  names(ws);  dims names(namesmax);
     153 .+s66    end nameset blank;
     154      size  nc10(ps);         $ position in current word nowd
     155      size  nerrors(ps); data nerrors=0;  $ number of detected errors.
     156
     157      size  normwork(5);  $ normal work to do for a card
     158      $   this is needed by -givecr- to determine what processing
     159      $   is needed for each card.  the flags in the variable
     160      $   indicate the following types of processing:
     161      +*  proc_work = 1b'10001' **  $ have -lex- process card
     162      +*  list_work = 1b'10010' **  $ have -lex- list card
     163      +*  elim_work = 1b'10100' **  $ eliminate qualifiers fro card
     164      +*  out_work  = 1b'11000' **  $ send card to -gen- to list
     165
     166      data  normwork = out_work!proc_work;
     167
     168      size  nowc(ps); data nowc=mccd+1; $ last column of input processed
     169      size  nowd(ws);  $ current word in iwd
     170      size  nowdp(ps);  $     $ idex in iwds of current word
     171      size  nparen(ps);  $ number of parens seen in macro argument
     172      size  namesptr(ps); data namesptr=1; $ next free word in names
     173      size  numargs(ps);  $ number of macro arguments
     174      size  nwarnings(ps); data nwarnings=0; $ warning count.
     175      $   punchdefine on to punch macro definitions; punchexpand on
     176      $   punch expanded text.
     177      size  punchdefine(1);  data punchdefine = no;
     178      size  punchexpand(1);  data punchexpand = no;
     179      size  punchfilename(sds(filenamelen));  $ name of punch file
     180      size  punchopened(1); data punchopened=no; $ on when pun file open
     181      size  punchpos(ps); data punchpos=0; $ position in punch buffer
     182      size  punchbuf(cs);  dims punchbuf(80);  $ punch line.
     183      size  punhold1(ps), punhold2(ps);  $ keept tokens.
     184      size  punlastlt(ps);  $ last lexical type for punch.
     185 .+bub.
     186      size  res(ps); dims res(reslim);  $ token backup buffer (for pa
     187      size  resptr(ps); data resptr=0;  $ top of (unused) token back
     188 ..bub
     189      size  subtitling(1); data subtitling=no;  $ on when doing subtitle
     190 .+tallycomments.  $ counters for optional comment statistics
     191      /*  these statistics count the number and type of comments.
     192          they are included in the production compiler as they provide
     193          a rough measure of documentation quality. */
     194      size  tallypl1(ps); data tallypl1=0; $ no. of pl/1 comments
     195      size  tallyeol(ps); data tallyeol=0; $ number of $-style comments
     196 ..tallycomments
     197 .+tallytokens.  $ counters for optional token statistics
     198      /*  the token statistics count the number of immediate tokens,
     199          the number of tokens found by the scanner, and the number of
     200          tokens sent to the parser.*/
     201      size  tallytrue(ps); data tallytrue=0; $ number of true tokens
     202      size  tallyimtok(ps); data tallyimtok=0; $ immediate tokens
     203      size  tallyparse(ps); data tallyparse=0; $ tokens to parser
     204      size  tallyblank(ps); data tallyblank=0; $ blank words seen
     205 ..tallytokens
     206 .+tallyhash.  $ counters for optional hash statistics
     207      /*  the hash statistics count the number of times the symbol
     208          table is searched, and the number of entries examined. */
     209      size  tally_haprobes(ps); data tally_haprobes=0; $ number of probe
     210      size  tally_haentries(ps); data tally_haentries=0; $ number of ent
     211      size  tally_halinks(ps);   data tally_halinks = 0; $ number of lin
     212 ..tallyhash
     213      size  termlex(ps);  $ on to terminate after lexical phase.
     214      size  tok(cs); dims tok(maxtoklen+1);  $ token array
     215      size  tokptr(ps);  $ current entry in token buffer
     216 .+s66    nameset blank;      $  keep in blank common on s66.
     217      size  tokrbuf(ws);  dims tokrbuf(tokrbuflim);
     218 .+s66    end nameset blank;
     219      size  tokrbufp(ps);  data tokrbufp=0;  $ index of last token outpu
     220      size  tokrwd(ws); $ for outputting token descriptor
     221      size  toktrace(ps); data toktrace=no; $ on for -trulex- -ha- trace
     222      size  tokwrt(1); $ switch on when writing token file
     223      size  tokenfilename(sds(filenamelen)); $ name of token file
     224
     225      call lexini;
     226      call lexdo;  $ main driver routine for scanner
     227      exitcode = 0; call lexexit;  $ terminate scan
     228
dsn   30 .+s10  end prog start;
vax   40 .+s32  end prog start;
dsn   31 .+s37  end prog start;
utsa  42 .+s47  end prog start;
dsn   32 .+s66  end subr start;
       1 .=member lexini
       2      subr lexini;  $  initialization
       3 $    lexini is initialization routine, called only once from start.
       4 $    lexini initializes variables, processes the control-card
       5 $    options for the scan, and prints the initial part
       6 $    of the header on the scanner output file.
       7
       8      size  c(cs);  $ temporary for character table set up
       9      size  tmparm(sds(filenamelen));  $ target machine parameter.
      10 .+ca    size  inisetparm(sds(filenamelen));  $ initial set request.
      11      size  lstimestr(.sds. lstimelen);
      13      size  i(ps), j(ps), l(ps);  $ loop indices
      14      size  inimemname(.sds. filenamelen);  $ name of initial member.
      15      size  ilp(.sds. filenamelen);  $ initial list parameter.
      16      size  tokrwd(ws);       $ for writing list control on token file.
      17      size  liststr(sds(1));  $ used to process -list- parameter
dsq  102      size  updseq(ps);       $ upd sequence option.
dsq  103      size  brkc(ws);      $ function to locate character in string.
dsr   15      size  appstr(.sds. getapp_len);  $ actual parameter string.
      18 .+s66    size  ha_00b(ps);  $ hash code for character 3b'00'.
      19 .+s66    size  ha_63b(ps);  $ hash code for character 3b'63'.
      20
      21      do  i = 1 to hadim;  ha(i) = 0;  end do;  $ clear the ha.
      22
dsq  104      call blds('+-.', ss_conda); $ string set for conditional assembly
      50
      51      sorg hashtok = hashtokorg;  $ origin will never be changed
      52
      53      $   get name in initial member to include.
      54      call getspp(inimemname, 'imem=/');
      55
vax   41 .+s32    call getspp(tokenfilename,'tokens=tokens.tmp/');
      56 .+s37    call getspp(tokenfilename,'tokens=sysut1/');
utsa  43 .+s47    call getspp(tokenfilename,'tokens=sysut1/');
      57 .+s66    call getspp(tokenfilename,'tokens=tokens/');
mgfa  23 .+s10    call getspp(tokenfilename, 'tokens=*.tok/');
      59
      60      tokwrt = (.ch. 1,tokenfilename ^=1r0); $ on if writing tokens
      61 $    tokwrt is now zero if not writing token file; otherwise
      62 $    is name of token file
      63      call opensio(tokenfile, iorc, access_write, tokenfilename,
      64          tokrbuflim*cpw, i, 0, 0);
dsr   16 .+s66  call rewisio(tokenfile, iorc, 0);
vax   42 .+s32    call getspp(punchfilename, 'pfn=little.pun/');
      66 .+s37    call getspp(punchfilename, 'pfn=syspunch/');
utsa  44 .+s47    call getspp(punchfilename, 'pfn=syspunch/');
      67 .+s66    call getspp(punchfilename, 'pfn=lexout/');
      68 .+s10    call getspp(punchfilename, 'pfn=*.pun/');
      69
      74
      75 $  param -lt- used to get token list in -lexdo- set initial value
      76      call getipp(lexdotrace, 'lt=0/1');
      77 .+ct call getipp(chartrace, 'ct=0/1');
      78 .+ht call getipp(hashtrace, 'ht=0/1');
      79 .+mt call getipp(mactrace, 'mt=0/1');
      80
      81 .+cr.
vax   44 .+s32    call getspp(crfileparm, 'rf=little.rf0/');
      82 .+s37    call getspp(crfileparm, 'rf=sysref(ref0)/');
utsa  45 .+s47    call getspp(crfileparm, 'rf=sysref(ref0)/');
      83 .+s66    call getspp(crfileparm, 'rf=ref0/');
dsn   33 .+s10    call getspp(crfileparm, 'rf=*.rf0/');
      85      call getipp(isonxrf, 'lcr=0/1');
      86      if  isonxrf  then
      87          call crfnam(crfilename, crfileparm, 1);
      88          call opensio(crfile, iorc, access_write, crfilename,
      89              0, i, 0, 0);
      90          creftot = 0;
      91          end if;
      92 ..cr
      93
dsz   12      call getipp(dodetect, 'susp=0/0');
dst   13 .+mdc.
      95      call getipp(mdclist, 'mdc=0/1');
dst   14 ..mdc
      96
      97      call getipp(lelvalue, 'lel=25/');
      98      $   scan aborted if more than lelvalue errors detected.
      99
     100      $   lcp_opt gives parameter list if on; lcs_opt lists statistics.
     101      call getipp(lcp_opt, 'lcp=1/0');
     102      call getipp(lcs_opt, 'lcs=1/0');
utsb  17 .+s32u.  $ minimal listing by default for unix.
dsv   46      call getipp(lcp_opt, 'lcp=0/1');
dsv   47      call getipp(lcs_opt, 'lcs=0/1');
utsb  18 ..s32u
utsb  19 .+s47.  $ minimal listing by default for unix.
utsb  20      call getipp(lcp_opt, 'lcp=0/1');
utsb  21      call getipp(lcs_opt, 'lcs=0/1');
utsb  22 ..s47
     103
     104      listnow = 0;  listnew = 0;  $ clear values
     105
     106      call getspp(ilp, 'list=sq/isqa');
     107
dsq  105      call getipp(updseq, 'upd=0/1');  $ upd sequence option
dsq  106
     108      sorg liststr = sds(1)+1; slen liststr = 1; $ initialize string
     109      do  i = 1 to numlistparms;  $ process each parm
     110          .f. i, 1, listnow = listval_df listvals(i);  $ set default
     111          .f. i, 1, listnew = listval_df listvals(i);
     112          c = listchars(i); $ get character
     113          if  c then  $ use value given
     114              .ch. 1, liststr = c;  $ build into sds
     115              if  (liststr .in. ilp) .f. i, 1, listnew = yes;
     116              end if;
     117          end do;
     118
     119      listprev(1) = listnow;  $ set prior options
     120      listnow = listnow .ex. listnew;  $ flag changed options
     121
     122      do  i = 1 to numlistparms; $ process changes
     123          if  (.f. i, 1, listnow = no) cont do;  $ not changed
     124          if  listval_tf listvals(i) & tokwrt then  $ write to token fil
     125              tokrwd = 0;
     126              tokrtyp tokrwd = listcontroltok;
     127              tokrlen tokrwd = i;  $ set list parameter number
     128              tokrlc  tokrwd = .f. i, 1, listnew;  $ set value
     129              tokout1(tokrwd);
     130              end if;
     131          end do;
     132
     133      listnow = listnew;  $ set active listing mode
     134      if  ('0' .in. ilp) listignore = yes;
     135      punchdefine = .f. list_definitions, 1, listnow;
     136      punchexpand = .f. list_expansions,  1, listnow;
     137      if  (listinginput) normwork = normwork ! list_work;
vax   45 .+s32    call getspp(tmparm, 'tm=32/');
     138 .+s37    call getspp(tmparm, 'tm=37/');
utsa  46 .+s47    call getspp(tmparm, 'tm=47/');
     139 .+s10    call getspp(tmparm, 'tm=10/');
     140 .+s66    call getspp(tmparm, 'tm=66/');
     141
     142 .+ca.
     143      call getspp(inisetparm, 'iset=/');
     144 ..ca
     145
     146      call getipp(termlex, 'termlex=0/1');
dsr   17
dsr   18      $   get actual parameters specified.
dsr   19      call getapp(appstr, getapp_len);
dsr   20
     147      $   set up listing title, get compilation date.
     148      call ltitlr(scannerlevel);
     149      call stitlr(0, 'little compilation - lexical scan phase.');
     150
     151      call lstime(lstimestr);
     152
     153      if  (lcp_opt=0) go to parmslisted;
     154
     155      call stitlr(1, 'parameters for lexical scan.');
dsr   21
dsr   22      if  .len. appstr  then $ if any explicitly specified.
dsr   23          textl(appstr)  endl endl
dsr   24          end if;
dsr   25
     160      if  slen inimemname  then  $ if including initial member.
     161          textl('initial member to include: imem = ')
     162          textl(inimemname)  charl(1r.)  endl
     163          end if;
     164      if  slen ilp then  $ if list parameters specified
     165          textl('initial list options: list = ') textl(ilp)
     166          textl('.') endl
     167          end if;
     168      textl('token file: tokens = ') textl(tokenfilename)
     169      textl('.  punch file: pfn = ') textl(punchfilename)
     170      textl('.') endl
     171
     172      textl('list statistics: lcs =') intlp(lcs_opt,2)
     173      textl('.  list suspicious names: susp =')  intlp(dodetect, 2)
     174      textl('.')  endl
     175      textl('lexical error limit: lel =') intl(lelvalue)
dsq  107      textl('.  upd sequence: upd =') intlp(updseq, 2)
     176      textl('.') endl
     177 .+cr.
     178      textl('lexical cross reference list: lcr =')  intlp(isonxrf,2)
     179      textl('.  reference file: rf = ')  textl(crfileparm) textl('.')
     180      endl
     181 ..cr
     182 .+ca.
     183      endl  textl('conditional inclusion selected for symbol')
     184      if  slen inisetparm  then
     185          textl('s:  ')
     186          textl(inisetparm)
     187      else
     188          textl(':')
     189          end if;
     190      textl('   s') textl(tmparm)
utsb  23 .+s32u  textl('  s32u')
     191      endl
     192 ..ca
     193      endl  endl
     194 /parmslisted/
     195
     196 $        initialize table for detecting special period delim tokens
     197      +* lextokstr =
     198'chtr nochtr hatr nohatr lextr nolextr mactr nomactr compdate '
     199     **
     200      hashtyp = optok;  $ type remains fixed for all used of bughash
     201      tokch(1, 1r.);  j = 0;  l = 1;
     202      do  i = 1 to slen lextokstr;
     203          c = .ch. i, lextokstr;
     204          if  c=1r  then  $ if end of current
     205              l = l+1; tokch(l, 1r.);
     206              slen hashtok = l;
     207              hashin(l);  j = j + 1; bugtoks(j) = l;
     208              l = 1;
     209          else  $ add character to current literal
     210              l = l+1; tokch(l, c);
     211              end if;
     212          end do;
     213      macdrop(lextokstr)
     214
     215 $    initialize one-character special token table
     217      slen hashtok = 1;  $ all immediate tokens are 1 char
     218      hashtyp = spectok;  $ and are special
     219
dsq  108      do  i = 1 to num_imtoks;
dsq  109          c = .ch. i, imtoks;
     222          tokch(1, c);  $ enter into hashtok
     223          hashin(haptr);
dsq  110          imtoktab(1+brkc(imtoks, 1, c)) = haptr;
dsq  111          end do;
dsq  112
dsq  113 .+s66.
dsq  114      $   for s66, initialize so both codes 3b'00' and 3b'63' accepted
dsq  115      $   as little colon.
dsq  116      .ch. 14, imtoks = 3b'63';
dsq  117      tokch(1, 3b'63'); hashin(ha_63b); imtoktab(14) = ha_63b;
dsq  118      .ch. 15, imtoks = 3b'00';
dsq  119      tokch(1, 3b'00'); hashin(ha_00b); imtoktab(15) = ha_00b;
dsq  120 ..s66
dsq  121
dsq  122      call blds(imtoks, ss_immed); $ string set for immediate tokens
     230 .+ca.
     231 $    hash in name -set- for use by conditional-assemblyfeature
     232
     233      tokch(1,1rs); tokch(2,1re); tokch(3,1rt);
     234      slen hashtok = 3;  hashtyp = nametok;
     235      hashin(hashcaset);  $ put hashcode in -hashcaset-
     236      $   generate set corresponding to target machine.
     237      tokch(2, (.ch. 1, tmparm));
     238      tokch(3, (.ch. 2, tmparm));
     239      hashin(i);
     240      cab ha(i) = yes;
     241      nuses ha(i) = suspi+1;  $ avoid listing as suspicious.
utsb  24 .+s32u.  $ if compiling in s32u, define symbol 's32u'.
utsb  25      tokch(1,1rs); tokch(2,1r3); tokch(3,1r2); tokch(4,1ru);
dsx   13      slen hashtok = 4;
dsx   14      hashin(i); cab ha(i) = yes; nuses ha(i) = suspi+1;
utsb  26 ..s32u
     242 ..ca
     243
     244      $   build string with compilation date for .compdate. value.
     245      slen hashtok = lstimelen;
     246      do  i = 1 to lstimelen;
     247          tokch(i, (.ch. i,lstimestr));
     248          end do;
     249      hashtyp = stringtok;
     250      hashin(ihcompdate);
     251
     252      hashtyp = spectok;
     253 +*   inihash(var, sym) =
     254      slen hashtok = slen sym;  $ set length in characters for hash
     255      do  i = 1 to slen sym;  tokch(i, (.ch. i, sym));  end do;
     256 .+ht.
     257      if  hashtrace  then
     258      textl('inihash -') textl(sym) charl(1r )
     259          tintl(' type',hashtyp)  endl   end if;
     260 ..ht
     261      hashin(var); **
     262
dsq  123      ihlp = imtoktab(1+brkc(imtoks, 1, 1r( ));
dsq  124      ihrp = imtoktab(1+brkc(imtoks, 1, 1r) ));
dsq  125      ihpl = imtoktab(1+brkc(imtoks, 1, 1r+ ));
dsq  126      ihst = imtoktab(1+brkc(imtoks, 1, 1r* ));
dsq  127      ihcm = imtoktab(1+brkc(imtoks, 1, 1r, ));
dsq  128      ihsemi = imtoktab(1+brkc(imtoks, 1, 1r; ));
dsq  129      iheq = imtoktab(1+brkc(imtoks, 1, 1r= ));
     267      inihash(ihsl, '/');  inihash(ihpr, '.');
     268
     269      hashtyp = nametok;
     270      call setlit;            $ routine to set literal codes
     271
     272 .+s66  litcod ha(ha_63b) = 70;  $ set literal code for colon.
     273 .+s66  litcod ha(ha_00b) = 70;  $ set literal code for colon.
     274 .+ca  nuses ha(hashcaset) = suspi + 1;
     275 .+ca.
     276      $   if initial set requested, set conditional bit for name.
     277      if  slen inisetparm  then
dsy   11           call cainit(inisetparm);
     281          end if;
     282 ..ca
     283      initializing = no;  $ indicate termination of initialization
     284      call stitlr(1, 'program listing (lexical phase)');
     285
dsq  130      call opninc('', inimemname, '', updseq); $ open input file.
     287
     288      macdrop(inihash);      $  drop -inihash- macro
     289      end subr lexini;
       1 .=member cainit
       2 .+ca.
       3       subr cainit(iparm);
       4
       5 $     initialize iset parameter string, which consists of names
       6 $     separated by plus sign characters with optional
       7 $     plus sign before first name.
       8
       9       size iparm(.sds. filenamelen);
      10       size  plen(ps);           $ length of parm string
      11       size  inow(ws);           $ current position
      12       size  ilen(ws);           $ length of current part.
      13       size  cnow(cs);           $ current character
      14       size  i(ws);              $ ha index.
      15       size  anyc(ws), brkc(ws); $ string search functions.
      16
      17       plen = .len. iparm;
      18       if  (plen = 0)  return; $ quit if null string.
      19
      20       inow = 1;
      21
      22       while inow <= plen;  $ loop over string
      23           cnow = .ch. inow, iparm;  $ get current character.
      24           if  cnow = 1r+  then $ if sign char.
      25               inow = inow + 1;  $ advance to next character
      26               cont while;
      27               end if;
      28           ilen = brkc(iparm, inow, 1r+); $ look for next plus
      29           hashtyp = nametok; $ assume name.
      30           if  ilen<0  then  $ if none, name is rest
      31               ilen = plen - inow + 1;
      32               end if;
      33           if alphabetic(cnow) = no then  $ error
      34               call ermsg(5,cnow,0); $ check error number
      35           else
      36               do  i = 1 to ilen;
      37                   cnow = .ch. (inow+i-1), iparm; $ next char.
      38                   if alphameric(cnow) = no then $ error
      39                       hashtyp = 0; $ indicate illegal.
      40                       quit do;
      41                       end if;
      42                   tokch(i, cnow);
      43                   end do;
      44               if hashtyp = 0 then  $ if illformed token
      45                   call ermsg(5, cnow, 0);
      46               else
      47                   slen hashtok = ilen;
      48                   hashin(i);
      49                   cab ha(i) = yes;
      50                   end if;
      51               end if;
      52           inow = inow + ilen;
      53           end while;
      54        end subr cainit;
      55 ..ca
       1 .=member setlit
       2      subr setlit;
       3      +* il(s) = call inslit(s); **
       4
       5      /*  literal strings and their literal numbers are encoded as
       6      described below in -inslit-. */
       7
       8
       9 $    note that the following mapping is identical to macro definitions
      10 $    in gen and any change  or addition must also be made in gen.
      11
      12      hashtyp = nametok;
      13
      14 il('1 if + while + until + do + end + else + size + dims + data ')
      15
      16 il('11 nameset + access + real + call + goby + return + elseif ')
      17
      18 il('18 in 21 rewind + filestat + go + cont + quit 32 to ')
      19
      20 il('59 check + trace + assert + nocheck + notrace + subr + fnct ')
      21
      22 il('66 monitor 71 then + by + index + flow + stores + entry ')
      23
      24 il('80 file 85 get + put 92 limit + read + write + prog ')
      25
      26      hashtyp = spectok;      $ special symbols
      27
      28 il('10 ; 36 ! 38 & 46 = 47 < + > + ^ + + + - + * + / ')
      29
      30 il('67 ( + ) + , + : ')
      31
      32      hashtyp = optok;
      33
      34 il('19 .sds. + .voapart. ')
      35
      36 il('26 .f. + .e. + .s. + .ch. 31 .cc. 33 .or. + .ex. + .exor. ')
      37
      38 il('37 .and. 39 .a. + .eq. + .ne. + .gt. + .lt. + .ge. + .le. ')
      39
      40 il('54 .in. + .not. + .n. + .fb. + .nb. ')
      41
      42 il('77 .voadump. + .len. + .pad. ')
      43
      44 il('81 .nocontr. + .toktr. + .notoktr. + .contr. ')
      45
      46 il('87 .ws. + .ps. + .cs. + .sl. + .so. 96 .seq. + .sne. ')
      47
      48      macdrop(il)
      49
      50      end subr setlit;
       1 .=member inslit
       2      subr inslit(s);  $ insert literal in hash table
       3      $ called by macro -il- to set literal code in ha for all
       4      $ keywords and literal
       5
       6      size  s(sds(70));  $ literal to hash
       7      size  litlc(ps);   $ literal code to set
       8      size  i(ps);             $ hash index of lit
       9      size  l(ps);     $ length of literal
      10      size  c(cs);       $ current character
      11      size  state(ps);     $ current state during scan
      12
      13      /* s is an encoding of literal numbers and corresponding literals.
      14      entries alternate between numerics and literals; numerics
      15      give the literal numbers (a + indicates that literal
      16      number is to be incremented).  fields are separated by one or more
      17      blanks.  the first field is a number, the last character must be
      18      blank.  */
      19
      20      state = 1;  $ begin with search for numeric
      21      litlc = 0;  $ literal code to set
      22
      23      do  i = 1 to slen s;
      24          c = .ch. i, s;  $ current character
      25          go to st(state) in 1 to 4;
      26      /st(1)/  $ skip blanks to start of numeric field
      27          if  (c=1r ) cont do;
      28          if  c = 1r+  then litlc = litlc + 1; state = 3;
      29          else
      30              litlc = digofchar(c); state = 2; end if;
      31          cont do;
      32      /st(2)/  $ collect numerics up to blanks
      33          if  (c=1r )  then  state = 3;
      34          else litlc = 10*litlc + digofchar(c); end if;
      35          cont do;
      36      /st(3)/  $ skip blanks to start of literal
      37          if  (c=1r ) cont do;
      38          l = 0;   state = 4;  $ start literal
      39          $ fall through to st(4) to get first character
      40      /st(4)/  $ add non-blanks to literal
      41          if  c=1r   then
      42              slen hashtok = l;  $ set length of literal
      43              hashin(l);  $ hash in, set hash code to l
      44              litcod ha(l) = litlc;  $ set literal code
      45              state = 1;
      46          else
      47              l = l+1; tokch(l, c); $ add character to literal
      48              end if;
      49          end do;
      50
      51      end subr inslit;
       1 .=member lexdo
       2      subr lexdo;  $  control routine - gets tokens and writes them out
       3 $    -lexdo- is main driver routine for scanner
       4 $    the initialisation routine -lexini- is called.
       5 $    tokens are then obtained from -nextw- and written
       6      size  i(ps);   $ temporary.
dsq  131      size  anyc(ws);   $ any string search function.
dsq  132      size  brkc(ws);   $ break string search function.
       7
       8  while  yes;  $ loop forever.
       9      while  yes;  $ loop until got a token.
      10 .+bub.
      11          if  rptr < resptr then  $ get from backup table.
      12              rptr = rptr+1;  iwd = res(rptr);  $ get token index.
      13              quit while;  $ show token obtained.
      14              end if;
      15 ..bub
      16
      17          dfabsrb(iwd);  $ get token from below.
      18          while  macimm ha(iwd);  $ process immediate macros.
      19              iwd = macorg ha(iwd);  $ get new token.
      20              end while;
      21
      22          $   now see if this token is a normal macro.
      23          if  macorg ha(iwd) then  $ it is a macro.
      24              call nextw;  $ call routine to start expansion.
      25              cont while;  $ go get next token.
      26              end if;
      27
      28          until  yes;  $ now check for zzz or zzy tokens.
      29              if  (lexlen ha(iwd) ^= 4) quit until;  $ not if length 4.
      30              if  (lextyp ha(iwd) ^= nametok) quit until;  $ not name.
      31              if  (.f. ws+1-2*cs, 2*cs, names(nameptr ha(iwd)) ^= 2rzz)
      32                  quit until;  $ first two characters not zz.
      33              i=lettercode((.f. ws+1-4*cs, cs, names(nameptr ha(iwd))));
      34              if  (i=0) quit until;  $ not letter *** assumes cpw>=4 ***
      35              if  .f. ws+1-3*cs, cs, names(nameptr ha(iwd)) = 1ry !
      36                  .f. ws+1-3*cs, cs, names(nameptr ha(iwd)) = 1rz then
      37                  call buildz(iwd, i, nametok + (dectok-nametok) *
      38                      (.f. ws+1-3*cs,cs,names(nameptr ha(iwd))=1ry));
      39                  end if;
      40              end until;
      41
      42          quit while;  $ show got token.
      43          end while;
      44
      45 .+bub.
      46      resptr = resptr+1;  res(resptr) = iwd;  $ save in backup buffer.
      47      rptr = resptr;  $ set pointer.
      48      if  resptr >= reslim then  $ this is a full buffer.
      49          do  i = 1 to reslim/2;  $ move down contents.
      50              res(i) = res(i + reslim/2);  $ move each entry.
      51              end do;
      52
      53          resptr = reslim/2;  rptr = resptr;  $ set new pointer.
      54          end if;
      55 ..bub
      56
      57      if  lexdotrace ! punchexpand then  $ must output something.
      58          if  punchexpand then  mflshr(iwd);  end if;
      59          if  lexdotrace then  $ print out token trace.
      60              tintl('lexdo, typ', lextyp ha(iwd)) tintl('hash', iwd)
      61              tintl('length', lexlen ha(iwd))
      62              tintl('litcod', litcod ha(iwd)) textl(' symbol <')
      63              tokl(iwd) textl('>') endl
      64              end if;
      65          end if;
      66
      67      if  (tokwrt = no) cont while;  $ skip if not writing token file.
      68
      69      $   now check to see if there is a card that has not been sent
      70      $   to gen.  if so, send it.
      71      if  cardsent = no then    $ if card has not been sent.
      72          if  lastwd = 0 then  $ if last word not determined yet.
      73              do  lastwd = wpc to 2 by -1;  $ scan down card.
      74                  if  (iwds(lastwd) ^= blankword) quit do;
      75                  end do;
      76              end if;
      77
      78          tokrwd = 0;  tokrlen tokrwd = cpw*lastwd;  $ set length.
      79          tokrtyp tokrwd = tokrcard;  $ set token type.
      80          tokrlc tokrwd = icdno-icdlast;  icdlast = icdno;  $ set diff.
      81          tokout(tokrwd, iwds, 1);  $ write out on token file.
      82          cardsent = yes;  $ show card written.
      83          end if;
      84
      85 .+tallytokens     tally(tallyparse)  $ count tokens sent to parser
      86
      87      tokrtyp tokrwd = lextyp ha(iwd);
      88      tokrlen tokrwd = lexlen ha(iwd);  $ enter length in characters
      89      tokrlc tokrwd = litcod ha(iwd);
      90      if  lexlen ha(iwd) <= cpstr  then  $ if short record, write single
      91          tokrval tokrwd = tokrval names(nameptr ha(iwd));
      92          tokout1(tokrwd);
      93      else
      94          tokout(tokrwd, names, (nameptr ha(iwd)));
      95          end if;
      96      end while;
      97
      98      end subr lexdo;
      99 .+mp.
       1 .=member nextw
       2      subr  nextw;  $ starts expansion of macros.
       3      size  astkcardno(ps);  $ card no. when start to get macro args.
       4      size  imacsta(ps);  $ holds current place in -mstk-
       5      size  j(ps);            $ do loop index for argument collection
       6      size  mbeg(ps);  $ index in -mtab- of start of mac defn
       7      size  place(ps);  $ position on arg stack
       8      size  prevloc(ps);  $ start of previous argument
       9
      10      +*  astkput(v) =  $ add value to arguemt stack.
      11          astkpt = astkpt + 1;  $ increment pointer.
      12          if  astkpt > astklim then  $ this is an overflow.
      13              call ermsg(28, mname, astkcardno);  $ print error message.
      14              astkpt = initloc;  $ back up to last position.
      15              astkset(astkpt, 0);  $ reset to end of last argument.
      16              return;  $ done - get next token.
      17
      18          else    $   this entry will fit.
      19              astkset(astkpt, v);  $ add value to stack.
      20              end if;
      21          **
      22
      23      mname = iwd;  $ save name of macro.
      24      mbeg = macorg ha(mname);
      25      numargs = mtget(mbeg);
      26      if  numargs = 0  then  $ no arguments, prepare for expansion
      27 $    stack current location of argstack top, macstack top, and stack
      28 $       initial dictionary pointer for current macro
      29          if  mstkpt+3 <= mstklim  then $ add 3 entries
      30              mstk(mstkpt+1) = astkpt;
      31              mstk(mstkpt+2) = mstkpt; $ save current position
      32              mstk(mstkpt+3) = mbeg + 1;
      33              mstkpt = mstkpt+3;
      34              astkput(0);
      35              return;  $ get next symbol.
      36          else  $ mstk overflow, force overflow error exit
dso   11              call ermsg(21, 0, 0);  call lexexit;  $ fatal error.
      38              end if;
      39          end if;
      40
      41      dfabsrb(iwd);
      42      if  iwd ^= ihlp  then  $ error, called with no arguments
dso   12          call ermsg(1, mname, 0);  $ issue diagnostic
      44          keepwd = iwd;  return;
      45          end if;
      46
      47      astkput(0);
      48      prevloc = astkpt;
      49      initloc = prevloc;
      50      nparen = 0;
      51
      52      astkcardno = icdno;  $ record card no. at start of macro
      53      $ so if overflow occurs, we can list this card number.
      54      j = 1;  $ show processing first argument.
      55      while  yes;  $ loop until exited.
      56          dfabsrb(iwd);  $ get next token.
      57          nparen = nparen + (iwd=ihlp) - (iwd=ihrp);  $ new paren level.
      58          until  yes;  $ quit if this token ends argument.
      59              if  (nparen = 0 & iwd = ihcm) quit until;  $ comma.
      60              if  nparen < 0 then  $ this end the argument list.
      61                  if  j < numargs then  $ too few arguments.
dso   13                      call ermsg(2, mname, 0);  $ print error message.
      63                      astkpt = initloc;  astkset(astkpt, 0);  $ reset ex
      64                      return;  $ go get next token.
      65                      end if;
      66
      67                  $   else this is a normal end of argument list.
      68                  quit until;  $ first, it is an end of argument.
      69                  end if;
      70
      71              $   this is now an item in the arguments.  if this is not
      72              $   past the last argument, add to list.
      73              if  j <= numargs then  $ add to stack.
      74                  astkput(iwd);  $ add to stack.
      75                  end if;
      76
      77              cont while;  $ go around again.
      78              end until;
      79
      80          $   this is argument terminator.  unless past last argument,
      81          $   add entry to stack.
      82          if  j <= numargs then  $ ok.
      83              astkput(0);  astkset(prevloc, astkpt);  $ chain.
      84              prevloc = astkpt;  $ set new previous location.
      85              end if;
      86
      87          if  (nparen < 0) quit while;  $ done if last argument.
      88
      89          if  j = numargs then  $ too many arguments.
dso   14              call ermsg(3, mname, 0);  $ print error message.
      91              end if;
      92
      93          j = j + 1;  $ increment argument count.
      94          end while;
      95
      96      place = initloc;
      97      imacsta = mstkpt;
      98      do  j =  1 to  numargs;
      99          countup(mstkpt, mstklim,
     100                  'macro recursion or excessive nesting.');
     101          mstk(mstkpt) = place + 1;
     102          size  ipl(ps); ipl = place;
     103          place = astkget(place);  $ advance to next arg
     104          astkset(ipl, 0);
     105          end do;
     106
     107      if  mstkpt+3 <= mstklim  then  $ add 3 entries
     108          mstk(mstkpt+1) = initloc-1;
     109          mstk(mstkpt+2) = imacsta;
     110          mstk(mstkpt+3) = mbeg + 1;
     111          mstkpt = mstkpt+3;
     112          astkput(0);
     113          return;
     114      else  $ mstk overflow, force overflow exit
dso   15          call ermsg(21, 0, 0);  call lexexit;
     116          end if;
     117
     118      end subr nextw;
       1 .=member buildz
       2      subr buildz(wd, ndx, typ);  $ build zzy or zzz token.
       3      size  wd(ps);           $ ha index of token constructed.
       4      size  ndx(ps);          $ index of counter.
       5      size  typ(ps);          $ lexical type desired.
       6
       7      if  typ = dectok  then
       8          call fivdec(countzzy(ndx));  $ get trailer part
       9          slen hashtok = 5;
      10          tokch(1, fivdecara(1));  tokch(2, fivdecara(2));
      11          tokch(3, fivdecara(3));  tokch(4, fivdecara(4));
      12          tokch(5, fivdecara(5));
      13      else
      14          tokch(1, 1rz); tokch(2, 1rz);  tokch(3,1rz);
      15          tokch(4,(.ch. ndx, 'abcdefghijklmnopqrstuvwxyz_'));
      16          call fivdec(countzzz(ndx));  $ get numeric trailer
      17          tokch(5, fivdecara(1));  tokch(6, fivdecara(2));
      18          tokch(7, fivdecara(3));  tokch(8, fivdecara(4));
      19          tokch(9, fivdecara(5));
      20          slen hashtok = 9;
      21          end if;
      22
      23      hashtyp = typ;
      24      hashin(wd);
      25
      26      end subr buildz;
       1 .=member defabsrb
       2      subr defabsrb;  $ detects macro definitions, and digests them
       3 $        this routine collects macro definitions and enters macro text
       4 $    in macro dictionary.  tokens are obtained from mcexpand and
       5 $    are sent on to nextw.  the bulk of the code consists of
       6 $    tests for a variety of errors in macro definitions.
       7 $        the routine also punches out macro definitions if the user
       8 $    has requested this feature.
       9      size  ano(1);   $ set if duplicate argument.
      10      size  cno(ps);  $ holds bit position in zzz zzy var search
      11      size  j(ps);  $ do loop index
      12      size  increm(ps);  $ ha-index bias used in -mtab-
      13      size  startl(ps);  $ holds current -mtab- pointer when def begun
      14      size  ismacimm(1);  $ 'is this immediate macro.'
      15      size  firstsym(ps);  $ first token in macro text.
      16      $   casezzy and casezzz distinguish first from later instances
      17      $   of zzy and zzz symbols, respectively.  the new symbol is
      18      $   generated on expansion of first instance.
      19      size  casezzy(27), casezzz(27);
dsq  133      size  brkc(ws);  $ break string match function.
      20
      21 /top/
      22      j = iwd;   $ save + or *.
      23      mcexpnd(iwd);   $ get next token.
      24      if  iwd ^= ihst then  $ no macro definitions.
      25          keepwd = iwd;  iwd = j;  return;  end if;  $ return token.
      26
      27      if  j = ihst then  $ macro closer in open text.
dso   16          call ermsg(4, 0, 0);  iwd = 0;  $ give error message.
      29          return;  $ return ignoring tokens.
      30          end if;
      31
      32 /macname/
      33      mcexpnd(mname);  $ get macro name
      34      listapt = 0;  $ set argument list pointer.
      35 $    if lexical type is name, go off to continue processing.
      36 $    otherwise print diagnostic 'missing macro name'.
      37
      38      if  lextyp ha(mname) ^= nametok  then  $ error, not name
dso   17          call ermsg(8, mname, 0);  $ issue diagnostic
      40          go to flush;  $ flush macro definition.
      41          end if;
      42
      43      if  punchdefine  then  $ if punching macros, punch + * name
      44          mflshr(ihpl); mflshr(ihst);
      45          mflshr(mname);
      46          end if;
      47
      48      mcexpnd(iwd);
      49      if  iwd = iheq then  $ this starts the parameters.
      50          if  punchdefine then  mflshr(iheq);  end if;
      51      elseif  iwd = ihlp then  $  seen (, must have macro args
      52          if  punchdefine  then  mflshr(ihlp); end if;
      53          until  iwd ^= ihcm;  $ loop until end of argument list.
      54              mcexpnd(iwd);
      55              if  lextyp ha(iwd) = nametok then
      56                  ano = no;  $ if non-zero will be argument number
      57                  do  j =  1 to  listapt;
      58                      if  iwd=listarg(j) then  ano=yes; quit do; end if;
      59                      end do;
      60
      61                  if  ano ! iwd = mname  then  $ error - duplicate argu
      62                      call ermsg(17, iwd, mname);
      63                  else
      64                      countup(listapt, listarglim, 'listapt');  $ add ne
      65                      listarg(listapt) = iwd;  $ list of macro arguments
      66                      if  punchdefine  then  mflshr(iwd); end if;
      67                      end if;
      68                  end if;
      69
      70              mcexpnd(iwd);  $ get next token.
      71
      72              if  iwd = ihcm then   $ this is normal ender.
      73                  if  punchdefine then  mflshr(iwd);  end if;
      74              elseif  iwd ^= ihrp then  $ this is an error.
dso   18                  call ermsg(16, mname,0);  keepwd = iwd;  $ flag error.
      76                  end if;
      77              end until;
      78
      79          if  punchdefine  then  mflshr(iwd); end if;
      80
      81          mcexpnd(iwd);
      82          if  punchdefine  then  mflshr(iheq); end if;
      83
      84          if  iwd ^= iheq then
dso   19              call ermsg(15, mname, 0);
      86              keepwd = iwd;
      87              end if;
      88
      89      else  $ if not (or = after +*name, then have error
      90          call ermsg(9, iwd, mname);
      91          go to flush;  $ go flush macro definition.
      92          end if;
      93
      94 $    here begin to accumulate macro text.  get hash table entry, number
      95 $    of prior uses
      96 $    prior  macro flag.  if flagged as macro, go off to zero word
      97 $    preceeding macro text, allowing eventual garbage collection. if
      98 $    used before, go off to give warning message.  save location
      99 $    in macro-text dictionary for eventual garbage collection.
     100 $    note starting macro-text dictionary location
     101
     102      if  macorg ha(mname) = 0 then
     103          if  nuses ha(mname) > 1 then  $ warning - name with prior use
dso   20              call ermsg(10, mname, 0);  end if;
     105 .+mtgc.
     106      else
     107          if  macorg ha(mname) > 1  then  $ clear origin word
     108              mtset(macorg ha(mname)-1, 0);  end if;
     109 ..mtgc
     110          end if;
     111 .+mtgc   countup(mtptr, mtlim, 'macro gc word');
     112      $   reserve entry for macro argument count.
     113      countup(mtptr, mtlim, 'macro arg. count');
     114      startl = mtptr;
     115      casezzy = 0;  casezzz = 0;
     116
     117 $        at the 'gettext' label below we
     118 $    collect text up to a closing '**',
     119 $    reporting on '+*' which is illegal.
     120 $    the macro text is transferred into
     121 $    mtable.
     122
     123 /gettext/
     124 $   sequence for collection of macro-body text
     125      mcexpnd(iwd);
     126      if  iwd = ihst ! iwd = ihpl then  $ this could be opener or closer
     127          j = iwd;  $ save whichever it was.
     128          mcexpnd(iwd);  $ get next token.
     129          if  iwd ^= ihst then  $ if not star, then last was not special
     130              keepwd = iwd;  $ keep last token.
     131              if  punchdefine then  mflshr(j);  end if;
     132              iwd = j;  go to sendback;  $ go back to previous and proce
     133              end if;
     134
     135          $   this was now either a '+*' or a '**'.  in either case
     136          $   terminate the current macro but issue an error message
     137          $   in the case of '+*'.
     138          if  j = ihpl then  $ this is an error.
dso   21              call ermsg(22, 0, 0);  $ give error message.
     140              iwd = 0;  $ set flag to loop back.
     141              end if;
     142
     143          if  punchdefine then  mflshr(ihst);  mflshr(ihst);  end if;
     144
     145      else    $   not special token.
     146          if  punchdefine then  mflshr(iwd);  end if;
     147          go to putmaywd;  $ now put into table.
     148          end if;
     149
     150      if  mtptr <= startl then
     151 $    drop macro status of -mname-
     152          nuses ha(mname) = 0;  $ clear use field
     153 .+mtgc.
     154          if  macorg ha(mname) > 1  then  $ clear origin word
     155              mtset((macorg ha(mname))-1, 0);
     156              end if;
     157 ..mtgc
     158          macorg ha(mname) = 0;
     159          macimm ha(mname) = no;
     160          mtptr = mtptr - 1;  $ reclaim argument count word.
     161          go to trysend;  $ try to get next token.
     162          end if;
     163
     164      $   see if macro can be made immediate.
     165      ismacimm = no;
     166      until 1;
     167          if  (mtptr > (startl+1))  quit until;  $ if more than one symb
     168          if  (listapt)  quit until; $ if arguments.
     169          firstsym = mtget(mtptr);  $ get symbol.
     170          if  (firstsym <= 300)  quit until;  $ if arg or zzz symbol.
     171          firstsym = firstsym - 300;  $ convert to ha index.
     172          $ if symbol is itself macro, cannot make immediate so can
     173          $ still detect macro recursion.
     174          if  (macorg ha(firstsym))  quit until;
     175          $   if symbol is +, cannot make immediate because of
     176          $   possibility of occurring in a macro definition.
     177          if  (firstsym = ihpl) quit until;
     178
     179          ismacimm = yes;  $ is immediate macro.
     180          end until;
     181
dso   22      if  (macorg ha(mname)) call ermsg(11, mname,0); $ redefining macro
     183
     184      macimm ha(mname) = ismacimm;
     185      if  ismacimm  then  $ if immediate.
     186          macorg ha(mname) = firstsym;
     187          mtptr = startl  - 1;
     188      else
     189          countup(mtptr, mtlim, 'mt');
     190          mtset(mtptr, 0);  $ mark end of macro text
     191 .+mtgc   mtset(startl, mname); $ record macro name index
     192          mtset(startl, listapt);  $ enter argument count.
     193          macorg ha(mname) = startl;
     194          end if;
     195
     196 /trysend/
     197      if  (iwd = 0) go to macname;  $ loop in error case.
     198      mcexpnd(iwd);  $ get the next token.
     199      if  (iwd = ihpl) go to top;  $ start again if +.
     200      return;  $ else return token.
     201
     202 /putmaywd/
     203      if  listapt  then  $ if arguments, see if argument.
     204          if  lextyp ha(iwd) = nametok  then  $ check only names.
     205              do  j = 1 to listapt;
     206                  if  iwd = listarg(j)  then
     207                      countup(mtptr, mtlim, 'mt');
     208                      mtset(mtptr, j);
     209                      go to gettext;  $ continue definition search.
     210                      end if iwd;
     211                  end do j;
     212              end if;
     213          end if listapt;
     214
     215   until 1;
     216      if  (lexlen ha(iwd) ^= 4) quit until; $ not zzz type
     217      if  (lextyp ha(iwd) ^= nametok) quit until;
     218      if  (.f. ws+1-2*cs, 2*cs, names(nameptr ha(iwd)) ^= 2rzz) quit;
     219      j = .f. ws+1-3*cs, cs, names(nameptr ha(iwd));  $ get third char
     220      if  (j=1rz) ! (j=1ry)  then
     221          cno = lettercode((.f. ws+1-4*cs, cs,names(nameptr ha(iwd))));
     222          if  (cno=0) quit until ;$ must be alphabetic, els skip
     223          increm = 100;
     224          if  j = 1ry  then  $ if zzy symbol.
     225              increm = increm + 50;
     226              if  .f. cno, 1, casezzy = 0  then  $ if first instance.
     227                  .f. cno, 1, casezzy = 1;
     228                  increm = increm + 100;
     229                  end if;
     230          else
     231              if  .f. cno, 1, casezzz = 0  then  $ if first instance.
     232                  .f. cno, 1, casezzz = 1;
     233                  increm = increm + 100;
     234                  end if;
     235              end if;
     236          countup(mtptr, mtlim, 'mt');
     237          mtset(mtptr, increm+cno); $ add biased symbol code to text
     238          go to gettext;
     239          end if;
     240   end until;
     241
     242 $  +* macro = zzza,zzza,zzyc,zzyc,zzyc**
     243 $    is put in mtable in the form
     244 $    201,101,253,153,153
     245
     246      if  iwd = mname then  $ error - macro occurs in self
dso   23          call ermsg(13, iwd, 0);  go to gettext; end if;
     248
     249 /sendback/
     250      countup(mtptr, mtlim, 'mt');
     251      mtset(mtptr, iwd+300);  $ enter standard token in text
     252      go to gettext;
     253
     254 /flush/  $ flush macro definition because of error.
     255      until  j = ihst & iwd = ihst;   $ until two stars.
     256          j = iwd;  mcexpnd(iwd);
     257          if  j = ihpl & iwd = ihst then  $ +* found.
dso   24              $ give error and continue.
dso   25              call ermsg(22, 0, 0);  go to macname;
     259              end if;
     260
     261          end until;
     262
     263      iwd = 0;  $ show no token gotten.
     264
     265      end subr defabsrb;
       1 .=member mcexpand
       2      subr mcexpand;  $  expands macros
       3 $    this routine expands macros, obtaining next token from trulex
       4 $    if no macros to expand.
       5
       6      size  aptr(ps);  $ index to part of macro arg list
       7      size  indx(ps);   $ index for zzzy, zzzz.
       8
       9 $    the encoding used in this section is as follows -
      10 $    pointers to the macro-text dictionary are integers not greater
      11 $    than the dimension 'mtlim' of the  dictionary. pointers
      12 $    to the argument stack are offset by a positive increment
      13 $    equal to mtlim
      14
      15 /macnext/
      16      aptr = mstk(mstkpt);
      17      if  aptr > mtlim  then  $ if expanding macro argument
      18          iwd = astkget(aptr - mtlim); $ next word in argument
      19          if  iwd = 0 then  $ have reached end of argument
      20              mstkpt = mstkpt - 1;  $ move down to next arg
      21              mstk(mstkpt) = mstk(mstkpt) + 1; $ move to next mac item
      22              if  (mstkpt > 1) go to macnext;  $ if more to do.
      23
      24          else  $ return word of macro text
      25              mstk(mstkpt) = aptr+1;
      26              end if;
      27
      28      else
      29          iwd = mtget(aptr);  $ get item from macro text
      30          if  iwd = 0 then  $ end of macro,restore state
      31              astkpt = mstk(mstkpt-2);  $ restore argstak pointer
      32              mstkpt = mstk(mstkpt-1);  $ restore mstak pointer
      33              if  (mstkpt) go to macnext;  $ continue if more ma
      34
      35          else
      36              if  iwd < 100 then  $ begin argument copy
      37                  countup(mstkpt, mstklim, 'mstk');
      38                  mstk(mstkpt) = mstk(mstk(mstkpt-2) + iwd) + mtlim;
      39                  go to macnext;
      40              else
      41                  if  iwd < 300 then  $ zzzy or zzzz case.
      42                      indx = mod(iwd-100, 50);  $ get case index.
      43                      go to zy((iwd-100)/50) in 0 to 3;
      44                   /zy(2)/ countzzz(indx) = countzzz(indx)+1;
      45                   /zy(0)/ call buildz(iwd, indx, nametok);
      46                      go to zydone;
      47                   /zy(3)/ countzzy(indx) = countzzy(indx)+1;
      48                   /zy(1)/ call buildz(iwd, indx, dectok);
      49                  else
      50                      iwd = iwd-300;
      51                      end if;
      52
      53                  /zydone/ mstk(mstkpt) = mstk(mstkpt) + 1;
      54                  end if;
      55              end if;
      56          end if;
      57
      58      end subr mcexpand;
      59 ..mp
       1 .=member trulex
       2      subr trulex;   $  gets tokens, eliminates comments
       3
       4 $    the routine -trulex- collects input characters together
       5 $    into tokens.
       6
       7      size  c(cs);          $ character scanned
       8      size  len(ps);                   $ string length.
       9      size  delimchar(cs);  $ delimiter for 0-type string constants
      10      size  i(ps);    $ while and do loop index
      11      size  bitmax(ps);    $ code for maximum acceptable char in bit con
      12      $   need nultyp since lexca may also call hash and so set hashtyp.
      13      size  nultyp(ps);       $ new lexical type.
      14      size  blankinsidenumeric(1);  $ on if numeric contained blank.
dsq  134      size  anyc(ws);    $ any string match function.
dsv   49 .+mc size  ctpc(cs);   $ function to convert character to primary case.
dsq  136      size  brkc(ws);  $ break string match function.
      15
      16
      17 /scanon/
      18      tokptr = 0;  $ reset token pointer
      19
      20      giveq(c);  $ get a character.
      21
      22 /newchar/  $ here to process a gotten character.
      23 .+bskp_env.  $ if assembler blank skip.
dsqa   1      while  c=1r ;
      25          call 7nbskp$li(iwds, nowdp, nc10, nowc, nowd, c, tallyeol);
dsqc   1          $   if rest of line blank, then read next line
dsqc   2          $   and process here following lines which have
dsqc   3          $   initial $ and hence are comments.
dsqc   4          if  nowc>mccd & c=1r  then  $ if rest blank.
dsqa   3              while 1;
dsqa   4                  call givecr(c);  $ get next line.
dsv   50 .+mc             c = ctpc(c);  $ in case first char is other-case.
dsqa   6                  if  (c^=1r$)  quit while;
dsqa   7 .+tallycomments  tally(tallyeol);
dsqa   8                  end while;
dsqa   9              end if;
dsqa  10          end while;
dsq  137      $   bskp skips only blanks so need check again in case
dsq  138      $   character is now non-blank separator.
dsq  139 ..bskp_env
      28      $   we know that blanks cannot be in -keep- so we can use a
      29      $   quicker scan.
dsq  140      while  isblank(c);  giveqnk(c);  end while;
      32
dsq  141  if anyc(c, ss_immed)  then  $ if immediate token.
      34 .+tallytokens  tally(tallyimtok) $ count immediate tokens
      35 .+ht.
      36      if  hashtrace  then  textl(' imtok=') charl(c) charl(1r ) end if;
      37 ..ht
dsq  142          iwd = imtoktab(1+brkc(imtoks, 1, c));
dsq  143          return;
      39
      40 elseif  alphabetic(c)  then  $ if name.
      41          nultyp = nametok;
      42          while  alphameric(c);  charin(c);  giveq(c);  end while;
      43          go to endc;
      44
      45 elseif  numeric(c)  then
      46
      47          nultyp = dectok;
      48          blankinsidenumeric = no;
      49          while  1;
      50              charin(c);  giveq(c);
      52              if  (numeric(c)) cont while;  $ continue if numeric.
dsq  144              if  isblank(c)  then  $ look for run of blanks in integer
      54                  blankinsidenumeric = yes;
dsq  145                  while  isblank(c);  giveqnk(c);  end while;
      56                  if  (numeric(c)) cont while;
      57                  go to endc;
      58              elseif  c = 1rb  then
      59                  if  (tokptr>1)  go to endc;
      60                  i = digofchar(tok(1));
      61                  if  (i<1 ! i>4)  go to endc;
      62                  givec(c);
      63                  if  c=1r'  then  charin(1rb);
      64                  else  keepc(1rb);  go to endc;  end if;
      65                  nultyp = bittok;
dsq  146                  bitmax = 0;
      67                  .f. i+1, 1, bitmax = 1;
      68                  do  i = 1 to maxtoklen-3;
      69                      tokptr = tokptr+1;  tok(tokptr) = c;  giveqnk(c);
      70                      if  c = 1r'  then  $ if end of constant.
      71                          tokptr=tokptr+1;  tok(tokptr)=c;  go to endc2;
dsq  147                      $ gen requires blanks within constants
dsq  148                      elseif  isblank(c)  then c = 1r ;
dsq  149                      $   here to check for valid code.
dsq  150                      elseif  brkc('0123456789abcdef', 1, c) < 0
dsq  151                          ! brkc('0123456789abcdef', 1, c)>=bitmax  then
dso   26                          call ermsg(32,c,0);
      75                          c = 1r0;
      76                          end if;
      77                      end do;
dso   27                  call ermsg(33, 0, 0);
      79              elseif  c = 1r.  then  go to periodafterint;
      80              elseif  c = 1re  then  $ insert e, go get exponent.
      81                  charin(1re);  givec(c);  go to getexpval;
      82              elseif  alphabetic(c)  then  quit while;
      83              else  go to endc;
      84                  end if;
      85              end while;
      86
      87          if  alphabetic(c)  then
      88          if  (tokptr>5)  go to endc;
      89          if  (blankinsidenumeric)  go to endc;
      90          if  c = 1rn  then  nultyp = nametok;
      91          elseif c = 1rq  then nultyp = stringtok;
      92          elseif c = 1rr  then nultyp = rztok;
      93          elseif c = 1rs  then nultyp = sstok;
      94          else  go to endc;  end if;
      95
      96          len = 0;
      97          do  i = 1 to tokptr; len = len*10 + digofchar(tok(i)); end do;
      98          tokptr = 0;  $ reset token pointer
      99          $ see if next char after integer is string type char
     100          $ in which case then collect and format string contents
     101          if  len = 0  then  $ contents are delimited
     102              givecstr(delimchar);
     103              givecstr(c);  $ first char in contents
dsv   51 .+mc         if (nultyp=sstok ! nultyp=nametok) c = ctpc(c);
dsq  153              while  c ^= delimchar;
dsq  154                  charin(c);
dsq  155                  givecstr(c);
dsv   52 .+mc             if (nultyp=sstok ! nultyp=nametok) c = ctpc(c);
dsq  157                  end while;
     105              len = tokptr;  $ save length of delimited string
     106          else     $ length known, accumulate contents
dsq  158              do  i = 1 to len;
dsq  159                  givecstr(c);
dsv   53 .+mc             if (nultyp=sstok ! nultyp=nametok) c = ctpc(c);
dsq  161                  charin(c);
dsq  162                  end do;
     108              end if;
     109          go to endc2;    $ current character absorbed
     110          else  go to endc;  end if;
     111
     112 elseif  c = 1r$  then
     113
     114          call givecr(c);  $ read next card
dsw   16 .+mc     c = ctpc(c);  $ convert to primary case.
     115 .+tallycomments   tally(tallyeol)  $ count eol comments
     116          go to newchar;
     117
     118 elseif  c = 1r/  then
     119
     120 $    we have seen  /. if * follows, then collect comment; otherwise
     121 $    token is /.  we monitor inside of comment for unexpected  / * .
     122          givec(c);
     123 $   reach here after seeing slash asterisk, so check
     124 $   for corresponding asterisk slash  closure
     125          if  c ^= 1r*  then  $ not pl1 comment, end token
     126 .+ht.  $ if hash trace on, hash in normally to get trace.
     127              if  hashtrace  then
     128                  charin(1r/);  nultyp = spectok;  go to endc;
     129                  end if;
     130 ..ht
     131              iwd = ihsl;  $ token is slash.
     132              keepc(c);  $ save character after slash.
     133              return;
     134              end if;
     135 $    now absorb pl1 style comment
     136 .+tallycomments   tally(tallypl1) $ count pl/1 comments
     137      while  1;  $ collect comment body.
     138          givec(c);  $ loop while asterisk seen
     139          if  c=1r/  then  $ if / * inside comment, treat as error.
     140              givec(c);
dso   28              $ error if see / * inside comment.
dso   29              if  (c=1r*)  call ermsg(27, 0, 0);
     142              end if;
     143          if  (c ^= 1r*) cont while; $ continue if not -*-
     144          givec(c);  $ now see if / after *
     145          while c=1r*; givec(c); end while; $ look for run of *'s.
     146          if  (c=1r/)  quit while;
     147          end while;
     148      go to scanon;
     149
     150 elseif  c = 1r'  then
     151
     152          nultyp = stringtok;
     153 $        here we collect quoted string, using givecstr to get character
     154 $        since inside string
     155          while tokptr <= maxtoklen-2;  $ at most lnqtmax chars in strin
     156              givecstr(c);
     157              if  (c=1r')  then
     158                  givecstr(c);  $ get char after quote
dsq  163                  if  c ^= 1r'  then  $ if end of string.
dsv   54 .+mc                 c = ctpc(c); $ fold following character.
dsq  165                      go to endc;
dsq  166                      end if;
     160                  end if;
     161          tokptr = tokptr+1;  tok(tokptr) = c;  $ add to token.
     162              end while;
dso   30          call ermsg(18,maxtoklen, 0);  go to endc;
     164
     165 elseif  c = 1r.  then
     166
     167          charin(c);  $ dot begins token.
     168          givec(c);
     169          if  numeric(c)  then  go to real3;  $ if  real constant.
     170          elseif  alphabetic(c) = no  then  $ if not start of op.
     171              nultyp = spectok;  go to endc;  $ is special token.
     172          end if;
     173
     174          nultyp = optok;
     175          charin(c);  givec(c);
     176          while alphabetic(c);  charin(c); givec(c); end while;
     177          if  c=1r.  then  charin(c);  else  go to endc2;  end if;
     178 $       end of period-delimited token. check for special operator
     179 $        type tokens which have special meaning to scanner
     180 $        tokens and actions are
     181
     182 $    .chtr.        trace each character received from -givec-
     183 $    .nochtr.      end character trace
     184 $    .hatr.        enable trace of hash routine
     185 $    .nohatr.      end hash trace
     186 $    .lextr.       trace tokens sent to parser ,ie from nextw)
     187 $    .nolextr.     end parser token ttace
     188 $    .compdate.    return string with compilation date.
     189
     190
     191      $   .mactr.  trace macro routines
     192 $   .nomactr.  disable trace of macro routines
     193
     194 $    any special tokens detected are absorbed here
     195
     196      if  (tokptr <= 5) go to endc2;    $ special at least six character
     197      sdspack(tok, tokptr);  $ pack into hashtok for hash
     198      $  hash in token so can see if special
     199      hashtyp = optok;
     200      hashin(iwd);
     201      do  i =  1 to  numbugtoks;  $ search for special bug token
     202          if  (bugtoks(i) ^= iwd) cont do;
     203          go to bt(i) in 1 to numbugtoks;
     204 /bt(1)/    /bt(2)/
     205 .+ct     chartrace = (i=1);
     206          go to scanon;
     207
     208 /bt(3)/    /bt(4)/
     209 .+ht     hashtrace = (i=3);
     210          go to scanon;
     211
     212 /bt(5)/    /bt(6)/
     213          lexdotrace = (i=5);
     214          go to scanon;
     215
     216 /bt(7)/    /bt(8)/
     217 .+mt     mactrace = (i=7);
     218          go to scanon;
     219
     220 /bt(9)/  iwd = ihcompdate;  return;  $ pass on date.
     221          end do;
     222
     223      $   since not special, pass on to parser.
     224      return;  $ no need to hash again
     225
     226 else  $ if special token.
     227          charin(c);
     228          nultyp = spectok;
     229          go to endc2;
     230          end if;
     231
     232 /periodafterint/
     233 $    we have seen '123.' - may have real, or integer followed by dot-op
     234      givec(c);
     235      if  numeric(c)  then  $ if next char numeric, must have real
     236          charin(1r.);  go to real3;
     237
     238      elseif  alphabetic(c) & (c^=1re)  then
     239 $        if  letter other than e follows ., have dot-op after int.
     240          keepc(c);  keepc(1r.);
     241          go to endc2;
     242
     243      elseif  c=1re  then  $ if have 123.e, may be real or operator
     244          givec(c);
     245          if  numeric(c) ! c=1r+ ! c=1r-  then  $ definitely real
     246              charin(1r.);  charin(1re);  go to getexpval;
     247          else  $  not exponent, so have integer then dot-op
     248              keepc(c);  keepc(1re);  c = 1r.;  go to endc;
     249              end if;
     250      else  $ dot is not part of dot-op, so have simple real
     251          charin(1r.);  nultyp = realtok;  go to endc;
     252          end if;
     253
     254 /real3/
     255      $  seen real, collect remaining numeric part, then exponent if pre
     256      nultyp = realtok;
     257      if  numeric(c)  then  $ collect numbers, watch for internal blanks
     258
     259          while numeric(c);
     260              charin(c);  givec(c);
dsq  167              if  isblank(c)  then  $ if blank, watch for run of blanks
dsq  168                  while  isblank(c);  givec(c);  end while;
     263                  if  (numeric(c)=no)  go to endc;  $ at end of run
     264                  $ must see numeric to remain inside constant
     265                  end if;
     266              end while;
     267
     268          end if;
     269      if  c=1re  $ if exponent present, digest it.
     270          then charin(c); givec(c);
     271          else go to endc;  end if;
     272
     273 /getexpval/
     274      $ collect exponent value
     275      nultyp = realtok;
     276      if  c=1r+ ! c=1r-  then  charin(c);  givec(c);  end if;  $ absorb
     277          $ sign field, if present.
     278
     279      if  numeric(c)  then  $ absorb value, watching for internal blanks
     280          while numeric(c);
     281              charin(c); givec(c);
dsq  169              while  isblank(c);  givec(c);  end while;
     283              end while;
     284      else  $ missing exponent value, take 0
dso   31          call ermsg(26, 0, 0);
     286          charin(1r0);
     287          end if;
     288      go to endc;
     289
     290 /endc/
     291      keepc(c);
     292 /endc2/
     293 $    pack token into -hashtok-, set length, hash in.
     294      sdspack(tok, tokptr);  $ pack token into hashtok.
     295      hashtyp = nultyp;
     296      hashin(iwd);  $ hash and set -iwd- to hash-index obtained
     297
     298      end subr trulex;
       1 .=member givesp
       2      subr givesp(ic);  $ get char. inside string.
       3      size  ic(ps);
       4
       5      if  keepindex  then  $ if prior token kept.
       6          getfromkeep(ic);
       7      elseif  nowc > mccd  then  $ elseif new card needed.
       8          call givecr(ic);    $ read next card.
       9      else
      10          if  nc10 = 1 then  $ if need next word
      11              nowdp = nowdp + 1;
      12              nowd = iwds(nowdp); $ fetch next word.
      13              nc10 = ws + 1;
      14              end if;
      15          nc10 = nc10 - cs;   $ advance to next character position.
      16          ic = .f. nc10, cs, nowd;  $ extract character.
      17          nowc = nowc + 1;
      18          end if;
      19 .+ct.
      20      if  chartrace  then  $ if tracing characters.
      21          textl(' ct=<') charl(ic) textl('> ')
      22          end if;
      23 ..ct
      24      return;
      25      end subr givesp;
       1 .=member givecp
       2      subr givecp(c);  $ get character
       3      size  c(cs);
dsv   55 .+mc size  ctpc(cs);   $ function to convert character to primary case.
       4      givec_text(c);
       5      return;
       6      end subr givecp;
       1 .=member givecr
       2      subr givecr(ic);  $ process card (list, output, ca, .. etc)
       3      size  ic(cs);  $ returned character
       4      size  work(ps);  $ work to do; see -normwork- in -start-
       5 .+ca size  col(ps);  $ no. cols to clear (ca)
       6      size  i(ps), j(ps);  $ do loop indexes
dsq  171      size  anyc(ws);  $ any string match function.
dsv   56 .+mc size  ctpc(cs);  $ function to convert to primary case character.
       7
       8 /reread/
       9      work = normwork;  $ set to normal options
      10      if  errecho then  $ just want to list
      11          work = list_work; $ just set list flag
      12          go to l(list_work);
      13          end if;
      14
      15      call getinc(iwds, 1, wpc, iorc);  $ read next card
      16      if  iorc then  $ end-of-file
      17          exitcode = 0; call lexexit; $ exit at end of file
      18          end if;
      19
      20      icdno = icdno+1;  $ increment cards read counter
      21
      22      $   now check if this could overflow the -tokrlc- field.
      23      if  icdno-icdlast > 200 then  $ could overflow.
      24          if  tokwrt then   $ if writing token file.
      25              $   must write out null card.
      26              tokrwd = 0;  tokrtyp tokrwd = tokrcard;  $ set type.
      27              tokrlc tokrwd = icdno-icdlast;  $ insert value.
      28              tokout1(tokrwd);  $ write to token file.
      29              end if;
      30
      31          icdlast = icdno;  $ set new line number.
      32          end if;
      33
      34      cardlisted = no;  $ show card not listed yet
      35      lastwd = 0;  $ set unknown last word
      36
      37      $   now check for directive or conditional card
      38      until yes;   $ start 'maybe' loop
      39          if  (.f. ws+1-2*cs, cs, iwds(1) ^= 1r.) quit until;
      40          if  (alphabetic((.f. ws+1-4*cs,cs, iwds(1))) = no) quit until;
      41 $ *********note********* above assumes at least 4 chars/word
      42          if  (.f. ws+1-1*cs, cs, iwds(1) ^= 1r ) quit until;
      43          $   may now have card of interest - check column 3
      44          col3char = .f. ws+1-3*cs, cs, iwds(1);
      45          if  col3char = 1r= & cardskip = no then $ may be directive
      46              call lexdir(work);  $ process if so
      47 .+ca.
      48          elseif  iscachar(col3char) then  $ may be ca
      49              call lexca(work, col);  $ process if so
      50 ..ca
      51              end if;
      52          end until;
      53
      54      $   the variable -work- has been set to select the work that must
      55      $   be done on the current card.  the -go to- statement branches
      56      $   to labels which select the order in which the work is
      57      $   to be done.
      58      while  work;  $ loop until no work to
      59          work = work ! 1b'10000';     $ turn on extra bit.
      60          go to l(work) in 17 to list_work!elim_work!out_work!proc_work;
      61
      62 /l(list_work!out_work!elim_work!proc_work)/
      63 /l(list_work!out_work!elim_work          )/
      64 /l(list_work!out_work          !proc_work)/
      65 /l(list_work!out_work                    )/
      66 /l(list_work         !elim_work!proc_work)/
      67 /l(list_work         !elim_work          )/
      68 /l(list_work                   !proc_work)/
      69 /l(list_work                             )/
      70          work = work & ^list_work;  $ clear list flag
      71          if  (cardlisted) cont while;  $ dont list twice
      72          cardlisted = yes; $ show will list card
      73          if  lastwd = 0 then  $ determine last word to list
      74              do  lastwd = wpc to 2 by -1; $ get blanks off end
      75                  if  (iwds(lastwd) ^= blankword) quit do;
      76                  end do;
      77              end if;
dsq  173      intl(icdno)  $ print line number.
dsq  174      $   print tab if available to retain correct tabular alignment.
dsq  175      if  cc_tab ^= 1r   then  $ list tab if available.
dsq  176          charl(cc_tab)
dsq  177      else  $ else list two blanks.
dsq  178          skipl(2)
dsq  179          end if;
      79          call wordsr(iwds, 1, lastwd);  $ list line.
      80          endl  $ end of line
      81          cont while;
      82
      83 /l(elim_work!out_work!proc_work)/
      84 /l(elim_work!out_work          )/
      85 .+ca     if  (.f. list_qualifiers, 1, listnow) go to l(out_work);
      86
      87 /l(elim_work!proc_work)/
      88 /l(elim_work          )/
      89 .+ca.
      90          work = work & ^elim_work;  $ turn off flag
      91          i = col/cpw;  $ set no. words to clear
      92          do  j = 1 to i;  $ clear each word
      93              iwds(j) = blankword;
      94              end do;
      95          i = col - i*cpw; $ set no. remaining cols to clear
      96          if  (i) .f. ws+1-i*cs, i*cs, iwds(j) = blankword; $ clear
      97          cont while;
      98 ..ca
      99
     100 /l(out_work!proc_work)/
     101 /l(out_work          )/
     102          work = work & ^out_work;  $ reset flag.
     103          if  tokwrt then  $ write to token file
     104          $   if gen will not list cards, then it will only
     105          $   need a card if there is an error detected.  however,
     106          $   there cannot be an error on a card without tokens.
     107          $   therefore, if gen will not list cards, we should not
     108          $   pass the card unless there are tokens on it.  so set
     109          $   a flag and have -lexdo- send the card.
     110          if  listingen = no then  $ gen will not list.
     111              cardsent = no;  $ set flag to show not sent.
     112              cont while;  $ done with this bit of work.
     113              end if;
     114
     115              if  lastwd = 0 then  $ must check for last word
     116                  do  lastwd = wpc to 2 by -1;  $ find last non-blank
     117                      if  (iwds(lastwd) ^= blankword) quit do;;
     118                      end do;
     119                  end if;
     120              tokrwd = 0; tokrlen tokrwd = cpw*lastwd; $ set length
     121              tokrtyp tokrwd = tokrcard;  $ code for card
     122              tokrlc tokrwd = icdno-icdlast;  $ set number of cards.
     123              icdlast = icdno;  $ reset last card number.
     124              tokout(tokrwd, iwds, 1);  $ output card image
     125              cardsent = yes;  $ show card sent to gen.
     126              end if;
     127          cont while;
     128
     129 /l(proc_work)/
     130          $   now, set to read first char on card
     131          nowdp = 1;  $ point to first word of card
     132          nc10 = ws-cs+1;  $ point to next char position
     133          nowd = iwds(1);  $ first word of card
     134          ic = .f. ws-cs+1, cs, nowd;  $ get first char
     135          nowc = 2;  $ next char will be col 2
     136          return;
     137
     138          end while;
     139
     140      $   done with all work.  we now either read another card or,
     141      $   if -errecho- is set, return.
     142      if  (errecho = no) go to reread;
     143      errecho = no;  $ reset flag
     144
     145      end subr givecr;
       1 .=member lexca
       2      subr lexca(work, col);  $ process conditional card
       3      $   this routine processes the conditional qualifiers that may
       4      $   appear on cards.  it is responsible for setting -normwork-
       5      $   and -cardskip- when a skip is to be done or ends.
       6      size  work(ps);  $ work to be done on card
       7      size  col(ps);   $ output - no. of cols to clear
       8      size  i(ps);     $ do loop index
       9      size  c(cs);     $ character from card
dsq  180      size  anyc(ws);   $ any string match function.
dsv   57 .+mc size  ctpc(cs);   $ function to map character to primary case.
      10
      11      +*  getc(ic) =  $ macro to get next character from card
      12          if  nowc > mccd then  $ at end of card
      13              ic = 1r$;  $ pass non-alpha and non-blank
      14          else
      15              if  nc10 = 1 then  $ new word needed
      16                  nowdp = nowdp+1; nowd = iwds(nowdp);
      17                  nc10 = ws+1;  $ reset to start of word
      18                  end if;
      19              nc10 = nc10-cs;  $ advance to next character
dsv   58 .+mc         ic = ctpc((.f. nc10, cs, nowd));
dsv   59 .-mc         ic = .f. nc10, cs, nowd;
dsq  184              nowc = nowc+1;
      21              end if;
      22          **
      23
      24      nowc = 4; $ next char is fourth
      25      nowdp = 1;  $ set to word 1 **** assumes cpw >= 4****
      26      nowd = iwds(1);  $ get proper word
      27      nc10 = ws+1+cs-4*cs;   $ set to place to get next char.
      28
      29      if  cardskip then  $ must find matching name.
      30          do  i = 1 to canamel; $ compare each character
      31              getc(c); if (c ^= caname(i)) return; $ ignore card if not
      32              end do;
      33          $   name matches, ensure next character is not part of name.
      34          getc(c); if  (alphameric(c)) return;  $ not matching if so
      35      else  $ get ca name
dsy   12           getc(c);
dsy   13           if alphabetic(c)=no then  $ if first not alphabetic
dsy   14               call ermsg(6,0,0); $ report error.
dsy   15               return;
dsy   16               end if;
dsy   17           caname(1) = c;
dsy   18          do  canamel = 2 to mccd;  $ collect name - loop will be -quit-
      37              getc(c);  $ get a character
      38              if  (alphameric(c) = no) quit do;  $ stop at non-alpha
      39              caname(canamel) = c;  $ insert character
      40              end do;
      41          canamel = canamel-1; $ reset because last character not in str
      42          end if;
      43
      44      $   we now have conditional name to process.  hash in and
      45      $   determine new status.
      46      sdspack(caname, canamel);  $ pack into -hashtok-
      47      hashtyp = nametok; hashin(hashca);  $ hash in
      48
      49      if  col3char ^= 1r. & hashca = hashcaset then  $ this is 'set'
      50          while  c ^= 1r$;  $ loop until end of input
dsy   19              until  alphabetic(c) ! c = 1r$;  $ skip blanks
      52                  getc(c);  $ get next character
      53                  end until;
      54              canamel = 0;  $ reset name length
      55              while  alphameric(c);  $ process name
      56                  canamel = canamel+1; caname(canamel) = c; $ set char.
      57                  getc(c);  $ get next character
      58                  end while;
      59              if  canamel then  $ name present
      60                  sdspack(caname, canamel);  $ pack ino -hashtok-
      61                  hashtyp = nametok; hashin(hashca);
      62                  cab ha(hashca) = (col3char = 1r+); $ set value
      63                  end if;
      64              end while;
      65          work = work & ^proc_work;  $ dont scan for tokens
      66          if  (.f. list_qualifiers, 1, listnow = no) $ dont send to -gen
      67              work = work & ^out_work;  $ dont write to token file
      68          return;  $ done in this case
      69          end if;
      70
      71      $   we now have a 'normal' conditional card.  see if we should
      72      $   skip this card and whether -cardskip- should be set.
      73      if  col3char = 1r. then  $ this always ends skip
      74          cardskip = no; $ set no skip
      75      else  $ test -cab- agreement
      76          cardskip = ((col3char = 1r+) ^= cab ha(hashca));
      77          work = work ! (out_work!proc_work);  $ set default values
      78          if  cardskip then  $ this card will be skiped
      79              work = work & ^proc_work;  $ -lex- wont process
      80              if  (.f. list_skip, 1, listnow = no) $ dont give to -gen-
      81                  work = work & ^out_work;  $ dont write to token file
      82              cardskip = (c = 1r.);  $ only skip if next char is '.'.
      83              end if;
      84          end if;
      85
      86      $   finally, set final status according to -cardskip-.
      87      if  (work & ^list_work) work = work ! elim_work;  $ elim if needed
      88      col = nowc-1;  $ set elimination boundary
      89      normwork = normwork ! (out_work!proc_work); $ set to process.
      90      if  cardskip then  $ dont process until further notice.
      91          normwork = normwork & ^proc_work;  $ dont process
      92          if  (.f. list_skip, 1, listnow = no)  $ dont list in -gen-
      93              normwork = normwork & ^out_work;  $ dont write to token
      94              end if;
      95
      96
      97      macdrop(getc)
      98      end subr lexca;
       1 .=member lexdir
       2      subr lexdir(work);  $ parse input directive
       3      $   process  .=eject  .=list  .=punch  .=title
       4
       5      $   line is sds form of current line.  lorg is macro giving
       6      $   string origin.
       7      +*  lorg = (1 + .sds.(cpw*wpc)) **
       8      +*  linech(i) = .f. lorg -(i)*cs, cs, line**  $ ith character of l
       9      $   ara holds words to be written on token file.
      10      $   ara will contain several list entries, eject entry or
      11      $   title entry.
      12      size  ara(ws);  dims ara(wpc+2);
      13      size  araptr(ps);       $ top of ara list.
      14      size  c(cs);            $ character.
      15      size  i(ps), j(ps), l(ps);    $ counters.
      16      size  work(ps);  $ work value for card
      17      size  key(.sds.10);
      18      size  keycode(ps);      $ position in directive code list.
      19      size  line(lorg-1);   $ input line as string.
      20      size  lpos(ps);        $ start of parameter list.
      21      size  parmvalue(1);     $ set if parm present.
      22      size  pgiven(ps);       $ bit i set if ith code present.
      23      size  pl(ps);
      24      size  prm(.sds. 6);     $ parameter from list.
      25      size  pvalue(ps);       $ bit i set if ith code set.
      26      $   parmstr gives list of directive codes.
      27      size  parmstr(.sds. (5 +7*numlistparms));
      28      size  prmcopy(.sds. 6); $ copy of parm if 'no' given.
      29      size  resuming(1);      $ on when resuming previous list status.
      30      size  tokrwd(ws);       $ word for token file.
      31      size  lexlist(1); $ on to list card in -lex-
      32      size  genlist(1); $ on to list card in -gen-
      33      size  listdir(1); $ value of 'dir' parm
dsq  185      size  anyc(ws);   $ any string match function.
dsv   60 .+mc size  ctpc(cs);   $ function to convert character to primary case.
dsq  187      size  brkc(ws);  $ break string match function.
      34
      35      l = 0;
      36      sorg line = lorg;
      37      do  i = 1 to wpc;
      38          .f. lorg - i*ws, ws, line = iwds(i);
      39          end do i;
      40      sorg line = lorg;
      41      slen line = mccd + 1;
      42      linech(mccd+1) = 1r ;
      43      lpos = 3;
dsq  188      until isblank(linech(lpos));
      45          lpos = lpos + 1;
      46          end until;
      47      key = .s. 1, 10, line;
      48      if  (lpos<10)  slen key = lpos;
      49        parmstr = ' 1 .=eject  2 .=list  3 .=punch  4 .=title '
      50            !! ' 5 .=zzyorg  6 .=member ';
dsv   61 .+mc     call stpc(key); $ convert to primary case.
      51      keycode = key .in. parmstr;
      52      if  (keycode)  keycode = digofchar((.ch. keycode-1, parmstr));
      53      if  (keycode = 0)  return;
      54      $   set lpos to index start of parameter string.
dsq  190      while isblank(linech(lpos));
      56          lpos = lpos + 1;
      57          if  (lpos>mccd) quit while;
      58          end while;
      59      if  (lpos>=mccd) lpos = 0;
      60
      61      slen parmstr = 0;
      62      if(keycode=2) parmstr = ' cod=01 inp=02 aut=03 ski=04 qua=05'
      63          .cc. ' lin=06 ref=07 res=10 dir=11 ';
      64      if(keycode=3) parmstr = ' def=08 exp=09 dir=11 ';
      65      if  (slen parmstr = 0 ! lpos = 0) go to endparmlist;
      66      prm = 6q------;  $ set - so will not find in parm code list.
      67      pgiven = 0; pvalue = 0;
      68      pl = 0;
      69      while 1;  $ process listed values until blank seen.
      70          c = linech(lpos);
      71          if  alphameric(c)  then
      72              if  pl < 5  then
      73                  pl = pl + 1; .ch. pl, prm = c;
      74                  end if;
      75          else  $ nonalphabetic character ends parameter.
      76              slen prm = pl;
      77              if  ('no' .in. prm) = 1  then  $ if disabling, remove 'no'
      78                  prmcopy = prm;
      79                  prm = 6q------;
      80                  do  i = 1 to pl-2;
      81                      .ch. i, prm = .ch. i+2, prmcopy;
      82                      end do;
      83                  slen prm = pl-2;
      84                  parmvalue = 0;  $ disable option.
      85              else  $ else enable option.
      86                  parmvalue = 1;
      87                  end if;
      88              slen prm = 4;
      89              .ch. 4, prm = 1r=;  $ use '=' to anchor place in lookup
dsv   62 .+mc         call stpc(prm); $ convert to primary case.
      90              i = prm .in. parmstr;  $ see if valid option.
      91              if  i  then  $ if option valid, extract code.
      92                  i = digofchar((.ch. i+4, parmstr))*10+
      93                      digofchar((.ch. i+5, parmstr));
      94                  .f. i, 1, pgiven = yes;  $ indicate option present.
      95                  .f. i, 1, pvalue = parmvalue;  $ set option.
      96                  end if;
      97              pl = 0;  prm = 6q------;
      98              end if;
      99
     100          lpos = lpos+1;
dsq  192          if  (isblank(c)) quit while;
     102          end while;
     103 /endparmlist/
     104      araptr = 0;  $ reset tok ara top.
     105      lexlist = no; genlist = no;  $ default is not to list cards
     106      go to l(keycode) in 1 to 6;
     107 /l(6)/   $ skip member definition line.
     108      go to retara;
     109 /l(1)/   $ process eject.
     110      l = 0;
     111      if  lpos then
     112          c = 1r0;  lpos = lpos-1;
     113          while numeric(c);  $ collect count.
     114              l = l*10 + digofchar(c);
     115              lpos = lpos + 1;  if (lpos>mccd)  quit while;
     116              c = .ch. lpos, prm;
     117              end while;
     118          end if;
     119
     120      if  (listinginput)  ejectlp(l);
     121      tokrwd = 0;  tokrtyp tokrwd = listejecttok;
     122      tokrlen tokrwd = l;
     123      araptr = 1;  ara(1) = tokrwd;
     124      go to retara;
     125 /l(3)/   $ process punch.
     126      if  (listignore) go to retara;  $ if should ignore, done
     127      lexlist = yes; genlist = yes;  $ we list punch cards
     128      listdir = .f. list_directive, 1, pvalue; $ set directive list valu
     129      if  .f. list_definitions, 1, pgiven then  $ change value
     130          punchdefine = .f. list_definitions, 1, pvalue;
     131          end if;
     132      if  .f. list_expansions,  1, pgiven then
     133          punchexpand = .f. list_expansions,  1, pvalue;
     134          end if;
     135      go to dircheck;  $ check for dir/nodir
     136 /l(2)/   $ process list.
     137      if  (listignore) go to retara; $ do nothing if ignoring
     138      resuming = .f. list_resume, 1, pvalue; $ get resume flag
     139      listdir = .f. list_directive, 1, pvalue; $ get directive list flag
     140      .f. list_resume,    1, pvalue = no; $ clear these
     141      .f. list_directive, 1, pvalue = no;
     142      if  resuming then  $ if resume, pop listing stack
     143          listnew = listprev(listprevptr);
dst   15          listprevptr = listprevptr - (listprevptr>1);
     145      else
     146          listnew = (listnow & ^pgiven) ! pvalue;  $ set new list value
     147          end if;
     148
     149      if  listnew ^= listnow  then  $ if change.
     150          do   i = 1 to numlistparms;
     151              j = .f. i, 1, listnew;
     152              l = .f. i, 1, listnow;
     153              if  j ^= l  then
     154                  lexlist = lexlist ! listval_ll listvals(i);
     155                  genlist = genlist ! listval_gl listvals(i);
     156                  if  listval_tf listvals(i) & tokwrt then
     157                      tokrwd = 0;
     158                      tokrtyp tokrwd = listcontroltok;
     159                      tokrlen tokrwd = i;
     160                      tokrlc  tokrwd = j;
     161                      araptr = araptr + 1;  ara(araptr) = tokrwd;
     162                      end if;
     163                  end if;
     164              end do;
     165          end if;
     166
     167      if  resuming = no  then  $ if not resume, save list word.
     168          if  listprevptr = listprevmax  then
     169              do  i = 3 to listprevmax;
     170                  listprev(i-1) = listprev(i);  end do;
     171          else
     172              listprevptr = listprevptr + 1;
     173              end if;
     174          listprev(listprevptr) = listnow;
     175          end if;
     176      listnow = listnew; $ set current value
     177
     178 /dircheck/  $ check for dir/nodir override
     179      if  .f. list_directive, 1, pgiven then  $ present
     180          lexlist = listdir; genlist = listdir;
     181          end if;
     182
     183      go to retara;
     184 /l(4)/   $ process title.
     185      l = 0;                 $ title length.
     186      if  (lpos=0)  go to dotitle;  $ avoid null title.
     187      $   check that first char is quote.
     188      c = linech(lpos);
     189      if  (c^=1r')  go to retara;
     190      while  1;
     191          lpos = lpos + 1;  if  (lpos>=(mccd-1))  quit while;
     192          c = linech(lpos);
     193          if  c = 1r'  then  $ if quote, see if interior or terminator.
     194              if  linech(lpos+1) = 1r'  then  $ if interior quote,
     195                  lpos = lpos + 1;  $ skip so add one quote to title.
     196              else  $ if terminator, end title.
     197                  quit while;
     198                  end if;
     199              end if;
     200          l = l + 1;  linech(l) = c;
     201          end while;
     202 /dotitle/
     203      $   convert null title to single blank to simplify read in gen.
     204      $   avoid null title to simplify gen processing.
     205      $   if first char of line could not be blank, would have to reset
     206      l = l + (l=0);
     207      slen line = l;
     208      if  (listinginput) call stitlr(subtitling, line);
     209      if  subtitling & listinginput  then  $ if subtitle, eject if listi
     210          ejectl;
     211          end if;
     212      subtitling = 1;
     213      tokrwd = 0;
     214      tokrtyp tokrwd = listtitletok;
     215      tokrlen tokrwd = l;
     216      ara(1) = tokrwd;  araptr = 1;
     217      l = (l-1)/cpw + 1;  $ convert length to word count.
     218      do  i = 1 to l;
     219          ara(araptr+i) = .f. lorg - i*ws, ws, line;
     220          end do;
     221      araptr = araptr + l;
     222      go to retara;
     223 /l(5)/   $   process 'zzyorg' setl library directive.
     224      if  (lpos=0)  go to retara;  $ if no parameter.
     225      genlist = yes;  lexlist = yes;  $ list this card.
     226      while lpos <= mccd;
     227          c = .ch. lpos, line;
dsw   17 .+mc     c = ctpc(c);  $ convert to primary case.
     228          if  alphabetic(c)  then  countzzy(lettercode(c)) = 0;
     229          else  quit while;  end if;
     230          lpos = lpos + 1;
     231          end while;
     232      go to retara;
     233 /retara/     $ write entries in ara to token file.
     234      do  i = 1 to araptr;
     235          tokout1(ara(i));
     236          end do;
     237      work = work & ^proc_work;  $ we dont have -lex- process this card
     238      work = work ! (list_work*listinginput);  $ set if list is now set
     239      if  (lexlist = no) work = work & ^list_work;
     240      if  (genlist = no) work = work & ^out_work;
     241      normwork = (normwork & ^list_work) ! (list_work*listinginput);
     242
     243      +* lorg = **  $ drop lorg macro.
     244      end subr lexdir;
       1 .=member hash
       2      subr hash;  $  adds token to scanner symbol table
       3
       4 $    the routine -hash- adds a token to the symbol table (ha).
       5 $    we then compute hash-code for token and see if it has already
       6 $    been entered in the symbol table.  if not, a new entry in the tabl
       7 $    table is build, and the symbolic name stored in the -names- ar
       8 $    array.
       9 $    hash performs the additional function of posting
      10 $    references to symbols if the cross-reference option has
      11 $    been raised.  in this case, references to names are collected.
      12
      13
      14      size  hashcode(ws);     $ hash-code computed
      15      size  i(ps);            $ do-loop index
      16      size  hashtokara(ws); dims hashtokara(1+maxtoklen/cpw); $
      17      size  haent(hasz);  $ ha(haptr)
      18      size  l(ps);
      19      size  rem(ps);          $ characters remaining in last word.
      20
      21 .+tallyhash      tally(tally_haprobes)  $ count ha searches
      22      hashlen = slen hashtok;  $ get length in characters
      23      if  (hashlen>maxtoklen)  hashlen = maxtoklen;
      24 .+ht.
      25      if  hashtrace  then
      26          tintl('hatrace len',hashlen) tintl('type',hashtyp)
      27          textl('symbol = ') textl(hashtok)
      28          end if;
      29 ..ht
      30      hashwords = (hashlen-1) / cpw;  $ number of extra words in item
      31      if  (hashlen=0)  hashwords = 0;
      32          $ blank fill last word in hashtok if necessary
      33      rem = cpw - (hashlen - hashwords*cpw);  $ no. of trailing chracter
      34      if  rem  then  $ if need blank fill.
      35          .f. hashtokorg -(hashwords+1)*ws, rem*cs, hashtok
      36              = blankword;
      37          end if;
      38 $    now copy words from sds-input hashtok into array of words.
      39 $    compute hash-code as exclusive-or of all input words, followed
      40 $    by exclusive-or of left and right halves, an
      41 $    take remainder modulo hash-table length.
      42      hashcode = .f. hashtokorg - ws, ws, hashtok;
      43      hashtokara(1) = .f. hashtokorg - ws, ws, hashtok; $ word 1
      44      do  i = 1 to hashwords;
      45          hashtokara(i+1) = .f. hashtokorg - (i+1)*ws, ws, hashtok;
      46          hashcode = hashcode .ex. .f. hashtokorg-(i+1)*ws, ws, hashtok;
      47          end do;
      48
      49      hashcode = .f. 1, ws/2, hashcode  .exor. .f. ws/2+1,ws/2,hashcode;
      50      haptr = mod(hashcode, haprime) + 1;
      51 $    examine table until find matching or unused entry
      52
      53 /probe/
      54 .+tallyhash      tally(tally_haentries) $ count entries seen
      55      if  (lexlen ha(haptr) ^= hashlen !  lextyp ha(haptr) ^= hashtyp)
      56          go to nomatch;
      57      if  (names(nameptr ha(haptr)) ^= hashtokara(1)) go to nomatch;
      58
      59      if  hashwords then  $ if something to check.
      60          l = nameptr ha(haptr) - 1;  $ set starting name pointer - 1.
      61          do  i = 2 to hashwords+1;  $ check the extra words.
      62              if  (names(l+i) ^= hashtokara(i))  go to nomatch;
      63              end do;
      64          end if;
      65      go to found;
      66
      67 /nomatch/
      68      if  halink ha(haptr)  then  $ if more in chain.
      69          haptr = halink ha(haptr);
      70          go to probe;
      71          end if;
      72
      73      if  (lextyp ha(haptr) = 0) go to addnew;  $ this is free.
      74
      75      do  hafree = hafree-1 to 1 by -1;  $ scan down from top.
      76          if  lextyp ha(hafree) = 0 then  $ found free entry.
      77              halink ha(haptr) = hafree;  $ link this one in.
      78 .+tallyhash  tally(tally_halinks)   $ count the link.
      79              haptr = hafree;  go to addnew;  $ go build entry.
      80              end if;
      81          end do;
      82
dso   32      call ermsg(20, 0, 0);  call lexexit;  $ ha is full.
      84
      85 /addnew/
      86      haused = haused + 1;  $ increment entries used count.
      87      haent = 0;  $ set ha entry to zero.
      88      lexlen haent = hashlen;  $ set length.
      89      lextyp haent = hashtyp;   $  set lexical type.
      90      nameptr haent = namesptr;  $ set pointer to -names-.
      91      ha(haptr) = haent;  $ set entry into table.
      92      namesptr = namesptr + hashwords;  $ set to new position - 1;
      93      countup(namesptr, namesmax, 'names');
      94      do  i = 1 to hashwords+1;  $ move in all words.
      95          names(namesptr+i-hashwords-2) = hashtokara(i);  $ move a word.
      96          end do;
      97
      98 /found/
      99 .+ht.
     100      if  (hashtrace=yes)  then
     101          tintl('hash code', haptr) endl
     102          end if;
     103 ..ht
     104 $    if just hashed name, update useage count, for subsequent use by
     105 $    detect.
     106      if  (hashtyp ^= nametok) return;  $ done if not name.
     107      if  litcod ha(haptr) = 0 then  $ have something more to do.
     108          if  (nuses ha(haptr) < suspi)
     109              nuses ha(haptr) = nuses ha(haptr) + 1;  $ count uses.
     110 .+cr.             $ cross reference.
     111          if  (isonxrf=no) return;
     112          if  (collectingrefs = no)  return;
     113          if  (initializing) return;  $ dont write ref for init.
     114          creftot = creftot + 1;
     115          crefent = 0;
     116          cref_ha crefent = haptr;
     117          cref_line crefent = icdno;  $ set line number.
     118          cref_macro crefent = (macorg ha(haptr) ^= 0);  $ macro state
     119          crefput(crefent);
     120 ..cr
     121          end if;
     122
     123      end subr hash;
     124      subr fivdec(n);  $ integer to sds converter
       1 .=member fivdec
       2      size  i(ps);  $ do-loop index
       3      size  j(ps);  $ remaining value to convert
       4      size  n(ps);
       5
       6      j = n;
       7      do  i = 5 to 1 by -1;
       8          fivdecara(i) = charofdig(mod(j, 10));
       9          j = j/10;
      10          end do;
      11
      12      end subr fivdec;
       1 .=member ibigr
       2      fnct ibigr(jarg, karg);  $ compare two symbols.
       3      size  jarg(ps), karg(ps);  $ ha indices of symbols.
       4      size  ibigr(1);
       5      size  jsym(sdstl), ksym(sdstl);  $ symbol strings to compare
       6      size  jlen(ps), klen(ps); size minlen(ps);
       7      size  jch(cs), kch(cs);  $  characters.
       8      size  i(ps);            $ loop index.
       9
      10      jch = .f. ws+1-cs, cs, names(nameptr ha(jarg));
      11      kch = .f. ws+1-cs, cs, names(nameptr ha(karg));
      12      if  jch ^= kch  then  $ if initial characters differ,
      13          ibigr = (jch > kch);  $ compare to get result.
      14          return;
      15          end if;
      16
      17      $   must examine rest of symbols, retrieve as sds and compare.
      18      getsym(jsym, jarg);  getsym(ksym, karg);
      19      jlen = slen jsym; klen = slen ksym;
      20      minlen = jlen; if  (klen < minlen) then minlen = klen; end if;
      21      ibigr=1;  $ assume j bigger
      22      do  i = 1 to minlen;
      23          jch = .ch. i, jsym;  kch = .ch. i, ksym;
      24          if  jch ^= kch  then
      25              ibigr = (jch > kch);
      26              return;
      27              end if;
      28          end do;
      29
      30      ibigr = (jlen > klen);  $
      31
      32      end fnct ibigr;
       1 .=member detect
       2      subr detect;  $  finds and lists suspicious variables
       3 $        detect lists 'suspicious' names, i.e., names which
       4 $    have been used less than 'suspi' times in the program.
       5      size  i(ps);  $ do-loop index
       6      size  ksym(sdstl);  $ string for name.
       7      size  lines(ps);  $ number of lines for list.
       8      size  m(ps);           $loop index.
       9      size  hapack(ps);  $ size of packed ha.
      10      size  top(ps);  $ loop indices
      11      size  targ(ps);
      12      size  temp(hasz);  $ temporary for swapping
      13      size  ibigr(1);   $ function to compare symbols.
      14
      15      hapack = 0;
      16      if  (dodetect=no) return;  $ check is sus vars list off
      17      do  i =  1 to  hadim;
      18          if  (nameptr ha(i) = 0) cont do;
      19          if  ((litcod ha(i))
      20              !(nuses ha(i) >= suspi)
      21              !(nuses ha(i) = 0)
      22              !(lextyp ha(i) ^= nametok)) cont do;
      23          hapack = hapack + 1;  ha(hapack) = ha(i);
      24          end do;
      25
      26      $ if no suspicious names, return
      27      if  (hapack = 0)  return;  $ if no suspicious names.
      28
      29      +*  swap(a,b) = $ macro for swapping, common sort operation
      30          temp = ha(a); ha(a) = ha(b); ha(b) = temp; **
      31
      32      do  i = 2 to hapack; $ make into heap, i is parent.
      33          m = i;
      34          while  m>1;  $ examine parents in turn
      35              if  ibigr(m/2, m)  quit while; $ if parent no smaller,
      36              swap(m,m/2); $ promote large child
      37              m = m/2;
      38              end while;
      39          end do i;
      40
      41      do  top = hapack to 2 by -1; $ sort subtrees in turn
      42          swap(1,top);  $ extract largest element
      43          m = 1;  $$ force remaining subtree to be heap
      44          while  m*2 < top;
      45              if  ibigr(m*2+1, m*2) & (m*2+1 < top)
      46                  then  targ = m*2+1;
      47                  else  targ = m*2;  end if;
      48              if  ibigr(targ,m)  then
      49                  swap(m, targ); $ child too big, so exchange
      50              else  quit while;  end if;
      51              m = targ;  $ move to subtree of largest child
      52              end while m;
      53          end do top;
      54
      55      macdrop(swap)
      56      textl(' ') endl  $ blank line
      57      textl(' * * * suspicious names used ')
      58      if  suspi = 2 then  $ print shorter message.
      59          textl('only once:')
      60      else  $ print long message.
      61          textl('less than') intl(suspi) textl(' times:')
      62          end if;
      63      endl
      64      lines = (hapack+5)/6;   $ number of lines.
      65      do  m = 1 to lines;
      66          i = m;
      67          while i <= hapack;
      68              getsym(ksym, i);
      69              textl(ksym);  $ print symbol
      70              skipl(21-slen ksym)
      71              i = i + lines;
      72              end while;
      73          endl
      74          end do;
      75      endl  $ flushing last few names
      76
      77      end subr detect;
       1 .=member pflshr
       2      subr pflshr(wd);   $ lexical punch routine.
       3      size  wd(ws);   $ ha index of token to punch.
       4      size  i(ps), j(ps);    $ temporaries and counters.
       5
       6      +*  puncha(c) =   $ macro to punch a character.
       7          punchpos = punchpos+1;  $ advance column pointer.
       8          if  (punchpos > mccd) call pncr;  $ flush card if too long.
       9          punchbuf(punchpos) = c;  $ insert character.
      10          **
      11
      12      $   first, open the punch file if not previously opened.
      13      if  punchopened = no then  $ must open punch file.
      14          call opensio(punchfile, iorc, access_put, punchfilename, 80,j,
      15              0, 0);    $ open the punch file.
      16          punchopened = yes;  $ show file is opened.
      17          punhold1 = 0;  punhold2 = 0;  punlastlt = 0;
      18          do  i = 1 to 80;  punchbuf(i) = 1r ; end do;  $ clear buffer.
      19          punchpos = 6;   $ start punching at column 7.
      20          end if;
      21
      22      $   now see if this is an end-of-job call.
      23      if  wd < 0 then  $ this is end-of-job call.
      24          $   see if anything is in our 'hold' buffers.  if so, flush th
      25          if  punhold1 = ihpl then  $ flush this.
      26              puncha(1r+)
      27          elseif  punhold1 = ihst then
      28              puncha(1r*)
      29          elseif  punhold1 = ihsl then
      30              puncha(1r/)
      31              if  punhold2 then  $ second token held.
      32                  if  punchpos+lexlen ha(punhold2) > 70 then
      33                      call pncr;  punchpos = 10;
      34                      end if;
      35
      36                  do  i = 1 to lexlen ha(punhold2);  $ punch symbol.
      37                      puncha(isymc(punhold2, i))
      38                      end do;
      39                  end if;
      40              end if;
      41
      42          call pncr;  $ flush card.
      43          call clossio(punchfile, iorc);  $ close punch file.
      44          return;   $ done in end case.
      45          end if;
      46
      47
      48      $   this is the normal case where we have a symbol to punch.
      49      $   first see if this will cause a special case.
      50      if  punhold1 = ihpl then  $ last was +.
      51          if  wd = ihst then  $ makes this +*
      52              call pncr;  $ this starts new card.
      53              punchpos = 6;   $ start at column 7.
      54              puncha(1r+)  puncha(1r*)  puncha(1r )  puncha(1r )
      55              punhold1 = 0;  punlastlt = 0;  $ reset.
      56              return;    $ done with this case.
      57              end if;
      58
      59          $   we are here if we have a + that if not followed by
      60          $   a *.  in this case we must flush the +.
      61          puncha(1r+)  punhold1 = 0;  punlastlt= 0;
      62
      63      elseif  punhold1 = ihst then  $ last token was *.
      64          if  wd = ihst then  $ this was **.
      65              if  (punchpos < 9) punchpos = 9;  $ move to offset.
      66              puncha(1r )  puncha(1r*)  puncha(1r*)
      67              call pncr;  punchpos = 6;  $ this ends card.
      68              punhold1 = 0;  punlastlt = 0;  $ reset.
      69              return;  $ done in this case.
      70              end if;
      71
      72          $   we are here if we have a * that is not followed by
      73          $   another *.  in this case we must flush the *.
      74          puncha(1r*)  punhold1 = 0;  punlastlt = 0;
      75
      76      elseif  punhold1 = ihsl then  $ last token was /.
      77          if  punhold2 then  $ there was a name held also.
      78              if  wd = ihsl then  $ this was label definition.
      79                  call pncr;  $ start new card.
      80                  punchpos = 0;  $ reset position.
      81                  puncha(1r )  puncha(1r/)
      82                  do  i = 1 to lexlen ha(punhold2);  $ output name.
      83                      puncha(isymc(punhold2, i))
      84                      end do;
      85
      86                  puncha(1r/)
      87                  call pncr;  $ this is alone on a card.
      88                  punchpos = 0;  $ reset position.
      89                  punhold1 = 0;  punhold2 = 0;  punlastlt = 0;
      90                  return;  $ done in this case.
      91                  end if;
      92
      93              $   in this case we have  /name  and no /.
      94              puncha(1r/)   $ punch out the /.
      95              if  lexlen ha(punhold2)+punchpos > 70 then
      96                  call pncr;  punchpos = 10;
      97                  end if;
      98
      99              do  i = 1 to lexlen ha(punhold2);  $ punch name.
     100                  puncha(isymc(punhold2, i))
     101                  end do;
     102
     103              punhold1 = 0;  punhold2 = 0;  punlastlt = nametok;
     104
     105          else  $ this is / and nothing else held.
     106              if  lextyp ha(wd) = nametok then  $ /name
     107                  punhold2 = wd;  $ hold this token.
     108                  return;   $ done in this case.
     109                  end if;
     110
     111              $   else we must flush the /.
     112              puncha(1r/)  punhold1 = 0;  punlastlt = 0;
     113              end if;
     114          end if;
     115
     116
     117      $   now see if this symbol should be held.
     118      if  wd = ihpl ! wd = ihst ! wd = ihsl then  $ hold +*/.
     119          punhold1 = wd;  return;  $ hold and return.
     120          end if;
     121
     122      $   now we will punch symbol.  first ensure it will fit on card.
     123      if  lexlen ha(wd)+punchpos > 70 then  $ will not fit.
     124          call pncr;  punchpos = 10;  punlastlt = 0;
     125          end if;
     126
     127      $   now if this token and last token were names or integers,
     128      $   insert a blank.
     129      if  (punlastlt = nametok ! punlastlt = dectok) & (lextyp ha(wd) =
     130          nametok ! lextyp ha(wd) = dectok) then
     131          puncha(1r )
     132          end if;
     133
     134      punlastlt = lextyp ha(wd);  $ now set lexical type.
     135
     136      $   now actually punch token.
     137      if  punlastlt = rztok ! punlastlt = sstok then  $ punch length.
     138          call fivdec(lexlen ha(wd));  $ get length.
     139          do  i = 1 to 5;  $ output length.
     140              if  fivdecara(i)^=1r0 then puncha(fivdecara(i));  end if;
     141              end do;
     142
     143          if punlastlt = rztok then puncha(1rr) else puncha(1rs) end if;
     144
     145      elseif  punlastlt = stringtok then  $ this is string.
     146          puncha(1r')
     147          end if;
     148
     149      do  i = 1 to lexlen ha(wd);  $ output actual token.
     150          puncha(isymc(wd, i))  $ punch a character.
     151          if  punlastlt = stringtok & isymc(wd, i) = 1r' then
     152              puncha(1r')  $ double the quotes.
     153              end if;
     154          end do;
     155
     156      if punlastlt = stringtok then  puncha(1r')  end if;
     157
     158      $   if this token is a semicolon or a 'then', flush this card
     159      $   unless it is almost empty.
     160      if  wd = ihsemi ! litcod ha(wd) = 71 then
     161          if  punchpos > 35 then
     162              call pncr;  punchpos = 6;  $ start a new card.
     163          else   $ a fairly empty card.
     164              puncha(1r )  puncha(1r )
     165              end if;
     166
     167          punlastlt = 0;  $ no space needed next time.
     168          end if;
     169
     170      macdrop(puncha)
     171      end subr pflshr;
       1 .=member pncr
       2      subr pncr;  $ actually punch the card.
       3      size  i(ps);    $ temporary.
       4
       5      until  yes;  $ quit if must punch the card.
       6          if  (punchpos > 6) quit until;
       7          do  i = 1 to punchpos;
       8              if  (punchbuf(i) ^= 1r ) quit until;
       9              end do;
      10
      11          return;  $ else this would be a blank card.
      12          end until;
      13
      14      call fivdec(icdno);  $ convert card number.
      15      punchbuf(75) = 1rp;  $ set id flag.
      16      do  i = 1 to 5;  punchbuf(75+i) = fivdecara(i);  end do;
      17      call putcsio(punchfile, iorc, punchbuf, 1, 0);  $ punch card.
      18      do  i = 1 to 80;  punchbuf(i) = 1r ;  end do;
      19      punchpos = 0;  $ start at start of next card.
      20
      21      end subr pncr;
       1 .=member ermsg
       2      subr ermsg(ernum, par1, par2); $ error message printer
       3 $        ermsg is called to list warning or error message.
       4 $    ernum is error number, and par1 and par2 are optional
       5 $    parameters whose meaning depends on ernum; typically
       6 $    they are ha indices to tokens related to error.
       7 $    a special call to givecr is made to list the current line
       8 $    if it has not yet been listed, and ertlist is called to
       9 $    list the last few tokens seen before the error.
      10
      11      +*  ermsgmax = 33 **  $ max. number of error messages
      12      size  ermsgwarn(ermsgmax);  $ flags warnings
      13      data ermsgwarn = 1b'000 00010 00000 00000 00001 10000 00000';
dso   33      size  ernum(10), par1(ws), par2(ws);
      15      size  dummyarg(ps);  $ dummy argument for givecr
      16
      17      ejectlp(4);  $ ensure whole message on one page
      18
      19      terml((.f. ernum, 1, ermsgwarn) = no)
      20      errecho = yes;  $ list current card if not yet listed
      21      call givecr(dummyarg);
      22      skipl(7+nowc) charl(1r$) endl
      23
      24      if  .f. ernum, 1, ermsgwarn  then  $ if warning
dsq  193 .+s10    warn_s10;  $ flag warning message for s10.
      25          textl(warning_notice)
      26          nwarnings = nwarnings + 1;
      27      else
dsq  194 .+s10    error_s10;  $ flag error message for s10.
      28          textl(error_notice)
      29          nerrors = nerrors +1;
      30          end if;
      31
      32      go to e(ernum) in 1 to 33;
      33 /e(1)/
      34      textl('macro ''') tokl(par1)
      35      textl(''' called with no arguments.') go to errtn;
      36 /e(2)/
      37      textl('macro ''') tokl(par1)
      38      textl(''' called with too few arguments.')  go to errtn;
      39 /e(3)/
      40      textl('macro ''')  tokl(par1)
      41      textl(''' called with too many arguments')  go to errtn;
      42 /e(4)/
      43      textl('macro close occurs outside macro definition.') go to errtn;
      44 /e(5)/
dsy   20 $ error 5 - illformed iset parameter
dsy   21       textl('illegal iset character ''')
dsy   22       charl(par1)  charl(1r')  go to errtn;
      45 /e(6)/
dsy   23 $ error 6 - illformed name after .+set
dsy   24       textl('expect name after .+set ') go to errtn;
      46 /e(7)/
      47      go to notext;
      48 /e(8)/
      49      textl('illegal symbol ''')  tokl(par1)
      50      textl(''' follows macro opening.')  go to errtn;
      51 /e(9)/
      52      textl('illegal symbol ''')  tokl(par1)
      53      textl(''' follows macro name ''') tokl(par2) textl('''.')
      54      go to errtn;
      55 /e(10)/
dsz   13      nwarnings = nwarnings - 1; $ do not include this in warning count.
      56      textl('name ''')  tokl(par1)
      57      textl(''' with prior usage is being designated as a macro.')
      58      endl return;
      59 /e(11)/
      60      textl('macro ''')  tokl(par1)
      61      textl(''' has been redefined.') endl return;
      62 /e(12)/
      63      textl('macro definition opened before required close.  ')
      64      textl('possibly missed earlier termination.')  go to errtn;
      65 /e(13)/
      66      textl('macro ''') tokl(par1) textl(''' occurs within itself.')
      67      go to errtn;
      68 /e(14)/
      69      go to notext;
      70 /e(15)/
      71      textl('no ''='' after argument list for macro ''') tokl(par1)
      72      textl('''.') go to errtn;
      73 /e(16)/
      74      textl('parameter list for macro ''')  tokl(par1)
      75      textl(''' mispunctuated..') go to errtn;
      76 /e(17)/
      77      textl('illegal repetition of name ''') tokl(par1) textl('''  ')
      78      textl('in argument for macro ''')  tokl(par2)  textl('''.')
      79      go to errtn;
      80 /e(18)/
      81      textl('maximum length of')  intl(par1)
      82      textl(' characters in string exceeded.')  go to errtn;
      83 /e(19)/
      84      textl('token longer than') intl(par1) textl(' characters.')
      85      go to errtn;
      86 /e(20)/
      87      textl('hash table overflow.')  go to errtn;
      88 /e(21)/
      89      textl('excessive macro nesting or recursion.') go to errtn;
      90 /e(22)/
dsz   14      textl(' expect ** ending prior macro definition')
dsz   15      go to errtn;
      91 /e(23)/
      92 /e(24)/
      93 /e(25)/
      94      go to notext;
      95 /e(26)/
      96      textl('missing or illegal real exponent')  go to errtn;
      97 /e(27)/
      98      textl('/*   occurs inside   /* ... */   comment') endl return;
      99 /e(28)/
     100      textl('excessively long macro argument list.  probably missing ')
     101      textl(''')'' in arguments to ''') tokl(par1) textl(''' at line ')
     102      intl(par2) textl('.') go to errtn;
     103 /e(29)/
     104 /e(30)/
     105 /e(31)/
     106      go to notext;
     107 /e(32)/
     108      textl('illegal character''') charl(par1)
     109      textl(''' in bit constant.');  go to errtn;
     110 /e(33)/
     111      textl('bit constant too long.');  go to errtn;
     112 /notext/  $ error without identifying text.
     113      textl('error number ') intl(ernum)  endl
     114      textl(' no text supplied, traceback follows.') endl
     115      call ltlxtr;
     116 /errtn/
     117      call ertlist;  $ list last few tokens
     118      if  ernum = 28 then  $ special text for this error.
dsq  195 .+s10    warn_s10;  $ flag warning message for s10.
     119          textl(warning_notice)  textl('compilation continuing but ')
     120          textl('tokens from ''') tokl(par1) textl(''' at line ')
     121          intl(par2) textl(' to last token listed have been skipped.')
     122          endl
     123          end if;
     124
     125      if  nerrors>lelvalue  then  $ if error limit exceeded.
dsq  196 .+s10    error_s10;  $ flag error message for s10.
     126          textl('**** lexical error limit of') intl(lelvalue)
     127          textl(' exceeded, scan aborted.') endl
     128          terml(no); call lexexit;
     129          end if;
     130      terml(no);  $ end of terminal file output
     131
     132      end subr ermsg;
       1 .=member ertlist
       2      subr ertlist;  $ list tokens if error detected
       3      size  inp(ps);
       4
       5      inp = lsvtkp + 1;  $ position of last 0 word put in lsvtk
       6      endl skipl(15) textl('last few tokens: ')
       7      while  lsvtk(inp+1);  $ loop until next zero found
       8          tokl(lsvtk(inp+1));  charl(1r );  $ write out token
       9          inp = (inp+1) & lsvtkz;  $ step to next
      10          end while;
      11      endl endl
      12
      13      end subr ertlist;
       1 .=member toklr
       2      subr toklr(hap);  $ list token given hash code
       3      size  hap(ps);  $  hash code of token to ljst
       4      size  np(ps);  $ pointer to names array for token
       5      size  cp(ps);  $ character position during list
       6      size  i(ps);  $ do loop index
       7
       8      np = nameptr ha(hap);
       9      cp = ws+1;  $ starting character pos
      10      do  i = 1 to lexlen ha(hap);  $ list characters in turn
      11          cp = cp - cs;  $ move to next character
      12          charl((.f. cp, cs, names(np)))  $ list character
      13          if  cp = 1  then  cp=ws+1; np=np+1;  end if;
      14          end do;
      15
      16      end subr toklr;
      17
       1 .=member ltoflo
       2      subr ltoflo(pt, lim, msg);  $  called if scanner array overflow
       3      size  pt(ps);  $ var to increment
       4      size  lim(ps);  $  maximum allowed value for -pt-
       5      size  msg(ws+1);  $  diagnostic test passed if overflow occurs
       6      size  dummyarg(ps);
       7
       8      terml(yes);  $ send this to terminal file
       9      endl  endl
dsq  197 .+s10    error_s10;  $ flag error message for s10.
      10      textl(error_notice)
      11      textl('overflow of scanner array ') textl(msg)
      12      tintl(' ptr',pt) tintl('limit',lim) endl
      13 $    echo last input line seen.
      14      textl(' next line is last line processed before overflow.')endl
      15      errecho = yes;  call givecr(dummyarg);
      16      call ltlxtr; $ give trace back chain
      17      terml(no); call lexexit;
      18      end subr ltoflo;
       1 .=member lexexit
       2      subr lexexit; $ exit routine - prints statistics
       3 $        lexexit is called to end the scan, and proceeds as follows -
       4 $    1.  the cross-reference name buffer isbuf is flushed
       5 $            if cross-reference list being generated, and final
       6 $            action is taken.
       7 $    2.  the token file buffer is flushed if any tokens remain,
       8 $            and the end-file token is sent out.
       9 $    3.  scanner statistics are collected and listed, giving the
      10 $            structure of ha-table, macro usage, etc.
      11 $    4.  optionally, a list of machine-dependent constants is
      12 $            listed, to aid in production of portable software.
      13 $    5.  error count is output, and abort is generated
      14 $            if user so requests abort on errors.
      15 $    6.  finally, lexexit exits to the routine ltlterm,
      16 $            which initiates the generator phase.
      17
      18      size  hats(ps);  dims hats(20); data hats = 0(20); $ token types.
      19      size  hat(ps);  $ ha index.
      20      size  hatzz(ps);  data hatzz=0;  $ number of zz-type names.
      21      size  hap(ps);          $ ha pointer
      22      size  halt(ps);  $ lex type of ha entry
      23      size  haln(ps);         $ lex length of ha entry
      24      size  i(ps);  $ do loop index
dsv   63      size  termcode(ws);     $ termination code.
      25 .+s66.   $ to pass count to root.
      26      nameset lexcard;
      27          size  cardtot(ps);  $ no of cards read, used by driver routine
      28          end nameset lexcard;
      29      cardtot = icdno; $ pass total number of cards to driver routine
      30 ..s66
      31      skipl(1) endl $ blank line
      32      call clsinc; $ close the input file
      33
      34 $    now close the punch file it was opened, first call pflshr
      35 $    with special end of job code, and then close file
      36      if  punchopened  then
      37          call pflshr(-1);
      38          call clossio(punchfile, iorc);
      39          end if;
      40
      41      if  tokwrt  then
      42          tokrwd = 0;
      43          tokrtyp tokrwd = tokreof;  $ build eof token
      44          tokrlen tokrwd = 0;
      45          tokout1(tokrwd);
      46          if  tokrbufp  then  $ flush token buffer
      47              call wtrwsio(tokenfile, iorc, tokrbuf, 1, tokrbuflim);
      48              $ write entire buffer, gen phase will detect special eof t
      49              $ token code to determine true end of data
      50              end if;
      51          call clossio(tokenfile, iorc);  $ close token file.
      52          end if;
      53
      54      endl
      55      if  (lcs_opt=no) go to endofstatistics;
      56      $   list lexical scan statistics.
      57      call stitlr(1, 'statistics for lexical scan.'); ejectlp(20);
      58      textl('statistics for lexical scan.') endl
      59 .+tallycomments.  $ if requested, give comment statistics
      60      textl('source has ') intl(icdno) textl(' lines, with ')
      61      intl(tallypl1) textl(' pl/1 comments, and ') intl(tallyeol)
      62      textl(' $-style comments.') endl
      63 ..tallycomments
      64 .+tallytokens.  $ if requested, give token statistics
      65      textl('scanner detected ') intlp(tallytrue, 8)
      66      textl(' tokens (') intlp(tallyimtok, 8) textl(' immediate).')
      67      intlp(tallyparse, 8) textl(' tokens sent to parser.') endl
      68      textl('source contains ') intlp(tallyblank,8)
      69      textl(' words of blanks.')  endl
      70 ..tallytokens
      71 .+tallyhash.  $ if requested, list hash statistics
      72      textl('symbol table searched') intlp(tally_haprobes, 8)
      73      textl(' times;') intlp(tally_haentries,8)
      74      textl(' entries examined. ')
      75      if  tally_halinks then intl(tally_halinks)textl(' links.') end if;
      76      endl
      77 ..tallyhash
     100      if  mtptr  then
     101      textl('used ') intl(mtptr) textl(' of ') intl(mtlim)
     102          textl(' entries in macro definition table.') endl
     106      end if;
     107
     108      textl('used ') intl(haused) textl(' of ') intl(hadim)
     109          textl(' entries in symbol table.') endl
     110      textl('used ') intl(namesptr) textl(' of ') intl(namesmax)
     111          textl(' entries in names array.') endl
     112 $    list ha entries by tpye
     113      do  i =  1 to  hadim;
     114          if  (nameptr ha(i)=0) cont do;
     115          hat = lextyp ha(i);
     116          hats(hat) = hats(hat) + 1;
     117          if  (hat  ^= nametok) cont do;
     118     $    count names beginning with -zz-
     119          if  (isymc(i, 1)  ^= 1rz) cont do;
     120          if  (isymc(i,2)  ^= 1rz) cont do;
     121          hatzz = hatzz + 1;
     122          end do;
     123      endl textl('symbol table composition') endl
     124      skipl(5)
     125      textl(' name   zz-name   special    dot op   decimal      ')
     126      textl('real       bit    string         r         s')
     127      endl
     128      intlp(hats(nametok),10)  intlp(hatzz,10)
     129      intlp(hats(spectok),10)  intlp(hats(optok),10)
     130      intlp(hats(dectok), 10) intlp(hats(realtok), 10)
     131      intlp(hats(bittok), 10)
     132      intlp(hats(stringtok),10)  intlp(hats(rztok),10)
     133      intlp(hats(sstok),10)
     134      endl endl endl
     135
     136
dst   16 .+mdc.
     137      if  (mdclist = 0) go to endmdclist;
     138      textl('machine dependent constants:')   endl
     139      do  hap =  1 to  hadim;  $ look at ha
     140          $   long r or any s constant.s are machine-dependant
     141          if  (nameptr ha(hap) = 0) cont do;  $ ignore empty entries
     142          halt = lextyp ha(hap); haln = lexlen ha(hap); $ get type and l
     143          if  (halt=rztok & haln > 1) ! halt = sstok then
     144              intl(haln)
     145              if  halt=rztok then  charl(1rr) else charl(1rs) end if;
     146              do  i =  1 to  haln; charl(isymc(hap,i)); end do; $ output
     147              textl('    ')
     148              end if;
     149          end do;
     150      endl
     151 /endmdclist/
dst   17 ..mdc
     152
     153 .+mp.        $ here to list values of active zzy counters.
     154      size  nzzy(ps);       $ counter.
     155      nzzy = 0;
     156      do  i = 1 to 27;  $ find active zzy counters.
     157          if  countzzy(i)  then  nzzy = i;  quit do;  end if;
     158          end do;
     159      if  nzzy  then  $ if any active, list values.
     160          endl  textl('final values of active zzy counters: ')
     161          do  i = nzzy to 27;
     162              nzzy = countzzy(i);
     163              if  nzzy  then  $ if active.
     164                  textl('zzy')
     165                  charl((.ch. i, 'abcdefghijklmnopqrstuvwxyz_'))
     166                  textl(' = ')  intl(nzzy)  textl('   ')
     167                  end if;
     168              end do;
     169          endl
     170          end if;
     171 ..mp
     172
     173 /endofstatistics/
     174
     175 .+cr.
     176      size  nametot(ps);  $ number of names
     177      size  nptr(ps), nc(ps),  j(ps);
     178      if  isonxrf  then  $ if cross reference on, complete ref. file.
     179          crefput(0);  $ mark end of references.
     180          if  crbuffptr  then  $ flush buffer if not empty
     181              call wtrwsio(crfile, iorc, crbuff, 1, crbuffmax);
     182              end if;
     183          call clossio(crfile, iorc);  $ close reference file 1.
     184          call crfnam(crfilename, crfileparm, 2);
     185          call opensio(crfile, iorc, access_write, crfilename,
     186              0, i, 0, 0);
     187          crbuffptr = 0;
     188          crefput(creftot);
     189          crefput(icdno);  $ last card number.
     190          crefput(hadim);
     191          $  determine space needed for names.
     192          nametot = 0;
     193          do  i = 1 to hadim;
     194              if  (lextyp ha(i) ^= nametok)  cont do;
     195              nptr = nameptr ha(i);
     196              if  nptr  then  $ if name, get length
     197                  nc = lexlen ha(i);
     198                  nametot = nametot + (nc + (cpw-1))/cpw;
     199                  end if;
     200              end do;
     201          crefput(nametot);  $ indicate space needed for names.
     202
     203          do  i = 1 to hadim;
     204              if  (lextyp ha(i) ^= nametok)  cont do;
     205              crefput(i);
     206              nc = lexlen ha(i);
     207              crefput(nc);
     208              nptr = nameptr ha(i) - 1;
     209              $  write out name, packing chars into ref. size.
     210              do  j = 1 to (nc + (cpw-1))/cpw;
     211                  crefput(names(nptr+j));
     212                  end do;
     213              end do;
     214          crefput(0);  $ indicate end of ha.
     215
     216          if  crbuffptr  then
     217              call wtrwsio(crfile, iorc, crbuff, 1, crbuffmax);
     218              end if;
     219          call clossio(crfile, iorc);  $ close reference file 2.
     220          end if;
     221 ..cr
     222      call detect;
     223
     224      if  nwarnings  then  $ if warnings encountered.
dsq  198 .+s10    warn_s10;  $ flag warning message for s10.
     225          intl(nwarnings) textl(' warnings issued.')  endl
     226          end if;
     227      if  nerrors  then  $ if errors detected.
     228          terml(yes)
dsq  199 .+s10    error_s10;  $ flag error message for s10.
     229          textl('scan detected') intl(nerrors)
     230          textl(' lexical errors.')   endl
     234          end if;
     235
     236      $   fatal if no input lines read.
     237      if  icdno =  0  then
dsq  200          terml(yes)
dsq  201 .+s10    error_s10;  $ flag error message for s10.
dsq  202          textl('no input lines - fatal error.') endl
     239          terml(no)
     240          exitcode = yes;  $ force fatal termination.
     241          end if;
     242
     243      if  exitcode then  $ if abnormal termination
dsq  203          terml(yes)
dsq  204 .+s10    error_s10;  $ flag error message for s10.
dsq  205          textl('abnormal scanner termination') endl
     245          terml(no); call clsterm;
     246          call ltlfin(1, 1);  $ abnormal termination.
     247          end if;
     248
     249      if  tokwrt = no  then
     250          textl('no token file.')
     251          termlex = yes;  $ end compilation.
     252          end if;
     253
     254      endl  endl
     255      call clsterm;
dsv   64
dsv   65 $    determine termination code.
dsv   66
dsv   67      termcode = 0;
dsv   68      if  (nwarnings)  termcode = 4;
dsv   69      if  (nerrors)  termcode = 8;
dsv   70
     256      if  termlex  then  $ if lex phase terminates compilation.
     257          textl('end of compilation.')  endl
dsv   71          call ltlfin(0, termcode);
     259      else  $ if continuing to gen phase.
dsv   72          call ltlterm(1, termcode);
     261          end if;
     262
     263      end subr lexexit;
« October 2024 »
Su Mo Tu We Th Fr Sa
1 2 3 4 5
6 7 8 9 10 11 12
13 14 15 16 17 18 19
20 21 22 23 24 25 26
27 28 29 30 31
 

Powered by Plone CMS, the Open Source Content Management System

This site conforms to the following standards: