home *** CD-ROM | disk | FTP | other *** search
/ Club Amiga de Montreal - CAM / CAM_CD_1.iso / files / 116.lha / Web / web.w < prev    next >
Encoding:
Text File  |  1986-11-20  |  43.1 KB  |  1,951 lines

  1.  
  2. 1.  Web preprocesses structured assembler programs and produces
  3. an output file for the assembler.  This very file must itself be
  4. preprocessed by web before assembly, so it will serve as an example
  5. of web usage.  There is a file 'web.doc' with more information.
  6.  
  7.     ¶ The structure so far allows for:
  8.     (1)  argumentless macros (whose names begin with 2 hyphens),
  9.     (2)  a variant syntax for calling procedures (names begin with capital),
  10.     (3)  defined symbols,
  11.     (4)  statement grouping with '{...}' and '«...»',
  12.     (5)  alternate symbols for branch instructions,
  13.     (6)  infix statments with '=' and '?',
  14.     (7)  simple data declarations,
  15. and    (8)  new ways of giving comments.
  16.  
  17.     ¶ To assemble this program:
  18.           web web.w
  19.           assem web.a -o web.o
  20.           delete web.a
  21.           alink web.o to web
  22.           delete web.o
  23.                         --- Greg Lee, July 4, 1986
  24.  
  25. 2. Assembler initialization.
  26.  
  27.     idnt  Web
  28.     section  one
  29.     --Define macros for assembler      · 39
  30.     --Define library references      · 40
  31.     --EQU statements              · 38
  32.  
  33. ¶    Here are some notes on register use:
  34.        D0 used often
  35.        D1 used globally during part of input phase for quote flag
  36.        D2 used globally during part of input phase
  37.        D3 used globally, usually holds current line length
  38.        D4 not used
  39.        D5 not used
  40.        D6 not used
  41.        D7 not used
  42.        A0 used often; used globally in both input and output phases
  43.        A1 used often; used globally in both input and output phases
  44.        A2 used globally in input phase to point to parenthesis flag
  45.        A3 used locally
  46.        A4 used locally
  47.        A5 not used
  48.        A6 used globally; holds AmigaDOS library base pointer
  49.  
  50. 3. The main routine reads input file into a buffer, noting definitions,
  51. then writes buffer to output file, doing requisite processing
  52. dynamically.
  53.  
  54. Main
  55.  
  56.  define  push  -(sp).L
  57.  define  pop    (sp)+
  58.  define  chr    D0.B
  59.  
  60.     --Get file name from command line     ·  4
  61.     --Initialize standard input and output    · 36
  62.     --Open input and output files        ·  5
  63.  
  64.  define  msecttype      1
  65.  define  csecttype      2
  66.  define  deftype      3
  67.  
  68.  long    fpoint
  69.  long    filebuf
  70.     d0.l  =  # maxfsize
  71.     d1    =  0
  72.     callex   AllocMem
  73.     filebuf  =  d0
  74.     = { d0  =  100
  75.         rts
  76.     }
  77.     fpoint   =  filebuf
  78.  
  79.  
  80.  long    lastsect
  81.     lastsect    =  #sectlist
  82.  
  83.     --Input the file, noting definitions and trimming comments       · 6
  84.     arg`a  =    ihandle;   call     Close
  85.     --Output the file, substituting appropriately for defined names  · 7
  86.     --Add bss section                              · 8
  87.     fprint   end.line
  88.     arg`a  =    ohandle;   call     Close
  89.  
  90.     a1.l  =  filebuf
  91.     d0.l  =  # maxfsize
  92.     callex  FreeMem
  93.  
  94.     d0    =  0
  95.  
  96. 4. Make a copy of the name in the command tail.  If the name does not end
  97. in '.w', add this.  Use this copy as the input file name.
  98.    Make another copy of this, and change the last letter of the second
  99. copy to 'a', and use this as the output file name.
  100.  
  101. --Get file name from command line
  102.     a1    =  ^infname
  103.     a2.l  =  a1
  104. next.fname.char
  105.     tst.l    d0
  106.     !=  { d1.b  =  (a0)+
  107.           d1.b  ?  ' '
  108.           > «  (a1)+.b  =  D1
  109.          d0     -=  1
  110.          ->  next.fname.char »
  111.     }
  112.     -2(a1).b    ?  '.'
  113.     = «  -1(a1).b  ?    'w'
  114.          = «    a1 -= 2  » »
  115.     (a1)+.b  =  '.'
  116.     (a1)+.b  =  'w'
  117.     clr.b    (a1)
  118.  
  119.     a1  =  ^outfname
  120.     {  (a1)+.b  =  (A2)+;  bne   }
  121.     -2(a1).b    =  'a'
  122.  
  123. 5. Just AmigaDOS stuff.
  124.  
  125. --Open input and output files
  126.  
  127.  define  arg`a  D1.L    · arguments to AmigaDOS functions
  128.  define  arg`b  D2.L
  129.  long    chandle
  130.  long    ihandle
  131.  long    ohandle
  132.  
  133.     a1  =  ^infname
  134.     tst.b    (a1)
  135.     beq      abort    · cf. output section
  136.  
  137.     arg`a  =    a1
  138.     arg`b  =    #1005
  139.     call     Open
  140.     tst.l    d0
  141.     beq      abort
  142.     ihandle  =  d0
  143.  
  144.     arg`a  =    #outfname
  145.     arg`b  =    #1006
  146.     call     Open
  147.     tst.l    d0
  148.     beq      abort1    · cf. output section
  149.     ohandle  =  d0
  150.  
  151.  
  152.  
  153. 6. This is the first half of the task.  Names of macro sections and
  154. procedure sections are detected, and their addresses placed in a
  155. table for later use by the output half of the program.
  156.  
  157. --Input the file, noting definitions and trimming comments
  158.     byte  instatus
  159.     byte  parenstatus
  160.     instatus = 1
  161.  
  162.     ->       next.line
  163.     {  chr  =  (input_line)
  164.        a2  =    ^parenstatus
  165.     define   paren_flag (A2).B
  166.        --Keep ignoring lines of a comment paragraph           · 6.1
  167.        --Examine beginning of input line               · 6.2
  168.  · line will now be placed in buffer, probably
  169.        --Examine each character of input line            · 6.3
  170.        tst.b      paren_flag       · ignore parenthical line
  171.        = { --Append possible data label               · 6.4
  172.            --Move l_length chars from obuf to file buffer  · 6.5
  173.        }
  174. next.line
  175.        --Read an input line                       · 22
  176.        tst.l      l_length
  177.        bne   }
  178.  
  179.  
  180.  
  181. 6.1 In a comment section, discard everything, but keep looking for
  182. a blank line to terminate the section.
  183.  
  184. --Keep ignoring lines of a comment paragraph
  185.     tst.b    instatus
  186.     = { chr  ?  new_line
  187.         bne       next.line
  188.         instatus  =  1
  189.         ->   next.line
  190.     }
  191.  
  192.  
  193. 6.2 The portion of the input phase syntactic analysis that can be done
  194. on the basis of the first few characters of an input line is done
  195. here.  Also, we make a few adjustments to the beginning of the line:
  196. deleting extra spaces, and left adjusting braces.
  197.  
  198. --Examine beginning of input line
  199.  
  200.     chr  ?  new_line           · discard blank lines
  201.     beq      next.line
  202.     chr  ?  '*'     · line with initial '*' is a comment
  203.     beq      next.line
  204.  
  205.     chr  ?  '('     · line-initial '(' begins a parenthetical
  206.     = {          ·    comment
  207.     paren_flag += 1
  208.     --Trim off first character of input line        · 6.2.1
  209.       · remove it from line so that it won't count
  210.       ·  twice when checking parenthesis balance below
  211.     }
  212.  
  213.  define   tmp_ln   A1.L
  214.     tmp_ln  =  input_line
  215.     --Trim extra initial blanks                · 6.2.2
  216. · here tmp_ln points to first non-blank character
  217.     --Left adjust braces                    · 6.2.3
  218.     --Look for key words                    · 6.2.4
  219.     --Check for comment paragraph header            · 6.2.5
  220. · tmp_ln is no longer correct
  221.     --Check for name of procedure or code section        · 6.2.6
  222.  
  223.  
  224. 6.2.1  This code is also used below.
  225.  
  226. --Trim off first character of input line
  227.     input_line    +=  1
  228.     l_length    -=  1
  229.  
  230. 6.2.2  Aside from trimming all but one initial blank, leave tmp_ln
  231. pointing at first non-blank character.
  232.  
  233. --Trim extra initial blanks
  234.     chr  ?  ' '
  235.     = { { tmp_ln    +=  1
  236.           (tmp_ln).b    ?  ' '
  237.           bne      §
  238.           --Trim off first character of input line     · 6.2.1
  239.         ->   }
  240.     }
  241.  
  242. 6.2.3  Braces will later be changed to labels.  Eliminate preceding
  243. blank so assembler will recognize them as such.
  244.  
  245. --Left adjust braces
  246.     (tmp_ln).b  ?  '{'
  247.     beq      is.a.brace
  248.     (tmp_ln).b  ?  #leftg.char
  249.     beq      is.a.brace
  250.     (tmp_ln).b  ?  '}'
  251.     beq      is.a.brace
  252.     (tmp_ln).b  ?  '['
  253.     beq      is.a.brace
  254.     (tmp_ln).b  ?  ']'
  255.     =  {
  256. is.a.brace
  257.         -1(tmp_ln).b    ?  ' '
  258.         = {  --Trim off first character of input line  · 6.2.1
  259.         }
  260.     }
  261.  
  262. 6.2.4  If we find a key word, remove the key word, put a null byte before
  263. the defined symbol to signal that this line should not be put out during
  264. output phase, and enter address in the table.
  265.  
  266. --Look for key words
  267.     byte  defstatus
  268.  
  269.     tst.b    paren_flag    · check for '(define...' at beginning of line
  270.     bne      §
  271.  
  272.     a4    =  ^key.define
  273.     d0    =  6
  274.     Match this key                 · 6.2.4.1
  275.     = « d0 = deftype; -> reference.line »
  276.     a4    =  ^key.byte
  277.     d0    =  4
  278.     Match this key
  279.     = « d0 = 1; -> data.decl »
  280.     a4    =  ^key.word
  281.     d0    =  4
  282.     Match this key
  283.     = « d0 = 2; -> data.decl »
  284.     a4    =  ^key.long
  285.     d0    =  4
  286.     Match this key
  287.     = « d0 = 4; -> data.decl »
  288.     ->  §
  289. data.decl
  290.     defstatus = d0
  291.     d0.w     <<= 8
  292.     d0.b  =  deftype
  293.     ->  reference.line
  294.  
  295. 6.2.4.1  If the key matches, adjust the line by removing the key and
  296. marking the line with a nul.
  297.  
  298. Match this key
  299.     a3.l  =  tmp_ln
  300.     d2    =  d0
  301.     { (a4)+.b  ?  (a3)+
  302.       dbne     d0,}
  303.     = { d0.l    =  tmp_ln
  304.         d1.l    =  input_line
  305.         d0.l    -=  d1
  306.         d0        +=  d2
  307.         { (a3)+.b  ?    ' '
  308.           bne      ¶
  309.           d0    +=  1
  310.         ->   }
  311.         a0.l    += d0
  312.         l_length    -= d0
  313.         (input_line).b =  0
  314.     }
  315.  
  316.  
  317. 6.2.5  Comment sections are introduced by '§', '¶', or by a number and '.';
  318.   any of these may be preceded by blanks.  If we see one of these, reset
  319.   instatus flag.
  320.  
  321. --Check for comment paragraph header
  322.     chr  =  (tmp_ln)+
  323.     chr  ?  #para.char
  324.     beq      now.commenting
  325.     chr  ?  #section.char
  326.     beq      now.commenting
  327.     Is it a digit?
  328.     = { { chr  =  (tmp_ln)+
  329.           Is it a digit?
  330.           beq   }
  331.         chr  ?  '.'
  332.         = {
  333.     now.commenting:
  334.         · Remember that we are in a comment section.
  335.           instatus  =  0
  336.           ->    next.line
  337.         }
  338.     }
  339.  
  340. 6.2.6  If we find a section name, put its address in the table.
  341.  
  342. --Check for name of procedure or code section
  343.     tst.b    paren_flag
  344.     bne      §
  345.  
  346.      · Check for name of a procedure section.
  347.     chr  =  (input_line)
  348.     Is it a capital?
  349.     = « d0.w    =  csecttype; ->  section.reference »
  350.  
  351.      · Check for name of a macro section.
  352.     (input_line).b  ?  '-'
  353.     = { 1(input_line).b  ?  '-'
  354.         = { d0.w  =  msecttype
  355.   section.reference:
  356.             a1    =  ^branch.stack
  357.             a1.l  ?  brace.level
  358.             != { brace.level.l = a1
  359.            --Warn about unmatched brace            · 6.2.6.1
  360.             }
  361.             sect.name.l = fpoint
  362.             sect.namelen.b = l_length
  363.   reference.line:          · branch to here from 6.2.4
  364.             --Enter in table                   · 6.2.6.2
  365.         }
  366.     }
  367.  
  368. 6.2.6.1  Error message to standard output.
  369.  
  370. --Warn about unmatched brace
  371.     movem.l  d0-d3/a0,-(sp)
  372.     print    brace.prob
  373.     arg`a    =    chandle
  374.     clr.l    l_length
  375.     l_length.b  =  sect.namelen
  376.     arg`b    =    sect.name
  377.     call     Write
  378.     movem.l  (sp)+,d0-d3/a0
  379.  
  380.  
  381. 6.2.6.2 The current place in the file buffer is where the input line
  382. we are working on will be placed.  Enter this into the table, with
  383. entry type passed in d0.
  384.  
  385. --Enter in table
  386.     a1.l      =  lastsect
  387.     (a1)+.l      =  fpoint
  388.     (a1)+.w      =  d0
  389.     lastsect  =  a1
  390.  
  391. 6.3  Various special characters in the input line trigger web
  392. transformations.
  393.  
  394. --Examine each character of input line
  395.  define   quote_flag  D1
  396.     quote_flag    =  0
  397.      · count of characters in line to examine
  398.  define   char_count  D2.L
  399.     char_count  =  l_length
  400.     tmp_ln  =  ^obuf
  401.     clr.b    -1(tmp_ln) · guard byte when search backwards
  402.     ->    next.character
  403.   no.put.character:
  404.     l_length -= 1
  405.     ->       next.character
  406. {
  407.  is.it    ''''; =  «  eor.b    #1,quote_flag  » · enclosed in quotes?
  408.  tst.b    quote_flag
  409.  = {   · This part of line is not within quotes.
  410.     is.it    ';';  = «  chr    =  new_line;  -> put.character »
  411.     --For blank, ignore if redundant               · 6.3.1
  412.     --For bullet character, strip end of line            · 6.3.2
  413.     --For grouping characters, substitute labels           · 6.3.3
  414.     --For parentheses, keep track of nesting           · 6.3.4
  415.     --For colon, left adjust label and start new line      · 6.3.5
  416.  }
  417.  put.character:
  418.  tst.b    paren_flag; bne   no.put.character
  419.  (tmp_ln)+.b  =  chr
  420. next.character
  421.  chr  =  (input_line)+; char_count -= 1
  422.  bpl      }
  423. .end.6.3
  424.  
  425. 6.3.1 Strip off extra white space.  Note that tabs in input file have been
  426. converted to blanks already.
  427.  
  428. --For blank, ignore if redundant
  429.     is.it   <' '>;   bne    §
  430.     (input_line).b  ?  ' '
  431.     beq    no.put.character
  432.  
  433.  
  434. 6.3.2  Discard what is after the end-line comment character, and
  435. trim any preceding blanks.
  436.  
  437. --For bullet character, strip end of line
  438.     --Other characters treated as bullets
  439.     is.it    bullet.char
  440.     = { l_length -=  char_count
  441.         char_count  =  l_length
  442.         {  char_count -= 1
  443.             · If line has become empty, ignore it altogether.
  444.            beq      next.line
  445.            (tmp_ln).b  =  new_line
  446.            chr  =  -(tmp_ln)
  447.            is.it    <' '>
  448.            bne      .end.6.3
  449.            l_length -= 1
  450.            ->  }
  451.     }
  452.  
  453.  
  454. --Other characters treated as bullets
  455.     chr  ?  'A' + 128;    bcs    §
  456.     chr  ?  'Z' + 128;    bhi    §
  457.     chr  =  # bullet.char
  458.  
  459.  
  460.  
  461. 6.3.3  In addition to labels, insert newlines for '«','{', and '»'. Place
  462. an additional break label on the line after '}', and when we see '¶',
  463. substitue this label.
  464.  
  465. --For grouping characters, substitute labels
  466.     tst.b    paren_flag
  467.     bne      §
  468.  
  469.        byte bracket_flag
  470.     bracket_flag  =  0
  471.  
  472.     is.it    leftg.char
  473.     beq      begin.group
  474.     is.it    '['
  475.     = {    bracket_flag    =  1
  476.           ->   begin.group
  477.     }
  478.  
  479.     is.it    rightg.char
  480.     = {    (tmp_ln)+.b  =    new_line
  481.         l_length  += 1
  482.         ->     end.group
  483.     }
  484.  
  485.     is.it    '{'
  486.     = {
  487.  begin.group:
  488.       Another left adjustment     · 6.3.3.1
  489.       Push brace level        · 28
  490.       Generate branch label        · 32
  491.       bracket_flag  =  0
  492.       (input_line).b    ?  new_line
  493.       beq     no.put.character
  494.       chr  =    new_line
  495.       ->    put.character
  496.     }
  497.     is.it    ']'
  498.     = { bracket_flag    =  1
  499.         ->   end.group
  500.     }
  501.     is.it    '}'
  502.     = {
  503.  end.group:
  504.       Another left adjustment    · 6.3.3.1
  505.       Pop brace level        · 29
  506.       Generate branch label        · 32
  507.       tst.b  bracket_flag
  508.       != { bracket_flag  =  0
  509.            -> no.put.character
  510.       }
  511.       (tmp_ln)+.b  =    new_line
  512.       l_length += 1
  513.       --Get last break label    · 31
  514.       Generate branch label        · 32
  515.       ->  no.put.character
  516.     }
  517.  
  518.     is.it    para.char
  519.     = { --Get break label        · 30
  520.         Generate branch label    · 32
  521.         ->  no.put.character
  522.     }
  523.  
  524. 6.3.3.1  Labels from braces at the beginning of a line will not be left
  525. adjusted after newlines due to ':', ';', or another brace, unless we
  526. make this special adjustment.   When the first preceding non-blank is
  527. other than a newline, we don't want an adjustment, so the saved values
  528. of l_length and tmp_ln are restored.  But when it is newline, we
  529. discard the following blanks.
  530.  
  531. Another left adjustment
  532.     movem.l  l_length/tmp_ln,-(sp)
  533. more.left
  534.     chr  =  -1(tmp_ln)
  535.     chr  ?  new_line;   = « a7  +=  8; ->  § »
  536. ( Have to use a7 above, not sp, to get an addq. )
  537.     chr  ?  ' '
  538.     = { tmp_ln    -= 1
  539.         l_length    -= 1
  540.         ->       more.left
  541.     }
  542.     movem.l  (sp)+,l_length/tmp_ln
  543.  
  544. 6.3.4  The only thing special here is to watch for the right paren that
  545. closes out the comment, and make sure to discard it.  It's not important,
  546. but in case nothing follows on the line, we also avoid storing a blank
  547. line.
  548.  
  549. --For parentheses, keep track of nesting
  550.     tst.b    paren_flag
  551.     beq      §
  552.     is.it    '(';   =  «  paren_flag += 1 »
  553.     is.it    ')'
  554.     bne      §
  555.     paren_flag  -= 1
  556.     bne      no.put.character
  557.     (input_line).b  ?  new_line
  558.     beq      next.line
  559.     ->       no.put.character
  560.  
  561. 6.3.5  In output phase, it is convenient to be able to distinguish
  562. labels just by whether the line starts with a space.  The BS character
  563. will not be put in the file buffer.
  564.  
  565. --For colon, left adjust label and start new line
  566.     tst.b    paren_flag
  567.     bne      §
  568.  
  569.     is.it    ':'
  570.     bne      §
  571.     obuf.b  ?  ' '
  572.     = «  obuf.b  =  8  »
  573.     (input_line).b  ?  new_line
  574.     beq      no.put.character
  575.     (tmp_ln)+.b  =  new_line
  576.     l_length += 1
  577.  
  578.     (input_line).b  ?  ' '  · make sure of space after colon
  579.     beq      no.put.character
  580.     chr  =  ' '
  581.     ->   put.character
  582.  
  583. 6.4  If a data declaration was detected, append a generated label
  584. to add to the definition.
  585.  
  586. --Append possible data label
  587.  word  declcount
  588.     chr  =  defstatus
  589.     beq   §
  590.     tmp_ln -= 1    · replace newline with blank
  591.     (tmp_ln)+.b = ' '
  592.     a3    = ^declcount
  593.     d0.w  =  (a3)
  594.     (a3).w += 1
  595.     Generate branch label     · 32
  596.     (tmp_ln)+.b = 'Q'
  597.     (tmp_ln)+.b = '.'
  598.     chr  =  defstatus
  599.     is.it  1; = « (tmp_ln)+.b = 'B' »
  600.     is.it  2; = « (tmp_ln)+.b = 'W' »
  601.     is.it  4; = « (tmp_ln)+.b = 'L' »
  602.     (tmp_ln)+.b  =  new_line
  603.     l_length     += 4
  604.     defstatus   = 0
  605.  
  606.  
  607. 6.5  A string copy routine.    Skips an initial BS which is used to
  608. left adjust labels.
  609.  
  610. --Move l_length chars from obuf to file buffer
  611.     a1.l    =  fpoint
  612.     a0      =  ^obuf
  613.     (a0).b  ?  8
  614.     = « l_length -= 1; a0 += 1 »
  615.     l_length -= 1
  616.     bmi      §
  617.     {  (a1)+.b  =  (a0)+
  618.        dbra      l_length,}
  619.     fpoint  =  a1
  620.  
  621.  
  622.  
  623.  
  624.  
  625. 7. This is the second half of the task.  We take each procedure that
  626. was noted in in the input phase and put it out.  Macro sections are
  627. thus skipped over, but they will be included where they are invoked
  628. by the recursive subroutine 'Output section ...'.
  629.  
  630. --Output the file, substituting appropriately for defined names
  631.  define   t_entry    A1.L
  632.     t_entry        =  lastsect
  633.     clr.l    (t_entry)   · in case later decide to use alloc to get mem
  634.     t_entry        =  ^sectlist
  635.     lastsect    =  t_entry
  636.  define  p_buffer    A0.L
  637.     p_buffer    =  filebuf
  638.  define  sect_count D3.L
  639.     sect_count  =  0
  640.  word    bracecount
  641.     bracecount  = 1
  642.  word    bracketcount
  643.  word    typeofsect
  644.  
  645. next.sect
  646.     push    =  sect_count
  647.     Push brace level       · 28
  648.     Output section starting at p_buffer in filebuf     · 7.1
  649.     Pop brace level       · 29
  650.     sect_count  =  pop
  651.  
  652.     {    tst.l    (t_entry)
  653.         beq      §
  654.         p_buffer    =  (t_entry)+
  655.         d0.w        =  (t_entry)+
  656.         d0.w  ?  csecttype
  657.         bne      }
  658.     typeofsect    =    d0
  659.     lastsect    =    t_entry
  660.     sect_count    +=    1
  661.     movem.l  sect_count/p_buffer,-(sp)
  662.     --Generate procedure label        · 27
  663.     movem.l  (sp)+,sect_count/p_buffer
  664.     Find registers to save
  665.     bra      next.sect
  666.  
  667. abort1
  668.     arg`a  =    ihandle
  669.     call     Close
  670. abort
  671.     print    nogo
  672.     d0  =  10
  673.     rts
  674.  
  675.  
  676. Find registers to save
  677.     long    saveregs
  678.  
  679.     clr.l    saveregs
  680.     {    chr    =    (p_buffer)+
  681.         chr  ?  new_line;    beq    ¶
  682.         chr  ?  '('
  683.         = {  {    chr  =    (p_buffer)+
  684.             chr  ?    '('
  685.             = {    {  (p_buffer)+.b  ? ')'
  686.                    bne    }
  687.                 chr  =    (p_buffer)+
  688.             }
  689.             chr  ?  ')'
  690.             = {    (p_buffer).b  ?    new_line
  691.                 = {    p_buffer  +=    1
  692.                     ->    §
  693.                 }
  694.                 push    =    sect_count
  695.                 saveregs  =    p_buffer
  696.                 Move line at p_buffer in file buffer to obuf
  697.                 push    =    p_buffer
  698.                 Do substitution for defined symbols
  699.                 Purge length suffixes
  700.                 push    =    l_length
  701.                 fprint    moveminst
  702.                 l_length  =    pop
  703.                 a0    =    ^ obuf
  704.                 (a0).b  ?  9
  705.                 = {    a0  +=    1
  706.                     l_length  -=    1
  707.                 }
  708.                 arg`a    =    ohandle
  709.                 arg`b    =    a0
  710.                 l_length  -=    1
  711.                 call    Write
  712.                 fprint    pushsuffix
  713.                 p_buffer  =    pop
  714.                 sect_count  =    pop
  715.                 ->    §
  716.             }
  717.              ->       }
  718.         }
  719.         ->   }
  720.  
  721.  
  722. 7.1. Detect procedure and macro invocations.  For procedures, we generate
  723. a 'bsr' instruction.  For macros, we redirect the buffer pointer to
  724. where the macro definition is and do a recursive call.
  725.  
  726. Output section starting at p_buffer in filebuf
  727. · branch to here from 7.1.2
  728. outsect
  729.     t_entry  =  lastsect
  730.     p_buffer    ?  fpoint
  731.     bcc      done.sect
  732. · look for next section, past any defines in table
  733.     {    5(t_entry).b  ?  deftype
  734.         bne      ¶
  735.         t_entry += 6
  736.         bra   }
  737. · if doing last section, continue to end of file
  738.     tst.l    (t_entry)
  739.     beq      this.sect
  740. · have we gotten to beginning of next section?
  741.     p_buffer    ?  (t_entry)
  742.     bcs      this.sect
  743. done.sect
  744.     --Generate end section label     · 24
  745.     d0  =  0
  746.     rts
  747.  
  748. this.sect
  749.     Move line at p_buffer in file buffer to obuf       · 7.1.1
  750.     chr  =    obuf
  751.       · ignore 'define' lines (which were marked with nul)
  752.     beq    outsect
  753.     chr  ?  new_line
  754.     beq    outsect
  755.  
  756.     push  =  p_buffer · save point to next line
  757.  
  758.      · check for macro call
  759.     tmp_ln  =  ^obuf
  760. find.end.label
  761.     chr  =  (tmp_ln)+
  762.     chr  ?  ' '
  763.     != { chr    ?  new_line
  764.          bne    find.end.label
  765.     }
  766.     chr  ?  ' '
  767.     = { d2    =   csecttype
  768.         chr  =   (tmp_ln)
  769.         Is it a capital?     · If so, we have a procedure call
  770.         beq       embedded.sect
  771.  
  772.         (tmp_ln).b  ?  '-'
  773.         = { 1(tmp_ln).b  ?  '-'
  774.             = { d2  =  msecttype
  775.      embedded.sect:
  776.           push.w  =  typeofsect
  777.           push      =  lastsect
  778.           push      =  saveregs
  779.           Push brace level     · 28
  780.           Find and output macro section        · 7.1.2
  781.           Pop brace level      · 29
  782.           saveregs  =  pop
  783.           lastsect  =  pop
  784.           typeofsect  = pop
  785.           p_buffer  =  pop
  786.           ->   outsect
  787.             }
  788.         }
  789.         push    =  tmp_ln
  790.         --Do substitution for branch symbols       · 7.1.3
  791.         tmp_ln  =  (sp)
  792.         Do substitution for defined symbols        · 7.1.4
  793.         tmp_ln  =  pop
  794.         --Rearrange statements with an equals sign       · 7.1.5
  795.     }
  796.     Purge length suffixes                   · 7.1.6
  797.     arg`a  =    ohandle
  798.     arg`b  =    #obuf
  799.     call     Write
  800.     p_buffer    =  pop
  801.  
  802.     l_length    ?  d0
  803.     beq      outsect    · loop for next line
  804. · sure hope we don't get to here
  805.     print    prob
  806.     d0  =  10
  807.  
  808.  
  809. 7.1.1  A string copy routine.  This also handles substitution of
  810. label for '§' as target of branch.
  811.  
  812. Move line at p_buffer in file buffer to obuf
  813.     l_length    =  0
  814.     a1    =  ^obuf
  815.     {  chr       =  (p_buffer)+
  816.        (a1)+.b   =  chr
  817.        l_length += 1
  818.        chr  ?  new_line
  819.        bne      }
  820.     a1 -= 1
  821.     {  -(a1).b  ?  ' '
  822.        bne      ¶
  823.        l_length -= 1
  824.        (a1).b  =  new_line
  825.        ->    }
  826.     (a1).b  ?  #section.char
  827.     = { l_length -= 1  · for losing section char
  828.         --Append end section label   · 25
  829.     }
  830.  
  831. 7.1.2  Action when procedure or macro invocation is detected.
  832.  
  833. Find and output macro section
  834.     sect_count  =  0
  835.     d1.l      =  tmp_ln
  836.     t_entry      =  ^sectlist
  837.  {
  838.     { tst.l     (t_entry)
  839.       = « push    =  d1
  840.           print    what.mac
  841.           tmp_ln    =  pop
  842.           --Tell the bad name
  843.           d0    =  10
  844.           rts »
  845.       p_buffer  =  (t_entry)+
  846.       d0.w        =  (t_entry)+
  847.       d0.w  ?  d2  · secttype passed by caller
  848.       =   }
  849.     sect_count += 1
  850.     lastsect    =  t_entry
  851.     a2.l  =  d1
  852.     { chr  =    (p_buffer)+
  853.       chr  ?    new_line
  854.       != «  chr  ?  '('  »
  855.       = {   chr  ?  (a2)
  856.             beq      c.m.match
  857.       }
  858.       chr  ?    (a2)+
  859.       beq     }
  860.  ->    }
  861.  
  862. c.m.match
  863. ( If chr is '(', put out = stmts.  Parameter list
  864.   is at p_buffer, and arg list is at a2+1 in obuf.)
  865.  
  866.     chr  ?  '('
  867.     = « --Arguments to parameters  »
  868.  
  869.     d2.w  ?  msecttype
  870.     = {    typeofsect = d2
  871.         p_buffer  -= 1
  872.         Find registers to save
  873.         ->    outsect
  874.     }
  875.     d2.w  ?  csecttype
  876.     = { --Generate BSR procedure label  · 23
  877.         d0  =  0
  878.         rts
  879.     }
  880.     · stub other sector types
  881.     d0  =  0
  882.  
  883.  
  884.  
  885. ( If chr is '(', put out = stmts.  Parameter list
  886.   is at p_buffer, and arg list is at a2+1 in obuf.)
  887.  
  888. --Arguments to parameters
  889.     a2    +=    1
  890.     (a2).b    ?    ')';    beq    §
  891.     push    =    p_buffer
  892.     push    =    d2
  893.     push    =    sect_count
  894.     push    =    p_buffer
  895. · strip name from procedure call
  896.     p_buffer  =    a2
  897.     Move line at p_buffer in file buffer to obuf
  898.         Do substitution for defined symbols
  899.     Purge length suffixes
  900. · save in ibuf
  901.     source_s  =    ^ obuf
  902.     target_s  =    ^ ibuf
  903.     l_length -=    1
  904.     {    (target_s)+.b    =  (source_s)+
  905.         dbra    l_length,}
  906.  
  907. · strip off name from procedure header
  908.     p_buffer  =    pop
  909.     Move line at p_buffer in file buffer to obuf
  910.         Do substitution for defined symbols
  911.     Purge length suffixes
  912. · generate moves from list of args in ibuf to list of parms in obuf
  913.     --Moves from args to parms
  914.     sect_count  =    pop
  915.     d2.l    =    pop
  916.     p_buffer  =    pop
  917.  
  918.  
  919. --Moves from args to parms
  920.     source_s  =    ^ ibuf
  921.     target_s  =    ^ obuf
  922.     {    (source_s).b  ?    ')';    beq    §
  923.         (target_s).b  ?    ')';    beq    §
  924.         · How long is parm?
  925.         Measure length of list item(target_s)
  926.         push    =    tmp_ln
  927.         d1.l    =    l_length
  928.         Measure length of list item(source_s)
  929.         push    =    tmp_ln
  930.         tst.l    l_length
  931.         > {    tst.l    d1
  932.             > {    push    =    target_s
  933.                 push    =    d1
  934.                 push    =    source_s
  935.                 push    =    l_length
  936.                 fprint    moveinst
  937.                 l_length  =    pop
  938.                 arg`b    =    pop
  939.                 arg`a    =    ohandle
  940.                 call    Write
  941.                 fprint    commachar
  942.                 l_length  =    pop
  943.                 arg`b    =    pop
  944.                 arg`a    =    ohandle
  945.                 call    Write
  946.                 fprint    newlinechar
  947.             }
  948.         }
  949.         source_s  =    pop
  950.         target_s  =    pop
  951.         ->    }
  952.  
  953. Measure length of list item(tmp_ln)
  954.     l_length  =    0
  955.     {    chr    =    (tmp_ln)+
  956.         chr  ?  '('
  957.         = {    {    l_length  +=    1
  958.                 (tmp_ln)+.b  ?  ')'
  959.                 bne    }
  960. ·            l_length  +=    1
  961. ·            chr    =    (tmp_ln)
  962.         }
  963.         chr  ?    ',';    beq    §
  964.         chr  ?    ')'
  965.         = {    tmp_ln  -=    1
  966.             ->    §
  967.         }
  968.         l_length  +=    1
  969.         ->    }
  970.  
  971.  
  972. ( s. 7.1.3 is below )
  973.  
  974. 7.1.4  The line in obuf is just about to be written to output file.  Here
  975. we want to make substitutions for define's that were found in the
  976. input phase.
  977.  
  978. Do substitution for defined symbols
  979. (l_length is in use now.)
  980.  define   target_s  A0.L
  981.     target_s      =  ^obuf
  982.     quote_flag  =  0
  983. look.for.symbol
  984.     {  chr  =  (target_s)+
  985.        chr  ?  new_line
  986.        beq      §
  987.        is.it      ''''
  988.        = «  eor.b  #1,quote_flag »
  989.        tst.b      quote_flag
  990.        bne      }
  991.     is.it    '_'
  992.     bcs      look.for.symbol
  993.     is.it    'z'
  994.     bhi      look.for.symbol
  995.     target_s -= 1
  996.     --Try to find symbol in table · 7.1.4.1
  997.     !=  {
  998.         --Do the substitution     · 7.1.4.2
  999.     }
  1000.  
  1001.     { quote_flag  =  0
  1002.       chr  =    (target_s)+
  1003.       chr  ?    new_line
  1004.       beq     §
  1005.       is.it     ''''
  1006.       = «  eor.b  #1,quote_flag; -> look.for.symbol »
  1007.       is.it     '_'
  1008.       bcs     look.for.symbol
  1009.       is.it     'z'
  1010.       bhi     look.for.symbol
  1011.       ->   }
  1012.  
  1013.  
  1014. 7.1.4.1  Go through table and try to match each symbol name of each
  1015. definition.  If matched, return condition code 'not equal', and source_s
  1016. pointing at beginning of definition.
  1017.  
  1018. --Try to find symbol in table
  1019. (target_s points to the candidate symbol.)
  1020.  define  source_s    A2.L
  1021.  define  defn_type    D2
  1022.     defn_type  =  deftype
  1023.  
  1024.     t_entry     =  ^sectlist
  1025.    {
  1026. try.next.entry
  1027.     {    tst.l     (t_entry)
  1028.         beq     §     · sym.not.there
  1029.         source_s  =  (t_entry)+
  1030.         d0.w  =  (t_entry)+
  1031.         d0.b  ?  defn_type
  1032.         bne     }
  1033.  
  1034.     source_s += 1   · skip the 0 byte
  1035.     a3.l  =  target_s
  1036.  
  1037.     {    chr  =    (source_s)+
  1038.         chr  ?    ' '  · end of reference symbol?
  1039.         != [    chr  ?  (a3)+
  1040.             beq    }
  1041.         ->    try.next.entry
  1042.         ]
  1043.     chr  =  (a3)
  1044.     chr  ?  '_'
  1045.     bcs    ¶
  1046.     chr  ?  'z'
  1047.     bhi    ¶
  1048.    ->    }       · try next entry
  1049.  
  1050. · point source_s past any spaces
  1051.  
  1052.     {    (source_s).b  ?  ' '
  1053.         bne    ¶
  1054.         source_s += 1
  1055.         ->    }
  1056.  
  1057.   · condition flag is not equal here
  1058.  
  1059.  
  1060.  
  1061. 7.1.4.2  Substitute in obuf the symbol pointed to by source_s for the symbol
  1062. pointed to by target_s.  The new source_s text ends with newline, while the
  1063. old target_s text ends with a non-lower-case-alphabetic.
  1064.   target_s is left pointing at the new text, and l_length is
  1065. adjusted for the new length.
  1066.  
  1067. --Do the substitution
  1068. · What is length of new text?
  1069.     d1     =    -1
  1070.     a3.l   =    source_s
  1071.     { d1  +=    1
  1072.       (a3)+.b  ?  new_line
  1073.       bne   }
  1074. · What is length of old text?
  1075.     d2    =  -1
  1076.     a1.l  =  target_s
  1077.     { d2   +=  1
  1078.       chr  =    (a1)+
  1079.       Is it an alphabetic?     · 7.1.4.2.1
  1080.       beq   }
  1081. · How much longer is the new text?
  1082.     d0.l  =  d1
  1083.     d0.l -=  d2
  1084.  !={
  1085.     + {
  1086.       · It is longer, so make more room.
  1087.         · Where is end of line?
  1088.       a1    =  ^obuf
  1089.       a1.l +=  l_length   · a1 points 1 beyond end
  1090.       a3.l  =  a1
  1091.       a3.l +=  d0    · 1 past new end
  1092.       { -(a3).b  =  -(a1)
  1093.         target_s  ?  a1
  1094.         bne    }
  1095.       ->  done.length.adjust
  1096.       }
  1097.     · It is shorter, so shorten old text
  1098.     a1   -=  1    · back to 1st char after old text
  1099.     a3.l  =  a1
  1100.     a3.l += d0    · 1st position after new text
  1101.     { (a3)+.b  =  (a1)+
  1102.       -1(a1).b  ?  new_line
  1103.       bne   }
  1104.  }
  1105. done.length.adjust
  1106.  
  1107.     l_length += d0    · new length
  1108. · copy in new text: length is in D1
  1109.     a1.l  =  target_s
  1110.     d1   -= 1
  1111.     + {
  1112.       { (a1)+.b  =  (source_s)+
  1113.         dbra       d1,}
  1114.     }
  1115.   · in case substitute text begins with a defined symbol, here we will
  1116.   · point back to preceding non-alphabetic, so main routine will not
  1117.   · skip over it
  1118.   target_s -= 1
  1119.  
  1120.  
  1121. 7.1.4.2.1 Test for lower case alphabetic in d0, returning conclusion as
  1122. condition code 'equal' if it was.
  1123.  
  1124. Is it an alphabetic?
  1125.     chr  ?  '_';  bcs   §
  1126.     chr  ?  'z';  bhi   §
  1127.     chr  ?  chr
  1128.  
  1129.  
  1130. 7.1.3  Look through table to see if line begins with '=', '<=', etc.
  1131. If so, get branch mnemonic from table and substitute it.
  1132.  
  1133. --Do substitution for branch symbols
  1134.  define br_len D2
  1135.     a2  =  ^branch.table
  1136.     bra      next.branch.entry
  1137.     {  br_len  =  1
  1138.        chr  ?  (tmp_ln)
  1139.        = { chr  =  1(A2)
  1140.            beq     matching.branch
  1141.            br_len  =    2
  1142.            chr  ?  1(tmp_ln)
  1143.            = { chr  =  2(A2)
  1144.          beq     matching.branch
  1145.          br_len  =  3
  1146.          chr  ?  2(tmp_ln)
  1147.          = {
  1148.      matching.branch:  --Substitute branch mnemonic · 7.1.3.1
  1149.              ->  §
  1150.          }
  1151.            }
  1152.        }
  1153.        a2  +=  6
  1154. next.branch.entry
  1155.        chr  =  (a2)
  1156.        bne   }
  1157.  
  1158.  
  1159. 7.1.3.1  Replace special branch symbol in obuf at position tmp_ln with
  1160. regular mnemonic in table, which is offset 3 bytes from the
  1161. beginning of the entry. Pointer to entry was left in A2 by search
  1162. routine, and br_len has length of special symbol.
  1163.  
  1164. --Substitute branch mnemonic
  1165.     d0     =    4    · amount extra room needed
  1166.     d0.l  -=    br_len
  1167.     a0     =    ^obuf
  1168.     a0.l  +=    l_length   · one beyond end of line
  1169.     l_length += d0
  1170.     a3.l   =    a0
  1171.     a3.l  +=    d0     · new end of line
  1172.     {  -(a3).b  =  -(a0)
  1173.        a0.l      ?  tmp_ln
  1174.        bne   }
  1175.     (tmp_ln)+.b  =  3(A2)
  1176.     (tmp_ln)+.b  =  4(A2)
  1177.     (tmp_ln)+.b  =  5(A2)
  1178.     (tmp_ln)+.b  =  ' '
  1179.  
  1180.  
  1181. 7.1.5  Change 'a = b' to 'move b,a', etc.
  1182.  
  1183. --Rearrange statements with an equals sign
  1184.     a3.l        =  tmp_ln
  1185.     source_s    =  ^ibuf
  1186.     quote_flag    =  0
  1187.     target_s    =  quote_flag
  1188.     {  chr  =  (tmp_ln)+
  1189.        is.it      ''''
  1190.        =  «  eor.b    #1,quote_flag »
  1191.        tst.b      quote_flag
  1192.        =  {  is.it    '?'
  1193.              != «  is.it  '='  »
  1194.              =  «  target_s  =  source_s »
  1195.              is.it    <' '>
  1196.              =  «  chr  =  -(source_s) »
  1197.        }
  1198.        (source_s)+.b    =  chr
  1199.        chr  ?  new_line
  1200.        bne      }
  1201.     tmp_ln  =  a3
  1202.     clr.b    -1(source_s)
  1203.     d0.l  =  target_s
  1204.     != { --Do the rearrangement      · 7.1.5.1
  1205.     }
  1206.  
  1207. 7.1.5.1  Copy to obuf the mnemonic, then the source, then the destination
  1208.  
  1209. --Do the rearrangement
  1210.     --Point source_s at correct mnemonic    · 7.1.5.1.1
  1211.     { (tmp_ln)+.b  =    (source_s)+;  bne  }
  1212.     tmp_ln  -=  1
  1213.     --Attach length suffix            · 7.1.5.1.2
  1214.     (tmp_ln)+.b  =  ' '
  1215.     clr.b    (target_s)+
  1216.     --Find start of second operand        · 7.1.5.1.3
  1217.     --Detect literal operand            · 7.1.5.1.4
  1218.     { (tmp_ln)+.b  =    (target_s)+;  bne  }
  1219.     -1(tmp_ln).b  =  ','
  1220.     source_s    =  ^ibuf
  1221.     { (tmp_ln)+.b  =    (source_s)+;  bne  }
  1222.     -1(tmp_ln).b  =  new_line
  1223.     source_s        =  ^obuf
  1224.     tmp_ln       -= source_s
  1225.     l_length        =  tmp_ln
  1226.  
  1227. 7.1.5.1.1  Look at characters before and after the '=' to decide.
  1228.  
  1229. --Point source_s at correct mnemonic
  1230.     source_s         =    ^mnem.move  · initial assumption
  1231.     1(target_s).b  ?    '&'
  1232.     != « 1(target_s).b  ?  '^' »
  1233.     =  «  source_s  =  ^mnem.lea; -> §  »
  1234.     (target_s).b   ?    '?'
  1235.     =  «  source_s  =  ^mnem.cmp; -> §  »
  1236.  
  1237.     chr  =  -1(target_s)
  1238. ( What to do about signed multiply and divide? )
  1239.     is.it  '*'; = « source_s = ^ mnem.mulu; -> k.ob. »
  1240.     is.it  '/'; = « source_s = ^ mnem.divu; -> k.ob. »
  1241.     is.it  '&'; = « source_s = ^ mnem.and;  -> k.ob. »
  1242.     is.it  '|'; = « source_s = ^ mnem.or;   -> k.ob. »
  1243. ( Use <<= and >>= here.  Should there
  1244.   be a convention for asl/asr? Rotate instructions? )
  1245.     is.it  '<'; = « source_s = ^ mnem.lsl; clr.b  -(target_s);  -> k.ob. »
  1246.     is.it  '>'; = « source_s = ^ mnem.lsr; clr.b  -(target_s);  -> k.ob. »
  1247.  
  1248.     · test for +=/-=
  1249.     -2(target_s).b  ?  ')'; beq  §  · '+' after ')' must be post increment
  1250.     is.it    '+'
  1251.     =  «  source_s  =  ^mnem.add; -> chk.long.as »
  1252.     is.it    '-'
  1253.     =  «  source_s  =  ^mnem.sub; -> chk.long.as »
  1254.     -> §
  1255. chk.long.as
  1256.     · does it have arg from 1 to 8?
  1257.     chr = 2(target_s)
  1258.     chr  ?  '('; beq    k.ob.  · no addq/subq if indirect register ref.
  1259.     Is it a digit?    · if so, out of range
  1260.     != «  chr = 1(target_s)
  1261.           chr ? '1'
  1262.           >= « chr ? '8'
  1263.          <= « source_s += 4 » » » · point to 'q.l' version
  1264. k.ob.
  1265.     target_s -= 1  · discard '+', '-', etc.
  1266.  
  1267.  
  1268. 7.1.5.1.2  A length suffix on the first operand gets put onto the
  1269. instruction mnemonic.
  1270.  
  1271. --Attach length suffix
  1272.     -2(target_s).b  ?  '.'; bne §
  1273.  
  1274.     -2(tmp_ln).b ? '.'  · replace '.l' if add/sub
  1275.     = « tmp_ln -= 2 »
  1276.     (tmp_ln)+.b  =  '.'
  1277.     chr   =  -1(target_s)
  1278.     bset  #5,chr
  1279.     (tmp_ln)+.b  =  chr
  1280.     clr.b    -2(target_s)
  1281.  
  1282. 7.1.5.1.3  The previous analysis may have moved us back a little.  Now
  1283. get back to the '=', and ignore any following pointer mark.
  1284.  
  1285. --Find start of second operand
  1286.     chr  =  (target_s)
  1287.     =  «   target_s += 1; chr  =  (target_s)    »
  1288.     is.it    '='
  1289.     =  «   target_s += 1; chr  =  (target_s)    »
  1290.     is.it    '&'
  1291.     != « is.it    '^' »
  1292.     =  «   target_s += 1  »
  1293.  
  1294. 7.1.5.1.4  Decide whether to stick in a '#', and also see if it's ok to
  1295. use moveq instead of move.
  1296.  
  1297. --Detect literal operand
  1298.     is.it    '''';  beq  .lit.add
  1299. *     is.it    '$' ;  beq  .lit.add
  1300. * Not before $ is inconsistent, but I have too much code that
  1301. * uses hex register offsets ...
  1302.  
  1303.     is.it    '@' ;  beq  .lit.add
  1304.     is.it    '%' ;  beq  .lit.add
  1305.  
  1306.     source_s    = target_s
  1307.     is.it    '-'
  1308.     =  «  source_s += 1; chr = (source_s) »
  1309.     --Is it just a number?
  1310.     =  {  chr  =  -2(target_s)
  1311.           d2.b =  -3(target_s)
  1312.           is.it 'L'
  1313.           = { tst.b  -3(target_s)
  1314.         = { chr  = -4(target_s)
  1315.             d2.b = -5(target_s)
  1316.             bclr  #5,d2
  1317.             d2.b  ?  'D'
  1318.             = { Is it a digit?
  1319.             = { -4(tmp_ln).b  ?  'e'
  1320.                 = « tmp_ln -= 2 »
  1321.             }
  1322.              }
  1323.         }
  1324.           }
  1325.           bclr  #5,d2
  1326.           d2.b  ?  'D'; bne .lit.add
  1327.           -2(tmp_ln).b  ?  'e'; bne .lit.add    · test for move mnemonic
  1328.           Is it a digit?
  1329.           =  «  -1(tmp_ln).b    =  'q';  (tmp_ln)+.b  =  ' '  »
  1330.            · Above is not sufficient test for reference to data reg!
  1331.            · .. could be symbol ending in 'd' + digit
  1332.       .lit.add:
  1333.           (tmp_ln)+.b  =  '#'
  1334.     }
  1335.  
  1336. --Is it just a number?
  1337.     Is it a digit?
  1338.     bne   §
  1339.     source_s += 1
  1340.     {  chr = (source_s)+
  1341.        Is it a digit?
  1342.        beq   }
  1343.     chr  ?  '('
  1344.     = « tst.b  chr; -> § »
  1345.     chr  ?  chr
  1346.  
  1347. 7.1.6  Elide all occurrences of '.B', '.W', and '.L'.
  1348.  
  1349. Purge length suffixes
  1350.     tmp_ln   =  &obuf
  1351.     source_s    =  tmp_ln
  1352.     quote_flag  =  0
  1353.     {    d2.b  =  (source_s)+
  1354.         d2.b  ?  '''';  =  «  eor.b    #1,quote_flag »
  1355.         tst.b    quote_flag
  1356.         = {    d2.b    ?  ' '
  1357.             = {    d2.b    =    9
  1358.                 [  (source_s).b ? ' ';  bne  ¶
  1359.                    source_s  +=  1
  1360.                    ->  ]
  1361.             }
  1362.             d2.b    ?  '.'
  1363.             = {    chr  =  (source_s)
  1364.                 Is it a length?           · 7.1.6.1
  1365.                 = {    source_s += 1
  1366.                     d2.b        = (source_s)+
  1367.                     l_length -= 2
  1368.                 }
  1369.             }
  1370.         }
  1371.         (tmp_ln)+.b = d2
  1372.         d2.b  ?  new_line
  1373.         bne   }
  1374.  
  1375.  
  1376. 7.1.6.1
  1377.  
  1378. Is it a length?
  1379.     chr  ?  'B'; beq §
  1380.     chr  ?  'W'; beq §
  1381.     chr  ?  'L'
  1382.  
  1383.  
  1384.  
  1385. 8.  Go through the table and print out DS directives for entries that were
  1386. left by data declarations.  Do the 'byte' declarations last, so we will
  1387. get word alignment for the others.
  1388.  
  1389. --Add bss section
  1390.     fprint     titl.bss
  1391.     d2    =  4
  1392.  {
  1393.     t_entry     =  ^sectlist
  1394.  { { { tst.l    (t_entry)
  1395.         beq       nxt.bs
  1396.         source_s  =  (t_entry)+
  1397.         d0.w    =  (t_entry)+
  1398.         d0.b    ?  deftype
  1399.         bne       }
  1400.       d0.w  >>= 8
  1401.       d0.w  ?  d2
  1402.       bne    }
  1403.     { (source_s)+.b  ?  ' '; bne }
  1404.  
  1405.     target_s    =  ^obuf
  1406.     a3.l    =  target_s
  1407.     {  chr   =  (source_s)+
  1408.        (target_s)+.b = chr
  1409.        chr  ?  new_line
  1410.        bne   }
  1411.     target_s -= 3
  1412.     chr    =  1(target_s)
  1413.     (target_s)+.b  =    ' '
  1414.     (target_s)+.b  =    'D'
  1415.     (target_s)+.b  =    'S'
  1416.     (target_s)+.b  =    '.'
  1417.     (target_s)+.b  =    chr
  1418.     (target_s)+.b  =    ' '
  1419.     (target_s)+.b  =    '1'
  1420.     (target_s)+.b  =    new_line
  1421.     target_s -   = a3
  1422.     l_length       = target_s
  1423.     target_s       = ^-1(a3)
  1424.     (target_s).b = l_length
  1425.     push       = t_entry
  1426.     push       = d2
  1427.     Put line to output file     · 35
  1428.     d2.l       = pop
  1429.     t_entry       = pop
  1430.     ->   }
  1431. nxt.bs
  1432.     d2.b  >>=  1
  1433.     bne  }
  1434.  
  1435.  
  1436.  
  1437. ( reserve §9-§19 for expansion )
  1438.  
  1439. 20. Test for digit in chr, returning conclusion as condition code 'equal'
  1440. if it was a digit.
  1441.  
  1442. Is it a digit?
  1443.     chr  ?  '0'; bcs §
  1444.     chr  ?  '9'; bhi §
  1445.     chr  ?  chr
  1446.  
  1447. 21. Test for capital letter in chr, returning conclusion as condition
  1448. code 'equal' if it was one.
  1449.  
  1450. Is it a capital?
  1451.     chr  ?  'A'; bcs §
  1452.     chr  ?  'Z'; bhi §
  1453.     chr  ?  chr
  1454.  
  1455.  
  1456.  
  1457. 22. Fill the input buffer, and return lines from it until there are
  1458. no more complete lines.  Then move the last partial line back,
  1459. fill the input buffer, and so on.
  1460.  
  1461. --Read an input line
  1462.  
  1463.     define   input_line   A0.L
  1464.     define   l_length     D3.L
  1465.     define   new_line     #10
  1466.     byte     bufchcount
  1467.  
  1468.     input_line  =  bufptr
  1469.     push     =  input_line
  1470.     l_length =  0           · no chars in line yet
  1471. · back to here when was necessary to read more from file
  1472. .rdln.cont
  1473.     d2    =  0
  1474.     d2.b  =  bufchcount
  1475.     bmi      rdln.keep.info          · this means file is exhausted
  1476.     beq      .rdln.more
  1477.  
  1478.     d2.b -= 1
  1479.     « chr  =    (input_line)+
  1480.       chr  ?    new_line
  1481.       beq     rdln.keep.one
  1482.       chr  ?    9
  1483.       = « -1(input_line).b = ' ' »
  1484.       l_length   +=  1
  1485.       l_length.b  ?  #ibufLen
  1486.       beq     rdln.keep.info
  1487.       dbra     D2,}
  1488. · ran out of chars -- go get more
  1489.     bra      .rdln.more
  1490. · have one line -- check not empty
  1491. rdln.keep.one
  1492.     l_length += 1
  1493. rdln.keep.info
  1494.     bufptr.l        =  input_line
  1495.     bufchcount    =  d2
  1496.     input_line  =  pop
  1497.     ->     §
  1498.  
  1499. .rdln.more
  1500. · have partial line in buffer with l_length chars in it
  1501.     a1.l     =  pop     · beginning of partial line
  1502. · while l_length > 0 move chars back to beginning of buffer
  1503.     input_line  =  ^ibuf
  1504.     push  =  input_line    · for ret.
  1505.     push  =  l_length
  1506.     l_length.b -= 1
  1507.          · if line was of > 0 length
  1508.     + {
  1509.     « (input_line)+.b  =  (a1)+
  1510.       dbra     l_length,}
  1511.       }
  1512. · fill remainder of buffer with 80-(l_length) chars
  1513.     l_length    =  # ibufLen
  1514.     d0.l      =  pop
  1515.     l_length.b -= d0
  1516.     push      =  d0
  1517.  
  1518.     a1      =  ^ibuf
  1519.     a1.l     += d0
  1520. · save where to continue processing line
  1521.     push      =  a1
  1522.  
  1523.     arg`a  =    ihandle
  1524.     arg`b  =    a1
  1525.     call     Read
  1526.  
  1527.     tst.b    d0
  1528.     = «  st  d0  »
  1529.     bufchcount    =  d0
  1530.  
  1531.     input_line  =  pop    · continue processing here
  1532.     l_length      =  pop    · chars scanned so far
  1533.     bra      .rdln.cont
  1534.  
  1535.  
  1536. 23. Used during output phase when a procedure invocation is detected.
  1537.  
  1538. --Generate BSR procedure label
  1539.     a0  =  ^obuf
  1540.     (a0)+.b  =  9
  1541.     (a0)+.b  =  'b'
  1542.     (a0)+.b  =  's'
  1543.     (a0)+.b  =  'r'
  1544.     (a0)+.b  =  9
  1545.     (a0)+.b  =  'P'
  1546.     olen.b   =  5 + 1 + 4 + 1
  1547.     Binary to hex string     · 33
  1548.     a0       =  ^olen
  1549.     Put line to output file     · 35
  1550.  
  1551. 24. Label goes at end of every section to serve as target for possible
  1552. branch to § statements.
  1553.  
  1554. --Generate end section label
  1555.     push     =  a1
  1556.     Get current section number · 26
  1557.     d3.w     =  d0
  1558.     a0       =  ^obuf
  1559.     (a0)+.b  =  'S'
  1560.     olen.b   =  1 + 4 + 1
  1561.     Binary to hex string     · 33
  1562.     a0       =  ^olen
  1563.     Put line to output file     · 35
  1564.  
  1565.     d0.l    =    saveregs
  1566.     != {    push    =    d0
  1567.         fprint    moveminst
  1568.         fprint    popprefix
  1569.         p_buffer  =    pop
  1570.         Move line at p_buffer in file buffer to obuf
  1571.         Do substitution for defined symbols
  1572.         Purge length suffixes
  1573.         a0    =    ^ obuf
  1574.         (a0).b  ?  9
  1575.         = {    a0  +=    1
  1576.             l_length  -=  1
  1577.         }
  1578.         arg`a    =    ohandle
  1579.         arg`b    =    a0
  1580.         call    Write
  1581.     }
  1582.  
  1583.     d0.w     =  typeofsect
  1584.     d0.w  ?  csecttype
  1585.     = «    fprint    rtsinst    »
  1586.  
  1587.     a1.l  =  pop
  1588.  
  1589.  
  1590. 25. Corresponding to above label at end of section, when we see a §
  1591. character at end of line, substitute a label.
  1592.  
  1593. --Append end section label
  1594.     Get current section number · 26
  1595.     push     =  a1
  1596.     Generate branch label     · 32
  1597.     a1.l     =  pop
  1598.     (a1).b   =  'S'
  1599.  
  1600. 26. Glance at stack for number to use in constructing label.
  1601.  
  1602. Get current section number
  1603.     push   =    a0
  1604.     a0.l   =    brace.level
  1605.     d0.w   =    (a0)
  1606.     a0.l   =    pop
  1607.  
  1608. 27. Called during output phase when procedure name -- beginning of
  1609. section -- is detected.
  1610.  
  1611. --Generate procedure label
  1612.     a0       =  ^obuf
  1613.     (a0)+.b  =  'P'
  1614.     olen.b   =   1 + 4 + 1
  1615.     Binary to hex string     · 33
  1616.     a0       =  ^olen
  1617.     Put line to output file     · 35
  1618.  
  1619. 28. At left brace (input phase) or beginning of section (output phase)
  1620. bump and push the current number, so can later construct corresponding
  1621. label at matching right brace or end of section.
  1622.  
  1623. Push brace level
  1624.     push     =  a0
  1625.     tst.b  bracket_flag
  1626.     != { a0        =  ^bracketcount
  1627.          (a0).w  += 1
  1628.          d0.w     =  (a0)
  1629.          a0.l     =  bracket.level
  1630.          -(a0).w  =  d0
  1631.          bracket.level.l  =  a0
  1632.          a0.l     =  pop
  1633.          ->  §
  1634.     }
  1635.     a0       =  ^bracecount
  1636.     (a0).w  += 1
  1637.     d0.w     =  (a0)
  1638.     a0.l     =  brace.level
  1639.     -(a0).w  =  d0
  1640.     brace.level.l  =    a0
  1641.     a0.l     =  pop
  1642.  
  1643. 29. Now we need it.
  1644.  
  1645. Pop brace level
  1646.     push     =  a0
  1647.     tst.b  bracket_flag
  1648.     != { a0.l     =  bracket.level
  1649.          d0.w     =  (a0)+
  1650.          bracket.level.l  =  a0
  1651.          a0.l     =  pop
  1652.          ->  §
  1653.     }
  1654.     a0.l     =  brace.level
  1655.     d0.w     =  (a0)+
  1656.     brace.level.l  =    a0
  1657.     a0.l     =  pop
  1658.  
  1659. 30. Glance at stack for number to construct label for branch to ¶ statement.
  1660.  
  1661. --Get break label
  1662.     push     =  a0
  1663.     a0.l     =  brace.level
  1664.     d0.w     =  (a0)
  1665.     bset     #15,D0
  1666.     a0.l     =  pop
  1667.  
  1668. 31. Glance at stack for number to construct label after right brace
  1669. to serve as target for possible branch to ¶ statement.
  1670.  
  1671. --Get last break label
  1672.     push     =  a0
  1673.     a0.l     =  brace.level
  1674.     d0.w     =  -2(a0)
  1675.     bset     #15,D0
  1676.     a0.l     =  pop
  1677.  
  1678. 32. Generate label to replace a brace.  This is also used to construct
  1679. end of section labels and labels for data declarations.
  1680.  
  1681. Generate branch label
  1682.     movem.l  D1-D3/A0-A2,-(sp)
  1683.     a0.l     =  a1
  1684.     d3.w     =  d0
  1685.     (a0)+.b  =  '.'
  1686.     Binary to hex string     · 33
  1687.     tst.b  bracket_flag
  1688.     != « (a0).b  +=  32  »
  1689.     movem.l  (sp)+,D1-D3/A0-A2
  1690.     d0       =  1 + 4
  1691.     l_length += d0
  1692.     tmp_ln   += d0
  1693.  
  1694.  
  1695. 33. Convert number to 4 hex digits when generating unique labels.
  1696.  
  1697. Binary to hex string
  1698.     d0       =  0
  1699.     d0.w     =  D3
  1700.     a0.l    +=  4
  1701.     (a0).b   =  new_line
  1702.     a1       =  ^hextab
  1703.     d1       =  4 - 1
  1704.     {  d2.l      =  d0
  1705.        d2.l     &=  15
  1706.        -(a0).b  =  0(A1,D2)
  1707.        d0.l     >>= 4
  1708.        dbra      d1,}
  1709.  
  1710.  
  1711. 34. This is for console messages. [used by 'print' macro]
  1712.  
  1713. Display string
  1714.     arg`a      =  chandle
  1715.     clr.l    l_length
  1716.     l_length.b  =  (a0)+
  1717.     arg`b      =  a0
  1718.     call     Write
  1719.  
  1720. 35. As above, except output goes to output file.
  1721.  
  1722. Put line to output file
  1723.     arg`a      =  ohandle
  1724.     clr.l    l_length
  1725.     l_length.b  =  (a0)+
  1726.     arg`b      =  a0
  1727.     call     Write
  1728.  
  1729. 36. AmigaDOS stuff.
  1730.  
  1731. --Initialize standard input and output
  1732.     a1    =  ^libname
  1733.     d0    =  0
  1734.     callex   OpenLibrary
  1735.     a6.l  =  d0
  1736. · obtain file handles for output and input opened by CLI
  1737.     call     Output
  1738.     ohandle  =  d0
  1739.     chandle  =  d0
  1740.     call     Input
  1741.     ihandle  =  d0
  1742.  
  1743.  
  1744. 37. Identify the name of a macro or procedure call which was
  1745. not found.  tmp_ln points to it.
  1746.  
  1747. --Tell the bad name
  1748.     l_length  =    0
  1749.     a0.l    =    tmp_ln
  1750.     {    l_length  +=  1
  1751.         (tmp_ln)+.b  ?  10
  1752.         bne    }
  1753.     arg`a      =  chandle
  1754.     arg`b      =  a0
  1755.     call     Write
  1756.  
  1757.  
  1758. 38. Not really a procedure, of course.
  1759.  
  1760. Data sections
  1761.  
  1762.     section  three,bss
  1763.  
  1764. olen        ds.b  1
  1765. obuf        ds.b  ibufLen
  1766. ilen        ds.b  1
  1767. ibuf        ds.b  ibufLen
  1768. · now on word boundary
  1769.  
  1770. infname     ds.b  30
  1771. outfname    ds.b  30
  1772.  
  1773.        cnop      0,2
  1774.  
  1775. ( Stack to keep label numbers for right braces
  1776.   during input phase, and end of section labels
  1777.   during output phase. )
  1778.           ds.w    maxbracenest
  1779. branch.stack   ds.w    4  · room for stack to underflow a little
  1780.           ds.w    maxbracenest
  1781. bracket.stack  ds.w    4  · room for stack to underflow a little
  1782.  
  1783. ( Table to keep track of definitions.  Each entry
  1784.   is a longword and a word.    The longword points to
  1785.   the name in the text stored in the filebuffer, and
  1786.   the word holds the type of the definition.  In the
  1787.   case of 'define' entries and data declarations, the
  1788.   type word is split into two bytes.  The low byte says
  1789.   it's a 'define', and the high byte is 0 for regular
  1790.   defines, but 1, 2, or 4 for 'byte', 'word', and 'long'
  1791.   declarations, respectively. )
  1792. sectlist      ds.b    maxsects*6
  1793.  
  1794. ( Buffer to hold text read in from source file. )
  1795. · now using allocation
  1796. ·filebuf       ds.b  maxfsize
  1797.  
  1798.  
  1799.     section two,data
  1800.  
  1801. libname  dc.b  'dos.library',0
  1802.  
  1803. bufptr      dc.l    ibuf
  1804.     cnop     0,2
  1805. brace.level      dc.l    branch.stack
  1806. bracket.level  dc.l    bracket.stack
  1807. sect.name      dc.l    sect.noname
  1808. sect.namelen   dc.b    16
  1809. sect.noname      dc.b    'unnamed section',10
  1810. brace.prob      dc.b    29,'unmatched braces in section: '
  1811.  
  1812. branch.table
  1813.     dc.b  '<=',177,'bgt'
  1814.     dc.b  '<=',0,'bhi'
  1815.     dc.b  '>=',177,'blt'
  1816.     dc.b  '>=',0,'bcs'
  1817.     dc.b  '~=',0,'beq'
  1818.     dc.b  '!=',0,'beq'
  1819.     dc.b  '->',0,'bra'
  1820.     dc.b  '<',177,0,'bge'
  1821.     dc.b  '<',0,0,'bcc'
  1822.     dc.b  '>',177,0,'ble'
  1823.     dc.b  '>',0,0,'bls'
  1824.     dc.b  '=',0,0,'bne'
  1825.     dc.b  '- ',0,'bpl'
  1826.     dc.b  '+',0,0,'bmi'
  1827.     dc.b  0
  1828.  
  1829. hextab   dc.b  '0123456789ABCDEF'
  1830.  
  1831.           bstr  nogo,<couldn''t open file>
  1832.           bstr  prob,<problem with output file>
  1833.           bstr  what.mac,<didn''t find proc/macro...>
  1834.           bstr  titl.bss,< section webroom,bss>
  1835. end.line    dc.b  1$-*-1
  1836.         dc.b  9,'end',10,10
  1837. 1$
  1838. moveinst    dc.b  1$-*-1
  1839.         dc.b  9,'move.l',9
  1840. 1$
  1841. moveminst    dc.b  1$-*-1
  1842.         dc.b  9,'movem.l',9
  1843. 1$
  1844. rtsinst        dc.b    5,9,'rts',10
  1845. pushsuffix    dc.b    7,',-(sp)',10
  1846. popprefix    dc.b    6,'(sp)+,'
  1847. commachar    dc.b    1,','
  1848. newlinechar    dc.b    1,10
  1849.  
  1850. key.define  dc.b  'define ',0
  1851. key.byte    dc.b  'byte ',0
  1852. key.word    dc.b  'word ',0
  1853. key.long    dc.b  'long ',0
  1854.  
  1855. mnem.move   dc.b  'move',0
  1856. mnem.lea    dc.b  'lea',0
  1857. mnem.cmp    dc.b  'cmp',0
  1858. mnem.add    dc.b  'add',0
  1859.         dc.b  'addq.l',0
  1860. mnem.sub    dc.b  'sub',0
  1861.         dc.b  'subq.l',0
  1862. mnem.mulu   dc.b  'mulu',0
  1863. mnem.divu   dc.b  'divu',0
  1864. mnem.and    dc.b  'and',0
  1865. mnem.or     dc.b  'or',0
  1866. mnem.lsl    dc.b  'lsl',0
  1867. mnem.lsr    dc.b  'lsr',0
  1868.  
  1869.     section  one   · to rationalize rts that web will put below here
  1870.  
  1871.  
  1872.  
  1873. 38. Note that equ'd symbols must not start with a cap, lest the equ
  1874. statement be interpreted as a procedure section name.
  1875.  
  1876. --EQU statements
  1877. sysBase      equ        4
  1878. ibufLen      equ       100
  1879. maxfsize      equ    80000
  1880. maxsects      equ      400
  1881. maxbracenest   equ     50
  1882. ( Character used for end-line comments. )
  1883. bullet.char      equ    183
  1884. ( Characters used to introduce comment sections. )
  1885. para.char      equ    182
  1886. section.char   equ    167
  1887. ( Alternate braces. )
  1888. leftg.char      equ    171
  1889. rightg.char      equ    187
  1890.  
  1891.  
  1892. 39.
  1893.  
  1894. --Define macros for assembler
  1895.  
  1896. lref  macro
  1897. _LVO\1      equ  -6*(\2+4)
  1898.        endm
  1899.  
  1900. call  macro
  1901.        jsr   _LVO\1(A6)
  1902.        endm
  1903.  
  1904. callex  macro
  1905.        push  =  a6
  1906.        a6.l  =  sysBase
  1907.        jsr   _LVO\1(A6)
  1908.        a6.l  =  pop
  1909.        endm
  1910.  
  1911. print macro
  1912.        a0  =    ^\1
  1913.        Display string         · 34
  1914.        endm
  1915.  
  1916. fprint macro
  1917.        a0  =    ^\1
  1918.        Put line to output file    · 35
  1919.        endm
  1920.  
  1921. bstr  macro
  1922. \1    dc.b  1$-*-1
  1923.        dc.b  '\2',10
  1924. 1$
  1925.        endm
  1926.  
  1927. is.it macro
  1928.        chr  ? #\1
  1929.        endm
  1930.  
  1931. 40. The following way of getting values for the _LVO symbols to reference
  1932. library routines is not standard, but it avoids having to link with
  1933. amiga.lib (which is slow) or keeping the standard include files around
  1934. (which are bulky).
  1935.  
  1936. --Define library references
  1937.  
  1938.     lref     AllocMem,29
  1939.     lref     FreeMem,31
  1940.     lref     OpenLibrary,88
  1941.  
  1942.     lref     Output,6
  1943.     lref     Input,5
  1944.     lref     Write,4
  1945.     lref     Read,3
  1946.     lref     Open,1
  1947.     lref     Close,2
  1948. ·    lref     IoErr,18  not used yet
  1949.  
  1950.  
  1951.