#!/usr/bin/lua
overrides = { 
   ["NUM_PPP"]                   = { "int", 1 },
   ["MEM_ALIGNMENT"]             = { "int", 1 },
   ["MEMP_OVERFLOW_CHECK"]       = { "int", 1 },
   ["MEMP_NUM_NETDB"]            = { "int", 1 },
   ["MEMP_NUM_LOCALHOSTLIST"]    = { "int", 1 },
   ["MEMP_NUM_PPPOE_INTERFACES"] = { "int", 1 },
   ["ETH_PAD_SIZE"]              = { "int", 1 },
}

descriptions = {

}

depends = {

}


print("#Autogenerated from lwip opt.h")
file="src/lib/contrib/lwip/include/lwip/opt.h";

outkcnf="src/lib/contrib/lwip/lwip.kcnf"
outh="src/lib/contrib/lwip/include/lwipopts.h"
outextra="lwipextra.h"


kcnf = io.open(outkcnf,"w");
hdr = io.open(outh,"w");

state=0
f = io.open(file);
last_comment={ };
comment_is_section=false
menu_opened=false


function split(text,sep)
   local sep, fields = sep or ":", {}
   local pattern = string.format("([^%s]+)", sep)
   string.gsub(text,pattern, function(c) fields[#fields+1] = c end)
   return fields
end


function extract_options(comment) 
   a = split(comment, " ");
   define  = a[2];
   default = a[3];
   i,j = string.find(define, "LWIP_");
   if nil == i then
      config="LWIP_"..define
   else
      config=define
   end
   l,k = string.find(a[3],"%(")
   if l ~=nil then
      optstring = string.gsub(table.concat(a," ",3),"/%*","")
   else
      optstring = string.gsub(table.concat(a," ",4),"/%*","")
   end
   optstring = string.gsub(optstring,"%*/","")
   return define,config,optstring,default,extra
end

function trim(s)
  -- from PiL2 20.4
  return (s:gsub("^%s*(.-)%s*$", "%1"))
end

function makecommentdsc(exclude)
   desc = table.concat(last_comment,"");
   desc = string.gsub(desc, "[/%*\n]", "");
   desc = string.gsub(desc, exclude, "");
   desc = trim(desc)
   return desc
end


function write_description(type, define)
   if nil == descriptions[define] then
      kcnf:write(type..' "'..define..'"\n')
   else
      kcnf:write(type..' "'..descriptions[define]..'"\n')
   end   
end

function write_depends(define)
   if nil ~= depends[define] then
      kcnf:write(depends[define].."\n")
   end   
end

function write_help(c)
   kcnf:write(c..'help\n')
   for i,j in pairs(last_comment) do
      line = trim(j)
      kcnf:write(c.."\t"..line.."\n")
   end
   kcnf:write("\n")
end

function write_header(config, define)
hdr:write("#ifdef CONFIG_"..config.."\n");
	 hdr:write("#define "..define.." CONFIG_"..config.."\n")
	 hdr:write("#endif\n\n");
end

optiontypes = {
   ["debug"] = function(define,config,name,default)
      i,j = string.find(define, "DEBUG");
      if nil ~= i then
	 desc=makecommentdsc(define..":")
	 kcnf:write("config "..config.."\n");
	 kcnf:write('bool "'..desc..'"\n')
	 write_depends(define)
	 kcnf:write("default n\n\n")
	 hdr:write("#ifdef CONFIG_"..config.."\n");
	 hdr:write("#define "..define.." LWIP_DBG_ON\n")
	 hdr:write("#else\n")
	 hdr:write("#define "..define.." LWIP_DBG_OFF\n")	
	 hdr:write("#endif\n\n"); 
	 return 1;
      else
	 return nil
      end
   end,
   ["string"] = function(define,config,name,default)
      i,j = string.find(default, '["]');
      if j==1 then
	 kcnf:write("config "..config.."\n");
	 write_description("string",define)
	 kcnf:write('default '..default..'\n')
	 write_depends(define);
	 write_help("")
	 write_header(config,define)
	 return 1
      end
      return nil
   end,
   ["bool"] = function(define,config,name,default)
      n = tonumber(default);
      if n==0 or n ==1 then
	 kcnf:write("config "..config.."\n");
	 write_description("bool", define)
	 if n==1 then
	    kcnf:write('default y \n')
	 else
	    kcnf:write('default n \n')
	 end
	 write_help("")
	 hdr:write("#ifdef CONFIG_"..config.."\n");
	 hdr:write("#define "..define.." 1 \n")
	 hdr:write("#else\n")
	 hdr:write("#define "..define.." 0 \n")	
	 hdr:write("#endif\n\n"); 
	 return 1
      end
   end,
   ["int"] = function(define,config,name,default)
      n = tonumber(default);
      if n ~= nil then
	 kcnf:write("config "..config.."\n");
	 write_description("int", define)
	 kcnf:write('default '..n..'\n')
	 write_depends(define);
	 write_help("")
	 write_header(config,define)
	 return 1
      else
	 return nil
      end
   end,
   ["manual"] = function(define,config,name,default)
      kcnf:write("#config "..config.."\n");
      write_description("#int", config)
--      write_depends(define);
      write_help("#")
      write_header(config, define)
      return 1
   end,
}



function extract_option(comment)
   define,config,name,default = extract_options(comment)
   if nil ~= overrides[define] then
      default = overrides[define][2]
      optiontypes[overrides[define][1]](define,config,name,default)
   else
      for i,j in pairs(optiontypes) do
	 ret = j(define,config,name,default)
	 if nil ~= ret then break end
      end
   end

--[[
   if (nil ~=tonumber(a[3])) then
      type="int"
   else
      type="string"
   end

 
   kcnf:write("config "..config.."\n");
   if a[4]~=nil then
      kcnf:write(type.." \""..table.concat(a,"",4).."\"\n");
   else
       kcnf:write(type.." \""..a[2].."\"\n");
   end
   kcnf:write("default \""..a[3].."\"\n");
   if a[4]==nil then
      kcnf:write("help \n");
      for i,j in pairs(last_comment) do
	 kcnf:write("\t"..j.."\n");
      end
   end
]]--
end
				 

function extract_section(comment)
   name=""
   for i,j in pairs(comment) do
      name=name..j
   end
   name = string.gsub(name,"[/%*-]","")
   name = string.gsub(name,"  ","")
   name = trim(name)
   if (menu_opened) then
      kcnf:write("\nendmenu \n\n\n")
   end
   menu_opened=true;
   kcnf:write("menu \""..name.."\"\n\n")
   hdr:write("\n/* "..name.."*/\n");
end

parser = {
   [0] = function(line)
      i,j = string.find(line, "/%*")
      if (i~=nil) then
	 --print(i,j,"~ "..string.sub(line,i,j))
	 --print("state trans")
	 state="comment_reader";
	 last_comment={ };
	 comment_is_section=false
	 parser[state](line);
      end
      i,j = string.find(line, "#define")
      if ((i~=nil) and (i==1)) then
	 k,l = string.find(line, "__")
	 if (k==nil) then
	    extract_option(line)
	 end
      end
   end,
   ["comment_reader"] = function(line)
      --print(line)
      table.insert(last_comment, line)
      i,j = string.find(line,"%-%-%-")
      if (i~=nil) then
	 comment_is_section=true;
      end
      i,j=string.find(line, "%*/")
      if (i~=nil) then
	 if comment_is_section then
	    extract_section(last_comment);
	 end
	 state=0
      end
   end,
}


hdr:write("/* \n * AUTOGENERATED!!! \n * DO NOT SUBMIT PATCHES AGAINST THIS FILE \n */\n")
hdr:write("#ifndef __LWIP_OPTS_H \n")
hdr:write("#define __LWIP_OPTS_H \n")
kcnf:write("# AUTOGENERATED\n");
kcnf:write("# DO NOT SUBMIT PATCHES AGAINST THIS FILE\n");

while true do
   line = f:read("*line");
   if (nil==line) then break end;
   parser[state](line)   
end

if (menu_opened) then
      kcnf:write("\n endmenu \n\n\n")
end
hdr:write("\n#endif \n\n\n")