patched ElColmo's system command code with some minor style changes
This commit is contained in:
parent
74b80b4aca
commit
c412ec117a
3
error.c
3
error.c
|
@ -145,6 +145,8 @@ static const char *err_msgs[] = {
|
|||
"%s:%u: function name already used by existing variable at: %s\n",
|
||||
/* IN_CANNOT_CAST_VALUE_TO_ARRAY */
|
||||
"%s:%u: cannot cast value to array at: %s\n",
|
||||
/* IN_UNABLE_TO_EXECUTE_COMMAND */
|
||||
"Unable to execute command\n",
|
||||
};
|
||||
|
||||
static const int err_codes[] = {
|
||||
|
@ -227,6 +229,7 @@ static const int err_codes[] = {
|
|||
537, /* IN_INVALID_TYPE */
|
||||
538, /* IN_FUNCTION_NAME_USED_BY_VARIABLE */
|
||||
539, /* IN_CANNOT_CAST_VALUE_TO_ARRAY */
|
||||
540, /* IN_UNABLE_TO_EXECUTE_COMMAND */
|
||||
};
|
||||
|
||||
int error(ErrorType e, ...)
|
||||
|
|
1
error.h
1
error.h
|
@ -103,6 +103,7 @@ typedef enum {
|
|||
IN_INVALID_TYPE,
|
||||
IN_FUNCTION_NAME_USED_BY_VARIABLE,
|
||||
IN_CANNOT_CAST_VALUE_TO_ARRAY,
|
||||
IN_UNABLE_TO_EXECUTE_COMMAND,
|
||||
} ErrorType;
|
||||
|
||||
int error(ErrorType, ...);
|
||||
|
|
|
@ -1765,6 +1765,66 @@ ValueObject *interpretFuncCallExprNode(ExprNode *node,
|
|||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* Interprets a system command
|
||||
*
|
||||
* \param [in] node A pointer to the expression to interpret.
|
||||
*
|
||||
* \param [in,out] scope A pointer to a scope to evaluate \a node under.
|
||||
*
|
||||
* \pre \a node contains an expression created by createSystemCommandExprNode().
|
||||
*
|
||||
* \return A pointer to the returned value.
|
||||
*
|
||||
* \retval NULL An error occurred during interpretation.
|
||||
*/
|
||||
ValueObject *interpretSystemCommandExprNode(ExprNode *node,
|
||||
ScopeObject *scope)
|
||||
{
|
||||
SystemCommandExprNode *expr = (SystemCommandExprNode *)node->expr;
|
||||
ValueObject *val = NULL;
|
||||
FILE *f;
|
||||
char *cmd = NULL;
|
||||
unsigned int buflen = 2048;
|
||||
char buf[buflen];
|
||||
char *out = NULL;
|
||||
unsigned int len;
|
||||
unsigned int total = 0;
|
||||
unsigned int prev = 0;
|
||||
|
||||
/* Sanity checks */
|
||||
if (scope == NULL) return NULL;
|
||||
if (node->type != ET_SYSTEMCOMMAND) return NULL;
|
||||
if (expr == NULL) return NULL;
|
||||
|
||||
val = interpretExprNode(expr->cmd, scope);
|
||||
if (!val) return NULL;
|
||||
|
||||
cmd = getString(val);
|
||||
|
||||
|
||||
/* Open the command for reading */
|
||||
f = popen(cmd, "r");
|
||||
if (f == NULL) {
|
||||
error(IN_UNABLE_TO_EXECUTE_COMMAND);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
while ((len = fread(buf, 1, buflen, f)) > 0) {
|
||||
prev = total;
|
||||
total += len;
|
||||
out = realloc(out, total + 1);
|
||||
memcpy(out + prev, buf, len);
|
||||
}
|
||||
if (total > 0) out[total] = '\0';
|
||||
|
||||
/* Close */
|
||||
pclose(f);
|
||||
|
||||
/* Return the command object */
|
||||
return createStringValueObject(out == NULL ? "" : out);
|
||||
}
|
||||
|
||||
/**
|
||||
* Interprets an identifier.
|
||||
*
|
||||
|
@ -2925,13 +2985,14 @@ ValueObject *interpretOpExprNode(ExprNode *node,
|
|||
* A jump table for expressions. The index of a function in the table is given
|
||||
* by its its index in the enumerated ExprType type.
|
||||
*/
|
||||
static ValueObject *(*ExprJumpTable[6])(ExprNode *, ScopeObject *) = {
|
||||
static ValueObject *(*ExprJumpTable[7])(ExprNode *, ScopeObject *) = {
|
||||
interpretCastExprNode,
|
||||
interpretConstantExprNode,
|
||||
interpretIdentifierExprNode,
|
||||
interpretFuncCallExprNode,
|
||||
interpretOpExprNode,
|
||||
interpretImpVarExprNode };
|
||||
interpretImpVarExprNode,
|
||||
interpretSystemCommandExprNode };
|
||||
|
||||
/**
|
||||
* Interprets an expression.
|
||||
|
|
|
@ -225,6 +225,7 @@ ValueObject *interpretCastExprNode(ExprNode *, ScopeObject *);
|
|||
ValueObject *interpretFuncCallExprNode(ExprNode *, ScopeObject *);
|
||||
ValueObject *interpretIdentifierExprNode(ExprNode *, ScopeObject *);
|
||||
ValueObject *interpretConstantExprNode(ExprNode *, ScopeObject *);
|
||||
ValueObject *interpretSystemCommandExprNode(ExprNode *, ScopeObject *);
|
||||
/**@}*/
|
||||
|
||||
/**
|
||||
|
|
100
parser.c
100
parser.c
|
@ -1234,6 +1234,9 @@ void deleteExprNode(ExprNode *node)
|
|||
break;
|
||||
case ET_IMPVAR:
|
||||
break; /* This expression type does not have any content */
|
||||
case ET_SYSTEMCOMMAND:
|
||||
deleteSystemCommandExprNode((SystemCommandExprNode *)node->expr);
|
||||
break;
|
||||
default:
|
||||
error(PR_UNKNOWN_EXPRESSION_TYPE);
|
||||
break;
|
||||
|
@ -1372,6 +1375,26 @@ FuncCallExprNode *createFuncCallExprNode(IdentifierNode *scope,
|
|||
return p;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a system command expression.
|
||||
*
|
||||
* \param [in] cmd The command to execute.
|
||||
*
|
||||
* \return A pointer to a system command expression with the desired properties.
|
||||
*
|
||||
* \retval NULL Memory allocation failed.
|
||||
*/
|
||||
SystemCommandExprNode *createSystemCommandExprNode(ExprNode *cmd)
|
||||
{
|
||||
SystemCommandExprNode *p = malloc(sizeof(SystemCommandExprNode));
|
||||
if (!p) {
|
||||
perror("malloc");
|
||||
return NULL;
|
||||
}
|
||||
p->cmd = cmd;
|
||||
return p;
|
||||
}
|
||||
|
||||
/**
|
||||
* Deletes a function call expression.
|
||||
*
|
||||
|
@ -1388,6 +1411,20 @@ void deleteFuncCallExprNode(FuncCallExprNode *node)
|
|||
free(node);
|
||||
}
|
||||
|
||||
/**
|
||||
* Deletes a system command expression.
|
||||
*
|
||||
* \param [in,out] node The system command expression to delete.
|
||||
*
|
||||
* \post The memory at \a node and all of its members will be freed.
|
||||
*/
|
||||
void deleteSystemCommandExprNode(SystemCommandExprNode *node)
|
||||
{
|
||||
if (!node) return;
|
||||
deleteExprNode(node->cmd);
|
||||
free(node);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates an operation expression.
|
||||
*
|
||||
|
@ -2134,6 +2171,65 @@ parseFuncCallExprNodeAbort: /* Exception handling */
|
|||
return NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
* Parses tokens into a system command expression.
|
||||
*
|
||||
* \param [in] tokenp The position in a token list to start parsing at.
|
||||
*
|
||||
* \post \a Tokenp will point to the next unparsed token.
|
||||
*
|
||||
* \return A pointer to a system command expression.
|
||||
*
|
||||
* \retval NULL Unable to parse.
|
||||
*/
|
||||
ExprNode *parseSystemCommandExprNode(Token ***tokenp)
|
||||
{
|
||||
ExprNode *name = NULL;
|
||||
SystemCommandExprNode *expr = NULL;
|
||||
ExprNode *ret = NULL;
|
||||
int status;
|
||||
|
||||
/* Work from a copy of the token stream in case something goes wrong */
|
||||
Token **tokens = *tokenp;
|
||||
|
||||
#ifdef DEBUG
|
||||
debug("ET_SYSTEMCOMMAND");
|
||||
#endif
|
||||
|
||||
/* Parse the system command token */
|
||||
status = acceptToken(&tokens, TT_IDUZ);
|
||||
if (!status) {
|
||||
parser_error_expected_token(TT_IDUZ, tokens);
|
||||
goto parseSystemCommandExprNodeAbort;
|
||||
}
|
||||
|
||||
/* Parse the expression name */
|
||||
name = parseExprNode(&tokens);
|
||||
if (!name) goto parseSystemCommandExprNodeAbort;
|
||||
|
||||
/* Create the new SystemCommandExprNode structure */
|
||||
expr = createSystemCommandExprNode(name);
|
||||
if (!expr) goto parseSystemCommandExprNodeAbort;
|
||||
|
||||
/* Create the new ExprNode structure */
|
||||
ret = createExprNode(ET_SYSTEMCOMMAND, expr);
|
||||
if (!ret) goto parseSystemCommandExprNodeAbort;
|
||||
|
||||
/* Since we're successful, update the token stream */
|
||||
*tokenp = tokens;
|
||||
|
||||
return ret;
|
||||
|
||||
parseSystemCommandExprNodeAbort: /* Exception handling */
|
||||
|
||||
/* Clean up any allocated structures */
|
||||
if (ret) deleteExprNode(ret);
|
||||
else if (expr) deleteSystemCommandExprNode(expr);
|
||||
else if (name) deleteExprNode(name);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
* Parses tokens into an operation expression.
|
||||
*
|
||||
|
@ -2449,6 +2545,10 @@ ExprNode *parseExprNode(Token ***tokenp)
|
|||
/* Since we're successful, update the token stream */
|
||||
*tokenp = tokens;
|
||||
}
|
||||
else if (peekToken(&tokens, TT_IDUZ)) {
|
||||
/* System command */
|
||||
ret = parseSystemCommandExprNode(tokenp);
|
||||
}
|
||||
else {
|
||||
parser_error(PR_EXPECTED_EXPRESSION, tokens);
|
||||
}
|
||||
|
|
28
parser.h
28
parser.h
|
@ -155,7 +155,7 @@
|
|||
*
|
||||
* \par
|
||||
* ExprNode ::= CastExprNode | ConstantNode | IdentifierNode | FuncCallExprNode
|
||||
* | OpExprNode | ImplicitVariable
|
||||
* | OpExprNode | ImplicitVariable | SystemCommandExprNode
|
||||
*
|
||||
* \par
|
||||
* CastExprNode ::= \c TT_MAEK ExprNode \c TT_A TypeNode
|
||||
|
@ -165,6 +165,9 @@
|
|||
* TT_MKAY
|
||||
*
|
||||
* \par
|
||||
* SystemCommandExprNode ::= \c TT_DUZ \c IdentifierNode
|
||||
*
|
||||
* \par
|
||||
* OpExprNode ::= UnaryOp | BinaryOp | NaryOp
|
||||
*
|
||||
* \par
|
||||
|
@ -257,7 +260,8 @@ typedef enum {
|
|||
ET_IDENTIFIER, /**< Identifier expression. */
|
||||
ET_FUNCCALL, /**< Function call expression. */
|
||||
ET_OP, /**< Operation expression. */
|
||||
ET_IMPVAR /**< \ref impvar "Implicit variable". */
|
||||
ET_IMPVAR, /**< \ref impvar "Implicit variable". */
|
||||
ET_SYSTEMCOMMAND, /**< System command expression. */
|
||||
} ExprType;
|
||||
|
||||
/**
|
||||
|
@ -522,6 +526,15 @@ typedef struct {
|
|||
ExprNodeList *args; /**< The arguments to supply the function. */
|
||||
} FuncCallExprNode;
|
||||
|
||||
/**
|
||||
* Stores a system command expression. This expression evaluates an identifier
|
||||
* which contains a system command, and evaluates to the standard output of the
|
||||
* executed system command.
|
||||
*/
|
||||
typedef struct {
|
||||
ExprNode *cmd; /**< The expression containing the command to execute */
|
||||
} SystemCommandExprNode;
|
||||
|
||||
/**
|
||||
* Represents the type of operation an OpExprNode performs.
|
||||
*/
|
||||
|
@ -789,6 +802,16 @@ FuncCallExprNode *createFuncCallExprNode(IdentifierNode *, IdentifierNode *, Exp
|
|||
void deleteFuncCallExprNode(FuncCallExprNode *);
|
||||
/**@}*/
|
||||
|
||||
/**
|
||||
* \name SystemCommandExprNode modifiers
|
||||
*
|
||||
* Functions for creating and deleting SystemCommandExprNode.
|
||||
*/
|
||||
/**@{*/
|
||||
SystemCommandExprNode *createSystemCommandExprNode(ExprNode *);
|
||||
void deleteSystemCommandExprNode(SystemCommandExprNode *);
|
||||
/**@}*/
|
||||
|
||||
/**
|
||||
* \name OpExprNode modifiers
|
||||
*
|
||||
|
@ -827,6 +850,7 @@ ExprNode *parseCastExprNode(Token ***);
|
|||
ExprNode *parseConstantExprNode(Token ***);
|
||||
ExprNode *parseIdentifierExprNode(Token ***);
|
||||
ExprNode *parseFuncCallExprNode(Token ***);
|
||||
ExprNode *parseSystemCommandExprNode(Token ***);
|
||||
ExprNode *parseOpExprNode(Token ***);
|
||||
StmtNode *parseCastStmtNode(Token ***);
|
||||
StmtNode *parsePrintStmtNode(Token ***);
|
||||
|
|
|
@ -104,6 +104,7 @@ typedef enum {
|
|||
TT_OHAIIM, /**< Alternate array declaration. */
|
||||
TT_IMLIEK, /**< Alternate inherited object declaration. */
|
||||
TT_KTHX, /**< End of alternate array declaration. */
|
||||
TT_IDUZ, /**< System command. */
|
||||
TT_CANHAS, /**< Library import declaration. */
|
||||
TT_QUESTION, /**< End of library import declaration. */
|
||||
|
||||
|
@ -183,6 +184,7 @@ static const char *keywords[] = {
|
|||
"O HAI IM", /* TT_OHAIIM */
|
||||
"IM LIEK", /* TT_IMLIEK */
|
||||
"KTHX", /* TT_KTHX */
|
||||
"I DUZ", /* TT_IDUZ */
|
||||
"CAN HAS", /* TT_CANHAS */
|
||||
"?", /* TT_QUESTION */
|
||||
"" /* TT_ENDOFTOKENS */
|
||||
|
|
Loading…
Reference in New Issue