Subversion Repositories Kolibri OS

Rev

Rev 8097 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
7983 leency 1
(*
7597 akron1 2
    BSD 2-Clause License
3
 
8859 leency 4
    Copyright (c) 2018-2021, Anton Krotov
7597 akron1 5
    All rights reserved.
6
*)
7
 
8
MODULE ARITH;
9
 
8859 leency 10
IMPORT STRINGS, UTILS, LISTS;
7597 akron1 11
 
12
 
13
CONST
14
 
15
    tINTEGER* = 1;  tREAL* = 2;  tSET*    = 3;
16
    tBOOLEAN* = 4;  tCHAR* = 5;  tWCHAR*  = 6;
17
    tSTRING*  = 7;
18
 
8097 maxcodehac 19
    opEQ* = 0; opNE* = 1; opLT* = 2; opLE* = 3; opGT* = 4; opGE* = 5;
20
    opIN* = 6; opIS* = 7;
7597 akron1 21
 
8097 maxcodehac 22
 
7597 akron1 23
TYPE
24
 
25
    VALUE* = RECORD
26
 
27
        typ*:      INTEGER;
28
 
29
        int:       INTEGER;
30
        float:     REAL;
31
        set:       SET;
32
        bool:      BOOLEAN;
33
 
8859 leency 34
        string*:   LISTS.ITEM
7597 akron1 35
 
36
    END;
37
 
38
 
39
VAR
40
 
41
    digit: ARRAY 256 OF INTEGER;
42
 
43
 
44
PROCEDURE Int* (v: VALUE): INTEGER;
45
VAR
46
    res: INTEGER;
47
 
48
BEGIN
49
 
7696 akron1 50
    CASE v.typ OF
51
    |tINTEGER, tCHAR, tWCHAR:
7597 akron1 52
        res := v.int
7696 akron1 53
    |tSET:
7693 akron1 54
        res := UTILS.Long(ORD(v.set))
7696 akron1 55
    |tBOOLEAN:
7597 akron1 56
        res := ORD(v.bool)
57
    END
58
 
59
    RETURN res
60
END Int;
61
 
62
 
63
PROCEDURE getBool* (v: VALUE): BOOLEAN;
64
BEGIN
65
    ASSERT(v.typ = tBOOLEAN);
66
 
67
    RETURN v.bool
68
END getBool;
69
 
70
 
71
PROCEDURE Float* (v: VALUE): REAL;
72
BEGIN
73
    ASSERT(v.typ = tREAL);
74
 
75
    RETURN v.float
76
END Float;
77
 
78
 
7983 leency 79
PROCEDURE range* (i: VALUE; a, b: INTEGER): BOOLEAN;
80
    RETURN (a <= i.int) & (i.int <= b)
81
END range;
82
 
83
 
7597 akron1 84
PROCEDURE check* (v: VALUE): BOOLEAN;
85
VAR
7696 akron1 86
    res: BOOLEAN;
7597 akron1 87
 
88
BEGIN
7696 akron1 89
    CASE v.typ OF
7983 leency 90
    |tINTEGER: res := range(v, UTILS.target.minInt, UTILS.target.maxInt)
91
    |tCHAR:    res := range(v, 0, 255)
92
    |tWCHAR:   res := range(v, 0, 65535)
7696 akron1 93
    |tREAL:    res := (-UTILS.target.maxReal <= v.float) & (v.float <= UTILS.target.maxReal)
7597 akron1 94
    END
95
 
7696 akron1 96
    RETURN res
7597 akron1 97
END check;
98
 
99
 
100
PROCEDURE isZero* (v: VALUE): BOOLEAN;
101
VAR
102
    res: BOOLEAN;
7696 akron1 103
 
7597 akron1 104
BEGIN
7696 akron1 105
    CASE v.typ OF
106
    |tINTEGER: res := v.int = 0
107
    |tREAL:    res := v.float = 0.0
7597 akron1 108
    END
109
 
110
    RETURN res
111
END isZero;
112
 
113
 
114
PROCEDURE iconv* (s: ARRAY OF CHAR; VAR v: VALUE; VAR error: INTEGER);
115
VAR
116
    value: INTEGER;
117
    i:     INTEGER;
118
    d:     INTEGER;
119
 
120
BEGIN
121
    error := 0;
122
    value := 0;
123
 
124
    i := 0;
125
    WHILE STRINGS.digit(s[i]) & (error = 0) DO
126
        d := digit[ORD(s[i])];
127
        IF value <= (UTILS.maxint - d) DIV 10 THEN
128
            value := value * 10 + d;
129
            INC(i)
130
        ELSE
131
            error := 1
132
        END
133
    END;
134
 
135
    IF error = 0 THEN
136
        v.int := value;
137
        v.typ := tINTEGER;
138
        IF ~check(v) THEN
139
            error := 1
140
        END
141
    END
142
 
143
END iconv;
144
 
145
 
146
PROCEDURE hconv* (s: ARRAY OF CHAR; VAR v: VALUE; VAR error: INTEGER);
147
VAR
148
    value: INTEGER;
149
    i:     INTEGER;
150
    n:     INTEGER;
151
    d:     INTEGER;
152
 
153
BEGIN
154
    ASSERT(STRINGS.digit(s[0]));
155
 
156
    error := 0;
157
    value := 0;
158
 
159
    n := -1;
160
    i := 0;
8859 leency 161
    WHILE (s[i] # "H") & (s[i] # "X") & (s[i] # "h") & (s[i] # "x") & (error = 0) DO
7597 akron1 162
 
163
        d := digit[ORD(s[i])];
164
        IF (n = -1) & (d # 0) THEN
165
            n := i
166
        END;
167
 
7693 akron1 168
        IF (n # -1) & (i - n + 1 > UTILS.target.maxHex) THEN
7597 akron1 169
            error := 2
170
        ELSE
171
            value := value * 16 + d;
172
            INC(i)
173
        END
174
 
175
    END;
176
 
7693 akron1 177
    value := UTILS.Long(value);
7597 akron1 178
 
8859 leency 179
    IF ((s[i] = "X") OR (s[i] = "x")) & (n # -1) & (i - n > 4) THEN
7597 akron1 180
        error := 3
181
    END;
182
 
183
    IF error = 0 THEN
184
        v.int := value;
8859 leency 185
        IF (s[i] = "X") OR (s[i] = "x") THEN
7597 akron1 186
            v.typ := tCHAR;
187
            IF ~check(v) THEN
188
                v.typ := tWCHAR;
189
                IF ~check(v) THEN
190
                    error := 3
191
                END
192
            END
193
        ELSE
194
            v.typ := tINTEGER;
195
            IF ~check(v) THEN
196
                error := 2
197
            END
198
        END
199
    END
200
 
201
END hconv;
202
 
203
 
204
PROCEDURE opFloat2 (VAR a: REAL; b: REAL; op: CHAR): BOOLEAN;
205
BEGIN
206
    CASE op OF
7983 leency 207
    |"+": a := a + b
208
    |"-": a := a - b
209
    |"*": a := a * b
210
    |"/": a := a / b
7597 akron1 211
    END
212
 
7983 leency 213
    RETURN (-UTILS.maxreal <= a) & (a <= UTILS.maxreal) (* +inf > UTILS.maxreal *)
7597 akron1 214
END opFloat2;
215
 
216
 
217
PROCEDURE fconv* (s: ARRAY OF CHAR; VAR v: VALUE; VAR error: INTEGER);
218
VAR
219
    value:    REAL;
8859 leency 220
    frac:     REAL;
7597 akron1 221
    exp10:    REAL;
222
    i, n, d:  INTEGER;
223
    minus:    BOOLEAN;
224
 
225
BEGIN
226
    error := 0;
227
    value := 0.0;
8859 leency 228
    frac  := 0.0;
229
    exp10 := 1.0;
7597 akron1 230
    minus := FALSE;
231
    n := 0;
232
 
233
    i := 0;
234
    WHILE (error = 0) & STRINGS.digit(s[i]) DO
235
        IF opFloat2(value, 10.0, "*") & opFloat2(value, FLT(digit[ORD(s[i])]), "+") THEN
236
            INC(i)
237
        ELSE
238
            error := 4
239
        END
240
    END;
241
 
242
    INC(i);
243
 
244
    WHILE (error = 0) & STRINGS.digit(s[i]) DO
8859 leency 245
        IF opFloat2(frac, 10.0, "*") & opFloat2(frac, FLT(digit[ORD(s[i])]), "+") THEN
246
            exp10 := exp10 * 10.0;
7597 akron1 247
            INC(i)
248
        ELSE
249
            error := 4
250
        END
251
    END;
252
 
8859 leency 253
    IF ~opFloat2(value, frac / exp10, "+") THEN
254
        error := 4
255
    END;
256
 
257
    IF (s[i] = "E") OR (s[i] = "e") THEN
7597 akron1 258
        INC(i)
259
    END;
260
 
261
    IF (s[i] = "-") OR (s[i] = "+") THEN
262
        minus := s[i] = "-";
263
        INC(i)
264
    END;
265
 
266
    WHILE (error = 0) & STRINGS.digit(s[i]) DO
267
        d := digit[ORD(s[i])];
268
        IF n <= (UTILS.maxint - d) DIV 10 THEN
269
            n := n * 10 + d;
270
            INC(i)
271
        ELSE
272
            error := 5
273
        END
274
    END;
275
 
276
    exp10 := 1.0;
277
    WHILE (error = 0) & (n > 0) DO
278
        IF opFloat2(exp10, 10.0, "*") THEN
279
            DEC(n)
280
        ELSE
281
            error := 4
282
        END
283
    END;
284
 
285
    IF error = 0 THEN
286
        IF minus THEN
287
            IF ~opFloat2(value, exp10, "/") THEN
288
                error := 4
289
            END
290
        ELSE
291
            IF ~opFloat2(value, exp10, "*") THEN
292
                error := 4
293
            END
294
        END
295
    END;
296
 
297
    IF error = 0 THEN
298
        v.float := value;
299
        v.typ := tREAL;
300
        IF ~check(v) THEN
301
            error := 4
302
        END
303
    END
304
 
305
END fconv;
306
 
307
 
308
PROCEDURE setChar* (VAR v: VALUE; ord: INTEGER);
309
BEGIN
310
    v.typ := tCHAR;
311
    v.int := ord
312
END setChar;
313
 
314
 
315
PROCEDURE setWChar* (VAR v: VALUE; ord: INTEGER);
316
BEGIN
317
    v.typ := tWCHAR;
318
    v.int := ord
319
END setWChar;
320
 
321
 
322
PROCEDURE addInt (VAR a: INTEGER; b: INTEGER): BOOLEAN;
323
VAR
324
    error: BOOLEAN;
325
 
326
BEGIN
327
    IF (a > 0) & (b > 0) THEN
328
        error := a > UTILS.maxint - b
329
    ELSIF (a < 0) & (b < 0) THEN
330
        error := a < UTILS.minint - b
331
    ELSE
332
        error := FALSE
333
    END;
334
 
335
    IF ~error THEN
336
        a := a + b
337
    ELSE
338
        a := 0
339
    END
340
 
341
    RETURN ~error
342
END addInt;
343
 
344
 
345
PROCEDURE subInt (VAR a: INTEGER; b: INTEGER): BOOLEAN;
346
VAR
347
    error: BOOLEAN;
348
 
349
BEGIN
350
    IF (a > 0) & (b < 0) THEN
351
        error := a > UTILS.maxint + b
352
    ELSIF (a < 0) & (b > 0) THEN
353
        error := a < UTILS.minint + b
354
    ELSIF (a = 0) & (b < 0) THEN
355
        error := b = UTILS.minint
356
    ELSE
357
        error := FALSE
358
    END;
359
 
360
    IF ~error THEN
361
        a := a - b
362
    ELSE
363
        a := 0
364
    END
365
 
366
    RETURN ~error
367
END subInt;
368
 
369
 
370
PROCEDURE lg2 (x: INTEGER): INTEGER;
371
VAR
372
    n: INTEGER;
373
 
374
BEGIN
375
    ASSERT(x > 0);
376
 
7983 leency 377
    n := UTILS.Log2(x);
378
    IF n = -1 THEN
7597 akron1 379
        n := 255
380
    END
381
 
382
    RETURN n
383
END lg2;
384
 
385
 
386
PROCEDURE mulInt* (VAR a: INTEGER; b: INTEGER): BOOLEAN;
387
VAR
388
    error:    BOOLEAN;
389
    min, max: INTEGER;
390
 
391
BEGIN
392
    min := UTILS.minint;
393
    max := UTILS.maxint;
394
 
395
    IF ((a > 1) & (b > 1)) OR ((a < 0) & (b < 0)) THEN
396
        error := (a = min) OR (b = min) OR (ABS(a) > max DIV ABS(b))
397
 
398
    ELSIF ((a > 1) & (b < 0)) OR ((a < 0) & (b > 1)) THEN
399
        error := (a = min) OR (b = min);
400
        IF ~error THEN
401
            IF lg2(ABS(a)) + lg2(ABS(b)) >= UTILS.bit_depth THEN
402
                error := ABS(a) > max DIV ABS(b)
403
            END
404
        END
405
 
406
    ELSE
407
        error := FALSE
408
    END;
409
 
410
    IF ~error THEN
411
        a := a * b
412
    ELSE
413
        a := 0
414
    END
415
 
416
    RETURN ~error
417
END mulInt;
418
 
419
 
420
PROCEDURE _ASR (x, n: INTEGER): INTEGER;
7693 akron1 421
    RETURN ASR(UTILS.Long(x), n)
7597 akron1 422
END _ASR;
423
 
424
 
425
PROCEDURE _LSR (x, n: INTEGER): INTEGER;
7693 akron1 426
    RETURN UTILS.Long(LSR(UTILS.Short(x), n))
7597 akron1 427
END _LSR;
428
 
429
 
430
PROCEDURE _LSL (x, n: INTEGER): INTEGER;
7693 akron1 431
    RETURN UTILS.Long(LSL(x, n))
7597 akron1 432
END _LSL;
433
 
434
 
435
PROCEDURE _ROR1_32 (x: INTEGER): INTEGER;
436
BEGIN
7693 akron1 437
    x := UTILS.Short(x);
7597 akron1 438
    x := ORD(BITS(LSR(x, 1)) + BITS(LSL(x, 31)))
7693 akron1 439
    RETURN UTILS.Long(x)
7597 akron1 440
END _ROR1_32;
441
 
442
 
7693 akron1 443
PROCEDURE _ROR1_16 (x: INTEGER): INTEGER;
444
BEGIN
445
    x := x MOD 65536;
446
    x := ORD(BITS(LSR(x, 1)) + BITS(LSL(x, 15)))
447
    RETURN UTILS.Long(x)
448
END _ROR1_16;
449
 
450
 
7597 akron1 451
PROCEDURE _ROR (x, n: INTEGER): INTEGER;
452
BEGIN
7693 akron1 453
 
454
    CASE UTILS.bit_diff OF
455
    |0: x := ROR(x, n)
456
    |16, 48:
457
        n := n MOD 16;
458
        WHILE n > 0 DO
459
            x := _ROR1_16(x);
460
            DEC(n)
461
        END
462
    |32:
7597 akron1 463
        n := n MOD 32;
464
        WHILE n > 0 DO
465
            x := _ROR1_32(x);
466
            DEC(n)
467
        END
468
    END
469
 
470
    RETURN x
471
END _ROR;
472
 
473
 
474
PROCEDURE opInt* (VAR a: VALUE; b: VALUE; op: CHAR): BOOLEAN;
475
VAR
476
    success: BOOLEAN;
477
 
478
BEGIN
479
    success := TRUE;
480
 
481
    CASE op OF
482
    |"+": success := addInt(a.int, b.int)
483
    |"-": success := subInt(a.int, b.int)
484
    |"*": success := mulInt(a.int, b.int)
485
    |"/": success := FALSE
7983 leency 486
    |"D": a.int := a.int DIV b.int
7597 akron1 487
    |"M": a.int := a.int MOD b.int
488
    |"L": a.int := _LSL(a.int, b.int)
489
    |"A": a.int := _ASR(a.int, b.int)
490
    |"O": a.int := _ROR(a.int, b.int)
491
    |"R": a.int := _LSR(a.int, b.int)
492
    |"m": a.int := MIN(a.int, b.int)
493
    |"x": a.int := MAX(a.int, b.int)
494
    END;
495
    a.typ := tINTEGER
496
 
497
    RETURN success & check(a)
498
END opInt;
499
 
500
 
501
PROCEDURE charToStr* (c: VALUE; VAR s: ARRAY OF CHAR);
502
BEGIN
503
    s[0] := CHR(c.int);
504
    s[1] := 0X
505
END charToStr;
506
 
507
 
508
PROCEDURE opSet* (VAR a: VALUE; b: VALUE; op: CHAR);
509
BEGIN
510
    CASE op OF
511
    |"+": a.set := a.set + b.set
512
    |"-": a.set := a.set - b.set
513
    |"*": a.set := a.set * b.set
514
    |"/": a.set := a.set / b.set
515
    END;
516
    a.typ := tSET
517
END opSet;
518
 
519
 
520
PROCEDURE opFloat* (VAR a: VALUE; b: VALUE; op: CHAR): BOOLEAN;
521
BEGIN
522
    a.typ := tREAL
523
    RETURN opFloat2(a.float, b.float, op) & check(a)
524
END opFloat;
525
 
526
 
527
PROCEDURE ord* (VAR v: VALUE);
528
BEGIN
529
    CASE v.typ OF
530
    |tCHAR, tWCHAR:
531
    |tBOOLEAN: v.int := ORD(v.bool)
7693 akron1 532
    |tSET:     v.int := UTILS.Long(ORD(v.set))
7597 akron1 533
    END;
534
    v.typ := tINTEGER
535
END ord;
536
 
537
 
538
PROCEDURE odd* (VAR v: VALUE);
539
BEGIN
540
    v.typ := tBOOLEAN;
541
    v.bool := ODD(v.int)
542
END odd;
543
 
544
 
545
PROCEDURE bits* (VAR v: VALUE);
546
BEGIN
547
    v.typ := tSET;
548
    v.set := BITS(v.int)
549
END bits;
550
 
551
 
552
PROCEDURE abs* (VAR v: VALUE): BOOLEAN;
553
VAR
554
    res: BOOLEAN;
555
 
556
BEGIN
7693 akron1 557
    res := FALSE;
7597 akron1 558
 
559
    CASE v.typ OF
560
    |tREAL:
561
        v.float := ABS(v.float);
562
        res := TRUE
563
    |tINTEGER:
564
        IF v.int # UTILS.minint THEN
565
            v.int := ABS(v.int);
566
            res := TRUE
567
        END
7693 akron1 568
    END
569
 
7597 akron1 570
    RETURN res
571
END abs;
572
 
573
 
574
PROCEDURE floor* (VAR v: VALUE): BOOLEAN;
575
VAR
576
    res: BOOLEAN;
577
 
578
BEGIN
579
    v.typ := tINTEGER;
580
    res := (FLT(UTILS.minint) <= v.float) & (v.float <= FLT(UTILS.maxint));
581
    IF res THEN
582
        v.int := FLOOR(v.float)
583
    END
584
 
585
    RETURN res
586
END floor;
587
 
588
 
589
PROCEDURE flt* (VAR v: VALUE);
590
BEGIN
591
    v.typ := tREAL;
592
    v.float := FLT(v.int)
593
END flt;
594
 
595
 
596
PROCEDURE neg* (VAR v: VALUE): BOOLEAN;
597
VAR
598
    z: VALUE;
599
    res: BOOLEAN;
600
 
601
BEGIN
602
    res := TRUE;
603
 
604
    z.typ := tINTEGER;
605
    z.int := 0;
606
 
607
    CASE v.typ OF
608
    |tREAL:     v.float := -v.float
609
    |tSET:      v.set := -v.set
610
    |tINTEGER:  res := opInt(z, v, "-"); v := z
611
    |tBOOLEAN:  v.bool := ~v.bool
612
    END
613
 
614
    RETURN res
615
END neg;
616
 
617
 
618
PROCEDURE setbool* (VAR v: VALUE; b: BOOLEAN);
619
BEGIN
620
    v.bool := b;
621
    v.typ := tBOOLEAN
622
END setbool;
623
 
624
 
625
PROCEDURE opBoolean* (VAR a: VALUE; b: VALUE; op: CHAR);
626
BEGIN
627
    CASE op OF
628
    |"&": a.bool := a.bool & b.bool
629
    |"|": a.bool := a.bool OR b.bool
630
    END;
631
    a.typ := tBOOLEAN
632
END opBoolean;
633
 
634
 
635
PROCEDURE less (v, v2: VALUE; VAR error: INTEGER): BOOLEAN;
636
VAR
637
    res: BOOLEAN;
638
 
639
BEGIN
640
    res := FALSE;
641
 
642
    IF (v.typ = v2.typ) OR (v.typ IN {tCHAR, tWCHAR}) & (v2.typ IN {tCHAR, tWCHAR}) THEN
643
        CASE v.typ OF
644
        |tINTEGER,
645
         tWCHAR,
646
         tCHAR:     res := v.int < v2.int
647
        |tREAL:     res := v.float < v2.float
648
        |tBOOLEAN,
649
         tSET:      error := 1
650
        END
651
    ELSE
652
        error := 1
653
    END
654
 
655
    RETURN res
656
END less;
657
 
658
 
659
PROCEDURE equal (v, v2: VALUE; VAR error: INTEGER): BOOLEAN;
660
VAR
661
    res: BOOLEAN;
662
 
663
BEGIN
664
    res := FALSE;
665
 
666
    IF (v.typ = v2.typ) OR (v.typ IN {tCHAR, tWCHAR}) & (v2.typ IN {tCHAR, tWCHAR}) THEN
667
        CASE v.typ OF
668
        |tINTEGER,
669
         tWCHAR,
670
         tCHAR:     res := v.int = v2.int
671
        |tREAL:     res := v.float = v2.float
672
        |tBOOLEAN:  res := v.bool = v2.bool
673
        |tSET:      res := v.set = v2.set
674
        END
675
    ELSE
676
        error := 1
677
    END
678
 
679
    RETURN res
680
END equal;
681
 
682
 
8097 maxcodehac 683
PROCEDURE relation* (VAR v: VALUE; v2: VALUE; op: INTEGER; VAR error: INTEGER);
7597 akron1 684
VAR
685
    res: BOOLEAN;
686
 
687
BEGIN
688
    error := 0;
689
 
690
    res := FALSE;
691
 
8097 maxcodehac 692
    CASE op OF
7597 akron1 693
 
8097 maxcodehac 694
    |opEQ:
7597 akron1 695
        res := equal(v, v2, error)
696
 
8097 maxcodehac 697
    |opNE:
7597 akron1 698
        res := ~equal(v, v2, error)
699
 
8097 maxcodehac 700
    |opLT:
701
        res := less(v, v2, error)
7597 akron1 702
 
8097 maxcodehac 703
    |opLE:
704
        res := less(v, v2, error);
705
        IF error = 0 THEN
706
            res := equal(v, v2, error) OR res
7597 akron1 707
        END
708
 
8097 maxcodehac 709
    |opGE:
710
        res := ~less(v, v2, error)
711
 
712
    |opGT:
713
        res := less(v, v2, error);
714
        IF error = 0 THEN
715
            res := equal(v, v2, error) OR res
716
        END;
717
        res := ~res
718
 
719
    |opIN:
7597 akron1 720
        IF (v.typ = tINTEGER) & (v2.typ = tSET) THEN
7693 akron1 721
            IF range(v, 0, UTILS.target.maxSet) THEN
7597 akron1 722
                res := v.int IN v2.set
723
            ELSE
724
                error := 2
725
            END
726
        ELSE
727
            error := 1
728
        END
729
 
730
    END;
731
 
732
    IF error = 0 THEN
733
        v.bool := res;
734
        v.typ  := tBOOLEAN
735
    END
736
 
737
END relation;
738
 
739
 
740
PROCEDURE emptySet* (VAR v: VALUE);
741
BEGIN
742
    v.typ := tSET;
743
    v.set := {}
744
END emptySet;
745
 
746
 
747
PROCEDURE constrSet* (VAR v: VALUE; a, b: VALUE);
748
BEGIN
749
    v.typ := tSET;
750
    v.set := {a.int .. b.int}
751
END constrSet;
752
 
753
 
754
PROCEDURE getInt* (v: VALUE): INTEGER;
755
BEGIN
756
    ASSERT(check(v))
757
 
758
    RETURN v.int
759
END getInt;
760
 
761
 
762
PROCEDURE setInt* (VAR v: VALUE; i: INTEGER): BOOLEAN;
763
BEGIN
764
    v.int := i;
765
    v.typ := tINTEGER
766
 
767
    RETURN check(v)
768
END setInt;
769
 
770
 
8097 maxcodehac 771
PROCEDURE concat* (VAR s: ARRAY OF CHAR; s1: ARRAY OF CHAR): BOOLEAN;
772
VAR
773
    res: BOOLEAN;
774
 
775
BEGIN
776
    res := LENGTH(s) + LENGTH(s1) < LEN(s);
777
    IF res THEN
778
        STRINGS.append(s, s1)
779
    END
780
 
781
    RETURN res
782
END concat;
783
 
784
 
7597 akron1 785
PROCEDURE init;
786
VAR
787
    i: INTEGER;
788
 
789
BEGIN
790
    FOR i := 0 TO LEN(digit) - 1 DO
791
        digit[i] := -1
792
    END;
793
 
794
    FOR i := ORD("0") TO ORD("9") DO
795
        digit[i] := i - ORD("0")
796
    END;
797
 
798
    FOR i := ORD("A") TO ORD("F") DO
799
        digit[i] := i - ORD("A") + 10
800
    END
801
END init;
802
 
803
 
804
BEGIN
805
    init
7983 leency 806
END ARITH.