Two gaps the raylib examples hit. The layout check compared a Flan enum against the header's `int` and called it a disagreement. It is not one: Shim.cty lowers a defenum to int32_t in a struct field exactly as it does in a parameter, which is what the signature check already knew and the layout check did not. One predicate now serves both, symmetric, and tolerant of a 32-bit integer and nothing else -- f64 against the library's float still fails, in the very struct whose other field is an enum. Camera3D.projection is a CameraProjection again and rl/camera-projection is gone with it, so `.projection :perspective` resolves at the construction site. And generate-c's claim said nothing about a defconst or a defenum member, so a wrong flag bit was completely silent. `bindings` gained `enum`, `const` and `constant` lines saying what a Flan constant is called in C -- the prefix is nowhere in the Flan name, so it is declared rather than guessed. Nothing goes quiet in either direction: a name the rule builds and the header lacks is reported, a rule that reaches nothing is reported, and a defenum with no line is itself a finding, because otherwise the silence just moves up one level. clang's dump gives anonymous EnumDecls for every raylib enum and no value at all for an enumerator written without `= n`, so the constants are one flat table and the values are counted the way C counts them. cache_format bumped with the dump type.
74 lines
3.7 KiB
C
74 lines
3.7 KiB
C
/* A small C header, for testing the importer against something that does not
|
|
* move. The raylib case needs raylib installed, needs the right version of it,
|
|
* and needs an environment variable set, so it is the wrong thing to hang the
|
|
* refusal catalogue on: it would skip everywhere and cover nothing. This
|
|
* header has one function per decision Cimport makes, and the test asserts on
|
|
* the reasons rather than on the count.
|
|
*
|
|
* Deliberately includes nothing. A header that pulls in stdio would make the
|
|
* dump thirty times larger and would put libc's declarations in the way of
|
|
* reading the test's. */
|
|
|
|
typedef struct Pair { float x; float y; } Pair;
|
|
typedef struct Shade { unsigned char r, g, b, a; } Shade;
|
|
typedef struct Undescribed { int a; int b; } Undescribed;
|
|
|
|
/* A second typedef name for a record the package already describes under
|
|
* another one. raylib does this: struct Texture is Texture2D and also
|
|
* TextureCubemap. Both have to resolve to the one defstruct. */
|
|
typedef struct Pair Point;
|
|
|
|
typedef enum Mood { MOOD_CALM = 0, MOOD_CROSS = 1 } Mood;
|
|
|
|
/* Constants, for the defconst and defenum check.
|
|
*
|
|
* Anonymous on purpose: this is the shape raylib uses everywhere — the
|
|
* EnumDecl carries no name at all and the typedef beside it is a separate
|
|
* node — so enumerators have to be collected flat rather than keyed on the
|
|
* enum they came from. SHADE_DARK has no initialiser, so its value is counted
|
|
* from the one before rather than read; raylib's TraceLogLevel is written
|
|
* exactly that way and reading only the explicit ones would check one member
|
|
* of eight. SHADE_HALFDARK is the one a prefix rule cannot reach, the way
|
|
* raylib writes GESTURE_DOUBLETAP where every sibling is underscored. */
|
|
typedef enum { SHADE_LIGHT = 4, SHADE_MID = 5, SHADE_DARK, SHADE_HALFDARK = 9 } Shading;
|
|
|
|
/* A bitfield, which a Flan package holds as separate defconsts rather than as
|
|
* one enum because the call takes the OR of several — raylib's ConfigFlags. */
|
|
typedef enum { OPT_LOUD = 1, OPT_FAST = 2, OPT_FANCY_MODE = 4 } Options;
|
|
|
|
/* An int field a package may reasonably describe with an enum: the two are
|
|
* the same four bytes and the enum is the better face. `scale` beside it is
|
|
* the width the check must go on refusing. */
|
|
typedef struct Mode { int kind; float scale; } Mode;
|
|
|
|
/* And the same thing the other way round, so the tolerance is symmetric: the
|
|
* header names the enum and the package may say i32. */
|
|
typedef struct Feel { Mood mood; int n; } Feel;
|
|
|
|
typedef void (*Notify)(void *user, unsigned int n);
|
|
|
|
/* --- accepted --- */
|
|
void set_seed(unsigned int seed);
|
|
int add_ints(int a, int b);
|
|
Pair make_pair(float x, float y); /* aggregate out, by out-pointer */
|
|
float pair_len(Pair p); /* aggregate in, by pointer */
|
|
Shade tint(Shade base, Shade over);
|
|
int name_length(const char *text); /* const char * is a string in */
|
|
int count_at(const int *values, int n); /* T * is (Ptr T) */
|
|
Pair point_of(Point p); /* the second typedef name */
|
|
int mood_value(Mood m); /* a C enum is an int */
|
|
void take_nothing(void);
|
|
|
|
/* --- refused, one per reason --- */
|
|
const char *name_of(int which); /* returns char * */
|
|
void fill_buffer(char *out, int cap); /* non-const char *: C writes it */
|
|
int printf_like(const char *fmt, ...); /* variadic */
|
|
void on_event(Notify cb); /* a callback */
|
|
long file_time(const char *path); /* long varies across our targets */
|
|
Undescribed make_undescribed(void); /* no defstruct for it */
|
|
|
|
/* Two names that kebab to one, so the collision is refused by name rather than
|
|
* arriving at the checker as a duplicate declaration nobody wrote. */
|
|
int Spin2D(int n);
|
|
int spin2d(int n);
|