{ self, openwrt }: let # the files that contain port definitions defFiles = builtins.filter (self.lib.hasSuffix "/etc/board.d/02_network") (self.lib.filesystem.listFilesRecursive "${openwrt}/target/linux"); # files contents as one string defSource = builtins.concatStringsSep "\n" ( map builtins.readFile defFiles ); defSourceLines = builtins.filter (s: s != []) ( builtins.split "\n" ( builtins.replaceStrings [ "\\\n" ] [ "" ] defSource )); parseCommand = line: let tokens = builtins.concatMap (frag: if builtins.isString frag then builtins.split "[[:space:]]+" frag else frag ) ( builtins.split "\"([^\"]*)\"" line ); words = builtins.filter (word: word != [] && word != "" ) tokens; command = builtins.head words; args = builtins.tail words; makeLinkFromArg = port: arg: builtins.foldl' (result: interface: if port != [] then result // { "${port}" = { type = "phys"; inherit interface port; }; } else result ) {} (builtins.split "[[:space:]]+" arg); commands = { ucidef_add_switch.ports = builtins.foldl' (ports: arg: let switch = builtins.head args; m1 = builtins.match "([[:digit:]]+):(.+)" arg; m2 = builtins.match "([[:digit:]]+)([ut]?)@(.+)" arg; m2flag = builtins.elemAt m2 1; port = if m1 != null then { inherit switch; type = "port"; index = builtins.elemAt m1 0; port = builtins.elemAt m1 1; } else if m2 != null then { inherit switch; type = "host"; index = builtins.elemAt m2 0; interface = builtins.elemAt m2 2; } // self.lib.optionalAttrs (m2flag == "u") { only = "untagged"; } // self.lib.optionalAttrs (m2flag == "t") { only = "tagged"; } else throw "Unimplemented port scheme: ${arg}"; in if m1 != null || m2 != null then ports // { "${port.index}" = port; } else builtins.trace "Unimplemented port scheme: ${arg}" ports ) {} (builtins.tail args); ucidef_set_interface_wan.ports = { "${builtins.head args}" = { type = "phys"; interface = builtins.head args; port = "wan"; }; }; ucidef_set_interface_lan.ports = makeLinkFromArg "lan" (builtins.elemAt args 0); ucidef_set_interfaces_lan_wan.ports = makeLinkFromArg "lan" (builtins.elemAt args 0) // makeLinkFromArg "wan" (builtins.elemAt args 1); }; in if commands ? ${command} then commands.${command} else { unknown."${command}" = args; }; in ( builtins.foldl' ({ state, result, models ? null, data ? {} }: line: if state == "start" then if builtins.match "[[:space:]]*case \"?\\$board\"? in" line != null then { state = "case"; inherit result; } else { inherit state result; } else if state == "case" then if builtins.match "[[:space:]]*esac" line != null then { state = "start"; inherit result; } else let m = builtins.match "[[:space:]]*(.+)\\)" line; in if m == null then { inherit state result; } else { inherit result; state = "model"; models = builtins.filter (m: m != null) ( map (s: let m = builtins.split "," s; in if s != [] && m != null && builtins.length m == 3 then { vendor = builtins.elemAt m 0; model = builtins.elemAt m 2; } else null ) ( builtins.split "[[:space:]]*\\|[[:space:]]*" ( builtins.head m ))); } else if state == "model" then if builtins.match "[[:space:]]*;;" line != null then { state = "case"; result = result ++ [ { inherit models data; } ]; } else { inherit result state models; data = self.lib.recursiveUpdate data (parseCommand line); } else throw "Invalid state ${state}" ) { state = "start"; result = []; } defSourceLines ).result