# 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.