Beispiel #1
0
VImage VSelectDestImage (VStringConst routine, VImage dest,
			 int nbands, int nrows, int ncolumns,
			 VRepnKind pixel_repn)
{
  /* If no destination image was specified, allocate one: */
  if (! dest)
    return VCreateImage (nbands, nrows, ncolumns, pixel_repn);

    /* Otherwise check that the destination provided has the appropriate
       characteristics: */
  if (VImageNBands (dest) != nbands) {
    VWarning ("%s: Destination image has %d bands; %d expected",
	      routine, VImageNBands (dest), nbands);
    return NULL;
  }
  if (VImageNRows (dest) != nrows) {
    VWarning ("%s: Destination image has %d rows; %d expected",
	      routine, VImageNRows (dest), nrows);
    return NULL;
  }
  if (VImageNColumns (dest) != ncolumns) {
    VWarning ("%s: Destination image has %d columns; %d expected",
	      routine, VImageNColumns (dest), ncolumns);
    return NULL;
  }
  if (VPixelRepn (dest) != pixel_repn) {
    VWarning ("%s: Destination image has %s pixels; %s expected", routine, 
	      VPixelRepnName (dest), VRepnName (pixel_repn));
    return NULL;
  }
  return dest;
}
Beispiel #2
0
VBoolean VWriteObjects (FILE *file, VRepnKind repn, VAttrList attributes,
			int nobjects, VPointer objects[])
{
    VAttrList list;
    VAttrListPosn posn;
    int i;
    VBoolean result;

    /* Create an attribute list if none was supplied: */
    list = attributes ? attributes : VCreateAttrList ();

    /* Prepend to the attribute list an attribute for each object: */
    for (i = nobjects - 1; i >= 0; i--)
	VPrependAttr (list, VRepnName (repn), NULL, repn, objects[i]);

    /* Write the attribute list: */
    result = VWriteFile (file, list);

    /* Remove the attributes just prepended: */
    VFirstAttr (list, & posn);
    for (i = 0; i < nobjects; i++)
	VDeleteAttr (& posn);
    if (list != attributes)
	VDestroyAttrList (list);

    return result;
}
Beispiel #3
0
VBoolean VUnpackData (VRepnKind repn,
		      size_t nels, VPointer packed, VPackOrder packed_order,
		      size_t *length, VPointer *unpacked, VBoolean *alloced)
{
    VPackOrder unpacked_order;
    size_t unpacked_elsize = VRepnSize (repn) * CHAR_BIT;
    size_t packed_elsize = VRepnPrecision (repn);
    size_t unpacked_length = nels * VRepnSize (repn);

    /* If a space for the unpacked data was supplied, ensure there's
       enough of it: */
    if (! alloced && unpacked_length > *length) {
	VWarning ("VUnpackData: Insufficient space for unpacked data");
	return FALSE;
    }
    *length = unpacked_length;

    /* Determine the present machine's internal byte order: */
    unpacked_order = MachineByteOrder ();

    /* If the desired byte order matches that of the present machine's, and
       the unpacked and packed data element sizes are identical,
       just return the packed data: */
    if (unpacked_order == packed_order && unpacked_elsize == packed_elsize) {
	if (alloced) {
	    *unpacked = packed;
	    *alloced = FALSE;
	} else if (packed != *unpacked)
	    memcpy (*unpacked, packed, unpacked_length);
	return TRUE;
    }

    /* Unpack data elements into the buffer: */
    if (packed_elsize == unpacked_elsize) {

	/* If the packed and unpacked are the same size, do a straight copy: */
	if (packed != *unpacked)
	    memcpy (*unpacked, packed, unpacked_length);

	/* Swap bytes if necessary: */
	if (packed_order != unpacked_order && packed_elsize > 8)
	    SwapBytes (nels, packed_elsize / 8, (char *) *unpacked);

    } else if (packed_elsize == 1) {

	/* If the elements are VBits, this unpacks them: */
	VUnpackBits (nels, packed_order, (char *) packed, (char *) *unpacked);

    } else 
    
	/* Unpacking multi-byte integers or floats is currently not
	   supported: */
	VError ("VUnpackData: "
		"Unpacking %s from %d to %d bits is not supported",
		VRepnName (repn), packed_elsize, unpacked_elsize);

    return TRUE;
}
Beispiel #4
0
int VReadObjects (FILE *file, VRepnKind repn, VAttrList *attributes,
		  VPointer **objects)
{
    VAttrList list;
    VAttrListPosn posn;
    int i, nobjects = 0;
    VPointer *vector;

    /* Read the file's contents: */
    list = VReadFile (file, NULL);
    if (! list)
	return FALSE;

    /* Count the objects found: */
    for (VFirstAttr (list, & posn); VAttrExists (& posn); VNextAttr (& posn))
	nobjects += (VGetAttrRepn (& posn) == repn);
    if (nobjects == 0) {
	VWarning ("VReadObjects: No %s objects present in stream",
		  VRepnName (repn));
	VDestroyAttrList (list);
	return FALSE;
    }

    /* Allocate a vector of that many object pointers: */
    vector = VMalloc (nobjects * sizeof (VPointer));

    /* Extract the objects from the attribute list and place them in the
       vector: */
    for (VFirstAttr (list, & posn), i = 0; VAttrExists (& posn); )
	if (VGetAttrRepn (& posn) == repn) {
	    VGetAttrValue (& posn, NULL, repn, vector + i);
	    VDeleteAttr (& posn);
	    i++;
	} else VNextAttr (& posn);

    /* Return the objects and the remaining attributes: */
    *attributes = list;
    *objects = vector;
    return nobjects;
}
Beispiel #5
0
/* Parse command without license information */
VBoolean VParseCommand_nl (int noptions, VOptionDescRec options[],
			int *argc, char **argv)
{
  int arg, nvalues, i, j;
  char *cp;
  VBoolean *opts_seen, result = TRUE;
  VOptionDescRec *opt, *opt_t;

  /* Note the program's name: */
  VSetProgramName (argv[0]);

  /* Allocate storage for a set of flags indicating which
     arguments have been seen: */
  opts_seen = VCalloc (noptions, sizeof (VBoolean));

  /* Initialize any "found" flags to false, and the number field of any
     VArgVector values to zero: */
  for (opt = options + noptions - 1; opt >= options; opt--) {
    if (opt->found)
      *opt->found = FALSE;
    if (opt->number == 0 && opt->value)
      ((VArgVector *) opt->value)->number = 0;
  }

  /* For each argument supplied with the command: */
  for (arg = 1; arg < *argc; ) {
    cp = argv[arg++];

    /* If it doesn't start with - it can't be an option: */
    if (cp[0] != '-' || cp[1] == 0)
      continue;

    /* Check for -help: */
    if (strcmp (cp + 1, "help") == 0) {

      /* If found, return FALSE to force printing of usage info: */
      *argc = 1;
      return FALSE;
    }

    /* Look up the argument in the list of options: */
    i = strlen (cp + 1);
    opt = NULL;
    for (opt_t = options + noptions - 1; opt_t >= options; opt_t--) {
      if (strncmp (cp + 1, opt_t->keyword, i) != 0)
	continue;	/* not this one */
      if (i == strlen (opt_t->keyword)) {
	opt = opt_t;
	break;		/* an exact match */
      }
      if (opt)
	goto NextArg;	/* already matched another prefix */
      opt = opt_t;	/* note a prefix match */
    }

    /* If the argument isn't recognized, skip it: */
    if (! opt)
      goto NextArg;	/* not recognized */

    /* Remove it from the list of command arguments: */
    argv[arg - 1] = 0;

    /* Ensure that the option has not already been seen: */
    if (opts_seen[opt - options]) {
      fprintf (stderr,
	       "%s: Duplicate -%s option; ignoring all but last.\n",
	       argv[0], opt->keyword);

      /* If it has been seen, delete its previous value: */
      if (opt->number == 0) {
	VFree (((VArgVector *) opt->value)->vector);
	((VArgVector *) opt->value)->number = 0;
      }
    } else opts_seen[opt - options] = TRUE;

    /* Swallow any value(s) that follow: */
    switch (opt->repn) {

    case VBitRepn:
    case VUByteRepn:
    case VSByteRepn:
    case VShortRepn:
    case VLongRepn:
    case VFloatRepn:
    case VDoubleRepn:
    case VBooleanRepn:
    case VStringRepn:
      nvalues = ParseArgValues (& arg, *argc, argv, opt);
      break;

    default:
      VError ("Parsing of command options with %s values "
	      "is not implemented", VRepnName (opt->repn));
      nvalues = 0;	/* to quiet lint */
    }

    /* Ensure that the expected number of arguments was found: */
    if (opt->number && nvalues != opt->number) {

      /* Either we encountered an argument we couldn't parse, or
	 we used up all arguments before finding the expected number
	 of them: */
      fprintf (stderr, "%s: Option -%s ", argv[0], opt->keyword);
      if (arg < *argc)
	fprintf (stderr, "has incorrect value %s.\n", argv[arg]);
      else if (opt->number > 1)
	fprintf (stderr, "requires %d values; found only %d.\n",
		 opt->number, nvalues);
      else fprintf (stderr, "requires a value.\n");
      result = FALSE;
      break;
    }
    if (opt->number == 0)
      ((VArgVector *) opt->value)->number = nvalues;

    /* Note that a value was successfully obtained for this option: */
    if (opt->found)
      *(opt->found) = TRUE;

  NextArg: ;
  }

  /* Ensure that each mandatory option was seen: */
  for (i = 0; i < noptions; i++)
    if (options[i].found == VRequiredOpt && ! opts_seen[i]) {
      fprintf (stderr, "%s: Option -%s must be specified.\n",
	       argv[0], options[i].keyword);
      result = FALSE;
    }
  VFree ((VPointer) opts_seen);

  /* Squeeze together the remaining arguments in argv: */
  for (i = j = 1; i < *argc; i++)
    if (argv[i])
      argv[j++] = argv[i];
  *argc = j;

  return result;
}
Beispiel #6
0
VBoolean VParseCommand (int noptions, VOptionDescRec options[],
			int *argc, char **argv)
{
  int arg, nvalues, i, j;
  char *cp;
  VBoolean *opts_seen, result = TRUE;
  VOptionDescRec *opt, *opt_t;

  /* Note the program's name: */
  VSetProgramName (argv[0]);

  /* Allocate storage for a set of flags indicating which
     arguments have been seen: */
  opts_seen = VCalloc (noptions, sizeof (VBoolean));

  /* Initialize any "found" flags to false, and the number field of any
     VArgVector values to zero: */
  for (opt = options + noptions - 1; opt >= options; opt--) {
    if (opt->found)
      *opt->found = FALSE;
    if (opt->number == 0 && opt->value)
      ((VArgVector *) opt->value)->number = 0;
  }

 /* For each argument supplied with the command: */
  for (arg = 1; arg < *argc; ) {
    cp = argv[arg++];

    /* If it doesn't start with - it can't be an option: */
    if (cp[0] != '-' || cp[1] == 0)
      continue;

   /* Check for -help: */
    if (strcmp (cp + 1, "license") == 0) {

    char* license="This program is free software; you can redistribute it and/or\n modify it under the terms of the GNU General Public License\n as published by the Free Software Foundation; either version 2\n of the License, or (at your option) any later version.\n This program is distributed in the hope that it will be useful,\n but WITHOUT ANY WARRANTY; without even the implied warranty of\n MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n GNU General Public License for more details.\n\n You should have received a copy of the GNU General Public License\n along with this program; if not, write to the Free Software\n Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.\n";


    fprintf(stderr,"%s\n",license);
    exit(0);
    }
  }


  /* For each argument supplied with the command: */
  for (arg = 1; arg < *argc; ) {
    cp = argv[arg++];

    /* If it doesn't start with - it can't be an option: */
    if (cp[0] != '-' || cp[1] == 0)
      continue;

    /* Check for -help: */
    if (strcmp (cp + 1, "help") == 0) {

      /* If found, return FALSE to force printing of usage info: */
      *argc = 1;
      return FALSE;
    }

    /* Look up the argument in the list of options: */
    i = strlen (cp + 1);
    opt = NULL;
    for (opt_t = options + noptions - 1; opt_t >= options; opt_t--) {
      if (strncmp (cp + 1, opt_t->keyword, i) != 0)
	continue;	/* not this one */
      if (i == strlen (opt_t->keyword)) {
	opt = opt_t;
	break;		/* an exact match */
      }
      if (opt)
	goto NextArg;	/* already matched another prefix */
      opt = opt_t;	/* note a prefix match */
    }

    /* If the argument isn't recognized, skip it: */
    if (! opt)
      goto NextArg;	/* not recognized */

    /* Remove it from the list of command arguments: */
    argv[arg - 1] = 0;

    /* Ensure that the option has not already been seen: */
    if (opts_seen[opt - options]) {
      fprintf (stderr,
	       "%s: Duplicate -%s option; ignoring all but last.\n",
	       argv[0], opt->keyword);

      /* If it has been seen, delete its previous value: */
      if (opt->number == 0) {
	VFree (((VArgVector *) opt->value)->vector);
	((VArgVector *) opt->value)->number = 0;
      }
    } else opts_seen[opt - options] = TRUE;

    /* Swallow any value(s) that follow: */
    switch (opt->repn) {

    case VBitRepn:
    case VUByteRepn:
    case VSByteRepn:
    case VShortRepn:
    case VLongRepn:
    case VFloatRepn:
    case VDoubleRepn:
    case VBooleanRepn:
    case VStringRepn:
      nvalues = ParseArgValues (& arg, *argc, argv, opt);
      break;

    default:
      VError ("Parsing of command options with %s values "
	      "is not implemented", VRepnName (opt->repn));
      nvalues = 0;	/* to quiet lint */
    }

    /* Ensure that the expected number of arguments was found: */
    if (opt->number && nvalues != opt->number) {

      /* Either we encountered an argument we couldn't parse, or
	 we used up all arguments before finding the expected number
	 of them: */
      fprintf (stderr, "%s: Option -%s ", argv[0], opt->keyword);
      if (arg < *argc)
	fprintf (stderr, "has incorrect value %s.\n", argv[arg]);
      else if (opt->number > 1)
	fprintf (stderr, "requires %d values; found only %d.\n",
		 opt->number, nvalues);
      else fprintf (stderr, "requires a value.\n");
      result = FALSE;
      break;
    }
    if (opt->number == 0)
      ((VArgVector *) opt->value)->number = nvalues;

    /* Note that a value was successfully obtained for this option: */
    if (opt->found)
      *(opt->found) = TRUE;

  NextArg: ;
  }

  /* Ensure that each mandatory option was seen: */
  for (i = 0; i < noptions; i++)
    if (options[i].found == VRequiredOpt && ! opts_seen[i]) {
      fprintf (stderr, "%s: Option -%s must be specified.\n",
	       argv[0], options[i].keyword);
      result = FALSE;
    }
  VFree ((VPointer) opts_seen);

  /* Squeeze together the remaining arguments in argv: */
  for (i = j = 1; i < *argc; i++)
    if (argv[i])
      argv[j++] = argv[i];
  *argc = j;

  return result;
}
Beispiel #7
0
static VBoolean WriteAttr (FILE *f, VAttrListPosn *posn, int indent, VList *data_list, long *offset)
{
    int i;
    char *str;
    VRepnKind repn;
    VAttrList sublist;
    VBundle b;
    DataBlock *db;
    VTypeMethods *methods;
    size_t length;
    VPointer value;
    VBoolean result;
    VAttrListPosn subposn;

    /* Indent by the specified amount: */
    for (i = 0; i < indent; i++)
	FailTest (fputc ('\t', f));
    indent++;

    /* Output the attribute's name: */
    FailTest (fprintf (f, "%s: ", VGetAttrName (posn)));

    /* Ouput its value: */
    switch (repn = VGetAttrRepn (posn)) {

    case VAttrListRepn:
	VGetAttrValue (posn, NULL, VAttrListRepn, (VPointer) & sublist);
	result = WriteAttrList (f, sublist, indent, data_list, offset);
	break;

    case VBundleRepn:
	VGetAttrValue (posn, NULL, VBundleRepn, (VBundle) & b);
	if (! WriteString (f, b->type_name))
	    return FALSE;
	FailTest (fputc (' ', f));

	/* If it's a typed value with binary data... */
	if (b->length > 0) {

	    /* Include "data" and "length" attributes in its attribute list: */
	    VPrependAttr (b->list, VLengthAttr, NULL, VLongRepn,
			  (VLong) b->length);
	    VPrependAttr (b->list, VDataAttr, NULL, VLongRepn,
			  (VLong) *offset);

	    /* Add it to the queue of binary data blocks to be written: */
	    *offset += b->length;
	    db = VNew (DataBlock);
	    db->posn = *posn;
	    db->list = b->list;
	    db->length = b->length;
	    VListAppend (*data_list, db);
	}

	/* Write the typed value's attribute list: */
	result = WriteAttrList (f, b->list, indent, data_list, offset);

	/* Remove the "data" and "length" attributes added earlier: */
	if (b->length > 0) {
	    VFirstAttr (b->list, & subposn);
	    VDeleteAttr (& subposn);
	    VDeleteAttr (& subposn);
	}
	break;

    case VStringRepn:
	VGetAttrValue (posn, NULL, VStringRepn, (VPointer) & str);
	result = WriteString (f, str);
	break;

    default:
	if (! (methods = VRepnMethods (repn)) ||
	    ! methods->encode_attr || ! methods->encode_data) {
	    VWarning ("VWriteFile: "
		      "%s attribute has unwriteable representation: %s",
		      VGetAttrName (posn), VRepnName (repn));
	    return FALSE;
	}

	/* Write the type name: */
	if (! WriteString (f, VRepnName (repn)))
	    return FALSE;
	FailTest (fputc (' ', f));

	/* Invoke the object type's encode_attr method to obtain an
	   attribute list: */
	VGetAttrValue (posn, NULL, repn, & value);
	sublist = (methods->encode_attr) (value, & length);

	/* If binary data is indicated... */
	if (length > 0) {

	    /* Include "data" and "length" attributes in the attr list: */
	    VPrependAttr (sublist, VLengthAttr, NULL, VLongRepn,
			  (VLong) length);
	    VPrependAttr (sublist, VDataAttr, NULL, VLongRepn,
			  (VLong) *offset);

	    *offset += length;
	}

	/* Add the object to the queue of binary data blocks to be written: */
	db = VNew (DataBlock);
	db->posn = *posn;
	db->list = sublist;
	db->length = length;
	VListAppend (*data_list, db);

	/* Write the typed value's attribute list: */
	result = WriteAttrList (f, sublist, indent, data_list, offset);

	/* Remove the "data" and "length" attributes added earlier: */
	if (length > 0) {
	    VFirstAttr (sublist, & subposn);
	    VDeleteAttr (& subposn);
	    VDeleteAttr (& subposn);
	}
    }

    /* Output a trailing newline: */
    if (result)
	FailTest (fputc ('\n', f));
    return result;

Fail:
    VWarning ("VWriteFile: Write to stream failed");
    return FALSE;
}
Beispiel #8
0
static VStringConst Encode (VDictEntry *dict, VRepnKind repn, va_list *args)
{
    VLong i_value = 0;
    VDouble f_value = 0.0;
    VString s_value = NULL;
    static char buf[40];

    /* Fetch the attribute value: */
    switch (repn) {
    case VBitRepn: i_value = va_arg (*args, VBitPromoted); break;
    case VUByteRepn: i_value = va_arg (*args, VUBytePromoted); break;
    case VSByteRepn: i_value = va_arg (*args, VSBytePromoted); break;
    case VShortRepn: i_value = va_arg (*args, VShortPromoted); break;
    case VLongRepn: i_value = va_arg (*args, VLongPromoted); break;
    case VFloatRepn: f_value = va_arg (*args, VFloatPromoted); break;
    case VDoubleRepn: f_value = va_arg (*args, VDoublePromoted); break;
    case VBooleanRepn: i_value = va_arg (*args, VBooleanPromoted); break;
    case VStringRepn: s_value = va_arg (*args, VString); break;

    default:
	VError ("VEncodeAttrValue: Can't encode from %s", VRepnName (repn));
    }

    /* If its numeric, convert it to a string: */
    switch (repn) {

    case VBitRepn:
    case VUByteRepn:
    case VSByteRepn:
    case VShortRepn:
    case VLongRepn:
    case VBooleanRepn:
	sprintf (s_value = buf, "%ld", (long) i_value);
	break;

    case VFloatRepn:
    case VDoubleRepn:
	sprintf (s_value = buf, "%.20g", (double) f_value);
	break;

    default:
	break;
    }

    /* If a dictionary was supplied, try to map the encoded value to
       a keyword: */
    if (dict)
	switch (repn) {

	case VBitRepn:
	case VUByteRepn:
	case VSByteRepn:
	case VShortRepn:
	case VLongRepn:
	case VBooleanRepn:
	    dict = VLookupDictValue (dict, VLongRepn, i_value);
	    break;

	case VFloatRepn:
	case VDoubleRepn:
	    dict = VLookupDictValue (dict, VDoubleRepn, f_value);
	    break;

	case VStringRepn:
	    dict = VLookupDictValue (dict, VStringRepn, s_value);
	    break;

	default:
	    break;
	}
    return dict ? dict->keyword : s_value;
}
Beispiel #9
0
VBoolean VDecodeAttrValue (VStringConst str, VDictEntry *dict,
			   VRepnKind repn, VPointer value)
{
    VLong i_value = 0;
    VDouble f_value = 0.0;
    char *cp = NULL, buf[20];

    /* If a dict is provided, see if str maps to any dict entry keyword,
       substituting the associated value if found: */
    if (dict) {
	dict = VLookupDictKeyword (dict, str);

	/* If there's a dictionary entry, complete it: */
	if (dict && ! dict->svalue) {
	    str = NULL;
	    dict->icached = dict->fcached = TRUE;
	    sprintf (buf, "%ld", (long) dict->ivalue);
	    dict->svalue = VNewString (buf);
	    dict->fvalue = dict->ivalue;
	}
    }

    /* Convert to the internal representation: */
    switch (repn) {

    case VBitRepn:
    case VUByteRepn:
    case VSByteRepn:
    case VShortRepn:
    case VLongRepn:
    case VBooleanRepn:
	if (dict) {
	    if (dict->icached)
		i_value = dict->ivalue;
	    else {
		dict->ivalue = i_value = strtol (dict->svalue, & cp, 0);
		dict->icached = TRUE;
	    }
	} else i_value = strtol (str, & cp, 0);
	break;

    case VFloatRepn:
    case VDoubleRepn:
	if (dict) {
	    if (dict->fcached)
		f_value = dict->fvalue;
	    else {
		dict->fvalue = f_value = strtod (dict->svalue, & cp);
		dict->fcached = TRUE;
	    }
	} else f_value = strtod (str, & cp);
	break;

    case VStringRepn:
	if (dict)
	    str = dict->svalue;
	break;

    default:
	VError ("VDecodeAttrValue: Can't decode to %s", VRepnName (repn));
    }
    if (cp && *cp)
	return FALSE;

    /* Store at *value: */
    switch (repn) {
    case VBitRepn: * (VBit *) value = i_value; break;
    case VUByteRepn: * (VUByte *) value = i_value; break;
    case VSByteRepn: * (VSByte *) value = i_value; break;
    case VShortRepn: * (VShort *) value = i_value; break;
    case VLongRepn: * (VLong *) value = i_value; break;
    case VFloatRepn: * (VFloat *) value = f_value; break;
    case VDoubleRepn: * (VDouble *) value = f_value; break;
    case VBooleanRepn: * (VBoolean *) value = i_value; break;
    case VStringRepn: * (VStringConst *) value = str; break;

    default:
	break;
    }

    return TRUE;
}
Beispiel #10
0
VDictEntry *VLookupDictValue (VDictEntry *dict, VRepnKind repn, ...)
{
    va_list args;
    VLong i_value = 0;
    VDouble f_value = 0.0;
    VString s_value = NULL;
    VBoolean i_valid;

    /* Unravel the arguments passed: */
    if (! dict)
        return NULL;
    va_start (args, repn);
    switch (repn) {
    case VBitRepn:
        i_value = va_arg (args, VBitPromoted);
        break;
    case VUByteRepn:
        i_value = va_arg (args, VUBytePromoted);
        break;
    case VSByteRepn:
        i_value = va_arg (args, VSBytePromoted);
        break;
    case VShortRepn:
        i_value = va_arg (args, VShortPromoted);
        break;
    case VLongRepn:
        i_value = va_arg (args, VLongPromoted);
        break;
    case VFloatRepn:
        f_value = va_arg (args, VFloatPromoted);
        break;
    case VDoubleRepn:
        f_value = va_arg (args, VDoublePromoted);
        break;
    case VBooleanRepn:
        i_value = va_arg (args, VBooleanPromoted);
        break;
    case VStringRepn:
        s_value = va_arg (args, VString);
        break;
    default:
        VError ("VLookupDictValue: Can't lookup %s value", VRepnName (repn));
    }
    va_end (args);

    /* Search the dictionary by value: */
    switch (repn) {

    case VBitRepn:
    case VUByteRepn:
    case VSByteRepn:
    case VShortRepn:
    case VLongRepn:
    case VBooleanRepn:
        for ( ; dict->keyword; dict++) {

            /* Is the entry's value only stored as a string? */
            if (dict->svalue && ! dict->icached) {

                /* Yes -- try to convert the string to an integer, and
                   cache that value: */
                if (! VDecodeAttrValue (dict->svalue, NULL,
                                        VLongRepn, & dict->ivalue))
                    break;
                dict->icached = TRUE;
            }

            /* Test against the integer value stored in the entry: */
            if (i_value == dict->ivalue)
                return dict;
        }
        break;

    case VFloatRepn:
    case VDoubleRepn:
        for ( ; dict->keyword; dict++) {

            /* Does the entry include a cached floating point value? */
            if (! dict->fcached) {

                /* No -- obtain it from an integer or string value: */
                if (dict->svalue) {
                    if (! VDecodeAttrValue (dict->svalue, NULL,
                                            VDoubleRepn, & dict->fvalue))
                        break;
                } else dict->fvalue = dict->ivalue;
                dict->fcached = TRUE;
            }

            /* Test against the cached float value now stored in the entry: */
            if (f_value == dict->fvalue)
                return dict;
        }
        break;

    case VStringRepn:

        /* In case we're searching a dictionary with only integer values
           stored, try to convert the supplied string value to an integer: */
        i_valid = VDecodeAttrValue (s_value, NULL, VLongRepn, & i_value);

        for ( ; dict->keyword; dict++) {

            /* If the entry includes a string value, compare with it: */
            if (dict->svalue) {
                if (strcmp (s_value, dict->svalue) == 0)
                    return dict;
            }

            /* Otherwise, compare with its integer value: */
            else if (i_valid && i_value == dict->ivalue)
                return dict;
        }
        break;

    default:
        break;
    }
    return NULL;
}