/* begincopyright Copyright (c) 1988 Xerox Corporation. All rights reserved. Use and copying of this software and preparation of derivative works based upon this software are permitted. Any distribution of this software or derivative works must comply with all applicable United States export control laws. This software is made available AS IS, and Xerox Corporation makes no warranty about the software, its performance or its conformity to any specification. Any person obtaining a copy of this software is requested to send their name and post office or electronic mail address to PCRCoordinator.pa@xerox.com, or to: PCR Coordinator Xerox PARC 3333 Coyote Hill Rd. Palo Alto, CA 94304 endcopyright */ /* * CommandLine.h * * PCR command line interface. * * All procs in this interface are usable from initialization code, * (before allocator and threads have been set up) * EXCEPT the ones that use the XR_Fildes type. * * Demers, April 15, 1990 11:43:36 am PDT */ #ifndef _XR_COMMAND_LINE_ #define _XR_COMMAND_LINE_ 1 #ifndef _XR_BASIC_TYPES_ # include "xr/BasicTypes.h" #endif #ifndef _XR_THREADS_ # include "xr/Threads.h" #endif /* * Command Lines */ typedef XR_Pointer /* opaque */ XR_CLHandle; /* Handle to a command line. To construct one see XR_CLCreateHandleFromXXX below. */ extern XR_CLHandle XR_CLCreateHandleFromArgs(/* int argc, char **argv */); /* Create handle from given args. The argv vector and the arg strings it points to are NOT copied, and so should be immutable. */ extern XR_CLHandle XR_CLCreateHandleFromCharProc(/* XR_MesaProc charProc -- closure for int (*charProc)(XR_MesaProc self) XR_MesaProc promptProc -- closure for void (*promptProc)(char *prompt, int nBytes, XR_MesaProc self) */); /* The charProc should behave like a Unix getchar -- it should return the char as an int, or (-1) at the end. If non-NIL, the promptProc is called to print interactive prompts. Implementation is lazy -- the charProc is actually called as a result of calling CLProcess on the resulting CLHandle. */ extern XR_CLHandle XR_CLCreateHandleFromFile(/* XR_Fildes file; XR_Fildes promptFile; */); /* Create handle for reading from given file, which must be open. The prompt may be (usually is) XR_nullFildes; */ extern XR_CLHandle XR_CLCreateHandleFromString(/* char *string; */); /* Create handle for reading args from given string. The string is not copied, and so should be immutable. */ extern int XR_CLPrependArgsToHandle(/* XR_CLHandle h, int argc, char **argv */); /* Prepend args to handle. The argv vector is copied. The underlying strings are not copied, and so should be immutable. Return 0 on success, (-1) on failure. */ extern void XR_CLDestroyHandle(/* XR_CLHandle h */); /* Destroy the Handle. It's okay just to drop it on the floor. If the handle was created from a file, this does NOT close the file. */ /* * Command Line Processing Procs -- * * registration, invocation, ... */ typedef XR_Pointer /* opaque */ XR_CLProcsHandle; /* Handle to collection of registered command line processing procs (see below). */ typedef struct XR_CLCallEnvRep { XR_CLHandle clce_h; XR_CLProcsHandle clce_pH; XR_MesaProc clce_msgSink; /* closure for void (*sink)(char *buf, int nBytes, XR_MesaProc self) */ int *clce_msgVerbosityP; struct XR_JmpBufRep clce_jmpBuf; XR_MesaProc clce_handlerProc; /* closure for int (*handlerProc)(int prevResult, XR_MesaProc self) */ XR_Pointer clce_clientData; } *XR_CLCallEnv; /* Call environment passed to CLProc (below). The CLProc can either return or call XR_longjmp(clce_jmpBuf, x). If it promises not to do the XR_longjmp, the CLProc is free to store into clce_jmpbuf. The CLProc may store into clce_handlerProc; the stored handler proc will be invoked if this or a subsequent CLProc returns an error value. */ typedef int (*XR_CLProc)(/* XR_CLCallEnv clce, int argc, char **argv, int prevResult, XR_MesaProc self */); /* "Command Line Proc" -- proc to process a command line argument group. The clce value provides command line and procs handles, as well as a place to put message output. If the result is nonzero, it will be stored with associated argument group in command line. The intent is that 0 means "ignored" or "not processed;" positive values are success codes and negative values are error codes. The prevResult value comes from a previous call to a CLProc; see the description of XR_CLApply below. Usual result: 0 means "ignored" or "not processed" >0 means success of some sort <0 means error of some sort but see the description of postProc in XR_CLApply below. */ /* Proc header for a CLProc ... */ #define XR_CLPROC(name) \ int name (clce, argc, argv, prevResult, self) \ XR_CLCallEnv clce; \ int argc; \ char **argv; \ int prevResult; \ XR_MesaProc self; /* Message printing macros for CLProcs ... */ /* To use, omit left paren, e.g. */ /* XR_CLXXXMsg "Hello %d %s\n", 17, "world" ); */ #define XR_CLCEVerbose(clce,which) \ ( *((clce)->clce_msgVerbosityP) >= (which) ) #define XR_CLVerbose(which) \ XR_CLCEVerbose(clce,(which)) #define XR_CLCEMsg(clce) \ XR_PPrintF( (clce)->clce_msgSink, #define XR_CLMsg XR_CLCEMsg(clce) #define XR_CLMsgIf(which) \ if( XR_CLVerbose(which) ) XR_CLMsg #define XR_CLPanicMsg XR_CLMsg #define XR_CLErrorMsg XR_CLMsgIf(XR_VERBOSITY_ERROR) #define XR_CLQuietMsg XR_CLMsgIf(XR_VERBOSITY_QUIET) #define XR_CLWarningMsg XR_CLMsgIf(XR_VERBOSITY_WARNING) #define XR_CLNormalMsg XR_CLMsgIf(XR_VERBOSITY_NORMAL) #define XR_CLLogMsg XR_CLMsgIf(XR_VERBOSITY_LOG) #define XR_CLStatsMsg XR_CLMsgIf(XR_VERBOSITY_STATS) #define XR_CLVerboseMsg XR_CLMsgIf(XR_VERBOSITY_VERBOSE) /* Indirect call from one CLProc to another */ extern int XR_CLCallIndirect(/* XR_CLCallEnv clce, char *key, int argc, char **argv */); /* Invoke CLProc for key on remaining arguments. The prevResult argument will be 0. This can be simulated with other procs in this interface, and is provided as a convenience. */ /* simple utilities for creating CLProcs */ typedef bool /* oldVal = */ (*XR_CLSetBoolProc)(/* bool newVal */); typedef unsigned /* oldVal = */ (*XR_CLSetUnsignedProc)(/* unsigned newVal */); extern int XR_CLProc_setBool(/* ... */); /* An XR_CLProc that expects self->mp_x to be an XR_CLSetBoolProc. Prints " set to (was )" at normal verbosity. */ extern int XR_CLProc_setUnsigned(/* ... */); /* An XR_CLProc that expects self->mp_x to be an XR_CLSetUnsignedProc. Prints " set to (was )" at normal verbosity. */ /* ProcsHandles -- collections of registered procs */ extern XR_CLProcsHandle XR_CLCreateProcsHandle(/* */); /* Create a CLProcsHandle. */ typedef XR_Pointer /* opaque */ XR_CLRegistration; /* Handle to a registered CLProc. */ extern XR_CLRegistration XR_CLRegisterProc(/* XR_CLProcsHandle pH, char *key, bool caseSensitive, char *helpMsg, XR_MesaProc proc, -- closure of an XR_CLProc bool replace */); /* Add a new Registration to the CLProcsHandle. Return it, or NIL on failure. Multiple procs may not be registered for given key; if a registration already exists the call will fail unless `replace' is TRUE. */ extern int XR_CLUnsafeRegisterProcs(/* XR_CLProcsHandle pH, char **description */); /* The description points to a NIL-terminated sequence, where each sequence element consists of (char *) theMesaProc.mp_proc, (char *) theMesaProc.mp_x, (char *) helpMessage (may be NIL), (char *) firstKey, ... (char *) lastKey, NIL (thus, the whole thing ends with two consecutive NILs). All the procs are registered, with replace == TRUE. Return 0 on success, <0 on failure. Like the name says, this is <<>>, but a useful creature comfort. */ extern int XR_CLUnregister(/* XR_CLProcsHandle pH, XR_CLRegistration r */); /* Undo a registration. Return 0 on success, (-1) on failure. */ extern XR_CLRegistration XR_CLGetRegistrationWithKey(/* XR_CLProcsHandle pH, char *key */); /* Return specified registration, or NIL if none exists. */ extern void XR_CLEnumerateRegistrations(/* XR_CLProcsHandle pH, XR_MesaProc eachRegistration -- closure of bool (*proc)(XR_CLRegistration r, XR_MesaProc self) */); /* Enumerate specified registrations. The proc should return FALSE to abort enumeration. The CLEnumerateRegistrations call holds a monitor; the callback proc may not call into this package except for CLGetRegistrationDetails. */ extern void XR_CLGetRegistrationDetails(/* XR_CLRegistration r, char **key, (* result *) bool *caseSensitive, (* result *) char **helpMsg, (* result *) XR_MesaProc *proc (* result *) */); /* Fill in non-NIL result buffers. */ extern XR_MesaProc XR_CLGetProcForKey(/* XR_CLProcsHandle pH, char *key */); /* Return registered MesaProc, or NIL if none exists. This can be simulated with above procs, is provided as a convenience. */ extern void XR_CLDestroyProcsHandle(/* XR_CLProcsHandle pH */); /* Destroy the ProcsHandle. It's okay just to drop it on the floor. */ /* * * Command Line Processing ... * */ extern int XR_CLApply(/* XR_CLCallEnv clce, XR_MesaProc preProc, -- closure for XR_CLProc, may be NIL XR_MesaProc postProc, -- closure for XR_CLProc, may be NIL */); /* Process the argument groups in command line clce->clce_h using CLProc values registered with clce->clce_pH. For each arg group: - If preProc is specified, invoke it on each arg group. Interpret the result as follows: < 0 => abort processing 0 => call registered CLProc >0 => don't call registered CLProc but continue processing A missing preProc is equivalent to one that always returns 0. - Lookup the registered CLProc and invoke it. Save the result it returns to be passed to the postProc, as described below. A missing registered CLProc is equivalent to a CLProc that does nothing and returns 0. The CLProc can simulate a nonzero return by doing an XR_longjmp to clce->clce_jb. - If postProc is specified, invoke it on each selected arg group after calling the registered CLProc. The result returned by the CLProc is passed as the prevResult argument in this call. Interpret the result as follows: <= 0 => abort processing > 0 => continue processing A missing postProc is equivalent to one that always returns its prevResult argument; thus, it aborts after the first arg group whose CLProc fails or is missing. Return the result of the last postProc invoked. */ #endif