1 /*******************************************************/
2 /* "C" Language Integrated Production System */
3 /* */
4 /* CLIPS Version 6.30 01/26/15 */
5 /* */
6 /* FILE I/O ROUTER MODULE */
7 /*******************************************************/
8
9 /*************************************************************/
10 /* Purpose: I/O Router routines which allow files to be used */
11 /* as input and output sources. */
12 /* */
13 /* Principal Programmer(s): */
14 /* Gary D. Riley */
15 /* */
16 /* Contributing Programmer(s): */
17 /* Brian L. Dantes */
18 /* */
19 /* Revision History: */
20 /* */
21 /* 6.24: Added environment parameter to GenClose. */
22 /* Added environment parameter to GenOpen. */
23 /* */
24 /* Added pragmas to remove compilation warnings. */
25 /* */
26 /* 6.30: Removed conditional code for unsupported */
27 /* compilers/operating systems (IBM_MCW, */
28 /* MAC_MCW, and IBM_TBC). */
29 /* */
30 /* Used gengetc and genungetchar rather than */
31 /* getc and ungetc. */
32 /* */
33 /* Replaced BASIC_IO and ADVANCED_IO compiler */
34 /* flags with the single IO_FUNCTIONS compiler */
35 /* flag. */
36 /* */
37 /* Added const qualifiers to remove C++ */
38 /* deprecation warnings. */
39 /* */
40 /* Added STDOUT and STDIN logical name */
41 /* definitions. */
42 /* */
43 /*************************************************************/
44
45 #define _FILERTR_SOURCE_
46
47 #include <stdio.h>
48 #define _STDIO_INCLUDED_
49 #include <string.h>
50
51 #include "setup.h"
52
53 #include "constant.h"
54 #include "envrnmnt.h"
55 #include "memalloc.h"
56 #include "router.h"
57 #include "sysdep.h"
58
59 #include "filertr.h"
60
61 /***************************************/
62 /* LOCAL INTERNAL FUNCTION DEFINITIONS */
63 /***************************************/
64
65 static int ExitFile(void *,int);
66 static int PrintFile(void *,const char *,const char *);
67 static int GetcFile(void *,const char *);
68 static int UngetcFile(void *,int,const char *);
69 static void DeallocateFileRouterData(void *);
70
71 /***************************************************************/
72 /* InitializeFileRouter: Initializes file input/output router. */
73 /***************************************************************/
InitializeFileRouter(void * theEnv)74 globle void InitializeFileRouter(
75 void *theEnv)
76 {
77 AllocateEnvironmentData(theEnv,FILE_ROUTER_DATA,sizeof(struct fileRouterData),DeallocateFileRouterData);
78
79 EnvAddRouter(theEnv,"fileio",0,FindFile,
80 PrintFile,GetcFile,
81 UngetcFile,ExitFile);
82 }
83
84 /*****************************************/
85 /* DeallocateFileRouterData: Deallocates */
86 /* environment data for file routers. */
87 /*****************************************/
DeallocateFileRouterData(void * theEnv)88 static void DeallocateFileRouterData(
89 void *theEnv)
90 {
91 struct fileRouter *tmpPtr, *nextPtr;
92
93 tmpPtr = FileRouterData(theEnv)->ListOfFileRouters;
94 while (tmpPtr != NULL)
95 {
96 nextPtr = tmpPtr->next;
97 GenClose(theEnv,tmpPtr->stream);
98 rm(theEnv,(void *) tmpPtr->logicalName,strlen(tmpPtr->logicalName) + 1);
99 rtn_struct(theEnv,fileRouter,tmpPtr);
100 tmpPtr = nextPtr;
101 }
102 }
103
104 /*****************************************/
105 /* FindFptr: Returns a pointer to a file */
106 /* stream for a given logical name. */
107 /*****************************************/
FindFptr(void * theEnv,const char * logicalName)108 globle FILE *FindFptr(
109 void *theEnv,
110 const char *logicalName)
111 {
112 struct fileRouter *fptr;
113
114 /*========================================================*/
115 /* Check to see if standard input or output is requested. */
116 /*========================================================*/
117
118 if (strcmp(logicalName,STDOUT) == 0)
119 { return(stdout); }
120 else if (strcmp(logicalName,STDIN) == 0)
121 { return(stdin); }
122 else if (strcmp(logicalName,WTRACE) == 0)
123 { return(stdout); }
124 else if (strcmp(logicalName,WDIALOG) == 0)
125 { return(stdout); }
126 else if (strcmp(logicalName,WPROMPT) == 0)
127 { return(stdout); }
128 else if (strcmp(logicalName,WDISPLAY) == 0)
129 { return(stdout); }
130 else if (strcmp(logicalName,WERROR) == 0)
131 { return(stdout); }
132 else if (strcmp(logicalName,WWARNING) == 0)
133 { return(stdout); }
134
135 /*==============================================================*/
136 /* Otherwise, look up the logical name on the global file list. */
137 /*==============================================================*/
138
139 fptr = FileRouterData(theEnv)->ListOfFileRouters;
140 while ((fptr != NULL) ? (strcmp(logicalName,fptr->logicalName) != 0) : FALSE)
141 { fptr = fptr->next; }
142
143 if (fptr != NULL) return(fptr->stream);
144
145 return(NULL);
146 }
147
148 /*****************************************************/
149 /* FindFile: Find routine for file router logical */
150 /* names. Returns TRUE if the specified logical */
151 /* name has an associated file stream (which means */
152 /* that the logical name can be handled by the */
153 /* file router). Otherwise, FALSE is returned. */
154 /*****************************************************/
FindFile(void * theEnv,const char * logicalName)155 globle int FindFile(
156 void *theEnv,
157 const char *logicalName)
158 {
159 if (FindFptr(theEnv,logicalName) != NULL) return(TRUE);
160
161 return(FALSE);
162 }
163
164 /********************************************/
165 /* ExitFile: Exit routine for file router. */
166 /********************************************/
ExitFile(void * theEnv,int num)167 static int ExitFile(
168 void *theEnv,
169 int num)
170 {
171 #if MAC_XCD
172 #pragma unused(num)
173 #endif
174 #if IO_FUNCTIONS
175 CloseAllFiles(theEnv);
176 #else
177 #if MAC_XCD
178 #pragma unused(theEnv)
179 #endif
180 #endif
181 return(1);
182 }
183
184 /*********************************************/
185 /* PrintFile: Print routine for file router. */
186 /*********************************************/
PrintFile(void * theEnv,const char * logicalName,const char * str)187 static int PrintFile(
188 void *theEnv,
189 const char *logicalName,
190 const char *str)
191 {
192 FILE *fptr;
193
194 fptr = FindFptr(theEnv,logicalName);
195
196 genprintfile(theEnv,fptr,str);
197
198 return(1);
199 }
200
201 /*******************************************/
202 /* GetcFile: Getc routine for file router. */
203 /*******************************************/
GetcFile(void * theEnv,const char * logicalName)204 static int GetcFile(
205 void *theEnv,
206 const char *logicalName)
207 {
208 FILE *fptr;
209 int theChar;
210
211 fptr = FindFptr(theEnv,logicalName);
212
213 if (fptr == stdin)
214 { theChar = gengetchar(theEnv); }
215 else
216 { theChar = getc(fptr); }
217
218 /*=================================================*/
219 /* The following code prevents Control-D on UNIX */
220 /* machines from terminating all input from stdin. */
221 /*=================================================*/
222
223 if ((fptr == stdin) && (theChar == EOF)) clearerr(stdin);
224
225 return(theChar);
226 }
227
228 /***********************************************/
229 /* UngetcFile: Ungetc routine for file router. */
230 /***********************************************/
UngetcFile(void * theEnv,int ch,const char * logicalName)231 static int UngetcFile(
232 void *theEnv,
233 int ch,
234 const char *logicalName)
235 {
236 FILE *fptr;
237
238 fptr = FindFptr(theEnv,logicalName);
239
240 if (fptr == stdin)
241 { return(genungetchar(theEnv,ch)); }
242 else
243 { return(ungetc(ch,fptr)); }
244 }
245
246 /*********************************************************/
247 /* OpenFile: Opens a file with the specified access mode */
248 /* and stores the opened stream on the list of files */
249 /* associated with logical names Returns TRUE if the */
250 /* file was succesfully opened, otherwise FALSE. */
251 /*********************************************************/
OpenAFile(void * theEnv,const char * fileName,const char * accessMode,const char * logicalName)252 globle int OpenAFile(
253 void *theEnv,
254 const char *fileName,
255 const char *accessMode,
256 const char *logicalName)
257 {
258 FILE *newstream;
259 struct fileRouter *newRouter;
260 char *theName;
261
262 /*==================================*/
263 /* Make sure the file can be opened */
264 /* with the specified access mode. */
265 /*==================================*/
266
267 if ((newstream = GenOpen(theEnv,fileName,accessMode)) == NULL)
268 { return(FALSE); }
269
270 /*===========================*/
271 /* Create a new file router. */
272 /*===========================*/
273
274 newRouter = get_struct(theEnv,fileRouter);
275 theName = (char *) gm2(theEnv,strlen(logicalName) + 1);
276 genstrcpy(theName,logicalName);
277 newRouter->logicalName = theName;
278 newRouter->stream = newstream;
279
280 /*==========================================*/
281 /* Add the newly opened file to the list of */
282 /* files associated with logical names. */
283 /*==========================================*/
284
285 newRouter->next = FileRouterData(theEnv)->ListOfFileRouters;
286 FileRouterData(theEnv)->ListOfFileRouters = newRouter;
287
288 /*==================================*/
289 /* Return TRUE to indicate the file */
290 /* was opened successfully. */
291 /*==================================*/
292
293 return(TRUE);
294 }
295
296 /*************************************************************/
297 /* CloseFile: Closes the file associated with the specified */
298 /* logical name. Returns TRUE if the file was successfully */
299 /* closed, otherwise FALSE. */
300 /*************************************************************/
CloseFile(void * theEnv,const char * fid)301 globle int CloseFile(
302 void *theEnv,
303 const char *fid)
304 {
305 struct fileRouter *fptr, *prev;
306
307 for (fptr = FileRouterData(theEnv)->ListOfFileRouters, prev = NULL;
308 fptr != NULL;
309 fptr = fptr->next)
310 {
311 if (strcmp(fptr->logicalName,fid) == 0)
312 {
313 GenClose(theEnv,fptr->stream);
314 rm(theEnv,(void *) fptr->logicalName,strlen(fptr->logicalName) + 1);
315 if (prev == NULL)
316 { FileRouterData(theEnv)->ListOfFileRouters = fptr->next; }
317 else
318 { prev->next = fptr->next; }
319 rm(theEnv,fptr,(int) sizeof(struct fileRouter));
320
321 return(TRUE);
322 }
323
324 prev = fptr;
325 }
326
327 return(FALSE);
328 }
329
330 /**********************************************/
331 /* CloseAllFiles: Closes all files associated */
332 /* with a file I/O router. Returns TRUE if */
333 /* any file was closed, otherwise FALSE. */
334 /**********************************************/
CloseAllFiles(void * theEnv)335 globle int CloseAllFiles(
336 void *theEnv)
337 {
338 struct fileRouter *fptr, *prev;
339
340 if (FileRouterData(theEnv)->ListOfFileRouters == NULL) return(FALSE);
341
342 fptr = FileRouterData(theEnv)->ListOfFileRouters;
343
344 while (fptr != NULL)
345 {
346 GenClose(theEnv,fptr->stream);
347 prev = fptr;
348 rm(theEnv,(void *) fptr->logicalName,strlen(fptr->logicalName) + 1);
349 fptr = fptr->next;
350 rm(theEnv,prev,(int) sizeof(struct fileRouter));
351 }
352
353 FileRouterData(theEnv)->ListOfFileRouters = NULL;
354
355 return(TRUE);
356 }
357
358
359
360