368 lines
8.3 KiB
C++
Raw Normal View History

/*
** Command & Conquer Generals Zero Hour(tm)
** Copyright 2025 Electronic Arts Inc.
**
** This program is free software: you can redistribute it and/or modify
** it under the terms of the GNU General Public License as published by
** the Free Software Foundation, either version 3 of the License, or
** (at your option) any later version.
**
** This program is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
** GNU General Public License for more details.
**
** You should have received a copy of the GNU General Public License
** along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "debug.h"
#include "expander.h"
#include "KVPair.h"
#include "misc.h"
#include <iostream>
#include <list>
#include <stdlib.h>
#include <stdio.h>
//=============================================================================
std::string tableRow;
//=============================================================================
static void exitWait(void)
{
system("PAUSE");
}
//=============================================================================
#define LINESIZE 1024
static bool getNextLine(FILE *fp, char *line, int& frame, int& index) {
if (!fp)
return false;
char buf[LINESIZE];
while (fgets(buf, LINESIZE-1, fp) != NULL)
{
int len = strlen(buf);
if (buf[len-1] == '\n')
buf[len-1] = '\0';
if (sscanf(buf, "%d:%d ", &frame, &index) == 2)
{
strcpy(line, buf);
return true;
}
}
fclose(fp);
return false;
}
//=============================================================================
static std::string readInFile(const char *fname) {
FILE *fp = fopen(fname, "rt");
if (!fp)
return "";
std::string ret;
char buf[LINESIZE];
while (fgets(buf, LINESIZE-1, fp) != NULL)
{
ret.append(buf);
}
fclose(fp);
return ret;
}
//=============================================================================
static FILE *ofp = NULL;
void dumpQueued(void);
static void outputLine(const char *line)
{
dumpQueued();
//cout << line << endl;
if (ofp)
{
fputs(line, ofp);
}
}
//=============================================================================
static void outputLine(int frame, int index, int linkNum,
const char *class1, const char *line1,
const char *class2, const char *line2, bool same = false)
{
dumpQueued();
if (!line1)
line1 = "&nbsp;";
if (!line2)
line2 = "&nbsp;";
if (!class1)
class1 = "";
if (!class2)
class2 = "";
Expander e("((", "))");
e.addExpansion("LEFTCLASS", class1);
e.addExpansion("LEFTLINE", line1);
e.addExpansion("RIGHTCLASS", class2);
e.addExpansion("RIGHTLINE", line2);
if (same)
{
e.addExpansion("NAME", "");
e.addExpansion("PREV", intToString(linkNum-1));
e.addExpansion("NEXT", intToString(linkNum));
}
else
{
e.addExpansion("NAME", intToString(linkNum));
e.addExpansion("PREV", intToString(linkNum-1));
e.addExpansion("NEXT", intToString(linkNum+1));
}
std::string out;
e.expand(tableRow, out);
const char *buf = out.c_str();
//cout << buf << endl;
if (ofp)
{
fputs(buf, ofp);
}
}
//=============================================================================
std::list<std::string> queuedLines;
static void queueLine(int frame, int index, const char *line1)
{
if (!line1)
line1 = "&nbsp;";
Expander e("((", "))");
e.addExpansion("LEFTCLASS", "leftHistory");
e.addExpansion("LEFTLINE", line1);
e.addExpansion("RIGHTCLASS", "rightHistory");
e.addExpansion("RIGHTLINE", line1);
e.addExpansion("NAME", "");
e.addExpansion("PREV", intToString(0));
e.addExpansion("NEXT", intToString(1));
std::string out;
e.expand(tableRow, out);
queuedLines.push_back(out);
if (queuedLines.size() > 150)
queuedLines.pop_front();
//cout << buf << endl;
}
void dumpQueued(void)
{
while (!queuedLines.empty())
{
std::list<std::string>::iterator it = queuedLines.begin();
const char *buf = (*it).c_str();
//cout << buf << endl;
if (ofp)
{
fputs(buf, ofp);
}
queuedLines.pop_front();
}
}
//=============================================================================
int main(int argc, char *argv[])
{
atexit(exitWait);
const char *inFname[2];
const char *outFname = "out.html";
FILE *ifp[2] = {NULL, NULL};
std::string header, footer;
if (argc != 7)
{
cout << "Usage: munkeeDiff top.html row.html bottom.html in1.txt in2.txt out.txt" << endl;
header = readInFile("top.html");
tableRow = readInFile("row.html");
footer = readInFile("bottom.html");
inFname[0] = "test1.txt";
inFname[1] = "test2.txt";
//return 0;
}
else
{
header = readInFile(argv[1]);
tableRow = readInFile(argv[2]);
footer = readInFile(argv[3]);
inFname[0] = argv[4];
inFname[1] = argv[5];
outFname = argv[6];
}
ifp[0] = fopen(inFname[0], "rt");
if (!ifp[0])
{
cout << "could not open " << inFname[0] << endl;
return 1;
}
ifp[1] = fopen(inFname[1], "rt");
if (!ifp[1])
{
fclose(ifp[0]);
cout << "could not open " << inFname[1] << endl;
return 1;
}
ofp = fopen(outFname, "wt");
char lastLine[2][LINESIZE];
int lastFrame[2] = {-1, -1};
int lastIndex[2] = {-1, -1};
bool fileOk[2] = {true, true};
outputLine(header.c_str());
int linkNum = 1;
int numDiffs = 0;
bool seenRight = false;
bool seenLeft = false;
while (fileOk[0] || fileOk[1])
{
for (int i=0; i<2; ++i)
{
if (fileOk[i] == true && lastFrame[i] < 0)
{
fileOk[i] = getNextLine(ifp[i], lastLine[i],
lastFrame[i], lastIndex[i]);
}
}
if (fileOk[0] && fileOk[1])
{
if (lastFrame[0] < lastFrame[1] ||
(lastFrame[0]==lastFrame[1] && lastIndex[0] < lastIndex[1]))
{
//if (!seenLeft)
//cout << "Seen left on " << lastFrame[0] << ":" << lastIndex[0] << endl;
//seenLeft = true;
if (seenRight && seenLeft)
{
outputLine(lastFrame[0], lastIndex[0], linkNum++,
"leftOnly", lastLine[0], NULL, NULL);
++numDiffs;
}
lastFrame[0] = -1;
}
else if (lastFrame[1] < lastFrame[0] ||
(lastFrame[1]==lastFrame[0] && lastIndex[1] < lastIndex[0]))
{
//if (!seenRight)
//cout << "Seen right on " << lastFrame[1] << ":" << lastIndex[1] << endl;
//seenRight = true;
if (seenRight && seenLeft)
{
outputLine(lastFrame[1], lastIndex[1], linkNum++,
NULL, NULL, "rightOnly", lastLine[1]);
++numDiffs;
}
lastFrame[1] = -1;
}
else
{
int res = strcmp(lastLine[0], lastLine[1]);
if (res!=0)
{
if (!seenLeft || !seenRight)
cout << "Seen both on " << lastFrame[0] << ":" << lastIndex[0] << endl;
seenLeft = seenRight = true;
outputLine(lastFrame[0], lastIndex[0], linkNum++,
"leftDiff", lastLine[0], "rightDiff", lastLine[1]);
++numDiffs;
}
else
{
//if (!seenLeft || !seenRight)
// cout << "Seen both on " << lastFrame[0] << ":" << lastIndex[0] << endl;
//seenLeft = seenRight = true;
static bool printedFirst = false;
if (!printedFirst)
{
outputLine(lastFrame[0], lastIndex[0], linkNum,
"leftSame", lastLine[0], "rightSame", lastLine[1], true);
printedFirst = true;
}
else if (seenLeft && seenRight)
{
outputLine(lastFrame[0], lastIndex[0], linkNum,
"leftSame", lastLine[0], "rightSame", lastLine[1], true);
++numDiffs;
}
else
queueLine(lastFrame[0], lastIndex[0], lastLine[0]);
//++numDiffs;
}
lastFrame[0] = -1;
lastFrame[1] = -1;
}
}
else if (fileOk[0])
{
//if (!seenLeft)
//cout << "Seen left on " << lastFrame[0] << ":" << lastIndex[0] << endl;
//seenLeft = true;
if (seenRight && seenLeft)
{
outputLine(lastFrame[0], lastIndex[0], linkNum++,
"leftOnly", lastLine[0], NULL, NULL);
++numDiffs;
}
lastFrame[0] = -1;
}
else if (fileOk[1])
{
//if (!seenRight)
//cout << "Seen right on " << lastFrame[1] << ":" << lastIndex[1] << endl;
//seenRight = true;
if (seenRight && seenLeft)
{
outputLine(lastFrame[1], lastIndex[1], linkNum++,
NULL, NULL, "rightOnly", lastLine[1]);
++numDiffs;
}
lastFrame[1] = -1;
}
if (numDiffs > 1000)
break;
}
Expander e("((", "))");
e.addExpansion("LAST", intToString(linkNum-1));
e.addExpansion("BOTTOM", intToString(linkNum));
std::string out;
e.expand(footer, out);
outputLine(out.c_str());
if (ofp)
{
fclose(ofp);
}
return 0;
}