| // Copyright 2012 The Go Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style |
| // license that can be found in the LICENSE file. |
| |
| package main |
| |
| import ( |
| "bytes" |
| "fmt" |
| "strconv" |
| "strings" |
| ) |
| |
| /* |
| * Helpers for building cmd/gc. |
| */ |
| |
| // gcopnames creates opnames.h from go.h. |
| // It finds the OXXX enum, pulls out all the constants |
| // from OXXX to OEND, and writes a table mapping |
| // op to string. |
| func gcopnames(dir, file string) { |
| var out bytes.Buffer |
| fmt.Fprintf(&out, "// auto generated by go tool dist\n") |
| fmt.Fprintf(&out, "static char *opnames[] = {\n") |
| |
| in := readfile(pathf("%s/go.h", dir)) |
| lines := splitlines(in) |
| i := 0 |
| for i < len(lines) && !strings.Contains(lines[i], "OXXX") { |
| i++ |
| } |
| for _, line := range lines[i:] { |
| if i := strings.Index(line, "//"); i >= 0 { |
| line = line[:i] |
| } |
| for _, field := range splitfields(line) { |
| field = strings.TrimPrefix(field, "O") |
| field = strings.TrimSuffix(field, ",") |
| fmt.Fprintf(&out, "\t[O%s] = \"%s\",\n", field, field) |
| } |
| if strings.Contains(line, "OEND") { |
| break |
| } |
| } |
| fmt.Fprintf(&out, "};\n") |
| |
| writefile(out.String(), file, 0) |
| } |
| |
| // mkanames reads [5689].out.h and writes anames[5689].c |
| // The format is much the same as the Go opcodes above. |
| // It also writes out cnames array for C_* constants and the dnames |
| // array for D_* constants. |
| func mkanames(dir, file string) { |
| ch := file[len(file)-3] |
| targ := pathf("%s/../cmd/%cl/%c.out.h", dir, ch, ch) |
| in := readfile(targ) |
| lines := splitlines(in) |
| |
| // Include link.h so that the extern declaration there is |
| // checked against the non-extern declaration we are generating. |
| var out bytes.Buffer |
| fmt.Fprintf(&out, "// auto generated by go tool dist\n") |
| fmt.Fprintf(&out, "#include <u.h>\n") |
| fmt.Fprintf(&out, "#include <libc.h>\n") |
| fmt.Fprintf(&out, "#include <bio.h>\n") |
| fmt.Fprintf(&out, "#include <link.h>\n") |
| fmt.Fprintf(&out, "#include \"../cmd/%cl/%c.out.h\"\n", ch, ch) |
| fmt.Fprintf(&out, "\n") |
| |
| fmt.Fprintf(&out, "char* anames%c[] = {\n", ch) |
| for _, line := range lines { |
| if strings.HasPrefix(line, "\tA") { |
| if i := strings.Index(line, ","); i >= 0 { |
| line = line[:i] |
| } |
| if i := strings.Index(line, "\n"); i >= 0 { |
| line = line[:i] |
| } |
| line = line[2:] |
| fmt.Fprintf(&out, "\t\"%s\",\n", line) |
| } |
| } |
| fmt.Fprintf(&out, "};\n") |
| |
| j := 0 |
| var out2 bytes.Buffer |
| fmt.Fprintf(&out2, "char* cnames%c[] = {\n", ch) |
| for _, line := range lines { |
| if strings.HasPrefix(line, "\tC_") { |
| if i := strings.Index(line, ","); i >= 0 { |
| line = line[:i] |
| } |
| if i := strings.Index(line, "\n"); i >= 0 { |
| line = line[:i] |
| } |
| line = line[3:] |
| fmt.Fprintf(&out2, "\t\"%s\",\n", line) |
| j++ |
| } |
| } |
| fmt.Fprintf(&out2, "};\n") |
| if j > 0 { |
| out.Write(out2.Bytes()) |
| } |
| |
| var dnames [128][]string |
| j = 0 |
| unknown := false |
| n := -1 |
| for _, line := range lines { |
| if strings.HasPrefix(line, "\tD_") { |
| if i := strings.Index(line, ","); i >= 0 { |
| line = line[:i] |
| } |
| |
| // Parse explicit value, if any |
| if i := strings.Index(line, "="); i >= 0 { |
| value := strings.TrimSpace(line[i+1:]) |
| line = strings.TrimSpace(line[:i]) |
| var err error |
| n, err = strconv.Atoi(value) |
| if err != nil { |
| // We can't do anything about |
| // non-numeric values or anything that |
| // follows. |
| unknown = true |
| continue |
| } |
| unknown = false |
| } else { |
| n++ |
| } |
| |
| if unknown || n < 0 || n >= len(dnames) { |
| continue |
| } |
| |
| line = strings.TrimSpace(line) |
| line = line[len("D_"):] |
| |
| if strings.Contains(line, "LAST") { |
| continue |
| } |
| dnames[n] = append(dnames[n], line) |
| j++ |
| } |
| } |
| |
| if j > 0 { |
| fmt.Fprintf(&out, "char* dnames%c[D_LAST] = {\n", ch) |
| for _, d := range dnames { |
| if len(d) == 0 { |
| continue |
| } |
| fmt.Fprintf(&out, "\t[D_%s] = \"", d[0]) |
| for k, name := range d { |
| if k > 0 { |
| fmt.Fprintf(&out, "/") |
| } |
| fmt.Fprintf(&out, "%s", name) |
| } |
| fmt.Fprintf(&out, "\",\n") |
| } |
| fmt.Fprintf(&out, "};\n") |
| } |
| |
| writefile(out.String(), file, 0) |
| } |