// kate: space-indent on; indent-width 3; replace-tabs on; remove-trailing-spaces all;
// kate: syntax pascal; indent-mode pascal;

// these variables are understood by the pascal indenter ...
// kate: cfgIndentCase true;          // indent elements in a case statement
// kate: cfgIndentBegin 2;            // indent 'begin' this many spaces
// kate: debugMode false;              // show how indent is determined
// kate: cfgAutoInsertStar true;      // auto insert '*' in (* ... *)-comments
// kate: cfgSnapParen true;           // snap ')' to '*)' in comments


function f1( var z: integer;
var p,q : real;
t : boolean	   ) : integer; // indentation should line up

type   tArray = array[0..17] of real;

r= record a: integer; c: char; end;

// nested variant record - too hard to get right. tough
MyRec = Record
X : Longint;
Case byte of
1,2,8 : (Y : Longint;
               case byte of
               3 : (Z : Longint);   // CHECK: parens inside parens aligned correctly
         );
end;

                                                   commands = (    crsupp,crbefore,blinbefore,
                                                                  dindonkey,dindent,spbef,
spaft,gobsym,
inbytab,   { indent current margin (was indent from symbol pos) }
crafter,
finl            { force symbol to follow on same line as previous symbol }
);

tR = record
i: integer;  // should indent after record
r: real;
a: array[1..11] of char;

case boolean of
true:( a: int);
dontKnow:
(z: real;
 fred : real;       // should be indented after case value
joe  : integer;
);
false:
(  ted : array[
                  1..16
] of boolean;
moe: char; // should align to ''ted''
);
end; // end of case + end of record

commandset = set of commands;       // should be aligned to 'record', not 'case'

begin { f1 }
case currsym^.name of

   { for procs, etc just record that we have one, wait for name }
progsym, procsym, funcsym: begin
symbol_seen := procsym;
proc_state := proc_header;
annotate_push( procsym );
end;
s1;                   // coding error, a case value should be here
   { remember we are in the declaraions part }
                        varsym, typesym, constsym, labelsym:
                           proc_state := proc_declarations;

                           { if it's a proc, there will be no begin/end ==> pop info we just saved
                           if it's an external var ==> do nothing  }
                        forwardsym, externalsym:
if proc_state = proc_header then begin
sym := annotate_pop;
tok := annotate_pop_tok;
if annotate_trace in traceFlags then
writeln( 'undo ', tok.val:tok.len );
end;

{ if a proc has just occurred, this is its name
otherwise, remember it, just in case it's a record name }
othersym: begin
if symbol_seen = procsym then begin
tok.val := currsym^.value;
tok.len := currsym^.length;
annotate_push_tok( tok );
symbol_seen := othersym;
end
else begin
annotate_temp_tok.val := currsym^.value;
annotate_temp_tok.len := currsym^.length;
end;
end;

{ we have the name, push it so the end symbol can get it back }
recordsym: begin
annotate_push_tok(annotate_temp_tok);
annotate_push( recordsym );
symbol_seen := recordsym;
end;

{ we must remember these so they can pushed if the begin symbol occurs }
ifsym, forsym, whilesym, withsym: begin
symbol_seen := currsym^.name;
end;

{ this is the second part of an if statement }
elsesym:
symbol_seen := ifsym;

{ if in a declaration ==> ignore
if in a statement (assume case statement) ==> prepare for possible begin following }
colon:
if proc_state = proc_statements then
   symbol_seen := colon;

{ reset symbol_seen }
semicolon:
symbol_seen := semicolon;

{ could be the begin of a proc
==> get value, leaving it for the corresponding end symbol
or it could be part of an if, etc,
==> push the symbol so the end symbol knows what to do  }
beginsym: begin
proc_state := proc_statements;
if symbol_seen in [ifsym, forsym, whilesym, withsym, elsesym, colon] then begin
annotate_push( symbol_seen );
end
else begin
sym := annotate_peek;
if sym = procsym then begin
   { this is a proc begin, add annotation }
annotate_pending_tok := true;
annotate_temp_tok := annotate_peek_tok;
end
else begin
if annotate_trace in traceFlags then
writeln( infilename,' line ', inlines, ': orphaned begin found' );
annotate_push( nosymbol );
end
end;
end;

{ push the symbol so the end symbol can get it back }
                                 casesym: annotate_push( casesym );

                                    { end of proc, end of record  ==> pop name
                                    end of if, etc statement    ==> pop symbol
                                    end of case item (colon)    ==> ignore
                                    end of record ==> check if named record  }
endsym: begin
symbol_seen := endsym;
sym := annotate_pop;
if sym = recordsym then begin
   annotate_temp_tok := annotate_pop_tok;
   if annotate_temp_tok.val[1] in ['A'..'Z','a'..'z'] then
      annotate_pending_tok := true;
end
else if sym = procsym then begin
   annotate_pending_tok := true;
   annotate_temp_tok := annotate_pop_tok;
end
else if sym = ifsym then begin
   { if there's an else part, don't do an annotation here }
   if nextsym^.name <> elsesym then begin
      annotate_pending := true;
      annotate_temp := sym;
   end
end
else if sym in [forsym, whilesym, withsym, casesym] then begin
   annotate_pending := true;
   annotate_temp := sym;
end
else if sym = colon then begin
         if annotate_trace in traceFlags then
            writeln( 'case item not annotated' );
      end
      else begin
         if annotate_trace in traceFlags then
            writeln( infilename,' line: ', inlines, ' end symbol found but not handled' );
      end;
   end;
end; { case }

if annotate_pending then begin
if nextsym^.crsbefore > 0 then begin
   { rest of line is empty }
                              insert_annotation(annotate_temp);
                              annotate_pending := false;
                           end else if nextsym^.name in [opencomment, closecomment] then begin
                              { there's another comment already on the same line }
if annotate_trace in traceFlags then
writeln( infilename,' line: ', inlines, ' annotate ', keyword[annotate_temp], ' abandoned' );
annotate_pending := false;
end
else if (nextsym^.name <> semicolon) then begin
insert_annotation(annotate_temp);
annotate_pending := false;
end;
end;

if annotate_pending_tok then begin
if nextsym^.crsbefore > 0 then begin
   { rest of line is empty }
   insert_annotation_tok( annotate_temp_tok );
   annotate_pending_tok := false;
end
else if nextsym^.name in [opencomment, closecomment] then begin
   { there's another comment already on the same line }
if annotate_trace in traceFlags then
writeln( infilename,
         ' line: ', inlines,
' annotate ', annotate_temp_tok.val:annotate_temp_tok.len, ' abandoned'
);
annotate_pending_tok := false;
end
else if not (nextsym^.name in [semicolon, period]) then begin
   insert_annotation_tok( annotate_temp_tok );
   annotate_pending_tok := false;
end;
end;
end; { f1 }


function f2( p: boolean;
             var q: real;
var x: ttype;              // should line up with first param
var c: char;

var i1, i2: integer;

ch: char;
z: boolean
) : real;

var
a: integer;
b: boolean;

begin { f2 }

with floodlePtr^ do
begin name := '        '; id := nil; next := nil; floodleAddr := 0;
cow := grass + floodle  // should be indented
end;

case e of
1: s1;   // CHECK: cr here should go to new case value!
88:
s3;

2:  begin
s2;
s3;
end;

3: s3;
4,5,6..9: s6;

otherwise
writeln('lots');
writeln(' and lots');
end; {case}

if c then begin
s1;
a := func( 12,
fffff( 89,
t
),
a // should align with '12'
);
end; // this must be aligned to the 'if' statement


fredzarmplezzzzzzzzzzzz(       arg1,
arg1,
arg2,
arg3
);

x := f(a) + f(b);


if (e111) + e2 then fffffffffffff(    func0(  func1(    func2( f3(       arg1,


                                                                         arg2,
   arg3,
   arg4
),


a1,  // should be aligned with arg f3, not '('
a2,
a3,
a4
),

aa2,
aa3,
aa4,
aa5
),
bb1,
bb2,
bb3,
bb4
),
cc1,
cc2,
cc3,
cc4
)
else if c1 then begin
s1;
end;

nextStmt := 13;

while c1 do
if q then
s1
else if qq then begin
s2;
s3
end;


if c1
and c2 then begin // this can be aligned manually
a := 12;
s1;
f(x)
end;

if cc1 then
while c2 do
f(x);

while c1 do f(  arg1,
arg2  // this should line up with arg1
);

if c4 then f( arg1,
arg2
);

f1        ( arg1,
arg2
);
fred      (  arg1,
arg2
arg3
arg4,

arg5
);

ff( arg1,
arg2
);

a[1] := 13;
repeat
s1;
while c3 do begin
s3;
while c2 do begin
s4;
while c4 do begin
if c3 then
begin
s1;
s2;
end else
s3;
if c3 then begin
s1
end else

if a then b
else
if c then d
else

s2;
if c3 then
if c4 then
s5;

s3
end;
end
end
until c3;


s5;

s3;
while c7 do begin
s3;
s4
end;

s4
end;

s2
until c1;  // there is no matching repeat here

end;  { f2 }
