| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255 |
- # AWK file for parsing uci specification files
- #
- # Copyright (C) 2006 by Fokus Fraunhofer <[email protected]>
- #
- # This program is free software; you can redistribute it and/or modify
- # it under the terms of the GNU General Public License as published by
- # the Free Software Foundation; either version 2 of the License, or
- # (at your option) any later version.
- #
- # This program is distributed in the hope that it will be useful,
- # but WITHOUT ANY WARRANTY; without even the implied warranty of
- # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- # General Public License for more details.
- #
- # You should have received a copy of the GNU General Public License
- # along with this program; if not, write to the Free Software
- # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- #
- #
- # general: unfortunately, the development was done using gawk providing
- # a different match() functions than e.g. mawk on debian systems
- # - therefore, the script was changed to run on most awk's
- # - even things like [:space:] are not used
- #
- # - script parses the config section definition contained in one
- # specification file
- # global variables:
- # * section - contains the current config section name
- # * var - contains the name of the current config option
- # * type - contains the type of the current config option
- # * required - contains the requirements of the current config option
- # * optional - contains the optional scope of the current config option
- # * vars[] - array, contains the name of all config options valid within
- # a certain config section, format: csv
- #
- # XXX todo: more than one config option with the same in different section
- # will clash for the following tables
- # * types[] - contains the type of a config option
- # * reqs[] - contains the requirements of a config option
- # * opts[] - contains the optional scope of a config option
- #
- BEGIN {
- section_count=1
- section = ""
- simple_types = "int|ip|netmask|string|wep|hostname|mac|port|ports|wpapsk"
- }
- # function print_specification
- # - prints all information about the created tables containing the
- # specification
- function print_specification() {
- for (section in vars) {
- printf("%s\n",section);
- split(vars[section],arr,",")
- for (idx in arr) {
- printf("\t%s[%s]",arr[idx],types[section "_" arr[idx]]);
- if (length(reqs[section "_" arr[idx]])) {
- if (reqs[section "_" arr[idx]]==1) {
- printf(",req");
- }else{
- printf(", req(%s)", reqs[section "_" arr[idx]]);
- }
- }
- if (length(opts[section "_" arr[idx]])) {
- printf(", opt(%s)", opts[section "_" arr[idx]]);
- }
- printf("\n");
- }
- }
- }
- function reset_option() {
- # just set global variables parsed on one line back to defaults
- var = ""
- type = ""
- required = ""
- optional = ""
- found = 0
- }
- function store_option() {
- # save all information about a config option parsed from the spec file
- # to the relevant tables for future use
- # first check minimum requirements for storing information
- if (!length(section)) {
- print STDERR "line " NR ": section definition missing"
- exit 1
- }
- if (!length(var)) {
- print STDERR "line " NR ": invalid config option name"
- exit 1
- }
- if (!length(type)) {
- print STDERR "line " NR ": invalid config option type"
- exit 1
- }
- # add config options to the names of options available for this
- # section
- if (exists[section]!=1) {
- section_names[section_count] = section
- section_count++
- exists[section] = 1
- vars[section] = var
- } else {
- vars[section] = vars[section] "," var
- }
-
- # save the type, the requirements and the optional scope of the
- # config option
- types[section "_" var] = type
- reqs[section "_" var] = required
- opts[section "_" var] = optional
- }
- /^declare -x|^export/ {
- sub(/^declare -x /,"")
- sub(/^export /,"")
- split($0,arr,"=")
- val=substr(arr[2],2,length(arr[2])-2)
- ENVIRON[arr[1]] = val
- next
- }
- # main parsing function
- # this is done in one function block to allow multiple semicolon separated
- # definitions on one line
- {
- # replace leading/trailing white space
- gsub("^[ \t\n]+","");
- gsub("[ \t\n]+$","");
- # comments are removed
- # XXX todo: check for quoted comments??
- if (match($0,/[^#]*/)) {
- rest=substr($0,RSTART,RLENGTH)
- } else {
- rest=$0
- }
- # match the config section "<section> {"
- if (match(rest,/^[^ \t\n{]+[ \t\n]*\{/)) {
- match(rest,/^[^ \t\n{]+/)
- section = substr(rest,RSTART,RLENGTH)
- rest=substr($0,RSTART+RLENGTH);
- match(rest,/[ \t\n]*\{/)
- rest=substr(rest,RSTART+RLENGTH)
- # check for array indication
- if (match(section,/\[[ \t\n]*\]/)) {
- section=substr(section,1,RSTART-1)
- multiple[section] = 1
- } else {
- multiple[section] = 0
- }
- }
- reset_option()
- # parse the remaing line as long as there is something to parse
- while (rest ~ "[^ \t\n}]+") {
- found = 0
- # get option name and option type
- # first, check for "simple" datatype definitions
- if (match(rest,"[^: \t\n]+[ \t\n]*:[ \t\n]*(" \
- simple_types ")")){
- match(rest,"[^: \t\n]+")
- var=substr(rest,RSTART,RLENGTH)
- rest=substr(rest,RSTART+RLENGTH)
- match(rest,"[ \t\n]*:[ \t\n]*")
- rest=substr(rest,RSTART+RLENGTH)
- match(rest,"(" simple_types ")")
- type=substr(rest,RSTART,RLENGTH)
- rest = substr(rest,RSTART+RLENGTH)
- found = 1
- # next, check for enum definitions
- } else if (match(rest,/[^: \t\n]+[ \t\n]*:[ \t\n]*enum\([^\)]+\)/ )) {
- match(rest,"[^: \t\n]+")
- var=substr(rest,RSTART,RLENGTH)
- rest=substr(rest,RSTART+RLENGTH)
- match(rest,/[ \t\n]*:[ \t\n]*enum\(/)
- rest=substr(rest,RSTART+RLENGTH)
- match(rest,/[^\)]+/)
- type="enum," substr(rest,RSTART,RLENGTH)
- rest = substr(rest,RSTART+RLENGTH+1)
- found=1
- }
- # after the name and the type,
- # get the option requirements/scope
- if (match(rest,/[^,]*,[ \t\n]*required\[[^]]+\]/)) {
- match(rest,"[^,]*")
- save=substr(rest,RSTART,RLENGTH)
- rest=substr(rest,RSTART+RLENGTH)
- match(rest,/,[ \t\n]*required\[/);
- rest=substr(rest,RSTART+RLENGTH)
- match(rest,/[^]]+\]/)
- required=substr(rest,RSTART,RLENGTH-1)
- save=save substr(rest,RSTART+RLENGTH)
- rest=save
- found=1
- } else if (match(rest,/[^,]*,[ \t\n]*required/)) {
- match(rest,"[^,]*")
- save=substr(rest,RSTART,RLENGTH)
- rest=substr(rest,RSTART+RLENGTH)
- match(rest,",[ \t\n]*required");
- rest=substr(rest,RSTART+RLENGTH)
- required=1
- save=save substr(rest,RSTART+RLENGTH)
- rest=save
- found=1
- }
- if (match(rest,/[^,]*,[ \t\n]*optional\[[^]]+\]/)) {
- match(rest,"[^,]*")
- save=substr(rest,RSTART,RLENGTH)
- rest=substr(rest,RSTART+RLENGTH)
- match(rest,/,[ \t\n]*optional\[/);
- rest=substr(rest,RSTART+RLENGTH)
- match(rest,/[^]]+\]/)
- optional=substr(rest,RSTART,RLENGTH-1)
- save=save substr(rest,RSTART+RLENGTH)
- rest=save
- found=1
- }
-
- # if the remaining line contains a semicolon, complete the
- # specification of the config options
- if (match(rest, "^[ \t\n]*;(.*)")) {
- match(rest,"^[ \t\n]*;")
- rest=substr(rest,RSTART+RLENGTH)
- if (found==1) {
- store_option()
- }
- reset_option()
- # if nothing matched on this line, clear the rest
- } else if (!found) {
- rest = ""
- }
- }
- # after the line is pared, store the configuration option in the
- # table if any has been defined
- if (length(var)) {
- store_option()
- reset_option()
- }
- # close the section if the line contained a closing section bracket,
- # XXX todo: check if this has to be done more intelligent
- if ($0 ~ /\}/) {
- section=""
- }
- }
|