home *** CD-ROM | disk | FTP | other *** search
/ Source Code 1992 March / Source_Code_CD-ROM_Walnut_Creek_March_1992.iso / usenet / altsrcs / 0 / 0988 / stream.c < prev    next >
Encoding:
C/C++ Source or Header  |  1990-12-28  |  6.5 KB  |  382 lines

  1. /* stream commands for tcl */
  2. #include <stdio.h>
  3. #include <tcl.h>
  4.  
  5. #define STATIC
  6.  
  7. int streamOpen(),
  8.     streamClose(),
  9.     streamGets(),
  10.     streamPuts(),
  11.     streamEof(),
  12.     streamName(),
  13.     streamErr(),
  14.     streamTell(),
  15.     streamSeek();
  16.  
  17. static struct subcmd {
  18.     int (*func)();
  19.     char *name;
  20.     int min;
  21.     int max;
  22.     char *args;
  23. } commands[] = {
  24.     { streamOpen, "open", 2, 2, "name mode" },
  25.     { streamClose, "close", 0, 0, "" },
  26.     { streamGets, "gets", 0, 0, "" },
  27.     { streamPuts, "puts", 1, 1, "line" },
  28.     { streamEof, "eof", 0, 0, "" },
  29.     { streamErr, "error", 0, 0, "" },
  30.     { streamName, "name", 0, 0, "" },
  31.     { streamTell, "tell", 0, 0, "" },
  32.     { streamSeek, "seek", 1, 2, "offset [whence]" },
  33. };
  34.  
  35. static struct stream {
  36.     struct stream *next;
  37.     char *name;
  38.     char *filename;
  39.     char *error;
  40.     FILE *fp;
  41. } *streams = NULL;
  42.  
  43. save_err(s)
  44. struct stream *s;
  45. {
  46.     char *strerror();
  47.     extern int errno;
  48.     char *name;
  49.  
  50.     name = strerror(errno);
  51.     if(!name)
  52.         return;
  53.  
  54.     if(s->error) ckfree(s->error);
  55.     s->error = 0;
  56.     s->error = ckalloc(strlen(name)+1);
  57.     strcpy(s->error, name);
  58. }
  59.  
  60. STATIC struct stream *get_stream(name)
  61. char *name;
  62. {
  63.     struct stream *s;
  64.  
  65.     for(s = streams; s; s = s->next)
  66.         if(strcmp(name, s->name) == 0)
  67.             break;
  68.     return s;
  69. }
  70.  
  71. STATIC struct stream *add_stream(name, filename, fp)
  72. char *name;
  73. char *filename;
  74. FILE *fp;
  75. {
  76.     struct stream *s;
  77.  
  78.     s = (struct stream *)ckalloc(sizeof(struct stream)
  79.         + strlen(name) + 1
  80.         + (filename ? (strlen(filename)+1) : 0) );
  81.  
  82.     s->name = (char *)&s[1];
  83.     strcpy(s->name, name);
  84.     if(filename) {
  85.         s->filename = s->name + strlen(name) + 1;
  86.         strcpy(s->filename, filename);
  87.     } else
  88.         s->filename = NULL;
  89.     s->fp = fp;
  90.     s->error = NULL;
  91.     s->next = streams;
  92.     streams = s;
  93. }
  94.  
  95. STATIC del_stream(name)
  96. char *name;
  97. {
  98.     struct stream *p, *q;
  99.  
  100.     p = streams;
  101.     q = NULL;
  102.     while(p) {
  103.         if(strcmp(p->name, name) == 0) {
  104.             if(q)
  105.                 q->next = p->next;
  106.             else
  107.                 streams = p->next;
  108.             if(p->error) ckfree(p->error);
  109.             ckfree(p);
  110.             return 1;
  111.         }
  112.         q = p;
  113.         p = p->next;
  114.     }
  115.     return 0;
  116. }
  117.  
  118. STATIC cmdStream(cmdname, interp, argc, argv)
  119. char *cmdname;
  120. Tcl_Interp *interp;
  121. int argc;
  122. char **argv;
  123. {
  124.     struct subcmd *cmdv = commands;
  125.     int cmdc = sizeof commands / sizeof *commands;
  126.  
  127.     char *handle, *action;
  128.  
  129.     char *err;
  130.     char *name;
  131.     char *args;
  132.  
  133.     err = "wrong # args in";
  134.     action = "stream";
  135.     name = "command";
  136.     args = "args...";
  137.  
  138.     if(argc < 3)
  139.         goto error;
  140.  
  141.     argv++; --argc;
  142.     handle = *argv++; --argc;
  143.     action = *argv++; --argc;
  144.  
  145.     while(cmdc > 0) {
  146.         if(strcmp(action, cmdv->name) == 0) {
  147.             int result;
  148.  
  149.             name = cmdv->name;
  150.             args = cmdv->args;
  151.             if(argc < cmdv->min
  152.                || (cmdv->max != -1 && argc > cmdv->max))
  153.                 goto error;
  154.             result = (*cmdv->func)(interp, handle, argc, argv);
  155.             return result;
  156.         }
  157.         cmdv++;
  158.         cmdc--;
  159.     }
  160.     err = "unknown subcommand";
  161. error:
  162.     sprintf(interp->result, "%s %s:  should be \"%.50s handle %s %s\"",
  163.         err, action, cmdname, name, args);
  164.     return TCL_ERROR;
  165. }
  166.  
  167. stream_init(interp)
  168. Tcl_Interp *interp;
  169. {
  170.     Tcl_CreateCommand(interp, "stream",
  171.         cmdStream, (ClientData) "stream", NULL);
  172.     add_stream("stdin", (char *)NULL, stdin);
  173.     add_stream("stdout", (char *)NULL, stdout);
  174.     add_stream("stderr", (char *)NULL, stderr);
  175. }
  176.  
  177. STATIC int streamOpen(interp, handle, argc, argv)
  178. Tcl_Interp *interp;
  179. char *handle;
  180. int argc;
  181. char **argv;
  182. {
  183.     FILE *fp;
  184.  
  185.     if(!(fp = fopen(argv[0], argv[1]))) {
  186.         char *strerror();
  187.         extern int errno;
  188.         char *s = strerror(errno);
  189.         if(s)
  190.             sprintf(interp->result, "%s: %s", argv[0], s);
  191.         else
  192.             Tcl_Return(interp, (char *)NULL, TCL_STATIC);
  193.         return TCL_ERROR;
  194.     }
  195.  
  196.     add_stream(handle, argv[0], fp);
  197.     return TCL_OK;
  198. }
  199.  
  200. STATIC not_open(interp, name)
  201. Tcl_Interp *interp;
  202. char *name;
  203. {
  204.     sprintf(interp->result,
  205.         "%.50s is not an open stream", name);
  206. }
  207.  
  208. STATIC int streamClose(interp, handle, argc, argv)
  209. Tcl_Interp *interp;
  210. char *handle;
  211. int argc;
  212. char **argv;
  213. {
  214.     struct stream *s = get_stream(handle);
  215.  
  216.     if(!s) {
  217.         not_open(interp, handle);
  218.         return TCL_ERROR;
  219.     }
  220.  
  221.     fclose(s->fp);
  222.     del_stream(handle);
  223.     return TCL_OK;
  224. }
  225.  
  226. STATIC int streamGets(interp, handle, argc, argv)
  227. Tcl_Interp *interp;
  228. char *handle;
  229. int argc;
  230. char **argv;
  231. {
  232.     struct stream *s = get_stream(handle);
  233.     char *buffer = ckalloc(BUFSIZ);
  234.     char *ptr, *strchr();
  235.  
  236.     if(!s) {
  237.         not_open(interp, handle);
  238.         ckfree(buffer);
  239.         return TCL_ERROR;
  240.     }
  241.  
  242.     if(fgets(buffer, BUFSIZ, s->fp)) {
  243.         ptr = strchr(buffer, '\n');
  244.         if(ptr) 
  245.             *ptr = 0;
  246.         Tcl_Return(interp, buffer, TCL_VOLATILE);
  247.     }
  248.     else
  249.     {
  250.         Tcl_Return(interp, (char *)NULL, TCL_STATIC);
  251.     }
  252.     ckfree(buffer);
  253.     return TCL_OK;
  254. }
  255.  
  256. STATIC int streamPuts(interp, handle, argc, argv)
  257. Tcl_Interp *interp;
  258. char *handle;
  259. int argc;
  260. char **argv;
  261. {
  262.     struct stream *s = get_stream(handle);
  263.     char buffer[BUFSIZ];
  264.  
  265.     if(!s) {
  266.         not_open(interp, handle);
  267.         return TCL_ERROR;
  268.     }
  269.  
  270.     if(fputs(argv[0], s->fp) == EOF) save_err(s);
  271.     if(putc('\n', s->fp) == EOF) save_err(s);
  272.  
  273.     return TCL_OK;
  274. }
  275.  
  276. STATIC int streamTell(interp, handle, argc, argv)
  277. Tcl_Interp *interp;
  278. char *handle;
  279. int argc;
  280. char **argv;
  281. {
  282.     struct stream *s = get_stream(handle);
  283.     long offset, ftell();
  284.  
  285.     if(!s) {
  286.         not_open(interp, handle);
  287.         return TCL_ERROR;
  288.     }
  289.  
  290.     sprintf(interp->result, "%ld", offset = ftell(s->fp));
  291.     if(offset == -1) save_err(s);
  292.     return TCL_OK;
  293. }
  294.  
  295. STATIC int streamEof(interp, handle, argc, argv)
  296. Tcl_Interp *interp;
  297. char *handle;
  298. int argc;
  299. char **argv;
  300. {
  301.     struct stream *s = get_stream(handle);
  302.  
  303.     if(!s) {
  304.         not_open(interp, handle);
  305.         return TCL_ERROR;
  306.     }
  307.  
  308.     sprintf(interp->result, "%d", !!feof(s->fp));
  309.     return TCL_OK;
  310. }
  311.  
  312. STATIC int streamErr(interp, handle, argc, argv)
  313. Tcl_Interp *interp;
  314. char *handle;
  315. int argc;
  316. char **argv;
  317. {
  318.     struct stream *s = get_stream(handle);
  319.  
  320.     if(!s) {
  321.         not_open(interp, handle);
  322.         return TCL_ERROR;
  323.     }
  324.  
  325.     if(ferror(s->fp) && s->error)
  326.         Tcl_Return(interp, s->error, TCL_VOLATILE);
  327.     else
  328.         Tcl_Return(interp, (char *)NULL, TCL_STATIC);
  329.  
  330.     return TCL_OK;
  331. }
  332.  
  333. STATIC int streamName(interp, handle, argc, argv)
  334. Tcl_Interp *interp;
  335. char *handle;
  336. int argc;
  337. char **argv;
  338. {
  339.     struct stream *s = get_stream(handle);
  340.  
  341.     if(!s) {
  342.         not_open(interp, handle);
  343.         return TCL_ERROR;
  344.     }
  345.  
  346.     if(s->filename)
  347.         Tcl_Return(interp, s->filename, TCL_VOLATILE);
  348.     else
  349.         Tcl_Return(interp, (char *)NULL, TCL_STATIC);
  350.  
  351.     return TCL_OK;
  352. }
  353.  
  354. STATIC int streamSeek(interp, handle, argc, argv)
  355. Tcl_Interp *interp;
  356. char *handle;
  357. int argc;
  358. char **argv;
  359. {
  360.     struct stream *s = get_stream(handle);
  361.     int whence;
  362.     long offset, fseek();
  363.     long strtol();
  364.     char *endptr;
  365.  
  366.     if(!s) {
  367.         not_open(interp, handle);
  368.         return TCL_ERROR;
  369.     }
  370.  
  371.     if(argc > 1) whence = atoi(argv[1]);
  372.     else whence = 0;
  373.  
  374.     offset = strtol(argv[0], &endptr, 0);
  375.  
  376.     offset = fseek(s->fp, offset, whence);
  377.     sprintf(interp->result, "%ld", offset);
  378.     if(offset == -1) save_err(s);
  379.  
  380.     return TCL_OK;
  381. }
  382.