function patchConfig()

in patcher/patcher.js [914:1025]


function patchConfig(buf, cfg) {
    init()
    const cfgMap = {}
    let lineNo = 0
    for (let line of cfg.split(/\n/)) {
        lineNo++
        line = line.replace(/(#|\/\/).*/, "")
        line = line.trim()
        if (!line)
            continue
        let m = /(\w+)\s*=\s*([^#]+)/.exec(line)
        if (!m)
            err("syntax error at config line " + lineNo)
        let kn = m[1].toUpperCase()
        let k = configKeys[kn]
        if (!k && /^_\d+$/.test(kn))
            k = parseInt(kn.slice(1))
        if (!k)
            err("Unrecognized key name: " + kn)
        cfgMap[k + ""] = m[2]
    }

    let cfgdata = readWriteConfig(buf, null)

    for (let i = 0; i < cfgdata.length; i += 2) {
        let k = cfgdata[i] + ""
        if (!cfgMap.hasOwnProperty(k))
            cfgMap[k] = cfgdata[i + 1] + ""
    }

    const forAll = f => {
        for (let k of Object.keys(cfgMap)) {
            let kn = configInvKeys[k]
            f(kn, k, cfgMap[k])
        }
    }

    // expand enums
    forAll((kn, k, v) => {
        let e = enums[kn]
        if (e && e[v.toUpperCase()])
            cfgMap[k] = e[v] + ""
    })

    let portSize = cfgMap[configKeys.PINS_PORT_SIZE]
    if (portSize) portSize = parseInt(portSize)
    let portSize0 = portSize
    if (portSize)
        portSize &= 0xfff;

    // expand pin names
    forAll((kn, k, v) => {
        let p = parsePinName(v, portSize)
        if (p)
            cfgMap[k] = p
    })

    // expand existing keys
    for (let i = 0; i < 10; ++i)
        forAll((kn, k, v) => {
            if (configKeys[v]) {
                let curr = cfgMap[configKeys[v] + ""]
                if (curr == null)
                    err("Value not specified, but referenced: " + v)
                cfgMap[k] = curr
            }
        })

    let changes = ""
    forAll((kn, k, v) => {
        v = v.toUpperCase()
        if (v == "NULL" || v == "UNDEFINED") {
            let old = lookupCfg(cfgdata, k)
            changes += "remove " + showKV(k, old, portSize0) + "\n"
            delete cfgMap[k]
        }
    })

    forAll((kn, k, v) => {
        if (isNaN(parseInt(v)))
            err("Value not understood: " + v)
    })

    let sorted = Object.keys(cfgMap)
    sorted.sort((a, b) => parseInt(a) - parseInt(b))
    let patch = []
    for (let k of sorted) {
        patch.push(parseInt(k))
        patch.push(parseInt(cfgMap[k]))
    }

    for (let i = 0; i < patch.length; i += 2) {
        let k = patch[i]
        let v = patch[i + 1]
        let old = lookupCfg(cfgdata, k)
        if (old != v) {
            let newOne = showKV(k, v, portSize0)
            if (old !== null) {
                let oldOne = showKV(k, old, portSize0)
                newOne += " (was: " + oldOne.replace(/.* = /, "") + ")"
            }
            changes += newOne + "\n"
        }
    }

    let patched = readWriteConfig(buf, patch)

    return {
        changes,
        patched
    }
}