SAS/C Compiler Reference¶
SAS/C (Version 6.50) is the C compiler used to build all the NDK example code. This article documents its key features, extensions, and the knowledge needed to compile AmigaOS programs with it. Source: SAS/C User's Guide Volumes 1+2 (SAS Institute, 1993).
The compilation chain¶
source.c → sc (compiler) → object.o → slink (linker) → executable
source.c → sc link (one-step compile+link) → executable
| Tool | Purpose |
|---|---|
sc |
C compiler (also does assembly via .s input) |
slink |
Linker |
smake |
Make utility (reads smakefile) |
cdbg |
Source-level debugger (CodeProbe) |
bum |
Library maintenance |
oml |
Object module librarian |
Key sc compiler options¶
| Option | Effect |
|---|---|
link |
Compile + link in one step |
optimize=N |
Optimization level 0–4 (0=none, 4=max) |
define=SYM |
Define preprocessor symbol |
ignore=NN |
Suppress warning number NN |
nostackcheck |
Disable stack overflow checking |
structureequivalence |
Allow struct assignment by structure type |
verbose |
Verbose compilation output |
includedir=dir |
Additional include path |
code=small |
Small code model |
data=far |
Far data model |
math=standard |
Standard math library |
smakefile patterns¶
An smakefile (SAS/C makefile) uses tab-indented rules like standard make:
CFLAGS = optimize=2 structureequivalence
all: myapp helper
myapp: myapp.c
sc link $(CFLAGS) $*
helper: helper.c
sc $(CFLAGS) $*.c
slink lib:c.o helper.o myapp.o lib:sc.lib lib:amiga.lib to myapp
$* = target name without extension. $< = first dependency. $@ = full target name.
All NDK smakefiles follow the pattern: sc link structureequivalence $*.
SAS/C-specific keywords¶
These are critical for correct AmigaOS code:
__saveds — load data segment¶
void __saveds my_callback(void)
{
/* Data segment (A4) is loaded — safe to access globals */
}
Mandatory for: interrupt handlers, hook callbacks, timer callbacks, any function called from a different task context or supervisor mode. Without __saveds, the function may access the wrong data segment, causing silent corruption or crashes.
The NDK examples consistently use __saveds on:
- Hook entry functions
- Interrupt handlers (AddIntServer callbacks)
- Timer callbacks
- BOOPSI dispatcher functions
__interrupt — interrupt handler¶
Marks a function as an interrupt handler (no stack switch, must preserve all registers). Combined with __saveds.
__regargs / __stdargs¶
__regargs— pass all arguments in CPU registers (D0–D2, A0–A1) instead of on the stack. Faster but non-standard ABI.__stdargs— standard C calling convention (stack-based). Default.
Amiga library functions use the register-based ABI via the library's jump table and #pragma libcall.
Startup modules¶
SAS/C provides startup code that runs before main():
- OS calls the program entry point with:
A6=ExecBaseA0= BCPL return vectorA2= argument BSTR- Startup module (e.g.,
c.o) opensDOSBase, parses arguments intoargc/argv - Calls
main(argc, argv) - After
main()returns, startup closesDOSBaseand exits
Without a startup module (for libraries, device drivers):
void __saveds __startup entry(void)
{
/* A6 = ExecBase guaranteed */
/* Must manually open DOSBase if needed */
}
#pragma statements¶
Seven pragmas control library calls and diagnostics:
| Pragma | Purpose |
|---|---|
#pragma libcall |
Call library function via register ABI |
#pragma flibcall |
Library call with floating-point registers |
#pragma amicall |
Aztec C-compatible library call |
#pragma regcall |
Register-based call (Aztec compat) |
#pragma syscall |
System call |
#pragma tagcall |
Tag-based (TagItem) call |
#pragma msg |
Control diagnostic message severity |
#pragma msg — diagnostic control¶
#pragma msg 123 warn /* make message 123 a warning */
#pragma msg 123 ignore /* suppress message 123 */
#pragma msg 123 error /* make message 123 an error */
#pragma msg 123 warn push /* save current state, then change */
#pragma msg 123 pop /* restore previous state */
Only works on messages numbered 1–299 (C compiler messages, not C++ translator).
Stack management¶
Default stack: 4000 bytes (stkneed = 400). This is often enough but can overflow with deep recursion or large local arrays.
| Solution | How | When |
|---|---|---|
stackext keyword |
Per-function stack extension | Deep recursion in one function |
stackext option |
Entire program | Many functions need more stack |
Increase stkneed |
extern long stkneed = 8192; |
All functions need more |
nostackcheck |
Disable checking | Release builds (minor speed gain) |
Never set stkneed below 400. The stackext keyword adds overhead (extra register + entry code), so use selectively.
CodeProbe debugger (cdbg)¶
Source-level debugger with:
cdbg program # load program
| Command | Action |
|---|---|
break function |
Breakpoint at function |
break file.c:42 |
Breakpoint at source line |
watch variable |
Break when variable changes |
step / next |
Single step (into/over) |
continue |
Resume execution |
print expr |
Evaluate expression |
backtrace |
Call stack |
list |
Show source around PC |
CodeProbe supports debugging shared libraries (Chapter 5) and multitasking programs (Chapter 6) — both essential for AmigaOS where most programs spawn multiple tasks.
Optimization levels¶
| Level | Effect | Recommended use |
|---|---|---|
| 0 | No optimization | Debugging |
| 1 | Basic peephole | Quick dev builds |
| 2 | Standard | Development builds |
| 3 | Aggressive (inlining, loop opts) | Release candidates |
| 4 | Maximum (may alter FP precision) | Release builds |
Trade-off: higher optimization = slower compilation, harder to debug.
See Also¶
Sources: SAS Institute Inc., "SAS/C Development System User's Guide" Volumes 1+2, Version 6.50 (1993).
Raw: raw/sasc/sasc-reference-extract.md; raw/sasc/sasc-syslib-ref.md
Updated: 2026-08-09
Updated: 2026-08-08