40package com.jogamp.gluegen;
42import com.jogamp.common.GlueGenVersion;
46import java.util.logging.Level;
50import com.jogamp.gluegen.cgram.*;
51import com.jogamp.gluegen.cgram.types.*;
52import com.jogamp.gluegen.jcpp.JCPP;
54import static java.lang.System.*;
65 private final List<String> forcedStructNames =
new ArrayList<String>();
69 private List<ConstantDefinition> allConstants;
70 private List<FunctionSymbol> allFunctions;
72 private static boolean debug =
false;
74 private static Level logLevel =
null;
76 public static void setDebug(
final boolean v) { debug=v; }
82 forcedStructNames.add(typedefName);
87 return preprocessor.
findFile(headerFileName);
93 final List<ConstantDefinition> newConstants = filter.
getConstants();
94 final List<FunctionSymbol> newFunctions = filter.
getFunctions();
95 if (newConstants !=
null) {
96 allConstants = newConstants;
98 if (newFunctions !=
null) {
99 allFunctions = newFunctions;
106 @SuppressWarnings(
"unchecked")
107 public
void run(final Reader reader, final String filename, final Class<?> emitterClass, final List<String> includePaths, final List<String> cfgFiles, final String outputRootDir,
108 final
boolean copyCPPOutput2Stderr, final
boolean enablePragmaOnce, final
boolean preserveGeneratedCPP)
113 System.err.println(
"GlueGen.run: filename: "+filename+
", emitter: "+emitterClass.getName()+
", outputRootDir "+outputRootDir+
114 ", copyCPPOutput2Stderr "+copyCPPOutput2Stderr+
", enablePragmaOnce "+enablePragmaOnce+
", preserveGeneratedCPP "+preserveGeneratedCPP);
115 System.err.println(
"GlueGen.run: includePaths "+includePaths);
116 System.err.println(
"GlueGen.run: cfgFiles "+cfgFiles);
117 }
else if(
null != logLevel ) {
121 if (emitterClass ==
null) {
126 }
catch (
final Exception e) {
127 throw new RuntimeException(
"Exception occurred while instantiating emitter class.", e);
131 for (
final String config : cfgFiles) {
136 final File out = File.createTempFile(
"CPPTemp",
".cpp");
137 final FileOutputStream outStream =
new FileOutputStream(out);
140 preprocessor =
new JCPP(includePaths, debug, copyCPPOutput2Stderr, enablePragmaOnce);
141 final String cppName = preprocessor.getClass().getSimpleName();
142 if(debug || preserveGeneratedCPP) {
143 System.err.println(
"CPP <"+cppName+
"> output at (persistent): " + out.getAbsolutePath());
149 preprocessor.
setOut(outStream);
151 preprocessor.
run(reader, filename);
155 System.err.println(
"CPP <"+cppName+
"> done");
158 final FileInputStream inStream =
new FileInputStream(out);
159 final DataInputStream dis =
new DataInputStream(inStream);
162 lexer.setTokenObjectClass(
CToken.class.getName());
168 parser.setASTNodeClass(
TNode.class.getName());
174 }
catch (
final RecognitionException e) {
175 throw new RuntimeException(String.format(
176 "Fatal error during translation (Localisation : %s:%s:%s)",
177 e.getFilename(), e.getLine(), e.getColumn()
179 }
catch (
final TokenStreamRecognitionException e) {
180 throw new RuntimeException(String.format(
181 "Fatal error during translation (Localisation : %s:%s:%s)",
182 e.recog.getFilename(), e.recog.getLine(), e.recog.getColumn()
184 }
catch (
final TokenStreamException e) {
185 throw new RuntimeException(
"Fatal IO error", e);
196 headerParser.setASTNodeClass(
TNode.class.getName());
213 if (
null != outputRootDir && outputRootDir.trim().length() > 0) {
225 allConstants =
new ArrayList<ConstantDefinition>();
227 String enumName = enumeration.getName();
228 if (enumName.equals(
"<anonymous>")) {
232 for (
int i = 0; i < enumeration.getNumEnumerates(); ++i) {
237 enumName, enumeration.getASTLocusTag());
238 allConstants.add(def);
241 for (
final Object elem : lexer.
getDefines()) {
257 System.err.println(
"Filtered Constants: "+allConstants.size());
260 System.err.println(
"Filtered ["+i+
"]: "+def.getAliasedString());
265 System.err.println(
"Filtered Functions: "+allFunctions.size());
267 System.err.println(
"Filtered ["+i+
"]: "+cFunc.getAliasedString());
274 final Set<String> emittedDefines =
new HashSet<String>(100);
276 final StringBuilder comment =
new StringBuilder();
278 if (!emittedDefines.contains(def.getName())) {
279 emittedDefines.add(def.getName());
281 if (aliases !=
null && aliases.size() > 0 ) {
283 comment.append(
"Alias for: <code>");
284 for (
final String alias : aliases) {
286 comment.append(
"</code>, <code>");
288 comment.append(alias);
291 comment.append(
"</code>");
293 if (comment.length() > 0) {
294 comment.append(
"<br>\n");
296 if (def.getEnumName() !=
null) {
297 comment.append(
"Defined as part of enum type \"");
298 comment.append(def.getEnumName());
299 comment.append(
"\"");
301 comment.append(
"Define \"");
302 comment.append(def.getName());
303 comment.append(
"\"");
305 comment.append(
" with expression '<code>"+def.getNativeExpr()+
"</code>'");
306 if (comment.length() > 0) {
308 comment.setLength(0);
325 sym.getType().visit(referencedStructs);
331 for (
final String name : forcedStructNames) {
332 final Type type = td.
get(name);
334 err.println(
"WARNING: during forced struct emission: struct \"" + name +
"\" not found");
336 err.println(
"WARNING: during forced struct emission: type \"" + name +
"\" was not a struct");
338 type.
visit(referencedStructs);
344 for (
final Iterator<CompoundType> iter = referencedStructs.
layouts(); iter.hasNext();) {
354 for (
final Iterator<Type> iter = referencedStructs.
results(); iter.hasNext();) {
355 final Type t = iter.next();
357 assert t.isTypedef() && t.
getName() == null :
"ReferencedStructs incorrectly recorded compound type " + t;
362 assert p.
isTypedef() && c.
getName() == null :
"ReferencedStructs incorrectly recorded pointer type " + p;
378 }
catch (
final Exception e) {
379 throw new RuntimeException(
"Exception occurred while generating glue code.", e);
383 public static void main(
final String... args) {
385 if (args.length == 0) {
390 Reader reader =
null;
391 String filename =
null;
392 String emitterFQN =
null;
393 String outputRootDir =
null;
394 final List<String> cfgFiles =
new ArrayList<String>();
395 boolean copyCPPOutput2Stderr =
false;
396 boolean enablePragmaOnce =
true;
397 boolean preserveGeneratedCPP =
false;
399 final List<String> includePaths =
new ArrayList<String>();
400 for (
int i = 0; i < args.length; i++) {
401 if (i < args.length - 1) {
402 final String arg = args[i];
403 if (arg.startsWith(
"-I")) {
404 final String[] paths = arg.substring(2).split(getProperty(
"path.separator"));
405 includePaths.addAll(Arrays.asList(paths));
406 }
else if (arg.startsWith(
"-O")) {
407 outputRootDir = arg.substring(2);
408 }
else if (arg.startsWith(
"-E")) {
409 emitterFQN = arg.substring(2);
410 }
else if (arg.startsWith(
"-C")) {
411 cfgFiles.add(arg.substring(2));
412 }
else if (arg.equals(
"--logLevel")) {
414 logLevel = Level.parse(args[i]);
415 }
else if (arg.equals(
"--debug")) {
417 }
else if (arg.equals(
"--dumpCPP")) {
418 copyCPPOutput2Stderr=
true;
419 }
else if (arg.equals(
"--disablePragmaOnce")) {
420 enablePragmaOnce=
false;
421 }
else if (arg.equals(
"--preserveGeneratedCPP")) {
422 preserveGeneratedCPP=
true;
427 final String arg = args[i];
428 if (arg.equals(
"-")) {
429 reader =
new InputStreamReader(in);
430 filename =
"standard input";
432 if (arg.startsWith(
"-")) {
437 reader =
new BufferedReader(
new FileReader(filename));
438 }
catch (
final FileNotFoundException ex) {
439 throw new RuntimeException(
"input file not found", ex);
446 final Class<?> emitterClass = emitterFQN ==
null ? null : Class.forName(emitterFQN);
447 new GlueGen().
run(reader, filename, emitterClass, includePaths, cfgFiles, outputRootDir, copyCPPOutput2Stderr, enablePragmaOnce, preserveGeneratedCPP);
448 }
catch (
final ClassNotFoundException ex) {
449 throw new RuntimeException(
"specified emitter class was not in the classpath", ex);
457 private static void usage() {
458 out.println(
"Usage: java GlueGen [-I...] [-Eemitter_class_name] [-Ccfg_file_name...] <filename | ->");
460 out.println(
"Runs C header parser on input file or standard input, first");
461 out.println(
"passing input through minimal pseudo-C-preprocessor. Use -I");
462 out.println(
"command-line arguments to specify the search path for #includes.");
463 out.println(
"Emitter class name can be specified with -E option: i.e.,");
464 out.println(
"-Ecom.jogamp.gluegen.JavaEmitter (the default). Use");
465 out.println(
"-Ecom.jogamp.gluegen.DebugEmitter to print recognized entities");
466 out.println(
"(#define directives to constant numbers, typedefs, and function");
467 out.println(
"declarations) to standard output. Emitter-specific configuration");
468 out.println(
"file or files can be specified with -C option; e.g,");
469 out.println(
"-Cjava-emitter.cfg.");
470 out.println(
" --debug enables debug mode");
471 out.println(
" --dumpCPP directs CPP to dump all output to stderr as well");
472 out.println(
" --disablePragmaOnce disable handling of #pragma once directive during parsing (enabled by default)");
473 out.println(
" --preserveGeneratedCPP preserve generated CPP file during generation (File it's already preserved by debug mode)");
static GlueGenVersion getInstance()
Represents a [native] constant expression, comprises the [native] expression, see getNativeExpr() and...
Glue code generator for C functions and data structures.
static void main(final String... args)
String findHeaderFile(final String headerFileName)
Finds the full path name of the specified header file based on the include directories specified on t...
static void setDebug(final boolean v)
void run(final Reader reader, final String filename, final Class<?> emitterClass, final List< String > includePaths, final List< String > cfgFiles, final String outputRootDir, final boolean copyCPPOutput2Stderr, final boolean enablePragmaOnce, final boolean preserveGeneratedCPP)
void runSymbolFilter(final SymbolFilter filter)
Runs the given filter on the #defines, enum definitions and function symbols that this controller has...
static final String __GLUEGEN__
GlueGen's build in macro name {@value}, when compiling w/ GlueGen.
static void setLogLevel(final Level l)
void forceStructEmission(final String typedefName)
Requests emission of an accessor for a struct that will not be referenced by any functions or other s...
Parses and provides access to the contents of .cfg files for the JavaEmitter.
Set< String > getAliasedDocNames(final AliasedSymbol symbol)
Return a set of aliased-name for comment in docs.
void setOutputRootDir(final String s)
JavaConfiguration getConfig()
static LoggerIf getLogger()
Returns the root package logger.
Iterator< Type > results()
Iterator< CompoundType > layouts()
Represents a #define of a literal to a value (a number represented in string form....
ASTLocusTag getASTLocusTag()
Returns this instance's ASTLocusTag, if available, otherwise returns null.
List getDefines()
Returns a list of Define objects corresponding to the preprocessor definitions seen during parsing.
void initialize(String src)
final void translationUnit()
Class TNode is an implementation of the AST interface and adds many useful features:
static void setTokenVocabulary(final String s)
Set the token vocabulary to a tokentypes class generated by antlr.
Models all compound types, i.e., those containing fields: structs and unions.
Describes enumerated types.
Describes a function symbol, which includes the name and type.
final Type getTargetType()
Helper method to returns the target type of this type, in case another type is being referenced,...
Utility class for recording names of typedefs and structs.
Type get(final String name)
Get the type corresponding to the given name.
PointerType asPointer()
Casts this to a PointerType or returns null if not a PointerType.
final String getName()
Returns the name of this type.
void visit(final TypeVisitor visitor)
Traverse this Type and all of its component types; for example, the return type and argument types of...
final boolean isPointer()
Indicates whether this is a PointerType.
CompoundType asCompound()
Casts this to a CompoundType or returns null if not a CompoundType.
final boolean isTypedef()
Indicates whether this type is a typedef type, i.e.
final boolean isCompound()
Indicates whether this is a CompoundType.
Generic C preprocessor interface for GlueGen.
String findFile(String filename)
List< ConstantDefinition > getConstantDefinitions()
Returns a list of ConstantDefinition, i.e.
void setOut(OutputStream out)
void addDefine(String name, String value)
void run(Reader reader, String filename)
Specifies the interface by which a GlueEmitter can request additional information from the glue gener...
Specifies the interface by which GlueGen requests glue code to be generated.
void endEmission()
Finish the emission of glue code.
void beginStructs(TypeDictionary typedefDictionary, TypeDictionary structDictionary, Map< Type, Type > canonMap)
void beginStructLayout()
Begins the process of computing field offsets and type sizes for the structs to be emitted.
void endStructLayout()
Finishes the struct layout process.
JavaConfiguration getConfig()
void emitDefine(ConstantDefinition def, String optionalComment)
void beginFunctions(TypeDictionary typedefDictionary, TypeDictionary structDictionary, Map< Type, Type > canonMap, List< FunctionSymbol > cFunctions)
void readConfigurationFile(String filename)
void layoutStruct(CompoundType t)
Lays out one struct which will be emitted later.
void emitStruct(CompoundType t, Type typedefType)
Emit glue code for the given CompoundType.
Iterator< FunctionSymbol > emitFunctions(List< FunctionSymbol > cFunctions)
Emit glue code for the list of FunctionSymbols.
void beginEmission(GlueEmitterControls controls)
Begin the emission of glue code.
void setLevel(final Level newLevel)
See Logger#setLevel(Level).
Provides a mechanism by which the GlueEmitter can look at all of the #defines, enum values and functi...
List< ConstantDefinition > getConstants()
Returns the filtered list of constants.
void filterSymbols(List< ConstantDefinition > constants, List< FunctionSymbol > functions)
Filters the given constant and function symbols.
List< FunctionSymbol > getFunctions()
Returns the filtered list of function symbols.
String getName()
Return the current-name, which is the last renamed-name if issued, or the original-name.