0,0 → 1,1006 |
; $$$$$$$$$$$$$$$$$$$ ABAKIS $$$$$$$$$$$$$$$$$$$$$ |
; *************** STAR^2 SOFTWARE **************** |
; ???????????????????? TEXT ?????????????????????? |
|
; fast portable text operations |
|
; text.zero t ; initialize, *t=0 |
; text.end t ; return end address (*t=0) |
; text.n t ; get # characters |
; text.copy a, b ; standard copy with 0 |
; text.copy.n... ; copy with maximum size |
; text.attach a, b ; attach b to a |
; text.attach.c... ; attach c/haracter |
; text.compare a, b ; compare lexical. <0> |
; text.equal a, b ; equal? return 1/0 |
; text.search a, b ; search for text. &/0 |
; text.find a, c ; search for c. &/0 |
; text.find.r a, c ; search for c in reverse |
; text.count.c t, c ; count # of 'c's |
; text.count.w t ; count # of words: 'a b c' |
; text.count.n t ; count # of lines |
; text.go t, n ; advance to line # |
; text.upper t ; uppercase |
; text.lower t ; lowercase |
; text.reverse t ; reverse |
; text.begins a, b ; begins with b? |
; text.ends a, b ; ends with b? |
; text.skip.0 t ; skip '0's. return & |
; text.shift.l t, n ; shift characters left |
; text.shift.la... ; shift left and assign |
; text.expand t, n ; expand; shift right at 0 |
; text.align t, n ; align; prefix with '0's |
|
; x2t n, t ; convert number to text |
; u2t n, t ; unsigned decimal |
; h2t n, t ; hexadecimal |
; b2t n, t ; binary |
|
; t2x t ; convert text to number |
; t2u t ; unsigned decimal |
; t2h t ; hexadecimal |
; t2b t ; binary |
|
; print t, f, ... - a fast print formatted |
; text to buffer |
|
macro debug { callf _say, bug.t, bug.t } |
|
RET equ ,0Dh,0Ah, |
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
|
; text.zero t - initialize |
|
macro text.zero t { . r0=t, *r0=0 } |
|
; text.end t - return end address: *p=0 |
|
function text.end, t |
alias p=r0, c=r1 |
. p=t, c=1 |
while c, c=*p++, endw, p-- |
endf |
|
; text.n t - get length, # characters |
|
function text.n, t |
alias p=r0, s=r1, c=r2 |
. p=t, s=p, c=1 |
while c, c=*p++, endw, p-s, p-- |
endf |
|
; text.copy a, b - standard copy with |
; 0 after. return advanced address |
|
function text.copy, a, b |
alias p=r0, s=r1, c=r2 |
. p=a, s=b, c=1 |
while c, c=*s++, *p++=c, endw, p-- |
endf |
|
; text.copy.n a, b, n - copy with maximum |
; size specified. return & |
|
function text.copy.n, a, b, n |
alias p=r0, s=r1, c=r2 |
. p=a, s=b |
loop n, c=*s++, *p++=c |
if c=0, break, end |
endl, p-- |
endf |
|
; text.attach a, b - attach b to a. return & |
|
function text.attach, a, b |
text.end a |
text.copy r0, b |
endf |
|
; text.attach.c t, c - attach c/haracter. |
; return & |
|
function text.attach.c, t, c |
alias p=r0, x=r1 |
text.end t |
. x=c, *p++=x, *p=0 |
endf |
|
; text.compare a, b - lexical comparison. |
; return <0> |
|
function text.compare, a, b |
alias p=r0, s=r1, c=r2, d=r3 |
. p=a, s=b, c=d |
while c=d, c=*p++, d=*s++ |
if c=0, break, end |
if d=0, break, end |
endw, p=c, p-d |
endf |
|
; text.equal a, b - equal? return 1/0 |
|
function text.equal, a, b |
text.compare a, b |
if false, return 1, end |
endf 0 |
|
; text.find t, c - search for character: |
; if t contains c. return &/0 |
|
function text.find, t, x |
alias p=r0, c=r1, k=r2 |
. p=t, k=x |
loop, c=*p |
if c=0, return 0, end |
if c=k, return p, end, p++ |
endl |
endf |
|
; text.count.c t, c - count # of c/haracters |
|
function text.count.c, t, x |
locals n |
alias p=r0, c=r1, k=r2 |
. p=t, k=x, n=0, c=1 |
while c, c=*p++ |
if c=k, n++, end |
endw |
endf n |
|
; text.count.w t - count # words 'a b c' |
|
function text.count.w, t |
try text.count.c t, ' ' |
. r0++ |
endf |
|
; text.count.n t - count # lines |
|
function text.count.n, t |
try text.count.c t, 0Dh |
. r0++ |
endf |
|
; text.go t, n - advance to line # |
|
function text.go, t, n |
loop n |
try t=text.find t, 0Dh |
. t+2 |
endl |
endf t |
|
; text.upper t - convert to uppercase |
|
function text.upper, t |
alias p=r0, c=r1 |
. p=t |
loop, c=*p |
if c=0, return, end |
if c>=97 |
if c<=122, c-32, *p=c, end |
end, p++ |
endl |
endf |
|
; text.lower t - convert to lowercase |
|
function text.lower, t |
alias p=r0, c=r1 |
. p=t |
loop, c=*p |
if c=0, return, end |
if c>=65 |
if c<=90, c+32, *p=c, end |
end, p++ |
endl |
endf |
|
; text.reverse t - reverse text |
|
function text.reverse, t |
locals p |
alias s=r0, e=r1, c=r2 |
get p=text.end t |
. e=&(s-1), s=t |
while s<e, c=*s, *s++=*e, *e--=c, endw |
endf p |
|
; text.begins a, b - a begins with b? |
|
function text.begins, a, b |
alias p=r0, q=r1, c=r2, d=r3 |
. p=a, q=b, d=c |
while c=d, c=*p++, d=*q++ |
if c=0, break, end |
if d=0, break, end |
endw |
if d<>0, return 0, end |
endf |
|
; text.ends a, b - a ends with b? |
|
function text.ends, a, b |
locals p |
get p=text.end a |
text.n b |
. p-r0 |
text.equal p, b |
endf |
|
; text.search t, c - search for text: |
; if a contains b. return &/0 |
|
function text.search, a, b |
locals n, p |
get n=text.n a |
. p=a |
loop n |
text.begins p, b |
if true, return p, end |
. p++ |
endl |
endf 0 |
|
; text.skip.0 a - skip 0s, return address or 0 |
|
function text.skip.0, a |
alias p=r0, c=r1 |
. p=a, c='0' |
while c='0', c=*p++, endw, p-- |
if c=0, return 0, end |
endf |
|
; shift all characters left |
|
; before: 'abc123' |
; after <<3: '123' |
|
function text.shift.l, t, n |
alias p=r0, q=r1 |
. p=t, q=p, q+n |
text.copy p, q |
endf |
|
; shift left and assign s to BITs |
; copied out ('abc' in example above) |
|
function text.shift.la, t, s, n |
alias p=r0, q=r1 |
. p=t, q=p, q+n |
text.copy.n s, t, n |
text.shift.l t, n |
endf |
|
; expand; shift all characters right. |
; example: 'abc123' becomes 'XXXabc123' |
; after expand 3 where X is unknown |
|
function text.expand, t, n |
locals x |
alias p=r0, q=r1, c=r2 |
get x=text.n t |
. p+t, p--, q=p, p+n, *p=0 |
loop x, *p--=*q--, endl |
endf |
|
; prefix text with '0's or ensure maximum n. |
; example: before: t='7FAB' |
; text.align t, 8 ; after: t='00007FAB' |
|
function text.align, t, n |
locals tn |
alias n1=r0, n2=r1,\ |
c=r1, p=r2 |
get tn=text.n t |
. n2=n |
if n1=n2, return, end ; same size |
if n1>n2, p=t, *(p+n1)=0 ; exceeds maximum |
return ; end at t+n |
end, n-n1 ; else, n2>n1 |
text.expand t, n ; expand t |
. p=t, c='0' ; write '0's |
loop n, *p++=c, endl |
endf |
|
; search text array ta for t using text.equal. |
; return index or -1 (<0) if not found. ta is |
; an array of text addresses (text[]) |
|
function text.array.equal, ta, t, n |
locals i |
alias p=r0, q=r1, x=r2 |
. i=0 |
loop n, x=i, q=ta, (u32) p=*(q+x*4) |
text.equal p, t |
if true, return i, end |
. i++ |
endl |
endf -1 |
|
;;;;;;;;;;;;;;;;;; CONVERSIONS ;;;;;;;;;;;;;;;;;;; |
|
; u2t n, t ; unsigned decimal |
; h2t n, t ; hexadecimal |
; b2t n, t ; binary |
|
; convert unsigned 32BIT integer to text |
|
function u2t, n, t |
alias i=r0, x=r1, y=r2, c=r3, p=r7 |
push c p |
. i=n, p=t |
if i=0, *p++='0', *p=0 |
. r0=p |
go .r |
end |
. x=1999999Ah |
while i, c=i, mul x, i=y, y=&(y+y*4) |
. y+y, c-y, c+'0', *p++=c |
endw, *p=0 |
text.reverse t |
.r: |
pop p c |
endf |
|
; convert 32BIT hexadecimal number to text |
|
function h2t, n, t |
alias p=r0, x=r1 |
. p=t |
if n=0, *p++='0', *p=0 |
return |
end |
while n, x=n, x&15 |
. x=*(@HEX+x), *p++=x, n>>>4 |
endw, *p=0 |
text.reverse t |
endf |
|
align @HEX: db '0123456789ABCDEF' |
|
; convert 32BIT binary number to text |
|
function b2t, n, t |
alias p=r0, x=r1 |
. p=t |
if n=0, *p++='0', *p=0 |
return |
end |
while n, x=n, x&1, x+'0' |
. *p++=x, n>>>1 |
endw, *p=0 |
text.reverse t |
endf |
|
; t2u t ; unsigned decimal |
; t2h t ; hexadecimal |
; t2b t ; binary |
|
; convert text to unsigned 32BIT integer |
|
function t2u, t |
alias p=r0, c=r1, n=r2, x=r3 |
try text.skip.0 t |
. n=0 |
loop, c=*p++ |
if c=0, return n, end |
. x=n, x<<2, n+x, n+n, n-'0', n+c |
endl |
endf |
|
; convert text to 32BIT hexadecimal |
|
function t2h, t |
alias p=r0, c=r1, n=r2 |
try text.skip.0 t |
. n=0 |
loop, c=*p++ |
if c=0, return n, end |
if c<=39h, c-30h |
else.if c>=61h, c-57h |
else, c-37h, end, n<<4, n+c |
endl |
endf |
|
; convert text to 32BIT binary |
|
function t2b, t |
alias p=r0, c=r1, n=r2 |
try text.skip.0 t |
. n=0 |
loop, c=*p++ |
if c=0, return n, end |
. n<<1, n-'0', n+c |
endl |
endf |
|
; convert number to text with alignment. |
; example: n2t.a 1234h, t, 8, h |
; after: t='00001234' |
|
macro n2t.a n, t, a, b { |
b#2t n, t |
text.align t, a |
} |
|
macro u2t.a n, t, a { n2t.a n, t, a, u } |
macro h2t.a n, t, a { n2t.a n, t, a, h } |
macro b2t.a n, t, a { n2t.a n, t, a, b } |
|
;;;;;;;;;;;;;;;;;;;;; PRINT ;;;;;;;;;;;;;;;;;;;;;; |
|
; print t, f, ... - a fast print formatted |
; text to buffer |
|
; %t %s - 'text'; "string" |
; %c - character |
; %n %u - 32BIT decimal unsigned |
; %b - 32BIT binary |
; %h - 32BIT hexadecimal |
; %r - return. insert 0Dh, 0Ah |
; %0 - 0/NULL |
; %% - % |
|
macro print t, f, [p] { |
common callv !print, t, f, p |
} |
|
; note: text.copy/reverse/etc and x2t |
; must return end (*p=0) address for this |
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
|
align integer BASE='n' |
|
; !print(n, $t, $f, ...) |
|
!print: |
alias \ ; aliases... |
s=r6, p=r7,\ ; source, destiny |
c=r0, i=r1,\ |
va.s=r2,\ ; &va[...] start |
va.n=[esp+4],\ ; # va |
va=[r2+r1*4],\ ; current va[i] |
n=[.a], z=[.z] ; temporary |
|
. (u32) c=*(esp+8) ; text buffer |
. (u32) i=*(esp+12) ; format |
. va.s=&(esp+16) ; &va[...] start |
|
push s p |
. p=c, s=i, i=0 ; index=0 |
|
.get: . c=*s++ ; get c/haracter |
if c=0, go .e, end ; end? *s=0 |
if c<>'%' ; not % |
.1: . *p++=c ; copy c |
go .get ; next |
end |
. c=*s++ ; %x |
if c='%', go .1 ; 2 %% = % |
end |
|
if c='0', *p++=0 ; '0' = 0/NULL |
go .get |
end |
|
if c='r' ; 'r' = return |
. *p++=\ |
0A0Dh, go .get |
end |
|
if c='c' ; %c |
. c=va, i++ ; get va[i++] |
. *p++=c |
go .get |
end |
|
if c='t' |
.t: ; %t %s - text |
. z=va, i++ ; get va[i++] |
pusha |
get z=\ |
text.copy p, z ; copy, save & |
popa |
. p=z ; advance text buffer |
go .get |
end |
if c='s', go .t |
end |
|
if c='n', go .n, end |
if c='u', go .n, end |
if c='h', go .n, end |
if c='b', go .n, end |
|
go .x ; unrecognized |
|
.n: |
. n=va, i++ ; get va[i] |
pusha ; copy/convert |
if c='n' ; number to text |
u2t n, p ; in selected base |
else.if c='u' |
u2t n, p |
else.if c='h' |
h2t n, p |
else.if c='b' |
b2t n, p |
end |
. z=r0 ; save end address |
popa |
. p=z ; advance text buffer |
go .get |
|
.x: . *p++='?' ; else, unrecognized, |
go .get ; replace with '?' |
|
.0: . r0=0, go .q ; error |
.e: . r0=p, *r0=0 ; success. terminate |
.q: ; return end |
pop p s |
ret ; callv adjusts esp after |
|
endal ; end alias |
|
.a dd 0 |
.z dd 0 |
|
;;;;;;;;;;;;;;; CHARACTER TABLES ;;;;;;;;;;;;;;;;; |
|
; ILT - insensitive lookup table. A-Z/a-z are |
; the same. this increases processing speed by |
; many times. example: if (tt[a]=tt[b]) instead |
; of: if ((a>='a'&a<='z')&(b>='a'&b<='z')) | |
; ((a>='A'&a<='Z')&(b>='Z'&b<='Z')) |
|
; TLT - type lookup table. each byte contains |
; C.X BITs to determine its type fast in one |
; comparison. example: if tt[c]&SYMBOL |
|
align 8 |
|
; byte XLT[128]= |
|
ILT db \ |
00h,01h,02h,03h,04h,05h,06h,07h,08h,09h,0Ah,0Bh,0Ch,0Dh,0Eh,0Fh,\ |
10h,11h,12h,13h,14h,15h,16h,17h,18h,19h,1Ah,1Bh,1Ch,1Dh,1Eh,1Fh,\ |
20h,21h,22h,23h,24h,25h,26h,27h,28h,29h,2Ah,2Bh,2Ch,2Dh,2Eh,2Fh,\ |
30h,31h,32h,33h,34h,35h,36h,37h,38h,39h,3Ah,3Bh,3Ch,3Dh,3Eh,3Fh,\ |
40h,41h,42h,43h,44h,45h,46h,47h,48h,49h,4Ah,4Bh,4Ch,4Dh,4Eh,4Fh,\ |
50h,51h,52h,53h,54h,55h,56h,57h,58h,59h,5Ah,5Bh,5Ch,5Dh,5Eh,5Fh,\ |
60h,41h,42h,43h,44h,45h,46h,47h,48h,49h,4Ah,4Bh,4Ch,4Dh,4Eh,4Fh,\ |
50h,51h,52h,53h,54h,55h,56h,57h,58h,59h,5Ah,7Bh,7Ch,7Dh,7Eh,7Fh |
|
TLT db \ |
00h,80h,80h,80h,80h,80h,80h,80h,80h,80h,40h,80h,80h,40h,80h,80h,\ |
80h,80h,80h,80h,80h,80h,80h,80h,80h,80h,80h,80h,80h,80h,80h,80h,\ |
20h,10h,04h,04h,10h,04h,04h,04h,04h,04h,04h,04h,04h,04h,10h,04h,\ |
01h,01h,01h,01h,01h,01h,01h,01h,01h,01h,04h,04h,04h,04h,04h,10h,\ |
10h,0Ah,0Ah,0Ah,0Ah,0Ah,0Ah,02h,0Ah,02h,02h,0Ah,02h,0Ah,02h,02h,\ |
02h,02h,02h,02h,02h,02h,02h,02h,02h,02h,02h,04h,04h,04h,04h,10h,\ |
04h,0Ah,0Ah,0Ah,0Ah,0Ah,0Ah,02h,0Ah,02h,02h,0Ah,02h,0Ah,02h,02h,\ |
02h,02h,02h,02h,02h,02h,02h,02h,02h,02h,02h,04h,04h,04h,04h,80h |
|
; 76543210b |
C.NULL = 00000000b ; 0 |
C.NUMBER = 00000001b ; 0-9 |
C.ALPHA = 00000010b ; A-Z, a-z |
C.SYMBOL = 00000100b ; all symbols except _.?!@$ |
C.NUMERIC = 00001000b ; A-F/a-f, h,b,k,m/H,B,K,M |
C.SYMBOLIC = 00010000b ; _.?!@$ |
C.SPACE = 00100000b ; ' ', '/t' |
C.RETURN = 01000000b ; 0Dh, 0Ah |
C.IGNORE = 10000000b ; extended: 1.XXXXXXXb |
C.KEYWORD = 11111111b |
|
C.DIGIT = C.NUMBER or C.NUMERIC |
C.NAME = C.ALPHA or C.NUMBER or C.SYMBOLIC |
C.SYMBOLS = C.SYMBOL or C.SYMBOLIC |
C.ALPHAN = C.ALPHA or C.NUMBER |
C.VISIBLE = C.ALPHAN or C.SYMBOLS |
C.WHITE = C.SPACE or C.RETURN |
C.BLANK = C.WHITE or C.IGNORE |
C.END = C.SYMBOL or C.WHITE |
C.0 = 0 |
|
function is.c, c, type |
. r0=c, r0=*(TLT+r0), r0&type |
endf |
|
macro if.is c, t { |
is.c c, t |
if true |
} |
|
;;;;;;;;;;;;;;;;;;; PARSE TEXT ;;;;;;;;;;;;;;;;;;; |
|
; skip while type and not 0 |
|
; get p=text.skip.while p, C.WHITE |
|
function text.skip.while, t, type |
alias p=r0, q=r1, c=r2 |
. p=t, c=1 |
while c, c=*p++ |
. c=*(TLT+c), c&type |
endw, p-- |
endf |
|
; skip until type and while not 0. |
; kind of tricky |
|
; get p=text.skip.until p, C.RETURN |
|
function text.skip.until, t, type |
alias p=r0, q=r1, c=r2 |
. p=t, c=0 |
while c=0, c=*p++ |
if c=0, return 0, end |
. c=*(TLT+c), c&type |
endw, p-- |
endf |
|
; copy while type and not 0 |
|
; get s=text.copy.while t, s, C.NAME |
|
function text.copy.while, t, s, type |
alias a=r7, b=r6, c=r1, x=r2 |
. a=t, b=s, c=*b |
if c=0, return 0, end |
while c, c=*b++, *a++=c |
. x=*(TLT+c), x&type |
if x=0, break, end |
endw, a--, *a=0, b-- |
endf b |
|
; copy until type and while not 0 |
|
; get s=text.copy.until t, s, C.END |
|
function text.copy.until, t, s, type |
alias a=r7, b=r6, c=r1, x=r2 |
. a=t, b=s, c=*b |
if c=0, return 0, end |
while c, c=*b++, *a++=c |
. x=*(TLT+c), x&type |
if x, break, end |
endw, a--, *a=0, b-- |
endf b |
|
; copy until 'c'/x. if 0 or return is |
; encountered before, return 0 |
|
function text.copy.until.c, t, s, x |
alias a=r7, b=r6, c=r1 |
. a=t, b=s, c=*b |
if c=0, return 0, end |
while c, c=*b++, *a++=c |
if c=x, break, end |
if c=0, return 0, end |
if c=0Dh, return 0, end |
endw, a--, *a=0, b-- |
endf b |
|
; skip whitespace and returns |
; (if parse.skip.r?) or only spaces |
; and tabs. return advanced & |
|
align boolean parse.skip.r?=YES |
|
function text.skip.ws, t |
if parse.skip.r? |
text.skip.while t, C.WHITE |
else |
text.skip.while t, C.SPACE |
end |
endf |
|
; skip all whitespace, returns |
; (if parse.skip.r?) and comments. |
; return advanced & |
|
function text.skip.x, t |
locals q |
alias p=r0, c=r1 |
. p=t, q=p |
.get: |
. p=q, c=*p |
if c=0 |
return 0 |
end |
if.is c, C.WHITE |
try q=text.skip.ws q |
end |
. p=q, c=*p |
if c=';' |
try q=text.skip.until \ |
q, C.RETURN |
. p+2 |
go .get |
end |
endf q |
|
function text.get, a, b |
locals q |
alias p=r0, c=r1 |
. q=b |
try q=text.skip.x q |
. c=*p |
if c=0, return 0, end |
if.is c, C.SYMBOL |
. p=a, *p++=c, *p=0, q++ |
return q |
end |
text.copy.until a, q, C.END |
endf |
|
;;;;;;;;;;;;;;;; SOURCE, DESTINY ;;;;;;;;;;;;;;;;; |
|
align |
|
void source.p, destiny.p, token.p |
integer source.n, destiny.n, token.n |
|
macro set.source p { . source.p=p } |
macro set.destiny p { . destiny.p=p } |
macro set.token p { . token.p=p } |
|
function skip.while, type |
get source.p=text.skip.while \ |
source.p, type |
endf |
|
function skip.until, type |
get source.p=text.skip.until \ |
source.p, type |
endf |
|
function copy.while, type |
get source.p=text.copy.while \ |
token.p, source.p, type |
endf |
|
function copy.until, type |
get source.p=text.copy.until \ |
token.p, source.p, type |
endf |
|
function copy.until.c, c |
get source.p=text.copy.until.c \ |
token.p, source.p, c |
endf |
|
macro skip.space { skip.while C.SPACE } |
macro skip.white { skip.while C.WHITE } |
macro skip.line { skip.until C.RETURN } |
|
; skip all whitespace, returns |
; (if parse.skip.r?) and comments. |
; return advanced & |
|
function skip.x |
alias p=r0, c=r1 |
.get: |
. p=source.p, c=*p |
if c=0, return 0, end |
if.is c, C.WHITE |
try skip.while C.WHITE |
end |
. p=source.p, c=*p |
if c=';' |
try skip.until C.RETURN |
. source.p+2 |
go .get |
end |
. p=source.p |
endf p |
|
; get token |
|
function get.token |
alias p=r0, c=r1 |
try skip.x |
. c=*p |
if c=0, return 0, end |
if.is c, C.SYMBOL |
. p=token.p, *p++=c, *p++=0 |
. source.p++, p=source.p |
if c='''', c=*p |
if c='''', source.p++ |
return source.p |
end |
try copy.until.c '''' |
. source.p++ |
end |
. p=source.p |
return |
end |
copy.until C.END |
endf |
|
; MOVE TO PARSE.INC... |
|
;;;;;;;;;;;;;;;;;;; NAME TABLE ;;;;;;;;;;;;;;;;;;; |
|
; name table: |
|
; 'ann',0, 'kim',0, 'sue',0 |
|
align 4 |
|
void name.table, name.table.p,\ |
name.table.n, name.table.size, name.table.end |
|
; allocate name.table |
|
function create.name.table, size |
try name.table=call !allocate, size |
. name.table.p=r0, r0+size |
. name.table.end=r0, name.table.n=0 |
. name.table.size=0 |
endf 1 |
|
; get name address by index |
|
function get.name, i |
locals p |
. p=name.table |
loop i |
get p=text.end p |
. p++ |
endl |
endf p |
|
; search for name. return index or -1 |
|
function search.name, t |
locals i, p |
. p=name.table, i=name.table.n |
loop i |
get.name i |
text.equal p, r0 |
if true, return i, end |
endl |
endf -1 |
|
; attach 'text'. return address |
|
function create.name, t |
locals p, n |
. p=name.table.p |
text.n t |
. r0++, n=r0, r0+p |
if r0>=name.table.end |
return 0 |
end |
text.copy name.table.p, t |
. r0=p, r0+n, name.table.p=r0 |
. name.table.n++, r0=n |
. name.table.size+r0 |
endf p |
|
; remove name at index |
|
function remove.name, i |
locals p, q, n, size |
get p=get.name i |
get n=text.n p |
. i++ |
get q=get.name i |
. r0=name.table.p, r0+name.table.size |
. r0-p, size=r0, r0=n |
. name.table.size-r0, name.table.p-r0 |
memory.copy p, q, size |
. name.table.n-- |
endf |
|
; get name at index |
|
function copy.name, i, t |
get.name i |
text.copy t, r0 |
endf |
|
; name structure: 16 bytes |
|
virtual at 0 |
?define: |
.type dd 0 ; type: TTTT... |
.value dd 0 ; name index |
.name dd 0 ; value or index |
.i dd 0 ; anything, align 16 |
.$=$ |
END virtual |
|
powers DEFINE.*, ALIVE, USED,\ |
D, ABLE, NUMERIC |
|
; .type = |
|
; TTTT.SSSS XXXXXXXX XXXXXXXX XXX.NR.DUA |
; 23-16 15-8 7-0 |
|
; T: type: number, define, constant, label, |
; macro, register, instruction, variable |
; S: data size |
; P: parameter 1 |
; Q: parameter 2 |
; X: anything |
; N: 1=numeric, 0=symbolic |
; R: 1=redefinable, 0=not |
; D: 1=defined, 0=not |
; U: 1=used, 0=not |
; A: 1=alive, 0=dead |
|
; name structures. last structure is |
; defines.p+((defines.n-1)*48) |
|
align 4 |
|
void defines.p ; name structures |
void defines.end.p ; end allocation |
integer defines.n |
|
;;;;;;;;;;;;;;;;;;;;; ERRORS ;;;;;;;;;;;;;;;;;;;;; |
|
; MOVE TO ASSEMBLER.INC |
|
text errors.ta[]=\ |
E.NONE ='None',\ |
E.SYNTAX ='Syntax',\ |
E.LOAD ='Error loading',\ |
E.FILE ='File I/O error',\ |
E.UNEXPECT ='Unexpected',\ |
E.CPU ='Unsupported by CPU',\ |
E.ADDRESS ='Address not aligned',\ |
E.OPERANDS ='Invalid operand/s',\ |
E.AMODE ='Invalid addressing mode',\ |
E.SHIFT ='Invalid shift #',\ |
E.NUMBER ='Invalid number',\ |
E.NUMBER2 ='Number can''t be encoded',\ |
E.VALUE ='Value exceeds size',\ |
E.ALIGN ='Number must be aligned',\ |
E.POWER ='# must be power of 2',\ |
E.REGISTER ='Register expected',\ |
E.EXPECTN ='Number expected',\ |
E.EXPECTA ='Name expected',\ |
E.INAME ='Invalid name',\ |
E.NAME ='Name too long',\ |
E.RESERVE ='Reserved name',\ |
E.UNDEFINE ='Undefined',\ |
E.REDEFINE ='Redefinition',\ |
E.EXPECTT ='Text expected',\ |
E.ENDT ='Text has no end ''',\ |
E.COMMA =', expected',\ |
E.END ='end expected',\ |
E.MISMATCH ='Mismatched parenthesis' |
|
;;;;;;;;;;;;;;;;;;; KEYWORDS ;;;;;;;;;;;;;;;;;;;;; |
|
; MOVE TO ASSEMBLER.INC |
|
text keywords.ta[]=\ |
K.ALIGN='align', K.BYTE='byte',\ |
K.D1='d1', K.D2='d2', K.D4='d4', K.D8='d8',\ |
K.DEFINE='define', K.DOUBLE='double',\ |
K.EQUATE='equate', K.FLOAT='float',\ |
K.FORMAT='format', K.INCLUDE='include',\ |
K.INJECT='inject', K.INTEGER='integer',\ |
K.MAIN='main', K.ORG='org',\ |
K.RESTORE='restore', K.TEXT='text',\ |
K.USE='use', K.VOID='void' |
|
align 4 |
|
void keywords.ta.p=keywords.ta |
integer keywords.n=keywords.ta.$ |
|
function is.keyword, t |
if keywords.n=0, return -1, end |
text.array.equal \ |
keywords.ta.p, t, keywords.n |
endf |