Commit 7ff696aa authored by zhixuan wang's avatar zhixuan wang
Browse files

...

parent c19abdcc
File added
#ifndef ___boolean___h____
#define ___boolean___h____
/*
* Type: bool
* ----------
* This type has two values, FALSE and TRUE, which are equal to 0
* and 1, respectively. Most of the advantage of defining this type
* comes from readability because it allows the programmer to
* provide documentation that a variable will take on only one of
* these two values. Designing a portable representation, however,
* is surprisingly hard, because many libraries and some compilers
* define these names. The definitions are usually compatible but
* may still be flagged as errors.
*/
#ifdef THINK_C
typedef int bool;
#else
# ifdef TRUE
# ifndef bool
# define bool int
# endif
# else
# ifdef bool
# define FALSE 0
# define TRUE 1
# else
typedef enum {FALSE, TRUE} bool;
# endif
# endif
#endif
#endif // #ifndef ___boolean___h____
/*
* File: exception.c
* Version: 1.0
* Last modified on Sun Jul 24 10:28:11 1994 by eroberts
* -----------------------------------------------------
* This file implements the C exception handler. Much of the
* real work is done in the exception.h header file.
*/
#include <stdio.h>
#include <stdarg.h>
#include "genlib.h"
#include "gcalloc.h"
#include "exception.h"
/*
* Constant: MaxUnhandledMessage
* -----------------------------
* This constant should be large enough to accommodate the
* unhandled exception message, including the exception name.
*/
#define MaxUnhandledMessage 100
/* Publically accessible exceptions */
exception ANY = { "ANY" };
exception ErrorException = { "ErrorException" };
/*
* Global variable: exceptionStack
* -------------------------------
* This variable is the head pointer to a linked list of
* context blocks that act as the exception stack. The chain
* pointer is referenced by the macros in exception.h and must
* therefore be exported, but clients should not reference it
* directly.
*/
context_block *exceptionStack = NULL;
/* Private function prototypes */
static context_block *FindHandler(exception *e);
/* Public entries */
/*
* Function: RaiseException
* ------------------------
* This function operates by finding an appropriate handler
* and then using longjmp to return to the context stored
* there after resetting the exception stack. If no handler
* exists, the function notes an unhandled exception. Much
* of the complexity comes from the fact that allocation
* within the exception handler may fail.
*/
void RaiseException(exception *e, string name, void *value)
{
context_block *cb;
char errbuf[MaxUnhandledMessage + 1];
string errmsg;
int errlen;
cb = FindHandler(e);
if (cb == NULL) {
sprintf(errbuf, "Unhandled exception (%.30s)", name);
errlen = strlen(errbuf);
if (_acb == NULL) {
errmsg = malloc(errlen + 1);
} else {
errmsg = _acb->allocMethod(errlen + 1);
}
if (errmsg == NULL) {
errmsg = "Unhandled exception: unknown";
} else {
strcpy(errmsg, errbuf);
}
Error(errmsg);
}
exceptionStack = cb;
cb->id = e;
cb->value = value;
cb->name = name;
longjmp(cb->jmp, ES_Exception);
}
/*
* Function: HandlerExists
* -----------------------
* This public entry is used primarily by the Error function
* to determine if ErrorException has been trapped, although
* it is available to other clients as well.
*/
bool HandlerExists(exception *e)
{
return (FindHandler(e) != NULL);
}
/* Private functions */
/*
* Function: FindHandler
* ---------------------
* This function searches the exception stack to find the
* first active handler for the indicated exception. If a
* match is found, the context block pointer is returned.
* If not, FindHandler returns NULL.
*/
static context_block *FindHandler(exception *e)
{
context_block *cb;
exception *t;
int i;
for (cb = exceptionStack; cb != NULL; cb = cb->link) {
for (i = 0; i < cb->nx; i++) {
t = cb->array[i];
if (t == e || t == &ANY) return (cb);
}
}
return (NULL);
}
/*
* File: exception.h
* Version: 1.0
* Last modified on Sun Jul 24 10:26:20 1994 by eroberts
* -----------------------------------------------------
* The exception package provides a general exception
* handling mechanism for use with C that is portable
* across a variety of compilers and operating systems.
*/
#ifndef _exception_h
#define _exception_h
/*
* Overview:
* --------
* The exception package makes it possible for clients to
* specify a handler for an exceptional conditions in a
* syntactically readable way. As a client, your first step
* is to declare an exception condition name by declaring
* a variable of type exception, as in
*
* exception MyException;
*
* Normal visibility rules apply, so that you should declare
* the exception variable at the appropriate level. For
* example, if an exception is local to an implementation,
* it should be declared statically within that module. If
* an exception condition is shared by many modules, the
* exception variable should be declared in an interface
* and exported to all clients that need it. This package
* defines and exports the exception ErrorException, which
* is likely to be sufficient for many clients.
*
* The basic functionality of exceptions is that one piece
* of code can "raise" an exception so that it can then be
* "handled" by special code in a dynamically enclosing
* section of the program. Exceptions are raised by calling
* the pseudo-function raise with the exception name, as in
*
* raise(MyException);
*
* Exceptions are handled using the "try" statement
* (actually implemented using macros), which has the form:
*
* try {
* . . . statements in the body of the block . . .
* except(exception1)
* . . . statements to handle exception 1 . . .
* except(exception2)
* . . . statements to handle exception 2 . . .
* except(ANY)
* . . . statements to handle any exception . . .
* } endtry
*
* Any number of except clauses may appear (up to a
* maximum defined by the constant MaxExceptionsPerScope),
* and the ANY clause is optional.
*
* When the program encounters the "try" statement, the
* statements in the body are executed. If no exception
* conditions are raised during that execution, either
* in this block or by a function call nested inside
* this block, control passes to the end of the "try"
* statement when the last statement in the block is
* executed. If an exception is raised during the
* dynamic execution of the block, control immediately
* passes to the statements in the appropriate except
* clause. Only the statements in that clause are
* executed; no break statement is required to exit
* the block. If no handler for the raised exception
* appears anywhere in the control history, the program
* exits with an error.
*
* Examples of use:
*
* 1. Catching errors.
*
* The following code fragment traps calls to Error, so
* that the program does not quit but instead returns
* to the top-level read-and-execute loop.
*
* while (TRUE) {
* try {
* printf("> ");
* cmd = ReadCommand();
* ExecuteCommand(cmd);
* except(ErrorException)
* -- additional handling code, if any --
* } endtry
* }
*
* If either ReadCommand or ExecuteCommand calls Error,
* control will be passed back to the main loop, after
* executing any additional handler code. (The error
* message is printed by the Error routine, so it is
* often the case that no additional work is needed.)
*
* 2. Handling control-C
*
* The following code extends the example above so that
* typing ^C also returns to top-level.
*
* #include <signal.h>
*
* static exception ControlCException;
* static int errorCount = 0;
* static int ControlCHandler();
*
* main()
* {
* string cmd;
*
* signal(SIGINT, ControlCHandler);
* while (TRUE) {
* try {
* printf("> ");
* cmd = ReadCommand();
* ExecuteCommand(cmd);
* except(ControlCException);
* printf("^C\n");
* signal(SIGINT, ControlCHandler);
* except(ErrorException)
* errorCount++;
* } endtry
* }
* }
*
* static int ControlCHandler()
* {
* raise(ControlCException);
* }
*/
/*
* Actual interface specification
* ------------------------------
* Most of the implementation of the exception mechanism is
* actually done in the macros defined by this file.
* Clients should ordinarily be able to read the description
* above and ignore the detailed code below.
*/
#include <setjmp.h>
#include <string.h>
#include "genlib.h"
/* Define parameters and error status indicators */
#define MaxExceptionsPerScope 10
#define ETooManyExceptClauses 101
#define EUnhandledException 102
/* Codes to keep track of the state of the try handler */
#define ES_Initialize 0
#define ES_EvalBody 1
#define ES_Exception 2
/*
* Type: exception
* ---------------
* Exceptions are specified by their address, so that the
* actual structure does not matter. Strings are used here
* so that exporters of exceptions can store the exception
* name for the use of debuggers and other tools.
*/
typedef struct { string name; } exception;
/*
* Type: context_block
* -------------------
* This structure is used internally to maintain a chain of
* exception scopes on the control stack.
*/
typedef struct ctx_block {
jmp_buf jmp;
int nx;
exception *array[MaxExceptionsPerScope];
exception *id;
void *value;
string name;
struct ctx_block *link;
} context_block;
/* Declare the built-in exceptions */
extern exception ErrorException;
extern exception ANY;
/* Declare a global pointer to the context stack */
extern context_block *exceptionStack;
/*
* Function: RaiseException
* Usage: RaiseException(&e, name, value);
* ---------------------------------------
* This function is called by the raise macro and does the
* work necessary to raise the exception. See the exception.c file
* for details. Clients do not ordinarily call this directly.
*/
void RaiseException(exception *e, string name, void *value);
/*
* Function: HandlerExists
* Usage: if (HandlerExists(&e)) ...
* ---------------------------------
* Determines whether a handler exists for an exception in
* the dynamically enclosing scope. Intended only for use
* by special clients, such as the Error package.
*/
bool HandlerExists(exception *e);
/* Define the pseudo-functions for raise and try */
#define raise(e) RaiseException(&e, #e, NULL)
#define try \
{ \
jmp_buf _tmpbuf; \
context_block _ctx; \
volatile int _es; \
_es = ES_Initialize; \
_ctx.nx = 0; \
_ctx.link = exceptionStack; \
exceptionStack = (context_block *) &_ctx; \
if (setjmp(_tmpbuf) != 0) _es = ES_Exception; \
memcpy((void *) _ctx.jmp, (void *) _tmpbuf, sizeof(jmp_buf)); \
while (1) { \
if (_es == ES_EvalBody)
#define except(e) \
if (_es == ES_EvalBody) exceptionStack = _ctx.link; \
break; \
} \
if (_es == ES_Initialize) { \
if (_ctx.nx >= MaxExceptionsPerScope) \
exit(ETooManyExceptClauses); \
_ctx.array[_ctx.nx++] = &e; \
} else if (_ctx.id == &e || &e == &ANY) { \
exceptionStack = _ctx.link;
#define endtry \
if (_es != ES_Initialize) break; \
_es = ES_EvalBody; \
} \
}
#define GetExceptionName() _ctx.name
#define GetExceptionValue() _ctx.value
#define GetCurrentException() _ctx.id
#endif
This diff is collapsed.
/*
* File: gcalloc.h
* Version: 1.0
* Last modified on Wed Sep 21 16:21:37 1994 by eroberts
* -----------------------------------------------------
* This file is a stub version of the interface for a
* garbage-collecting allocator that will be part of
* a future library release. When the garbage-collecting
* allocator is in use, the memory returned by the GetBlock
* and FreeBlock functions in genlib.h can be traced and
* collected automatically when it is no longer accessible.
*
* The garbage-collecting allocator is not part of the
* current cslib distribution. Even so, functions in the
* other libraries call the ProtectVariable and ProtectBlock
* functions, so that they will continue to work when the
* full library is released. Those functions are implemented
* in genlib.c.
*/
#ifndef _gcalloc_h
#define _gcalloc_h
/*
* Macro: ProtectVariable
* Usage: ProtectVariable(v);
* --------------------------
* This macro registers a global variable with the allocation
* system, so that the variable is traced when the garbage
* collector is used. This operation needs is implemented
* in genlib.c so that code can be written to function correctly
* whether or not the garbage-collecting allocator is loaded.
*/
#define ProtectVariable(v) ProtectBlock(&v, sizeof v)
/*
* Function: ProtectBlock
* Usage: ProtectBlock(ptr, nbytes);
* ---------------------------------
* This function is not usually called by clients (who will
* ordinarily use ProtectVariable instead), but has the
* effect of protecting the block of memory beginning at
* ptr and extending for nbytes from the garbage collector.
*/
void ProtectBlock(void *ptr, size_t nbytes);
/*
* Global linkage variable: _acb
* -----------------------------
* This variable is used to hold the allocation control block
* that provides the linkage between this package and the
* dynamic allocator. The reason for using the structure
* as a linkage is so that the garbage-collecting allocator
* need not even be loaded if it is not explicitly called.
*/
typedef struct {
void *(*allocMethod)(size_t nbytes);
void (*freeMethod)(void *ptr);
void (*protectMethod)(void *ptr, size_t nbytes);
} *_GCControlBlock;
extern _GCControlBlock _acb;
#endif
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
/*
* File: random.c
* Version: 1.0
* Last modified on Mon Sep 13 10:42:45 1993 by eroberts
* -----------------------------------------------------
* This file implements the random.h interface.
*/
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include "genlib.h"
#include "random.h"
/*
* Function: Randomize
* -------------------
* This function operates by setting the random number
* seed to the current time. The srand function is
* provided by the <stdlib.h> library and requires an
* integer argument. The time function is provided
* by <time.h>.
*/
void Randomize(void)
{
srand((int) time(NULL));
}
/*
* Function: RandomInteger
* -----------------------
* This function first obtains a random integer in
* the range [0..RAND_MAX] by applying four steps:
* (1) Generate a real number between 0 and 1.
* (2) Scale it to the appropriate range size.
* (3) Truncate the value to an integer.
* (4) Translate it to the appropriate starting point.
*/
int RandomInteger(int low, int high)
{
int k;
double d;
d = (double) rand() / ((double) RAND_MAX + 1);
k = (int) (d * (high - low + 1));
return (low + k);
}
/*
* Function: RandomReal
* --------------------
* The implementation of RandomReal is similar to that
* of RandomInteger, without the truncation step.
*/
double RandomReal(double low, double high)
{
double d;
d = (double) rand() / ((double) RAND_MAX + 1);
return (low + d * (high - low));
}
/*
* Function: RandomChance
* ----------------------
* This function uses RandomReal to generate a number
* between 0 and 100, which it then compares to p.
*/
bool RandomChance(double p)
{
return (RandomReal(0, 1) < p);
}
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment