function generatedFiles = plc_postcg_callback_pilz(fileNames)

%   Copyright 2012-2014 The MathWorks, Inc.
    
    fileName = fileNames{1};
    str = fileread(fileName);
    
    % SAFE types
    str = regexprep(str, 'SAFE_(\w+): ARRAY \[(\d+)\.\.(\d+)\] OF (\w+)', '$1: ARRAY [$2..$3] OF SAFE$4');
    str = regexprep(str, 'SAFE_(\w+): (\w+)', '$1: SAFE$2');
    str = regexprep(str, '(\W)SAFE_(\w+)(\W)', '$1$2$3');
    
    % fix initialization of _PII vars
    str = regexprep(str, '(\w+_PII):([^:]+) :=[^;]+;', '$1:$2;');
    % AT types
    str = regexprep(str, '(\w+)_PII:([^;]+);', '$1 AT %I*:$2;');
    str = regexprep(str, '(\W)(\w+)_PII(\W)', '$1$2$3');
    str = regexprep(str, '(\w+)_PIO:([^;]+);', '$1 AT %Q*:$2;');
    str = regexprep(str, '(\W)(\w+)_PIO(\W)', '$1$2$3');
    
    % fix initialization of _VAL vars
    str = regexprep(str, '(\w+_VAL):([^:]+) :=[^;]+;', '$1:$2;');
    % AT VALID types
    str = regexprep(str, '(\w+)_VAL: (\w+);', '$1 WITH VALID AT %I*: $2;');
    str = regexprep(str, '(\w+)_VAL: ARRAY \[(\d+)\.\.(\d+)\] OF (\w+);', '$1 WITH VALID AT %I*: ARRAY [$2..$3] OF $4;');
    str = regexprep(str, '(\W)(\w+)_VAL(\W)', '$1$2$3');
    
    % fix initialization of _EXTVAL vars
    str = regexprep(str, '(\w+_EXTVAL):([^:]+) :=[^;]+;', '$1:$2;');
    % VALID EXTENSION types
    str = regexprep(str, '(\w+)_EXTVAL: (\w+);', '$1_VALID EXTENSION VALID OF $1: $2;');
    str = regexprep(str, '(\W)(\w+)_EXTVAL(\W)', '$1$2_VALID$3');

    % fix timer function block hoisting
    str = regexprep(str, '([^\n ] *)temporalCounter_(\w+)\(timerAction := [\w#\d]+, maxTime := [\w#\d]+\)', '$1temporalCounter_$2.done');

    % timer
    % fix variable decl
    str = strrep(str, ': PLC_CODER_TIMER', ': TON');
    % fix reset method
    str = strrep(str, '(timerAction := INT#1, maxTime := DINT#0)', '(in := FALSE, pt := TIME#0ms)');    
    % fix after method
    str = regexprep(str, '\(timerAction := INT#2, maxTime := DINT#(\d+)\)', '(in := TRUE, pt := TIME#$1ms)');
    str = regexprep(str, '\(timerAction := INT#2, maxTime := ([^;]+) \* DINT#1000(\)+);', '(in := TRUE, pt := DINT_TO_TIME(IN := $1 * DINT#1000000$2);');
    str = regexprep(str, '\(timerAction := INT#2, maxTime := TRUNC\(([^;]+) \* REAL#1000.0(\)+);', '(in := TRUE, pt := DINT_TO_TIME(IN := TRUNC($1 * REAL#1000000.0$2);');
    str = regexprep(str, '\(timerAction := INT#2, maxTime := TRUNC\(([^;]+) \* LREAL#1000.0(\)+);', '(in := TRUE, pt := DINT_TO_TIME(IN := TRUNC($1 * LREAL#1000000.0$2);');
    % fix output
    str = regexprep(str, 'temporalCounter(\w+).done', 'temporalCounter$1.q');
    
    % remove unnecessary code
    str = regexprep(str, ['    presentTicks: UDINT;[\r\n]+' ...
        '    elapsedTicks: UDINT;[\r\n]+' ...
        '    previousTicks: UDINT;[\r\n]+'], '');
    str = regexprep(str, ['    presentTicks := UDINT#0;[\r\n]+' ...
        '    elapsedTicks := UDINT#0;[\r\n]+' ...
        '    previousTicks := UDINT#0;[\r\n]+'], '');
    
    % fix casts
    type_list = '(BOOL|BYTE|WORD|DWORD|LWORD|USINT|UINT|UDINT|ULINT|SINT|INT|DINT|LINT|REAL|LREAL)';
    pattern = [type_list '_TO_' type_list '\('];
    str = regexprep(str, pattern, '$1_TO_$2(IN := ');
    
    str = fixUnaryIntrinsic(str);
    str = fixBinaryIntrinsic(str);
    str = fixShift(str);
    str = fixTrunc(str);
    
    % fix bool constants
    str = strrep(str, 'BOOL#TRUE', 'TRUE');
    str = strrep(str, 'BOOL#FALSE', 'FALSE');
    
    % fix empty VAR_GLOBAL sections
    str = regexprep(str, '[\r\n]+VAR_GLOBAL CONSTANT\s+END_VAR', '');
    str = regexprep(str, '[\r\n]+VAR_GLOBAL\s+END_VAR', '');
    
    sfprivate ('str2file', str, fileName);
    generatedFiles = {fileName};
end

function str = fixUnaryIntrinsic(str)
    fun_list = '(SIN|COS|TAN|ASIN|ACOS|ATAN|ABS|EXP|LOG|LN|SQRT)';
    pattern = [fun_list '\((' intrinsicArgStr ')\)'];
    str = regexprep(str, pattern, '$1(IN := $2)');    
end

function str=fixBinaryIntrinsic(str)
    fun_list = '(MIN|MAX|POW)';
    pattern = [fun_list '\((' intrinsicArgStr '),\ (' intrinsicArgStr ')\)'];
    str = regexprep(str, pattern, '$1(IN1 := $2, IN2 := $3)');    
end

function str=fixShift(str)
    fun_list = '(SHL|SHR|ROL|ROR)';
    pattern = [fun_list '\((' intrinsicArgStr '),\ (' intrinsicArgStr ')\)'];
    str = regexprep(str, pattern, '$1(IN := $2, N := $3)');    
end

function str=fixTrunc(str)
    fun_list = '(TRUNC)';
    pattern = [fun_list '\('];
    str = regexprep(str, pattern, '$1(IN := ');    
end

function str = intrinsicArgStr()
    str = '[\w|#|\.|\-\+]+';
end



% LocalWords:  Ied TRUNC tu strnew iec BLOCKFUNCTION BLOCKEND FUNCTIONEND PRG
% LocalWords:  pu PII PIO EXTVAL UDINT DWORD LWORD USINT ULINT decl LREAL SHL
% LocalWords:  SHR ROL ROR
