Files
five/hbrtl/register.go
CharlesKWON d98f5e1767 feat(pgserver): PostgreSQL-wire MVP — psql can SELECT from FiveSql2
First end-to-end working version of the PostgreSQL-wire-compatible
TCP server frontend. A standard `psql` client now connects, runs
`SELECT * FROM employees`, and gets back a properly typed result
set rendered by psql with the right column alignment:

    ID |         NAME         |  SALARY
    ----+----------------------+----------
      1 | Alice                | 50000.00
      2 | Bob                  | 42000.50
      3 | Cho                  | 77500.00

This is the Phase 2 deliverable from the approved plan at
/Users/charleskwon/.claude/plans/compiled-launching-shore.md.
Builds on the session-state refactor in 93cf5c8 — each connection
gets its own TSqlSession on the PRG side via the new PG_NEW_SESSION
HB_FUNC, so concurrent psql clients won't share transaction logs
or plan caches.

Scope
-----

v1.0 MVP: Simple Query only, trust auth, no TLS yet. SELECT works
against the full FiveSql2 surface (CTEs, window functions, JOINs,
aggregates). DML + per-session transactions are Phase 3, extended
protocol is Phase 4, auth + TLS are Phases 5/6.

Architecture
------------

  psql/pgx/JDBC ──TCP:5432──▶ pgserver.Listener
                                  │ accept()
                                  ▼ go handleConn(net.Conn)
                             ┌─────────────────────────────┐
                             │ Session goroutine            │
                             │  1. SSLRequest peek          │
                             │  2. StartupMessage           │
                             │  3. AuthenticationOk (trust) │
                             │  4. ParameterStatus×7        │
                             │  5. BackendKeyData           │
                             │  6. ReadyForQuery('I')       │
                             │  7. loop: Receive() →        │
                             │     dispatchSimpleQuery →    │
                             │     hbrt.Thread.Function(    │
                             │       FIVE_SQL,sql,...,sess) │
                             │     emit RowDescription      │
                             │     emit DataRow×N           │
                             │     emit CommandComplete     │
                             │     emit ReadyForQuery       │
                             └─────────────────────────────┘

One goroutine per connection, each owning its own *hbrt.Thread and
TSqlSession instance. Uses the existing audit-fixed NewThread()
(cde8673) so statics + WA factory propagate.

New files (hbrtl/pgserver/)
---------------------------

* server.go — Config, Server, Serve loop with MaxConnections gate
  via semaphore, Close drains in-flight sessions.
* session.go — full lifecycle: SSLRequest peek + prefixedConn
  byte-injection trick for StartupMessage, ParameterStatus
  broadcast (server_version "14.0 (FiveSql2)" so pgx negotiates),
  BackendKeyData (random pid+secret per session, no CancelRequest
  yet), query loop dispatching only Simple Query in v1.0 with a
  loud "0A000 not supported" for Extended messages.
* dispatch.go — runSQL invokes FIVE_SQL via PushSymbol+Function,
  unpacks the engine's `{aFieldNames, aRows}` envelope or the
  `{{"__error__"}, {{nCode, cMsg, cSQL}}}` error shape, emits
  RowDescription with text-format OIDs and DataRow per row.
* typemap.go — pgTypeFor() picks INT4 / INT8 / NUMERIC / TEXT /
  DATE / TIMESTAMP / BOOL by sampling the first row's value type;
  encodeText() formats each cell, returning nil-slice for NULL
  (the PG length=-1 convention).
* errmap.go — sqlStateFor() maps FiveSql2 SQL_ERR_* codes to
  canonical PG SQLSTATEs (42601/42P01/42703/42804/23505/23514/
  23503/25P02/42501/02000/XX000).
* auth.go — trust mode in v1.0; password/MD5/SCRAM lands Phase 5
  but the dispatch sentinel is already in place.
* tls.go — upgradeToTLS stub for SSLRequest handling; the byte-
  ordering is already wired so Phase 6 just plugs in tls.Config.
* register.go — package init() registers pg_server_start /
  pg_server_stop HB_FUNCs. Importing the package (done from
  hbrtl/register.go via blank import) is enough to enable them.
* pgserver_test.go — unit tests for encodeText (numeric, string,
  NIL), pgTypeFor (OID dispatch), sqlStateFor (error mapping),
  commandTagFor (SELECT/INSERT/UPDATE/DELETE/BEGIN/COMMIT).

Other changes
-------------

* _FiveSql2/src/TSqlSession.prg — added PG_NEW_SESSION() factory
  used by the Go dispatcher to allocate a per-connection session
  bypassing the embedded process default.
* hbrtl/register.go — blank-import five/hbrtl/pgserver so its
  init() fires and the HB_FUNCs land in the global dynamic-func
  table for VM symbol lookup.
* go.mod / go.sum — github.com/jackc/pgx/v5 v5.9.2 (pgproto3
  subpackage). MIT license. Same library pgx itself uses, so
  protocol coverage matches the de-facto Go PG ecosystem.

Verification
------------

  $ pg_server_start(15432, "trust")     /* PRG one-liner */
  $ psql -h 127.0.0.1 -p 15432 -U fiveuser -c 'SELECT * FROM employees'
  → 3 rows rendered correctly by psql (ID as INT4, NAME as TEXT,
    SALARY as NUMERIC(10,2) with 2 decimal places)

All six release gates green:
  go test ./...               ✓ (incl. new hbrtl/pgserver tests)
  FiveSql2 SQL:1999 43/43     ✓
  Harbour compat 56/56        ✓
  std.ch 17/17                ✓
  FRB 7/7                     ✓
  examples 65/71              ✓ (unchanged baseline)

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-16 18:40:32 +09:00

825 lines
33 KiB
Go

// Copyright (c) 2026 Charles KWON OhJun (charleskwonohjun@gmail.com)
// All rights reserved.
// RTL registration for the Five runtime library.
// Centralized registration following tsgo's NodeFactory pattern.
package hbrtl
import (
"five/hbrdd"
"five/hbrt"
_ "five/hbrtl/pgserver" // registers pg_server_start / pg_server_stop HB_FUNCs
"strings"
)
// RegisterRTL registers all standard library functions with the VM.
func RegisterRTL(vm *hbrt.VM) {
// Auto-create WorkAreaManager for each thread
vm.SetWAFactory(func() interface{} {
return hbrdd.NewWorkAreaManager()
})
// Restore terminal on exit
vm.SetOnExit(func() {
RestoreTerminal()
})
mod := hbrt.NewModule("_RTL",
// Console
hbrt.Sym("QOUT", hbrt.FsPublic, rtlQOut),
hbrt.Sym("QQOUT", hbrt.FsPublic, rtlQQOut),
hbrt.Sym("OUTSTD", hbrt.FsPublic, rtlOutStd),
hbrt.Sym("OUTERR", hbrt.FsPublic, rtlOutErr),
// Strings / Conversion
hbrt.Sym("STR", hbrt.FsPublic, Str),
hbrt.Sym("VAL", hbrt.FsPublic, Val),
hbrt.Sym("LEN", hbrt.FsPublic, Len),
hbrt.Sym("SUBSTR", hbrt.FsPublic, SubStr),
hbrt.Sym("UPPER", hbrt.FsPublic, Upper),
hbrt.Sym("LOWER", hbrt.FsPublic, Lower),
hbrt.Sym("ALLTRIM", hbrt.FsPublic, AllTrim),
hbrt.Sym("LTRIM", hbrt.FsPublic, LTrim),
hbrt.Sym("RTRIM", hbrt.FsPublic, RTrim),
hbrt.Sym("TRIM", hbrt.FsPublic, RTrim), // TRIM = RTRIM in Harbour
hbrt.Sym("SPACE", hbrt.FsPublic, Space),
hbrt.Sym("PADR", hbrt.FsPublic, PadR),
hbrt.Sym("PADL", hbrt.FsPublic, PadL),
hbrt.Sym("REPLICATE", hbrt.FsPublic, Replicate),
// Type / Conversion
hbrt.Sym("VALTYPE", hbrt.FsPublic, ValType),
hbrt.Sym("EMPTY", hbrt.FsPublic, Empty),
hbrt.Sym("ABS", hbrt.FsPublic, Abs),
hbrt.Sym("INT", hbrt.FsPublic, Int),
// Array
hbrt.Sym("AADD", hbrt.FsPublic, AAdd),
hbrt.Sym("ADEL", hbrt.FsPublic, ADel),
hbrt.Sym("AINS", hbrt.FsPublic, AIns),
hbrt.Sym("ASIZE", hbrt.FsPublic, ASize),
hbrt.Sym("ACLONE", hbrt.FsPublic, AClone),
hbrt.Sym("HBDEEPCLONE", hbrt.FsPublic, HbDeepClone),
hbrt.Sym("HB_DEEPCOPY", hbrt.FsPublic, HbDeepClone),
hbrt.Sym("ACOPY", hbrt.FsPublic, ACopy),
hbrt.Sym("AFILL", hbrt.FsPublic, AFill),
hbrt.Sym("ASORT", hbrt.FsPublic, ASort),
hbrt.Sym("AEVAL", hbrt.FsPublic, AEval),
hbrt.Sym("ASCAN", hbrt.FsPublic, AScan),
hbrt.Sym("ATAIL", hbrt.FsPublic, ATail),
// Hash
hbrt.Sym("HB_HASH", hbrt.FsPublic, HbHash),
hbrt.Sym("HB_HGET", hbrt.FsPublic, HbHGet),
hbrt.Sym("HB_HSET", hbrt.FsPublic, HbHSet),
hbrt.Sym("HB_HDEL", hbrt.FsPublic, HbHDel),
hbrt.Sym("HB_HHASKEY", hbrt.FsPublic, HbHHasKey),
hbrt.Sym("HB_HKEYS", hbrt.FsPublic, HbHKeys),
hbrt.Sym("HB_HVALUES", hbrt.FsPublic, HbHValues),
// Date / Time
hbrt.Sym("DATE", hbrt.FsPublic, Date),
hbrt.Sym("TIME", hbrt.FsPublic, Time),
hbrt.Sym("YEAR", hbrt.FsPublic, Year),
hbrt.Sym("MONTH", hbrt.FsPublic, Month),
hbrt.Sym("DAY", hbrt.FsPublic, Day),
hbrt.Sym("DOW", hbrt.FsPublic, DOW),
hbrt.Sym("SECONDS", hbrt.FsPublic, Seconds),
hbrt.Sym("DTOC", hbrt.FsPublic, DToC),
hbrt.Sym("DTOS", hbrt.FsPublic, DToS),
hbrt.Sym("STOD", hbrt.FsPublic, SToD),
// Eval
hbrt.Sym("EVAL", hbrt.FsPublic, rtlEval),
hbrt.Sym("DO", hbrt.FsPublic, rtlDo),
// String (new)
hbrt.Sym("AT", hbrt.FsPublic, At),
hbrt.Sym("LEFT", hbrt.FsPublic, Left),
hbrt.Sym("RIGHT", hbrt.FsPublic, Right),
hbrt.Sym("ASC", hbrt.FsPublic, Asc),
hbrt.Sym("CHR", hbrt.FsPublic, Chr),
hbrt.Sym("STRTRAN", hbrt.FsPublic, StrTran),
hbrt.Sym("STUFF", hbrt.FsPublic, Stuff),
hbrt.Sym("PADC", hbrt.FsPublic, PadC),
hbrt.Sym("HB_STRREPLACE", hbrt.FsPublic, HbStrReplace),
hbrt.Sym("HB_NTOS", hbrt.FsPublic, HbNToS),
// Math (new)
hbrt.Sym("ROUND", hbrt.FsPublic, Round),
hbrt.Sym("MAX", hbrt.FsPublic, Max),
hbrt.Sym("MIN", hbrt.FsPublic, Min),
hbrt.Sym("SQRT", hbrt.FsPublic, Sqrt),
hbrt.Sym("LOG", hbrt.FsPublic, Log),
hbrt.Sym("EXP", hbrt.FsPublic, Exp),
hbrt.Sym("MOD", hbrt.FsPublic, Mod),
// Date (new)
hbrt.Sym("CTOD", hbrt.FsPublic, CToD),
hbrt.Sym("CDOW", hbrt.FsPublic, CDoW),
hbrt.Sym("CMONTH", hbrt.FsPublic, CMonth),
// Misc (new)
hbrt.Sym("TYPE", hbrt.FsPublic, TypeFunc),
hbrt.Sym("PCOUNT", hbrt.FsPublic, PCount),
hbrt.Sym("BREAK", hbrt.FsPublic, Break),
hbrt.Sym("ARRAY", hbrt.FsPublic, ArrayFunc),
hbrt.Sym("FCOUNT", hbrt.FsPublic, FCount),
hbrt.Sym("FIELDNAME", hbrt.FsPublic, FieldName),
hbrt.Sym("SELECT", hbrt.FsPublic, SelectFunc),
hbrt.Sym("FILE", hbrt.FsPublic, FileFunc),
hbrt.Sym("INKEY", hbrt.FsPublic, Inkey),
hbrt.Sym("TRANSFORM", hbrt.FsPublic, Transform),
hbrt.Sym("SETDATEFORMAT", hbrt.FsPublic, rtlSetDateFormat),
hbrt.Sym("SETEPOCH", hbrt.FsPublic, rtlSetEpoch),
hbrt.Sym("SETCENTURY", hbrt.FsPublic, rtlSetCentury),
// Terminal
hbrt.Sym("SETPOS", hbrt.FsPublic, SetPos),
hbrt.Sym("ROW", hbrt.FsPublic, Row),
hbrt.Sym("COL", hbrt.FsPublic, Col),
hbrt.Sym("DEVPOS", hbrt.FsPublic, DevPos),
hbrt.Sym("DEVOUT", hbrt.FsPublic, DevOut),
hbrt.Sym("DISPOUT", hbrt.FsPublic, DispOut),
hbrt.Sym("DEVOUTPICT", hbrt.FsPublic, DevOutPict),
hbrt.Sym("DISPBOX", hbrt.FsPublic, DispBox),
hbrt.Sym("CLS", hbrt.FsPublic, Cls),
hbrt.Sym("SCROLL", hbrt.FsPublic, Scroll),
hbrt.Sym("SETCOLOR", hbrt.FsPublic, SetColor),
hbrt.Sym("SETCURSOR", hbrt.FsPublic, SetCursor),
hbrt.Sym("MAXROW", hbrt.FsPublic, MaxRow),
hbrt.Sym("MAXCOL", hbrt.FsPublic, MaxCol),
// dbEdit / Browse / TBrowse
hbrt.Sym("DBEDIT", hbrt.FsPublic, DbEdit),
hbrt.Sym("TBROWSEDB", hbrt.FsPublic, rtlTBrowseDB),
hbrt.Sym("TBROWSENEW", hbrt.FsPublic, rtlTBrowseNew),
hbrt.Sym("TBCOLUMNNEW", hbrt.FsPublic, rtlTBColumnNew),
// RDD functions
hbrt.Sym("EOF", hbrt.FsPublic, rtlEOF),
hbrt.Sym("BOF", hbrt.FsPublic, rtlBOF),
hbrt.Sym("FOUND", hbrt.FsPublic, rtlFound),
hbrt.Sym("RECNO", hbrt.FsPublic, rtlRecNo),
hbrt.Sym("RECCOUNT", hbrt.FsPublic, rtlRecCount),
hbrt.Sym("LASTREC", hbrt.FsPublic, rtlRecCount), // alias
hbrt.Sym("DELETED", hbrt.FsPublic, rtlDeleted),
hbrt.Sym("FIELDGET", hbrt.FsPublic, rtlFieldGet),
// Database callable functions
hbrt.Sym("FIELDPUT", hbrt.FsPublic, rtlFieldPut),
hbrt.Sym("ALIAS", hbrt.FsPublic, rtlAlias),
hbrt.Sym("DBEVAL", hbrt.FsPublic, rtlDbEval),
hbrt.Sym("USED", hbrt.FsPublic, Used),
hbrt.Sym("DBUSEAREA", hbrt.FsPublic, rtlDbUseArea),
hbrt.Sym("DBCLOSEAREA", hbrt.FsPublic, rtlDbCloseArea),
hbrt.Sym("DBCLOSEALL", hbrt.FsPublic, rtlDbCloseAll),
hbrt.Sym("DBGOTO", hbrt.FsPublic, rtlDbGoTo),
hbrt.Sym("DBSKIP", hbrt.FsPublic, rtlDbSkip),
hbrt.Sym("DBGOTOP", hbrt.FsPublic, rtlDbGoTop),
hbrt.Sym("DBGOBOTTOM", hbrt.FsPublic, rtlDbGoBottom),
hbrt.Sym("DBAPPEND", hbrt.FsPublic, rtlDbAppend),
hbrt.Sym("DBDELETE", hbrt.FsPublic, rtlDbDelete),
hbrt.Sym("DBRECALL", hbrt.FsPublic, rtlDbRecall),
hbrt.Sym("DBCOMMIT", hbrt.FsPublic, rtlDbCommit),
hbrt.Sym("DBRLOCK", hbrt.FsPublic, rtlDbRLock),
hbrt.Sym("DBRUNLOCK", hbrt.FsPublic, rtlDbRUnlock),
hbrt.Sym("FLOCK", hbrt.FsPublic, rtlFLock),
hbrt.Sym("DBUNLOCK", hbrt.FsPublic, rtlDbUnlock),
hbrt.Sym("DBSEEK", hbrt.FsPublic, rtlDbSeek),
hbrt.Sym("DBSELECTAREA", hbrt.FsPublic, rtlDbSelectArea),
hbrt.Sym("DBPACK", hbrt.FsPublic, rtlDbPack),
hbrt.Sym("DBZAP", hbrt.FsPublic, rtlDbZap),
hbrt.Sym("RECALL", hbrt.FsPublic, rtlDbRecall),
hbrt.Sym("PACK", hbrt.FsPublic, rtlDbPack),
hbrt.Sym("ZAP", hbrt.FsPublic, rtlDbZap),
hbrt.Sym("__DBPACK", hbrt.FsPublic, rtlDbPack),
hbrt.Sym("__DBZAP", hbrt.FsPublic, rtlDbZap),
hbrt.Sym("DBRECALL", hbrt.FsPublic, rtlDbRecall),
// Locate / Filter
hbrt.Sym("DBLOCATE", hbrt.FsPublic, rtlDbLocate),
hbrt.Sym("__DBLOCATE", hbrt.FsPublic, rtlDbLocate),
hbrt.Sym("__DBCONTINUE", hbrt.FsPublic, rtlDbContinue),
hbrt.Sym("__DBAVERAGE", hbrt.FsPublic, rtlDbAverage),
hbrt.Sym("__DBCOPY", hbrt.FsPublic, rtlDbCopy),
hbrt.Sym("__DBSORT", hbrt.FsPublic, rtlDbSort),
hbrt.Sym("__DBLIST", hbrt.FsPublic, rtlDbList),
hbrt.Sym("__DBTOTAL", hbrt.FsPublic, rtlDbTotal),
hbrt.Sym("__DBJOIN", hbrt.FsPublic, rtlDbJoin),
hbrt.Sym("__DBUPDATE", hbrt.FsPublic, rtlDbUpdate),
hbrt.Sym("__DBNOTIMPL", hbrt.FsPublic, rtlDbNotImpl),
hbrt.Sym("DBSETFILTER", hbrt.FsPublic, rtlDbSetFilter),
hbrt.Sym("DBCLEARFILTER", hbrt.FsPublic, rtlDbClearFilter),
hbrt.Sym("DBFILTER", hbrt.FsPublic, rtlDbFilter),
// Encoding / Hashing (Go stdlib)
hbrt.Sym("HB_MD5", hbrt.FsPublic, HbMD5),
hbrt.Sym("HB_SHA256", hbrt.FsPublic, HbSHA256),
hbrt.Sym("HB_BASE64ENCODE", hbrt.FsPublic, HbBase64Encode),
hbrt.Sym("HB_BASE64DECODE", hbrt.FsPublic, HbBase64Decode),
hbrt.Sym("HB_CRC32", hbrt.FsPublic, HbCRC32),
// Bit operations (Go native)
hbrt.Sym("HB_BITAND", hbrt.FsPublic, HbBitAnd),
hbrt.Sym("HB_BITOR", hbrt.FsPublic, HbBitOr),
hbrt.Sym("HB_BITXOR", hbrt.FsPublic, HbBitXor),
hbrt.Sym("HB_BITNOT", hbrt.FsPublic, HbBitNot),
hbrt.Sym("HB_BITSHIFT", hbrt.FsPublic, HbBitShift),
hbrt.Sym("HB_BITTEST", hbrt.FsPublic, HbBitTest),
hbrt.Sym("HB_BITSET", hbrt.FsPublic, HbBitSet),
hbrt.Sym("HB_BITRESET", hbrt.FsPublic, HbBitReset),
// Regex (Go regexp)
hbrt.Sym("HB_REGEXCOMP", hbrt.FsPublic, HbRegexComp),
hbrt.Sym("HB_REGEXMATCH", hbrt.FsPublic, HbRegexMatch),
hbrt.Sym("HB_REGEXSPLIT", hbrt.FsPublic, HbRegexSplit),
hbrt.Sym("HB_REGEXALL", hbrt.FsPublic, HbRegexAll),
hbrt.Sym("HB_REGEXREPLACE", hbrt.FsPublic, HbRegexReplace),
// String (additional)
hbrt.Sym("RAT", hbrt.FsPublic, Rat),
hbrt.Sym("STRZERO", hbrt.FsPublic, StrZero),
hbrt.Sym("DESCEND", hbrt.FsPublic, Descend),
hbrt.Sym("HB_VALTOSTR", hbrt.FsPublic, HbValToStr),
hbrt.Sym("HB_VALTOEXP", hbrt.FsPublic, HbValToExp),
hbrt.Sym("HB_CSTR", hbrt.FsPublic, HbCStr),
hbrt.Sym("HB_NTOS", hbrt.FsPublic, HbNtos),
hbrt.Sym("MEMOREAD", hbrt.FsPublic, MemoRead),
hbrt.Sym("MEMOWRIT", hbrt.FsPublic, MemoWrit),
hbrt.Sym("MEMOTRAN", hbrt.FsPublic, MemoTran),
// Binary conversion
hbrt.Sym("BIN2I", hbrt.FsPublic, Bin2I),
hbrt.Sym("BIN2L", hbrt.FsPublic, Bin2L),
hbrt.Sym("BIN2W", hbrt.FsPublic, Bin2W),
hbrt.Sym("I2BIN", hbrt.FsPublic, I2Bin),
hbrt.Sym("L2BIN", hbrt.FsPublic, L2Bin),
hbrt.Sym("W2BIN", hbrt.FsPublic, W2Bin),
// Keyboard
hbrt.Sym("LASTKEY", hbrt.FsPublic, LastKey),
hbrt.Sym("NEXTKEY", hbrt.FsPublic, NextKey),
hbrt.Sym("READKEY", hbrt.FsPublic, ReadKeyFunc),
hbrt.Sym("SETKEY", hbrt.FsPublic, SetKeyFunc),
hbrt.Sym("KEYBOARD", hbrt.FsPublic, Keyboard),
hbrt.Sym("HB_KEYPUT", hbrt.FsPublic, HbKeyPut),
// Display
hbrt.Sym("DISPBEGIN", hbrt.FsPublic, DispBegin),
hbrt.Sym("DISPEND", hbrt.FsPublic, DispEnd),
hbrt.Sym("DISPCOUNT", hbrt.FsPublic, DispCount),
hbrt.Sym("SAVESCREEN", hbrt.FsPublic, SaveScreen),
hbrt.Sym("RESTSCREEN", hbrt.FsPublic, RestScreen),
hbrt.Sym("ALERT", hbrt.FsPublic, Alert),
// Error handling
hbrt.Sym("ERRORBLOCK", hbrt.FsPublic, ErrorBlock),
hbrt.Sym("ERRORNEW", hbrt.FsPublic, ErrorNew),
hbrt.Sym("DOSERROR", hbrt.FsPublic, DosError),
hbrt.Sym("FERROR", hbrt.FsPublic, FError),
// SET commands
hbrt.Sym("SET", hbrt.FsPublic, SetFunc),
hbrt.Sym("__SETDATEFORMAT", hbrt.FsPublic, SetDateFunc),
hbrt.Sym("__SETDECIMALS", hbrt.FsPublic, SetDecimalsFunc),
hbrt.Sym("__SETEPOCH", hbrt.FsPublic, SetEpochFunc),
// SET toggle functions
hbrt.Sym("SETDELETED", hbrt.FsPublic, SetDeletedFunc),
hbrt.Sym("SETEXACT", hbrt.FsPublic, SetExactFunc),
hbrt.Sym("SETSOFTSEEK", hbrt.FsPublic, SetSoftSeekFunc),
hbrt.Sym("SETEXCLUSIVE", hbrt.FsPublic, SetExclusiveFunc),
hbrt.Sym("SETFIXED", hbrt.FsPublic, SetFixedFunc),
hbrt.Sym("SETCANCEL", hbrt.FsPublic, SetCancelFunc),
hbrt.Sym("SETBELL", hbrt.FsPublic, SetBellFunc),
hbrt.Sym("SETCONFIRM", hbrt.FsPublic, SetConfirmFunc),
hbrt.Sym("SETINSERT", hbrt.FsPublic, SetInsertFunc),
hbrt.Sym("SETESCAPE", hbrt.FsPublic, SetEscapeFunc),
hbrt.Sym("SETWRAP", hbrt.FsPublic, SetWrapFunc),
// SET constants
hbrt.Sym("_SET_EXACT", hbrt.FsPublic, SetConstExact),
hbrt.Sym("_SET_DELETED", hbrt.FsPublic, SetConstDeleted),
hbrt.Sym("_SET_SOFTSEEK", hbrt.FsPublic, SetConstSoftSeek),
hbrt.Sym("_SET_EXCLUSIVE", hbrt.FsPublic, SetConstExclusive),
hbrt.Sym("_SET_DATEFORMAT", hbrt.FsPublic, SetConstDateFmt),
hbrt.Sym("_SET_DECIMALS", hbrt.FsPublic, SetConstDecimals),
hbrt.Sym("_SET_EPOCH", hbrt.FsPublic, SetConstEpoch),
// Error handling
hbrt.Sym("ERRORBLOCK", hbrt.FsPublic, ErrorBlock),
hbrt.Sym("ERRORNEW", hbrt.FsPublic, ErrorNew),
hbrt.Sym("DOSERROR", hbrt.FsPublic, DosError),
hbrt.Sym("FERROR", hbrt.FsPublic, FError),
hbrt.Sym("BREAK", hbrt.FsPublic, Break),
hbrt.Sym("HB_ERRORLOG", hbrt.FsPublic, HbErrorLog),
hbrt.Sym("HB_SETERRORLOGPATH", hbrt.FsPublic, HbSetErrorLogPath),
hbrt.Sym("HB_SETERRORLOGHOOK", hbrt.FsPublic, HbSetErrorLogHook),
// File I/O
hbrt.Sym("FOPEN", hbrt.FsPublic, FOpen),
hbrt.Sym("FCREATE", hbrt.FsPublic, FCreate),
hbrt.Sym("FCLOSE", hbrt.FsPublic, FClose),
hbrt.Sym("FREAD", hbrt.FsPublic, FRead),
hbrt.Sym("FWRITE", hbrt.FsPublic, FWrite),
hbrt.Sym("FSEEK", hbrt.FsPublic, FSeek),
hbrt.Sym("FERASE", hbrt.FsPublic, FErase),
hbrt.Sym("FRENAME", hbrt.FsPublic, FRename),
hbrt.Sym("HB_FILEEXISTS", hbrt.FsPublic, HbFileExists),
// Directory/Disk
hbrt.Sym("CURDIR", hbrt.FsPublic, CurDir),
hbrt.Sym("DIRCHANGE", hbrt.FsPublic, DirChange),
hbrt.Sym("DIRECTORY", hbrt.FsPublic, Directory),
hbrt.Sym("DIRMAKE", hbrt.FsPublic, DirMake),
hbrt.Sym("DIRREMOVE", hbrt.FsPublic, DirRemove),
// Type checking (HB_IS*)
hbrt.Sym("HB_ISARRAY", hbrt.FsPublic, HbIsArray),
// Classic Clipper/Harbour aliases — `common.ch` #translate rules
// map these to HB_IS*. Registering the short names as direct
// symbols bypasses the PP altogether and makes them work even
// when code doesn't include common.ch.
hbrt.Sym("ISARRAY", hbrt.FsPublic, HbIsArray),
hbrt.Sym("HB_ISBLOCK", hbrt.FsPublic, HbIsBlock),
hbrt.Sym("ISBLOCK", hbrt.FsPublic, HbIsBlock),
hbrt.Sym("HB_ISCHAR", hbrt.FsPublic, HbIsChar),
hbrt.Sym("HB_ISSTRING", hbrt.FsPublic, HbIsString),
hbrt.Sym("ISCHARACTER", hbrt.FsPublic, HbIsString),
hbrt.Sym("ISMEMO", hbrt.FsPublic, HbIsString), // memo ≈ string for Five
hbrt.Sym("HB_ISDATE", hbrt.FsPublic, HbIsDate),
hbrt.Sym("ISDATE", hbrt.FsPublic, HbIsDate),
hbrt.Sym("HB_ISDATETIME", hbrt.FsPublic, HbIsDateTime),
hbrt.Sym("HB_ISLOGICAL", hbrt.FsPublic, HbIsLogical),
hbrt.Sym("ISLOGICAL", hbrt.FsPublic, HbIsLogical),
hbrt.Sym("HB_ISNUMERIC", hbrt.FsPublic, HbIsNumeric),
hbrt.Sym("ISNUMBER", hbrt.FsPublic, HbIsNumeric),
hbrt.Sym("ISNUMERIC", hbrt.FsPublic, HbIsNumeric),
hbrt.Sym("HB_ISOBJECT", hbrt.FsPublic, HbIsObject),
hbrt.Sym("ISOBJECT", hbrt.FsPublic, HbIsObject),
hbrt.Sym("HB_ISHASH", hbrt.FsPublic, HbIsHash),
hbrt.Sym("HB_ISNIL", hbrt.FsPublic, HbIsNil),
hbrt.Sym("ISNIL", hbrt.FsPublic, HbIsNil),
hbrt.Sym("HB_ISPOINTER", hbrt.FsPublic, HbIsPointer),
// OS/Environment
hbrt.Sym("GETENV", hbrt.FsPublic, GetEnv),
hbrt.Sym("HB_GETENV", hbrt.FsPublic, HbGetEnv),
hbrt.Sym("SETENV", hbrt.FsPublic, SetEnvFunc),
hbrt.Sym("OS", hbrt.FsPublic, OSFunc),
hbrt.Sym("VERSION", hbrt.FsPublic, VersionFunc),
hbrt.Sym("HB_RUN", hbrt.FsPublic, HbRun),
hbrt.Sym("HB_FNAMEDIR", hbrt.FsPublic, HbFNameDir),
hbrt.Sym("HB_FNAMEEXT", hbrt.FsPublic, HbFNameExt),
hbrt.Sym("HB_FNAMENAME", hbrt.FsPublic, HbFNameName),
hbrt.Sym("HB_FNAMEMERGE", hbrt.FsPublic, HbFNameMerge),
// Character classification
hbrt.Sym("ISDIGIT", hbrt.FsPublic, IsDigit),
hbrt.Sym("ISALPHA", hbrt.FsPublic, IsAlpha),
hbrt.Sym("ISALNUM", hbrt.FsPublic, IsAlnum),
hbrt.Sym("ISUPPER", hbrt.FsPublic, IsUpper),
hbrt.Sym("ISLOWER", hbrt.FsPublic, IsLower),
hbrt.Sym("ISSPACE", hbrt.FsPublic, IsSpace),
// Harbour extension functions
hbrt.Sym("HB_ISEVALITEM", hbrt.FsPublic, HbIsEvalItem),
hbrt.Sym("HB_ASCIIUPPER", hbrt.FsPublic, HbAsciiUpper),
hbrt.Sym("HB_ASCIILOWER", hbrt.FsPublic, HbAsciiLower),
hbrt.Sym("HB_DEFAULT", hbrt.FsPublic, HbDefault),
hbrt.Sym("HB_DEFAULTVALUE", hbrt.FsPublic, HbDefaultValue),
hbrt.Sym("HB_DISPOUTAT", hbrt.FsPublic, HbDispOutAt),
hbrt.Sym("HB_COLORINDEX", hbrt.FsPublic, HbColorIndex),
hbrt.Sym("HB_LEFTEQ", hbrt.FsPublic, HbLeftEq),
hbrt.Sym("HB_VAL", hbrt.FsPublic, HbVal),
hbrt.Sym("HB_KEYCHAR", hbrt.FsPublic, HbKeyChar),
hbrt.Sym("HB_KEYINS", hbrt.FsPublic, HbKeyIns),
hbrt.Sym("FIELDWBLOCK", hbrt.FsPublic, FieldWBlock),
hbrt.Sym("MEMVARBLOCK", hbrt.FsPublic, MemVarBlock),
hbrt.Sym("__DEFAULTNIL", hbrt.FsPublic, DefaultNIL),
hbrt.Sym("HB_DISPOUTATBOX", hbrt.FsPublic, HbDispOutAtBox),
hbrt.Sym("HB_DISPBOX", hbrt.FsPublic, HbDispBox),
hbrt.Sym("HB_TOKENGET", hbrt.FsPublic, HbTokenGet),
hbrt.Sym("HB_TOKENCOUNT", hbrt.FsPublic, HbTokenCount),
// Bitmap/Rushmore
hbrt.Sym("BM_DBSETFILTER", hbrt.FsPublic, BmDbSetFilter),
hbrt.Sym("BM_DBSEEKWILD", hbrt.FsPublic, BmDbSeekWild),
hbrt.Sym("BM_TURBO", hbrt.FsPublic, BmTurbo),
hbrt.Sym("BM_DBGETFILTERARRAY", hbrt.FsPublic, BmDbGetFilterArray),
hbrt.Sym("BM_DBSETFILTERARRAY", hbrt.FsPublic, BmDbSetFilterArray),
hbrt.Sym("BM_DBSETFILTERARRAYADD", hbrt.FsPublic, BmDbSetFilterArrayAdd),
hbrt.Sym("BM_DBSETFILTERARRAYDEL", hbrt.FsPublic, BmDbSetFilterArrayDel),
// HBSIX compatibility
hbrt.Sym("SX_SETTAG", hbrt.FsPublic, SxSetTag),
hbrt.Sym("SX_INDEXTAG", hbrt.FsPublic, SxIndexTag),
hbrt.Sym("SX_TAGORDER", hbrt.FsPublic, SxTagOrder),
hbrt.Sym("SX_TAGCOUNT", hbrt.FsPublic, SxTagCount),
hbrt.Sym("SX_TAGS", hbrt.FsPublic, SxTags),
hbrt.Sym("SX_SETFILEORD", hbrt.FsPublic, SxSetFileOrd),
hbrt.Sym("SX_ISDBT", hbrt.FsPublic, SxIsDBT),
hbrt.Sym("SX_ISFPT", hbrt.FsPublic, SxIsFPT),
hbrt.Sym("SX_ISSMT", hbrt.FsPublic, SxIsSMT),
hbrt.Sym("SX_AUTOOPEN", hbrt.FsPublic, SxAutoOpen),
hbrt.Sym("SX_AUTOSHARE", hbrt.FsPublic, SxAutoShare),
hbrt.Sym("SX_BLOB2FILE", hbrt.FsPublic, SxBlob2File),
hbrt.Sym("SX_FILE2BLOB", hbrt.FsPublic, SxFile2Blob),
hbrt.Sym("SX_SETTRIGGER", hbrt.FsPublic, SxSetTrigger),
hbrt.Sym("SX_VFGET", hbrt.FsPublic, SxVFGet),
hbrt.Sym("SX_DBFENCRYPT", hbrt.FsPublic, SxDbfEncrypt),
hbrt.Sym("SX_DBFDECRYPT", hbrt.FsPublic, SxDbfDecrypt),
hbrt.Sym("SX_COMPRESS", hbrt.FsPublic, SxCompress),
hbrt.Sym("SX_DECOMPRESS", hbrt.FsPublic, SxDecompress),
hbrt.Sym("RDDINFO", hbrt.FsPublic, RddInfo),
hbrt.Sym("RDDNAME", hbrt.FsPublic, RddName),
hbrt.Sym("RDDLIST", hbrt.FsPublic, RddList),
// Timestamp
hbrt.Sym("HB_DATETIME", hbrt.FsPublic, HbDateTime),
hbrt.Sym("HB_HOUR", hbrt.FsPublic, HbHour),
hbrt.Sym("HB_MINUTE", hbrt.FsPublic, HbMinute),
hbrt.Sym("HB_SEC", hbrt.FsPublic, HbSec),
hbrt.Sym("HB_TTOC", hbrt.FsPublic, HbTToC),
hbrt.Sym("HB_CTOT", hbrt.FsPublic, HbCToT),
hbrt.Sym("HB_SECOND", hbrt.FsPublic, HbSecond),
hbrt.Sym("HB_ATOKENS", hbrt.FsPublic, HbATokens),
hbrt.Sym("HB_CDPSELECT", hbrt.FsPublic, HbCdpSelect),
hbrt.Sym("DBSETINDEX", hbrt.FsPublic, rtlDbSetIndex),
hbrt.Sym("HB_TTOS", hbrt.FsPublic, HbTToS),
hbrt.Sym("HB_STOT", hbrt.FsPublic, HbSToT),
hbrt.Sym("HB_MILLISECONDS", hbrt.FsPublic, HbMilliseconds),
// Index / DB introspection
hbrt.Sym("INDEXORD", hbrt.FsPublic, IndexOrd),
hbrt.Sym("INDEXKEY", hbrt.FsPublic, IndexKey),
hbrt.Sym("ORDSETFOCUS", hbrt.FsPublic, OrdSetFocus),
hbrt.Sym("ORDCREATE", hbrt.FsPublic, OrdCreate),
hbrt.Sym("DBCREATEINDEX", hbrt.FsPublic, DbCreateIndex),
hbrt.Sym("DBCLEARINDEX", hbrt.FsPublic, DbClearIndex),
hbrt.Sym("FIELDTYPE", hbrt.FsPublic, FieldType),
hbrt.Sym("FIELDLEN", hbrt.FsPublic, FieldLen),
hbrt.Sym("FIELDDEC", hbrt.FsPublic, FieldDec),
hbrt.Sym("ORDCOUNT", hbrt.FsPublic, OrdCount),
hbrt.Sym("ORDLISTREBUILD", hbrt.FsPublic, OrdListRebuild),
hbrt.Sym("ORDERLISTREBUILD", hbrt.FsPublic, OrdListRebuild),
hbrt.Sym("DBREINDEX", hbrt.FsPublic, OrdListRebuild),
hbrt.Sym("ORDNAME", hbrt.FsPublic, OrdName),
hbrt.Sym("ORDKEY", hbrt.FsPublic, OrdKey),
hbrt.Sym("ORDFOR", hbrt.FsPublic, OrdFor),
hbrt.Sym("DBINFO", hbrt.FsPublic, DbInfo),
hbrt.Sym("ORDINFO", hbrt.FsPublic, OrdInfo),
hbrt.Sym("ORDSCOPE", hbrt.FsPublic, OrdScope),
hbrt.Sym("DBORDERINFO", hbrt.FsPublic, DbOrderInfo),
hbrt.Sym("RDDSETDEFAULT", hbrt.FsPublic, RddSetDefault),
hbrt.Sym("DBCREATE", hbrt.FsPublic, DbCreate),
// Directory / Temp file (session 1)
hbrt.Sym("HB_DIREXISTS", hbrt.FsPublic, HbDirExists),
hbrt.Sym("HB_DIRCREATE", hbrt.FsPublic, HbDirCreate),
hbrt.Sym("HB_FTEMPCREATE", hbrt.FsPublic, HbFTempCreate),
hbrt.Sym("HB_FNAMESPLIT", hbrt.FsPublic, HbFNameSplit),
// File extended (session 2)
hbrt.Sym("HB_FSIZE", hbrt.FsPublic, HbFSize),
hbrt.Sym("HB_FCOPY", hbrt.FsPublic, HbFCopy),
hbrt.Sym("HB_FEOF", hbrt.FsPublic, HbFEof),
hbrt.Sym("HB_FCOMMIT", hbrt.FsPublic, HbFCommit),
hbrt.Sym("HB_FREADLEN", hbrt.FsPublic, HbFReadLen),
hbrt.Sym("HB_FGETATTR", hbrt.FsPublic, HbFGetAttr),
hbrt.Sym("HB_FSETATTR", hbrt.FsPublic, HbFSetAttr),
hbrt.Sym("HB_FGETDATETIME", hbrt.FsPublic, HbFGetDateTime),
hbrt.Sym("HB_FSETDATETIME", hbrt.FsPublic, HbFSetDateTime),
hbrt.Sym("HB_FLOCK", hbrt.FsPublic, HbFLock),
hbrt.Sym("HB_FUNLOCK", hbrt.FsPublic, HbFUnlock),
hbrt.Sym("HB_FILEDELETE", hbrt.FsPublic, HbFileDelete),
hbrt.Sym("HB_FILEMATCH", hbrt.FsPublic, HbFileMatch),
hbrt.Sym("HB_FNAMEEXISTS", hbrt.FsPublic, HbFNameExists),
hbrt.Sym("HB_FNAMEEXTSET", hbrt.FsPublic, HbFNameExtSet),
hbrt.Sym("HB_FNAMENAMEEXT", hbrt.FsPublic, HbFNameNameExt),
hbrt.Sym("HB_MEMOREAD", hbrt.FsPublic, HbMemoRead),
hbrt.Sym("HB_MEMOWRIT", hbrt.FsPublic, HbMemoWrit),
hbrt.Sym("HB_DIRTEMP", hbrt.FsPublic, HbDirTemp),
hbrt.Sym("HB_DISKSPACE", hbrt.FsPublic, HbDiskSpace),
hbrt.Sym("DISKSPACE", hbrt.FsPublic, DiskSpaceFunc),
// String extended (session 2)
hbrt.Sym("HB_AT", hbrt.FsPublic, HbAt),
hbrt.Sym("HB_RAT", hbrt.FsPublic, HbRat),
hbrt.Sym("HB_ATI", hbrt.FsPublic, HbAtI),
hbrt.Sym("HB_ATX", hbrt.FsPublic, HbAtX),
hbrt.Sym("HB_LEFTEQI", hbrt.FsPublic, HbLeftEqI),
hbrt.Sym("HB_ASCIIISALPHA", hbrt.FsPublic, HbAsciiIsAlpha),
hbrt.Sym("HB_ASCIIISDIGIT", hbrt.FsPublic, HbAsciiIsDigit),
hbrt.Sym("HB_ASCIIISLOWER", hbrt.FsPublic, HbAsciiIsLower),
hbrt.Sym("HB_ASCIIISUPPER", hbrt.FsPublic, HbAsciiIsUpper),
hbrt.Sym("HB_STRISUTF8", hbrt.FsPublic, HbStrIsUtf8),
hbrt.Sym("HB_STRDECODESCAPE", hbrt.FsPublic, HbStrDecodeEscape),
hbrt.Sym("HB_STRXOR", hbrt.FsPublic, HbStrXor),
hbrt.Sym("HB_WILDMATCH", hbrt.FsPublic, HbWildMatch),
hbrt.Sym("HB_WILDMATCHI", hbrt.FsPublic, HbWildMatchI),
hbrt.Sym("HARDCR", hbrt.FsPublic, HardCR),
// DateTime extended (session 2)
hbrt.Sym("HB_DATE", hbrt.FsPublic, HbDate),
hbrt.Sym("HB_CTOD", hbrt.FsPublic, HbCToD),
hbrt.Sym("HB_DTOC", hbrt.FsPublic, HbDToC),
hbrt.Sym("HB_STOD", hbrt.FsPublic, HbSToD),
hbrt.Sym("HB_DTOT", hbrt.FsPublic, HbDToT),
hbrt.Sym("HB_TTOD", hbrt.FsPublic, HbTToD),
hbrt.Sym("HB_TTOHOUR", hbrt.FsPublic, HbTToHour),
hbrt.Sym("HB_TTOMIN", hbrt.FsPublic, HbTToMin),
hbrt.Sym("HB_TTOSEC", hbrt.FsPublic, HbTToSec),
hbrt.Sym("HB_TTOMSEC", hbrt.FsPublic, HbTToMsec),
hbrt.Sym("HB_TTON", hbrt.FsPublic, HbTToN),
hbrt.Sym("HB_NTOT", hbrt.FsPublic, HbNToT),
hbrt.Sym("HB_NTOHOUR", hbrt.FsPublic, HbNToHour),
hbrt.Sym("HB_NTOMIN", hbrt.FsPublic, HbNToMin),
hbrt.Sym("HB_NTOSEC", hbrt.FsPublic, HbNToSec),
hbrt.Sym("HB_WEEK", hbrt.FsPublic, HbWeek),
hbrt.Sym("HB_CDAY", hbrt.FsPublic, HbCDay),
hbrt.Sym("DAYS", hbrt.FsPublic, Days),
hbrt.Sym("ELAPTIME", hbrt.FsPublic, ElapTime),
hbrt.Sym("AMPM", hbrt.FsPublic, AMPM),
hbrt.Sym("SECS", hbrt.FsPublic, Secs),
// Utilities (session 2)
hbrt.Sym("HB_SETENV", hbrt.FsPublic, HbSetEnv),
hbrt.Sym("HB_PS", hbrt.FsPublic, HbPS),
hbrt.Sym("HB_EOL", hbrt.FsPublic, HbEOL),
hbrt.Sym("HB_ISNULL", hbrt.FsPublic, HbIsNull),
hbrt.Sym("ERRORSYS", hbrt.FsPublic, ErrorSys),
// Token
hbrt.Sym("TOKEN", hbrt.FsPublic, Token),
hbrt.Sym("NUMTOKEN", hbrt.FsPublic, NumToken),
// Hex conversion
hbrt.Sym("HB_NUMTOHEX", hbrt.FsPublic, HbNumToHex),
hbrt.Sym("HB_HEXTONUM", hbrt.FsPublic, HbHexToNum),
// Hash position access
hbrt.Sym("HB_HPOS", hbrt.FsPublic, HbHPos),
hbrt.Sym("HB_HKEYAT", hbrt.FsPublic, HbHKeyAt),
hbrt.Sym("HB_HVALUEAT", hbrt.FsPublic, HbHValueAt),
hbrt.Sym("HB_HCLONE", hbrt.FsPublic, HbHClone),
// Sleep
hbrt.Sym("HB_IDLESLEEP", hbrt.FsPublic, HbIdleSleep),
// UTF-8
hbrt.Sym("HB_UTF8TOSTR", hbrt.FsPublic, HbUTF8ToStr),
hbrt.Sym("HB_STRTOUTF8", hbrt.FsPublic, HbStrToUTF8),
hbrt.Sym("HB_UTF8LEN", hbrt.FsPublic, HbUTF8Len),
hbrt.Sym("HB_UTF8SUBSTR", hbrt.FsPublic, HbUTF8SubStr),
// Stack introspection
hbrt.Sym("PROCNAME", hbrt.FsPublic, ProcName),
hbrt.Sym("PROCLINE", hbrt.FsPublic, ProcLine),
hbrt.Sym("PROCFILE", hbrt.FsPublic, ProcFile),
hbrt.Sym("ERRORLEVEL", hbrt.FsPublic, ErrorLevel),
// Field/DB introspection
hbrt.Sym("FIELDPOS", hbrt.FsPublic, FieldPos),
hbrt.Sym("FIELDBLOCK", hbrt.FsPublic, FieldBlockFunc),
hbrt.Sym("FIELDNAME", hbrt.FsPublic, FieldNameFunc),
hbrt.Sym("AFIELDS", hbrt.FsPublic, AFields),
hbrt.Sym("DBSTRUCT", hbrt.FsPublic, DbStruct),
// Misc
hbrt.Sym("TONE", hbrt.FsPublic, Tone),
hbrt.Sym("CENTER", hbrt.FsPublic, Center),
hbrt.Sym("SOUNDEX", hbrt.FsPublic, Soundex),
// JSON — Harbour compatible
hbrt.Sym("HB_JSONENCODE", hbrt.FsPublic, HbJsonEncode),
hbrt.Sym("HB_JSONDECODE", hbrt.FsPublic, HbJsonDecode),
// JSON — Five extensions (Go-native)
hbrt.Sym("JSONPRETTY", hbrt.FsPublic, JsonPretty),
hbrt.Sym("JSONTO", hbrt.FsPublic, JsonTo),
hbrt.Sym("JSONFROM", hbrt.FsPublic, JsonFrom),
hbrt.Sym("JSONPATH", hbrt.FsPublic, JsonPath),
hbrt.Sym("JSONMERGE", hbrt.FsPublic, JsonMerge),
hbrt.Sym("JSONTYPE", hbrt.FsPublic, JsonType),
hbrt.Sym("JSONVALID", hbrt.FsPublic, JsonValid),
hbrt.Sym("JSONHTTPGET", hbrt.FsPublic, JsonHttpGet),
hbrt.Sym("JSONHTTPPOST", hbrt.FsPublic, JsonHttpPost),
// Random
hbrt.Sym("HB_RANDOM", hbrt.FsPublic, HbRandom),
hbrt.Sym("HB_RANDOMINT", hbrt.FsPublic, HbRandomInt),
hbrt.Sym("HB_RANDOMSEED", hbrt.FsPublic, HbRandomSeed),
hbrt.Sym("HB_RANDSTR", hbrt.FsPublic, HbRandStr),
// OS Info
hbrt.Sym("HB_VERSION", hbrt.FsPublic, HbVersion),
hbrt.Sym("HB_COMPILER", hbrt.FsPublic, HbCompiler),
hbrt.Sym("HB_OSNEWLINE", hbrt.FsPublic, HbOsNewLine),
hbrt.Sym("HB_OSPATHSEPARATOR", hbrt.FsPublic, HbOsPathSeparator),
hbrt.Sym("HB_CWD", hbrt.FsPublic, HbCwd),
hbrt.Sym("HB_DIRBASE", hbrt.FsPublic, HbDirBase),
hbrt.Sym("HB_PROGNAME", hbrt.FsPublic, HbProgName),
hbrt.Sym("HB_USERNAME", hbrt.FsPublic, HbUserName),
hbrt.Sym("HB_GETHOSTNAME", hbrt.FsPublic, HbGetHostName),
// Process
hbrt.Sym("HB_PROCESSRUN", hbrt.FsPublic, HbProcessRun),
hbrt.Sym("WAIT", hbrt.FsPublic, WaitCmd),
// UTF-8 String
hbrt.Sym("HB_UTF8LEN", hbrt.FsPublic, HbUtf8Len),
hbrt.Sym("HB_UTF8SUBSTR", hbrt.FsPublic, HbUtf8Substr),
hbrt.Sym("HB_UTF8LEFT", hbrt.FsPublic, HbUtf8Left),
hbrt.Sym("HB_UTF8RIGHT", hbrt.FsPublic, HbUtf8Right),
hbrt.Sym("HB_UTF8AT", hbrt.FsPublic, HbUtf8At),
hbrt.Sym("HB_STRTOHEX", hbrt.FsPublic, HbStrToHex),
hbrt.Sym("HB_HEXTOSTR", hbrt.FsPublic, HbHexToStr),
hbrt.Sym("HB_STRFORMAT", hbrt.FsPublic, HbStrFormat),
// Memo line
hbrt.Sym("MEMOLINE", hbrt.FsPublic, MemoLine),
hbrt.Sym("MLCOUNT", hbrt.FsPublic, MlCount),
// FRB (Five Runtime Binary)
hbrt.Sym("FRBLOAD", hbrt.FsPublic, FrbLoadFunc),
hbrt.Sym("FRBDO", hbrt.FsPublic, FrbDoFunc),
hbrt.Sym("FRBUNLOAD", hbrt.FsPublic, FrbUnloadFunc),
hbrt.Sym("FRBRUN", hbrt.FsPublic, FrbRunFunc),
hbrt.Sym("FRBCOMPILE", hbrt.FsPublic, FrbCompileFunc),
hbrt.Sym("FRBEXEC", hbrt.FsPublic, FrbExecFunc),
// Expression bytecode compilation (FiveSql2 hot-path optimization)
hbrt.Sym("PCCOMPILE", hbrt.FsPublic, PcCompile),
hbrt.Sym("PCEVAL", hbrt.FsPublic, PcEval),
// Go-native SQL scan loop (bypasses PRG interpreter for hot path)
hbrt.Sym("SQLSCAN", hbrt.FsPublic, SqlScan),
hbrt.Sym("SQLEACH", hbrt.FsPublic, SqlEach),
hbrt.Sym("SQLHASHBUILD", hbrt.FsPublic, SqlHashBuild),
hbrt.Sym("SQLHASHJOIN", hbrt.FsPublic, SqlHashJoin),
hbrt.Sym("SQLORDERBY", hbrt.FsPublic, SqlOrderBy),
hbrt.Sym("SQLGROUPBY", hbrt.FsPublic, SqlGroupBy),
hbrt.Sym("SQLDISTINCT", hbrt.FsPublic, SqlDistinct),
hbrt.Sym("SQLUNIONDISTINCT", hbrt.FsPublic, SqlUnionDistinct),
hbrt.Sym("SQLBUILDSUBCACHEKEY", hbrt.FsPublic, SqlBuildSubCacheKey),
hbrt.Sym("SQLEXPRHASAGG", hbrt.FsPublic, SqlExprHasAgg),
hbrt.Sym("SQLBULKINSERT", hbrt.FsPublic, SqlBulkInsert),
hbrt.Sym("SQLBULKUPDATE", hbrt.FsPublic, SqlBulkUpdate),
hbrt.Sym("SQLBULKDELETE", hbrt.FsPublic, SqlBulkDelete),
hbrt.Sym("SQLWINDOWSLIDEAGG", hbrt.FsPublic, SqlWindowSlideAgg),
hbrt.Sym("SQLWINDOWPARTITIONS", hbrt.FsPublic, SqlWindowPartitions),
hbrt.Sym("SQLGROUPROWS", hbrt.FsPublic, SqlGroupRows),
hbrt.Sym("SQLCOMPUTEAGGSIMPLE", hbrt.FsPublic, SqlComputeAggSimple),
hbrt.Sym("SQLEVALHAVING", hbrt.FsPublic, SqlEvalHaving),
hbrt.Sym("SQLCOERCESTR", hbrt.FsPublic, SqlCoerceStr),
hbrt.Sym("SQLCOERCENUM", hbrt.FsPublic, SqlCoerceNum),
hbrt.Sym("SQLCOERCEFORCMP", hbrt.FsPublic, SqlCoerceForCmp),
hbrt.Sym("SQLISTRUE", hbrt.FsPublic, SqlIsTrue),
hbrt.Sym("SQLISAGGNAME", hbrt.FsPublic, SqlIsAggName),
hbrt.Sym("SQLFETCHROWFAST", hbrt.FsPublic, SqlFetchRowFast),
hbrt.Sym("SQLCMPEQ", hbrt.FsPublic, SqlCmpEq),
hbrt.Sym("SQLCMPLT", hbrt.FsPublic, SqlCmpLt),
hbrt.Sym("SQLEXTRACTTEMPLATE", hbrt.FsPublic, SqlExtractTemplate),
hbrt.Sym("SQLLEXERTOKENIZE", hbrt.FsPublic, SqlLexerTokenize),
hbrt.Sym("SQLLEXANDEXTRACTTEMPLATE", hbrt.FsPublic, SqlLexAndExtractTemplate),
hbrt.Sym("SQLWACACHEENABLE", hbrt.FsPublic, SqlWACacheEnable),
hbrt.Sym("SQLWACACHEDISABLE", hbrt.FsPublic, SqlWACacheDisable),
hbrt.Sym("SQLWACACHEISENABLED", hbrt.FsPublic, SqlWACacheIsEnabled),
hbrt.Sym("SQLWACACHEGET", hbrt.FsPublic, SqlWACacheGet),
hbrt.Sym("SQLWACACHEPUT", hbrt.FsPublic, SqlWACachePut),
hbrt.Sym("SQLWACACHEINVALIDATE", hbrt.FsPublic, SqlWACacheInvalidate),
hbrt.Sym("SQLWACACHECLOSEALL", hbrt.FsPublic, SqlWACacheCloseAll),
hbrt.Sym("SQLWINDOWSORTPARTITION", hbrt.FsPublic, SqlWindowSortPartition),
hbrt.Sym("SQLWINDOWASSIGNRANK", hbrt.FsPublic, SqlWindowAssignRank),
// Goroutine / Concurrency
hbrt.Sym("GO", hbrt.FsPublic, GoFunc),
hbrt.Sym("CHANNEL", hbrt.FsPublic, ChannelFunc),
hbrt.Sym("CHSEND", hbrt.FsPublic, ChSend),
hbrt.Sym("CHRECEIVE", hbrt.FsPublic, ChReceive),
hbrt.Sym("CHCLOSE", hbrt.FsPublic, ChClose),
hbrt.Sym("WAITGROUP", hbrt.FsPublic, WaitGroupFunc),
hbrt.Sym("WGDONE", hbrt.FsPublic, WgDone),
hbrt.Sym("WGWAIT", hbrt.FsPublic, WgWait),
hbrt.Sym("WGADD", hbrt.FsPublic, WgAdd),
hbrt.Sym("MUTEX", hbrt.FsPublic, MutexFunc),
hbrt.Sym("LOCK", hbrt.FsPublic, LockFunc),
hbrt.Sym("UNLOCK", hbrt.FsPublic, UnlockFunc),
hbrt.Sym("SLEEP", hbrt.FsPublic, SleepFunc),
)
vm.RegisterModule(mod)
}
// rtlQOut implements ? command as a variadic function.
func rtlQOut(t *hbrt.Thread) {
nParams := t.ParamCount()
t.Frame(nParams, 0)
defer t.EndProc()
args := make([]hbrt.Value, nParams)
for i := 0; i < nParams; i++ {
args[i] = t.Local(i + 1)
}
qoutImpl(args)
t.RetNil()
}
// rtlQQOut implements ?? command.
func rtlQQOut(t *hbrt.Thread) {
nParams := t.ParamCount()
t.Frame(nParams, 0)
defer t.EndProc()
args := make([]hbrt.Value, nParams)
for i := 0; i < nParams; i++ {
args[i] = t.Local(i + 1)
}
qqoutImpl(args)
t.RetNil()
}
// rtlDo — Harbour DO(xTarget, [arg1, ...]) → xResult.
//
// Dispatches the named function, code block, or symbol dynamically.
// String target: looked up in the VM symbol table (uppercased, like
// compile-time calls) and invoked. Block target: evaluated with the
// remaining args just like Eval. Anything else returns NIL.
//
// Reference: harbour-core/src/rtl/do.c HB_FUNC( DO ).
func rtlDo(t *hbrt.Thread) {
nParams := t.ParamCount()
t.Frame(nParams, 0)
defer t.EndProc()
if nParams < 1 {
t.RetNil()
return
}
target := t.Local(1)
nArgs := nParams - 1
switch {
case target.IsString():
name := strings.ToUpper(target.AsString())
vm := t.VM()
if vm == nil {
t.RetNil()
return
}
sym := vm.FindSymbol(name)
if sym == nil {
panic(&hbrt.HbError{
Description: "DO: unknown function " + target.AsString(),
Operation: "DO",
SubSystem: "BASE",
})
}
t.PushSymbol(sym)
t.PushNil() // self placeholder
for i := 2; i <= nParams; i++ {
t.PushValue(t.Local(i))
}
t.Function(nArgs)
// Function() leaves the callee's return value on the stack.
t.RetValue()
case target.IsBlock():
blk := target.AsBlock()
for i := 2; i <= nParams; i++ {
t.PushValue(t.Local(i))
}
t.PendingParams2(nArgs)
blk.Fn(t)
t.PushValue(t.GetRetValue())
t.RetValue()
default:
t.RetNil()
}
}
// rtlEval evaluates a code block.
// Harbour: Eval(bBlock, [xArg1, ...]) → xResult
func rtlEval(t *hbrt.Thread) {
nParams := t.ParamCount()
t.Frame(nParams, 0)
defer t.EndProc()
blkVal := t.Local(1)
if !blkVal.IsBlock() {
t.RetNil()
return
}
blk := blkVal.AsBlock()
// Push block args onto stack for the block's Frame() to pick up
blockArgs := nParams - 1
for i := 2; i <= nParams; i++ {
t.PushValue(t.Local(i))
}
// Call block function — it will call Frame(N, 0) internally
t.PendingParams2(blockArgs)
blk.Fn(t)
// Return block's result
t.PushValue(t.GetRetValue())
t.RetValue()
}