📄 router.c
字号:
/*******************************************************/
/* "C" Language Integrated Production System */
/* */
/* CLIPS Version 6.24 07/01/05 */
/* */
/* I/O ROUTER MODULE */
/*******************************************************/
/*************************************************************/
/* Purpose: Provides a centralized mechanism for handling */
/* input and output requests. */
/* */
/* Principal Programmer(s): */
/* Gary D. Riley */
/* */
/* Contributing Programmer(s): */
/* Brian L. Donnell */
/* */
/* Revision History: */
/* 6.24: Removed conversion of '\r' to '\n' from the */
/* EnvGetcRouter function. */
/* */
/* Renamed BOOLEAN macro type to intBool. */
/* */
/* Added support for passing context information */
/* to the router functions. */
/* */
/*************************************************************/
#define _ROUTER_SOURCE_
#include <stdio.h>
#define _STDIO_INCLUDED_
#include <stdlib.h>
#include <string.h>
#include "setup.h"
#include "argacces.h"
#include "constant.h"
#include "envrnmnt.h"
#include "extnfunc.h"
#include "filertr.h"
#include "memalloc.h"
#include "strngrtr.h"
#include "sysdep.h"
#include "router.h"
/***************************************/
/* LOCAL INTERNAL FUNCTION DEFINITIONS */
/***************************************/
static int QueryRouter(void *,char *,struct router *);
static void DeallocateRouterData(void *);
/*********************************************************/
/* InitializeDefaultRouters: Initializes output streams. */
/*********************************************************/
globle void InitializeDefaultRouters(
void *theEnv)
{
AllocateEnvironmentData(theEnv,ROUTER_DATA,sizeof(struct routerData),DeallocateRouterData);
RouterData(theEnv)->CommandBufferInputCount = -1;
#if (! RUN_TIME)
EnvDefineFunction2(theEnv,"exit", 'v', PTIEF ExitCommand, "ExitCommand", "*1i");
#endif
InitializeFileRouter(theEnv);
InitializeStringRouter(theEnv);
}
/*************************************************/
/* DeallocateRouterData: Deallocates environment */
/* data for I/O routers. */
/*************************************************/
static void DeallocateRouterData(
void *theEnv)
{
struct router *tmpPtr, *nextPtr;
tmpPtr = RouterData(theEnv)->ListOfRouters;
while (tmpPtr != NULL)
{
nextPtr = tmpPtr->next;
rtn_struct(theEnv,router,tmpPtr);
tmpPtr = nextPtr;
}
}
/*******************************************/
/* EnvPrintRouter: Generic print function. */
/*******************************************/
globle int EnvPrintRouter(
void *theEnv,
char *logicalName,
char *str)
{
struct router *currentPtr;
/*===================================================*/
/* If the "fast save" option is being used, then the */
/* logical name is actually a pointer to a file and */
/* fprintf can be called directly to bypass querying */
/* all of the routers. */
/*===================================================*/
if (((char *) RouterData(theEnv)->FastSaveFilePtr) == logicalName)
{
fprintf(RouterData(theEnv)->FastSaveFilePtr,"%s",str);
return(2);
}
/*==============================================*/
/* Search through the list of routers until one */
/* is found that will handle the print request. */
/*==============================================*/
currentPtr = RouterData(theEnv)->ListOfRouters;
while (currentPtr != NULL)
{
SetEnvironmentRouterContext(theEnv,currentPtr->context);
if ((currentPtr->printer != NULL) ? QueryRouter(theEnv,logicalName,currentPtr) : FALSE)
{
if (currentPtr->environmentAware)
{ (*currentPtr->printer)(theEnv,logicalName,str); }
else
{ ((int (*)(char *,char *)) (*currentPtr->printer))(logicalName,str); }
return(1);
}
currentPtr = currentPtr->next;
}
/*=====================================================*/
/* The logical name was not recognized by any routers. */
/*=====================================================*/
if (strcmp(WERROR,logicalName) != 0) UnrecognizedRouterMessage(theEnv,logicalName);
return(0);
}
/**************************************************/
/* EnvGetcRouter: Generic get character function. */
/**************************************************/
globle int EnvGetcRouter(
void *theEnv,
char *logicalName)
{
struct router *currentPtr;
int inchar;
/*===================================================*/
/* If the "fast load" option is being used, then the */
/* logical name is actually a pointer to a file and */
/* getc can be called directly to bypass querying */
/* all of the routers. */
/*===================================================*/
if (((char *) RouterData(theEnv)->FastLoadFilePtr) == logicalName)
{
inchar = getc(RouterData(theEnv)->FastLoadFilePtr);
if ((inchar == '\r') || (inchar == '\n'))
{
if (((char *) RouterData(theEnv)->FastLoadFilePtr) == RouterData(theEnv)->LineCountRouter)
{ IncrementLineCount(theEnv); }
}
/* if (inchar == '\r') return('\n'); */
return(inchar);
}
/*===============================================*/
/* If the "fast string get" option is being used */
/* for the specified logical name, then bypass */
/* the router system and extract the character */
/* directly from the fast get string. */
/*===============================================*/
if (RouterData(theEnv)->FastCharGetRouter == logicalName)
{
inchar = (unsigned char) RouterData(theEnv)->FastCharGetString[RouterData(theEnv)->FastCharGetIndex];
RouterData(theEnv)->FastCharGetIndex++;
if (inchar == '\0') return(EOF);
if ((inchar == '\r') || (inchar == '\n'))
{
if (RouterData(theEnv)->FastCharGetRouter == RouterData(theEnv)->LineCountRouter)
{ IncrementLineCount(theEnv); }
}
/* if (inchar == '\r') return('\n'); */
return(inchar);
}
/*==============================================*/
/* Search through the list of routers until one */
/* is found that will handle the getc request. */
/*==============================================*/
currentPtr = RouterData(theEnv)->ListOfRouters;
while (currentPtr != NULL)
{
if ((currentPtr->charget != NULL) ? QueryRouter(theEnv,logicalName,currentPtr) : FALSE)
{
if (currentPtr->environmentAware)
{ inchar = (*currentPtr->charget)(theEnv,logicalName); }
else
{ inchar = ((int (*)(char *)) (*currentPtr->charget))(logicalName); }
if ((inchar == '\r') || (inchar == '\n'))
{
if ((RouterData(theEnv)->LineCountRouter != NULL) &&
(strcmp(logicalName,RouterData(theEnv)->LineCountRouter) == 0))
{ IncrementLineCount(theEnv); }
}
/* if (inchar == '\r') return('\n'); */
/*
if (inchar != '\b')
{ return(inchar); }
*/
return(inchar);
}
currentPtr = currentPtr->next;
}
/*=====================================================*/
/* The logical name was not recognized by any routers. */
/*=====================================================*/
UnrecognizedRouterMessage(theEnv,logicalName);
return(-1);
}
/******************************************************/
/* EnvUngetcRouter: Generic unget character function. */
/******************************************************/
globle int EnvUngetcRouter(
void *theEnv,
int ch,
char *logicalName)
{
struct router *currentPtr;
/*===================================================*/
/* If the "fast load" option is being used, then the */
/* logical name is actually a pointer to a file and */
/* ungetc can be called directly to bypass querying */
/* all of the routers. */
/*===================================================*/
if (((char *) RouterData(theEnv)->FastLoadFilePtr) == logicalName)
{
if ((ch == '\r') || (ch == '\n'))
{
if (((char *) RouterData(theEnv)->FastLoadFilePtr) == RouterData(theEnv)->LineCountRouter)
{ DecrementLineCount(theEnv); }
}
return(ungetc(ch,RouterData(theEnv)->FastLoadFilePtr));
}
/*===============================================*/
/* If the "fast string get" option is being used */
/* for the specified logical name, then bypass */
/* the router system and unget the character */
/* directly from the fast get string. */
/*===============================================*/
if (RouterData(theEnv)->FastCharGetRouter == logicalName)
{
if ((ch == '\r') || (ch == '\n'))
{
if (RouterData(theEnv)->FastCharGetRouter == RouterData(theEnv)->LineCountRouter)
{ DecrementLineCount(theEnv); }
}
if (RouterData(theEnv)->FastCharGetIndex > 0) RouterData(theEnv)->FastCharGetIndex--;
return(ch);
}
/*===============================================*/
/* Search through the list of routers until one */
/* is found that will handle the ungetc request. */
/*===============================================*/
currentPtr = RouterData(theEnv)->ListOfRouters;
while (currentPtr != NULL)
{
if ((currentPtr->charunget != NULL) ? QueryRouter(theEnv,logicalName,currentPtr) : FALSE)
{
if ((ch == '\r') || (ch == '\n'))
{
if ((RouterData(theEnv)->LineCountRouter != NULL) &&
(strcmp(logicalName,RouterData(theEnv)->LineCountRouter) == 0))
{ DecrementLineCount(theEnv); }
}
if (currentPtr->environmentAware)
{ return((*currentPtr->charunget)(theEnv,ch,logicalName)); }
else
{ return(((int (*)(int,char *)) (*currentPtr->charunget))(ch,logicalName)); }
}
currentPtr = currentPtr->next;
}
/*=====================================================*/
/* The logical name was not recognized by any routers. */
/*=====================================================*/
UnrecognizedRouterMessage(theEnv,logicalName);
return(-1);
}
/*****************************************************/
/* ExitCommand: H/L command for exiting the program. */
/*****************************************************/
globle void ExitCommand(
void *theEnv)
{
int argCnt;
int status;
if ((argCnt = EnvArgCountCheck(theEnv,"exit",NO_MORE_THAN,1)) == -1) return;
if (argCnt == 0)
{ EnvExitRouter(theEnv,EXIT_SUCCESS); }
else
{
status = (int) EnvRtnLong(theEnv,1);
if (GetEvaluationError(theEnv)) return;
EnvExitRouter(theEnv,status);
}
return;
}
/***********************************************/
/* EnvExitRouter: Generic exit function. Calls */
/* all of the router exit functions. */
/***********************************************/
globle void EnvExitRouter(
void *theEnv,
int num)
{
struct router *currentPtr, *nextPtr;
RouterData(theEnv)->Abort = FALSE;
currentPtr = RouterData(theEnv)->ListOfRouters;
while (currentPtr != NULL)
{
nextPtr = currentPtr->next;
if (currentPtr->active == TRUE)
{
if (currentPtr->exiter != NULL)
{
if (currentPtr->environmentAware)
{ (*currentPtr->exiter)(theEnv,num); }
else
{ ((int (*)(int))(*currentPtr->exiter))(num); }
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -