Merge pull request #27 from 0x0dea/invisible
add INVISIBLE operator for writing to stderr
This commit is contained in:
commit
b1ae721da5
|
@ -3087,12 +3087,12 @@ ReturnObject *interpretPrintStmtNode(StmtNode *node,
|
|||
deleteValueObject(use);
|
||||
return NULL;
|
||||
}
|
||||
printf("%s", getString(use));
|
||||
fprintf(stmt->file, "%s", getString(use));
|
||||
deleteValueObject(val);
|
||||
deleteValueObject(use);
|
||||
}
|
||||
if (!stmt->nonl)
|
||||
printf("\n");
|
||||
putc('\n', stmt->file);
|
||||
return createReturnObject(RT_DEFAULT, NULL);
|
||||
}
|
||||
|
||||
|
|
27
parser.c
27
parser.c
|
@ -629,6 +629,8 @@ void deleteCastStmtNode(CastStmtNode *node)
|
|||
*
|
||||
* \param [in] args The expressions to print.
|
||||
*
|
||||
* \param [in] file Where to print (\c stdout or \c stderr).
|
||||
*
|
||||
* \param [in] nonl Whether an ending newline should be surpressed.
|
||||
*
|
||||
* \return A pointer to the print statement with the desired properties.
|
||||
|
@ -636,6 +638,7 @@ void deleteCastStmtNode(CastStmtNode *node)
|
|||
* \retval NULL Memory allocation failed.
|
||||
*/
|
||||
PrintStmtNode *createPrintStmtNode(ExprNodeList *args,
|
||||
FILE *file,
|
||||
int nonl)
|
||||
{
|
||||
PrintStmtNode *p = malloc(sizeof(PrintStmtNode));
|
||||
|
@ -644,6 +647,7 @@ PrintStmtNode *createPrintStmtNode(ExprNodeList *args,
|
|||
return NULL;
|
||||
}
|
||||
p->args = args;
|
||||
p->file = file;
|
||||
p->nonl = nonl;
|
||||
return p;
|
||||
}
|
||||
|
@ -2477,6 +2481,7 @@ StmtNode *parsePrintStmtNode(Token ***tokenp)
|
|||
{
|
||||
ExprNode *arg = NULL;
|
||||
ExprNodeList *args = NULL;
|
||||
FILE *file = stdout;
|
||||
int nonl = 0;
|
||||
PrintStmtNode *stmt = NULL;
|
||||
StmtNode *ret = NULL;
|
||||
|
@ -2489,13 +2494,21 @@ StmtNode *parsePrintStmtNode(Token ***tokenp)
|
|||
debug("ST_PRINT");
|
||||
#endif
|
||||
|
||||
/* Remove the print keyword from the token stream */
|
||||
/**
|
||||
* Remove the print keyword from the token stream
|
||||
* A "quad-bool" is used to indicate whether we succeeded or failed to
|
||||
* accept either a \c TT_VISIBLE or \c TT_INVISIBLE token.
|
||||
*/
|
||||
status = acceptToken(&tokens, TT_VISIBLE);
|
||||
if (!status) {
|
||||
parser_error_expected_token(TT_VISIBLE, tokens);
|
||||
if (!status) status = acceptToken(&tokens, TT_INVISIBLE) ? 2 : -1;
|
||||
if (status < 1) {
|
||||
parser_error_expected_token(TT_VISIBLE - status, tokens);
|
||||
goto parsePrintStmtNodeAbort;
|
||||
}
|
||||
|
||||
/* Use standard error if we accepted a \c TT_INVISIBLE above */
|
||||
if (status == 2) file = stderr;
|
||||
|
||||
/* Parse the arguments to the print statement */
|
||||
args = createExprNodeList();
|
||||
if (!args) goto parsePrintStmtNodeAbort;
|
||||
|
@ -2515,7 +2528,7 @@ StmtNode *parsePrintStmtNode(Token ***tokenp)
|
|||
&& !peekToken(&tokens, TT_BANG));
|
||||
|
||||
/* Check for the no-newline token */
|
||||
if(acceptToken(&tokens, TT_BANG)) nonl = 1;
|
||||
if (acceptToken(&tokens, TT_BANG)) nonl = 1;
|
||||
|
||||
/* Make sure the statement ends with a newline */
|
||||
status = acceptToken(&tokens, TT_NEWLINE);
|
||||
|
@ -2525,7 +2538,7 @@ StmtNode *parsePrintStmtNode(Token ***tokenp)
|
|||
}
|
||||
|
||||
/* Create the new PrintStmtNode structure */
|
||||
stmt = createPrintStmtNode(args, nonl);
|
||||
stmt = createPrintStmtNode(args, file, nonl);
|
||||
if (!stmt) goto parsePrintStmtNodeAbort;
|
||||
|
||||
/* Create the new StmtNode structure */
|
||||
|
@ -3963,6 +3976,10 @@ StmtNode *parseStmtNode(Token ***tokenp)
|
|||
else if (peekToken(&tokens, TT_VISIBLE)) {
|
||||
ret = parsePrintStmtNode(tokenp);
|
||||
}
|
||||
/* Warn */
|
||||
else if (peekToken(&tokens, TT_INVISIBLE)) {
|
||||
ret = parsePrintStmtNode(tokenp);
|
||||
}
|
||||
/* Input */
|
||||
else if (peekToken(&tokens, TT_GIMMEH)) {
|
||||
ret = parseInputStmtNode(tokenp);
|
||||
|
|
4
parser.h
4
parser.h
|
@ -70,6 +70,7 @@
|
|||
*
|
||||
* \par
|
||||
* PrintStmtNode ::= \c TT_VISIBLE ExprNodeList \c TT_BANG ? \c TT_NEWLINE
|
||||
* | \c TT_INVISIBLE ExprNodeList \c TT_BANG ? \c TT_NEWLINE
|
||||
*
|
||||
* \par
|
||||
* InputStmtNode ::= \c TT_GIMMEH IdentifierNode \c TT_NEWLINE
|
||||
|
@ -395,6 +396,7 @@ typedef struct {
|
|||
*/
|
||||
typedef struct {
|
||||
ExprNodeList *args; /**< The expressions to print. */
|
||||
FILE *file; /**< Where to print (\c stdout or \c stderr). */
|
||||
int nonl; /**< Whether to print an ending newline. */
|
||||
} PrintStmtNode;
|
||||
|
||||
|
@ -612,7 +614,7 @@ void deleteCastStmtNode(CastStmtNode *);
|
|||
* Functions for creating and deleting PrintStmtNodes.
|
||||
*/
|
||||
/**@{*/
|
||||
PrintStmtNode *createPrintStmtNode(ExprNodeList *, int);
|
||||
PrintStmtNode *createPrintStmtNode(ExprNodeList *, FILE *, int);
|
||||
void deletePrintStmtNode(PrintStmtNode *);
|
||||
/**@}*/
|
||||
|
||||
|
|
|
@ -76,6 +76,7 @@ typedef enum {
|
|||
TT_A, /**< Cast target separator. */
|
||||
TT_ISNOWA, /**< In-place cast. */
|
||||
TT_VISIBLE, /**< Print. */
|
||||
TT_INVISIBLE, /**< Print to standard error. */
|
||||
TT_SMOOSH, /**< String concatenation. */
|
||||
TT_BANG, /**< Exclamation point (!) */
|
||||
TT_GIMMEH, /**< Input. */
|
||||
|
@ -153,6 +154,7 @@ static const char *keywords[] = {
|
|||
"A", /* TT_A */
|
||||
"IS NOW A", /* TT_ISNOWA */
|
||||
"VISIBLE", /* TT_VISIBLE */
|
||||
"INVISIBLE", /* TT_INVISIBLE */
|
||||
"SMOOSH", /* TT_SMOOSH */
|
||||
"!", /* TT_BANG */
|
||||
"GIMMEH", /* TT_GIMMEH */
|
||||
|
|
Loading…
Reference in New Issue