diff --git a/source/compiler/sc1.c b/source/compiler/sc1.c index 9b30d31..10f303c 100644 --- a/source/compiler/sc1.c +++ b/source/compiler/sc1.c @@ -143,6 +143,7 @@ static void dostate(void); static void addwhile(int *ptr); static void delwhile(void); static int *readwhile(void); +static char *parsestringparam(int onlycheck,int *bck_litidx); static void dopragma(void); static void pragma_apply(symbol *sym); @@ -8284,10 +8285,86 @@ static int *readwhile(void) } /* if */ } -static void dopragma(void) +/* parsestringparam() + * + * Uses the standard string parsing mechanism to parse string parameters + * for operator '__pragma'. + */ +static char *parsestringparam(int onlycheck,int *bck_litidx) { int tok; - int bck_litidx,bck_packstr; + int bck_packstr; + cell val; + char *str; + + assert(bck_litidx!=NULL); + + /* back up 'litidx', so we can remove the string from the literal queue later */ + *bck_litidx=litidx; + /* force the string to be packed by default, so it would be easier to process it */ + bck_packstr=sc_packstr; + sc_packstr=TRUE; + + /* read the string parameter */ + tok=lex(&val,&str); + sc_packstr=bck_packstr; + if (tok!=tSTRING || !pc_ispackedstr) { + /* either not a string, or the user prepended "!" to the option string */ + char tokstr[2]; + if (tok==tSTRING) { + tok='!'; + litidx=*bck_litidx; /* remove the string from the literal queue */ + } /* if */ + if (tok*bck_litidx); + + if (onlycheck) { + /* skip the byte swapping and remove the string from the literal queue, + * as the caller only needed to check if the string was valid */ + litidx=*bck_litidx; + return NULL; + } /* if */ + + /* swap the cell bytes if we're on a Little Endian platform */ +#if BYTE_ORDER==LITTLE_ENDIAN + { /* local */ + char *bytes; + cell i=val; + do { + char t; + bytes=(char *)&litq[i++]; + t=bytes[0], bytes[0]=bytes[sizeof(cell)-1], bytes[sizeof(cell)-1]=t; +#if PAWN_CELL_SIZE>=32 + t=bytes[1], bytes[1]=bytes[sizeof(cell)-2], bytes[sizeof(cell)-2]=t; +#if PAWN_CELL_SIZE==64 + t=bytes[2], bytes[2]=bytes[sizeof(cell)-3], bytes[sizeof(cell)-3]=t; + t=bytes[3], bytes[3]=bytes[sizeof(cell)-4], bytes[sizeof(cell)-4]=t; +#endif // PAWN_CELL_SIZE==64 +#endif // PAWN_CELL_SIZE>=32 + } while (bytes[0]!='\0' && bytes[1]!='\0' +#if PAWN_CELL_SIZE>=32 + && bytes[2]!='\0' && bytes[3]!='\0' +#if PAWN_CELL_SIZE==64 + && bytes[4]!='\0' && bytes[5]!='\0' && bytes[6]!='\0' && bytes[7]!='\0' +#endif // PAWN_CELL_SIZE==64 +#endif // PAWN_CELL_SIZE>=32 + ); /* do */ + } /* local */ +#endif + return (char*)&litq[val]; +} + +static void dopragma(void) +{ + int bck_litidx; int i; cell val; char *str; @@ -8300,60 +8377,13 @@ static void dopragma(void) * mechanism. This way, as a bonus, we'll also be able to use multi-line * strings and the stringization operator. */ - /* first, back up litidx, so we can remove the string from the literal queue later */ - bck_litidx=litidx; - /* also, force the string to be packed by default, so it would be easier to process it */ - bck_packstr=sc_packstr; - sc_packstr=TRUE; - do { /* read the option string */ - tok=lex(&val,&str); - if (tok!=tSTRING || !pc_ispackedstr) { - /* either not a string, or the user prepended "!" to the option string */ - char tokstr[2]; - if (tok==tSTRING) - tok='!'; - if (tokbck_litidx); - - /* swap the cell bytes if we're on a Little Endian platform */ -#if BYTE_ORDER==LITTLE_ENDIAN - { /* local */ - char *bytes; - i=(int)val; - do { - char t; - bytes=(char *)&litq[i++]; - t=bytes[0], bytes[0]=bytes[sizeof(cell)-1], bytes[sizeof(cell)-1]=t; -#if PAWN_CELL_SIZE>=32 - t=bytes[1], bytes[1]=bytes[sizeof(cell)-2], bytes[sizeof(cell)-2]=t; -#if PAWN_CELL_SIZE==64 - t=bytes[2], bytes[2]=bytes[sizeof(cell)-3], bytes[sizeof(cell)-3]=t; - t=bytes[3], bytes[3]=bytes[sizeof(cell)-4], bytes[sizeof(cell)-4]=t; -#endif // PAWN_CELL_SIZE==64 -#endif // PAWN_CELL_SIZE>=32 - } while (bytes[0]!='\0' && bytes[1]!='\0' -#if PAWN_CELL_SIZE>=32 - && bytes[2]!='\0' && bytes[3]!='\0' -#if PAWN_CELL_SIZE==64 - && bytes[4]!='\0' && bytes[5]!='\0' && bytes[6]!='\0' && bytes[7]!='\0' -#endif // PAWN_CELL_SIZE==64 -#endif // PAWN_CELL_SIZE>=32 - ); /* do */ - } /* local */ -#endif - + str=parsestringparam(FALSE,&bck_litidx); + if (str==NULL) + continue; + /* split the option name from parameters */ - str=(char*)&litq[val]; for (i=0; str[i]!='\0' && str[i]!=' '; i++) /* nothing */; if (str[i]!='\0') { @@ -8417,13 +8447,11 @@ unknown_pragma: error(207); /* unknown #pragma */ } /* if */ - next: /* remove the string from the literal queue */ litidx=bck_litidx; } while (matchtoken(',')); needtoken(')'); - sc_packstr=bck_packstr; } static void pragma_apply(symbol *sym)