Menu

SVN-Code Commit Log


Commit Date  
[r13051] by mikeaubury

Add the C# generator plug-in source (lex_cs)

lex_cs was copied into the tree but never added to SVN, so it - and the
retargeting in r13050 - existed only in a working copy. This adds the 16
source files the plug-in builds from, 432K in total.

Deliberately NOT added: the directory also holds about 35M of backup
copies (latest/, 250210/, CM/, old1/, backup_221009/), seven copies of
the same 1.7M tarball, and .exe/.dll/.mdb binaries including an Informix
DLL. Those are ignored rather than versioned; they are still on disk if
any of them turn out to matter.

The plug-in is still not built by the top-level make - it has to be
built by hand in lib/liblex/lex_cs. Wiring it in is a separate decision,
since it would make every build depend on it.

2026-09-02 07:45:49 Tree
[r13050] by mikeaubury

Retarget the C# generator onto the .NET runtime

The CSNEW generator already built and worked - it was simply never wired
into the top-level build. Retargeting it turned out to be a handful of
edits rather than a rewrite:

namespace and using -> Aubit4GL / Aubit4GL.Generated
base class -> FglModule, which carries the session
DATE -> DateOnly, an exact match
DECIMAL and MONEY -> decimal (this is where unknown_8 dies)
DATETIME, INTERVAL -> FglDateTime, FglInterval
BYTE and TEXT -> byte[]
SMALLINT -> short, not int
CLIPPED, LENGTH,
UPSHIFT and friends -> Fgl.*

DISPLAY now emits its expressions as separate arguments rather than
concatenating them, because 4GL renders each value at its type's own
width - an INTEGER in 11 columns, a SMALLINT in 6 - and joining them
into one string first threw that away. SMALLINT mapping to int? had the
same effect and is fixed.

A new end-to-end probe compiles ONE 4GL program through BOTH toolchains
and diffs what they print. It is the only check that exercises the
generator and the runtime together; every other probe tests a
hand-written .NET side. It passes.

Known gap, recorded at the head of the probe: CHAR(n) maps to a bare
string, so its declared width is lost and an unclipped CHAR prints
without its padding. Fixing that means carrying the width into the
declaration and routing assignment through Assign(), which touches the
declaration, LET and parameter paths.

2026-09-02 07:44:09 Tree
[r13049] by mikeaubury

.NET: REPORT engine

Page and line tracking, the four margins, COLUMN positioning, SKIP, NEED,
page breaks, and the aggregates. A probe compares a report's output
against the C runtime line for line - nothing normalised, since a report
is entirely about column and page layout - and all 66 lines match.

The state follows BaseFGLReport from the original C# library, which had
the data model right even though the behaviour was never written. The
layout defaults were read out of the generated C rather than guessed:
page length 66, margins top 3, bottom 3, left 5, right 132.

COUNT(*) and SUM/AVG keep separate counters: COUNT counts rows while the
others only see non-null values, so a row with a NULL still counts but
does not drag the average down.

2026-09-02 07:33:32 Tree
[r13048] by mikeaubury

.NET: USING format engine

Thirty formats now render identically to the C runtime, checked by a new
probe. Padding is significant here, so values are bracketed and compared
exactly rather than trimmed.

Four rules the probe corrected me on, all of which look wrong coming
from another language:

0 is a LITERAL, not a digit placeholder - the zero-fill character is &.
"###,##0.00" is valid in Oracle and means something else entirely in
4GL, and the C is right to render 1234.5 as 12,340.00 for it.

A zero integer part is blank under #: 0 with "###" is three spaces.

Fill is per position, not per field - one & in "##&" does not zero-fill
the other two.

Sign and currency characters occupy digit positions, so "-----" is five
of them; treating them as decoration overflows the field to asterisks.
Parentheses are the exception and never hold a digit. A single sign sits
where the mask puts it, a run of them floats to the first digit.

2026-09-02 07:29:25 Tree
[r13047] by mikeaubury

.NET: 4GL builtin functions

LENGTH, CLIPPED, UPSHIFT, DOWNSHIFT, ORD, ASCII, the substring operator,
MDY, DAY, MONTH, YEAR, WEEKDAY and DBDATE-aware date formatting - all
checked against the C runtime through the probe, which now compares 27
values rather than 13.

Two details worth having pinned down: the substring operator is 1-based
and inclusive at both ends, so s[1,5] is five characters and not four;
and WEEKDAY counts Sunday as 0, which the C confirms by giving 4 for
29 February 2024. The probe also agrees on day number 45350 for that
date, which independently checks the epoch.

Substrings step in characters, so a subscript cannot cut a surrogate
pair in half.

The divergence note in the probe was stale and has been corrected: the C
no longer leaves a partial character behind when a CHAR is truncated,
but the width is still counted in bytes there and in characters here.

2026-09-02 07:06:32 Tree
[r13046] by mikeaubury

.NET: protocol probe covers MENU; two mismatches it found

The probe now compares canonical JSON rather than text. The C wraps its
output in an envelope and spreads nested objects over many lines, so a
textual diff was only testing formatting; both streams are now parsed
and re-emitted sorted, with the C's array terminators dropped.

Two real differences surfaced once MENU was covered:

Dialog contexts were numbered from 1 here and from 0 in the C. Clients
key on the value, so they now start at 0.

EXIT MENU compiles to a menu action entry the C sends alongside the
commands - {"ACTION":"fgl_exit_menu","CMD_NO_TIMEOUT":n} - which was
never emitted. AddAction() sends it, so a menu built here is the same
menu on the wire.

Eight messages now identical, including the whole nested MENU.

2026-09-02 07:02:03 Tree
[r13045] by mikeaubury

.NET: protocol-level fidelity probe, and a row/column fix it found

dotnet/fidelity/ui/ runs the same sequence of UI operations through both
runtimes and diffs the message streams. The envelope and PROGRAMSTARTUP
are filtered out - a .NET program does not reproduce those and should
not - so what is compared is the message bodies.

It failed on its first run, and the bug was mine: in DISPLAYAT, X is the
COLUMN and Y is the ROW, so 4GL's "AT row, column" is transposed on the
wire. I had it the wrong way round in both the probe and the reference
example, where DISPLAY ... AT n, 1 was emitting X:n, Y:1. It only shows
up when the row and column differ, which is why AT 1,1 looked fine.

Now six messages byte-identical across the two runtimes. DisplayAt says
which field is which, so it does not get repeated.

2026-09-02 06:53:09 Tree
[r13044] by mikeaubury

.NET: complete UI protocol coverage

The remaining 38 verbs, with field names and order transcribed from the
format strings in lib/libui/ui_json. All 66 verbs the C runtime emits
now have a .NET counterpart.

A coverage test guards it: it lists every verb the C emits and fails if
one has no .NET message, which is the only way a protocol split across
two runtimes stays in step. A second test rejects two messages claiming
the same verb - which immediately caught WAITFOREVENT being declared
twice. The C emits it both bare and with CONTEXT/CACHED, so one type now
covers both and omits the fields rather than sending nulls.

2026-09-02 06:51:35 Tree
[r13043] by mikeaubury

.NET: CONSTRUCT, DISPLAY ARRAY and INPUT ARRAY

CONSTRUCT is close to INPUT but not the same - no WITHOUT_DEFAULTS, and
a Columns array naming the database column each screen field searches,
which is what the WHERE clause it produces is written in terms of.

The array dialogs send their rows up front. Row data keeps its padding,
unlike a menu option's text, because it fills fixed-width screen fields.
ARRLINE and SCRLINE are tracked separately: they differ once the list
has scrolled, and conflating them is a standard porting bug.

INPUT ARRAY turned out not to be DISPLAY ARRAY with a different verb -
it carries MAXARRSIZE, WITHOUT_DEFAULTS, ALLOWINSERT, ALLOWDELETE,
NONEWLINES and WRAP as well. Caught by checking the emitter rather than
assuming the two matched.

2026-09-02 06:49:04 Tree
[r13042] by mikeaubury

.NET: INPUT dialog

Modelled from what the C runtime emits for INPUT BY NAME, not from the
source. Three details that only show up in the real output: Fields is
not null-terminated while Events is, event entries use a lowercase
"event" key rather than "type", and event ids are 1-based.

The dialog is declared once - fields, then the events wanted - and the
client drives it, reporting each event by id. Field values arrive with
the events (the reply's SVS array of FN/FT/T/Value) and accumulate, so
a program reads them by name and field_touched() works.

Nested arrays now carry their own null-termination flag, since MENU and
INPUT disagree about it.

2026-09-02 06:45:14 Tree
Older >