Switch the license of all .c files to GPLv3.
[deliverable/binutils-gdb.git] / gdb / value.c
index 939275365288bc68a2c12abf1562adf255883da3..8435404d687b9227e292a5c6036028e607695cfa 100644 (file)
@@ -1,14 +1,14 @@
 /* Low level packing and unpacking of values for GDB, the GNU Debugger.
 
-   Copyright 1986, 1987, 1988, 1989, 1990, 1991, 1992, 1993, 1994,
-   1995, 1996, 1997, 1998, 1999, 2000, 2002, 2003, 2004, 2005 Free
-   Software Foundation, Inc.
+   Copyright (C) 1986, 1987, 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995,
+   1996, 1997, 1998, 1999, 2000, 2002, 2003, 2004, 2005, 2006, 2007
+   Free Software Foundation, Inc.
 
    This file is part of GDB.
 
    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
-   the Free Software Foundation; either version 2 of the License, or
+   the Free Software Foundation; either version 3 of the License, or
    (at your option) any later version.
 
    This program is distributed in the hope that it will be useful,
@@ -17,9 +17,7 @@
    GNU General Public License for more details.
 
    You should have received a copy of the GNU General Public License
-   along with this program; if not, write to the Free Software
-   Foundation, Inc., 59 Temple Place - Suite 330,
-   Boston, MA 02111-1307, USA.  */
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
 
 #include "defs.h"
 #include "gdb_string.h"
@@ -31,7 +29,6 @@
 #include "gdbcmd.h"
 #include "target.h"
 #include "language.h"
-#include "scm-lang.h"
 #include "demangle.h"
 #include "doublest.h"
 #include "gdb_assert.h"
@@ -158,6 +155,9 @@ struct value
      actually exist in the program.  */
   char optimized_out;
 
+  /* If value is a variable, is it initialized or not.  */
+  int initialized;
+
   /* Actual contents of the value.  For use of this value; setting it
      uses the stuff above.  Not valid if lazy is nonzero.  Target
      byte-order.  We force it to be aligned properly for any possible
@@ -165,7 +165,7 @@ struct value
      declared here.  */
   union
   {
-    bfd_byte contents[1];
+    gdb_byte contents[1];
     DOUBLEST force_doublest_align;
     LONGEST force_longest_align;
     CORE_ADDR force_core_addr_align;
@@ -233,6 +233,7 @@ allocate_value (struct type *type)
   val->embedded_offset = 0;
   val->pointed_to_offset = 0;
   val->modifiable = 1;
+  val->initialized = 1;  /* Default to initialized.  */
   return val;
 }
 
@@ -306,13 +307,13 @@ set_value_bitsize (struct value *value, int bit)
   value->bitsize = bit;
 }
 
-bfd_byte *
+gdb_byte *
 value_contents_raw (struct value *value)
 {
   return value->aligner.contents + value->embedded_offset;
 }
 
-bfd_byte *
+gdb_byte *
 value_contents_all_raw (struct value *value)
 {
   return value->aligner.contents;
@@ -324,7 +325,7 @@ value_enclosing_type (struct value *value)
   return value->enclosing_type;
 }
 
-const bfd_byte *
+const gdb_byte *
 value_contents_all (struct value *value)
 {
   if (value->lazy)
@@ -344,18 +345,38 @@ set_value_lazy (struct value *value, int val)
   value->lazy = val;
 }
 
-const bfd_byte *
+const gdb_byte *
 value_contents (struct value *value)
 {
   return value_contents_writeable (value);
 }
 
-bfd_byte *
+gdb_byte *
 value_contents_writeable (struct value *value)
 {
   if (value->lazy)
     value_fetch_lazy (value);
-  return value->aligner.contents;
+  return value_contents_raw (value);
+}
+
+/* Return non-zero if VAL1 and VAL2 have the same contents.  Note that
+   this function is different from value_equal; in C the operator ==
+   can return 0 even if the two values being compared are equal.  */
+
+int
+value_contents_equal (struct value *val1, struct value *val2)
+{
+  struct type *type1;
+  struct type *type2;
+  int len;
+
+  type1 = check_typedef (value_type (val1));
+  type2 = check_typedef (value_type (val2));
+  len = TYPE_LENGTH (type1);
+  if (len != TYPE_LENGTH (type2))
+    return 0;
+
+  return (memcmp (value_contents (val1), value_contents (val2), len) == 0);
 }
 
 int
@@ -531,7 +552,7 @@ value_copy (struct value *arg)
   struct value *val = allocate_value (encl_type);
   val->type = arg->type;
   VALUE_LVAL (val) = VALUE_LVAL (arg);
-  VALUE_ADDRESS (val) = VALUE_ADDRESS (arg);
+  val->location = arg->location;
   val->offset = arg->offset;
   val->bitpos = arg->bitpos;
   val->bitsize = arg->bitsize;
@@ -612,14 +633,14 @@ access_value_history (int num)
   if (absnum <= 0)
     {
       if (num == 0)
-       error ("The history is empty.");
+       error (_("The history is empty."));
       else if (num == 1)
-       error ("There is only one value in the history.");
+       error (_("There is only one value in the history."));
       else
-       error ("History does not go back to $$%d.", -num);
+       error (_("History does not go back to $$%d."), -num);
     }
   if (absnum > value_history_count)
-    error ("History has not yet reached $%d.", absnum);
+    error (_("History has not yet reached $%d."), absnum);
 
   absnum--;
 
@@ -633,29 +654,6 @@ access_value_history (int num)
   return value_copy (chunk->values[absnum % VALUE_HISTORY_CHUNK]);
 }
 
-/* Clear the value history entirely.
-   Must be done when new symbol tables are loaded,
-   because the type pointers become invalid.  */
-
-void
-clear_value_history (void)
-{
-  struct value_history_chunk *next;
-  int i;
-  struct value *val;
-
-  while (value_history_chain)
-    {
-      for (i = 0; i < VALUE_HISTORY_CHUNK; i++)
-       if ((val = value_history_chain->values[i]) != NULL)
-         xfree (val);
-      next = value_history_chain->next;
-      xfree (value_history_chain);
-      value_history_chain = next;
-    }
-  value_history_count = 0;
-}
-
 static void
 show_values (char *num_exp, int from_tty)
 {
@@ -682,9 +680,9 @@ show_values (char *num_exp, int from_tty)
   for (i = num; i < num + 10 && i <= value_history_count; i++)
     {
       val = access_value_history (i);
-      printf_filtered ("$%d = ", i);
+      printf_filtered (("$%d = "), i);
       value_print (val, gdb_stdout, 0, Val_pretty_default);
-      printf_filtered ("\n");
+      printf_filtered (("\n"));
     }
 
   /* The next "info history +" should start after what we just printed.  */
@@ -707,6 +705,39 @@ show_values (char *num_exp, int from_tty)
 
 static struct internalvar *internalvars;
 
+/* If the variable does not already exist create it and give it the value given.
+   If no value is given then the default is zero.  */
+static void
+init_if_undefined_command (char* args, int from_tty)
+{
+  struct internalvar* intvar;
+
+  /* Parse the expression - this is taken from set_command().  */
+  struct expression *expr = parse_expression (args);
+  register struct cleanup *old_chain =
+    make_cleanup (free_current_contents, &expr);
+
+  /* Validate the expression.
+     Was the expression an assignment?
+     Or even an expression at all?  */
+  if (expr->nelts == 0 || expr->elts[0].opcode != BINOP_ASSIGN)
+    error (_("Init-if-undefined requires an assignment expression."));
+
+  /* Extract the variable from the parsed expression.
+     In the case of an assign the lvalue will be in elts[1] and elts[2].  */
+  if (expr->elts[1].opcode != OP_INTERNALVAR)
+    error (_("The first parameter to init-if-undefined should be a GDB variable."));
+  intvar = expr->elts[2].internalvar;
+
+  /* Only evaluate the expression if the lvalue is void.
+     This may still fail if the expresssion is invalid.  */
+  if (TYPE_CODE (value_type (intvar->value)) == TYPE_CODE_VOID)
+    evaluate_expression (expr);
+
+  do_cleanups (old_chain);
+}
+
+
 /* Look up an internal variable with name NAME.  NAME should not
    normally include a dollar sign.
 
@@ -723,8 +754,9 @@ lookup_internalvar (char *name)
       return var;
 
   var = (struct internalvar *) xmalloc (sizeof (struct internalvar));
-  var->name = concat (name, NULL);
+  var->name = concat (name, (char *)NULL);
   var->value = allocate_value (builtin_type_void);
+  var->endian = gdbarch_byte_order (current_gdbarch);
   release_value (var->value);
   var->next = internalvars;
   internalvars = var;
@@ -735,12 +767,46 @@ struct value *
 value_of_internalvar (struct internalvar *var)
 {
   struct value *val;
+  int i, j;
+  gdb_byte temp;
 
   val = value_copy (var->value);
   if (value_lazy (val))
     value_fetch_lazy (val);
   VALUE_LVAL (val) = lval_internalvar;
   VALUE_INTERNALVAR (val) = var;
+
+  /* Values are always stored in the target's byte order.  When connected to a
+     target this will most likely always be correct, so there's normally no
+     need to worry about it.
+
+     However, internal variables can be set up before the target endian is
+     known and so may become out of date.  Fix it up before anybody sees.
+
+     Internal variables usually hold simple scalar values, and we can
+     correct those.  More complex values (e.g. structures and floating
+     point types) are left alone, because they would be too complicated
+     to correct.  */
+
+  if (var->endian != gdbarch_byte_order (current_gdbarch))
+    {
+      gdb_byte *array = value_contents_raw (val);
+      struct type *type = check_typedef (value_enclosing_type (val));
+      switch (TYPE_CODE (type))
+       {
+       case TYPE_CODE_INT:
+       case TYPE_CODE_PTR:
+         /* Reverse the bytes.  */
+         for (i = 0, j = TYPE_LENGTH (type) - 1; i < j; i++, j--)
+           {
+             temp = array[j];
+             array[j] = array[i];
+             array[i] = temp;
+           }
+         break;
+       }
+    }
+
   return val;
 }
 
@@ -748,7 +814,7 @@ void
 set_internalvar_component (struct internalvar *var, int offset, int bitpos,
                           int bitsize, struct value *newval)
 {
-  bfd_byte *addr = value_contents_writeable (var->value) + offset;
+  gdb_byte *addr = value_contents_writeable (var->value) + offset;
 
   if (bitsize)
     modify_field (addr, value_as_long (newval),
@@ -779,6 +845,7 @@ set_internalvar (struct internalvar *var, struct value *val)
      long.  */
   xfree (var->value);
   var->value = newval;
+  var->endian = gdbarch_byte_order (current_gdbarch);
   release_value (newval);
   /* End code which must not call error().  */
 }
@@ -789,22 +856,49 @@ internalvar_name (struct internalvar *var)
   return var->name;
 }
 
-/* Free all internalvars.  Done when new symtabs are loaded,
-   because that makes the values invalid.  */
+/* Update VALUE before discarding OBJFILE.  COPIED_TYPES is used to
+   prevent cycles / duplicates.  */
+
+static void
+preserve_one_value (struct value *value, struct objfile *objfile,
+                   htab_t copied_types)
+{
+  if (TYPE_OBJFILE (value->type) == objfile)
+    value->type = copy_type_recursive (objfile, value->type, copied_types);
+
+  if (TYPE_OBJFILE (value->enclosing_type) == objfile)
+    value->enclosing_type = copy_type_recursive (objfile,
+                                                value->enclosing_type,
+                                                copied_types);
+}
+
+/* Update the internal variables and value history when OBJFILE is
+   discarded; we must copy the types out of the objfile.  New global types
+   will be created for every convenience variable which currently points to
+   this objfile's types, and the convenience variables will be adjusted to
+   use the new global types.  */
 
 void
-clear_internalvars (void)
+preserve_values (struct objfile *objfile)
 {
+  htab_t copied_types;
+  struct value_history_chunk *cur;
   struct internalvar *var;
+  int i;
 
-  while (internalvars)
-    {
-      var = internalvars;
-      internalvars = var->next;
-      xfree (var->name);
-      xfree (var->value);
-      xfree (var);
-    }
+  /* Create the hash table.  We allocate on the objfile's obstack, since
+     it is soon to be deleted.  */
+  copied_types = create_copied_types_hash (objfile);
+
+  for (cur = value_history_chain; cur; cur = cur->next)
+    for (i = 0; i < VALUE_HISTORY_CHUNK; i++)
+      if (cur->values[i])
+       preserve_one_value (cur->values[i], objfile, copied_types);
+
+  for (var = internalvars; var; var = var->next)
+    preserve_one_value (var->value, objfile, copied_types);
+
+  htab_delete (copied_types);
 }
 
 static void
@@ -819,14 +913,16 @@ show_convenience (char *ignore, int from_tty)
        {
          varseen = 1;
        }
-      printf_filtered ("$%s = ", var->name);
-      value_print (var->value, gdb_stdout, 0, Val_pretty_default);
-      printf_filtered ("\n");
+      printf_filtered (("$%s = "), var->name);
+      value_print (value_of_internalvar (var), gdb_stdout,
+                  0, Val_pretty_default);
+      printf_filtered (("\n"));
     }
   if (!varseen)
-    printf_unfiltered ("No debugger convenience variables now defined.\n\
+    printf_unfiltered (_("\
+No debugger convenience variables now defined.\n\
 Convenience variables have names starting with \"$\";\n\
-use \"set\" as in \"set $foo = 5\" to define them.\n");
+use \"set\" as in \"set $foo = 5\" to define them.\n"));
 }
 \f
 /* Extract a value as a C number (either long or double).
@@ -852,7 +948,7 @@ value_as_double (struct value *val)
 
   foo = unpack_double (value_type (val), value_contents (val), &inv);
   if (inv)
-    error ("Invalid floating value found in program.");
+    error (_("Invalid floating value found in program."));
   return foo;
 }
 /* Extract a value as a C pointer. Does not deallocate the value.  
@@ -864,10 +960,10 @@ value_as_address (struct value *val)
   /* Assume a CORE_ADDR can fit in a LONGEST (for now).  Not sure
      whether we want this to be true eventually.  */
 #if 0
-  /* ADDR_BITS_REMOVE is wrong if we are being called for a
+  /* gdbarch_addr_bits_remove is wrong if we are being called for a
      non-address (e.g. argument to "signal", "info break", etc.), or
      for pointers to char, in which the low bits *are* significant.  */
-  return ADDR_BITS_REMOVE (value_as_long (val));
+  return gdbarch_addr_bits_remove (current_gdbarch, value_as_long (val));
 #else
 
   /* There are several targets (IA-64, PowerPC, and others) which
@@ -975,25 +1071,23 @@ value_as_address (struct value *val)
    to an INT (or some size).  After all, it is only an offset.  */
 
 LONGEST
-unpack_long (struct type *type, const char *valaddr)
+unpack_long (struct type *type, const gdb_byte *valaddr)
 {
   enum type_code code = TYPE_CODE (type);
   int len = TYPE_LENGTH (type);
   int nosign = TYPE_UNSIGNED (type);
 
-  if (current_language->la_language == language_scm
-      && is_scmvalue_type (type))
-    return scm_unpack (type, valaddr, TYPE_CODE_INT);
-
   switch (code)
     {
     case TYPE_CODE_TYPEDEF:
       return unpack_long (check_typedef (type), valaddr);
     case TYPE_CODE_ENUM:
+    case TYPE_CODE_FLAGS:
     case TYPE_CODE_BOOL:
     case TYPE_CODE_INT:
     case TYPE_CODE_CHAR:
     case TYPE_CODE_RANGE:
+    case TYPE_CODE_MEMBERPTR:
       if (nosign)
        return extract_unsigned_integer (valaddr, len);
       else
@@ -1008,11 +1102,8 @@ unpack_long (struct type *type, const char *valaddr)
          whether we want this to be true eventually.  */
       return extract_typed_address (valaddr, type);
 
-    case TYPE_CODE_MEMBER:
-      error ("not implemented: member types in unpack_long");
-
     default:
-      error ("Value can't be converted to integer.");
+      error (_("Value can't be converted to integer."));
     }
   return 0;                    /* Placate lint.  */
 }
@@ -1024,7 +1115,7 @@ unpack_long (struct type *type, const char *valaddr)
    format, result is in host format.  */
 
 DOUBLEST
-unpack_double (struct type *type, const char *valaddr, int *invp)
+unpack_double (struct type *type, const gdb_byte *valaddr, int *invp)
 {
   enum type_code code;
   int len;
@@ -1045,7 +1136,7 @@ unpack_double (struct type *type, const char *valaddr, int *invp)
         only in a non-portable way.  Fixing the portability problem
         wouldn't help since the VAX floating-point code is also badly
         bit-rotten.  The target needs to add definitions for the
-        methods TARGET_FLOAT_FORMAT and TARGET_DOUBLE_FORMAT - these
+        methods gdbarch_float_format and gdbarch_double_format - these
         exactly describe the target floating-point format.  The
         problem here is that the corresponding floatformat_vax_f and
         floatformat_vax_d values these methods should be set to are
@@ -1088,7 +1179,7 @@ unpack_double (struct type *type, const char *valaddr, int *invp)
    to an INT (or some size).  After all, it is only an offset.  */
 
 CORE_ADDR
-unpack_pointer (struct type *type, const char *valaddr)
+unpack_pointer (struct type *type, const gdb_byte *valaddr)
 {
   /* Assume a CORE_ADDR can fit in a LONGEST (for now).  Not sure
      whether we want this to be true eventually.  */
@@ -1132,8 +1223,8 @@ value_static_field (struct type *type, int fieldno)
          /* SYM should never have a SYMBOL_CLASS which will require
             read_var_value to use the FRAME parameter.  */
          if (symbol_read_needs_frame (sym))
-           warning ("static field's value depends on the current "
-                    "frame - bad debug info?");
+           warning (_("static field's value depends on the current "
+                    "frame - bad debug info?"));
          retval = read_var_value (sym, NULL);
        }
       if (retval && VALUE_LVAL (retval) == lval_memory)
@@ -1249,11 +1340,9 @@ value_primitive_field (struct value *arg1, int offset,
   VALUE_LVAL (v) = VALUE_LVAL (arg1);
   if (VALUE_LVAL (arg1) == lval_internalvar)
     VALUE_LVAL (v) = lval_internalvar_component;
-  VALUE_ADDRESS (v) = VALUE_ADDRESS (arg1);
+  v->location = arg1->location;
   VALUE_REGNUM (v) = VALUE_REGNUM (arg1);
   VALUE_FRAME_ID (v) = VALUE_FRAME_ID (arg1);
-/*  VALUE_OFFSET (v) = VALUE_OFFSET (arg1) + offset
-   + TYPE_FIELD_BITPOS (arg_type, fieldno) / 8; */
   return v;
 }
 
@@ -1338,7 +1427,7 @@ value_fn_field (struct value **arg1p, struct fn_field *f, int j, struct type *ty
    If the field is signed, we also do sign extension. */
 
 LONGEST
-unpack_field_as_long (struct type *type, const char *valaddr, int fieldno)
+unpack_field_as_long (struct type *type, const gdb_byte *valaddr, int fieldno)
 {
   ULONGEST val;
   ULONGEST valmask;
@@ -1385,7 +1474,7 @@ unpack_field_as_long (struct type *type, const char *valaddr, int fieldno)
    0 <= BITPOS, where lbits is the size of a LONGEST in bits.  */
 
 void
-modify_field (char *addr, LONGEST fieldval, int bitpos, int bitsize)
+modify_field (gdb_byte *addr, LONGEST fieldval, int bitpos, int bitsize)
 {
   ULONGEST oword;
   ULONGEST mask = (ULONGEST) -1 >> (8 * sizeof (ULONGEST) - bitsize);
@@ -1400,7 +1489,7 @@ modify_field (char *addr, LONGEST fieldval, int bitpos, int bitsize)
     {
       /* FIXME: would like to include fieldval in the message, but
          we don't have a sprintf_longest.  */
-      warning ("Value does not fit in %d bits.", bitsize);
+      warning (_("Value does not fit in %d bits."), bitsize);
 
       /* Truncate it, otherwise adjoining fields may be corrupted.  */
       fieldval &= mask;
@@ -1418,39 +1507,49 @@ modify_field (char *addr, LONGEST fieldval, int bitpos, int bitsize)
   store_unsigned_integer (addr, sizeof oword, oword);
 }
 \f
-/* Convert C numbers into newly allocated values */
+/* Pack NUM into BUF using a target format of TYPE.  */
 
-struct value *
-value_from_longest (struct type *type, LONGEST num)
+void
+pack_long (gdb_byte *buf, struct type *type, LONGEST num)
 {
-  struct value *val = allocate_value (type);
-  enum type_code code;
   int len;
-retry:
-  code = TYPE_CODE (type);
+
+  type = check_typedef (type);
   len = TYPE_LENGTH (type);
 
-  switch (code)
+  switch (TYPE_CODE (type))
     {
-    case TYPE_CODE_TYPEDEF:
-      type = check_typedef (type);
-      goto retry;
     case TYPE_CODE_INT:
     case TYPE_CODE_CHAR:
     case TYPE_CODE_ENUM:
+    case TYPE_CODE_FLAGS:
     case TYPE_CODE_BOOL:
     case TYPE_CODE_RANGE:
-      store_signed_integer (value_contents_raw (val), len, num);
+    case TYPE_CODE_MEMBERPTR:
+      store_signed_integer (buf, len, num);
       break;
 
     case TYPE_CODE_REF:
     case TYPE_CODE_PTR:
-      store_typed_address (value_contents_raw (val), type, (CORE_ADDR) num);
+      store_typed_address (buf, type, (CORE_ADDR) num);
       break;
 
     default:
-      error ("Unexpected type (%d) encountered for integer constant.", code);
+      error (_("Unexpected type (%d) encountered for integer constant."),
+            TYPE_CODE (type));
     }
+}
+
+
+/* Convert C numbers into newly allocated values.  */
+
+struct value *
+value_from_longest (struct type *type, LONGEST num)
+{
+  struct value *val = allocate_value (type);
+
+  pack_long (value_contents_raw (val), type, num);
+
   return val;
 }
 
@@ -1507,7 +1606,7 @@ value_from_double (struct type *type, DOUBLEST num)
       store_typed_floating (value_contents_raw (val), base_type, num);
     }
   else
-    error ("Unexpected type encountered for floating constant.");
+    error (_("Unexpected type encountered for floating constant."));
 
   return val;
 }
@@ -1553,7 +1652,7 @@ coerce_enum (struct value *arg)
 \f
 
 /* Should we use DEPRECATED_EXTRACT_STRUCT_VALUE_ADDRESS instead of
-   EXTRACT_RETURN_VALUE?  GCC_P is true if compiled with gcc and TYPE
+   gdbarch_extract_return_value?  GCC_P is true if compiled with gcc and TYPE
    is the type (which is known to be struct, union or array).
 
    On most machines, the struct convention is used unless we are
@@ -1589,7 +1688,7 @@ using_struct_return (struct type *value_type, int gcc_p)
   enum type_code code = TYPE_CODE (value_type);
 
   if (code == TYPE_CODE_ERROR)
-    error ("Function return type unknown.");
+    error (_("Function return type unknown."));
 
   if (code == TYPE_CODE_VOID)
     /* A void return value is never in memory.  See also corresponding
@@ -1602,19 +1701,43 @@ using_struct_return (struct type *value_type, int gcc_p)
          != RETURN_VALUE_REGISTER_CONVENTION);
 }
 
+/* Set the initialized field in a value struct.  */
+
+void
+set_value_initialized (struct value *val, int status)
+{
+  val->initialized = status;
+}
+
+/* Return the initialized field in a value struct.  */
+
+int
+value_initialized (struct value *val)
+{
+  return val->initialized;
+}
+
 void
 _initialize_values (void)
 {
-  add_cmd ("convenience", no_class, show_convenience,
-          "Debugger convenience (\"$foo\") variables.\n\
+  add_cmd ("convenience", no_class, show_convenience, _("\
+Debugger convenience (\"$foo\") variables.\n\
 These variables are created when you assign them values;\n\
-thus, \"print $foo=1\" gives \"$foo\" the value 1.  Values may be any type.\n\n\
+thus, \"print $foo=1\" gives \"$foo\" the value 1.  Values may be any type.\n\
+\n\
 A few convenience variables are given values automatically:\n\
 \"$_\"holds the last address examined with \"x\" or \"info lines\",\n\
-\"$__\" holds the contents of the last address examined with \"x\".",
+\"$__\" holds the contents of the last address examined with \"x\"."),
           &showlist);
 
   add_cmd ("values", no_class, show_values,
-          "Elements of value history around item number IDX (or last ten).",
+          _("Elements of value history around item number IDX (or last ten)."),
           &showlist);
+
+  add_com ("init-if-undefined", class_vars, init_if_undefined_command, _("\
+Initialize a convenience variable if necessary.\n\
+init-if-undefined VARIABLE = EXPRESSION\n\
+Set an internal VARIABLE to the result of the EXPRESSION if it does not\n\
+exist or does not contain a value.  The EXPRESSION is not evaluated if the\n\
+VARIABLE is already initialized."));
 }
This page took 0.032863 seconds and 4 git commands to generate.