home *** CD-ROM | disk | FTP | other *** search
- /* stream commands for tcl */
- #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;
- }
-