source/contest2.cpp 0100755 0000000 0000000 00000064366 07331012006 013334 0 ustar root root // contest 2001.cpp : Defines the entry point for the console application.
//
#include "stdio.h"
#include "string.h"
//#include "io.h"
#include "stdlib.h"
#define GetSecondChar(ch) thischar = getchar(); if (thischar != ch) { printf("\n ** bad tag 2 %c, expecting %c", thischar, ch); }; //Error!
#define FALSE 0
#define TRUE 1
#define ColorFlag 0x0040
#define UnderLineFlag 0x0080
#define SizeFlag 0x0020
#define BoldFlag 0x0001
#define EmphasisFlag 0x0002
#define StrongFlag 0x0008
#define ItalicFlag 0x0004
#define TeletypeFlag 0x0010
#define AttrFlags BoldFlag|EmphasisFlag|StrongFlag|ItalicFlag|TeletypeFlag
#define PlainFlags UnderLineFlag|AttrFlags
#define ColorMask 0xF000
#define UnderLineMask 0x00E0
#define UnderLine1Mask 0x0020
#define UnderLine2Mask 0x0040
#define UnderLine3Mask 0x0080
#define SizeMask 0x0F00
#define BoldMask 0x0001
#define EmphasisMask 0x0002
#define StrongMask 0x0008
#define ItalicMask 0x0004
#define TeletypeMask 0x0010
#define AttrMask (UnderLineMask|BoldMask|EmphasisMask|StrongMask|ItalicMask|TeletypeMask)
#define PlainMask (UnderLineMask|AttrMask)
#define ColorShift 12
#define UnderLineShift 5
#define UnderLine1Shift 5
#define UnderLine2Shift 6
#define UnderLine3Shift 7
#define SizeShift 8
#define BoldShift 0
#define EmphasisShift 1
#define StrongShift 3
#define ItalicShift 2
#define TeletypeShift 4
#define PlainShift 0
#define AttrShift 0
#define SetField(Word,Fld,Value) Word = (ChAttr)((Word & ~Fld##Mask) | (ChAttr)((Value) << Fld##Shift))
#define GetField(Word,Fld) ((Word & Fld##Mask) >> Fld##Shift)
#define SetFlag(Word,Fld) Word = (ChAttr)(Word | (ChAttr)(1 << Fld##Shift))
#define ResetFlag(Word,Fld) Word = (ChAttr)(Word & ~Fld##Mask)
#define GetFlag(Word,Fld) (Word & Fld##Mask)
#define FlipFlag(Word,Fld) Word = (ChAttr)(Word ^ Fld##Mask)
#define EqualFields(Word1, Word2, Fld) (GetFlag(Word1,Fld) == GetFlag(Word2,Fld))
#define CopyField(dst, src, Fld) dst = (ChAttr)((dst & ~Fld##Mask) | (src & Fld##Mask))
enum Colors { c_unknown, c_red, c_green, c_blue, c_cyan, c_magenta, c_yellow, c_black, c_white};
enum Cmds {C_None, C_Bold, C_Emphasis, C_Italic, C_Strong, C_Teletype, C_UnderLine,
C_UnderLine1, C_UnderLine2, C_UnderLine3,
C_Plain, C_Size0, C_Size1, C_Size2, C_Size3, C_Size4, C_Size5, C_Size6,
C_Size7, C_Size8, C_Size9, C_red, C_green, C_blue, C_cyan, C_magenta,
C_yellow, C_black, C_white};
enum Tags {T_Bold, T_Emphasis, T_Italic, T_Strong, T_Teletype, T_Size, T_Color, T_UnderLine, T_UnderLine1, T_UnderLine2, T_UnderLine3};
char *TagNames[] = {"Bold","Emphasis","Italic","Strong","Teletype","Size","Color","Underline","Underline1","Underline2","Underline3"};
char *TagOpenStr[] = {"", "", "", "", "", "",
"", "", "", "", "", "<0>", "<1>", "<2>", "<3>",
"<4>", "<5>", "<6>", "<7>", "<8>", "<9>",
"", "", "", "", "", "",
"", ""};
char *TagCloseStr[] = {"", "", "", "", "", "",
"", "", "", "", "", "0>", "1>", "2>", "3>",
"4>", "5>", "6>", "7>", "8>", "9>",
"", "", "", "", "", "",
"", ""};
struct ChAttrStruct {
int Emphasis : 1;
int Bold : 1;
int Strong : 1;
int Italic : 1;
int Teletype : 1;
unsigned UnderLine : 3;
unsigned Color : 4;
unsigned Size : 4;
};
#define MaxStack 20000
#define IncStack(s) {if (++s > 20000) }
typedef unsigned ChAttr;
typedef struct CmdAttrStackStruct {
ChAttr Attr;
Cmds Cmd;
struct CmdAttrStackStruct *Prev;
} StackType;
typedef struct ColorStackStruct {
Colors Color;
struct ColorStackStruct *Prev;
} ColorStackType;
typedef struct SizeStackStruct {
unsigned Size;
struct SizeStackStruct *Prev;
} SizeStackType;
Cmds CmdTable[256];
ChAttr *Attrs;
char *Chars;
int IsWhiteSpace = FALSE;
long OutIx = 0;
long EmphasisCount = 0;
ChAttr *LastAttr;
// Linked list stack support macros
#define MakeStackVars(ST) ST##Type ST##First, *ST##Top, *ST##Free, *ST##Temp
#define Push(ST) \
{if (ST##Free) { \
ST##Temp = ST##Free;\
ST##Free = ST##Free->Prev;\
}else{\
ST##Temp = (ST##Type *)malloc(sizeof (ST##Type));\
}\
ST##Temp->Prev = ST##Top;\
ST##Top = ST##Temp;\
}
#define Pop(ST) \
{\
if (ST##Top != &ST##First) {\
ST##Temp = ST##Top;\
ST##Top = ST##Top->Prev; \
ST##Temp->Prev = ST##Free; \
ST##Free = ST##Temp; \
}\
}
#define InitStack(ST) \
{\
ST##First.Prev = NULL;\
ST##Top = &ST##First;\
ST##Free = NULL;\
}
#define FreeStack(ST) \
{\
while (ST##Free) {\
ST##Temp = ST##Free;\
ST##Free = ST##Free->Prev;\
free(ST##Temp);\
}}
// Stacks for cmds & attributes, Color, Size
MakeStackVars(Stack);
MakeStackVars(ColorStack);
MakeStackVars(SizeStack);
void InitCmdTable(void)
{
memset(CmdTable, C_None, 256);
CmdTable['B'] = C_Bold;
CmdTable['E'] = C_Emphasis;
CmdTable['I'] = C_Italic;
CmdTable['S'] = C_Strong;
CmdTable['T'] = C_Teletype;
CmdTable['U'] = C_UnderLine;
CmdTable['P'] = C_Plain;
CmdTable['0'] = C_Size0;
CmdTable['1'] = C_Size1;
CmdTable['2'] = C_Size2;
CmdTable['3'] = C_Size3;
CmdTable['4'] = C_Size4;
CmdTable['5'] = C_Size5;
CmdTable['6'] = C_Size6;
CmdTable['7'] = C_Size7;
CmdTable['8'] = C_Size8;
CmdTable['9'] = C_Size9;
CmdTable['r'] = C_red;
CmdTable['b'] = C_blue;
CmdTable['g'] = C_green;
CmdTable['c'] = C_cyan;
CmdTable['m'] = C_magenta;
CmdTable['y'] = C_yellow;
CmdTable['k'] = C_black;
CmdTable['w'] = C_white;
} //InitCmdTable;
void ParseInput(void)
{
int thischar;
Cmds ThisCmd;
while ( (thischar = getchar()) != EOF) {
if (thischar == '<') {
// Parse tag
thischar = getchar();
if (thischar == '/') {
thischar = getchar();
ThisCmd = CmdTable[thischar];
if (ThisCmd != C_None) {
if (ThisCmd != StackTop->Cmd) {
// Error!
printf("\n ** tag mismatch, expecting %d, got %d\n",StackTop->Cmd,ThisCmd);
}
else {
Pop(Stack);
switch (ThisCmd) {
case C_Emphasis:
GetSecondChar('M');
break;
case C_Plain:
GetSecondChar('L');
break;
case C_Teletype:
GetSecondChar('T');
break;
case C_UnderLine:
IsWhiteSpace = FALSE;
break;
default:
break;
}
}
}
}
else { // Open tag
ThisCmd = CmdTable[thischar];
if (ThisCmd != C_None) {
Push(Stack);
ThisCmd = ThisCmd;
StackTop->Attr = (StackTop->Prev)->Attr;
StackTop->Cmd = ThisCmd;
}
else
printf("\n ** Bad tag %c\n",thischar);
switch (CmdTable[thischar]) {
case C_None : // should not happen!
break;
case C_Bold:
SetFlag(StackTop->Attr,Bold);
break;
case C_Emphasis:
GetSecondChar('M');
if (!GetFlag(StackTop->Attr,Strong)) {
FlipFlag(StackTop->Attr,Emphasis);
}
break;
case C_Italic:
SetFlag(StackTop->Attr,Italic);
break;
case C_Strong:
StackTop->Attr = (ChAttr)((StackTop->Attr & ~EmphasisMask) | StrongMask);
break;
case C_Teletype:
GetSecondChar('T');
SetFlag(StackTop->Attr,Teletype);
break;
case C_UnderLine:
int tempunder;
tempunder = GetField(StackTop->Attr,UnderLine);
switch (tempunder) {
case 7 :
case 6:
case 5 :
case 4 :
case 3 :
case 2 : tempunder |= 4;
case 1 : tempunder |= 2;
case 0 : tempunder |= 1;
}
SetField(StackTop->Attr,UnderLine,tempunder);
IsWhiteSpace = FALSE;
break;
case C_Plain:
GetSecondChar('L');
ResetFlag(StackTop->Attr, Plain);
break;
case C_Size0:
case C_Size1:
case C_Size2:
case C_Size3:
case C_Size4:
case C_Size5:
case C_Size6:
case C_Size7:
case C_Size8:
case C_Size9:
SetField(StackTop->Attr, Size, (thischar-'0'));
break;
case C_red:
case C_green:
case C_blue:
case C_cyan:
case C_magenta:
case C_yellow:
case C_black:
case C_white:
SetField(StackTop->Attr, Color, ((ThisCmd-C_red)+c_red));
break;
}
}
GetSecondChar('>');
}
else if ((thischar == ' ') ||
(thischar == '\t') ||
(thischar == '\n') ||
(thischar == '\r') ) {
if (!GetFlag(StackTop->Attr,Teletype)) {
// whitespace
if (IsWhiteSpace) {
if ( ( GetFlag(StackTop->Attr,UnderLine) && !EqualFields(StackTop->Attr,Attrs[OutIx-1],Color) ) ||
!EqualFields(StackTop->Attr,Attrs[OutIx-1],Size) ){
Chars[OutIx] = (char)thischar;
Attrs[OutIx] = StackTop->Attr;
OutIx++;
}
else {
if ((Chars[OutIx-1] == '\r') && (thischar == '\n')) Chars[OutIx-1] = '\n';
}
}
else {
IsWhiteSpace = TRUE;
Chars[OutIx] = (char)thischar;
Attrs[OutIx] = StackTop->Attr;
OutIx++;
}
}
else { //Teletype mode
Chars[OutIx] = (char)thischar;
Attrs[OutIx] = StackTop->Attr;
OutIx++;
IsWhiteSpace = FALSE;
}
}
else { //Not white space
Chars[OutIx] = (char)thischar;
Attrs[OutIx] = StackTop->Attr;
OutIx++;
IsWhiteSpace = FALSE;
}
}
Attrs[OutIx] = StackFirst.Attr;
Chars[OutIx] = 0;
LastAttr = Attrs+OutIx;
OutIx++;
} //ParseInput
void dumpbuf()
{
FILE *Dump = fopen("Dump.txt","w");
long Ix;
for (Ix = 0; Ix < OutIx; Ix++) {
if (Chars[Ix] == '\n') fprintf (Dump,"char=\\n ");
else fprintf(Dump,"char=%c ",Chars[Ix]);
if (GetFlag(Attrs[Ix],Bold)) fprintf(Dump,"B");
else fprintf(Dump," ");
if (GetFlag(Attrs[Ix],Emphasis)) fprintf(Dump,"E");
else fprintf(Dump," ");
if (GetFlag(Attrs[Ix],Italic)) fprintf(Dump,"I");
else fprintf(Dump," ");
if (GetFlag(Attrs[Ix],Strong)) fprintf(Dump,"S");
else fprintf(Dump," ");
if (GetFlag(Attrs[Ix],Teletype)) fprintf(Dump,"T");
else fprintf(Dump," ");
if (GetField(Attrs[Ix],Size) != 12) fprintf(Dump,"%1d",GetField(Attrs[Ix],Size));
else fprintf(Dump," ");
fprintf(Dump,"_%1d_",GetField(Attrs[Ix],UnderLine));
if (GetField(Attrs[Ix],Color) == c_unknown) fprintf(Dump," ");
else {
switch(GetField(Attrs[Ix],Color)) {
case c_red : fprintf(Dump,"r");
break;
case c_green: fprintf(Dump,"g");
break;
case c_blue: fprintf(Dump,"b");
break;
case c_cyan: fprintf(Dump,"c");
break;
case c_magenta: fprintf(Dump,"m");
break;
case c_yellow: fprintf(Dump,"y");
break;
case c_black: fprintf(Dump,"k");
break;
case c_white: fprintf(Dump,"w");
break;
}
}
fprintf(Dump,"\n");
} //for
fclose(Dump);
}
//
// Write the result
//
// Obviously, this is where the hard stuff happens.
//
//
// -- PutString
// Write a string, no interpretation.
//
void PutString(char *str)
{
while (*str) putchar(*str++);
}
//
//
void PopCmdStack()
{
if (StackTop != &StackFirst) {
if ( (StackTop->Cmd >= C_red) && (StackTop->Cmd <= C_white) )
Pop(ColorStack);
if ( (StackTop->Cmd >= C_Size0) && (StackTop->Cmd <= C_Size9) )
Pop(SizeStack);
if ( StackTop->Cmd == C_Emphasis ) EmphasisCount--;
PutString(TagCloseStr[StackTop->Cmd]);
Pop(Stack);
}
}
void WindDownStack(Cmds thisTag)
{
while ((StackTop != &StackFirst) && (StackTop->Cmd != thisTag)) {
PopCmdStack();
}
PopCmdStack();
} // WindDownStack
int CountBits(ChAttr SomeAttr)
{
int c;
c = ((SomeAttr & 0xAAAA) >> 1) + (SomeAttr & 0x5555);
c = ((c & 0xCCCC) >> 2) + (c & 0x3333);
c = ((c & 0xF0F0) >> 4) + (c & 0x0F0F);
c = ((c & 0xFF00) >> 8) + (c & 0x00FF);
return c;
}
#define ChkFlag(Fld) if (GetFlag(FlagsChanged, Fld)) {\
if (GetFlag(ThisAttr,Fld)) \
GotSet[(*SetCount)++] = C_##Fld; \
else \
GotReset[(*ResetCount)++] = C_##Fld; \
}
#define ChkValue(Fld, BaseCmd, BaseValue) if (!EqualFields(BaseAttr,ThisAttr,Fld)) {\
Fld##Changed = TRUE; \
New##Fld = (Cmds)(GetField(ThisAttr,Fld)-BaseValue+BaseCmd); \
}
//
// Scan the stack to see if popping to the indicated command will
// give us a compatible set of attributes.
//
int ScanStackForState(Cmds CmdToFind, ChAttr ThisAttr)
{
short Matching = TRUE;
ChAttr TestFlags;
StackTemp = StackTop;
while ((StackTemp->Cmd != CmdToFind) && (StackTemp != &StackFirst)) {
TestFlags = StackTemp->Attr ^ ThisAttr;
if (GetFlag(TestFlags,Color) ) {
Matching = EqualFields(StackTemp->Attr, ThisAttr, Color);
}
if (GetFlag(TestFlags,Size) ) {
Matching &= EqualFields(StackTemp->Attr, ThisAttr, Size);
}
if ( (StackTemp->Attr & TestFlags & AttrMask) != (ThisAttr & TestFlags & AttrMask) ) {
Matching = FALSE;
}
StackTemp = StackTemp->Prev;
};
return Matching;
} //ScanStackForState
int ScanStackForColorSize(Cmds CmdToFind, ChAttr ThisAttr)
{
short Matching = TRUE;
ChAttr TestFlags;
StackTemp = StackTop;
while ((StackTemp->Cmd != CmdToFind) && (StackTemp != &StackFirst)) {
StackTemp = StackTemp->Prev;
};
StackTemp = StackTemp->Prev;
if (StackTemp) {
TestFlags = StackTemp->Attr ^ ThisAttr;
if (GetFlag(TestFlags,Color) ) {
Matching = EqualFields(StackTemp->Attr, ThisAttr, Color);
}
if (GetFlag(TestFlags,Size) ) {
Matching &= EqualFields(StackTemp->Attr, ThisAttr, Size);
}
if ( (StackTemp->Attr & TestFlags & AttrMask) != (ThisAttr & TestFlags & AttrMask) ) {
Matching = FALSE;
}
}
return Matching;
} //ScanStackForState
// WhatChanged -
//
// Scans the current attributes against the base attributes and returns
// true if they are different.
// Also, a list is provided of:
// Tags that are set.
// Tags that are reset.
// if color changed.
// if size changed.
// change in underline (+ or -).
//
int WhatChanged(ChAttr BaseAttr, int Ix,
Cmds *GotSet, int *SetCount,
Cmds *GotReset, int *ResetCount,
// char *ColorChanged, Cmds *NewColor,
// char *SizeChanged, Cmds *NewSize,
int *PlainDiff)
{
int IsWhiteSpace;
int Iy = 0;
ChAttr ThisAttr = Attrs[Ix];
char ThisChar = Chars[Ix];
ChAttr FlagsChanged = BaseAttr ^ ThisAttr;
Cmds NewColor = C_None;
Cmds NewSize = C_None;
*SetCount = 0;
*ResetCount = 0;
char ColorChanged = FALSE;
char SizeChanged = FALSE;
*PlainDiff = 0;
int PrevColorMatch, PrevSizeMatch;
Cmds CmdStkTop = StackTop->Cmd;
Colors ColorToFind, ColorToPop;
unsigned SizeToFind, SizeToPop;
if ( BaseAttr != ThisAttr) {
ChkValue(Color, C_red, c_red);
ChkValue(Size, C_Size0, 0);
if (ColorChanged) {
// if cmdstack == set to current color
// and previous color on color stack is what we want,
// then this is a reset.
// otherwise, it is a set, unless by resetting other flags we end up
// in a different state!
// Simple minded version for now:
#ifdef Simple
PrevColorMatch = (ColorStackTop->Color != c_unknown) && (ColorStackTop->Prev->Color == (Colors)(GetField(ThisAttr,Color)));
if ( ((CmdStkTop == (Cmds)(C_red+GetField(BaseAttr,Color)-c_red) )
&& PrevColorMatch) || (GetField(ThisAttr,Color) == c_unknown) ) {
GotReset[(*ResetCount)++] = CmdStkTop;
}
else {
GotSet[(*SetCount)++] = NewColor;
}
#else
if (GetField(BaseAttr, Color) == c_unknown) {
GotSet[(*SetCount)++] = NewColor;
}
else if (GetField(ThisAttr, Color) == c_unknown) {
GotReset[(*ResetCount)++] = (Cmds)(ColorStackTop->Color-c_red+C_red);
}
else {
PrevColorMatch = FALSE;
ColorStackTemp = ColorStackTop->Prev;
ColorToPop = ColorStackTop->Color;
ColorToFind = (Colors)GetField(ThisAttr, Color);
while (!PrevColorMatch) {
PrevColorMatch = (ColorStackTemp->Color == ColorToFind);
if (!PrevColorMatch) {
ColorToPop = ColorStackTemp->Color;
}
ColorStackTemp = ColorStackTemp->Prev;
if (ColorStackTemp == NULL) break;
}
if ( PrevColorMatch && ScanStackForColorSize((Cmds)(ColorToPop-c_red+C_red), ThisAttr) ) {
GotReset[(*ResetCount)++] = (Cmds)(C_red+ColorToPop-c_red);
}
else
GotSet[(*SetCount)++] = NewColor;
}
}
#endif
#ifdef Simple
if (SizeChanged) {
PrevSizeMatch = (SizeStackTop->Size != 12) && (SizeStackTop->Prev->Size == (unsigned)GetField(ThisAttr,Size));
if ( ((CmdStkTop == (Cmds)(C_Size0+GetField(BaseAttr,Size)) )
&& PrevSizeMatch) || (GetField(ThisAttr,Size) == 12) ) {
GotReset[(*ResetCount)++] = CmdStkTop;
}
else {
GotSet[(*SetCount)++] = NewSize;
}
}
#else
if (GetField(BaseAttr, Size) == 12) {
GotSet[(*SetCount)++] = NewSize;
}
else if (GetField(ThisAttr, Size) == 12) {
GotReset[(*ResetCount)++] = (Cmds)(SizeStackTop->Size+C_Size0);
}
else {
PrevSizeMatch = FALSE;
SizeStackTemp = SizeStackTop->Prev;
SizeToPop = SizeStackTop->Size;
SizeToFind = (unsigned)GetField(ThisAttr, Size);
while (!PrevSizeMatch) {
PrevSizeMatch = (SizeStackTemp->Size == SizeToFind);
if (!PrevSizeMatch) {
SizeToPop = SizeStackTemp->Size;
}
SizeStackTemp = SizeStackTemp->Prev;
if (SizeStackTemp == NULL) break;
}
if ( PrevSizeMatch && ScanStackForColorSize((Cmds)(SizeToPop+C_Size0), ThisAttr) ) {
GotReset[(*ResetCount)++] = (Cmds)(C_Size0+SizeToPop);
}
else
GotSet[(*SetCount)++] = NewSize;
}
#endif
// Plain check
if ( (ThisAttr & PlainMask) == 0) {
// All attributes that get reset by plain will be reset in new char.
if ( ( (FlagsChanged & PlainMask) != 0 ) && (CountBits(FlagsChanged & PlainMask) > 1) ){
// Attributes that are affected by plain were switched in new char
Iy = Ix+1;
while (Iy < OutIx) {
if (Attrs[Iy] != ThisAttr) {
if (Attrs[Iy] == BaseAttr) *PlainDiff = 1;
break;
}
Iy++;
} //while
}
}
else { //See if we need to turn plain off.
if (StackTop->Cmd == C_Plain) {
*PlainDiff = -1;
}
}
if (*PlainDiff == 0) {
// Emphasis optimization:
// If Strong is set, then we can ignore Emphasis for now;
if (!GetFlag(ThisAttr,Strong) && GetFlag(FlagsChanged, Emphasis)) {
// If the emphasis flag got flipped
// If there are no outstanding emphasis, this is easy
if (EmphasisCount == 0)
GotSet[(*SetCount)++] = C_Emphasis;
// If the command on the top of the stack is emphasis,
// do the reset
else if (StackTop->Cmd == C_Emphasis) {
GotReset[(*ResetCount)++] = C_Emphasis;
}
// The next case a reset is optimal,
// is if when we find the last emphasis command, do the attributes
// that changed this match (is the set that changed now a match
// the things that change if we unwind the stack)
else {
if (ScanStackForState(C_Emphasis, ThisAttr) )
GotReset[(*ResetCount)++] = C_Emphasis;
else
GotSet[(*SetCount)++] = C_Emphasis;
}
}
ChkFlag(Bold);
ChkFlag(Italic);
ChkFlag(Strong);
ChkFlag(Teletype);
ChkFlag(UnderLine3);
ChkFlag(UnderLine2);
ChkFlag(UnderLine1);
// for whitespace characters:
// Some changes we can ignore for the time being as they don't affect
// whitespace. This sometimes lets us to ignore flags that get reset then
// set again on the next line (for instance).
//
if (FlagsChanged & (UnderLineMask | SizeMask | TeletypeMask)) return TRUE;
IsWhiteSpace = (ThisChar == ' ') || (ThisChar == '\t') ||
(ThisChar == '\n') || (ThisChar == '\r');
if (!IsWhiteSpace) return TRUE;
// Looking at white space
if ((ThisAttr & (UnderLineMask | TeletypeMask) )&& ColorChanged) return TRUE;
return FALSE;
}
else
return TRUE;
}
return FALSE;
} // WhatChanged
//
// ScanForChanges --
// Scan the text for a change to the attributes
#define TestFlag(Flg) if (GetFlag(FlagsChanged, Flg) && !GetFlag(Attrs[Ix], Flg)) {\
*NewMask = Flg##Mask; \
*NewValue = 1 << Flg##Shift; \
return C_##Flg; \
}
#define TestField(Fld, base) if (GetFlag(FlagsChanged, Fld)) {\
if (!Changed##Fld) Changed##Fld = Ix; \
if (EqualFields(Attrs[Ix], BaseAttr, Fld) ){ \
*NewMask = Fld##Mask; \
*NewValue = GetField(Attrs[StartIx], Fld) << Fld##Shift; \
return (Cmds)((base)+GetField(Attrs[StartIx],Fld)); \
} \
}
Cmds ScanForChanges(ChAttr BaseAttr, ChAttr BaseMask, int StartIx, ChAttr *NewMask, ChAttr *NewValue)
{
ChAttr FlagsChanged;
int ChangedColor = 0, ChangedSize = 0;
for (int Ix = StartIx; Ix < OutIx; Ix++) {
FlagsChanged = (BaseMask & Attrs[Ix]) ^ (BaseMask & Attrs[StartIx]);
if (FlagsChanged) {
TestFlag(Bold);
TestFlag(Italic);
TestFlag(Strong);
TestFlag(Teletype);
TestFlag(UnderLine3);
TestFlag(UnderLine2);
TestFlag(UnderLine1);
TestField(Color, C_red-c_red);
TestField(Size, C_Size0);
if (GetFlag(FlagsChanged, Emphasis) && (GetField(Attrs[Ix], Emphasis) == (unsigned)(EmphasisCount & 1)) ) {
*NewMask = EmphasisMask;
*NewValue = ((EmphasisCount^1) & 1) << EmphasisShift;
return C_Emphasis;
}
// TestFlag(Emphasis);
}
}
if (ChangedColor || ChangedSize) {
if ( ChangedColor && ( (ChangedColor < ChangedSize) || !ChangedSize) ) {
*NewMask = ColorMask;
*NewValue = GetField(Attrs[StartIx], Color) << ColorShift;
return (Cmds)(GetField(Attrs[StartIx], Color)+C_red-c_red);
}
else {
*NewMask = SizeMask;
*NewValue = GetField(Attrs[StartIx], Size) << SizeShift;
return (Cmds) (GetField(Attrs[StartIx], Size) + C_Size0);
}
}
return C_None;
}
//
//
int SortCnt;
void FixupTags2(int Ix)
{
Cmds ResetCmds[11];
Cmds SetCmds[11];
Cmds SortedCmds[11];
// Cmds ColorCmd;
// Cmds SizeCmd;
int SetCnt;
int ResetCnt;
int FlagsChanged;
// char NewColor, NewSize; // Booleans
ChAttr AttrStkTop;
Cmds CmdStkTop;
ChAttr NewAttrs;
// int PrevColorMatch;
// int PrevSizeMatch;
int TagIx;
StackType *StackPtr;
// int SortCnt;
int TagCnt;
int FlagsToScanFor;
ChAttr RevisedValue[11];
ChAttr RevisedMask[11];
int PlainDiff;
while ( WhatChanged ( AttrStkTop = StackTop->Attr, Ix,
SetCmds, &SetCnt,
ResetCmds, &ResetCnt,
// &NewColor, &ColorCmd,
// &NewSize, &SizeCmd,
&PlainDiff) )
{
CmdStkTop = StackTop->Cmd;
NewAttrs = Attrs[Ix];
FlagsChanged = AttrStkTop ^ NewAttrs;
// Reset anything that needs it, then try this again
if (PlainDiff < 0) {
WindDownStack(C_Plain);
continue;
}
if (ResetCnt) {
SortCnt = 0;
TagCnt = 0;
for (StackPtr = StackTop; (StackPtr != &StackFirst) && (TagCntPrev) {
for (TagIx=0; TagIx < ResetCnt; TagIx++) {
if (StackPtr->Cmd == ResetCmds[TagIx]) {
if ( (StackPtr->Cmd != C_Emphasis) || !GetFlag(NewAttrs, Strong) ) {
// Don't worry about emphasis getting reset now if strong was set
SortedCmds[SortCnt++] = ResetCmds[TagIx];
}
ResetCmds[TagIx] = C_None;
TagCnt++;
break;
}
}
}
if (SortCnt) {
WindDownStack(SortedCmds[SortCnt-1]);
continue;
}
}
if (SetCnt) {
FlagsToScanFor = AttrStkTop & FlagsChanged & AttrMask;
if (GetFlag(FlagsChanged, Color) ) {
CopyField(FlagsToScanFor, AttrStkTop, Color);
FlagsChanged |= ColorMask;
}
if (GetFlag(FlagsChanged, Size) ) {
CopyField(FlagsToScanFor, AttrStkTop, Size);
FlagsChanged |= SizeMask;
}
SortCnt = 0;
while (FlagsChanged) {
SortedCmds[SortCnt] = ScanForChanges(FlagsToScanFor, FlagsChanged, Ix,
&(RevisedMask[SortCnt]),
&(RevisedValue[SortCnt]));
FlagsChanged &= ~RevisedMask[SortCnt];
if (RevisedMask[SortCnt] == StrongMask) {
FlagsChanged &= ~EmphasisMask;
ResetFlag(FlagsToScanFor, Emphasis);
}
SortCnt++;
}
while (SortCnt) {
SortCnt--;
PutString(TagOpenStr[SortedCmds[SortCnt]]);
Push(Stack)
StackTop->Attr = StackTop->Prev->Attr & ~RevisedMask[SortCnt] | RevisedValue[SortCnt];
StackTop->Cmd = SortedCmds[SortCnt];
if (StackTop->Cmd == C_Emphasis) EmphasisCount++;
if (RevisedMask[SortCnt] == ColorMask) {
Push(ColorStack);
ColorStackTop->Color = (Colors)(RevisedValue[SortCnt] >> ColorShift);
}
if (RevisedMask[SortCnt] == SizeMask) {
Push(SizeStack);
SizeStackTop->Size = RevisedValue[SortCnt] >> SizeShift;
}
if (RevisedMask[SortCnt] == StrongMask)
ResetFlag(StackTop->Attr, Emphasis);
}// while
if (PlainDiff == 0)
continue;
}
if (PlainDiff > 0) {
PutString(TagOpenStr[C_Plain]);
Push(Stack);
StackTop->Attr = StackTop->Prev->Attr & ~PlainMask;
StackTop->Cmd = C_Plain;
continue;
}
} // while
}// FixupTags2
//
void OutputResult()
{
long Ix;
for (Ix = 0; Ix < OutIx; Ix++) {
// FixupTags(Attrs[Ix]);
FixupTags2(Ix);
if (Chars[Ix])
/* if ((Chars[Ix] == '\n') || (Chars[Ix] == '\r'))
putchar('\n');
else */
putchar(Chars[Ix]);
}
WindDownStack(StackFirst.Cmd);
printf("\n");
} //OutputResult
#define _filelength(k) 5200000
int main(int argc, char* argv[])
{
long OriginalFileLength = _filelength(0);
Chars = (char *)malloc(OriginalFileLength);
memset(Chars, 0, OriginalFileLength);
Attrs = (ChAttr *) malloc(OriginalFileLength * sizeof(ChAttr) );
memset(Attrs, 0, OriginalFileLength * sizeof(ChAttr) );
InitCmdTable();
InitStack(Stack);
StackFirst.Attr = 0;
StackFirst.Cmd = C_None;
StackFirst.Prev = NULL;
SetField(StackFirst.Attr, Size, 12);
SetField(StackFirst.Attr, Color, c_unknown);
InitStack(ColorStack);
ColorStackFirst.Color = c_unknown;
ColorStackFirst.Prev = NULL;
InitStack(SizeStack);
SizeStackFirst.Size = 12;
SizeStackFirst.Prev = NULL;
ParseInput();
// dumpbuf();
OutputResult();
free(Attrs);
free(Chars);
FreeStack(ColorStack);
FreeStack(SizeStack);
FreeStack(Stack);
return 0;
}
buildme 0100755 0000000 0000000 00000000046 07331014771 011127 0 ustar root root g++ source/contest2.cpp -o runme -O3
runme 0100755 0000000 0000000 00000057631 07331015033 010640 0 ustar root root ELF 4 M 4 ( 4 44 `' `' `' `` @ X) XX /lib/ld-linux.so.2 GNU
) X - 2 Ѕ 8 r B ( " % 8 H2 Z P X h " x ` 1 C $ v Ȇ " __gmon_start__ libstdc++-libc6.2-2.so.3 _DYNAMIC _init __rethrow __deregister_frame_info _fini _GLOBAL_OFFSET_TABLE_ __register_frame_info libm.so.6 _IO_stdin_used libc.so.6 printf stdout __cxa_finalize malloc fprintf stdin _IO_getc memset fclose fopen _IO_putc __libc_start_main free _edata __bss_start _end GLIBC_2.1.3 GLIBC_2.1 GLIBC_2.0 si 6 ii
B ii
L T $ $ ( , 0
4 8
< @ D H L P U) * 5% %h % h %$h %(h %,h %0h( %4h0 %8h8 p%<h@ `%@hH P%DhP @%HhX 0%Lh` %Phh 1^PTRhPhЅQVhl7USP [2 D tЋ]ÉUluIhtt&