📄 iofun.c
字号:
/*******************************************************/
/* "C" Language Integrated Production System */
/* */
/* CLIPS Version 6.24 07/01/05 */
/* */
/* I/O FUNCTIONS MODULE */
/*******************************************************/
/*************************************************************/
/* Purpose: Contains the code for several I/O functions */
/* including printout, read, open, close, remove, rename, */
/* format, and readline. */
/* */
/* Principal Programmer(s): */
/* Brian L. Donnell */
/* Gary D. Riley */
/* Bebe Ly */
/* */
/* Contributing Programmer(s): */
/* */
/* Revision History: */
/* 6.24: Added the get-char, set-locale, and */
/* read-number functions. */
/* */
/* Modified printing of floats in the format */
/* function to use the locale from the set-locale */
/* function. */
/* */
/* Moved IllegalLogicalNameMessage function to */
/* argacces.c. */
/* */
/*************************************************************/
#define _IOFUN_SOURCE_
#include "setup.h"
#if EXT_IO
#include <locale.h>
#include <stdlib.h>
#include <ctype.h>
#endif
#include <stdio.h>
#define _STDIO_INCLUDED_
#include <string.h>
#include "envrnmnt.h"
#include "router.h"
#include "strngrtr.h"
#include "filertr.h"
#include "argacces.h"
#include "extnfunc.h"
#include "scanner.h"
#include "constant.h"
#include "memalloc.h"
#include "commline.h"
#include "sysdep.h"
#include "utility.h"
#include "iofun.h"
/***************/
/* DEFINITIONS */
/***************/
#define FORMAT_MAX 512
#define FLAG_MAX 80
/********************/
/* ENVIRONMENT DATA */
/********************/
#define IO_FUNCTION_DATA 64
struct IOFunctionData
{
void *locale;
};
#define IOFunctionData(theEnv) ((struct IOFunctionData *) GetEnvironmentData(theEnv,IO_FUNCTION_DATA))
/****************************************/
/* LOCAL INTERNAL FUNCTION DEFINITIONS */
/****************************************/
#if BASIC_IO
static void ReadTokenFromStdin(void *,struct token *);
#endif
#if EXT_IO
static char *ControlStringCheck(void *,int);
static char FindFormatFlag(char *,unsigned *,char *,int *);
static char *PrintFormatFlag(void *,char *,int,int,int);
static char *FillBuffer(void *,char *,int *,unsigned *);
static void ReadNumber(void *,char *,struct token *,int);
#endif
/**************************************/
/* IOFunctionDefinitions: Initializes */
/* the I/O functions. */
/**************************************/
globle void IOFunctionDefinitions(
void *theEnv)
{
AllocateEnvironmentData(theEnv,IO_FUNCTION_DATA,sizeof(struct IOFunctionData),NULL);
IOFunctionData(theEnv)->locale = (SYMBOL_HN *) EnvAddSymbol(theEnv,setlocale(LC_ALL,NULL));
IncrementSymbolCount(IOFunctionData(theEnv)->locale);
#if ! RUN_TIME
#if BASIC_IO
EnvDefineFunction2(theEnv,"printout", 'v', PTIEF PrintoutFunction, "PrintoutFunction", "1*");
EnvDefineFunction2(theEnv,"read", 'u', PTIEF ReadFunction, "ReadFunction", "*1");
EnvDefineFunction2(theEnv,"open", 'b', OpenFunction, "OpenFunction", "23*k");
EnvDefineFunction2(theEnv,"close", 'b', CloseFunction, "CloseFunction", "*1");
EnvDefineFunction2(theEnv,"get-char", 'i', GetCharFunction, "GetCharFunction", "*1");
#endif
#if EXT_IO
EnvDefineFunction2(theEnv,"remove", 'b', RemoveFunction, "RemoveFunction", "11k");
EnvDefineFunction2(theEnv,"rename", 'b', RenameFunction, "RenameFunction", "22k");
EnvDefineFunction2(theEnv,"format", 's', PTIEF FormatFunction, "FormatFunction", "2**us");
EnvDefineFunction2(theEnv,"readline", 'k', PTIEF ReadlineFunction, "ReadlineFunction", "*1");
EnvDefineFunction2(theEnv,"set-locale", 'u', PTIEF SetLocaleFunction, "SetLocaleFunction", "*1");
EnvDefineFunction2(theEnv,"read-number", 'u', PTIEF ReadNumberFunction, "ReadNumberFunction", "*1");
#endif
#else
#if MAC_MCW || IBM_MCW || MAC_XCD
#pragma unused(theEnv)
#endif
#endif
}
#if BASIC_IO
/******************************************/
/* PrintoutFunction: H/L access routine */
/* for the printout function. */
/******************************************/
globle void PrintoutFunction(
void *theEnv)
{
char *dummyid;
int i, argCount;
DATA_OBJECT theArgument;
/*=======================================================*/
/* The printout function requires at least one argument. */
/*=======================================================*/
if ((argCount = EnvArgCountCheck(theEnv,"printout",AT_LEAST,1)) == -1) return;
/*=====================================================*/
/* Get the logical name to which output is to be sent. */
/*=====================================================*/
dummyid = GetLogicalName(theEnv,1,"stdout");
if (dummyid == NULL)
{
IllegalLogicalNameMessage(theEnv,"printout");
SetHaltExecution(theEnv,TRUE);
SetEvaluationError(theEnv,TRUE);
return;
}
/*============================================================*/
/* Determine if any router recognizes the output destination. */
/*============================================================*/
if (strcmp(dummyid,"nil") == 0)
{ return; }
else if (QueryRouters(theEnv,dummyid) == FALSE)
{
UnrecognizedRouterMessage(theEnv,dummyid);
return;
}
/*===============================================*/
/* Print each of the arguments sent to printout. */
/*===============================================*/
for (i = 2; i <= argCount; i++)
{
EnvRtnUnknown(theEnv,i,&theArgument);
if (EvaluationData(theEnv)->HaltExecution) break;
switch(GetType(theArgument))
{
case SYMBOL:
if (strcmp(DOToString(theArgument),"crlf") == 0)
{ EnvPrintRouter(theEnv,dummyid,"\n"); }
else if (strcmp(DOToString(theArgument),"tab") == 0)
{ EnvPrintRouter(theEnv,dummyid,"\t"); }
else if (strcmp(DOToString(theArgument),"vtab") == 0)
{ EnvPrintRouter(theEnv,dummyid,"\v"); }
else if (strcmp(DOToString(theArgument),"ff") == 0)
{ EnvPrintRouter(theEnv,dummyid,"\f"); }
else if (strcmp(DOToString(theArgument),"t") == 0)
{ EnvPrintRouter(theEnv,dummyid,"\n"); }
else
{ EnvPrintRouter(theEnv,dummyid,DOToString(theArgument)); }
break;
case STRING:
EnvPrintRouter(theEnv,dummyid,DOToString(theArgument));
break;
default:
PrintDataObject(theEnv,dummyid,&theArgument);
break;
}
}
}
/*************************************************************/
/* ReadFunction: H/L access routine for the read function. */
/*************************************************************/
globle void ReadFunction(
void *theEnv,
DATA_OBJECT_PTR returnValue)
{
struct token theToken;
int numberOfArguments;
char *logicalName = NULL;
/*===============================================*/
/* Check for an appropriate number of arguments. */
/*===============================================*/
if ((numberOfArguments = EnvArgCountCheck(theEnv,"read",NO_MORE_THAN,1)) == -1)
{
returnValue->type = STRING;
returnValue->value = (void *) EnvAddSymbol(theEnv,"*** READ ERROR ***");
return;
}
/*======================================================*/
/* Determine the logical name from which input is read. */
/*======================================================*/
if (numberOfArguments == 0)
{ logicalName = "stdin"; }
else if (numberOfArguments == 1)
{
logicalName = GetLogicalName(theEnv,1,"stdin");
if (logicalName == NULL)
{
IllegalLogicalNameMessage(theEnv,"read");
SetHaltExecution(theEnv,TRUE);
SetEvaluationError(theEnv,TRUE);
returnValue->type = STRING;
returnValue->value = (void *) EnvAddSymbol(theEnv,"*** READ ERROR ***");
return;
}
}
/*============================================*/
/* Check to see that the logical name exists. */
/*============================================*/
if (QueryRouters(theEnv,logicalName) == FALSE)
{
UnrecognizedRouterMessage(theEnv,logicalName);
SetHaltExecution(theEnv,TRUE);
SetEvaluationError(theEnv,TRUE);
returnValue->type = STRING;
returnValue->value = (void *) EnvAddSymbol(theEnv,"*** READ ERROR ***");
return;
}
/*=======================================*/
/* Collect input into string if the read */
/* source is stdin, else just get token. */
/*=======================================*/
if (strcmp(logicalName,"stdin") == 0)
{ ReadTokenFromStdin(theEnv,&theToken); }
else
{ GetToken(theEnv,logicalName,&theToken); }
RouterData(theEnv)->CommandBufferInputCount = -1;
/*====================================================*/
/* Copy the token to the return value data structure. */
/*====================================================*/
returnValue->type = theToken.type;
if ((theToken.type == FLOAT) || (theToken.type == STRING) ||
#if OBJECT_SYSTEM
(theToken.type == INSTANCE_NAME) ||
#endif
(theToken.type == SYMBOL) || (theToken.type == INTEGER))
{ returnValue->value = theToken.value; }
else if (theToken.type == STOP)
{
returnValue->type = SYMBOL;
returnValue->value = (void *) EnvAddSymbol(theEnv,"EOF");
}
else if (theToken.type == UNKNOWN_VALUE)
{
returnValue->type = STRING;
returnValue->value = (void *) EnvAddSymbol(theEnv,"*** READ ERROR ***");
}
else
{
returnValue->type = STRING;
returnValue->value = (void *) EnvAddSymbol(theEnv,theToken.printForm);
}
return;
}
/********************************************************/
/* ReadTokenFromStdin: Special routine used by the read */
/* function to read a token from standard input. */
/********************************************************/
static void ReadTokenFromStdin(
void *theEnv,
struct token *theToken)
{
char *inputString;
unsigned inputStringSize;
int inchar;
/*=============================================*/
/* Continue processing until a token is found. */
/*=============================================*/
theToken->type = STOP;
while (theToken->type == STOP)
{
/*===========================================*/
/* Initialize the variables used for storing */
/* the characters retrieved from stdin. */
/*===========================================*/
inputString = NULL;
RouterData(theEnv)->CommandBufferInputCount = 0;
inputStringSize = 0;
inchar = EnvGetcRouter(theEnv,"stdin");
/*========================================================*/
/* Continue reading characters until a carriage return is */
/* entered or the user halts execution (usually with */
/* control-c). Waiting for the carriage return prevents */
/* the input from being prematurely parsed (such as when */
/* a space is entered after a symbol has been typed). */
/*========================================================*/
while ((inchar != '\n') && (inchar != '\r') && (inchar != EOF) &&
(! GetHaltExecution(theEnv)))
{
inputString = ExpandStringWithChar(theEnv,inchar,inputString,&RouterData(theEnv)->CommandBufferInputCount,
&inputStringSize,inputStringSize + 80);
inchar = EnvGetcRouter(theEnv,"stdin");
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -