1 (* M2LexBuf.mod provides a buffer for m2.lex.
3 Copyright (C) 2001-2024 Free Software Foundation, Inc.
4 Contributed by Gaius Mulley <gaius.mulley@southwales.ac.uk>.
6 This file is part of GNU Modula-2.
8 GNU Modula-2 is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 3, or (at your option)
13 GNU Modula-2 is distributed in the hope that it will be useful, but
14 WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 General Public License for more details.
18 You should have received a copy of the GNU General Public License
19 along with GNU Modula-2; see the file COPYING3. If not see
20 <http://www.gnu.org/licenses/>. *)
22 IMPLEMENTATION MODULE M2LexBuf ;
26 FROM libc IMPORT strlen ;
27 FROM SYSTEM IMPORT ADDRESS ;
28 FROM Storage IMPORT ALLOCATE, DEALLOCATE ;
29 FROM DynamicStrings IMPORT string, InitString, InitStringCharStar, Equal, Mark, KillString ;
30 FROM FormatStrings IMPORT Sprintf1 ;
31 FROM NameKey IMPORT NulName, Name, makekey, MakeKey, KeyToCharStar ;
32 FROM M2Reserved IMPORT toktype, tokToTok ;
33 FROM M2Printf IMPORT printf0, printf1, printf2, printf3 ;
34 FROM M2Debug IMPORT Assert ;
35 FROM NameKey IMPORT makekey ;
36 FROM m2linemap IMPORT location_t, GetLocationBinary ;
37 FROM M2Emit IMPORT UnknownLocation, BuiltinsLocation ;
38 FROM M2Error IMPORT WarnStringAt ;
43 DebugRecover = FALSE ;
44 InitialSourceToken = 2 ; (* 0 is unknown, 1 is builtin. *)
47 SourceList = POINTER TO RECORD
57 str : Name ; (* ident name or string literal. *)
63 insert: TokenBucket ; (* contains any inserted tokens. *)
66 TokenBucket = POINTER TO RECORD
67 buf : ARRAY [0..MaxBucketSize] OF TokenDesc ;
75 LastBucketOffset: CARDINAL ;
79 CurrentSource : SourceList ;
81 CurrentUsed : BOOLEAN ;
82 ListOfTokens : ListDesc ;
83 CurrentTokNo : CARDINAL ;
84 InsertionIndex : CARDINAL ;
85 SeenEof : BOOLEAN ; (* Have we seen eof since the last call
90 InitTokenList - creates an empty token list, which starts the first source token
91 at position 2. This allows position 0 to be for unknown location
92 and position 1 for builtin token.
95 PROCEDURE InitTokenList ;
97 NEW (ListOfTokens.head) ;
98 ListOfTokens.tail := ListOfTokens.head ;
99 WITH ListOfTokens.tail^.buf[0] DO
106 loc := UnknownLocation ()
108 WITH ListOfTokens.tail^.buf[1] DO
115 loc := BuiltinsLocation ()
117 ListOfTokens.tail^.len := InitialSourceToken
122 Init - initializes the token list and source list.
128 InsertionIndex := 0 ;
129 currenttoken := eoftok ;
130 CurrentTokNo := InitialSourceToken ;
131 CurrentSource := NIL ;
132 ListOfTokens.head := NIL ;
133 ListOfTokens.tail := NIL ;
134 UseBufferedTokens := FALSE ;
140 AddTo - adds a new element to the end of SourceList, CurrentSource.
143 PROCEDURE AddTo (l: SourceList) ;
145 l^.right := CurrentSource ;
146 l^.left := CurrentSource^.left ;
147 CurrentSource^.left^.right := l ;
148 CurrentSource^.left := l ;
150 line := m2flex.GetLineNo() ;
151 col := m2flex.GetColumnNo()
157 SubFrom - subtracts, l, from the source list.
160 PROCEDURE SubFrom (l: SourceList) ;
162 l^.left^.right := l^.right ;
163 l^.right^.left := l^.left
168 NewElement - returns a new SourceList
171 PROCEDURE NewElement (s: ADDRESS) : SourceList ;
181 name := InitStringCharStar(s) ;
191 NewList - initializes an empty list with the classic dummy header element.
194 PROCEDURE NewList () : SourceList ;
209 CheckIfNeedToDuplicate - checks to see whether the CurrentSource has
210 been used, if it has then duplicate the list.
213 PROCEDURE CheckIfNeedToDuplicate ;
219 l := CurrentSource^.right ;
221 CurrentSource := NewList() ;
223 AddTo (NewElement (l^.name)) ;
227 END CheckIfNeedToDuplicate ;
231 PushFile - indicates that, filename, has just been included.
234 PROCEDURE PushFile (filename: ADDRESS) ;
238 CheckIfNeedToDuplicate ;
239 AddTo (NewElement (filename)) ;
242 IF CurrentSource^.right#CurrentSource
246 printf3('name = %s, line = %d, col = %d\n', l^.name, l^.line, l^.col) ;
248 UNTIL l=CurrentSource
255 PopFile - indicates that we are returning to, filename, having finished
259 PROCEDURE PopFile (filename: ADDRESS) ;
263 CheckIfNeedToDuplicate ;
264 IF (CurrentSource#NIL) AND (CurrentSource^.left#CurrentSource)
266 l := CurrentSource^.left ; (* last element *)
269 IF (CurrentSource^.left#CurrentSource) AND
270 (NOT Equal(CurrentSource^.name, Mark(InitStringCharStar(filename))))
272 (* mismatch in source file names after preprocessing files *)
275 (* source file list is empty, cannot pop an include.. *)
281 KillList - kills the SourceList providing that it has not been used.
288 IF (NOT CurrentUsed) AND (CurrentSource#NIL)
295 UNTIL l=CurrentSource
301 ReInitialize - re-initialize the all the data structures.
304 PROCEDURE ReInitialize ;
308 IF ListOfTokens.head#NIL
310 t := ListOfTokens.head ;
316 CurrentUsed := FALSE ;
324 SetFile - sets the current filename to, filename.
327 PROCEDURE SetFile (filename: ADDRESS) ;
330 CurrentUsed := FALSE ;
331 CurrentSource := NewList () ;
332 AddTo (NewElement (filename))
337 OpenSource - Attempts to open the source file, s.
338 The success of the operation is returned.
341 PROCEDURE OpenSource (s: String) : BOOLEAN ;
349 IF m2flex.OpenSource (string (s))
351 SetFile (string (s)) ;
363 CloseSource - closes the current open file.
366 PROCEDURE CloseSource ;
370 WHILE currenttoken#eoftok DO
374 (* a subsequent call to m2flex.OpenSource will really close the file *)
380 ResetForNewPass - reset the buffer pointers to the beginning ready for
384 PROCEDURE ResetForNewPass ;
386 InsertionIndex := 0 ;
387 CurrentTokNo := InitialSourceToken ;
388 UseBufferedTokens := TRUE
389 END ResetForNewPass ;
393 DisplayToken - display the token name using printf0 no newline is emitted.
396 PROCEDURE DisplayToken (tok: toktype) ;
400 eoftok: printf0('eoftok') |
401 plustok: printf0('plustok') |
402 minustok: printf0('minustok') |
403 timestok: printf0('timestok') |
404 dividetok: printf0('dividetok') |
405 becomestok: printf0('becomestok') |
406 ambersandtok: printf0('ambersandtok') |
407 periodtok: printf0('periodtok') |
408 commatok: printf0('commatok') |
409 semicolontok: printf0('semicolontok') |
410 lparatok: printf0('lparatok') |
411 rparatok: printf0('rparatok') |
412 lsbratok: printf0('lsbratok') |
413 rsbratok: printf0('rsbratok') |
414 lcbratok: printf0('lcbratok') |
415 rcbratok: printf0('rcbratok') |
416 uparrowtok: printf0('uparrowtok') |
417 singlequotetok: printf0('singlequotetok') |
418 equaltok: printf0('equaltok') |
419 hashtok: printf0('hashtok') |
420 lesstok: printf0('lesstok') |
421 greatertok: printf0('greatertok') |
422 lessgreatertok: printf0('lessgreatertok') |
423 lessequaltok: printf0('lessequaltok') |
424 greaterequaltok: printf0('greaterequaltok') |
425 periodperiodtok: printf0('periodperiodtok') |
426 colontok: printf0('colontok') |
427 doublequotestok: printf0('doublequotestok') |
428 bartok: printf0('bartok') |
429 andtok: printf0('andtok') |
430 arraytok: printf0('arraytok') |
431 begintok: printf0('begintok') |
432 bytok: printf0('bytok') |
433 casetok: printf0('casetok') |
434 consttok: printf0('consttok') |
435 definitiontok: printf0('definitiontok') |
436 divtok: printf0('divtok') |
437 dotok: printf0('dotok') |
438 elsetok: printf0('elsetok') |
439 elsiftok: printf0('elsiftok') |
440 endtok: printf0('endtok') |
441 exittok: printf0('exittok') |
442 exporttok: printf0('exporttok') |
443 fortok: printf0('fortok') |
444 fromtok: printf0('fromtok') |
445 iftok: printf0('iftok') |
446 implementationtok: printf0('implementationtok') |
447 importtok: printf0('importtok') |
448 intok: printf0('intok') |
449 looptok: printf0('looptok') |
450 modtok: printf0('modtok') |
451 moduletok: printf0('moduletok') |
452 nottok: printf0('nottok') |
453 oftok: printf0('oftok') |
454 ortok: printf0('ortok') |
455 pointertok: printf0('pointertok') |
456 proceduretok: printf0('proceduretok') |
457 qualifiedtok: printf0('qualifiedtok') |
458 unqualifiedtok: printf0('unqualifiedtok') |
459 recordtok: printf0('recordtok') |
460 repeattok: printf0('repeattok') |
461 returntok: printf0('returntok') |
462 settok: printf0('settok') |
463 thentok: printf0('thentok') |
464 totok: printf0('totok') |
465 typetok: printf0('typetok') |
466 untiltok: printf0('untiltok') |
467 vartok: printf0('vartok') |
468 whiletok: printf0('whiletok') |
469 withtok: printf0('withtok') |
470 asmtok: printf0('asmtok') |
471 volatiletok: printf0('volatiletok') |
472 periodperiodperiodtok: printf0('periodperiodperiodtok') |
473 datetok: printf0('datetok') |
474 linetok: printf0('linetok') |
475 filetok: printf0('filetok') |
476 integertok: printf0('integertok') |
477 identtok: printf0('identtok') |
478 realtok: printf0('realtok') |
479 stringtok: printf0('stringtok')
487 UpdateFromBucket - updates the global variables: currenttoken,
488 currentstring, currentcolumn and currentinteger
489 from TokenBucket, b, and, offset.
492 PROCEDURE UpdateFromBucket (b: TokenBucket; offset: CARDINAL) ;
494 IF InsertionIndex > 0
496 (* we have an inserted token to use. *)
497 Assert (b^.buf[offset].insert # NIL) ;
498 WITH b^.buf[offset].insert^.buf[InsertionIndex] DO
499 currenttoken := token ;
500 currentstring := KeyToCharStar(str) ;
501 currentcolumn := col ;
502 currentinteger := int ;
505 printf3('line %d (# %d %d) ', line, offset, CurrentTokNo)
508 INC (InsertionIndex) ;
509 IF InsertionIndex = b^.buf[offset].insert^.len
511 InsertionIndex := 0 ; (* finished consuming the inserted tokens. *)
514 ELSIF (b^.buf[offset].insert # NIL) AND (InsertionIndex = 0)
516 (* this source token has extra tokens appended after it by the error recovery. *)
517 Assert (b^.buf[offset].insert^.len > 0) ; (* we must have at least one token. *)
518 InsertionIndex := 1 ; (* so set the index ready for the next UpdateFromBucket. *)
519 (* and read the original token. *)
520 WITH b^.buf[offset] DO
521 currenttoken := token ;
522 currentstring := KeyToCharStar(str) ;
523 currentcolumn := col ;
524 currentinteger := int ;
527 printf3('line %d (# %d %d) ', line, offset, CurrentTokNo)
531 (* no inserted tokens after this token so read it and move on. *)
532 WITH b^.buf[offset] DO
533 currenttoken := token ;
534 currentstring := KeyToCharStar(str) ;
535 currentcolumn := col ;
536 currentinteger := int ;
539 printf3('line %d (# %d %d) ', line, offset, CurrentTokNo)
544 END UpdateFromBucket ;
551 PROCEDURE DisplayTokenEntry (topBucket: TokenBucket; index, total: CARDINAL) ;
555 printf1 ("%d: ", total) ;
556 DisplayToken (topBucket^.buf[index].token) ;
557 printf1 (" %a ", topBucket^.buf[index].str) ;
558 IF total = GetTokenNo ()
560 printf0 (" <- current token")
563 (* now check for inserted tokens. *)
564 IF topBucket^.buf[index].insert # NIL
567 WHILE i < topBucket^.buf[index].insert^.len DO
568 printf1 (" %d: ", i) ;
569 DisplayToken (topBucket^.buf[index].insert^.buf[i].token) ;
570 printf1 (" %a\n", topBucket^.buf[index].insert^.buf[i].str) ;
574 END DisplayTokenEntry ;
578 DumpTokens - developer debugging aid.
581 PROCEDURE DumpTokens ;
589 tokenNo := GetTokenNo () ;
590 tb := ListOfTokens.head ;
596 DisplayTokenEntry (tb, i, total) ;
602 printf2 ("%d: tokenNo, %d: total\n", tokenNo, total) ;
603 IF (total # 0) AND (tokenNo = total)
605 printf1 ("%d: end of buffer ", total) ;
606 printf0 (" <- current token") ;
613 GetNonEofToken - providing that we have not already seen an eof for this source
614 file call m2flex.GetToken and GetToken if requested.
617 PROCEDURE GetNonEofToken (callGetToken: BOOLEAN) ;
621 currenttoken := eoftok
623 (* Call the lexical phase to place a new token into the last bucket. *)
634 GetToken - gets the next token into currenttoken.
645 b := FindTokenBucket(t) ;
646 UpdateFromBucket (b, t)
648 IF ListOfTokens.tail=NIL
650 GetNonEofToken (FALSE) ;
651 IF ListOfTokens.tail=NIL
656 IF CurrentTokNo>=ListOfTokens.LastBucketOffset
658 (* CurrentTokNo is in the last bucket or needs to be read. *)
659 IF CurrentTokNo-ListOfTokens.LastBucketOffset<ListOfTokens.tail^.len
661 UpdateFromBucket (ListOfTokens.tail,
662 CurrentTokNo-ListOfTokens.LastBucketOffset)
664 (* and call ourselves again to collect the token from bucket *)
665 GetNonEofToken (TRUE)
669 b := FindTokenBucket (t) ;
670 UpdateFromBucket (b, t)
677 SyncOpenWithBuffer - synchronise the buffer with the start of a file.
678 Skips all the tokens to do with the previous file.
681 PROCEDURE SyncOpenWithBuffer ;
683 IF ListOfTokens.tail#NIL
685 WITH ListOfTokens.tail^ DO
686 CurrentTokNo := ListOfTokens.LastBucketOffset+len
689 END SyncOpenWithBuffer ;
693 GetInsertBucket - returns the insertion bucket associated with token count
694 and the topBucket. It creates a new TokenBucket if necessary.
697 PROCEDURE GetInsertBucket (topBucket: TokenBucket; count: CARDINAL) : TokenBucket ;
699 IF topBucket^.buf[count].insert = NIL
701 NEW (topBucket^.buf[count].insert) ;
702 topBucket^.buf[count].insert^.buf[0] := topBucket^.buf[count] ;
703 topBucket^.buf[count].insert^.buf[0].insert := NIL ;
704 topBucket^.buf[count].insert^.len := 1 (* empty, slot 0 contains the original token for ease. *)
706 RETURN topBucket^.buf[count].insert
707 END GetInsertBucket ;
711 AppendToken - appends desc to the end of the insertionBucket.
714 PROCEDURE AppendToken (insertionBucket: TokenBucket; desc: TokenDesc) ;
716 IF insertionBucket^.len < MaxBucketSize
718 insertionBucket^.buf[insertionBucket^.len] := desc ;
719 INC (insertionBucket^.len)
725 InsertToken - inserts a symbol, token, infront of the current token
726 ready for the next pass.
729 PROCEDURE InsertToken (token: toktype) ;
731 topBucket, insertionBucket: TokenBucket ;
735 Assert (ListOfTokens.tail # NIL) ;
736 count := GetTokenNo () -1 ;
737 topBucket := FindTokenBucket (count) ;
738 insertionBucket := GetInsertBucket (topBucket, count) ;
739 desc := topBucket^.buf[count] ;
740 desc.token := token ;
742 AppendToken (insertionBucket, desc) ;
751 InsertTokenAndRewind - inserts a symbol, token, infront of the current token
752 and then moves the token stream back onto the inserted token.
755 PROCEDURE InsertTokenAndRewind (token: toktype) ;
758 topBucket: TokenBucket ;
762 InsertToken (token) ;
763 offset := CurrentTokNo -2 ;
764 topBucket := FindTokenBucket (offset) ;
765 InsertionIndex := topBucket^.buf[offset].insert^.len -1 ;
766 DEC (CurrentTokNo, 2) ;
769 END InsertTokenAndRewind ;
773 GetPreviousTokenLineNo - returns the line number of the previous token.
776 PROCEDURE GetPreviousTokenLineNo () : CARDINAL ;
781 RETURN( TokenToLineNo(GetTokenNo()-1, 0) )
787 END GetPreviousTokenLineNo ;
791 GetLineNo - returns the current line number where the symbol occurs in
795 PROCEDURE GetLineNo () : CARDINAL ;
801 RETURN TokenToLineNo (GetTokenNo (), 0)
807 GetColumnNo - returns the current column where the symbol occurs in
811 PROCEDURE GetColumnNo () : CARDINAL ;
817 RETURN TokenToColumnNo (GetTokenNo (), 0)
823 GetTokenNo - returns the current token number.
826 PROCEDURE GetTokenNo () : CARDINAL ;
832 RETURN CurrentTokNo-1
838 GetTokenName - returns the token name given the tokenno.
841 PROCEDURE GetTokenName (tokenno: CARDINAL) : Name ;
846 b := FindTokenBucket (tokenno) ;
851 WITH b^.buf[tokenno] DO
852 n := tokToTok (token) ;
865 FindTokenBucket - returns the TokenBucket corresponding to the TokenNo.
868 PROCEDURE FindTokenBucket (VAR TokenNo: CARDINAL) : TokenBucket ;
872 b := ListOfTokens.head ;
885 END FindTokenBucket ;
889 TokenToLineNo - returns the line number of the current file for the
890 TokenNo. The depth refers to the include depth.
891 A depth of 0 is the current file, depth of 1 is the file
892 which included the current file. Zero is returned if the
893 depth exceeds the file nesting level.
896 PROCEDURE TokenToLineNo (TokenNo: CARDINAL; depth: CARDINAL) : CARDINAL ;
901 IF (TokenNo = UnknownTokenNo) OR (TokenNo = BuiltinTokenNo)
905 b := FindTokenBucket (TokenNo) ;
912 RETURN b^.buf[TokenNo].line
914 l := b^.buf[TokenNo].file^.left ;
917 IF l=b^.buf[TokenNo].file^.left
931 TokenToColumnNo - returns the column number of the current file for the
932 TokenNo. The depth refers to the include depth.
933 A depth of 0 is the current file, depth of 1 is the file
934 which included the current file. Zero is returned if the
935 depth exceeds the file nesting level.
938 PROCEDURE TokenToColumnNo (TokenNo: CARDINAL; depth: CARDINAL) : CARDINAL ;
943 IF (TokenNo = UnknownTokenNo) OR (TokenNo = BuiltinTokenNo)
947 b := FindTokenBucket (TokenNo) ;
954 RETURN b^.buf[TokenNo].col
956 l := b^.buf[TokenNo].file^.left ;
959 IF l=b^.buf[TokenNo].file^.left
969 END TokenToColumnNo ;
973 TokenToLocation - returns the location_t corresponding to, TokenNo.
976 PROCEDURE TokenToLocation (TokenNo: CARDINAL) : location_t ;
980 IF TokenNo = UnknownTokenNo
982 RETURN UnknownLocation ()
983 ELSIF TokenNo = BuiltinTokenNo
985 RETURN BuiltinsLocation ()
987 b := FindTokenBucket (TokenNo) ;
990 RETURN UnknownLocation ()
992 RETURN b^.buf[TokenNo].loc
995 END TokenToLocation ;
999 FindFileNameFromToken - returns the complete FileName for the appropriate
1000 source file yields the token number, TokenNo.
1001 The, Depth, indicates the include level: 0..n
1002 Level 0 is the current. NIL is returned if n+1
1006 PROCEDURE FindFileNameFromToken (TokenNo: CARDINAL; depth: CARDINAL) : String ;
1011 b := FindTokenBucket (TokenNo) ;
1016 IF TokenNo = UnknownTokenNo
1019 ELSIF TokenNo = BuiltinTokenNo
1023 l := b^.buf[TokenNo].file^.left ;
1026 IF l=b^.buf[TokenNo].file^.left
1035 END FindFileNameFromToken ;
1039 GetFileName - returns a String defining the current file.
1042 PROCEDURE GetFileName () : String ;
1044 RETURN FindFileNameFromToken (GetTokenNo (), 0)
1049 AddTokToList - adds a token to a dynamic list.
1052 PROCEDURE AddTokToList (t: toktype; n: Name;
1053 i: INTEGER; l: CARDINAL; c: CARDINAL;
1054 f: SourceList; location: location_t) ;
1056 IF ListOfTokens.head=NIL
1058 NEW (ListOfTokens.head) ;
1059 IF ListOfTokens.head=NIL
1063 ListOfTokens.tail := ListOfTokens.head ;
1064 ListOfTokens.tail^.len := 0
1065 ELSIF ListOfTokens.tail^.len=MaxBucketSize
1067 Assert(ListOfTokens.tail^.next=NIL) ;
1068 NEW (ListOfTokens.tail^.next) ;
1069 IF ListOfTokens.tail^.next=NIL
1073 ListOfTokens.tail := ListOfTokens.tail^.next ;
1074 ListOfTokens.tail^.len := 0
1076 INC (ListOfTokens.LastBucketOffset, MaxBucketSize)
1078 WITH ListOfTokens.tail^ DO
1096 IsLastTokenEof - returns TRUE if the last token was an eoftok
1099 PROCEDURE IsLastTokenEof () : BOOLEAN ;
1103 IF ListOfTokens.tail#NIL
1105 IF ListOfTokens.tail^.len=0
1107 b := ListOfTokens.head ;
1108 IF b=ListOfTokens.tail
1112 WHILE b^.next#ListOfTokens.tail DO
1116 b := ListOfTokens.tail
1119 Assert (len>0) ; (* len should always be >0 *)
1120 RETURN buf[len-1].token=eoftok
1124 END IsLastTokenEof ;
1128 PrintTokenNo - displays token and the location of the token.
1131 PROCEDURE PrintTokenNo (tokenno: CARDINAL) ;
1135 printf1 ("tokenno = %d, ", tokenno) ;
1136 s := InitStringCharStar (KeyToCharStar (GetTokenName (tokenno))) ;
1137 printf1 ("%s\n", s) ;
1143 isSrcToken - returns TRUE if tokenno is associated with
1144 program source code.
1147 PROCEDURE isSrcToken (tokenno: CARDINAL) : BOOLEAN ;
1149 RETURN (tokenno # UnknownTokenNo) AND (tokenno # BuiltinTokenNo)
1154 MakeVirtualTok - providing caret, left, right are associated with a source file
1155 and exist on the same src line then
1156 create and return a new tokenno which is created from
1157 tokenno range1 and range2. Otherwise return caret.
1160 PROCEDURE MakeVirtualTok (caret, left, right: CARDINAL) : CARDINAL ;
1162 bufLeft, bufRight: TokenBucket ;
1163 lc, ll, lr : location_t ;
1165 IF isSrcToken (caret) AND isSrcToken (left) AND isSrcToken (right)
1167 lc := TokenToLocation (caret) ;
1168 ll := TokenToLocation (left) ;
1169 lr := TokenToLocation (right) ;
1170 bufLeft := FindTokenBucket (left) ; (* left maybe changed now. *)
1171 bufRight := FindTokenBucket (right) ; (* right maybe changed now. *)
1173 IF (bufLeft^.buf[left].line = bufRight^.buf[right].line) AND
1174 (bufLeft^.buf[left].file = bufRight^.buf[right].file)
1176 (* on the same line, create a new token and location. *)
1177 AddTokToList (virtualrangetok, NulName, 0,
1178 bufLeft^.buf[left].line, bufLeft^.buf[left].col, bufLeft^.buf[left].file,
1179 GetLocationBinary (lc, ll, lr)) ;
1180 RETURN ListOfTokens.LastBucketOffset + ListOfTokens.tail^.len - 1
1184 END MakeVirtualTok ;
1187 (* ***********************************************************************
1189 * These functions allow m2.flex to deliver tokens into the buffer
1191 ************************************************************************* *)
1194 AddTok - adds a token to the buffer.
1197 PROCEDURE AddTok (t: toktype) ;
1205 IF NOT ((t=eoftok) AND IsLastTokenEof())
1207 AddTokToList(t, NulName, 0,
1208 m2flex.GetLineNo(), m2flex.GetColumnNo(), CurrentSource,
1209 m2flex.GetLocation()) ;
1210 CurrentUsed := TRUE ;
1213 (* display each token as a warning. *)
1214 s := InitStringCharStar (KeyToCharStar (GetTokenName (GetTokenNo ()))) ;
1215 WarnStringAt (s, GetTokenNo ())
1222 AddTokCharStar - adds a token to the buffer and an additional string, s.
1223 A copy of string, s, is made.
1226 PROCEDURE AddTokCharStar (t: toktype; s: ADDRESS) ;
1228 AddTokToList(t, makekey(s), 0, m2flex.GetLineNo(),
1229 m2flex.GetColumnNo(), CurrentSource, m2flex.GetLocation()) ;
1231 END AddTokCharStar ;
1235 AddTokInteger - adds a token and an integer to the buffer.
1238 PROCEDURE AddTokInteger (t: toktype; i: INTEGER) ;
1244 l := m2flex.GetLineNo() ;
1245 c := m2flex.GetColumnNo() ;
1246 s := Sprintf1(Mark(InitString('%d')), i) ;
1247 AddTokToList(t, makekey(string(s)), i, l, c, CurrentSource, m2flex.GetLocation()) ;
1248 s := KillString(s) ;