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", "%s:%u: function name already used by existing variable at: %s\n",
/* IN_CANNOT_CAST_VALUE_TO_ARRAY */ /* IN_CANNOT_CAST_VALUE_TO_ARRAY */
"%s:%u: cannot cast value to array at: %s\n", "%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[] = { static const int err_codes[] = {
@ -227,6 +229,7 @@ static const int err_codes[] = {
537, /* IN_INVALID_TYPE */ 537, /* IN_INVALID_TYPE */
538, /* IN_FUNCTION_NAME_USED_BY_VARIABLE */ 538, /* IN_FUNCTION_NAME_USED_BY_VARIABLE */
539, /* IN_CANNOT_CAST_VALUE_TO_ARRAY */ 539, /* IN_CANNOT_CAST_VALUE_TO_ARRAY */
540, /* IN_UNABLE_TO_EXECUTE_COMMAND */
}; };
int error(ErrorType e, ...) int error(ErrorType e, ...)

View File

@ -103,6 +103,7 @@ typedef enum {
IN_INVALID_TYPE, IN_INVALID_TYPE,
IN_FUNCTION_NAME_USED_BY_VARIABLE, IN_FUNCTION_NAME_USED_BY_VARIABLE,
IN_CANNOT_CAST_VALUE_TO_ARRAY, IN_CANNOT_CAST_VALUE_TO_ARRAY,
IN_UNABLE_TO_EXECUTE_COMMAND,
} ErrorType; } ErrorType;
int error(ErrorType, ...); int error(ErrorType, ...);

View File

@ -1765,6 +1765,66 @@ ValueObject *interpretFuncCallExprNode(ExprNode *node,
return ret; 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. * 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 * A jump table for expressions. The index of a function in the table is given
* by its its index in the enumerated ExprType type. * by its its index in the enumerated ExprType type.
*/ */
static ValueObject *(*ExprJumpTable[6])(ExprNode *, ScopeObject *) = { static ValueObject *(*ExprJumpTable[7])(ExprNode *, ScopeObject *) = {
interpretCastExprNode, interpretCastExprNode,
interpretConstantExprNode, interpretConstantExprNode,
interpretIdentifierExprNode, interpretIdentifierExprNode,
interpretFuncCallExprNode, interpretFuncCallExprNode,
interpretOpExprNode, interpretOpExprNode,
interpretImpVarExprNode }; interpretImpVarExprNode,
interpretSystemCommandExprNode };
/** /**
* Interprets an expression. * Interprets an expression.

View File

@ -225,6 +225,7 @@ ValueObject *interpretCastExprNode(ExprNode *, ScopeObject *);
ValueObject *interpretFuncCallExprNode(ExprNode *, ScopeObject *); ValueObject *interpretFuncCallExprNode(ExprNode *, ScopeObject *);
ValueObject *interpretIdentifierExprNode(ExprNode *, ScopeObject *); ValueObject *interpretIdentifierExprNode(ExprNode *, ScopeObject *);
ValueObject *interpretConstantExprNode(ExprNode *, ScopeObject *); ValueObject *interpretConstantExprNode(ExprNode *, ScopeObject *);
ValueObject *interpretSystemCommandExprNode(ExprNode *, ScopeObject *);
/**@}*/ /**@}*/
/** /**

100
parser.c
View File

@ -1234,6 +1234,9 @@ void deleteExprNode(ExprNode *node)
break; break;
case ET_IMPVAR: case ET_IMPVAR:
break; /* This expression type does not have any content */ break; /* This expression type does not have any content */
case ET_SYSTEMCOMMAND:
deleteSystemCommandExprNode((SystemCommandExprNode *)node->expr);
break;
default: default:
error(PR_UNKNOWN_EXPRESSION_TYPE); error(PR_UNKNOWN_EXPRESSION_TYPE);
break; break;
@ -1372,6 +1375,26 @@ FuncCallExprNode *createFuncCallExprNode(IdentifierNode *scope,
return p; 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. * Deletes a function call expression.
* *
@ -1388,6 +1411,20 @@ void deleteFuncCallExprNode(FuncCallExprNode *node)
free(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. * Creates an operation expression.
* *
@ -2134,6 +2171,65 @@ parseFuncCallExprNodeAbort: /* Exception handling */
return NULL; 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. * Parses tokens into an operation expression.
* *
@ -2449,6 +2545,10 @@ ExprNode *parseExprNode(Token ***tokenp)
/* Since we're successful, update the token stream */ /* Since we're successful, update the token stream */
*tokenp = tokens; *tokenp = tokens;
} }
else if (peekToken(&tokens, TT_IDUZ)) {
/* System command */
ret = parseSystemCommandExprNode(tokenp);
}
else { else {
parser_error(PR_EXPECTED_EXPRESSION, tokens); parser_error(PR_EXPECTED_EXPRESSION, tokens);
} }

View File

@ -155,7 +155,7 @@
* *
* \par * \par
* ExprNode ::= CastExprNode | ConstantNode | IdentifierNode | FuncCallExprNode * ExprNode ::= CastExprNode | ConstantNode | IdentifierNode | FuncCallExprNode
* | OpExprNode | ImplicitVariable * | OpExprNode | ImplicitVariable | SystemCommandExprNode
* *
* \par * \par
* CastExprNode ::= \c TT_MAEK ExprNode \c TT_A TypeNode * CastExprNode ::= \c TT_MAEK ExprNode \c TT_A TypeNode
@ -165,6 +165,9 @@
* TT_MKAY * TT_MKAY
* *
* \par * \par
* SystemCommandExprNode ::= \c TT_DUZ \c IdentifierNode
*
* \par
* OpExprNode ::= UnaryOp | BinaryOp | NaryOp * OpExprNode ::= UnaryOp | BinaryOp | NaryOp
* *
* \par * \par
@ -252,12 +255,13 @@ typedef struct {
* Represents an expression type. * Represents an expression type.
*/ */
typedef enum { typedef enum {
ET_CAST, /**< Cast expression. */ ET_CAST, /**< Cast expression. */
ET_CONSTANT, /**< Constant expression. */ ET_CONSTANT, /**< Constant expression. */
ET_IDENTIFIER, /**< Identifier expression. */ ET_IDENTIFIER, /**< Identifier expression. */
ET_FUNCCALL, /**< Function call expression. */ ET_FUNCCALL, /**< Function call expression. */
ET_OP, /**< Operation expression. */ ET_OP, /**< Operation expression. */
ET_IMPVAR /**< \ref impvar "Implicit variable". */ ET_IMPVAR, /**< \ref impvar "Implicit variable". */
ET_SYSTEMCOMMAND, /**< System command expression. */
} ExprType; } ExprType;
/** /**
@ -522,6 +526,15 @@ typedef struct {
ExprNodeList *args; /**< The arguments to supply the function. */ ExprNodeList *args; /**< The arguments to supply the function. */
} FuncCallExprNode; } 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. * Represents the type of operation an OpExprNode performs.
*/ */
@ -789,6 +802,16 @@ FuncCallExprNode *createFuncCallExprNode(IdentifierNode *, IdentifierNode *, Exp
void deleteFuncCallExprNode(FuncCallExprNode *); void deleteFuncCallExprNode(FuncCallExprNode *);
/**@}*/ /**@}*/
/**
* \name SystemCommandExprNode modifiers
*
* Functions for creating and deleting SystemCommandExprNode.
*/
/**@{*/
SystemCommandExprNode *createSystemCommandExprNode(ExprNode *);
void deleteSystemCommandExprNode(SystemCommandExprNode *);
/**@}*/
/** /**
* \name OpExprNode modifiers * \name OpExprNode modifiers
* *
@ -827,6 +850,7 @@ ExprNode *parseCastExprNode(Token ***);
ExprNode *parseConstantExprNode(Token ***); ExprNode *parseConstantExprNode(Token ***);
ExprNode *parseIdentifierExprNode(Token ***); ExprNode *parseIdentifierExprNode(Token ***);
ExprNode *parseFuncCallExprNode(Token ***); ExprNode *parseFuncCallExprNode(Token ***);
ExprNode *parseSystemCommandExprNode(Token ***);
ExprNode *parseOpExprNode(Token ***); ExprNode *parseOpExprNode(Token ***);
StmtNode *parseCastStmtNode(Token ***); StmtNode *parseCastStmtNode(Token ***);
StmtNode *parsePrintStmtNode(Token ***); StmtNode *parsePrintStmtNode(Token ***);

View File

@ -104,6 +104,7 @@ typedef enum {
TT_OHAIIM, /**< Alternate array declaration. */ TT_OHAIIM, /**< Alternate array declaration. */
TT_IMLIEK, /**< Alternate inherited object declaration. */ TT_IMLIEK, /**< Alternate inherited object declaration. */
TT_KTHX, /**< End of alternate array declaration. */ TT_KTHX, /**< End of alternate array declaration. */
TT_IDUZ, /**< System command. */
TT_CANHAS, /**< Library import declaration. */ TT_CANHAS, /**< Library import declaration. */
TT_QUESTION, /**< End of library import declaration. */ TT_QUESTION, /**< End of library import declaration. */
@ -183,6 +184,7 @@ static const char *keywords[] = {
"O HAI IM", /* TT_OHAIIM */ "O HAI IM", /* TT_OHAIIM */
"IM LIEK", /* TT_IMLIEK */ "IM LIEK", /* TT_IMLIEK */
"KTHX", /* TT_KTHX */ "KTHX", /* TT_KTHX */
"I DUZ", /* TT_IDUZ */
"CAN HAS", /* TT_CANHAS */ "CAN HAS", /* TT_CANHAS */
"?", /* TT_QUESTION */ "?", /* TT_QUESTION */
"" /* TT_ENDOFTOKENS */ "" /* TT_ENDOFTOKENS */