Back to index

plt-scheme  4.2.1
plargs.c
Go to the documentation of this file.
00001 /* $Id: plargs.c,v 1.1 2004/03/01 20:54:50 cozmic Exp $
00002 
00003     Copyright 1993, 1994, 1995
00004     Maurice LeBrun                 mjl@dino.ph.utexas.edu
00005     Institute for Fusion Studies   University of Texas at Austin
00006 
00007     This library is free software; you can redistribute it and/or
00008     modify it under the terms of the GNU Library General Public
00009     License as published by the Free Software Foundation; either
00010     version 2 of the License, or (at your option) any later version.
00011 
00012     This library is distributed in the hope that it will be useful,
00013     but WITHOUT ANY WARRANTY; without even the implied warranty of
00014     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00015     Library General Public License for more details.
00016 
00017     You should have received a copy of the GNU Library General Public
00018     License along with this library; if not, write to the Free
00019     Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
00020 
00021     Some parts of this code were derived from "xterm.c" and "ParseCmd.c" of 
00022     the X-windows Version 11 distribution.  The copyright notice is
00023     reproduced here:
00024 
00025 Copyright 1987, 1988 by Digital Equipment Corporation, Maynard, Massachusetts,
00026 and the Massachusetts Institute of Technology, Cambridge, Massachusetts.
00027 
00028                         All Rights Reserved
00029 
00030     The full permission notice is given in the PLplot documentation.
00031 
00032 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
00033 
00034     This file contains routines to extract & process command flags.  The
00035     command flags recognized by PLplot are stored in the "ploption_table"
00036     structure, along with strings giving the syntax, long help message, and
00037     option handler.  
00038 
00039     The command line parser -- plParseOpts() -- removes all recognized flags
00040     (decreasing argc accordingly), so that invalid input may be readily
00041     detected.  It can also be used to process user command line flags.  The
00042     user can merge an option table of type PLOptionTable into the internal
00043     option table info structure using plMergeOpts().  Or, the user can
00044     specify that ONLY the external table(s) be parsed by calling
00045     plClearOpts() before plMergeOpts().  
00046 
00047     The default action taken by plParseOpts() is as follows:
00048        - Returns with an error if an unrecognized option or badly formed
00049          option-value pair are encountered.
00050        - Returns immediately (return code 0) when the first non-option
00051          command line argument is found.
00052        - Returns with the return code of the option handler, if one
00053          was called.
00054        - Deletes command line arguments from argv list as they are found,
00055          and decrements argc accordingly.
00056        - Does not show "invisible" options in usage or help messages.
00057        - Assumes the program name is contained in argv[0].
00058 
00059     These behaviors may be controlled through the "mode" argument, which can
00060     have the following bits set:
00061 
00062     PL_PARSE_FULL -- Full parsing of command line and all error messages
00063     enabled, including program exit when an error occurs.  Anything on the
00064     command line that isn't recognized as a valid option or option argument
00065     is flagged as an error.
00066 
00067     PL_PARSE_QUIET -- Turns off all output except in the case of
00068     errors.
00069 
00070     PL_PARSE_NODELETE -- Turns off deletion of processed arguments.
00071 
00072     PL_PARSE_SHOWALL -- Show invisible options 
00073 
00074     PL_PARSE_NOPROGRAM -- Specified if argv[0] is NOT a pointer to the
00075     program name.
00076 
00077     PL_PARSE_NODASH -- Set if leading dash is NOT required.
00078 
00079     PL_PARSE_SKIP -- Set to quietly skip over any unrecognized args.
00080 
00081     Note: if you want to have both your option and a PLplot option of the
00082     same name processed (e.g. the -v option in plrender), do the following:
00083        1. Tag your option with PL_OPT_NODELETE
00084        2. Give it an option handler that uses a return code of 1.
00085        3. Merge your option table in.
00086     By merging your table, your option will be processed before the PLplot
00087     one.  The PL_OPT_NODELETE ensures that the option string is not deleted
00088     from the argv list, and the return code of 1 ensures that the parser
00089     continues looking for it.
00090 
00091     See plrender.c for examples of actual usage.  */
00092 
00093 #include "plplotP.h"
00094 #include <ctype.h>
00095 
00096 /* Support functions */
00097 
00098 static int  ParseOpt (int *, char ***, int *, char ***, PLOptionTable *);
00099 static int  ProcessOpt      (char *, PLOptionTable *, int *, char ***, int *);
00100 static int  GetOptarg       (char **, int *, char ***, int *);
00101 static void Help     (void);
00102 static void Syntax   (void);
00103 
00104 /* Option handlers */
00105 
00106 static int opt_h            (char *, char *, void *);
00107 static int opt_v            (char *, char *, void *);
00108 static int opt_verbose             (char *, char *, void *);
00109 static int opt_debug        (char *, char *, void *);
00110 static int opt_hack         (char *, char *, void *);
00111 static int opt_dev          (char *, char *, void *);
00112 static int opt_o            (char *, char *, void *);
00113 static int opt_geo          (char *, char *, void *);
00114 static int opt_a            (char *, char *, void *);
00115 static int opt_jx           (char *, char *, void *);
00116 static int opt_jy           (char *, char *, void *);
00117 static int opt_mar          (char *, char *, void *);
00118 static int opt_ori          (char *, char *, void *);
00119 static int opt_freeaspect   (char *, char *, void *);
00120 static int opt_portrait            (char *, char *, void *);
00121 static int opt_width        (char *, char *, void *);
00122 static int opt_bg           (char *, char *, void *);
00123 static int opt_ncol0        (char *, char *, void *);
00124 static int opt_ncol1        (char *, char *, void *);
00125 static int opt_fam          (char *, char *, void *);
00126 static int opt_fsiz         (char *, char *, void *);
00127 static int opt_fbeg         (char *, char *, void *);
00128 static int opt_finc         (char *, char *, void *);
00129 static int opt_fflen        (char *, char *, void *);
00130 static int opt_bufmax              (char *, char *, void *);
00131 static int opt_nopixmap            (char *, char *, void *);
00132 static int opt_db           (char *, char *, void *);
00133 static int opt_np           (char *, char *, void *);
00134 static int opt_px           (char *, char *, void *);
00135 static int opt_py           (char *, char *, void *);
00136 static int opt_wplt         (char *, char *, void *);
00137 static int opt_drvopt              (char *, char *, void *);
00138 
00139 static int opt_plserver            (char *, char *, void *);
00140 static int opt_plwindow            (char *, char *, void *);
00141 static int opt_tcl_cmd             (char *, char *, void *);
00142 static int opt_auto_path    (char *, char *, void *);
00143 static int opt_bufmax              (char *, char *, void *);
00144 static int opt_server_name  (char *, char *, void *);
00145 static int opt_server_host  (char *, char *, void *);
00146 static int opt_server_port  (char *, char *, void *);
00147 static int opt_user         (char *, char *, void *);
00148 static int opt_tk_file          (char *, char *, void *);
00149 static int opt_dpi          (char *, char *, void *);
00150 static int opt_dev_compression     (char *, char *, void *);
00151 
00152 /* Global variables */
00153 
00154 static char *program = NULL;
00155 static char *usage   = NULL;
00156 
00157 static int  mode_full;
00158 static int  mode_quiet;
00159 static int  mode_nodelete;
00160 static int  mode_showall;
00161 static int  mode_noprogram;
00162 static int  mode_nodash;
00163 static int  mode_skip;
00164 
00165 /* Temporary buffer used for parsing */
00166 
00167 #define OPTMAX 1024
00168 static char opttmp[OPTMAX];
00169 
00170 /*--------------------------------------------------------------------------*\
00171  * PLPLOT options data structure definition.
00172  *
00173  * The table is defined as follows
00174  *
00175  * typedef struct {
00176  *     char *opt;
00177  *     int  (*handler)      (char *, char *, void *);
00178  *     void *client_data;
00179  *     void *var;
00180  *     long mode;
00181  *     char *syntax;
00182  *     char *desc;
00183  * } PLOptionTable;
00184  *
00185  * where each entry has the following meaning:
00186  *
00187  * opt        option string
00188  * handler    pointer to function for processing the option and
00189  *             (optionally) its argument
00190  * client_data       pointer to data that gets passed to (*handler)
00191  * var        address of variable to set based on "mode"
00192  * mode              governs handling of option (see below)
00193  * syntax     short syntax description
00194  * desc              long syntax description
00195  *
00196  * The syntax and or desc strings can be NULL if the option is never to be
00197  * described.  Usually this is only used for obsolete arguments; those we
00198  * just wish to hide from normal use are better made invisible (which are
00199  * made visible by either specifying -showall first or PL_PARSE_SHOWALL).
00200  *
00201  * The mode bits are:
00202  *
00203  * PL_OPT_ARG        Option has an argment 
00204  * PL_OPT_NODELETE   Don't delete after processing 
00205  * PL_OPT_INVISIBLE  Make invisible (usually for debugging)
00206  * PL_OPT_DISABLED   Ignore this option
00207  *
00208  * The following mode bits cause the option to be processed as specified:
00209  *
00210  * PL_OPT_FUNC              Call function handler (opt, optarg)
00211  * PL_OPT_BOOL              Set *var=1
00212  * PL_OPT_INT        Set *var=atoi(optarg)
00213  * PL_OPT_FLOAT             Set *var=atof(optarg)
00214  * PL_OPT_STRING     Set *var=optarg
00215  *
00216  * where opt points to the option string and optarg points to the
00217  * argument string.
00218  *
00219 \*--------------------------------------------------------------------------*/
00220 
00221 static PLOptionTable ploption_table[] = {
00222 {
00223     "showall",                     /* Turns on invisible options */
00224     NULL,
00225     NULL,
00226     &mode_showall,
00227     PL_OPT_BOOL | PL_OPT_INVISIBLE,
00228     "-showall",
00229     "Turns on invisible options" },
00230 {
00231     "h",                    /* Help */
00232     opt_h,
00233     NULL,
00234     NULL,
00235     PL_OPT_FUNC,
00236     "-h",
00237     "Print out this message" },
00238 {
00239     "v",                    /* Version */
00240     opt_v,
00241     NULL,
00242     NULL,
00243     PL_OPT_FUNC,
00244     "-v",
00245     "Print out the PLplot library version number" },
00246 {
00247     "verbose",                     /* Be more verbose than usual */
00248     opt_verbose,
00249     NULL,
00250     NULL,
00251     PL_OPT_FUNC,
00252     "-verbose",
00253     "Be more verbose than usual" },
00254 {
00255     "debug",                /* Print debugging info */
00256     opt_debug,
00257     NULL,
00258     NULL,
00259     PL_OPT_FUNC,
00260     "-debug",
00261     "Print debugging info (implies -verbose)" },
00262 {
00263     "hack",                 /* Enable driver-specific hack(s) */
00264     opt_hack,
00265     NULL,
00266     NULL,
00267     PL_OPT_FUNC | PL_OPT_INVISIBLE,
00268     "-hack",
00269     "Enable driver-specific hack(s)" },
00270 {
00271     "dev",                  /* Output device */
00272     opt_dev,
00273     NULL,
00274     NULL,
00275     PL_OPT_FUNC | PL_OPT_ARG,
00276     "-dev name",
00277     "Output device name" },
00278 {
00279     "o",                    /* Output filename */
00280     opt_o,
00281     NULL,
00282     NULL,
00283     PL_OPT_FUNC | PL_OPT_ARG,
00284     "-o name",
00285     "Output filename" },
00286 {
00287     "display",                     /* X server */
00288     opt_o,
00289     NULL,
00290     NULL,
00291     PL_OPT_FUNC | PL_OPT_ARG,
00292     "-display name",
00293     "X server to contact" },
00294 {
00295     "px",                   /* Plots per page in x */
00296     opt_px,
00297     NULL,
00298     NULL,
00299     PL_OPT_FUNC | PL_OPT_ARG,
00300     "-px number",
00301     "Plots per page in x" },
00302 {
00303     "py",                   /* Plots per page in y */
00304     opt_py,
00305     NULL,
00306     NULL,
00307     PL_OPT_FUNC | PL_OPT_ARG,
00308     "-py number",
00309     "Plots per page in y" },
00310 {
00311     "geometry",                    /* Geometry */
00312     opt_geo,
00313     NULL,
00314     NULL,
00315     PL_OPT_FUNC | PL_OPT_ARG,
00316     "-geometry geom",
00317     "Window size, in pixels (e.g. -geometry 400x300)" },
00318 {
00319     "geo",                  /* Geometry (alias) */
00320     opt_geo,
00321     NULL,
00322     NULL,
00323     PL_OPT_FUNC | PL_OPT_ARG | PL_OPT_INVISIBLE,
00324     "-geo geom",
00325     "Window size, in pixels (e.g. -geo 400x300)" },
00326 {
00327     "wplt",                 /* Plot window */
00328     opt_wplt,
00329     NULL,
00330     NULL,
00331     PL_OPT_FUNC | PL_OPT_ARG,
00332     "-wplt xl,yl,xr,yr",
00333     "Relative coordinates [0-1] of window into plot" },
00334 {
00335     "mar",                  /* Margin */
00336     opt_mar,
00337     NULL,
00338     NULL,
00339     PL_OPT_FUNC | PL_OPT_ARG,
00340     "-mar margin",
00341     "Margin space in relative coordinates (0 to 0.5, def 0)" },
00342 {
00343     "a",                    /* Aspect ratio */
00344     opt_a,
00345     NULL,
00346     NULL,
00347     PL_OPT_FUNC | PL_OPT_ARG,
00348     "-a aspect",
00349     "Page aspect ratio (def: same as output device)"},
00350 {
00351     "jx",                   /* Justification in x */
00352     opt_jx,
00353     NULL,
00354     NULL,
00355     PL_OPT_FUNC | PL_OPT_ARG,
00356     "-jx justx",
00357     "Page justification in x (-0.5 to 0.5, def 0)"},
00358 {
00359     "jy",                   /* Justification in y */
00360     opt_jy,
00361     NULL,
00362     NULL,
00363     PL_OPT_FUNC | PL_OPT_ARG,
00364     "-jy justy",
00365     "Page justification in y (-0.5 to 0.5, def 0)"},
00366 {
00367     "ori",                  /* Orientation */
00368     opt_ori,
00369     NULL,
00370     NULL,
00371     PL_OPT_FUNC | PL_OPT_ARG,
00372     "-ori orient",
00373     "Plot orientation (0,1,2,3=landscape,portrait,seascape,upside-down)" },
00374 {
00375     "freeaspect",           /* floating aspect ratio */
00376     opt_freeaspect,
00377     NULL,
00378     NULL,
00379     PL_OPT_FUNC,
00380     "-freeaspect",
00381     "Allow aspect ratio to adjust to orientation swaps" },
00382 {
00383     "portrait",                    /* floating aspect ratio */
00384     opt_portrait,
00385     NULL,
00386     NULL,
00387     PL_OPT_FUNC,
00388     "-portrait",
00389     "Sets portrait mode (both orientation and aspect ratio)" },
00390 {
00391     "width",                /* Pen width */
00392     opt_width,
00393     NULL,
00394     NULL,
00395     PL_OPT_FUNC | PL_OPT_ARG,
00396     "-width width",
00397     "Sets pen width (0 <= width)" },
00398 {
00399     "bg",                   /* Background color */
00400     opt_bg,
00401     NULL,
00402     NULL,
00403     PL_OPT_FUNC | PL_OPT_ARG,
00404     "-bg color",
00405     "Background color (0=black, FFFFFF=white)" },
00406 {
00407     "ncol0",                /* Allocated colors in cmap 0 */
00408     opt_ncol0,
00409     NULL,
00410     NULL,
00411     PL_OPT_FUNC | PL_OPT_ARG,
00412     "-ncol0 n",
00413     "Number of colors to allocate in cmap 0 (upper bound)" },
00414 {
00415     "ncol1",                /* Allocated colors in cmap 1 */
00416     opt_ncol1,
00417     NULL,
00418     NULL,
00419     PL_OPT_FUNC | PL_OPT_ARG,
00420     "-ncol1 n",
00421     "Number of colors to allocate in cmap 1 (upper bound)" },
00422 {
00423     "fam",                  /* Familying on switch */
00424     opt_fam,
00425     NULL,
00426     NULL,
00427     PL_OPT_FUNC,
00428     "-fam",
00429     "Create a family of output files" },
00430 {
00431     "fsiz",                 /* Family file size */
00432     opt_fsiz,
00433     NULL,
00434     NULL,
00435     PL_OPT_FUNC | PL_OPT_ARG,
00436     "-fsiz size[kKmMgG]",
00437     "Output family file size (e.g. -fsiz 0.5G, def MB)" },
00438 {
00439     "fbeg",                 /* Family starting member */
00440     opt_fbeg,
00441     NULL,
00442     NULL,
00443     PL_OPT_FUNC | PL_OPT_ARG,
00444     "-fbeg number",
00445     "First family member number on output" },
00446 {
00447     "finc",                 /* Family member increment */
00448     opt_finc,
00449     NULL,
00450     NULL,
00451     PL_OPT_FUNC | PL_OPT_ARG,
00452     "-finc number",
00453     "Increment between family members" },
00454 {
00455     "fflen",                /* Family member min field width */
00456     opt_fflen,
00457     NULL,
00458     NULL,
00459     PL_OPT_FUNC | PL_OPT_ARG,
00460     "-fflen length",
00461     "Family member number minimum field width" },
00462 {
00463     "nopixmap",                    /* Do not use pixmaps */
00464     opt_nopixmap,
00465     NULL,
00466     NULL,
00467     PL_OPT_FUNC,
00468     "-nopixmap",
00469     "Don't use pixmaps in X-based drivers" },
00470 {
00471     "db",                   /* Double buffering on switch */
00472     opt_db,
00473     NULL,
00474     NULL,
00475     PL_OPT_FUNC,
00476     "-db",
00477     "Double buffer X window output" },
00478 {
00479     "np",                   /* Page pause off switch */
00480     opt_np,
00481     NULL,
00482     NULL,
00483     PL_OPT_FUNC,
00484     "-np",
00485     "No pause between pages" },
00486 {
00487     "bufmax",               /* # bytes sent before flushing output */
00488     opt_bufmax,
00489     NULL,
00490     NULL,
00491     PL_OPT_FUNC | PL_OPT_ARG | PL_OPT_INVISIBLE,
00492     "-bufmax",
00493     "bytes sent before flushing output" },
00494 {
00495     "server_name",          /* Main window name of server */
00496     opt_server_name,
00497     NULL,
00498     NULL,
00499     PL_OPT_FUNC | PL_OPT_ARG,
00500     "-server_name name",
00501     "Main window name of PLplot server (tk driver)" },
00502 {
00503     "server_host",          /* Host to run server on */
00504     opt_server_host,
00505     NULL,
00506     NULL,
00507     PL_OPT_FUNC | PL_OPT_ARG,
00508     "-server_host name",
00509     "Host to run PLplot server on (dp driver)" },
00510 {
00511     "server_port",          /* Port to talk to server on */
00512     opt_server_port,
00513     NULL,
00514     NULL,
00515     PL_OPT_FUNC | PL_OPT_ARG,
00516     "-server_port name",
00517     "Port to talk to PLplot server on (dp driver)" },
00518 {
00519     "user",                 /* user name on remote node */
00520     opt_user,
00521     NULL,
00522     NULL,
00523     PL_OPT_FUNC | PL_OPT_ARG,
00524     "-user name",
00525     "User name on remote node (dp driver)" },
00526 {
00527     "plserver",                    /* PLplot server name */
00528     opt_plserver,
00529     NULL,
00530     NULL,
00531     PL_OPT_FUNC | PL_OPT_ARG | PL_OPT_INVISIBLE,
00532     "-plserver name",
00533     "Invoked name of PLplot server (tk or dp driver)" },
00534 {
00535     "plwindow",                    /* PLplot container window name */
00536     opt_plwindow,
00537     NULL,
00538     NULL,
00539     PL_OPT_FUNC | PL_OPT_ARG | PL_OPT_INVISIBLE,
00540     "-plwindow name",
00541     "Name of PLplot container window (tk or dp driver)" },
00542 {
00543     "tcl_cmd",                     /* TCL initialization command */
00544     opt_tcl_cmd,
00545     NULL,
00546     NULL,
00547     PL_OPT_FUNC | PL_OPT_ARG | PL_OPT_INVISIBLE,
00548     "-tcl_cmd command",
00549     "TCL command string run at startup (note: disabled)" },
00550 {
00551     "auto_path",            /* Additional directory(s) to autoload */
00552     opt_auto_path,
00553     NULL,
00554     NULL,
00555     PL_OPT_FUNC | PL_OPT_ARG | PL_OPT_INVISIBLE,
00556     "-auto_path dir",
00557     "Additional directory(s) to autoload (tk or dp driver)" },
00558 {
00559     "tk_file",      /* -file option for plserver */
00560     opt_tk_file,
00561     NULL,
00562     NULL,
00563     PL_OPT_FUNC | PL_OPT_ARG | PL_OPT_INVISIBLE,
00564     "-tk_file file",
00565     "file for plserver (tk or dp driver)" },
00566 {
00567     "dpi",                  /* Dots per inch */
00568     opt_dpi,
00569     NULL,
00570     NULL,
00571     PL_OPT_FUNC | PL_OPT_ARG,
00572     "-dpi dpi",
00573     "Resolution, in dots per inch (e.g. -dpi 360x360)" },
00574 {
00575     "compression",                 /* compression */
00576     opt_dev_compression,
00577     NULL,
00578     NULL,
00579     PL_OPT_FUNC | PL_OPT_ARG,
00580     "-compression num",
00581     "Sets compression level in supporting devices" },
00582 {
00583     "drvopt",               /* Driver specific options */
00584     opt_drvopt,
00585     NULL,
00586     NULL,
00587     PL_OPT_ARG | PL_OPT_FUNC,
00588     "-drvopt option[=value][,option[=value]]*",
00589     "Driver specific options" },
00590 {
00591     NULL,                   /* option */
00592     NULL,                   /* handler */
00593     NULL,                   /* client data */
00594     NULL,                   /* address of variable to set */
00595     0,                      /* mode flag */
00596     NULL,                   /* short syntax */
00597     NULL }                  /* long syntax */
00598 };
00599 
00600 static char *plplot_notes[] = {
00601 "All parameters must be white-space delimited.  Some options are driver",
00602 "dependent.  Please see the PLplot reference document for more detail.",
00603 NULL};
00604 
00605 /*--------------------------------------------------------------------------*\
00606  * Array of option tables and associated info.
00607  *
00608  * The user may merge up to PL_MAX_OPT_TABLES custom option tables (of type
00609  * PLOptionTable) with the internal one.  The resulting treatment is simple,
00610  * powerful, and robust.  The tables are parsed in the order of last added
00611  * first, to the internal table last.  If multiple options of the same name
00612  * occur, only the first parsed is "seen", thus, the user can easily
00613  * override any PLplot internal option merely by providing the same option.
00614  * This same precedence is followed when printing help and usage messages,
00615  * with each set of options given separately.  See example usage in
00616  * plrender.c.
00617 \*--------------------------------------------------------------------------*/
00618 
00619 typedef struct {
00620     PLOptionTable *options;
00621     char *name;
00622     char **notes;
00623 } PLOptionInfo;
00624 
00625 PLOptionInfo ploption_info_default = {
00626     ploption_table,
00627     "PLplot options",
00628     plplot_notes
00629 };
00630 
00631 #define PL_MAX_OPT_TABLES 10
00632 PLOptionInfo ploption_info[PL_MAX_OPT_TABLES] = { 
00633     {
00634        ploption_table,
00635        "PLplot options",
00636        plplot_notes
00637     }
00638 };
00639 
00640 /* The structure that hold the driver specific command line options */
00641 
00642 typedef struct DrvOptCmd {
00643   char *option;
00644   char *value;
00645   struct DrvOptCmd *next;
00646 } DrvOptCmd;
00647 
00648 /* the variable where opt_drvopt() stores the driver specific command line options */
00649 static DrvOptCmd drv_opt;
00650   
00651 static int  tables = 1;
00652 
00653 /*--------------------------------------------------------------------------*\
00654  * plSetOpt()
00655  *
00656  * Process input strings, treating them as an option and argument pair.
00657  * Returns 1 on an error.
00658 \*--------------------------------------------------------------------------*/
00659 
00660 int
00661 c_plsetopt(char *opt, char *optarg)
00662 {
00663     return(plSetOpt(opt, optarg));
00664 }
00665 
00666 int
00667 plSetOpt(char *opt, char *optarg)
00668 {
00669     int mode = 0, argc = 2, status;
00670     char *argv[3];
00671 
00672     argv[0] = opt;
00673     argv[1] = optarg;
00674     argv[2] = NULL;
00675     mode =
00676        PL_PARSE_QUIET |
00677        PL_PARSE_NODELETE |
00678        PL_PARSE_NOPROGRAM |
00679        PL_PARSE_NODASH;
00680 
00681     status = plParseOpts(&argc, argv, mode);
00682     if (status) {
00683        fprintf( stderr, "plSetOpt: Unrecognized option %s\n", opt);
00684     }
00685     return status;
00686 }
00687 
00688 /*--------------------------------------------------------------------------*\
00689  * plMergeOpts()
00690  *
00691  * Merge user option table info structure with internal one.
00692 \*--------------------------------------------------------------------------*/
00693 
00694 int
00695 plMergeOpts(PLOptionTable *options, char *name, char **notes)
00696 {
00697     PLOptionTable *tab;
00698 
00699     pllib_init();
00700 
00701 /* Check to make sure option table has been terminated correctly */
00702 
00703     for (tab = options; tab->opt; tab++)
00704        ;
00705 
00706 /* We've reached the last table entry.  All the subentries must be NULL or 0 */
00707 
00708     if ((tab->handler     != NULL) ||
00709        (tab->client_data != NULL) ||
00710        (tab->var         != NULL) ||
00711        (tab->mode        != 0) ||
00712        (tab->syntax      != NULL) ||
00713        (tab->desc        != NULL)) {
00714 
00715        plabort("plMergeOpts: input table improperly terminated");
00716        return 1;
00717     }
00718 
00719 /* No room for more tables */
00720 
00721     if (tables++ >= PL_MAX_OPT_TABLES) {
00722        plabort("plMergeOpts: max tables limit exceeded, table not merged");
00723        return 1;
00724     }
00725 
00726     ploption_info[tables-1].options = options;
00727     ploption_info[tables-1].name    = name;
00728     ploption_info[tables-1].notes   = notes;
00729 
00730     return 0;
00731 }
00732 
00733 /*--------------------------------------------------------------------------*\
00734  * plClearOpts()
00735  *
00736  * Clear internal option table info structure.
00737 \*--------------------------------------------------------------------------*/
00738 
00739 void
00740 plClearOpts(void)
00741 {
00742     tables = 0;
00743 }
00744 
00745 /*--------------------------------------------------------------------------*\
00746  * plResetOpts()
00747  *
00748  * Reset internal option table info structure.
00749 \*--------------------------------------------------------------------------*/
00750 
00751 void
00752 plResetOpts(void)
00753 {
00754     ploption_info[0] = ploption_info_default;
00755     tables = 1;
00756 }
00757 
00758 /*--------------------------------------------------------------------------*\
00759  * plParseOpts()
00760  *
00761  * Process options list using current ploptions_info structure.
00762  * An error in parsing the argument list causes a program exit if
00763  * mode_full is set, otherwise the function returns with an error.
00764 \*--------------------------------------------------------------------------*/
00765 
00766 int
00767 plParseOpts(int *p_argc, char **argv, PLINT mode)
00768 {
00769     char **argsave, **argend;
00770     int       i, myargc, status = 0;
00771 
00772     pllib_init();
00773 
00774 /* Initialize */
00775 
00776     mode_full      = mode & PL_PARSE_FULL;
00777     mode_quiet     = mode & PL_PARSE_QUIET;
00778     mode_nodelete  = mode & PL_PARSE_NODELETE;
00779     mode_showall   = mode & PL_PARSE_SHOWALL;
00780     mode_noprogram = mode & PL_PARSE_NOPROGRAM;
00781     mode_nodash    = mode & PL_PARSE_NODASH;
00782     mode_skip      = mode & PL_PARSE_SKIP;
00783 
00784     /* Initialize the driver specific option linked structure */
00785     drv_opt.option  = drv_opt.value  = NULL;
00786     drv_opt.next  = NULL;
00787 
00788     myargc = (*p_argc); 
00789     argend = argv + myargc;
00790 
00791 /* If program name is first argument, save and advance */
00792 
00793     if ( ! mode_noprogram) {
00794        plsc->program = program = argv[0];
00795        --myargc; ++argv;
00796     }
00797     if (myargc == 0)
00798        return 0;
00799 
00800 /* Process the command line */
00801 
00802     argsave = argv;
00803     for (; myargc > 0; --myargc, ++argv) {
00804 
00805     /* Allow for "holes" in argv list */
00806 
00807        if (*argv == NULL || *argv[0] == '\0')
00808            continue;
00809 
00810     /* Loop over all options tables, starting with the last */
00811 
00812        for (i = tables-1; i >= 0; i--) {
00813 
00814        /* Check option table for option */
00815 
00816            status = ParseOpt(&myargc, &argv, p_argc, &argsave,
00817                            ploption_info[i].options);
00818 
00819            if ( ! status) break;
00820        }
00821 
00822     /* Handle error return as specified by the mode flag */
00823 
00824        if (status == -1) {
00825 
00826        /* No match.  Keep going if mode_skip is set, otherwise abort if
00827           fully parsing, else return without error. */
00828 
00829            if (mode_skip) {
00830               if ( ! mode_nodelete) 
00831                   *argsave++ = *argv;
00832               continue;
00833            }
00834            if ( ! mode_quiet && mode_full) {
00835               fprintf(stderr, "\nBad command line option \"%s\"\n", argv[0]);
00836               plOptUsage();
00837            }
00838            if (mode_full) exit(1);
00839 
00840            status = 0;
00841            break;
00842 
00843        } else if (status == 1) {
00844 
00845        /* Illegal or badly formed */
00846 
00847            if ( ! mode_quiet) {
00848               fprintf(stderr, "\nBad command line option \"%s\"\n", argv[0]);
00849               plOptUsage();
00850            }
00851            if (mode_full) exit(1);
00852 
00853            break;
00854 
00855        } else if (status == 2) {
00856 
00857        /* Informational option encountered (-h or -v) */
00858 
00859            exit(0);
00860        }
00861     }
00862 
00863 /* Compress and NULL-terminate argv */
00864 
00865     if ( ! mode_nodelete) {
00866        for (i = 0; i < myargc; i++)
00867            *argsave++ = *argv++;
00868 
00869        if (argsave < argend)
00870            *argsave = NULL;
00871     }
00872 
00873     return status;
00874 }
00875 
00876 /*--------------------------------------------------------------------------*\
00877  * ParseOpt()
00878  *
00879  * Parses & determines appropriate action for input flag.
00880 \*--------------------------------------------------------------------------*/
00881 
00882 static int
00883 ParseOpt(int *p_myargc, char ***p_argv, int *p_argc, char ***p_argsave,
00884         PLOptionTable *option_table)
00885 {
00886     PLOptionTable *tab;
00887     char *opt;
00888 
00889 /* Only handle actual flags and their arguments */
00890 
00891     if ( mode_nodash || (*p_argv)[0][0] == '-') {
00892 
00893        opt = (*p_argv)[0];
00894        if (*opt == '-') 
00895            opt++;
00896 
00897        for (tab = option_table; tab->opt; tab++) {
00898 
00899        /* Skip if option not enabled */
00900 
00901            if (tab->mode & PL_OPT_DISABLED) 
00902               continue;
00903 
00904        /* Try to match it */
00905 
00906            if (*opt == *tab->opt && ! strcmp(opt, tab->opt)) {
00907 
00908            /* Option matched, so remove from argv list if applicable. */
00909 
00910               if ( ! mode_nodelete) {
00911                   if (tab->mode & PL_OPT_NODELETE)
00912                      (*(*p_argsave)++) = (**p_argv);
00913                   else
00914                      --(*p_argc);
00915               }
00916 
00917            /* Process option (and argument if applicable) */
00918 
00919               return (ProcessOpt(opt, tab, p_myargc, p_argv, p_argc));
00920            }
00921        }
00922     }
00923 
00924     return -1;
00925 }
00926 
00927 /*--------------------------------------------------------------------------*\
00928  * ProcessOpt()
00929  *
00930  * Process option (and argument if applicable).
00931 \*--------------------------------------------------------------------------*/
00932 
00933 static int
00934 ProcessOpt(char *opt, PLOptionTable *tab, int *p_myargc, char ***p_argv,
00935           int *p_argc)
00936 {
00937     int need_arg, res;
00938     char *optarg = NULL;
00939 
00940 /* Get option argument if necessary */
00941 
00942     need_arg = PL_OPT_ARG | PL_OPT_INT | PL_OPT_FLOAT | PL_OPT_STRING;
00943 
00944     if (tab->mode & need_arg) {
00945        if (GetOptarg(&optarg, p_myargc, p_argv, p_argc))
00946            return 1;
00947     }
00948 
00949 /* Process argument */
00950 
00951     switch (tab->mode & 0xFF00) {
00952 
00953     case PL_OPT_FUNC:
00954 
00955     /* Call function handler to do the job */
00956 
00957        if (tab->handler == NULL) {
00958            fprintf(stderr,
00959                   "ProcessOpt: no handler specified for option %s\n",
00960                   tab->opt);
00961            return 1;
00962        }
00963 
00964         if (mode_nodelete && optarg) {
00965 
00966        /* Make a copy, since handler may mung optarg with strtok() */
00967            char *copy = 
00968              (char *) malloc((size_t)(1+strlen(optarg))*sizeof(char));
00969            if (copy == NULL) {
00970                plabort("ProcessOpt: out of memory");
00971               return 1;
00972            }
00973            strcpy(copy, optarg);
00974            res = ((*tab->handler) (opt, copy, tab->client_data));
00975            free((void *) copy);
00976            return res;
00977        }
00978        else {
00979          return ((*tab->handler) (opt, optarg, tab->client_data));
00980        }
00981 
00982     case PL_OPT_BOOL:
00983 
00984     /* Set *var as a boolean */
00985 
00986        if (tab->var == NULL) {
00987            fprintf(stderr,
00988                   "ProcessOpt: no variable specified for option %s\n",
00989                   tab->opt);
00990            return 1;
00991        }
00992        *(int *)tab->var = 1;
00993        break;
00994 
00995     case PL_OPT_INT:
00996 
00997     /* Set *var as an int */
00998 
00999        if (tab->var == NULL) {
01000            fprintf(stderr,
01001                   "ProcessOpt: no variable specified for option %s\n",
01002                   tab->opt);
01003            return 1;
01004        }
01005        *(int *)tab->var = atoi(optarg);
01006        break;
01007 
01008     case PL_OPT_FLOAT:
01009 
01010     /* Set *var as a float */
01011 
01012        if (tab->var == NULL) {
01013            fprintf(stderr,
01014                   "ProcessOpt: no variable specified for option %s\n",
01015                   tab->opt);
01016            return 1;
01017        }
01018        *(PLFLT *)tab->var = atof(optarg);
01019        break;
01020 
01021     case PL_OPT_STRING:
01022 
01023     /* Set var (can be NULL initially) to point to optarg string */
01024 
01025        *(char **)tab->var = (char *)optarg;
01026        break;
01027 
01028     default:
01029 
01030     /* Somebody messed up.. */
01031 
01032        fprintf(stderr,
01033               "ProcessOpt: invalid processing mode for option %s\n",
01034               tab->opt);
01035        return 1;
01036     }
01037     return 0;
01038 }
01039 
01040 /*--------------------------------------------------------------------------*\
01041  * GetOptarg()
01042  *
01043  * Retrieves an option argument.
01044  * If an error occurs here it is a true syntax error.
01045 \*--------------------------------------------------------------------------*/
01046 
01047 static int
01048 GetOptarg(char **poptarg, int *p_myargc, char ***p_argv, int *p_argc)
01049 {
01050     int result = 0;
01051 
01052     --(*p_myargc);
01053 
01054     if ((*p_myargc) <= 0)          /* oops, no more arguments */
01055        result = 1;
01056 
01057     if ( ! result) {
01058        (*p_argv)++;
01059        if ((*p_argv)[0][0] == '-' && isalpha((*p_argv)[0][1])) {
01060 
01061            (*p_argv)--;            /* oops, next arg is a flag */
01062            result = 1;
01063        }
01064     }
01065 
01066     if ( ! result) {               /* yeah, the user got it right */
01067        (*p_argc)--;
01068        *poptarg = (*p_argv)[0];
01069     }
01070     else {
01071        if ( ! mode_quiet) {
01072            fprintf(stderr, "Argument missing for %s option.\n", (*p_argv)[0]);
01073            plOptUsage();
01074        }
01075     }
01076     return result;
01077 }
01078 
01079 /*--------------------------------------------------------------------------*\
01080  * plSetUsage()
01081  *
01082  * Set the strings used in usage and syntax messages.
01083 \*--------------------------------------------------------------------------*/
01084 
01085 void
01086 plSetUsage(char *program_string, char *usage_string)
01087 {
01088     if (program_string != NULL)
01089        program = program_string;
01090 
01091     if (usage_string != NULL)
01092        usage = usage_string;
01093 }
01094 
01095 /*--------------------------------------------------------------------------*\
01096  * plOptUsage()
01097  *
01098  * Print usage & syntax message.
01099 \*--------------------------------------------------------------------------*/
01100 
01101 void
01102 plOptUsage(void)
01103 {
01104     if (usage == NULL)
01105        fprintf(stderr, "\nUsage:\n        %s [options]\n", program);
01106     else
01107        fputs(usage, stderr);
01108 
01109     Syntax();
01110 
01111     fprintf(stderr, "\n\nType %s -h for a full description.\n\n",
01112            program);
01113 }
01114 
01115 /*--------------------------------------------------------------------------*\
01116  * Syntax()
01117  *
01118  * Print short syntax message.
01119 \*--------------------------------------------------------------------------*/
01120 
01121 static void
01122 Syntax(void)
01123 {
01124     PLOptionTable *tab;
01125     int i, col, len;
01126 
01127 /* Loop over all options tables */
01128 
01129     for (i = tables-1; i >= 0; i--) {
01130 
01131     /* Introducer */
01132 
01133        if (ploption_info[i].name)
01134            fprintf(stderr, "\n%s:", ploption_info[i].name);
01135        else
01136            fputs("\nUser options:", stderr);
01137 
01138     /* Print syntax for each option */
01139 
01140        col = 80;
01141        for (tab = ploption_info[i].options; tab->opt; tab++) {
01142            if (tab->mode & PL_OPT_DISABLED)
01143               continue;
01144 
01145            if ( ! mode_showall && (tab->mode & PL_OPT_INVISIBLE))
01146               continue;
01147 
01148            if (tab->syntax == NULL)
01149               continue;
01150 
01151            len = 3 + strlen(tab->syntax);        /* space [ string ] */
01152            if (col + len > 79) {
01153               fprintf(stderr, "\n   ");          /* 3 spaces */
01154               col = 3;
01155            }
01156            fprintf(stderr, " [%s]", tab->syntax);
01157            col += len;
01158        }
01159        fprintf(stderr, "\n");
01160     }
01161 }
01162 
01163 /*--------------------------------------------------------------------------*\
01164  * Help()
01165  *
01166  * Print long help message.
01167 \*--------------------------------------------------------------------------*/
01168 
01169 static void
01170 Help(void)
01171 {
01172     PLOptionTable *tab;
01173     char **note;
01174     int i;
01175     FILE *outfile = stderr;
01176 
01177 #ifdef HAVE_POPEN
01178     FILE *pager = NULL;
01179     if (getenv("PAGER") != NULL)
01180        pager = (FILE *) popen("$PAGER", "w");
01181     if (pager == NULL)
01182        pager = (FILE *) popen("more", "w");
01183     if (pager != NULL)
01184        outfile = pager;
01185 #endif
01186 
01187 /* Usage line */
01188 
01189     if (usage == NULL)
01190        fprintf(outfile, "\nUsage:\n        %s [options]\n", program);
01191     else
01192        fputs(usage, outfile);
01193 
01194 /* Loop over all options tables */
01195 
01196     for (i = tables-1; i >= 0; i--) {
01197 
01198     /* Introducer */
01199 
01200        if (ploption_info[i].name)
01201            fprintf(outfile, "\n%s:\n", ploption_info[i].name);
01202        else
01203            fputs("\nUser options:\n", outfile);
01204 
01205     /* Print description for each option */
01206 
01207        for (tab = ploption_info[i].options; tab->opt; tab++) {
01208            if (tab->mode & PL_OPT_DISABLED)
01209               continue;
01210 
01211            if ( ! mode_showall && (tab->mode & PL_OPT_INVISIBLE))
01212               continue;
01213 
01214            if (tab->desc == NULL)
01215               continue;
01216 
01217            if (tab->mode & PL_OPT_INVISIBLE) 
01218               fprintf(outfile, " *  %-20s %s\n", tab->syntax, tab->desc);
01219            else 
01220               fprintf(outfile, "    %-20s %s\n", tab->syntax, tab->desc);
01221        }
01222 
01223     /* Usage notes */
01224 
01225        if (ploption_info[i].notes) {
01226            putc('\n', outfile);
01227            for (note = ploption_info[i].notes; *note; note++) {
01228               fputs(*note, outfile);
01229               putc('\n', outfile);
01230            }
01231        }
01232     }
01233 
01234 #ifdef HAVE_POPEN
01235     if (pager != NULL)
01236        pclose(pager);
01237 #endif
01238 }
01239 
01240 /*--------------------------------------------------------------------------*\
01241  * plParseDrvOpts
01242  * 
01243  * Parse driver specific options
01244 \*--------------------------------------------------------------------------*/
01245 
01246 int
01247 plParseDrvOpts(DrvOpt *acc_opt) {
01248   DrvOptCmd *drvp;
01249   DrvOpt *t;
01250   int fl;
01251   char msg[80];
01252 
01253   if (!drv_opt.option)
01254     return 1;
01255 
01256   drvp = &drv_opt;
01257   do {
01258     t = acc_opt; fl = 0;
01259     while (t->opt) {
01260       if (strcmp(drvp->option, t->opt) == 0) {
01261        fl = 1;
01262        switch (t->type) {
01263 
01264        case DRV_STR:
01265          *(char **)(t->var_ptr) = (drvp->value);
01266 #ifdef DEBUG
01267          fprintf(stderr,"plParseDrvOpts: %s %s\n", t->opt, *(char**)t->var_ptr);
01268 #endif
01269          break;
01270 
01271        case DRV_INT:
01272          if (sscanf(drvp->value, "%d", (int *)t->var_ptr) != 1) {
01273            sprintf(msg,"Incorrect argument to '%s' option", drvp->option);
01274            plexit(msg);
01275          }
01276 #ifdef DEBUG
01277          fprintf(stderr,"plParseDrvOpts: %s %d\n", t->opt, *(int *) t->var_ptr);
01278 #endif  
01279          break;
01280 
01281        case DRV_FLT:
01282          if (sscanf(drvp->value, "%f", (float *)t->var_ptr) != 1) {
01283            sprintf(msg,"Incorrect argument to '%s' option", drvp->option);
01284            plexit(msg);
01285          }
01286 #ifdef DEBUG
01287          fprintf(stderr,"plParseDrvOpts: %s %f\n", t->opt, *(float *) t->var_ptr);
01288 #endif  
01289          break;
01290        }
01291       }
01292     t++;
01293     }
01294 
01295     if (!fl) {
01296       sprintf(msg, "Option '%s' not recognized.\n\nRecognized options for this driver are:\n", drvp->option);
01297       plwarn(msg);
01298       plHelpDrvOpts(acc_opt);      
01299       plexit(""); 
01300     }
01301   }
01302   while((drvp = drvp->next))
01303       ;
01304 
01305   return 0;
01306 }
01307 
01308 /*--------------------------------------------------------------------------*\
01309  * plHelpDrvOpts
01310  * 
01311  * Give driver specific help
01312 \*--------------------------------------------------------------------------*/
01313 
01314 void
01315 plHelpDrvOpts(DrvOpt *acc_opt) {
01316   DrvOpt *t;
01317 
01318   t = acc_opt;
01319   while(t->opt) {
01320     fprintf(stderr, "%s:\t%s\n", t->opt, t->hlp_msg);
01321     t++;
01322   }
01323 }
01324 
01325 /*--------------------------------------------------------------------------*\
01326  * Option handlers
01327 \*--------------------------------------------------------------------------*/
01328 
01329 /*--------------------------------------------------------------------------*\
01330  * opt_h()
01331  *
01332  * Performs appropriate action for option "h":
01333  * Issues help message
01334 \*--------------------------------------------------------------------------*/
01335 
01336 static int
01337 opt_h(char *opt, char *optarg, void *client_data)
01338 {
01339     if ( ! mode_quiet)
01340        Help();
01341 
01342     return 2;
01343 }
01344 
01345 /*--------------------------------------------------------------------------*\
01346  * opt_v()
01347  *
01348  * Performs appropriate action for option "v":
01349  * Issues version message
01350 \*--------------------------------------------------------------------------*/
01351 
01352 static int
01353 opt_v(char *opt, char *optarg, void *client_data)
01354 {
01355     if ( ! mode_quiet) 
01356        fprintf(stderr, "PLplot library version: %s\n", VERSION);
01357 
01358     return 2;
01359 }
01360 
01361 /*--------------------------------------------------------------------------*\
01362  * opt_verbose()
01363  *
01364  * Performs appropriate action for option "verbose":
01365  * Turn on verbosity flag
01366 \*--------------------------------------------------------------------------*/
01367 
01368 static int
01369 opt_verbose(char *opt, char *optarg, void *client_data)
01370 {
01371     plsc->verbose = 1;
01372     return 0;
01373 }
01374 
01375 /*--------------------------------------------------------------------------*\
01376  * opt_debug()
01377  *
01378  * Performs appropriate action for option "debug":
01379  * Turn on debugging flag
01380 \*--------------------------------------------------------------------------*/
01381 
01382 static int
01383 opt_debug(char *opt, char *optarg, void *client_data)
01384 {
01385     plsc->debug = 1;
01386     plsc->verbose = 1;
01387     return 0;
01388 }
01389 
01390 /*--------------------------------------------------------------------------*\
01391  * opt_hack()
01392  *
01393  * Performs appropriate action for option "hack":
01394  * Enables driver-specific hack(s)
01395 \*--------------------------------------------------------------------------*/
01396 
01397 static int
01398 opt_hack(char *opt, char *optarg, void *client_data)
01399 {
01400     plsc->hack = 1;
01401     return 0;
01402 }
01403 
01404 /*--------------------------------------------------------------------------*\
01405  * opt_dev()
01406  *
01407  * Performs appropriate action for option "dev":
01408  * Sets output device keyword
01409 \*--------------------------------------------------------------------------*/
01410 
01411 static int
01412 opt_dev(char *opt, char *optarg, void *client_data)
01413 {
01414     plsdev(optarg);
01415     return 0;
01416 }
01417 
01418 /*--------------------------------------------------------------------------*\
01419  * opt_o()
01420  *
01421  * Performs appropriate action for option "o":
01422  * Sets output file name
01423 \*--------------------------------------------------------------------------*/
01424 
01425 static int
01426 opt_o(char *opt, char *optarg, void *client_data)
01427 {
01428     plsfnam(optarg);
01429     return 0;
01430 }
01431 
01432 /*--------------------------------------------------------------------------*\
01433  * opt_mar()
01434  *
01435  * Performs appropriate action for option "mar":
01436  * Sets relative margin width
01437 \*--------------------------------------------------------------------------*/
01438 
01439 static int
01440 opt_mar(char *opt, char *optarg, void *client_data)
01441 {
01442     plsdidev(atof(optarg), PL_NOTSET, PL_NOTSET, PL_NOTSET);
01443     return 0;
01444 }
01445 
01446 /*--------------------------------------------------------------------------*\
01447  * opt_a()
01448  *
01449  * Performs appropriate action for option "a":
01450  * Sets plot aspect ratio on page
01451 \*--------------------------------------------------------------------------*/
01452 
01453 static int
01454 opt_a(char *opt, char *optarg, void *client_data)
01455 {
01456     plsdidev(PL_NOTSET, atof(optarg), PL_NOTSET, PL_NOTSET);
01457     return 0;
01458 }
01459 
01460 /*--------------------------------------------------------------------------*\
01461  * opt_jx()
01462  *
01463  * Performs appropriate action for option "jx":
01464  * Sets relative justification in x
01465 \*--------------------------------------------------------------------------*/
01466 
01467 static int
01468 opt_jx(char *opt, char *optarg, void *client_data)
01469 {
01470     plsdidev(PL_NOTSET, PL_NOTSET, atof(optarg), PL_NOTSET);
01471     return 0;
01472 }
01473 
01474 /*--------------------------------------------------------------------------*\
01475  * opt_jy()
01476  *
01477  * Performs appropriate action for option "jy":
01478  * Sets relative justification in y
01479 \*--------------------------------------------------------------------------*/
01480 
01481 static int
01482 opt_jy(char *opt, char *optarg, void *client_data)
01483 {
01484     plsdidev(PL_NOTSET, PL_NOTSET, PL_NOTSET, atof(optarg));
01485     return 0;
01486 }
01487 
01488 /*--------------------------------------------------------------------------*\
01489  * opt_ori()
01490  *
01491  * Performs appropriate action for option "ori":
01492  * Sets orientation
01493 \*--------------------------------------------------------------------------*/
01494 
01495 static int
01496 opt_ori(char *opt, char *optarg, void *client_data)
01497 {
01498     plsdiori(atof(optarg));
01499     return 0;
01500 }
01501 
01502 /*--------------------------------------------------------------------------*\
01503  * opt_freeaspect()
01504  *
01505  * Performs appropriate action for option "freeaspect":
01506  * Allow aspect ratio to adjust to orientation swaps.
01507 \*--------------------------------------------------------------------------*/
01508 
01509 static int
01510 opt_freeaspect(char *opt, char *optarg, void *client_data)
01511 {
01512     plsc->freeaspect = 1;
01513     return 0;
01514 }
01515 
01516 /*--------------------------------------------------------------------------*\
01517  * opt_portrait()
01518  *
01519  * Performs appropriate action for option "portrait":
01520  * Set portrait mode.  If plsc->portrait = 1, then the orientation for certain 
01521  * drivers is changed by 90 deg to portrait orientation from the default
01522  * landscape orientation used by PLplot while the  aspect ratio allowed to
01523  * adjust using freeaspect.
01524  * N.B. the driver list where this flag is honored is currently limited
01525  * to ljii, ljiip, psc, ps, and pstex.  A 90 deg rotation is just not
01526  * appropriate for certain other drivers.  These drivers where portrait
01527  * mode is ignored include display drivers (e.g., xwin, tk), drivers 
01528  * which are subequently going to be transformed to another form 
01529  * (e.g., meta or pbm), or drivers which are normally used for web 
01530  * publishing (e.g., png, jpeg).  That said, the case is not entirely clear
01531  * for all drivers so the list of drivers where portrait mode is honored
01532  * may increase in the future. To add to the list simply copy the small
01533  * bit of code from  ps.c that has to do with pls->portrait to the 
01534  * appropriate driver file.
01535 \*--------------------------------------------------------------------------*/
01536 
01537 static int
01538 opt_portrait(char *opt, char *optarg, void *client_data)
01539 {
01540     plsc->portrait = 1;
01541     return 0;
01542 }
01543 
01544 /*--------------------------------------------------------------------------*\
01545  * opt_width()
01546  *
01547  * Performs appropriate action for option "width":
01548  * Sets pen width
01549 \*--------------------------------------------------------------------------*/
01550 
01551 static int
01552 opt_width(char *opt, char *optarg, void *client_data)
01553 {
01554     int width;
01555 
01556     width = atoi(optarg);
01557     if (width < 0) {
01558        fprintf(stderr, "?invalid width\n");
01559        return 1;
01560     }
01561     else {
01562        plwid(width);
01563        plsc->widthlock = 1;
01564     }
01565     return 0;
01566 }
01567 
01568 /*--------------------------------------------------------------------------*\
01569  * opt_bg()
01570  *
01571  * Performs appropriate action for option "bg":
01572  * Sets background color
01573 \*--------------------------------------------------------------------------*/
01574 
01575 static int
01576 opt_bg(char *opt, char *optarg, void *client_data)
01577 {
01578     char *rgb;
01579     long bgcolor, r, g, b;
01580 
01581 /* Always in hex!  Strip off leading "#" (TK-ism) if present. */
01582 
01583     if (*optarg == '#')
01584        rgb = optarg + 1;
01585     else
01586        rgb = optarg;
01587 
01588 /* Get number in hex */
01589 
01590     bgcolor = strtol(rgb, NULL, 16);
01591 
01592 /* Must be either a 3 or 6 digit hex number */
01593 /* If 3 digits, each is "doubled" (i.e. ABC becomes AABBCC). */
01594 
01595     switch (strlen(rgb)) {
01596     case 3:
01597        r = (bgcolor & 0xF00) >> 8;
01598        g = (bgcolor & 0x0F0) >> 4;
01599        b = (bgcolor & 0x00F);
01600 
01601        r = r | (r << 4);
01602        g = g | (g << 4);    /* doubling */
01603        b = b | (b << 4);
01604        break;
01605 
01606     case 6:
01607        r = (bgcolor & 0xFF0000) >> 16;
01608        g = (bgcolor & 0x00FF00) >> 8;
01609        b = (bgcolor & 0x0000FF);
01610        break;
01611 
01612     default:
01613        fprintf(stderr, "Unrecognized background color value %s\n", rgb);
01614        return 1;
01615     }
01616 
01617     plscolbg(r, g, b);
01618 
01619     return 0;
01620 }
01621 
01622 /*--------------------------------------------------------------------------*\
01623  * opt_ncol0()
01624  *
01625  * Performs appropriate action for option "ncol0":
01626  * Sets number of colors to allocate in cmap 0 (upper bound).
01627 \*--------------------------------------------------------------------------*/
01628 
01629 static int
01630 opt_ncol0(char *opt, char *optarg, void *client_data)
01631 {
01632     plsc->ncol0 = atoi(optarg);
01633     return 0;
01634 }
01635 
01636 /*--------------------------------------------------------------------------*\
01637  * opt_ncol1()
01638  *
01639  * Performs appropriate action for option "ncol1":
01640  * Sets number of colors to allocate in cmap 1 (upper bound).
01641 \*--------------------------------------------------------------------------*/
01642 
01643 static int
01644 opt_ncol1(char *opt, char *optarg, void *client_data)
01645 {
01646     plsc->ncol1 = atoi(optarg);
01647     return 0;
01648 }
01649 
01650 /*--------------------------------------------------------------------------*\
01651  * opt_wplt()
01652  *
01653  * Performs appropriate action for option "wplt":
01654  * Sets (zoom) window into plot (e.g. "0,0,0.5,0.5")
01655 \*--------------------------------------------------------------------------*/
01656 
01657 static int
01658 opt_wplt(char *opt, char *optarg, void *client_data)
01659 {
01660     char *field;
01661     PLFLT xl, yl, xr, yr;
01662 
01663     strncpy(opttmp, optarg, OPTMAX-1);
01664 
01665     if ((field = strtok(opttmp, ",")) == NULL)
01666        return 1;
01667 
01668     xl = atof(field);
01669 
01670     if ((field = strtok(NULL, ",")) == NULL)
01671        return 1;
01672 
01673     yl = atof(field);
01674 
01675     if ((field = strtok(NULL, ",")) == NULL)
01676        return 1;
01677 
01678     xr = atof(field);
01679 
01680     if ((field = strtok(NULL, ",")) == NULL)
01681        return 1;
01682 
01683     yr = atof(field);
01684 
01685     plsdiplt(xl, yl, xr, yr);
01686     return 0;
01687 }
01688 
01689 /*--------------------------------------------------------------------------*\
01690  * opt_drvopt()
01691  *
01692  * Get driver specific options in the form <option[=value]>[,option[=value]]*
01693  * If "value" is not specified, it defaults to "1".
01694 \*--------------------------------------------------------------------------*/
01695 
01696 static int
01697 opt_drvopt(char *opt, char *optarg, void *client_data)
01698 {
01699   char t, *tt, *option, *value;
01700   int fl = 0;
01701   DrvOptCmd *drvp;
01702 
01703   option = (char *) malloc((size_t)(1+strlen(optarg))*sizeof(char));
01704   if (option == NULL)
01705     plexit("opt_drvopt: Out of memory!?");
01706 
01707   value = (char *) malloc((size_t)(1+1)*sizeof(char));
01708   if (value == NULL)
01709     plexit("opt_drvopt: Out of memory!?");
01710 
01711   drvp = &drv_opt;
01712   *option = *value = '\0';
01713   tt = option;
01714     while((t = *optarg++)) {
01715       switch (t) {
01716       case ',':
01717        if (fl)
01718          fl = 0;
01719        else {
01720          value[0] = '1';
01721          value[1] = '\0';
01722        }
01723        
01724        *tt = '\0'; tt = option;
01725        drvp->option = plstrdup(option); /* it should not be release, because of familying */
01726        drvp->value = plstrdup(value); /* don't release */
01727        drvp->next = (DrvOptCmd *) malloc(sizeof(DrvOptCmd)); /* don't release */
01728        if (drvp->next == NULL)
01729          plexit("opt_drvopt: Out of memory!?\n");
01730 
01731        drvp = drvp->next;
01732        break;
01733 
01734       case '=':
01735        fl = 1;
01736        *tt = '\0'; tt = value;
01737        break;
01738 
01739       default:
01740        *tt++ = t;
01741       }
01742     }
01743 
01744     *tt = '\0';
01745     if (!fl) {
01746       value[0] = '1';
01747       value[1] = '\0';
01748     }
01749 
01750     drvp->option = plstrdup(option); /* don't release */
01751     drvp->value = plstrdup(value); /* don't release */
01752     drvp->next = NULL;
01753 
01754 #ifdef DEBUG
01755     fprintf(stderr, "\nopt_drvopt: -drvopt parsed options:\n");
01756     drvp = &drv_opt;
01757     do 
01758       fprintf(stderr, "%s %s\n", drvp->option, drvp->value);
01759     while(drvp = drvp->next);
01760     fprintf(stderr, "\n");
01761 #endif
01762 
01763     free(option); free(value);
01764 
01765     return 0;
01766 }
01767 
01768 /*--------------------------------------------------------------------------*\
01769  * opt_fam()
01770  *
01771  * Performs appropriate action for option "fam":
01772  * Enables family output files
01773 \*--------------------------------------------------------------------------*/
01774 
01775 static int
01776 opt_fam(char *opt, char *optarg, void *client_data)
01777 {
01778     plsfam(1, -1, -1);
01779     return 0;
01780 }
01781 
01782 /*--------------------------------------------------------------------------*\
01783  * opt_fsiz()
01784  *
01785  * Performs appropriate action for option "fsiz":
01786  * Sets size of a family member file (may be somewhat larger since eof must
01787  * occur at a page break).  Also turns on familying.  Example usage:
01788  *
01789  *     -fsiz 5M      (5 MB)
01790  *     -fsiz 300K    (300 KB)
01791  *     -fsiz .3M     (same)
01792  *     -fsiz .5G     (half a GB)
01793  *
01794  * Note case of the trailing suffix doesn't matter.
01795  * If no suffix, defaults to MB.
01796 \*--------------------------------------------------------------------------*/
01797 
01798 static int
01799 opt_fsiz(char *opt, char *optarg, void *client_data)
01800 {
01801     PLINT bytemax;
01802     int len = strlen(optarg);
01803     char lastchar = optarg[len-1];
01804     PLFLT multiplier = 1.0e6;
01805     char *spec = (char*)malloc(len+1);
01806 
01807 /* Interpret optional suffix */
01808 
01809     switch (lastchar) {
01810     case 'k':
01811     case 'K':
01812        multiplier = 1.0e3; len--;
01813        break;
01814     case 'm':
01815     case 'M':
01816        multiplier = 1.0e6; len--;
01817        break;
01818     case 'g':
01819     case 'G':
01820        multiplier = 1.0e9; len--;
01821        break;
01822     }
01823     strncpy(spec, optarg, len);
01824     spec[len] = '\0';
01825 
01826     bytemax = multiplier * atof(spec);
01827     if (bytemax == 0) {
01828        fprintf(stderr, "?invalid bytemax\n");
01829        return 1;
01830     }
01831     plsfam(1, -1, bytemax);
01832 
01833     return 0;
01834 }
01835 
01836 /*--------------------------------------------------------------------------*\
01837  * opt_fbeg()
01838  *
01839  * Performs appropriate action for option "fbeg":
01840  * Starts with the specified family member number.
01841 \*--------------------------------------------------------------------------*/
01842 
01843 static int
01844 opt_fbeg(char *opt, char *optarg, void *client_data)
01845 {
01846     plsc->member = atoi(optarg);
01847 
01848     return 0;
01849 }
01850 
01851 /*--------------------------------------------------------------------------*\
01852  * opt_finc()
01853  *
01854  * Performs appropriate action for option "finc":
01855  * Specify increment between family members.
01856 \*--------------------------------------------------------------------------*/
01857 
01858 static int
01859 opt_finc(char *opt, char *optarg, void *client_data)
01860 {
01861     plsc->finc = atoi(optarg);
01862 
01863     return 0;
01864 }
01865 
01866 /*--------------------------------------------------------------------------*\
01867  * opt_fflen()
01868  *
01869  * Performs appropriate action for option "fflen":
01870  * Specify minimum field length for family member number.
01871 \*--------------------------------------------------------------------------*/
01872 
01873 static int
01874 opt_fflen(char *opt, char *optarg, void *client_data)
01875 {
01876     plsc->fflen = atoi(optarg);
01877 
01878     return 0;
01879 }
01880 
01881 /*--------------------------------------------------------------------------*\
01882  * opt_np()
01883  *
01884  * Performs appropriate action for option "np":
01885  * Disables pause between pages
01886 \*--------------------------------------------------------------------------*/
01887 
01888 static int
01889 opt_np(char *opt, char *optarg, void *client_data)
01890 {
01891     plspause(0);
01892     return 0;
01893 }
01894 
01895 /*--------------------------------------------------------------------------*\
01896  * opt_nopixmap()
01897  *
01898  * Performs appropriate action for option "nopixmap":
01899  * Disables use of pixmaps in X drivers
01900 \*--------------------------------------------------------------------------*/
01901 
01902 static int
01903 opt_nopixmap(char *opt, char *optarg, void *client_data)
01904 {
01905     plsc->nopixmap = 1;
01906     return 0;
01907 }
01908 
01909 /*--------------------------------------------------------------------------*\
01910  * opt_db()
01911  *
01912  * Performs appropriate action for option "db":
01913  * Double buffer X output (update only done on eop or Expose)
01914 \*--------------------------------------------------------------------------*/
01915 
01916 static int
01917 opt_db(char *opt, char *optarg, void *client_data)
01918 {
01919     plsc->db = 1;
01920     return 0;
01921 }
01922 
01923 /*--------------------------------------------------------------------------*\
01924  * opt_bufmax()
01925  *
01926  * Performs appropriate action for option "bufmax":
01927  * Sets size of data buffer for tk driver
01928 \*--------------------------------------------------------------------------*/
01929 
01930 static int
01931 opt_bufmax(char *opt, char *optarg, void *client_data)
01932 {
01933     plsc->bufmax = atoi(optarg);
01934     return 0;
01935 }
01936 
01937 /*--------------------------------------------------------------------------*\
01938  * opt_server_name()
01939  *
01940  * Performs appropriate action for option "server_name":
01941  * Sets main window name of server (Tcl/TK/DP driver only)
01942 \*--------------------------------------------------------------------------*/
01943 
01944 static int
01945 opt_server_name(char *opt, char *optarg, void *client_data)
01946 {
01947     plsc->server_name = optarg;
01948     return 0;
01949 }
01950 
01951 /*--------------------------------------------------------------------------*\
01952  * opt_server_host()
01953  *
01954  * Performs appropriate action for option "server_host":
01955  * Sets host to run server on (Tcl/TK/DP driver only)
01956 \*--------------------------------------------------------------------------*/
01957 
01958 static int
01959 opt_server_host(char *opt, char *optarg, void *client_data)
01960 {
01961     plsc->server_host = optarg;
01962     return 0;
01963 }
01964 
01965 /*--------------------------------------------------------------------------*\
01966  * opt_server_port()
01967  *
01968  * Performs appropriate action for option "server_port":
01969  * Sets port to talk to server on (Tcl/TK/DP driver only)
01970 \*--------------------------------------------------------------------------*/
01971 
01972 static int
01973 opt_server_port(char *opt, char *optarg, void *client_data)
01974 {
01975     plsc->server_port = optarg;
01976     return 0;
01977 }
01978 
01979 /*--------------------------------------------------------------------------*\
01980  * opt_user()
01981  *
01982  * Performs appropriate action for option "user":
01983  * Sets user name on remote node (for remsh), dp driver only
01984 \*--------------------------------------------------------------------------*/
01985 
01986 static int
01987 opt_user(char *opt, char *optarg, void *client_data)
01988 {
01989     plsc->user = optarg;
01990     return 0;
01991 }
01992 
01993 /*--------------------------------------------------------------------------*\
01994  * opt_plserver()
01995  *
01996  * Performs appropriate action for option "plserver":
01997  * Sets name to use when invoking server (Tcl/TK/DP driver only)
01998 \*--------------------------------------------------------------------------*/
01999 
02000 static int
02001 opt_plserver(char *opt, char *optarg, void *client_data)
02002 {
02003     plsc->plserver = optarg;
02004     return 0;
02005 }
02006 
02007 /*--------------------------------------------------------------------------*\
02008  * opt_plwindow()
02009  *
02010  * Performs appropriate action for option "plwindow":
02011  * Sets PLplot window name
02012 \*--------------------------------------------------------------------------*/
02013 
02014 static int
02015 opt_plwindow(char *opt, char *optarg, void *client_data)
02016 {
02017     plsc->plwindow = (char *) malloc((size_t)(1+strlen(optarg))*sizeof(char));
02018     strcpy (plsc->plwindow, optarg);
02019     return 0;
02020 }
02021 
02022 /*--------------------------------------------------------------------------*\
02023  * opt_tcl_cmd()
02024  *
02025  * Performs appropriate action for option "tcl_cmd":
02026  * Sets TCL command(s) to eval on startup
02027 \*--------------------------------------------------------------------------*/
02028 
02029 static int
02030 opt_tcl_cmd(char *opt, char *optarg, void *client_data)
02031 {
02032     plsc->tcl_cmd = optarg;
02033     return 0;
02034 }
02035 
02036 /*--------------------------------------------------------------------------*\
02037  * opt_auto_path()
02038  *
02039  * Performs appropriate action for option "auto_path":
02040  * Sets additional directories to autoload
02041 \*--------------------------------------------------------------------------*/
02042 
02043 static int
02044 opt_auto_path(char *opt, char *optarg, void *client_data)
02045 {
02046     plsc->auto_path = optarg;
02047     return 0;
02048 }
02049 
02050 /*--------------------------------------------------------------------------*\
02051  * opt_px()
02052  *
02053  * Performs appropriate action for option "px":
02054  * Set packing in x
02055 \*--------------------------------------------------------------------------*/
02056 
02057 static int
02058 opt_px(char *opt, char *optarg, void *client_data)
02059 {
02060     plssub(atoi(optarg), -1);
02061     return 0;
02062 }
02063 
02064 /*--------------------------------------------------------------------------*\
02065  * opt_py()
02066  *
02067  * Performs appropriate action for option "py":
02068  * Set packing in y
02069 \*--------------------------------------------------------------------------*/
02070 
02071 static int
02072 opt_py(char *opt, char *optarg, void *client_data)
02073 {
02074     plssub(-1, atoi(optarg));
02075     return 0;
02076 }
02077 
02078 /*--------------------------------------------------------------------------*\
02079  * opt_geo()
02080  *
02081  * Performs appropriate action for option "geo":
02082  * Set geometry for output window
02083  *   e.g.,  "-geometry 400x400+100+0"
02084  * or with offsets alone "-geometry +Xoff+Yoff"
02085  *   e.g., "-geometry +100+0"
02086 \*--------------------------------------------------------------------------*/
02087 
02088 static int
02089 opt_geo(char *opt, char *optarg, void *client_data)
02090 {
02091     char *field;
02092     PLFLT xdpi = 0., ydpi = 0.;
02093     PLINT xwid = 0, ywid = 0, xoff = 0, yoff = 0;
02094     
02095 /* The TK driver uses the geometry string directly */    
02096 
02097     plsc->geometry = (char *) malloc((size_t)(1+strlen(optarg))*sizeof(char));
02098     strcpy (plsc->geometry, optarg);
02099 
02100 /* Set up plplot dimensions */
02101 
02102     strncpy(opttmp, optarg, OPTMAX-1);
02103     if (strchr (opttmp, 'x')) {
02104 
02105     /* -geometry WxH or -geometry WxH+Xoff+Yoff */
02106 
02107        field = strtok (opttmp, "x");
02108        xwid = atoi (field);
02109        if (xwid == 0)
02110            fprintf (stderr, "?invalid xwid\n");
02111 
02112        if ((field = strtok (NULL, "+")) == NULL)
02113            return 1;
02114 
02115        ywid = atoi (field);
02116        if (ywid == 0)
02117            fprintf (stderr, "?invalid ywid\n");
02118 
02119        field = strtok (NULL, "+");
02120     }
02121     else {
02122 
02123     /* -geometry +Xoff or -geometry +Xoff+Yoff only */
02124 
02125        field = strtok (opttmp, "+");
02126     }
02127 
02128     if (field != NULL) {
02129        xoff = atoi (field);
02130        if ((field = strtok (NULL, "+")) != NULL)
02131            yoff = atoi (field);
02132     }
02133 
02134     plspage (xdpi, ydpi, xwid, ywid, xoff, yoff);
02135     return 0;
02136 }
02137 
02138 /*--------------------------------------------------------------------------*\
02139  * opt_tk_file()
02140  *
02141  * File name for plserver tk_file option
02142 \*--------------------------------------------------------------------------*/
02143    
02144 static int
02145 opt_tk_file(char *opt, char *optarg, void *client_data)
02146 {
02147     plsc->tk_file = (char *) malloc((size_t)(1+strlen(optarg))*sizeof(char));
02148     strcpy (plsc->tk_file, optarg);
02149     return 0;
02150 }
02151 
02152 /*--------------------------------------------------------------------------*\
02153  * opt_dpi()
02154  *
02155  * Performs appropriate action for option "dpi":
02156  * Set dpi resolution for output device
02157  *   e.g.,  "-dpi 600x300", will set X dpi to 600 and Y dpi to 300
02158  *            or 
02159  *   e.g., "-dpi 1200"
02160  * Will set both X and Y dpi to 1200 dpi
02161 \*--------------------------------------------------------------------------*/
02162 
02163 static int
02164 opt_dpi(char *opt, char *optarg, void *client_data)
02165 {
02166     char *field;
02167     PLFLT xdpi = 0., ydpi = 0.;
02168     PLINT xwid = 0, ywid = 0, xoff = 0, yoff = 0;
02169     
02170     strncpy(opttmp, optarg, OPTMAX-1);
02171     if (strchr (opttmp, 'x')) {
02172        field = strtok (opttmp, "x");
02173        xdpi = atof (field);
02174        if (xdpi == 0)
02175            fprintf (stderr, "?invalid xdpi\n");
02176 
02177        if ((field = strtok (NULL, " ")) == NULL)
02178           return 1;
02179           
02180         ydpi = atof (field);
02181         if (ydpi == 0)
02182           fprintf (stderr, "?invalid ydpi\n");
02183 
02184     } else {
02185        xdpi = atof (opttmp);
02186        ydpi=xdpi;
02187        if (xdpi==0) return 1;
02188     }
02189 
02190     plspage (xdpi, ydpi, xwid, ywid, xoff, yoff);
02191     return 0;
02192 }
02193 
02194 /*--------------------------------------------------------------------------*\
02195  * opt_dev_compression()
02196  *
02197  * Sets device compression
02198 \*--------------------------------------------------------------------------*/
02199 
02200 static int
02201 opt_dev_compression(char *opt, char *optarg, void *client_data)
02202 {
02203     PLINT comp = 0;
02204    
02205     comp = atoi(optarg);
02206     if (comp == 0) {
02207        fprintf(stderr, "?invalid compression\n");
02208        return 1;
02209     }
02210     plscompression (comp);
02211 
02212     return 0;
02213 }