home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 January / usenetsourcesnewsgroupsinfomagicjanuary1994.iso / sources / misc / volume9 / draw_jt / part02 / draw.c < prev   
Encoding:
C/C++ Source or Header  |  1989-12-12  |  16.7 KB  |  702 lines

  1. /*
  2.  
  3. Copyright (C) 1988, 1989 by Juha Takala, jta@sah.vtt.fi
  4.  
  5.      This program is free software; you can redistribute it and/or modify
  6.      it under the terms of the GNU General Public License as published by
  7.      the Free Software Foundation; version 1.
  8.  
  9.      This program is distributed in the hope that it will be useful,
  10.      but WITHOUT ANY WARRANTY; without even the implied warranty of
  11.      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  12.      the file "License for more details
  13.  
  14.      You should have received a copy of the GNU General Public License
  15.      along with this program; if not, write to the Free Software
  16.      Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  17.  
  18.  
  19.  */
  20.  
  21. /* Description:
  22.  *  Non-interactive user interface program to provide interface between
  23.  *  device manipulation subroutines and user supplied command files.
  24.  *  This program will accept all kinds of command line arguments and
  25.  *  pseudo comments mixed in between the data lines.  See the man page.
  26.  *
  27.  *  The good thing about this program is that it will accept infinite
  28.  *  amount of input data points; they are not stored, but processed one
  29.  *  at a time.
  30.  */
  31. static char *RCS_id =
  32.   "$Id: draw.c,v 2.7 89/12/08 14:00:39 jta Exp Locker: jta $";
  33.  
  34. #include <stdio.h>
  35. #ifdef MSDOS
  36. #include <stdlib.h>
  37. #endif /* MSDOS */
  38. #include <string.h>
  39. #include <sys/types.h>
  40. #include <time.h>
  41. #include <math.h>
  42. #include <signal.h>
  43. #ifndef MSDOS
  44. #include <sys/inode.h>
  45. #include <sys/file.h>
  46. #endif
  47. #include <string.h>
  48. #include "dr_lib.h"
  49.  
  50. double strtod();
  51.  
  52. char *myname;
  53. float xlowl = 0.0;        /* relative plotting area on paper */
  54. float ylowl = 0.0;
  55. float xhighr= 1.0;
  56. float yhighr = 1.0;
  57.  
  58. float xlow = -1.0;        /* x axis range */
  59. float xincr = 0.5;
  60. float xhigh = 1.0;
  61. int xgrid_n = 0;
  62. char *xlabel_text = NULL;
  63.  
  64. float ylow = -1.0;        /* y axis range */
  65. float yincr = 0.5;
  66. float yhigh = 1.0;
  67. int ygrid_n = 0;
  68. char *ylabel_text = NULL;
  69.  
  70. static float x, y;        /* current point, needs to be */
  71.                 /* remembered, eg. when relative text is */
  72.                 /* inserted by #$texthere */
  73. char *name_text = NULL;        /* name of picture */
  74. int pennum = 1;
  75. int penup = 1;
  76. int no_axes = 0;
  77. int init_done = 0;
  78. int dateflag = 0;
  79. int linetype = 7;        /* default for solid linetype */
  80. float text_angle = 0.0;        /* radians */
  81. float text_size = 1.0;        /* text size factor */
  82. float text_shape = 1.0;        /* text shape factor */
  83. int cset = 0;            /* char set, default is US Ascii */
  84. int continuous = 1;        /* continuous line / discrete points */
  85.                 /* 0 = discontinous */
  86. char marker = '*';        /* default marker char in discontinous mode */
  87. char informat[200] = "%f %f";    /* default input data line format */
  88. int reversed = 0;        /* != 0 means input is y before x  */
  89. int absolute = 0;        /* != 0 when 'absolute' coordinates are */
  90.                 /* to be processed */
  91. float xabs_origin = 0.0;    /* origin of 'absolute' mode data points */
  92. float yabs_origin = 0.0;
  93.  
  94. int device = HP7475 | SIZE_A4;
  95.  
  96. static int setmode();
  97. static int labelpic();
  98. static void doit();
  99. static void setdevice();
  100. extern void exit();
  101.  
  102. static void (*old_int_handler)();
  103. static void new_int_handler();
  104. static void fatal();
  105. static void usage();
  106.  
  107. #define PUT_TEXT(x,y,xofs,yofs,text) \
  108.       dr_put_text((x), (y), (xofs), (yofs), text_angle, 1.0, (text))
  109. #define PUT_X_TEXT(x,y,text) \
  110.       dr_put_text((x), (y), -(float)strlen(text), -2.0, 0.0, 1.4, (text))
  111. #define PUT_Y_TEXT(x,y,text) \
  112.       dr_put_text((x), (y), 0.0, -2.0, -M_PI_2, 1.4, (text))
  113. #define PUT_N_TEXT(x,y,text) \
  114.       dr_put_text((x), (y), -(float)strlen(text)/2.0, 0.4, 0.0, 2.0, (text))
  115.  
  116. main(argc, argv)
  117. int argc;
  118. char *argv[];
  119. {
  120.     int c;
  121.     extern char *optarg;
  122.     extern int optind, opterr;
  123.     char *opts = "a:bc:df:g:hl:m:n:p:s:S:t:x:X:y:Y:v";
  124.  
  125.     FILE *fp;
  126.  
  127.     myname = *argv;
  128.     setdevice(getenv("DRAWDEV"));
  129.  
  130.  
  131.     while ((c = getopt(argc, argv, opts)) != -1) {
  132.     switch (c) {
  133.     case 'a':
  134.         if (sscanf(optarg, "%f,%f,%f,%f",
  135.                &xlowl, &ylowl, &xhighr, &yhighr) != 4)
  136.           fatal("invalid plotting area definition: ", optarg);
  137.         break;
  138.     case 'b': no_axes++; break;
  139.     case 'c': cset = atoi(optarg); break;
  140.     case 'd': dateflag++; break;
  141.     case 'f':
  142.         /* input lines are : "-- -- y -- -- x -- --"
  143.          * (dashes indicate fields, that we are not interested in)
  144.          * and we want to plot y=f(x), so we specify option
  145.          * "-f 6,3" (fields are numbered from 1...)
  146.          */
  147.         {
  148.         int xcol, ycol;
  149.         if (sscanf(optarg, "%d,%d", &xcol, &ycol) != 2)
  150.           fatal("invalid input format definition: %s", optarg);
  151.         if (xcol == ycol)
  152.           fatal("invalid input format definition: %s", optarg);
  153.         if (xcol > ycol) {
  154.             int temp = xcol;
  155.             reversed++;
  156.             xcol = ycol;
  157.             ycol = temp;
  158.         }
  159.         ycol -= xcol;
  160.         informat[0] = '\0';
  161.         while (--xcol)
  162.           (void)strcat(informat, "%*f ");
  163.         (void)strcat(informat, "%f ");
  164.         while (--ycol)
  165.           (void)strcat(informat, "%*f ");
  166.         (void)strcat(informat, "%f");
  167.         }
  168.         break;
  169.     case 'g':
  170.         if (sscanf(optarg, "%d,%d", &xgrid_n, &ygrid_n) != 2)
  171.           fatal("invalid grid spec.: ", optarg);
  172.         break;
  173.     case 'h': case '?':
  174.         usage(); break;
  175.     case 'l':
  176.         if (sscanf(optarg, "%d", &linetype) != 1)
  177.           fatal("invalid line type:", optarg);
  178.         break;        /* draw axes before setting it! */
  179.     case 'm':
  180.         continuous = 0;
  181.         if (sscanf(optarg, "%1s", &marker) != 1)
  182.           fatal ("no marker found.", "\0");
  183.         break;
  184.     case 'n':
  185.         name_text = optarg; break;
  186.     case 'p':
  187.         if (sscanf(optarg, "%d", &pennum) != 1)
  188.           fatal("invalid pen:", optarg);
  189.         if ((pennum > 6) || (pennum < 1))
  190.           pennum = 1;
  191.         break;
  192.     case 's':
  193.         if (sscanf(optarg, "%f", &text_size) != 1)
  194.           fatal("invalid text size: ", optarg);
  195.         break;
  196.     case 'S':
  197.         if (sscanf(optarg, "%f", &text_shape) != 1)
  198.           fatal("invalid text shape: ", optarg);
  199.         break;
  200.     case 't': setdevice(optarg); break;
  201.     case 'x':
  202.         if (sscanf(optarg, "%f,%f,%f",
  203.                &xlow, &xincr, &xhigh) != 3)
  204.           fatal("invalid x range: ", optarg);
  205.         break;
  206.     case 'X':
  207.         xlabel_text = optarg; break;
  208.     case 'y':
  209.         if (sscanf(optarg, "%f,%f,%f",
  210.                &ylow, &yincr, &yhigh) != 3)
  211.           fatal("invalid y range: ", optarg);
  212.         break;
  213.     case 'Y':
  214.         ylabel_text = optarg; break;
  215.     case 'v':
  216.         fprintf(stderr, "%s\n", RCS_id);
  217.         exit (0);
  218.     default:
  219.         exit(1);
  220.     }
  221.     }
  222.     argc -= optind;
  223.     argv += optind;
  224.  
  225.     old_int_handler = signal (SIGINT, new_int_handler);
  226.  
  227.     /*
  228.      * Options have been taken, start the work.  Initializations will be
  229.      * done just before first data point is used...  This is jippo to
  230.      * make it possible to give coordinate specifications from inside
  231.      * the data....
  232.      */
  233.     if (argc == 0)        /* no files, take points from stdin */
  234.       doit(stdin);
  235.     else {            /* take points from all files */
  236.     for ( ; argc; argc--, argv++) {
  237.         if (NULL == (fp = fopen(*argv, "r"))) {
  238.         perror(*argv);
  239.         continue;
  240.         }
  241.         doit(fp);
  242.         fclose(fp);
  243.     }
  244.     }
  245.     if (init_done)
  246.       return(dr_finish(1) ? 1 : 0); /* 1 == error(s) */
  247.     else
  248.       return 2;            /* nothing was done! */
  249. }
  250.  
  251.  
  252. /* gl_plot will set int handler at its initialization time, and restore
  253.    what it saw there previously, and finally it will
  254.    kill(SIGINT,getpid()).  This is what we are going to do, too, so that
  255.    OUR caller can clean ITS data stuctures etc.
  256. */
  257. static void new_int_handler() {
  258.     (void)dr_finish(0);
  259.     signal (SIGINT, old_int_handler);
  260.     kill (getpid(), SIGINT);    /* zap my self */
  261.     sleep(1);
  262.     exit(3);            /* if that is not enough */
  263. }
  264.  
  265.  
  266. static void do_initializations()
  267. {
  268.     init_done++;        /* remember it is done */
  269.     dr_start(xlowl, ylowl, xhighr, yhighr, device);
  270.     if (cset != 0) dr_set_cset(cset);
  271.     dr_set_size(text_size);
  272.     dr_set_shape(text_shape);
  273.     dr_set_pen(pennum);
  274.     dr_area_def(xlow, xincr, xhigh, ylow, yincr, yhigh, no_axes);
  275.     if (!no_axes) {
  276.     if (xgrid_n) dr_xgrid(xgrid_n);
  277.     if (ygrid_n) dr_ygrid(ygrid_n);
  278.     }
  279.     if (xlabel_text) PUT_X_TEXT(xhigh, ylow, xlabel_text);
  280.     if (ylabel_text) PUT_Y_TEXT(xlow, yhigh, ylabel_text);
  281.     if (name_text) PUT_N_TEXT((xhigh+xlow)/2.0, yhigh, name_text);
  282.     if (dateflag) putdate(dateflag);
  283.     dr_set_ltype(linetype);
  284. }
  285.  
  286. static void setdevice(s)
  287. char *s;
  288. {
  289.     if (s == NULL) return;
  290.     if      (!strcmp(s,"a4")) device = (HP7475 | SIZE_A4);
  291.     else if (!strcmp(s,"a3")) device = (HP7475 | SIZE_A3);
  292.     else if (!strcmp(s,"a"))  device = (HP7475 | SIZE_A);
  293.     else if (!strcmp(s,"b"))  device = (HP7475 | SIZE_B);
  294. #ifdef GL_LIB
  295.     else if (!strcmp(s,"ega")) device = SCREEN;
  296. #endif
  297. #ifdef PLOT
  298.     else if (!strcmp(s,"plot")) device = PLOTLIB;
  299. #endif
  300. #ifdef TEK
  301.     else if (!strcmp(s,"tek"))
  302.       fatal("Sorry,", "Tek4010 not yet.");
  303. #endif
  304.     else fatal("Unsupported plotting device", s);
  305. }
  306.   
  307. static void doit(fp)
  308. FILE *fp;
  309. {
  310. #define LINESIZE 512
  311.     char buf[LINESIZE+1], *p;
  312.     char emsg[200];
  313.     int lineno = 0;
  314.     
  315.     while (1) {
  316.     if (NULL == fgets(buf, LINESIZE, fp)) /* EOF */
  317.       return;
  318.  
  319.     lineno++;
  320.     for (p=buf; *p; p++)    /* skip white space */
  321.       if (strchr(" \t",*p) == NULL)
  322.         break;
  323.     if (*p == '\n')
  324.       continue;
  325.  
  326.     if (*p == '#') {
  327.         if (setmode(p+1)) {
  328.         sprintf(emsg, "Invalid pseudo comment line (%d): %s",
  329.             lineno, buf);
  330.         if (init_done)
  331.           dr_errmsg(emsg);
  332.         else
  333.           write(2, emsg, strlen(emsg));
  334.         }
  335.         continue;
  336.     }
  337.                 /* now we expect data lines, */
  338.                 /* initializations must be done by now */
  339.     if (!init_done) do_initializations();
  340.  
  341.     if (sscanf(p, informat, &x, &y) != 2) {
  342.         sprintf(emsg, "Invalid data line (%d): %s", lineno, buf);
  343.         dr_errmsg(emsg);
  344.         continue;
  345.     }
  346.     if (reversed) {
  347.         float temp = x;
  348.         x = y;
  349.         y = temp;
  350.     }
  351.     if (absolute) {
  352.         x = xlow + (xabs_origin + x) * (xhigh - xlow);
  353.         y = ylow + (yabs_origin + y) * (yhigh - ylow);
  354.     }
  355.     /* this needs to be fixed: reversed directions not handled! */
  356.     if (x < xlow || x > xhigh || y < ylow || y > yhigh) {
  357.         sprintf (emsg, "point out of range at line (%d): %s",
  358.              lineno, buf);
  359.         dr_warnmsg(emsg);
  360.     }
  361.     if (continuous) {
  362.         dr_goto(x, y, penup);
  363.         penup = 0;
  364.     }
  365.     else {
  366.         dr_put_mark(x, y, marker);
  367.     }
  368.     }
  369. }
  370.  
  371. static void remember(to, from)    /* copy string to safe place, put its */
  372.                 /* addr into `*to' */
  373. char **to, *from;
  374. {
  375. #ifndef MSDOS
  376.     extern char *malloc();
  377. #endif
  378.     *to = malloc(strlen(from)+1);
  379.     strcpy(*to, from);
  380. }
  381.  
  382.                 /* handle '#<something>' lines */
  383. static int setmode(s)        /* return 0 on success, != when trouble */
  384. char *s;
  385. {
  386.     for (; *s; s++)        /* skip white space */
  387.       if (strchr(" \t",*s) == NULL)
  388.     break;
  389.     if (*s++ != '$')        /* only '$' causes action */
  390.       return 0;
  391.  
  392.     for (; *s; s++)        /* skip white space */
  393.       if (strchr(" \t",*s) == NULL)
  394.     break;
  395.     
  396.     if (!strncmp (s, "absolute", 8)) {
  397.     absolute = 1;
  398.     if (sscanf(s+8, "%f,%f", &xabs_origin, &yabs_origin) == 2)
  399.       return 0;
  400.     xabs_origin = 0.0;
  401.     yabs_origin = 0.0;
  402.     return 1;
  403.     }
  404.  
  405.     if (!strncmp (s, "endabsolute", 11)) {
  406.     absolute = 0;
  407.     return 0;
  408.     }
  409.  
  410.     if (!strncmp (s,"penup",5)) {
  411.     penup = 1;
  412.     return 0;
  413.     }
  414.  
  415.  
  416.     if (!strncmp(s, "include", 7)) {
  417.     FILE *fp;
  418.     char *p;
  419.     
  420.     for (s+=8; *s; s++)    /* skip whitespace */
  421.       if (strchr(" \t",*s) == NULL)
  422.          break;
  423.     for (p=s; *p; p++)
  424.        if (strchr(" \t\n",*s) != NULL)
  425.          break;
  426.      *(p-1) = '\0';        /* put terminator */
  427.      
  428.      if (NULL == (fp = fopen(s, "r"))) {
  429.          perror(p);
  430.          return 1;
  431.      }
  432.      doit(fp);        /* recursive call */
  433.      fclose(fp);
  434.      return 0;
  435.     }
  436.  
  437.     if (!strncmp (s, "cset", 4)) {
  438.     int csetnum = 0;
  439.     if (sscanf(s+4, "%d", &csetnum) != 1)
  440.       return 1;
  441.     if (!init_done) do_initializations();
  442.     dr_set_cset(csetnum);
  443.     return 0;
  444.     }
  445.  
  446.     if (!strncmp (s, "pen", 3)) {
  447.     if (sscanf(s+3, "%d", &pennum) != 1)
  448.       return 1;
  449.     if (!init_done) do_initializations();
  450.     dr_set_pen(pennum);
  451.     return 0;
  452.     }
  453.  
  454.     if (!strncmp (s, "ltype", 5)) {
  455.     int linetype = 1;
  456.     if (sscanf(s+5, "%d", &linetype) != 1)
  457.       return 1;
  458.     if (!init_done) do_initializations();
  459.     dr_set_ltype(linetype);
  460.     return 0;
  461.     }
  462.  
  463.     if (!strncmp(s, "mark", 4)) {
  464.     s += 4;
  465.     while (1) {
  466.         marker = *s++;
  467.         if (strchr(" \t", marker) == NULL)
  468.           break;
  469.     }
  470.     continuous = (strchr (" \n\r\t", marker) != NULL);
  471.     return 0;
  472.     }
  473.  
  474.     if (!strncmp(s, "date",   4)) {
  475.     if (dateflag)
  476.       return 1;
  477.     dateflag = 1;
  478.     if (init_done)
  479.       putdate(1);
  480.     return 0;
  481.     }
  482.     if (!strncmp(s, "time",   4)) {
  483.     if (dateflag)
  484.       return 1;
  485.     dateflag = 2;
  486.     if (init_done)
  487.       putdate(2);
  488.     return 0;
  489.     }
  490.  
  491.     if (!strncmp(s, "xlabel", 6)) {
  492.     if (xlabel_text) return 1;
  493.     s += 7;            /* skip one space/separator */
  494.     s[strlen(s)-1] = '\0';    /* drop newline */
  495.     if (!init_done) {
  496.         remember(&xlabel_text, s);
  497.         return 0;
  498.     }
  499.     PUT_X_TEXT(xhigh, ylow, s);
  500.     xlabel_text = myname;    /* some char-pointer that has non NULL */
  501.                 /* value, so that we remember this */
  502.     penup = 1;
  503.     return 0;
  504.     }
  505.  
  506.     if (!strncmp(s, "ylabel", 6)) {
  507.     if (ylabel_text) return 1;
  508.     s += 7;
  509.     s[strlen(s)-1] = '\0';
  510.     if (!init_done) {
  511.         remember(&ylabel_text, s);
  512.         return 0;
  513.     }
  514.     PUT_Y_TEXT(xlow, yhigh, s);
  515.     ylabel_text = myname;
  516.     penup = 1;
  517.     return 0;
  518.     }
  519.  
  520.     if (!strncmp(s, "name", 4)) {
  521.     if (name_text) return 1;
  522.     s += 5;            /* skip the space */
  523.     s[strlen(s)-1] = '\0';    /* drop newline */
  524.     if (!init_done) {
  525.         remember(&name_text, s);
  526.         return 0;
  527.     }
  528.     PUT_N_TEXT((xhigh+xlow)/2.0, yhigh, s);
  529.     name_text = myname;    
  530.     penup = 1;
  531.     return 0;
  532.     }
  533.  
  534.     if (!strncmp(s, "xrange", 6)) {
  535.     if (sscanf(s+6, "%f,%f,%f", &xlow, &xincr, &xhigh) != 3)
  536.       return 1;
  537.     return 0;
  538.     }
  539.  
  540.     if (!strncmp(s, "yrange", 6)) {
  541.     if (sscanf(s+6, "%f,%f,%f", &ylow, &yincr, &yhigh) != 3)
  542.       return 1;
  543.     return 0;
  544.     }
  545.  
  546.     if (!strncmp(s, "area", 4)) {
  547.     if (sscanf(s+4, "%f,%f,%f,%f",
  548.            &xlowl, &ylowl, &xhighr, &yhighr) != 4)
  549.       return 1;
  550.     return 0;
  551.     }
  552.  
  553.     if (!strncmp(s, "grid", 4)) {
  554.     if (sscanf(s+4, "%d,%d", &xgrid_n, &ygrid_n) != 2)
  555.       return 1;
  556.     return 0;
  557.     }
  558.  
  559.     if (!strncmp(s, "noaxes", 6)) {
  560.     no_axes++;
  561.     return 0;
  562.     }
  563.  
  564.     if (!strncmp(s, "init", 4)) {
  565.     if (!init_done) do_initializations();
  566.     return 0;
  567.     }
  568.  
  569.     if (!strncmp(s, "size", 4)) {
  570.     if (sscanf(s+4, "%f", &text_size) != 1)
  571.       return 1;
  572.     if (init_done)
  573.       dr_set_size(text_size);
  574.     return 0;
  575.     }
  576.  
  577.     if (!strncmp(s, "shape", 5)) {
  578.     if (sscanf(s+5, "%f", &text_shape) != 1)
  579.       return 1;
  580.     if (init_done)
  581.       dr_set_shape(text_shape);
  582.     return 0;
  583.     }
  584.  
  585.     if (!strncmp(s, "direction", 9)) {
  586.     float xx;
  587.  
  588.     if (sscanf(s+9, "%f", &xx) != 1)
  589.       return 1;
  590.     text_angle = xx;
  591.     return 0;
  592.     }
  593.  
  594.     if (!strncmp(s, "text",   4)) return (labelpic(s+4, 0, 0));
  595.     if (!strncmp(s, "alabel", 6)) return (labelpic(s+6, 0, 1));
  596.     if (!strncmp(s, "rlabel", 6)) return (labelpic(s+6, 1, 1));
  597.  
  598.                 /* other options are errors */
  599.     return 1;
  600. }
  601.  
  602. static int labelpic(s, rel, conn)
  603. char *s;
  604. int rel, conn;
  605. {
  606.     float xx, yy;
  607.     char *s1;
  608.     int old_linetype;
  609.  
  610.     if (!init_done) do_initializations();
  611.  
  612.     old_linetype = dr_set_ltype(7); /* set solid line */
  613.     xx = strtod(s, &s1);
  614.     if (s1 == s) return 1;
  615.     s = s1+1;
  616.     yy = strtod(s, &s1);
  617.     if (s1 == s) return 1;
  618.     s1++;            /* skip the separator */
  619.     s1[strlen(s1)-1] = '\0';
  620.     if (rel) {
  621.     xx += x;
  622.     yy += y;
  623.     }
  624.     PUT_TEXT(xx, yy, 0.0, 0.15, s1);
  625.     if (conn) {
  626.     dr_goto(xx, yy, 0);
  627.     dr_goto(x, y, 0);
  628.     dr_draw_circle();
  629.     }
  630.     else
  631.       penup = 1;
  632.     (void) dr_set_ltype(old_linetype);
  633.     return 0;
  634. }
  635.  
  636. int putdate(flag)
  637. int flag;
  638. {
  639.     struct tm *timp;
  640.     long clk;
  641.     char buf1[40], buf2[20];
  642.  
  643.     if (time(&clk) < 0) {
  644.     (void) sprintf (buf1, "time() failed.");
  645.     (void) dr_errmsg(buf1);
  646.     return 1;
  647.     }
  648.     timp = localtime(&clk);
  649.     sprintf(buf1, "%d/%d/%d",
  650.         timp->tm_mday, timp->tm_mon+1, timp->tm_year + 1900);
  651.     if (flag > 1)
  652.       sprintf(buf2, " %02d:%02d:%02d",
  653.           timp->tm_hour, timp->tm_min, timp->tm_sec);
  654.     else
  655.       buf2[0] = '\0';
  656.     strcat(buf1, buf2);
  657.     PUT_TEXT(xhigh, yhigh, -(float)strlen(buf1), 0.7, buf1);
  658.     penup = 1;
  659.     return 0;
  660. }
  661.  
  662.  
  663. void fatal(s1, s2)
  664. char *s1, *s2;
  665. {
  666.     fprintf (stderr,"%s: Fatal error: %s %s\n", myname, s1, s2);
  667.     exit(1);
  668. }
  669.  
  670. static char *utbl[] = {
  671.     "-a xlo,ylo,xhi,yhi\tspecify relative plot area on paper",
  672.     "-b\t\t\tdon't draw axes",
  673.     "-c num\t\t\tchoose character set `num'",
  674.     "-d\t\t\tinclude date (time) stamp",
  675.     "-f c1,c2\t\tuse these columns of input, higher is for y",
  676.     "-g xgrid,ygrid\t\tspecify x&y grids",
  677.     "-h\t\t\tgive this stuff",
  678.     "-l\t\t\tlinetype",
  679.     "-m marker\t\tspecify marker & discontinous mode",
  680.     "-n text\t\tname the picture",
  681.     "-p num\t\t\tspecify pen number",
  682. #ifdef GL_LIB
  683.     "-t target\t\tspecify device: `ega', `a3', `a4' etc. Defaults from env.",
  684. #else
  685.     "-t target\t\tspecify device: `a3', `a4' etc. Defaults from env.",
  686. #endif
  687.     "-x|y low,incr,high\tspecify axis range",
  688.     "-X|Y text\t\taxis label",
  689.     "-v\t\t\tprint version ID",
  690.     "Most (all?) of these may also be given inside the data, look for manual",
  691.     NULL
  692. };
  693.  
  694. void usage()
  695. {
  696.     register char **p;
  697.     printf ("usage: \"%s [opts] [file ...]\"\n", myname);
  698.     for (p=utbl; *p; p++)
  699.       (void)printf (" %s\n", *p);
  700.     exit(0);
  701. }
  702.