Subversion Repositories Kolibri OS

Rev

Blame | Last modification | View Log | Download | RSS feed

  1. ; $$$$$$$$$$$$$$$$$$$ ABAKIS $$$$$$$$$$$$$$$$$$$$$
  2. ; *************** STAR^2 SOFTWARE ****************
  3. ; ???????????????????? TEXT ??????????????????????
  4.  
  5. ; fast portable text operations
  6.  
  7. ; text.zero t       ; initialize, *t=0
  8. ; text.end t        ; return end address (*t=0)
  9. ; text.n t          ; get # characters
  10. ; text.copy a, b    ; standard copy with 0
  11. ; text.copy.n...    ; copy with maximum size
  12. ; text.attach a, b  ; attach b to a
  13. ; text.attach.c...  ; attach c/haracter
  14. ; text.compare a, b ; compare lexical. <0>
  15. ; text.equal a, b   ; equal? return 1/0
  16. ; text.search a, b  ; search for text. &/0
  17. ; text.find a, c    ; search for c. &/0
  18. ; text.find.r a, c  ; search for c in reverse
  19. ; text.count.c t, c ; count # of 'c's
  20. ; text.count.w t    ; count # of words: 'a b c'
  21. ; text.count.n t    ; count # of lines
  22. ; text.go t, n      ; advance to line #
  23. ; text.upper t      ; uppercase
  24. ; text.lower t      ; lowercase
  25. ; text.reverse t    ; reverse
  26. ; text.begins a, b  ; begins with b?
  27. ; text.ends a, b    ; ends with b?
  28. ; text.skip.0 t     ; skip '0's. return &
  29. ; text.shift.l t, n ; shift characters left
  30. ; text.shift.la...  ; shift left and assign
  31. ; text.expand t, n  ; expand; shift right at 0
  32. ; text.align t, n   ; align; prefix with '0's
  33.  
  34. ; x2t n, t ; convert number to text
  35. ; u2t n, t ; unsigned decimal
  36. ; h2t n, t ; hexadecimal
  37. ; b2t n, t ; binary
  38.  
  39. ; t2x t    ; convert text to number
  40. ; t2u t    ; unsigned decimal
  41. ; t2h t    ; hexadecimal
  42. ; t2b t    ; binary
  43.  
  44. ; print t, f, ... - a fast print formatted
  45. ; text to buffer
  46.  
  47. macro debug { callf _say, bug.t, bug.t }
  48.  
  49. RET equ ,0Dh,0Ah,
  50.  
  51. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  52.  
  53. ; text.zero t - initialize
  54.  
  55. macro text.zero t { . r0=t, *r0=0 }
  56.  
  57. ; text.end t - return end address: *p=0
  58.  
  59. function text.end, t
  60.   alias p=r0, c=r1
  61.   . p=t, c=1
  62.   while c, c=*p++, endw, p--
  63. endf
  64.  
  65. ; text.n t - get length, # characters
  66.  
  67. function text.n, t
  68.   alias p=r0, s=r1, c=r2
  69.   . p=t, s=p, c=1
  70.   while c, c=*p++, endw, p-s, p--
  71. endf
  72.  
  73. ; text.copy a, b - standard copy with
  74. ; 0 after. return advanced address
  75.  
  76. function text.copy, a, b
  77.   alias p=r0, s=r1, c=r2
  78.   . p=a, s=b, c=1
  79.   while c, c=*s++, *p++=c, endw, p--
  80. endf
  81.  
  82. ; text.copy.n a, b, n - copy with maximum
  83. ; size specified. return &
  84.  
  85. function text.copy.n, a, b, n
  86.   alias p=r0, s=r1, c=r2
  87.   . p=a, s=b
  88.   loop n, c=*s++, *p++=c
  89.     if c=0, break, end
  90.   endl, p--
  91. endf
  92.  
  93. ; text.attach a, b - attach b to a. return &
  94.  
  95. function text.attach, a, b
  96.   text.end a
  97.   text.copy r0, b
  98. endf
  99.  
  100. ; text.attach.c t, c - attach c/haracter.
  101. ; return &
  102.  
  103. function text.attach.c, t, c
  104.   alias p=r0, x=r1
  105.   text.end t
  106.   . x=c, *p++=x, *p=0
  107. endf
  108.  
  109. ; text.compare a, b - lexical comparison.
  110. ; return <0>
  111.  
  112. function text.compare, a, b
  113.   alias p=r0, s=r1, c=r2, d=r3
  114.   . p=a, s=b, c=d
  115.   while c=d, c=*p++, d=*s++
  116.     if c=0, break, end
  117.     if d=0, break, end
  118.   endw, p=c, p-d
  119. endf
  120.  
  121. ; text.equal a, b - equal? return 1/0
  122.  
  123. function text.equal, a, b
  124.   text.compare a, b
  125.   if false, return 1, end
  126. endf 0
  127.  
  128. ; text.find t, c - search for character:
  129. ; if t contains c. return &/0
  130.  
  131. function text.find, t, x
  132.   alias p=r0, c=r1, k=r2
  133.   . p=t, k=x
  134.   loop, c=*p
  135.     if c=0, return 0, end
  136.     if c=k, return p, end, p++
  137.   endl
  138. endf
  139.  
  140. ; text.count.c t, c - count # of c/haracters
  141.  
  142. function text.count.c, t, x
  143.   locals n
  144.   alias p=r0, c=r1, k=r2
  145.   . p=t, k=x, n=0, c=1
  146.   while c, c=*p++
  147.     if c=k, n++, end
  148.   endw
  149. endf n
  150.  
  151. ; text.count.w t - count # words 'a b c'
  152.  
  153. function text.count.w, t
  154.   try text.count.c t, ' '
  155.   . r0++
  156. endf
  157.  
  158. ; text.count.n t - count # lines
  159.  
  160. function text.count.n, t
  161.   try text.count.c t, 0Dh
  162.   . r0++
  163. endf
  164.  
  165. ; text.go t, n - advance to line #
  166.  
  167. function text.go, t, n
  168.   loop n
  169.     try t=text.find t, 0Dh
  170.     . t+2
  171.   endl
  172. endf t
  173.  
  174. ; text.upper t - convert to uppercase
  175.  
  176. function text.upper, t
  177.   alias p=r0, c=r1
  178.   . p=t
  179.   loop, c=*p
  180.     if c=0, return, end
  181.     if c>=97
  182.       if c<=122, c-32, *p=c, end
  183.     end, p++
  184.   endl
  185. endf
  186.  
  187. ; text.lower t - convert to lowercase
  188.  
  189. function text.lower, t
  190.   alias p=r0, c=r1
  191.   . p=t
  192.   loop, c=*p
  193.     if c=0, return, end
  194.     if c>=65
  195.       if c<=90, c+32, *p=c, end
  196.     end, p++
  197.   endl
  198. endf
  199.  
  200. ; text.reverse t - reverse text
  201.  
  202. function text.reverse, t
  203.   locals p
  204.   alias s=r0, e=r1, c=r2
  205.   get p=text.end t
  206.   . e=&(s-1), s=t
  207.   while s<e, c=*s, *s++=*e, *e--=c, endw
  208. endf p
  209.  
  210. ; text.begins a, b - a begins with b?
  211.  
  212. function text.begins, a, b
  213.   alias p=r0, q=r1, c=r2, d=r3
  214.   . p=a, q=b, d=c
  215.   while c=d, c=*p++, d=*q++
  216.     if c=0, break, end
  217.     if d=0, break, end
  218.   endw
  219.   if d<>0, return 0, end
  220. endf
  221.  
  222. ; text.ends a, b - a ends with b?
  223.  
  224. function text.ends, a, b
  225.   locals p
  226.   get p=text.end a
  227.   text.n b
  228.   . p-r0
  229.   text.equal p, b
  230. endf
  231.  
  232. ; text.search t, c - search for text:
  233. ; if a contains b. return &/0
  234.  
  235. function text.search, a, b
  236.   locals n, p
  237.   get n=text.n a
  238.   . p=a
  239.   loop n
  240.     text.begins p, b
  241.     if true, return p, end
  242.     . p++
  243.   endl
  244. endf 0
  245.  
  246. ; text.skip.0 a - skip 0s, return address or 0
  247.  
  248. function text.skip.0, a
  249.   alias p=r0, c=r1
  250.   . p=a, c='0'
  251.   while c='0', c=*p++, endw, p--
  252.   if c=0, return 0, end
  253. endf
  254.  
  255. ; shift all characters left
  256.  
  257. ; before:    'abc123'
  258. ; after <<3: '123'
  259.  
  260. function text.shift.l, t, n
  261.   alias p=r0, q=r1
  262.   . p=t, q=p, q+n
  263.   text.copy p, q
  264. endf
  265.  
  266. ; shift left and assign s to BITs
  267. ; copied out ('abc' in example above)
  268.  
  269. function text.shift.la, t, s, n
  270.   alias p=r0, q=r1
  271.   . p=t, q=p, q+n
  272.   text.copy.n s, t, n
  273.   text.shift.l t, n
  274. endf
  275.  
  276. ; expand; shift all characters right.
  277. ; example: 'abc123' becomes 'XXXabc123'
  278. ; after expand 3 where X is unknown
  279.  
  280. function text.expand, t, n
  281.   locals x
  282.   alias p=r0, q=r1, c=r2
  283.   get x=text.n t
  284.   . p+t, p--, q=p, p+n, *p=0
  285.   loop x, *p--=*q--, endl
  286. endf
  287.  
  288. ; prefix text with '0's or ensure maximum n.
  289. ; example: before: t='7FAB'
  290. ; text.align t, 8 ; after: t='00007FAB'
  291.  
  292. function text.align, t, n
  293.   locals tn
  294.   alias n1=r0, n2=r1,\
  295.    c=r1, p=r2
  296.   get tn=text.n t
  297.   . n2=n
  298.   if n1=n2, return, end    ; same size
  299.   if n1>n2, p=t, *(p+n1)=0 ; exceeds maximum
  300.     return                 ; end at t+n
  301.   end, n-n1                ; else, n2>n1
  302.   text.expand t, n         ; expand t
  303.   . p=t, c='0'             ; write '0's
  304.   loop n, *p++=c, endl
  305. endf
  306.  
  307. ; search text array ta for t using text.equal.
  308. ; return index or -1 (<0) if not found. ta is
  309. ; an array of text addresses (text[])
  310.  
  311. function text.array.equal, ta, t, n
  312.   locals i
  313.   alias p=r0, q=r1, x=r2
  314.   . i=0
  315.   loop n, x=i, q=ta, (u32) p=*(q+x*4)
  316.     text.equal p, t
  317.     if true, return i, end
  318.     . i++
  319.   endl
  320. endf -1
  321.  
  322. ;;;;;;;;;;;;;;;;;; CONVERSIONS ;;;;;;;;;;;;;;;;;;;
  323.  
  324. ; u2t n, t ; unsigned decimal
  325. ; h2t n, t ; hexadecimal
  326. ; b2t n, t ; binary
  327.  
  328. ; convert unsigned 32BIT integer to text
  329.  
  330. function u2t, n, t
  331.   alias i=r0, x=r1, y=r2, c=r3, p=r7
  332.   push c p
  333.   . i=n, p=t
  334.   if i=0, *p++='0', *p=0
  335.     . r0=p
  336.     go .r
  337.   end
  338.   . x=1999999Ah
  339.   while i, c=i, mul x, i=y, y=&(y+y*4)
  340.     . y+y, c-y, c+'0', *p++=c
  341.   endw, *p=0
  342.   text.reverse t
  343.   .r:
  344.   pop p c
  345. endf
  346.  
  347. ; convert 32BIT hexadecimal number to text
  348.  
  349. function h2t, n, t
  350.   alias p=r0, x=r1
  351.   . p=t
  352.   if n=0, *p++='0', *p=0
  353.     return
  354.   end
  355.   while n, x=n, x&15
  356.     . x=*(@HEX+x), *p++=x, n>>>4
  357.   endw, *p=0
  358.   text.reverse t
  359. endf
  360.  
  361. align @HEX: db '0123456789ABCDEF'
  362.  
  363. ; convert 32BIT binary number to text
  364.  
  365. function b2t, n, t
  366.   alias p=r0, x=r1
  367.   . p=t
  368.   if n=0, *p++='0', *p=0
  369.     return
  370.   end
  371.   while n, x=n, x&1, x+'0'
  372.     . *p++=x, n>>>1
  373.   endw, *p=0
  374.   text.reverse t
  375. endf
  376.  
  377. ; t2u t ; unsigned decimal
  378. ; t2h t ; hexadecimal
  379. ; t2b t ; binary
  380.  
  381. ; convert text to unsigned 32BIT integer
  382.  
  383. function t2u, t
  384.   alias p=r0, c=r1, n=r2, x=r3
  385.   try text.skip.0 t
  386.   . n=0
  387.   loop, c=*p++
  388.     if c=0, return n, end
  389.     . x=n, x<<2, n+x, n+n, n-'0', n+c
  390.   endl
  391. endf
  392.  
  393. ; convert text to 32BIT hexadecimal
  394.  
  395. function t2h, t
  396.   alias p=r0, c=r1, n=r2
  397.   try text.skip.0 t
  398.   . n=0
  399.   loop, c=*p++
  400.     if c=0, return n, end
  401.     if c<=39h, c-30h
  402.     else.if c>=61h, c-57h
  403.     else, c-37h, end, n<<4, n+c
  404.   endl
  405. endf
  406.  
  407. ; convert text to 32BIT binary
  408.  
  409. function t2b, t
  410.   alias p=r0, c=r1, n=r2
  411.   try text.skip.0 t
  412.   . n=0
  413.   loop, c=*p++
  414.     if c=0, return n, end
  415.     . n<<1, n-'0', n+c
  416.   endl
  417. endf
  418.  
  419. ; convert number to text with alignment.
  420. ; example: n2t.a 1234h, t, 8, h
  421. ; after: t='00001234'
  422.  
  423. macro n2t.a n, t, a, b {
  424.   b#2t n, t
  425.   text.align t, a
  426. }
  427.  
  428. macro u2t.a n, t, a { n2t.a n, t, a, u }
  429. macro h2t.a n, t, a { n2t.a n, t, a, h }
  430. macro b2t.a n, t, a { n2t.a n, t, a, b }
  431.  
  432. ;;;;;;;;;;;;;;;;;;;;; PRINT ;;;;;;;;;;;;;;;;;;;;;;
  433.  
  434. ; print t, f, ... - a fast print formatted
  435. ; text to buffer
  436.  
  437. ; %t %s - 'text'; "string"
  438. ; %c    - character
  439. ; %n %u - 32BIT decimal unsigned
  440. ; %b    - 32BIT binary
  441. ; %h    - 32BIT hexadecimal
  442. ; %r    - return. insert 0Dh, 0Ah
  443. ; %0    - 0/NULL
  444. ; %%    - %
  445.  
  446. macro print t, f, [p] {
  447.   common callv !print, t, f, p
  448. }
  449.  
  450. ; note: text.copy/reverse/etc and x2t
  451. ; must return end (*p=0) address for this
  452.  
  453. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  454.  
  455. align integer BASE='n'
  456.  
  457. ; !print(n, $t, $f, ...)
  458.  
  459. !print:
  460.  alias \               ; aliases...
  461.   s=r6, p=r7,\         ; source, destiny
  462.   c=r0, i=r1,\
  463.   va.s=r2,\            ; &va[...] start
  464.   va.n=[esp+4],\       ; # va
  465.   va=[r2+r1*4],\       ; current va[i]
  466.   n=[.a], z=[.z]       ; temporary
  467.  
  468.   . (u32) c=*(esp+8)   ; text buffer
  469.   . (u32) i=*(esp+12)  ; format
  470.   . va.s=&(esp+16)     ; &va[...] start
  471.  
  472.   push s p
  473.   . p=c, s=i, i=0      ; index=0
  474.  
  475.   .get: . c=*s++       ; get c/haracter
  476.   if c=0, go .e, end   ; end? *s=0
  477.   if c<>'%'            ; not %
  478.     .1: . *p++=c       ; copy c
  479.     go .get            ; next
  480.   end
  481.   . c=*s++             ; %x
  482.   if c='%', go .1      ; 2 %% = %
  483.   end
  484.  
  485.   if c='0', *p++=0     ; '0' = 0/NULL
  486.     go .get
  487.   end
  488.  
  489.   if c='r'             ; 'r' = return
  490.     .  *p++=\
  491.      0A0Dh, go .get
  492.   end
  493.  
  494.   if c='c'             ; %c
  495.     . c=va, i++        ; get va[i++]
  496.     . *p++=c
  497.     go .get
  498.   end
  499.  
  500.   if c='t'
  501.     .t:                ; %t %s - text
  502.     . z=va, i++        ; get va[i++]
  503.     pusha
  504.     get z=\
  505.      text.copy p, z    ; copy, save &
  506.     popa
  507.     . p=z              ; advance text buffer
  508.     go .get
  509.   end
  510.   if c='s', go .t
  511.   end
  512.  
  513.   if c='n', go .n, end
  514.   if c='u', go .n, end
  515.   if c='h', go .n, end
  516.   if c='b', go .n, end
  517.  
  518.   go .x                ; unrecognized
  519.  
  520.   .n:
  521.   . n=va, i++          ; get va[i]
  522.   pusha                ; copy/convert
  523.   if c='n'             ; number to text
  524.     u2t n, p           ; in selected base
  525.   else.if c='u'
  526.     u2t n, p
  527.   else.if c='h'
  528.     h2t n, p
  529.   else.if c='b'
  530.     b2t n, p
  531.   end
  532.   . z=r0               ; save end address
  533.   popa
  534.   . p=z                ; advance text buffer
  535.   go .get
  536.  
  537.   .x: . *p++='?'       ; else, unrecognized,
  538.   go .get              ; replace with '?'
  539.  
  540.   .0: . r0=0, go .q    ; error
  541.   .e: . r0=p, *r0=0    ; success. terminate
  542.   .q:                  ; return end
  543.   pop p s
  544.  ret                   ; callv adjusts esp after
  545.  
  546. endal                  ; end alias
  547.  
  548. .a dd 0
  549. .z dd 0
  550.  
  551. ;;;;;;;;;;;;;;; CHARACTER TABLES ;;;;;;;;;;;;;;;;;
  552.  
  553. ; ILT - insensitive lookup table. A-Z/a-z are
  554. ; the same. this increases processing speed by
  555. ; many times. example: if (tt[a]=tt[b]) instead
  556. ; of: if ((a>='a'&a<='z')&(b>='a'&b<='z')) |
  557. ; ((a>='A'&a<='Z')&(b>='Z'&b<='Z'))
  558.  
  559. ; TLT - type lookup table. each byte contains
  560. ; C.X BITs to determine its type fast in one
  561. ; comparison. example: if tt[c]&SYMBOL
  562.  
  563. align 8
  564.  
  565. ; byte XLT[128]=
  566.  
  567. ILT db \
  568.  00h,01h,02h,03h,04h,05h,06h,07h,08h,09h,0Ah,0Bh,0Ch,0Dh,0Eh,0Fh,\
  569.  10h,11h,12h,13h,14h,15h,16h,17h,18h,19h,1Ah,1Bh,1Ch,1Dh,1Eh,1Fh,\
  570.  20h,21h,22h,23h,24h,25h,26h,27h,28h,29h,2Ah,2Bh,2Ch,2Dh,2Eh,2Fh,\
  571.  30h,31h,32h,33h,34h,35h,36h,37h,38h,39h,3Ah,3Bh,3Ch,3Dh,3Eh,3Fh,\
  572.  40h,41h,42h,43h,44h,45h,46h,47h,48h,49h,4Ah,4Bh,4Ch,4Dh,4Eh,4Fh,\
  573.  50h,51h,52h,53h,54h,55h,56h,57h,58h,59h,5Ah,5Bh,5Ch,5Dh,5Eh,5Fh,\
  574.  60h,41h,42h,43h,44h,45h,46h,47h,48h,49h,4Ah,4Bh,4Ch,4Dh,4Eh,4Fh,\
  575.  50h,51h,52h,53h,54h,55h,56h,57h,58h,59h,5Ah,7Bh,7Ch,7Dh,7Eh,7Fh
  576.  
  577. TLT db \
  578.  00h,80h,80h,80h,80h,80h,80h,80h,80h,80h,40h,80h,80h,40h,80h,80h,\
  579.  80h,80h,80h,80h,80h,80h,80h,80h,80h,80h,80h,80h,80h,80h,80h,80h,\
  580.  20h,10h,04h,04h,10h,04h,04h,04h,04h,04h,04h,04h,04h,04h,10h,04h,\
  581.  01h,01h,01h,01h,01h,01h,01h,01h,01h,01h,04h,04h,04h,04h,04h,10h,\
  582.  10h,0Ah,0Ah,0Ah,0Ah,0Ah,0Ah,02h,0Ah,02h,02h,0Ah,02h,0Ah,02h,02h,\
  583.  02h,02h,02h,02h,02h,02h,02h,02h,02h,02h,02h,04h,04h,04h,04h,10h,\
  584.  04h,0Ah,0Ah,0Ah,0Ah,0Ah,0Ah,02h,0Ah,02h,02h,0Ah,02h,0Ah,02h,02h,\
  585.  02h,02h,02h,02h,02h,02h,02h,02h,02h,02h,02h,04h,04h,04h,04h,80h
  586.  
  587. ;            76543210b
  588. C.NULL     = 00000000b ; 0
  589. C.NUMBER   = 00000001b ; 0-9
  590. C.ALPHA    = 00000010b ; A-Z, a-z
  591. C.SYMBOL   = 00000100b ; all symbols except _.?!@$
  592. C.NUMERIC  = 00001000b ; A-F/a-f, h,b,k,m/H,B,K,M
  593. C.SYMBOLIC = 00010000b ; _.?!@$
  594. C.SPACE    = 00100000b ; ' ', '/t'
  595. C.RETURN   = 01000000b ; 0Dh, 0Ah
  596. C.IGNORE   = 10000000b ; extended: 1.XXXXXXXb
  597. C.KEYWORD  = 11111111b
  598.  
  599. C.DIGIT    = C.NUMBER or C.NUMERIC
  600. C.NAME     = C.ALPHA or C.NUMBER or C.SYMBOLIC
  601. C.SYMBOLS  = C.SYMBOL or C.SYMBOLIC
  602. C.ALPHAN   = C.ALPHA or C.NUMBER
  603. C.VISIBLE  = C.ALPHAN or C.SYMBOLS
  604. C.WHITE    = C.SPACE or C.RETURN
  605. C.BLANK    = C.WHITE or C.IGNORE
  606. C.END      = C.SYMBOL or C.WHITE
  607. C.0        = 0
  608.  
  609. function is.c, c, type
  610.   . r0=c, r0=*(TLT+r0), r0&type
  611. endf
  612.  
  613. macro if.is c, t {
  614.   is.c c, t
  615.   if true
  616. }
  617.  
  618. ;;;;;;;;;;;;;;;;;;; PARSE TEXT ;;;;;;;;;;;;;;;;;;;
  619.  
  620. ; skip while type and not 0
  621.  
  622. ; get p=text.skip.while p, C.WHITE
  623.  
  624. function text.skip.while, t, type
  625.   alias p=r0, q=r1, c=r2
  626.   . p=t, c=1
  627.   while c, c=*p++
  628.     . c=*(TLT+c), c&type
  629.   endw, p--
  630. endf
  631.  
  632. ; skip until type and while not 0.
  633. ; kind of tricky
  634.  
  635. ; get p=text.skip.until p, C.RETURN
  636.  
  637. function text.skip.until, t, type
  638.   alias p=r0, q=r1, c=r2
  639.   . p=t, c=0
  640.   while c=0, c=*p++
  641.     if c=0, return 0, end
  642.     . c=*(TLT+c), c&type
  643.   endw, p--
  644. endf
  645.  
  646. ; copy while type and not 0
  647.  
  648. ; get s=text.copy.while t, s, C.NAME
  649.  
  650. function text.copy.while, t, s, type
  651.   alias a=r7, b=r6, c=r1, x=r2
  652.   . a=t, b=s, c=*b
  653.   if c=0, return 0, end
  654.   while c, c=*b++, *a++=c
  655.     . x=*(TLT+c), x&type
  656.     if x=0, break, end
  657.   endw, a--, *a=0, b--
  658. endf b
  659.  
  660. ; copy until type and while not 0
  661.  
  662. ; get s=text.copy.until t, s, C.END
  663.  
  664. function text.copy.until, t, s, type
  665.   alias a=r7, b=r6, c=r1, x=r2
  666.   . a=t, b=s, c=*b
  667.   if c=0, return 0, end
  668.   while c, c=*b++, *a++=c
  669.     . x=*(TLT+c), x&type
  670.     if x, break, end
  671.   endw, a--, *a=0, b--
  672. endf b
  673.  
  674. ; copy until 'c'/x. if 0 or return is
  675. ; encountered before, return 0
  676.  
  677. function text.copy.until.c, t, s, x
  678.   alias a=r7, b=r6, c=r1
  679.   . a=t, b=s, c=*b
  680.   if c=0, return 0, end
  681.   while c, c=*b++, *a++=c
  682.     if c=x, break, end
  683.     if c=0, return 0, end
  684.     if c=0Dh, return 0, end
  685.   endw, a--, *a=0, b--
  686. endf b
  687.  
  688. ; skip whitespace and returns
  689. ; (if parse.skip.r?) or only spaces
  690. ; and tabs. return advanced &
  691.  
  692. align boolean parse.skip.r?=YES
  693.  
  694. function text.skip.ws, t
  695.   if parse.skip.r?
  696.     text.skip.while t, C.WHITE
  697.   else
  698.     text.skip.while t, C.SPACE
  699.   end
  700. endf
  701.  
  702. ; skip all whitespace, returns
  703. ; (if parse.skip.r?) and comments.
  704. ; return advanced &
  705.  
  706. function text.skip.x, t
  707.   locals q
  708.   alias p=r0, c=r1
  709.   . p=t, q=p
  710.   .get:
  711.   . p=q, c=*p
  712.   if c=0
  713.     return 0
  714.   end
  715.   if.is c, C.WHITE
  716.     try q=text.skip.ws q
  717.   end
  718.   . p=q, c=*p
  719.   if c=';'
  720.     try q=text.skip.until \
  721.      q, C.RETURN
  722.     . p+2
  723.     go .get
  724.   end
  725. endf q
  726.  
  727. function text.get, a, b
  728.   locals q
  729.   alias p=r0, c=r1
  730.   . q=b
  731.   try q=text.skip.x q
  732.   . c=*p
  733.   if c=0, return 0, end
  734.   if.is c, C.SYMBOL
  735.     . p=a, *p++=c, *p=0, q++
  736.     return q
  737.   end
  738.   text.copy.until a, q, C.END
  739. endf
  740.  
  741. ;;;;;;;;;;;;;;;; SOURCE, DESTINY ;;;;;;;;;;;;;;;;;
  742.  
  743. align
  744.  
  745. void source.p, destiny.p, token.p
  746. integer source.n, destiny.n, token.n
  747.  
  748. macro set.source p  { . source.p=p }
  749. macro set.destiny p { . destiny.p=p }
  750. macro set.token p   { . token.p=p }
  751.  
  752. function skip.while, type
  753.   get source.p=text.skip.while \
  754.    source.p, type
  755. endf
  756.  
  757. function skip.until, type
  758.   get source.p=text.skip.until \
  759.    source.p, type
  760. endf
  761.  
  762. function copy.while, type
  763.   get source.p=text.copy.while \
  764.    token.p, source.p, type
  765. endf
  766.  
  767. function copy.until, type
  768.   get source.p=text.copy.until \
  769.    token.p, source.p, type
  770. endf
  771.  
  772. function copy.until.c, c
  773.   get source.p=text.copy.until.c \
  774.    token.p, source.p, c
  775. endf
  776.  
  777. macro skip.space { skip.while C.SPACE }
  778. macro skip.white { skip.while C.WHITE }
  779. macro skip.line  { skip.until C.RETURN }
  780.  
  781. ; skip all whitespace, returns
  782. ; (if parse.skip.r?) and comments.
  783. ; return advanced &
  784.  
  785. function skip.x
  786.   alias p=r0, c=r1
  787.   .get:
  788.   . p=source.p, c=*p
  789.   if c=0, return 0, end
  790.   if.is c, C.WHITE
  791.     try skip.while C.WHITE
  792.   end
  793.   . p=source.p, c=*p
  794.   if c=';'
  795.     try skip.until C.RETURN
  796.     . source.p+2
  797.     go .get
  798.   end
  799.   . p=source.p
  800. endf p
  801.  
  802. ; get token
  803.  
  804. function get.token
  805.   alias p=r0, c=r1
  806.   try skip.x
  807.   . c=*p
  808.   if c=0, return 0, end
  809.   if.is c, C.SYMBOL
  810.     . p=token.p, *p++=c, *p++=0
  811.     . source.p++, p=source.p
  812.     if c='''', c=*p
  813.       if c='''', source.p++
  814.         return source.p
  815.       end
  816.       try copy.until.c ''''
  817.       . source.p++
  818.     end
  819.     . p=source.p
  820.     return
  821.   end
  822.   copy.until C.END
  823. endf
  824.  
  825. ; MOVE TO PARSE.INC...
  826.  
  827. ;;;;;;;;;;;;;;;;;;; NAME TABLE ;;;;;;;;;;;;;;;;;;;
  828.  
  829. ; name table:
  830.  
  831. ; 'ann',0, 'kim',0, 'sue',0
  832.  
  833. align 4
  834.  
  835. void name.table, name.table.p,\
  836.  name.table.n, name.table.size, name.table.end
  837.  
  838. ; allocate name.table
  839.  
  840. function create.name.table, size
  841.   try name.table=call !allocate, size
  842.   . name.table.p=r0, r0+size
  843.   . name.table.end=r0, name.table.n=0
  844.   . name.table.size=0
  845. endf 1
  846.  
  847. ; get name address by index
  848.  
  849. function get.name, i
  850.   locals p
  851.   . p=name.table
  852.   loop i
  853.     get p=text.end p
  854.     . p++
  855.   endl
  856. endf p
  857.  
  858. ; search for name. return index or -1
  859.  
  860. function search.name, t
  861.   locals i, p
  862.   . p=name.table, i=name.table.n
  863.   loop i
  864.     get.name i
  865.     text.equal p, r0
  866.     if true, return i, end
  867.   endl
  868. endf -1
  869.  
  870. ; attach 'text'. return address
  871.  
  872. function create.name, t
  873.   locals p, n
  874.   . p=name.table.p
  875.   text.n t
  876.   . r0++, n=r0, r0+p
  877.   if r0>=name.table.end
  878.     return 0
  879.   end
  880.   text.copy name.table.p, t
  881.   . r0=p, r0+n, name.table.p=r0
  882.   . name.table.n++, r0=n
  883.   . name.table.size+r0
  884. endf p
  885.  
  886. ; remove name at index
  887.  
  888. function remove.name, i
  889.   locals p, q, n, size
  890.   get p=get.name i
  891.   get n=text.n p
  892.   . i++
  893.   get q=get.name i
  894.   . r0=name.table.p, r0+name.table.size
  895.   . r0-p, size=r0, r0=n
  896.   . name.table.size-r0, name.table.p-r0
  897.   memory.copy p, q, size
  898.   . name.table.n--
  899. endf
  900.  
  901. ; get name at index
  902.  
  903. function copy.name, i, t
  904.   get.name i
  905.   text.copy t, r0
  906. endf
  907.  
  908. ; name structure: 16 bytes
  909.  
  910. virtual at 0
  911.   ?define:
  912.   .type dd 0  ; type: TTTT...
  913.   .value dd 0 ; name index
  914.   .name dd 0  ; value or index
  915.   .i dd 0     ; anything, align 16
  916.   .$=$
  917. END virtual
  918.  
  919. powers DEFINE.*, ALIVE, USED,\
  920.  D, ABLE, NUMERIC
  921.  
  922. ; .type =
  923.  
  924. ; TTTT.SSSS XXXXXXXX XXXXXXXX XXX.NR.DUA
  925. ;           23-16    15-8     7-0
  926.  
  927. ; T: type: number, define, constant, label,
  928. ; macro, register, instruction, variable
  929. ; S: data size
  930. ; P: parameter 1
  931. ; Q: parameter 2
  932. ; X: anything
  933. ; N: 1=numeric, 0=symbolic
  934. ; R: 1=redefinable, 0=not
  935. ; D: 1=defined, 0=not
  936. ; U: 1=used, 0=not
  937. ; A: 1=alive, 0=dead
  938.  
  939. ; name structures. last structure is
  940. ; defines.p+((defines.n-1)*48)
  941.  
  942. align 4
  943.  
  944. void defines.p     ; name structures
  945. void defines.end.p ; end allocation
  946. integer defines.n
  947.  
  948. ;;;;;;;;;;;;;;;;;;;;; ERRORS ;;;;;;;;;;;;;;;;;;;;;
  949.  
  950. ; MOVE TO ASSEMBLER.INC
  951.  
  952. text errors.ta[]=\
  953.  E.NONE     ='None',\
  954.  E.SYNTAX   ='Syntax',\
  955.  E.LOAD     ='Error loading',\
  956.  E.FILE     ='File I/O error',\
  957.  E.UNEXPECT ='Unexpected',\
  958.  E.CPU      ='Unsupported by CPU',\
  959.  E.ADDRESS  ='Address not aligned',\
  960.  E.OPERANDS ='Invalid operand/s',\
  961.  E.AMODE    ='Invalid addressing mode',\
  962.  E.SHIFT    ='Invalid shift #',\
  963.  E.NUMBER   ='Invalid number',\
  964.  E.NUMBER2  ='Number can''t be encoded',\
  965.  E.VALUE    ='Value exceeds size',\
  966.  E.ALIGN    ='Number must be aligned',\
  967.  E.POWER    ='# must be power of 2',\
  968.  E.REGISTER ='Register expected',\
  969.  E.EXPECTN  ='Number expected',\
  970.  E.EXPECTA  ='Name expected',\
  971.  E.INAME    ='Invalid name',\
  972.  E.NAME     ='Name too long',\
  973.  E.RESERVE  ='Reserved name',\
  974.  E.UNDEFINE ='Undefined',\
  975.  E.REDEFINE ='Redefinition',\
  976.  E.EXPECTT  ='Text expected',\
  977.  E.ENDT     ='Text has no end ''',\
  978.  E.COMMA    =', expected',\
  979.  E.END      ='end expected',\
  980.  E.MISMATCH ='Mismatched parenthesis'
  981.  
  982. ;;;;;;;;;;;;;;;;;;; KEYWORDS ;;;;;;;;;;;;;;;;;;;;;
  983.  
  984. ; MOVE TO ASSEMBLER.INC
  985.  
  986. text keywords.ta[]=\
  987.  K.ALIGN='align', K.BYTE='byte',\
  988.  K.D1='d1', K.D2='d2', K.D4='d4', K.D8='d8',\
  989.  K.DEFINE='define', K.DOUBLE='double',\
  990.  K.EQUATE='equate', K.FLOAT='float',\
  991.  K.FORMAT='format', K.INCLUDE='include',\
  992.  K.INJECT='inject', K.INTEGER='integer',\
  993.  K.MAIN='main', K.ORG='org',\
  994.  K.RESTORE='restore', K.TEXT='text',\
  995.  K.USE='use', K.VOID='void'
  996.  
  997. align 4
  998.  
  999. void keywords.ta.p=keywords.ta
  1000. integer keywords.n=keywords.ta.$
  1001.  
  1002. function is.keyword, t
  1003.   if keywords.n=0, return -1, end
  1004.   text.array.equal \
  1005.    keywords.ta.p, t, keywords.n
  1006. endf