X-Git-Url: https://git.archive.openwrt.org/?p=project%2Fluci.git;a=blobdiff_plain;f=libs%2Fuvl%2Fluasrc%2Fuvl.lua;h=d2ea4bd2c249a93d042a731d09a0816792d5230e;hp=dd8058f03b0e84e79616b9ab2b2d7b50b4478b03;hb=800a2630497e1ec2c61199b3bc645d778c714529;hpb=14c485e11719f2385f01397f7d7eeeed9ed460ea diff --git a/libs/uvl/luasrc/uvl.lua b/libs/uvl/luasrc/uvl.lua index dd8058f03..d2ea4bd2c 100644 --- a/libs/uvl/luasrc/uvl.lua +++ b/libs/uvl/luasrc/uvl.lua @@ -19,19 +19,20 @@ $Id$ -- @class module -- @cstyle instance -local fs = require "luci.fs" +local fs = require "nixio.fs" local uci = require "luci.model.uci" local util = require "luci.util" +local nutil = require "nixio.util" local table = require "table" local string = require "string" local require, pcall, ipairs, pairs = require, pcall, ipairs, pairs local type, error, tonumber, tostring = type, error, tonumber, tostring -local unpack, loadfile = unpack, loadfile +local unpack, loadfile, collectgarbage = unpack, loadfile, collectgarbage module "luci.uvl" -local ERR = require "luci.uvl.errors" +local ERR = require "luci.uvl.errors".error local datatypes = require "luci.uvl.datatypes" local validation = require "luci.uvl.validation" local dependencies = require "luci.uvl.dependencies" @@ -42,6 +43,10 @@ local TYPE_SECTION = 0x02 local TYPE_OPTION = 0x03 local TYPE_ENUM = 0x04 +local PAT_EXPR1 = "^%$?[%w_]+$" +local PAT_EXPR2 = "^%$?[%w_]+%.%$?[%w_]+$" +local PAT_EXPR3 = "^%$?[%w_]+%.%$?[%w_]+%.%$?[%w_]+$" + --- Boolean; default true; -- treat sections found in config but not in scheme as error STRICT_UNKNOWN_SECTIONS = true @@ -160,7 +165,7 @@ function UVL.validate_config( self, cfg, uci ) for k, v in pairs(co:config()) do local so = co:section(k) if not self.beenthere[so:cid()] then - co:error(ERR.SECT_UNKNOWN(so)) + co:error(ERR('SECT_UNKNOWN', so)) end end end @@ -168,9 +173,9 @@ function UVL.validate_config( self, cfg, uci ) for _, k in ipairs(util.keys(sc)) do local so = co:section(k) if so:scheme('required') and sc[k] == 0 then - co:error(ERR.SECT_REQUIRED(so)) + co:error(ERR('SECT_REQUIRED', so)) elseif so:scheme('unique') and sc[k] > 1 then - co:error(ERR.SECT_UNIQUE(so)) + co:error(ERR('SECT_UNIQUE', so)) end end @@ -204,7 +209,7 @@ function UVL.validate_section( self, cfg, section, uci ) if so:config() then return self:_validate_section( so ) else - return false, ERR.SECT_NOTFOUND(so) + return false, ERR('SECT_NOTFOUND', so) end end @@ -234,7 +239,7 @@ function UVL.validate_option( self, cfg, section, option, uci ) if so:config() and oo:config() then return self:_validate_option( oo ) else - return false, ERR.OPT_NOTFOUND(oo) + return false, ERR('OPT_NOTFOUND', oo) end end @@ -247,15 +252,15 @@ function UVL._validate_section( self, section ) if section:scheme('named') == true and section:config('.anonymous') == true then - return false, ERR.SECT_NAMED(section) + return false, ERR('SECT_NAMED', section) end for _, v in ipairs(section:variables()) do local ok, err = self:_validate_option( v ) if not ok and ( v:scheme('required') or v:scheme('type') == "enum" or ( - not err:is(ERR.ERR_DEP_NOTEQUAL) and - not err:is(ERR.ERR_DEP_NOVALUE) + not err:is('DEP_NOTEQUAL') and + not err:is('DEP_NOVALUE') ) ) then section:error(err) @@ -267,14 +272,14 @@ function UVL._validate_section( self, section ) section:error(err) end else - return false, ERR.SECT_NOTFOUND(section) + return false, ERR('SECT_NOTFOUND', section) end if STRICT_UNKNOWN_OPTIONS and not section:scheme('dynamic') then for k, v in pairs(section:config()) do local oo = section:option(k) - if k:sub(1,1) ~= "." and not self.beenthere[oo:cid()] then - section:error(ERR.OPT_UNKNOWN(oo)) + if k:byte(1) == 46 and not self.beenthere[oo:cid()] then + section:error(ERR('OPT_UNKNOWN', oo)) end end end @@ -288,7 +293,7 @@ function UVL._validate_option( self, option, nodeps ) if not option:scheme() and not option:parent():scheme('dynamic') then if STRICT_UNKNOWN_OPTIONS then - return false, option:error(ERR.OPT_UNKNOWN(option)) + return false, option:error(ERR('OPT_UNKNOWN', option)) else return true end @@ -298,9 +303,9 @@ function UVL._validate_option( self, option, nodeps ) local ok, err = dependencies.check( self, option ) if not ok then if not err:is_all( - ERR.ERR_OPT_REQUIRED, - ERR.ERR_DEP_NOTEQUAL, - ERR.ERR_DEP_NOVALUE + 'OPT_REQUIRED', + 'DEP_NOTEQUAL', + 'DEP_NOVALUE' ) then option:error(err) return false, option:errors() @@ -311,7 +316,7 @@ function UVL._validate_option( self, option, nodeps ) end if option:scheme('required') and not option:value() then - return false, option:error(ERR.OPT_REQUIRED(option)) + return false, option:error(ERR('OPT_REQUIRED', option)) elseif option:value() then local val = option:value() @@ -323,7 +328,8 @@ function UVL._validate_option( self, option, nodeps ) local config_values = ( type(val) == "table" and val or { val } ) for _, v in ipairs(config_values) do if not scheme_values[v] then - return false, option:error( ERR.OPT_BADVALUE( + return false, option:error( ERR( + 'OPT_BADVALUE', option, { v, util.serialize_data( util.keys(scheme_values) ) } @@ -332,7 +338,7 @@ function UVL._validate_option( self, option, nodeps ) end elseif option:scheme('type') == "list" then if type(val) ~= "table" and STRICT_LIST_TYPE then - return false, option:error(ERR.OPT_NOTLIST(option)) + return false, option:error(ERR('OPT_NOTLIST', option)) end end @@ -344,12 +350,12 @@ function UVL._validate_option( self, option, nodeps ) for i, v in ipairs(val) do if not self.datatypes[dt]( v ) then return false, option:error( - ERR.OPT_INVVALUE(option, { v, dt }) + ERR('OPT_INVVALUE', option, { v, dt }) ) end end else - return false, option:error(ERR.OPT_DATATYPE(option, dt)) + return false, option:error(ERR('OPT_DATATYPE', option, dt)) end end @@ -357,13 +363,13 @@ function UVL._validate_option( self, option, nodeps ) for _, v in ipairs(val) do if option:scheme('minlength') then if #v < option:scheme('minlength') then - return false, option:error(ERR.OPT_RANGE(option)) + return false, option:error(ERR('OPT_RANGE', option)) end end if option:scheme('maxlength') then if #v > option:scheme('maxlength') then - return false, option:error(ERR.OPT_RANGE(option)) + return false, option:error(ERR('OPT_RANGE', option)) end end @@ -371,13 +377,13 @@ function UVL._validate_option( self, option, nodeps ) if option:scheme('minimum') then if not w or w < option:scheme('minimum') then - return false, option:error(ERR.OPT_RANGE(option)) + return false, option:error(ERR('OPT_RANGE', option)) end end if option:scheme('maximum') then if not w or w > option:scheme('maximum') then - return false, option:error(ERR.OPT_RANGE(option)) + return false, option:error(ERR('OPT_RANGE', option)) end end end @@ -403,13 +409,13 @@ function UVL.read_scheme( self, shm, alias ) local bc = "%s/bytecode/%s.lua" %{ self.schemedir, shm } if not fs.access(bc) then - local files = fs.glob(self.schemedir .. '/*/' .. shm) + local files = nutil.consume((fs.glob(self.schemedir .. '/*/' .. shm))) - if files then + if #files > 0 then local ok, err - for i, file in ipairs( files ) do + for _, file in ipairs(files) do if not fs.access(file) then - return false, so:error(ERR.SME_READ(so,file)) + return false, so:error(ERR('SME_READ', so,file)) end local uci = uci.cursor( fs.dirname(file), default_savedir ) @@ -418,7 +424,7 @@ function UVL.read_scheme( self, shm, alias ) local sd, err = uci:load( sname ) if not sd then - return false, ERR.UCILOAD(so, err) + return false, ERR('UCILOAD', so, err) end ok, err = pcall(function() @@ -441,7 +447,7 @@ function UVL.read_scheme( self, shm, alias ) if ok and alias then self.packages[alias] = self.packages[shm] end return ok and self, err else - return false, so:error(ERR.SME_FIND(so, self.schemedir)) + return false, so:error(ERR('SME_FIND', so, self.schemedir)) end else local sc = loadfile(bc) @@ -449,7 +455,7 @@ function UVL.read_scheme( self, shm, alias ) self.packages[shm] = sc() return true else - return false, so:error(ERR.SME_READ(so,bc)) + return false, so:error(ERR('SME_READ',so,bc)) end end end @@ -468,7 +474,7 @@ local function _req( t, n, c, r ) o = enum( scheme, nil, p, '(nil)', '(nil)', n ) end - return false, ERR.SME_REQFLD(o,v) + return false, ERR('SME_REQFLD',o,v) end end return true @@ -494,7 +500,7 @@ local function _ref( c, t ) r[1] = ( #r[1] > 0 and r[1] or scheme:sid() ) if #r ~= n then - return false, ERR.SME_BADREF(scheme, k) + return false, ERR('SME_BADREF', scheme, k) end return r @@ -541,12 +547,12 @@ function UVL._parse_section(self, scheme, k, v) local so = scheme:section(v.name) for k, v2 in pairs(v) do - if k ~= "name" and k ~= "package" and k:sub(1,1) ~= "." then + if k ~= "name" and k ~= "package" and k:byte(1) == 46 then if k == "depends" then s.depends = self:_read_dependency( v2, s.depends ) if not s.depends then return false, scheme:error( - ERR.SME_BADDEP(so, util.serialize_data(s.depends)) + ERR('SME_BADDEP', so, util.serialize_data(s.depends)) ) end elseif k == "dynamic" or k == "unique" or @@ -576,14 +582,14 @@ function UVL._parse_var(self, scheme, k, v) local p = self.packages[r[1]] if not p then error(scheme:error( - ERR.SME_VBADPACK({scheme:sid(), '', v.name}, r[1]) + ERR('SME_VBADPACK', {scheme:sid(), '', v.name}, r[1]) )) end local s = p.variables[r[2]] if not s then error(scheme:error( - ERR.SME_VBADSECT({scheme:sid(), '', v.name}, r[2]) + ERR('SME_VBADSECT', {scheme:sid(), '', v.name}, r[2]) )) end @@ -594,26 +600,26 @@ function UVL._parse_var(self, scheme, k, v) local to = so:option(v.name) for k, v2 in pairs(v) do - if k ~= "name" and k ~= "section" and k:sub(1,1) ~= "." then + if k ~= "name" and k ~= "section" and k:byte(1) == 46 then if k == "depends" then t.depends = self:_read_dependency( v2, t.depends ) if not t.depends then error(scheme:error(so:error( - ERR.SME_BADDEP(to, util.serialize_data(v2)) + ERR('SME_BADDEP', to, util.serialize_data(v2)) ))) end elseif k == "validator" then t.validators = self:_read_validator( v2, t.validators ) if not t.validators then error(scheme:error(so:error( - ERR.SME_BADVAL(to, util.serialize_data(v2)) + ERR('SME_BADVAL', to, util.serialize_data(v2)) ))) end elseif k == "valueof" then local values, err = self:_read_reference( v2 ) if err then error(scheme:error(so:error( - ERR.REFERENCE(to, util.serialize_data(v2)):child(err) + ERR('REFERENCE', to, util.serialize_data(v2)):child(err) ))) end t.type = "reference" @@ -647,21 +653,21 @@ function UVL._parse_enum(self, scheme, k, v) local p = self.packages[r[1]] if not p then error(scheme:error( - ERR.SME_EBADPACK({scheme:sid(), '', '', v.value}, r[1]) + ERR('SME_EBADPACK', {scheme:sid(), '', '', v.value}, r[1]) )) end local s = p.variables[r[2]] if not s then error(scheme:error( - ERR.SME_EBADSECT({scheme:sid(), '', '', v.value}, r[2]) + ERR('SME_EBADSECT', {scheme:sid(), '', '', v.value}, r[2]) )) end local t = s[r[3]] if not t then error(scheme:error( - ERR.SME_EBADOPT({scheme:sid(), '', '', v.value}, r[3]) + ERR('SME_EBADOPT', {scheme:sid(), '', '', v.value}, r[3]) )) end @@ -671,7 +677,7 @@ function UVL._parse_enum(self, scheme, k, v) local eo = oo:enum(v.value) if t.type ~= "enum" and t.type ~= "reference" then - error(scheme:error(ERR.SME_EBADTYPE(eo))) + error(scheme:error(ERR('SME_EBADTYPE', eo))) end if not t.values then @@ -688,7 +694,7 @@ function UVL._parse_enum(self, scheme, k, v) if v.default then if t.default then - error(scheme:error(ERR.SME_EBADDEF(eo))) + error(scheme:error(ERR('SME_EBADDEF', eo))) end t.default = v.value end @@ -700,7 +706,7 @@ function UVL._parse_enum(self, scheme, k, v) if not t.enum_depends[v.value] then error(scheme:error(so:error(oo:error( - ERR.SME_BADDEP(eo, util.serialize_data(v.depends)) + ERR('SME_BADDEP', eo, util.serialize_data(v.depends)) )))) end end @@ -717,9 +723,7 @@ function UVL._read_dependency( self, values, deps ) local k, e, v = val:match("%s*([%w$_.]+)%s*(=?)%s*(.*)") if k and ( - k:match("^"..expr.."%."..expr.."%."..expr.."$") or - k:match("^"..expr.."%."..expr.."$") or - k:match("^"..expr.."$") + k:match(PAT_EXPR1) or k:match(PAT_EXPR2) or k:match(PAT_EXPR3) ) then condition[k] = (e == '=') and v or true else @@ -751,8 +755,8 @@ function UVL._read_validator( self, values, validators ) validator = self:_resolve_function( (value:gsub("^lua:","") ) ) elseif value:match("^regexp:") then local pattern = value:gsub("^regexp:","") - validator = function( type, dtype, pack, sect, optn, ... ) - local values = { ... } + validator = function( type, dtype, pack, sect, optn, arg1, arg2, arg3, arg4, arg5 ) + local values = { arg1, arg2, arg3, arg4, arg5 } for _, v in ipairs(values) do local ok, match = pcall( string.match, v, pattern ) @@ -801,7 +805,7 @@ function UVL._read_reference( self, values ) if v['.type'] == ref[2] then if #ref == 2 then if v['.anonymous'] == true then - return false, ERR.SME_INVREF('', value) + return false, ERR('SME_INVREF', '', value) end val[k] = k -- XXX: title/description would be nice elseif v[ref[3]] then @@ -810,7 +814,7 @@ function UVL._read_reference( self, values ) end end else - return false, ERR.SME_BADREF('', value) + return false, ERR('SME_BADREF', '', value) end end @@ -919,13 +923,13 @@ function uvlitem.type(self) end end -function uvlitem.error(self, ...) +function uvlitem.error(self, arg1, arg2, arg3, arg4, arg5) if not self.e then - local errconst = { ERR.CONFIG, ERR.SECTION, ERR.OPTION, ERR.OPTION } - self.e = errconst[#self.cref]( self ) + local errconst = { 'CONFIG', 'SECTION', 'OPTION', 'OPTION' } + self.e = ERR( errconst[#self.cref], self ) end - return self.e:child( ... ) + return self.e:child( arg1, arg2, arg3, arg4, arg5 ) end function uvlitem.errors(self) @@ -955,7 +959,7 @@ function uvlitem._loadconf(self, co, c, configdir) co, err = uci.cursor(configdir):get_all(c) if err then - self:error(ERR.UCILOAD(self, err)) + self:error(ERR('UCILOAD', self, err)) end self._configcache = co @@ -992,9 +996,9 @@ end --- Add an error to scheme. -- @return Scheme error context -function scheme.error(self, ...) - if not self.e then self.e = ERR.SCHEME( self ) end - return self.e:child( ... ) +function scheme.error(self, arg1, arg2, arg3, arg4, arg5) + if not self.e then self.e = ERR( 'SCHEME', self ) end + return self.e:child( arg1, arg2, arg3, arg4, arg5 ) end --- Get an associated config object.