patched ElColmo's system command code with some minor style changes

This commit is contained in:
Justin Meza 2014-05-09 23:59:18 -04:00
parent 74b80b4aca
commit c412ec117a
7 changed files with 201 additions and 9 deletions

View File

@ -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, ...)

View File

@ -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, ...);

View File

@ -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.

View File

@ -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
View File

@ -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);
}

View File

@ -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
@ -252,12 +255,13 @@ typedef struct {
* Represents an expression type.
*/
typedef enum {
ET_CAST, /**< Cast expression. */
ET_CONSTANT, /**< Constant expression. */
ET_IDENTIFIER, /**< Identifier expression. */
ET_FUNCCALL, /**< Function call expression. */
ET_OP, /**< Operation expression. */
ET_IMPVAR /**< \ref impvar "Implicit variable". */
ET_CAST, /**< Cast expression. */
ET_CONSTANT, /**< Constant expression. */
ET_IDENTIFIER, /**< Identifier expression. */
ET_FUNCCALL, /**< Function call expression. */
ET_OP, /**< Operation expression. */
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 ***);

View File

@ -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 */