2702b745d5
Added the EditUser, EditUserEmail, EditUserPassword, EditUserGroup, EditUserGroupSuperMod and EditUserGroupAdmin permissions. Allocations are now tracked in the benchmarks. The topics template is now tracked in the benchmarks. The entire topic, topics, forum and forums routes are now benchmarked. Initial attempts to benchmark the router have begun, I'll probably have a benchmark in a later commit without the fluff so that it's easier to see it's performance impact. Improved the security on some of the moderation routes. SettingLabel is now OptionLabel for easier reuse. Moved one of the inline queries into a prepared statement. Added the initial draft for the new router. Fixed a bug where you lose all of your guest permissions when your session is invalidated.
657 lines
17 KiB
Go
657 lines
17 KiB
Go
package main
|
|
import "log"
|
|
import "fmt"
|
|
import "strings"
|
|
import "reflect"
|
|
import "path/filepath"
|
|
import "io/ioutil"
|
|
import "text/template/parse"
|
|
|
|
/* Keeping this so I can benchmark against it */
|
|
|
|
type CTemplateSet2 struct
|
|
{
|
|
tlist map[string]*parse.Tree
|
|
dir string
|
|
funcMap map[string]interface{}
|
|
importMap map[string]string
|
|
varList map[string]VarItem
|
|
localVars map[string]map[string]VarItemReflect
|
|
//tempVars map[string]string
|
|
doImports bool
|
|
expectsInt interface{}
|
|
}
|
|
|
|
func (c *CTemplateSet2) compile_template_2(name string, dir string, expects string, expectsInt interface{}, varList map[string]VarItem) (out string) {
|
|
c.dir = dir
|
|
c.doImports = true
|
|
c.funcMap = make(map[string]interface{})
|
|
c.funcMap["and"] = "&&"
|
|
c.funcMap["not"] = "!"
|
|
c.funcMap["or"] = "||"
|
|
c.funcMap["eq"] = true
|
|
c.funcMap["ge"] = true
|
|
c.funcMap["gt"] = true
|
|
c.funcMap["le"] = true
|
|
c.funcMap["lt"] = true
|
|
c.funcMap["ne"] = true
|
|
c.importMap = make(map[string]string)
|
|
c.importMap["strconv"] = "strconv"
|
|
c.varList = varList
|
|
c.expectsInt = expectsInt
|
|
holdreflect := reflect.ValueOf(expectsInt)
|
|
|
|
res, err := ioutil.ReadFile(dir + name)
|
|
if err != nil {
|
|
log.Fatal(err)
|
|
}
|
|
content := string(res)
|
|
|
|
tree := parse.New(name, c.funcMap)
|
|
var treeSet map[string]*parse.Tree = make(map[string]*parse.Tree)
|
|
tree, err = tree.Parse(content,"{{","}}", treeSet, c.funcMap)
|
|
if err != nil {
|
|
log.Fatal(err)
|
|
}
|
|
|
|
if debug {
|
|
fmt.Println(name)
|
|
}
|
|
|
|
out = ""
|
|
fname := strings.TrimSuffix(name, filepath.Ext(name))
|
|
c.tlist = make(map[string]*parse.Tree)
|
|
c.tlist[fname] = tree
|
|
varholder := "tmpl_" + fname + "_vars"
|
|
|
|
if debug {
|
|
fmt.Println(c.tlist)
|
|
}
|
|
|
|
c.localVars = make(map[string]map[string]VarItemReflect)
|
|
c.localVars[fname] = make(map[string]VarItemReflect)
|
|
c.localVars[fname]["."] = VarItemReflect{".",varholder,holdreflect}
|
|
|
|
subtree := c.tlist[fname]
|
|
if debug {
|
|
fmt.Println(subtree.Root)
|
|
}
|
|
|
|
for _, node := range subtree.Root.Nodes {
|
|
if debug {
|
|
fmt.Println("Node: " + node.String())
|
|
}
|
|
out += c.compile_switch(varholder, holdreflect, fname, node)
|
|
}
|
|
|
|
var importList string
|
|
if c.doImports {
|
|
for _, item := range c.importMap {
|
|
importList += "import \"" + item + "\"\n"
|
|
}
|
|
}
|
|
|
|
var varString string
|
|
for _, varItem := range c.varList {
|
|
varString += "var " + varItem.Name + " " + varItem.Type + " = " + varItem.Destination + "\n"
|
|
}
|
|
|
|
out = "package main\n" + importList + "\nfunc init() {\nctemplates[\"" + fname + "\"] = template_" + fname + "\n}\n\nfunc template_" + fname + "(tmpl_" + fname + "_vars " + expects + ") (tmpl string) {\n" + varString + out + "return tmpl\n}\n"
|
|
if debug {
|
|
fmt.Println("Output!")
|
|
fmt.Println(out)
|
|
}
|
|
return out
|
|
}
|
|
|
|
func (c *CTemplateSet2) compile_switch(varholder string, holdreflect reflect.Value, template_name string, node interface{}) (out string) {
|
|
switch node := node.(type) {
|
|
case *parse.ActionNode:
|
|
if debug {
|
|
fmt.Println("Action Node")
|
|
}
|
|
|
|
if node.Pipe == nil {
|
|
break
|
|
}
|
|
for _, cmd := range node.Pipe.Cmds {
|
|
out += c.compile_subswitch(varholder, holdreflect, template_name, cmd)
|
|
}
|
|
return out
|
|
case *parse.IfNode:
|
|
if debug {
|
|
fmt.Println("If Node: ")
|
|
fmt.Println(node.Pipe)
|
|
}
|
|
|
|
var expr string
|
|
for _, cmd := range node.Pipe.Cmds {
|
|
if debug {
|
|
fmt.Println("If Node Bit: ")
|
|
fmt.Println(cmd)
|
|
fmt.Println(reflect.ValueOf(cmd).Type().Name())
|
|
}
|
|
expr += c.compile_varswitch(varholder, holdreflect, template_name, cmd)
|
|
}
|
|
|
|
if node.ElseList == nil {
|
|
if debug {
|
|
fmt.Println("Branch 1")
|
|
}
|
|
return "if " + expr + " {\n" + c.compile_switch(varholder, holdreflect, template_name, node.List) + "}\n"
|
|
} else {
|
|
if debug {
|
|
fmt.Println("Branch 2")
|
|
}
|
|
return "if " + expr + " {\n" + c.compile_switch(varholder, holdreflect, template_name, node.List) + "} else {\n" + c.compile_switch(varholder, holdreflect, template_name, node.ElseList) + "}\n"
|
|
}
|
|
case *parse.ListNode:
|
|
if debug {
|
|
fmt.Println("List Node")
|
|
}
|
|
for _, subnode := range node.Nodes {
|
|
out += c.compile_switch(varholder, holdreflect, template_name, subnode)
|
|
}
|
|
return out
|
|
case *parse.RangeNode:
|
|
if debug {
|
|
fmt.Println("Range Node!")
|
|
fmt.Println(node.Pipe)
|
|
}
|
|
|
|
var outVal reflect.Value
|
|
for _, cmd := range node.Pipe.Cmds {
|
|
if debug {
|
|
fmt.Println("Range Bit: ")
|
|
fmt.Println(cmd)
|
|
}
|
|
out, outVal = c.compile_reflectswitch(varholder, holdreflect, template_name, cmd)
|
|
}
|
|
|
|
if debug {
|
|
fmt.Println("Returned: ")
|
|
fmt.Println(out)
|
|
fmt.Println("Range Kind Switch!")
|
|
}
|
|
|
|
switch outVal.Kind() {
|
|
case reflect.Map:
|
|
var item reflect.Value
|
|
for _, key := range outVal.MapKeys() {
|
|
item = outVal.MapIndex(key)
|
|
}
|
|
|
|
out = "if len(" + out + ") != 0 {\nfor _, item := range " + out + " {\n" + c.compile_switch("item", item, template_name, node.List) + "}\n}"
|
|
case reflect.Invalid:
|
|
return ""
|
|
}
|
|
|
|
if node.ElseList != nil {
|
|
out += " else {\n" + c.compile_switch(varholder, holdreflect, template_name, node.ElseList) + "}\n"
|
|
} else {
|
|
out += "\n"
|
|
}
|
|
return out
|
|
case *parse.TemplateNode:
|
|
if debug {
|
|
fmt.Println("Template Node")
|
|
}
|
|
return c.compile_subtemplate(varholder, holdreflect, node)
|
|
case *parse.TextNode:
|
|
return "tmpl += `" + string(node.Text) + "`\n"
|
|
default:
|
|
panic("Unknown Node in main switch")
|
|
}
|
|
return ""
|
|
}
|
|
|
|
func (c *CTemplateSet2) compile_subswitch(varholder string, holdreflect reflect.Value, template_name string, node *parse.CommandNode) (out string) {
|
|
firstWord := node.Args[0]
|
|
switch n := firstWord.(type) {
|
|
case *parse.FieldNode:
|
|
if debug {
|
|
fmt.Println("Field Node: ")
|
|
fmt.Println(n.Ident)
|
|
}
|
|
|
|
/* Use reflect to determine if the field is for a method, otherwise assume it's a variable. Coming Soon. */
|
|
cur := holdreflect
|
|
|
|
var varbit string
|
|
if cur.Kind() == reflect.Interface {
|
|
cur = cur.Elem()
|
|
varbit += ".(" + cur.Type().Name() + ")"
|
|
}
|
|
|
|
for _, id := range n.Ident {
|
|
if debug {
|
|
fmt.Println("Data Kind: ")
|
|
fmt.Println(cur.Kind().String())
|
|
fmt.Println("Field Bit: ")
|
|
fmt.Println(id)
|
|
}
|
|
|
|
cur = cur.FieldByName(id)
|
|
if cur.Kind() == reflect.Interface {
|
|
cur = cur.Elem()
|
|
/*if cur.Kind() == reflect.String && cur.Type().Name() != "string" {
|
|
varbit = "string(" + varbit + "." + id + ")"*/
|
|
//if cur.Kind() == reflect.String && cur.Type().Name() != "string" {
|
|
if cur.Type().PkgPath() != "main" {
|
|
c.importMap["html/template"] = "html/template"
|
|
varbit += "." + id + ".(" + strings.TrimPrefix(cur.Type().PkgPath(),"html/") + "." + cur.Type().Name() + ")"
|
|
} else {
|
|
varbit += "." + id + ".(" + cur.Type().Name() + ")"
|
|
}
|
|
} else {
|
|
varbit += "." + id
|
|
}
|
|
|
|
if debug {
|
|
fmt.Println("End Cycle")
|
|
}
|
|
}
|
|
out = c.compile_varsub(varholder + varbit, cur)
|
|
|
|
for _, varItem := range c.varList {
|
|
if strings.HasPrefix(out, varItem.Destination) {
|
|
out = strings.Replace(out, varItem.Destination, varItem.Name, 1)
|
|
}
|
|
}
|
|
return out
|
|
case *parse.DotNode:
|
|
if debug {
|
|
fmt.Println("Dot Node")
|
|
fmt.Println(node.String())
|
|
}
|
|
return c.compile_varsub(varholder, holdreflect)
|
|
case *parse.NilNode:
|
|
panic("Nil is not a command x.x")
|
|
case *parse.VariableNode:
|
|
if debug {
|
|
fmt.Println("Variable Node")
|
|
fmt.Println(n.String())
|
|
fmt.Println(n.Ident)
|
|
}
|
|
|
|
out, _ = c.compile_if_varsub(n.String(), varholder, template_name, holdreflect)
|
|
return "tmpl += " + out + "\n"
|
|
case *parse.StringNode:
|
|
return n.Quoted
|
|
default:
|
|
fmt.Println("Unknown Kind: ")
|
|
fmt.Println(reflect.ValueOf(firstWord).Elem().Kind())
|
|
fmt.Println("Unknown Type: ")
|
|
fmt.Println(reflect.ValueOf(firstWord).Elem().Type().Name())
|
|
panic("I don't know what node this is")
|
|
}
|
|
return ""
|
|
}
|
|
|
|
func (c *CTemplateSet2) compile_varswitch(varholder string, holdreflect reflect.Value, template_name string, node *parse.CommandNode) (out string) {
|
|
firstWord := node.Args[0]
|
|
switch n := firstWord.(type) {
|
|
case *parse.FieldNode:
|
|
if debug {
|
|
fmt.Println("Field Node: ")
|
|
fmt.Println(n.Ident)
|
|
|
|
for _, id := range n.Ident {
|
|
fmt.Println("Field Bit: ")
|
|
fmt.Println(id)
|
|
}
|
|
}
|
|
|
|
/* Use reflect to determine if the field is for a method, otherwise assume it's a variable. Coming Soon. */
|
|
return c.compile_boolsub(n.String(), varholder, template_name, holdreflect)
|
|
case *parse.ChainNode:
|
|
if debug {
|
|
fmt.Println("Chain Node: ")
|
|
fmt.Println(n.Node)
|
|
fmt.Println(node.Args)
|
|
}
|
|
break
|
|
case *parse.IdentifierNode:
|
|
if debug {
|
|
fmt.Println("Identifier Node: ")
|
|
fmt.Println(node)
|
|
fmt.Println(node.Args)
|
|
}
|
|
return c.compile_identswitch(varholder, holdreflect, template_name, node)
|
|
case *parse.DotNode:
|
|
return varholder
|
|
case *parse.VariableNode:
|
|
if debug {
|
|
fmt.Println("Variable Node")
|
|
fmt.Println(n.String())
|
|
fmt.Println(n.Ident)
|
|
}
|
|
|
|
out, _ = c.compile_if_varsub(n.String(), varholder, template_name, holdreflect)
|
|
return out
|
|
case *parse.NilNode:
|
|
panic("Nil is not a command x.x")
|
|
case *parse.PipeNode:
|
|
if debug {
|
|
fmt.Println("Pipe Node!")
|
|
fmt.Println(n)
|
|
}
|
|
|
|
/*for _, cmd := range n.Cmds {
|
|
if debug {
|
|
fmt.Println("Pipe Bit: ")
|
|
fmt.Println(cmd)
|
|
}
|
|
out += c.compile_if_varsub_n(n.String(), varholder, template_name, holdreflect)
|
|
}*/
|
|
|
|
if debug {
|
|
fmt.Println("Args: ")
|
|
fmt.Println(node.Args)
|
|
}
|
|
|
|
/*argcopy := node.Args[1:]
|
|
for _, arg := range argcopy {
|
|
if debug {
|
|
fmt.Println("Pipe Arg: ")
|
|
fmt.Println(arg)
|
|
fmt.Println(reflect.ValueOf(arg).Elem().Type().Name())
|
|
fmt.Println(reflect.ValueOf(arg).Kind())
|
|
}
|
|
|
|
switch arg.(type) {
|
|
case *parse.IdentifierNode:
|
|
out += c.compile_identswitch(varholder, holdreflect, template_name, node)
|
|
break
|
|
case *parse.PipeNode:
|
|
break
|
|
//out += c.compile_if_varsub_n(a.String(), varholder, template_name, holdreflect)
|
|
default:
|
|
panic("Unknown Pipe Arg type! Did Mario get stuck in the pipes again?")
|
|
}
|
|
//out += c.compile_varswitch(arg.String(), holdreflect, template_name, arg)
|
|
}*/
|
|
out += c.compile_identswitch(varholder, holdreflect, template_name, node)
|
|
|
|
if debug {
|
|
fmt.Println("Out: ")
|
|
fmt.Println(out)
|
|
}
|
|
return out
|
|
default:
|
|
fmt.Println("Unknown Kind: ")
|
|
fmt.Println(reflect.ValueOf(firstWord).Elem().Kind())
|
|
fmt.Println("Unknown Type: ")
|
|
fmt.Println(reflect.ValueOf(firstWord).Elem().Type().Name())
|
|
panic("I don't know what node this is! Grr...")
|
|
}
|
|
return ""
|
|
}
|
|
|
|
func (c *CTemplateSet2) compile_identswitch(varholder string, holdreflect reflect.Value, template_name string, node *parse.CommandNode) (out string) {
|
|
ArgLoop:
|
|
for pos, id := range node.Args {
|
|
if debug {
|
|
fmt.Println(id)
|
|
}
|
|
|
|
switch id.String() {
|
|
case "not":
|
|
out += "!"
|
|
case "or":
|
|
out += " || "
|
|
case "and":
|
|
out += " && "
|
|
case "le":
|
|
out += c.compile_if_varsub_n(node.Args[pos + 1].String(), varholder, template_name, holdreflect) + " <= " + c.compile_if_varsub_n(node.Args[pos + 2].String(), varholder, template_name, holdreflect)
|
|
break ArgLoop
|
|
default:
|
|
if debug {
|
|
fmt.Println("Variable!")
|
|
}
|
|
out += c.compile_if_varsub_n(id.String(), varholder, template_name, holdreflect)
|
|
}
|
|
}
|
|
return out
|
|
}
|
|
|
|
func (c *CTemplateSet2) compile_reflectswitch(varholder string, holdreflect reflect.Value, template_name string, node *parse.CommandNode) (out string, outVal reflect.Value) {
|
|
firstWord := node.Args[0]
|
|
switch n := firstWord.(type) {
|
|
case *parse.FieldNode:
|
|
if debug {
|
|
fmt.Println("Field Node: ")
|
|
fmt.Println(n.Ident)
|
|
|
|
for _, id := range n.Ident {
|
|
fmt.Println("Field Bit: ")
|
|
fmt.Println(id)
|
|
}
|
|
}
|
|
/* Use reflect to determine if the field is for a method, otherwise assume it's a variable. Coming Soon. */
|
|
return c.compile_if_varsub(n.String(), varholder, template_name, holdreflect)
|
|
case *parse.ChainNode:
|
|
if debug {
|
|
fmt.Println("Chain Node: ")
|
|
fmt.Println(n.Node)
|
|
fmt.Println(node.Args)
|
|
}
|
|
return "", outVal
|
|
/*case *parse.IdentifierNode:
|
|
fmt.Println("Identifier Node: ")
|
|
fmt.Println(node)
|
|
fmt.Println(node.Args)
|
|
|
|
ArgLoop:
|
|
for pos, id := range node.Args {
|
|
fmt.Println(id)
|
|
switch id.String() {
|
|
case "not":
|
|
out += "!"
|
|
case "or":
|
|
out += " || "
|
|
case "and":
|
|
out += " && "
|
|
case "le":
|
|
out += c.compile_if_varsub_n(node.Args[pos + 1].String(), varholder, holdreflect) + " <= " + c.compile_if_varsub_n(node.Args[pos + 2].String(), varholder, holdreflect)
|
|
break ArgLoop
|
|
default:
|
|
fmt.Println("Variable!")
|
|
out += c.compile_if_varsub_n(id.String(), varholder, holdreflect)
|
|
}
|
|
}
|
|
return out*/
|
|
case *parse.DotNode:
|
|
return varholder, holdreflect
|
|
case *parse.NilNode:
|
|
panic("Nil is not a command x.x")
|
|
default:
|
|
//panic("I don't know what node this is")
|
|
}
|
|
return "", outVal
|
|
}
|
|
|
|
func (c *CTemplateSet2) compile_if_varsub_n(varname string, varholder string, template_name string, cur reflect.Value) (out string) {
|
|
out, _ = c.compile_if_varsub(varname, varholder, template_name, cur)
|
|
return out
|
|
}
|
|
|
|
func (c *CTemplateSet2) compile_if_varsub(varname string, varholder string, template_name string, cur reflect.Value) (out string, val reflect.Value) {
|
|
if varname[0] != '.' && varname[0] != '$' {
|
|
return varname, cur
|
|
}
|
|
|
|
bits := strings.Split(varname,".")
|
|
if varname[0] == '$' {
|
|
var res VarItemReflect
|
|
if varname[1] == '.' {
|
|
res = c.localVars[template_name]["."]
|
|
} else {
|
|
res = c.localVars[template_name][strings.TrimPrefix(bits[0],"$")]
|
|
}
|
|
out += res.Destination
|
|
cur = res.Value
|
|
|
|
if cur.Kind() == reflect.Interface {
|
|
cur = cur.Elem()
|
|
}
|
|
} else {
|
|
if cur.Kind() == reflect.Interface {
|
|
cur = cur.Elem()
|
|
out += varholder + ".(" + cur.Type().Name() + ")"
|
|
} else {
|
|
out += varholder
|
|
}
|
|
}
|
|
bits[0] = strings.TrimPrefix(bits[0],"$")
|
|
|
|
if debug {
|
|
fmt.Println("Cur Kind: ")
|
|
fmt.Println(cur.Kind())
|
|
fmt.Println("Cur Type: ")
|
|
fmt.Println(cur.Type().Name())
|
|
}
|
|
|
|
for _, bit := range bits {
|
|
if debug {
|
|
fmt.Println("Variable Field!")
|
|
fmt.Println(bit)
|
|
}
|
|
|
|
if bit == "" {
|
|
continue
|
|
}
|
|
|
|
cur = cur.FieldByName(bit)
|
|
if cur.Kind() == reflect.Interface {
|
|
cur = cur.Elem()
|
|
out += "." + bit + ".(" + cur.Type().Name() + ")"
|
|
} else {
|
|
out += "." + bit
|
|
}
|
|
|
|
if debug {
|
|
fmt.Println("Data Kind: ")
|
|
fmt.Println(cur.Kind())
|
|
fmt.Println("Data Type: ")
|
|
fmt.Println(cur.Type().Name())
|
|
}
|
|
}
|
|
|
|
for _, varItem := range c.varList {
|
|
if strings.HasPrefix(out, varItem.Destination) {
|
|
out = strings.Replace(out, varItem.Destination, varItem.Name, 1)
|
|
}
|
|
}
|
|
return out, cur
|
|
}
|
|
|
|
func (c *CTemplateSet2) compile_boolsub(varname string, varholder string, template_name string, val reflect.Value) string {
|
|
out, val := c.compile_if_varsub(varname, varholder, template_name, val)
|
|
switch val.Kind() {
|
|
case reflect.Int:
|
|
out += " > 0"
|
|
case reflect.Bool:
|
|
// Do nothing
|
|
case reflect.String:
|
|
out += " != \"\""
|
|
case reflect.Int64:
|
|
out += " > 0"
|
|
default:
|
|
panic("I don't know what this variable's type is o.o\n")
|
|
}
|
|
return out
|
|
}
|
|
|
|
func (c *CTemplateSet2) compile_varsub(varname string, val reflect.Value) string {
|
|
for _, varItem := range c.varList {
|
|
if strings.HasPrefix(varname, varItem.Destination) {
|
|
varname = strings.Replace(varname, varItem.Destination, varItem.Name, 1)
|
|
}
|
|
}
|
|
|
|
if val.Kind() == reflect.Interface {
|
|
val = val.Elem()
|
|
}
|
|
|
|
switch val.Kind() {
|
|
case reflect.Int:
|
|
return "tmpl += strconv.Itoa(" + varname + ")\n"
|
|
case reflect.Bool:
|
|
return "if " + varname + " {\ntmpl += \"true\"} else {\ntmpl += \"false\"\n}\n"
|
|
case reflect.String:
|
|
if val.Type().Name() != "string" && !strings.HasPrefix(varname,"string(") {
|
|
return "tmpl += string(" + varname + ")\n"
|
|
} else {
|
|
return "tmpl += " + varname + "\n"
|
|
}
|
|
case reflect.Int64:
|
|
return "tmpl += strconv.FormatInt(" + varname + ", 10)"
|
|
default:
|
|
fmt.Println("Unknown Kind: ")
|
|
fmt.Println(val.Kind())
|
|
fmt.Println("Unknown Type: ")
|
|
fmt.Println(val.Type().Name())
|
|
panic("// I don't know what this variable's type is o.o\n")
|
|
}
|
|
}
|
|
|
|
func (c *CTemplateSet2) compile_subtemplate(pvarholder string, pholdreflect reflect.Value, node *parse.TemplateNode) (out string) {
|
|
if debug {
|
|
fmt.Println("Template Node: " + node.Name)
|
|
}
|
|
|
|
fname := strings.TrimSuffix(node.Name, filepath.Ext(node.Name))
|
|
varholder := "tmpl_" + fname + "_vars"
|
|
var holdreflect reflect.Value
|
|
if node.Pipe != nil {
|
|
for _, cmd := range node.Pipe.Cmds {
|
|
firstWord := cmd.Args[0]
|
|
switch firstWord.(type) {
|
|
case *parse.DotNode:
|
|
varholder = pvarholder
|
|
holdreflect = pholdreflect
|
|
break
|
|
case *parse.NilNode:
|
|
panic("Nil is not a command x.x")
|
|
default:
|
|
out = "var " + varholder + " := false\n"
|
|
out += c.compile_command(cmd)
|
|
}
|
|
}
|
|
}
|
|
|
|
res, err := ioutil.ReadFile(c.dir + node.Name)
|
|
if err != nil {
|
|
log.Fatal(err)
|
|
}
|
|
content := string(res)
|
|
|
|
tree := parse.New(node.Name, c.funcMap)
|
|
var treeSet map[string]*parse.Tree = make(map[string]*parse.Tree)
|
|
tree, err = tree.Parse(content,"{{","}}", treeSet, c.funcMap)
|
|
if err != nil {
|
|
log.Fatal(err)
|
|
}
|
|
|
|
c.tlist[fname] = tree
|
|
subtree := c.tlist[fname]
|
|
if debug {
|
|
fmt.Println(subtree.Root)
|
|
}
|
|
|
|
c.localVars[fname] = make(map[string]VarItemReflect)
|
|
c.localVars[fname]["."] = VarItemReflect{".",varholder,holdreflect}
|
|
|
|
for _, node := range subtree.Root.Nodes {
|
|
if debug {
|
|
fmt.Println("Node: " + node.String())
|
|
}
|
|
out += c.compile_switch(varholder, holdreflect, fname, node)
|
|
}
|
|
return out
|
|
}
|
|
|
|
func (c *CTemplateSet2) compile_command(*parse.CommandNode) (out string) {
|
|
return ""
|
|
} |