This source file includes following definitions.
- save_err
- get_stream
- add_stream
- del_stream
- cmdStream
- stream_init
- streamOpen
- not_open
- streamClose
- streamGets
- streamPuts
- streamTell
- streamEof
- streamErr
- streamName
- streamSeek
#include <stdio.h>
#include <tcl.h>
#define STATIC
int streamOpen(),
streamClose(),
streamGets(),
streamPuts(),
streamEof(),
streamName(),
streamErr(),
streamTell(),
streamSeek();
static struct subcmd {
int (*func)();
char *name;
int min;
int max;
char *args;
} commands[] = {
{ streamOpen, "open", 2, 2, "name mode" },
{ streamClose, "close", 0, 0, "" },
{ streamGets, "gets", 0, 0, "" },
{ streamPuts, "puts", 1, 1, "line" },
{ streamEof, "eof", 0, 0, "" },
{ streamErr, "error", 0, 0, "" },
{ streamName, "name", 0, 0, "" },
{ streamTell, "tell", 0, 0, "" },
{ streamSeek, "seek", 1, 2, "offset [whence]" },
};
static struct stream {
struct stream *next;
char *name;
char *filename;
char *error;
FILE *fp;
} *streams = NULL;
save_err(s)
struct stream *s;
{
char *strerror();
extern int errno;
char *name;
name = strerror(errno);
if(!name)
return;
if(s->error) ckfree(s->error);
s->error = 0;
s->error = ckalloc(strlen(name)+1);
strcpy(s->error, name);
}
STATIC struct stream *get_stream(name)
char *name;
{
struct stream *s;
for(s = streams; s; s = s->next)
if(strcmp(name, s->name) == 0)
break;
return s;
}
STATIC struct stream *add_stream(name, filename, fp)
char *name;
char *filename;
FILE *fp;
{
struct stream *s;
s = (struct stream *)ckalloc(sizeof(struct stream)
+ strlen(name) + 1
+ (filename ? (strlen(filename)+1) : 0) );
s->name = (char *)&s[1];
strcpy(s->name, name);
if(filename) {
s->filename = s->name + strlen(name) + 1;
strcpy(s->filename, filename);
} else
s->filename = NULL;
s->fp = fp;
s->error = NULL;
s->next = streams;
streams = s;
}
STATIC del_stream(name)
char *name;
{
struct stream *p, *q;
p = streams;
q = NULL;
while(p) {
if(strcmp(p->name, name) == 0) {
if(q)
q->next = p->next;
else
streams = p->next;
if(p->error) ckfree(p->error);
ckfree(p);
return 1;
}
q = p;
p = p->next;
}
return 0;
}
STATIC cmdStream(cmdname, interp, argc, argv)
char *cmdname;
Tcl_Interp *interp;
int argc;
char **argv;
{
struct subcmd *cmdv = commands;
int cmdc = sizeof commands / sizeof *commands;
char *handle, *action;
char *err;
char *name;
char *args;
err = "wrong # args in";
action = "stream";
name = "command";
args = "args...";
if(argc < 3)
goto error;
argv++; --argc;
handle = *argv++; --argc;
action = *argv++; --argc;
while(cmdc > 0) {
if(strcmp(action, cmdv->name) == 0) {
int result;
name = cmdv->name;
args = cmdv->args;
if(argc < cmdv->min
|| (cmdv->max != -1 && argc > cmdv->max))
goto error;
result = (*cmdv->func)(interp, handle, argc, argv);
return result;
}
cmdv++;
cmdc--;
}
err = "unknown subcommand";
error:
sprintf(interp->result, "%s %s: should be \"%.50s handle %s %s\"",
err, action, cmdname, name, args);
return TCL_ERROR;
}
stream_init(interp)
Tcl_Interp *interp;
{
Tcl_CreateCommand(interp, "stream",
cmdStream, (ClientData) "stream", NULL);
add_stream("stdin", (char *)NULL, stdin);
add_stream("stdout", (char *)NULL, stdout);
add_stream("stderr", (char *)NULL, stderr);
}
STATIC int streamOpen(interp, handle, argc, argv)
Tcl_Interp *interp;
char *handle;
int argc;
char **argv;
{
FILE *fp;
if(!(fp = fopen(argv[0], argv[1]))) {
char *strerror();
extern int errno;
char *s = strerror(errno);
if(s)
sprintf(interp->result, "%s: %s", argv[0], s);
else
Tcl_Return(interp, (char *)NULL, TCL_STATIC);
return TCL_ERROR;
}
add_stream(handle, argv[0], fp);
return TCL_OK;
}
STATIC not_open(interp, name)
Tcl_Interp *interp;
char *name;
{
sprintf(interp->result,
"%.50s is not an open stream", name);
}
STATIC int streamClose(interp, handle, argc, argv)
Tcl_Interp *interp;
char *handle;
int argc;
char **argv;
{
struct stream *s = get_stream(handle);
if(!s) {
not_open(interp, handle);
return TCL_ERROR;
}
fclose(s->fp);
del_stream(handle);
return TCL_OK;
}
STATIC int streamGets(interp, handle, argc, argv)
Tcl_Interp *interp;
char *handle;
int argc;
char **argv;
{
struct stream *s = get_stream(handle);
char *buffer = ckalloc(BUFSIZ);
char *ptr, *strchr();
if(!s) {
not_open(interp, handle);
ckfree(buffer);
return TCL_ERROR;
}
if(fgets(buffer, BUFSIZ, s->fp)) {
ptr = strchr(buffer, '\n');
if(ptr)
*ptr = 0;
Tcl_Return(interp, buffer, TCL_VOLATILE);
}
else
{
Tcl_Return(interp, (char *)NULL, TCL_STATIC);
}
ckfree(buffer);
return TCL_OK;
}
STATIC int streamPuts(interp, handle, argc, argv)
Tcl_Interp *interp;
char *handle;
int argc;
char **argv;
{
struct stream *s = get_stream(handle);
char buffer[BUFSIZ];
if(!s) {
not_open(interp, handle);
return TCL_ERROR;
}
if(fputs(argv[0], s->fp) == EOF) save_err(s);
if(putc('\n', s->fp) == EOF) save_err(s);
return TCL_OK;
}
STATIC int streamTell(interp, handle, argc, argv)
Tcl_Interp *interp;
char *handle;
int argc;
char **argv;
{
struct stream *s = get_stream(handle);
long offset, ftell();
if(!s) {
not_open(interp, handle);
return TCL_ERROR;
}
sprintf(interp->result, "%ld", offset = ftell(s->fp));
if(offset == -1) save_err(s);
return TCL_OK;
}
STATIC int streamEof(interp, handle, argc, argv)
Tcl_Interp *interp;
char *handle;
int argc;
char **argv;
{
struct stream *s = get_stream(handle);
if(!s) {
not_open(interp, handle);
return TCL_ERROR;
}
sprintf(interp->result, "%d", !!feof(s->fp));
return TCL_OK;
}
STATIC int streamErr(interp, handle, argc, argv)
Tcl_Interp *interp;
char *handle;
int argc;
char **argv;
{
struct stream *s = get_stream(handle);
if(!s) {
not_open(interp, handle);
return TCL_ERROR;
}
if(ferror(s->fp) && s->error)
Tcl_Return(interp, s->error, TCL_VOLATILE);
else
Tcl_Return(interp, (char *)NULL, TCL_STATIC);
return TCL_OK;
}
STATIC int streamName(interp, handle, argc, argv)
Tcl_Interp *interp;
char *handle;
int argc;
char **argv;
{
struct stream *s = get_stream(handle);
if(!s) {
not_open(interp, handle);
return TCL_ERROR;
}
if(s->filename)
Tcl_Return(interp, s->filename, TCL_VOLATILE);
else
Tcl_Return(interp, (char *)NULL, TCL_STATIC);
return TCL_OK;
}
STATIC int streamSeek(interp, handle, argc, argv)
Tcl_Interp *interp;
char *handle;
int argc;
char **argv;
{
struct stream *s = get_stream(handle);
int whence;
long offset, fseek();
long strtol();
char *endptr;
if(!s) {
not_open(interp, handle);
return TCL_ERROR;
}
if(argc > 1) whence = atoi(argv[1]);
else whence = 0;
offset = strtol(argv[0], &endptr, 0);
offset = fseek(s->fp, offset, whence);
sprintf(interp->result, "%ld", offset);
if(offset == -1) save_err(s);
return TCL_OK;
}