7 changed files with 298 additions and 3 deletions
-
2src/frontend/Makefile.am
-
181src/frontend/com_fileio.c
-
9src/frontend/com_fileio.h
-
51src/frontend/com_strcmp.c
-
5src/frontend/com_strcmp.h
-
49src/frontend/commands.c
-
2visualc/vngspice.vcxproj
@ -0,0 +1,181 @@ |
|||
/* Commands for opening and reading arbitrary files. */ |
|||
|
|||
#include <stdio.h> |
|||
#include <string.h> |
|||
#include <errno.h> |
|||
|
|||
#include "ngspice/ngspice.h" |
|||
|
|||
#include "ngspice/bool.h" |
|||
#include "ngspice/wordlist.h" |
|||
|
|||
#include "com_strcmp.h" |
|||
#include "variable.h" |
|||
|
|||
/* Track open files with these structures, indexed by the underlying |
|||
* descriptor. Not many should be needed. |
|||
*/ |
|||
|
|||
#define MAX_OPEN_FILES 20 |
|||
#define MAX_TEXT_LINE 8192 |
|||
|
|||
static struct { |
|||
FILE *fp; |
|||
char *name; |
|||
} Open_Files[MAX_OPEN_FILES]; |
|||
|
|||
/* Check whether error messages should be suppressed. That is useful when |
|||
* opening a file to see if it exists. |
|||
*/ |
|||
|
|||
static int verbose(void) |
|||
{ |
|||
return !cp_getvar("silent_fileio", CP_BOOL, NULL, 0); |
|||
} |
|||
|
|||
/* fopen handle file_name [mode] |
|||
* |
|||
* For example: fopen handle result.txt r |
|||
* |
|||
* The underlying file descriptor (or -1) is returned in the variable "handle". |
|||
*/ |
|||
|
|||
void com_fopen(wordlist *wl) |
|||
{ |
|||
char *var, *file_name, *mode; |
|||
FILE *fp; |
|||
int fd; |
|||
|
|||
var = wl->wl_word; |
|||
wl = wl->wl_next; |
|||
file_name = cp_unquote(wl->wl_word); |
|||
wl = wl->wl_next; |
|||
mode = wl ? cp_unquote(wl->wl_word) : "r"; |
|||
fp = fopen(file_name, mode); |
|||
if (fp) { |
|||
fd = fileno(fp); |
|||
if (fd < MAX_OPEN_FILES) { |
|||
if (Open_Files[fd].fp) // Not expected! |
|||
fclose(Open_Files[fd].fp); |
|||
if (Open_Files[fd].name) |
|||
tfree(Open_Files[fd].name); |
|||
Open_Files[fd].fp = fp; |
|||
Open_Files[fd].name = copy(file_name); |
|||
} else { |
|||
fclose(fp); |
|||
fprintf(stderr, |
|||
"com_fopen() cannot open %s: too many open files\n", |
|||
file_name); |
|||
fd = -1; |
|||
} |
|||
} else { |
|||
fd = -1; |
|||
if (verbose()) { |
|||
fprintf(stderr, "com_fopen() cannot open %s: %s\n", |
|||
file_name, strerror(errno)); |
|||
} |
|||
} |
|||
tfree(file_name); |
|||
if (wl) |
|||
tfree(mode); |
|||
cp_vset(var, CP_NUM, &fd); |
|||
} |
|||
|
|||
/* Command looks like: |
|||
* fread result handle [length] |
|||
* where handle is a small positive integer, result names a variable |
|||
* and length is the name of a variable used to return the length of the line. |
|||
* The returned length is -1 at EOF, -2 on failure. |
|||
*/ |
|||
|
|||
void com_fread(wordlist *wl) |
|||
{ |
|||
char *handle, *result, *lvar; |
|||
int fd, length; |
|||
char buf[MAX_TEXT_LINE]; |
|||
|
|||
result = cp_unquote(wl->wl_word); |
|||
wl = wl->wl_next; |
|||
handle = cp_unquote(wl->wl_word); |
|||
fd = atoi(handle); |
|||
tfree(handle); |
|||
wl = wl->wl_next; |
|||
if (wl) |
|||
lvar = cp_unquote(wl->wl_word); |
|||
else |
|||
lvar = NULL; |
|||
|
|||
if (fd >= 0 && fd < MAX_OPEN_FILES) { |
|||
if (!Open_Files[fd].fp) { |
|||
/* Allow stdin, for example. */ |
|||
|
|||
Open_Files[fd].fp = fdopen(fd, "r"); |
|||
if (!Open_Files[fd].fp && verbose()) { |
|||
fprintf(stderr, "com_fread() cannot open handle %d\n", fd); |
|||
goto err; |
|||
} |
|||
} |
|||
|
|||
if (fgets(buf, sizeof buf, Open_Files[fd].fp)) { |
|||
length = strlen(buf); |
|||
if (length > 0 && buf[length - 1] == '\n') { |
|||
--length; |
|||
if (length > 0 && buf[length - 1] == '\r') { |
|||
/* Windows CRLF line termination. */ |
|||
|
|||
--length; |
|||
} |
|||
buf[length] = '\0'; |
|||
} else if (verbose()) { |
|||
fprintf(stderr, |
|||
"com_fread() found line in %s " |
|||
"too long for buffer\n", |
|||
Open_Files[fd].name); |
|||
} |
|||
} else { |
|||
if (feof(Open_Files[fd].fp)) { |
|||
length = -1; |
|||
} else if (verbose()) { |
|||
fprintf(stderr, |
|||
"com_fread() error reading %s: %s\n", |
|||
Open_Files[fd].name, strerror(errno)); |
|||
length = -2; |
|||
} |
|||
*buf = '\0'; |
|||
} |
|||
} else if (verbose()) { |
|||
fprintf(stderr, |
|||
"com_fread(): file handle %d is not in accepted range.\n", |
|||
fd); |
|||
err: |
|||
length = -1; |
|||
*buf = '\0'; |
|||
} |
|||
cp_vset(result, CP_STRING, buf); |
|||
tfree(result); |
|||
if (lvar) { |
|||
cp_vset(lvar, CP_NUM, &length); |
|||
tfree(lvar); |
|||
} |
|||
} |
|||
|
|||
void com_fclose(wordlist *wl) |
|||
{ |
|||
char *handle; |
|||
int fd; |
|||
|
|||
handle = cp_unquote(wl->wl_word); |
|||
fd = atoi(handle); |
|||
tfree(handle); |
|||
if (fd <= 2 || fd >= MAX_OPEN_FILES) |
|||
return; |
|||
if (Open_Files[fd].fp) { |
|||
fclose(Open_Files[fd].fp); |
|||
Open_Files[fd].fp = NULL; |
|||
} |
|||
if (Open_Files[fd].name) |
|||
tfree(Open_Files[fd].name); |
|||
} |
|||
|
|||
|
|||
|
|||
@ -0,0 +1,9 @@ |
|||
#ifndef ngspice_COM_FILEIO_H |
|||
#define ngspice_COM_FILEIO_H |
|||
|
|||
|
|||
extern void com_fopen(wordlist *wl); |
|||
extern void com_fread(wordlist *wl); |
|||
extern void com_fclose(wordlist *wl); |
|||
|
|||
#endif |
|||
@ -1,7 +1,8 @@ |
|||
#ifndef ngspice_COM_STRCMP_H |
|||
#define ngspice_COM_STRCMP_H |
|||
|
|||
|
|||
void com_strcmp(wordlist *wl); |
|||
extern void com_strcmp(wordlist *wl); |
|||
extern void com_strstr(wordlist *wl); |
|||
extern void com_strslice(wordlist *wl); |
|||
|
|||
#endif |
|||
Write
Preview
Loading…
Cancel
Save
Reference in new issue