scite_require 'extlib.lua'

local make_state='ready'
local make_obj
local coverage_fname
local coverage_fdir
local coverage_module

local project_name='_all_.exe'
local build_goal='all'

function cpp_getMakeState()
  return make_state
end

function run_docmd(cmd,res)
    spawner.verbose(false)
    make_obj = spawner.new(Utf8ToAnsi('"'..props['SciteDefaultHome']..'\\docmd.cmd" "'..props['FileDir']..'" "'..cmd..'"'))
    make_obj:set_output('MakeProcessChunk')
    make_obj:set_result(res)
    make_state='running'
    return make_obj:run()
end

function vcs_repoName()
    local fname=props['FileDir']
    fname=fname:gsub('^.*[\\/]','')
    return fname..'.repo'
end

function vcs_commit()
    run_docmd('vcs_commit.cmd '..vcs_repoName(),'MakeProcessResult')
end

function vcs_changes()
    run_docmd('vcs_changes.cmd','MakeProcessResult')
end

function vcs_diff()
    run_docmd('vcs_diff.cmd '..props['FileNameExt'],'MakeProcessResult')
end

function vcs_UI()
    run_docmd('vcs_ui.cmd','MakeProcessResult')
end

function cpp_runMakeAsync(makefile,goal)
    if make_state=='running' then
      return false
    end
    local target=''
    if goal:find('^release/') then
      target=' TARGET=release'
    end
    local makecmd='make'..target
    if goal=='' or goal=='all' then
      print('>Выполняется построение из всех')
    else
      print('>Выполняется построение '..goal)
      makecmd='make -f '..makefile..target..' '..goal
    end
    return run_docmd(makecmd,'MakeProcessResult')
end

function cpp_runUnitTest(m)
    local res='MakeProcessResult'
    if make_state=='running' then
      return false
    end
    if m:sub(-5)=='.gcov' then
      print('>Выполняется анализ покрытия тестами '..m:sub(10,-6))
      res='MakeCoverageResult'
    elseif m:sub(-8)=='.feature' then
      print('>Выполняется тестирование функции '..m:gsub('features SCENARIO=',''))
    elseif m=='' then
      print('>Выполняется тестирование всех модулей')
    elseif m=='features' then
      print('>Выполняется функциональное тестирование')
    else
      print('>Выполняется тестирование модуля '..m)
      m=m..'_unittest'
    end
    return run_docmd('make -f UnitTests '..m,res)
end

local escpos=-1
local escstyle=0
function traceutf8(s)
  local r=''
  local b1,b2
  local i=1
  while i<=s:len() do
    b1=s:byte(i)
    if i<s:len() then
      b2=s:byte(i+1)
      if b1==208 and b2>=144 and b2<=191 then
        r=r..string.char(b2+48)
        i=i+2
      elseif b1==209 and b2>=128 and b2<=143 then
        r=r..string.char(b2+112)
        i=i+2
      elseif b1==208 and b2==129 then
        r=r..'Ё'
        i=i+2
      elseif b1==209 and b2==145 then
        r=r..'ё'
        i=i+2
      else
        r=r..string.char(b1)
        i=i+1
      end
    else
      r=r..string.char(b1)
      i=i+1
    end
  end
  trace(r)
end
function MakeProcessChunk(s)
   while 1 do
     local p=s:find('\27')
     if p then
       traceutf8(s:sub(1,p-1))
       s=s:sub(p)
       if escpos~=-1 then
         output:StartStyling(escpos,0)
         output:SetStyling(output.CurrentPos-escpos,escstyle)
       end
       escpos=output.CurrentPos
       if s:sub(1,4)=='\27[0m' then
         escpos=-1
         s=s:sub(5)
       elseif s:sub(1,3)=='\27[m' then
         escpos=-1
         s=s:sub(4)
       elseif s:sub(1,5)=='\27[31m' then
         escstyle=13
         s=s:sub(6)
       elseif s:sub(1,7)=='\27[0;96m' then
         escstyle=11
         s=s:sub(8)
       elseif s:sub(1,5)=='\27[32m' then
         escstyle=10
         s=s:sub(6)
       else
         s=s:sub(2)
         escpos=-1
       end
     else
       break
     end
   end  
   traceutf8(s)
   if escpos~=-1 then
     output:StartStyling(escpos,0)
     output:SetStyling(output.CurrentPos-escpos,escstyle)
     escpos=-1
   end
end

function MakeProcessResult(res)
  if make_state ~= 'ready' then
    make_state='ready'
  end
end
local function walign(s,w)
  local r=s:gsub('of','из')
  r=r:gsub('%.%d%d%%','%%')
  if w<=#r then
    return r:sub(1,w)
  end
  local p=r:find('%%')
  if p then
    r=string.rep(' ',4-p)..r..string.rep(' ',w-#r-(4-p))
  else
    r=string.rep(' ',w-1-#s)..r..' '
  end
  return r:sub(1,w)
end
function MakeCoverageResult(res)
  if make_state ~= 'ready' then
    make_state='ready'
    if tonumber(res)==0 then
    local f=io.open(coverage_fname,'r')
    if f then
      print('                                                Покрытие      Покрытие')
      print('Функция                                 Вызвана операторов    ветвлений')
      local str=f:read('*all')
      io.close(f)
      local lines = {}
      for s in str:gmatch("[^\r\n]+") do
        table.insert(lines, s)
      end
      local fname=''
      local a,b,c,d,e,n
      for i,s in pairs(lines) do
        if s:sub(1,8)=='function' then
          a,b,c,d,e=s:match("^function:(.-)\t(.-)\t(.-)\t(.-)\t(.-)$")
          n=fname..':'..b..': '..a..string.rep(' ',40)
          print(n:sub(1,40)..walign(c,8)..walign(d,14)..walign(e,14))
        elseif s:sub(1,4)=='file' then
          a,b,c,d,e=s:match("^file:(.-)\t(.-)\t(.-)\t(.-)\t(.-)$")
          fname=a
          n=fname..': Итого по файлу'..string.rep(' ',40)
          print(n:sub(1,40)..walign(c,8)..walign(d,14)..walign(e,14))
          if props['FileNameExt']~=fname then
            if scite_FileExists(coverage_fdir..'/'..fname) then
              scite.Open(coverage_fdir..'/'..fname)
            end
          end
        elseif props['FileNameExt']==fname then
          a,b,c=s:match("^(%d+):(.-)\t(.-)$")
          if not a then
            c=nil
            a,b=s:match("^(%d+):(.-)$")
          end
          if a and b~='0' then
            if c and c:find('-') then
              AddCovered(tonumber(a),false)
            else
              AddCovered(tonumber(a),true)
            end
          end
        end
      end
    else
      print('>Ошибка: не найден файл '..coverage_module..'.gcov')
      return
    end
   else
     print('>Ошибка при анализе покрытия '..coverage_module)
   end
  end
end

function cpp_generateMakefile(makename,maketext)
local makef=io.open(makename,'r')
local str=''
local rewr_flg=true
if makef then
  str=makef:read('*all')
  io.close(makef)
  if str:sub(1,20)~='# Generated Makefile' then
    return
  end
  if str==maketext then
    rewr_flg=false
  end
end
if rewr_flg then
  makef=io.open(makename,'w')
  makef:write(maketext)
  io.close(makef)
  print('Создан '..makename)
end
end


function cpp_doMake()
  local goal=props['CurrentWord']
  local sel=props['CurrentSelection']
  if sel:len()<goal:len() then
    sel=goal
  end
  if sel:match('[^0-9a-zA-Z_./]') then
    sel=goal
  end
  if sel and sel:len()>0 then
    cpp_runMakeAsync(props['FileName'],sel)
  else
    print('Цель не указана')
  end
end

function unittest_genMake()
local list=''
local flist=''
local slist=''
local test=''
local testlist={}
local n=0
local f=nil
for f in spawner.popen(Utf8ToAnsi('dir /b "'..props['FileDir']..'\\*_unittest.cpp" "'..props['FileDir']..'\\*_featuretest.cpp" "'..props['FileDir']..'\\*.feature"')):lines() do
  if f:find('unittest') then
    n=n+1
    test=f:sub(1,-5)
    testlist[n]=test
    list=list..' '..test
  elseif f:find('featuretest') then
    n=n+1
    test=f:sub(1,-5)
    testlist[n]=test
    flist=flist..' '..test
  elseif f:find('.feature') then
    slist=slist..':'..f
  end
end
local maketext=[[
# Generated Makefile. При изменении этого файла вручную удалите данную строку

ifndef TARGET
TARGET = coverage
endif

ifndef SCENARIO
SCENARIO = ]]..slist:sub(2)..[[ 
endif

CSOURCES = $(wildcard *.c)
CPPSOURCES = $(filter-out %_unittest.cpp %_featuretest.cpp, $(wildcard *.cpp))
CHEADERS = $(wildcard *.h)
CPPHEADERS = $(wildcard *.hpp)
ifeq ($(TARGET),coverage)
CCFLAGS = -O0 ]]..props['compile.flags']..[[ 
COVFLAGS = -fprofile-arcs -ftest-coverage
else ifeq ($(TARGET),debug)
CCFLAGS = -g -O0 ]]..props['compile.flags']..[[ 
COVFLAGS = 
else
CCFLAGS = -O1 ]]..props['compile.flags']..[[ 
COVFLAGS = 
endif
CCCS = -finput-charset=utf-8 -fexec-charset=windows-1251
CCCW = -finput-charset=windows-1251 -fexec-charset=windows-1251
GCC = gcc -std=c11
LFLAGS = -Wl,--stack,83886080 -static
GPP = g++ -std=c++20
CC = $(GPP)
LIBS = ]]..props['compile.libs']..[[ gdi32 comdlg32 uuid oleaut32 ole32 gmock gherkin-cpp units gcov
OBJS = $(sort $(patsubst %.c,$(TARGET)/%.o,$(CSOURCES)) $(patsubst %.cpp,$(TARGET)/%.o,$(CPPSOURCES)))
TESTLIST = ]]..list..[[ 
FEATURELIST = ]]..flist..[[ 
FEATURELISTEXE = $(addprefix $(TARGET)/,$(addsuffix .exe,$(FEATURELIST)))

ifeq ($(filter %.gcov, $(MAKECMDGOALS)),)
ifneq ($(wildcard $(TARGET)/*.gcda),)
CLEANGCDA:=$(shell del "$(TARGET)\\*.gcda")
endif
endif

.PHONY : all clean cleangcda features $(TESTLIST)

all: $(TESTLIST)

clean:
	$(if $(wildcard coverage),rmdir /q /s coverage)
	$(if $(wildcard release),rmdir /q /s release)
	$(if $(wildcard debug),rmdir /q /s debug)
	$(if $(wildcard temp),rmdir /q /s temp)

cleangcda:

$(TESTLIST) features $(OBJS) : | $(TARGET)

$(TARGET):
	mkdir $(TARGET)

$(TARGET)/%.o: %.cpp $(CPPHEADERS) $(CHEADERS)
	$(GPP) $(CCFLAGS) $(COVFLAGS) $(if $(filter uc%,$<),$(CCCS),$(CCCW)) -o $@ -c $<

$(TARGET)/%.o: %.c $(CHEADERS)
	$(GCC) $(CCFLAGS) $(COVFLAGS) $(if $(filter uc%,$<),$(CCCS),$(CCCW)) -o $@ -c $<

$(TARGET)/%.c.gcov: %.c $(TARGET)/%.gcda
	gcov -b -s . -o $(TARGET) -m -r -f $< >$(TARGET)\\gcov.lst
	gcov2 $(TARGET)\\gcov.lst $@

$(TARGET)/%.cpp.gcov: %.cpp $(TARGET)/%.gcda
	gcov -b -s . -o $(TARGET) -m -r -f $< >$(TARGET)\\gcov.lst
	gcov2 $(TARGET)\\gcov.lst $@

$(TARGET)/libunits.a: $(OBJS) UnitTests
	$(if $(wildcard $(TARGET)/libunits.a),del $(TARGET)\\libunits.a)
	ar -rv $(TARGET)/libunits.a $(OBJS)

]]
local runtest=''
local runftest=''
for i=1,n do
  test=testlist[i]
  if test:find('unittest') then
    runtest=runtest..test..[[: $(TARGET)/]]..test..[[.exe
	$(TARGET)/]]..test..[[.exe

]]
  else
    runftest=runftest..[[
	set SCENARIO=$(SCENARIO) && $(TARGET)\]]..test..[[.exe
]]
  end
  maketext=maketext..[[ 
$(TARGET)/]]..test..'.exe: '..test..[[.cpp $(TARGET)/libunits.a $(CPPHEADERS) $(CHEADERS)
	$(CC) $(CCFLAGS) $(LFLAGS) -L$(TARGET) -o $(TARGET)/]]..test..' '..test..'.cpp '..'"'..Utf8ToAnsi(props['SciteDefaultHome'])..[[/../lib/initansicp.o" $(addprefix -l,$(LIBS))

]]
end
maketext=maketext..[[ 
features: $(FEATURELISTEXE)
]]..runftest.."\n"..runtest

cpp_generateMakefile(props['FileDir']..'/UnitTests',maketext)

end

function cpp_UnitTestAll()
unittest_genMake()
cpp_runUnitTest('')
end

function cpp_UnitTest1()
unittest_genMake()
local test=props['FileName']
if test:sub(-9)=='_unittest' then
  test=test:sub(1,-10)
end
cpp_runUnitTest(test)
end

function cpp_FeatureTestAll()
unittest_genMake()
cpp_runUnitTest('features')
end

function cpp_FeatureTest1()
unittest_genMake()
cpp_runUnitTest('features SCENARIO='..props['FileNameExt'])
end

function cpp_ShowCoverage1()
unittest_genMake()
local test=props['FileName']
local ext=props['FileExt']
if test:sub(-9)=='_unittest' then
  test=test:sub(1,-10)
  if not scite_FileExists(props['FileDir']..'/'..test..'.'..ext) then
     ext='c'
     if not scite_FileExists(props['FileDir']..'/'..test..'.'..ext) then
       print('>Не найден модуль '..test)
     end
  end
end  
if not scite_FileExists(props['FileDir']..'/coverage/'..test..'.gcda') then
  print('>Не выполнено тестирование модуля '..test)
  return
end
coverage_fname=props['FileDir']..'/coverage/'..test..'.'..ext..'.gcov'
coverage_fdir=props['FileDir']
coverage_module=test..'.'..ext
cpp_runUnitTest('coverage/'..test..'.'..ext..'.gcov')
end

function cpp_ClearCoverage1()
  ClearCovered()
end
function cpp_genMake()
cpp_generateMakefile(props['FileDir']..'/Makefile',[[
# Generated Makefile. При изменении этого файла вручную удалите данную строку

TARGET = release

CSOURCES = $(wildcard *.c)
CPPSOURCES = $(filter-out %_unittest.cpp %_featuretest.cpp,$(wildcard *.cpp))

SMSOURCES = $(wildcard statemachine*.uxf)
SMGENERH = $(patsubst %.uxf,$(TARGET)/%.hpp,$(SMSOURCES))
SMGENERCPP = $(patsubst %.uxf,$(TARGET)/%.cpp,$(SMSOURCES))
SMGENER =  $(SMGENERH) $(SMGENERCPP)


CAIOSOURCES = $(wildcard *.caio)
CAIOGENERCPP = $(patsubst %.caio,$(TARGET)/%.cpp,$(CAIOSOURCES)) $(patsubst %.caio,$(TARGET)/%.lex.cpp,$(CAIOSOURCES)) $(patsubst %.caio,$(TARGET)/%.grm.cpp,$(CAIOSOURCES))
CAIOGENERH = $(patsubst %.caio,$(TARGET)/%.hpp,$(CAIOSOURCES))
CAIOGENER =  $(CAIOGENERH) $(CAIOGENERCPP)

LEXSOURCE = $(firstword $(wildcard *.lex))
GRMSOURCE = $(firstword $(wildcard *.grm))

ifneq (,$(LEXSOURCE))
LEXGENER = $(TARGET)/lex.yy.cpp
else
LEXGENER =
endif

ifneq (,$(GRMSOURCE))
GRMGENER = $(TARGET)/y.tab.cpp
GRMHEADER = $(TARGET)/y.tab.h
else
GRMGENER =
GRMHEADER =
endif

CHEADERS = $(wildcard *.h)
CPPHEADERS = $(wildcard *.hpp)
ifeq ($(TARGET),debug)
CCFLAGS = -g -O0 ]]..props['compile.flags']..[[ 
else
CCFLAGS = -O1 ]]..props['compile.flags']..[[ 
endif
GCC = gcc -std=c11
GPP = g++ -std=c++20
LFLAGS = -Wl,--stack,83886080 -static
CPPLIBS = ]]..props['compile.libs']..[[ gdi32 msimg32 comdlg32 uuid oleaut32 ole32 reflex
CLIBS = ]]..props['compile.libs']..[[ gdi32 msimg32
ifneq (,$(strip $(CPPSOURCES) $(LEXSOURCE) $(GRMSOURCE) $(CAIOSOURCES) $(SMSOURCES)))
CC = $(GPP)
LIBS = $(CPPLIBS)
OBJS = $(sort $(patsubst %.c,$(TARGET)/%.o,$(CSOURCES)) $(patsubst %.cpp,$(TARGET)/%.o,$(subst $(TARGET)/,,$(CPPSOURCES) $(LEXGENER) $(GRMGENER) $(CAIOGENERCPP) $(SMGENERCPP))))
else
CC = $(GCC)
LIBS = $(CLIBS)
OBJS = $(sort $(patsubst %.c,$(TARGET)/%.o,$(CSOURCES)))
endif

CCCS = -finput-charset=utf-8 -fexec-charset=windows-1251
CCCW = -finput-charset=windows-1251 -fexec-charset=windows-1251
HS = $(sort $(CHEADERS) $(GRMHEADER) $(CAIOGENERH) $(SMGENERH))
INIT="]]..Utf8ToAnsi(props['SciteDefaultHome'])..[[/../lib/initansicp.o"

.PHONY : all clean

all: $(TARGET)/_all_.exe

$(TARGET)/_all_.exe $(OBJS) $(GRMGENER) $(GRMHEADER) $(LEXGENER) $(CAIOGENER) $(SMGENER): | $(TARGET)

$(TARGET):
	mkdir $(TARGET)

$(TARGET)/lex.yy.o: | $(LEXGENER)

$(TARGET)/y.tab.o: | $(GRMGENER)

$(LEXGENER): $(LEXSOURCE)
	reflex --flex -o$(LEXGENER) $<

$(GRMGENER) $(GRMHEADER): $(GRMSOURCE)
	bison -Werror=conflicts-sr,conflicts-rr -Wcounterexamples -o$(GRMGENER) -d $<

$(TARGET)/%.cpp $(TARGET)/%.hpp: %.uxf
	smgen -o $(TARGET)/ $<

$(TARGET)/%.cpp $(TARGET)/%.hpp $(TARGET)/%.lex.cpp $(TARGET)/%.grm.cpp: %.caio
	caio -o$(TARGET)/ $<
	ifexist.cmd $(TARGET)/$(patsubst %.caio,%.lex,$<) "reflex --flex -o$(TARGET)/$(patsubst %.caio,%.lex.cpp,$<) $(TARGET)/$(patsubst %.caio,%.lex,$<)" "echo // >$(TARGET)/$(patsubst %.caio,%.lex.cpp,$<)"
	ifexist.cmd $(TARGET)/$(patsubst %.caio,%.grm,$<) "bison -Werror=conflicts-sr,conflicts-rr -Wcounterexamples -o$(TARGET)/$(patsubst %.caio,%.grm.cpp,$<) $(TARGET)/$(patsubst %.caio,%.grm,$<)" "echo // >$(TARGET)/$(patsubst %.caio,%.grm.cpp,$<)"

$(TARGET)/%.o: %.cpp $(CPPHEADERS) $(HS)
	$(GPP) $(CCFLAGS) $(if $(filter uc%,$<),$(CCCS),$(CCCW)) -o $@ -I. -I$(TARGET) -c $<

$(TARGET)/%.o: $(TARGET)/%.cpp $(CPPHEADERS) $(HS)
	$(GPP) $(CCFLAGS) $(if $(filter uc%,$<),$(CCCS),$(CCCW)) -o $@ -I. -I$(TARGET) -c $<

$(TARGET)/%.o: %.c $(HS)
	$(GCC) $(CCFLAGS) $(if $(filter uc%,$<),$(CCCS),$(CCCW)) -o $@ -I. -I$(TARGET) -c $<

$(TARGET)/_all_.exe: $(OBJS) Makefile
	$(CC) $(CCFLAGS) $(LFLAGS) -o $(TARGET)/_all_ $(OBJS) $(INIT) $(addprefix -l,$(LIBS))

$(TARGET)/%.exe: %.lex Makefile
	$(if $(wildcard $(TARGET)),,mkdir $(TARGET))
	reflex --flex --bison -o$(TARGET)/lex.yy.cpp $<
	$(GPP) $(CCFLAGS) $(LFLAGS) $(if $(filter uc%,$<),$(CCCS),$(CCCW)) -o $(TARGET)/$(patsubst %.lex,%,$<) -I. -I$(TARGET) $(TARGET)/lex.yy.cpp $(INIT) $(addprefix -l,$(CPPLIBS))

$(TARGET)/%.exe: %.grm Makefile
	$(if $(wildcard $(TARGET)),,mkdir $(TARGET))
	bison -Werror=conflicts-sr,conflicts-rr -Wcounterexamples -o$(TARGET)/y.tab.cpp $<
	$(GPP) $(CCFLAGS) $(LFLAGS) $(if $(filter uc%,$<),$(CCCS),$(CCCW)) -o $(TARGET)/$(patsubst %.grm,%,$<) -I. -I$(TARGET) $(TARGET)/y.tab.cpp $(INIT) $(addprefix -l,$(CPPLIBS))

$(TARGET)/%.exe: %.caio Makefile
	$(if $(wildcard $(TARGET)),,mkdir $(TARGET))
	caio.exe -o$(TARGET)/ $<
	ifexist.cmd $(TARGET)/$(patsubst %.caio,%.lex,$<) "reflex --flex -o$(TARGET)/$(patsubst %.caio,%.lex.cpp,$<) $(TARGET)/$(patsubst %.caio,%.lex,$<)" "echo // >$(TARGET)/$(patsubst %.caio,%.lex.cpp,$<)"
	ifexist.cmd $(TARGET)/$(patsubst %.caio,%.grm,$<) "bison -Werror=conflicts-sr,conflicts-rr -Wcounterexamples -o$(TARGET)/$(patsubst %.caio,%.grm.cpp,$<) $(TARGET)/$(patsubst %.caio,%.grm,$<)" "echo // >$(TARGET)/$(patsubst %.caio,%.grm.cpp,$<)"
	$(GPP) $(CCFLAGS) $(LFLAGS) -o $(TARGET)/$(patsubst %.caio,%,$<) $(TARGET)/$(patsubst %.caio,%.cpp,$<) $(TARGET)/$(patsubst %.caio,%.lex.cpp,$<) $(TARGET)/$(patsubst %.caio,%.grm.cpp,$<) $(INIT) $(addprefix -l,$(CPPLIBS))

$(TARGET)/%.exe: %.c Makefile
	$(if $(wildcard $(TARGET)),,mkdir $(TARGET))
	$(GCC) $(CCFLAGS) $(LFLAGS) $(if $(filter uc%,$<),$(CCCS),$(CCCW)) -o $(TARGET)/$(patsubst %.c,%,$<) -I. -I$(TARGET) $< $(INIT) $(addprefix -l,$(CLIBS))

$(TARGET)/%.exe: %.cpp Makefile
	$(if $(wildcard $(TARGET)),,mkdir $(TARGET))
	$(GPP) $(CCFLAGS) $(LFLAGS) $(if $(filter uc%,$<),$(CCCS),$(CCCW)) -o $(TARGET)/$(patsubst %.cpp,%,$<) -I. -I$(TARGET) $< $(INIT) $(addprefix -l,$(CPPLIBS))

clean:
	$(if $(wildcard release),rmdir /q /s release)
	$(if $(wildcard debug),rmdir /q /s debug)
	$(if $(wildcard coverage),rmdir /q /s coverage)
	$(if $(wildcard temp),rmdir /q /s temp)
	$(if $(wildcard *.orig),del *.orig)

]])
end

function cpp_MakeAll()
--    trace(project_name..'\n')
    if project_name:find('_unittest%.exe$') then
      unittest_genMake()
      cpp_runMakeAsync('UnitTests','release/'..project_name)
    else
      cpp_genMake()
      cpp_runMakeAsync('Makefile',build_goal)
    end
end


local function change_build_name(fn)
   output.CodePage=0
   if fn:find('%.cpp$') or fn:find('%.c$') or fn:find('%.lex$') or fn:find('%.grm$') or fn:find('%.m$') or fn:find('%.h$') or fn:find('%.hpp$') or fn:find('%.caio$')  then
--      trace(props['build.goal'])
--      trace(':'..fn.."\n")
      local fname=fn
      if fn:find('%.h$') or fn:find('%.hpp$') then
         fname=fn:gsub('%.hp*$','.cpp')
         if not scite_FileExists(fname) then
           fname=fn:gsub('%.hp*$','.c')
           if not scite_FileExists(fname) then
             fname='?'
           end
         end
      end
      fname=fname:gsub('^.*[\\/]','')
      if not props['build.goal'] or props['build.goal']=='' or fname:find('_unittest%.cpp$') then
         props['build_text']=AnsiToUtf8("Cобирать из "..fname)
         project_name=fname:gsub('%.[%a]+$','.exe')
         build_goal='release/'..project_name
      elseif props['build.goal']=='all' then
         props['build_text']=AnsiToUtf8("Cобирать из всех")
         project_name='_all_.exe'
         build_goal='all'
      else
         props['build_text']=AnsiToUtf8("Cобрать "..props['build.goal'])
         project_name=props['build.goal']
         build_goal='release/'..project_name
      end
      props['program.exe']=project_name
      scite.MenuCommand(1199)
   end
end

local save_calls=0

local function save_step1(fn)
  save_calls=save_calls+1
end
local function save_step2(fn)
  if save_calls>0 then
    save_calls=save_calls-1
  else
    change_build_name(fn)
  end
end

scite_OnOpenSwitch(change_build_name)
scite_OnBeforeSave(save_step1)
scite_OnSave(save_step2)
