diff -ur csound5~/Engine/csound_orc.l csound5/Engine/csound_orc.l --- csound5~/Engine/csound_orc.l 2011-11-22 11:11:54.000000000 +0100 +++ csound5/Engine/csound_orc.l 2011-11-22 19:27:14.000000000 +0100 @@ -49,6 +49,8 @@ void do_macro_arg(CSOUND *, char *, yyscan_t); void do_macro(CSOUND *, char *, yyscan_t); void do_umacro(CSOUND *, char *, yyscan_t); +void do_ifdef(CSOUND *, char *, yyscan_t); +void do_ifdef_skip_code(CSOUND *, yyscan_t); #define udoflag csound->parserUdoflag #define namedInstrFlag csound->parserNamedInstrFlag //extern int udoflag; @@ -92,6 +94,9 @@ INCLUDE "#include" DEFINE "#define" UNDEF "#undef" +IFDEF #ifn?def +ELSE #else[ \t]*(;.*)?$ +END #end(if)?[ \t]*(;.*)?\n CONT \\[[ \t]*\n XSTR "{{" EXSTR "}}" @@ -99,6 +104,7 @@ %x incl %x macro %x umacro +%x ifdef %x xstr %% @@ -495,6 +501,36 @@ csound_orcget_lineno(yyscanner), yytext[0],yytext[0]); } +{IFDEF} { + PARM->isIfndef = (yytext[3] == 'n'); /* #ifdef or #ifndef */ + BEGIN(ifdef); + } +[ \t]* /* eat the whitespace */ +{IDENT} { + do_ifdef(csound, yytext, yyscanner); + BEGIN(INITIAL); + } +{ELSE} { + if (PARM->ifdefStack == NULL) { + csound->Message(csound, Str("#else without #if\n")); + csound->LongJmp(csound, 1); + } + else if (PARM->ifdefStack->isElse) { + csound->Message(csound, Str("#else after #else\n")); + csound->LongJmp(csound, 1); + } + PARM->ifdefStack->isElse = 1; + do_ifdef_skip_code(csound, yyscanner); + } +{END} { + IFDEFSTACK *pp = PARM->ifdefStack; + if (UNLIKELY(pp == NULL)) { + csound->Message(csound, Str("Unmatched #end\n")); + csound->LongJmp(csound, 1); + } + PARM->ifdefStack = pp->prv; + mfree(csound, pp); + } %% @@ -667,6 +703,74 @@ csound_orcset_lineno(1+csound_orcget_lineno(yyscanner),yyscanner); } +void do_ifdef(CSOUND *csound, char *name0, yyscan_t yyscanner) +{ + int c; + MACRO *mm; + IFDEFSTACK *pp; + pp = (IFDEFSTACK*) mcalloc(csound, sizeof(IFDEFSTACK)); + pp->prv = PARM->ifdefStack; + pp->isDef = PARM->isIfndef; + for (mm = PARM->macros; mm != NULL; mm = mm->next) { + if (strcmp(name0, mm->name) == 0) { + pp->isDef ^= (unsigned char) 1; + break; + } + } + PARM->ifdefStack = pp; + pp->isSkip = pp->isDef ^ (unsigned char) 1; + if (pp->isSkip) + do_ifdef_skip_code(csound, yyscanner); + else + while ((c = input(yyscanner)) != '\n' && c != EOF); +} + +void do_ifdef_skip_code(CSOUND *csound, yyscan_t yyscanner) +{ + int i, c, nested_ifdef = 0; + char *buf; + IFDEFSTACK *pp; + buf = (char*)malloc(8*sizeof(char)); + pp = PARM->ifdefStack; + c = input(yyscanner); + for (;;) { + while (c!='\n') { + if (UNLIKELY(c == EOF)) { + csound->Message(csound, Str("Unmatched #if%sdef\n"), + PARM->isIfndef ? "n" : ""); + csound->LongJmp(csound, 1); + } + c = input(yyscanner); + } + while (isblank(c = input(yyscanner))); /* eat the whitespace */ + if (c == '#') { + for (i=0; islower(c = input(yyscanner)) && i < 7; i++) + buf[i] = c; + buf[i] = '\0'; + if (strcmp("end", buf) == 0 || strcmp("endif", buf) == 0) { + if (nested_ifdef-- == 0) { + PARM->ifdefStack = pp->prv; + mfree(csound, pp); + break; + } + } + else if (strcmp("ifdef", buf) == 0 || strcmp("ifndef", buf) == 0) { + nested_ifdef++; + } + else if (strcmp("else", buf) == 0 && nested_ifdef == 0) { + if (pp->isElse) { + csound->Message(csound, Str("#else after #else\n")); + csound->LongJmp(csound, 1); + } + pp->isElse = 1; + break; + } + } + } + free(buf); + while (c != '\n' && c != EOF) c = input(yyscanner); +} + ORCTOKEN *new_token(CSOUND *csound, int type) { ORCTOKEN *ans = (ORCTOKEN*)mcalloc(csound, sizeof(ORCTOKEN)); diff -ur csound5~/Engine/new_orc_parser.c csound5/Engine/new_orc_parser.c --- csound5~/Engine/new_orc_parser.c 2011-11-20 14:38:05.000000000 +0100 +++ csound5/Engine/new_orc_parser.c 2011-11-23 09:52:49.000000000 +0100 @@ -82,6 +82,10 @@ retVal = csound_orcparse(&pp, pp.yyscanner, csound, astTree); + if (UNLIKELY(pp.ifdefStack != NULL)) { + csound->Message(csound, Str("Unmatched #ifdef\n")); + csound->LongJmp(csound, 1); + } if (LIKELY(retVal == 0)) { csound->Message(csound, "Parsing successful!\n"); } diff -ur csound5~/Engine/parse_param.h csound5/Engine/parse_param.h --- csound5~/Engine/parse_param.h 2011-11-22 11:11:54.000000000 +0100 +++ csound5/Engine/parse_param.h 2011-11-22 19:27:27.000000000 +0100 @@ -16,6 +16,15 @@ char *arg[MARGS]; /* With these arguments */ } MACRO; +typedef struct IFDEFSTACK_ { + struct IFDEFSTACK_ *prv; + unsigned char isDef; /* non-zero if #ifdef is true, or #ifndef */ + /* is false */ + unsigned char isElse; /* non-zero between #else and #endif */ + unsigned char isSkip; /* sum of: 1: skipping code due to this */ + /* #ifdef, 2: skipping due to parent */ +} IFDEFSTACK; + typedef struct parse_parm_s { void *yyscanner; char *buffer; @@ -30,6 +39,8 @@ unsigned int macro_stack_ptr; char *xstrbuff; int xstrptr,xstrmax; + IFDEFSTACK *ifdefStack; + unsigned char isIfndef; unsigned char isInclude; unsigned char clearBufferAfterEOF; } PARSE_PARM;