2
0
Эх сурвалжийг харах

* fixed using readstr/writestr inside routines called from the parameter
list of another readstr/writestr expression (mantis #23912)

git-svn-id: trunk@23888 -

Jonas Maebe 12 жил өмнө
parent
commit
e1e11f81e3

+ 1 - 0
.gitattributes

@@ -13275,6 +13275,7 @@ tests/webtbs/tw2378.pp svneol=native#text/plain
 tests/webtbs/tw23819.pp -text svneol=native#text/plain
 tests/webtbs/tw2382.pp svneol=native#text/plain
 tests/webtbs/tw2388.pp svneol=native#text/plain
+tests/webtbs/tw23912.pp -text svneol=native#text/plain
 tests/webtbs/tw23962.pp svneol=native#text/plain
 tests/webtbs/tw2397.pp svneol=native#text/plain
 tests/webtbs/tw24007.pp svneol=native#text/plain

+ 34 - 29
compiler/ninl.pas

@@ -1171,9 +1171,34 @@ implementation
         { make inserting of additional statements easier                            }
         newblock:=internalstatements(newstatement);
 
+        if is_rwstr then
+          begin
+            { create a dummy temp text file that will be used to cache the
+              readstr/writestr state. Can't use a global variable in the system
+              unit because these can be nested (in case of parameters to
+              writestr that are function calls to functions that also call
+              readstr/writestr) }
+            textsym:=search_system_type('TEXT');
+            filetemp:=ctempcreatenode.create(textsym.typedef,textsym.typedef.size,tt_persistent,false);
+            addstatement(newstatement,filetemp);
+
+            if (do_read) then
+              name:='fpc_setupreadstr_'
+            else
+              name:='fpc_setupwritestr_';
+            name:=name+tstringdef(filepara.resultdef).stringtypname;
+            { remove the source/destination string parameter from the }
+            { parameter chain                                         }
+            left:=filepara.right;
+            filepara.right:=ccallparanode.create(ctemprefnode.create(filetemp),nil);
+            { pass the temp text file and the source/destination string to the
+              setup routine, which will store the string's address in the
+              textrec }
+            addstatement(newstatement,ccallnode.createintern(name,filepara));
+            filepara:=ccallparanode.create(ctemprefnode.create(filetemp),nil);
+          end
         { if we don't have a filepara, create one containing the default }
-        if not assigned(filepara) or
-           is_rwstr then
+        else if not assigned(filepara) then
           begin
             { since the input/output variables are threadvars loading them into
               a temp once is faster. Create a temp which will hold a pointer to the file }
@@ -1187,34 +1212,14 @@ implementation
             { typecheckpassed if the resultdef of the temp is known) }
             typecheckpass(tnode(filetemp));
 
-            if not is_rwstr then
-              begin
-                { assign the address of the file to the temp }
-                if do_read then
-                  name := 'input'
-                else
-                  name := 'output';
-                addstatement(newstatement,
-                  cassignmentnode.create(ctemprefnode.create(filetemp),
-                    ccallnode.createintern('fpc_get_'+name,nil)));
-              end
+            { assign the address of the file to the temp }
+            if do_read then
+              name := 'input'
             else
-              begin
-                if (do_read) then
-                  name := 'fpc_setupreadstr_'
-                else
-                  name := 'fpc_setupwritestr_';
-                name:=name+tstringdef(filepara.resultdef).stringtypname;
-                { remove the source/destination string parameter from the }
-                { parameter chain                                         }
-                left:=filepara.right;
-                filepara.right:=nil;
-                { pass the source/destination string to the setup routine, which }
-                { will store the string's address in the returned textrec        }
-                addstatement(newstatement,
-                  cassignmentnode.create(ctemprefnode.create(filetemp),
-                    ccallnode.createintern(name,filepara)));
-              end;
+              name := 'output';
+            addstatement(newstatement,
+              cassignmentnode.create(ctemprefnode.create(filetemp),
+                ccallnode.createintern('fpc_get_'+name,nil)));
 
             { create a new fileparameter as follows: file_type(temp^)    }
             { (so that we pass the value and not the address of the temp }

+ 8 - 8
rtl/inc/compproc.inc

@@ -376,26 +376,26 @@ Procedure fpc_Write_Text_WideChar(Len : Longint;var t : Text;c : WideChar); comp
 
 { all var rather than out, because they must not be trashed/finalized as they
   can appear inside the other arguments of writerstr }
-function fpc_SetupWriteStr_Shortstr(var s: shortstring): PText; compilerproc;
+procedure fpc_SetupWriteStr_Shortstr(var ReadWriteStrText: text; var s: shortstring); compilerproc;
 {$ifdef FPC_HAS_FEATURE_ANSISTRINGS}
-function fpc_SetupWriteStr_Ansistr(var s: ansistring): PText; compilerproc;
+procedure fpc_SetupWriteStr_Ansistr(var ReadWriteStrText: text; var s: ansistring); compilerproc;
 {$endif FPC_HAS_FEATURE_ANSISTRINGS}
 {$ifdef FPC_HAS_FEATURE_WIDESTRINGS}
-function fpc_SetupWriteStr_Unicodestr(var s: unicodestring): PText; compilerproc;
+procedure fpc_SetupWriteStr_Unicodestr(var ReadWriteStrText: text; var s: unicodestring); compilerproc;
 {$endif FPC_HAS_FEATURE_WIDESTRINGS}
 {$ifndef FPC_WIDESTRING_EQUAL_UNICODESTRING}
-function fpc_SetupWriteStr_Widestr(var s: widestring): PText; compilerproc;
+procedure fpc_SetupWriteStr_Widestr(var ReadWriteStrText: text; var s: widestring); compilerproc;
 {$endif FPC_WIDESTRING_EQUAL_UNICODESTRING}
 
-function fpc_SetupReadStr_Shortstr(const s: shortstring): PText; compilerproc;
+procedure fpc_SetupReadStr_Shortstr(var ReadWriteStrText: text; const s: shortstring); compilerproc;
 {$ifdef FPC_HAS_FEATURE_ANSISTRINGS}
-function fpc_SetupReadStr_Ansistr(const s: ansistring): PText; compilerproc;
+procedure fpc_SetupReadStr_Ansistr(var ReadWriteStrText: text; const s: ansistring); compilerproc;
 {$endif FPC_HAS_FEATURE_ANSISTRINGS}
 {$ifdef FPC_HAS_FEATURE_WIDESTRINGS}
-function fpc_SetupReadStr_Unicodestr(const s: unicodestring): PText; compilerproc;
+procedure fpc_SetupReadStr_Unicodestr(var ReadWriteStrText: text; const s: unicodestring); compilerproc;
 {$endif FPC_HAS_FEATURE_WIDESTRINGS}
 {$ifndef FPC_WIDESTRING_EQUAL_UNICODESTRING}
-function fpc_SetupReadStr_Widestr(const s: widestring): PText; compilerproc;
+procedure fpc_SetupReadStr_Widestr(var ReadWriteStrText: text; const s: widestring); compilerproc;
 {$endif FPC_WIDESTRING_EQUAL_UNICODESTRING}
 { $endif FPC_HAS_FEATURE_TEXTIO}
 

+ 38 - 50
rtl/inc/text.inc

@@ -1893,13 +1893,6 @@ const
   { how many bytes of the string have been processed already (used for readstr) }
   BytesReadIndex = 17;
 
-{$ifdef FPC_HAS_FEATURE_THREADING}
-ThreadVar
-{$else FPC_HAS_FEATURE_THREADING}
-Var
-{$endif FPC_HAS_FEATURE_THREADING}
-  ReadWriteStrText: textrec;
-
 procedure WriteStrShort(var t: textrec);
 var
   str: pshortstring;
@@ -2041,66 +2034,62 @@ begin
 end;
 
 
-function fpc_SetupWriteStr_Shortstr(var s: shortstring): PText; compilerproc;
+procedure fpc_SetupWriteStr_Shortstr(var ReadWriteStrText: text; var s: shortstring); compilerproc;
 begin
-  setupwritestrcommon(ReadWriteStrText);
-  PPointer(@ReadWriteStrText.userdata[StrPtrIndex])^:=@s;
+  setupwritestrcommon(TextRec(ReadWriteStrText));
+  PPointer(@TextRec(ReadWriteStrText).userdata[StrPtrIndex])^:=@s;
 
   { temporary destination (see comments for TempWriteStrDestIndex) }
-  getmem(PPointer(@ReadWriteStrText.userdata[TempWriteStrDestIndex])^,high(s)+1);
-  setlength(pshortstring(ppointer(@ReadWriteStrText.userdata[TempWriteStrDestIndex])^)^,0);
+  getmem(PPointer(@TextRec(ReadWriteStrText).userdata[TempWriteStrDestIndex])^,high(s)+1);
+  setlength(pshortstring(ppointer(@TextRec(ReadWriteStrText).userdata[TempWriteStrDestIndex])^)^,0);
 
-  ReadWriteStrText.userdata[ShortStrLenIndex]:=high(s);
-  ReadWriteStrText.InOutFunc:=@WriteStrShort;
-  ReadWriteStrText.FlushFunc:=@WriteStrShortFlush;
-  result:=@ReadWriteStrText;
+  TextRec(ReadWriteStrText).userdata[ShortStrLenIndex]:=high(s);
+  TextRec(ReadWriteStrText).InOutFunc:=@WriteStrShort;
+  TextRec(ReadWriteStrText).FlushFunc:=@WriteStrShortFlush;
 end;
 
 
 {$ifdef FPC_HAS_FEATURE_ANSISTRINGS}
-function fpc_SetupWriteStr_Ansistr(var s: ansistring): PText; compilerproc;
+procedure fpc_SetupWriteStr_Ansistr(var ReadWriteStrText: text; var s: ansistring); compilerproc;
 begin
-  setupwritestrcommon(ReadWriteStrText);
-  PPointer(@ReadWriteStrText.userdata[StrPtrIndex])^:=@s;
+  setupwritestrcommon(TextRec(ReadWriteStrText));
+  PPointer(@TextRec(ReadWriteStrText).userdata[StrPtrIndex])^:=@s;
 
   { temp destination ansistring, nil = empty string }
-  PPointer(@ReadWriteStrText.userdata[TempWriteStrDestIndex])^:=nil;
+  PPointer(@TextRec(ReadWriteStrText).userdata[TempWriteStrDestIndex])^:=nil;
 
-  ReadWriteStrText.InOutFunc:=@WriteStrAnsi;
-  ReadWriteStrText.FlushFunc:=@WriteStrAnsiFlush;
-  result:=@ReadWriteStrText;
+  TextRec(ReadWriteStrText).InOutFunc:=@WriteStrAnsi;
+  TextRec(ReadWriteStrText).FlushFunc:=@WriteStrAnsiFlush;
 end;
 {$endif FPC_HAS_FEATURE_ANSISTRINGS}
 
 
 {$ifdef FPC_HAS_FEATURE_WIDESTRINGS}
-function fpc_SetupWriteStr_Unicodestr(var s: unicodestring): PText; compilerproc;
+procedure fpc_SetupWriteStr_Unicodestr(var ReadWriteStrText: text; var s: unicodestring); compilerproc;
 begin
-  setupwritestrcommon(ReadWriteStrText);
-  PPointer(@ReadWriteStrText.userdata[StrPtrIndex])^:=@s;
+  setupwritestrcommon(TextRec(ReadWriteStrText));
+  PPointer(@TextRec(ReadWriteStrText).userdata[StrPtrIndex])^:=@s;
 
   { temp destination unicodestring, nil = empty string }
-  PPointer(@ReadWriteStrText.userdata[TempWriteStrDestIndex])^:=nil;
+  PPointer(@TextRec(ReadWriteStrText).userdata[TempWriteStrDestIndex])^:=nil;
 
-  ReadWriteStrText.InOutFunc:=@WriteStrUnicode;
-  ReadWriteStrText.FlushFunc:=@WriteStrUnicodeFlush;
-  result:=@ReadWriteStrText;
+  TextRec(ReadWriteStrText).InOutFunc:=@WriteStrUnicode;
+  TextRec(ReadWriteStrText).FlushFunc:=@WriteStrUnicodeFlush;
 end;
 {$endif FPC_HAS_FEATURE_WIDESTRINGS}
 
 
 {$ifndef FPC_WIDESTRING_EQUAL_UNICODESTRING}
-function fpc_SetupWriteStr_Widestr(var s: widestring): PText; compilerproc;
+procedure fpc_SetupWriteStr_Widestr(var ReadWriteStrText: text; var s: widestring); compilerproc;
 begin
-  setupwritestrcommon(ReadWriteStrText);
-  PPointer(@ReadWriteStrText.userdata[StrPtrIndex])^:=@s;
+  setupwritestrcommon(TextRec(ReadWriteStrText));
+  PPointer(@TextRec(ReadWriteStrText).userdata[StrPtrIndex])^:=@s;
 
   { temp destination widestring }
-  PWideString(@ReadWriteStrText.userdata[TempWriteStrDestIndex])^:='';
+  PWideString(@TextRec(ReadWriteStrText).userdata[TempWriteStrDestIndex])^:='';
 
-  ReadWriteStrText.InOutFunc:=@WriteStrWide;
-  ReadWriteStrText.FlushFunc:=@WriteStrWideFlush;
-  result:=@ReadWriteStrText;
+  TextRec(ReadWriteStrText).InOutFunc:=@WriteStrWide;
+  TextRec(ReadWriteStrText).FlushFunc:=@WriteStrWideFlush;
 end;
 {$endif FPC_WIDESTRING_EQUAL_UNICODESTRING}
 
@@ -2155,22 +2144,21 @@ end;
 
 
 {$ifdef FPC_HAS_FEATURE_ANSISTRINGS}
-function fpc_SetupReadStr_Ansistr(const s: ansistring): PText; [public, alias: 'FPC_SETUPREADSTR_ANSISTR']; compilerproc;
+procedure fpc_SetupReadStr_Ansistr(var ReadWriteStrText: text; const s: ansistring); [public, alias: 'FPC_SETUPREADSTR_ANSISTR']; compilerproc;
 begin
-  setupreadstrcommon(ReadWriteStrText);
+  setupreadstrcommon(TextRec(ReadWriteStrText));
   { we need a reference, because 's' may be a temporary expression }
-  PAnsiString(@ReadWriteStrText.userdata[StrPtrIndex])^:=s;
-  ReadWriteStrText.InOutFunc:=@ReadStrAnsi;
+  PAnsiString(@TextRec(ReadWriteStrText).userdata[StrPtrIndex])^:=s;
+  TextRec(ReadWriteStrText).InOutFunc:=@ReadStrAnsi;
   { this is called at the end, by fpc_read_end }
-  ReadWriteStrText.FlushFunc:=@ReadAnsiStrFinal;
-  result:=@ReadWriteStrText;
+  TextRec(ReadWriteStrText).FlushFunc:=@ReadAnsiStrFinal;
 end;
 
-function fpc_SetupReadStr_Ansistr_Intern(const s: ansistring): PText; [external name 'FPC_SETUPREADSTR_ANSISTR'];
+procedure fpc_SetupReadStr_Ansistr_Intern(var ReadWriteStrText: text; const s: ansistring); [external name 'FPC_SETUPREADSTR_ANSISTR'];
 {$endif FPC_HAS_FEATURE_ANSISTRINGS}
 
 
-function fpc_SetupReadStr_Shortstr(const s: shortstring): PText; compilerproc;
+procedure fpc_SetupReadStr_Shortstr(var ReadWriteStrText: text; const s: shortstring); compilerproc;
 begin
   { the reason we convert the short string to ansistring, is because the semantics of
     readstr are defined as:
@@ -2197,7 +2185,7 @@ begin
     to use the other ansistring readstr helpers too.
   }
 {$ifdef FPC_HAS_FEATURE_ANSISTRINGS}
-  result:=fpc_SetupReadStr_Ansistr_Intern(s);
+  fpc_SetupReadStr_Ansistr_Intern(ReadWriteStrText,s);
 {$else FPC_HAS_FEATURE_ANSISTRINGS}
   runerror(217);
 {$endif FPC_HAS_FEATURE_ANSISTRINGS}
@@ -2205,21 +2193,21 @@ end;
 
 
 {$ifdef FPC_HAS_FEATURE_WIDESTRINGS}
-function fpc_SetupReadStr_Unicodestr(const s: unicodestring): PText; compilerproc;
+procedure fpc_SetupReadStr_Unicodestr(var ReadWriteStrText: text; const s: unicodestring); compilerproc;
 begin
   { we use an ansistring to avoid code duplication, and let the    }
   { assignment convert the widestring to an equivalent ansistring  }
-  result:=fpc_SetupReadStr_Ansistr_Intern(s);
+  fpc_SetupReadStr_Ansistr_Intern(ReadWriteStrText,s);
 end;
 {$endif FPC_HAS_FEATURE_WIDESTRINGS}
 
 
 {$ifndef FPC_WIDESTRING_EQUAL_UNICODESTRING}
-function fpc_SetupReadStr_Widestr(const s: widestring): PText; compilerproc;
+procedure fpc_SetupReadStr_Widestr(var ReadWriteStrText: text; const s: widestring); compilerproc;
 begin
   { we use an ansistring to avoid code duplication, and let the    }
   { assignment convert the widestring to an equivalent ansistring  }
-  result:=fpc_SetupReadStr_Ansistr_Intern(s);
+  fpc_SetupReadStr_Ansistr_Intern(ReadWriteStrText,s);
 end;
 {$endif FPC_WIDESTRING_EQUAL_UNICODESTRING}
 

+ 8 - 8
rtl/java/jcompproc.inc

@@ -340,26 +340,26 @@ Procedure fpc_Write_Text_WideChar(Len : Longint;var t : Text;c : WideChar); comp
 
 { all var rather than out, because they must not be trashed/finalized as they
   can appear inside the other arguments of writerstr }
-function fpc_SetupWriteStr_Shortstr(var s: shortstring): PText; compilerproc;
+procedure fpc_SetupWriteStr_Shortstr(var ReadWriteStrText: text; var s: shortstring); compilerproc;
 {$ifdef FPC_HAS_FEATURE_ANSISTRINGS}
-function fpc_SetupWriteStr_Ansistr(var s: ansistring): PText; compilerproc;
+procedure fpc_SetupWriteStr_Ansistr(var ReadWriteStrText: text; var s: ansistring); compilerproc;
 {$endif FPC_HAS_FEATURE_ANSISTRINGS}
 {$ifdef FPC_HAS_FEATURE_WIDESTRINGS}
-function fpc_SetupWriteStr_Unicodestr(var s: unicodestring): PText; compilerproc;
+procedure fpc_SetupWriteStr_Unicodestr(var ReadWriteStrText: text; var s: unicodestring); compilerproc;
 {$endif FPC_HAS_FEATURE_WIDESTRINGS}
 {$ifndef FPC_WIDESTRING_EQUAL_UNICODESTRING}
-function fpc_SetupWriteStr_Widestr(var s: widestring): PText; compilerproc;
+procedure fpc_SetupWriteStr_Widestr(var ReadWriteStrText: text; var s: widestring); compilerproc;
 {$endif FPC_WIDESTRING_EQUAL_UNICODESTRING}
 
-function fpc_SetupReadStr_Shortstr(const s: shortstring): PText; compilerproc;
+procedure fpc_SetupReadStr_Shortstr(var ReadWriteStrText: text; const s: shortstring); compilerproc;
 {$ifdef FPC_HAS_FEATURE_ANSISTRINGS}
-function fpc_SetupReadStr_Ansistr(const s: ansistring): PText; compilerproc;
+procedure fpc_SetupReadStr_Ansistr(var ReadWriteStrText: text; const s: ansistring); compilerproc;
 {$endif FPC_HAS_FEATURE_ANSISTRINGS}
 {$ifdef FPC_HAS_FEATURE_WIDESTRINGS}
-function fpc_SetupReadStr_Unicodestr(const s: unicodestring): PText; compilerproc;
+procedure fpc_SetupReadStr_Unicodestr(var ReadWriteStrText: text; const s: unicodestring); compilerproc;
 {$endif FPC_HAS_FEATURE_WIDESTRINGS}
 {$ifndef FPC_WIDESTRING_EQUAL_UNICODESTRING}
-function fpc_SetupReadStr_Widestr(const s: widestring): PText; compilerproc;
+procedure fpc_SetupReadStr_Widestr(var ReadWriteStrText: text; const s: widestring); compilerproc;
 {$endif FPC_WIDESTRING_EQUAL_UNICODESTRING}
 {$endif FPC_HAS_FEATURE_TEXTIO}
 

+ 93 - 0
tests/webtbs/tw23912.pp

@@ -0,0 +1,93 @@
+program crash_2_7_1;
+
+{$mode objfpc}{$H+}
+
+//uses
+
+type
+  TSynCommentType = (sctAnsi, sctBor, sctSlash);
+  TSynCommentIndentFlag = (
+    // * For Matching lines (FCommentMode)
+      // By default indent is the same as for none comment lines (none overrides sciAlignOpen)
+      sciNone,      // Does not Indent comment lines (Prefix may contain a fixed indent)
+      sciAlignOpen, // Indent to real opening pos on first line, if comment does not start at BOL "Foo(); (*"
+      sciAddTokenLen,        // add 1 or 2 spaces to indent (for the length of the token)
+      sciAddPastTokenIndent, // Adds any indent found past the opening token  "(*", "{" or "//".
+      sciMatchOnlyTokenLen,        // Apply the Above only if first line matches. (Only if sciAddTokenLen is specified)
+      sciMatchOnlyPastTokenIndent,
+      sciAlignOnlyTokenLen,        // Apply the Above only if sciAlignOpen was used (include via max)
+      sciAlignOnlyPastTokenIndent,
+      sciApplyIndentForNoMatch  // Apply above rules For NONE Matching lines (FCommentMode),
+                                // includes FIndentFirstLineExtra
+    );
+  TSynCommentIndentFlags = set of TSynCommentIndentFlag;
+  TSynCommentContineMode = (
+      sccNoPrefix,      // May still do indent, if matched
+      sccPrefixAlways,  // If the pattern did not match all will be done, except the indent AFTER the prefix (can not be detected)
+      sccPrefixMatch
+    );
+  TSynCommentMatchMode = (
+      scmMatchAfterOpening, // will not include (*,{,//. The ^ will match the first char after
+      scmMatchOpening,      // will include (*,{,//. The ^ will match the ({/
+      scmMatchWholeLine,    // Match the entire line
+      scmMatchAtAsterisk    // AnsiComment only, will match the * of (*, but not the (
+    );
+  TSynCommentMatchLine = (
+      sclMatchFirst, // Match the first line of the comment to get substitutes for Prefix ($1)
+      sclMatchPrev   // Match the previous line of the comment to get substitutes for Prefix ($1)
+    );
+  TSynBeautifierIndentType = (sbitSpace, sbitCopySpaceTab, sbitPositionCaret);
+  TSynCommentExtendMode = (
+      sceNever,                // Never Extend
+      sceAlways,               // Always
+      sceSplitLine,            // If the line was split (caret was not at EOL, when enter was pressed
+      sceMatching,             // If the line matched (even if sccPrefixAlways or sccNoPrefix
+      sceMatchingSplitLine
+    );
+
+
+function dbgs(AIndentFlag: TSynCommentIndentFlag): String;
+begin
+  Result := ''; WriteStr(Result, AIndentFlag);
+end;
+
+function dbgs(AIndentFlags: TSynCommentIndentFlags): String;
+var
+  i: TSynCommentIndentFlag;
+begin
+  Result := '';
+  for i := low(TSynCommentIndentFlag) to high(TSynCommentIndentFlag) do
+    if i in AIndentFlags then
+      if Result = ''
+      then Result := dbgs(i)
+      else Result := Result + ',' + dbgs(i);
+  if Result <> '' then
+    Result := '[' + Result + ']';
+end;
+
+
+procedure Foo(Atype: TSynCommentType;
+    AIndentMode: TSynCommentIndentFlags;
+    AIndentFirstLineMax:   Integer; AIndentFirstLineExtra: String;
+    ACommentMode: TSynCommentContineMode; AMatchMode: TSynCommentMatchMode;
+    AMatchLine: TSynCommentMatchLine; ACommentIndent: TSynBeautifierIndentType;
+    AMatch: String;  APrefix: String;
+    AExtenbSlash: TSynCommentExtendMode = sceNever);
+var
+  s: String;
+begin
+    writestr(s, AType,':',
+             ' IMode=', dbgs(AIndentMode), ' IMax=', AIndentFirstLineMax, ' IExtra=', AIndentFirstLineExtra,
+             ' CMode=', ACommentMode, ' CMatch=', AMatchMode, ' CLine=', AMatchLine,
+             ' M=''', AMatch, ''' R=''', APrefix, ''' CIndent=', ACommentIndent
+            );
+    if s<>'sctAnsi: IMode=[sciAddTokenLen] IMax=5 IExtra=   CMode=sccPrefixMatch CMatch=scmMatchOpening CLine=sclMatchPrev M=''.'' R=''+'' CIndent=sbitCopySpaceTab' then
+      halt(1);
+end;
+
+begin
+  Foo(sctAnsi, [sciAddTokenLen], 5, '  ', sccPrefixMatch, scmMatchOpening,
+      sclMatchPrev, sbitCopySpaceTab, '.', '+');
+
+end.
+