/***** ** ** Module Header ******************************************************* ** ** ** ** Modules Revision 3.0 ** ** Providing a flexible user environment ** ** ** ** File: cmdXResource.c ** ** First Edition: 91/10/23 ** ** ** ** Authors: John Furlan, jlf@behere.com ** ** Leif Hedstrom ** ** Jens Hamisch, jens@Strawberry.COM ** ** ** ** Description: Module command to merge/remove resources from the X11** ** resource manager. The database is update internally, ** ** ie. its not done at evaluation of string modulecmd ** ** returns. It will do something like "xrdb -merge" ** ** using the default display ($DISPLAY). ** ** ** ** Exports: xresourceFinish ** ** cmdXResource ** ** ** ** Notes: Fragments of this code are from the original xrdb ** ** source, Copyright 1987 & 1991 by DIGITAL EQUIPMENT ** ** CORPORATION. Xrdb was written and modified by: ** ** ** ** Jim Gettys, August 28, 1987 ** ** Phil Karlton, January 5, 1987 ** ** Bob Scheifler, February, 1991 ** ** ** ** ToDo/Bugs: + The command only handles screen independant re- ** ** sources. ** ** ************************************************************************ ** ****/ /** ** Copyright *********************************************************** ** ** ** ** Copyright 1991-1994 by John L. Furlan. ** ** see LICENSE.GPL, which must be provided, for details ** ** ** ** ************************************************************************ **/ static char Id[] = "@(#)$Id: cmdXResource.c,v 1.2 2001/06/09 09:48:46 rkowen Exp $"; static void *UseId[] = { &UseId, Id }; /** ************************************************************************ **/ /** HEADERS **/ /** ************************************************************************ **/ #include "modules_def.h" #ifdef HAS_X11LIBS #include #include #include #endif /** ************************************************************************ **/ /** LOCAL DATATYPES **/ /** ************************************************************************ **/ #ifdef HAS_X11LIBS typedef struct _ResourceDB { Tcl_HashTable *data; Window root; Atom prop; } ResourceDB; #endif /** ************************************************************************ **/ /** CONSTANTS **/ /** ************************************************************************ **/ #ifndef R_OK #define F_OK 0 /** does file exist **/ #define X_OK 1 /** is it executable by caller **/ #define W_OK 2 /** is it writable by caller **/ #define R_OK 4 /** is it readable by caller **/ #endif /** ************************************************************************ **/ /** MACROS **/ /** ************************************************************************ **/ #ifdef HAS_X11LIBS #define MAXHOSTNAME 255 #define Resolution( pixels, mm) (((pixels * 100000 / mm) + 50) / 100) #endif /** ************************************************************************ **/ /** LOCAL DATA **/ /** ************************************************************************ **/ static char module_name[] = "cmdXResource.c"; /** File name of this module **/ #if WITH_DEBUGGING_UTIL_2 static char _proc_addDef[] = "addDef"; static char _proc_addNum[] = "addNum"; #endif #if WITH_DEBUGGING_UTIL_1 static char _proc_doDisplayDefines[] = "doDisplayDefines"; static char _proc_doScreenDefines[] = "doScreenDefines"; static char _proc_readFile[] = "readFile"; static char _proc_getEntries[] = "getEntries"; static char _proc_storeResProp[] = "storeResProp"; static char _proc_getOld[] = "getOld"; static char _proc_initBuffers[] = "initBuffers"; static char _proc_xresourceFinish[] = "xresourceFinish"; #endif #if WITH_DEBUGGING_CALLBACK static char _proc_cmdXResource[] = "cmdXResource"; #endif #ifdef HAS_X11LIBS static Display *dpy = (Display *) NULL; static char *defines = (char *) NULL; static int def_base = 0; static Tcl_DString *buffer = (Tcl_DString *) NULL; static ResourceDB resDB = { NULL, (Window) 0, (Atom) 0 }; #endif /** ************************************************************************ **/ /** PROTOTYPES **/ /** ************************************************************************ **/ static void addDef( char*, char*); static void addNum( char*, int); static void doDisplayDefines(void); static void doScreenDefines( int); static int readFile( register FILE *, int); static ErrType getEntries(Tcl_Interp*, Tcl_HashTable*, register char*, int); #ifdef HAS_X11LIBS static void storeResProp( register ResourceDB* ); #endif static ErrType getOld( register char**); static ErrType initBuffers(Tcl_Interp*, register int ); #ifdef HAS_X11LIBS /*++++ ** ** Function-Header ***************************************************** ** ** ** ** Function: addDef, addNum ** ** ** ** Description: Adds DEFINES to the define buffer. This code is main-** ** ly the same as in the original xrdb.c ** ** ** ** First Edition: 91/10/23 ** ** ** ** Parameters: char *title Name of the ressource ** ** char *value and its value ** ** ** ** Result: - ** ** ** ** Attached Globals: defines Buffer for all DEFINES which will be ** ** written here in command lien syntax: ** ** -D = ** ** ** ** ************************************************************************ ** ++++*/ static void addDef( char *title, char *value) { register int quote; #if WITH_DEBUGGING_UTIL_2 ErrorLogger( NO_ERR_START, LOC, _proc_addDef, NULL); #endif /** ** Add '-D title' at first **/ if( title && *title) { strcat( defines, " -D"); strcat( defines, title); /** ** Add the value if there is one **/ if( value && *value) { quote = (value && strchr( value, ' ')); strcat( defines, (quote ? "=\"" : "=")); strcat( defines, value); if( quote) strcat( defines,"\""); } /** if( value) **/ } /** if( title) **/ } /** End of 'addDef' **/ static void addNum( char *title, int value) { char num[ 20]; #if WITH_DEBUGGING_UTIL_2 ErrorLogger( NO_ERR_START, LOC, _proc_addNum, NULL); #endif sprintf( num, "%d", value); addDef( title, num); } /** End of 'addNum' **/ /*++++ ** ** Function-Header ***************************************************** ** ** ** ** Function: doDisplayDefines ** ** ** ** Description: Put the client and server specific defines on the ** ** define buffer ** ** ** ** First Edition: 91/10/23 ** ** ** ** Parameters: - ** ** ** ** Result: - ** ** ** ** Attached Globals: dpy For seeking the name of the display ** ** defines (via addDef and addNum) ** ** ** ** ************************************************************************ ** ++++*/ static void doDisplayDefines() { char client[ MAXHOSTNAME], /** X client name buffer **/ server[ MAXHOSTNAME], /** X server name buffer **/ *colon; /** Pointer for seeking the **/ /** colon in the server name **/ #if WITH_DEBUGGING_UTIL_1 ErrorLogger( NO_ERR_START, LOC, _proc_doDisplayDefines, NULL); #endif /** ** Get client and server hostname. Remove everything after the ':' from ** the server name. If there's no server name available, the server de- ** faults to the client. **/ XmuGetHostname( client, MAXHOSTNAME); strcpy( server, XDisplayName( NULL)); if( colon = strchr( server, ':')) *colon = '\0'; if( !*server) strcpy( server, client); /** ** Add the standard defines now ... **/ addDef( "HOST", server); addDef( "SERVERHOST", server); addDef( "CLIENTHOST", client); addNum( "VERSION", ProtocolVersion( dpy)); addNum( "REVISION", ProtocolRevision( dpy)); addDef( "VENDOR", ServerVendor( dpy)); addNum( "RELEASE", VendorRelease( dpy)); } /** End of 'doDisplayDefines' **/ /*++++ ** ** Function-Header ***************************************************** ** ** ** ** Function: doScreenDefines ** ** ** ** Description: Put the screen specific defines on the define buffer ** ** ** ** First Edition: 91/10/23 ** ** ** ** Parameters: int scrno Screen number ** ** ** ** Result: - ** ** ** ** Attached Globals: dpy For seeking the name of the display ** ** defines (via addDef and addNum) ** ** ** ** ************************************************************************ ** ++++*/ static void doScreenDefines( int scrno) { register Screen *screen; register Visual *visual; #if WITH_DEBUGGING_UTIL_1 ErrorLogger( NO_ERR_START, LOC, _proc_doScreenDefines, NULL); #endif /** ** Get screen data at first **/ screen = ScreenOfDisplay( dpy, scrno); visual = DefaultVisualOfScreen( screen); /** ** Put screen data on the defines buffer **/ addNum( "WIDTH", screen->width); addNum( "HEIGHT", screen->height); addNum( "X_RESOLUTION", Resolution( screen->width, screen->mwidth)); addNum( "Y_RESOLUTION", Resolution( screen->height, screen->mheight)); addNum( "PLANES", DisplayPlanes( dpy, scrno)); addNum( "BITS_PER_RGB", visual->bits_per_rgb); /** ** The CLASS and COLOR do depend on the screen class **/ switch(visual->class) { case StaticGray: addDef( "CLASS", "StaticGray"); break; case GrayScale: addDef( "CLASS", "GrayScale"); break; case StaticColor: addDef( "CLASS", "StaticColor"); addDef( "COLOR", NULL); break; case PseudoColor: addDef( "CLASS", "PseudoColor"); addDef( "COLOR", NULL); break; case TrueColor: addDef( "CLASS", "TrueColor"); addDef( "COLOR", NULL); break; case DirectColor: addDef( "CLASS", "DirectColor"); addDef( "COLOR", NULL); break; } /** switch **/ } /** End of 'doScreenDefines' **/ /*++++ ** ** Function-Header ***************************************************** ** ** ** ** Function: readFile ** ** ** ** Description: Read resource from a file, which normally is a pipe ** ** opened with popen. ** ** The file will be closed, when reading is finished ** ** ** ** Note: This routine uses the global variable 'line', declar-** ** ed in another file!!! ** ** ** ** First Edition: 91/10/23 ** ** ** ** Parameters: register FILE *input The stream to be read from ** ** int do_cpp Differs betweem a pipe or a ** ** file being assigned to input ** ** ** ** Result: - ** ** ** ** Attached Globals: line Buffer for a line to be read ** ** buffer Buffer for the whole ressource file ** ** image ** ** ** ** ************************************************************************ ** ++++*/ static int readFile( register FILE *input, int do_cpp) { register int bytes; #if WITH_DEBUGGING_UTIL_1 ErrorLogger( NO_ERR_START, LOC, _proc_readFile, NULL); #endif while( !feof( input) && (bytes = fread( line, 1, LINELENGTH, input))) Tcl_DStringAppend( buffer, line, bytes); if( do_cpp) { if( -1 == pclose( input)) if( OK != ErrorLogger( ERR_PCLOSE, LOC, NULL)) return( TCL_ERROR); /** -------- EXIT (FAILURE) -------> **/ } else { if( EOF == fclose( input)) if( OK != ErrorLogger( ERR_CLOSE, LOC, NULL)) return( TCL_ERROR); /** -------- EXIT (FAILURE) -------> **/ } return( TCL_OK); } /** End of 'readFile' **/ /*++++ ** ** Function-Header ***************************************************** ** ** ** ** Function: getEntries ** ** ** ** Description: Updates the ressources database (which is a Tcl hash ** ** table) with the ressources passed in the buffer. The ** ** buffer contains a X ressource lookalike text image. ** ** ** ** First Edition: 91/10/23 ** ** ** ** Parameters: Tcl_Interp *interp According Tcl interp.** ** Tcl_HashTable *data The hash tables holding the ** ** ressource data ** ** register char *buf The buffer containing the ** ** ressources to be modified in ** ** X ressource syntax ** ** int remove Remove or add ressources ** ** ** ** Result: ErrType NO_ERR Success ** ** ERR_PARSE Parse error ** ** ** ** Attached Globals: - ** ** ** ** ************************************************************************ ** ++++*/ static ErrType getEntries( Tcl_Interp *interp, Tcl_HashTable *data, register char *buf, int remove) { static Tcl_RegExp res_exp = (Tcl_RegExp) NULL; register Tcl_HashEntry *entry; char *end; int new_res; #if WITH_DEBUGGING_UTIL_1 ErrorLogger( NO_ERR_START, LOC, _proc_getEntries, NULL); #endif /** ** The following regular expression matches pattern like ** ** : ** ** The ressource will be returned as \1 and the value as \2 ** Set the regexp pointer only, if it hasn't already been set. This ** is a constant regexp! **/ if( !res_exp) res_exp = Tcl_RegExpCompile(interp, "[ \t]*([^ \t]*)[ \t]*:[ \t]*(.*)[ \t]*"); /** ** Seek for the lines (buffers) end. Put a terminator there. Take care of ** escaped newlines! **/ for( end = buf; *end; end++) if( *end == '\\' && *(end+1) == '\n') end++; else if( *end == '\n') *end = '\0'; /** ** Now read the whole buffer. ** At first, we have to ignore comments **/ while( buf <= end) { if( *buf == '#' || *buf == '!' || !*buf) { while( *buf++) ; /** ** Otherwise we're seeking for a syntacticl correct X ressource entry **/ } else if( !Tcl_RegExpExec(interp, res_exp, buf, buf)) { if( OK != ErrorLogger( ERR_PARSE, LOC, NULL)) { return( ERR_PARSE); /** ------ EXIT (PARSE ERROR) -----> **/ } } else { /** ** Valid entry found. Set up buf pointing behind the pattern ** that has matched and put a terminator at the end of either the ** ressource name and its value. **/ char *startp, *endp; Tcl_RegExpRange(res_exp, 0, &startp, &endp); buf = endp + 1; Tcl_RegExpRange(res_exp, 1, &startp, &endp); *endp = '\0'; Tcl_RegExpRange(res_exp, 2, &startp, &endp); *endp = '\0'; /** ** Now create (or remove) a hash entry for the parsed ressource **/ if( remove) { Tcl_RegExpRange(res_exp, 1, &startp, &endp); if( entry = Tcl_FindHashEntry( data, startp)) { free( Tcl_GetHashValue( entry)); Tcl_DeleteHashEntry( entry); } } else { Tcl_RegExpRange(res_exp, 1, &startp, &endp); entry = Tcl_CreateHashEntry( data, startp, &new_res); if( !new_res) free( Tcl_GetHashValue( entry)); Tcl_RegExpRange(res_exp, 2, &startp, &endp); Tcl_SetHashValue( entry, strdup( startp)); } } /** if( reg exp matched) **/ } /** while **/ /** ** Return on success **/ return( NO_ERR); } /** end of 'getEntries' **/ /*++++ ** ** Function-Header ***************************************************** ** ** ** ** Function: storeResProp ** ** ** ** Description: Update the X11 resource property, adding new resour- ** ** ces. ** ** ** ** First Edition: 91/10/23 ** ** ** ** Parameters: register ResourceDB *rdb Ressource database ** ** ** ** Result: - ** ** ** ** Attached Globals: - ** ** ** ** ************************************************************************ ** ++++*/ #ifdef HAS_X11LIBS static void storeResProp( register ResourceDB *rdb) { Tcl_HashSearch search; register int mode = PropModeReplace; register int max = (XMaxRequestSize( dpy) << 2) - 28; register int left; register Tcl_HashEntry *entry = Tcl_FirstHashEntry( rdb->data, &search); unsigned char *buf; #if WITH_DEBUGGING_UTIL_1 ErrorLogger( NO_ERR_START, LOC, _proc_storeResProp, NULL); #endif /** ** Write all attached ressources into the buffer. Follow the X ** ressource syntax: ** ** : **/ Tcl_DStringTrunc( buffer, 0); while( entry) { Tcl_DStringAppend( buffer, Tcl_GetHashKey(rdb->data, entry), -1); Tcl_DStringAppend( buffer, ":\t", 2); Tcl_DStringAppend( buffer, (char *)Tcl_GetHashValue( entry), -1); Tcl_DStringAppend( buffer, "\n", 1); entry = Tcl_NextHashEntry( &search); } /** ** In case of the request being larger than the largest request the X ** server may handle, spool it block by block until the final one. **/ buf = (unsigned char *) Tcl_DStringValue( buffer); if( max < (left = Tcl_DStringLength( buffer))) { XGrabServer( dpy); mode = PropModeAppend; do { XChangeProperty( dpy, rdb->root, rdb->prop, XA_STRING, 8, mode, buf, max); buf += max; } while( max < (left -= max)); } /** ** Put the final request block (which may be the only one, if the if- ** statement above doesn't match) to the X server **/ XChangeProperty( dpy, rdb->root, rdb->prop, XA_STRING, 8, mode, buf, left); if( mode != PropModeReplace) XUngrabServer( dpy); } /** End of 'storeResProp' **/ #endif /*++++ ** ** Function-Header ***************************************************** ** ** ** ** Function: getOld ** ** ** ** Description: First, we have to find the resources already loaded ** ** into the X11 resource property. This routine current-** ** ly only handles one screen, the default screen for ** ** the DISPLAY. This routine should only be called if ** ** resDB.data is NULL. ** ** ** ** First Edition: 91/10/23 ** ** ** ** Parameters: register char **buf Buffer for the old ressource ** ** database ** ** ** ** Result: ErrType ERR_PARAM resDB.data != NULL ** ** ERR_ALLOC out of memory ** ** NO_ERR Success ** ** ** ** Attached Globals: resDB The data area will be installed as a ** ** Tcl hash table ** ** dpy The current display ** ** ** ** ************************************************************************ ** ++++*/ static ErrType getOld( register char **buf) { #if WITH_DEBUGGING_UTIL_1 ErrorLogger( NO_ERR_START, LOC, _proc_getOld, NULL); #endif /** ** Allocate memory for the hash table **/ if( resDB.data) if( OK != ErrorLogger( ERR_PARAM, LOC, "Ressource database", NULL)) return( ERR_PARAM); /** ------- EXIT (PARAMETER) -----> **/ if( !(resDB.data = (Tcl_HashTable *) malloc( sizeof( Tcl_HashTable)))) if( OK != ErrorLogger( ERR_ALLOC, LOC, NULL)) return( ERR_ALLOC); /** ----- EXIT (OUT OF MEMORY) ----> **/ /** ** Initialize the hash table and read in the old ressources **/ Tcl_InitHashTable( resDB.data, TCL_STRING_KEYS); resDB.root = RootWindow( dpy, 0); resDB.prop = XA_RESOURCE_MANAGER; *buf = XResourceManagerString( dpy); /** ** Success **/ return( NO_ERR); } /** End of 'getOld' **/ /*++++ ** ** Function-Header ***************************************************** ** ** ** ** Function: initBuffers ** ** ** ** Description: Initilize buffers if not already done, or reinitia- ** ** lize some variables if buffers already exists. ** ** ** ** First Edition: 91/10/23 ** ** ** ** Parameters: Tcl_Interp *interp According Tcl interp.** ** register int is_file Differs between a single X ** ** ressource to be modified or ** ** a ressource file to be merged** ** ** ** Result: ErrType ERR_DISPLAY Cannot open DISPLAY ** ** ERR_ALLOC ALLOC failure ** ** ERR_EXTRACT ** ** NO_ERR Success ** ** ** ** Attached Globals: dpy Display will be openend ** ** resDB Ressource database will be filled up ** ** with the current setup ** ** defines ** ** ** ** ************************************************************************ ** ++++*/ static ErrType initBuffers( Tcl_Interp *interp, register int is_file) { char *tmpbuf; #if WITH_DEBUGGING_UTIL_1 ErrorLogger( NO_ERR_START, LOC, _proc_initBuffers, NULL); #endif /** ** Open the display **/ if( !dpy && !(dpy = XOpenDisplay( NULL))) if( OK != ErrorLogger( ERR_DISPLAY, LOC, NULL)) return( ERR_DISPLAY); /** -------- EXIT (FAILURE) -------> **/ /** ** Read in the old setup at first and put it into the ressource database **/ if( !resDB.data) { if( getOld( &tmpbuf) != NO_ERR) /** NULL if no resources exists **/ if( OK != ErrorLogger( ERR_ALLOC, LOC, NULL)) return( ERR_ALLOC); /** ----- EXIT (OUT OF MEMORY) ----> **/ if( tmpbuf && (getEntries(interp, resDB.data, tmpbuf, 0) != NO_ERR)) if( OK != ErrorLogger( ERR_EXTRACT, LOC, NULL)) return( ERR_EXTRACT); } /** ** Conditionally allocate a buffer and initialize this guy **/ if( !buffer) { if( !(buffer = (Tcl_DString *) malloc( sizeof( Tcl_DString)))) { if( OK != ErrorLogger( ERR_ALLOC, LOC, NULL)) return( ERR_ALLOC); /** ----- EXIT (OUT OF MEMORY) ----> **/ } else Tcl_DStringInit( buffer); } else Tcl_DStringTrunc( buffer, 0); /** ** Set up all the defines according display and screen **/ if( defines) defines[ def_base] = '\0'; else if( is_file) { if( !(defines = (char *) malloc( BUFSIZ * sizeof( char)))) if( OK != ErrorLogger( ERR_ALLOC, LOC, NULL)) return( ERR_ALLOC); /** ----- EXIT (OUT OF MEMORY) ----> **/ /* sprintf( defines, "%s %s ", CPPSTDIN, CPPMINUS); */ strcpy( defines, CPPSTDIN); strcat( defines, " "); strcat( defines, CPPMINUS); strcat( defines, " "); doDisplayDefines(); doScreenDefines( DefaultScreen( dpy)); def_base = strlen( strcat( defines, " ")); } /** ** Return on success **/ return( NO_ERR); } /** End of 'initBuffers' **/ #endif /*++++ ** ** Function-Header ***************************************************** ** ** ** ** Function: xresourceFinish ** ** ** ** Description: Update the resource property if everything is ok. ** ** This routine should be called when all properies have** ** been defines or updated. Remember that this routine ** ** always will be called, even if there was no ** ** "x-resource" command in the module! ** ** ** ** First Edition: 91/10/23 ** ** ** ** Parameters: ** ** ** ** Result: ** ** ** ** Attached Globals: - ** ** ** ** ************************************************************************ ** ++++*/ void xresourceFinish(register int no_errors) { #if WITH_DEBUGGING_UTIL_1 ErrorLogger( NO_ERR_START, LOC, _proc_xresourceFinish, NULL); #endif #ifdef HAS_X11LIBS /** ** If there is data stored in the ressource database, spool it to the ** according X server **/ if( resDB.data && no_errors) storeResProp( &resDB); /** ** Close the display and free what has been used **/ if( dpy) XCloseDisplay( dpy); if( buffer) Tcl_DStringFree( buffer); #endif } /** End of 'xresourceFinish' **/ /*++++ ** ** Function-Header ***************************************************** ** ** ** ** Function: cmdXResource ** ** ** ** Description: Callback function for 'x-ressource'. The function ** ** sets up a hash table containing all ressources to be ** ** passed to the X server. This hash table will be ** ** flushed whenever the function xresourceFinish is cal-** ** led. ** ** ** ** First Edition: 91/10/23 ** ** ** ** Parameters: ClientData client_data ** ** Tcl_Interp *interp According Tcl interp.** ** int argc Number of arguments ** ** char *argv[] Argument array ** ** ** ** Result: int TCL_OK Successfull completion ** ** TCL_ERROR Any error ** ** ** ** Attached Globals: g_flags These are set up accordingly before ** ** this function is called in order to ** ** control everything ** ** ** ** ************************************************************************ ** ++++*/ int cmdXResource( ClientData client_data, Tcl_Interp *interp, int argc, char *argv[]) { register FILE *inp; int is_file, i, do_cpp = 1, opt_ind = 1; #if WITH_DEBUGGING_CALLBACK ErrorLogger( NO_ERR_START, LOC, _proc_cmdXResource, NULL); #endif /** ** Whatis mode? **/ if( g_flags & (M_WHATIS | M_HELP)) return( TCL_OK); /** ------- EXIT PROCEDURE -------> **/ /** ** Parameter check **/ if( argc > 1 && !strcmp( argv[1], "-nocpp")) { do_cpp = 0; opt_ind++; } if( argc <= opt_ind) { if( OK != ErrorLogger( ERR_USAGE, LOC, argv[0], "[ -nocpp ] strings", NULL)) return( TCL_ERROR); /** -------- EXIT (FAILURE) -------> **/ } /** ** Ok, now let's treat all remaining arguments as X ressources or ** X ressource files. At first let's check if it is a file ... **/ while( opt_ind < argc) { is_file = (access( argv[ opt_ind], R_OK & F_OK) == 0); #ifdef HAS_X11LIBS if( g_flags & M_DISPLAY) { fprintf( stderr, "xrdb -merge\t "); for( i=1; i **/ /** ** This puts all required ressources into a text image buffer ... **/ if( !is_file) { Tcl_DStringAppend( buffer, argv[ opt_ind], -1); } else { if( NULL == (inp = (do_cpp ? popen( strcat( defines, argv[ opt_ind]), "r") : fopen( argv[ opt_ind], "r")) ) ) if( OK != ErrorLogger( (do_cpp ? ERR_POPEN : ERR_OPEN), LOC, "argv[ opt_ind]", "reading" )) return( TCL_ERROR); /** ---- EXIT (FAILURE) ---> **/ if( TCL_ERROR == readFile( inp, do_cpp)) return( TCL_ERROR); /** -------- EXIT (FAILURE) -------> **/ } /** ** ... and this transforms the text image buffer into a Tcl hash ** table **/ if( NO_ERR != getEntries(interp, resDB.data, Tcl_DStringValue( buffer), g_flags & M_REMOVE)) { return( TCL_ERROR); /** -------- EXIT (FAILURE) -------> **/ } } #else if( g_flags & M_DISPLAY) { fprintf( stderr, "xrdb -merge\t "); for( i=1; i