Menu

SVN-Code Commit Log


Commit Date  
[r13069] by mikeaubury

common/dataio: drop the dead menu_x rpcgen rules

You were right, and it goes further than the rpcgen path: nothing in
the default build consumes common/dataio/menu_x.x at all.

- menu_x_xdr.o was a prerequisite of nothing. The four XDRPACKER
plug-ins are struct_form, report, module and module_definition.
- lib/libmenu is not wired into lib/Makefile, so no libMENU_* is
built - configure already says so in a comment, and aubitrc reports
A4GL_MENUTYPE_DETECTED="NOMENU GENERIC" with no XDR in the list.
- The one place that could still have wanted the rpcgen header,
compilers/menus/a4gl_mcompile_int.h, takes the xgen branch:
_USE_RPCGEN_HEADERS_ is not defined anywhere in the tree.
- compilers/menus/Makefile had already commented its own rpcgen rules
out, with "Should be obsolete - using xgen instead of rpcgen".
- Even the xgen side is unused here: libDATA_any is the only thing
that wants menu_x.xio.o, and it is commented out of ALL. An Alma
build produces libDATA_struct_form, _report, _module and
_module_definition, and no menu_x object of any kind.

So the RPCGEN_MENU definitions and the menu_x_xdr.c and menu_x_xdr.o
rules are gone, including the fallback line I added to them in r13066 -
which never fired, since nothing asked for the file.

One distinction worth keeping straight, because the two files have the
same name: compilers/menus/menu_x.x IS live. xgen turns it into
menu_x.xs.h, which mcompile includes, and bin/mcompile is built. Only
the common/dataio copy is dead. Nothing has been removed from
compilers/menus.

tools/cygwin/menu_x.h and menu_x_xdr.c are now referenced by nothing.
They are still the odd ones out there - hand-adapted rather than
rpcgen output - and deleting versioned files is your call, so they are
left alone; refresh.norpcgen does not touch them either way.

Verified: common/dataio and compilers/menus both still build, a clean
Alma 8 container build with no rpcgen still configures, makes and runs
a compiled 4GL program, and the fidelity probes still pass.

2026-09-02 19:34:21 Tree
[r13068] by mikeaubury

Makefile: make refresh.norpcgen work again, and refresh what had drifted

The target was there, as you said. It had not copied anything in a very
long time, for two reasons:

if test "$x" = "1"

"$x" is expanded by make, not by the shell, so the shell saw
test "" = "1" and the branch never ran. It wanted "$$x" - which
refresh.noyacc, twenty lines below, gets right.

The sense was inverted anyway. diff -q exits 0 when two files are the
SAME, so

if diff -q common/dataio/form_x.h tools/cygwin/form_x.h ; then x=1; fi

set "needs updating" precisely when they already matched, and left it
clear when they had diverged. Both bugs had to be fixed for either to
show.

Rewritten as a loop over the file list, so a new .x file is one word to
add rather than three lines, and it now says which files it copied.

Then run, which refreshed three files that had drifted from the .x
sources:

form_x.h FA_S_ALLOWEDCHARS, an enum used by lib/libui/ui_curses
fgl.h the s_expr_json type and a struct's config field
fgl_xdr.c the matching xdr_s_expr_json serialiser

All additions; nothing was removed. report.h, report_xdr.c, npcode.h
and npcode_xdr.c were already current.

menu_x stays out of the list, as it always was. Unlike the other four,
tools/cygwin/menu_x.h is not rpcgen output - it is hand-adapted to need
no RPC headers, declaring bool_t itself rather than including
<rpc/rpc.h>. Copying rpcgen's version over it would throw that away.
That is now written down in the target rather than being implicit in
the omission.

Verified: a second run reports everything up to date; the fidelity
probes still pass here; and the no-rpcgen Alma 8 container build still
configures, makes and runs a compiled 4GL program against the refreshed
files - which is the case these copies exist for.

2026-09-02 19:30:04 Tree
[r13067] by mikeaubury

etc/containers: build on Alma 8 without needing an Alma 8

We have been fixing RHEL-family build failures blind, one report at a
time, because they do not happen on a current Debian. Three in a row now
- --with-pg-all being silently ignored, configure dying with no message
where there is no controlling terminal, and the missing -ldl - were all
invisible here and obvious there.

./etc/containers/build-in-container.sh # alma8, no rpcgen
./etc/containers/build-in-container.sh alma8-rpcgen # with rpcgen
./etc/containers/build-in-container.sh alma8 --with-mysql

It exports the tree rather than mounting the working copy, so a
generated file or an object file from a host build cannot mask a
missing dependency - which is the entire point of building elsewhere.
Then it configures, makes, and compiles and runs a 4GL program, so a
green result means the toolchain works rather than merely that it
linked. Uses podman when it is there and docker otherwise; podman needs
no daemon and no group membership, so it works without setup.

Alma 8 is worth the trouble because of how it differs:

glibc 2.28 libdl.so.2 is still a separate object
gcc 8.5 stricter in places than what we develop against
autoconf 2.69 older than configure.ac wants, so the image installs
no autoconf at all and builds with the configure that
ships in the tree - what a release user actually does
rpcgen in PowerTools, off by default; the plain image leaves
it out so the pre-generated files get exercised, and
the -rpcgen image puts it back to cover the other path

Both images verified: configure, make and the smoke test pass on each.

2026-09-02 19:05:23 Tree
[r13066] by mikeaubury

build: rpcgen is not a requirement again

I made rpcgen a hard configure error. It never was one, and it should
not have become one - this reverses that.

tools/cygwin holds a checked-in copy of every file rpcgen produces:
form_x.h, fgl.h, menu_x.h, npcode.h, report.h and their _xdr.c
partners. They are not raw rpcgen output - they are hand-adapted to
compile with no RPC headers at all, defining bool_t themselves rather
than including <rpc/rpc.h>. That is exactly what a machine without
rpcgen needs, and it is how this built for years before rpcgen was on
anyone's dependency list.

common/dataio now generates when rpcgen is there and copies those files
when it is not. configure says which it is doing instead of stopping.

The error was an over-correction on my part. What actually broke on
Debian 13 was the ancient bundled RPC runtime headers under
tools/no_rpc/cygwin/rpc, where XDR_INLINE() returns long * while
rpcgen output declares int32_t * - a hard error with gcc 14. That is a
different directory and a different problem from the pre-generated
output in tools/cygwin, and the second was made to pay for the first.

The requirement also landed hardest on the people least able to satisfy
it: on RHEL 8, Alma and Rocky rpcgen lives in PowerTools, which is not
enabled by default, so the advice the error gave - "dnf install rpcgen"
- does not work as written. The notice now says
--enablerepo=powertools.

Verified in a container on the reporter's platform, AlmaLinux 8.10 with
glibc 2.28:

- with no rpcgen installed at all: configure and make both succeed,
and the resulting compiler builds and runs a 4GL program
- with rpcgen present, here on Debian: form_x.h is still generated
from form_x.x, and the end-to-end probes still pass

The pre-generated copies have drifted from the .x files - form_x.h is
missing FA_S_ALLOWEDCHARS, menu_x more than that. It does not break the
build, because the enum that matters reaches the code through
incl/dataio/form_x.xs.h, which xgen generates and which is versioned.
Worth refreshing, but it needs doing by hand to keep the no-RPC-headers
adaptation, so it is not being done blind here.

2026-09-02 19:02:19 Tree
[r13065] by mikeaubury

build: link -ldl where dlclose() is called directly

Reported from a RHEL-family build:

/bin/ld: API_lex.o: undefined reference to symbol 'dlclose@@GLIBC_2.2.5'
//usr/lib64/libdl.so.2: error adding symbols: DSO missing from command line
make[2]: *** [Makefile:192: ../../bin/4glc] Error 1

4glc calls dlclose() itself - the .spec-generated API_lex.c and
API_parse.c declare their own prototype for it and call it from
A4GLLEX_clrlibptr() - so it has to link against libdl in its own right,
not lean on libaubit4gl having pulled it in. Nothing put -ldl on the
line: configure has worked out USE_LIBDL correctly all along, but no
Makefile ever used it, and EXTRALIBS - which the link lines do use - is
substituted empty.

It only shows on some distributions because glibc 2.34 merged libdl
into libc. On Debian and Ubuntu dlclose resolves out of libc and the
missing library is invisible; on RHEL, Alma and Rocky 8, where
libdl.so.2 is still its own object, the link fails. compilers/pcode has
the same direct calls and so had the same latent problem.

USE_LIBDL now goes into EXTRASYSTEMLIBS, which every link rule already
uses, so this covers the executables rather than just the one that was
reported. It is empty on macOS, where dlopen is in libc anyway, and
-ldl still links harmlessly on a merged-libc glibc - the stub library
is kept for compatibility - so nothing needs to be conditional beyond
what configure already decides.

Verified: -ldl now appears on the 4glc link line, 4glc rebuilds and
runs, and the end-to-end probes still pass.

2026-09-02 18:45:32 Tree
[r13064] by mikeaubury

dotnet: bring the README up to date

Records what actually compiles now - d4 and 30 of 33 standalone demo
programs - and how to collect prototypes for a multi-module program,
which is the one part of the build that is not obvious: fglproto takes
the .dat files rather than the .4gl, and they all have to go in
together or a cross-module call cannot be typed.

Replaces the SQL known-gap, which is done, with the ORDER BY report
path, which is not. Adds the four things the probes caught since the
last update to the list of mistakes they caught - including the
comparison-returns-INTEGER one, which compiled everywhere and was still
wrong.

2026-09-02 17:43:20 Tree
[r13063] by mikeaubury

dotnet: 30 of the 32 demo programs now compile, plus the d4 application

Standalone demo programs compiling clean went 6 -> 30 of 33. The 33rd,
mkstore4, fails the C toolchain too, so it is a broken demo rather than
a gap here. d4, the eight-module application, stays at zero.

The 2009 C# backend's names were still being emitted throughout -
IfxExecute, IfxResult, IfxBinding, IfxCursorType, BuildIfxCursor,
IfxException, IfxSetError, IfxPrepare, IfxToday, IfxAscii, the
IfxDateTimeQual and IfxIntervalQual enums, and a dozen more. 120 lines
of the generator now name the runtime that exists.

Generator fixes:

- assign_wrapper handled CHAR and DECIMAL and fell through for
everything else, so a SMALLINT target took whatever int-typed
expression was assigned to it. 4GL narrows without comment; C#
refuses to. That alone was 58 of the errors.
- A 4GL literal with a decimal point is a DECIMAL, not a float, and
it was emitted bare - which C# reads as a double, so lv_price *
1.15 would not compile against a DECIMAL. It now carries the m
suffix.
- CONSTRUCT emitted "new UI.Construct(this, ...)", treating UI as a
type; it is a property, and Construct is a factory on it.
- FIELD_TOUCHED and NOT FIELD_TOUCHED are expressions, emitted inside
an if condition, but each wrote a trailing semicolon - a syntax
error that stopped the file parsing and hid every other error in
it.
- The thisApp prefix rule from r13062 was too broad in one direction
and too narrow in the other. Inside a report, Fgl.Length must not
be prefixed - it is a static - but SQL.ASqlExecute must be, because
SQL is a property on the module. Asking whether the name carries a
qualifier cannot tell those apart, so the runtime's static classes
are now named explicitly.

Runtime: MATCHES and NOT MATCHES (Informix's pattern language, not a
regular expression), CURRENT, EXIT PROGRAM, STARTLOG and ERRORLOG,
SHOWHELP, SHOW/HIDE OPTION ALL, OPTIONS with a text value, the full
window attribute set, INPUT ARRAY and DISPLAY ARRAY with their screen
and program arrays, BEFORE/AFTER FIELD over several fields at once,
FIELD_TOUCHED, PRINT of a non-text value, and FormField accepting a
nullable subscript - ARR_CURR lands in a SMALLINT and 4GL widens it
freely.

AsBool now returns bool rather than bool?, but only the cast on
FglModule: it is what the generator emits for IF lv_int THEN, and 4GL
treats NULL as false in a condition. Fgl.AsBool stays nullable, because
a NULL column read out of a row really is null and the difference
matters there.

Still open: ORDER BY reports (report4 and report6, 21 errors each).
That path builds a temp table and re-reads it through a second cursor,
and its generated code refers to a startReportOrdered that is never
emitted, to cursors that are never declared, and reaches the session
from a static context. It is one coherent piece of work rather than a
scatter of small gaps.

Fidelity: 27 semantics, 9 UI messages, 30 USING, the 66-line report and
5 end-to-end programs all agree with C. 203 runtime tests pass.

2026-09-02 17:42:28 Tree
[r13062] by mikeaubury

dotnet: the whole d4 demo application now compiles

d4 is the Informix demo app that ships with Aubit - eight modules,
globals in one of them, cross-module calls, forms, menus, input
arrays and two reports. It now generates and compiles to .NET with no
errors. That was 501 errors across its two biggest modules alone when
this started.

Nothing needed to change about how modules combine: 4GL has one flat
function namespace per program, and the generator already emits every
module as "public partial class Simple", so the modules of one program
merge into one class and cross-module calls and globals resolve on
their own. What was missing was the prototype collection - fglproto
takes the .dat module definitions, and the whole program's modules have
to go in together, or a call into another module cannot be typed. Note
that fglproto wants the .dat, not the .4gl, and that a .glb has no
module definition to load, so it has to be left out or the run aborts.

Generator fixes:

- Inside a report, every call was prefixed with thisApp. on the basis
that a report is a nested class and its module's functions live on
the outer one. That was applied before checking whether the name had
already been rewritten to a runtime static, so a builtin came out as
thisApp.Fgl.Length(...), which resolves to nothing. The prefix is
now skipped for an already-qualified name.
- IS NULL and IS NOT NULL were emitted bare, so they only resolved at
module level, not from inside a report. Both now name the runtime.
- INPUT ARRAY binds the SHAPE of a row - the column types and widths,
with the values coming from the array handed to the dialog - but it
emitted the same Append names the value form uses, and the two
collide on arity: AppendString(3) is a CHAR(3) column in one and the
value 3 in the other. The shape form is Declare* now.

Runtime: MESSAGE, ERROR, FGLIdent, DRAW BOX, ARR_CURR, SCR_LINE,
ARR_COUNT, SET_COUNT, STATUS, INT_FLAG; the scroll-cursor fetches
(FIRST, LAST, NEXT, PREVIOUS, ABSOLUTE, RELATIVE); IsNotNull; column
declarations on ASqlBinding; PAUSE with a message.

FglBool is new, and it is worth explaining. 4GL has no boolean type: a
comparison yields an INTEGER, and the language uses it both ways -

IF lv_a = lv_b THEN ... -- a condition
LET lv_flag = lv_a = lv_b -- a value, 0 or 1

C# will take neither an int as a condition nor a bool as a number, so
a comparison now returns a type that converts implicitly to both and
renders as "0"/"1". The first attempt simply returned bool, which
compiled everywhere and was wrong: the types probe caught it printing
"False" where C prints "0". That is exactly the kind of thing these
probes exist to catch, and it would have been invisible in a review.

Standalone demo programs compiling clean: 13 of 33, up from 6. The
largest remaining group is SMALLINT: the generator maps it to short?
but arithmetic on it yields int, and it does not insert a narrowing
cast, which is about 58 of the ~130 errors left.

Fidelity: 27 semantics, 9 UI messages, 30 USING, the 66-line report and
5 end-to-end programs all agree with C. 203 runtime tests pass.

2026-09-02 17:26:44 Tree
[r13061] by mikeaubury

dotnet: the UI API generated code targets

The last of the three APIs a generated module refers to. 22 UI entry
points and 7 dialog types, all built on the existing IUiChannel and its
message records.

Every 4GL interactive statement lowers to the same shape:

using (var d = UI.CreateX(...)) {
...configure...
while (d.Run()) { switch (d.GetEventID()) { case 3: ... } }
}

so UILib_Dialog owns that loop and each dialog says only how its own
clauses resolve. Clause ids are allocated by the generator as it walks
the source; -1 means the client did something no clause claimed, which
the generated switch falls through on - the same as 4GL, where an
unhandled key does nothing.

UILib_Menu COMMAND, BEFORE MENU, NEXT/SHOW/HIDE OPTION - which
address an option by its text, as 4GL does
UILib_Prompt PROMPT ... FOR
UILib_Input INPUT, with the BEFORE/AFTER FIELD clauses
UILib_InputArray INPUT ARRAY, plus ARR_CURR and SCR_LINE
UILib_Construct CONSTRUCT, returning the WHERE fragment
UILib_DisplayArray, UILib_keylist, FormField, FglWindowAttribute

The two INPUT bindings are the whole data path: one fills InBind from
the program's variables, the other reads RSet back into them. RSet is
an ASqlResult, the same type a FETCH returns, so an INPUT reads its
fields back with the same GetData calls - which is right, because in
4GL a screen record and a table row are the same thing. FglRow gained
a constructor from a UI event's field values to make that work.

UI is an instance property on FglModule, like SQL, so the channel and
the dialog contexts belong to the session.

DISPLAYTO was wrong and is now right. The generated protocol stub
carried its values as one opaque string; the real message sends the
field list and the values as two parallel arrays, neither
null-terminated, with a numeric ATTRIBUTE of -1 when the statement
named none, and values tagged with the 4GL type code the client
formats by. It was found by reading lib/libui/ui_json/json.c and then
confirmed against the live C runtime - the first version of this was
modelled on uilib.c, which is a different backend and disagrees.

It is the single most common thing a generated program sends - 83 call
sites in the demo corpus - so the UI probe now covers it: two fields,
two 4GL types, and the blank padding a CHAR keeps on its way to the
form. The two streams agree byte for byte.

A protocol guard test earned its keep here, failing the moment two
records claimed the DISPLAYTO verb.

Fidelity: 27 semantics, 9 UI messages, 30 USING, the 66-line report and
5 end-to-end programs all agree with C. 203 runtime tests pass.

2026-09-02 17:12:44 Tree
[r13060] by mikeaubury

configure: stop the usage-report prompt killing configure on a headless build

The tty probe in AUBIT_USAGE_REPORT was written as

if test -c /dev/tty && { exec 9</dev/tty; } 2>/dev/null; then

A brace group is not a subshell - it runs in the current shell - so a
failing exec redirection terminates that shell. /dev/tty is exactly the
case where that bites: the device node exists, so test -c passes, but
opening it fails whenever the process has no controlling terminal.

So on every scripted install - Ansible, CI, a docker build - configure
printed its summary, died silently at that line, and exited 1 with no
error message. The macro's own comment promises it "can never make
configure fail", which is what it was trying to do by redirecting
stderr; the redirect hides the message but not the death.

Attempting the open in a subshell contains the failure:

if test -c /dev/tty && ( exec 9</dev/tty ) 2>/dev/null; then

Verified with setsid and no stdin: configure now reaches "Run 'make' to
build." and exits 0, and still exits 0 with a terminal present.

Also add a fourth path to the informix/esql/decimal.h probe. The three
existing ones all assume a distribution include directory - pgsql/,
postgresql/, pg/ - but with a versioned prefix such as PGDG's
/usr/pgsql-18 the headers sit directly under the include directory, so
the path relative to -I is a bare informix/esql/decimal.h. That is also
the path the HAVE_PG_INFORMIX_ESQL_DECIMAL_H branch of
a4gl_esql_postgres.h actually includes, so the check now matches what
the code does.

Worth noting for anyone reading a config.log: these header probes
reporting "no", with gcc's "fatal error: ... No such file or directory"
underneath, is what a negative AC_CHECK_HEADER looks like. It is the
test doing its job, not a build failure - and nothing in a PostgreSQL
build consumes those defines anyway, since a4gl_esql_postgres.h is
included only by lib/libsql/esqlc, which configure does not build.

2026-09-02 17:01:52 Tree
Older >