Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
60 changes: 6 additions & 54 deletions interp/functions.go
Original file line number Diff line number Diff line change
Expand Up @@ -53,13 +53,13 @@ func (p *interp) callNative(index int, args []value) (value, error) {
return null(), nil
case 1:
// Single return value
return fromNative(outs[0]), nil
return fromNative(outs[0], p.chars), nil
case 2:
// Two-valued return of (scalar, error)
if !outs[1].IsNil() {
return null(), outs[1].Interface().(error)
}
return fromNative(outs[0]), nil
return fromNative(outs[0], p.chars), nil
default:
// Should never happen (checked at parse time)
panic(fmt.Sprintf("unexpected number of return values: %d", len(outs)))
Expand Down Expand Up @@ -110,7 +110,7 @@ func (p *interp) toNative(v value, typ reflect.Type) reflect.Value {
}

// Convert from a native Go value to an AWK value
func fromNative(v reflect.Value) value {
func fromNative(v reflect.Value, chars bool) value {
switch v.Kind() {
case reflect.Bool:
return boolean(v.Bool())
Expand All @@ -121,10 +121,10 @@ func fromNative(v reflect.Value) value {
case reflect.Float32, reflect.Float64:
return num(v.Float())
case reflect.String:
return str(v.String())
return str(v.String(), chars)
case reflect.Slice:
if b, ok := v.Interface().([]byte); ok {
return str(string(b))
return str(string(b), chars)
}
// Shouldn't happen: prevented by checkNativeFunc
panic(fmt.Sprintf("unexpected return slice: %s", v.Type().Elem().Kind()))
Expand Down Expand Up @@ -279,7 +279,7 @@ func (p *interp) split(s string, scope resolver.Scope, index int, fs string, mod
}
array := make(map[string]value, len(parts))
for i, part := range parts {
array[strconv.Itoa(i+1)] = numStr(part)
array[strconv.Itoa(i+1)] = numStr(part, p.chars)
}
p.arrays[p.arrayIndex(scope, index)] = array
return len(array), nil
Expand Down Expand Up @@ -449,51 +449,3 @@ func (p *interp) sprintf(format string, args []value) (string, error) {
}
return fmt.Sprintf(format, converted...), nil
}

func substrChars(s string, pos int) string {
// Count characters till we get to pos.
chars := 1
start := 0
for start = range s {
chars++
if chars > pos {
break
}
}
if pos >= chars {
start = len(s)
}
return s[start:]
}

func substrLengthChars(s string, pos, length int) string {
// Count characters till we get to pos.
chars := 1
start := 0
for start = range s {
chars++
if chars > pos {
break
}
}
if pos >= chars {
start = len(s)
}

// Count characters from start till we reach length.
chars = 0
end := 0
for end = range s[start:] {
chars++
if chars > length {
break
}
}
if length >= chars {
end = len(s)
} else {
end += start
}

return s[start:end]
}
46 changes: 23 additions & 23 deletions interp/interp.go
Original file line number Diff line number Diff line change
Expand Up @@ -475,10 +475,10 @@ func (p *interp) setExecuteConfig(config *Config) error {

// Set up ARGV and other variables from config
argvIndex := p.arrayIndexes["ARGV"]
p.setArrayValue(resolver.Global, argvIndex, "0", str(config.Argv0))
p.setArrayValue(resolver.Global, argvIndex, "0", str(config.Argv0, p.chars))
p.argc = len(config.Args) + 1
for i, arg := range config.Args {
p.setArrayValue(resolver.Global, argvIndex, strconv.Itoa(i+1), numStr(arg))
p.setArrayValue(resolver.Global, argvIndex, strconv.Itoa(i+1), numStr(arg, p.chars))
}
p.noArgVars = config.NoArgVars
p.filenameIndex = 1
Expand All @@ -505,13 +505,13 @@ func (p *interp) setExecuteConfig(config *Config) error {
environIndex := p.arrayIndexes["ENVIRON"]
if config.Environ != nil {
for i := 0; i < len(config.Environ); i += 2 {
p.setArrayValue(resolver.Global, environIndex, config.Environ[i], numStr(config.Environ[i+1]))
p.setArrayValue(resolver.Global, environIndex, config.Environ[i], numStr(config.Environ[i+1], p.chars))
}
} else {
for _, kv := range os.Environ() {
key, val, ok := strings.Cut(kv, "=")
if ok {
p.setArrayValue(resolver.Global, environIndex, key, numStr(val))
p.setArrayValue(resolver.Global, environIndex, key, numStr(val, p.chars))
}
}
}
Expand Down Expand Up @@ -748,27 +748,27 @@ func (p *interp) getSpecial(index int) value {
case ast.V_ARGC:
return num(float64(p.argc))
case ast.V_CONVFMT:
return str(p.convertFormat)
return str(p.convertFormat, p.chars)
case ast.V_FILENAME:
return p.filename
case ast.V_FS:
return str(p.fieldSep)
return str(p.fieldSep, p.chars)
case ast.V_OFMT:
return str(p.outputFormat)
return str(p.outputFormat, p.chars)
case ast.V_OFS:
return str(p.outputFieldSep)
return str(p.outputFieldSep, p.chars)
case ast.V_ORS:
return str(p.outputRecordSep)
return str(p.outputRecordSep, p.chars)
case ast.V_RS:
return str(p.recordSep)
return str(p.recordSep, p.chars)
case ast.V_RT:
return str(p.recordTerminator)
return str(p.recordTerminator, p.chars)
case ast.V_SUBSEP:
return str(p.subscriptSep)
return str(p.subscriptSep, p.chars)
case ast.V_INPUTMODE:
return str(inputModeString(p.inputMode, p.csvInputConfig))
return str(inputModeString(p.inputMode, p.csvInputConfig), p.chars)
case ast.V_OUTPUTMODE:
return str(outputModeString(p.outputMode, p.csvOutputConfig))
return str(outputModeString(p.outputMode, p.csvOutputConfig), p.chars)
default:
panic(fmt.Sprintf("unexpected special variable index: %d", index))
}
Expand All @@ -778,11 +778,11 @@ func (p *interp) getSpecial(index int) value {
func (p *interp) setVarByName(name, value string) error {
index := ast.SpecialVarIndex(name)
if index > 0 {
return p.setSpecial(index, numStr(value))
return p.setSpecial(index, numStr(value, p.chars))
}
index, ok := p.scalarIndexes[name]
if ok {
p.globals[index] = numStr(value)
p.globals[index] = numStr(value, p.chars)
return nil
}
// Ignore variables that aren't defined in program
Expand Down Expand Up @@ -925,25 +925,25 @@ func (p *interp) setArrayValue(scope resolver.Scope, arrayIndex int, index strin
func (p *interp) getField(index int) value {
if index == 0 {
if p.lineIsTrueStr {
return str(p.line)
return str(p.line, p.chars)
} else {
return numStr(p.line)
return numStr(p.line, p.chars)
}
}
p.ensureFields()
if index < 1 {
index = len(p.fields) + 1 + index
if index < 1 {
return str("")
return str("", p.chars)
}
}
if index > len(p.fields) {
return str("")
return str("", p.chars)
}
if p.fieldsIsTrueStr[index-1] {
return str(p.fields[index-1])
return str(p.fields[index-1], p.chars)
} else {
return numStr(p.fields[index-1])
return numStr(p.fields[index-1], p.chars)
}
}

Expand All @@ -961,7 +961,7 @@ func (p *interp) getFieldByName(name string) (value, error) {
}
index := p.fieldIndexes[name]
if index == 0 {
return str(""), nil
return str("", p.chars), nil
}
return p.getField(index), nil
}
Expand Down
4 changes: 2 additions & 2 deletions interp/io.go
Original file line number Diff line number Diff line change
Expand Up @@ -285,7 +285,7 @@ func (p *interp) setFieldNames(names []string) {
delete(fieldsArray, k)
}
for i, name := range names {
fieldsArray[strconv.Itoa(i+1)] = str(name)
fieldsArray[strconv.Itoa(i+1)] = str(name, p.chars)
}
}

Expand Down Expand Up @@ -620,7 +620,7 @@ func nextRune(b []byte) rune {

// Setup for a new input file with given name (empty string if stdin)
func (p *interp) setFile(filename string) {
p.filename = numStr(filename)
p.filename = numStr(filename, p.chars)
p.fileLineNum = 0
p.hadFiles = true
}
Expand Down
35 changes: 30 additions & 5 deletions interp/value.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,8 @@ const (
type value struct {
typ valueType // Type of value
s string // String value (for typeStr and typeNumStr)
n float64 // Numeric value (for typeNum)
r *[]rune
n float64 // Numeric value (for typeNum)
}

// Create a new null value
Expand All @@ -36,13 +37,25 @@ func num(n float64) value {
}

// Create a new string value
func str(s string) value {
return value{typ: typeStr, s: s}
func str(s string, chars bool) value {
var runes *[]rune
if chars {
runes = new([]rune)
}
return value{typ: typeStr, s: s, r: runes}
}

func strFromRunes(runes []rune) value {
return value{typ: typeStr, s: string(runes), r: &runes}
}

// Create a new value to represent a "numeric string" from an input field
func numStr(s string) value {
return value{typ: typeNumStr, s: s}
func numStr(s string, chars bool) value {
var runes *[]rune
if chars {
runes = new([]rune)
}
return value{typ: typeNumStr, s: s, r: runes}
}

// Create a numeric value from a Go bool
Expand All @@ -53,6 +66,18 @@ func boolean(b bool) value {
return num(0)
}

func (v value) runes(floatFormat string) []rune {
switch v.typ {
case typeStr, typeNumStr:
if *v.r == nil {
*v.r = []rune(v.s)
}
return *v.r
default: // typeNum, typeNull
return []rune(v.str(floatFormat))
}
}

// String returns a string representation of v for debugging.
func (v value) String() string {
switch v.typ {
Expand Down
Loading