Skip to content

Commit

Permalink
feat(kconfig): Introduce Walk and minor fixes (#1855)
Browse files Browse the repository at this point in the history
Reviewed-by: Cezar Craciunoiu <[email protected]>
Approved-by: Cezar Craciunoiu <[email protected]>
  • Loading branch information
craciunoiuc authored Aug 26, 2024
2 parents c8f5da5 + 9f9e8b1 commit 0208c45
Show file tree
Hide file tree
Showing 2 changed files with 71 additions and 16 deletions.
76 changes: 64 additions & 12 deletions kconfig/kconfig.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,34 @@ type KConfigFile struct {
Configs map[string]*KConfigMenu `json:"configs,omitempty"`
}

// recursiveWalk accepts an input menu and uses the provided callback against
// all visited nodes.
func recursiveWalk(menu *KConfigMenu, cb func(*KConfigMenu) error) error {
if err := cb(menu); err != nil {
return err
}

for _, child := range menu.Children {
if err := recursiveWalk(child, cb); err != nil {
return err
}
}

return nil
}

// Walk iterates through each node expressed in the KConfig DAG and executes
// the provided callback.
func (file *KConfigFile) Walk(cb func(*KConfigMenu) error) error {
for _, menu := range file.Configs {
if err := recursiveWalk(menu, cb); err != nil {
return err
}
}

return nil
}

// KConfigMenu represents a single hierarchical menu or config.
type KConfigMenu struct {
// Kind represents the structure type, e.g. config/menu/choice/etc
Expand All @@ -49,6 +77,9 @@ type KConfigMenu struct {
// Default value of the entry.
Default DefaultValue `json:"default,omitempty"`

// Source of the KConfig file that enabled this menu.
Source string `json:"source,omitempty"`

// Parent menu, non-nil for everythign except for mainmenu
parent *KConfigMenu
kconfigFile *KConfigFile // back-link to the owning KConfig
Expand All @@ -74,10 +105,12 @@ type (
)

const (
MenuConfig = MenuKind("config")
MenuGroup = MenuKind("group")
MenuChoice = MenuKind("choice")
MenuComment = MenuKind("comment")
MenuMain = MenuKind("main")
MenuMenuConfig = MenuKind("menuconfig")
MenuConfig = MenuKind("config")
MenuGroup = MenuKind("group")
MenuChoice = MenuKind("choice")
MenuComment = MenuKind("comment")
)

const (
Expand Down Expand Up @@ -139,7 +172,7 @@ func ParseData(data []byte, file string, extra ...*KeyValue) (*KConfigFile, erro
env[kcv.Key] = kcv
}
kp := &kconfigParser{
parser: newParser(data, file, env),
parser: newParser(data, filepath.Dir(file), file, env),
baseDir: filepath.Dir(file),
}

Expand Down Expand Up @@ -167,7 +200,7 @@ func (kconf *KConfigFile) walk(m *KConfigMenu, dependsOn, visibleIf expr) {
m.dependsOn = exprAnd(dependsOn, m.dependsOn)
m.visibleIf = exprAnd(visibleIf, m.visibleIf)

if m.Kind == MenuConfig {
if m.Kind == MenuConfig || m.Kind == MenuMenuConfig {
kconf.Configs[m.Name] = m
}

Expand Down Expand Up @@ -205,6 +238,12 @@ func (kp *kconfigParser) parseLine() {
return
}

// To make this package compatible with Linux, ignore error-if statements
if kp.TryConsume("$(error-if") {
_ = kp.ConsumeLine()
return
}

ident := kp.Ident()
if kp.TryConsume("=") || kp.TryConsume(":=") {
// Macro definition, see:
Expand All @@ -229,40 +268,53 @@ func (kp *kconfigParser) parseMenu(cmd string) {

case "mainmenu":
kp.pushCurrent(&KConfigMenu{
Kind: MenuConfig,
Kind: MenuMain,
Prompt: KConfigPrompt{Text: kp.QuotedString()},
Source: filepath.Clean(kp.file),
})

case "comment":
kp.newCurrent(&KConfigMenu{
Kind: MenuComment,
Prompt: KConfigPrompt{Text: kp.QuotedString()},
Source: filepath.Clean(kp.file),
})

case "menu":
kp.pushCurrent(&KConfigMenu{
Kind: MenuGroup,
Prompt: KConfigPrompt{Text: kp.QuotedString()},
Source: filepath.Clean(kp.file),
})

case "if":
kp.pushCurrent(&KConfigMenu{
Kind: MenuGroup,
visibleIf: kp.parseExpr(),
Source: filepath.Clean(kp.file),
})

case "choice":
kp.pushCurrent(&KConfigMenu{
Kind: MenuChoice,
Kind: MenuChoice,
Source: filepath.Clean(kp.file),
})

case "endmenu", "endif", "endchoice":
kp.popCurrent()

case "config", "menuconfig":
case "config":
kp.newCurrent(&KConfigMenu{
Kind: MenuConfig,
Name: kp.Ident(),
Source: filepath.Clean(kp.file),
})

case "menuconfig":
kp.newCurrent(&KConfigMenu{
Kind: MenuConfig,
Name: kp.Ident(),
Kind: MenuMenuConfig,
Name: kp.Ident(),
Source: filepath.Clean(kp.file),
})

default:
Expand Down Expand Up @@ -380,7 +432,7 @@ func (kp *kconfigParser) includeSource(file string) {
}

kp.includes = append(kp.includes, kp.parser)
kp.parser = newParser(data, file, kp.env)
kp.parser = newParser(data, kp.baseDir, file, kp.env)
kp.parseFile()
err = kp.err
kp.parser = kp.includes[len(kp.includes)-1]
Expand Down
11 changes: 7 additions & 4 deletions kconfig/parser.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,13 +23,15 @@ type parser struct {
line int
err error
env KeyValueMap
baseDir string
}

func newParser(data []byte, file string, env KeyValueMap) *parser {
func newParser(data []byte, baseDir, file string, env KeyValueMap) *parser {
return &parser{
data: data,
file: file,
env: env,
data: data,
file: file,
env: env,
baseDir: baseDir,
}
}

Expand Down Expand Up @@ -211,6 +213,7 @@ func (p *parser) interpolate(b []byte) string {

var buf bytes.Buffer
cmd := exec.Command(args[0], args[1:]...)
cmd.Dir = p.baseDir
cmd.Stdout = bufio.NewWriter(&buf)
if err := cmd.Run(); err != nil {
p.failf("could not execute shell: %s", err.Error())
Expand Down

0 comments on commit 0208c45

Please sign in to comment.