.SH Introduction
.LP
Saber-C is an interactive programming environment for the C language.
It helps programmers develop, test, and debug C programs.
With Saber-C, users can interpret and debug their programs as they
are being developed, without having to use a compiler or a debugger.
.LP
This manual provides new users with a quick introduction
to the features and commands of Saber-C.
The reader should have some familiarity with the C programming
language and the UNIX operating system.
.SH Starting and Exiting Saber-C
.LP
To start Saber-C, enter the command \*n to the shell.
@(E
    % \*u\*(NS\*p

				Saber-C (Version 1.2)
		Copyright (C) 1986, 1987 by Saber Software

	Attaching: /lib/libc.a

	Do you want instructions ? \*un\*p

	1 ->
@)E
.LP
When \*n starts up, it examines the current working directory and the
user's home directory for the file
.FN .saberinit .
If the file is not found, \*n prompts for instructions.
If you intend to continue reading this manual, you should skip the
on-line instructions.
(The instructions prompt can be eliminated by creating a file called
.FN .saberinit
in your home directory. The file can be empty.)
.LP
To exit \*n, use the
.CO quit
command.
@(E
	1 -> \*uquit();\*p

	%
@)E
.SH Getting Help
.LP
The
.CO help
command provides on-line information on how to use all the
\*n commands.
To see a list of all the commands, call
.CO help .
To get information about a particular command, call
.CO help
with the name of the command.
@(E
	1 -> \*uhelp();\*p
	/* displays a list of all commands */

	2 -> \*uhelp("load") ;\*p
	/* displays information on the load command */
@)E
.SH Interacting with Saber-C
.LP
When \*n is ready to accept input from the user, it displays a line
number followed by a 
.UI ->
prompt.
All input to \*n must consist of proper C expressions or statements. 
\*bEvery expression or statement must be followed by a semi-colon.\*p
@(E
	1 -> \*uint i ;\*p
	2 -> \*ui = 100 ;\*p
	(int) 100
	3 ->
@)E
.LP
\*N uses different prompts to indicate different input conditions.
If the user enters an incomplete expression or statement \(em
usually because of a missing semi-colon or an incomplete block \(em the
.UI +>
prompt is used.
@(E
	1 -> \*u123 +\*p
	2 +> \*u456 +\*p
	3 +> \*u789 ;\*p
	(int) 1368
	4 ->
@)E
.SH Executing C in the Environment
.LP
\*N's environment will accept and execute the entire C language.
The user can declare variables, create types, and use the C
preprocessor.
@(E
	1 -> \*u#define ARRAY_SIZE 10\*p
	2 -> \*ustruct pair { int x ; double d ; } ;\*p
	3 ->
	4 -> \*ustruct pair list[ARRAY_SIZE] ;\*p
	5 ->
@)E
Functions can be declared directly in the environment.
When defining a function, the return type of the function
must be specified.
For example, the return type
.KW int
for the function
.EX factorial
must be specified when entering the function, even though
both \*n and compiler do not require this of functions defined
in a file.
@(E
	1 -> \*uint factorial(n)\*p
	2 +> \*uint n ;\*p
	3 +> \*u{\*p
	4 +>    \*uif( n > 1 ) return (n * factorial(n-1)) ;\*p
	5 +>    \*uelse return 1 ;\*p
	6 +> \*u}\*p
	7 ->
@)E
.LP
Although the user can write entire programs in the
environment, it is difficult to modify and debug source
code that has been entered directly in the environment.
The user should place program code in a file so that it
can be easily edited and loaded.
.SH Executing Commands
.LP
All \*n commands are implemented as C functions that can be executed
directly from the environment.
The user executes a command by calling it as a function.
Any options or additional information for the command are
passed as arguments to the function.
@(E
	1 -> /* Call load with a file as the argument */
	2 -> \*uload("main.c") ;\*p
	Loading: main.c
	(int) 0
	3 ->
@)E
Since commands are executed as functions, they must always be followed
by an open parentheses, a close parentheses, and a semi-colon, even if
the command is being called without an argument.
@(E
	4 -> /* Calling load without an argument */
	5 -> \*uload();\*p
	load: All loaded modules are up to date.
	(int) 0
	6 ->
@)E
.SH Responding to Errors and Warnings
.LP
\*N checks all input, either from the terminal or from a file, for
syntax errors and static violations.
When an expression, statement, or program is executed, \*n checks it
for possible run-time violations.
.LP
Benign violations are reported as warnings, from which the user can
continue.
More serious violations are reported as errors; the user usually
cannot continue from errors.
.LP
When a violation is reported, the user is presented with a list of
options.
For example, at the error shown below, the user can break execution
at the location of the violation, quit execution of the statement,
or edit the line containing the violation.
@(E
	1 -> \*uextern int test() ;\*p
	2 -> \*utest() ;\*p
	Error #61: Calling undefined function test().
	Options: break/quit/edit [b] ?
@)E
The default choice, which is selected if the user enters a
carriage return, is enclosed within the square brackets.
.SH Creating Break Levels
.LP
A break level is is generated when the user breaks execution
at an error or warning.
(Break levels can also be generated with the
.CO stop
command, which is discussed later.)
Break levels allow the user to examine or correct a violation
before continuing execution.
.LP
In the example below, the user chose to break execution
at the location where the undefined function is called.
@(E
	2 -> \*utest() ;\*p
	Error #61: Calling undefined function test(). 
	Options: break/quit/edit [b] ? \*ub\*p

	To continue, use 'cont(int)'.  If you define the
	function, use 'cont()' or <Control-D> to retry.
	(break 1) 3 ->
@)E
.LP
At a break level, the user can perform nearly any action that
is permitted at the top level of the environment, as well as
examine the execution stack by using the
.CO where
command.
@(E
	(break 1) 3 -> \*uwhere() ;\*p

	break #1, line 3, caused by error #61 (Undefined function)
	top level, line 2.
	(void)
	(break 1) 4 ->
@)E
.SH Leaving a Break Level
.LP
The message that is displayed when the break level is generated
indicates how the user can continue execution.
.LP
One way to continue execution from the break level generated
in the previous example would be to call the
.CO cont
command with an integer value.
This value would represent the return value of the undefined
function
.EX test .
@(E
	(break 1) 3 -> \*ucont(99);\*p
	(int) 99
	4 ->
@)E
.LP
Another way to continue execution would be to define the function
.EX test
at the break level and call
.CO cont
without an argument.
A shortcut for calling
.CO cont
without an argument is to enter a \*(^D.
@(E
	(break 1) 3 -> \*uint test() { return 1234; }\*p
	(break 1) 4 -> \*u^D\*p
	(int) 1234
	5 ->
@)E
.LP
The
.CO reset
command can be used if the user wants to exit the break level
without continuing execution.
@(E
	(break 1) 3 -> \*ureset() ;\*p
	Resetting to top level.
	4 ->
@)E
.SH Loading Files
.LP
Users can load source code files, object code files (with and without
debugging information), and library files
into \*n.
A file can be loaded two ways: it can be specified on
the command line when \*n is invoked or it can be loaded
interactively from within \*n.
.LP
The example below displays the listing for the file
.FN calc.c
which contains the functions
.EX main
and
.EX calc.
This program takes one argument that tells it how many values
to calculate.
For every calculation, it prompts the user for a number and
prints the square root and log of the number.
@(E
	#include <math.h>

	void calc() ;
	float num ;

	main(argc, argv) int argc ; char **argv ;
	{
		char buf[100] ;

		printf("Please enter a number: ") ; 
		gets(buf) ;
		num = atof(buf) ;
		calc(num) ;

		exit(0) ;
	}

	void calc(val) float val ;
	{
		printf( "val = %f, square root = %f, log = %f\en",
			val, sqrt(val), log(val) ) ;
	}
@)E
The example below shows how to load the source code file
and the system math library from the command line.
(The
.EX -w
switch is used to suppress reporting of any warnings
when loading the files.)
@(E
	% \*usaber -w calc.c -lm\*p


				Saber-C (Version 1.2)
		Copyright (C) 1986, 1987 by Saber Software

	Attaching: /lib/libc.a
	Loading: -w calc.c 
	Attaching: -w /usr/lib/libm.a
@)E
These files could be loaded interactively, after entering \*n, by
using the
.CO load
command.
@(E
	1 -> \*uload("-w calc.c -lm") ;\*p

	Loading: -w calc.c 
	Attaching: -w /usr/lib/libm.a
@)E
.LP
Any options or switches that specify how the files should be loaded are
included within the argument to the
.CO load
command.
In the example above, the user specified that the files should be
loaded with the
.KW -w
option, which suppresses the reporting of warnings (similar to
the compiler).
.LP
If the
.CO load
command is called with the name of a library, it
.ID attaches
the library, thereby making the contents of the library
available for use.
The modules of the library are linked dynamically when
they are needed.
For example, the standard library function
.EX printf
is linked from the library when it is used.
@(E
	2 -> \*uprintf("Done loading.\en") ;\*p
	Linking from /lib/libc.a ...Linking completed.
	Done loading.
	(int) 14
	3 ->
@)E
Once a function has been linked from a library, it does
not need to be linked again.
.SH Executing Programs
.LP
\*N supports two modes of execution:
direct execution of functions from the environment and
execution of programs with processing of command line
arguments.
.LP
Functions may be executed as soon as they are defined,
even if they contain references to undefined variables.
When a function is executed, all loaded libraries are searched in
order to satisfy references to undefined variables and functions.
@(E
	3 -> \*ucalc(100.0) ;\*p
	Linking from /lib/libm.a -w ...Linking completed.
	Linking from /lib/libc.a ...Linking completed.
	val = 100.000000, square root = 10.000000, log = 4.605170
	(void)
	4 ->
@)E
.LP
The
.CO run
command is used to mimic the behavior of a program as if it were being
executed from the shell.
.CO Run
reinitializes all global variables, executes
.EX main
with "command line" arguments, and
closes all input/output buffers and file descriptors after
.EX main
exits.
If \*n is executing within a windowing system,
.CO run
will also open a separate window for handling program input
and output.
@(E
	4 -> \*urun() ;\*p
	Executing: a.out
	Linking from /lib/libc.a ...Linking completed.
	Please enter a number: \*u10\*p
	val = 10.000000, square root = 3.162278, log = 2.302585
	Program exiting with return status = 0.
	Resetting to top level.
	5 ->
@)E
.LP
.CO Run
constructs its arguments for
.EX main
from the "command line" passed to it.
If this argument is missing, command line arguments from the previous
call to 
.CO run
are re-used.
To execute 
.EX main
without command line arguments, use an empty string as the argument to
.CO run .
.SH Using the Debugging Commands
.LP
\*N lets users set breakpoints, which interrupt execution at a specific
location in a program, and watchpoints, which interrupt execution when an
address is modified.
.LP
A breakpoint is set by calling the
.CO stop
command with a line number, a filename and a line number, or a function.
@(E
	5 -> \*ustop(calc);\*p
	Breakpoint #1 set at "calc.c", line 17, calc().
	6 ->
@)E
When the breakpoint is reached, execution stops, and a break level is created.
All source lines at which breakpoints are set are preceded by the character
.EX B .
The source line at which execution was interrupted is preceded by a
.EX * .
@(E
	6 -> \*urun() ;\*p
	Executing a.out
	Please enter a number: \*u144\*p

	Stopped in calc(val = (double) 1.440000e+02) at "calc.c", line 17
	   16: {
	*B 17:  printf( "val = %f, square root = %f, log = %f\en",
	   18:          val, sqrt(val), log(val) ) ;
	(break 1) 7 -> 
@)E
All active functions, variables, macros, and tag names may be examined
directly from the break level.
Execution can be continued by entering a \*(^D or calling the
.CO cont
command.
@(E
	(break 1) 7 -> \*u^D\*p
	val = 144.000000, square root = 12.000000, log = 4.969813
	Program exiting with return status = 0.
	Resetting to top level.
@)E
.LP
The
.CO tag
command can be used to interrupt execution when an address is
modified.
In the example below, a tag is set on the global variable
.EX num .
@(E
	10 -> \*utag(&num);\*p
	Tag #1 set on 4 bytes beginning at address 0x89448.
	(int 1)
	11 ->
@)E
.LP
When the tagged address is modified, execution will be
interrupted.
@(E
	11 -> \*urun() ;\*p
	Executing: a.out
	Please enter a number: \*u99\*p

	Stopped in main(argc = (int) 1, argv = (char **) 0x89ba0)
	at "calc.c", line 14
	   13:  gets(buf) ;
	*  14:  num = atof(buf) ;
			*** tag #1 triggered.***
	   15:  calc(num) ; 
	(break 1) 11 -> 
@)E
.LP
All debugging actions can be listed with the
.CO status
command and deleted with the
.CO delete
command.
.CO Delete
should be called with the number of the debugging
action.
@(E
	(break 1) 11 -> \*ustatus() ;\*p
	 (1) Tag: addresses 0x89448 - 0x8944b  (location 'num').
 
	(void) 
	12 -> \*udelete(1) ;\*p
	Tag #1 deleted.
	13 ->
@)E
.LP
The commands
.CO action
and
.CO tagaction
are versions of
.CO stop
and
.CO tag
that do not interrupt execution when triggered.
Instead, they will execute an arbitrary action specified
by the user.
For example,
.CO action
can be used to create conditional breakpoints by combining a
C statement with the
.CO stop
command
@(E
	13 -> \*uaction(calc);\*p
	Setting action at "calc.c", line 19, calc().
	Use braces for multiple statements.  <Control-D> to quit,
		<Control-C> to redo.
	action -> \*uif( num == 0.0 ) stop() ;\*p
	Action #1 set.
	15 ->
@)E
Execution will be interrupted only if the value of
.EX num
equals
.VL 0 .
In the example below,
.EX num
equals
.VL 123
for the first execution of the program.
When the program is executed again,
.EX num
equals
.VL 0 ,
and execution is interrupted by the action.
@(E
	16 -> \*urun() ;\*p
	Execution a.out
	Please enter a number: \*u123\*p
	val = 123.000000, square root = 11.090537, log = 4.812184
	Program exiting with return status = 0.
	Resetting to top level.
	17 -> 
	18 -> \*urun() ;\*p
	Please enter a number: \*u0\*p
	Stopped in action #1, line 1, set in 
	calc(val = (double) 0.000000e+00) at "calc.c", line 19
	   18: {
	*<A1>  1: if( num == 0.0 ) stop() ;
	   19:  printf( "val = %f, square root = %f, log = %f\en",
	   20:          val, sqrt(val), log(val) ) ;
	(break 1) 19 -> 
@)E
.SH Editing and Reloading
.LP
Files can be edited from within \*n by using the
.CO edit
command.
.CO Edit
can be called with the name of a file, the name of
a function, or a line number of a file.
The example below will start the editor on the first
line of the function
.EX calc .
@(E
	20 -> \*uedit(calc) ;\*p
@)E
.CO Edit
uses the editor specified by the shell variable
.SV EDITOR ;
if this variable is unset, the editor
.SC vi
is used.
.LP
If \*n is being run in a windowing environment, the edit job
will be placed in a separate window.
If the user is working on an ascii terminal, \*n will be suspended
while the editing job is active.
.LP
Once the file being edited has been modified and saved, the user
can enter a \*(^Z (suspend signal) to notify \*n that the file
is ready to be reloaded.
If \*n is being used with a windowing system, the file will be
automatically reloaded; otherwise, the user will be prompted
to reload the file.
.LP
If an error or warning is detected while the file is being reloaded, 
the editor will be updated to the location of the violation.
This mechanism allows the user to correct all syntax errors and 
static violations without leaving the editor.
.LP
Another mechanism to reload modified files is with the
.CO load
command.
If
.CO load
is called without an argument it will reload any modules
that have been modified since they were loaded into \*n.
If
.CO load
is called with the name of a file that has already been loaded,
the file will be reloaded if it has been modified.
@(E
	21 -> \*uload() ;\*p
	load: All loaded modules are up to date.
	(int) 0
	22 -> \*uload("calc.c") ;\*p
	load: Module 'calc.c' is up to date.
	(int) 0
	23 ->
@)E
.LP
A source code module will be reloaded if the source file
or any of the header files it includes have been modified.
An object code module will be reloaded if the object file
has been recompiled.
