• Main Page
  • Namespaces
  • Classes
  • Files
  • File List
  • File Members

plserver.c

Go to the documentation of this file.
00001 // $Id: plserver.c 11760 2011-06-01 19:29:11Z airwin $
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  Joao Cardoso
00008 //
00009 //  This file is part of PLplot.
00010 //
00011 //  PLplot is free software; you can redistribute it and/or modify
00012 //  it under the terms of the GNU Library General Public License as published
00013 //  by the Free Software Foundation; either version 2 of the License, or
00014 //  (at your option) any later version.
00015 //
00016 //  PLplot is distributed in the hope that it will be useful,
00017 //  but WITHOUT ANY WARRANTY; without even the implied warranty of
00018 //  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00019 //  GNU Library General Public License for more details.
00020 //
00021 //  You should have received a copy of the GNU Library General Public License
00022 //  along with PLplot; if not, write to the Free Software
00023 //  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
00024 //
00025 //--------------------------------------------------------------------------
00026 //
00027 //  PLplot graphics server.
00028 //
00029 //  Just a front-end to the pltkMain() function.  Structured along the
00030 //  preferred lines for extended wish'es.  Is typically run as a child
00031 //  process from the PLplot TK driver to render output.  Can use either TK
00032 //  send or Tcl-DP RPC for communication, depending on how it is invoked.
00033 //
00034 //  Note that plserver can be used the same way as wish or dpwish, as it
00035 //  contains the functionality of each of these (except the -notk Tcl-DP
00036 //  command-line option is not supported).
00037 //
00038 
00039 #define NEED_PLDEBUG
00040 #include "plserver.h"
00041 
00042 // Application-specific command-line options
00043 // Variable declarations
00044 
00045 static char        *client_name; // Name of client main window
00046 static char        *auto_path;   // addition to auto_path
00047 static int         child;        // set if child of TK driver
00048 #ifdef PLD_dp
00049 static int         dp;           // set if using Tcl-DP to communicate
00050 #endif
00051 static char        *client_host; // Host id for client
00052 static char        *client_port; // Communications port id for client
00053 
00054 static Tk_ArgvInfo argTable[] = {
00055     { "-client_name", TK_ARGV_STRING,   (char *) NULL, (char *) &client_name,
00056       "Client main window name to connect to" },
00057     { "-client_host", TK_ARGV_STRING,   (char *) NULL, (char *) &client_host,
00058       "Client host to connect to" },
00059     { "-client_port", TK_ARGV_STRING,   (char *) NULL, (char *) &client_port,
00060       "Client port (Tcl-DP) to connect to" },
00061     { "-auto_path",   TK_ARGV_STRING,   (char *) NULL, (char *) &auto_path,
00062       "Additional directory(s) to autoload" },
00063     { "-child",       TK_ARGV_CONSTANT, (char *) 1,    (char *) &child,
00064       "Set ONLY when child of PLplot TK driver" },
00065     { (char *) NULL,  TK_ARGV_END,      (char *) NULL, (char *) NULL,
00066       (char *) NULL }
00067 };
00068 
00069 // PLplot/Tk extension command -- handle exit.
00070 
00071 static int
00072 plExitCmd( ClientData clientData, Tcl_Interp *interp, int argc, char **argv );
00073 
00074 // Evals the specified command, aborting on an error.
00075 
00076 static void
00077 tcl_cmd( Tcl_Interp *interp, char *cmd );
00078 
00079 // Application-specific startup
00080 
00081 static int
00082 AppInit( Tcl_Interp *interp );
00083 
00084 //--------------------------------------------------------------------------
00085 // main --
00086 //
00087 // Just a stub routine to call pltkMain.  The latter is nice to have
00088 // when building extended wishes, since then you don't have to rely on
00089 // sucking the Tk main out of libtk (which doesn't work correctly on all
00090 // systems/compilers/linkers/etc).  Hopefully in the future Tk will
00091 // supply a sufficiently capable tkMain() type function that can be used
00092 // instead.
00093 //--------------------------------------------------------------------------
00094 
00095 int
00096 main( int argc, const char **argv )
00097 {
00098     int        i, myargc = argc;
00099     const char *myargv[20];
00100     Tcl_Interp *interp;
00101     char       *helpmsg = "Command-specific options:";
00102 
00103 #ifdef DEBUG
00104     fprintf( stderr, "Program %s called with arguments :\n", argv[0] );
00105     for ( i = 1; i < argc; i++ )
00106     {
00107         fprintf( stderr, "%s ", argv[i] );
00108     }
00109     fprintf( stderr, "\n" );
00110 #endif
00111 
00112 // Create interpreter just for argument parsing
00113 
00114     interp = Tcl_CreateInterp();
00115 
00116 // Save arglist to get around tk_ParseArgv limitations
00117 
00118     for ( i = 0; i < argc; i++ )
00119     {
00120         myargv[i] = argv[i];
00121     }
00122 
00123 // Parse args
00124 // Examine the result string to see if an error return is really an error
00125 
00126     if ( Tk_ParseArgv( interp, (Tk_Window) NULL, &argc, argv,
00127              argTable, TK_ARGV_NO_DEFAULTS ) != TCL_OK )
00128     {
00129         fprintf( stderr, "\n(plserver) %s\n\n", interp->result );
00130         fprintf( stderr, "\
00131 The client_<xxx> and -child options should not be used except via the\n\
00132 PLplot/Tk driver.\n\n(wish) " );
00133         if ( strncmp( interp->result, helpmsg, strlen( helpmsg ) ) )
00134             exit( 1 );
00135     }
00136 
00137 // No longer need interpreter
00138 
00139 #if TCL_MAJOR_VERSION < 7 || ( TCL_MAJOR_VERSION == 7 && TCL_MINOR_VERSION < 5 )
00140     Tcl_DeleteInterp( interp );
00141 #endif
00142 
00143 // Call pltkMain() with original argc/argv list, to make sure -h is seen
00144 // Does not return until program exit
00145 
00146     exit( pltkMain( myargc, myargv, NULL, AppInit ) );
00147 }
00148 
00149 
00150 //
00151 //--------------------------------------------------------------------------
00152 //
00153 // AppInit --
00154 //
00155 //      This procedure performs application-specific initialization.
00156 //      Most applications, especially those that incorporate additional
00157 //      packages, will have their own version of this procedure.
00158 //
00159 // Results:
00160 //      Returns a standard Tcl completion code, and leaves an error
00161 //      message in interp->result if an error occurs.
00162 //
00163 // Side effects:
00164 //      Depends on the startup script.
00165 //
00166 //--------------------------------------------------------------------------
00167 //
00168 
00169 static int
00170 AppInit( Tcl_Interp *interp )
00171 {
00172     Tk_Window mainWindow = Tk_MainWindow( interp );
00173 
00174 //
00175 // Call the init procedures for included packages.  Each call should
00176 // look like this:
00177 //
00178 // if (Mod_Init(interp) == TCL_ERROR) {
00179 //     return TCL_ERROR;
00180 // }
00181 //
00182 // where "Mod" is the name of the module.
00183 //
00184     if ( Pltk_Init( interp ) == TCL_ERROR )
00185     {
00186         return TCL_ERROR;
00187     }
00188 
00189 // Application-specific startup.  That means: for use in plserver ONLY.
00190 
00191 // Pass child variable to interpreter if set.
00192 
00193     if ( child != 0 )
00194         Tcl_SetVar( interp, "child", "1", 0 );
00195 
00196 // If client_name is set, TK send is being used to communicate.
00197 // If client_port is set, Tcl-DP RPC is being used to communicate.
00198 // The "dp" variable determines which style communication is used
00199 
00200     if ( client_name != NULL )
00201     {
00202         Tcl_SetVar( interp, "client_name", client_name, 0 );
00203         tcl_cmd( interp, "set dp 0" );
00204 #ifdef PLD_dp
00205         dp = 0;
00206 #endif
00207     }
00208     else if ( client_port != NULL )
00209     {
00210 #ifdef PLD_dp
00211         Tcl_SetVar( interp, "client_port", client_port, 0 );
00212         if ( client_host != NULL )
00213             Tcl_SetVar( interp, "client_host", client_host, 0 );
00214         dp = 1; tcl_cmd( interp, "set dp 1" );
00215 #else
00216         Tcl_AppendResult( interp,
00217             "no Tcl-DP support in this version of plserver",
00218             (char *) NULL );
00219         return TCL_ERROR;
00220 #endif
00221     }
00222 
00223 // Add user-specified directory(s) to auto_path
00224 
00225     if ( auto_path != NULL )
00226     {
00227         Tcl_SetVar( interp, "dir", auto_path, 0 );
00228         tcl_cmd( interp, "set auto_path [list $dir $auto_path]" );
00229     }
00230 
00231 // Rename "exit" to "tkexit", and insert custom exit handler
00232 
00233     tcl_cmd( interp, "rename exit tkexit" );
00234 
00235     Tcl_CreateCommand( interp, "exit", (Tcl_CmdProc *) plExitCmd,
00236         (ClientData) mainWindow, (Tcl_CmdDeleteProc *) NULL );
00237 
00238 // Define the flags as variables in the PLPLOT namespace
00239 
00240     set_plplot_parameters( interp );
00241 
00242     return TCL_OK;
00243 }
00244 
00245 //--------------------------------------------------------------------------
00246 // plExitCmd
00247 //
00248 // PLplot/Tk extension command -- handle exit.
00249 // The reason for overriding the normal exit command is so we can tell the
00250 // client to abort.
00251 //--------------------------------------------------------------------------
00252 
00253 static int
00254 plExitCmd( ClientData clientData, Tcl_Interp *interp, int argc, char **argv )
00255 {
00256     int value = 0;
00257 
00258 // Print error message if one given
00259 
00260     if ( interp->result != NULL && interp->result[0] != '\0' )
00261         fprintf( stderr, "%s\n", interp->result );
00262 
00263 // Best to check the syntax before proceeding
00264 
00265     if ( ( argc != 1 ) && ( argc != 2 ) )
00266     {
00267         Tcl_AppendResult( interp, "wrong # args: should be \"", argv[0],
00268             " ?returnCode?\"", (char *) NULL );
00269         return TCL_ERROR;
00270     }
00271     if ( ( argc != 1 ) && ( Tcl_GetInt( interp, argv[1], &value ) != TCL_OK ) )
00272     {
00273         Tcl_AppendResult( interp, "non-integer return code: \"", argv[1],
00274             "\"", (char *) NULL );
00275         return TCL_ERROR;
00276     }
00277 
00278 // If client exists, tell it to self destruct
00279 
00280     Tcl_VarEval( interp, "plserver_link_end", (char **) NULL );
00281 
00282 // Now really exit
00283 
00284     return Tcl_VarEval( interp, "tkexit", argv[1], (char **) NULL );
00285 }
00286 
00287 //--------------------------------------------------------------------------
00288 // tcl_cmd
00289 //
00290 // Evals the specified command, aborting on an error.
00291 //--------------------------------------------------------------------------
00292 
00293 static void
00294 tcl_cmd( Tcl_Interp *interp, char *cmd )
00295 {
00296     int result;
00297 
00298     dbug_enter( "tcl_cmd" );
00299     pldebug( "tcl_cmd", "evaluating command %s\n", cmd );
00300 
00301     result = Tcl_VarEval( interp, cmd, (char **) NULL );
00302     if ( result != TCL_OK )
00303     {
00304         Tcl_Eval( interp, "exit" );
00305         exit( 1 );
00306     }
00307 }

Generated on Wed Oct 12 2011 20:42:22 for PLplot by  doxygen 1.7.1