| 1 | #!/usr/bin/env python2
|
| 2 | # Copyright 2019 Wilke Schwiedop. All rights reserved.
|
| 3 | # Licensed under the Apache License, Version 2.0 (the "License");
|
| 4 | # you may not use this file except in compliance with the License.
|
| 5 | # You may obtain a copy of the License at
|
| 6 | #
|
| 7 | # http://www.apache.org/licenses/LICENSE-2.0
|
| 8 | """
|
| 9 | find.py: Clone of GNU find.
|
| 10 | """
|
| 11 |
|
| 12 | from __future__ import print_function
|
| 13 |
|
| 14 | import os
|
| 15 | import sys
|
| 16 |
|
| 17 | #from typing import TYPE_CHECKING, Dict, IO
|
| 18 | #if TYPE_CHECKING:
|
| 19 | # from pgen2.parse import PNode
|
| 20 |
|
| 21 | import tokenizer
|
| 22 | import parser
|
| 23 | from _devbuild.gen import find_nt
|
| 24 | from ast import AST
|
| 25 | from eval import EvalExpr, Thing
|
| 26 | import eval
|
| 27 |
|
| 28 | def printTree(pnode, nametable, f=sys.stderr, indentChars="\t"):
|
| 29 | def _printTree(pnode, nametable, f, i, depth, indentChars):
|
| 30 | v = pnode.tok[0] if tokenizer.is_terminal(pnode.typ) else ""
|
| 31 | print(indentChars * depth, '#%d' % i, nametable.get(pnode.typ, "UNKNOWN"), v, file=f)
|
| 32 | if not pnode.children:
|
| 33 | return
|
| 34 | for i, c in enumerate(pnode.children):
|
| 35 | _printTree(c, nametable, f, i, depth+1, indentChars)
|
| 36 | _printTree(pnode, nametable, f, 0, 0, indentChars)
|
| 37 |
|
| 38 | def contains_print_blocker(node):
|
| 39 | # all actions except -print and -prune
|
| 40 | XYZActions = [
|
| 41 | tokenizer.DELETE, tokenizer.QUIT,
|
| 42 | # tokenizer.PRUNE,
|
| 43 | tokenizer.PRINT,
|
| 44 | tokenizer.PRINT0, tokenizer.PRINTF,
|
| 45 | tokenizer.FPRINT, tokenizer.FPRINT0, tokenizer.FPRINTF,
|
| 46 | tokenizer.LS,
|
| 47 | tokenizer.FLS, tokenizer.EXEC, tokenizer.EXECDIR, tokenizer.OK, tokenizer.OKDIR,
|
| 48 | ]
|
| 49 | return node.typ in XYZActions or (node.children and any(contains_print_blocker(c) for c in node.children))
|
| 50 |
|
| 51 | # find
|
| 52 | # for root, dirs, files in os.walk('.', topdown=True):
|
| 53 | # print(root, *(os.path.join(root, f) for f in files), sep='\n')
|
| 54 | # find -depth
|
| 55 | # for root, dirs, files in os.walk('.', topdown=False):
|
| 56 | # print(*(os.path.join(root, f) for f in files), root, sep='\n')
|
| 57 | def main(argv):
|
| 58 | i = 1
|
| 59 | while i < len(argv) and argv[i][0] not in ('!', '(', '-'):
|
| 60 | i += 1
|
| 61 |
|
| 62 | paths = argv[1:i]
|
| 63 | if not paths:
|
| 64 | paths.append('.')
|
| 65 |
|
| 66 | tokens = tokenizer.tokenize(argv[i:])
|
| 67 |
|
| 68 | parse_root = parser.ParseTree(tokens)
|
| 69 |
|
| 70 | names = tokenizer.tok_name.copy()
|
| 71 | names.update(parser.nt_name)
|
| 72 | printTree(parse_root, names)
|
| 73 |
|
| 74 | ast_root = AST(parse_root)
|
| 75 |
|
| 76 | ast_root.PrettyPrint(f=sys.stderr)
|
| 77 | print(file=sys.stderr)
|
| 78 |
|
| 79 | # if ast contains no actions other than -prune or -print:
|
| 80 | # ast_root = Conjunction(ast_root, -print)
|
| 81 | # if ast_root is a Conjunction, append child
|
| 82 | if not contains_print_blocker(parse_root):
|
| 83 | # print("adding '-a -print'", file=sys.stderr)
|
| 84 | from _devbuild.gen import find_asdl as asdl
|
| 85 | if parse_root.children[0].typ == find_nt.conjunction:
|
| 86 | ast_root.exprs.append(asdl.expr.PrintAction())
|
| 87 | else:
|
| 88 | ast_root = asdl.expr.Conjunction([ast_root, asdl.expr.PrintAction()])
|
| 89 |
|
| 90 | expr = EvalExpr(ast_root)
|
| 91 | for path in paths:
|
| 92 | for root, dirs, files in os.walk(path):
|
| 93 | t = Thing(root)
|
| 94 | b = expr(t)
|
| 95 | if t.quit:
|
| 96 | break
|
| 97 | if t.prune:
|
| 98 | del dirs[:]
|
| 99 | continue
|
| 100 | for fname in files:
|
| 101 | t = Thing(os.path.join(root,fname))
|
| 102 | expr(t)
|
| 103 | # -prune should be ignored for files
|
| 104 | else:
|
| 105 | continue
|
| 106 | # TODO run -exec ... {} +
|
| 107 | break
|
| 108 |
|
| 109 | if __name__ == '__main__':
|
| 110 | try:
|
| 111 | main(sys.argv)
|
| 112 | except RuntimeError as e:
|
| 113 | print('FATAL: %s' % e, file=sys.stderr)
|
| 114 | sys.exit(1)
|