]> git.ipfire.org Git - thirdparty/bash.git/commitdiff
fix to make += work with dynamic integer vars like RANDOM
authorChet Ramey <chet.ramey@case.edu>
Mon, 13 Dec 2021 14:37:23 +0000 (09:37 -0500)
committerChet Ramey <chet.ramey@case.edu>
Mon, 13 Dec 2021 14:37:23 +0000 (09:37 -0500)
12 files changed:
CWRU/CWRU.chlog
doc/Makefile.in
doc/bash.0
doc/bash.1
doc/bashref.info
doc/bashref.texi
doc/builtins.0
doc/builtins.1
doc/rbash.0
doc/rbash.1
examples/loadables/realpath.c
variables.c

index 821e85c03a4065da43836b25e36f0538b2fece56..9995e6167370e7e1b25ec6dbeb24685fb0770b60 100644 (file)
@@ -2622,3 +2622,21 @@ lib/readline/colors.c
        - _rl_custom_readline_prefix: use STREQN to check for the extension
          string in $LS_COLORS, since it's not necessarily null-terminated.
          From https://savannah.gnu.org/patch/?10158
+
+                                  12/10
+                                  -----
+variables.c
+       - set_int_value,set_string_value: broke common code for setting int
+         and string dynamic variable values out into separate functions;
+         changed all callers to use them where appropriate. set_int_value
+         takes a flags argument saying whether or not to force the integer
+         attribute on
+       - assign_random: store the value assigned as the variable value so
+         things like RANDOM=42; RANDOM+=7 generate consistent sequences
+         like in ksh93
+       - assign_seconds: store the value assigned as the variable value so
+         things like SECONDS=42 ; SECONDS+=7 generate what's expected
+
+doc/Makefile.in
+       - changes to allow man pages that include others (.so FN) to be built
+         outside the source tree
index 4bcd42928d40d3c59d4c206368f1e3edf8dba5b5..8bf775e14a208c9809dfb3fe8533e6333fc68e63 100644 (file)
@@ -107,11 +107,11 @@ BASHREF_FILES = $(srcdir)/bashref.texi $(srcdir)/fdl.texi $(srcdir)/version.texi
 
 .1.ps:
        $(RM) $@
-       -${GROFF} -man $< > $@
+       -${GROFF} -I${srcdir} -man $< > $@
 
 .1.0:
        $(RM) $@
-       -${NROFF} -man $< > $@
+       -${NROFF} -I${srcdir} -man $< > $@
 
 .1.html:
        $(RM) $@
@@ -127,11 +127,11 @@ BASHREF_FILES = $(srcdir)/bashref.texi $(srcdir)/fdl.texi $(srcdir)/version.texi
 
 .3.ps:
        $(RM) $@
-       -${GROFF} -man $< > $@
+       -${GROFF} -I${srcdir} -man $< > $@
 
 .3.0:
        $(RM) $@
-       -${NROFF} -man $< > $@
+       -${NROFF} -I${srcdir} -man $< > $@
 
 .3.html:
        $(RM) $@
index 62e1bab9d3061e8897fc5d870476ce34da291fe9..472346063b21535782e1319ccd84383d29e2638b 100644 (file)
@@ -1078,12 +1078,12 @@ P\bPA\bAR\bRA\bAM\bME\bET\bTE\bER\bRS\bS
        R\bRE\bEP\bPL\bLY\bY  Set to the line of input read by the r\bre\bea\bad\bd builtin  command  when
               no arguments are supplied.
        S\bSE\bEC\bCO\bON\bND\bDS\bS
-              Each  time  this  parameter is referenced, the number of seconds
-              since shell invocation is returned.  If a value is  assigned  to
+              Each time this parameter is referenced, it expands to the number
+              of seconds since shell invocation.  If a value  is  assigned  to
               S\bSE\bEC\bCO\bON\bND\bDS\bS,  the  value  returned upon subsequent references is the
               number of seconds since the assignment plus the value  assigned.
               The  number  of seconds at shell invocation and the current time
-              is always determined by querying the system clock.   If  S\bSE\bEC\bCO\bON\bND\bDS\bS
+              are always determined by querying the system clock.  If  S\bSE\bEC\bCO\bON\bND\bDS\bS
               is  unset, it loses its special properties, even if it is subse-
               quently reset.
        S\bSH\bHE\bEL\bLL\bLO\bOP\bPT\bTS\bS
index c3dee17b6112dad898655c35a73ebb76023ca46f..1cf056cc22a25721aea3dfb94de8d19162182db5 100644 (file)
@@ -2014,14 +2014,14 @@ builtin command when no arguments are supplied.
 .TP
 .B SECONDS
 Each time this parameter is
-referenced, the number of seconds since shell invocation is returned.  If a
-value is assigned to
+referenced, it expands to the number of seconds since shell invocation.
+If a value is assigned to
 .SM
 .BR SECONDS ,
 the value returned upon subsequent
 references is
 the number of seconds since the assignment plus the value assigned.
-The number of seconds at shell invocation and the current time is always
+The number of seconds at shell invocation and the current time are always
 determined by querying the system clock.
 If
 .SM
index 1361ce7c698da5dd0cd3d90cdf7fab33ec38152d..9bd3e92e354ab64c66f16639588cfb03543b8580 100644 (file)
@@ -5754,7 +5754,7 @@ Variables::).
      started.  Assignment to this variable resets the count to the value
      assigned, and the expanded value becomes the value assigned plus
      the number of seconds since the assignment.  The number of seconds
-     at shell invocation and the current time is always determined by
+     at shell invocation and the current time are always determined by
      querying the system clock.  If 'SECONDS' is unset, it loses its
      special properties, even if it is subsequently reset.
 
@@ -12476,77 +12476,77 @@ Node: Special Builtins\7f216717
 Node: Shell Variables\7f217696
 Node: Bourne Shell Variables\7f218133
 Node: Bash Variables\7f220237
-Node: Bash Features\7f253052
-Node: Invoking Bash\7f254065
-Node: Bash Startup Files\7f260078
-Node: Interactive Shells\7f265181
-Node: What is an Interactive Shell?\7f265591
-Node: Is this Shell Interactive?\7f266240
-Node: Interactive Shell Behavior\7f267055
-Node: Bash Conditional Expressions\7f270684
-Node: Shell Arithmetic\7f275326
-Node: Aliases\7f278270
-Node: Arrays\7f280883
-Node: The Directory Stack\7f287130
-Node: Directory Stack Builtins\7f287914
-Node: Controlling the Prompt\7f292174
-Node: The Restricted Shell\7f295139
-Node: Bash POSIX Mode\7f297749
-Node: Shell Compatibility Mode\7f309022
-Node: Job Control\7f317051
-Node: Job Control Basics\7f317511
-Node: Job Control Builtins\7f322513
-Node: Job Control Variables\7f327913
-Node: Command Line Editing\7f329069
-Node: Introduction and Notation\7f330740
-Node: Readline Interaction\7f332363
-Node: Readline Bare Essentials\7f333554
-Node: Readline Movement Commands\7f335337
-Node: Readline Killing Commands\7f336297
-Node: Readline Arguments\7f338215
-Node: Searching\7f339259
-Node: Readline Init File\7f341445
-Node: Readline Init File Syntax\7f342706
-Node: Conditional Init Constructs\7f364194
-Node: Sample Init File\7f368390
-Node: Bindable Readline Commands\7f371514
-Node: Commands For Moving\7f372718
-Node: Commands For History\7f374769
-Node: Commands For Text\7f379763
-Node: Commands For Killing\7f383412
-Node: Numeric Arguments\7f386445
-Node: Commands For Completion\7f387584
-Node: Keyboard Macros\7f391775
-Node: Miscellaneous Commands\7f392462
-Node: Readline vi Mode\7f398401
-Node: Programmable Completion\7f399308
-Node: Programmable Completion Builtins\7f407088
-Node: A Programmable Completion Example\7f417783
-Node: Using History Interactively\7f423030
-Node: Bash History Facilities\7f423714
-Node: Bash History Builtins\7f426719
-Node: History Interaction\7f431727
-Node: Event Designators\7f435347
-Node: Word Designators\7f436701
-Node: Modifiers\7f438461
-Node: Installing Bash\7f440272
-Node: Basic Installation\7f441409
-Node: Compilers and Options\7f445131
-Node: Compiling For Multiple Architectures\7f445872
-Node: Installation Names\7f447565
-Node: Specifying the System Type\7f449674
-Node: Sharing Defaults\7f450390
-Node: Operation Controls\7f451063
-Node: Optional Features\7f452021
-Node: Reporting Bugs\7f463239
-Node: Major Differences From The Bourne Shell\7f464514
-Node: GNU Free Documentation License\7f481364
-Node: Indexes\7f506541
-Node: Builtin Index\7f506995
-Node: Reserved Word Index\7f513822
-Node: Variable Index\7f516270
-Node: Function Index\7f532762
-Node: Concept Index\7f546546
+Node: Bash Features\7f253053
+Node: Invoking Bash\7f254066
+Node: Bash Startup Files\7f260079
+Node: Interactive Shells\7f265182
+Node: What is an Interactive Shell?\7f265592
+Node: Is this Shell Interactive?\7f266241
+Node: Interactive Shell Behavior\7f267056
+Node: Bash Conditional Expressions\7f270685
+Node: Shell Arithmetic\7f275327
+Node: Aliases\7f278271
+Node: Arrays\7f280884
+Node: The Directory Stack\7f287131
+Node: Directory Stack Builtins\7f287915
+Node: Controlling the Prompt\7f292175
+Node: The Restricted Shell\7f295140
+Node: Bash POSIX Mode\7f297750
+Node: Shell Compatibility Mode\7f309023
+Node: Job Control\7f317052
+Node: Job Control Basics\7f317512
+Node: Job Control Builtins\7f322514
+Node: Job Control Variables\7f327914
+Node: Command Line Editing\7f329070
+Node: Introduction and Notation\7f330741
+Node: Readline Interaction\7f332364
+Node: Readline Bare Essentials\7f333555
+Node: Readline Movement Commands\7f335338
+Node: Readline Killing Commands\7f336298
+Node: Readline Arguments\7f338216
+Node: Searching\7f339260
+Node: Readline Init File\7f341446
+Node: Readline Init File Syntax\7f342707
+Node: Conditional Init Constructs\7f364195
+Node: Sample Init File\7f368391
+Node: Bindable Readline Commands\7f371515
+Node: Commands For Moving\7f372719
+Node: Commands For History\7f374770
+Node: Commands For Text\7f379764
+Node: Commands For Killing\7f383413
+Node: Numeric Arguments\7f386446
+Node: Commands For Completion\7f387585
+Node: Keyboard Macros\7f391776
+Node: Miscellaneous Commands\7f392463
+Node: Readline vi Mode\7f398402
+Node: Programmable Completion\7f399309
+Node: Programmable Completion Builtins\7f407089
+Node: A Programmable Completion Example\7f417784
+Node: Using History Interactively\7f423031
+Node: Bash History Facilities\7f423715
+Node: Bash History Builtins\7f426720
+Node: History Interaction\7f431728
+Node: Event Designators\7f435348
+Node: Word Designators\7f436702
+Node: Modifiers\7f438462
+Node: Installing Bash\7f440273
+Node: Basic Installation\7f441410
+Node: Compilers and Options\7f445132
+Node: Compiling For Multiple Architectures\7f445873
+Node: Installation Names\7f447566
+Node: Specifying the System Type\7f449675
+Node: Sharing Defaults\7f450391
+Node: Operation Controls\7f451064
+Node: Optional Features\7f452022
+Node: Reporting Bugs\7f463240
+Node: Major Differences From The Bourne Shell\7f464515
+Node: GNU Free Documentation License\7f481365
+Node: Indexes\7f506542
+Node: Builtin Index\7f506996
+Node: Reserved Word Index\7f513823
+Node: Variable Index\7f516271
+Node: Function Index\7f532763
+Node: Concept Index\7f546547
 \1f
 End Tag Table
 
index a0b7ce5a987ba41084e703682a5047c65dec8817..ec538a38438cd36bb8d145044dea27334d7ee380 100644 (file)
@@ -6662,12 +6662,11 @@ with @samp{bind -x} (@pxref{Bash Builtins}).
 The default variable for the @code{read} builtin.
 
 @item SECONDS
-This variable expands to the number of seconds since the
-shell was started.  Assignment to this variable resets
-the count to the value assigned, and the expanded value
-becomes the value assigned plus the number of seconds
+This variable expands to the number of seconds since the shell was started. 
+Assignment to this variable resets the count to the value assigned, and the
+expanded value becomes the value assigned plus the number of seconds
 since the assignment.
-The number of seconds at shell invocation and the current time is always
+The number of seconds at shell invocation and the current time are always
 determined by querying the system clock.
 If @env{SECONDS}
 is unset, it loses its special properties,
index 750128af3ea87241a3507df54101e9d66a506af7..7ecfe91f7d3ac620ffd60ee92fdaa4fd02bfaf91 100644 (file)
@@ -2071,4 +2071,4 @@ S\bSE\bEE\bE A\bAL\bLS\bSO\bO
 
 
 
-GNU Bash 5.1                   2021 September 30              BASH_BUILTINS(1)
+GNU Bash 5.2                   2021 November 22               BASH_BUILTINS(1)
index 611de93fe4ea01d9fd6208204025fd32ce7a354e..43d92a2fc7eef8da4684f274a056d881284d7641 100644 (file)
@@ -7,7 +7,7 @@
 .de FN
 \fI\|\\$1\|\fP
 ..
-.TH BASH_BUILTINS 1 "2021 September 30" "GNU Bash 5.1"
+.TH BASH_BUILTINS 1 "2021 November 22" "GNU Bash 5.2"
 .SH NAME
 :, ., [, alias, bg, bind, break, builtin, caller,
 cd, command, compgen, complete, compopt,
index eccc5bf8a0b455ac3a0cfc7974d557c66a7cb90b..96845d0c2fd4d78ebd4edd9975a26f195cf412cd 100644 (file)
@@ -61,4 +61,4 @@ S\bSE\bEE\bE A\bAL\bLS\bSO\bO
 
 
 
-GNU Bash-4.0                      2004 Apr 20                         RBASH(1)
+Bash-5.2                       2021 November 22                       RBASH(1)
index 56e38fd030a516f3293f66a741d93bc1bb9fd396..39309b4cb9f0f66ff25417a4afbcbf21c5f7007e 100644 (file)
@@ -1,4 +1,4 @@
-.TH RBASH 1 "2004 Apr 20" "GNU Bash-4.0"
+.TH RBASH 1 "2021 November 22" "Bash-5.2"
 .SH NAME
 rbash \- restricted bash, see \fBbash\fR(1)
 .SH RESTRICTED SHELL
index 3591e47aa8d8f53f4fb9bfebc289cd6d987fef47..81c96aa172ce33d96c8799e99bd92a63a73d5d89 100644 (file)
@@ -7,6 +7,7 @@
  *                     variable NAME
  *             -c      check whether or not each resolved path exists
  *             -s      no output, exit status determines whether path is valid
+ *             -S      strip . and .. from the pathname only, no symlink resolution
  *             -v      produce verbose output
  *
  *
@@ -63,11 +64,10 @@ extern int  errno;
 extern char    *sh_realpath();
 
 int
-realpath_builtin(list)
-WORD_LIST      *list;
+realpath_builtin(WORD_LIST *list)
 {
-       int     opt, cflag, vflag, sflag, aflag, es;
-       char    *r, realbuf[PATH_MAX], *p;
+       int     opt, cflag, vflag, sflag, Sflag, aflag, es;
+       char    *r, realbuf[PATH_MAX], *p, *newpath;
        struct stat sb;
 #if defined (ARRAY_VARS)
        arrayind_t      ind;
@@ -80,14 +80,14 @@ WORD_LIST   *list;
                return (EX_USAGE);
        }
 
-       vflag = cflag = sflag = aflag = 0;
+       vflag = cflag = sflag = aflag = Sflag = 0;
 #if defined (ARRAY_VARS)
        aname = NULL;
        v = NULL;
        ind = 0;
 #endif
        reset_internal_getopt();
-       while ((opt = internal_getopt (list, "a:csv")) != -1) {
+       while ((opt = internal_getopt (list, "a:Scsv")) != -1) {
                switch (opt) {
 #if defined (ARRAY_VARS)
                case 'a':
@@ -101,6 +101,9 @@ WORD_LIST   *list;
                case 's':
                        sflag = 1;
                        break;
+               case 'S':
+                       Sflag = 1;
+                       break;
                case 'v':
                        vflag = 1;
                        break;
@@ -143,14 +146,20 @@ WORD_LIST *list;
 
        for (es = EXECUTION_SUCCESS; list; list = list->next) {
                p = list->word->word;
-               r = sh_realpath(p, realbuf);
+               if (Sflag) {
+                       /* sh_canonpath doesn't convert to absolute pathnames */
+                       newpath = make_absolute(p, get_string_value("PWD"));
+                       r = sh_canonpath(newpath, PATH_CHECKDOTDOT|PATH_CHECKEXISTS);
+                       free(newpath);
+               } else
+                       r = sh_realpath(p, realbuf);
                if (r == 0) {
                        es = EXECUTION_FAILURE;
                        if (sflag == 0)
                                builtin_error("%s: cannot resolve: %s", p, strerror(errno));
                        continue;
                }
-               if (cflag && (stat(realbuf, &sb) < 0)) {
+               if (cflag && (stat(r, &sb) < 0)) {
                        es = EXECUTION_FAILURE;
                        if (sflag == 0)
                                builtin_error("%s: %s", p, strerror(errno));
@@ -158,14 +167,16 @@ WORD_LIST *list;
                }
                if (sflag == 0) {
                        if (aflag) {
-                               bind_array_element (v, ind, realbuf, 0);
+                               bind_array_element (v, ind, r, 0);
                                ind++;
                        } else {
                                if (vflag)
                                        printf ("%s -> ", p);
-                               printf("%s\n", realbuf);
+                               printf("%s\n", r);
                        }
                }
+               if (Sflag)
+                       free (r);
        }
        return es;
 }
@@ -174,10 +185,14 @@ char *realpath_doc[] = {
        "Display pathname in canonical form.",
        "",
        "Display the canonicalized version of each PATHNAME argument, resolving",
-       "symbolic links.  The -c option checks whether or not each resolved name",
-       "exists.  The -s option produces no output; the exit status determines the",
-       "validity of each PATHNAME.  The -v option produces verbose output.  The",
-       "exit status is 0 if each PATHNAME was resolved; non-zero otherwise.",
+       "symbolic links.",
+       "If the -S option is supplied, canonicalize . and .. pathname components",
+       "without resolving symbolic links.",
+       "The -c option checks whether or not each resolved name exists.",
+       "The -s option produces no output; the exit status determines the",
+       "validity of each PATHNAME.",
+       "The -v option produces verbose output.",
+       "The exit status is 0 if each PATHNAME was resolved; non-zero otherwise.",
        (char *)NULL
 };
 
@@ -186,6 +201,6 @@ struct builtin realpath_struct = {
        realpath_builtin,       /* function implementing the builtin */
        BUILTIN_ENABLED,        /* initial flags for builtin */
        realpath_doc,           /* array of long documentation strings */
-       "realpath [-csv] pathname [pathname...]",       /* usage synopsis */
+       "realpath [-Scsv] pathname [pathname...]",      /* usage synopsis */
        0                       /* reserved for internal use */
 };
index 5f216328cd562ac47a7a2c7bae70d0f4e52f320b..b5bdec201ad8ebff62ab717d2fcb8af09f8e5edf 100644 (file)
@@ -199,6 +199,9 @@ static SHELL_VAR *init_dynamic_array_var PARAMS((char *, sh_var_value_func_t *,
 static SHELL_VAR *init_dynamic_assoc_var PARAMS((char *, sh_var_value_func_t *, sh_var_assign_func_t *, int));
 #endif
 
+static inline SHELL_VAR *set_int_value (SHELL_VAR *, intmax_t, int);
+static inline SHELL_VAR *set_string_value (SHELL_VAR *, const char *, int);
+
 static SHELL_VAR *assign_seconds PARAMS((SHELL_VAR *, char *, arrayind_t, char *));
 static SHELL_VAR *get_seconds PARAMS((SHELL_VAR *));
 static SHELL_VAR *init_seconds_var PARAMS((void));
@@ -1275,6 +1278,39 @@ init_dynamic_assoc_var (name, getfunc, setfunc, attrs)
 }
 #endif
 
+/* Set the string value of VAR to the string representation of VALUE.
+   Right now this takes an INTMAX_T because that's what itos needs. If
+   FLAGS&1, we force the integer attribute on. */
+static inline SHELL_VAR *
+set_int_value (SHELL_VAR *var, intmax_t value, int flags)
+{
+  char *p;
+
+  p = itos (value);
+  FREE (value_cell (var));
+  var_setvalue (var, p);
+  if (flags & 1)
+    VSETATTR (var, att_integer);
+  return (var);
+}
+
+static inline SHELL_VAR *
+set_string_value (SHELL_VAR *var, const char *value, int flags)
+{
+  char *p;
+
+  if (value && *value)
+    p = savestring (value);
+  else
+    {
+      p = (char *)xmalloc (1);
+      p[0] = '\0';
+    }
+  FREE (value_cell (var));
+  var_setvalue (var, p);
+  return (var);
+}
+
 /* The value of $SECONDS.  This is the number of seconds since shell
    invocation, or, the number of seconds since the last assignment + the
    value of the last assignment. */
@@ -1297,7 +1333,7 @@ assign_seconds (self, value, unused, key)
   seconds_value_assigned = expok ? nval : 0;
   gettimeofday (&shellstart, NULL);
   shell_start_time = shellstart.tv_sec;
-  return (self);
+  return (set_int_value (self, nval, integer_p (self) != 0));
 }
 
 static SHELL_VAR *
@@ -1305,18 +1341,11 @@ get_seconds (var)
      SHELL_VAR *var;
 {
   time_t time_since_start;
-  char *p;
   struct timeval tv;
 
   gettimeofday(&tv, NULL);
   time_since_start = tv.tv_sec - shell_start_time;
-  p = itos(seconds_value_assigned + time_since_start);
-
-  FREE (value_cell (var));
-
-  VSETATTR (var, att_integer);
-  var_setvalue (var, p);
-  return (var);
+  return (set_int_value (var, seconds_value_assigned + time_since_start, 1));
 }
 
 static SHELL_VAR *
@@ -1358,7 +1387,7 @@ assign_random (self, value, unused, key)
   sbrand (seedval);
   if (subshell_environment)
     seeded_subshell = getpid ();
-  return (self);
+  return (set_int_value (self, seedval, integer_p (self) != 0));
 }
 
 int
@@ -1386,16 +1415,9 @@ get_random (var)
      SHELL_VAR *var;
 {
   int rv;
-  char *p;
 
   rv = get_random_number ();
-  p = itos (rv);
-
-  FREE (value_cell (var));
-
-  VSETATTR (var, att_integer);
-  var_setvalue (var, p);
-  return (var);
+  return (set_int_value (var, rv, 1));
 }
 
 static SHELL_VAR *
@@ -1403,16 +1425,9 @@ get_urandom (var)
      SHELL_VAR *var;
 {
   u_bits32_t rv;
-  char *p;
 
   rv = get_urandom32 ();
-  p = itos (rv);
-
-  FREE (value_cell (var));
-
-  VSETATTR (var, att_integer);
-  var_setvalue (var, p);
-  return (var);
+  return (set_int_value (var, rv, 1));
 }
 
 static SHELL_VAR *
@@ -1435,14 +1450,10 @@ static SHELL_VAR *
 get_lineno (var)
      SHELL_VAR *var;
 {
-  char *p;
   int ln;
 
   ln = executing_line_number ();
-  p = itos (ln);
-  FREE (value_cell (var));
-  var_setvalue (var, p);
-  return (var);
+  return (set_int_value (var, ln, 0));
 }
 
 static SHELL_VAR *
@@ -1464,12 +1475,7 @@ static SHELL_VAR *
 get_subshell (var)
      SHELL_VAR *var;
 {
-  char *p;
-
-  p = itos (subshell_level);
-  FREE (value_cell (var));
-  var_setvalue (var, p);
-  return (var);
+  return (set_int_value (var, subshell_level, 0));
 }
 
 static SHELL_VAR *
@@ -1477,14 +1483,9 @@ get_epochseconds (var)
      SHELL_VAR *var;
 {
   intmax_t now;
-  char *p;
 
   now = NOW;
-  p = itos (now);
-
-  FREE (value_cell (var));
-  var_setvalue (var, p);
-  return (var);
+  return (set_int_value (var, now, 0));
 }
 
 static SHELL_VAR *
@@ -1492,7 +1493,6 @@ get_epochrealtime (var)
      SHELL_VAR *var;
 {
   char buf[32];
-  char *p;
   struct timeval tv;
 
   gettimeofday (&tv, NULL);
@@ -1500,10 +1500,7 @@ get_epochrealtime (var)
                                           locale_decpoint (),
                                           (unsigned)tv.tv_usec);
 
-  p = savestring (buf);
-  FREE (value_cell (var));
-  var_setvalue (var, p);
-  return (var);
+  return (set_string_value (var, buf, 0));
 }
 
 static SHELL_VAR *
@@ -1511,27 +1508,16 @@ get_bashpid (var)
      SHELL_VAR *var;
 {
   int pid;
-  char *p;
 
   pid = getpid ();
-  p = itos (pid);
-
-  FREE (value_cell (var));
-  VSETATTR (var, att_integer); /* XXX - was also att_readonly */
-  var_setvalue (var, p);
-  return (var);
+  return (set_int_value (var, pid, 1));
 }
 
 static SHELL_VAR *
 get_bash_argv0 (var)
      SHELL_VAR *var;
 {
-  char *p;
-
-  p = savestring (dollar_vars[0]);
-  FREE (value_cell (var));
-  var_setvalue (var, p);
-  return var;
+  return (set_string_value (var, dollar_vars[0], 0));
 }
 
 static char *static_shell_name = 0;
@@ -1576,16 +1562,8 @@ get_bash_command (var)
 {
   char *p;
 
-  if (the_printed_command_except_trap)
-    p = savestring (the_printed_command_except_trap);
-  else
-    {
-      p = (char *)xmalloc (1);
-      p[0] = '\0';
-    }
-  FREE (value_cell (var));
-  var_setvalue (var, p);
-  return (var);
+  p = the_printed_command_except_trap ? the_printed_command_except_trap : "";
+  return (set_string_value (var, p, 0));
 }
 
 #if defined (HISTORY)
@@ -1593,7 +1571,6 @@ static SHELL_VAR *
 get_histcmd (var)
      SHELL_VAR *var;
 {
-  char *p;
   int n;
 
   /* Do the same adjustment here we do in parse.y:prompt_history_number,
@@ -1604,10 +1581,7 @@ get_histcmd (var)
      already been saved to history and the history number incremented.
      Right now we use EXECUTING as the determinant. */
   n = history_number () - executing;
-  p = itos (n);
-  FREE (value_cell (var));
-  var_setvalue (var, p);
-  return (var);
+  return (set_int_value (var, n, 0));
 }
 #endif
 
@@ -1621,10 +1595,7 @@ get_comp_wordbreaks (var)
   if (rl_completer_word_break_characters == 0 && bash_readline_initialized == 0)
     enable_hostname_completion (perform_hostname_completion);
 
-  FREE (value_cell (var));
-  var_setvalue (var, savestring (rl_completer_word_break_characters));
-
-  return (var);
+  return (set_string_value (var, rl_completer_word_break_characters, 0));
 }
 
 /* When this function returns, rl_completer_word_break_characters points to
@@ -1860,13 +1831,8 @@ get_funcname (self)
      SHELL_VAR *self;
 {
 #if ! defined (ARRAY_VARS)
-  char *t;
   if (variable_context && this_shell_function)
-    {
-      FREE (value_cell (self));
-      t = savestring (this_shell_function->name);
-      var_setvalue (self, t);
-    }
+    return (set_string_value (self, this_shell_function->name, 0));
 #endif
   return (self);
 }