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)
|