-
Notifications
You must be signed in to change notification settings - Fork 0
/
griffin
executable file
·328 lines (279 loc) · 12.1 KB
/
griffin
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
#!/usr/bin/env python
"""Griffin launcher script."""
import os.path, sys, re, griffin as conf
here = os.path.dirname(__file__)
class Griffin:
premises = ["jython.jar", "antlr.jar", "xercesImpl.jar", \
"junit.jar", "xmlParserAPIs.jar"]
premisedir = "premises"
jardir = os.path.join(here, premisedir)
if not os.path.isdir(jardir): jardir = "/usr/share/java"
robindir = "/usr/share/robin"
DEFAULT_OUTFILE = "./4robin.cc"
GRIFFIN_JAR = "Griffin.jar"
def __init__(self):
self.griffin_bin = os.path.join(here, self.GRIFFIN_JAR)
if not os.path.isfile(self.griffin_bin):
self.griffin_bin = os.path.join(self.jardir, self.GRIFFIN_JAR)
self.javacmd = "backend.Launcher robin"
self.javaflags = "-Xmx496M"
self.compiler = {'-D': [], '-I': []}
self.module = "."
self.verbose = False
def setXML(self, xmldir):
if not os.path.isdir(xmldir):
raise OSError, "'%s' not found" % xmldir
self.xmldir = xmldir
def setSources(self, sources, modules):
self.doxygen(self.module, sources, modules)
self.xmldir = os.path.join(self.module, "xml")
def locate(self, filename):
for path in [here, os.path.join(here, "build"), self.robindir]:
full = os.path.join(path, filename)
if os.path.isfile(full):
return full
return None
def doxygen(self, project, sources, modules):
import os.path
stltag = self.locate("stl.tag") or ""
tagfiles = [stltag] + [os.path.join(x, "module.tag") for x in modules]
tagfile = os.path.join(project, "module.tag")
stdmacros = ["__STDC__", "STDC", "__doxygen", "__cplusplus"]
doxyfile = {
"INPUT": " ".join(sources),
"OUTPUT_DIRECTORY": project,
"TAGFILES": " ".join(tagfiles),
"PREDEFINED": " ".join(stdmacros + self.compiler["-D"]),
"INCLUDE_PATH": " ".join(["/usr/include"] + self.compiler["-I"]),
"MACRO_EXPANSION": "Yes",
"SEARCH_INCLUDES": "Yes",
"GENERATE_TAGFILE": tagfile,
"GENERATE_XML": "Yes",
"XML_PROGRAMLISTING": "No",
"GENERATE_HTML": "No", "GENERATE_LATEX": "No",
"EXTRACT_ALL": "Yes"
}
fmtd_doxyfile = "\n".join("%s = %s" % item
for item in doxyfile.iteritems())
if self.verbose: print ".griffin-doxyfile:\n" + fmtd_doxyfile
open(".griffin-doxyfile", "w").write(fmtd_doxyfile)
Dots(self.verbose).run("doxygen .griffin-doxyfile")
if self.verbose: print "unlink .griffin-doxyfile"
try:
os.unlink(".griffin-doxyfile")
except OSError, e:
print "Couldn't remove .griffin-doxyfile"
def _command(self, modules):
from os.path import join
classpath = [join(self.jardir, x) for x in self.premises]
classpath += [self.griffin_bin]
doxpath = join(here, "build/dox-xml")
stpath = join(here, "src/griffin/modules/stl")
if not os.path.isdir(doxpath): doxpath = os.path.join(here, "dox-xml")
if not os.path.isdir(doxpath): doxpath = join(self.robindir, "dox-xml")
if not os.path.isdir(stpath): stpath = here
if not os.path.isdir(stpath): stpath = self.robindir
doxpath = [doxpath] + [os.path.join(x, "xml") for x in modules]
stpath = [stpath]
cmd = '%s -Dgriffin.dox.path="%s" -Dgriffin.st.path="%s" ' \
'-classpath "%s" %s %s' % \
(conf.config.java, conf.classpath(doxpath),
conf.classpath(stpath), conf.classpath(classpath),
self.javaflags, self.javacmd)
return cmd
def run(self, args, modules):
cmdline = " ".join([self._command(modules),
"--input", self.xmldir] + args)
if self.verbose: print >> sys.stderr, cmdline
os.system(cmdline)
def _opt_eclipse(self):
self.griffin_bin = os.path.join(here, "build/eclipse-bin")
def _argv(self, args):
"""Parse command-line arguments."""
from robinlib import argparse
parser = argparse.ArgumentParser("griffin",
description="Griffin - wrapper code generator for Robin.")
parser.add_argument(
"--in", metavar="filename", type=str, nargs="+", default=[],
help="either list of input source filenames, or XML directory "
"previously generated by doxygen")
parser.add_argument(
"--out", metavar="filename", type=str,
default=self.DEFAULT_OUTFILE,
help="generated output file (default: %s)" % self.DEFAULT_OUTFILE)
parser.add_argument(
"inputs", metavar="identifier", type=str, nargs="*",
help="source files, classes, and functions to be wrapped")
parser.add_argument(
"--classes", metavar="identifier", type=str, nargs="+", default=[],
help="classes and functions to be wrapped")
parser.add_argument(
"--module", metavar="module-name",
help="name for the generated module (generates doxygen tag file"
" and xml output directory for use in later projects)")
parser.add_argument(
"--import", metavar="path", type=str, nargs="+", default=[],
help="doxygen output directory of external modules to refer to")
parser.add_argument(
"--include", action='store_true', default=False,
help="process #included header files recursively")
parser.add_argument(
"--checksources", action='store_true', default=False,
help="check sources for existance, and warn on unexisting ones")
parser.add_argument(
"-I", action='append', type=str, metavar="macro", default=[],
help="search path for header files in #include directives")
parser.add_argument(
"-D", action='append', type=str, metavar="macro", default=[],
help="preprocessor directives to predefine (name or name=value)")
parser.add_argument(
"--interceptors", action='store_true', default=False,
help="also generate interceptor classes for wrapped interfaces")
parser.add_argument(
"--hints", type=str, metavar="jython-hints",
help="specify a Jython file containing code generation hints")
parser.add_argument(
"-v", action='store_true', default=False,
help="be verbose")
parser.add_argument(
"--eclipse", action='store_true', default=False,
help="(development) use Griffin as compiled by Eclipse "
"instead of Griffin.jar")
parser.add_argument(
"--debug", metavar="port", type=int,
help="(development) launch JVM in debug mode")
if not args: args = ["-h"]
values = parser.parse_args(args)
FLAGS = ["include", "checksources", "v", "debug", "interceptors", "module"]
OPTS = ["hints", "import"]
arg_in = values.__dict__['in']
arg_out = values.out
arg_classes = values.classes
arg_opts = dict([(x,y) for (x,y) in values.__dict__.items()
if (y and x in FLAGS) or x in OPTS])
if values.inputs:
arg_in += [x for x in values.inputs if "." in x]
arg_classes += [x for x in values.inputs if "." not in x]
if values.eclipse:
self._opt_eclipse()
self.compiler["-D"].extend(values.D)
self.compiler["-I"].extend(values.I)
return arg_in, [arg_out], arg_opts, arg_classes
def jarg(self, name, value):
"""
Encodes an argument for the Java application.
"""
if isinstance(value, str):
return "--%s=%s" % (name, value)
else:
return "--%s" % name
def process(self, args):
"""Runs Griffin front-end and back-end using the given arguments."""
arg_in, arg_out, arg_opts, arg_other = self._argv(args)
arg_out = ["--outfile"] + arg_out
arg_other = ["--classes"] + arg_other
if len(arg_in) > 0:
if arg_in[0] in ["xml", "sources"]:
input_type = arg_in[0]
arg_in = arg_in[1:]
else:
# - try to intelligently guess input type
import os.path
if os.path.isfile(arg_in[0]):
input_type = "sources"
else:
input_type = "xml"
else:
input_type = "none"
self.verbose = "v" in arg_opts
wizard = "w" in arg_opts or "wizard" in arg_opts
imported = arg_opts["import"]
if "module" in arg_opts: self.module = arg_opts["module"]
# Set input source
if input_type == "sources":
if "include" in arg_opts:
arg_in = Preprocessor().extractAllIncluded(arg_in)
if "checksources" in arg_opts:
arg_in = Preprocessor().checkSources(arg_in)
self.setSources(arg_in, imported)
elif input_type == "xml" or wizard:
if len(arg_in) == 0:
self.setXML("xml")
else:
self.setXML(arg_in[0])
else:
print "griffin: No input specified. Quit."
raise SystemExit
JOPTS = ["interceptors", "hints"]
arg_jopts = [self.jarg(x,y) for (x,y) in arg_opts.items()
if x in JOPTS]
if "debug" in arg_opts:
self.javaflags += " -Xrunjdwp:transport=dt_socket,address=%d,server=y,suspend=y" % arg_opts["debug"]
if wizard:
self.javacmd = "wizard.Main"
self.premises.extend(["swt.jar","jface.jar",
"org.eclipse.core.runtime.jar"])
# engage
self.run(arg_out + arg_jopts + arg_other, imported)
class Preprocessor(object):
INCLUDE_DIRECTIVE = re.compile(r'^\s*#\s*include\s*"(.*)"')
def findHeader(self, included_in, included):
if os.path.isfile(included):
return included
rel = os.path.join(included_in, os.path.pardir, included)
return os.path.normpath(rel)
def extractIncluded(self, filename):
if not os.path.isfile(filename): return []
# Look for 'include' directives
all_included = []
for line in open(filename):
mo = Preprocessor.INCLUDE_DIRECTIVE.search(line)
if mo:
included = self.findHeader(filename, mo.group(1))
if included:
all_included.append(included)
return all_included
def extractAllIncluded(self, filenames):
filenames = map(os.path.normpath, filenames)
i = 0
while i < len(filenames):
for included in self.extractIncluded(filenames[i]):
if included not in filenames and os.path.isfile(included):
filenames.append(included)
i += 1
return filenames
def checkSources(self, filenames):
l = []
for filename in filenames:
if os.path.isfile(filename):
l.append(filename)
else:
print "Griffin: warning: file %s wasn't found" % filename
return l
class CommandRunner(object):
def __init__(self, verbose = False):
self.verbose = verbose
def run(self, command):
pass
class ShellRunner(CommandRunner):
def run(self, command):
if self.verbose: print command
os.system(command)
class Dots(CommandRunner):
"""Runs an external command without sending all the output to the tty."""
def run(self, command):
if self.verbose: print command
pipe = os.popen(command)
for line in pipe:
sys.stderr.write(".")
if pipe.close():
sys.stderr.write(" [FAILED]\n")
raise OSError, "failed to run " + command.split()[0]
else:
sys.stderr.write(" [ OK ]\n")
if __name__ == "__main__":
g = Griffin()
try:
g.process(sys.argv[1:])
except OSError, msg:
print "griffin:", msg