adding zephyr-im master branch
This commit is contained in:
300
zwgc/eval.c
Normal file
300
zwgc/eval.c
Normal file
@@ -0,0 +1,300 @@
|
||||
/* This file is part of the Project Athena Zephyr Notification System.
|
||||
* It is one of the source files comprising zwgc, the Zephyr WindowGram
|
||||
* client.
|
||||
*
|
||||
* Created by: Marc Horowitz <marc@athena.mit.edu>
|
||||
*
|
||||
* $Id$
|
||||
*
|
||||
* Copyright (c) 1989 by the Massachusetts Institute of Technology.
|
||||
* For copying and distribution information, see the file
|
||||
* "mit-copyright.h".
|
||||
*/
|
||||
|
||||
#include <sysdep.h>
|
||||
|
||||
#if (!defined(lint) && !defined(SABER))
|
||||
static const char rcsid_eval_c[] = "$Id$";
|
||||
#endif
|
||||
|
||||
#include <zephyr/mit-copyright.h>
|
||||
|
||||
/****************************************************************************/
|
||||
/* */
|
||||
/* Code to evaluate an expression: */
|
||||
/* */
|
||||
/****************************************************************************/
|
||||
|
||||
#include <zephyr/zephyr.h>
|
||||
#include "new_memory.h"
|
||||
#include "node.h"
|
||||
#include "eval.h"
|
||||
#include "substitute.h"
|
||||
#include "port.h"
|
||||
#include "buffer.h"
|
||||
#include "regexp.h"
|
||||
#include "formatter.h"
|
||||
#include "text_operations.h"
|
||||
#include "zwgc.h"
|
||||
#include "variables.h"
|
||||
|
||||
/****************************************************************************/
|
||||
/* */
|
||||
/* Code to deal with string/boolean conversion: */
|
||||
/* */
|
||||
/****************************************************************************/
|
||||
|
||||
/*
|
||||
* Internal Routine:
|
||||
*
|
||||
* int string_to_bool(string str)
|
||||
* Effects: Returns true iff the string str represents true.
|
||||
* True is represented by any string which is equal to
|
||||
* "true" when case is disregraded.
|
||||
*/
|
||||
|
||||
#define string_to_bool(str) (!strcasecmp(str,"true"))
|
||||
|
||||
/*
|
||||
* Internal Routine:
|
||||
*
|
||||
* string bool_to_string(int bool)
|
||||
* Effects: Returns a string representive for the C boolean bool.
|
||||
* (In C, true == non-zero) I.e.,
|
||||
* string_to_bool(bool_to_string(x)) == !!x.
|
||||
* The string returned is on the heap & must be freed
|
||||
* eventually.
|
||||
*/
|
||||
|
||||
static string
|
||||
bool_to_string(int bool)
|
||||
{
|
||||
return(bool ? string_Copy("TRUE") : string_Copy("FALSE"));
|
||||
}
|
||||
|
||||
/*
|
||||
* int eval_bool_expr(Node *expr)
|
||||
* Modifies: dict
|
||||
* Requires: expr is a proper expression or NULL. (see node.c)
|
||||
* Effects: Evaluates expr to its boolean value which is returned.
|
||||
* NULL is defined to have the boolean value true.
|
||||
*/
|
||||
|
||||
int
|
||||
eval_bool_expr(Node *expr)
|
||||
{
|
||||
string temp;
|
||||
int result;
|
||||
|
||||
if (!expr)
|
||||
return(1);
|
||||
|
||||
temp = eval_expr(expr);
|
||||
result = string_to_bool(temp);
|
||||
free(temp);
|
||||
|
||||
return(result);
|
||||
}
|
||||
|
||||
/****************************************************************************/
|
||||
/* */
|
||||
/* Code to evaluate an expression: */
|
||||
/* */
|
||||
/****************************************************************************/
|
||||
|
||||
/*
|
||||
* string eval_expr(Node *expr)
|
||||
* Modifies: dict
|
||||
* Requires: expr is a proper expression (NOT NULL). (see node.c)
|
||||
* Effects: Evaluates expr to its string value which is returned.
|
||||
* The returned string is on the heap and must be freed
|
||||
* eventually.
|
||||
*/
|
||||
|
||||
string
|
||||
eval_expr(Node *expr)
|
||||
{
|
||||
int opcode = expr->opcode;
|
||||
int bool_result = 0;
|
||||
string first, second;
|
||||
char *result = NULL;
|
||||
string *text_ptr;
|
||||
|
||||
/*
|
||||
* Dispatch based on the opcode of the top node in the expression:
|
||||
*/
|
||||
switch (opcode) {
|
||||
case STRING_CONSTANT_OPCODE:
|
||||
return(string_Copy(expr->d.string_constant));
|
||||
|
||||
case VARREF_OPCODE:
|
||||
return(string_Copy(var_get_variable(expr->d.string_constant)));
|
||||
|
||||
case BUFFER_OPCODE:
|
||||
return(string_Copy(buffer_to_string()));
|
||||
|
||||
/*
|
||||
* Handle unary expressions:
|
||||
*/
|
||||
case NOT_OPCODE:
|
||||
case SUBSTITUTE_OPCODE:
|
||||
case PROTECT_OPCODE:
|
||||
case VERBATIM_OPCODE:
|
||||
case STYLESTRIP_OPCODE:
|
||||
case GETENV_OPCODE:
|
||||
case UPCASE_OPCODE:
|
||||
case DOWNCASE_OPCODE:
|
||||
case ZVAR_OPCODE:
|
||||
case GET_OPCODE:
|
||||
first = eval_expr(expr->d.nodes.first);
|
||||
|
||||
switch (opcode) {
|
||||
case NOT_OPCODE:
|
||||
result = bool_to_string(! string_to_bool(first));
|
||||
break;
|
||||
|
||||
case SUBSTITUTE_OPCODE:
|
||||
result = substitute(var_get_variable, first);
|
||||
break;
|
||||
|
||||
case PROTECT_OPCODE:
|
||||
result=protect(first);
|
||||
break;
|
||||
|
||||
case VERBATIM_OPCODE:
|
||||
return(verbatim(first,0));
|
||||
|
||||
case STYLESTRIP_OPCODE:
|
||||
return(stylestrip(first));
|
||||
|
||||
case GETENV_OPCODE:
|
||||
result = getenv(first);
|
||||
if (!result)
|
||||
result = string_Copy("");
|
||||
else
|
||||
result = string_Copy(result);
|
||||
break;
|
||||
|
||||
case UPCASE_OPCODE:
|
||||
return(string_Upcase(first));
|
||||
|
||||
case DOWNCASE_OPCODE:
|
||||
return(string_Downcase(first));
|
||||
|
||||
case ZVAR_OPCODE:
|
||||
result = ZGetVariable(first);
|
||||
if (!result)
|
||||
result = string_Copy("");
|
||||
else
|
||||
result = string_Copy(result);
|
||||
break;
|
||||
|
||||
case GET_OPCODE:
|
||||
result = read_from_port(first);
|
||||
break;
|
||||
}
|
||||
free(first);
|
||||
break;
|
||||
|
||||
/*
|
||||
* Handle binary operators:
|
||||
*/
|
||||
case PLUS_OPCODE:
|
||||
case AND_OPCODE:
|
||||
case OR_OPCODE:
|
||||
case EQ_OPCODE:
|
||||
case NEQ_OPCODE:
|
||||
case REGEQ_OPCODE:
|
||||
case REGNEQ_OPCODE:
|
||||
first = eval_expr(expr->d.nodes.first);
|
||||
second = eval_expr(expr->d.nodes.second);
|
||||
|
||||
switch (opcode) {
|
||||
case PLUS_OPCODE:
|
||||
result = string_Concat(first, second);
|
||||
free(first);
|
||||
free(second);
|
||||
return(result);
|
||||
|
||||
case AND_OPCODE:
|
||||
bool_result = string_to_bool(first) && string_to_bool(second);
|
||||
break;
|
||||
|
||||
case OR_OPCODE:
|
||||
bool_result = string_to_bool(first) || string_to_bool(second);
|
||||
break;
|
||||
|
||||
case EQ_OPCODE:
|
||||
bool_result = string_Eq(first, second);
|
||||
break;
|
||||
|
||||
case NEQ_OPCODE:
|
||||
bool_result = string_Neq(first, second);
|
||||
break;
|
||||
|
||||
case REGEQ_OPCODE:
|
||||
bool_result = ed_regexp_match_p(first, second);
|
||||
break;
|
||||
|
||||
case REGNEQ_OPCODE:
|
||||
bool_result = !ed_regexp_match_p(first, second);
|
||||
break;
|
||||
}
|
||||
free(first);
|
||||
free(second);
|
||||
result = bool_to_string(bool_result);
|
||||
break;
|
||||
|
||||
/*
|
||||
* Handle text-manipulation operators:
|
||||
*/
|
||||
case LANY_OPCODE: case RANY_OPCODE:
|
||||
case LBREAK_OPCODE: case RBREAK_OPCODE:
|
||||
case LSPAN_OPCODE: case RSPAN_OPCODE:
|
||||
first = eval_expr(expr->d.nodes.first);
|
||||
second = eval_expr(expr->d.nodes.second);
|
||||
text_ptr = &first;
|
||||
|
||||
switch (opcode) {
|
||||
case LANY_OPCODE:
|
||||
result = lany(text_ptr, second);
|
||||
break;
|
||||
|
||||
case RANY_OPCODE:
|
||||
result = rany(text_ptr, second);
|
||||
break;
|
||||
|
||||
case LBREAK_OPCODE:
|
||||
result = lbreak(text_ptr, string_to_character_class(second));
|
||||
break;
|
||||
|
||||
case RBREAK_OPCODE:
|
||||
result = rbreak(text_ptr, string_to_character_class(second));
|
||||
break;
|
||||
|
||||
case LSPAN_OPCODE:
|
||||
result = lspan(text_ptr, string_to_character_class(second));
|
||||
break;
|
||||
|
||||
case RSPAN_OPCODE:
|
||||
result = rspan(text_ptr, string_to_character_class(second));
|
||||
break;
|
||||
}
|
||||
|
||||
if (expr->d.nodes.first->opcode == VARREF_OPCODE)
|
||||
var_set_variable(expr->d.nodes.first->d.string_constant, first);
|
||||
free(first);
|
||||
free(second);
|
||||
break;
|
||||
|
||||
#ifdef DEBUG
|
||||
default:
|
||||
printf("zwgc: internal error: attempt to evaluate the following non-expression:\n"); fflush(stdout);
|
||||
node_display(expr);
|
||||
printf("\n\n");
|
||||
exit(2);
|
||||
#endif
|
||||
}
|
||||
|
||||
return(result);
|
||||
}
|
||||
Reference in New Issue
Block a user