Menu ▾ ▴

SVN-Code Commit Log


Commit Date  
[r13123] by mikeaubury

adbschema: -json output and complete type names

-json writes the schema as JSON (docs/adbschema_json.txt). Added SERIAL8, LVARCHAR(n),
BOOLEAN, BIGSERIAL and nested SET/MULTISET/LIST/ROW (read from sysattrtypes). An unknown
type is written as UNKNOWN_TYPE_<n> and the dump continues, where it used to exit.
tools/adbschema/test-types.sh checks the types against a live database.

2026-10-04 13:50:35 Tree
[r13122] by mikeaubury

REST/JSON services callable from 4GL

rest_register / run_rest_server in libaubit4gl (registration from a JSON file found via
DBPATH, DLL loaded with dlopen), a Node gateway with a worker pool, OpenAPI generation
and tests under tools/rest. See docs/rest_services.txt.

2026-10-04 13:50:31 Tree
[r13121] by mikeaubury

Compiler: completion hooks, #line fixes, NULL lextype, fgllint in default build

- 4glc and fcompile can report which tokens the parser accepts at end of input
(A4GL_COMPLETE_FILE, see docs/completion_support.txt); fcompile spellings come from
complete_spell.h, generated from screen.lex by gen_complete_spell.sh.
- INCLINES (#line directives) never worked for programs without GLOBALS:
print_global_variable_init left suppress_lines raised. Also repeat the current #line
before continuation lines when merging the C file, so a multi-line declaration is not
attributed to later 4GL lines (debuggers put breakpoints in the prologue otherwise).
- LEX_NULL lextype (parse and check, write nothing) and A4GL_ERRFILE=- (errors to stdout):
docs/check_only_compile.txt.
- fglproto: terminate buffers, comma fix in the JS emitter.
- bin/fgllint is built by the default make in compilers/4glc.
- Move two prototypes into a4gl_incl_4gldef.h (generated code failed with implicit
declarations).

2026-10-04 13:50:20 Tree
[r13120] by mikeaubury

odbc: sqlex.c and array.c still passed 32 bit length indicators

r13115 fixed the SQLLEN mismatches in sql.c, but the plugin is built from
four files and two more had the same fault, declared with SDWORD rather than
through the SQLLEN fallback:

sqlex.c A4GL_odbc_get_blob_data_int SDWORD i -> SQLGetData arg 6
array.c static SDWORD outlen[512] -> SQLBindCol arg 6

SDWORD is 4 bytes on LP64 while those parameters are SQLLEN *, 8 bytes, so the
driver writes 8 bytes into a 4 byte object - a warning before gcc 14 and an
error since. The unixODBC build stopped on the first of them:

sqlex.c:780:70: error: passing argument 6 of 'SQLGetData' from incompatible
pointer type [-Wincompatible-pointer-types]

and array.c would have followed with three more at SQLBindCol. Both are now
SQLLEN, which the bundled-header SQLITEODBC build still gets from the fallback
in a4gl_lib_sql_odbc_int.h. Every use of either variable is a comparison,
sum or size argument, all of which read the same with the wider type.

Checked against the unixODBC 2.3.12 headers (unixodbc-dev, Ubuntu 24.04):
before this change sqlex.c gives exactly the reported error and array.c the
three that would follow; after it all four files compile, and the unixodbc
make target builds libSQL_unixodbc.so with the Makefile's own flags. Also
clean against the Informix CLI headers (IFXODBC, 64 bit SQLLEN) and the
bundled tools/odbctest/incl set (SQLITEODBC, no SQLLEN at all). No other
SDWORD or SQLINTEGER in the plugin is passed where ODBC wants an SQLLEN.

2026-09-24 16:00:35 Tree
[r13119] by mikeaubury

OPEN FORM: pass the FORM variable's member, not the struct

A FORM variable is generated as

static struct { long objectid ; } list;

and OPEN FORM emitted A4GL_open_gui_form(&list,...) against a parameter
declared long* (API_ui.spec). That only worked because objectid happens to be
the single member and so shares the struct's address; to the C compiler it is
a type error, and one that gcc 14 refuses:

error: passing argument 1 of 'A4GL_open_gui_form' from incompatible pointer
type; expected 'long int *' but argument is of type 'struct <anonymous> *'

so tools/test/gui/calc.4gl could not be compiled. The member is now passed
explicitly - &list.objectid - which is the same address, so nothing changes at
runtime and the plugin API is left alone. The backends do write through that
pointer (*form_variable = (long)tlw in ui_glade), so long* is the right type
for it to keep.

While there: the name emitted here comes from the command as a plain
identifier rather than a variable usage, so it was not going through the scope
prefixing that r13117 added - under MARK_SCOPE the form was declared M_list and
opened as list. It is now looked up by name to find its scope, the same way the
CODE block aliases do, so declaration and use agree again. This could not have
shown up before, as the statement did not compile either way.

defprog.4gl calls time() in a CODE block without including <time.h>; it does
now, as clock.4gl does for usleep() since r13116.

Checked on the 142-module corpus: 112 compile where 110 did, the two being
calc.4gl and defprog.4gl, with nothing that compiled before failing now, and
the results identical with MARK_SCOPE and MARK_SCOPE_MODULE set.

2026-09-21 11:14:47 Tree
[r13118] by mikeaubury

Declare the 4GL-callable builtins where generated code can see them

Compiling a 4GL program that calls a4gl_get_ui_mode() fails:

error: implicit declaration of function 'aclfgl_a4gl_get_ui_mode';
did you mean 'aclfgl_a4gl_get_info'? [-Wimplicit-function-declaration]

The function exists (lib/libaubit4gl/fglwrap.c) and is prototyped in
a4gl_libaubit4gl.h - but that is the library include path, and generated code
uses the other one (a4gl_incl_4glhdr.h -> a4gl_incl_4gldef.h), so it never sees
the declaration. Implicit declarations were legal C89 and are an error in gcc
14, so what used to be a warning now stops the compile.

a4gl_get_ui_mode was not alone. Every name in lib/generated/std_funcs.c was
compiled as a call against the generated-code include path: 23 of them are
implemented in lib/libaubit4gl with the usual convention and had no prototype
there. All 23 are declared in a4gl_incl_4gldef.h now, which both paths include,
and the 16 declarations that existed in a4gl_libaubit4gl.h (one of them split
over two lines) are removed so there is a single source of truth, as are four
local prototypes at the top of builtin.c that now duplicate it.

A4GL_endis_fields goes the same way: the generator emits a call to it for the
field controls (print_endis_* in cmds_funcs.c) and it too was declared only in
a4gl_libaubit4gl.h. That is what stopped tools/test/gui/gui.4gl and
hello-gui.4gl from compiling; both do now.

Signatures were checked against the definitions, not against other headers.

Checked on 142 modules from tools/ and the test suite: 110 compile where 108
did, the two gui programs being the difference, and no module that compiled
before fails now. The same holds with MARK_SCOPE set. libaubit4gl builds with
no redundant-declaration warnings.

Not fixed here, found by the same scan and worth a look on their own:
- the DDE family, winexec, winexecwait and fgl_strtosend are listed as
builtins but are defined taking char* arguments, while the compiler emits
aclfgl_<name>(nargs) like every other builtin - so they cannot be called
from 4GL as they stand
- a4gl_dump_screen, a4gl_load_datatype, set_page and the *_rowid_s family are
listed as builtins with no implementation anywhere - a link error if called
- about 20 more A4GL_* functions the generator emits are declared only in
a4gl_libaubit4gl.h; each is the same latent error for whichever statement
emits it (menus, PDF reports, ESQL cursor state)

2026-09-21 10:59:19 Tree
[r13117] by mikeaubury

C back end: make MARK_SCOPE work

A4GL_MARK_SCOPE (and MARK_SCOPE_MODULE) prefixes variables with their scope -
G_ for globals, M_ or M_<module>_ for module variables, L_ for locals - so a
4GL name cannot collide with a C one. For the C back end it only ever renamed
the DECLARATION: every use still emitted the bare name, so a module with a
variable in it produced

static long M_dup ;
...
dup=0;

and did not compile. Only the C# back end, which applies the prefix wherever a
name is written, actually worked. So the one setting meant for this problem
could not be used for it.

The declaration and every use now take the name from one function,
scoped_variable_name(), so the two cannot drift apart again - expressions,
assignments, function and report parameter binding, nullify, dynamic arrays,
the object list and COPYBACK all go through it.

- system variables (status, sqlca, int_flag...) live in the library and keep
their names; a use is looked up to recognise them, as only the definition
records that

- class members and associative arrays keep the plain name: they are declared
through their own paths (objData->..., the ASSOCIATE_ macros)

- simple and object function parameters had no scope recorded at all, so they
were never prefixed; they are now marked local, as record and reference
parameters already were

- a CODE block is hand written C that names variables as the 4GL wrote them,
so each variable a block mentions is #defined to its scoped name for the
length of the block and #undef'd after. Only the block sees the aliases, so
generated code keeps the protection. Without this every tool with embedded
C - 4glpc, asql, adbschema, a4gl - failed to compile under the flag.

Checked on 142 modules from tools/ and the test suite compiled three ways - no
flag, MARK_SCOPE, MARK_SCOPE_MODULE: the same 108 compile in all three, and the
34 that fail fail identically, all for reasons that predate this. With no flag
set the generated C is byte for byte what it was, bar the cursor and prepare
identifiers that differ on every compile. Runtime output is identical in all
three modes for a program exercising globals, module variables, locals,
records, arrays, dynamic arrays, a report and variables called dup, read, write
and close; for both OO test programs; and for a 4glpc built with the flag and
then used to compile and run a program. ESQL/C output compiles through Informix
esql with either flag. A clean export of r13115 with this change builds with 0
errors and the same 361 warnings as without it.

Two things the flag cannot do: C outside the module must use the prefixed name
of a GLOBALS variable, and if a name is both a 4GL variable and a struct member
used across CODE blocks the aliasing renames the member too - a compile error,
not a silent change of meaning.

The description of A4GL_MARK_SCOPE said it adds the module name, which is what
MARK_SCOPE_MODULE does; corrected, and MARK_SCOPE_MODULE is now described too.

2026-09-21 10:08:40 Tree
[r13116] by mikeaubury

Generated code: do not include <unistd.h>

r13105 added <unistd.h> to a4gl_incl_4glhdr.h so that a CODE block calling
usleep would not rely on an implicit declaration, which gcc 14 rejects. That
header also declares dup, read, write, close, link and access, and generated C
puts module and GLOBALS variables at file scope under their 4GL names - so any
program with a variable of such a name stopped compiling:

error: 'dup' redeclared as different kind of symbol

Those are ordinary 4GL variable names: such programs compiled in 1.6.3 and up
to r13104. The include is removed again, and the two files in the tree that
need the header now ask for it themselves in a CODE block - tools/test/clock.4gl
for usleep() and tools/test/html/html_report.4gl for unlink(). Every other CODE
block calling a POSIX function is in a file that already reaches the header
through tools/asql/simple.h; all 243 versioned .4gl files were scanned for this.

Checked on clean exports of r13115 built with and without the change: configure
and make both succeed, with 0 errors and the same 361 warnings, and not one
diagnostic appears or disappears. The files r13105 was aimed at are not part of
any default target, which is why the build does not move either way.

A variable can still collide with stdio.h, string.h or stdlib.h - index, time
and system, say. A4GL_MARK_SCOPE covers that case.

2026-09-21 10:08:18 Tree
[r13115] by mikeaubury

odbc: stop redefining SQLLEN to a 32 bit type

sql.c opened with

#ifndef SQLLEN
#define SQLLEN SQLINTEGER
#endif

meant as a fallback for header sets that predate SQLLEN. SQLLEN is a
typedef in every modern set, and the preprocessor cannot see a typedef,
so the test was always true: the define fired everywhere and quietly
turned the real 64 bit type into a 32 bit one for the whole file - the
indicator fields of struct sql_col_bind_data included, which is why
calls that read correctly still failed.

That produced 20 errors under gcc 14 (SQLBindCol argument 6, SQLRowCount
argument 2, SQLGetData argument 6, SQLBindParameter argument 10,
SQLDescribeCol argument 7, which wants SQLULEN *), reported by a user
building on AlmaLinux 10. gcc 14 turns -Wincompatible-pointer-types into
an error; before that this was a warning nobody was reading, over a real
defect: on any LP64 platform the driver was handing 4 byte objects to
functions that write 8 bytes into them, including a heap allocation of
sizeof(SQLINTEGER) for a value ODBC writes a SQLLEN into.

The fallback now keys off A4GL_ODBC_HEADERS_LACK_SQLLEN, set only by the
SQLITEODBC branch that includes the bundled tools/odbctest/incl headers -
the one set that genuinely has no SQLLEN. It cannot be detected any other
way: ODBCVER is no help, since those same bundled headers announce
0x0350. unixODBC does define SQLLEN as a macro, but only in the cases
where it is SQLINTEGER anyway, so the !defined(SQLLEN) half is kept.

It moved into a4gl_lib_sql_odbc_int.h because the prototypes there use
these types, so every file including that header needs them.

The declarations that feed ODBC out parameters are corrected to
SQLLEN/SQLULEN, and A4GL_display_size takes SQLULEN to match
SQLDescribeCol.

Verified by compiling sql.c against all three header sets: unixODBC
2.3.12 goes from 20 errors to none, iODBC builds clean, and the
SQLITEODBC path still builds with the fallback active. sqlite3odbc.c and
sqliteodbc.c are unchanged by this - they fail the same way before and
after, wanting a system <sql.h> on the include path.

2026-09-14 18:44:00 Tree
[r13114] by mikeaubury

tools/misql: link with 4glpc, not 4glc

misql compiles each module to a .ao and then links the set of them. Both
steps went through ${FGLPCEXEC}, which resolves to bin/4glc here -
FGLPC_NAME in Makefile-common.in is 4glc, and the 4glpc spelling next to
it is commented out.

Driving 4glc directly to link .ao files leaves the library link line off,
so misql.4ae failed with undefined references to A4GL_set_status,
A4GL_setnull, A4GLSTK_pushFunction_v2 and the rest of libaubit4gl.
adbload gets away with the same variable only because it compiles and
links a .4gl in one step.

Both rules now use "aubit 4glpc", the documented way to drive the
compiler, which does add the link line. Verified from scratch with every
.ao and .4ae deleted first: misql.4ae builds and ldd reports
libaubit4gl.so.1 where it previously resolved nothing.

Masked on any tree built before now, because a stale misql.4ae satisfies
the target and "make clean" does not remove it. It only appears on a
fresh checkout, like the adbload breakage in r13113.

FGLPCEXEC itself is left alone: other makefiles use it and work, so what
it should point at is a bigger question than this fix.

2026-09-14 18:38:30 Tree
Older >