diff --git a/include/acc/acc.h b/include/acc/acc.h index 054d6a0d4..e25fde0d1 100644 --- a/include/acc/acc.h +++ b/include/acc/acc.h @@ -69,6 +69,9 @@ void accGetScriptInfoLog(ACCscript* script, void accGetScriptLabel(ACCscript* script, const ACCchar * name, ACCvoid** address); +void accGetPragmas(ACCscript* script, ACCsizei* actualStringCount, + ACCsizei maxStringCount, ACCchar** strings); + #ifdef __cplusplus }; #endif diff --git a/libacc/acc.cpp b/libacc/acc.cpp index 733f1880d..096500dd8 100644 --- a/libacc/acc.cpp +++ b/libacc/acc.cpp @@ -1039,16 +1039,35 @@ class Compiler : public ErrorSink { class InputStream { public: + int getChar() { + if (bumpLine) { + line++; + bumpLine = false; + } + int ch = get(); + if (ch == '\n') { + bumpLine = true; + } + return ch; + } + int getLine() { + return line; + } + protected: + InputStream() : + line(1), bumpLine(false) { + } + private: virtual int get() = 0; - virtual long tell() = 0; + int line; + bool bumpLine; }; class FileInputStream : public InputStream { public: FileInputStream(FILE* in) : f(in) {} - virtual int get() { return fgetc(f); } - virtual long tell() { return ftell(f); } private: + virtual int get() { return fgetc(f); } FILE* f; }; @@ -1057,14 +1076,12 @@ class Compiler : public ErrorSink { TextInputStream(const char* text, size_t textLength) : pText(text), mTextLength(textLength), mPosition(0) { } + + private: virtual int get() { return mPosition < mTextLength ? pText[mPosition++] : EOF; } - virtual long tell() { - return mPosition; - } - private: const char* pText; size_t mTextLength; size_t mPosition; @@ -1091,14 +1108,83 @@ class Compiler : public ErrorSink { CodeBuf codeBuf; CodeGenerator* pGen; - static const int ERROR_BUF_SIZE = 512; - char mErrorBuf[ERROR_BUF_SIZE]; + class String { + public: + String() { + mpBase = 0; + mUsed = 0; + mSize = 0; + } + + ~String() { + if (mpBase) { + free(mpBase); + } + } + + char* getUnwrapped() { + return mpBase; + } + + void appendCStr(const char* s) { + int n = strlen(s); + memcpy(ensure(n), s, n + 1); + } + + void append(char c) { + * ensure(1) = c; + } + + void printf(const char* fmt,...) { + va_list ap; + va_start(ap, fmt); + vprintf(fmt, ap); + va_end(ap); + } + + void vprintf(const char* fmt, va_list ap) { + char* temp; + int numChars = vasprintf(&temp, fmt, ap); + memcpy(ensure(numChars), temp, numChars+1); + free(temp); + } + + size_t len() { + return mUsed; + } + + private: + char* ensure(int n) { + size_t newUsed = mUsed + n; + if (newUsed > mSize) { + size_t newSize = mSize * 2 + 10; + if (newSize < newUsed) { + newSize = newUsed; + } + mpBase = (char*) realloc(mpBase, newSize + 1); + mSize = newSize; + } + mpBase[newUsed] = '\0'; + char* result = mpBase + mUsed; + mUsed = newUsed; + return result; + } + + char* mpBase; + size_t mUsed; + size_t mSize; + }; + + String mErrorBuf; + jmp_buf mErrorRecoveryJumpBuf; + String mPragmas; + int mPragmaStringCount; + static const int ALLOC_SIZE = 99999; - /* depends on the init string */ - static const int TOK_STR_SIZE = 48; + // Indentifiers start at 0x100 and increase by # (chars + 1) * 8 static const int TOK_IDENT = 0x100; static const int TOK_INT = 0x100; static const int TOK_IF = 0x120; @@ -1107,8 +1193,9 @@ class Compiler : public ErrorSink { static const int TOK_BREAK = 0x190; static const int TOK_RETURN = 0x1c0; static const int TOK_FOR = 0x1f8; - static const int TOK_DEFINE = 0x218; - static const int TOK_MAIN = 0x250; + static const int TOK_PRAGMA = 0x218; + static const int TOK_DEFINE = TOK_PRAGMA + (7*8); + static const int TOK_MAIN = TOK_DEFINE + (7*8); static const int TOK_DUMMY = 1; static const int TOK_NUM = 2; @@ -1168,7 +1255,7 @@ class Compiler : public ErrorSink { ch = dch; } } else - ch = file->get(); + ch = file->getChar(); /* printf("ch=%c 0x%x\n", ch, ch); */ } @@ -1197,14 +1284,18 @@ class Compiler : public ErrorSink { pdef(TAG_TOK); /* fill last ident tag */ *(int *) tok = SYM_DEFINE; *(char* *) (tok + 4) = dstk; /* define stack */ - } - /* well we always save the values ! */ - while (ch != '\n') { + while (ch != '\n') { + pdef(ch); + inp(); + } pdef(ch); - inp(); + pdef(TAG_MACRO); + } else if (tok == TOK_PRAGMA) { + doPragma(); + } else { + error("Unsupported preprocessor directive \"%s\"", last_id); } - pdef(ch); - pdef(TAG_MACRO); + } inp(); } @@ -1321,23 +1412,54 @@ class Compiler : public ErrorSink { #endif } + void doPragma() { + // # pragma name(val) + int state = 0; + while(ch != EOF && ch != '\n' && state < 10) { + switch(state) { + case 0: + if (isspace(ch)) { + inp(); + } else { + state++; + } + break; + case 1: + if (isalnum(ch)) { + mPragmas.append(ch); + inp(); + } else if (ch == '(') { + mPragmas.append(0); + inp(); + state++; + } else { + state = 11; + } + break; + case 2: + if (isalnum(ch)) { + mPragmas.append(ch); + inp(); + } else if (ch == ')') { + mPragmas.append(0); + inp(); + state = 10; + } else { + state = 11; + } + break; + } + } + if(state != 10) { + error("Unexpected pragma syntax"); + } + mPragmaStringCount += 2; + } virtual void verror(const char* fmt, va_list ap) { - char* pBase = mErrorBuf; - int bytesLeft = sizeof(mErrorBuf); - int bytesAdded = snprintf(pBase, bytesLeft, "%ld: ", file->tell()); - bytesLeft -= bytesAdded; - pBase += bytesAdded; - if (bytesLeft > 0) { - bytesAdded = vsnprintf(pBase, bytesLeft, fmt, ap); - bytesLeft -= bytesAdded; - pBase += bytesAdded; - } - if (bytesLeft > 0) { - bytesAdded = snprintf(pBase, bytesLeft, "\n"); - bytesLeft -= bytesAdded; - pBase += bytesAdded; - } + mErrorBuf.printf("%ld: ", file->getLine()); + mErrorBuf.vprintf(fmt, ap); + mErrorBuf.printf("\n"); longjmp(mErrorRecoveryJumpBuf, 1); } @@ -1680,7 +1802,7 @@ class Compiler : public ErrorSink { pGlobalBase = 0; pVarsBase = 0; pGen = 0; - mErrorBuf[0] = 0; + mPragmaStringCount = 0; } void setArchitecture(const char* architecture) { @@ -1745,9 +1867,10 @@ public: pGen->init(&codeBuf); file = new TextInputStream(text, textLength); sym_stk = (char*) calloc(1, ALLOC_SIZE); - dstk = strcpy(sym_stk, - " int if else while break return for define main ") - + TOK_STR_SIZE; + static const char* predefinedSymbols = + " int if else while break return for pragma define main "; + dstk = strcpy(sym_stk, predefinedSymbols) + + strlen(predefinedSymbols); pGlobalBase = (char*) calloc(1, ALLOC_SIZE); glo = pGlobalBase; pVarsBase = (char*) calloc(1, ALLOC_SIZE); @@ -1810,8 +1933,26 @@ public: return NULL; } + void getPragmas(ACCsizei* actualStringCount, + ACCsizei maxStringCount, ACCchar** strings) { + int stringCount = mPragmaStringCount; + if (actualStringCount) { + *actualStringCount = stringCount; + } + if (stringCount > maxStringCount) { + stringCount = maxStringCount; + } + if (strings) { + char* pPragmas = mPragmas.getUnwrapped(); + while (stringCount-- > 0) { + *strings++ = pPragmas; + pPragmas += strlen(pPragmas) + 1; + } + } + } + char* getErrorMessage() { - return mErrorBuf; + return mErrorBuf.getUnwrapped(); } }; @@ -1988,5 +2129,12 @@ void accGetScriptLabel(ACCscript* script, const ACCchar * name, } } +extern "C" +void accGetPragmas(ACCscript* script, ACCsizei* actualStringCount, + ACCsizei maxStringCount, ACCchar** strings){ + script->compiler.getPragmas(actualStringCount, maxStringCount, strings); +} + + } // namespace acc diff --git a/libacc/tests/data/otcc-noinclude.c b/libacc/tests/data/otcc-noinclude.c new file mode 100644 index 000000000..530f9e2e8 --- /dev/null +++ b/libacc/tests/data/otcc-noinclude.c @@ -0,0 +1,446 @@ +// #include +#define k *(int*) +#define a if( +#define c ad() +#define i else +#define p while( +#define x *(char*) +#define b == +#define V =calloc(1,99999) +#define f () +#define J return +#define l ae( +#define n e) +#define u d!= +#define F int +#define y (j) +#define r m= +#define t +4 +F d,z,C,h,P,K,ac,q,G,v,Q,R,D,L,W,M; +E(n{ +x D++=e; +} +o f{ +a L){ +h=x L++; +a h b 2){ +L=0; +h=W; +} +} +i h=fgetc(Q); +} +X f{ +J isalnum(h)|h b 95; +} +Y f{ +a h b 92){ +o f; +a h b 110)h=10; +} +} +c{ +F e,j,m; +p isspace(h)|h b 35){ +a h b 35){ +o f; +c; +a d b 536){ +c; +E(32); +k d=1; +k(d t)=D; +} +p h!=10){ +E(h); +o f; +} +E(h); +E(2); +} +o f; +} +C=0; +d=h; +a X f){ +E(32); +M=D; +p X f){ +E(h); +o f; +} +a isdigit(d)){ +z=strtol(M,0,0); +d=2; +} +i{ +x D=32; +d=strstr(R,M-1)-R; +x D=0; +d=d*8+256; +a d>536){ +d=P+d; +a k d b 1){ +L=k(d t); +W=h; +o f; +c; +} +} +} +} +i{ +o f; +a d b 39){ +d=2; +Y f; +z=h; +o f; +o f; +} +i a d b 47&h b 42){ +o f; +p h){ +p h!=42)o f; +o f; +a h b 47)h=0; +} +o f; +c; +} +i{ +e="++#m--%am*@R<^1c/@%[_[H3c%@%[_[H3c+@.B#d-@%:_^BKd<>`/03e<=0f>=/f<@.f>@1f==&g!='g&&k||#l&@.BCh^@.BSi|@.B+j~@/%Yd!@&d*@b"; +p j=x e++){ +r x e++; +z=0; +p(C=x e++-98)<0)z=z*64+C+64; +a j b d&(m b h|m b 64)){ +a m b h){ +o f; +d=1; +} +break; +} +} +} +} +} +l g){ +p g&&g!=-1){ +x q++=g; +g=g>>8; +} +} +A(n{ +F g; +p n{ +g=k e; +k e=q-e-4; +e=g; +} +} +s(g,n{ +l g); +k q=e; +e=q; +q=q t; +J e; +} +H(n{ +s(184,n; +} +B(n{ +J s(233,n; +} +S(j,n{ +l 1032325); +J s(132+j,n; +} +Z(n{ +l 49465); +H(0); +l 15); +l e+144); +l 192); +} +N(j,n{ +l j+131); +s((e<512)<<7|5,n; +} +T y{ +F g,e,m,aa; +g=1; +a d b 34){ +H(v); +p h!=34){ +Y f; +x v++=h; +o f; +} +x v=0; +v=v t&-4; +o f; +c; +} +i{ +aa=C; +r z; +e=d; +c; +a e b 2){ +H(m); +} +i a aa b 2){ +T(0); +s(185,0); +a e b 33)Z(m); +i l m); +} +i a e b 40){ +w f; +c; +} +i a e b 42){ +c; +e=d; +c; +c; +a d b 42){ +c; +c; +c; +c; +e=0; +} +c; +T(0); +a d b 61){ +c; +l 80); +w f; +l 89); +l 392+(e b 256)); +} +i a n{ +a e b 256)l 139); +i l 48655); +q++; +} +} +i a e b 38){ +N(10,k d); +c; +} +i{ +g=k e; +a!g)g=dlsym(0,M); +a d b 61&j){ +c; +w f; +N(6,g); +} +i a u 40){ +N(8,g); +a C b 11){ +N(0,g); +l z); +c; +} +} +} +} +a d b 40){ +a g b 1)l 80); +r s(60545,0); +c; +j=0; +p u 41){ +w f; +s(2393225,j); +a d b 44)c; +j=j t; +} +k r j; +c; +a!g){ +e=e t; +k e=s(232,k n; +} +i a g b 1){ +s(2397439,j); +j=j t; +} +i{ +s(232,g-q-5); +} +a j)s(50305,j); +} +} +O y{ +F e,g,m; +a j--b 1)T(1); +i{ +O y; +r 0; +p j b C){ +g=d; +e=z; +c; +a j>8){ +r S(e,m); +O y; +} +i{ +l 80); +O y; +l 89); +a j b 4|j b 5){ +Z(n; +} +i{ +l n; +a g b 37)l 146); +} +} +} +a m&&j>8){ +r S(e,m); +H(e^1); +B(5); +A(m); +H(n; +} +} +} +w f{ +O(11); +} +U f{ +w f; +J S(0,0); +} +I y{ +F m,g,e; +a d b 288){ +c; +c; +r U f; +c; +I y; +a d b 312){ +c; +g=B(0); +A(m); +I y; +A(g); +} +i{ +A(m); +} +} +i a d b 352|d b 504){ +e=d; +c; +c; +a e b 352){ +g=q; +r U f; +} +i{ +a u 59)w f; +c; +g=q; +r 0; +a u 59)r U f; +c; +a u 41){ +e=B(0); +w f; +B(g-q-5); +A(n; +g=e t; +} +} +c; +I(&m); +B(g-q-5); +A(m); +} +i a d b 123){ +c; +ab(1); +p u 125)I y; +c; +} +i{ +a d b 448){ +c; +a u 59)w f; +K=B(K); +} +i a d b 400){ +c; +k j=B(k j); +} +i a u 59)w f; +c; +} +} +ab y{ +F m; +p d b 256|u-1&!j){ +a d b 256){ +c; +p u 59){ +a j){ +G=G t; +k d=-G; +} +i{ +k d=v; +v=v t; +} +c; +a d b 44)c; +} +c; +} +i{ +A(k(d t)); +k d=q; +c; +c; +r 8; +p u 41){ +k d=m; +r m t; +c; +a d b 44)c; +} +c; +K=G=0; +l 15042901); +r s(60545,0); +I(0); +A(K); +l 50121); +k r G; +} +} +} +main(g,n{ +Q=stdin; +a g-->1){ +e=e t; +Q=fopen(k e,"r"); +} +D=strcpy(R V," int if else while break return for define main ")+48; +v V; +q=ac V; +P V; +o f; +c; +ab(0); +J(*(int(*)f)k(P+592))(g,n; +} + diff --git a/libacc/tests/data/returnval.c b/libacc/tests/data/returnval.c index 3142fe2bd..1b9dd8177 100644 --- a/libacc/tests/data/returnval.c +++ b/libacc/tests/data/returnval.c @@ -1,3 +1,7 @@ +#pragma foo3(bar) //sdfsfd +#pragma a(b) + main() { return 42; -} \ No newline at end of file +} + diff --git a/libacc/tests/main.cpp b/libacc/tests/main.cpp index e65103e83..6b39f5732 100644 --- a/libacc/tests/main.cpp +++ b/libacc/tests/main.cpp @@ -86,10 +86,23 @@ int main(int argc, char** argv) { if (result != 0) { char buf[1024]; accGetScriptInfoLog(script, sizeof(buf), NULL, buf); - fprintf(stderr, "%ss", buf); + fprintf(stderr, "%s", buf); goto exit; } + { + ACCsizei numPragmaStrings; + accGetPragmas(script, &numPragmaStrings, 0, NULL); + if (numPragmaStrings) { + char** strings = new char*[numPragmaStrings]; + accGetPragmas(script, NULL, numPragmaStrings, strings); + for(ACCsizei i = 0; i < numPragmaStrings; i += 2) { + fprintf(stderr, "#pragma %s(%s)\n", strings[i], strings[i+1]); + } + delete[] strings; + } + } + accGetScriptLabel(script, "main", (ACCvoid**) & mainPointer); result = accGetError(script); diff --git a/libacc/tests/testlocal b/libacc/tests/testlocal index a76322bdc..547aed57a 100755 --- a/libacc/tests/testlocal +++ b/libacc/tests/testlocal @@ -8,8 +8,8 @@ if [ -x "test-acc" ]; then if [ "$(uname)" = "Linux" ]; then if [ "$(uname -m)" = "i686" ]; then - echo "Linux i686. Testing otcc.c" - ./test-acc data/otcc.c data/otcc.c data/returnval.c + echo "Linux i686. Testing otcc-noinclude.c" + ./test-acc data/otcc-noinclude.c data/otcc.c data/returnval.c fi fi fi