# SAN Kit — Pascal examples

A Free Pascal interface unit for `libsan.a` (`sankit.pas`), and
Pascal translations of the first three programs in `../examples/`
(`01_hello_board.c`, `02_setup_position.c`, `03_san_notation.c`),
built and tested against [Free Pascal](https://www.freepascal.org/)
3.2.2 on Linux/x86-64.

## Scope

`sankit.pas` binds exactly what these three programs need — not the
whole library. Extending it to cover more of `../SAN_SRC` (say, to
translate `04_move_generation.c` next, which would need the `mT`
move-record struct's real C layout rather than the opaque pointer
used here) is meant to be a matter of following the same pattern for
whichever function or global comes next; see the unit's own header
comment for exactly how its existing bindings were worked out and
checked, so the next one can be checked the same way rather than
guessed at.

## Building

```sh
cd ../SAN_SRC && make lib   # once, or after editing the library
cd ../examples-pascal && make
./01_hello_board
```

## What each one shows

Same material as their C originals in `../examples/` — see that
directory's own `README.md` for the full descriptions. All three
were checked to produce byte-for-byte identical output to the C
version they were translated from:

| File | Demonstrates |
|---|---|
| `01_hello_board.pas` | `SANInit()`, `SANDspBoard()`, `SANFENGen()` — the minimum needed to link against the library at all |
| `02_setup_position.pas` | Loading a position via `SANFENSet()`, and building one square-by-square with `SANClrBoard()`/`SANPutSq()`/`SANUpdate()` |
| `03_san_notation.pas` | Parsing SAN text to a move with `SANDecodeAux()`, formatting it back with `SANEncode()` |

## Things worth knowing before extending this

- **C `int` (SAN Kit's `siT` family — `sqT`, `cpT`, `cT`, `castT`,
  ...) is Pascal `LongInt`; C `char *` (`charptrT`) is Pascal
  `PChar`.** True on this platform (x86-64 Linux) because that's
  what a small throwaway C program compiled against `sandef.h`
  measured — `sizeof(siT)` is 4, `sizeof(charptrT)` is 8 — not
  because the C source says so directly (`siT` is itself just
  `typedef int siT`, and could in principle be a different width on
  a platform this port was never tested on). Numeric constants used
  here (square numbers, color-piece codes, array bounds) were
  checked the same way: compiled and printed, not hand-computed from
  the `#define` macro arithmetic in `sandef.h`.

- **`sanT` (a `char[16]` in C, `TSanBuf` here) is a fixed buffer, not
  a pointer** — same caveat as `../examples/README.md` gives for the
  C originals. C arrays decay to a pointer to their first element
  when passed to a function, which is what `SANDecodeAux()` and
  `SANEncode()`'s C prototypes actually receive; `SanBufPtr()` in
  `sankit.pas` does that conversion explicitly on the Pascal side,
  since Pascal arrays don't decay to pointers implicitly the way C's
  do.

- **A move (`PMove`/`mptrT`) is bound as an opaque `Pointer` here**,
  not a Pascal record matching the C `mT` struct's real layout,
  because none of these three programs ever reads or writes one of
  its fields directly — a move only ever travels from one SAN Kit
  call straight to another. A program that needs to inspect a move's
  own squares or flags (say, a translation of
  `04_move_generation.c`) would need `mT`'s exact C field order,
  types, and alignment reproduced as a Pascal record instead.

- **Global C arrays/variables** (`optnv[]`, `accv[]`, `acpv[]`,
  `cv_c_cpv[]`, `cv_p_cpv[]`) are bound with FPC's `cvar; external;`,
  which shares the real memory the C library reads and writes —
  confirmed by setting `optnv[optn_nabd]` from Pascal and observing
  the C library's own `SANPlayMove()` actually stop displaying the
  board because of it, not just by reading back what Pascal itself
  had just written.

- **Pascal's `Write`/`WriteLn` and the C library's own `printf`-based
  output use separate stdio buffers over the same file descriptor**,
  and can print out of the intended order — especially once stdout
  isn't a terminal (piped to a file or another program, exactly what
  capturing a program's output for testing does), since C's stdio
  then defaults to fully buffered rather than line-buffered. See
  `sankit.pas`'s header comment (under "A note on mixed C/Pascal
  output") for the fix used throughout these three programs:
  `Flush(Output)` before, and `FlushCOutput(nil)` (a thin binding for
  C's `fflush(NULL)`) after, any SAN Kit call that might print.
