Dec 092017
 
SCI is a "C" language interpreter loosely based on the language subset described in James Hendrix's book "Small C".
File CINTERP.ZIP from The Programmer’s Corner in
Category C Source Code
SCI is a “C” language interpreter loosely based on the language subset described in James Hendrix’s book “Small C”.
File Name File Size Zip Size Zip Type
CALC.SCI 1540 423 deflated
SCI.COM 25764 14421 deflated
SCI.DOC 42802 13646 deflated
SHELL.SCI 2913 1082 deflated

Download File CINTERP.ZIP Here

Contents of the SCI.DOC file


ii
iiii
ii
sss cccc
ssssssss cccccccc iiiii
sss sss ccc ccc iiiii
sssss ccc iii
sssss ccc iii
sssss ccc iii
sss sss ccc ccc iii
ssssssss cccccccc iiiiiiiii
ssss cccc iiiiiiiii


Small C Interpreter
Version 1.3 for MS-DOS
by Bob Brodt, 28 Nov 1985


DISCLAIMER

The author makes no expressed or implied warranties of any kind
regarding this program and documentation. In no event will the
author be liable for any damages or losses arising out of use of
this program and documentation.


Bob Brodt
34 Mehrhof Road
Little Ferry, NJ 07643
Phone (201) 641-9582




INTRODUCTION

SCI is a "C" language interpreter loosely based on the language
subset described in James Hendrix' "Small C" (see the section
"DIFFERENCES FROM SMALL C", below). It is a fully interactive
interpreter (no compilation!) that includes a simple line editor and
a program trace facility. SCI was meant to be a stepping stone for
the experienced BASIC programmer who is ready to move up to the
exciting world of "C"!

The SCI interpreter is very similar to BASIC internally - each
line of input is first scanned and "tokenized", a process in which
language elements (numbers, variables, keywords, etc.) are converted
to one-, two- or three-byte "tokens" which are easier to handle by a
computer than arbitrarily long character sequences. Unlike BASIC
however, SCI programs do not require line numbers. The program flow
is directed by SCI purely through the structured programming
constructs inherent in the "C" language.

SCI should run on any MS-DOS or PC-DOS computer that has a minimum
of 64Kbytes of RAM. The available free memory (that portion of memory
not used by the interpreter's code and data storage) is automatically
divided among "user progam code", "variable table", "function table"
and "stack" memory segments. If necessary, the sizes of these
segments may be changed at program startup, however their total may
not exceed 64Kbytes.

The integrated editor does require that the terminal emulation
firmware in your particular computer be capable of responding to the
following ASCII control codes:

backspace (08 HEX) - moves the cursor one column to the left
without destroying the character at the
new column position.
return (0D HEX) - positions the cursor at the left margin
of the current line on the CRT.
linefeed (OA HEX) - moves the cursor down one line and causes
the screen to scroll up at the last CRT
display line.

These control codes are fairly standard and should work on your
machine.


STARTING OUT

The files on the distribution diskette are:

SCI.DOC - documentation
SCI.COM - the interpreter proper
SHELL.SCI - the command shell, written in "Small C"
CALC.SCI - a sample calculator program written in "Small C"

To start up SCI, make sure that SHELL.SCI resides on the current
drive and then execute SCI.COM. The interpreter will then read and
execute the program it finds in SHELL.SCI.

You may also specify a different "Small C" program file for SCI
to execute on startup. By typing the following operating system
command line, for example:

A>SCI B:STARTUP

the interpreter will search disk B: for a file called STARTUP and
execute it in lieu of the default SHELL.SCI file. Be aware,
however, that the standard SHELL.SCI file contains many often-used
operating system interface functions that must be copied over to
your customized startup program if they are going to be used by
that program. See the section on "LIBRARY FUNCTIONS" for a list of
these functions.

MEMORY ALLOCATION

The interpreter automatically divides up whatever free memory is
available (after SCI is loaded) among four segments for use by your
programs and data. These segments are: the Program Code, Variable
Table, Function Table and Stack. The Program Code segment contains
the tokenized version of your program code. The Variable Table
contains information about all "active" variables. All global
variables are active at all times. Local variables are considered
to be active if the function in which they were declared is still
active. A function is active even though it may be waiting for
another called function to return to it. Thus, if you have a habit
of writing deeply recursive functions, you will soon run out of
Variable Table space. Each function takes up exactly one
entry in the Function Table.

If the interpreter complains about "out of memory", "too many
variables", "too many functions" or "stack overflow", you may be
able to circumvent the problem by telling SCI how much memory to
assign to each of these four segments with the following options:

-P nnnn - assign "nnnn" decimal bytes for program storage.
-V nn - allow space for a maximum of "nn" active variables.
-F nn - allow space for a maximum of "nn" functions.
-S nn - set the stack size to "nn".

Thus, the command line:

A>SCI -P 8000 -V 30 -F 80 -S 40

will set aside 8000 bytes for program storage, allow a maximum of
30 variables to be active at one time, allow a maximum of 80 function
declarations and leave 40 stack entries.


COMMAND LINE OPTIONS

It is possible to pass command line parameters to the startup
program with the "-A" option, thus:

A>SCI STARTUP -A FILE1.DAT FILE2.DAT FILE3.DAT

will pass the strings FILE1.DAT, FILE2.DAT and FILE3.DAT to the
startup program in the file called STARTUP. See the section on
"PASSING ARGUMENTS TO THE SHELL" for an example of how these
arguments are handled from within a program.


THE SHELL

The "stock" version of the shell simply displays a prompt on the
console, reads a line of input, and attempts to execute the input
line. The entire shell program (sans Library Functions) is shown
here:

int size,top;
char line[80];
char program[24000];

main()
{
int from, to;

top=24000;
program[0]='Z'; # This is an "End of program" token - required
size=1;

# print sign-on message
printf("%s\nShell V1.1, 24 Oct 1985\n",sys(0));

while(1)
{
puts("> ");
if(gets(line))
{
if (!strncmp(line,"edit",4))
size = sys(atoi(line+5),program,15); # envoke the editor
else if (!strncmp(line,"list",4))
{
if(line[4])
sscanf(line+4,"%d %d",&from,&to);
else
{
from=1;
to=32765;
}
sys(program,from,to,22); # list the program buffer
}
else if (!strncmp(line,"save",4))
sys(line+5,program,21); # save the program buffer
else if (!strncmp(line,"load",4))
size = sys(line+5,program,20); # load the program buffer
else if (!strncmp(line,"core",4))
printf("%d bytes free\n",top-size); # memory available
else
#
# attempt to parse the line as a "Small C" statement.
# Note that the shell always displays the results of the
# statement, so you could enter something like: 2+2 and
# a 4 would be printed.
#
printf("%d\n",sys(line,program,12));
}
}
}


Later, as you become more familiar with the "C" language, you may
wish to modify the shell program and add your own commands. The
stock version of the shell recognizes four basic (pardon the pun)
commands: "edit", "list", "load", "save", "core" and "exit". These
are functionally similar to the BASIC commands: "EDIT", "LIST",
"LOAD", "SAVE", "FREE" and "SYSTEM" respectively, with the exception
that no quote (") is required in front of the file name for the
"load" and "save" commands. Anything else typed at the shell prompt
is assumed to be a valid "Small C" statement and is handed off to the
interpreter to be executed.

By the way, programs that are "save"d by SCI are ordinary text
files, suitable for editing with your favourite text editor.


THE EDITOR

To edit a program, simply type "edit", or "edit n", where "n" is
the line number in the program to start editing. The requested line
number is displayed followed by a colon (:) and then by the program
text of that line. The cursor is positioned on the first character
of the program text, i.e. immediately to the right of the colon.

The editor has two different operating modes: EDIT and INSERT.
In EDIT mode, you may move the current character position ("cursor")
anywhere within the program and you may delete text. In INSERT mode,
any characters that you type are inserted into the program until you
return to EDIT mode. There are two flavors of INSERT: CHARACTER
INSERT and LINE INSERT. CHARACTER INSERT mode remains in effect only
until you type a , in other words you may only insert
characters on the current line. LINE INSERT mode allows you to enter
entire lines into the program buffer and is ended when you type an
. These will be described more fully below.

Any changes you make during an editing session affect only the
program currently residing in memory. The copy of the program on disk
(if one exists) is not changed until you issue a "save" command from
the standard command shell.

To leave the editor and return to the command shell, type an
character.

Editing commands are divided into 3 categories: cursor movement,
text insertion and text deletion. The cursor movement commands allow
you to position the cursor anywhere in the program. These are:

'h' or -
moves the cursor to the left by 1 character position.

'l' (that's a lower-case "ell") or -
moves the cursor to the right by 1 character position.

'j' or or -
advances the cursor to the next line ON THE SCREEN and displays
the next line of the program.

'k' -
advances the cursor to the next line ON THE SCREEN and displays
the previous line of the program.

'g' -
prompts for a line number, advances the cursor to the next line
on the screen and displays the requested line of the program.
If the requested line number is beyond the last line (or before
the first) line of program text, the last (resp. first) line is
displayed.

'f' -
prompts for a character sequence to be searched for in the
program, advances the cursor to the next line on the screen and
displays the requested line of the program. The cursor is
positioned to the first character of the string sought.

If the cursor is moved past the end of the program, the editor will
display an and will not allow you to move past it. Similarly, if
the cursor is moved to the first line of the program, the 'k' command
will be inoperative.

The text insertion commands are:

'i' -
will cause characters to be inserted before the current cursor
position. As you type, the characters to the right of the
cursor will appear to be overwritten on the screen, but are
actually shifted (in the editor's buffer) to make room for the
inserted text. To leave the character insertion mode, end the
line with a . The cursor will advance to the next line
on the screen and the line will be redrawn with the newly
inserted text. Typing an will cancel anything that
was typed before it and return to EDIT mode with the original
line intact.

'I' -
will enter LINE INSERT mode. All characters typed will be
inserted into the program in front of the line the cursor was
resting on. When in LINE INSERT mode, you will be prompted
with the word "new:" instead of the current line number, to
indicate that the editor is in the special INSERT mode. To
leave LINE INSERT mode type an .

Text may be deleted from the program either a character-at-a-time
or a line-at-a-time:

'd' -
will delete the character the cursor is resting on. The cursor
advances to the next line on the screen and the current line is
redrawn with the deleted character missing.

'D' -
will delete the line the cursor is resting on. The cursor
advances to the next line on the screen and the next line in
the program is displayed.

Remember, type to exit the editor!


LANGUAGE ELEMENTS

Although SCI implements only a subset of the "C" language, it is
powerful enough to teach you the major principles of "C". We're going
to cop out now and refer you to a higher authority for a sound
introduction to "C", but we will list here the major features of the
language subset recognized by SCI for easy reference.

Line Terminators

In standard "C", a statement is typically terminated with a semi-
colon (;). In SCI, all statements are terminated by either the end
of the line or by a semicolon, although the semicolon is optional.
This means that an expression MUST be completely contained on one
line. This is not as major a deficiency as it may seem at first,
when you consider the fact that extremely long expressions are very
difficult for the human reader to understand and, after all, we ARE
interested in learning how to write readable programs.

Comments

Comments start with a number symbol (#) and end at the end of the
current program line. The standard "C" comment delimiters, /* and */
are not recognized and will cause a "syntax error" message.

Identifiers

Identifiers may be a maximum of 8 characters long, the first
character must be an uppercase or lowercase letter ("a-z", "A-Z") or
an underscore ("_"). The remaining 7 characters may include digits
("0-9").

The following are all examples of valid identifiers:

this_is_an_identifier
_0123
XYZ

Keywords

The following words are reserved by SCI and may not be used as
variable names:

break entry return
char if sys
else int while

The "entry" keyword is used to tell the interpreter which function
in the startup program (normally SHELL.SCI) is to be executed first
after the program has been loaded. There may be only one "entry"
within a program. Any functions or variables that were declared
before the "entry" keyword are considered "Library Functions" and are
globally known to all functions. Functions and variables declared
after the "entry" keyword are hidden from user-written functions.
Please read the section on "SCOPE OF VARIABLES" for more information.

The keyword "sys" is a user program interface to some useful
interpreter functions, such as the program editor. These are
described in the "LIBRARY FUNCTIONS" section.

Constants

Numeric Constants

SCI supports decimal integer constants in the range -32767 to
32766. SCI also supports the standard "C" notation for integer
hexadecimal and octal notation.

Character Constants

A character constant must be surrounded by apostrophes (')
and may be one of the following:

* a single ASCII alphanumeric or punctuation (i.e. printable)
character
* a backslash (\) character followed by 3 octal digits which
may be used to represent any 1 byte value
* a backslash followed by one of the characters n, r, b or t
which represent the (a.k.a. "newline"),
carriage return), backspace and tab characters respectively

The following are examples of valid character constants:

'A' the ASCII character "A"
'\177' octal character
'\n' newline
'\r' carriage return
'\b' backspace
'\t' horizontal tab
'\\' the backslash character
'\'' the apostrophe character

Strings

Strings may include any of the character constants mentioned
above, as for example:

"this is a string\007\n"

Strings always include a null (zero) byte, marking the end of the
string. A zero-length string may be written as two consecutive
quotes, thus: ""

Data Types

Only the "char" and "int" data types are supported. Characters
(char's) are 1 byte and integers (int's) 2 bytes in length. Both
are treated as signed quantities. Chars may range in value from -128
to +127. Ints range from -32767 to 32766.

SCI also supports pointers and arrays of both char and int.
Pointers require 2 bytes of storage.

Operators

Unary Operators

The following unary operators are supported, all are evaluated from
right to left:

+--------------------------------+
| * pointer |
| & address |
| - negation |
| ! logical NOT |
| ~ one's complement |
| ++ pre- and post-increment |
| -- pre- and post-decrement |
+--------------------------------+

Binary Operators

The following binary operators are supported, all are evaluated
from left to right. The operators are listed from highest to lowest
precedence, each group of operators (in the boxes) have the same
precedence:

+--------------------------------+
| * multiplication |
| / division |
| % modulo (remainder) |
+--------------------------------+
| + addition |
| - subtraction |
+--------------------------------+
| << shift left |
| >> shift right |
+--------------------------------+
| < less than |
| > greater than |
| <= less than or equal to |
| >= greater than or equal to |
+--------------------------------+
| == equal |
| != not equal |
+--------------------------------+
| & bitwise AND |
+--------------------------------+
| ^ bitwise exclusive OR |
+--------------------------------+
| | bitwise OR |
+--------------------------------+
| && logical AND |
+--------------------------------+
| || logical OR |
+--------------------------------+

Assignment Operator

The assignment operator, "=", is evaluated from from right to left
and has lowest precedence of all operators.

Comma Operator

The Comma Operator (,) as used by SCI is not an operator in the
strict sense, but rather as a function argument and variable seperator.
Trying to use a comma anywhere other than in function calls, or data
declarations will cause a "syntax error".


SCOPE OF VARIABLES

When we talk about the "scope" of a variable, we are referring to



MY FIRST PROGRAM

To get you started writing "C" programs, step right up to your
computer (don't be shy), fire 'er up and insert the disk. Then type
"SCI" and wait for the shell program to load (don't get too anxious
now!). When the shell prompts you with "> " boldly type the word:

> edit

and hit . You are now in the editor. It's time to refer
back to "THE EDITOR" section of this manual. Since there is nothing
in the program buffer, the editor displays:

1:

Hold down that shift key and poke the key with the letter 'I' on
it. You are now in LINE INSERT mode. Anything you type from here on
will be inserted into the program buffer until you press .
So, why not just type in the little program below. Don't type in the
word "new:" each time, silly - they are the editor's LINE INSERT
prompts.

new:hi()
new:{
new: puts( "hello, world\n" );
new:}

When you're done, hit to end LINE INSERT mode, and then
again to leave the editor. When the shell gives you its
prompt, type:

> hi

The shell will hand the input line off to the interpreter, the
interpreter will scan the program buffer for a function named "hi"
and call that function. The "hi" function will then call the library
function "puts" to print the string "hello, world\n" on the console.
What you see is simply:

hello, world
>

Congratulations, even if six months ago you couldn't spell
"programmur", you now are one!


THE LIBRARY FUNCTIONS

The "sys" keyword has been reserved by SCI as a means of
communicating between a user's program and the interpreter. It is
treated exactly as a (pre-defined) function that may be referenced by
a user program. This interface has been provided mainly as a
convenience to the user.

A "sys" call may have several arguments, the number and type of
which depends upon the integer value of the last (right-most)
argument. This righ-most argument is called the "sys number" and
defines the actual function performed by a "sys" call. To make life
easier and to provide a more or less "standard" programming
environment, higher-level functions have been wrapped around these
"sys" calls - these are known as the "Library Functions" and may be
found in the standard command shell found on the distribution disk.
These "sys numbers" and their corresponding Library Functions are
listed below.

1 fputc
2 fgetc
3 fputs
4 fgets
5 sprintf
6 sscanf
7 fopen
8 fread
9 fwrite
10 fclose
11 exit
12 stmt
13 totok
14 untok
15 edit
16 strcmp and strncmp
17 memleft
18 malloc
19 free
20 load
21 save
22 list
23 trace

The Library functions are described below in more detail:


atoi( string )
char *string;

Converts the string "str" containing the ASCII representation of
a decimal number to an integer. The string consits of optional
leading spaces or tabs, an optional plus or minus sign (+ or -)
followed by one or more decimal digits.
Returns the integer value of the ASCII number string.

edit( line_num, program )
int line_num
char *program

Envokes the built-in program editor, starting at the line given
by "line_num" on the tokenized program buffer "program". Returns
the new size of the program buffer after the editing session.

exit( value )
int value

Causes the currently executing program to return control to the
operating system.

fclose( channel )
int channel;

Closes a disk file previously opened by the Library Function
"fopen". Returns zero if successful, -1 on error.

fgetc( channel )

Reads a single character from the given channel. Returns the
character read, or a -1 on error or end of file.

fgets( buffer, length, channel )
char *buffer;
int length;
int channel;

Reads characters from the file associated with "channel".
Characters are read from the file until either a newline is
encountered, length minus 1 characters have been read, or an end
of file is found. Returns the address of "buffer", or a zero on
end of file.

fopen( file_name, mode )
char *file_name, *mode;

Opens a disk file whose name is given by the string "file_name".
The string "mode" determines how the file will be opened:

"r" - open for ASCII read. The file MUST exist or fopen
returns an error code.
"rw" - open for ASCII read/write. The file MUST exist.
"w" - open for ASCII write. If the file exists, it is first
deleted.
"wr" - open for ASCII read/write. If the file already exists,
it is first deleted.
"a" - open for ASCII write append. If the file does not exist,
it is created. If it does exist, the file pointer is
positioned to the end of the file.
"ar" - open for ASCII read/write append. If the file does not
exist it is created. If it DOES exist, it is opened and
the file pointer positioned to the end of the file. The
file may then be read or written.

By appending a "b" to any of the modes above, the file is opened in
BINARY mode instead of ASCII.

When a file is opened in ASCII mode, all s ("\n") are
converted to character pairs when writing to
the file. Similarly, pairs are converted to
a single character on input from the file.

In binary read/write mode, no such conversions are performed.

Returns an integer value known as a "channel". The special
channels 0, 1 and 2 refer to the standard input, standard output
and standard error files. The channel number must be used in all
Library calls that perform file I/O functions. A Minus one is
returned if the file could not be opened.

fputc( c, channel )
char c;
int channel;

Writes the character "c" to the specified file channel. Returns

the character written, or a -1 on error.

fputs( string, channel )
char *string;
int channel;

Writes the string to the specified file channel. Returns zero, or
a -1 on error.

fread( buffer, length, channel )
int channel;
char *buffer;
int length;

Reads a maximum of "length" bytes into memory at the address
pointed to by "buffer" from the open file, "channel". If the file
was opened in ASCII read or read/write mode, "fread" only reads up
to and including a newline character. If the file was opened in
binary read mode, "length" number of characters are read if they
are available. Note that "channel" must be the value returned
from a previous "fopen" Library Function call, and the file must
still be open. Returns the number of characters that were
actually read, or 0 on EOF.

free( memory )
char *memory

Returns the block of memory pointed to by "memory" that was
previously gotten from a "malloc" Library Function call.

fwrite( channel, buffer, length )
int channel;
char *buffer;
int length;

Writes "length" number of characters from memory at the address
pointed to by "buffer" to the file associated with "channel".
Note that "channel" must be the value returned from a previous
"fopen" Library Function call, and the file must still be open.
Returns the number of characters actually written if successful,
or a -1 on error.

load( file, program )
char *file, *program

Loads a program from the file whose name is in the string "file"
tokenizes the statements therein and places the tokenized program
at "program". Returns the size of the resulting tokenized
program. If the file could not be found, an error message is
printed on the console.

memleft()

Returns a count of the number of free memory bytes available from
the main memory allocator.

malloc( size )
int size

Main memory allocator. This function is responsible for handing
out (to programs) chunks of free memory to be used by the program
as it sees fit. WARNING: wreckless programs that write data beyond
the size of the allocated chunk of memory will cause the allocator
to loose its mind and dole out "rotten" chunks of memory. This
will almost surely cause SCI to crash and burn. Returns a pointer
to a block of memory "size" bytes long. Be sure to de-allocate
the block using the Library Function "free" when you're done with
it, or it will be lost forever...

printf( format, arg1, arg2, ... arg8 )
char *format;
int arg1, arg2, ... arg8;

Prints a formatted string to the standard output file.
The characters in the string "format" are copied to the output
file. If a percent character ("%") is encountered in the
format string, it is assumed to be a conversion specification.
Each conversion specification converts exactly one argument in
the list "arg1", "arg2", ... "arg8". Once an argument has been
converted and output, it is skipped over the next time a
conversion specification is encountered. Therefore, you need just
as many arguments as you have conversion specifications.

The character(s) that follow a conversion specification may be
one or more of the following:

minus sign (-)
Indicates that output should be left justified instead of
right justified.

zero fill character (0)
The field will be padded on the left with zeros.

field width (number other than 0)
This is the minimum # of characters output. The field will
be padded with zeros or blanks depending on the fill
character (above).

precision (. followed by a number)
For numeric fields, this is the # of decimal places to the
right of the decimal point. For string fields, at most that
many characters of the string will be output.

conversion code (the letter d, u, x, o, b, s or c)
A conversion code indicates the type of conversion that is
to be done on the argument as follows:

d - convert to a decimal (base 10) number
u - unsigned decimal number
x - hexadecimal (base 16) number
o - octal (base 8) number
b - binary (base 2) number
s - string constant
c - single ASCII character

save( file, program )
char *file, *program

Saves a program in its tokenized form at "program" to the file
whose name is in the string "file". Returns the number of bytes
written to the file. If the file could not be created, an error
message is printed on the console.

scanf( format, arg1, arg2, ... arg8 )
char *format
int arg1, arg2, ... arg8

Read characters from the standard input file and converts them
using the conversion string "format" (same as for Library Function
"printf"). The arguments "arg1", "arg2", ... "arg8" must be
POINTERS to the appropriate data types.

sprintf( buffer, format, arg1, arg2, ... arg8 )
char *buffer, *format
int arg1, arg2, ... arg8

Performs formated conversion of the arguments, exactly like the
Library Function "printf", but writes its output to the "buffer"
instead of the standard output file.

sscanf( buffer, format, arg1, arg2, ... arg8 )
char *buffer, *format
int arg1, arg2, ... arg8

Performs formated input conversion of the arguments, exactly like
the Library Function "scanf" but reads its input from the "buffer"
instead of the standard input file.

stmt( line, program )
char *line, *program

Hands a "Small C" statement off to the interpreter for execution.
The statement is in its untokenized form at "line". The program
in its tokenized form at "program" is used by the interpreter to
satisfy any global variable or function references made by the
statement.

strcmp( string_1, string_2 )
char *string_1, *string_2

or

strncmp( string_1, string_2, limit )
char *string_1, *string_2
int limit

Compares (character-by-character) the two strings. The comparison
stops when a zero is encountered in either of the two strings.
"strncmp" does the same thing, but at most "limit" number of bytes
are compared. Returns a 0 if the two strings are identical,
non-zero if they differ.

totok( sourcebuf, tokenbuf )
char *sourcebuf, *tokenbuf

Converts the C statement at "sourcebuf" to its tokenized
equivalent and places the result at "tokenbuf". Returns the
length of "tokenbug".

trace( on_off )
int on_off;

Allows a program to enable or disable SCI's trace feature. If
"on_off" is zero, trace is disabled, anything else enables it.

untok( tokenbuf, sourcebuf )
char *tokenbuf, *sourcebuf

Converts the tokenized statement at "tokenbuf" to its printable
form at "sourcebuf". Returns the length of "tokenbuf" (not
"sourcebuf"!). This function is the opposite of the "totok"
function.


TRACE/DEBUG FEATURE

The Library Function "trace", described in the previous section,
allows you to enable or disable the program trace/debug feature.
In the trace mode, you can set and remove breakpoints, examine and
modify program variables and control the execution of your program.

When trace is enabled, the interpreter first displays each line of
the program on the console before it is executed, and then displays
a question mark (?) prompt. At this point, you may either enter
another "Small C" statement (to display the contents of a variable
for example), or enter one of the following commands (NOTE: all of
these commands must start with a dot (.) immediately following the
"?" prompt to distinguish them from a valid "Small C" statement):

.b# sets a breakpoint at a given line in your program. The "#"
symbol represents the line number at which the program will
be halted.

.B displays all breakpoints set in the program.

.c continues program execution until the next breakpoint is
encountered.

.d# deletes the breakpoint at line number "#". The breakpoint
must have been previously set with a ".b" command.

.D deletes all breakpoints.

.e# lets you examine the program with the program editor. Editor
commands that would normally modify the program are disabled.

.g displays all of the program's global variables and their
values. If the variable is an array, its address is printed
followed by the first 10 elements of the array.

.G same as ".g" but also displays the first line of every
function in the program along with its line number. This is
useful for locating a function in a long program.

.q quits program execution and returns to the shell program.

.s# steps through the program without displaying each line as it
is executed. The "#" is the number of lines to be executed
before control returns to the debuger.

.t displays the list of active functions with the current one
at the top of the list. This is handy for finding out "how
did I get here?".

.T same as ".t" but also displays each function's local variables
and their values.

repeats the last ".s" or ".c" command entered. This
is a handy way of tracing program flow from one breakpoint to
the next.

disables the trace/debug facility and continues execution
normally. The interpreter will no longer stop at

If the interpreter finds an error in your program, it will auto-
matically enable trace/debug and halt the program at the line where
the error occurred. This can be a little confusing if you are already
in the debuger and you happen to make a mistake while typing a
statement for the debuger to execute, because the resulting error
message and the "?" prompt will refer to the statement you just
entered. If this happens, just hit a and you will be
returned to the program trace session.


PASSING ARGUMENTS TO THE SHELL

A mechanism has been provided to pass operating system command
line areguments to the startup program in a way similar to most
commercially available "C" compilers. When you start up SCI, a "-A"
will cause all following arguments to be passed to the startup
program. For example, suppose the following program is to be
executed by SCI at startup:

main(argc, arv)
int argc, *argv;
{
int i;

while ( i printf("<%s>\n",argv[i++]);
}

Then, when the following command is entered at the operating system
level:

A>SCI -A HELLO OUT THERE

the program would print:





Note that since SCI does not support pointers to pointers, the "argv"
variable must be declared as a pointer to "int". Then, each "argv[i]"
is a pointer to a string that points to one of the words passed on
the command line.


DIFFERENCES FROM "SMALL C"

SCI supports the subset of the "C" language defined by J. Hendrix'
public domain "Small C" compiler, available for many CP/M and MS-DOS
machines. There are, however, some minor differences that have been
dictated in part by the fact that this is an interpreter. These are:

0) Program source lines are limited to 80 characters, just to keep
things simple. The editor will complain if you try to create
a line longer than 80 characters.
1) There are no #define or #include statements, simply because
there is no pre-processor!
2) Comments are introduced by the number symbol (#) and are
terminated by the end of the line. The "/*" and "*/"
combinations will only be barfed at by SCI.
3) Statements in general are terminated by the end of a line - the
semicolon required by the "C" language at the end of a statement
is superfluous. This restriction imposes that an expression be
completely on one line (boooo, hissss!), however you no longer
get penalized for forgeting a semicolon (hurray, yay!). This
also implies that string and character constants are terminated
by the end of the line. In fact, if you forget to add the
terminating quote or apostrophe delimiter, SCI will append one
for you.
4) The comma operator is recognized only when used in function
calls and data declarations. For instance, it would be illegal
to say:
while ( argv++, argc-- );
5) Data declarations may appear ANYWHERE within a program or
function (hurray, yay!), however local data declarations remain
active up to the end of the function - they don't go away at
the end of the compound statement they were declared in (boooo,
hissss!).
6) Pointer arithmetic is not smart enough to recognize data types
so that pointers to integers are advanced to the next BYTE, not
the next integer. For example, *(ip+1) will point to the least
significant byte of the next integer (on an 8086 machine), not
the next word (booo, hisss!). But, ip[1] and ++ip still point
to the next integer (whew!).


ERROR MESSAGES

When SCI detects an error in your program, it will stop execution,
display an error message and then the line number and program text of
the offending line. The possible error messages are listed below:

no entry point
You forgot to specify an entry function with the "entry" keyword.

not enough table space
There was insufficient free memory available for the program,
variable, function and stack segments. Specify a smaller
-P, -V, -F or -S value.

can't find ''
The specified program file could not be loaded, or SHELL.SCI
does not exist on the default disk drive.

can't create ''
The specified file could not be save on disk because of an
operating system error.

missing '}'
The interpreter wandered off the edge of your program because
you forgot a closing brace.

missing operator
The interpreter found two consecutive operands as for example
the statement: var 3;

missing ')' or ']'
Mismatched left and right parentheses or brackets were detected.

not a pointer
A variable or constant expression was used as an array or
pointer as for example the statement: *(buf+1);

syntax error
An error was detected in the structure of a statement.

lexical error: ...
An illegal character was found in a statement. The offending
character along with the remainder of the statement is printed.

need an lvalue
An attempt was made to assign a value to a constant.

stack underflow
Something is wrong!

stack overflow
The expression is too complex or function calls are nested too
deeply. Try specifying a larger -S value when starting up SCI.

too many functions
The interpreter ran out of Function Table space. Try specifying
a larger -F value when starting up SCI.

too many symbols
The interpreter ran out of Variabl Table space. Try specifying
a larger -V value when starting up SCI.

out of memory
The interpreter ran out of Program space. Try specifying a
larger -P value when starting up SCI.

stmt outside of function
There is something wrong with the structure of your program.
Typically this results from a statement appearing outside of
any function body.

missing '{'
The left brace that introduces a function body was missing.

wrong # of arguments in sys call
The number of arguments passed to a "sys" call is incorrect for
the specified "sys" number.

undefined symbol
A variable has been used without ever having been declared.

interrupt
The program was interrupted by pressing the key.


 December 9, 2017  Add comments

Leave a Reply