Added support for parsing macros and anonymous unnamed enums (#35)
closes #12, closes #50
- Support for parsing macros and anonymous unnamed enums.
- These are generated as top-level constants.
- unnamed enums can be disabled by using `unnamed-enums: false`, default is `true`.
diff --git a/CHANGELOG.md b/CHANGELOG.md
index bf34d90..9a32792 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,3 +1,6 @@
+# 0.1.5
+- Added support for parsing macros and anonymous unnamed enums. These are generated as top level constants.
+
# 0.1.4
- Comments config now has a style and length sub keys - `style: doxygen(default) | any`, `length: brief | full(default)`, and can be disabled by passing `comments: false`.
diff --git a/README.md b/README.md
index 4bf4abd..604a1bc 100644
--- a/README.md
+++ b/README.md
@@ -63,21 +63,18 @@
<thead>
<tr>
<th>Key</th>
- <th>Required</th>
<th>Explaination</th>
<th>Example</th>
</tr>
</thead>
<tbody>
<tr>
- <td>output</td>
- <td>yes</td>
+ <td>output<br><i>(Required)</i></td>
<td>Output path of the generated bindings.</td>
<td><pre lang="yaml"><code>output: 'generated_bindings.dart'</code></pre></td>
</tr>
<tr>
- <td>headers</td>
- <td>yes</td>
+ <td>headers<br><i>(Required)</i></td>
<td>List of C headers to use. Glob syntax is allowed.</td>
<td><pre lang="yaml"><code>
headers:
@@ -86,7 +83,6 @@
</tr>
<tr>
<td>header-filter</td>
- <td>no</td>
<td>Name of headers to include/exclude.</td>
<td><pre lang="yaml"><code>
header-filter:
@@ -95,26 +91,22 @@
- 'platform.h'</code></pre></td>
</tr>
<tr>
- <td>name</td>
- <td>prefer</td>
+ <td>name<br><i>(Prefer)</i></td>
<td>Name of generated class.</td>
<td><pre lang="yaml"><code>name: 'SQLite'</code></pre></td>
</tr>
<tr>
- <td>description</td>
- <td>prefer</td>
+ <td>description<br><i>(Prefer)</i></td>
<td>Dart Doc for generated class.</td>
<td><pre lang="yaml"><code>description: 'Bindings to SQLite'</code></pre></td>
</tr>
<tr>
<td>compiler-opts</td>
- <td>no</td>
<td>Pass compiler options to clang.</td>
<td><pre lang="yaml"><code>compiler-opts: '-I/usr/lib/llvm-9/include/'</code></pre></td>
</tr>
<tr>
- <td>functions<br>structs<br>enums</td>
- <td>no</td>
+ <td>functions<br>structs<br>enums<br>macros</td>
<td>Filters for declarations.<br><b>Default: all are included</b></td>
<td><pre lang="yaml"><code>
functions:
@@ -132,7 +124,6 @@
</tr>
<tr>
<td>array-workaround</td>
- <td>no</td>
<td>Should generate workaround for fixed arrays in Structs. See <a href="#array-workaround">Array Workaround</a><br>
<b>Default: false</b>
</td>
@@ -140,7 +131,6 @@
</tr>
<tr>
<td>comments</td>
- <td>no</td>
<td>Extract documentation comments for declarations.<br>
The style and length of the comments can be specified with the following options.<br>
<i>style: doxygen(default) | any </i><br>
@@ -156,7 +146,6 @@
</tr>
<tr>
<td>sort</td>
- <td>no</td>
<td>Sort the bindings according to name.<br>
<b>Default: false</b>, i.e keep the order as in the source files.
</td>
@@ -164,15 +153,20 @@
</tr>
<tr>
<td>use-supported-typedefs</td>
- <td>no</td>
<td>Should automatically map typedefs, E.g uint8_t => Uint8, int16_t => Int16 etc.<br>
<b>Default: true</b>
</td>
<td><pre lang="yaml"><code>use-supported-typedefs: true</code></pre></td>
</tr>
+ <tr>
+ <td>unnamed-enums</td>
+ <td>Should generate constants for anonymous unnamed enums.<br>
+ <b>Default: true</b>
+ </td>
+ <td><pre lang="yaml"><code>unnamed-enums: true</code></pre></td>
+ </tr>
<tr>
<td>preamble</td>
- <td>no</td>
<td>Raw header of the file, pasted as-it-is.</td>
<td><pre lang="yaml"><code>
preamble: |
@@ -182,7 +176,6 @@
</tr>
<tr>
<td>size-map</td>
- <td>no</td>
<td>Size of integers to use (in bytes).<br>
<b>The defaults (see example) <i>may</i> not be portable on all OS.
Do not change these unless absolutely sure.</b>
diff --git a/example/c_json/cjson_generated_bindings.dart b/example/c_json/cjson_generated_bindings.dart
index 25900b1..7c41b0f 100644
--- a/example/c_json/cjson_generated_bindings.dart
+++ b/example/c_json/cjson_generated_bindings.dart
@@ -1063,6 +1063,38 @@
ffi.Pointer<ffi.NativeFunction<_typedefC_2>> free_fn;
}
+const int CJSON_VERSION_MAJOR = 1;
+
+const int CJSON_VERSION_MINOR = 7;
+
+const int CJSON_VERSION_PATCH = 12;
+
+const int cJSON_Invalid = 0;
+
+const int cJSON_False = 1;
+
+const int cJSON_True = 2;
+
+const int cJSON_NULL = 4;
+
+const int cJSON_Number = 8;
+
+const int cJSON_String = 16;
+
+const int cJSON_Array = 32;
+
+const int cJSON_Object = 64;
+
+const int cJSON_Raw = 128;
+
+const int cJSON_IsReference = 256;
+
+const int cJSON_StringIsConst = 512;
+
+const int CJSON_NESTING_LIMIT = 1000;
+
+const double CJSON_DOUBLE_PRECISION = 1e-16;
+
typedef _c_cJSON_Version = ffi.Pointer<ffi.Int8> Function();
typedef _dart_cJSON_Version = ffi.Pointer<ffi.Int8> Function();
diff --git a/example/libclang-example/generated_bindings.dart b/example/libclang-example/generated_bindings.dart
index bd5b8ce..6148331 100644
--- a/example/libclang-example/generated_bindings.dart
+++ b/example/libclang-example/generated_bindings.dart
@@ -3293,6 +3293,14 @@
ffi.Pointer<ffi.NativeFunction<_typedefC_10>> indexEntityReference;
}
+const int CINDEX_VERSION_MAJOR = 0;
+
+const int CINDEX_VERSION_MINOR = 59;
+
+const int CINDEX_VERSION = 59;
+
+const String CINDEX_VERSION_STRING = '0.59';
+
typedef _c_clang_disposeStringSet = ffi.Void Function(
ffi.Pointer<CXStringSet> set_1,
);
diff --git a/lib/src/clang_library/wrapper.c b/lib/src/clang_library/wrapper.c
index 978b7e7..c43c7f6 100644
--- a/lib/src/clang_library/wrapper.c
+++ b/lib/src/clang_library/wrapper.c
@@ -333,4 +333,29 @@
return ptrToCXType(clang_getArrayElementType(*cxtype));
}
+unsigned clang_Cursor_isMacroFunctionLike_wrap(CXCursor *cursor)
+{
+ return clang_Cursor_isMacroFunctionLike(*cursor);
+}
+
+unsigned clang_Cursor_isMacroBuiltin_wrap(CXCursor *cursor)
+{
+ return clang_Cursor_isMacroBuiltin(*cursor);
+}
+
+CXEvalResult clang_Cursor_Evaluate_wrap(CXCursor *cursor)
+{
+ return clang_Cursor_Evaluate(*cursor);
+}
+
+unsigned clang_Cursor_isAnonymous_wrap(CXCursor *cursor)
+{
+ return clang_Cursor_isAnonymous(*cursor);
+}
+
+unsigned clang_Cursor_isAnonymousRecordDecl_wrap(CXCursor *cursor)
+{
+ return clang_Cursor_isAnonymousRecordDecl(*cursor);
+}
+
// END ===== WRAPPER FUNCTIONS =====================
diff --git a/lib/src/clang_library/wrapper.def b/lib/src/clang_library/wrapper.def
index 5a10727..c82231f 100644
--- a/lib/src/clang_library/wrapper.def
+++ b/lib/src/clang_library/wrapper.def
@@ -353,3 +353,8 @@
clang_getFileName_wrap
clang_getNumElements_wrap
clang_getArrayElementType_wrap
+clang_Cursor_isMacroFunctionLike_wrap
+clang_Cursor_isMacroBuiltin_wrap
+clang_Cursor_Evaluate_wrap
+clang_Cursor_isAnonymous_wrap
+clang_Cursor_isAnonymousRecordDecl_wrap
diff --git a/lib/src/code_generator/constant.dart b/lib/src/code_generator/constant.dart
index 6af8a6d..b5521ad 100644
--- a/lib/src/code_generator/constant.dart
+++ b/lib/src/code_generator/constant.dart
@@ -7,7 +7,6 @@
import 'binding.dart';
import 'binding_string.dart';
-import 'type.dart';
import 'utils.dart';
import 'writer.dart';
@@ -23,7 +22,8 @@
/// const int name = 10;
/// ```
class Constant extends NoLookUpBinding {
- final Type type;
+ /// The rawType is pasted as it is. E.g 'int', 'String', 'double'
+ final String rawType;
/// The rawValue is pasted as it is.
///
@@ -34,7 +34,7 @@
String originalName,
@required String name,
String dartDoc,
- @required this.type,
+ @required this.rawType,
@required this.rawValue,
}) : super(originalName: originalName ?? name, name: name, dartDoc: dartDoc);
@@ -47,7 +47,7 @@
s.write(makeDartDoc(dartDoc));
}
- s.write('const ${type.getDartType(w)} $constantName = $rawValue;\n\n');
+ s.write('const ${rawType} $constantName = $rawValue;\n\n');
return BindingString(
type: BindingStringType.constant, string: s.toString());
diff --git a/lib/src/config_provider/config.dart b/lib/src/config_provider/config.dart
index 0f872f9..eb75b80 100644
--- a/lib/src/config_provider/config.dart
+++ b/lib/src/config_provider/config.dart
@@ -43,6 +43,9 @@
/// Declaration config for Enums.
Declaration enumClassDecl;
+ /// Declaration config for Enums.
+ Declaration macroDecl;
+
/// If generated bindings should be sorted alphabetically.
bool sort;
@@ -58,6 +61,9 @@
/// members removed.
bool arrayWorkaround;
+ /// If constants should be generated for unnamed enums.
+ bool unnamedEnums;
+
/// Name of the wrapper class.
String wrapperName;
@@ -189,6 +195,16 @@
enumClassDecl = result as Declaration;
},
),
+ strings.macros: Specification<Declaration>(
+ description: 'Filter for macros',
+ requirement: Requirement.no,
+ validator: declarationConfigValidator,
+ extractor: declarationConfigExtractor,
+ defaultValue: () => Declaration(),
+ extractedResult: (dynamic result) {
+ macroDecl = result as Declaration;
+ },
+ ),
strings.sizemap: Specification<Map<int, SupportedNativeType>>(
description: 'map of types: byte size in int',
validator: sizemapValidator,
@@ -238,6 +254,14 @@
defaultValue: () => false,
extractedResult: (dynamic result) => arrayWorkaround = result as bool,
),
+ strings.unnamedEnums: Specification<bool>(
+ description: 'whether or not to generate constants for unnamed enums.',
+ requirement: Requirement.no,
+ validator: booleanValidator,
+ extractor: booleanExtractor,
+ defaultValue: () => true,
+ extractedResult: (dynamic result) => unnamedEnums = result as bool,
+ ),
strings.name: Specification<String>(
description: 'Name of the wrapper class',
requirement: Requirement.prefer,
diff --git a/lib/src/header_parser/clang_bindings/clang_bindings.dart b/lib/src/header_parser/clang_bindings/clang_bindings.dart
index afdf041..61fe3d8 100644
--- a/lib/src/header_parser/clang_bindings/clang_bindings.dart
+++ b/lib/src/header_parser/clang_bindings/clang_bindings.dart
@@ -174,6 +174,97 @@
_dart_clang_disposeTranslationUnit _clang_disposeTranslationUnit;
+ /// Returns the kind of the evaluated result.
+ int clang_EvalResult_getKind(
+ ffi.Pointer<ffi.Void> E,
+ ) {
+ _clang_EvalResult_getKind ??= _dylib.lookupFunction<
+ _c_clang_EvalResult_getKind,
+ _dart_clang_EvalResult_getKind>('clang_EvalResult_getKind');
+ return _clang_EvalResult_getKind(
+ E,
+ );
+ }
+
+ _dart_clang_EvalResult_getKind _clang_EvalResult_getKind;
+
+ /// Returns the evaluation result as integer if the
+ /// kind is Int.
+ int clang_EvalResult_getAsInt(
+ ffi.Pointer<ffi.Void> E,
+ ) {
+ _clang_EvalResult_getAsInt ??= _dylib.lookupFunction<
+ _c_clang_EvalResult_getAsInt,
+ _dart_clang_EvalResult_getAsInt>('clang_EvalResult_getAsInt');
+ return _clang_EvalResult_getAsInt(
+ E,
+ );
+ }
+
+ _dart_clang_EvalResult_getAsInt _clang_EvalResult_getAsInt;
+
+ /// Returns the evaluation result as a long long integer if the
+ /// kind is Int. This prevents overflows that may happen if the result is
+ /// returned with clang_EvalResult_getAsInt.
+ int clang_EvalResult_getAsLongLong(
+ ffi.Pointer<ffi.Void> E,
+ ) {
+ _clang_EvalResult_getAsLongLong ??= _dylib.lookupFunction<
+ _c_clang_EvalResult_getAsLongLong,
+ _dart_clang_EvalResult_getAsLongLong>('clang_EvalResult_getAsLongLong');
+ return _clang_EvalResult_getAsLongLong(
+ E,
+ );
+ }
+
+ _dart_clang_EvalResult_getAsLongLong _clang_EvalResult_getAsLongLong;
+
+ /// Returns the evaluation result as double if the
+ /// kind is double.
+ double clang_EvalResult_getAsDouble(
+ ffi.Pointer<ffi.Void> E,
+ ) {
+ _clang_EvalResult_getAsDouble ??= _dylib.lookupFunction<
+ _c_clang_EvalResult_getAsDouble,
+ _dart_clang_EvalResult_getAsDouble>('clang_EvalResult_getAsDouble');
+ return _clang_EvalResult_getAsDouble(
+ E,
+ );
+ }
+
+ _dart_clang_EvalResult_getAsDouble _clang_EvalResult_getAsDouble;
+
+ /// Returns the evaluation result as a constant string if the
+ /// kind is other than Int or float. User must not free this pointer,
+ /// instead call clang_EvalResult_dispose on the CXEvalResult returned
+ /// by clang_Cursor_Evaluate.
+ ffi.Pointer<ffi.Int8> clang_EvalResult_getAsStr(
+ ffi.Pointer<ffi.Void> E,
+ ) {
+ _clang_EvalResult_getAsStr ??= _dylib.lookupFunction<
+ _c_clang_EvalResult_getAsStr,
+ _dart_clang_EvalResult_getAsStr>('clang_EvalResult_getAsStr');
+ return _clang_EvalResult_getAsStr(
+ E,
+ );
+ }
+
+ _dart_clang_EvalResult_getAsStr _clang_EvalResult_getAsStr;
+
+ /// Disposes the created Eval memory.
+ void clang_EvalResult_dispose(
+ ffi.Pointer<ffi.Void> E,
+ ) {
+ _clang_EvalResult_dispose ??= _dylib.lookupFunction<
+ _c_clang_EvalResult_dispose,
+ _dart_clang_EvalResult_dispose>('clang_EvalResult_dispose');
+ return _clang_EvalResult_dispose(
+ E,
+ );
+ }
+
+ _dart_clang_EvalResult_dispose _clang_EvalResult_dispose;
+
ffi.Pointer<ffi.Int8> clang_getCString_wrap(
ffi.Pointer<CXString> string,
) {
@@ -612,6 +703,76 @@
}
_dart_clang_getArrayElementType_wrap _clang_getArrayElementType_wrap;
+
+ int clang_Cursor_isMacroFunctionLike_wrap(
+ ffi.Pointer<CXCursor> cursor,
+ ) {
+ _clang_Cursor_isMacroFunctionLike_wrap ??= _dylib.lookupFunction<
+ _c_clang_Cursor_isMacroFunctionLike_wrap,
+ _dart_clang_Cursor_isMacroFunctionLike_wrap>(
+ 'clang_Cursor_isMacroFunctionLike_wrap');
+ return _clang_Cursor_isMacroFunctionLike_wrap(
+ cursor,
+ );
+ }
+
+ _dart_clang_Cursor_isMacroFunctionLike_wrap
+ _clang_Cursor_isMacroFunctionLike_wrap;
+
+ int clang_Cursor_isMacroBuiltin_wrap(
+ ffi.Pointer<CXCursor> cursor,
+ ) {
+ _clang_Cursor_isMacroBuiltin_wrap ??= _dylib.lookupFunction<
+ _c_clang_Cursor_isMacroBuiltin_wrap,
+ _dart_clang_Cursor_isMacroBuiltin_wrap>(
+ 'clang_Cursor_isMacroBuiltin_wrap');
+ return _clang_Cursor_isMacroBuiltin_wrap(
+ cursor,
+ );
+ }
+
+ _dart_clang_Cursor_isMacroBuiltin_wrap _clang_Cursor_isMacroBuiltin_wrap;
+
+ ffi.Pointer<ffi.Void> clang_Cursor_Evaluate_wrap(
+ ffi.Pointer<CXCursor> cursor,
+ ) {
+ _clang_Cursor_Evaluate_wrap ??= _dylib.lookupFunction<
+ _c_clang_Cursor_Evaluate_wrap,
+ _dart_clang_Cursor_Evaluate_wrap>('clang_Cursor_Evaluate_wrap');
+ return _clang_Cursor_Evaluate_wrap(
+ cursor,
+ );
+ }
+
+ _dart_clang_Cursor_Evaluate_wrap _clang_Cursor_Evaluate_wrap;
+
+ int clang_Cursor_isAnonymous_wrap(
+ ffi.Pointer<CXCursor> cursor,
+ ) {
+ _clang_Cursor_isAnonymous_wrap ??= _dylib.lookupFunction<
+ _c_clang_Cursor_isAnonymous_wrap,
+ _dart_clang_Cursor_isAnonymous_wrap>('clang_Cursor_isAnonymous_wrap');
+ return _clang_Cursor_isAnonymous_wrap(
+ cursor,
+ );
+ }
+
+ _dart_clang_Cursor_isAnonymous_wrap _clang_Cursor_isAnonymous_wrap;
+
+ int clang_Cursor_isAnonymousRecordDecl_wrap(
+ ffi.Pointer<CXCursor> cursor,
+ ) {
+ _clang_Cursor_isAnonymousRecordDecl_wrap ??= _dylib.lookupFunction<
+ _c_clang_Cursor_isAnonymousRecordDecl_wrap,
+ _dart_clang_Cursor_isAnonymousRecordDecl_wrap>(
+ 'clang_Cursor_isAnonymousRecordDecl_wrap');
+ return _clang_Cursor_isAnonymousRecordDecl_wrap(
+ cursor,
+ );
+ }
+
+ _dart_clang_Cursor_isAnonymousRecordDecl_wrap
+ _clang_Cursor_isAnonymousRecordDecl_wrap;
}
/// A character string.
@@ -2012,6 +2173,24 @@
static const int CXChildVisit_Recurse = 2;
}
+abstract class CXEvalResultKind {
+ static const int CXEval_Int = 1;
+ static const int CXEval_Float = 2;
+ static const int CXEval_ObjCStrLiteral = 3;
+ static const int CXEval_StrLiteral = 4;
+ static const int CXEval_CFStr = 5;
+ static const int CXEval_Other = 6;
+ static const int CXEval_UnExposed = 0;
+}
+
+const int CINDEX_VERSION_MAJOR = 0;
+
+const int CINDEX_VERSION_MINOR = 59;
+
+const int CINDEX_VERSION = 59;
+
+const String CINDEX_VERSION_STRING = '0.59';
+
typedef _c_clang_createIndex = ffi.Pointer<ffi.Void> Function(
ffi.Int32 excludeDeclarationsFromPCH,
ffi.Int32 displayDiagnostics,
@@ -2086,6 +2265,54 @@
ffi.Pointer<CXTranslationUnitImpl> arg0,
);
+typedef _c_clang_EvalResult_getKind = ffi.Int32 Function(
+ ffi.Pointer<ffi.Void> E,
+);
+
+typedef _dart_clang_EvalResult_getKind = int Function(
+ ffi.Pointer<ffi.Void> E,
+);
+
+typedef _c_clang_EvalResult_getAsInt = ffi.Int32 Function(
+ ffi.Pointer<ffi.Void> E,
+);
+
+typedef _dart_clang_EvalResult_getAsInt = int Function(
+ ffi.Pointer<ffi.Void> E,
+);
+
+typedef _c_clang_EvalResult_getAsLongLong = ffi.Int64 Function(
+ ffi.Pointer<ffi.Void> E,
+);
+
+typedef _dart_clang_EvalResult_getAsLongLong = int Function(
+ ffi.Pointer<ffi.Void> E,
+);
+
+typedef _c_clang_EvalResult_getAsDouble = ffi.Double Function(
+ ffi.Pointer<ffi.Void> E,
+);
+
+typedef _dart_clang_EvalResult_getAsDouble = double Function(
+ ffi.Pointer<ffi.Void> E,
+);
+
+typedef _c_clang_EvalResult_getAsStr = ffi.Pointer<ffi.Int8> Function(
+ ffi.Pointer<ffi.Void> E,
+);
+
+typedef _dart_clang_EvalResult_getAsStr = ffi.Pointer<ffi.Int8> Function(
+ ffi.Pointer<ffi.Void> E,
+);
+
+typedef _c_clang_EvalResult_dispose = ffi.Void Function(
+ ffi.Pointer<ffi.Void> E,
+);
+
+typedef _dart_clang_EvalResult_dispose = void Function(
+ ffi.Pointer<ffi.Void> E,
+);
+
typedef _c_clang_getCString_wrap = ffi.Pointer<ffi.Int8> Function(
ffi.Pointer<CXString> string,
);
@@ -2369,3 +2596,43 @@
typedef _dart_clang_getArrayElementType_wrap = ffi.Pointer<CXType> Function(
ffi.Pointer<CXType> cxtype,
);
+
+typedef _c_clang_Cursor_isMacroFunctionLike_wrap = ffi.Uint32 Function(
+ ffi.Pointer<CXCursor> cursor,
+);
+
+typedef _dart_clang_Cursor_isMacroFunctionLike_wrap = int Function(
+ ffi.Pointer<CXCursor> cursor,
+);
+
+typedef _c_clang_Cursor_isMacroBuiltin_wrap = ffi.Uint32 Function(
+ ffi.Pointer<CXCursor> cursor,
+);
+
+typedef _dart_clang_Cursor_isMacroBuiltin_wrap = int Function(
+ ffi.Pointer<CXCursor> cursor,
+);
+
+typedef _c_clang_Cursor_Evaluate_wrap = ffi.Pointer<ffi.Void> Function(
+ ffi.Pointer<CXCursor> cursor,
+);
+
+typedef _dart_clang_Cursor_Evaluate_wrap = ffi.Pointer<ffi.Void> Function(
+ ffi.Pointer<CXCursor> cursor,
+);
+
+typedef _c_clang_Cursor_isAnonymous_wrap = ffi.Uint32 Function(
+ ffi.Pointer<CXCursor> cursor,
+);
+
+typedef _dart_clang_Cursor_isAnonymous_wrap = int Function(
+ ffi.Pointer<CXCursor> cursor,
+);
+
+typedef _c_clang_Cursor_isAnonymousRecordDecl_wrap = ffi.Uint32 Function(
+ ffi.Pointer<CXCursor> cursor,
+);
+
+typedef _dart_clang_Cursor_isAnonymousRecordDecl_wrap = int Function(
+ ffi.Pointer<CXCursor> cursor,
+);
diff --git a/lib/src/header_parser/includer.dart b/lib/src/header_parser/includer.dart
index f0ab13c..b00fa4f 100644
--- a/lib/src/header_parser/includer.dart
+++ b/lib/src/header_parser/includer.dart
@@ -13,6 +13,7 @@
Map<String, Struc> _structs = {};
Map<String, Func> _functions = {};
Map<String, EnumClass> _enumClass = {};
+Map<String, String> _macros = {};
bool shouldIncludeStruct(String name) {
if (_structs.containsKey(name) || name == '') {
@@ -47,9 +48,24 @@
}
}
+bool shouldIncludeMacro(String name) {
+ if (_macros.containsKey(name) || name == '') {
+ return false;
+ } else if (config.macroDecl == null || config.macroDecl.shouldInclude(name)) {
+ return true;
+ } else {
+ return false;
+ }
+}
+
/// True if a cursor should be included based on header-filter, use for root
/// declarations.
bool shouldIncludeRootCursor(String sourceFile) {
+ // Handle null in case of system headers or macros.
+ if (sourceFile == null) {
+ return false;
+ }
+
final name = p.basename(sourceFile);
if (config.headerFilter.excludedInclusionHeaders.contains(name)) {
@@ -103,3 +119,15 @@
EnumClass getSeenEnumClass(String originalName) {
return _enumClass[originalName];
}
+
+bool isSeenMacro(String originalName) {
+ return _macros.containsKey(originalName);
+}
+
+void addMacroToSeen(String originalName, String macro) {
+ _macros[originalName] = macro;
+}
+
+String getSeenMacro(String originalName) {
+ return _macros[originalName];
+}
diff --git a/lib/src/header_parser/parser.dart b/lib/src/header_parser/parser.dart
index bb171b3..6730d22 100644
--- a/lib/src/header_parser/parser.dart
+++ b/lib/src/header_parser/parser.dart
@@ -7,8 +7,10 @@
import 'package:ffi/ffi.dart';
import 'package:ffigen/src/code_generator.dart';
import 'package:ffigen/src/config_provider.dart';
+import 'package:ffigen/src/header_parser/sub_parsers/macro_parser.dart';
import 'package:ffigen/src/config_provider/config_types.dart';
import 'package:ffigen/src/find_resource.dart';
+import 'package:ffigen/src/header_parser/sub_parsers/unnamed_enumdecl_parser.dart';
import 'package:ffigen/src/header_parser/translation_unit_parser.dart';
import 'package:ffigen/src/strings.dart' as strings;
import 'package:logging/logging.dart';
@@ -96,7 +98,9 @@
cmdLen,
nullptr,
0,
- clang_types.CXTranslationUnit_Flags.CXTranslationUnit_SkipFunctionBodies,
+ clang_types.CXTranslationUnit_Flags.CXTranslationUnit_SkipFunctionBodies |
+ clang_types.CXTranslationUnit_Flags
+ .CXTranslationUnit_DetailedPreprocessingRecord,
);
if (tu == nullptr) {
@@ -116,6 +120,12 @@
clang.clang_disposeTranslationUnit(tu);
}
+ // Add all saved unnamed enums.
+ bindings.addAll(getSavedUnNamedEnums());
+
+ // Parse all saved macros.
+ bindings.addAll(parseSavedMacros());
+
if (config.compilerOpts != null) {
clangCmdArgs.dispose(config.compilerOpts.length);
}
diff --git a/lib/src/header_parser/sub_parsers/enumdecl_parser.dart b/lib/src/header_parser/sub_parsers/enumdecl_parser.dart
index 8cba1c9..293fa22 100644
--- a/lib/src/header_parser/sub_parsers/enumdecl_parser.dart
+++ b/lib/src/header_parser/sub_parsers/enumdecl_parser.dart
@@ -6,6 +6,7 @@
import 'package:ffigen/src/code_generator.dart';
import 'package:ffigen/src/header_parser/data.dart';
+import 'package:ffigen/src/header_parser/sub_parsers/unnamed_enumdecl_parser.dart';
import 'package:logging/logging.dart';
import '../clang_bindings/clang_bindings.dart' as clang_types;
@@ -31,10 +32,16 @@
String name,
}) {
_stack.push(_ParsedEnum());
-
final enumName = name ?? cursor.spelling();
if (enumName == '') {
- _logger.finest('unnamed enum declaration');
+ // Save this unnamed enum if it is anonymous (therefore not in a typedef).
+ if (config.unnamedEnums &&
+ clang.clang_Cursor_isAnonymous_wrap(cursor) != 0) {
+ _logger.fine('Saving anonymous enum.');
+ saveUnNamedEnum(cursor);
+ } else {
+ _logger.fine('Unnamed enum inside a typedef.');
+ }
} else if (shouldIncludeEnumClass(enumName) && !isSeenEnumClass(enumName)) {
_logger.fine('++++ Adding Enum: ${cursor.completeStringRepr()}');
_stack.top.enumClass = EnumClass(
diff --git a/lib/src/header_parser/sub_parsers/macro_parser.dart b/lib/src/header_parser/sub_parsers/macro_parser.dart
new file mode 100644
index 0000000..4da1b04
--- /dev/null
+++ b/lib/src/header_parser/sub_parsers/macro_parser.dart
@@ -0,0 +1,238 @@
+// Copyright (c) 2020, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'dart:ffi';
+import 'dart:io';
+
+import 'package:path/path.dart' as p;
+import 'package:ffi/ffi.dart';
+import 'package:ffigen/src/code_generator.dart';
+import 'package:ffigen/src/header_parser/data.dart';
+import 'package:ffigen/src/header_parser/includer.dart';
+import 'package:logging/logging.dart';
+
+import '../clang_bindings/clang_bindings.dart' as clang_types;
+import '../data.dart';
+import '../utils.dart';
+
+var _logger = Logger('ffigen.header_parser.macro_parser');
+
+/// Saved macros, Key: prefixedName, Value originalName.
+final _savedMacros = <String, String>{};
+
+/// Adds a macro definition to be parsed later.
+void saveMacroDefinition(Pointer<clang_types.CXCursor> cursor) {
+ final originalMacroName = cursor.spelling();
+ if (shouldIncludeMacro(originalMacroName) &&
+ !isSeenMacro(originalMacroName) &&
+ clang.clang_Cursor_isMacroBuiltin_wrap(cursor) == 0 &&
+ clang.clang_Cursor_isMacroFunctionLike_wrap(cursor) == 0) {
+ // Parse macro only if it's not builtin or function-like.
+ _logger.fine(
+ "++++ Saved Macro '$originalMacroName' for later : ${cursor.completeStringRepr()}");
+ final prefixedName = config.macroDecl.getPrefixedName(originalMacroName);
+ addMacroToSeen(originalMacroName, prefixedName);
+ _saveMacro(prefixedName, originalMacroName);
+ }
+}
+
+/// Saves a macro to be parsed later.
+///
+/// Macros are parsed later in [parseSavedMacros()].
+void _saveMacro(String name, String originalName) {
+ _savedMacros[name] = originalName;
+}
+
+List<Constant> _bindings;
+
+/// Macros cannot be parsed directly, so we create a new `.hpp` file in which
+/// they are assigned to a variable after which their value can be determined
+/// by evaluating the value of the variable.
+List<Constant> parseSavedMacros() {
+ _bindings = [];
+
+ if (_savedMacros.keys.isEmpty) {
+ return _bindings;
+ }
+
+ // Create a file for parsing macros;
+ final file = createFileForMacros();
+
+ final index = clang.clang_createIndex(0, 0);
+ Pointer<Pointer<Utf8>> clangCmdArgs = nullptr;
+ var cmdLen = 0;
+ if (config.compilerOpts != null) {
+ clangCmdArgs = createDynamicStringArray(config.compilerOpts);
+ cmdLen = config.compilerOpts.length;
+ }
+ final tu = clang.clang_parseTranslationUnit(
+ index,
+ Utf8.toUtf8(file.path).cast(),
+ clangCmdArgs.cast(),
+ cmdLen,
+ nullptr,
+ 0,
+ clang_types.CXTranslationUnit_Flags.CXTranslationUnit_KeepGoing,
+ );
+
+ if (tu == nullptr) {
+ _logger.severe('Unable to parse Macros.');
+ } else {
+ final rootCursor = clang.clang_getTranslationUnitCursor_wrap(tu);
+
+ final resultCode = clang.clang_visitChildren_wrap(
+ rootCursor,
+ Pointer.fromFunction(_macroVariablevisitor,
+ clang_types.CXChildVisitResult.CXChildVisit_Break),
+ uid,
+ );
+
+ visitChildrenResultChecker(resultCode);
+ rootCursor.dispose();
+ }
+
+ clang.clang_disposeTranslationUnit(tu);
+ clang.clang_disposeIndex(index);
+ // Delete the temp file created for macros.
+ file.deleteSync();
+
+ return _bindings;
+}
+
+/// Child visitor invoked on translationUnitCursor for parsing macroVariables.
+int _macroVariablevisitor(Pointer<clang_types.CXCursor> cursor,
+ Pointer<clang_types.CXCursor> parent, Pointer<Void> clientData) {
+ Constant constant;
+ try {
+ if (isFromGeneratedFile(cursor) &&
+ _macroVarNames.contains(cursor.spelling()) &&
+ cursor.kind() == clang_types.CXCursorKind.CXCursor_VarDecl) {
+ final e = clang.clang_Cursor_Evaluate_wrap(cursor);
+ final k = clang.clang_EvalResult_getKind(e);
+ _logger.fine('macroVariablevisitor: ${cursor.completeStringRepr()}');
+
+ /// Get macro name, the variable name starts with '<macro-name>_'.
+ final macroName = MacroVariableString.decode(cursor.spelling());
+ switch (k) {
+ case clang_types.CXEvalResultKind.CXEval_Int:
+ constant = Constant(
+ originalName: _savedMacros[macroName],
+ name: macroName,
+ rawType: 'int',
+ rawValue: clang.clang_EvalResult_getAsLongLong(e).toString(),
+ );
+ break;
+ case clang_types.CXEvalResultKind.CXEval_Float:
+ constant = Constant(
+ originalName: _savedMacros[macroName],
+ name: macroName,
+ rawType: 'double',
+ rawValue: clang.clang_EvalResult_getAsDouble(e).toString(),
+ );
+ break;
+ case clang_types.CXEvalResultKind.CXEval_StrLiteral:
+ constant = Constant(
+ originalName: _savedMacros[macroName],
+ name: macroName,
+ rawType: 'String',
+ rawValue:
+ "'${Utf8.fromUtf8(clang.clang_EvalResult_getAsStr(e).cast())}'",
+ );
+ break;
+ }
+ clang.clang_EvalResult_dispose(e);
+
+ if (constant != null) {
+ _bindings.add(constant);
+ }
+ }
+ cursor.dispose();
+ parent.dispose();
+ } catch (e, s) {
+ _logger.severe(e);
+ _logger.severe(s);
+ rethrow;
+ }
+ return clang_types.CXChildVisitResult.CXChildVisit_Continue;
+}
+
+/// Returns true if cursor is from generated file.
+bool isFromGeneratedFile(Pointer<clang_types.CXCursor> cursor) {
+ final s = cursor.sourceFileName();
+ if (s == null || s.isEmpty) {
+ return false;
+ } else {
+ return p.basename(s) == _generatedFileBaseName;
+ }
+}
+
+/// Base name of generated file.
+String _generatedFileBaseName;
+
+/// Generated macro variable names.
+///
+/// Used to determine if macro should be included in bindings or not.
+Set<String> _macroVarNames = {};
+
+/// Creates a temporary file for parsing macros in current directory.
+File createFileForMacros() {
+ final fileNameBase = 'temp_for_macros';
+ final fileExt = 'hpp';
+
+ // Find a filename which doesn't already exist.
+ var file = File('$fileNameBase.$fileExt');
+ var i = 0;
+ while (file.existsSync()) {
+ i++;
+ file = File('${fileNameBase.split('.')[0]}_$i.$fileExt');
+ }
+
+ // Create file.
+ file.createSync();
+ // Save generted name.
+ _generatedFileBaseName = p.basename(file.path);
+
+ // Write file contents.
+ final sb = StringBuffer();
+ for (final h in config.headers) {
+ sb.writeln('#include "$h"');
+ }
+
+ _macroVarNames = {};
+ for (final prefixedMacroName in _savedMacros.keys) {
+ // Write macro.
+ final macroVarName = MacroVariableString.encode(prefixedMacroName);
+ sb.writeln('auto ${macroVarName} = ${_savedMacros[prefixedMacroName]};');
+ // Add to _macroVarNames.
+ _macroVarNames.add(macroVarName);
+ }
+ final macroFileContent = sb.toString();
+ // Log this generated file for debugging purpose.
+ // We use the finest log because this file may be very big.
+ _logger.finest('=====FILE FOR MACROS====');
+ _logger.finest(macroFileContent);
+ _logger.finest('========================');
+
+ file.writeAsStringSync(macroFileContent);
+ return file;
+}
+
+/// Deals with encoding/decoding name of the variable generated for a Macro.
+class MacroVariableString {
+ static String encode(String s) {
+ return '_${s.length}_${s}_generated_macro_variable';
+ }
+
+ static String decode(String s) {
+ // Remove underscore.
+ s = s.substring(1);
+ final intReg = RegExp('[0-9]+');
+ final lengthEnd = intReg.matchAsPrefix(s).end;
+ final len = int.parse(s.substring(0, lengthEnd));
+
+ // Name starts after an unerscore.
+ final nameStart = lengthEnd + 1;
+ return s.substring(nameStart, nameStart + len);
+ }
+}
diff --git a/lib/src/header_parser/sub_parsers/unnamed_enumdecl_parser.dart b/lib/src/header_parser/sub_parsers/unnamed_enumdecl_parser.dart
new file mode 100644
index 0000000..8f8487b
--- /dev/null
+++ b/lib/src/header_parser/sub_parsers/unnamed_enumdecl_parser.dart
@@ -0,0 +1,68 @@
+// Copyright (c) 2020, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'dart:ffi';
+
+import 'package:ffigen/src/code_generator.dart';
+import 'package:ffigen/src/header_parser/data.dart';
+import 'package:logging/logging.dart';
+
+import '../clang_bindings/clang_bindings.dart' as clang_types;
+import '../data.dart';
+import '../utils.dart';
+
+var _logger = Logger('ffigen.header_parser.unnamed_enumdecl_parser');
+
+List<Constant> _constants = [];
+
+List<Constant> getSavedUnNamedEnums() => _constants;
+
+/// Saves unnamed enums.
+void saveUnNamedEnum(Pointer<clang_types.CXCursor> cursor) {
+ final resultCode = clang.clang_visitChildren_wrap(
+ cursor,
+ Pointer.fromFunction(_unnamedenumCursorVisitor,
+ clang_types.CXChildVisitResult.CXChildVisit_Break),
+ uid,
+ );
+
+ visitChildrenResultChecker(resultCode);
+}
+
+/// Visitor for a enum cursor [clang.CXCursorKind.CXCursor_EnumDecl].
+///
+/// Invoked on every enum directly under rootCursor.
+/// Used for for extracting enum values.
+int _unnamedenumCursorVisitor(Pointer<clang_types.CXCursor> cursor,
+ Pointer<clang_types.CXCursor> parent, Pointer<Void> clientData) {
+ try {
+ _logger
+ .finest(' unnamedenumCursorVisitor: ${cursor.completeStringRepr()}');
+ switch (clang.clang_getCursorKind_wrap(cursor)) {
+ case clang_types.CXCursorKind.CXCursor_EnumConstantDecl:
+ _addUnNamedEnumConstant(cursor);
+ break;
+ default:
+ _logger.severe('Invalid enum constant.');
+ }
+ cursor.dispose();
+ parent.dispose();
+ } catch (e, s) {
+ _logger.severe(e);
+ _logger.severe(s);
+ rethrow;
+ }
+ return clang_types.CXChildVisitResult.CXChildVisit_Continue;
+}
+
+/// Adds the parameter to func in [functiondecl_parser.dart].
+void _addUnNamedEnumConstant(Pointer<clang_types.CXCursor> cursor) {
+ _constants.add(
+ Constant(
+ name: cursor.spelling(),
+ rawType: 'int',
+ rawValue: clang.clang_getEnumConstantDeclValue_wrap(cursor).toString(),
+ ),
+ );
+}
diff --git a/lib/src/header_parser/translation_unit_parser.dart b/lib/src/header_parser/translation_unit_parser.dart
index 987254e..4723fe4 100644
--- a/lib/src/header_parser/translation_unit_parser.dart
+++ b/lib/src/header_parser/translation_unit_parser.dart
@@ -5,6 +5,7 @@
import 'dart:ffi';
import 'package:ffigen/src/code_generator.dart';
+import 'package:ffigen/src/header_parser/sub_parsers/macro_parser.dart';
import 'package:logging/logging.dart';
import 'clang_bindings/clang_bindings.dart' as clang_types;
@@ -55,6 +56,9 @@
case clang_types.CXCursorKind.CXCursor_EnumDecl:
addToBindings(parseEnumDeclaration(cursor));
break;
+ case clang_types.CXCursorKind.CXCursor_MacroDefinition:
+ saveMacroDefinition(cursor);
+ break;
default:
_logger.finer('rootCursorVisitor: CursorKind not implemented');
}
diff --git a/lib/src/strings.dart b/lib/src/strings.dart
index 963f84c..cfa1f5d 100644
--- a/lib/src/strings.dart
+++ b/lib/src/strings.dart
@@ -7,7 +7,7 @@
as clang;
// This version must be updated whenever we update the libclang wrapper.
-const dylibVersion = 'v1';
+const dylibVersion = 'v2';
/// Name of the dynamic library file according to current platform.
String get dylibFileName {
@@ -36,6 +36,7 @@
const functions = 'functions';
const structs = 'structs';
const enums = 'enums';
+const macros = 'macros';
// Sub-fields of Declarations.
const include = 'include';
@@ -82,6 +83,7 @@
const useSupportedTypedefs = 'use-supported-typedefs';
const warnWhenRemoving = 'warn-when-removing';
const arrayWorkaround = 'array-workaround';
+const unnamedEnums = 'unnamed-enums';
const comments = 'comments';
// Sub-fields of comments
diff --git a/pubspec.yaml b/pubspec.yaml
index e4f34cf..fb8ad12 100644
--- a/pubspec.yaml
+++ b/pubspec.yaml
@@ -3,7 +3,7 @@
# BSD-style license that can be found in the LICENSE file.
name: ffigen
-version: 0.1.4
+version: 0.1.5
homepage: https://github.com/dart-lang/ffigen
description: Experimental generator for FFI bindings, using LibClang to parse C/C++ header files.
diff --git a/test/code_generator_test.dart b/test/code_generator_test.dart
index a67f41e..47c0ac7 100644
--- a/test/code_generator_test.dart
+++ b/test/code_generator_test.dart
@@ -471,16 +471,12 @@
bindings: [
Constant(
name: 'test1',
- type: Type.nativeType(
- SupportedNativeType.Int32,
- ),
+ rawType: 'int',
rawValue: '20',
),
Constant(
name: 'test2',
- type: Type.nativeType(
- SupportedNativeType.Float,
- ),
+ rawType: 'double',
rawValue: '20.0',
),
],
diff --git a/test/collision_tests/decl_decl_collision_test.dart b/test/collision_tests/decl_decl_collision_test.dart
index e0ebb25..554795e 100644
--- a/test/collision_tests/decl_decl_collision_test.dart
+++ b/test/collision_tests/decl_decl_collision_test.dart
@@ -24,6 +24,18 @@
Func(
name: 'testFunc',
returnType: Type.nativeType(SupportedNativeType.Void)),
+ Constant(
+ originalName: 'Test_Macro',
+ name: 'Test_Macro',
+ rawType: 'int',
+ rawValue: '0',
+ ),
+ Constant(
+ originalName: 'Test_Macro',
+ name: 'Test_Macro',
+ rawType: 'int',
+ rawValue: '0',
+ ),
]);
final l2 = Library(name: 'Bindings', bindings: [
Struc(name: 'TestStruc'),
@@ -38,6 +50,18 @@
name: 'testFunc_1',
originalName: 'testFunc',
returnType: Type.nativeType(SupportedNativeType.Void)),
+ Constant(
+ originalName: 'Test_Macro',
+ name: 'Test_Macro',
+ rawType: 'int',
+ rawValue: '0',
+ ),
+ Constant(
+ originalName: 'Test_Macro',
+ name: 'Test_Macro_1',
+ rawType: 'int',
+ rawValue: '0',
+ ),
]);
expect(l1.generate(), l2.generate());
diff --git a/test/collision_tests/reserved_keyword_collision_test.dart b/test/collision_tests/reserved_keyword_collision_test.dart
index 964d7ea..b5b6931 100644
--- a/test/collision_tests/reserved_keyword_collision_test.dart
+++ b/test/collision_tests/reserved_keyword_collision_test.dart
@@ -40,6 +40,11 @@
),
],
returnType: Type.nativeType(SupportedNativeType.Void)),
+ Constant(
+ name: 'else',
+ rawType: 'int',
+ rawValue: '0',
+ ),
]);
final l2 = Library(name: 'Bindings', bindings: [
Struc(name: 'abstract_1'),
@@ -69,6 +74,11 @@
),
],
returnType: Type.nativeType(SupportedNativeType.Void)),
+ Constant(
+ name: 'else_1',
+ rawType: 'int',
+ rawValue: '0',
+ ),
]);
expect(l1.generate(), l2.generate());
});
diff --git a/test/header_parser_tests/macros.h b/test/header_parser_tests/macros.h
new file mode 100644
index 0000000..b405db4
--- /dev/null
+++ b/test/header_parser_tests/macros.h
@@ -0,0 +1,16 @@
+#define TEST1 1.1
+#define TEST2 10
+#define TEST3 (TEST1 + TEST2)
+#define TEST4 "test"
+
+// The comma operator should actually return the last value (3),
+// when returned by a function. This value, however, when assigned to a variable
+// will not compile and so libclang tries to fix it and assigns the first
+// value (4) to the generated macro variable.
+#define TEST5 4, \
+ 2, \
+ 3
+#define TEST6 (1 == 1);
+#define TEST7(x, y) x *y
+
+#define TEST8 5,2,3
diff --git a/test/header_parser_tests/macros_test.dart b/test/header_parser_tests/macros_test.dart
new file mode 100644
index 0000000..b912f78
--- /dev/null
+++ b/test/header_parser_tests/macros_test.dart
@@ -0,0 +1,85 @@
+// Copyright (c) 2020, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'package:ffigen/src/code_generator.dart';
+import 'package:ffigen/src/header_parser.dart' as parser;
+import 'package:ffigen/src/config_provider.dart';
+import 'package:logging/logging.dart';
+import 'package:test/test.dart';
+import 'package:yaml/yaml.dart' as yaml;
+import 'package:ffigen/src/strings.dart' as strings;
+
+import '../test_utils.dart';
+
+Library actual, expected;
+
+void main() {
+ group('macros_test', () {
+ setUpAll(() {
+ logWarnings(Level.WARNING);
+ expected = expectedLibrary();
+ actual = parser.parse(
+ Config.fromYaml(yaml.loadYaml('''
+${strings.name}: 'NativeLibrary'
+${strings.description}: 'Macros Test'
+${strings.output}: 'unused'
+${strings.headers}:
+ - 'test/header_parser_tests/macros.h'
+${strings.headerFilter}:
+ ${strings.include}:
+ - 'macros.h'
+ ''') as yaml.YamlMap),
+ );
+ });
+ test('Total bindings count', () {
+ expect(actual.bindings.length, expected.bindings.length);
+ });
+
+ test('TEST1', () {
+ expect(actual.getBindingAsString('TEST1'),
+ expected.getBindingAsString('TEST1'));
+ });
+ test('TEST2', () {
+ expect(actual.getBindingAsString('TEST2'),
+ expected.getBindingAsString('TEST2'));
+ });
+ test('TEST3', () {
+ expect(actual.getBindingAsString('TEST3'),
+ expected.getBindingAsString('TEST3'));
+ });
+
+ test('TEST4', () {
+ expect(actual.getBindingAsString('TEST4'),
+ expected.getBindingAsString('TEST4'));
+ });
+
+ test('TEST5', () {
+ expect(actual.getBindingAsString('TEST5'),
+ expected.getBindingAsString('TEST5'));
+ });
+ test('TEST6', () {
+ expect(actual.getBindingAsString('TEST6'),
+ expected.getBindingAsString('TEST6'));
+ });
+ test('TEST8', () {
+ expect(actual.getBindingAsString('TEST8'),
+ expected.getBindingAsString('TEST8'));
+ });
+ });
+}
+
+Library expectedLibrary() {
+ return Library(
+ name: 'NativeLibrary',
+ bindings: [
+ Constant(name: 'TEST1', rawType: 'double', rawValue: '1.1'),
+ Constant(name: 'TEST2', rawType: 'int', rawValue: '10'),
+ Constant(name: 'TEST3', rawType: 'double', rawValue: '11.1'),
+ Constant(name: 'TEST4', rawType: 'String', rawValue: "'test'"),
+ Constant(name: 'TEST5', rawType: 'int', rawValue: '4'),
+ Constant(name: 'TEST6', rawType: 'int', rawValue: '1'),
+ Constant(name: 'TEST8', rawType: 'int', rawValue: '5'),
+ ],
+ );
+}
diff --git a/test/header_parser_tests/unnamed_enums.h b/test/header_parser_tests/unnamed_enums.h
new file mode 100644
index 0000000..ecb4a85
--- /dev/null
+++ b/test/header_parser_tests/unnamed_enums.h
@@ -0,0 +1,13 @@
+// Only this should be parsed.
+enum{
+ A=1,
+ B=2,
+ C=3
+};
+
+// Shouldn't be parsed.
+typedef enum{
+ E,
+ F,
+ G
+} Named;
diff --git a/test/header_parser_tests/unnamed_enums_test.dart b/test/header_parser_tests/unnamed_enums_test.dart
new file mode 100644
index 0000000..7c07602
--- /dev/null
+++ b/test/header_parser_tests/unnamed_enums_test.dart
@@ -0,0 +1,81 @@
+// Copyright (c) 2020, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'package:ffigen/src/code_generator.dart';
+import 'package:ffigen/src/header_parser.dart' as parser;
+import 'package:ffigen/src/config_provider.dart';
+import 'package:test/test.dart';
+import 'package:yaml/yaml.dart' as yaml;
+import 'package:ffigen/src/strings.dart' as strings;
+
+import '../test_utils.dart';
+
+Library actual, expected;
+
+void main() {
+ group('unnamed_enums_test', () {
+ setUpAll(() {
+ logWarnings();
+ expected = expectedLibrary();
+ actual = parser.parse(
+ Config.fromYaml(yaml.loadYaml('''
+${strings.name}: 'NativeLibrary'
+${strings.description}: 'Unnamed Enums Test'
+${strings.output}: 'unused'
+${strings.headers}:
+ - 'test/header_parser_tests/unnamed_enums.h'
+${strings.headerFilter}:
+ ${strings.include}:
+ - 'unnamed_enums.h'
+${strings.enums}:
+ ${strings.exclude}:
+ ${strings.names}:
+ - Named
+ ''') as yaml.YamlMap),
+ );
+ });
+
+ test('Total bindings count', () {
+ expect(actual.bindings.length, expected.bindings.length);
+ });
+
+ test('Parse unnamed enum Values', () {
+ expect(actual.getBindingAsString('A'), expected.getBindingAsString('A'));
+ expect(actual.getBindingAsString('B'), expected.getBindingAsString('B'));
+ expect(actual.getBindingAsString('C'), expected.getBindingAsString('C'));
+ });
+
+ test('Ignore unnamed enums inside typedefs', () {
+ expect(() => actual.getBindingAsString('E'),
+ throwsA(TypeMatcher<NotFoundException>()));
+ expect(() => actual.getBindingAsString('F'),
+ throwsA(TypeMatcher<NotFoundException>()));
+ expect(() => actual.getBindingAsString('G'),
+ throwsA(TypeMatcher<NotFoundException>()));
+ });
+ });
+}
+
+Library expectedLibrary() {
+ return Library(
+ name: 'Bindings',
+ bindings: [
+ Constant(
+ name: 'A',
+ rawType: 'int',
+ rawValue: '1',
+ ),
+ Constant(
+ name: 'B',
+ rawType: 'int',
+ rawValue: '2',
+ ),
+ Constant(
+ name: 'C',
+ rawType: 'int',
+ rawValue: '3',
+ ),
+ ],
+ );
+}
diff --git a/test/large_integration_tests/_expected_cjson_bindings.dart b/test/large_integration_tests/_expected_cjson_bindings.dart
index e7766d2..7beb2ef 100644
--- a/test/large_integration_tests/_expected_cjson_bindings.dart
+++ b/test/large_integration_tests/_expected_cjson_bindings.dart
@@ -1063,6 +1063,38 @@
ffi.Pointer<ffi.NativeFunction<_typedefC_12>> free_fn;
}
+const int CJSON_VERSION_MAJOR = 1;
+
+const int CJSON_VERSION_MINOR = 7;
+
+const int CJSON_VERSION_PATCH = 12;
+
+const int cJSON_Invalid = 0;
+
+const int cJSON_False = 1;
+
+const int cJSON_True = 2;
+
+const int cJSON_NULL = 4;
+
+const int cJSON_Number = 8;
+
+const int cJSON_String = 16;
+
+const int cJSON_Array = 32;
+
+const int cJSON_Object = 64;
+
+const int cJSON_Raw = 128;
+
+const int cJSON_IsReference = 256;
+
+const int cJSON_StringIsConst = 512;
+
+const int CJSON_NESTING_LIMIT = 1000;
+
+const double CJSON_DOUBLE_PRECISION = 1e-16;
+
typedef _c_cJSON_Version = ffi.Pointer<ffi.Int8> Function();
typedef _dart_cJSON_Version = ffi.Pointer<ffi.Int8> Function();
diff --git a/test/large_integration_tests/_expected_libclang_bindings.dart b/test/large_integration_tests/_expected_libclang_bindings.dart
index c6642d8..f857457 100644
--- a/test/large_integration_tests/_expected_libclang_bindings.dart
+++ b/test/large_integration_tests/_expected_libclang_bindings.dart
@@ -4418,6 +4418,14 @@
static const int CXIndexOpt_SkipParsedBodiesInSession = 16;
}
+const int CINDEX_VERSION_MAJOR = 0;
+
+const int CINDEX_VERSION_MINOR = 59;
+
+const int CINDEX_VERSION = 59;
+
+const String CINDEX_VERSION_STRING = '0.59';
+
typedef _c_clang_disposeStringSet = ffi.Void Function(
ffi.Pointer<CXStringSet> set_1,
);
diff --git a/test/large_integration_tests/_expected_sqlite_bindings.dart b/test/large_integration_tests/_expected_sqlite_bindings.dart
index ba750ec..ad214b3 100644
--- a/test/large_integration_tests/_expected_sqlite_bindings.dart
+++ b/test/large_integration_tests/_expected_sqlite_bindings.dart
@@ -9856,6 +9856,887 @@
class fts5_api extends ffi.Struct {}
+const String SQLITE_VERSION = '3.32.3';
+
+const int SQLITE_VERSION_NUMBER = 3032003;
+
+const String SQLITE_SOURCE_ID =
+ '2020-06-18 14:00:33 7ebdfa80be8e8e73324b8d66b3460222eb74c7e9dfd655b48d6ca7e1933cc8fd';
+
+const int SQLITE_OK = 0;
+
+const int SQLITE_ERROR = 1;
+
+const int SQLITE_INTERNAL = 2;
+
+const int SQLITE_PERM = 3;
+
+const int SQLITE_ABORT = 4;
+
+const int SQLITE_BUSY = 5;
+
+const int SQLITE_LOCKED = 6;
+
+const int SQLITE_NOMEM = 7;
+
+const int SQLITE_READONLY = 8;
+
+const int SQLITE_INTERRUPT = 9;
+
+const int SQLITE_IOERR = 10;
+
+const int SQLITE_CORRUPT = 11;
+
+const int SQLITE_NOTFOUND = 12;
+
+const int SQLITE_FULL = 13;
+
+const int SQLITE_CANTOPEN = 14;
+
+const int SQLITE_PROTOCOL = 15;
+
+const int SQLITE_EMPTY = 16;
+
+const int SQLITE_SCHEMA = 17;
+
+const int SQLITE_TOOBIG = 18;
+
+const int SQLITE_CONSTRAINT = 19;
+
+const int SQLITE_MISMATCH = 20;
+
+const int SQLITE_MISUSE = 21;
+
+const int SQLITE_NOLFS = 22;
+
+const int SQLITE_AUTH = 23;
+
+const int SQLITE_FORMAT = 24;
+
+const int SQLITE_RANGE = 25;
+
+const int SQLITE_NOTADB = 26;
+
+const int SQLITE_NOTICE = 27;
+
+const int SQLITE_WARNING = 28;
+
+const int SQLITE_ROW = 100;
+
+const int SQLITE_DONE = 101;
+
+const int SQLITE_ERROR_MISSING_COLLSEQ = 257;
+
+const int SQLITE_ERROR_RETRY = 513;
+
+const int SQLITE_ERROR_SNAPSHOT = 769;
+
+const int SQLITE_IOERR_READ = 266;
+
+const int SQLITE_IOERR_SHORT_READ = 522;
+
+const int SQLITE_IOERR_WRITE = 778;
+
+const int SQLITE_IOERR_FSYNC = 1034;
+
+const int SQLITE_IOERR_DIR_FSYNC = 1290;
+
+const int SQLITE_IOERR_TRUNCATE = 1546;
+
+const int SQLITE_IOERR_FSTAT = 1802;
+
+const int SQLITE_IOERR_UNLOCK = 2058;
+
+const int SQLITE_IOERR_RDLOCK = 2314;
+
+const int SQLITE_IOERR_DELETE = 2570;
+
+const int SQLITE_IOERR_BLOCKED = 2826;
+
+const int SQLITE_IOERR_NOMEM = 3082;
+
+const int SQLITE_IOERR_ACCESS = 3338;
+
+const int SQLITE_IOERR_CHECKRESERVEDLOCK = 3594;
+
+const int SQLITE_IOERR_LOCK = 3850;
+
+const int SQLITE_IOERR_CLOSE = 4106;
+
+const int SQLITE_IOERR_DIR_CLOSE = 4362;
+
+const int SQLITE_IOERR_SHMOPEN = 4618;
+
+const int SQLITE_IOERR_SHMSIZE = 4874;
+
+const int SQLITE_IOERR_SHMLOCK = 5130;
+
+const int SQLITE_IOERR_SHMMAP = 5386;
+
+const int SQLITE_IOERR_SEEK = 5642;
+
+const int SQLITE_IOERR_DELETE_NOENT = 5898;
+
+const int SQLITE_IOERR_MMAP = 6154;
+
+const int SQLITE_IOERR_GETTEMPPATH = 6410;
+
+const int SQLITE_IOERR_CONVPATH = 6666;
+
+const int SQLITE_IOERR_VNODE = 6922;
+
+const int SQLITE_IOERR_AUTH = 7178;
+
+const int SQLITE_IOERR_BEGIN_ATOMIC = 7434;
+
+const int SQLITE_IOERR_COMMIT_ATOMIC = 7690;
+
+const int SQLITE_IOERR_ROLLBACK_ATOMIC = 7946;
+
+const int SQLITE_IOERR_DATA = 8202;
+
+const int SQLITE_LOCKED_SHAREDCACHE = 262;
+
+const int SQLITE_LOCKED_VTAB = 518;
+
+const int SQLITE_BUSY_RECOVERY = 261;
+
+const int SQLITE_BUSY_SNAPSHOT = 517;
+
+const int SQLITE_BUSY_TIMEOUT = 773;
+
+const int SQLITE_CANTOPEN_NOTEMPDIR = 270;
+
+const int SQLITE_CANTOPEN_ISDIR = 526;
+
+const int SQLITE_CANTOPEN_FULLPATH = 782;
+
+const int SQLITE_CANTOPEN_CONVPATH = 1038;
+
+const int SQLITE_CANTOPEN_DIRTYWAL = 1294;
+
+const int SQLITE_CANTOPEN_SYMLINK = 1550;
+
+const int SQLITE_CORRUPT_VTAB = 267;
+
+const int SQLITE_CORRUPT_SEQUENCE = 523;
+
+const int SQLITE_CORRUPT_INDEX = 779;
+
+const int SQLITE_READONLY_RECOVERY = 264;
+
+const int SQLITE_READONLY_CANTLOCK = 520;
+
+const int SQLITE_READONLY_ROLLBACK = 776;
+
+const int SQLITE_READONLY_DBMOVED = 1032;
+
+const int SQLITE_READONLY_CANTINIT = 1288;
+
+const int SQLITE_READONLY_DIRECTORY = 1544;
+
+const int SQLITE_ABORT_ROLLBACK = 516;
+
+const int SQLITE_CONSTRAINT_CHECK = 275;
+
+const int SQLITE_CONSTRAINT_COMMITHOOK = 531;
+
+const int SQLITE_CONSTRAINT_FOREIGNKEY = 787;
+
+const int SQLITE_CONSTRAINT_FUNCTION = 1043;
+
+const int SQLITE_CONSTRAINT_NOTNULL = 1299;
+
+const int SQLITE_CONSTRAINT_PRIMARYKEY = 1555;
+
+const int SQLITE_CONSTRAINT_TRIGGER = 1811;
+
+const int SQLITE_CONSTRAINT_UNIQUE = 2067;
+
+const int SQLITE_CONSTRAINT_VTAB = 2323;
+
+const int SQLITE_CONSTRAINT_ROWID = 2579;
+
+const int SQLITE_CONSTRAINT_PINNED = 2835;
+
+const int SQLITE_NOTICE_RECOVER_WAL = 283;
+
+const int SQLITE_NOTICE_RECOVER_ROLLBACK = 539;
+
+const int SQLITE_WARNING_AUTOINDEX = 284;
+
+const int SQLITE_AUTH_USER = 279;
+
+const int SQLITE_OK_LOAD_PERMANENTLY = 256;
+
+const int SQLITE_OK_SYMLINK = 512;
+
+const int SQLITE_OPEN_READONLY = 1;
+
+const int SQLITE_OPEN_READWRITE = 2;
+
+const int SQLITE_OPEN_CREATE = 4;
+
+const int SQLITE_OPEN_DELETEONCLOSE = 8;
+
+const int SQLITE_OPEN_EXCLUSIVE = 16;
+
+const int SQLITE_OPEN_AUTOPROXY = 32;
+
+const int SQLITE_OPEN_URI = 64;
+
+const int SQLITE_OPEN_MEMORY = 128;
+
+const int SQLITE_OPEN_MAIN_DB = 256;
+
+const int SQLITE_OPEN_TEMP_DB = 512;
+
+const int SQLITE_OPEN_TRANSIENT_DB = 1024;
+
+const int SQLITE_OPEN_MAIN_JOURNAL = 2048;
+
+const int SQLITE_OPEN_TEMP_JOURNAL = 4096;
+
+const int SQLITE_OPEN_SUBJOURNAL = 8192;
+
+const int SQLITE_OPEN_MASTER_JOURNAL = 16384;
+
+const int SQLITE_OPEN_NOMUTEX = 32768;
+
+const int SQLITE_OPEN_FULLMUTEX = 65536;
+
+const int SQLITE_OPEN_SHAREDCACHE = 131072;
+
+const int SQLITE_OPEN_PRIVATECACHE = 262144;
+
+const int SQLITE_OPEN_WAL = 524288;
+
+const int SQLITE_OPEN_NOFOLLOW = 16777216;
+
+const int SQLITE_IOCAP_ATOMIC = 1;
+
+const int SQLITE_IOCAP_ATOMIC512 = 2;
+
+const int SQLITE_IOCAP_ATOMIC1K = 4;
+
+const int SQLITE_IOCAP_ATOMIC2K = 8;
+
+const int SQLITE_IOCAP_ATOMIC4K = 16;
+
+const int SQLITE_IOCAP_ATOMIC8K = 32;
+
+const int SQLITE_IOCAP_ATOMIC16K = 64;
+
+const int SQLITE_IOCAP_ATOMIC32K = 128;
+
+const int SQLITE_IOCAP_ATOMIC64K = 256;
+
+const int SQLITE_IOCAP_SAFE_APPEND = 512;
+
+const int SQLITE_IOCAP_SEQUENTIAL = 1024;
+
+const int SQLITE_IOCAP_UNDELETABLE_WHEN_OPEN = 2048;
+
+const int SQLITE_IOCAP_POWERSAFE_OVERWRITE = 4096;
+
+const int SQLITE_IOCAP_IMMUTABLE = 8192;
+
+const int SQLITE_IOCAP_BATCH_ATOMIC = 16384;
+
+const int SQLITE_LOCK_NONE = 0;
+
+const int SQLITE_LOCK_SHARED = 1;
+
+const int SQLITE_LOCK_RESERVED = 2;
+
+const int SQLITE_LOCK_PENDING = 3;
+
+const int SQLITE_LOCK_EXCLUSIVE = 4;
+
+const int SQLITE_SYNC_NORMAL = 2;
+
+const int SQLITE_SYNC_FULL = 3;
+
+const int SQLITE_SYNC_DATAONLY = 16;
+
+const int SQLITE_FCNTL_LOCKSTATE = 1;
+
+const int SQLITE_FCNTL_GET_LOCKPROXYFILE = 2;
+
+const int SQLITE_FCNTL_SET_LOCKPROXYFILE = 3;
+
+const int SQLITE_FCNTL_LAST_ERRNO = 4;
+
+const int SQLITE_FCNTL_SIZE_HINT = 5;
+
+const int SQLITE_FCNTL_CHUNK_SIZE = 6;
+
+const int SQLITE_FCNTL_FILE_POINTER = 7;
+
+const int SQLITE_FCNTL_SYNC_OMITTED = 8;
+
+const int SQLITE_FCNTL_WIN32_AV_RETRY = 9;
+
+const int SQLITE_FCNTL_PERSIST_WAL = 10;
+
+const int SQLITE_FCNTL_OVERWRITE = 11;
+
+const int SQLITE_FCNTL_VFSNAME = 12;
+
+const int SQLITE_FCNTL_POWERSAFE_OVERWRITE = 13;
+
+const int SQLITE_FCNTL_PRAGMA = 14;
+
+const int SQLITE_FCNTL_BUSYHANDLER = 15;
+
+const int SQLITE_FCNTL_TEMPFILENAME = 16;
+
+const int SQLITE_FCNTL_MMAP_SIZE = 18;
+
+const int SQLITE_FCNTL_TRACE = 19;
+
+const int SQLITE_FCNTL_HAS_MOVED = 20;
+
+const int SQLITE_FCNTL_SYNC = 21;
+
+const int SQLITE_FCNTL_COMMIT_PHASETWO = 22;
+
+const int SQLITE_FCNTL_WIN32_SET_HANDLE = 23;
+
+const int SQLITE_FCNTL_WAL_BLOCK = 24;
+
+const int SQLITE_FCNTL_ZIPVFS = 25;
+
+const int SQLITE_FCNTL_RBU = 26;
+
+const int SQLITE_FCNTL_VFS_POINTER = 27;
+
+const int SQLITE_FCNTL_JOURNAL_POINTER = 28;
+
+const int SQLITE_FCNTL_WIN32_GET_HANDLE = 29;
+
+const int SQLITE_FCNTL_PDB = 30;
+
+const int SQLITE_FCNTL_BEGIN_ATOMIC_WRITE = 31;
+
+const int SQLITE_FCNTL_COMMIT_ATOMIC_WRITE = 32;
+
+const int SQLITE_FCNTL_ROLLBACK_ATOMIC_WRITE = 33;
+
+const int SQLITE_FCNTL_LOCK_TIMEOUT = 34;
+
+const int SQLITE_FCNTL_DATA_VERSION = 35;
+
+const int SQLITE_FCNTL_SIZE_LIMIT = 36;
+
+const int SQLITE_FCNTL_CKPT_DONE = 37;
+
+const int SQLITE_FCNTL_RESERVE_BYTES = 38;
+
+const int SQLITE_FCNTL_CKPT_START = 39;
+
+const int SQLITE_GET_LOCKPROXYFILE = 2;
+
+const int SQLITE_SET_LOCKPROXYFILE = 3;
+
+const int SQLITE_LAST_ERRNO = 4;
+
+const int SQLITE_ACCESS_EXISTS = 0;
+
+const int SQLITE_ACCESS_READWRITE = 1;
+
+const int SQLITE_ACCESS_READ = 2;
+
+const int SQLITE_SHM_UNLOCK = 1;
+
+const int SQLITE_SHM_LOCK = 2;
+
+const int SQLITE_SHM_SHARED = 4;
+
+const int SQLITE_SHM_EXCLUSIVE = 8;
+
+const int SQLITE_SHM_NLOCK = 8;
+
+const int SQLITE_CONFIG_SINGLETHREAD = 1;
+
+const int SQLITE_CONFIG_MULTITHREAD = 2;
+
+const int SQLITE_CONFIG_SERIALIZED = 3;
+
+const int SQLITE_CONFIG_MALLOC = 4;
+
+const int SQLITE_CONFIG_GETMALLOC = 5;
+
+const int SQLITE_CONFIG_SCRATCH = 6;
+
+const int SQLITE_CONFIG_PAGECACHE = 7;
+
+const int SQLITE_CONFIG_HEAP = 8;
+
+const int SQLITE_CONFIG_MEMSTATUS = 9;
+
+const int SQLITE_CONFIG_MUTEX = 10;
+
+const int SQLITE_CONFIG_GETMUTEX = 11;
+
+const int SQLITE_CONFIG_LOOKASIDE = 13;
+
+const int SQLITE_CONFIG_PCACHE = 14;
+
+const int SQLITE_CONFIG_GETPCACHE = 15;
+
+const int SQLITE_CONFIG_LOG = 16;
+
+const int SQLITE_CONFIG_URI = 17;
+
+const int SQLITE_CONFIG_PCACHE2 = 18;
+
+const int SQLITE_CONFIG_GETPCACHE2 = 19;
+
+const int SQLITE_CONFIG_COVERING_INDEX_SCAN = 20;
+
+const int SQLITE_CONFIG_SQLLOG = 21;
+
+const int SQLITE_CONFIG_MMAP_SIZE = 22;
+
+const int SQLITE_CONFIG_WIN32_HEAPSIZE = 23;
+
+const int SQLITE_CONFIG_PCACHE_HDRSZ = 24;
+
+const int SQLITE_CONFIG_PMASZ = 25;
+
+const int SQLITE_CONFIG_STMTJRNL_SPILL = 26;
+
+const int SQLITE_CONFIG_SMALL_MALLOC = 27;
+
+const int SQLITE_CONFIG_SORTERREF_SIZE = 28;
+
+const int SQLITE_CONFIG_MEMDB_MAXSIZE = 29;
+
+const int SQLITE_DBCONFIG_MAINDBNAME = 1000;
+
+const int SQLITE_DBCONFIG_LOOKASIDE = 1001;
+
+const int SQLITE_DBCONFIG_ENABLE_FKEY = 1002;
+
+const int SQLITE_DBCONFIG_ENABLE_TRIGGER = 1003;
+
+const int SQLITE_DBCONFIG_ENABLE_FTS3_TOKENIZER = 1004;
+
+const int SQLITE_DBCONFIG_ENABLE_LOAD_EXTENSION = 1005;
+
+const int SQLITE_DBCONFIG_NO_CKPT_ON_CLOSE = 1006;
+
+const int SQLITE_DBCONFIG_ENABLE_QPSG = 1007;
+
+const int SQLITE_DBCONFIG_TRIGGER_EQP = 1008;
+
+const int SQLITE_DBCONFIG_RESET_DATABASE = 1009;
+
+const int SQLITE_DBCONFIG_DEFENSIVE = 1010;
+
+const int SQLITE_DBCONFIG_WRITABLE_SCHEMA = 1011;
+
+const int SQLITE_DBCONFIG_LEGACY_ALTER_TABLE = 1012;
+
+const int SQLITE_DBCONFIG_DQS_DML = 1013;
+
+const int SQLITE_DBCONFIG_DQS_DDL = 1014;
+
+const int SQLITE_DBCONFIG_ENABLE_VIEW = 1015;
+
+const int SQLITE_DBCONFIG_LEGACY_FILE_FORMAT = 1016;
+
+const int SQLITE_DBCONFIG_TRUSTED_SCHEMA = 1017;
+
+const int SQLITE_DBCONFIG_MAX = 1017;
+
+const int SQLITE_DENY = 1;
+
+const int SQLITE_IGNORE = 2;
+
+const int SQLITE_CREATE_INDEX = 1;
+
+const int SQLITE_CREATE_TABLE = 2;
+
+const int SQLITE_CREATE_TEMP_INDEX = 3;
+
+const int SQLITE_CREATE_TEMP_TABLE = 4;
+
+const int SQLITE_CREATE_TEMP_TRIGGER = 5;
+
+const int SQLITE_CREATE_TEMP_VIEW = 6;
+
+const int SQLITE_CREATE_TRIGGER = 7;
+
+const int SQLITE_CREATE_VIEW = 8;
+
+const int SQLITE_DELETE = 9;
+
+const int SQLITE_DROP_INDEX = 10;
+
+const int SQLITE_DROP_TABLE = 11;
+
+const int SQLITE_DROP_TEMP_INDEX = 12;
+
+const int SQLITE_DROP_TEMP_TABLE = 13;
+
+const int SQLITE_DROP_TEMP_TRIGGER = 14;
+
+const int SQLITE_DROP_TEMP_VIEW = 15;
+
+const int SQLITE_DROP_TRIGGER = 16;
+
+const int SQLITE_DROP_VIEW = 17;
+
+const int SQLITE_INSERT = 18;
+
+const int SQLITE_PRAGMA = 19;
+
+const int SQLITE_READ = 20;
+
+const int SQLITE_SELECT = 21;
+
+const int SQLITE_TRANSACTION = 22;
+
+const int SQLITE_UPDATE = 23;
+
+const int SQLITE_ATTACH = 24;
+
+const int SQLITE_DETACH = 25;
+
+const int SQLITE_ALTER_TABLE = 26;
+
+const int SQLITE_REINDEX = 27;
+
+const int SQLITE_ANALYZE = 28;
+
+const int SQLITE_CREATE_VTABLE = 29;
+
+const int SQLITE_DROP_VTABLE = 30;
+
+const int SQLITE_FUNCTION = 31;
+
+const int SQLITE_SAVEPOINT = 32;
+
+const int SQLITE_COPY = 0;
+
+const int SQLITE_RECURSIVE = 33;
+
+const int SQLITE_TRACE_STMT = 1;
+
+const int SQLITE_TRACE_PROFILE = 2;
+
+const int SQLITE_TRACE_ROW = 4;
+
+const int SQLITE_TRACE_CLOSE = 8;
+
+const int SQLITE_LIMIT_LENGTH = 0;
+
+const int SQLITE_LIMIT_SQL_LENGTH = 1;
+
+const int SQLITE_LIMIT_COLUMN = 2;
+
+const int SQLITE_LIMIT_EXPR_DEPTH = 3;
+
+const int SQLITE_LIMIT_COMPOUND_SELECT = 4;
+
+const int SQLITE_LIMIT_VDBE_OP = 5;
+
+const int SQLITE_LIMIT_FUNCTION_ARG = 6;
+
+const int SQLITE_LIMIT_ATTACHED = 7;
+
+const int SQLITE_LIMIT_LIKE_PATTERN_LENGTH = 8;
+
+const int SQLITE_LIMIT_VARIABLE_NUMBER = 9;
+
+const int SQLITE_LIMIT_TRIGGER_DEPTH = 10;
+
+const int SQLITE_LIMIT_WORKER_THREADS = 11;
+
+const int SQLITE_PREPARE_PERSISTENT = 1;
+
+const int SQLITE_PREPARE_NORMALIZE = 2;
+
+const int SQLITE_PREPARE_NO_VTAB = 4;
+
+const int SQLITE_INTEGER = 1;
+
+const int SQLITE_FLOAT = 2;
+
+const int SQLITE_BLOB = 4;
+
+const int SQLITE_NULL = 5;
+
+const int SQLITE_TEXT = 3;
+
+const int SQLITE3_TEXT = 3;
+
+const int SQLITE_UTF8 = 1;
+
+const int SQLITE_UTF16LE = 2;
+
+const int SQLITE_UTF16BE = 3;
+
+const int SQLITE_UTF16 = 4;
+
+const int SQLITE_ANY = 5;
+
+const int SQLITE_UTF16_ALIGNED = 8;
+
+const int SQLITE_DETERMINISTIC = 2048;
+
+const int SQLITE_DIRECTONLY = 524288;
+
+const int SQLITE_SUBTYPE = 1048576;
+
+const int SQLITE_INNOCUOUS = 2097152;
+
+const int SQLITE_WIN32_DATA_DIRECTORY_TYPE = 1;
+
+const int SQLITE_WIN32_TEMP_DIRECTORY_TYPE = 2;
+
+const int SQLITE_INDEX_SCAN_UNIQUE = 1;
+
+const int SQLITE_INDEX_CONSTRAINT_EQ = 2;
+
+const int SQLITE_INDEX_CONSTRAINT_GT = 4;
+
+const int SQLITE_INDEX_CONSTRAINT_LE = 8;
+
+const int SQLITE_INDEX_CONSTRAINT_LT = 16;
+
+const int SQLITE_INDEX_CONSTRAINT_GE = 32;
+
+const int SQLITE_INDEX_CONSTRAINT_MATCH = 64;
+
+const int SQLITE_INDEX_CONSTRAINT_LIKE = 65;
+
+const int SQLITE_INDEX_CONSTRAINT_GLOB = 66;
+
+const int SQLITE_INDEX_CONSTRAINT_REGEXP = 67;
+
+const int SQLITE_INDEX_CONSTRAINT_NE = 68;
+
+const int SQLITE_INDEX_CONSTRAINT_ISNOT = 69;
+
+const int SQLITE_INDEX_CONSTRAINT_ISNOTNULL = 70;
+
+const int SQLITE_INDEX_CONSTRAINT_ISNULL = 71;
+
+const int SQLITE_INDEX_CONSTRAINT_IS = 72;
+
+const int SQLITE_INDEX_CONSTRAINT_FUNCTION = 150;
+
+const int SQLITE_MUTEX_FAST = 0;
+
+const int SQLITE_MUTEX_RECURSIVE = 1;
+
+const int SQLITE_MUTEX_STATIC_MASTER = 2;
+
+const int SQLITE_MUTEX_STATIC_MEM = 3;
+
+const int SQLITE_MUTEX_STATIC_MEM2 = 4;
+
+const int SQLITE_MUTEX_STATIC_OPEN = 4;
+
+const int SQLITE_MUTEX_STATIC_PRNG = 5;
+
+const int SQLITE_MUTEX_STATIC_LRU = 6;
+
+const int SQLITE_MUTEX_STATIC_LRU2 = 7;
+
+const int SQLITE_MUTEX_STATIC_PMEM = 7;
+
+const int SQLITE_MUTEX_STATIC_APP1 = 8;
+
+const int SQLITE_MUTEX_STATIC_APP2 = 9;
+
+const int SQLITE_MUTEX_STATIC_APP3 = 10;
+
+const int SQLITE_MUTEX_STATIC_VFS1 = 11;
+
+const int SQLITE_MUTEX_STATIC_VFS2 = 12;
+
+const int SQLITE_MUTEX_STATIC_VFS3 = 13;
+
+const int SQLITE_TESTCTRL_FIRST = 5;
+
+const int SQLITE_TESTCTRL_PRNG_SAVE = 5;
+
+const int SQLITE_TESTCTRL_PRNG_RESTORE = 6;
+
+const int SQLITE_TESTCTRL_PRNG_RESET = 7;
+
+const int SQLITE_TESTCTRL_BITVEC_TEST = 8;
+
+const int SQLITE_TESTCTRL_FAULT_INSTALL = 9;
+
+const int SQLITE_TESTCTRL_BENIGN_MALLOC_HOOKS = 10;
+
+const int SQLITE_TESTCTRL_PENDING_BYTE = 11;
+
+const int SQLITE_TESTCTRL_ASSERT = 12;
+
+const int SQLITE_TESTCTRL_ALWAYS = 13;
+
+const int SQLITE_TESTCTRL_RESERVE = 14;
+
+const int SQLITE_TESTCTRL_OPTIMIZATIONS = 15;
+
+const int SQLITE_TESTCTRL_ISKEYWORD = 16;
+
+const int SQLITE_TESTCTRL_SCRATCHMALLOC = 17;
+
+const int SQLITE_TESTCTRL_INTERNAL_FUNCTIONS = 17;
+
+const int SQLITE_TESTCTRL_LOCALTIME_FAULT = 18;
+
+const int SQLITE_TESTCTRL_EXPLAIN_STMT = 19;
+
+const int SQLITE_TESTCTRL_ONCE_RESET_THRESHOLD = 19;
+
+const int SQLITE_TESTCTRL_NEVER_CORRUPT = 20;
+
+const int SQLITE_TESTCTRL_VDBE_COVERAGE = 21;
+
+const int SQLITE_TESTCTRL_BYTEORDER = 22;
+
+const int SQLITE_TESTCTRL_ISINIT = 23;
+
+const int SQLITE_TESTCTRL_SORTER_MMAP = 24;
+
+const int SQLITE_TESTCTRL_IMPOSTER = 25;
+
+const int SQLITE_TESTCTRL_PARSER_COVERAGE = 26;
+
+const int SQLITE_TESTCTRL_RESULT_INTREAL = 27;
+
+const int SQLITE_TESTCTRL_PRNG_SEED = 28;
+
+const int SQLITE_TESTCTRL_EXTRA_SCHEMA_CHECKS = 29;
+
+const int SQLITE_TESTCTRL_LAST = 29;
+
+const int SQLITE_STATUS_MEMORY_USED = 0;
+
+const int SQLITE_STATUS_PAGECACHE_USED = 1;
+
+const int SQLITE_STATUS_PAGECACHE_OVERFLOW = 2;
+
+const int SQLITE_STATUS_SCRATCH_USED = 3;
+
+const int SQLITE_STATUS_SCRATCH_OVERFLOW = 4;
+
+const int SQLITE_STATUS_MALLOC_SIZE = 5;
+
+const int SQLITE_STATUS_PARSER_STACK = 6;
+
+const int SQLITE_STATUS_PAGECACHE_SIZE = 7;
+
+const int SQLITE_STATUS_SCRATCH_SIZE = 8;
+
+const int SQLITE_STATUS_MALLOC_COUNT = 9;
+
+const int SQLITE_DBSTATUS_LOOKASIDE_USED = 0;
+
+const int SQLITE_DBSTATUS_CACHE_USED = 1;
+
+const int SQLITE_DBSTATUS_SCHEMA_USED = 2;
+
+const int SQLITE_DBSTATUS_STMT_USED = 3;
+
+const int SQLITE_DBSTATUS_LOOKASIDE_HIT = 4;
+
+const int SQLITE_DBSTATUS_LOOKASIDE_MISS_SIZE = 5;
+
+const int SQLITE_DBSTATUS_LOOKASIDE_MISS_FULL = 6;
+
+const int SQLITE_DBSTATUS_CACHE_HIT = 7;
+
+const int SQLITE_DBSTATUS_CACHE_MISS = 8;
+
+const int SQLITE_DBSTATUS_CACHE_WRITE = 9;
+
+const int SQLITE_DBSTATUS_DEFERRED_FKS = 10;
+
+const int SQLITE_DBSTATUS_CACHE_USED_SHARED = 11;
+
+const int SQLITE_DBSTATUS_CACHE_SPILL = 12;
+
+const int SQLITE_DBSTATUS_MAX = 12;
+
+const int SQLITE_STMTSTATUS_FULLSCAN_STEP = 1;
+
+const int SQLITE_STMTSTATUS_SORT = 2;
+
+const int SQLITE_STMTSTATUS_AUTOINDEX = 3;
+
+const int SQLITE_STMTSTATUS_VM_STEP = 4;
+
+const int SQLITE_STMTSTATUS_REPREPARE = 5;
+
+const int SQLITE_STMTSTATUS_RUN = 6;
+
+const int SQLITE_STMTSTATUS_MEMUSED = 99;
+
+const int SQLITE_CHECKPOINT_PASSIVE = 0;
+
+const int SQLITE_CHECKPOINT_FULL = 1;
+
+const int SQLITE_CHECKPOINT_RESTART = 2;
+
+const int SQLITE_CHECKPOINT_TRUNCATE = 3;
+
+const int SQLITE_VTAB_CONSTRAINT_SUPPORT = 1;
+
+const int SQLITE_VTAB_INNOCUOUS = 2;
+
+const int SQLITE_VTAB_DIRECTONLY = 3;
+
+const int SQLITE_ROLLBACK = 1;
+
+const int SQLITE_FAIL = 3;
+
+const int SQLITE_REPLACE = 5;
+
+const int SQLITE_SCANSTAT_NLOOP = 0;
+
+const int SQLITE_SCANSTAT_NVISIT = 1;
+
+const int SQLITE_SCANSTAT_EST = 2;
+
+const int SQLITE_SCANSTAT_NAME = 3;
+
+const int SQLITE_SCANSTAT_EXPLAIN = 4;
+
+const int SQLITE_SCANSTAT_SELECTID = 5;
+
+const int SQLITE_SERIALIZE_NOCOPY = 1;
+
+const int SQLITE_DESERIALIZE_FREEONCLOSE = 1;
+
+const int SQLITE_DESERIALIZE_RESIZEABLE = 2;
+
+const int SQLITE_DESERIALIZE_READONLY = 4;
+
+const int NOT_WITHIN = 0;
+
+const int PARTLY_WITHIN = 1;
+
+const int FULLY_WITHIN = 2;
+
+const int FTS5_TOKENIZE_QUERY = 1;
+
+const int FTS5_TOKENIZE_PREFIX = 2;
+
+const int FTS5_TOKENIZE_DOCUMENT = 4;
+
+const int FTS5_TOKENIZE_AUX = 8;
+
+const int FTS5_TOKEN_COLOCATED = 1;
+
typedef _c_sqlite3_libversion = ffi.Pointer<ffi.Int8> Function();
typedef _dart_sqlite3_libversion = ffi.Pointer<ffi.Int8> Function();
diff --git a/test/prefix_tests/prefix.h b/test/prefix_tests/prefix.h
index 1e8b72d..d63d92a 100644
--- a/test/prefix_tests/prefix.h
+++ b/test/prefix_tests/prefix.h
@@ -2,6 +2,9 @@
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
+#define Macro1 1
+#define Test_Macro2 2
+
struct Struct1
{
};
diff --git a/test/prefix_tests/prefix_test.dart b/test/prefix_tests/prefix_test.dart
index abbe2b4..ba1e56d 100644
--- a/test/prefix_tests/prefix_test.dart
+++ b/test/prefix_tests/prefix_test.dart
@@ -15,10 +15,12 @@
final functionPrefix = 'fff';
final structPrefix = 'sss';
final enumPrefix = 'eee';
+final macroPrefix = 'mmm';
final functionPrefixReplacedWith = 'rf';
final structPrefixReplacedWith = 'rs';
final enumPrefixReplacedWith = 're';
+final macroPrefixReplacedWith = 'rm';
void main() {
group('prefix_test', () {
@@ -51,6 +53,10 @@
${strings.prefix_replacement}:
'Test_': '$enumPrefixReplacedWith'
+macros:
+ ${strings.prefix}: $macroPrefix
+ ${strings.prefix_replacement}:
+ 'Test_': '$macroPrefixReplacedWith'
''') as yaml.YamlMap));
});
@@ -66,6 +72,10 @@
expect(actual.getBindingAsString('${enumPrefix}Enum1'),
expected.getBindingAsString('${enumPrefix}Enum1'));
});
+ test('Macro prefix', () {
+ expect(actual.getBindingAsString('${macroPrefix}Macro1'),
+ expected.getBindingAsString('${macroPrefix}Macro1'));
+ });
test('Function prefix-replacement', () {
expect(
actual.getBindingAsString(
@@ -87,6 +97,13 @@
expected.getBindingAsString(
'${enumPrefix}${enumPrefixReplacedWith}Enum2'));
});
+ test('Macro prefix-replacement', () {
+ expect(
+ actual.getBindingAsString(
+ '${macroPrefix}${macroPrefixReplacedWith}Macro2'),
+ expected.getBindingAsString(
+ '${macroPrefix}${macroPrefixReplacedWith}Macro2'));
+ });
});
}
@@ -141,6 +158,18 @@
EnumConstant(name: 'g', value: 2),
],
),
+ Constant(
+ originalName: 'Macro1',
+ name: '${macroPrefix}Macro1',
+ rawType: 'int',
+ rawValue: '1',
+ ),
+ Constant(
+ originalName: 'TestMacro2',
+ name: '${macroPrefix}${macroPrefixReplacedWith}Macro2',
+ rawType: 'int',
+ rawValue: '2',
+ ),
],
);
}
diff --git a/tool/libclang_config.yaml b/tool/libclang_config.yaml
index 8159870..bc0754c 100644
--- a/tool/libclang_config.yaml
+++ b/tool/libclang_config.yaml
@@ -32,6 +32,7 @@
- CXTypeKind
- CXDiagnosticDisplayOptions
- CXTranslationUnit_Flags
+ - CXEvalResultKind
structs:
include:
@@ -54,6 +55,12 @@
- clang_disposeDiagnostic
- clang_parseTranslationUnit
- clang_disposeTranslationUnit
+ - clang_EvalResult_getKind
+ - clang_EvalResult_getAsInt
+ - clang_EvalResult_getAsLongLong
+ - clang_EvalResult_getAsDouble
+ - clang_EvalResult_getAsStr
+ - clang_EvalResult_dispose
- clang_getCString_wrap
- clang_disposeString_wrap
- clang_getCursorKind_wrap
@@ -85,3 +92,8 @@
- clang_getFileName_wrap
- clang_getNumElements_wrap
- clang_getArrayElementType_wrap
+ - clang_Cursor_isMacroFunctionLike_wrap
+ - clang_Cursor_isMacroBuiltin_wrap
+ - clang_Cursor_Evaluate_wrap
+ - clang_Cursor_isAnonymous_wrap
+ - clang_Cursor_isAnonymousRecordDecl_wrap