sdiff.c revision a85fbef1bf8ee04c3a4b2a244ce74b631fe41193
/*
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
* Common Development and Distribution License, Version 1.0 only
* (the "License"). You may not use this file except in compliance
* with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* See the License for the specific language governing permissions
* and limitations under the License.
*
* When distributing Covered Code, include this CDDL HEADER in each
* file and include the License file at usr/src/OPENSOLARIS.LICENSE.
* If applicable, add the following below this CDDL HEADER, with the
* fields enclosed by brackets "[]" replaced with your own identifying
* information: Portions Copyright [yyyy] [name of copyright owner]
*
* CDDL HEADER END
*/
/*
* Copyright 2005 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
/* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */
/* All Rights Reserved */
#pragma ident "%Z%%M% %I% %E% SMI"
/*
* sdiff [-l] [-s] [-w #] [-o output] file1 file2
* does side by side diff listing
* -l leftside only for identical lines
* -s silent; only print differences
* -w # width of output
* -o output interactive creation of new output commands:
* s silent; do not print identical lines
* v turn off silent
* l copy left side to output
* r copy right side to output
* e l call ed with left side
* e r call ed with right side
* e b call ed with cat of left and right
* e call ed with empty file
* q exit from program
*
* functions:
* cmd decode diff commands
* put1 output left side
* put2 output right side
* putmid output gutter
* putline output n chars to indicated file
* getlen calculate length of strings with tabs
* cmdin read and process interactive cmds
* cpp copy from file to file
* edit call ed with file
*/
#include <stdio.h>
#include <ctype.h>
#include <signal.h>
#include <unistd.h>
#include <stdlib.h>
#include <locale.h>
#include <limits.h>
#include <string.h>
#include <wchar.h>
#define STDOUT 1
#define WGUTTER 6
#define PROMPT '%'
static const char *DIFF = "diff -b ";
static char inbuf[10];
static int hlen; /* Half line length with space for gutter */
static int len1; /* Calculated length of left side */
static int nchars; /* Number of characters in left side - */
/* used for tab expansion */
static char change = ' ';
static int leftonly = 0; /* if set print left side only for */
/* identical lines */
static int silent = 0; /* if set do not print identical lines */
static int midflg = 0; /* set after middle was output */
static int rcode = 0; /* return code */
static char *file1;
static char *file2;
static int oflag;
static char *ofile;
static char *ltemp;
static char *rtemp;
static char *temp;
/* decoded diff cmd- left side from to; right side from, to */
static int tempfd = -1;
static char *filename(char *, char *);
static int put1(void);
static int put2(void);
static int cmd(char *);
static int getlen(int, char *);
static void putmid(int);
static void error(char *, char *);
static void onintr(void);
static void sremove(void);
static void cmdin(void);
static void edit(char *);
int
{
int com;
char *bp;
int lfd = -1;
int rfd = -1;
#if !defined(TEXT_DOMAIN)
#define TEXT_DOMAIN "SYS_TEST"
#endif
(void) textdomain(TEXT_DOMAIN);
switch (*++*argv) {
case 'w':
/* -w# instead of -w # */
if (*++*argv)
else {
argc--;
}
break;
case 'l':
leftonly++;
break;
case 's':
silent++;
break;
case 'o':
oflag++;
argc--;
break;
default:
}
}
if (argc != 2) {
"Usage: sdiff [-l] [-s] [-o output] [-w #] file1 file2\n"));
return (2);
}
if (oflag) {
if (tempfd == -1) {
if (tempfd == -1) {
temp = 0;
}
}
ltemp);
rtemp);
}
/* Call DIFF command */
/*
* Read in diff output and decode commands
* "change" is used to determine character to put in gutter
* num1 and num2 counts the number of lines in file1 and 2
*/
n = 0;
change = ' ';
/*
* handles all diff output that is not cmd
* lines starting with <, >, ., ---
*/
if (com == 0)
continue;
/* Catch up to from1 and from2 */
rcode = 1;
if (com == 'c' && n > 0)
n--;
if (silent)
while (n-- > 0) {
(void) put1();
(void) put2();
if (!silent)
midflg = 0;
}
/* Process diff cmd */
switch (com) {
case 'a':
change = '>';
(void) put2();
midflg = 0;
}
break;
case 'd':
change = '<';
(void) put1();
midflg = 0;
}
break;
case 'c':
change = '|';
do {
(void) put1();
(void) put2();
midflg = 0;
} while (n--);
change = '<';
(void) put1();
midflg = 0;
}
change = '>';
(void) put2();
midflg = 0;
}
break;
default:
"%c: cmd not found\n"), cmd);
break;
}
cmdin();
"main: Cannot open temp %s"), ltemp);
"main: Cannot open temp %s"), rtemp);
}
}
/* put out remainder of input files */
while (put1()) {
(void) put2();
if (!silent)
midflg = 0;
}
if (odes)
sremove();
return (rcode);
}
static int
put1(void)
{
/* len1 = length of left side */
/* nchars = num of chars including tabs */
char *bp;
if (oflag) {
/*
* put left side either to output file
* if identical to right
* or left temp file if not
*/
if (change == ' ')
else
}
if (change != ' ')
putmid(1);
num1++;
return (1);
} else
return (0);
}
static int
put2(void)
{
char *bp;
/*
* if the left and right are different they are always
* printed.
* If the left and right are identical
* right is only printed if leftonly is not specified
* or silent mode is not specified
* or the right contains other than white space (len1 !=0)
*/
if (change != ' ') {
/*
* put right side to right temp file only
* because left side was written to output for
* identical lines
*/
if (oflag)
if (midflg == 0)
putmid(1);
} else
if (midflg == 0)
putmid(1);
}
num2++;
len1 = 0;
return (1);
} else {
len1 = 0;
return (0);
}
}
static void
{
continue;
}
len = MB_LEN_MAX;
continue;
}
return;
for (i = 0; i < len; i++)
}
}
static int
{
unsigned char *cp;
char *cps;
int com;
return (0);
cp++;
if (*cp == ',') {
cp++;
cp++;
}
cp++;
if (*cp == ',') {
cp++;
cp++;
}
return (com);
}
static int
{
/*
* get the length of the string in buffer
* expand tabs to next multiple of 8
*/
unsigned char *cp;
int notspace;
nchars = 0;
notspace = 0;
if (*cp == '\t') {
break;
}
nchars++;
continue;
}
tlen++;
break;
}
notspace = 1;
nchars++;
continue;
}
tlen++;
break;
}
notspace = 1;
nchars++;
continue;
}
break;
}
notspace = 1;
}
}
static void
{
int i;
/*
* len1 set by getlen to the possibly truncated
* length of left side
* hlen is length of half line
*/
midflg = 1;
if (bflag) {
}
}
static void
{
sremove();
exit(2);
}
static void
onintr(void)
{
sremove();
}
static void
sremove(void)
{
if (ltemp) {
}
if (rtemp) {
}
if (temp) {
}
}
static void
cmdin(void)
{
int notacc;
notacc = 1;
while (notacc) {
break;
}
switch (*cp) {
case 's':
silent = 1;
break;
case 'v':
silent = 0;
break;
case 'q':
sremove();
/* NOTREACHED */
break;
case 'l':
notacc = 0;
break;
case 'r':
notacc = 0;
break;
case 'e':
while (*++cp == ' ')
;
switch (*cp) {
case 'l':
case '<':
notacc = 0;
break;
case 'r':
case '>':
notacc = 0;
break;
case 'b':
case '|':
"Cannot open temp file %s"),
temp);
notacc = 0;
break;
case '\n':
"Cannot open temp file %s"),
temp);
notacc = 0;
break;
default:
"Illegal command %s reenter\n"),
cp);
break;
}
if (notacc == 0)
break;
default:
"Illegal command reenter\n"));
break;
}
}
}
static void
{
"cpp: Cannot open %s"), from);
}
static void
{
int i;
void (*oldintr)(int);
case (pid_t)-1:
/* NOTREACHED */
break;
case (pid_t)0:
}
;
/* restore previous interrupt proc */
}
static char *
{
int c;
temp);
}
return (pa1);
}
/*
* like fgets, but reads upto and including a newline,
* the data is stored in a reusable dynamic buffer that grows to fit
* the largest line in the file, the buffer is NULL terminated
* returns a pointer to the dynamic buffer.
*/
static char *
{
static int blen = 0;
int sl;
/* allocate it for the first time */
}
/* check for error or nothing read */
return (NULL);
return (bp);
/* still more data, grow the buffer */
blen *= 2;
/* continue reading and add to end of buffer */
}
return (bp);
}