diff options
author | Fumitoshi Ukai <fumitoshi.ukai@gmail.com> | 2015-06-11 17:15:49 +0900 |
---|---|---|
committer | Fumitoshi Ukai <fumitoshi.ukai@gmail.com> | 2015-06-11 17:34:10 +0900 |
commit | 4a708512624fe1bec939fd41661665c27bd0ebcb (patch) | |
tree | bb862740ee8aeeec2a5ecbb7503293effa2585d9 /func.go | |
parent | 72598e7aba34804477c8fd6a32dee0216d32ad98 (diff) | |
download | android_build_kati-4a708512624fe1bec939fd41661665c27bd0ebcb.tar.gz android_build_kati-4a708512624fe1bec939fd41661665c27bd0ebcb.tar.bz2 android_build_kati-4a708512624fe1bec939fd41661665c27bd0ebcb.zip |
refactor sh builtins
add -use_shell_builtins flag to disable the feature
(when some builtin is broken)
Diffstat (limited to 'func.go')
-rw-r--r-- | func.go | 287 |
1 files changed, 8 insertions, 279 deletions
@@ -763,290 +763,19 @@ func (f *funcShell) Compact() Value { if !ok { return f } - // hack for android - if v, ok := matchAndroidRot13(expr); ok { - return &funcShellAndroidRot13{ - funcShell: f, - v: v, - } - } - if dir, ok := matchAndroidFindFileInDir(expr); ok { - androidFindCache.init(nil) - return &funcShellAndroidFindFileInDir{ - funcShell: f, - dir: dir, - } - } - if chdir, roots, ok := matchAndroidFindJavaInDir(expr); ok { - androidFindCache.init(nil) - return &funcShellAndroidFindJavaInDir{ - funcShell: f, - chdir: chdir, - roots: roots, - } - } - if dir, ok := matchAndroidFindJavaResourceFileGroup(expr); ok { - androidFindCache.init(nil) - return &funcShellAndroidFindJavaResourceFileGroup{ - funcShell: f, - dir: dir, - } - } - Logf("shell compact no match: %s", expr) - return f -} - -// pattern in repo/android/build/core/definisions.mk -// rot13 -// echo $(1) | tr 'a-zA-Z' 'n-za-mN-ZA-M' -func matchAndroidRot13(expr Expr) (Value, bool) { - // literal: "echo " - // paramref: 1 - // literal: " | tr 'a-zA-Z' 'n-za-mN-ZA-M'" - if len(expr) != 3 { - return nil, false - } - if expr[0] != literal("echo ") { - return nil, false - } - if expr[1] != paramref(1) { - return nil, false - } - if expr[2] != literal(" | tr 'a-zA-Z' 'n-za-mN-ZA-M'") { - return nil, false - } - return expr[1], true -} - -type funcShellAndroidRot13 struct { - *funcShell - v Value -} - -func rot13(buf []byte) { - for i, b := range buf { - // tr 'a-zA-Z' 'n-za-mN-ZA-M' - if b >= 'a' && b <= 'z' { - b += 'n' - 'a' - if b > 'z' { - b -= 'z' - 'a' + 1 + if useShellBuiltins { + // hack for android + for _, sb := range shBuiltins { + if v, ok := matchExpr(expr, sb.pattern); ok { + Logf("shell compact apply %s for %s", sb.name, expr) + return sb.compact(f, v) } - } else if b >= 'A' && b <= 'Z' { - b += 'N' - 'A' - if b > 'Z' { - b -= 'Z' - 'A' + 1 - } - } - buf[i] = b - } -} - -func (f *funcShellAndroidRot13) Eval(w io.Writer, ev *Evaluator) { - abuf := newBuf() - fargs := ev.args(abuf, f.v) - rot13(fargs[0]) - w.Write(fargs[0]) - freeBuf(abuf) -} - -// pattern in repo/android/build/core/definitions.mk -// find-subdir-assets -// if [ -d $1 ] ; then cd $1 ; find ./ -not -name '.*' -and -type f -and -not -type l ; fi -func matchAndroidFindFileInDir(expr Expr) (Value, bool) { - // literal: "if [ -d " - // paramref: 1 - // literal: " ] ; then cd " - // paramref: 1 - // literal: " ; find ./ -not -name '.*' -and -type f -and -not -type l ; fi" - if len(expr) != 5 { - return nil, false - } - if expr[0] != literal("if [ -d ") { - return nil, false - } - if expr[1] != paramref(1) { - return nil, false - } - if expr[2] != literal(" ] ; then cd ") { - return nil, false - } - if expr[3] != paramref(1) { - return nil, false - } - if expr[4] != literal(" ; find ./ -not -name '.*' -and -type f -and -not -type l ; fi") { - return nil, false - } - return paramref(1), true -} - -type funcShellAndroidFindFileInDir struct { - *funcShell - dir Value -} - -func (f *funcShellAndroidFindFileInDir) Eval(w io.Writer, ev *Evaluator) { - abuf := newBuf() - fargs := ev.args(abuf, f.dir) - dir := string(trimSpaceBytes(fargs[0])) - freeBuf(abuf) - Logf("shellAndroidFindFileInDir %s => %s", f.dir.String(), dir) - if strings.Contains(dir, "..") { - Logf("shellAndroidFindFileInDir contains ..: call original shell") - f.funcShell.Eval(w, ev) - return - } - if !androidFindCache.ready() { - Logf("shellAndroidFindFileInDir androidFindCache is not ready: call original shell") - f.funcShell.Eval(w, ev) - return - } - sw := ssvWriter{w: w} - androidFindCache.findInDir(&sw, dir) -} - -// pattern in repo/android/build/core/definitions.mk -// all-java-files-under -// cd ${LOCAL_PATH} ; find -L $1 -name "*.java" -and -not -name ".*" -func matchAndroidFindJavaInDir(expr Expr) (Value, Value, bool) { - // literal: "cd " - // varref: xxx - // literal: " ; find -L " - // paramref: 1 - // literal: " -name "*.java" -and -not -name ".*" - if len(expr) != 5 { - return nil, nil, false - } - if expr[0] != literal("cd ") { - return nil, nil, false - } - if _, ok := expr[1].(varref); !ok { - return nil, nil, false - } - if expr[2] != literal(" ; find -L ") { - return nil, nil, false - } - if expr[3] != paramref(1) { - return nil, nil, false - } - if expr[4] != literal(` -name "*.java" -and -not -name ".*"`) { - return nil, nil, false - } - return expr[1], paramref(1), true -} - -type funcShellAndroidFindJavaInDir struct { - *funcShell - chdir Value - roots Value -} - -func (f *funcShellAndroidFindJavaInDir) Eval(w io.Writer, ev *Evaluator) { - abuf := newBuf() - fargs := ev.args(abuf, f.chdir, f.roots) - chdir := string(trimSpaceBytes(fargs[0])) - var roots []string - hasDotDot := false - ws := newWordScanner(fargs[1]) - for ws.Scan() { - root := string(ws.Bytes()) - if strings.Contains(root, "..") { - hasDotDot = true - } - roots = append(roots, string(ws.Bytes())) - } - freeBuf(abuf) - Logf("shellAndroidFindJavaInDir %s,%s => %s,%s", f.chdir.String(), f.roots.String(), chdir, roots) - if strings.Contains(chdir, "..") || hasDotDot { - Logf("shellAndroidFindJavaInDir contains ..: call original shell") - f.funcShell.Eval(w, ev) - return - } - if !androidFindCache.ready() { - Logf("shellAndroidFindJavaInDir androidFindCache is not ready: call original shell") - f.funcShell.Eval(w, ev) - return - } - buf := newBuf() - sw := ssvWriter{w: buf} - for _, root := range roots { - if !androidFindCache.findJavaInDir(&sw, chdir, root) { - freeBuf(buf) - Logf("shellAndroidFindJavaInDir androidFindCache couldn't handle: call original shell") - f.funcShell.Eval(w, ev) - return } + Logf("shell compact no match: %s", expr) } - w.Write(buf.Bytes()) - freeBuf(buf) -} - -// pattern: in repo/android/build/core/base_rules.mk -// java_resource_file_groups+= ... -// cd ${TOP_DIR}${LOCAL_PATH}/${dir} && find . -type d -a -name ".svn" -prune \ -// -o -type f -a \! -name "*.java" -a \! -name "package.html" -a \! \ -// -name "overview.html" -a \! -name ".*.swp" -a \! -name ".DS_Store" \ -// -a \! -name "*~" -print ) -func matchAndroidFindJavaResourceFileGroup(expr Expr) (Value, bool) { - // literal: "cd " - // varref: TOP_DIR - // varref: LOCAL_PATH - // literal: "/" - // varref: dir - // literal: " && find . -type d -a name ".svn" -prune -o .." - if len(expr) != 6 { - return nil, false - } - if expr[0] != literal("cd ") { - return nil, false - } - if _, ok := expr[1].(varref); !ok { - return nil, false - } - if _, ok := expr[2].(varref); !ok { - return nil, false - } - if expr[3] != literal("/") { - return nil, false - } - if _, ok := expr[4].(varref); !ok { - return nil, false - } - if expr[5] != literal(` && find . -type d -a -name ".svn" -prune -o -type f -a \! -name "*.java" -a \! -name "package.html" -a \! -name "overview.html" -a \! -name ".*.swp" -a \! -name ".DS_Store" -a \! -name "*~" -print `) { - Logf("shell compact mismatch: expr[5]=%q", expr[5]) - return nil, false - } - return expr[1:5], true -} - -type funcShellAndroidFindJavaResourceFileGroup struct { - *funcShell - dir Value -} - -func (f *funcShellAndroidFindJavaResourceFileGroup) Eval(w io.Writer, ev *Evaluator) { - abuf := newBuf() - fargs := ev.args(abuf, f.dir) - dir := string(trimSpaceBytes(fargs[0])) - freeBuf(abuf) - Logf("shellAndroidFindJavaResourceFileGroup %s => %s", f.dir.String(), dir) - if strings.Contains(dir, "..") { - Logf("shellAndroidFindJavaResourceFileGroup contains ..: call original shell") - f.funcShell.Eval(w, ev) - return - } - if !androidFindCache.ready() { - Logf("shellAndroidFindJavaResourceFileGroup androidFindCache is not ready: call original shell") - f.funcShell.Eval(w, ev) - return - } - sw := ssvWriter{w: w} - androidFindCache.findJavaResourceFileGroup(&sw, dir) + return f } -// TODO(ukai): pattern: -// -// echo $1 | tr 'a-zA-Z' 'n-za-mN-ZA-M' - // https://www.gnu.org/software/make/manual/html_node/Call-Function.html#Call-Function type funcCall struct{ fclosure } |