allow relooper to manager its own output buffer, to avoid fixed output limits
This commit is contained in:
Родитель
ec3eba7709
Коммит
d1f37af979
|
@ -40,27 +40,56 @@ static void PutIndented(const char *String);
|
|||
static char *OutputBufferRoot = NULL;
|
||||
static char *OutputBuffer = NULL;
|
||||
static int OutputBufferSize = 0;
|
||||
static int OutputBufferOwned = false;
|
||||
|
||||
static int LeftInOutputBuffer() {
|
||||
return OutputBufferSize - (OutputBuffer - OutputBufferRoot);
|
||||
}
|
||||
|
||||
static bool EnsureOutputBuffer(int Needed) { // ensures the output buffer is sufficient. returns true is no problem happened
|
||||
Needed++; // ensure the trailing \0 is not forgotten
|
||||
int Left = LeftInOutputBuffer();
|
||||
if (!OutputBufferOwned) {
|
||||
assert(Needed < Left);
|
||||
} else {
|
||||
// we own the buffer, and can resize if necessary
|
||||
if (Needed >= Left) {
|
||||
int Offset = OutputBuffer - OutputBufferRoot;
|
||||
int TotalNeeded = OutputBufferSize + Needed - Left + 10240;
|
||||
int NewSize = OutputBufferSize;
|
||||
while (NewSize < TotalNeeded) NewSize = NewSize + (NewSize/2);
|
||||
//printf("resize %d => %d\n", OutputBufferSize, NewSize);
|
||||
OutputBufferRoot = (char*)realloc(OutputBufferRoot, NewSize);
|
||||
OutputBuffer = OutputBufferRoot + Offset;
|
||||
OutputBufferSize = NewSize;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void PrintIndented(const char *Format, ...) {
|
||||
assert(OutputBuffer);
|
||||
assert(OutputBuffer + Indenter::CurrIndent*INDENTATION - OutputBufferRoot < OutputBufferSize);
|
||||
EnsureOutputBuffer(Indenter::CurrIndent*INDENTATION);
|
||||
for (int i = 0; i < Indenter::CurrIndent*INDENTATION; i++, OutputBuffer++) *OutputBuffer = ' ';
|
||||
va_list Args;
|
||||
va_start(Args, Format);
|
||||
int left = OutputBufferSize - (OutputBuffer - OutputBufferRoot);
|
||||
int written = vsnprintf(OutputBuffer, left, Format, Args);
|
||||
assert(written < left);
|
||||
OutputBuffer += written;
|
||||
va_end(Args);
|
||||
int Written;
|
||||
while (1) { // write and potentially resize buffer until we have enough room
|
||||
int Left = LeftInOutputBuffer();
|
||||
va_list Args;
|
||||
va_start(Args, Format);
|
||||
Written = vsnprintf(OutputBuffer, Left, Format, Args);
|
||||
va_end(Args);
|
||||
if (EnsureOutputBuffer(Written)) break;
|
||||
}
|
||||
OutputBuffer += Written;
|
||||
}
|
||||
|
||||
void PutIndented(const char *String) {
|
||||
assert(OutputBuffer);
|
||||
assert(OutputBuffer + Indenter::CurrIndent*INDENTATION - OutputBufferRoot < OutputBufferSize);
|
||||
EnsureOutputBuffer(Indenter::CurrIndent*INDENTATION);
|
||||
for (int i = 0; i < Indenter::CurrIndent*INDENTATION; i++, OutputBuffer++) *OutputBuffer = ' ';
|
||||
int left = OutputBufferSize - (OutputBuffer - OutputBufferRoot);
|
||||
int needed = strlen(String)+1;
|
||||
assert(needed < left);
|
||||
int Needed = strlen(String)+1;
|
||||
EnsureOutputBuffer(Needed);
|
||||
strcpy(OutputBuffer, String);
|
||||
OutputBuffer += strlen(String);
|
||||
*OutputBuffer++ = '\n';
|
||||
|
@ -1158,11 +1187,17 @@ void Relooper::Render() {
|
|||
void Relooper::SetOutputBuffer(char *Buffer, int Size) {
|
||||
OutputBufferRoot = OutputBuffer = Buffer;
|
||||
OutputBufferSize = Size;
|
||||
OutputBufferOwned = false;
|
||||
}
|
||||
|
||||
void Relooper::MakeOutputBuffer(int Size) {
|
||||
OutputBufferRoot = OutputBuffer = (char*)malloc(Size);
|
||||
OutputBufferSize = Size;
|
||||
OutputBufferOwned = true;
|
||||
}
|
||||
|
||||
char *Relooper::GetOutputBuffer() {
|
||||
return OutputBufferRoot;
|
||||
}
|
||||
|
||||
void Relooper::SetAsmJSMode(int On) {
|
||||
|
|
|
@ -200,11 +200,16 @@ struct Relooper {
|
|||
void Render();
|
||||
|
||||
// Sets the global buffer all printing goes to. Must call this or MakeOutputBuffer.
|
||||
// XXX: this is deprecated, see MakeOutputBuffer
|
||||
static void SetOutputBuffer(char *Buffer, int Size);
|
||||
|
||||
// Creates an output buffer. Must call this or SetOutputBuffer.
|
||||
// Creates an internal output buffer. Must call this or SetOutputBuffer. Size is
|
||||
// a hint for the initial size of the buffer, it can be resized later one demand.
|
||||
// For that reason this is more recommended than SetOutputBuffer.
|
||||
static void MakeOutputBuffer(int Size);
|
||||
|
||||
static char *GetOutputBuffer();
|
||||
|
||||
// Sets asm.js mode on or off (default is off)
|
||||
static void SetAsmJSMode(int On);
|
||||
|
||||
|
|
|
@ -47,8 +47,18 @@ while(1) switch(label) {
|
|||
|
||||
int main() {
|
||||
char *buffer = (char*)malloc(10*1024*1024);
|
||||
'''
|
||||
|
||||
if random.randint(0, 1) == 0:
|
||||
make = False
|
||||
fast += '''
|
||||
Relooper::SetOutputBuffer(buffer, 10*1024*1024);
|
||||
'''
|
||||
else:
|
||||
make = True
|
||||
fast += '''
|
||||
Relooper::MakeOutputBuffer(%d);
|
||||
''' % random.randint(1, 1024*1024*10)
|
||||
|
||||
for i in range(1, num):
|
||||
slow += ' case %d: print(%d); state = check(); modded = state %% %d\n' % (i, i, len(branches[i])+1)
|
||||
|
@ -102,11 +112,11 @@ int main() {
|
|||
printf("\\n\\n");
|
||||
r.Render();
|
||||
|
||||
puts(buffer);
|
||||
puts(%s);
|
||||
|
||||
return 1;
|
||||
}
|
||||
'''
|
||||
''' % ('buffer' if not make else 'Relooper::GetOutputBuffer()')
|
||||
|
||||
slow += '}'
|
||||
|
||||
|
|
|
@ -286,5 +286,33 @@ int main() {
|
|||
|
||||
puts(buffer);
|
||||
}
|
||||
|
||||
if (1) {
|
||||
Relooper::MakeOutputBuffer(10);
|
||||
|
||||
printf("\n\n-- If pattern, emulated, using MakeOutputBuffer --\n\n");
|
||||
|
||||
Block *b_a = new Block("// block A\n", NULL);
|
||||
Block *b_b = new Block("// block B\n", "b_check()");
|
||||
Block *b_c = new Block("// block C\n", NULL);
|
||||
|
||||
b_a->AddBranchTo(b_b, "check == 10", "atob();");
|
||||
b_a->AddBranchTo(b_c, NULL, "atoc();");
|
||||
|
||||
b_b->AddBranchTo(b_c, "case 17:", "btoc();");
|
||||
b_b->AddBranchTo(b_a, NULL, NULL);
|
||||
|
||||
Relooper r;
|
||||
r.SetEmulate(true);
|
||||
r.AddBlock(b_a);
|
||||
r.AddBlock(b_b);
|
||||
r.AddBlock(b_c);
|
||||
|
||||
r.Calculate(b_a);
|
||||
printf("\n\n", "the_var");
|
||||
r.Render();
|
||||
|
||||
puts(buffer);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -276,6 +276,51 @@
|
|||
|
||||
|
||||
|
||||
label = 1;
|
||||
L0: while(1) {
|
||||
switch(label|0) {
|
||||
case 3: {
|
||||
// block C
|
||||
break;
|
||||
}
|
||||
case 1: {
|
||||
// block A
|
||||
if (check == 10) {
|
||||
atob();
|
||||
label = 2;
|
||||
continue L0;
|
||||
} else {
|
||||
atoc();
|
||||
label = 3;
|
||||
continue L0;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case 2: {
|
||||
// block B
|
||||
switch (b_check()) {
|
||||
case 17: {
|
||||
btoc();
|
||||
label = 3;
|
||||
continue L0;
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
label = 1;
|
||||
continue L0;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
-- If pattern, emulated, using MakeOutputBuffer --
|
||||
|
||||
|
||||
|
||||
label = 1;
|
||||
L0: while(1) {
|
||||
switch(label|0) {
|
||||
|
|
|
@ -345,7 +345,7 @@ def find_temp_directory():
|
|||
# we re-check sanity when the settings are changed)
|
||||
# We also re-check sanity and clear the cache when the version changes
|
||||
|
||||
EMSCRIPTEN_VERSION = '1.8.6'
|
||||
EMSCRIPTEN_VERSION = '1.8.7'
|
||||
|
||||
def generate_sanity():
|
||||
return EMSCRIPTEN_VERSION + '|' + get_llvm_target() + '|' + LLVM_ROOT + '|' + get_clang_version()
|
||||
|
|
Загрузка…
Ссылка в новой задаче