GlueGen v2.6.0-rc-20250712
GlueGen, Native Binding Generator for Java™ (public API).
TestCParser.java
Go to the documentation of this file.
1/**
2 * Copyright 2023 JogAmp Community. All rights reserved.
3 *
4 * Redistribution and use in source and binary forms, with or without modification, are
5 * permitted provided that the following conditions are met:
6 *
7 * 1. Redistributions of source code must retain the above copyright notice, this list of
8 * conditions and the following disclaimer.
9 *
10 * 2. Redistributions in binary form must reproduce the above copyright notice, this list
11 * of conditions and the following disclaimer in the documentation and/or other materials
12 * provided with the distribution.
13 *
14 * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
15 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
16 * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
17 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
18 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
19 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
20 * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
21 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
22 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
23 *
24 * The views and conclusions contained in the software and documentation are those of the
25 * authors and should not be interpreted as representing official policies, either expressed
26 * or implied, of JogAmp Community.
27 */
28
29package com.jogamp.gluegen.test.junit.generation;
30
31import com.jogamp.common.os.AndroidVersion;
32import com.jogamp.gluegen.ConstantDefinition;
33import com.jogamp.gluegen.JavaConfiguration;
34import com.jogamp.gluegen.cgram.CToken;
35import com.jogamp.gluegen.cgram.Define;
36import com.jogamp.gluegen.cgram.GNUCTokenTypes;
37import com.jogamp.gluegen.cgram.GnuCLexer;
38import com.jogamp.gluegen.cgram.GnuCParser;
39import com.jogamp.gluegen.cgram.HeaderParser;
40import com.jogamp.gluegen.cgram.TNode;
41import com.jogamp.gluegen.cgram.types.EnumType;
42import com.jogamp.gluegen.cgram.types.TypeDictionary;
43import com.jogamp.gluegen.jcpp.JCPP;
44import com.jogamp.gluegen.jcpp.LexerException;
45import com.jogamp.gluegen.jcpp.Macro;
46import com.jogamp.junit.util.SingletonJunitCase;
47
48import antlr.RecognitionException;
49import antlr.TokenStreamException;
50import antlr.TokenStreamRecognitionException;
51import junit.framework.Assert;
52
53import java.io.BufferedReader;
54import java.io.ByteArrayOutputStream;
55import java.io.DataInputStream;
56import java.io.File;
57import java.io.FileInputStream;
58import java.io.FileNotFoundException;
59import java.io.FileOutputStream;
60import java.io.FileReader;
61import java.io.IOException;
62import java.util.Collections;
63
64import org.junit.BeforeClass;
65import org.junit.Test;
66import static org.junit.Assert.*;
67
68/**
69 * serves mainly as entry point for debugging purposes.
70 * @author Sven Gothel, Michael Bien
71 */
72import org.junit.FixMethodOrder;
73import org.junit.runners.MethodSorters;
74
75@FixMethodOrder(MethodSorters.NAME_ASCENDING)
76public class TestCParser extends SingletonJunitCase {
77
78 static final String sourcePath = BuildEnvironment.gluegenRoot + "/src/junit/com/jogamp/gluegen/test/junit/generation/";
79 static final boolean debug = false;
80
81 @BeforeClass
82 public static void init() {
84 // JCPP is n/a on Android - GlueGen Runtime only
85 setTestSupported(false);
86 }
87 }
88
89 @Test
90 public void test01_cpp_cc() {
91 if( null != test10CCFileName ) {
92 return;
93 }
94 Exception ex = null;
95 try {
96 final String cppResultPath = cpp("cpptest_1", ".h", debug);
97 cc(cppResultPath, debug);
98 } catch (RecognitionException | IOException | LexerException e) {
99 e.printStackTrace();
100 ex = e;
101 }
102 assertNull(ex);
103 }
104
105 @Test
106 public void test10_cc() {
107 Exception ex = null;
108 try {
109 if( null != test10CCFileName ) {
110 cc(test10CCFileName, debug);
111 } else {
112 cc(sourcePath + "cpptest_10.hpp", debug);
113 }
114 } catch (RecognitionException | IOException | LexerException e) {
115 e.printStackTrace();
116 ex = e;
117 }
118 assertNull(ex);
119 }
120
121 public String cpp(final String cSourceBasename, final String cSourceSuffix, final boolean debug) throws FileNotFoundException, IOException, LexerException, RecognitionException {
122 final String cSourcePath = sourcePath + cSourceBasename + cSourceSuffix;
123 final FileReader cSourceReader = new FileReader(cSourcePath);
124
125 final String cppResultPath = BuildEnvironment.testOutput + "/" + cSourceBasename + ".hpp";
126 final File cppResultFile = new File( cppResultPath );
127 if( cppResultFile.exists() ) {
128 cppResultFile.delete();
129 }
130
131 System.err.println("XXX JCPP: "+cSourcePath);
132 System.err.println("XXX cpp result-file "+cppResultFile);
133 try( final FileOutputStream cppResultOStream = new FileOutputStream(cppResultFile) ) {
134 final JCPP pp = new JCPP(Collections.<String>singletonList(sourcePath), debug, false, true /* default */);
135 pp.addDefine("__GLUEGEN__", "2");
136 pp.setOut(cppResultOStream);
137 pp.run(new BufferedReader(cSourceReader), cSourceBasename);
138 cppResultOStream.flush();
139 cppResultOStream.close();
140 {
141 int macroCount = 0;
142 for (final Macro cdef : pp.cpp.getMacros(true)) {
143 System.err.println("XXX cpp Macr "+macroCount+" <"+cdef+">, isFunc "+
144 cdef.isFunctionLike()+", isConstExpr "+
146 ++macroCount;
147 }
148 }
149 {
150 int defCount = 0;
151 for (final ConstantDefinition cdef : pp.getConstantDefinitions()) {
152 System.err.println("XXX cpp Defn "+defCount+" <"+cdef+">");
153 ++defCount;
154 }
155 }
156 }
157
158 return cppResultPath;
159 }
160
161 public void cc(final String cppResultPath, final boolean debug) throws FileNotFoundException, IOException, LexerException, RecognitionException {
162 final File cppResultFile = new File( cppResultPath );
163 System.err.println("XXX C Parser: "+cppResultPath);
164 try( final FileInputStream inStream = new FileInputStream(cppResultFile) ) {
165 final DataInputStream dis = new DataInputStream(inStream);
166
167 final GnuCLexer lexer = new GnuCLexer(dis);
168 lexer.setTokenObjectClass(CToken.class.getName());
169 lexer.initialize();
170 // Parse the input expression.
171 final GnuCParser parser = new GnuCParser(lexer);
172
173 // set AST node type to TNode or get nasty cast class errors
174 parser.setASTNodeClass(TNode.class.getName());
175 TNode.setTokenVocabulary(GNUCTokenTypes.class.getName());
176
177 // invoke parser
178 parser.setDebug(debug);
179 try {
180 parser.translationUnit();
181 } catch (final RecognitionException e) {
182 throw new RuntimeException(String.format(
183 "Fatal error during translation (Localisation : %s:%s:%s)",
184 e.getFilename(), e.getLine(), e.getColumn()
185 ), e);
186 } catch (final TokenStreamRecognitionException e) {
187 throw new RuntimeException(String.format(
188 "Fatal error during translation (Localisation : %s:%s:%s)",
189 e.recog.getFilename(), e.recog.getLine(), e.recog.getColumn()
190 ), e);
191 } catch (final TokenStreamException e) {
192 throw new RuntimeException("Fatal IO error", e);
193 }
194
195 System.err.println("XXX C Header Tree Parser ...");
196 final JavaConfiguration cfg = new JavaConfiguration();
197 final HeaderParser headerParser = new HeaderParser();
198 headerParser.setDebug(debug);
199 headerParser.setJavaConfiguration(cfg);
200 final TypeDictionary td = new TypeDictionary();
201 headerParser.setTypedefDictionary(td);
202 final TypeDictionary sd = new TypeDictionary();
203 headerParser.setStructDictionary(sd);
204 // set AST node type to TNode or get nasty cast class errors
205 headerParser.setASTNodeClass(TNode.class.getName());
206 // walk that tree
207 headerParser.translationUnit(parser.getAST());
208 dis.close();
209 inStream.close();
210
211 {
212 int enumCount = 0;
213 for (final EnumType enumeration : headerParser.getEnums()) {
214 String enumName = enumeration.getName();
215 if (enumName.equals("<anonymous>")) {
216 enumName = null;
217 }
218 // iterate over all values in the enumeration
219 for (int i = 0; i < enumeration.getNumEnumerates(); ++i) {
220 final EnumType.Enumerator enumerate = enumeration.getEnum(i);
221 final ConstantDefinition cdef =
222 new ConstantDefinition(enumerate.getName(), enumerate.getExpr(),
223 enumerate.getNumber(),
224 enumName, enumeration.getASTLocusTag());
225 System.err.println("XXX cc_ Enum "+enumCount+":"+i+" <"+cdef+">");
226 }
227 ++enumCount;
228 }
229 }
230 {
231 int defCount = 0;
232 for (final Object elem : lexer.getDefines()) {
233 final Define def = (Define) elem;
234 final ConstantDefinition cdef =
235 new ConstantDefinition(def.getName(), def.getValue(), null, def.getASTLocusTag());
236 System.err.println("XXX cc_ Defn "+defCount+" <"+cdef+">");
237 ++defCount;
238 }
239 }
240 }
241 }
242
243 static String test10CCFileName = null;
244 public static void main(final String args[]) throws IOException {
245 for(int i=0; i<args.length; ++i ) {
246 if( "-in".equals(args[i]) ) {
247 test10CCFileName = args[++i];
248 }
249 }
250 final String tstname = TestCParser.class.getName();
251 org.junit.runner.JUnitCore.main(tstname);
252 }
253}
Represents a [native] constant expression, comprises the [native] expression, see getNativeExpr() and...
static boolean isConstantExpression(final String value)
Parses and provides access to the contents of .cfg files for the JavaEmitter.
Represents a #define of a literal to a value (a number represented in string form....
Definition: Define.java:48
ASTLocusTag getASTLocusTag()
Returns this instance's ASTLocusTag, if available, otherwise returns null.
Definition: Define.java:69
List getDefines()
Returns a list of Define objects corresponding to the preprocessor definitions seen during parsing.
Definition: GnuCLexer.java:116
void setStructDictionary(TypeDictionary dict)
Set the dictionary mapping struct names (i.e., the "foo" in "struct foo { ... };") to types for this ...
void setJavaConfiguration(JavaConfiguration cfg)
Set the configuration for this HeaderParser.
void setTypedefDictionary(TypeDictionary dict)
Set the dictionary mapping typedef names to types for this HeaderParser.
List< EnumType > getEnums()
Returns the EnumTypes this HeaderParser processed.
Class TNode is an implementation of the AST interface and adds many useful features:
Definition: TNode.java:38
static void setTokenVocabulary(final String s)
Set the token vocabulary to a tokentypes class generated by antlr.
Definition: TNode.java:70
Describes enumerated types.
Definition: EnumType.java:54
Utility class for recording names of typedefs and structs.
String cpp(final String cSourceBasename, final String cSourceSuffix, final boolean debug)
void cc(final String cppResultPath, final boolean debug)