forked from zentralwerk/network
131 lines
4.0 KiB
Nix
131 lines
4.0 KiB
Nix
|
{ 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.split "[[:space:]]+" line;
|
||
|
words =
|
||
|
builtins.map (word:
|
||
|
let m = builtins.match "\"(.+)\"" word;
|
||
|
in if m != null
|
||
|
then builtins.head m
|
||
|
else word
|
||
|
) (
|
||
|
builtins.filter (word:
|
||
|
word != [] && word != ""
|
||
|
) tokens
|
||
|
);
|
||
|
command = builtins.head words;
|
||
|
args = builtins.tail words;
|
||
|
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);
|
||
|
};
|
||
|
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
|