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