CVS update: /ccvs/, /ccvs/src/

[email protected] 27 May 2005 18:07:51 -0000
Newsgroups gmane.comp.version-control.cvs.cvs
Message-ID <[email protected]>
User: dprice  
Date: 05/05/27 11:07:51

Modified:
 /ccvs/
  BUGS, ChangeLog, NEWS
 /ccvs/src/
  ChangeLog, client.c, client.h, cvs.h, diff.c, patch.c, rcs.c, rcscmds.c, run.c,
  sanity.sh, update.c

Log:
 Merge changes from 1.11.x.

File Changes:

Directory: /ccvs/
=================

File [changed]: BUGS
Url: https://ccvs.cvshome.org/source/browse/ccvs/BUGS?r1=1.78&r2=1.79
Delta lines:  +0 -7
-------------------
--- BUGS	20 Nov 2004 23:42:58 -0000	1.78
+++ BUGS	27 May 2005 18:07:47 -0000	1.79
@@ -88,13 +88,6 @@
 noticed under BSDI.
 
 
-* Spaces in arguments to `cvs diff' are currently split on spaces and tabs
-before being passed to diff.  This can often cause diff to abort since it can
-no longer interpret its options string and if it can, coincidentally,
-interpret its option string, then the problem may be output in unexpected
-formats.
-
-
 * The CVS server is leaving a temp directory (/tmp/cvs-serv*) on AIX 4.3 under
 very rare circumstances (one out of c. 10,500 test cases).  This appears to be
 dependent on some sort of race condition as it disappears with tracing enabled

File [changed]: ChangeLog
Url: https://ccvs.cvshome.org/source/browse/ccvs/ChangeLog?r1=1.1216&r2=1.1217
Delta lines:  +5 -0
-------------------
--- ChangeLog	27 May 2005 18:06:08 -0000	1.1216
+++ ChangeLog	27 May 2005 18:07:47 -0000	1.1217
@@ -1,5 +1,10 @@
 2005-05-27  Derek Price  <[email protected]>
 
+	* NEWS: Note diff space split fix.
+	* BUGS: Remove diff space split note.
+
+2005-05-27  Derek Price  <[email protected]>
+
 	* maint-aux/gnulib-modules: Add quotearg module.
 
 2005-05-26  Derek Price  <[email protected]>

File [changed]: NEWS
Url: https://ccvs.cvshome.org/source/browse/ccvs/NEWS?r1=1.319&r2=1.320
Delta lines:  +2 -0
-------------------
--- NEWS	11 May 2005 20:07:21 -0000	1.319
+++ NEWS	27 May 2005 18:07:47 -0000	1.320
@@ -23,6 +23,8 @@
 
 BUG FIXES
 
+* `cvs diff' no longer splits its arguments on spaces.
+
 * Thanks to an old report and patch from Stewart Brodie <[email protected]>, a
   potential crash in response to a corrupt RCS file has been fixed.
 

Directory: /ccvs/src/
=====================

File [changed]: ChangeLog
Url: https://ccvs.cvshome.org/source/browse/ccvs/src/ChangeLog?r1=1.3200&r2=1.3201
Delta lines:  +23 -0
--------------------
--- ChangeLog	26 May 2005 17:48:05 -0000	1.3200
+++ ChangeLog	27 May 2005 18:07:48 -0000	1.3201
@@ -1,3 +1,26 @@
+2005-05-27  Derek Price  <[email protected]>
+
+	* client.c (send_arg): Make arg const.  Remove unnecessary copy to
+	buffer.
+	(send_option_string): Rename to...
+	(send_options): ...this and accept argc/argv in place of string.
+	* client.h: Update protos to match the changes to client.c.
+	* cvs.h (RCS_exec_rcsdiff, diff_exec): Update protos.
+	(run_add_arg_p, run_arg_free_p): New protos.
+	* diff.c (opts, opts_allocated): Replace with...
+	(diff_argv, diff_argc, diff_arg_allocated): ...these.
+	(add_diff_args): New convenience function.
+	(diff): Use new constructs and APIs.
+	* patch.c (patch_fileproc, RCS_checkin, RCS_delete_revs), rcscmds.c
+	(call_diff_add_arg, call_diff_setup, RCS_merge, RCS_exec_rcsdiff,
+	diff_exec, RCS_output_diff_options), update.c (patch_file): Use new
+	APIs.
+	* run.c (run_add_arg_p, run_arg_free_p): New functions.
+	(run_argc_allocated): Make size_t.
+	(run_setup, run_add_arg): Use new functions.
+	* sanity.sh: Accomodate above changes.
+	(rcslib-diffrgx-3): Slip in test for space splitting.
+
 2005-05-26  Derek Price  <[email protected]>
 
 	* subr.c (isabsolute), subr.h (isabsolute): Remove this function.

File [changed]: client.c
Url: https://ccvs.cvshome.org/source/browse/ccvs/src/client.c?r1=1.425&r2=1.426
Delta lines:  +7 -32
--------------------
--- client.c	26 May 2005 17:48:05 -0000	1.425
+++ client.c	27 May 2005 18:07:48 -0000	1.426
@@ -4177,7 +4177,6 @@
 void
 send_arg (const char *string)
 {
-    char buf[1];
     const char *p = string;
 
     send_to_server ("Argument ", 0);
@@ -4185,14 +4184,9 @@
     while (*p)
     {
 	if (*p == '\n')
-	{
 	    send_to_server ("\012Argumentx ", 0);
-	}
 	else
-        {
-	    buf[0] = *p;
-	    send_to_server (buf, 1);
-        }
+	    send_to_server (p, 1);
 	++p;
     }
     send_to_server ("\012", 1);
@@ -4645,35 +4639,16 @@
 
 
 /*
- * Send each option in a string to the server, one by one.
- * This assumes that the options are separated by spaces, for example
- * STRING might be "--foo -C5 -y".
+ * Send each option in an array to the server, one by one.
+ * argv might be "--foo=bar",  "-C", "5", "-y".
  */
 
 void
-send_option_string (const char *string)
+send_options (int argc, char * const *argv)
 {
-    char *copy;
-    char *p;
-
-    copy = xstrdup (string);
-    p = copy;
-    while (1)
-    {
-        char *s;
-	char l;
-
-	for (s = p; *s != ' ' && *s != '\0'; s++)
-	    ;
-	l = *s;
-	*s = '\0';
-	if (s != p)
-	    send_arg (p);
-	if (l == '\0')
-	    break;
-	p = s + 1;
-    }
-    free (copy);
+    int i;
+    for (i = 0; i < argc; i++)
+	send_arg (argv[i]);
 }
 
 

File [changed]: client.h
Url: https://ccvs.cvshome.org/source/browse/ccvs/src/client.h?r1=1.55&r2=1.56
Delta lines:  +1 -1
-------------------
--- client.h	12 Oct 2004 00:59:44 -0000	1.55
+++ client.h	27 May 2005 18:07:48 -0000	1.56
@@ -114,7 +114,7 @@
 
 /* Send a string of single-char options to the remote server, one by one.  */
 void
-send_option_string (const char *string);
+send_options (int argc, char * const *argv);
 
 void send_a_repository (const char *, const char *, const char *);
 

File [changed]: cvs.h
Url: https://ccvs.cvshome.org/source/browse/ccvs/src/cvs.h?r1=1.336&r2=1.337
Delta lines:  +5 -3
-------------------
--- cvs.h	26 May 2005 17:12:54 -0000	1.336
+++ cvs.h	27 May 2005 18:07:48 -0000	1.337
@@ -425,15 +425,15 @@
 #define RCS_FLAGS_KEEPFILE 16
 #define RCS_FLAGS_USETIME 32
 
-int RCS_exec_rcsdiff (RCSNode *rcsfile,
-                      const char *opts, const char *options,
+int RCS_exec_rcsdiff (RCSNode *rcsfile, int diff_argc,
+                      char * const *diff_argv, const char *options,
                       const char *rev1, const char *rev1_cache,
                       const char *rev2,
                       const char *label1, const char *label2,
                       const char *workfile);
 int diff_exec (const char *file1, const char *file2,
                const char *label1, const char *label2,
-               const char *options, const char *out);
+               int iargc, char * const *iargv, const char *out);
 
 
 #include "error.h"
@@ -670,6 +670,8 @@
 #define	RUN_SIGIGNORE         0x0010    /* ignore interrupts for command */
 #define	RUN_TTY               (char *)0 /* for the benefit of lint */
 
+void run_add_arg_p (int *, size_t *, char ***, const char *s);
+void run_arg_free_p (int, char **);
 void run_add_arg (const char *s);
 void run_print (FILE * fp);
 void run_setup (const char *prog);

File [changed]: diff.c
Url: https://ccvs.cvshome.org/source/browse/ccvs/src/diff.c?r1=1.115&r2=1.116
Delta lines:  +61 -42
---------------------
--- diff.c	11 Mar 2005 16:55:40 -0000	1.115
+++ diff.c	27 May 2005 18:07:48 -0000	1.116
@@ -60,8 +60,9 @@
 static char *user_file_rev;
 
 static char *options;
-static char *opts;
-static size_t opts_allocated = 1;
+static char **diff_argv;
+static int diff_argc;
+static size_t diff_arg_allocated;
 static int diff_errors;
 static int empty_files;
 
@@ -206,6 +207,46 @@
     {0, 0, 0, 0}
 };
 
+
+
+/* Add one of OPT or LONGOPT, and ARGUMENT, when present, to global DIFF_ARGV.
+ *
+ * INPUTS
+ *   opt		A character option representation.
+ *   longopt		A long option name.
+ *   argument		Optional option argument.
+ *   
+ * GLOBALS
+ *   diff_argc		The number of arguments in DIFF_ARGV.
+ *   diff_argv		Array of argument strings.
+ *   diff_arg_allocated	Allocated length of DIFF_ARGV.
+ *
+ * NOTES
+ *   Behavior when both OPT & LONGOPT are provided is undefined.
+ *
+ * RETURNS
+ *   Nothing.
+ */
+static void
+add_diff_args (char opt, const char *longopt, const char *argument)
+{
+    char *tmp;
+
+    /* Add opt or longopt to diff_arv.  */
+    assert (opt || (longopt && *longopt));
+    assert (!(opt && (longopt && *longopt)));
+    if (opt) tmp = Xasprintf ("-%c", opt);
+    else tmp = Xasprintf ("--%s", longopt);
+    run_add_arg_p (&diff_argc, &diff_arg_allocated, &diff_argv, tmp);
+    free (tmp);
+
+    /* When present, add ARGUMENT to DIFF_ARGV.  */
+    if (argument)
+	run_add_arg_p (&diff_argc, &diff_arg_allocated, &diff_argv, argument);
+}
+
+
+
 /* CVS 1.9 and similar versions seemed to have pretty weird handling
    of -y and -T.  In the cases where it called rcsdiff,
    they would have the meanings mentioned below.  In the cases where it
@@ -240,7 +281,6 @@
 int
 diff (int argc, char **argv)
 {
-    char tmp[50];
     int c, err = 0;
     int local = 0;
     int which;
@@ -261,12 +301,9 @@
     /* Clean out our global variables (multiroot can call us multiple
        times and the server can too, if the client sends several
        diff commands).  */
-    if (opts == NULL)
-    {
-	opts_allocated = 1;
-	opts = xmalloc (opts_allocated);
-    }
-    opts[0] = '\0';
+    run_arg_free_p (diff_argc, diff_argv);
+    diff_argc = 0;
+
     diff_orig1 = NULL;
     diff_orig2 = NULL;
     diff_rev1 = NULL;
@@ -289,7 +326,7 @@
 	switch (c)
 	{
 	    case 'y':
-		xrealloc_and_strcat (&opts, &opts_allocated, " --side-by-side");
+		add_diff_args (0, "side-by-side", NULL);
 		break;
 	    case 'a': case 'b': case 'c': case 'd': case 'e': case 'f':
 	    case 'h': case 'i': case 'n': case 'p': case 's': case 't':
@@ -297,8 +334,7 @@
             case '0': case '1': case '2': case '3': case '4': case '5':
             case '6': case '7': case '8': case '9':
 	    case 'B': case 'H': case 'T':
-		(void) sprintf (tmp, " -%c", (char) c);
-		xrealloc_and_strcat (&opts, &opts_allocated, tmp);
+		add_diff_args (c, NULL, NULL);
 		break;
 	    case 'L':
 		if (have_rev1_label++)
@@ -307,33 +343,15 @@
 			error (0, 0, "extra -L arguments ignored");
 			break;
 		    }
-
-	        xrealloc_and_strcat (&opts, &opts_allocated, " -L");
-	        xrealloc_and_strcat (&opts, &opts_allocated, optarg);
-		break;
+		/* Fall through.  */
 	    case 'C': case 'F': case 'I': case 'U': case 'W':
-		(void) sprintf (tmp, " -%c", (char) c);
-		xrealloc_and_strcat (&opts, &opts_allocated, tmp);
-		xrealloc_and_strcat (&opts, &opts_allocated, optarg);
+		add_diff_args (c, NULL, optarg);
 		break;
-	    case 131:
-		/* --ifdef.  */
-		xrealloc_and_strcat (&opts, &opts_allocated, " --ifdef=");
-		xrealloc_and_strcat (&opts, &opts_allocated, optarg);
-		break;
-	    case 129: case 130:           case 132: case 133: case 134:
+	    case 129: case 130: case 131: case 132: case 133: case 134:
 	    case 135: case 136: case 137: case 138: case 139: case 140:
 	    case 141: case 142: case 143: case 145: case 146:
-		xrealloc_and_strcat (&opts, &opts_allocated, " --");
-		xrealloc_and_strcat (&opts, &opts_allocated,
-				     longopts[option_index].name);
-		if (longopts[option_index].has_arg == 1
-		    || (longopts[option_index].has_arg == 2
-			&& optarg != NULL))
-		{
-		    xrealloc_and_strcat (&opts, &opts_allocated, "=");
-		    xrealloc_and_strcat (&opts, &opts_allocated, optarg);
-		}
+		add_diff_args (0, longopts[option_index].name,
+			      longopts[option_index].has_arg ? optarg : NULL);
 		break;
 	    case 'R':
 		local = 0;
@@ -397,7 +415,7 @@
 	    send_arg("-l");
 	if (empty_files)
 	    send_arg("-N");
-	send_option_string (opts);
+	send_options (diff_argc, diff_argv);
 	if (options[0] != '\0')
 	    send_arg (options);
 	if (diff_orig1)
@@ -701,8 +719,8 @@
 	if (empty_file == DIFF_ADDED)
 	{
 	    if (use_rev2 == NULL)
-                status = diff_exec (DEVNULL, finfo->file, label1, label2, opts,
-                                    RUN_TTY);
+                status = diff_exec (DEVNULL, finfo->file, label1, label2,
+				    diff_argc, diff_argv, RUN_TTY);
 	    else
 	    {
 		int retcode;
@@ -714,8 +732,8 @@
 		if (retcode != 0)
 		    goto out;
 
-		status = diff_exec (DEVNULL, tmp, label1, label2, opts,
-		                    RUN_TTY);
+		status = diff_exec (DEVNULL, tmp, label1, label2,
+				    diff_argc, diff_argv, RUN_TTY);
 	    }
 	}
 	else
@@ -729,12 +747,13 @@
 	    if (retcode != 0)
 		goto out;
 
-	    status = diff_exec (tmp, DEVNULL, label1, label2, opts, RUN_TTY);
+	    status = diff_exec (tmp, DEVNULL, label1, label2,
+				diff_argc, diff_argv, RUN_TTY);
 	}
     }
     else
     {
-	status = RCS_exec_rcsdiff (vers->srcfile, opts,
+	status = RCS_exec_rcsdiff (vers->srcfile, diff_argc, diff_argv,
                                    *options ? options : vers->options,
                                    use_rev1, rev1_cache, use_rev2,
                                    label1, label2, finfo->file);

File [changed]: patch.c
Url: https://ccvs.cvshome.org/source/browse/ccvs/src/patch.c?r1=1.103&r2=1.104
Delta lines:  +12 -2
--------------------
--- patch.c	18 Apr 2005 19:32:32 -0000	1.103
+++ patch.c	27 May 2005 18:07:48 -0000	1.104
@@ -392,6 +392,9 @@
     char *cp1, *cp2;
     FILE *fp;
     int line_length;
+    int dargc = 0;
+    size_t darg_allocated = 0;
+    char **dargv = NULL;
 
     line1 = NULL;
     line1_chars_allocated = 0;
@@ -567,7 +570,9 @@
 	    (void)utime (tmpfile2, &t);
     }
 
-    switch (diff_exec (tmpfile1, tmpfile2, NULL, NULL, unidiff ? "-u" : "-c",
+    if (unidiff) run_add_arg_p (&dargc, &darg_allocated, &dargv, "-u");
+    else run_add_arg_p (&dargc, &darg_allocated, &dargv, "-c");
+    switch (diff_exec (tmpfile1, tmpfile2, NULL, NULL, dargc, dargv,
                        tmpfile3))
     {
 	case -1:			/* fork/wait failure */
@@ -726,6 +731,11 @@
     free (tmpfile2);
     free (tmpfile3);
     tmpfile1 = tmpfile2 = tmpfile3 = NULL;
+    if (darg_allocated)
+    {
+	run_arg_free_p (dargc, dargv);
+	free (dargv);
+    }
 
  out2:
     if (vers_tag != NULL)

File [changed]: rcs.c
Url: https://ccvs.cvshome.org/source/browse/ccvs/src/rcs.c?r1=1.347&r2=1.348
Delta lines:  +24 -8
--------------------
--- rcs.c	24 May 2005 20:59:01 -0000	1.347
+++ rcs.c	27 May 2005 18:07:48 -0000	1.348
@@ -5013,7 +5013,9 @@
     Deltatext *dtext;
     Node *nodep;
     char *tmpfile, *changefile;
-    char *diffopts;
+    int dargc = 0;
+    size_t darg_allocated = 0;
+    char **dargv = NULL;
     size_t bufsize;
     int status, checkin_quiet;
     struct tm *ftm;
@@ -5452,9 +5454,10 @@
 
     /* Diff options should include --binary if the RCS file has -kb set
        in its `expand' field. */
-    diffopts = (rcs->expand != NULL && STREQ (rcs->expand, "b")
-		? "-a -n --binary"
-		: "-a -n");
+    run_add_arg_p (&dargc, &darg_allocated, &dargv, "-a");
+    run_add_arg_p (&dargc, &darg_allocated, &dargv, "-n");
+    if (rcs->expand != NULL && STREQ (rcs->expand, "b"))
+	run_add_arg_p (&dargc, &darg_allocated, &dargv, "--binary");
 
     if (STREQ (commitpt->version, rcs->head) &&
 	numdots (delta->version) == 1)
@@ -5477,7 +5480,8 @@
 	memset (commitpt->text, 0, sizeof (Deltatext));
 
 	bufsize = 0;
-	switch (diff_exec (workfile, tmpfile, NULL, NULL, diffopts, changefile))
+	switch (diff_exec (workfile, tmpfile, NULL, NULL,
+			   dargc, dargv, changefile))
 	{
 	    case 0:
 	    case 1:
@@ -5525,7 +5529,8 @@
 	/* This file is not being inserted at the head, but on a side
 	   branch somewhere.  Make a diff from the previous revision
 	   to the working file. */
-	switch (diff_exec (tmpfile, workfile, NULL, NULL, diffopts, changefile))
+	switch (diff_exec (tmpfile, workfile, NULL, NULL,
+			   dargc, dargv, changefile))
 	{
 	    case 0:
 	    case 1:
@@ -5552,6 +5557,9 @@
 	}
     }
 
+    run_arg_free_p (dargc, dargv);
+    free (dargv);
+
     /* Update DELTA linkage.  It is important not to do this before
        the very end of RCS_checkin; if an error arises that forces
        us to abort checking in, we must not have malformed deltas
@@ -6604,6 +6612,10 @@
 	}
 	else
 	{
+	    int dargc = 0;
+	    size_t darg_allocated = 0;
+	    char **dargv = NULL;
+
 	    beforefile = cvs_temp_name();
 	    status = RCS_checkout (rcs, NULL, before, NULL, "-ko", beforefile,
 				   NULL, NULL);
@@ -6611,8 +6623,12 @@
 		goto delrev_done;
 
 	    outfile = cvs_temp_name();
-	    status = diff_exec (beforefile, afterfile, NULL, NULL, "-an",
-                                outfile);
+	    run_add_arg_p (&dargc, &darg_allocated, &dargv, "-a");
+	    run_add_arg_p (&dargc, &darg_allocated, &dargv, "-n");
+	    status = diff_exec (beforefile, afterfile, NULL, NULL,
+				dargc, dargv, outfile);
+	    run_arg_free_p (dargc, dargv);
+	    free (dargv);
 
 	    if (status == 2)
 	    {

File [changed]: rcscmds.c
Url: https://ccvs.cvshome.org/source/browse/ccvs/src/rcscmds.c?r1=1.69&r2=1.70
Delta lines:  +66 -81
---------------------
--- rcscmds.c	24 May 2005 20:59:02 -0000	1.69
+++ rcscmds.c	27 May 2005 18:07:48 -0000	1.70
@@ -17,6 +17,7 @@
 #include "cvs.h"
 #include <stdio.h>
 #include "diffrun.h"
+#include "quotearg.h"
 
 /* This file, rcs.h, and rcs.c, together sometimes known as the "RCS
    library", are intended to define our interface to RCS files.
@@ -55,8 +56,8 @@
    On a related note, see the comments at diff_exec, later in this file,
    for more on the diff library.  */
 
-static void RCS_output_diff_options (const char *, const char *, const char *,
-                                     const char *);
+static void RCS_output_diff_options (int, char * const *, const char *,
+				     const char *, const char *);
 
 
 /* Stuff to deal with passing arguments the way libdiff.a wants to deal
@@ -68,7 +69,7 @@
    argument will be parsed into whitespace separated words and added
    to the global call_diff_argv list.
 
-   Then, optionally, call call_diff_arg for each additional argument
+   Then, optionally, call call_diff_add_arg for each additional argument
    that you'd like to pass to the diff library.
 
    Finally, call call_diff or call_diff3 to produce the diffs.  */
@@ -77,8 +78,6 @@
 static int call_diff_argc;
 static int call_diff_argc_allocated;
 
-static void call_diff_add_arg (const char *);
-static void call_diff_setup (const char *prog);
 static int call_diff (const char *out);
 static int call_diff3 (char *out);
 
@@ -87,59 +86,35 @@
 static void call_diff_write_stdout (const char *);
 static void call_diff_error (const char *, const char *, const char *);
 
+
+
 /* VARARGS */
 static void 
-call_diff_setup (const char *prog)
+call_diff_add_arg (const char *s)
+{
+    TRACE (TRACE_DATA, "call_diff_add_arg (%s)", s);
+    run_add_arg_p (&call_diff_argc, &call_diff_argc_allocated, &call_diff_argv,
+		   s);
+}
+
+
+
+static void 
+call_diff_setup (const char *prog, int argc, char * const *argv)
 {
-    char *cp;
     int i;
-    char *call_diff_prog;
 
     /* clean out any malloc'ed values from call_diff_argv */
-    for (i = 0; i < call_diff_argc; i++)
-    {
-	if (call_diff_argv[i])
-	{
-	    free (call_diff_argv[i]);
-	    call_diff_argv[i] = NULL;
-	}
-    }
+    run_arg_free_p (call_diff_argc, call_diff_argv);
     call_diff_argc = 0;
 
-    call_diff_prog = xstrdup (prog);
-
     /* put each word into call_diff_argv, allocating it as we go */
-    for (cp = strtok (call_diff_prog, " \t");
-	 cp != NULL;
-	 cp = strtok (NULL, " \t"))
-	call_diff_add_arg (cp);
-    free (call_diff_prog);
-}
-
-static void
-call_diff_arg (const char *s)
-{
-    call_diff_add_arg (s);
+    call_diff_add_arg (prog);
+    for (i = 0; i < argc; i++)
+	call_diff_add_arg (argv[i]);
 }
 
-static void
-call_diff_add_arg (const char *s)
-{
-    /* allocate more argv entries if we've run out */
-    if (call_diff_argc >= call_diff_argc_allocated)
-    {
-	call_diff_argc_allocated += 50;
-	call_diff_argv = xnrealloc (call_diff_argv,
-				    call_diff_argc_allocated,
-				    sizeof (char **));
-    }
 
-    if (s)
-	call_diff_argv[call_diff_argc++] = xstrdup (s);
-    else
-	/* Not post-incremented on purpose!  */
-	call_diff_argv[call_diff_argc] = NULL;
-}
 
 /* Callback function for the diff library to write data to the output
    file.  This is used when we are producing output to stdout.  */
@@ -205,6 +180,8 @@
 static int
 call_diff (const char *out)
 {
+    call_diff_add_arg (NULL);
+
     if (out == RUN_TTY)
 	return diff_run( call_diff_argc, call_diff_argv, NULL,
 			 &call_diff_stdout_callbacks );
@@ -291,21 +268,21 @@
     /* Remember that the first word in the `call_diff_setup' string is used now
        only for diagnostic messages -- CVS no longer forks to run diff3. */
     diffout = cvs_temp_name();
-    call_diff_setup ("diff3");
-    call_diff_arg ("-E");
-    call_diff_arg ("-am");
-
-    call_diff_arg ("-L");
-    call_diff_arg (workfile);
-    call_diff_arg ("-L");
-    call_diff_arg (xrev1);
-    call_diff_arg ("-L");
-    call_diff_arg (xrev2);
-
-    call_diff_arg ("--");
-    call_diff_arg (workfile);
-    call_diff_arg (tmp1);
-    call_diff_arg (tmp2);
+    call_diff_setup ("diff3", 0, NULL);
+    call_diff_add_arg ("-E");
+    call_diff_add_arg ("-am");
+
+    call_diff_add_arg ("-L");
+    call_diff_add_arg (workfile);
+    call_diff_add_arg ("-L");
+    call_diff_add_arg (xrev1);
+    call_diff_add_arg ("-L");
+    call_diff_add_arg (xrev2);
+
+    call_diff_add_arg ("--");
+    call_diff_add_arg (workfile);
+    call_diff_add_arg (tmp1);
+    call_diff_add_arg (tmp2);
 
     retval = call_diff3 (diffout);
 
@@ -371,7 +348,8 @@
    about this--any such features are undocumented in the context of
    CVS, and I'm not sure how important to users.  */
 int
-RCS_exec_rcsdiff (RCSNode *rcsfile, const char *opts, const char *options,
+RCS_exec_rcsdiff (RCSNode *rcsfile, int diff_argc,
+		  char * const *diff_argv, const char *options,
                   const char *rev1, const char *rev1_cache, const char *rev2,
                   const char *label1, const char *label2, const char *workfile)
 {
@@ -446,8 +424,9 @@
 	use_file2 = tmpfile2;
     }
 
-    RCS_output_diff_options (opts, rev1, rev2, workfile);
-    status = diff_exec( use_file1, use_file2, label1, label2, opts, RUN_TTY );
+    RCS_output_diff_options (diff_argc, diff_argv, rev1, rev2, workfile);
+    status = diff_exec (use_file1, use_file2, label1, label2,
+			diff_argc, diff_argv, RUN_TTY);
     if (status >= 0)
     {
 	retval = status;
@@ -527,9 +506,11 @@
 
 int
 diff_exec (const char *file1, const char *file2, const char *label1,
-           const char *label2, const char *options, const char *out)
+           const char *label2, int dargc, char * const *dargv,
+	   const char *out)
 {
-    char *args;
+    TRACE (TRACE_FUNCTION, "diff_exec (%s, %s, %s, %s, %s)",
+	   file1, file2, label1, label2, out);
 
 #ifdef PRESERVE_PERMISSIONS_SUPPORT
     /* If either file1 or file2 are special files, pretend they are
@@ -564,17 +545,15 @@
     }
 #endif
 
-    /* The first word in this string is used only for error reporting. */
-    args = Xasprintf ("diff %s", options);
-    call_diff_setup (args);
+    /* The first arg to call_diff_setup is used only for error reporting. */
+    call_diff_setup ("diff", dargc, dargv);
     if (label1)
-	call_diff_arg (label1);
+	call_diff_add_arg (label1);
     if (label2)
-	call_diff_arg (label2);
-    call_diff_arg ("--");
-    call_diff_arg (file1);
-    call_diff_arg (file2);
-    free (args);
+	call_diff_add_arg (label2);
+    call_diff_add_arg ("--");
+    call_diff_add_arg (file1);
+    call_diff_add_arg (file2);
 
     return call_diff (out);
 }
@@ -586,14 +565,20 @@
    that I have seen. */
 
 static void
-RCS_output_diff_options (const char *opts, const char *rev1, const char *rev2,
+RCS_output_diff_options (int diff_argc, char * const *diff_argv,
+			 const char *rev1, const char *rev2,
                          const char *workfile)
 {
-    char *tmp;
+    int i;
 
-    tmp = Xasprintf ("diff%s -r%s", opts, rev1);
-    cvs_output (tmp, 0);
-    free (tmp);
+    cvs_output ("diff", 0);
+    for (i = 0; i < diff_argc; i++)
+    {
+        cvs_output (" ", 1);
+	cvs_output (quotearg_style (shell_quoting_style, diff_argv[i]), 0);
+    }
+    cvs_output (" -r", 3);
+    cvs_output (rev1, 0);
 
     if (rev2)
     {

File [changed]: run.c
Url: https://ccvs.cvshome.org/source/browse/ccvs/src/run.c?r1=1.57&r2=1.58
Delta lines:  +31 -18
---------------------
--- run.c	22 Mar 2005 13:19:58 -0000	1.57
+++ run.c	27 May 2005 18:07:48 -0000	1.58
@@ -25,8 +25,8 @@
  * arguments.  The argument to run_setup will be parsed into whitespace 
  * separated words and added to the global run_argv list.
  * 
- * Then, optionally call run_arg() for each additional argument that you'd like
- * to pass to the executed program.
+ * Then, optionally call run_add_arg() for each additional argument that you'd
+ * like to pass to the executed program.
  * 
  * Finally, call run_exec() to execute the program with the specified arguments.
  * The execvp() syscall will be used, so that the PATH is searched correctly.
@@ -34,13 +34,24 @@
  */
 static char **run_argv;
 static int run_argc;
-static int run_argc_allocated;
+static size_t run_arg_allocated;
+
+
+
+void
+run_arg_free_p (int argc, char **argv)
+{
+    int i;
+    for (i = 0; i < argc; i++)
+	free (argv[i]);
+}
+
+
 
 /* VARARGS */
 void 
 run_setup (const char *prog)
 {
-    int i;
     char *run_prog;
     char *buf, *d, *s;
     size_t length;
@@ -49,14 +60,7 @@
     int dolastarg;
 
     /* clean out any malloc'ed values from run_argv */
-    for (i = 0; i < run_argc; i++)
-    {
-	if (run_argv[i])
-	{
-	    free (run_argv[i]);
-	    run_argv[i] = NULL;
-	}
-    }
+    run_arg_free_p (run_argc, run_argv);
     run_argc = 0;
 
     run_prog = xstrdup (prog);
@@ -111,19 +115,28 @@
 
 
 void
-run_add_arg (const char *s)
+run_add_arg_p (int *iargc, size_t *iarg_allocated, char ***iargv,
+	       const char *s)
 {
     /* allocate more argv entries if we've run out */
-    if (run_argc >= run_argc_allocated)
+    if (*iargc >= *iarg_allocated)
     {
-	run_argc_allocated += 50;
-	run_argv = xnrealloc (run_argv, run_argc_allocated, sizeof (char **));
+	*iarg_allocated += 50;
+	*iargv = xnrealloc (*iargv, *iarg_allocated, sizeof (char **));
     }
 
     if (s)
-	run_argv[run_argc++] = xstrdup (s);
+	(*iargv)[(*iargc)++] = xstrdup (s);
     else
-	run_argv[run_argc] = NULL;	/* not post-incremented on purpose! */
+	(*iargv)[*iargc] = NULL;	/* not post-incremented on purpose! */
+}
+
+
+
+void
+run_add_arg (const char *s)
+{
+    run_add_arg_p (&run_argc, &run_arg_allocated, &run_argv, s);
 }
 
 

File [changed]: sanity.sh
Url: https://ccvs.cvshome.org/source/browse/ccvs/src/sanity.sh?r1=1.1064&r2=1.1065
Delta lines:  +7 -4
-------------------
--- sanity.sh	23 May 2005 14:19:53 -0000	1.1064
+++ sanity.sh	27 May 2005 18:07:48 -0000	1.1065
@@ -2917,7 +2917,7 @@
 ===================================================================
 RCS file: ${CVSROOT_DIRNAME}/first-dir/sdir/ssdir/ssfile,v
 
-diff -c -C3isacrowd -r1\.1 ssfile
+diff -c -C 3isacrowd -r1\.1 ssfile
 ${SPROG} diff: invalid context length argument"
 	  dotest basica-7 "${testcvs} -q ci -m modify-it" \
 "$CVSROOT_DIRNAME/first-dir/sdir/ssdir/ssfile,v  <--  sdir/ssdir/ssfile
@@ -5655,7 +5655,7 @@
 ===================================================================
 RCS file: ${CVSROOT_DIRNAME}/first-dir/abc,v
 
-diff --ifdef=HAVE_WINSOCK_H -r1\.2 abc
+diff --ifdef HAVE_WINSOCK_H -r1\.2 abc
 #ifndef HAVE_WINSOCK_H
 extern int gethostname ();
 #else /\* HAVE_WINSOCK_H \*/
@@ -8612,12 +8612,15 @@
 }
 EOF
 	  # Use dotest_fail because exit status from `cvs diff' must be 1.
-	  dotest_fail rcslib-diffrgx-3 "${testcvs} diff -c -F'.*(' rgx.c" \
+	  #
+	  # Incidentally test that CVS no longer splits diff arguments on
+	  # spaces.
+	  dotest_fail rcslib-diffrgx-3 "$testcvs diff -c -F'.* (' rgx.c" \
 "Index: rgx\.c
 ===================================================================
 RCS file: ${CVSROOT_DIRNAME}/first-dir/rgx\.c,v
 
-diff -c -F\.\*( -r1\.1 rgx\.c
+diff -c -F '\.\* (' -r1\.1 rgx\.c
 \*\*\* rgx\.c	${RFCDATE}	1\.1
 --- rgx\.c	${RFCDATE}
 \*\*\*\*\*\*\*\*\*\*\*\*\*\*\* test_regex (whiz, bang)

File [changed]: update.c
Url: https://ccvs.cvshome.org/source/browse/ccvs/src/update.c?r1=1.253&r2=1.254
Delta lines:  +12 -15
---------------------
--- update.c	24 May 2005 20:59:02 -0000	1.253
+++ update.c	27 May 2005 18:07:49 -0000	1.254
@@ -1674,7 +1674,9 @@
     retcode = 0;
     if (! fail)
     {
-	char *diff_options;
+	int dargc = 0;
+	size_t darg_allocated = 0;
+	char **dargv = NULL;
 
 	/* If the client does not support the Rcs-diff command, we
            send a context diff, and the client must invoke patch.
@@ -1682,16 +1684,13 @@
            new approach only requires running diff in the server; the
            client can handle everything without invoking an external
            program.  */
-	if (! rcs_diff_patches)
-	{
+	if (!rcs_diff_patches)
 	    /* We use -c, not -u, because that is what CVS has
 	       traditionally used.  Kind of a moot point, now that
 	       Rcs-diff is preferred, so there is no point in making
 	       the compatibility issues worse.  */
-	    diff_options = "-c";
-	}
+	    run_add_arg_p (&dargc, &darg_allocated, &dargv, "-c");
 	else
-	{
 	    /* Now that diff is librarified, we could be passing -a if
 	       we wanted to.  However, it is unclear to me whether we
 	       would want to.  Does diff -a, in any significant
@@ -1701,20 +1700,18 @@
 	       'binary'.  Conversely, do they tend to be much larger
 	       in the bad cases?  This needs some more
 	       thought/investigation, I suspect.  */
-
-	    diff_options = "-n";
-	}
-	retcode = diff_exec (file1, file2, NULL, NULL, diff_options, finfo->file);
+	    run_add_arg_p (&dargc, &darg_allocated, &dargv, "-n");
+	retcode = diff_exec (file1, file2, NULL, NULL, dargc, dargv,
+			     finfo->file);
+	run_arg_free_p (dargc, dargv);
+	free (dargv);
 
 	/* A retcode of 0 means no differences.  1 means some differences.  */
-	if (retcode != 0
-	    && retcode != 1)
-	{
+	if (retcode != 0 && retcode != 1)
 	    fail = 1;
 	}
-    }
 
-    if (! fail)
+    if (!fail)
     {
 	struct stat file2_info;