//==============================================================================
//  processes zinc sections of code.
//  Input is JHInput.input, output is also JHInput.input
//==============================================================================
unit Zinc;

//==============================================================================
//  INTERFACE
//==============================================================================
interface

procedure ProcessZinc();

//==============================================================================
//  IMPLEMENTATION
//==============================================================================
implementation
uses JHInput, JHParams, TextOnly, TextCommon, ZincParser, JASSerException, JHInterface;

//==================================
// Zinc Magic!
procedure ProcessZinc();
var
    i,j,k,x:integer;
    word:string;
    output:Array of string;
    source,trace: Array of integer;
    outn: integer;

    procedure writeOutput(const s:string; const from:integer);
    begin
        if( Length(output) <= outn ) then begin
            SetLength(output, outn+1+outn div 5);
            SetLength(source, Length(output) );
        end;
        output[outn]:=s;
        source[outn]:= from;
        outn:=outn+1;
    end;
    {$ifdef ZINC_DEBUG}
    procedure writeDebugOutput;
      var
         f: textfile;
         i:integer;
    begin
        AssignFile(f,'logs/zincoutput.j');
        filemode:=fmOpenWrite;
        Rewrite(f);
        for i := 0 to outn - 1 do
            WriteLn(f, output[i]);
        CloseFile(f);



    end;
    {$endif}


begin
    i:=0;

    outn:=0;
    SetLength(output,inputN);
    SetLength(source,inputN);
    //ProStatus('  Zinc: ');

    while(i<inputN) do begin
        if(CompareLineWord('//!',JHInput.Get(i),x)  ) or (ZINC_MODE and (i=0) ) then begin
            GetLineWord(JHInput.Get(i), word, x,x);
            if(word='zinc')  or (ZINC_MODE and (i=0) ) then begin
                ZincParser.ResetInput;
                if(ZINC_MODE) then ZincParser.AddInputLine(JHInput.Get(i));
                j:=i;
                i:=i+1;
                while(i<inputN) do begin

                    if  (ZINC_MODE and (j=0) ) then
                    else if(CompareLineWord('//!',JHInput.Get(i),x) ) then begin
                        GetLineWord(JHInput.Get(i), word, x,x);
                        if(word='zinc') then
                            raise JasserLineDoubleException(i,'Nested //! zinc', j, 'First called here')
                        else if(word='endzinc') then
                            break;
                    end;
                    ZincParser.AddInputLine(JHInput.Get(i));
                    i:=i+1;
                end;
                if(i=inputN) and not ZINC_MODE then
                     raise JasserLineException(i,'Missing //! endzinc');


                try
                    ZincParser.Parse;
                except
                    on e: ZincSyntaxError do begin
                        raise JasserLineException(j+e.linen, e.msg);
                    end;

                end;
                for k := 0 to ZincParser.GetOutputLineCount-1 do
                    WriteOutput(ZincParser.GetOutputLine(k) , ZincParser.GetOutputLineSource(k)+j );

            end else if(word='endzinc') then begin
                raise JasserLineException(i,'Unexpected: //! endzinc');
            end else
                WriteOutput(JHInput.Get(i), i);

        end else WriteOutput(JHInput.Get(i), i);
        //ProPosition(i/inputN);
        i:=i+1;
    end;

    JHInput.Reset2();
    SetLength(trace, outn);
    SetLength(source, outn);
    for i := 0 to outn - 1 do begin
        trace[i]:=textmacrotrace[source[i]];
        source[i]:=source[i]+offset[source[i]];
        JHInput.AddLineEx(output[i], source[i]-i, trace[i]);
    end;

    {$ifdef ZINC_DEBUG}
        WriteDebugOutput;
    {$endif}
    //ProEnd();

end;


end.
