~ubuntu-branches/ubuntu/vivid/lazarus/vivid

« back to all changes in this revision

Viewing changes to converter/convcodetool.pas

  • Committer: Package Import Robot
  • Author(s): Paul Gevers, Abou Al Montacir, Paul Gevers
  • Date: 2014-02-22 10:25:57 UTC
  • mfrom: (1.1.11)
  • Revision ID: package-import@ubuntu.com-20140222102557-ors9d31r84nz31jq
Tags: 1.2~rc2+dfsg-1
[ Abou Al Montacir ]
* New upstream pre-release.
  + Moved ideintf to components directory.
  + Added new package cairocanvas.
* Remove usage of depreciated parameters form of find. (Closes: Bug#724776)
* Bumped standard version to 3.9.5.
* Clean the way handling make files generation and removal.

[ Paul Gevers ]
* Remove nearly obsolete bzip compression for binary packages
  (See https://lists.debian.org/debian-devel/2014/01/msg00542.html)
* Update d/copyright for newly added dir in examples and components
* Update Vcs-* fields with new packaging location
* Update d/watch file to properly (Debian way) change upstreams versions
* Prevent 46MB of package size by sym linking duplicate files
* Patches
  - refresh to remove fuzz
  - add more Lintian found spelling errors
  - new patch to add shbang to two scripts in lazarus-src
* Drop lcl-# from Provides list of lcl-units-#
* Make lazarus-ide-qt4-# an arch all until it really contains stuff
* Make all metapackages arch all as the usecase for arch any doesn't
  seem to warrant the addition archive hit
* Fix permissions of non-scripts in lazarus-src-#

Show diffs side-by-side

added added

removed removed

Lines of Context:
35
35
  Classes, SysUtils, FileProcs, Forms, Controls, DialogProcs, Dialogs,
36
36
  contnrs, strutils,
37
37
  // IDE
38
 
  LazarusIDEStrConsts, LazIDEIntf, FormEditor, IDEMsgIntf,
 
38
  LazarusIDEStrConsts, LazIDEIntf, FormEditor, IDEMsgIntf, IDEExternToolIntf,
39
39
  // codetools
40
 
  CodeToolManager, StdCodeTools, CodeTree, CodeAtom, AVL_Tree,
 
40
  CodeToolManager, StdCodeTools, CodeTree, CodeAtom,
41
41
  FindDeclarationTool, PascalReaderTool, PascalParserTool, LFMTrees,
42
42
  ExprEval, KeywordFuncLists, BasicCodeTools, LinkScanner,
43
43
  CodeCache, SourceChanger, CustomCodeTool, CodeToolsStructs, EventCodeTool,
54
54
    fCodeTool: TCodeTool;
55
55
    fCode: TCodeBuffer;
56
56
    fSrcCache: TSourceChangeCache;
57
 
    fAskAboutError: Boolean;
 
57
    fAskAboutError: boolean;
58
58
    fSettings: TConvertSettings;          // Conversion settings.
59
59
    procedure InitCodeTool;
60
 
    function HandleCodetoolError: TModalResult;
61
60
  public
62
61
    constructor Create(ACode: TCodeBuffer);
63
62
    destructor Destroy; override;
64
63
    procedure ResetMainScanner;
 
64
    function DummyReplacements: Boolean;
65
65
  public
66
66
    property CodeTool: TCodeTool read fCodeTool;
67
67
    property Code: TCodeBuffer read fCode;
68
68
    property SrcCache: TSourceChangeCache read fSrcCache;
69
 
    property AskAboutError: Boolean read fAskAboutError write fAskAboutError;
 
69
    property AskAboutError: boolean read fAskAboutError write fAskAboutError;
70
70
    property Settings: TConvertSettings read fSettings write fSettings;
71
71
  end;
72
72
 
76
76
  private
77
77
    fCTLink: TCodeToolLink;
78
78
    fCTLinkCreated: boolean;
79
 
    fIsConsoleApp: Boolean;
 
79
    fIsConsoleApp: boolean;
80
80
    fHasFormFile: boolean;
81
 
    fLowerCaseRes: boolean;
 
81
    fResAction: TResAction;
82
82
    fAddUnitEvent: TAddUnitEvent;
83
83
    // Delphi Function names to replace with FCL/LCL functions.
84
84
    fDefinedProcNames: TStringList;
95
95
    destructor Destroy; override;
96
96
    function Convert: TModalResult;
97
97
    function FindApptypeConsole: boolean;
 
98
    function RenameUnitIfNeeded: boolean;
98
99
    function RenameResourceDirectives: boolean;
99
100
    function FixMainClassAncestor(const AClassName: string;
100
101
                                  AReplaceTypes: TStringToStringTree): boolean;
101
102
  public
102
 
    property IsConsoleApp: Boolean read fIsConsoleApp write fIsConsoleApp;
 
103
    property IsConsoleApp: boolean read fIsConsoleApp write fIsConsoleApp;
103
104
    property HasFormFile: boolean read fHasFormFile write fHasFormFile;
104
 
    property LowerCaseRes: boolean read fLowerCaseRes write fLowerCaseRes;
 
105
    property ResAction: TResAction read fResAction write fResAction;
105
106
    property AddUnitEvent: TAddUnitEvent read fAddUnitEvent write fAddUnitEvent;
106
107
  end;
107
108
 
129
130
  fCodeTool:=nil;
130
131
  fSrcCache:=nil;
131
132
  if not CodeToolBoss.InitCurCodeTool(fCode) then exit;
132
 
  try
133
 
    fCodeTool:=CodeToolBoss.CurCodeTool;
134
 
    fSrcCache:=CodeToolBoss.SourceChangeCache;
135
 
    ResetMainScanner;
136
 
  except
137
 
    on e: Exception do
138
 
      CodeToolBoss.HandleException(e);
139
 
  end;
 
133
  fCodeTool:=CodeToolBoss.CurCodeTool;
 
134
  fSrcCache:=CodeToolBoss.SourceChangeCache;
 
135
  ResetMainScanner;
 
136
  fCodeTool.Scanner.IgnoreMissingIncludeFiles:=True;
140
137
end;
141
138
 
142
139
procedure TCodeToolLink.ResetMainScanner;
144
141
  fSrcCache.MainScanner:=fCodeTool.Scanner;
145
142
end;
146
143
 
147
 
function TCodeToolLink.HandleCodetoolError: TModalResult;
148
 
// returns mrOk or mrAbort
149
 
const
150
 
  CodetoolsFoundError='The codetools found an error in unit %s:%s%s%s';
 
144
function TCodeToolLink.DummyReplacements: Boolean;
 
145
// If Codetools cannot parse the code, do dummy replacement for all reserved words:
 
146
//  '.'+ReservedWord -> '.&'+ReservedWord, needed for OleVariant.
 
147
// Most Codetools functions cannot be used because the code is invalid,
 
148
//  but TSourceChangeCache.ReplaceEx works.
151
149
var
152
 
  ErrMsg: String;
 
150
  p, AStart: Integer;
 
151
  Src: string;
 
152
  LastWasPoint: Boolean;
153
153
begin
154
 
  ErrMsg:=CodeToolBoss.ErrorMessage;
155
 
  LazarusIDE.DoJumpToCodeToolBossError;
156
 
  if fAskAboutError then begin
157
 
    Result:=QuestionDlg(lisCCOErrorCaption,
158
 
      Format(CodetoolsFoundError, [ExtractFileName(fCode.Filename), #13, ErrMsg, #13]),
159
 
      mtWarning, [mrIgnore, lisIgnoreAndContinue, mrAbort], 0);
160
 
    if Result=mrIgnore then Result:=mrOK;
161
 
  end else begin
162
 
    Result:=mrOK;
163
 
  end;
 
154
  p:=1;
 
155
  LastWasPoint:=false;
 
156
  Src:=fCode.Source;
 
157
  repeat
 
158
    ReadRawNextPascalAtom(Src,p,AStart,false);
 
159
    if p>length(Src) then break;
 
160
    // Reserved words are in WordIsKeyWord list in CodeTools.
 
161
    if LastWasPoint and WordIsKeyWord.DoIdentifier(@Src[AStart]) then
 
162
    begin
 
163
      // '.'+ReservedWord was found
 
164
      if not fSrcCache.ReplaceEx(gtNone,gtNone,1,1,fCode,AStart,AStart,'&') then
 
165
        Exit(False);
 
166
    end;
 
167
    LastWasPoint:=Src[AStart]='.';
 
168
  until false;
 
169
  // Apply the changes in buffer
 
170
  if not fSrcCache.Apply then
 
171
    Exit(False);
 
172
  Result:=True;
164
173
end;
165
174
 
166
175
{ TConvDelphiCodeTool }
172
181
  inherited Create;
173
182
  fCTLink:=TCodeToolLink.Create(APascalBuffer);
174
183
  fCTLink.AskAboutError:=False;
175
 
  fLowerCaseRes:=True;
 
184
  fResAction:=raLowerCase;
176
185
  fIsConsoleApp:=False;
177
186
  fCTLinkCreated:=True;
178
 
  if fCTLink.CodeTool=nil then exit;
179
 
  try
 
187
  if Assigned(fCTLink.CodeTool) then
180
188
    fCTLink.CodeTool.BuildTree(lsrInitializationStart);
181
 
  except
182
 
    on e: Exception do
183
 
      CodeToolBoss.HandleException(e);
184
 
  end;
185
189
end;
186
190
 
187
191
constructor TConvDelphiCodeTool.Create(ACTLink: TCodeToolLink);
188
192
begin
189
193
  inherited Create;
190
194
  fCTLink:=ACTLink;
191
 
  fLowerCaseRes:=False;
 
195
  fResAction:=raNone;
192
196
  fIsConsoleApp:=False;
193
197
  fCTLinkCreated:=False;
194
198
end;
204
208
end;
205
209
 
206
210
function TConvDelphiCodeTool.Convert: TModalResult;
207
 
// add {$mode delphi} directive
208
 
// remove {$R *.dfm} or {$R *.xfm} directive
 
211
// Add {$mode delphi} directive
 
212
// Remove {$R *.dfm} or {$R *.xfm} directive
209
213
// Change {$R *.RES} to {$R *.res} if needed
210
214
// TODO: fix delphi ambiguouties like incomplete proc implementation headers
211
215
begin
212
216
  Result:=mrCancel;
213
217
  if fCTLink.CodeTool=nil then exit;
 
218
  fCTLink.SrcCache.BeginUpdate;
214
219
  try
215
 
    fCTLink.SrcCache.BeginUpdate;
216
 
    try
217
 
      // these changes can be applied together without rescan
218
 
      if not AddModeDelphiDirective then exit;
219
 
      if not RenameResourceDirectives then exit;
220
 
      if fCTLink.Settings.FuncReplaceMode=rsEnabled then
221
 
        if not ReplaceFuncCalls(fIsConsoleApp) then exit;
222
 
    finally
223
 
      fCTLink.SrcCache.EndUpdate;
224
 
    end;
225
 
    Result:=mrOK;
226
 
  except
227
 
    on e: Exception do begin
228
 
      CodeToolBoss.HandleException(e);
229
 
      Result:=fCTLink.HandleCodetoolError;
230
 
    end;
 
220
    // these changes can be applied together without rescan
 
221
    if not RenameUnitIfNeeded then exit;
 
222
    if not AddModeDelphiDirective then exit;
 
223
    if not RenameResourceDirectives then exit;
 
224
    if fCTLink.Settings.FuncReplaceMode=rsEnabled then
 
225
      if not ReplaceFuncCalls(fIsConsoleApp) then exit;
 
226
  finally
 
227
    fCTLink.SrcCache.EndUpdate;
231
228
  end;
 
229
  Result:=mrOK;
232
230
end;
233
231
 
234
232
function TConvDelphiCodeTool.FindApptypeConsole: boolean;
249
247
  end;
250
248
end;
251
249
 
 
250
function TConvDelphiCodeTool.RenameUnitIfNeeded: boolean;
 
251
// Change the unit name to match the disk name unless the disk name is all lowercase.
 
252
var
 
253
  NamePos: TAtomPosition;
 
254
  DiskNm, UnitNm: String;
 
255
begin
 
256
  Result:=false;
 
257
  //BuildTree(lsrSourceName);
 
258
  with fCTLink do begin
 
259
    DiskNm := ExtractFileNameOnly(Code.Filename);
 
260
    if LowerCase(DiskNm)<>DiskNm then begin    // Lowercase name is found always.
 
261
      if not CodeTool.GetSourceNamePos(NamePos) then exit;
 
262
      UnitNm:=copy(CodeTool.Src, NamePos.StartPos, NamePos.EndPos-NamePos.StartPos);
 
263
      if DiskNm<>UnitNm then begin
 
264
        SrcCache.MainScanner:=CodeTool.Scanner;
 
265
        SrcCache.Replace(gtNone, gtNone, NamePos.StartPos, NamePos.EndPos, DiskNm);
 
266
        if not SrcCache.Apply then exit;
 
267
        fSettings.AddLogLine(Format('Fixed unit name from %s to %s.',
 
268
                                    [UnitNm, DiskNm]));
 
269
      end;
 
270
    end;
 
271
  end;
 
272
  Result:=true;
 
273
end;
 
274
 
252
275
function TConvDelphiCodeTool.AddModeDelphiDirective: boolean;
253
276
var
254
277
  ModeDirectivePos: integer;
279
302
 
280
303
function TConvDelphiCodeTool.RenameResourceDirectives: boolean;
281
304
// rename {$R *.dfm} directive to {$R *.lfm}, or lowercase it.
282
 
// lowercase {$R *.RES} to {$R *.res}
 
305
// lowercase {$R *.RES} to {$R *.res}, or change it to a comment
283
306
var
284
 
  ParamPos, ACleanPos: Integer;
 
307
  ParamPos, CleanPos: Integer;
285
308
  Key, LowKey, NewKey: String;
286
309
  s: string;
287
310
begin
288
311
  Result:=false;
289
312
  if fCTLink.CodeTool=nil then exit;
290
 
  ACleanPos:=1;
 
313
  CleanPos:=1;
291
314
  // find $R directive
292
315
  with fCTLink.CodeTool do begin
293
316
    if Scanner=nil then exit;
294
317
    repeat
295
 
      ACleanPos:=FindNextCompilerDirectiveWithName(Src, ACleanPos, 'R',
296
 
                                                   Scanner.NestedComments, ParamPos);
297
 
      if (ACleanPos<1) or (ACleanPos>SrcLen) or (ParamPos>SrcLen-6) then break;
 
318
      CleanPos:=FindNextCompilerDirectiveWithName(Src, CleanPos, 'R',
 
319
                                                  Scanner.NestedComments, ParamPos);
 
320
      if (CleanPos<1) or (CleanPos>SrcLen) or (ParamPos>SrcLen-6) then break;
298
321
      NewKey:='';
299
 
      if (Src[ACleanPos]='{') and
 
322
      if (Src[CleanPos]='{') and
300
323
         (Src[ParamPos]='*') and (Src[ParamPos+1]='.') and (Src[ParamPos+5]='}')
301
324
      then begin
302
325
        Key:=copy(Src,ParamPos+2,3);
311
334
            end
312
335
            else begin
313
336
              // Add IFDEF for .lfm and .dfm allowing Delphi to use .dfm.
314
 
              s:='{$IFNDEF FPC}'+LineEnding+
 
337
              s:='{$IFnDEF FPC}'+LineEnding+
315
338
                 '  {$R *.dfm}'+LineEnding+
316
339
                 '{$ELSE}'+LineEnding+
317
340
                 '  {$R *.lfm}'+LineEnding+
318
341
                 '{$ENDIF}';
319
 
              Result:=fCTLink.SrcCache.Replace(gtNone,gtNone,ACleanPos,ParamPos+6,s);
 
342
              if not fCTLink.SrcCache.Replace(gtNone,gtNone,CleanPos,ParamPos+6,s) then exit;
320
343
            end;
321
344
          end
322
345
          else       // Change .dfm to .lfm.
323
346
            NewKey:='lfm';
324
347
        end
325
 
        // lowercase {$R *.RES} to {$R *.res}
326
 
        else if (Key='RES') and fLowerCaseRes then
327
 
          NewKey:=LowKey;
 
348
        // lowercase {$R *.RES} to {$R *.res}, or change it to a comment
 
349
        else if LowKey='res' then begin
 
350
          case fResAction of
 
351
            raLowerCase:
 
352
              if Key='RES' then
 
353
                NewKey:=LowKey;
 
354
            raDelete:        // Make it a comment by adding a dot (.)
 
355
              if not fCTLink.SrcCache.Replace(gtNone,gtNone,CleanPos,CleanPos+1,'{.') then exit;
 
356
          end;
 
357
        end;
328
358
        // Change a single resource name.
329
 
        if NewKey<>'' then begin
330
 
          if not fCTLink.SrcCache.Replace(gtNone,gtNone,ParamPos+2,ParamPos+5,NewKey) then
331
 
            exit;
332
 
        end;
 
359
        if NewKey<>'' then
 
360
          if not fCTLink.SrcCache.Replace(gtNone,gtNone,ParamPos+2,ParamPos+5,NewKey) then exit;
333
361
      end;
334
 
      ACleanPos:=FindCommentEnd(Src, ACleanPos, Scanner.NestedComments);
 
362
      CleanPos:=FindCommentEnd(Src, CleanPos, Scanner.NestedComments);
335
363
    until false;
336
364
  end;
337
365
  Result:=true;
346
374
  OldType, NewType: String;
347
375
begin
348
376
  Result:=false;
349
 
  if fCTLink.CodeTool=nil then exit;
 
377
  Assert(Assigned(fCTLink.CodeTool));
350
378
  with fCTLink.CodeTool do begin
351
 
    if Scanner=nil then exit;
 
379
    Assert(Assigned(Scanner));
352
380
    BuildTree(lsrImplementationStart);
353
381
    // Find the class name that the main class inherits from.
354
382
    ANode:=FindClassNodeInUnit(AClassName,true,false,false,false);
384
412
  ReplacementParams: TObjectList;           // Replacement parameters.
385
413
 
386
414
  function ParseReplacementParams(const aStr: string): integer;
387
 
  // Parse replacement params. They show which original params are copied where.
 
415
  // Parse replacement params which are defined in configuration.
 
416
  // They show which original params are copied where.
388
417
  // Returns the first position where comments can be searched from.
389
418
  var
390
419
    i, xNum, xStart, xLen: Integer;
 
420
    HasBracket: Boolean;
391
421
  begin
 
422
    HasBracket:=False;
392
423
    i:=0;
393
424
    while i<Length(aStr) do begin
394
425
      Inc(i);
 
426
      if aStr[i]='(' then
 
427
        HasBracket:=True;
395
428
      if aStr[i]='$' then begin
396
429
        xStart:=i;
397
430
        Inc(i);                           // Skip '$'
399
432
          Inc(i);                         // Get the number after '$'
400
433
        xLen:=i-xStart;
401
434
        if xLen<2 then
402
 
          raise EDelphiConverterError.Create('"$" should be followed by a number.');
 
435
          raise EDelphiConverterError.Create('"$" should be followed by a number: '+ aStr);
403
436
        xNum:=StrToInt(copy(aStr, xStart+1, xLen-1)); // Leave out '$', convert number.
404
437
        if xNum < 1 then
405
438
          raise EDelphiConverterError.Create(
406
 
                           'Replacement function parameter number should be >= 1.');
 
439
                           'Replacement function parameter number should be >= 1: '+ aStr);
407
440
        ReplacementParams.Add(TReplacementParam.Create(xNum, xLen, xStart));
408
441
      end;
409
442
    end;
410
 
    if aStr[i]<>')' then
411
 
      raise EDelphiConverterError.Create('")" is missing from replacement function.');
 
443
    if HasBracket and (aStr[i]<>')') then
 
444
      raise EDelphiConverterError.Create('")" is missing from replacement function: '+ aStr);
412
445
    Result:=i+1;
413
446
  end;
414
447
 
432
465
  end;
433
466
 
434
467
  function GetComment(const aStr: string; aPossibleStartPos: integer): string;
435
 
  // Extract and return a possible comment.
 
468
  // Extract and return a possible comment from replacement function definition.
436
469
  var
437
470
    CommChBeg, CommBeg, CommEnd, i: Integer;   // Start and end of comment.
438
471
  begin
472
505
      // Replace only if the params match somehow, so eg. a variable is not replaced.
473
506
      if (FuncInfo.Params.Count>0) or (ReplacementParams.Count=0) then begin
474
507
        NewFunc:=InsertParams2Replacement(FuncInfo);
 
508
        // Separate function body
 
509
        NewFunc:=NewFunc+FuncInfo.InclEmptyBrackets+FuncInfo.InclSemiColon;
 
510
        if fCTLink.fSettings.FuncReplaceComment then
 
511
          NewFunc:=NewFunc+' { *Converted from '+FuncInfo.FuncName+'* }';
475
512
        Comment:=GetComment(FuncInfo.ReplFunc, PossibleCommentPos);
476
 
        // Separate function body
477
 
        NewFunc:=Format('%s%s { *Converted from %s* %s }',
478
 
          [NewFunc, FuncInfo.InclSemiColon, FuncInfo.FuncName, Comment]);
 
513
        if Comment<>'' then            // Possible comment from the configuration
 
514
          NewFunc:=NewFunc+' { ' +Comment+' }';
479
515
        // Old function call with params for IDE message output.
480
516
        s:=copy(fCTLink.CodeTool.Src, FuncInfo.StartPos, FuncInfo.EndPos-FuncInfo.StartPos);
481
 
        s:=StringReplace(s, LineEnding, '', [rfReplaceAll]);
 
517
        s:=StringReplace(s, #10, '', [rfReplaceAll]);
 
518
        s:=StringReplace(s, #13, '', [rfReplaceAll]);
482
519
        // Now replace it.
483
520
        fCTLink.ResetMainScanner;
484
521
        if not fCTLink.SrcCache.Replace(gtNone, gtNone,
485
522
                            FuncInfo.StartPos, FuncInfo.EndPos, NewFunc) then exit;
486
 
        IDEMessagesWindow.AddMsg('Replaced call '+s, '', -1);
487
 
        IDEMessagesWindow.AddMsg('                  with '+NewFunc, '', -1);
 
523
        fCTLink.fSettings.AddLogLine('Replaced call '+s+' with '+NewFunc);
488
524
        // Add the required unit name to uses section if needed.
489
525
        if Assigned(AddUnitEvent) and (FuncInfo.UnitName<>'') then
490
526
          AddUnitEvent(FuncInfo.UnitName);
507
543
    ReadNextAtom;               // Read proc name.
508
544
    ProcName:=GetAtom;
509
545
    ReadNextAtom;
510
 
    if GetAtom<>'.' then        // Don't save a method name (like TClass.Method).
 
546
    if GetAtom<>'.' then        // Don't save a method name (like TMyClass.Method).
511
547
      fDefinedProcNames.Add(ProcName);
512
548
  end;
513
549
  Result:=aNode.Next;
516
552
function TConvDelphiCodeTool.ReplaceFuncCalls(aIsConsoleApp: boolean): boolean;
517
553
// Copied and modified from TFindDeclarationTool.FindReferences.
518
554
// Search for calls to functions / procedures in a list from current unit's
519
 
// implementation section. Replace found calls with a given replacement.
 
555
// implementation section code. Replace found calls with a given replacement.
520
556
var
521
557
  xStart: Integer;
522
558
 
531
567
 
532
568
  procedure ReadParams(FuncInfo: TFuncReplacement);
533
569
  var
534
 
    ExprStartPos, ExprEndPos, BracketCount: integer;
 
570
    ExprStartPos, ExprEndPos: integer;
 
571
    RoundBrLvl, SquareBrLvl: integer;
 
572
    HasParams, ShouldReadNextAtom: Boolean;
535
573
  begin
 
574
    FuncInfo.InclEmptyBrackets:='';
536
575
    FuncInfo.InclSemiColon:='';
537
576
    FuncInfo.StartPos:=xStart;
538
577
    with fCTLink.CodeTool do begin
539
578
      MoveCursorToCleanPos(xStart);
540
 
      ReadNextAtom;                     // Read func name.
 
579
      ReadNextAtom;                     // Read proc name.
541
580
      ReadNextAtom;                     // Read first atom after proc name.
542
 
      if AtomIsChar('(') then begin
 
581
      HasParams:=AtomIsChar('(');
 
582
      if HasParams then begin
543
583
        // read parameter list
544
584
        ReadNextAtom;
545
 
        if not AtomIsChar(')') then begin
 
585
        // Don't read twice inside a loop. Atom can be for example '['
 
586
        ShouldReadNextAtom:=False;
 
587
        HasParams:=not AtomIsChar(')');
 
588
        if HasParams then begin
546
589
          // read all expressions
547
 
          BracketCount:=0;
 
590
          RoundBrLvl:=0;
 
591
          SquareBrLvl:=0;
548
592
          while true do begin
549
593
            ExprStartPos:=CurPos.StartPos;
550
594
            // read til comma or bracket close
551
595
            repeat
552
 
              ReadNextAtom;
553
 
              if (CurPos.StartPos>SrcLen) or (CurPos.Flag=cafComma) then
554
 
                break;
555
 
              if CurPos.Flag=cafRoundBracketOpen then
556
 
                Inc(BracketCount)
 
596
              if ShouldReadNextAtom then
 
597
                ReadNextAtom;
 
598
              ShouldReadNextAtom:=True;
 
599
              if CurPos.StartPos>SrcLen then
 
600
                break;
 
601
              if (CurPos.Flag=cafComma) and (RoundBrLvl=0) and (SquareBrLvl=0) then
 
602
                break;
 
603
              if CurPos.Flag=cafEdgedBracketOpen then
 
604
                Inc(SquareBrLvl)
 
605
              else if CurPos.Flag=cafEdgedBracketClose then
 
606
                Dec(SquareBrLvl)
 
607
              else if CurPos.Flag=cafRoundBracketOpen then
 
608
                Inc(RoundBrLvl)
557
609
              else if CurPos.Flag=cafRoundBracketClose then begin
558
 
                if BracketCount=0 then
559
 
                  break;
560
 
                Dec(BracketCount);
 
610
                if RoundBrLvl=0 then
 
611
                  break;              // Closing bracket, end of parameters
 
612
                Dec(RoundBrLvl);
561
613
              end;
562
614
            until false;
563
615
            ExprEndPos:=CurPos.StartPos;
575
627
              raise EDelphiConverterError.Create('Bracket not found');
576
628
            ReadNextAtom;
577
629
          end;
 
630
        end
 
631
        else begin
 
632
          FuncInfo.InclEmptyBrackets:='()';
 
633
          ReadNextAtom;
578
634
        end;
579
 
      end
580
 
      else begin
 
635
      end;
 
636
      if not HasParams then begin
581
637
        FuncInfo.EndPos:=CurPos.StartPos;
582
638
        CheckSemiColon(FuncInfo);
583
639
      end;
608
664
          // UTF8 funcs are in LCL which console apps don't have -> don't change.
609
665
          and not (aIsConsoleApp and (FuncDefInfo.Category='UTF8Names'))
610
666
          // Keep Windows funcs in a Windows application.
611
 
          and (fCTLink.Settings.MultiPlatform or (FuncDefInfo.Category<>'WindowsAPI'))
 
667
          and (fCTLink.Settings.CrossPlatform or (FuncDefInfo.Category<>'WindowsAPI'))
612
668
          then begin
613
669
            // Create a new replacement object for params, position and other info.
614
670
            FuncCallInfo:=TFuncReplacement.Create(FuncDefInfo);