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",
|
"%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, ...)
|
||||||
|
|
1
error.h
1
error.h
|
@ -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, ...);
|
||||||
|
|
|
@ -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.
|
||||||
|
|
|
@ -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
100
parser.c
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
38
parser.h
38
parser.h
|
@ -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 ***);
|
||||||
|
|
|
@ -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 */
|
||||||
|
|
Loading…
Reference in New Issue