Unknown symbols after concatenating regular expression results

Please answer these questions before submitting your issue. Thanks!

What did you do?

I wrote simple version check program that reads data from serial port, searches for version with regular expression, concatenate regular expression groups and check if it is equal with given version in json file. If equal, then PASS is printed, else - failed is printed.
I used win 7 x64 to cross compile for x86.

What did you expect to see?

That my program finds good version.

What did you see instead?

For my colleagues that uses x86 windows 7 version sometimes found version contains unknown symbols like 01.01.20.Rev.05I[AE (This is not the real symbols that was seen but something like that). The same symbols where seen on few computers but only with win7 x86. I can’t reproduce this program for more info.

System details

go version go1.8.1 windows/amd64
GOARCH=“amd64"
GOBIN=”“
GOEXE=”.exe"
GOHOSTARCH="amd64"
GOHOSTOS="windows"
GOOS="windows"
GOPATH=“D:/gopath"
GORACE=”"
GOROOT="c:\go"
GOTOOLDIR="c:\go\pkg\tool\windows_amd64"
GCCGO="gccgo"
CC=“gcc"
GOGCCFLAGS=”-m64 -mthreads -fmessage-length=0 -fdebug-prefix-map=C:\Users\AUKSTK~1.DE\AppData\Local\Temp\go-build617008819=/tmp/go-build -gno-record-gcc-switches"
CXX=“g++“
CGO_ENABLED=“1"
PKG_CONFIG=“pkg-config"
CGO_CFLAGS=”-g -O2"
CGO_CPPFLAGS=”“
CGO_CXXFLAGS=”-g -O2"
CGO_FFLAGS=”-g -O2"
CGO_LDFLAGS=”-g -O2"
GOROOT/bin/go version: go version go1.8.1 windows/amd64
GOROOT/bin/go tool compile -V: compile version go1.8.1 X:framepointer
gdb --version: GNU gdb (GDB) 7.6.1

Source:

main.go:

package main

import (
	"bytes"
	"fmt"
	"os"
	"os/exec"
	"regexp"
	"time"

	"go.bug.st/serial.v1"
)

var settings JSONSettings

var verRegExp, eroras = regexp.Compile("Code Version:(.*)[\\s\\r\\n]Code Rev:(\\d+)")

func main() {
	if settings.Init() != nil {
		CreateSettingsFile()
		settings.Init()
	}
	for {
		time.Sleep(1 * time.Second)
		portWasFound := false
		list, err := serial.GetPortsList()
		if err != nil {
			fmt.Println("Error while listing ports:", err)
		}
		fmt.Printf("List Ports: %v                                                                 \r", list)
		for _, v := range list {
			if v == settings.Port {
				fmt.Println()
				fmt.Printf("Port %s was found\n", settings.Port)
				portWasFound = true
				break
			}
		}
		if portWasFound {
			com, err := openPort(settings.Port)
			if err != nil {
				fmt.Println("Failed to open port:", err)
				continue
			}
			fmt.Println("check version")
			ver, err := checkVersion(com)
			if err != nil {
				fmt.Println("Failed to check Version:", err)
			}
			fmt.Println("Version:", ver)
			if ver != settings.CheckVersion {
				fmt.Println("\n!!!!!!!!!!!!!FAILED!!!!!!!!!!!!!!")
				fmt.Println("!!!!!!!!!!!!!FAILED!!!!!!!!!!!!!!")
				fmt.Println()
			} else {
				fmt.Println()
				fmt.Println("--------PASS--------")
				fmt.Println()
			}
			if com.Close() != nil {
				fmt.Println("Failed to close port!")
				return
			}
			fmt.Println("Wait port to disappear...")
			for {
				portWasFound = false
				list, _ = serial.GetPortsList()
				for _, v := range list {
					if v == settings.Port {
						portWasFound = true
						time.Sleep(1 * time.Second)
					}
				}
				if !portWasFound {
					fmt.Println("Port is gone!")
					cmd := exec.Command("cmd", "/c", "cls")
					cmd.Stdout = os.Stdout
					cmd.Run()
					break
				}
			}
		}
	}
}

func openPort(port string) (serial.Port, error) {
	var err error
	var com serial.Port
	com, err = serial.Open(port, &serial.Mode{BaudRate: 115200, DataBits: 8, Parity: serial.NoParity, StopBits: serial.OneStopBit})
	if err != nil {
		return nil, err
	}
	return com, nil
}

func checkVersion(com serial.Port) (string, error) {
	var version string
	buffer := bytes.Buffer{}
	readBuf := make([]byte, 1024)
	for {
		_, err := com.Write([]byte(".info\r"))
		if err != nil {
			return "", err
		}
		n, err := com.Read(readBuf)
		if err != nil {
			return "", err
		}
		buffer.Write(readBuf[:n])
		subs := verRegExp.FindStringSubmatch(buffer.String())
		if len(subs) > 1 {
			fmt.Println("Found submatch!")
			version = subs[1] + ".Rev." + subs[2]
			break
		}
	}
	return version, nil
}

settings.go:

package main

import (
	"encoding/json"
	"errors"
	"fmt"
	"io/ioutil"
)

const settingsFile string = "Settings.json"

// JSONSettings this is structure for JSON file
type JSONSettings struct {
	Port         string `json:"Port"`
	CheckVersion string `json:"Check Version"`
}

var defaultSettings = `{
	"Port" : "COM12",
	"Check Version" : "01.00.22.Rev.12"
}`

// Init function initializes settings structure from settings.json file. If JSON file is missing, then new one is created
// with default settings.
func (st *JSONSettings) Init() error {
	if err := st.getSettings(); err != nil {
		return fmt.Errorf("settings: %s", err.Error())
	}
	return nil
}

func (st *JSONSettings) getSettings() error {
	file, err := ioutil.ReadFile(settingsFile)
	if err != nil {
		return errors.New("file not found. Check help")
	}
	err = json.Unmarshal([]byte(file), &st)
	if err != nil {
		return fmt.Errorf("can't parse settings: %s", err.Error())
	}
	return nil
}

// CreateSettingsFile - creates settings file in the current directory
func CreateSettingsFile() error {
	if err := ioutil.WriteFile(settingsFile, []byte(defaultSettings), 0644); err != nil {
		return fmt.Errorf("Can't create settings file: %s", err.Error())
	}
	return nil
}

build.cmd:

set GOOS=windows
set GOARCH=386
go build

settings.json:

{
	"Port" : "COM12",
	"Check Version" : "01.00.22.Rev.12"
}

Please fix the formatting of your code, use

[code]
// source code
[/code]

Around large code blocks to make them readable.

At a guess goserial needs some dlls’ installed on the system, they may differ by windows sub version and service pack.

My advice would be to reduce this to the smallest possible problem; remove regex and waiting for the port, just write a short main package that tries to open a serial port – the name should not matter, what you are saying is the program fails to run with unknown symbol errors, not that the program cannot open the serial port.

Once you’ve done that, give the program to the affected user and report back what they see.

Ok, But how searching I don’t see any problem with my regular expression:
var verRegExp, eroras = regexp.Compile(“Code Version:(.*)[\s\r\n]Code Rev:(\d+)”)
and when I find result:

buffer.Write(readBuf[:n])
subs := verRegExp.FindStringSubmatch(buffer.String())
if len(subs) > 1 {
	fmt.Println("Found submatch!")
	version = subs[1] + ".Rev." + subs[2]
	break
}
return version

after this version is 01.10.20.Rev.11I[AE or something. So why I get I[AE symbols when my regular expression is (\d+)?

Thanks for the tip :slight_smile: I fixed formating:)

Can you print out buffer.String()

fmt.Printf("%q\n", bufffer) will do it

This topic was automatically closed 90 days after the last reply. New replies are no longer allowed.