mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-10-11 12:25:53 +00:00
added htmlgeneration tool
This commit is contained in:
parent
4f14253e33
commit
e2ef1cf7c8
512
htmlparser/tests/htmlgen/htmlgen.cpp
Normal file
512
htmlparser/tests/htmlgen/htmlgen.cpp
Normal file
@ -0,0 +1,512 @@
|
||||
/*========================================================
|
||||
To Do:
|
||||
1. Tag sequences on the command line p..table
|
||||
2. Dumping documents into the right place
|
||||
*========================================================*/
|
||||
|
||||
|
||||
/*========================================================
|
||||
Special keywords:
|
||||
$0..$9: represent command line arguments
|
||||
@file: the name of the file being writtent
|
||||
@nextfile: the name of the next file to be written
|
||||
@htmlgen: runs the app recursively with given arguments.
|
||||
*========================================================*/
|
||||
|
||||
|
||||
#include <iostream.h>
|
||||
#include <fstream.h>
|
||||
#include <strstrea.h>
|
||||
#include <string>
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <errno.h>
|
||||
#include <time.h>
|
||||
#include <direct.h>
|
||||
|
||||
|
||||
static char* tagTable[] = {
|
||||
"A", "ABBR", "ACRONYM", "ADDRESS", "APPLET", "AREA",
|
||||
"B", "BASE", "BASEFONT", "BDO", "BGSOUND", "BIG", "BLINK", "BLOCKQUOTE", "BODY", "BR", "BUTTON",
|
||||
"CAPTION", "CENTER", "CITE", "CODE", "COL", "COLGROUP",
|
||||
"DD", "DEL", "DFN", "DIR", "DIV", "DL", "DT",
|
||||
"EM", "EMBED",
|
||||
"FIELDSET", "FONT", "FORM", "FRAME", "FRAMESET",
|
||||
"H1", "H2", "H3", "H4", "H5", "H6", "HEAD", "HR", "HTML",
|
||||
"I", "IFRAME", "ILAYER", "IMG", "INPUT", "INS", "ISINDEX",
|
||||
"KBD", "KEYGEN",
|
||||
"LABEL", "LAYER", "LEGEND", "LI", "LINK", "LISTING",
|
||||
"MAP", "MENU", "META", "MULTICOL",
|
||||
"NOBR", "NOEMBED", "NOFRAMES", "NOLAYER", "NOSCRIPT",
|
||||
"OBJECT", "OL", "OPTGROUP", "OPTION",
|
||||
"P", "PARAM", "PLAINTEXT", "PRE",
|
||||
"Q",
|
||||
"S","SAMP","SCRIPT","SELECT","SERVER","SMALL","SOUND","SPACER","SPAN","STRIKE","STRONG","STYLE","SUB","SUP",
|
||||
"TABLE", "TBODY", "TD", "TEXTAREA", "TFOOT", "TH", "THEAD", "TITLE", "TR", "TT",
|
||||
"U", "UL",
|
||||
"VAR",
|
||||
"WBR",
|
||||
"XMP",
|
||||
0
|
||||
};
|
||||
static char gCWD[1025];
|
||||
static char gPrevFile[128];
|
||||
static char gThisFile[128];
|
||||
static char gNextFile[128];
|
||||
static int gFileIndex=0;
|
||||
|
||||
|
||||
int findTag(const char* aTagName) {
|
||||
int low = 0;
|
||||
int high = 107;
|
||||
while (low <= high) {
|
||||
int middle = (low + high) >> 1;
|
||||
int result = stricmp(aTagName, tagTable[middle]);
|
||||
if (result == 0)
|
||||
return middle;
|
||||
if (result < 0)
|
||||
high = middle - 1;
|
||||
else
|
||||
low = middle + 1;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Call this to find a tag that closely resembles the given tag.
|
||||
* Note that we match based on the first char.
|
||||
* @update gess12/23/98
|
||||
* @param
|
||||
* @return
|
||||
*/
|
||||
int findNearestTag(char* aTag){
|
||||
int result=-1;
|
||||
if(aTag){
|
||||
char theChar=toupper(aTag[0]);
|
||||
int theIndex=-1;
|
||||
while(tagTable[++theIndex]){
|
||||
if(toupper(tagTable[theIndex][0])==theChar) {
|
||||
return theIndex;
|
||||
}
|
||||
}
|
||||
}
|
||||
if(toupper(aTag[0])<'A')
|
||||
result=0;
|
||||
else result=107;
|
||||
return result;
|
||||
}
|
||||
|
||||
char* getNthTagAfter(int aRangeIndex,char* aStartTag){
|
||||
int theIndex=findTag(aStartTag);
|
||||
if(-1==theIndex){
|
||||
theIndex=findNearestTag(aStartTag);
|
||||
}
|
||||
if(-1<theIndex){
|
||||
//now that you have the tag,
|
||||
return tagTable[theIndex+aRangeIndex];
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @update gess12/20/98
|
||||
* @param
|
||||
* @return
|
||||
*/
|
||||
class CMacros {
|
||||
public:
|
||||
CMacros() {
|
||||
mCount=0;
|
||||
mFilename[0]=0;
|
||||
memset(mKeys,0,sizeof(mKeys));
|
||||
memset(mRanges,0,sizeof(mRanges));
|
||||
memset(mIndex,0,sizeof(mIndex));
|
||||
mBorrowedKeys=false;
|
||||
}
|
||||
|
||||
CMacros(const CMacros& aCopy) {
|
||||
mBorrowedKeys=true;
|
||||
mCount=aCopy.mCount;
|
||||
strcpy(mFilename,aCopy.mFilename);
|
||||
memcpy(mKeys,aCopy.mKeys,sizeof(mKeys));
|
||||
memcpy(mIndex,aCopy.mIndex,sizeof(mIndex));
|
||||
}
|
||||
|
||||
~CMacros(){
|
||||
if(!mBorrowedKeys) {
|
||||
for(int i=0;i<mCount;i++){
|
||||
delete [] mKeys[i];
|
||||
mKeys[i]=0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool addMacro(char* aString) {
|
||||
|
||||
//copy a macro name...
|
||||
//start by stripping off the macro key (everything up to the equal sign...
|
||||
if(aString){
|
||||
int sLen=strlen(aString);
|
||||
if(sLen>0){
|
||||
if((strchr(aString,',')) || (strchr(aString,'-'))) {
|
||||
mRanges[mCount]=new char[sLen+1];
|
||||
strcpy(mRanges[mCount++],aString);
|
||||
}
|
||||
else {
|
||||
mKeys[mCount]=new char[sLen+1];
|
||||
strcpy(mKeys[mCount++],aString);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
int getCount() {return mCount;}
|
||||
|
||||
char* getMacro(int anIndex) {
|
||||
if(anIndex<mCount)
|
||||
return mKeys[anIndex];
|
||||
return 0;
|
||||
}
|
||||
|
||||
char* getFilename(void) {return mFilename;}
|
||||
|
||||
char* getRangeValueAt(char* aRange,int aRangeIndex) {
|
||||
static char theBuffer[100];
|
||||
char* result=0;
|
||||
char* p1=aRange;
|
||||
char* p2=0;
|
||||
int offset=0;
|
||||
int count=-1;
|
||||
|
||||
theBuffer[0]=0;
|
||||
if(p2=strchr(&aRange[offset],',')) {
|
||||
//in this case, our keys are taken 1 at a time from the range itself.
|
||||
while((++count<aRangeIndex) && (p1) && (p2)) {
|
||||
p1=p2+1;
|
||||
p2=strchr(p1,',');
|
||||
}
|
||||
if(p1 && (count==aRangeIndex)) {
|
||||
strncat(theBuffer,p1,p2-p1);
|
||||
}
|
||||
result=theBuffer;
|
||||
}
|
||||
else if(p2=strchr(&aRange[offset],'-')) {
|
||||
//in this case, our keys are computed based on HTMLTags within the given range (exclusive).
|
||||
strncat(theBuffer,p1,p2-p1);
|
||||
char* tag=getNthTagAfter(aRangeIndex,theBuffer);
|
||||
p2++; //p2 now points at the last item...
|
||||
if(tag){
|
||||
int end=findNearestTag(p2);
|
||||
char* endTag=tagTable[end];
|
||||
if(endTag){
|
||||
int icmp=stricmp(tag,endTag);
|
||||
if(icmp<=0){
|
||||
strcpy(theBuffer,tag);
|
||||
}
|
||||
else theBuffer[0]=0;
|
||||
result=theBuffer;
|
||||
}
|
||||
else result=0;
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
bool first(void) {
|
||||
bool result=true;
|
||||
for(int i=0;i<mCount;i++){
|
||||
mIndex[i]=0;
|
||||
if(mRanges[i]){
|
||||
char* key=getRangeValueAt(mRanges[i],mIndex[i]);
|
||||
if(key) {
|
||||
if(!mKeys[i])
|
||||
mKeys[i]=new char[100];
|
||||
strcpy(mKeys[i],key);
|
||||
}
|
||||
}
|
||||
//otherwise key is already set...
|
||||
}
|
||||
sprintf(gThisFile,"out%i.html",gFileIndex++);
|
||||
sprintf(gNextFile,"out%i.html",gFileIndex);
|
||||
return result;
|
||||
}
|
||||
|
||||
bool next(void) {
|
||||
|
||||
//the trick here is to find the rightmost range and increment it.
|
||||
//if it wraps, then reset it to 0, and increment the next range to the left.
|
||||
int rangeIndex=mCount;
|
||||
bool done=false;
|
||||
while((0<=--rangeIndex) && (!done)) {
|
||||
if(mRanges[rangeIndex]) {
|
||||
//ok, now we know the right most range object.
|
||||
//let's see if it can be incremented...
|
||||
char* key=getRangeValueAt(mRanges[rangeIndex],++mIndex[rangeIndex]);
|
||||
if((0==key) || (0==key[0])){
|
||||
mIndex[rangeIndex]=0;
|
||||
char* key=getRangeValueAt(mRanges[rangeIndex],mIndex[rangeIndex]);
|
||||
}//if
|
||||
else done=true;
|
||||
mKeys[rangeIndex][0]=0;
|
||||
if(key)
|
||||
strcpy(mKeys[rangeIndex],key);
|
||||
}//if
|
||||
}//while
|
||||
strcpy(gPrevFile,gThisFile);
|
||||
sprintf(gThisFile,"out%i.html",gFileIndex++);
|
||||
sprintf(gNextFile,"out%i.html",gFileIndex);
|
||||
return done;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @update gess12/23/98
|
||||
* @param
|
||||
* @return
|
||||
*/
|
||||
bool consume(istrstream& aStream){
|
||||
char theBuffer[100];
|
||||
bool readDefs=false;
|
||||
|
||||
while(!aStream.eof()){
|
||||
aStream >> theBuffer;
|
||||
if(!stricmp(theBuffer,"-F")){
|
||||
//copy the filename...
|
||||
aStream >> theBuffer;
|
||||
strcpy(mFilename,theBuffer);
|
||||
readDefs=false;
|
||||
}
|
||||
else if(!stricmp(theBuffer,"-D")){
|
||||
readDefs=true;
|
||||
}
|
||||
else if(!stricmp(theBuffer,"-O")){
|
||||
aStream >> theBuffer;
|
||||
readDefs=false;
|
||||
}
|
||||
else if(readDefs){
|
||||
if(theBuffer[0]){
|
||||
addMacro(theBuffer);
|
||||
theBuffer[0]=0;
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void buildArgBuffer(char* aBuffer) {
|
||||
aBuffer[0]=0;
|
||||
if(mFilename[0]) {
|
||||
sprintf(aBuffer,"-0 %s -f %s -d ",gThisFile,mFilename);
|
||||
}
|
||||
for(int i=0;i<mCount;i++){
|
||||
if(mKeys[i]) {
|
||||
strcat(aBuffer,mKeys[i]);
|
||||
strcat(aBuffer," ");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void dump(void) {
|
||||
for(int i=0;i<mCount;i++){
|
||||
cout << mKeys[i] << " ";
|
||||
}
|
||||
cout << endl;
|
||||
}
|
||||
|
||||
protected:
|
||||
int mCount;
|
||||
char* mKeys[100];
|
||||
char* mRanges[100];
|
||||
int mIndex[100];
|
||||
char mFilename[125];
|
||||
bool mBorrowedKeys;
|
||||
};
|
||||
|
||||
/**
|
||||
*
|
||||
* @update gess12/20/98
|
||||
* @param
|
||||
* @return
|
||||
*/
|
||||
void expandKeywords(char* aBuffer,CMacros& aMacroSet){
|
||||
char temp[1024];
|
||||
char theWord[100];
|
||||
|
||||
temp[0]=0;
|
||||
if(strchr(aBuffer,'@')){
|
||||
|
||||
int pos=-1;
|
||||
while(aBuffer[++pos]==' ')
|
||||
strcat(temp," ");
|
||||
|
||||
istrstream iStr(aBuffer);
|
||||
while(!iStr.eof()){
|
||||
theWord[0]=0;
|
||||
iStr>>theWord;
|
||||
char* thePos=strchr(theWord,'@');
|
||||
if(thePos){
|
||||
strncat(temp,theWord,thePos-theWord);
|
||||
if(!strnicmp(thePos,"@file",5)){
|
||||
strcat(temp,gThisFile);
|
||||
thePos+=5;
|
||||
}
|
||||
else if(!strnicmp(thePos,"@nextfile",9)){
|
||||
strcat(temp,gNextFile);
|
||||
thePos+=9;
|
||||
}
|
||||
else if(!strnicmp(thePos,"@prevfile",9)){
|
||||
strcat(temp,gPrevFile);
|
||||
thePos+=9;
|
||||
}
|
||||
strcat(temp,thePos);
|
||||
}
|
||||
else strcat(temp,theWord);
|
||||
strcat(temp," ");
|
||||
}
|
||||
strcpy(aBuffer,temp);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @update gess12/20/98
|
||||
* @param
|
||||
* @return
|
||||
*/
|
||||
void expandMacros(char* aBuffer,CMacros& aMacroSet){
|
||||
char temp[1024];
|
||||
int rPos=-1;
|
||||
int wPos=0;
|
||||
|
||||
if(aBuffer){
|
||||
while(aBuffer[++rPos]){
|
||||
if('$'==aBuffer[rPos]){
|
||||
temp[wPos]=0;
|
||||
rPos++; //skip the $...
|
||||
int theIndex=aBuffer[rPos]-'0';
|
||||
char* theMacro=aMacroSet.getMacro(theIndex);
|
||||
if(theMacro){
|
||||
strcat(temp,theMacro);
|
||||
wPos=strlen(temp);
|
||||
}
|
||||
}
|
||||
else temp[wPos++]=aBuffer[rPos];
|
||||
}
|
||||
temp[wPos]=0;
|
||||
strcpy(aBuffer,temp);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @update gess12/20/98
|
||||
* @param
|
||||
* @return
|
||||
*/
|
||||
int processFile(char* aDir,fstream& anOutputStream,istrstream& aInputArgs){
|
||||
int result=0;
|
||||
|
||||
CMacros theMacros;
|
||||
theMacros.consume(aInputArgs);
|
||||
|
||||
char* theFilename=theMacros.getFilename();
|
||||
fstream theInputStream(theFilename,ios::in);
|
||||
if(theInputStream.is_open()){
|
||||
bool done=false;
|
||||
char theBuffer[1024];
|
||||
char theWord[600];
|
||||
|
||||
while((!done) && (0==result)){
|
||||
|
||||
theInputStream.getline(theBuffer,sizeof(theBuffer)-1);
|
||||
if(theInputStream.gcount()){
|
||||
|
||||
//before doing anything else, expand the macros and keywords...
|
||||
expandMacros(theBuffer,theMacros);
|
||||
expandKeywords(theBuffer,theMacros);
|
||||
|
||||
//Now process each line:
|
||||
if(strchr(theBuffer,'@')) {
|
||||
|
||||
//First, see if the line is an htmlgen statement; if so, recurse to read new file...
|
||||
istrstream iStr(theBuffer);
|
||||
iStr>>theWord;
|
||||
if(!stricmp(theWord,"@htmlgen")){
|
||||
|
||||
//If you're here, we found an htmlgen statement.
|
||||
// To handle this, we have to:
|
||||
// 1. strip off the @htmlgen
|
||||
// 2. grab the filename and collect the args,
|
||||
// 3. and recurse...
|
||||
|
||||
result=processFile(aDir,anOutputStream,iStr);
|
||||
}
|
||||
}
|
||||
else anOutputStream << theBuffer << endl;
|
||||
}
|
||||
else done=true;
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* This is where the different combinations of arguments
|
||||
* gets constructed and passed on for processing.
|
||||
* Note that this is even called when the args have only 1 value.
|
||||
* @return error code
|
||||
*/
|
||||
int iterate(istrstream& aInputArgs){
|
||||
int result=0;
|
||||
|
||||
CMacros theArgs;
|
||||
theArgs.consume(aInputArgs);
|
||||
|
||||
char theBuffer[1024];
|
||||
char theFilename[1024];
|
||||
|
||||
bool done=!theArgs.first();
|
||||
while((!done) && (0==result)){
|
||||
CMacros theTempArgs(theArgs);
|
||||
theTempArgs.buildArgBuffer(theBuffer);
|
||||
istrstream theArgStream(theBuffer);
|
||||
sprintf(theFilename,"%s\\%s",gCWD,gThisFile);
|
||||
fstream theOutStream(theFilename,ios::trunc);
|
||||
result=processFile(gCWD,theOutStream,theArgStream);
|
||||
theArgs.dump();
|
||||
done=!theArgs.next();
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @update gess12/20/98
|
||||
* @param
|
||||
* @return
|
||||
*/
|
||||
int main(int argc,char* argv[]){
|
||||
int result=0;
|
||||
|
||||
gPrevFile[0]=gThisFile[0]=gNextFile[0];
|
||||
if(argc>1){
|
||||
char theBuffer[1024];
|
||||
theBuffer[0]=0;
|
||||
|
||||
for(int i=1;i<argc;i++){
|
||||
strcat(theBuffer,argv[i]);
|
||||
strcat(theBuffer," ");
|
||||
}
|
||||
|
||||
_getcwd(gCWD,sizeof(gCWD)-1);
|
||||
istrstream aStrStream(theBuffer);
|
||||
result=iterate(aStrStream);
|
||||
}
|
||||
else cout<<endl <<"HTMLGenerator usage -f filename [-d yyy|xxx,yyy|xxx...yyy]" << endl;
|
||||
return result;
|
||||
}
|
512
parser/htmlparser/tests/htmlgen/htmlgen.cpp
Normal file
512
parser/htmlparser/tests/htmlgen/htmlgen.cpp
Normal file
@ -0,0 +1,512 @@
|
||||
/*========================================================
|
||||
To Do:
|
||||
1. Tag sequences on the command line p..table
|
||||
2. Dumping documents into the right place
|
||||
*========================================================*/
|
||||
|
||||
|
||||
/*========================================================
|
||||
Special keywords:
|
||||
$0..$9: represent command line arguments
|
||||
@file: the name of the file being writtent
|
||||
@nextfile: the name of the next file to be written
|
||||
@htmlgen: runs the app recursively with given arguments.
|
||||
*========================================================*/
|
||||
|
||||
|
||||
#include <iostream.h>
|
||||
#include <fstream.h>
|
||||
#include <strstrea.h>
|
||||
#include <string>
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <errno.h>
|
||||
#include <time.h>
|
||||
#include <direct.h>
|
||||
|
||||
|
||||
static char* tagTable[] = {
|
||||
"A", "ABBR", "ACRONYM", "ADDRESS", "APPLET", "AREA",
|
||||
"B", "BASE", "BASEFONT", "BDO", "BGSOUND", "BIG", "BLINK", "BLOCKQUOTE", "BODY", "BR", "BUTTON",
|
||||
"CAPTION", "CENTER", "CITE", "CODE", "COL", "COLGROUP",
|
||||
"DD", "DEL", "DFN", "DIR", "DIV", "DL", "DT",
|
||||
"EM", "EMBED",
|
||||
"FIELDSET", "FONT", "FORM", "FRAME", "FRAMESET",
|
||||
"H1", "H2", "H3", "H4", "H5", "H6", "HEAD", "HR", "HTML",
|
||||
"I", "IFRAME", "ILAYER", "IMG", "INPUT", "INS", "ISINDEX",
|
||||
"KBD", "KEYGEN",
|
||||
"LABEL", "LAYER", "LEGEND", "LI", "LINK", "LISTING",
|
||||
"MAP", "MENU", "META", "MULTICOL",
|
||||
"NOBR", "NOEMBED", "NOFRAMES", "NOLAYER", "NOSCRIPT",
|
||||
"OBJECT", "OL", "OPTGROUP", "OPTION",
|
||||
"P", "PARAM", "PLAINTEXT", "PRE",
|
||||
"Q",
|
||||
"S","SAMP","SCRIPT","SELECT","SERVER","SMALL","SOUND","SPACER","SPAN","STRIKE","STRONG","STYLE","SUB","SUP",
|
||||
"TABLE", "TBODY", "TD", "TEXTAREA", "TFOOT", "TH", "THEAD", "TITLE", "TR", "TT",
|
||||
"U", "UL",
|
||||
"VAR",
|
||||
"WBR",
|
||||
"XMP",
|
||||
0
|
||||
};
|
||||
static char gCWD[1025];
|
||||
static char gPrevFile[128];
|
||||
static char gThisFile[128];
|
||||
static char gNextFile[128];
|
||||
static int gFileIndex=0;
|
||||
|
||||
|
||||
int findTag(const char* aTagName) {
|
||||
int low = 0;
|
||||
int high = 107;
|
||||
while (low <= high) {
|
||||
int middle = (low + high) >> 1;
|
||||
int result = stricmp(aTagName, tagTable[middle]);
|
||||
if (result == 0)
|
||||
return middle;
|
||||
if (result < 0)
|
||||
high = middle - 1;
|
||||
else
|
||||
low = middle + 1;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Call this to find a tag that closely resembles the given tag.
|
||||
* Note that we match based on the first char.
|
||||
* @update gess12/23/98
|
||||
* @param
|
||||
* @return
|
||||
*/
|
||||
int findNearestTag(char* aTag){
|
||||
int result=-1;
|
||||
if(aTag){
|
||||
char theChar=toupper(aTag[0]);
|
||||
int theIndex=-1;
|
||||
while(tagTable[++theIndex]){
|
||||
if(toupper(tagTable[theIndex][0])==theChar) {
|
||||
return theIndex;
|
||||
}
|
||||
}
|
||||
}
|
||||
if(toupper(aTag[0])<'A')
|
||||
result=0;
|
||||
else result=107;
|
||||
return result;
|
||||
}
|
||||
|
||||
char* getNthTagAfter(int aRangeIndex,char* aStartTag){
|
||||
int theIndex=findTag(aStartTag);
|
||||
if(-1==theIndex){
|
||||
theIndex=findNearestTag(aStartTag);
|
||||
}
|
||||
if(-1<theIndex){
|
||||
//now that you have the tag,
|
||||
return tagTable[theIndex+aRangeIndex];
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @update gess12/20/98
|
||||
* @param
|
||||
* @return
|
||||
*/
|
||||
class CMacros {
|
||||
public:
|
||||
CMacros() {
|
||||
mCount=0;
|
||||
mFilename[0]=0;
|
||||
memset(mKeys,0,sizeof(mKeys));
|
||||
memset(mRanges,0,sizeof(mRanges));
|
||||
memset(mIndex,0,sizeof(mIndex));
|
||||
mBorrowedKeys=false;
|
||||
}
|
||||
|
||||
CMacros(const CMacros& aCopy) {
|
||||
mBorrowedKeys=true;
|
||||
mCount=aCopy.mCount;
|
||||
strcpy(mFilename,aCopy.mFilename);
|
||||
memcpy(mKeys,aCopy.mKeys,sizeof(mKeys));
|
||||
memcpy(mIndex,aCopy.mIndex,sizeof(mIndex));
|
||||
}
|
||||
|
||||
~CMacros(){
|
||||
if(!mBorrowedKeys) {
|
||||
for(int i=0;i<mCount;i++){
|
||||
delete [] mKeys[i];
|
||||
mKeys[i]=0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool addMacro(char* aString) {
|
||||
|
||||
//copy a macro name...
|
||||
//start by stripping off the macro key (everything up to the equal sign...
|
||||
if(aString){
|
||||
int sLen=strlen(aString);
|
||||
if(sLen>0){
|
||||
if((strchr(aString,',')) || (strchr(aString,'-'))) {
|
||||
mRanges[mCount]=new char[sLen+1];
|
||||
strcpy(mRanges[mCount++],aString);
|
||||
}
|
||||
else {
|
||||
mKeys[mCount]=new char[sLen+1];
|
||||
strcpy(mKeys[mCount++],aString);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
int getCount() {return mCount;}
|
||||
|
||||
char* getMacro(int anIndex) {
|
||||
if(anIndex<mCount)
|
||||
return mKeys[anIndex];
|
||||
return 0;
|
||||
}
|
||||
|
||||
char* getFilename(void) {return mFilename;}
|
||||
|
||||
char* getRangeValueAt(char* aRange,int aRangeIndex) {
|
||||
static char theBuffer[100];
|
||||
char* result=0;
|
||||
char* p1=aRange;
|
||||
char* p2=0;
|
||||
int offset=0;
|
||||
int count=-1;
|
||||
|
||||
theBuffer[0]=0;
|
||||
if(p2=strchr(&aRange[offset],',')) {
|
||||
//in this case, our keys are taken 1 at a time from the range itself.
|
||||
while((++count<aRangeIndex) && (p1) && (p2)) {
|
||||
p1=p2+1;
|
||||
p2=strchr(p1,',');
|
||||
}
|
||||
if(p1 && (count==aRangeIndex)) {
|
||||
strncat(theBuffer,p1,p2-p1);
|
||||
}
|
||||
result=theBuffer;
|
||||
}
|
||||
else if(p2=strchr(&aRange[offset],'-')) {
|
||||
//in this case, our keys are computed based on HTMLTags within the given range (exclusive).
|
||||
strncat(theBuffer,p1,p2-p1);
|
||||
char* tag=getNthTagAfter(aRangeIndex,theBuffer);
|
||||
p2++; //p2 now points at the last item...
|
||||
if(tag){
|
||||
int end=findNearestTag(p2);
|
||||
char* endTag=tagTable[end];
|
||||
if(endTag){
|
||||
int icmp=stricmp(tag,endTag);
|
||||
if(icmp<=0){
|
||||
strcpy(theBuffer,tag);
|
||||
}
|
||||
else theBuffer[0]=0;
|
||||
result=theBuffer;
|
||||
}
|
||||
else result=0;
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
bool first(void) {
|
||||
bool result=true;
|
||||
for(int i=0;i<mCount;i++){
|
||||
mIndex[i]=0;
|
||||
if(mRanges[i]){
|
||||
char* key=getRangeValueAt(mRanges[i],mIndex[i]);
|
||||
if(key) {
|
||||
if(!mKeys[i])
|
||||
mKeys[i]=new char[100];
|
||||
strcpy(mKeys[i],key);
|
||||
}
|
||||
}
|
||||
//otherwise key is already set...
|
||||
}
|
||||
sprintf(gThisFile,"out%i.html",gFileIndex++);
|
||||
sprintf(gNextFile,"out%i.html",gFileIndex);
|
||||
return result;
|
||||
}
|
||||
|
||||
bool next(void) {
|
||||
|
||||
//the trick here is to find the rightmost range and increment it.
|
||||
//if it wraps, then reset it to 0, and increment the next range to the left.
|
||||
int rangeIndex=mCount;
|
||||
bool done=false;
|
||||
while((0<=--rangeIndex) && (!done)) {
|
||||
if(mRanges[rangeIndex]) {
|
||||
//ok, now we know the right most range object.
|
||||
//let's see if it can be incremented...
|
||||
char* key=getRangeValueAt(mRanges[rangeIndex],++mIndex[rangeIndex]);
|
||||
if((0==key) || (0==key[0])){
|
||||
mIndex[rangeIndex]=0;
|
||||
char* key=getRangeValueAt(mRanges[rangeIndex],mIndex[rangeIndex]);
|
||||
}//if
|
||||
else done=true;
|
||||
mKeys[rangeIndex][0]=0;
|
||||
if(key)
|
||||
strcpy(mKeys[rangeIndex],key);
|
||||
}//if
|
||||
}//while
|
||||
strcpy(gPrevFile,gThisFile);
|
||||
sprintf(gThisFile,"out%i.html",gFileIndex++);
|
||||
sprintf(gNextFile,"out%i.html",gFileIndex);
|
||||
return done;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @update gess12/23/98
|
||||
* @param
|
||||
* @return
|
||||
*/
|
||||
bool consume(istrstream& aStream){
|
||||
char theBuffer[100];
|
||||
bool readDefs=false;
|
||||
|
||||
while(!aStream.eof()){
|
||||
aStream >> theBuffer;
|
||||
if(!stricmp(theBuffer,"-F")){
|
||||
//copy the filename...
|
||||
aStream >> theBuffer;
|
||||
strcpy(mFilename,theBuffer);
|
||||
readDefs=false;
|
||||
}
|
||||
else if(!stricmp(theBuffer,"-D")){
|
||||
readDefs=true;
|
||||
}
|
||||
else if(!stricmp(theBuffer,"-O")){
|
||||
aStream >> theBuffer;
|
||||
readDefs=false;
|
||||
}
|
||||
else if(readDefs){
|
||||
if(theBuffer[0]){
|
||||
addMacro(theBuffer);
|
||||
theBuffer[0]=0;
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void buildArgBuffer(char* aBuffer) {
|
||||
aBuffer[0]=0;
|
||||
if(mFilename[0]) {
|
||||
sprintf(aBuffer,"-0 %s -f %s -d ",gThisFile,mFilename);
|
||||
}
|
||||
for(int i=0;i<mCount;i++){
|
||||
if(mKeys[i]) {
|
||||
strcat(aBuffer,mKeys[i]);
|
||||
strcat(aBuffer," ");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void dump(void) {
|
||||
for(int i=0;i<mCount;i++){
|
||||
cout << mKeys[i] << " ";
|
||||
}
|
||||
cout << endl;
|
||||
}
|
||||
|
||||
protected:
|
||||
int mCount;
|
||||
char* mKeys[100];
|
||||
char* mRanges[100];
|
||||
int mIndex[100];
|
||||
char mFilename[125];
|
||||
bool mBorrowedKeys;
|
||||
};
|
||||
|
||||
/**
|
||||
*
|
||||
* @update gess12/20/98
|
||||
* @param
|
||||
* @return
|
||||
*/
|
||||
void expandKeywords(char* aBuffer,CMacros& aMacroSet){
|
||||
char temp[1024];
|
||||
char theWord[100];
|
||||
|
||||
temp[0]=0;
|
||||
if(strchr(aBuffer,'@')){
|
||||
|
||||
int pos=-1;
|
||||
while(aBuffer[++pos]==' ')
|
||||
strcat(temp," ");
|
||||
|
||||
istrstream iStr(aBuffer);
|
||||
while(!iStr.eof()){
|
||||
theWord[0]=0;
|
||||
iStr>>theWord;
|
||||
char* thePos=strchr(theWord,'@');
|
||||
if(thePos){
|
||||
strncat(temp,theWord,thePos-theWord);
|
||||
if(!strnicmp(thePos,"@file",5)){
|
||||
strcat(temp,gThisFile);
|
||||
thePos+=5;
|
||||
}
|
||||
else if(!strnicmp(thePos,"@nextfile",9)){
|
||||
strcat(temp,gNextFile);
|
||||
thePos+=9;
|
||||
}
|
||||
else if(!strnicmp(thePos,"@prevfile",9)){
|
||||
strcat(temp,gPrevFile);
|
||||
thePos+=9;
|
||||
}
|
||||
strcat(temp,thePos);
|
||||
}
|
||||
else strcat(temp,theWord);
|
||||
strcat(temp," ");
|
||||
}
|
||||
strcpy(aBuffer,temp);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @update gess12/20/98
|
||||
* @param
|
||||
* @return
|
||||
*/
|
||||
void expandMacros(char* aBuffer,CMacros& aMacroSet){
|
||||
char temp[1024];
|
||||
int rPos=-1;
|
||||
int wPos=0;
|
||||
|
||||
if(aBuffer){
|
||||
while(aBuffer[++rPos]){
|
||||
if('$'==aBuffer[rPos]){
|
||||
temp[wPos]=0;
|
||||
rPos++; //skip the $...
|
||||
int theIndex=aBuffer[rPos]-'0';
|
||||
char* theMacro=aMacroSet.getMacro(theIndex);
|
||||
if(theMacro){
|
||||
strcat(temp,theMacro);
|
||||
wPos=strlen(temp);
|
||||
}
|
||||
}
|
||||
else temp[wPos++]=aBuffer[rPos];
|
||||
}
|
||||
temp[wPos]=0;
|
||||
strcpy(aBuffer,temp);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @update gess12/20/98
|
||||
* @param
|
||||
* @return
|
||||
*/
|
||||
int processFile(char* aDir,fstream& anOutputStream,istrstream& aInputArgs){
|
||||
int result=0;
|
||||
|
||||
CMacros theMacros;
|
||||
theMacros.consume(aInputArgs);
|
||||
|
||||
char* theFilename=theMacros.getFilename();
|
||||
fstream theInputStream(theFilename,ios::in);
|
||||
if(theInputStream.is_open()){
|
||||
bool done=false;
|
||||
char theBuffer[1024];
|
||||
char theWord[600];
|
||||
|
||||
while((!done) && (0==result)){
|
||||
|
||||
theInputStream.getline(theBuffer,sizeof(theBuffer)-1);
|
||||
if(theInputStream.gcount()){
|
||||
|
||||
//before doing anything else, expand the macros and keywords...
|
||||
expandMacros(theBuffer,theMacros);
|
||||
expandKeywords(theBuffer,theMacros);
|
||||
|
||||
//Now process each line:
|
||||
if(strchr(theBuffer,'@')) {
|
||||
|
||||
//First, see if the line is an htmlgen statement; if so, recurse to read new file...
|
||||
istrstream iStr(theBuffer);
|
||||
iStr>>theWord;
|
||||
if(!stricmp(theWord,"@htmlgen")){
|
||||
|
||||
//If you're here, we found an htmlgen statement.
|
||||
// To handle this, we have to:
|
||||
// 1. strip off the @htmlgen
|
||||
// 2. grab the filename and collect the args,
|
||||
// 3. and recurse...
|
||||
|
||||
result=processFile(aDir,anOutputStream,iStr);
|
||||
}
|
||||
}
|
||||
else anOutputStream << theBuffer << endl;
|
||||
}
|
||||
else done=true;
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* This is where the different combinations of arguments
|
||||
* gets constructed and passed on for processing.
|
||||
* Note that this is even called when the args have only 1 value.
|
||||
* @return error code
|
||||
*/
|
||||
int iterate(istrstream& aInputArgs){
|
||||
int result=0;
|
||||
|
||||
CMacros theArgs;
|
||||
theArgs.consume(aInputArgs);
|
||||
|
||||
char theBuffer[1024];
|
||||
char theFilename[1024];
|
||||
|
||||
bool done=!theArgs.first();
|
||||
while((!done) && (0==result)){
|
||||
CMacros theTempArgs(theArgs);
|
||||
theTempArgs.buildArgBuffer(theBuffer);
|
||||
istrstream theArgStream(theBuffer);
|
||||
sprintf(theFilename,"%s\\%s",gCWD,gThisFile);
|
||||
fstream theOutStream(theFilename,ios::trunc);
|
||||
result=processFile(gCWD,theOutStream,theArgStream);
|
||||
theArgs.dump();
|
||||
done=!theArgs.next();
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @update gess12/20/98
|
||||
* @param
|
||||
* @return
|
||||
*/
|
||||
int main(int argc,char* argv[]){
|
||||
int result=0;
|
||||
|
||||
gPrevFile[0]=gThisFile[0]=gNextFile[0];
|
||||
if(argc>1){
|
||||
char theBuffer[1024];
|
||||
theBuffer[0]=0;
|
||||
|
||||
for(int i=1;i<argc;i++){
|
||||
strcat(theBuffer,argv[i]);
|
||||
strcat(theBuffer," ");
|
||||
}
|
||||
|
||||
_getcwd(gCWD,sizeof(gCWD)-1);
|
||||
istrstream aStrStream(theBuffer);
|
||||
result=iterate(aStrStream);
|
||||
}
|
||||
else cout<<endl <<"HTMLGenerator usage -f filename [-d yyy|xxx,yyy|xxx...yyy]" << endl;
|
||||
return result;
|
||||
}
|
Loading…
Reference in New Issue
Block a user