Subversion Repositories Kolibri OS

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
5305 codemaster 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
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