diff --git a/docs/reference/04-plib-core.md b/docs/reference/04-plib-core.md new file mode 100644 index 0000000..0f1b88a --- /dev/null +++ b/docs/reference/04-plib-core.md @@ -0,0 +1,458 @@ +# PLIB Core API Reference (Psion SIBO / Workabout MX) + +Categorised function reference for the core **PLIB** library, drawn from the +*PLIB Reference*, Version 2.10 (3 February 1995), (C) Psion PLC. + +## Conventions + +- Signatures are transcribed from the manual. The OCR source occasionally + mangles glyphs; signatures below are corrected to the manual's own C types + where the intent is unambiguous. Uncertain items are marked **[?]**. +- Types: `TEXT` = char/byte string, `UBYTE`/`BYTE`, `UWORD`/`WORD` (16-bit), + `UINT`/`INT` (16-bit), `ULONG`/`LONG` (32-bit), `DOUBLE` (64-bit float), + `VOID`, `HANDLE`, `BOOL`. +- Many functions return `0` on success and a negative `E_*` error number + (defined in `p_gen.h` etc.) on failure. +- `f_*` twins of `p_*` allocators/senders behave identically except they call + `p_leave(E_GEN_NOMEMORY)` / `p_leave(err)` instead of returning `NULL`/`err`. + +--- + +## 1. String & Buffer Handling + +Declared chiefly in `p_std.h` / `plib.h`. Buffers (`b*`) take an explicit +length; strings (`s*`) are zero-terminated. + +### 1.1 Copy, length, concatenate, fill + +| Signature | Purpose | +|---|---| +| `UBYTE *p_bcpy(VOID *target, VOID *source, UINT len);` | Copy `len` bytes source→target (overlap-safe); returns `target+len`. | +| `UINT p_slen(TEXT *str);` | Return length of zero-terminated string, excluding the terminator. | +| `TEXT *p_scpy(TEXT *target, TEXT *source);` | Copy string source→target; returns address of target's terminating zero. | +| `TEXT *p_scpym(TEXT *target, ...);` | Copy+concatenate a NULL-terminated list of strings into target. | +| `TEXT *p_scat(TEXT *lstr, TEXT *rstr);` | Append rstr to lstr; returns address of new terminating zero. | +| `TEXT *p_scatm(TEXT *lstr, ...);` | Append a NULL-terminated list of strings to lstr. | +| `UBYTE *p_brep(VOID *buf, INT buf_len, VOID *pattern, INT pat_len);` | Fill buf by replicating a byte pattern; returns `buf+buf_len`. | +| `TEXT *p_srep(TEXT *buf, INT buf_len, TEXT *pattern);` | Fill buf by replicating a string pattern (terminator excluded). | +| `VOID p_bswap(VOID *buf1, VOID *buf2, INT len);` | Swap `len` bytes between two buffers. | +| `UBYTE *p_bfil(VOID *buf, UINT buf_len, INT fill_byte);` | Fill buf with a repeated byte; returns `buf+buf_len`. | +| `TEXT *p_jtob(TEXT *tbuf, INT tlen, TEXT *sbuf, INT slen, INT type, INT fill);` | Left/right/centre-align sbuf in tbuf (`P_JLEFT`/`P_JRIGHT`/`P_JCENTRE`), padding with `fill`. | + +### 1.2 Comparison + +| Signature | Purpose | +|---|---| +| `INT p_bcmp(VOID *lbuf, INT lbuf_len, VOID *rbuf, INT rbuf_len);` | Compare two buffers byte-wise; returns lbuf−rbuf (<0 / 0 / >0). | +| `INT p_scmp(TEXT *lstr, TEXT *rstr);` | Compare two strings; returns lstr−rstr. | +| `INT p_bcmpi(TEXT *lbuf, INT lbuf_len, TEXT *rbuf, INT rbuf_len);` | Case-independent buffer compare. | +| `INT p_scmpi(TEXT *lstr, TEXT *rstr);` | Case-independent string compare. | + +*(OCR renders these as `p_bemp`/`p_bempi`; the intended names are `p_bcmp`/`p_bcmpi`.)* + +### 1.3 Searching (character, substring, wildcard) + +| Signature | Purpose | +|---|---| +| `INT p_bloc(VOID *buf, INT buf_len, INT ch);` | Index of first `ch` in buffer, or −1. | +| `INT p_sloc(TEXT *str, INT ch);` | Index of first `ch` in string, or −1. | +| `INT p_bloci(TEXT *buf, INT buf_len, INT ch);` | Case-independent forward char search in buffer. | +| `INT p_sloci(TEXT *str, INT ch);` | Case-independent forward char search in string. | +| `INT p_slocr(TEXT *str, INT ch);` | Reverse (last-occurrence) char search in string. | +| `INT p_slocri(TEXT *str, INT ch);` | Case-independent reverse char search in string. | +| `INT p_bsub(VOID *buf, INT buf_len, VOID *sbuf, INT sbuf_len);` | Index of first occurrence of a byte sequence in buffer, or −1. | +| `INT p_ssub(TEXT *str, TEXT *substr);` | Index of first occurrence of substring in string, or −1. | +| `INT p_bsubi(TEXT *buf, INT buf_len, TEXT *sbuf, INT sbuf_len);` | Case-independent buffer subsequence search. | +| `INT p_ssubi(TEXT *str, TEXT *substr);` | Case-independent substring search. | +| `INT p_bmatch(TEXT *buf, INT blen, TEXT *mbuf, INT mlen);` | Match buffer against a wildcard spec (`*`, `?`); returns TRUE/FALSE. | +| `INT p_bmatchi(TEXT *buf, INT blen, TEXT *mbuf, INT mlen);` | Case-independent wildcard buffer match. | +| `INT p_smatch(TEXT *str, TEXT *mstr);` | Match string against wildcard spec (`*`, `?`). | +| `INT p_smatchi(TEXT *str, TEXT *mstr);` | Case-independent wildcard string match. | + +### 1.4 Character classification (return TRUE/FALSE for `c` modulo 256) + +| Signature | Purpose | +|---|---| +| `INT p_isupper(INT c);` | Uppercase alphabetic (accented or not). | +| `INT p_islower(INT c);` | Lowercase alphabetic. | +| `INT p_isalpha(INT c);` | Alphabetic either case. | +| `INT p_isdigit(INT c);` | Decimal digit 0–9. | +| `INT p_isalnum(INT c);` | Alphanumeric. | +| `INT p_isxdigit(INT c);` | Hex digit 0–9, A–F, a–f. | +| `INT p_isspace(INT c);` | Whitespace (space, HT, NL, VT, FF, CR). | +| `INT p_iscntrl(INT c);` | Control character (0–31, 127). | +| `INT p_ispunct(INT c);` | Printable graphic, not alphanumeric/space. | +| `INT p_isgraph(INT c);` | Printable graphic (alnum or punct). | +| `INT p_isprint(INT c);` | Printable, i.e. `p_isgraph` plus space. | + +### 1.5 Folding & case conversion, skipping + +| Signature | Purpose | +|---|---| +| `TEXT *p_skipwh(TEXT *str);` | Skip leading whitespace; return first non-white char. | +| `TEXT *p_skipch(TEXT *str);` | Skip non-white chars; return first whitespace/terminator. | +| `INT p_tofold(INT c);` | Fold char via built-in fold table (for case-insensitive matching). | +| `TEXT *p_scpyf(TEXT *target, TEXT *source);` | Copy string folding each char (like `p_scpy`). | +| `VOID p_sconf(TEXT *str);` | Fold the characters of a string in place. | +| `INT p_toupper(INT c);` | Convert char to upper case (display use, not matching). | +| `INT p_tolower(INT c);` | Convert char to lower case (display use, not matching). | +| `VOID p_scap(TEXT *str);` | Capitalise string: first char upper, rest lower. *(EPOC 2.14+)* | + +> **Folding vs. case:** `p_tofold`/`p_sconf` are for case-insensitive +> ordering/matching (symbol tables); `p_toupper`/`p_tolower`/`p_scap` are for +> human-visible text and must **not** be used for comparison. + +--- + +## 2. Arrays, Queues & Sorting (misc utilities) + +Doubly-linked circular queues use `P_QUE` headers; delta queues use `P_DELTA`. + +| Signature | Purpose | +|---|---| +| `INT p_bsrch(INT nrec, INT (*compf)(), INT *pmid, UBYTE *pmatch);` | Binary search over `nrec` records via callback; writes found index to `*pmid`. | +| `INT p_qsort(INT nrec, INT (*ordf)(), VOID (*excf)(), UBYTE *base);` | Quicksort `nrec` records using ordering and exchange callbacks. | +| `VOID p_enque(P_QUE *pNew, P_QUE *pEntry);` | Insert `pNew` before `pEntry` in its doubly-linked queue. | +| `VOID p_deque(P_QUE *pEntry);` | Unlink `pEntry` from its queue. | + +*(The manual also documents `p_dequed` for delta queues; its clean signature is +not printed in the source text — **[?]**.)* + +--- + +## 3. CRC & Checksums + +| Signature | Purpose | +|---|---| +| `VOID p_crc(UWORD *pcrc, UBYTE *buf, UINT len);` | Incrementally accumulate CCITT CRC-16 (x¹⁶+x¹²+x⁵+1) over `len` bytes; init `*pcrc` to 0 first. | + +--- + +## 4. Console I/O + +Primitive console services layered on the `CON:` device / window server. The +console is opened automatically on first use. PLIB offers only line output of +mono-spaced text and simple backspace-edited line input; richer row/column +control lives in the `CON:` device driver, and full UI in the Window Server. +Internal buffer is `P_MAXSYSIO` (258) bytes, limiting output to 256 bytes/call. + +| Signature | Purpose | +|---|---| +| `VOID p_putch(UINT c);` | Write one character to the console. | +| `VOID p_puts(TEXT *str);` | Write a string and start a new line. | +| `VOID p_printf(TEXT *fstr, ...);` | Format args (as `p_atob`), write line, advance to next line. | +| `VOID p_print(TEXT *fstr, ...);` | As `p_printf` but no automatic newline (use `\r`,`\n`). | +| `INT p_getch(VOID);` | Wait for a keypress; return its character code. | +| `INT p_gets(TEXT *str);` | Read a line (backspace editing) up to `P_MAXSYSIO-1`; returns length. | +| `INT p_getl(TEXT *pmt, TEXT *str, INT len);` | Write prompt `pmt`, read up to `len` chars into `str`; returns length. | + +--- + +## 5. Number ↔ String Conversion + +Declared in the *Integer Conversion and Rectangle Functions* chapter. + +### 5.1 Integer/long → text + +| Signature | Purpose | +|---|---| +| `UINT p_itob(TEXT *buf, INT value);` | Signed decimal of INT → buf; returns chars written. | +| `INT p_ltob(TEXT *buf, LONG value);` | Signed decimal of LONG → buf; returns chars written. | +| `INT p_gtob(TEXT *buf, UINT value, INT radix);` | Unsigned UINT in any radix → buf. | +| `INT p_gltob(TEXT *buf, ULONG value, INT radix);` | Unsigned ULONG in any radix → buf. | + +### 5.2 Formatted multi-argument output + +| Signature | Purpose | +|---|---| +| `INT p_atob(TEXT *buf, TEXT *fstr, VOID *parg);` | `printf`-style format of arg list `parg` into buf; returns chars written. | +| `VOID p_atos(TEXT *str, TEXT *fstr, ...);` | Convenience variadic wrapper over `p_atob` producing a zero-terminated string. | + +Format `%[][]`; types: `b` binary, `c` char, `d` +signed dec, `f` fill only, `m`/`w` 2-byte MSB/LSB binary *(EPOC 2.17+)*, `o` +octal, `s` string, `u` unsigned dec, `x` hex. Widen to long with `l`/`L` or +upper-case type; ``/`` may be `*` (taken from args). + +### 5.3 Text → integer/long (radix conversions) + +All take `TEXT **pstr` (advanced past the parsed field on success), return 0 or +`E_GEN_OVER`/`E_GEN_FAIL`. + +| Signature | Purpose | +|---|---| +| `INT p_stoi(TEXT **pstr, WORD *pval);` | Signed decimal string → 16-bit WORD. | +| `INT p_stol(TEXT **pstr, LONG *pval);` | Signed decimal string → 32-bit LONG. | +| `INT p_stog(TEXT **pstr, UWORD *pval, INT radix);` | Unsigned string in any radix → 16-bit UWORD. | +| `INT p_stogl(TEXT **pstr, ULONG *pval, INT radix);` | Unsigned string in any radix → 32-bit ULONG. | +| `INT p_stoa(TEXT **pstr, TEXT *fstr, ...);` | Scan multiple fields from a string into args per format `fstr`. | + +### 5.4 Double ↔ text (floating point conversion) + +| Signature | Purpose | +|---|---| +| `INT p_dtob(TEXT *pbuf, DOUBLE *pval, P_DTOB *pformat);` | Format a double to text per `P_DTOB` (type/width/decimals/point/triad); returns chars or `E_GEN_*`. | +| `INT p_stod(TEXT **pstr, DOUBLE *pval, INT point);` | Parse a floating-point number from text (`point` = decimal-point char) → double. | + +> Note: the manual provides no `p_dtos` — double→string is `p_dtob`. + +--- + +## 6. Floating Point, Scientific & Math + +Declared in `p_math.h`. Trig args are in **radians**. `E_CONFIG`/config via +`p_getctd`. Two families exist: + +- **Scientific functions** (`p_sin` … `p_pow`) and `p_rand`/`p_frand` require the + 8087 emulator (`sys$8087.ldd`). +- **Arithmetic primitives** (`p_fld` … `p_longtof`) are emulator-independent — + usable to do FP without loading the emulator. + +Macros (also emulator-triggering with FP operands): `ABS(x)`, `MAX(a,b)`, `MIN(a,b)`. + +### 6.1 Scientific (require emulator) + +All return 0 or `E_GEN_ARG`/`E_GEN_UNDER`/`E_GEN_OVER`. + +| Signature | Purpose | +|---|---| +| `INT p_sin(DOUBLE *pret, DOUBLE *parg);` | Sine. | +| `INT p_cos(DOUBLE *pret, DOUBLE *parg);` | Cosine. | +| `INT p_tan(DOUBLE *pret, DOUBLE *parg);` | Tangent (arg magnitude limited). | +| `INT p_asin(DOUBLE *pret, DOUBLE *parg);` | Arc sine (`ABS(*parg)<=1`). | +| `INT p_acos(DOUBLE *pret, DOUBLE *parg);` | Arc cosine (`ABS(*parg)<=1`). | +| `INT p_atan(DOUBLE *pret, DOUBLE *parg);` | Arc tangent. | +| `INT p_ln(DOUBLE *pret, DOUBLE *parg);` | Natural (base-e) log. | +| `INT p_exp(DOUBLE *pret, DOUBLE *parg);` | e raised to `*parg`. | +| `INT p_log(DOUBLE *pret, DOUBLE *parg);` | Base-10 log. | +| `INT p_sqrt(DOUBLE *pret, DOUBLE *parg);` | Square root. | +| `INT p_pow(DOUBLE *pret, DOUBLE *parg1, DOUBLE *parg2);` | `*parg1` raised to `*parg2`. | + +### 6.2 Emulator-independent FP arithmetic + +For one-arg functions, `pret` and `parg` may alias. Return 0 or `E_GEN_*`. + +| Signature | Purpose | +|---|---| +| `INT p_fld(DOUBLE *pret, DOUBLE *parg);` | Load: `*pret = *parg`. | +| `INT p_fadd(DOUBLE *pret, DOUBLE *parg);` | `*pret += *parg`. | +| `INT p_fsub(DOUBLE *pret, DOUBLE *parg);` | `*pret -= *parg`. | +| `INT p_fmul(DOUBLE *pret, DOUBLE *parg);` | `*pret *= *parg`. | +| `INT p_fdiv(DOUBLE *pret, DOUBLE *parg);` | `*pret /= *parg`. | +| `INT p_fcmp(DOUBLE *parg1, DOUBLE *parg2);` | Compare: returns 1 / 0 / −1. *(OCR: `p_femp`.)* | +| `INT p_fneg(DOUBLE *parg);` | Negate `*parg` in place. | +| `INT p_mod(DOUBLE *pret, DOUBLE *parg1, DOUBLE *parg2);` | Remainder of `*parg1 / *parg2`. | +| `INT p_int(DOUBLE *pret, DOUBLE *parg);` | Integer part (toward zero) → double. | +| `INT p_inti(WORD *pret, DOUBLE *parg);` | Integer part → 16-bit WORD (range-checked). | +| `INT p_intl(LONG *pret, DOUBLE *parg);` | Integer part → 32-bit LONG (range-checked). | +| `VOID p_itof(DOUBLE *pret, WORD *parg);` | Convert WORD → double. | +| `VOID p_longtof(DOUBLE *pret, LONG *parg);` | Convert LONG → double. | + +### 6.3 Random numbers + +| Signature | Purpose | +|---|---| +| `ULONG p_randl(ULONG *pseed);` | Next pseudo-random 32-bit long; updates `*pseed`. (No emulator.) | +| `DOUBLE p_rand(ULONG *pseed);` | Random double in [0,1); updates `*pseed`. (Emulator required.) | +| `VOID p_frand(DOUBLE *pret, ULONG *pseed);` | Random double in [0,1) → `*pret`; updates `*pseed`. | + +> **Long integer arithmetic:** PLIB exposes no dedicated `p_lmul`/`p_ldiv` +> helpers; 32-bit `LONG`/`ULONG` work is done with native C, the `l*` +> conversion routines above, and `p_ltob`/`p_stol`/`p_stogl`/`p_randl`. + +--- + +## 7. Rectangle & Geometry Utilities + +Operate on `P_RECT` / `P_POINT` (declared with the integer-conversion chapter). + +| Signature | Purpose | +|---|---| +| `VOID p_offrec(P_RECT *rect, INT xoffset, INT yoffset);` | Move a rectangle by an offset. | +| `VOID p_insrec(P_RECT *rect, INT xinset, INT yinset);` | Shrink/expand a rectangle about its centre. | +| `VOID p_unirec(P_RECT *rect1, P_RECT *rect2, P_RECT *result);` | Union (smallest enclosing rectangle). | +| `INT p_intrec(P_RECT *rect1, P_RECT *rect2, P_RECT *result);` | Intersection; returns TRUE if they intersect. | +| `INT p_pinrec(P_POINT *point, P_RECT *rect);` | TRUE if point lies inside rectangle. | +| `INT p_emprec(P_RECT *rect);` | TRUE if rectangle is empty. | +| `VOID p_absrec(P_RECT *rect, P_RECT *result);` | Normalise negative sides to positive. | + +--- + +## 8. Memory Allocation & the Heap + +Heap cells are allocated from the process data segment (max ~64K). `f_*` +variants leave with `E_GEN_NOMEMORY` instead of returning `NULL`. + +### 8.1 Cell allocation + +| Signature | Purpose | +|---|---| +| `VOID *p_alloc(UINT size);` | Allocate a heap cell ≥ `size` bytes; returns address or `NULL`. | +| `VOID *f_alloc(UINT size);` | As `p_alloc` but leaves on failure. | +| `VOID p_free(VOID *pcell);` | Free a cell (no-op if `pcell` is 0). | +| `VOID *p_realloc(VOID *pcell, UINT size);` | Resize a cell (preserving contents); `pcell==0` ⇒ `p_alloc`. | +| `VOID *f_realloc(VOID *pcell, UINT size);` | As `p_realloc` but leaves on failure. | +| `VOID *p_adjust(VOID *pcell, UINT offset, INT amount);` | Open (+) or close (−) a gap mid-cell for insert/delete. | +| `UINT p_alen(VOID *pcell);` | Return actual cell length in bytes (≥ requested). | + +### 8.2 Heap tuning & diagnostics + +| Signature | Purpose | +|---|---| +| `VOID p_hgran(UINT nparas);` | Set heap growth granularity (paragraphs of 16 bytes; ≤ `E_MAX_GROWBY`). | +| `VOID p_allwalk(VOID (*fptr)(VOID *fpar, INT isalloc, UINT len), VOID *fpar);` | Walk every heap cell, calling `fptr`; panics on inconsistency. | +| `VOID p_allchk(INT num);` | Check allocated cells vs. free list; `p_panic(0xff)` with diagnostics if corrupt. | +| `UINT p_allspc(VOID **pheap);` | Return potential free heap space; write heap start to `*pheap`. | +| `p_altchk(...)` **[?]** | Thorough heap-integrity check (referenced by name; full signature not printed in source). | + +### 8.3 System memory info + +| Signature | Purpose | +|---|---| +| `UINT p_getram(VOID);` | Addressable system RAM in 16-byte paragraphs (≤ 32768). | +| `UINT p_totalK(VOID);` | Total machine RAM in KB, ignoring bank-switching. *(EPOC 3.50+)* | +| `UINT p_sgfree(VOID);` | Available addressable segmented memory in paragraphs. | +| `UINT p_sgramdisk(VOID);` | Paragraphs of addressable RAM used by the internal RAM disk. | + +### 8.4 External data segments (shared memory / IPC) + +| Signature | Purpose | +|---|---| +| `INT p_sgdelete(TEXT *pName);` | Delete a named external data segment. | +| `INT p_sgcopyto(HANDLE nHandle, LONG pos, VOID *source, UINT len);` | Write `len` bytes into an open segment at `pos`. | +| `INT p_sgcopyfr(HANDLE nHandle, LONG pos, VOID *target, UINT len);` | Read `len` bytes from an open segment at `pos`. | +| `UINT p_sgsize(HANDLE nHandle);` | Size of an open segment in 16-byte paragraphs. | +| `INT p_sgadjust(HANDLE nHandle, INT nParas);` | Grow/shrink an open segment by `nParas` paragraphs. | +| `INT p_sgclose(HANDLE nHandle);` | Close an open segment. | +| `VOID p_sglock(HANDLE nHandle);` | Lock a segment against relocation. | +| `VOID p_sgunlock(HANDLE nHandle);` | Unlock a previously locked segment. | + +*(The chapter also references `p_sgcreate`/`p_sgopen`/`p_sgfind`; their clean +signatures are not isolated in the source text — **[?]**.)* + +### 8.5 Environment variables + +| Signature | Purpose | +|---|---| +| `INT p_getenv(TEXT *pMatch, TEXT *pValue);` | Get value of matching env var (string). | +| `INT p_getenviron(TEXT *pMatch, INT mLength, VOID *pValue);` | Get env var value (binary, length-specified match). | +| `INT p_setenv(TEXT *pName, TEXT *pValue);` | Set/create a string env var. | +| `INT p_setenviron(TEXT *pName, INT nLength, VOID *pValue, INT vLength);` | Set a binary env var. | +| `INT p_delenv(TEXT *pMatch);` | Delete matching env var. | +| `INT p_delenviron(TEXT *pMatch, INT mLength);` | Delete env var (length-specified match). | +| `INT p_fndenv(TEXT *pMatch, TEXT *pName, TEXT *pValue, HANDLE *pHandle);` | Iterate/find env vars by name pattern. | +| `INT p_findenviron(TEXT *pMatch, INT mLength, UBYTE *pBuf, HANDLE *pHandle);` | Iterate/find env vars (binary). | + +--- + +## 9. Date, Time & Timers + +System time = seconds since 00:00:00 1 Jan 1970 (`ULONG`). Day-based math uses +`P_DAYSEC` (days since 1900 + seconds in day); human form uses `P_DATE` +(year-1900, month 0–11, day 0–30, h/m/s, yrday). Declared in `p_date.h`. + +### 9.1 System clock + +| Signature | Purpose | +|---|---| +| `ULONG p_date(VOID);` | Return current system time (seconds since 1970). | +| `VOID p_sdate(ULONG newTime);` | Set system time (may fire due absolute timers). | + +### 9.2 Sleeping / synchronous timers + +| Signature | Purpose | +|---|---| +| `INT p_sleep(ULONG n);` | Sleep `n` tenths of a second (relative timer). | +| `INT p_sleept(LONG nTicks);` | Sleep `nTicks` system ticks (32/s SIBO). | +| `INT p_sleepa(ULONG time);` | Sleep until absolute system `time` (wakes machine). | + +*(Asynchronous timers are driven through an open `TIM:` channel via +`p_ioc(P_FRELATIVE)` / `p_ioc(P_FABSOLUTE)` and cancelled with `p_iow(...,P_FCANCEL)`.)* + +### 9.3 Date/time conversions + +| Signature | Purpose | +|---|---| +| `VOID p_sttods(ULONG *pstim, P_DAYSEC *pds);` | System time → days-since-1900 + seconds-in-day. | +| `INT p_dstost(P_DAYSEC *pds, ULONG *pstim);` | `P_DAYSEC` → system time. | +| `INT p_dstodt(P_DAYSEC *pds, P_DATE *pdt);` | `P_DAYSEC` → `P_DATE` (fills yrday). | +| `INT p_dttods(P_DATE *pdt, P_DAYSEC *pds);` | Validate `P_DATE` → `P_DAYSEC`. | +| `INT p_dayinm(INT year, INT month);` | Days in given month (leap-aware); year since 1900. | +| `INT p_wkday(ULONG nDay);` | Weekday (0=Mon … 6=Sun) for day-since-1900. | +| `INT p_weekno(ULONG nDay);` | Week number 1–53 for day-since-1900. | + +### 9.4 Localised name/text lookups + +| Signature | Purpose | +|---|---| +| `INT p_nmday(TEXT *buf, INT daynum);` | Language day name (0=Mon … 6). | +| `INT p_nmdaya(TEXT *buf, INT daynum);` | Abbreviated day name. *(EPOC 3.18+)* | +| `INT p_nmmon(TEXT *buf, INT monthnum);` | Language month name (0=Jan … 11). | +| `INT p_nmmona(TEXT *buf, INT monthnum);` | Abbreviated month name. *(EPOC 3.18+; OCR prints this as a second `p_nmmon`.)* | +| `VOID p_getsuffixes(TEXT *buf);` | Fill array of 31 day-of-month suffixes (3-byte elements). | +| `VOID p_getampmtext(TEXT *buf, INT n);` | am (`n=0`) / pm (`n=1`) suffix text. | +| `VOID p_getctd(E_CONFIG *pcfg);` | Copy system locale/config (`E_CONFIG`) struct. | + +--- + +## 10. Object-Oriented Programming Primitives (brief) + +PLIB provides run-time OOP: categories (load modules of classes) identified by +category number or `HANDLE`; objects are heap instances with a class header. +`f_*` twins leave with `p_leave` on failure. Declared with the OOP chapter. + +### 10.1 Category / object creation & class management + +| Signature | Purpose | +|---|---| +| `HANDLE p_getlibh(INT catNum);` | Convert a category number to a category handle (0 = local). | +| `VOID *p_new(INT catNum, INT classNum);` | Create an instance of `classNum` in category `catNum`; property zeroed. | +| `VOID *f_new(INT catNum, INT classNum);` | As `p_new`, leaves on OOM. | +| `VOID *p_newlibh(HANDLE catHandle, INT classNum);` | Create instance by category handle. | +| `VOID *f_newlibh(HANDLE catHandle, INT classNum);` | As `p_newlibh`, leaves on OOM. | +| `VOID *f_newsend(INT catNum, INT classNum, INT methodNum, ...);` | Create then send init `methodNum`; cleans up (destroy) on leave. | +| `VOID *f_newlibhsend(HANDLE catHandle, INT classNum, INT methodNum, ...);` | As `f_newsend` but by category handle. | +| `VOID p_reclass(INT catNum, INT classNum, VOID *pObject);` | Change an object's class (same property length). | +| `VOID p_reclassbyhandle(HANDLE catHandle, INT classNum, VOID *pObject);` | Reclass by category handle. | +| `INT p_loadfilelib(VOID *fcb, UINT n, HANDLE *pCatHandle, INT link);` | Load an external category (load module) and get its handle. | +| `VOID p_linklib(HANDLE catHandle);` | Link a loaded category to the local process. | +| `VOID p_ccpy(VOID *pTarget, VOID *pSource, UINT count);` | Copy `count` bytes (category/object helper copy). | + +### 10.2 Message sending + +`p_send*` use the stack (`CDECL`) convention; the `p_send2..5` / `f_send2..5` +numbered variants use the faster register convention. `f_*` leaves with +`p_leave(err)` if the method returns negative. + +| Signature | Purpose | +|---|---| +| `INT p_send(VOID *pObject, INT methodNum, ...);` | Dispatch `methodNum` to object, searching class then superclasses. | +| `INT f_send(VOID *pObject, INT methodNum, ...);` | As `p_send`, leaves on negative return. | +| `INT p_send2(VOID *pObject, INT methodNum);` … `p_send5(VOID *pObject, INT methodNum, VOID *p1, VOID *p2, VOID *p3);` | Register-convention sends with 0–3 extra args (`f_send2..5` twins). | +| `INT p_supersend(VOID *pObject, INT methodNum, ...);` | Dispatch starting at the superclass of the calling method (`p_supersend2..5`). | +| `INT p_entersend(VOID *pObject, INT methodNum, ...);` | Dispatch as if via `p_enter` (unwinds on `p_leave`) (`p_entersend2..5`). | +| `INT p_exactsend(HANDLE catHandle, INT classNum, VOID *pObject, INT methodNum, ...);` | Dispatch starting at an explicitly named class. | + +--- + +## 11. Related Error/Process Primitives (referenced above) + +These appear alongside the categories above and are commonly used with them: + +| Signature | Purpose | +|---|---| +| `INT p_enter(VOID *pfunc, ...);` | Enter a function under structured error trapping. | +| `VOID p_panic(INT nPanic);` | Abort the process with a panic number (unrecoverable). | +| `VOID p_exit(INT nReason);` | Graceful process termination. | + +*(Full error-handling and process/IPC APIs are outside this core-PLIB scope but +`p_enter`/`p_leave`/`p_panic` underpin the `f_*` allocator and sender twins.)* + +--- + +### Uncertainty notes + +- OCR corrected: `p_bcmp`/`p_bcmpi` (src `p_bemp`), `p_fcmp` (src `p_femp`), + `p_pow` (src fragment `p (…)1_POw`), `p_nmmona` (src duplicate `p_nmmon`). +- `p_altchk`, `p_dequed`, `p_sgcreate`, `p_sgopen`, `p_sgfind` are named in the + manual but their clean C signatures are not isolated in the source text; marked **[?]**. +- Version-gated functions annotated where the manual states a minimum EPOC version.