From 566d4363beead21df0edcbf2655cdb3db5d3d1bb Mon Sep 17 00:00:00 2001
From: rokath
Date: Mon, 14 Oct 2024 21:46:35 +0200
Subject: [PATCH] CLI switch -IDRange added, emitter "channels" renamed to
"tags"
---
internal/args/handler.go | 4 +
internal/args/init.go | 6 +-
internal/args/short_test.go | 15 ---
internal/args/tricehelpall_test.go | 13 +-
internal/emitter/emitter.go | 2 +-
internal/emitter/lineTransformerANSI.go | 103 ++++++++-------
internal/id/helper.go | 4 +-
internal/id/range_test.go | 57 +++++++++
internal/id/switchIDs.go | 158 ++++++++++++++++++------
internal/link/link.go | 7 +-
internal/translator/translator.go | 2 +-
internal/trexDecoder/trexDecoder.go | 2 +-
12 files changed, 262 insertions(+), 111 deletions(-)
create mode 100644 internal/id/range_test.go
diff --git a/internal/args/handler.go b/internal/args/handler.go
index aae89365b..566ecd3a2 100644
--- a/internal/args/handler.go
+++ b/internal/args/handler.go
@@ -94,6 +94,10 @@ func Handler(w io.Writer, fSys *afero.Afero, args []string) error {
case "i", "insert":
msg.OnErr(fsScInsert.Parse(subArgs))
id.CompactSrcs()
+ err := id.EvaluateIDRangeStrings()
+ if err != nil {
+ return err
+ }
w = do.DistributeArgs(w, fSys, LogfileName, Verbose)
return id.SubCmdIdInsert(w, fSys)
// // case "zeroSourceTreeIds":
diff --git a/internal/args/init.go b/internal/args/init.go
index aeb8762ec..c76b3f756 100644
--- a/internal/args/init.go
+++ b/internal/args/init.go
@@ -205,9 +205,9 @@ func addInit() {
// }
func insertIDsInit() {
- fsScInsert = flag.NewFlagSet("insertSourceTreeIds", flag.ExitOnError) // sub-command
+ fsScInsert = flag.NewFlagSet("insert", flag.ExitOnError) // sub-command
flagsRefreshAndUpdate(fsScInsert)
- // todo: flagTriceIDRange(fsScInsert)
+ flagTriceIDRange(fsScInsert)
fsScInsert.Var(&id.Min, "IDMin", "Lower end of ID range for normal trices.")
fsScInsert.Var(&id.Max, "IDMax", "Upper end of ID range for normal trices.")
fsScInsert.IntVar(&id.DefaultStampSize, "defaultStampSize", 32, "Default stamp size for written TRICE macros without id(0), Id(0 or ID(0). Valid values are 0, 16 or 32.")
@@ -246,7 +246,7 @@ func scanInit() {
}
func sdInit() {
- fsScSdSv = flag.NewFlagSet("shutdownServer", flag.ExitOnError) // sub-command
+ fsScSdSv = flag.NewFlagSet("shutdown", flag.ExitOnError) // sub-command
flagIPAddress(fsScSdSv)
}
diff --git a/internal/args/short_test.go b/internal/args/short_test.go
index afa678a09..9ad92c7bc 100644
--- a/internal/args/short_test.go
+++ b/internal/args/short_test.go
@@ -13,21 +13,6 @@ import (
"github.com/tj/assert"
)
-// func TestMain(m *testing.M) {
-// id.FnJSON = getTemporaryFileName("til-*.JSON")
-// code := m.Run()
-// msg.OnErr(os.Remove(id.FnJSON))
-// os.Exit(code) // os.Exit() does not respect defer statements
-// }
-
-func getTemporaryFileName(pattern string) string {
- tempFileHandle, e := os.CreateTemp(os.TempDir(), pattern) // opens for read and write
- msg.OnErr(e)
- tempFileName := tempFileHandle.Name()
- msg.OnErr(tempFileHandle.Close())
- return tempFileName
-}
-
func TestHelp(t *testing.T) {
args := []string{"trice", "help"}
expect := `syntax: 'trice sub-command' [params]
diff --git a/internal/args/tricehelpall_test.go b/internal/args/tricehelpall_test.go
index 5e4a217c9..4114dd9fa 100644
--- a/internal/args/tricehelpall_test.go
+++ b/internal/args/tricehelpall_test.go
@@ -396,6 +396,15 @@ sub-command 'i|insert': For updating til.json and inserting IDs into source file
Search method for new ID's in range- Options are 'upward', 'downward' & 'random'. (default "random")
-IDMin value
Lower end of ID range for normal trices. (default 1000)
+ -IDRange value
+ This allows channel specific routing in the target code.
+ This switch has one parameter string and is a multi-flag switch. It can be used for each Trice tag. Example:
+ Assign error tag Trice IDs in the range 10-99 and msg tag IDs in the range 100-199:
+ "trice insert -IDRange err:10,99 -IDRange msg:100,999" (overlapping ID ranges are forbidden)
+ All other trice tags get IDs from the -IDMin, -IDMax range. The used -IDMethod is the same for all tags.
+ For example you can have all trice messages in direct mode over RTT but err & msg tagged trices additionally
+ in deferred mode over a serial port and, if you need, store all error tagged Trice logs additionally in the Flash memory.
+ You need to configure the target code accordingly. (default "")
-addParamCount
Extend TRICE macro names with the parameter count _n to enable compile time checks.
-cache
@@ -404,7 +413,7 @@ sub-command 'i|insert': For updating til.json and inserting IDs into source file
Default stamp size for written TRICE macros without id(0), Id(0 or ID(0). Valid values are 0, 16 or 32. (default 32)
-dry-run
No changes applied but output shows what would happen.
- "trice insertSourceTreeIds -dry-run" will change nothing but show changes it would perform without the "-dry-run" switch.
+ "trice insert -dry-run" will change nothing but show changes it would perform without the "-dry-run" switch.
This is a bool switch. It has no parameters. Its default value is false. If the switch is applied its value is true. You can also set it explicit: =false or =true.
-i string
Short for '-idlist'.
@@ -444,7 +453,7 @@ sub-command 'i|insert': For updating til.json and inserting IDs into source file
-src value
Source dir or file, It has one parameter. Not usable in the form "-src *.c".
This is a multi-flag switch. It can be used several times for directories and also for files.
- Example: "trice insertSourceTreeIds -dry-run -v -src ./test/ -src pkg/src/trice.h" will scan all C|C++ header and
+ Example: "trice insert -dry-run -v -src ./test/ -src pkg/src/trice.h" will scan all C|C++ header and
source code files inside directory ./test and scan also file trice.h inside pkg/src directory.
Without the "-dry-run" switch it would create|extend a list file til.json in the current directory.
(default "./")
diff --git a/internal/emitter/emitter.go b/internal/emitter/emitter.go
index d34703ba7..1c79b9e6e 100644
--- a/internal/emitter/emitter.go
+++ b/internal/emitter/emitter.go
@@ -84,7 +84,7 @@ func appendIfMissing(slice []string, i string) []string {
func (i *channelArrayFlag) Set(value string) error {
ss := strings.Split(value, ":")
for _, s := range ss {
- cv := channelVariants(s)
+ cv := tagVariants(s)
for _, c := range cv {
*i = appendIfMissing(*i, c)
}
diff --git a/internal/emitter/lineTransformerANSI.go b/internal/emitter/lineTransformerANSI.go
index 3f1dd106c..31b14c884 100644
--- a/internal/emitter/lineTransformerANSI.go
+++ b/internal/emitter/lineTransformerANSI.go
@@ -97,64 +97,77 @@ func isLower(s string) bool {
return true
}
-type colorChannel struct {
- events int
- channel []string
- colorize func(string) string
+type tag struct {
+ count int // count counts each occurance of the trice tag.
+ Names []string // name contains all usable names fo a specific tag.
+ colorize func(string) string // colorize is the function called for each tag.
}
-var colorChannels = []colorChannel{
+// Tags contains all usable trice Tags and their possible names.
+var Tags = []tag{
// log level
{0, []string{"Fatal", "fatal", "FATAL"}, colorizeFATAL},
- {0, []string{"Critical", "critical", "CRITICAL", "crit", "Crit", "CRIT"}, colorizeCRITICAL},
- {0, []string{"Emergency", "emergency", "EMERGENCY"}, colorizeEMERGENCY},
- {0, []string{"Error", "e", "err", "error", "E", "ERR", "ERROR"}, colorizeERROR},
- {0, []string{"Warning", "w", "wrn", "warning", "W", "WRN", "WARNING", "Warn", "warn", "WARN"}, colorizeWARNING},
+ {0, []string{"crit", "Critical", "critical", "CRITICAL", "Crit", "CRIT"}, colorizeCRITICAL},
+ {0, []string{"em", "Emergency", "emergency", "EMERGENCY"}, colorizeEMERGENCY},
+ {0, []string{"e", "Error", "err", "error", "E", "ERR", "ERROR"}, colorizeERROR},
+ {0, []string{"w", "wrn", "Warning", "warning", "W", "WRN", "WARNING", "Warn", "warn", "WARN"}, colorizeWARNING},
{0, []string{"att", "attention", "Attention", "ATT", "ATTENTION"}, colorizeATTENTION},
- {0, []string{"Info", "i", "inf", "info", "informal", "I", "INF", "INFO", "INFORMAL"}, colorizeINFO},
- {0, []string{"Debug", "d", "db", "dbg", "deb", "debug", "D", "DB", "DBG", "DEBUG"}, colorizeDEBUG},
- {0, []string{"Trace", "trace", "TRACE"}, colorizeTRACE},
+ {0, []string{"i", "inf", "info", "Info", "informal", "I", "INF", "INFO", "INFORMAL"}, colorizeINFO},
+ {0, []string{"d", "db", "Debug", "dbg", "deb", "debug", "D", "DB", "DBG", "DEBUG"}, colorizeDEBUG},
+ {0, []string{"tr", "Trace", "trace", "TRACE"}, colorizeTRACE},
// user modes
- {0, []string{"Timestamp", "tim", "time", "TIM", "TIME", "TIMESTAMP", "timestamp"}, colorizeTIME},
+ {0, []string{"tim", "time", "TIM", "TIME", "TIMESTAMP", "timestamp", "Timestamp"}, colorizeTIME},
{0, []string{"m", "msg", "message", "M", "MSG", "MESSAGE", "OK"}, colorizeMESSAGE},
{0, []string{"r", "rx", "rd", "read", "rd_", "RD", "RD_", "READ"}, colorizeREAD},
{0, []string{"w", "tx", "wr", "write", "wr_", "WR", "WR_", "WRITE"}, colorizeWRITE},
- {0, []string{"receive", "rx", "RECEIVE", "Receive", "RX"}, colorizeRECEIVE},
- {0, []string{"transmit", "tx", "TRANSMIT", "Transmit", "TX"}, colorizeTRANSMIT},
+ {0, []string{"rx", "receive", "RECEIVE", "Receive", "RX"}, colorizeRECEIVE},
+ {0, []string{"tx", "transmit", "TRANSMIT", "Transmit", "TX"}, colorizeTRANSMIT},
{0, []string{"dia", "diag", "Diag", "DIA", "DIAG"}, colorizeDIAG},
{0, []string{"int", "isr", "ISR", "INT", "interrupt", "Interrupt", "INTERRUPT"}, colorizeINTERRUPT},
{0, []string{"s", "sig", "signal", "S", "SIG", "SIGNAL"}, colorizeSIGNAL},
{0, []string{"t", "tst", "test", "T", "TST", "TEST"}, colorizeTEST},
- {0, []string{"Default", "DEFAULT", "default"}, colorizeDEFAULT},
- {0, []string{"Notice", "NOTICE", "notice", "Note", "note", "NOTE"}, colorizeNOTICE},
+ {0, []string{"def", "Default", "DEFAULT", "default"}, colorizeDEFAULT},
+ {0, []string{"note", "Notice", "NOTICE", "notice", "Note", "NOTE"}, colorizeNOTICE},
{0, []string{"Alert", "alert", "ALERT"}, colorizeALERT},
{0, []string{"Assert", "assert", "ASSERT"}, colorizeASSERT},
- {0, []string{"Alarm", "alarm", "ALARM"}, colorizeALARM},
- {0, []string{"cycle", "CYCLE"}, colorizeCYCLE},
- {0, []string{"Verbose", "verbose", "VERBOSE"}, colorizeVERBOSE},
+ {0, []string{"a", "Alarm", "alarm", "ALARM"}, colorizeALARM},
+ {0, []string{"cy", "cycle", "CYCLE"}, colorizeCYCLE},
+ {0, []string{"v", "Verbose", "verbose", "VERBOSE"}, colorizeVERBOSE},
}
-// ColorChannelEvents returns count of occurred channel events.
+func FindTagName(name string) (tagName string, err error) {
+ for _, t := range Tags {
+ for _, tn := range t.Names {
+ if tn == name {
+ tagName = t.Names[0] // take the first tag name as reference.
+ return
+ }
+ }
+ }
+ return "", fmt.Errorf("no tagName found for name %s", name)
+}
+
+// TagEvents returns count of occurred channel events.
// If ch is unknown, the returned value is -1.
-func ColorChannelEvents(ch string) int {
- for _, s := range colorChannels {
- for _, c := range s.channel {
+func TagEvents(ch string) int {
+ for _, s := range Tags {
+ for _, c := range s.Names {
if c == ch {
- return s.events
+ return s.count
}
}
}
return -1
}
-// PrintColorChannelEvents shows the amount of occurred channel events.
-func PrintColorChannelEvents(w io.Writer) {
- for _, s := range colorChannels {
- if s.events != 0 {
- fmt.Fprintf(w, "%6d times: ", s.events)
- for _, c := range s.channel {
+// PrintTagEvents shows the amount of occurred channel events.
+func PrintTagEvents(w io.Writer) {
+ for _, s := range Tags {
+ if s.count != 0 {
+ fmt.Fprintf(w, "%6d times: ", s.count)
+ for _, c := range s.Names {
if ColorPalette != "off" && ColorPalette != "none" {
c = s.colorize(c)
}
@@ -165,22 +178,22 @@ func PrintColorChannelEvents(w io.Writer) {
}
}
-// channelVariants returns all variants of ch as string slice.
+// tagVariants returns all variants of ch as string slice.
// If ch is not inside ansiSel nil is returned.
-func channelVariants(ch string) []string {
- for _, s := range colorChannels {
- for _, c := range s.channel {
+func tagVariants(ch string) []string {
+ for _, s := range Tags {
+ for _, c := range s.Names {
if c == ch {
- return s.channel
+ return s.Names
}
}
}
return nil
}
-// isChannel returns true if ch is any ansiSel string.
-func isChannel(ch string) bool {
- cv := channelVariants(ch)
+// isTag returns true if tag is any tag variant string.
+func isTag(tag string) bool {
+ cv := tagVariants(tag)
return cv != nil
}
@@ -203,10 +216,10 @@ func (p *lineTransformerANSI) colorize(s string) (r string, show bool) {
if len(sc) < 2 { // no color separator (no log level)
return r, true // do nothing, return unchanged string
}
- for i, cc := range colorChannels {
- for _, c := range cc.channel {
+ for i, cc := range Tags {
+ for _, c := range cc.Names {
if c == sc[0] {
- colorChannels[i].events++ // count event
+ Tags[i].count++ // count event
logLev = i
}
if c == LogLevel {
@@ -223,14 +236,14 @@ func (p *lineTransformerANSI) colorize(s string) (r string, show bool) {
if p.colorPalette == "off" {
return r, true // do nothing (despite event counting)
}
- if isChannel(sc[0]) && isLower(sc[0]) {
+ if isTag(sc[0]) && isLower(sc[0]) {
r = sc[1] // remove channel info
}
if p.colorPalette == "none" {
return r, true
}
- for _, cs := range colorChannels {
- for _, c := range cs.channel {
+ for _, cs := range Tags {
+ for _, c := range cs.Names {
if c == sc[0] {
return cs.colorize(r), true
}
diff --git a/internal/id/helper.go b/internal/id/helper.go
index 2c9eacf28..3eb344151 100644
--- a/internal/id/helper.go
+++ b/internal/id/helper.go
@@ -22,6 +22,8 @@ import (
"github.com/spf13/afero"
)
+var SkipAdditionalChecks bool
+
// CompactSrcs adds local dir to Srcs if Srcs is empty and reduces variable Scrs to the minimum to address all intended folders.
func CompactSrcs() {
if len(Srcs) == 0 { // Srcs is an array flag containing desired folders & files
@@ -34,8 +36,6 @@ func CompactSrcs() {
Srcs = slices.Compact(Srcs)
}
-var SkipAdditionalChecks bool
-
// fileExists returns true, if path exits.
func fileExists(fSys *afero.Afero, path string) bool {
if _, err := fSys.Stat(path); err == nil {
diff --git a/internal/id/range_test.go b/internal/id/range_test.go
new file mode 100644
index 000000000..5b00d64a9
--- /dev/null
+++ b/internal/id/range_test.go
@@ -0,0 +1,57 @@
+// Copyright 2024 Thomas.Hoehenleitner [at] seerose.net
+// Use of this source code is governed by a license that can be found in the LICENSE file.
+
+package id_test
+
+import (
+ "fmt"
+ "testing"
+
+ "github.com/rokath/trice/internal/args"
+ . "github.com/rokath/trice/internal/id"
+ "github.com/tj/assert"
+)
+
+// source tree management
+
+func TestRange0(t *testing.T) {
+ defer Setup(t)()
+
+ // create src file
+ sFn := t.Name() + "file.c"
+ src := `trice("msg:Hi\n");trice("err:Alarm!\n");trice("msg:Lo\n");`
+ assert.Nil(t, FSys.WriteFile(sFn, []byte(src), 0777))
+
+ // action
+ assert.Nil(t, args.Handler(W, FSys, []string{"trice", "insert", "-IDMethod", "upward", "-src", sFn, "-til", FnJSON, "-li", LIFnJSON}))
+
+ // check modified src file
+ expSrc := `trice(iD(1000), "msg:Hi\n");trice(iD(1001), "err:Alarm!\n");trice(iD(1002), "msg:Lo\n");`
+
+ actSrc, e := FSys.ReadFile(sFn)
+ assert.Nil(t, e)
+
+ assert.Equal(t, expSrc, string(actSrc))
+}
+
+func TestRange1(t *testing.T) {
+ defer Setup(t)()
+
+ // create src file
+ sFn := t.Name() + "file.c"
+ src := `trice("msg:Hi\n"); ... trice("err:Alarm!\n"); ... trice("msg:Lo\n"); ... trice("dbg:foo\n");`
+ assert.Nil(t, FSys.WriteFile(sFn, []byte(src), 0777))
+
+ // action
+ assert.Nil(t, args.Handler(W, FSys, []string{"trice", "insert", "-IDRange", "e:100,109", "-IDRange", "dbg:200,209", "-IDMax=1005", "-IDMethod", "upward", "-src", sFn, "-til", FnJSON, "-li", LIFnJSON}))
+
+ fmt.Println(IDData.IDSpace)
+
+ // check modified src file
+ expSrc := `trice(iD(1000), "msg:Hi\n"); ... trice(iD(100), "err:Alarm!\n"); ... trice(iD(1001), "msg:Lo\n"); ... trice(iD(200), "dbg:foo\n");`
+
+ actSrc, e := FSys.ReadFile(sFn)
+ assert.Nil(t, e)
+
+ assert.Equal(t, expSrc, string(actSrc))
+}
diff --git a/internal/id/switchIDs.go b/internal/id/switchIDs.go
index ad58186e7..aa15da8f9 100644
--- a/internal/id/switchIDs.go
+++ b/internal/id/switchIDs.go
@@ -10,8 +10,10 @@ import (
"io"
"log"
"math/rand"
+ "strconv"
"strings"
+ "github.com/rokath/trice/internal/emitter"
"github.com/rokath/trice/pkg/ant"
"github.com/rokath/trice/pkg/msg"
"github.com/spf13/afero"
@@ -19,28 +21,28 @@ import (
// idData holds the Id specific data.
type idData struct {
- idToTrice TriceIDLookUp // idToTrice is a trice ID lookup map and is generated from existing til.json file at the begin of SubCmdIdInsert. This map is only extended during SubCmdIdInsert and goes back into til.json afterwards.
- triceToId triceFmtLookUp // triceToId is a trice fmt lookup map (reversed idToFmt for faster operation). Each fmt can have several trice IDs (slice). This map is only reduced during SubCmdIdInsert and goes _not_ back into til.json afterwards.
- idToLocRef TriceIDLookUpLI // idToLocRef is the trice ID location information as reference generated from li.json (if exists) at the begin of SubCmdIdInsert and is not modified at all. At the end of SubCmdIdInsert a new li.json is generated from itemToId.
- idToLocNew TriceIDLookUpLI // idToLocNew is the trice ID location information generated during insertTriceIDs. At the end of SubCmdIdInsert a new li.json is generated from idToLocRef + idToLocNew.
- idInitialCount int // idInitialCount is the initial used ID count.
- IDSpace []triceTagIDSpace // IDSpace contains the tag specific unused IDs.
+ idToTrice TriceIDLookUp // idToTrice is a trice ID lookup map and is generated from existing til.json file at the begin of SubCmdIdInsert. This map is only extended during SubCmdIdInsert and goes back into til.json afterwards.
+ triceToId triceFmtLookUp // triceToId is a trice fmt lookup map (reversed idToFmt for faster operation). Each fmt can have several trice IDs (slice). This map is only reduced during SubCmdIdInsert and goes _not_ back into til.json afterwards.
+ idToLocRef TriceIDLookUpLI // idToLocRef is the trice ID location information as reference generated from li.json (if exists) at the begin of SubCmdIdInsert and is not modified at all. At the end of SubCmdIdInsert a new li.json is generated from itemToId.
+ idToLocNew TriceIDLookUpLI // idToLocNew is the trice ID location information generated during insertTriceIDs. At the end of SubCmdIdInsert a new li.json is generated from idToLocRef + idToLocNew.
+ idInitialCount int // idInitialCount is the initial used ID count.
+ IDSpace []TagIDSpace // IDSpace contains the tag specific unused IDs.
err error
}
-// triceTagIDSpace is a Trice tag specific ID space, specified with the -IDTag CLI switch.
+// TagIDSpace is a Trice tag specific ID space, specified with the -IDTag CLI switch.
// Example: "trice insert -IDTag err:10,99" specifies for the Trice tag "err" the ID space 10-99.
-type triceTagIDSpace struct {
- tag string // tag is the Trice message tag like "err" in TRice("err:foo");.
- Min TriceID // Min is the smallest allowed trice tag specific ID.
- Max TriceID // Max is the biggest allowed trice tag specific ID.
- idSpace []TriceID // idSpace is the to tag assigned ID space.
+type TagIDSpace struct {
+ tagName string // TagName is the Trice message tag like "err" in TRice("err:foo");.
+ min TriceID // Min is the smallest allowed trice tag specific ID.
+ max TriceID // Max is the biggest allowed trice tag specific ID.
+ iDSpace []TriceID // idSpace is the to tag assigned ID space.
}
// IDIsPartOfIDSpace returns true if ID is existent inside p.IDSpace.
func (p *idData) IDIsPartOfIDSpace(id TriceID) bool {
for _, tis := range p.IDSpace {
- for _, iD := range tis.idSpace {
+ for _, iD := range tis.iDSpace {
if iD == id {
return true
}
@@ -54,14 +56,14 @@ func (p *idData) IDIsPartOfIDSpace(id TriceID) bool {
// Example: When -IDMin=10, -IDMax=20 and id=99 found in source.
func (p *idData) removeIDFromIDSpace(id TriceID) {
for _, tis := range p.IDSpace {
- for idx, iD := range tis.idSpace {
+ for idx, iD := range tis.iDSpace {
if iD == id {
if SearchMethod == "random" { // do not care about order inside tag.idSpace, so do it fast
- fmt.Println("tag.idSpace=", tis.idSpace, "idx=", idx, "iD=", iD)
- tis.idSpace[idx] = tis.idSpace[len(tis.idSpace)-1] // overwrite with last
- tis.idSpace = tis.idSpace[:len(tis.idSpace)-1] // remove last
+ fmt.Println("tag.idSpace=", tis.iDSpace, "idx=", idx, "iD=", iD)
+ tis.iDSpace[idx] = tis.iDSpace[len(tis.iDSpace)-1] // overwrite with last
+ tis.iDSpace = tis.iDSpace[:len(tis.iDSpace)-1] // remove last
} else { // keep order inside tag.idSpace, so do it costly
- tis.idSpace = append(tis.idSpace[:idx], tis.idSpace[idx+1:]...)
+ tis.iDSpace = append(tis.iDSpace[:idx], tis.iDSpace[idx+1:]...)
}
}
}
@@ -69,7 +71,7 @@ func (p *idData) removeIDFromIDSpace(id TriceID) {
}
// triceTag returns the trice tag, if any, or an empty string.
-func triceTag(t TriceFmt) string { // t.Strg contains the Trice tag information: string until the first colon matches a string in emitter.colorChannels.
+func triceTag(t TriceFmt) string { // t.Strg contains the Trice tag information: string until the first colon matches a string in emitter.tags.
before, _, ok := strings.Cut(t.Strg, ":")
if !ok {
return ""
@@ -80,27 +82,28 @@ func triceTag(t TriceFmt) string { // t.Strg contains the Trice tag information:
// newID returns a new, so far unused trice ID for usage.
// The global variable SearchMethod controls the way a new ID is selected.
func (p *idData) newID(t TriceFmt) (id TriceID) {
- tag := triceTag(t)
+ name := triceTag(t)
+ tag, _ := emitter.FindTagName(name)
common:
for i := range p.IDSpace {
// tis := p.IDSpace[i] <-- Why does this not work? todo
- if tag != p.IDSpace[i].tag {
+ if tag != p.IDSpace[i].tagName {
continue
}
if SearchMethod == "random" {
- if len(p.IDSpace[i].idSpace) <= 0 {
+ if len(p.IDSpace[i].iDSpace) <= 0 {
log.Fatal("Remaining IDSpace = is empty, check til.json. (You could re-create it or change -IDMin, -IDMax)")
}
- index := rand.Intn(len(p.IDSpace[i].idSpace))
- id = p.IDSpace[i].idSpace[index] // use random
- p.IDSpace[i].idSpace[index] = p.IDSpace[i].idSpace[len(p.IDSpace[i].idSpace)-1] // overwrite with last
- p.IDSpace[i].idSpace = p.IDSpace[i].idSpace[:len(p.IDSpace[i].idSpace)-1] // remove last
+ index := rand.Intn(len(p.IDSpace[i].iDSpace))
+ id = p.IDSpace[i].iDSpace[index] // use random
+ p.IDSpace[i].iDSpace[index] = p.IDSpace[i].iDSpace[len(p.IDSpace[i].iDSpace)-1] // overwrite with last
+ p.IDSpace[i].iDSpace = p.IDSpace[i].iDSpace[:len(p.IDSpace[i].iDSpace)-1] // remove last
} else if SearchMethod == "upward" {
- id = p.IDSpace[i].idSpace[0] // use first
- p.IDSpace[i].idSpace = p.IDSpace[i].idSpace[1:] // remove first
+ id = p.IDSpace[i].iDSpace[0] // use first
+ p.IDSpace[i].iDSpace = p.IDSpace[i].iDSpace[1:] // remove first
} else {
- id = p.IDSpace[i].idSpace[len(p.IDSpace[i].idSpace)-1] // use last
- p.IDSpace[i].idSpace = p.IDSpace[i].idSpace[:len(p.IDSpace[i].idSpace)-1] // remove last
+ id = p.IDSpace[i].iDSpace[len(p.IDSpace[i].iDSpace)-1] // use last
+ p.IDSpace[i].iDSpace = p.IDSpace[i].iDSpace[:len(p.IDSpace[i].iDSpace)-1] // remove last
}
return
}
@@ -126,21 +129,21 @@ func (p *idData) PreProcessing(w io.Writer, fSys *afero.Afero) {
p.GetIDStateFromJSONFiles(w, fSys)
- var common triceTagIDSpace
+ var common TagIDSpace
- common.tag = ""
- common.Min = Min
- common.Max = Max
+ common.tagName = ""
+ common.min = Min
+ common.max = Max
p.IDSpace = append(p.IDSpace, common)
for i, tis := range p.IDSpace {
- for id := tis.Min; id <= tis.Max; id++ {
+ for id := tis.min; id <= tis.max; id++ {
_, usedFmt := p.idToTrice[id]
_, usedLoc := p.idToLocRef[id]
if !usedFmt && !usedLoc {
//tis.idSpace = append(tis.idSpace, id) //<- does not work here! todo: why?
- p.IDSpace[i].idSpace = append(p.IDSpace[i].idSpace, id)
+ p.IDSpace[i].iDSpace = append(p.IDSpace[i].iDSpace, id)
} else if Verbose {
if usedFmt && !usedLoc {
fmt.Fprintln(w, "ID", id, "used, but only inside til.json")
@@ -154,7 +157,7 @@ func (p *idData) PreProcessing(w io.Writer, fSys *afero.Afero) {
}
}
if Verbose {
- fmt.Fprintln(w, "trice tag", tis.tag, "has", tis.Max-tis.Min+1, "IDs total space,", len(tis.idSpace), "IDs usable")
+ fmt.Fprintln(w, "trice tag", tis.tagName, "has", tis.max-tis.min+1, "IDs total space,", len(tis.iDSpace), "IDs usable")
}
}
}
@@ -198,3 +201,84 @@ func (p *idData) cmdSwitchTriceIDs(w io.Writer, fSys *afero.Afero, action ant.Pr
p.postProcessing(w, fSys)
return err
}
+
+// EvaluateIDRangeStrings reads the -IDRange strings and fills the IDData.IDSpace accordingly.
+// Each tag (like "err:") is allowed to occur only once, so a "e:" will fail after "err" was applied.
+// IDRanges are not allowed to overlap.
+func EvaluateIDRangeStrings() error {
+ var (
+ tis *TagIDSpace
+ mi, ma int
+ err error
+ )
+ // Interpret supplied IDRange string.
+ for _, x := range IDRange {
+ tis = new(TagIDSpace)
+ name, mima, found := strings.Cut(x, ":")
+ if !found {
+ continue
+ }
+ min, max, ok := strings.Cut(mima, ",")
+ if !ok {
+ goto returnErr
+ }
+ mi, err = strconv.Atoi(min)
+ if err != nil {
+ goto returnErr
+ }
+ tis.min = TriceID(mi)
+ ma, err = strconv.Atoi(max)
+ if err != nil {
+ goto returnErr
+ }
+ tis.max = TriceID(ma)
+ if mi > ma {
+ return fmt.Errorf("the with -IDRange applied ID range is inval Min(%d) > Max(%d)", mi, ma)
+ }
+ // Find tis.TagName.
+ for _, t := range emitter.Tags {
+ for _, tn := range t.Names {
+ if tn == name {
+ tis.tagName = t.Names[0] // take the first tag name as reference.
+ goto next
+ }
+ }
+ }
+ return fmt.Errorf("the with -IDRange applied name %s is unknown. Please check var Tags inside trice/internal/emitter/lineTransformerANSI.go for options", name)
+ next:
+ // Check for single name range assignment.
+ for _, ts := range IDData.IDSpace {
+ if ts.tagName == tis.tagName {
+ return fmt.Errorf("tagName %s has already an assigned ID range. Please check your command line", tis.tagName)
+ }
+ }
+ // Check for non overlapping ranges.
+ if !(Max < tis.min || tis.max < Min) {
+ return fmt.Errorf("overlapping ID ranges for %s (Min %d, Max %d) and default (Min %d, Max %d)", tis.tagName, tis.min, tis.max, Min, Max)
+ }
+ for _, ts := range IDData.IDSpace {
+ if ts.tagName == tis.tagName {
+ return fmt.Errorf("tagName %s has already an assigned ID range. Please check your command line", tis.tagName)
+ }
+ // ts.Min --- ts.Max --- tis.Min --- tis.Max <- non-overlapping: ts.Max < tis.Min
+ // tis.Min --- tis.Max --- ts.Min --- ts.Max <- non-overlapping: tis.Max < ts.Min
+ // ts.Min --- tis.Min --- tis.Max --- ts.Max <- !!! overlapping
+ // tis.Min --- ts.Min --- ts.Max --- tis.Max <- !!! overlapping
+ // tis.Min --- ts.Min --- tis.Max --- ts.Max <- !!! overlapping
+ // ts.Min --- tis.Min --- ts.Max --- tis.Max <- !!! overlapping
+ if !(ts.max < tis.min || tis.max < ts.min) {
+ return fmt.Errorf("overlapping ID ranges for %s (Min %d, Max %d) and %s (Min %d, Max %d)", tis.tagName, tis.min, tis.max, ts.tagName, ts.min, ts.max)
+ }
+ }
+ // Fill ID space.
+ for iD := tis.min; iD <= tis.max; iD++ {
+ tis.iDSpace = append(tis.iDSpace, iD)
+ }
+ IDData.IDSpace = append(IDData.IDSpace, *tis)
+ continue
+
+ returnErr:
+ return fmt.Errorf("invalid syntax in %s - expecting \"TagName:number,number\"", x)
+ }
+ return nil
+}
diff --git a/internal/link/link.go b/internal/link/link.go
index 8cd100c7b..caad3f217 100644
--- a/internal/link/link.go
+++ b/internal/link/link.go
@@ -18,7 +18,6 @@ import (
"time"
"github.com/pkg/errors"
- "github.com/rokath/trice/internal/id"
"github.com/rokath/trice/pkg/msg"
"github.com/spf13/afero"
)
@@ -109,11 +108,11 @@ func NewDevice(w io.Writer, fSys *afero.Afero, port, arguments string) *Device {
}
} else {
// get a temporary file name in a writable folder temp
- dir := filepath.Dir(id.FnJSON) // the id list folder is assumed to be writable and readable
+ //dir := filepath.Dir(id.FnJSON) // the id list folder is assumed to be writable and readable
// create temp folder if not exists
- tempDir := filepath.Join(dir, "temp")
- e := os.MkdirAll(tempDir, os.ModePerm)
+ tempDir := "./temp" // filepath.Join(dir, "temp")
+ e := fSys.MkdirAll(tempDir, os.ModePerm)
msg.OnErr(e)
// create a new file
diff --git a/internal/translator/translator.go b/internal/translator/translator.go
index 76d04903e..3c2ad73fd 100644
--- a/internal/translator/translator.go
+++ b/internal/translator/translator.go
@@ -91,7 +91,7 @@ func handleSIGTERM(w io.Writer, rc io.ReadCloser) {
if Verbose {
fmt.Fprintln(w, "####################################", sig, "####################################")
}
- emitter.PrintColorChannelEvents(w)
+ emitter.PrintTagEvents(w)
msg.FatalOnErr(rc.Close())
os.Exit(0) // end
case <-ticker.C:
diff --git a/internal/trexDecoder/trexDecoder.go b/internal/trexDecoder/trexDecoder.go
index e90004253..733fbff30 100644
--- a/internal/trexDecoder/trexDecoder.go
+++ b/internal/trexDecoder/trexDecoder.go
@@ -435,7 +435,7 @@ func (p *trexDec) Read(b []byte) (n int, err error) {
}
if cycle != 0xc0 { // with cycle counter and s.th. lost
if cycle != p.cycle { // no cycle check for 0xc0 to avoid messages on every target reset and when no cycle counter is active
- n += copy(b[n:], fmt.Sprint("CYCLE:\a", cycle, "!=", p.cycle, " # ", emitter.ColorChannelEvents("CYCLE")+1, " # "))
+ n += copy(b[n:], fmt.Sprint("CYCLE:\a", cycle, "!=", p.cycle, " # ", emitter.TagEvents("CYCLE")+1, " # "))
p.cycle = cycle // adjust cycle
}
decoder.InitialCycle = false
|