mirror of https://github.com/lianthony/NT4.0
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
487 lines
10 KiB
487 lines
10 KiB
/* This program unmerges the given source files */
|
|
|
|
#include <sys/types.h>
|
|
#include <stdarg.h>
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
#include <fcntl.h>
|
|
#include <io.h>
|
|
#include <errno.h>
|
|
#include <malloc.h>
|
|
#include "version.h"
|
|
#include "unicode.h"
|
|
|
|
#define szROBin "rb" //r/w changed to binary to allow ^Z to pass through
|
|
|
|
#define fTrue 1
|
|
#define fFalse 0
|
|
#define lnMax 0x7ffffffe
|
|
#define lnNil 0x7fffffff /* MUST be greater than lnMax */
|
|
#define cbszMin 200
|
|
#define cbszInc 100
|
|
#ifdef BIT16
|
|
#define cbszMax (0xfff0 - cbszInc)
|
|
#else
|
|
#define cbszMax (0x7ffffff0 - cbszInc)
|
|
#endif
|
|
|
|
void main(int iszMac, char *rgsz[]);
|
|
void CopySrc(long ln);
|
|
void SkipSrc(long cln);
|
|
void DoUnMerge(void);
|
|
void InitDiff(void);
|
|
void CopyDiff(long cln);
|
|
void GetDiffOp(void);
|
|
int FIsEOL(FILE *chkfile, WCHAR *ch, BOOL bUnicode);
|
|
WCHAR *FGetLineFrom(WCHAR **psz, FILE *chkfile, BOOL bUnicode);
|
|
int FGetDiffLine(WCHAR **psz);
|
|
int FGetSrcLine(WCHAR **psz);
|
|
void PutLine(WCHAR *sz, BOOL bUnicode);
|
|
void OpenSrc(void);
|
|
void CloseSrc(void);
|
|
void UnmergeFatalError(int w, char *fmt, ... );
|
|
void Debug(char *sz, ...);
|
|
|
|
int fDebug = fFalse;
|
|
|
|
char szUsage1[] = "\nUNMERGE %u.%u.%02u Beta\n";
|
|
char szUsage2[] = "(This utility is for SLM use only. DO NOT REMOVE!)\n";
|
|
|
|
/* diff file */
|
|
char *szDiff;
|
|
FILE *pfDiff;
|
|
long lnStart; /* set to lnNil when done */
|
|
long clnSrc;
|
|
long clnOrg;
|
|
int chOp; /* a, c, or d */
|
|
BOOL Diff_bUnicode;
|
|
|
|
/* source file */
|
|
char *szSrc;
|
|
long lnSrc;
|
|
FILE *pfSrc;
|
|
BOOL Src_bUnicode;
|
|
|
|
void __cdecl
|
|
main(
|
|
int iszMac,
|
|
char *rgsz[])
|
|
{
|
|
_setmode(1 /* stdout */, O_BINARY);
|
|
if (iszMac > 1 && strcmp(rgsz[1], "-d") == 0) {
|
|
fDebug = fTrue;
|
|
iszMac--;
|
|
rgsz[1] = rgsz[0];
|
|
rgsz++;
|
|
}
|
|
|
|
if (iszMac != 3)
|
|
UnmergeFatalError( 2, "usage: unmerge <source> <diff>\n" );
|
|
|
|
szSrc = rgsz[1];
|
|
szDiff = rgsz[2];
|
|
|
|
/* open files */
|
|
OpenSrc();
|
|
InitDiff();
|
|
|
|
while (lnStart != lnNil) { /* while diff operations left */
|
|
Debug("At line %d in source\n", lnSrc);
|
|
CopySrc(lnStart); /* copy to (not including) */
|
|
|
|
DoUnMerge();
|
|
GetDiffOp();
|
|
}
|
|
|
|
CopySrc(lnMax);
|
|
|
|
CloseSrc();
|
|
|
|
if (fflush(stdout) != 0 || ferror(stdout))
|
|
UnmergeFatalError( 2, "write error\n" );
|
|
|
|
exit(0);
|
|
}
|
|
|
|
/* copy source file up to (not including) ln */
|
|
void
|
|
CopySrc(
|
|
long ln)
|
|
{
|
|
WCHAR *sz;
|
|
|
|
if (NULL == (sz = malloc(cbszMin)))
|
|
UnmergeFatalError( 2, "out of memory\n" );
|
|
|
|
Debug("Copy from line %ld to %ld in source\n", lnSrc, ln);
|
|
|
|
if (ln < lnSrc)
|
|
UnmergeFatalError( 2, "%s: backwards copy\n", szSrc );
|
|
|
|
while(!feof(pfSrc) && lnSrc < ln) {
|
|
if (FGetSrcLine(&sz))
|
|
PutLine(sz, Src_bUnicode);
|
|
lnSrc++;
|
|
}
|
|
lnSrc = ln; /* in case of premature eof */
|
|
free(sz);
|
|
}
|
|
|
|
/* skips cln lines in source file */
|
|
void
|
|
SkipSrc(
|
|
long cln)
|
|
{
|
|
WCHAR *sz;
|
|
|
|
if (NULL == (sz = malloc(cbszMin)))
|
|
UnmergeFatalError( 2, "out of memory\n" );
|
|
|
|
Debug("Skip %ld line(s) in source starting at %ld\n", cln, lnSrc);
|
|
|
|
while(cln-- > 0) {
|
|
FGetSrcLine(&sz);
|
|
Debug("\t%ws", sz);
|
|
lnSrc++;
|
|
}
|
|
free(sz);
|
|
}
|
|
|
|
/* unmerge the current operation */
|
|
void
|
|
DoUnMerge(
|
|
void)
|
|
{
|
|
WCHAR *sz;
|
|
|
|
if (NULL == (sz = malloc(cbszMin)))
|
|
UnmergeFatalError( 2, "out of memory\n" );
|
|
|
|
Debug("unmerge from %s: clnOrg = %ld, lnStart = %ld, clnSrc = %ld, op = %c\n",
|
|
szDiff, clnOrg, lnStart, clnSrc, chOp);
|
|
|
|
if (chOp == L'd' || chOp == L'c')
|
|
CopyDiff(clnOrg);
|
|
|
|
if (chOp == L'a' || chOp == L'c') {
|
|
SkipSrc(clnSrc);
|
|
if (chOp == L'c') /* +1 for --- line in diff */
|
|
clnSrc++;
|
|
|
|
while(clnSrc-- > 0)
|
|
if(!FGetDiffLine(&sz))
|
|
UnmergeFatalError( 2, "error reading %s\n", szDiff );
|
|
}
|
|
|
|
free(sz);
|
|
}
|
|
|
|
void
|
|
InitDiff(
|
|
void)
|
|
{
|
|
Debug("Initialization for %s\n", szDiff);
|
|
|
|
Diff_bUnicode = IsFileUnicode (szDiff);
|
|
|
|
if ((pfDiff = fopen(szDiff, szROBin)) == 0)
|
|
UnmergeFatalError( 2, "cannot open %s\n", szDiff );
|
|
|
|
GetDiffOp(); /* get first op */
|
|
}
|
|
|
|
/* copy the original lines from the diff file */
|
|
void
|
|
CopyDiff(
|
|
long cln)
|
|
{
|
|
WCHAR *sz;
|
|
|
|
if (NULL == (sz = malloc(cbszMin)))
|
|
UnmergeFatalError( 2, "out of memory\n" );
|
|
|
|
Debug("Copy %ld line(s) from %s\n", cln, szDiff);
|
|
|
|
while(!feof(pfDiff) && cln-- > 0) {
|
|
if (FGetDiffLine(&sz)) /* read a line from diff */
|
|
PutLine(sz+2, Src_bUnicode); /* remove two characters */
|
|
}
|
|
free(sz);
|
|
}
|
|
|
|
|
|
/* decode next effect line */
|
|
void
|
|
GetDiffOp(
|
|
void)
|
|
{
|
|
long ln1, ln2, ln3, ln4;
|
|
WCHAR ch;
|
|
WCHAR *pchOp, *pchC1, *pchC2;
|
|
WCHAR *sz;
|
|
|
|
if (NULL == (sz = malloc(cbszMin)))
|
|
UnmergeFatalError( 2, "out of memory\n" );
|
|
|
|
Debug("Get next change from %s\n", szDiff);
|
|
|
|
if (!FGetDiffLine(&sz)) {
|
|
lnStart = lnNil;
|
|
clnSrc = 0;
|
|
clnOrg = 0;
|
|
chOp = 0;
|
|
free(sz);
|
|
return;
|
|
}
|
|
|
|
Debug("\tActual line: %ws", sz);
|
|
|
|
/* FORM: #[,#]a/c/d#[,#] */
|
|
if (((pchOp = wcsrchr(sz, L'a')) == 0) &&
|
|
((pchOp = wcsrchr(sz, L'c')) == 0) &&
|
|
((pchOp = wcsrchr(sz, L'd')) == 0))
|
|
UnmergeFatalError( 2, "%s: no operator character\n", szDiff );
|
|
|
|
ch = *pchOp;
|
|
|
|
ln1 = ln2 = ln3 = ln4 = lnMax; /* in case a sscanf fails */
|
|
if ((pchC2 = wcsrchr(sz, L',')) != 0) {
|
|
*pchC2 = L'\0';
|
|
swscanf(pchC2+1, L"%ld", &ln4);
|
|
}
|
|
|
|
if ((pchC1 = wcsrchr(sz, L',')) != 0) {
|
|
*pchC1 = L'\0';
|
|
swscanf(pchC1+1, L"%ld", &ln2);
|
|
}
|
|
|
|
swscanf(sz, L"%ld", &ln1); /* starting number */
|
|
swscanf(pchOp+1, L"%ld", &ln3); /* number after operator */
|
|
|
|
if (pchC1 == 0 && pchC2 == 0)
|
|
/* no commas */
|
|
ln4 = ln3, ln2 = ln1;
|
|
|
|
else if (pchC1 == 0) {
|
|
/* pchC2 != 0 */
|
|
if (pchC2 < pchOp)
|
|
/* only comma before operator */
|
|
ln2 = ln4, ln4 = ln3;
|
|
else
|
|
/* only comma after operator */
|
|
ln2 = ln1;
|
|
}
|
|
|
|
/* else pchC1 != 0 and pchC2 != 0; both commas */
|
|
|
|
if (ln1 == lnMax || ln3 == lnMax)
|
|
UnmergeFatalError( 2, "%s: invalid change record\n", szDiff );
|
|
|
|
chOp = ch;
|
|
lnStart = ln3 + (chOp == L'd');
|
|
if (ln2 == lnMax)
|
|
UnmergeFatalError( 2, "%s: diff -h output not accepted\n", szDiff );
|
|
|
|
clnOrg = (chOp == L'a') ? 0L : ln2 - ln1 + 1;
|
|
clnSrc = (chOp == L'd') ? 0L : ln4 - ln3 + 1;
|
|
|
|
Debug("\tCalculated line: %ld,%ld%c%ld,%ld\n", ln1, ln2, ch, ln3, ln4);
|
|
|
|
Debug("End GetOp\n");
|
|
free(sz);
|
|
}
|
|
|
|
|
|
/* puts next character from chkfile into ch, handling all three major
|
|
* endofline conventions (CR, LF, CRLF)
|
|
* returns 1 for EOL, 2 for EOF, 0 for other character;
|
|
* *ch is '\n' for cases 1 and 2, and the received character for case 0
|
|
*/
|
|
int
|
|
FIsEOL(
|
|
FILE *chkfile,
|
|
WCHAR *ch,
|
|
BOOL bUnicode)
|
|
{
|
|
int chIn, chT;
|
|
int low, high;
|
|
|
|
if (bUnicode) {
|
|
low = getc(chkfile);
|
|
high = getc(chkfile);
|
|
chIn = MAKEWORD(low, high);
|
|
}
|
|
else
|
|
chIn = getc(chkfile);
|
|
|
|
if (EOF == chIn) {
|
|
*ch = L'\n';
|
|
return 2;
|
|
}
|
|
if (L'\r' == (*ch = (WCHAR)chIn)) {
|
|
if (bUnicode) {
|
|
low = getc(chkfile);
|
|
high = getc(chkfile);
|
|
chT = MAKEWORD(low, high);
|
|
}
|
|
else
|
|
chT = getc(chkfile);
|
|
if (chT != EOF) {
|
|
if (bUnicode) {
|
|
ungetc(HIBYTE(chT), chkfile);
|
|
ungetc(LOBYTE(chT), chkfile);
|
|
}
|
|
else
|
|
ungetc(chT, chkfile);
|
|
}
|
|
return ((L'\n' == chT) ? 0 : 1);
|
|
}
|
|
else if (L'\n' == *ch)
|
|
return 1;
|
|
else
|
|
return 0;
|
|
}
|
|
|
|
/* fgets that handles more EOL conventions */
|
|
WCHAR *
|
|
FGetLineFrom(
|
|
WCHAR **psz,
|
|
FILE *chkfile,
|
|
BOOL bUnicode)
|
|
{
|
|
WCHAR *pch;
|
|
int fEOF;
|
|
unsigned cbsz = _msize(*psz) / sizeof(WCHAR);
|
|
unsigned ich;
|
|
|
|
for (ich = 0, pch = *psz; ; ich++, pch++) {
|
|
if ((ich + 3) >= cbsz) {
|
|
if (cbsz >= cbszMax)
|
|
UnmergeFatalError( 2, "out of memory\n" );
|
|
if (NULL == (*psz = realloc(*psz, _msize(*psz) + cbszInc)))
|
|
UnmergeFatalError( 2, "out of memory\n" );
|
|
cbsz += cbszInc / sizeof(WCHAR);
|
|
pch = &(*psz)[ich];
|
|
}
|
|
if ((fEOF = FIsEOL(chkfile, pch, bUnicode)) != 0)
|
|
break;
|
|
}
|
|
|
|
*(pch + 1) = L'\0';
|
|
if (2 == fEOF) {
|
|
*pch = L'\0';
|
|
return (*psz == pch) ? NULL : *psz;
|
|
}
|
|
else
|
|
return *psz;
|
|
}
|
|
|
|
int
|
|
FGetDiffLine(
|
|
WCHAR **psz)
|
|
{
|
|
return FGetLineFrom(psz, pfDiff, Diff_bUnicode) != NULL;
|
|
}
|
|
|
|
|
|
int
|
|
FGetSrcLine(
|
|
WCHAR **psz)
|
|
{
|
|
return FGetLineFrom(psz, pfSrc, Src_bUnicode) != NULL;
|
|
}
|
|
|
|
|
|
void
|
|
PutLine(
|
|
WCHAR *sz,
|
|
BOOL bUnicode)
|
|
{
|
|
long cbWritten;
|
|
|
|
#ifdef _WIN32
|
|
DWORD dwMode;
|
|
|
|
if (GetConsoleMode((HANDLE)_get_osfhandle(_fileno(stdout)), &dwMode)) {
|
|
if (fDebug)
|
|
WriteConsoleW ((HANDLE)_get_osfhandle(_fileno(stdout)), L"\t", 1, &cbWritten, NULL);
|
|
WriteConsoleW ((HANDLE)_get_osfhandle(_fileno(stdout)), sz, wcslen(sz), &cbWritten, NULL);
|
|
}
|
|
else
|
|
if (bUnicode)
|
|
fwprintf(stdout, (fDebug) ? L"\t%s" : L"%s", sz);
|
|
else
|
|
fprintf(stdout, (fDebug) ? "\t%ws" : "%ws", sz);
|
|
|
|
#else
|
|
if (bUnicode)
|
|
fwprintf(stdout, (fDebug) ? L"\t%s" : L"%s", sz);
|
|
else
|
|
fprintf(stdout, (fDebug) ? "\t%ws" : "%ws", sz);
|
|
#endif
|
|
|
|
if (ferror(stdout))
|
|
UnmergeFatalError( 2, "write error\n" );
|
|
}
|
|
|
|
/* open source */
|
|
void
|
|
OpenSrc(
|
|
void)
|
|
{
|
|
Src_bUnicode = IsFileUnicode (szSrc);
|
|
|
|
pfSrc = fopen(szSrc, szROBin);
|
|
if (pfSrc == 0)
|
|
UnmergeFatalError( 2, "cannot open %s\n", szSrc );
|
|
|
|
lnSrc = 1; /* current line; 1 based */
|
|
Debug("szSrc = %s\n", szSrc);
|
|
}
|
|
|
|
|
|
void
|
|
CloseSrc(
|
|
void)
|
|
{
|
|
if (pfSrc) {
|
|
fclose(pfSrc);
|
|
pfSrc = 0;
|
|
}
|
|
}
|
|
|
|
|
|
void
|
|
UnmergeFatalError(
|
|
int w,
|
|
char *fmt, ... )
|
|
{
|
|
va_list marker;
|
|
|
|
va_start( marker, fmt );
|
|
fprintf(stderr, "\n");
|
|
if (strncmp(fmt, "usage: ", 7) != 0)
|
|
fprintf(stderr, "unmerge: ");
|
|
vfprintf(stderr, fmt, marker);
|
|
va_end(marker);
|
|
|
|
fprintf(stderr, szUsage1, rmj, rmm, rup);
|
|
fprintf(stderr, szUsage2);
|
|
CloseSrc();
|
|
exit(w);
|
|
}
|
|
|
|
|
|
/*VARARGS1*/
|
|
void
|
|
Debug(
|
|
char *sz, ...)
|
|
{
|
|
va_list ap;
|
|
|
|
if (fDebug) {
|
|
va_start(ap, sz);
|
|
vfprintf(stderr, sz, ap);
|
|
va_end(ap);
|
|
}
|
|
}
|