__pragma: Move the string processing code into a separate function, so it could be reused by other operators

This commit is contained in:
Stanislav Gromov 2020-11-15 00:52:04 +07:00
parent a68bacf86e
commit 3dfad1f7fd

View File

@ -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<tFIRST) {
sprintf(tokstr,"%c",tok);
str=tokstr;
} else {
str=sc_tokens[tok-tFIRST];
} /* if */
error(1,sc_tokens[tSTRING-tFIRST],str);
return NULL;
} /* if */
assert(litidx>*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 (tok<tFIRST) {
sprintf(tokstr,"%c",tok);
str=tokstr;
} else {
str=sc_tokens[tok-tFIRST];
} /* if */
error(1,sc_tokens[tSTRING-tFIRST],str);
goto next;
} /* if */
assert(litidx>bck_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)