aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorAlon Zakai <alonzakai@gmail.com>2014-01-13 12:37:34 -0800
committerAlon Zakai <alonzakai@gmail.com>2014-01-13 12:37:34 -0800
commitd1f37af9792b048f7ef98140d067ba129a97c565 (patch)
tree840bf755de2b5530e392d13d15918ceec9978eaa /src
parentec3eba770983ad300ca958db5764206924452b0b (diff)
allow relooper to manager its own output buffer, to avoid fixed output limits1.8.7
Diffstat (limited to 'src')
-rw-r--r--src/relooper/Relooper.cpp59
-rw-r--r--src/relooper/Relooper.h7
-rw-r--r--src/relooper/fuzzer.py14
-rw-r--r--src/relooper/test.cpp28
-rw-r--r--src/relooper/test.txt45
5 files changed, 138 insertions, 15 deletions
diff --git a/src/relooper/Relooper.cpp b/src/relooper/Relooper.cpp
index 389d7447..1bad872f 100644
--- a/src/relooper/Relooper.cpp
+++ b/src/relooper/Relooper.cpp
@@ -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) {
diff --git a/src/relooper/Relooper.h b/src/relooper/Relooper.h
index dfabcabb..6b9394db 100644
--- a/src/relooper/Relooper.h
+++ b/src/relooper/Relooper.h
@@ -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);
diff --git a/src/relooper/fuzzer.py b/src/relooper/fuzzer.py
index fa47583e..18db997e 100644
--- a/src/relooper/fuzzer.py
+++ b/src/relooper/fuzzer.py
@@ -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 += '}'
diff --git a/src/relooper/test.cpp b/src/relooper/test.cpp
index 773f6ee4..b4ce669c 100644
--- a/src/relooper/test.cpp
+++ b/src/relooper/test.cpp
@@ -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);
+ }
}
diff --git a/src/relooper/test.txt b/src/relooper/test.txt
index 9bdd4093..cb02b867 100644
--- a/src/relooper/test.txt
+++ b/src/relooper/test.txt
@@ -315,3 +315,48 @@
}
}
+
+
+-- If pattern, emulated, using MakeOutputBuffer --
+
+
+
+ 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;
+ }
+ }
+ }
+