Open-CMSIS-Pack/generator-bridge

View on GitHub
internal/stm32CubeMX/iniReader.go

Summary

Maintainability
A
0 mins
Test Coverage
F
5%
/*
 * Copyright (c) 2023 Arm Limited. All rights reserved.
 *
 * SPDX-License-Identifier: Apache-2.0
 */

package stm32cubemx

import (
    "errors"
    "fmt"
    "path/filepath"
    "strconv"
    "strings"

    "github.com/open-cmsis-pack/generator-bridge/internal/utils"
    log "github.com/sirupsen/logrus"
    "golang.org/x/exp/slices"
    "gopkg.in/ini.v1"
)

type MxprojectAllType struct {
    Mxproject []MxprojectType
}

type MxprojectType struct {
    Context          string
    PreviousLibFiles struct {
        LibFiles []string
    }
    PreviousUsedFiles struct {
        SourceFiles []string
        HeaderPath  []string
        CDefines    []string
    }
    PreviousGenFiles struct {
        AdvancedFolderStructure string
        HeaderFilesList         []string
        HeaderPathList          []string
        HeaderFiles             string
        SourceFilesList         []string
        SourcePathList          []string
        SourceFiles             string
    }
}

type IniSectionsType struct {
    Context string
    Section string
}

func PrintKeyValStr(key, val string) {
    fmt.Printf("\n%v : %v", key, val)
}

func PrintKeyValStrs(key string, vals []string) {
    fmt.Printf("\n%v", key)
    for i := range vals {
        fmt.Printf("\n%d: %v", i, vals[i])
    }
}

func PrintKeyValInt(key string, val int) {
    fmt.Printf("\n%v : %v", key, val)
}

func PrintItemCsv(section *ini.Section, key string) {
    valStr := section.Key(key).String()
    commentStr := section.Key(key).Comment
    commentStrs := strings.Split(commentStr, ";")
    PrintKeyValStr(key, valStr)
    PrintKeyValStrs(key, commentStrs)
}

func PrintItem(section *ini.Section, key string) {
    valStr := section.Key(key).String()
    PrintKeyValStr(key, valStr)
}

func PrintItemIterator(section *ini.Section, key, iterator string) {
    valStr := section.Key(key).String()
    PrintKeyValStr(key, valStr)
    maxCnt, _ := strconv.Atoi(valStr)
    for cnt := 0; cnt < maxCnt; cnt++ {
        keyN := iterator + strconv.Itoa(cnt)
        valStr = section.Key(keyN).String()
        PrintKeyValStr(keyN, valStr)
    }
}

func StoreData(data *string, value string) {
    value = filepath.ToSlash(value)

    if value != "" {
        *data = value
    }
}

func StoreDataArray(data *[]string, values ...string) {
    for _, value := range values {
        value = filepath.ToSlash(value)
        if value != "" {
            if !slices.Contains(*data, value) {
                *data = append(*data, value)
            }
        }
    }
}

func StoreItem(data *string, section *ini.Section, key string) {
    StoreData(data, section.Key(key).String())
}

func StoreItemCsv(data *[]string, section *ini.Section, key string) {
    valStr := section.Key(key).String()
    commentStr := section.Key(key).Comment
    commentStrs := strings.Split(commentStr, ";")
    StoreDataArray(data, valStr)
    StoreDataArray(data, commentStrs...)
}

func StoreItemIterator(data *[]string, section *ini.Section, key, iterator string) {
    valStr := section.Key(key).String()
    maxCnt, _ := strconv.Atoi(valStr)
    for cnt := 0; cnt < maxCnt; cnt++ {
        keyN := iterator + strconv.Itoa(cnt)
        valStr = section.Key(keyN).String()
        StoreDataArray(data, valStr)
    }
}

func IniReader(path string, params []BridgeParamType) (MxprojectAllType, error) {
    var mxprojectAll MxprojectAllType

    if !utils.FileExists(path) {
        text := "File not found: "
        text += path
        return mxprojectAll, errors.New(text)
    }

    inidata, err := GetIni(path)
    if err != nil || inidata == nil {
        text := "File not found or error opening file: .mxproject"
        text += path
        return mxprojectAll, errors.New(text)
    }

    var iniSections []IniSectionsType
    err = GetSections(inidata, &iniSections)
    if err != nil {
        return mxprojectAll, err
    }

    for _, param := range params {
        context := param.CubeContext

        mxproject, _ := GetData(inidata, context, param.Compiler)
        mxproject.Context = context
        mxprojectAll.Mxproject = append(mxprojectAll.Mxproject, mxproject)
    }

    return mxprojectAll, nil
}

func GetIni(path string) (*ini.File, error) {
    log.Debugf("\nReading CubeMX config file: %v", path)

    inidata, err := ini.Load(path)
    if err != nil {
        log.Errorf("Fail to read file: %v", err)
        return inidata, nil
    }

    return inidata, nil
}

func GetSections(inidata *ini.File, iniSections *[]IniSectionsType) error {
    sectionsData := inidata.SectionStrings()
    for _, section := range sectionsData {
        var iniSection IniSectionsType
        sectionString := strings.Split(section, ":")
        if len(sectionString) > 1 {
            iniSection.Context = sectionString[0]
            iniSection.Section = sectionString[1]
        } else {
            iniSection.Context = ""
            iniSection.Section = section
        }

        *iniSections = append(*iniSections, iniSection)
    }

    return nil
}

func GetData(inidata *ini.File, iniName string, compiler string) (MxprojectType, error) {
    var mxproject MxprojectType
    var sectionName string
    var PreviousUsedFilesID string

    PreviousUsedFilesID, err := GetPreviousUsedFilesID(compiler)
    if err != nil {
        return mxproject, err
    }

    if iniName != "" {
        sectionName = iniName + ":" + PreviousUsedFilesID
    } else {
        sectionName = PreviousUsedFilesID
    }
    section := inidata.Section(sectionName)
    if section != nil {
        StoreItemCsv(&mxproject.PreviousUsedFiles.SourceFiles, section, "SourceFiles")
        StoreItemCsv(&mxproject.PreviousUsedFiles.HeaderPath, section, "HeaderPath")
        StoreItemCsv(&mxproject.PreviousUsedFiles.CDefines, section, "CDefines")
        PrintItemCsv(section, "SourceFiles")
        PrintItemCsv(section, "HeaderPath")
        PrintItemCsv(section, "CDefines")
    }

    const PreviousLibFilesID = "PreviousLibFiles"
    if iniName != "" {
        sectionName = iniName + ":" + PreviousLibFilesID
    } else {
        sectionName = PreviousLibFilesID
    }
    section = inidata.Section(sectionName)
    if section != nil {
        StoreItemCsv(&mxproject.PreviousLibFiles.LibFiles, section, "LibFiles")
        PrintItemCsv(section, "LibFiles")
    }

    const PreviousGenFilesID = "PreviousGenFiles"
    if iniName != "" {
        sectionName = iniName + ":" + PreviousGenFilesID
    } else {
        sectionName = PreviousGenFilesID
    }
    section = inidata.Section(sectionName)
    if section != nil {
        StoreItem(&mxproject.PreviousGenFiles.AdvancedFolderStructure, section, "AdvancedFolderStructure")
        StoreItemIterator(&mxproject.PreviousGenFiles.HeaderFilesList, section, "HeaderFileListSize", "HeaderFiles#")
        StoreItemIterator(&mxproject.PreviousGenFiles.HeaderPathList, section, "HeaderFolderListSize", "HeaderPath#")
        StoreItem(&mxproject.PreviousGenFiles.HeaderFiles, section, "HeaderFiles")
        StoreItemIterator(&mxproject.PreviousGenFiles.SourceFilesList, section, "SourceFileListSize", "SourceFiles#")
        StoreItemIterator(&mxproject.PreviousGenFiles.HeaderFilesList, section, "HeaderFileListSize", "HeaderFiles#")
        StoreItemIterator(&mxproject.PreviousGenFiles.SourcePathList, section, "SourceFolderListSize", "SourcePath#")
        StoreItem(&mxproject.PreviousGenFiles.SourceFiles, section, "SourceFiles")

        PrintItem(section, "AdvancedFolderStructure")
        PrintItemIterator(section, "HeaderFileListSize", "HeaderFiles#")
        PrintItemIterator(section, "HeaderFolderListSize", "HeaderPath#")
        PrintItem(section, "HeaderFiles")
        PrintItemIterator(section, "SourceFileListSize", "SourceFiles#")
        PrintItemIterator(section, "HeaderFileListSize", "HeaderFiles#")
        PrintItemIterator(section, "SourceFolderListSize", "SourcePath#")
        PrintItem(section, "SourceFiles")
    }

    return mxproject, nil
}

func GetPreviousUsedFilesID(compiler string) (string, error) {
    var sectionMapping = map[string]string{
        "AC6":   "PreviousUsedKeilFiles",
        "GCC":   "PreviousUsedCubeIDEFiles",
        "IAR":   "PreviousUsedIarFiles",
        "CLANG": "PreviousUsedCubeIDEFiles",
    }

    PreviousUsedFilesID, ok := sectionMapping[compiler]
    if !ok {
        return "", errors.New("unknown compiler")
    }
    return PreviousUsedFilesID, nil
}