SHS/ast/var_table.go
2020-07-18 14:40:35 -07:00

147 lines
3.9 KiB
Go

/* SHS: Syntactically Homogeneous Shell
* Copyright (C) 2019 Aidan Hahn
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package ast
import (
"os"
"fmt"
"math"
"strconv"
"strings"
"gitlab.com/whom/shs/log"
)
/* defines whether or not to synchronize tokens wiht os environment vars
* will not sync non stringable tokens
*/
var SyncTablesWithOSEnviron = false
/* mapping of key to token.
*/
type VarTable *map[string]*Token
/* retrieve the token cooresponding to a given key
* if SyncTablesWithOSEnviron is true and no token exists for a key
* os Environment variables will be searched for the key
*/
func GetVar(arg string, vt VarTable) *Token {
val, ok := (*vt)[arg]
if !ok {
if !SyncTablesWithOSEnviron {
return nil
}
e := os.Getenv(arg)
if e != "" {
t := &Token{inner: e}
if StrIsNumber(e) {
t.Tag = NUMBER
} else {
t.Tag = STRING
}
SetVar(arg, t, vt)
return t
}
return nil
}
return val
}
/* adds a key->token mapping to the table
* if SyncTablesWithOSEnviron is true, will also add value to os environment
* will not do so for non stringable tokens
*/
func SetVar(variable string, value *Token, vt VarTable) {
(*vt)[variable] = value
if SyncTablesWithOSEnviron &&
(value.Tag == NUMBER || value.Tag == STRING) {
token := value.Value()
if value.Tag == NUMBER {
// make sure its an int
a, err := strconv.ParseFloat(token, 64)
if err == nil && math.Mod(a, 1.0) == 0 {
token = fmt.Sprintf("%d", int(a))
}
}
os.Setenv(variable, token)
}
}
/* lists all vars in tables
*/
func ListVars(vt VarTable) []string {
keys := make([]string, len(*vt))
i := 0
for k := range *vt {
keys[i] = k
}
return keys
}
/* if SyncTablesWithOSEnviron is true
* function will put ever environment variable into VarTable
*/
func InitVarTable(table VarTable) {
if !SyncTablesWithOSEnviron {
return
}
for _, val := range os.Environ() {
variable := strings.Split(val, "=")
t := &Token{inner: variable[1]}
if StrIsNumber(variable[1]) {
t.Tag = NUMBER
} else {
t.Tag = STRING
}
if variable[0] == "HOME" {
SetVar("~", t, table)
}
SetVar(variable[0], t, table)
}
}
// Dont do this on var tables youve already called InitVarTable on.... please....
// This will pull currently contained variables OUT of the operating env
func DeleteVarTable(table VarTable) {
for key, _ := range (*table) {
// from what I can tell, theres not much we can do if this fails
err := os.Unsetenv(key)
if err != nil {
log.Log(log.DEBUG, "Failed to remove " + key + " from env: " + err.Error(), "vartable")
}
}
}
a
/* removes var from vartable
* if SyncTablesWithOSENviron is true, also unsets environment variable
*/
func RemoveVar(arg string, table VarTable) {
if SyncTablesWithOSEnviron {
err := os.Unsetenv(arg)
if err != nil {
log.Log(log.DEBUG,
"Failed to remove "+arg+" from env: "+err.Error(),
"vartable")
}
}
delete(*table, arg)
}