Menu

SVN-Code Commit Log


Commit Date  
[r13105] by mikeaubury

Give generated code the POSIX header as well as the C ones

A CODE block is C written by hand inside a 4GL program, and it reaches for
usleep as readily as for the standard functions the header chain already
provides. Without unistd.h those were implicitly declared, which was legal C89
and is an error in gcc 14 - so a program with such a block stopped compiling.

Not guarded on HAVE_UNISTD_H: the generated-code header chain does not pull in
a4gl_incl_config.h, so no HAVE_* symbol is defined by the time this is read.
Every platform this builds for - Linux, macOS, WSL2, MinGW-w64, FreeBSD -
provides the header, so it is included directly.

2026-09-07 15:31:42 Tree
[r13104] by mikeaubury

ace: pass ints to A4GLSQL_next_column, not 4GL INTEGERs

The CODE block in get_cols passed the addresses of two 4GL INTEGERs to

int A4GLSQL_next_column(char** colname, int* dtype, int* size);

A 4GL INTEGER is a long, so on a 64-bit platform the callee filled four bytes
of each eight-byte variable and left the rest as it found it. That worked only
because both happened to be zero when it ran, and gcc 14 rejects it outright:

error: passing argument 2 of 'A4GLSQL_next_column' from incompatible
pointer type

The values are now taken in ints and copied across, which is what the API
describes.

2026-09-07 15:31:37 Tree
[r13103] by mikeaubury

gzpacked: cast the handle back in the three macros that did not

The header maps the stdio calls onto zlib's, and fopen there hands back a
gzFile cast to FILE *, so every macro has to cast it back before use. Five did.
ftell, fseek and rewind did not:

#define fclose(a) gzclose((gzFile)(a)) <- casts
#define ftell(a) gztell(a) <- did not

Passing a FILE * where a gzFile is expected was a warning until gcc 14, which
rejects it:

error: passing argument 1 of 'gztell' from incompatible pointer type

Only ftell actually broke the build - fseek and rewind are not reached on this
path - but all three carry the same fault, so all three now cast as the rest of
the file already does.

2026-09-07 15:31:19 Tree
[r13102] by mikeaubury

ChangeLog: fill in 1.6.3, and summarise the changes since it

1.6.3 had no entries at all. Added, from the revisions between the 1.6.2 and
1.6.3 releases: web UI work, CLOSE CURSOR as a synonym for CLOSE, CONFIG = on a
form field accepting a JSON object, fgl_messagebox, the move to ExtJS 7.

The 1.8.1 section covers 162 revisions, so it is grouped by period rather than
listing each one - many of the individual messages are "." or "New build" and a
flat list would not be readable. Four groups: the JSON and web UI work through
late 2025, the build system rewrite in spring 2026, the Angular UI and
clean-checkout build fixes in August, and this month's compiler and C# back end
work.

2026-09-07 15:12:11 Tree
[r13101] by mikeaubury

Fix mk_states_opt.c so it builds with gcc 14

Three pieces of pre-C99 style that newer compilers no longer accept, reported
by a user building with gcc 14:

main() { -> int main (void)
int get_nints(...) -> static int get_nints(...)
printf("arr_%d,\n",a,a) -> printf("arr_%d,\n",a)

Implicit int was removed from the language in C99 and gcc 14 rejects it
outright rather than warning, which is what stopped the build:

error: return type defaults to 'int' [-Wimplicit-int]

get_nints is used only in this file, so static both silences the
missing-prototype warning and says what is true. The printf had two arguments
for one conversion.

This program generates the parser state table, so the old and new versions were
built side by side and their output compared: byte for byte identical, 1167625
bytes. The change only makes the generator compile; what it generates is
unchanged.

2026-09-07 15:11:55 Tree
[r13100] by mikeaubury

C# back end: reject a GOTO that jumps into a block

C# allows a goto to leave blocks but not to enter one: the label has to be in
the same block as the goto, or in one enclosing it. 4GL puts no such limit on
it and neither does C, so a program can be perfectly good 4GL and have no valid
C# translation. That used to surface as

error CS0159: No such label 'x' within the scope of the goto statement

against generated code, which takes some tracing before it is clear that the
4GL is what needs changing. It is now reported where it happens:

| Error at line 529, character 19
| GOTO carryon jumps into a block - the label is not in this branch, nor in
| one containing it. C# does not allow that, so this needs restructuring
| (move the label out, or use a flag and test it after the branch)

Every command list is a block: entering one pushes a fresh id and leaving pops
it, so the stack is the path from the function body to the current point. A
label's path is recorded where it is declared and a goto's likewise, and the
jump is legal exactly when the label's path is a prefix of the goto's.

The prefix test is the point. Comparing nesting depth is not enough: in the
case that prompted this the goto sits deeper than its label and still cannot
reach it, because the two are in the IF and the ELSE of the same statement -
siblings, not ancestor and descendant.

A goto to a label that is declared nowhere is left alone. That is a different
fault and not one this check should be guessing about.

Checked against 160 programs: no program that compiled before fails now, and
besides the case that prompted it the check found one more genuine instance.

2026-09-07 10:33:05 Tree
[r13099] by mikeaubury

C# back end: a switch needs its labels to be the subject's type

4GL will test an INTEGER against "1", converting as it goes. C# requires the
case labels to have the same type as the switch expression, so such a CASE was
emitted as a switch that would not compile.

Where the subject and its labels disagree about being character data, the
if/else fallback is used instead - it compares through the same conversion the
rest of the generated code uses, so the meaning is unchanged.

2026-09-06 13:53:00 Tree
[r13098] by mikeaubury

C# back end: restore three fixes lost to a revert

These were committed in r13095 and then reverted out of the working copy while
undoing an unrelated bad edit to the same file. The commit stands; the working
copy did not, and later work was built without them. Restored and verified
against the programs that first showed each:

- a struct with a field initialiser needs an explicit parameterless
constructor, and an array member is emitted with an initialiser
- two WHEN clauses may test the same value; 4GL runs the first that matches
and a C# switch rejects duplicate labels, so those take the if/else
fallback that already existed
- the keyword escape must not survive into a flattened identifier -
"InVar_a_@..." does not parse, and the flattened name cannot be a keyword

The lesson is narrower than it looks: revert takes the whole file, so undoing
one edit to a file that carries several loses the rest.

2026-09-06 13:47:01 Tree
[r13097] by mikeaubury

C# back end: type a function from its widest RETURN

A function not covered by the prototypes has its signature worked out by
scanning its RETURN statements - and the scan stopped at the first one it
found. A 4GL function may return different numbers of values on different
paths, so where a later path returned more, the function was typed too narrow
and its calls would not compile.

It now keeps the RETURN that yields the most values, matching how the compiler
chooses between a function's prototype variants (r13096): the signature has to
suit every call site, and the widest does.

2026-09-06 13:16:19 Tree
[r13096] by mikeaubury

Choose deliberately between a function's return shapes

A 4GL function may return different things on different paths - a value on one
and nothing on another, or a SMALLINT here and a DECIMAL there. fglproto emits
one prototype per shape, and is_bolton_function answered with whichever came
first, so which shape a back end saw depended on the order they happened to be
written. Arbitrary, and for a back end with a strict type system it decides
whether the program compiles at all.

The widest now wins: a function returning SMALLINT on one path and DECIMAL on
another is a DECIMAL function, and the narrow value converts to it without
loss. Where two shapes return different numbers of values the one returning
more wins, so no call site loses a result.

Ordering is SMALLINT < INTEGER < INT8 < DECIMAL < FLOAT < CHAR, comparing at
the first position where two shapes differ.

No change to the C back end's output on the example suite - it accepts either
shape, so it never depended on the choice.

2026-09-06 13:08:55 Tree
Older >