--- sdiff.c_orig Tue Aug 31 19:38:21 2004 +++ sdiff.c Tue Aug 31 19:41:09 2004 @@ -40,6 +40,11 @@ #define DEFAULT_EDITOR_PROGRAM "ed" #endif +/* Default sdiff keys for merging, in addition to historical 'l'/'r'. */ +#ifndef DEFAULT_MERGE_KEYS +#define DEFAULT_MERGE_KEYS "12" +#endif + extern char version_string[]; static char const *program_name; static char const *diffbin = DIFF_PROGRAM; @@ -48,6 +53,8 @@ static char *tmpname; static int volatile tmpmade; +static char leftkey; +static char rightkey; #if HAVE_FORK static pid_t volatile diffpid; @@ -60,6 +67,7 @@ static VOID *xmalloc PARAMS((size_t)); static char const *expand_name PARAMS((char *, int, char const *)); static int edit PARAMS((struct line_filter *, int, struct line_filter *, int, FILE*)); +static int calleditor PARAMS((int, struct line_filter *, int, struct line_filter *, int, FILE*)); static int interact PARAMS((struct line_filter *, struct line_filter *, struct line_filter *, FILE*)); static int lf_snarf PARAMS((struct line_filter *, char *, size_t)); static int skip_white PARAMS((void)); @@ -401,7 +409,8 @@ int opt; char *editor; char *differ; - + char *keys; + initialize_main (&argc, &argv); program_name = argv[0]; @@ -414,6 +423,15 @@ diffarg ("diff"); + keys = getenv("SDIFF_MERGE_KEYS"); + if (keys && strlen(keys) == 2) { + leftkey = keys[0]; + rightkey = keys[1]; + } else { + leftkey = DEFAULT_MERGE_KEYS[0]; + rightkey = DEFAULT_MERGE_KEYS[1]; + } + /* parse command line args */ while ((opt = getopt_long (argc, argv, "abBdHiI:lo:stvw:W", longopts, 0)) != EOF) @@ -794,10 +813,10 @@ static void give_help () { - fprintf (stderr,"l:\tuse the left version\n"); - fprintf (stderr,"r:\tuse the right version\n"); - fprintf (stderr,"e l:\tedit then use the left version\n"); - fprintf (stderr,"e r:\tedit then use the right version\n"); + fprintf (stderr,"l or %c:\tuse the left version\n", leftkey); + fprintf (stderr,"r or %c:\tuse the right version\n", rightkey); + fprintf (stderr,"e %c:\tedit then use the left version\n", leftkey); + fprintf (stderr,"e %c:\tedit then use the right version\n", rightkey); fprintf (stderr,"e b:\tedit then use the left and right versions concatenated\n"); fprintf (stderr,"e:\tedit a new version\n"); fprintf (stderr,"s:\tsilently include common lines\n"); @@ -841,197 +860,152 @@ int lenr; FILE *outfile; { - for (;;) - { - int cmd0, cmd1; - int gotcmd = 0; - - cmd1 = 0; /* Pacify `gcc -W'. */ - - while (!gotcmd) - { - if (putchar ('%') != '%') - perror_fatal ("output error"); - ck_fflush (stdout); - - cmd0 = skip_white (); - switch (cmd0) - { - case 'l': case 'r': case 's': case 'v': case 'q': - if (skip_white () != '\n') - { - give_help (); - flush_line (); - continue; - } - gotcmd = 1; - break; - - case 'e': - cmd1 = skip_white (); - switch (cmd1) - { - case 'l': case 'r': case 'b': - if (skip_white () != '\n') - { - give_help (); - flush_line (); - continue; - } - gotcmd = 1; - break; - case '\n': - gotcmd = 1; - break; - default: - give_help (); - flush_line (); - continue; - } - break; - case EOF: - if (feof (stdin)) - { - gotcmd = 1; - cmd0 = 'q'; - break; - } - /* falls through */ - default: - flush_line (); - /* falls through */ - case '\n': - give_help (); - continue; - } - } - - switch (cmd0) - { - case 'l': - lf_copy (left, lenl, outfile); - lf_skip (right, lenr); - return 1; - case 'r': - lf_copy (right, lenr, outfile); - lf_skip (left, lenl); - return 1; - case 's': - suppress_common_flag = 1; - break; - case 'v': - suppress_common_flag = 0; - break; - case 'q': - return 0; - case 'e': - { - int tfd; - FILE *tmp; - - if (tmpmade) - { - unlink (tmpname); - tmpmade = 0; - free (tmpname); - } - - asprintf (&tmpname, "%s/sdiff.XXXXXX", - getenv("TMPDIR") ?: P_tmpdir); - if (tmpname == NULL) - perror_fatal ("temporary file name"); - tfd = mkstemp(tmpname); - if (tfd == -1) - perror_fatal ("temporary file name"); - tmp = fdopen (tfd, "w+"); - if (tmp == NULL) - perror_fatal ("temporary file name"); - - tmpmade = 1; - - if (cmd1 == 'l' || cmd1 == 'b') - lf_copy (left, lenl, tmp); - else - lf_skip (left, lenl); - - if (cmd1 == 'r' || cmd1 == 'b') - lf_copy (right, lenr, tmp); - else - lf_skip (right, lenr); - - ck_fflush (tmp); + int cmd0, cmd1 = 0; + + for (;;) { + if (putchar ('%') != '%') + perror_fatal ("output error"); + ck_fflush (stdout); + + cmd0 = skip_white(); + if ((cmd0 == EOF) || (feof (stdin))) return 0; + + if ((cmd0 == 'l') || (cmd0 == leftkey)) { + lf_copy (left, lenl, outfile); + lf_skip (right, lenr); + flush_line(); + return 1; + } else if ((cmd0 == 'r') || (cmd0 == rightkey)) { + lf_copy (right, lenr, outfile); + lf_skip (left, lenl); + flush_line(); + return 1; + } else if (cmd0 == 's') { + suppress_common_flag = 1; + } else if (cmd0 == 'v') { + suppress_common_flag = 0; + } else if (cmd0 == 'q') { + return 0; + } else if (cmd0 == 'e') { + cmd1 = skip_white(); + if ((cmd1 == leftkey) || (cmd1 == rightkey) || + (cmd1 == 'l') || (cmd1 == 'r') || (cmd1 == 'b') || (cmd1 == '\n')) { + flush_line(); + return calleditor(cmd1, left, lenl, right, lenr, outfile); + } else { + give_help(); + } + } else if (cmd0 == '\n') { + continue; + } else { + give_help(); + } + flush_line(); + } +} - { - int wstatus; +/* Invoke the user's preferred editor on the data to be merged. */ +int calleditor(cmd1, left, lenl, right, lenr, outfile) + int cmd1; + struct line_filter *left; + int lenl; + struct line_filter *right; + int lenr; + FILE *outfile; +{ + int tfd; + FILE *tmp; + + if (tmpmade) { + unlink (tmpname); + tmpmade = 0; + free (tmpname); + } + + asprintf(&tmpname, "%s/sdiff.XXXXXX", getenv("TMPDIR") ?: P_tmpdir); + if (tmpname == NULL) + perror_fatal ("temporary file name"); + tfd = mkstemp(tmpname); + if (tfd == -1) + perror_fatal ("temporary file name"); + tmp = fdopen (tfd, "w+"); + if (tmp == NULL) + perror_fatal ("temporary file name"); + tmpmade = 1; + + if ((cmd1 == leftkey) || (cmd1 == 'l') || (cmd1 == 'b')) + lf_copy (left, lenl, tmp); + else + lf_skip (left, lenl); + + if ((cmd1 == rightkey) || (cmd1 == 'r') || (cmd1 == 'b')) + lf_copy (right, lenr, tmp); + else + lf_skip (right, lenr); + + ck_fflush (tmp); + + { + int wstatus; #if ! HAVE_FORK - char *command = xmalloc (strlen (edbin) + strlen (tmpname) + 2); - sprintf (command, "%s %s", edbin, tmpname); - wstatus = system (command); - free (command); + char *command = xmalloc (strlen (edbin) + strlen (tmpname) + 2); + sprintf (command, "%s %s", edbin, tmpname); + wstatus = system (command); + free (command); #else /* HAVE_FORK */ - pid_t pid; - - ignore_SIGINT = 1; - checksigs (); - - pid = vfork (); - if (pid == 0) - { - char const *argv[3]; - int i = 0; - - argv[i++] = edbin; - argv[i++] = tmpname; - argv[i++] = 0; - - execvp (edbin, (char **) argv); - write (STDERR_FILENO, edbin, strlen (edbin)); - write (STDERR_FILENO, ": not found\n", 12); - _exit (1); - } - - if (pid < 0) - perror_fatal ("fork failed"); - - while (waitpid (pid, &wstatus, 0) < 0) - if (errno == EINTR) - checksigs (); - else - perror_fatal ("wait failed"); - - ignore_SIGINT = 0; + pid_t pid; + + ignore_SIGINT = 1; + checksigs (); + + pid = vfork (); + if (pid == 0) { + char const *argv[3]; + int i = 0; + + argv[i++] = edbin; + argv[i++] = tmpname; + argv[i++] = 0; + + execvp (edbin, (char **) argv); + write (STDERR_FILENO, edbin, strlen (edbin)); + write (STDERR_FILENO, ": not found\n", 12); + _exit (1); + } + + if (pid < 0) + perror_fatal ("fork failed"); + + while (waitpid (pid, &wstatus, 0) < 0) + if (errno == EINTR) + checksigs (); + else + perror_fatal ("wait failed"); + + ignore_SIGINT = 0; #endif /* HAVE_FORK */ - - if (wstatus != 0) - fatal ("Subsidiary editor failed"); - } - - if (fseek (tmp, 0L, SEEK_SET) != 0) - perror_fatal ("fseek"); - { - /* SDIFF_BUFSIZE is too big for a local var - in some compilers, so we allocate it dynamically. */ - char *buf = xmalloc (SDIFF_BUFSIZE); - size_t size; - - while ((size = ck_fread (buf, SDIFF_BUFSIZE, tmp)) != 0) - { - checksigs (); - ck_fwrite (buf, size, outfile); - } - ck_fclose (tmp); - - free (buf); - } - return 1; - } - default: - give_help (); - break; - } + + if (wstatus != 0) + fatal ("Subsidiary editor failed"); + } + + if (fseek (tmp, 0L, SEEK_SET) != 0) + perror_fatal ("fseek"); + { + /* SDIFF_BUFSIZE is too big for a local var + in some compilers, so we allocate it dynamically. */ + char *buf = xmalloc (SDIFF_BUFSIZE); + size_t size; + + while ((size = ck_fread (buf, SDIFF_BUFSIZE, tmp)) != 0) { + checksigs (); + ck_fwrite (buf, size, outfile); } + ck_fclose(tmp); + free (buf); + } + return 1; } - /* Alternately reveal bursts of diff output and handle user commands. */