]> git.ipfire.org Git - thirdparty/gcc.git/blame - gcc/m2/gm2-compiler/CLexBuf.mod
Update copyright years.
[thirdparty/gcc.git] / gcc / m2 / gm2-compiler / CLexBuf.mod
CommitLineData
1eee94d3
GM
1(* CLexBuf.mod provides a lexical buffer for clex.
2
83ffe9cd 3Copyright (C) 2003-2023 Free Software Foundation, Inc.
1eee94d3
GM
4Contributed by Gaius Mulley <gaius.mulley@southwales.ac.uk>.
5
6This file is part of GNU Modula-2.
7
8GNU Modula-2 is free software; you can redistribute it and/or modify
9it under the terms of the GNU General Public License as published by
10the Free Software Foundation; either version 3, or (at your option)
11any later version.
12
13GNU Modula-2 is distributed in the hope that it will be useful, but
14WITHOUT ANY WARRANTY; without even the implied warranty of
15MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16General Public License for more details.
17
18You should have received a copy of the GNU General Public License
19along with GNU Modula-2; see the file COPYING3. If not see
20<http://www.gnu.org/licenses/>. *)
21
22IMPLEMENTATION MODULE CLexBuf ;
23
24IMPORT cflex ;
25
26FROM SYSTEM IMPORT ADDRESS ;
27FROM Storage IMPORT ALLOCATE, DEALLOCATE ;
28FROM DynamicStrings IMPORT string, InitString, InitStringCharStar, Equal, Mark, KillString ;
29FROM FormatStrings IMPORT Sprintf1 ;
30FROM NameKey IMPORT Name, NulName, makekey, KeyToCharStar ;
31FROM M2Printf IMPORT printf0, printf1, printf2, printf3 ;
32FROM Assertion IMPORT Assert ;
33FROM SymbolKey IMPORT NulKey, SymbolTree, InitTree, DelSymKey, PutSymKey, GetSymKey ;
34FROM Indexing IMPORT Index, InitIndex, IsIndiceInIndex, GetIndice, PutIndice ;
35
36CONST
37 MaxBucketSize = 100 ;
38 Debugging = FALSE ;
39
40TYPE
41 SourceList = POINTER TO sourcelist ;
42 sourcelist = RECORD
43 left,
44 right: SourceList ;
45 name : String ;
46 line : CARDINAL ;
47 END ;
48
49 TokenDesc = RECORD
50 token: toktype ;
51 str : Name ;
52 int : INTEGER ;
53 line : CARDINAL ;
54 file : SourceList ;
55 END ;
56
57 TokenBucket = POINTER TO tokenbucket ;
58 tokenbucket = RECORD
59 buf : ARRAY [0..MaxBucketSize] OF TokenDesc ;
60 len : CARDINAL ;
61 next: TokenBucket ;
62 END ;
63
64 ListDesc = RECORD
65 head,
66 tail : TokenBucket ;
67 LastBucketOffset: CARDINAL ;
68 END ;
69
70 MacroArgs = POINTER TO macroargs ;
71 macroargs = RECORD
72 next: MacroArgs ;
73 str : Name ;
74 END ;
75
76 Macro = POINTER TO macro ;
77 macro = RECORD
78 str : Name ;
79 tokno : CARDINAL ;
80 noArgs: CARDINAL ;
81 args : MacroArgs ;
82 END ;
83
84VAR
85 CurrentSource : SourceList ;
86 UseBufferedTokens,
87 CurrentUsed : BOOLEAN ;
88 ListOfTokens : ListDesc ;
89 CurrentTokNo : CARDINAL ;
90 MacroDefinitions : SymbolTree ;
91 MacroIndex : Index ;
92 DefineNo : CARDINAL ;
93 EnabledMacros : BOOLEAN ;
94
95
96(* M A C R O *)
97
98(*
99 EnableMacroSubstitutions -
100*)
101
102PROCEDURE EnableMacroSubstitutions (b: BOOLEAN) ;
103BEGIN
104 EnabledMacros := b
105END EnableMacroSubstitutions ;
106
107
108(*
109 IsMacroDefined - returns TRUE if macro, n, was defined.
110*)
111
112PROCEDURE IsMacroDefined (n: Name) : BOOLEAN ;
113VAR
114 i: CARDINAL ;
115 m: Macro ;
116BEGIN
117 i := GetSymKey(MacroDefinitions, n) ;
118 IF i=0
119 THEN
120 RETURN( FALSE )
121 ELSE
122 m := GetIndice(MacroIndex, i) ;
123 IF m=NIL
124 THEN
125 RETURN( FALSE )
126 ELSE
127 RETURN( TRUE )
128 END
129 END
130END IsMacroDefined ;
131
132
133(*
134 NoArgs - returns the number of arguments for macro, n.
135 -1 if the macro does not exist
136*)
137
138PROCEDURE NoArgs (n: Name) : INTEGER ;
139VAR
140 m: Macro ;
141 i: CARDINAL ;
142BEGIN
143 IF IsMacroDefined(n)
144 THEN
145 i := GetSymKey(MacroDefinitions, n) ;
146 m := GetIndice(MacroIndex, i) ;
147 RETURN( m^.noArgs )
148 ELSE
149 RETURN( -1 )
150 END
151END NoArgs ;
152
153
154(*
155 DefineMacro - defines macro, n, as defined to start at token, t.
156*)
157
158PROCEDURE DefineMacro (n: Name; t: CARDINAL) ;
159VAR
160 m: Macro ;
161 i: CARDINAL ;
162BEGIN
163 NEW(m) ;
164 WITH m^ DO
165 str := n ;
166 tokno := t ;
167 noArgs := 0 ;
168 args := NIL
169 END ;
170 UnDefineMacro(n) ;
171 i := GetSymKey(MacroDefinitions, n) ;
172 IF i=NulKey
173 THEN
174 PutSymKey(MacroDefinitions, n, DefineNo) ;
175 i := DefineNo ;
176 INC(DefineNo)
177 END ;
178 PutIndice(MacroIndex, i, m)
179END DefineMacro ;
180
181
182(*
183 UnDefineMacro -
184*)
185
186PROCEDURE UnDefineMacro (n: Name) ;
187VAR
188 m: Macro ;
189 i: CARDINAL ;
190BEGIN
191 IF IsMacroDefined(n)
192 THEN
193 i := GetSymKey(MacroDefinitions, n) ;
194 m := GetIndice(MacroIndex, i) ;
195 PutIndice(MacroIndex, i, NIL) ;
196 DISPOSE(m)
197 END
198END UnDefineMacro ;
199
200
201(*
202 PushMacroDefinition - pushes the macro definition, n, onto the token stream.
203 It returns TRUE if the macro was found and pushed.
204*)
205
206PROCEDURE PushMacroDefinition (n: Name) : BOOLEAN ;
207VAR
208 m: Macro ;
209 t: CARDINAL ;
210 b: TokenBucket ;
211 i: CARDINAL ;
212BEGIN
213 IF EnabledMacros AND IsMacroDefined(n)
214 THEN
215 i := GetSymKey(MacroDefinitions, n) ;
216 m := GetIndice(MacroIndex, i) ;
217 WITH m^ DO
218 IF tokno>0
219 THEN
220 t := tokno ;
221 LOOP
222 b := FindTokenBucket(t) ;
223 WITH b^.buf[t] DO
224 IF token=endhashtok
225 THEN
226 RETURN( TRUE )
227 ELSE
228 IF IsMacroDefined(str) AND (str#n)
229 THEN
230 IF PushMacroDefinition(str)
231 THEN
232 END
233 ELSE
234 AddTokToList(token, str, int, line, file)
235 END
236 END
237 END ;
238 INC(t)
239 END
240 END
241 END ;
242 RETURN( TRUE )
243 ELSE
244 RETURN( FALSE )
245 END
246END PushMacroDefinition ;
247
248
249(* e n d o f M A C R O r o u t i n e s *)
250
251PROCEDURE stop ; BEGIN END stop ;
252
253(*
254 Init - initializes the token list and source list.
255*)
256
257PROCEDURE Init ;
258BEGIN
259 currenttoken := eoftok ;
260 CurrentTokNo := 0 ;
261 CurrentSource := NIL ;
262 ListOfTokens.head := NIL ;
263 ListOfTokens.tail := NIL ;
264 UseBufferedTokens := FALSE ;
265 InitTree(MacroDefinitions) ;
266 EnabledMacros := TRUE ;
267 DefineNo := 1 ;
268 MacroIndex := InitIndex(1)
269END Init ;
270
271
272(*
273 AddTo - adds a new element to the end of SourceList, CurrentSource.
274*)
275
276PROCEDURE AddTo (l: SourceList) ;
277BEGIN
278 l^.right := CurrentSource ;
279 l^.left := CurrentSource^.left ;
280 CurrentSource^.left^.right := l ;
281 CurrentSource^.left := l ;
282 l^.left^.line := cflex.GetLineNo()
283END AddTo ;
284
285
286(*
287 SubFrom - subtracts, l, from the source list.
288*)
289
290PROCEDURE SubFrom (l: SourceList) ;
291BEGIN
292 l^.left^.right := l^.right ;
293 l^.right^.left := l^.left
294END SubFrom ;
295
296
297(*
298 NewElement - returns a new SourceList
299*)
300
301PROCEDURE NewElement (s: ADDRESS) : SourceList ;
302VAR
303 l: SourceList ;
304BEGIN
305 NEW(l) ;
306 IF l=NIL
307 THEN
308 HALT
309 ELSE
310 WITH l^ DO
311 name := InitStringCharStar(s) ;
312 left := NIL ;
313 right := NIL
314 END
315 END ;
316 RETURN( l )
317END NewElement ;
318
319
320(*
321 NewList - initializes an empty list with the classic dummy header element.
322*)
323
324PROCEDURE NewList () : SourceList ;
325VAR
326 l: SourceList ;
327BEGIN
328 NEW(l) ;
329 WITH l^ DO
330 left := l ;
331 right := l ;
332 name := NIL
333 END ;
334 RETURN( l )
335END NewList ;
336
337
338(*
339 CheckIfNeedToDuplicate - checks to see whether the CurrentSource has
340 been used, if it has then duplicate the list.
341*)
342
343PROCEDURE CheckIfNeedToDuplicate ;
344VAR
345 l, h: SourceList ;
346BEGIN
347 IF CurrentUsed
348 THEN
349 l := CurrentSource^.right ;
350 h := CurrentSource ;
351 CurrentSource := NewList() ;
352 WHILE l#h DO
353 AddTo(NewElement(l^.name)) ;
354 l := l^.right
355 END
356 END
357END CheckIfNeedToDuplicate ;
358
359
360(*
361 PushFile - indicates that, filename, has just been included.
362*)
363
364PROCEDURE PushFile (filename: ADDRESS) ;
365VAR
366 l: SourceList ;
367BEGIN
368 CheckIfNeedToDuplicate ;
369 AddTo(NewElement(filename)) ;
370 IF Debugging
371 THEN
372 IF CurrentSource^.right#CurrentSource
373 THEN
374 l := CurrentSource ;
375 REPEAT
376 printf2('name = %s, line = %d\n', l^.name, l^.line) ;
377 l := l^.right
378 UNTIL l=CurrentSource
379 END
380 END
381END PushFile ;
382
383
384(*
385 PopFile - indicates that we are returning to, filename, having finished
386 an include.
387*)
388
389PROCEDURE PopFile (filename: ADDRESS) ;
390VAR
391 l: SourceList ;
392BEGIN
393 CheckIfNeedToDuplicate ;
394 IF (CurrentSource#NIL) AND (CurrentSource^.left#CurrentSource)
395 THEN
396 l := CurrentSource^.left ; (* last element *)
397 SubFrom(l) ;
398 DISPOSE(l) ;
399 IF (CurrentSource^.left#CurrentSource) AND
400 (NOT Equal(CurrentSource^.name, Mark(InitStringCharStar(filename))))
401 THEN
402 (* mismatch in source file names after preprocessing files *)
403 END
404 ELSE
405 (* source file list is empty, cannot pop an include.. *)
406 END
407END PopFile ;
408
409
410(*
411 KillList - kills the SourceList providing that it has not been used.
412*)
413
414PROCEDURE KillList ;
415VAR
416 l, k: SourceList ;
417BEGIN
418 IF (NOT CurrentUsed) AND (CurrentSource#NIL)
419 THEN
420 l := CurrentSource ;
421 REPEAT
422 k := l ;
423 l := l^.right ;
424 DISPOSE(k)
425 UNTIL l=CurrentSource
426 END
427END KillList ;
428
429
430(*
431 ReInitialize - re-initialize the all the data structures.
432*)
433
434PROCEDURE ReInitialize ;
435VAR
436 s, t: TokenBucket ;
437BEGIN
438 IF ListOfTokens.head#NIL
439 THEN
440 t := ListOfTokens.head ;
441 REPEAT
442 s := t ;
443 t := t^.next ;
444 DISPOSE(s) ;
445 UNTIL t=NIL ;
446 CurrentUsed := FALSE ;
447 KillList
448 END ;
449 Init
450END ReInitialize ;
451
452
453(*
454 SetFile - sets the current filename to, filename.
455*)
456
457PROCEDURE SetFile (filename: ADDRESS) ;
458BEGIN
459 KillList ;
460 CurrentUsed := FALSE ;
461 CurrentSource := NewList() ;
462 AddTo(NewElement(filename))
463END SetFile ;
464
465
466(*
467 OpenSource - Attempts to open the source file, s.
468 The success of the operation is returned.
469*)
470
471PROCEDURE OpenSource (s: String) : BOOLEAN ;
472BEGIN
473 IF UseBufferedTokens
474 THEN
475 GetToken ;
476 RETURN( TRUE )
477 ELSE
478 IF cflex.OpenSource(string(s))
479 THEN
480 SetFile(string(s)) ;
481 SyncOpenWithBuffer ;
482 GetToken ;
483 RETURN( TRUE )
484 ELSE
485 RETURN( FALSE )
486 END
487 END
488END OpenSource ;
489
490
491(*
492 CloseSource - closes the current open file.
493*)
494
495PROCEDURE CloseSource ;
496BEGIN
497 IF UseBufferedTokens
498 THEN
499 WHILE currenttoken#eoftok DO
500 GetToken
501 END
502 ELSE
503 (* a subsequent call to cflex.OpenSource will really close the file *)
504 END
505END CloseSource ;
506
507
508(*
509 ResetForNewPass - reset the buffer pointers to the beginning ready for
510 a new pass
511*)
512
513PROCEDURE ResetForNewPass ;
514BEGIN
515 CurrentTokNo := 0 ;
516 UseBufferedTokens := TRUE
517END ResetForNewPass ;
518
519
520(*
521 DisplayToken -
522*)
523
524PROCEDURE DisplayToken ;
525VAR
526 n: Name ;
527BEGIN
528 cflex.CError(string(InitString('current token'))) ;
529 IF currenttoken=identtok
530 THEN
531 n := makekey(currentstring) ;
532 printf1('currenttoken = %a\n', n)
533 ELSE
534 CASE currenttoken OF
535
536 eoftok : printf0('eoftok\n') |
537 startok : printf0('*\n') |
538 arrowtok : printf0('->\n') |
539 structtok : printf0('struct\n') |
540 lsbratok : printf0('[\n') |
541 rsbratok : printf0(']\n') |
542 lcbratok : printf0('{\n') |
543 rcbratok : printf0('}\n') |
544 lparatok : printf0('(\n') |
545 rparatok : printf0(')\n') |
546 semicolontok : printf0(';\n') |
547 longtok : printf0('long\n') |
548 inttok : printf0('int\n') |
549 chartok : printf0('char\n') |
550 enumtok : printf0('enum\n') |
551 typedeftok : printf0('typedef\n') |
552 floattok : printf0('float\n') |
553 doubletok : printf0('double\n') |
554 unsignedtok : printf0('unsigned\n') |
555 consttok : printf0('const\n') |
556 periodperiodperiodtok: printf0('...\n') |
557 integertok : printf0('integer number\n') |
558 hexintegertok : printf0('hexadecimal number\n') |
559 octintegertok : printf0('octal number\n') |
560 identtok : printf0('identifier\n') |
561 realtok : printf0('real number\n') |
562 conststringtok : printf0('constant string\n') |
563 constchartok : printf0('constant char\n') |
564 codetok : printf0('some C code\n') |
565 starthashtok : printf0('start#\n') |
566 endhashtok : printf0('end#\n') |
567 definetok : printf0('define\n') |
568 definedtok : stop ; printf0('defined\n') |
569 undeftok : printf0('undef\n') |
570 iftok : printf0('if\n') |
571 elsetok : printf0('else\n') |
572 endiftok : printf0('endif\n') |
573 ifdeftok : printf0('ifdef\n') |
574 ifndeftok : printf0('ifndef\n') |
575 nottok : printf0('not\n') |
576 includetok : printf0('include\n') |
577 commatok : printf0('comma\n') |
578 periodtok : printf0('period\n') |
579 gretok : printf0('gre\n') |
580 lesstok : printf0('less\n') |
581 ortok : printf0('or\n') |
582 andtok : printf0('and\n') |
583 bartok : printf0('bar\n') |
584 ambersandtok : printf0('ambersand\n') |
585 shiftlefttok : printf0('shiftleft\n') |
586 shiftrighttok : printf0('shiftright\n') |
587 divtok : printf0('div\n') |
588 modtok : printf0('mod\n') |
589 sizeoftok : printf0('sizeof\n') |
590 hattok : printf0('hat\n') |
591 equaltok : printf0('equal\n') |
592 notequaltok : printf0('notequal\n') |
593 greequaltok : printf0('greequal\n') |
594 lessequaltok : printf0('lessequal\n') |
595 plustok : printf0('plus\n') |
596 minustok : printf0('minus\n') |
597 tildetok : printf0('tilde\n') |
598 externtok : printf0('extern\n') |
599 statictok : printf0('static\n') |
600 autotok : printf0('auto\n') |
601 registertok : printf0('register\n') |
602 voidtok : printf0('void\n') |
603 shorttok : printf0('short\n') |
604 signedtok : printf0('signed\n') |
605 uniontok : printf0('union\n') |
606 colontok : printf0('colon\n') |
607 becomestok : printf0('becomes\n') |
608 volatiletok : printf0('volatile\n') |
609 typetok : printf0('type\n')
610
611 ELSE
612 cflex.CError(string(InitString('unrecognised token')))
613 END
614 END
615END DisplayToken ;
616
617
618(*
619 GetToken - gets the next token into currenttoken.
620*)
621
622PROCEDURE GetToken ;
623VAR
624 t: CARDINAL ;
625 b: TokenBucket ;
626 l: CARDINAL ;
627BEGIN
628 IF UseBufferedTokens
629 THEN
630 t := CurrentTokNo ;
631 b := FindTokenBucket(t) ;
632 WITH b^.buf[t] DO
633 currenttoken := token ;
634 currentstring := KeyToCharStar(str) ;
635 currentinteger := int ;
636 IF Debugging
637 THEN
638 l := line
639 END
640 END ;
641 IF Debugging
642 THEN
643 printf3('line %d (# %d %d) ', l, t, CurrentTokNo) ;
644 DisplayToken
645 END ;
646 INC(CurrentTokNo)
647 ELSE
648 IF ListOfTokens.tail=NIL
649 THEN
650 cflex.AdvanceToken ;
651 IF ListOfTokens.tail=NIL
652 THEN
653 HALT
654 END
655 END ;
656
657 IF ListOfTokens.LastBucketOffset>CurrentTokNo
658 THEN
659 t := CurrentTokNo ;
660 b := FindTokenBucket(t) ;
661 WITH b^.buf[t] DO
662 currenttoken := token ;
663 currentstring := KeyToCharStar(str) ;
664 currentinteger := int ;
665 IF Debugging
666 THEN
667 l := line
668 END
669 END ;
670 INC(CurrentTokNo)
671 ELSE
672 WITH ListOfTokens.tail^ DO
673 IF CurrentTokNo-ListOfTokens.LastBucketOffset<len
674 THEN
675 WITH buf[CurrentTokNo-ListOfTokens.LastBucketOffset] DO
676 currenttoken := token ;
677 currentstring := KeyToCharStar(str) ;
678 currentinteger := int
679 END ;
680 IF Debugging
681 THEN
682 (* printf1('# %d ', CurrentTokNo) ; *)
683 DisplayToken
684 END ;
685 INC(CurrentTokNo)
686 ELSE
687 cflex.AdvanceToken ;
688 GetToken ;
689 (* printf0('\n'); cflex.CError(string(InitString('current token'))) ; *)
690 END
691 END
692 END
693 END
694END GetToken ;
695
696
697(*
698 FlushTokens - removes the last token.
699*)
700
701PROCEDURE FlushTokens ;
702BEGIN
703 INC(CurrentTokNo)
704END FlushTokens ;
705
706
707(*
708 SyncOpenWithBuffer - synchronise the buffer with the start of a file.
709 Skips all the tokens to do with the previous file.
710*)
711
712PROCEDURE SyncOpenWithBuffer ;
713BEGIN
714 IF ListOfTokens.tail#NIL
715 THEN
716 WITH ListOfTokens.tail^ DO
717 CurrentTokNo := ListOfTokens.LastBucketOffset+len
718 END
719 END
720END SyncOpenWithBuffer ;
721
722
723(*
724 InsertToken - inserts a symbol, token, infront of the current token
725 ready for the next pass.
726*)
727
728PROCEDURE InsertToken (token: toktype) ;
729BEGIN
730 IF ListOfTokens.tail#NIL
731 THEN
732 WITH ListOfTokens.tail^ DO
733 IF len>0
734 THEN
735 buf[len-1].token := token
736 END
737 END ;
738 AddTokToList(currenttoken, NulName, 0, GetLineNo(), CurrentSource) ;
739 GetToken
740 END
741END InsertToken ;
742
743
744(*
745 InsertTokenAndRewind - inserts a symbol, token, infront of the current token
746 and then moves the token stream back onto the inserted token.
747*)
748
749PROCEDURE InsertTokenAndRewind (token: toktype) ;
750BEGIN
751 IF ListOfTokens.tail#NIL
752 THEN
753 WITH ListOfTokens.tail^ DO
754 IF len>0
755 THEN
756 buf[len-1].token := token
757 END
758 END ;
759 AddTokToList(currenttoken, NulName, 0, GetLineNo(), CurrentSource) ;
760 currenttoken := token
761 END
762END InsertTokenAndRewind ;
763
764
765(*
766 GetLineNo - returns the current line number where the symbol occurs in
767 the source file.
768*)
769
770PROCEDURE GetLineNo () : CARDINAL ;
771BEGIN
772 IF CurrentTokNo=0
773 THEN
774 RETURN( 0 )
775 ELSE
776 RETURN( TokenToLineNo(GetTokenNo(), 0) )
777 END
778END GetLineNo ;
779
780
781(*
782 GetTokenNo - returns the current token number.
783*)
784
785PROCEDURE GetTokenNo () : CARDINAL ;
786BEGIN
787 IF CurrentTokNo=0
788 THEN
789 RETURN( 0 )
790 ELSE
791 RETURN( CurrentTokNo-1 )
792 END
793END GetTokenNo ;
794
795
796(*
797 FindTokenBucket - returns the TokenBucket corresponding to the TokenNo.
798*)
799
800PROCEDURE FindTokenBucket (VAR TokenNo: CARDINAL) : TokenBucket ;
801VAR
802 b: TokenBucket ;
803BEGIN
804 b := ListOfTokens.head ;
805 WHILE b#NIL DO
806 WITH b^ DO
807 IF TokenNo<len
808 THEN
809 RETURN( b )
810 ELSE
811 DEC(TokenNo, len)
812 END
813 END ;
814 b := b^.next
815 END ;
816 RETURN( NIL )
817END FindTokenBucket ;
818
819
820(*
821 TokenToLineNo - returns the line number of the current file for the
822 TokenNo. The depth refers to the include depth.
823 A depth of 0 is the current file, depth of 1 is the file
824 which included the current file. Zero is returned if the
825 depth exceeds the file nesting level.
826*)
827
828PROCEDURE TokenToLineNo (TokenNo: CARDINAL; depth: CARDINAL) : CARDINAL ;
829VAR
830 b: TokenBucket ;
831 l: SourceList ;
832BEGIN
833 b := FindTokenBucket(TokenNo) ;
834 IF b=NIL
835 THEN
836 RETURN( 0 )
837 ELSE
838 IF depth=0
839 THEN
840 RETURN( b^.buf[TokenNo].line )
841 ELSE
842 l := b^.buf[TokenNo].file^.left ;
843 WHILE depth>0 DO
844 l := l^.left ;
845 IF l=b^.buf[TokenNo].file^.left
846 THEN
847 RETURN( 0 )
848 END ;
849 DEC(depth)
850 END ;
851 RETURN( l^.line )
852 END
853 END
854END TokenToLineNo ;
855
856
857(*
858 FindFileNameFromToken - returns the complete FileName for the appropriate
859 source file yields the token number, TokenNo.
860 The, Depth, indicates the include level: 0..n
861 Level 0 is the current. NIL is returned if n+1
862 is requested.
863*)
864
865PROCEDURE FindFileNameFromToken (TokenNo: CARDINAL; depth: CARDINAL) : String ;
866VAR
867 b: TokenBucket ;
868 l: SourceList ;
869BEGIN
870 b := FindTokenBucket(TokenNo) ;
871 IF b=NIL
872 THEN
873 RETURN( NIL )
874 ELSE
875 l := b^.buf[TokenNo].file^.left ;
876 WHILE depth>0 DO
877 l := l^.left ;
878 IF l=b^.buf[TokenNo].file^.left
879 THEN
880 RETURN( NIL )
881 END ;
882 DEC(depth)
883 END ;
884 RETURN( l^.name )
885 END
886END FindFileNameFromToken ;
887
888
889(*
890 GetFileName - returns a String defining the current file.
891*)
892
893PROCEDURE GetFileName () : String ;
894BEGIN
895 RETURN( FindFileNameFromToken(GetTokenNo(), 0) )
896END GetFileName ;
897
898
899(*
900 AddTokToList - adds a token to a dynamic list.
901*)
902
903PROCEDURE AddTokToList (t: toktype; n: Name;
904 i: INTEGER; l: CARDINAL; f: SourceList) ;
905BEGIN
906 IF ListOfTokens.head=NIL
907 THEN
908 NEW(ListOfTokens.head) ;
909 IF ListOfTokens.head=NIL
910 THEN
911 (* list error *)
912 END ;
913 ListOfTokens.tail := ListOfTokens.head ;
914 ListOfTokens.tail^.len := 0
915 ELSIF ListOfTokens.tail^.len=MaxBucketSize
916 THEN
917 Assert(ListOfTokens.tail^.next=NIL) ;
918 NEW(ListOfTokens.tail^.next) ;
919 IF ListOfTokens.tail^.next=NIL
920 THEN
921 (* list error *)
922 ELSE
923 ListOfTokens.tail := ListOfTokens.tail^.next ;
924 ListOfTokens.tail^.len := 0
925 END ;
926 INC(ListOfTokens.LastBucketOffset, MaxBucketSize)
927 END ;
928 WITH ListOfTokens.tail^ DO
929 next := NIL ;
930 WITH buf[len] DO
931 token := t ;
932 str := n ;
933 int := i ;
934 line := l ;
935 file := f
936 END ;
937 INC(len)
938 END
939END AddTokToList ;
940
941
942(*
943 IsLastTokenEof - returns TRUE if the last token was an eoftok
944*)
945
946PROCEDURE IsLastTokenEof () : BOOLEAN ;
947VAR
948 b: TokenBucket ;
949BEGIN
950 IF ListOfTokens.tail#NIL
951 THEN
952 IF ListOfTokens.tail^.len=0
953 THEN
954 b := ListOfTokens.head ;
955 IF b=ListOfTokens.tail
956 THEN
957 RETURN( FALSE )
958 END ;
959 WHILE b^.next#ListOfTokens.tail DO
960 b := b^.next
961 END ;
962 ELSE
963 b := ListOfTokens.tail
964 END ;
965 WITH b^ DO
966 RETURN( buf[len-1].token=eoftok )
967 END
968 END ;
969 RETURN( FALSE )
970END IsLastTokenEof ;
971
972
973(* ***********************************************************************
974 *
975 * These functions allow c.flex to deliver tokens into the buffer
976 *
977 ************************************************************************* *)
978
979(*
980 AddTok - adds a token to the buffer.
981*)
982
983PROCEDURE AddTok (t: toktype) ;
984BEGIN
985 IF NOT ((t=eoftok) AND IsLastTokenEof())
986 THEN
987 AddTokToList(t, NulName, 0, cflex.GetLineNo(), CurrentSource) ;
988 CurrentUsed := TRUE
989 END
990END AddTok ;
991
992
993(*
994 AddTokCharStar - adds a token to the buffer and an additional string, s.
995 A copy of string, s, is made.
996*)
997
998PROCEDURE AddTokCharStar (t: toktype; s: ADDRESS) ;
999BEGIN
1000 IF (t=identtok) AND PushMacroDefinition(makekey(s))
1001 THEN
1002 (* do nothing *)
1003 ELSE
1004 AddTokToList(t, makekey(s), 0, cflex.GetLineNo(), CurrentSource) ;
1005 CurrentUsed := TRUE
1006 END
1007END AddTokCharStar ;
1008
1009
1010(*
1011 AddTokInteger - adds a token and an integer to the buffer.
1012*)
1013
1014PROCEDURE AddTokInteger (t: toktype; i: INTEGER) ;
1015VAR
1016 s: String ;
1017 lineno: CARDINAL ;
1018BEGIN
1019 lineno := cflex.GetLineNo() ;
1020 s := Sprintf1(Mark(InitString('%d')), lineno) ;
1021 AddTokToList(t, makekey(string(s)), i, lineno, CurrentSource) ;
1022 s := KillString(s) ;
1023 CurrentUsed := TRUE
1024END AddTokInteger ;
1025
1026
1027BEGIN
1028 Init
1029END CLexBuf.