Add support for #pragma foo(bar)
Report unsupported/unknown preprocessor directives.
Report line number of error rather than character offset.
diff --git a/include/acc/acc.h b/include/acc/acc.h
index 054d6a0..e25fde0 100644
--- a/include/acc/acc.h
+++ b/include/acc/acc.h
@@ -69,6 +69,9 @@
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 733f188..096500d 100644
--- a/libacc/acc.cpp
+++ b/libacc/acc.cpp
@@ -1039,16 +1039,35 @@
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 @@
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 @@
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 @@
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 @@
ch = dch;
}
} else
- ch = file->get();
+ ch = file->getChar();
/* printf("ch=%c 0x%x\n", ch, ch); */
}
@@ -1197,14 +1284,18 @@
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 @@
#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 @@
pGlobalBase = 0;
pVarsBase = 0;
pGen = 0;
- mErrorBuf[0] = 0;
+ mPragmaStringCount = 0;
}
void setArchitecture(const char* architecture) {
@@ -1745,9 +1867,10 @@
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 @@
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 @@
}
}
+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 0000000..530f9e2
--- /dev/null
+++ b/libacc/tests/data/otcc-noinclude.c
@@ -0,0 +1,446 @@
+// #include <stdio.h>
+#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<<Z/03e>>`/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 3142fe2..1b9dd81 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 e65103e..6b39f57 100644
--- a/libacc/tests/main.cpp
+++ b/libacc/tests/main.cpp
@@ -86,10 +86,23 @@
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 a76322b..547aed5 100755
--- a/libacc/tests/testlocal
+++ b/libacc/tests/testlocal
@@ -8,8 +8,8 @@
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