File: rpn.cc

package info (click to toggle)
gri 2.4.2-1
  • links: PTS
  • area: main
  • in suites: potato
  • size: 4,540 kB
  • ctags: 1,966
  • sloc: cpp: 32,542; lisp: 3,243; perl: 806; makefile: 548; sh: 253
file content (189 lines) | stat: -rw-r--r-- 5,689 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
#include	<string>
#include	<ctype.h>
#include	<math.h>
#include	<stdio.h>
#include	"gr.hh"
#include	"extern.hh"
#define BEGIN_MATH "{"
#define END_MATH   "}"
extern int      rpn(int nw, char **w, char ** result); // in rpncalc.cc
extern void     print_rpn_stack(void);		       // in rpncalc.cc

bool
rpnfunctionCmd()
{
    if (_nword < 3) {
	demonstrate_command_usage();
	err("Need some action for this rpn function");
	return false;
    }
    rpn_create_function(_word[1], &_word[2], _nword - 2);
    return true;
}

/* copy below from rpncalc.c */
/* Return codes: */
#define NO_ERROR 0		/* everything is OK */
#define BAD_WORD 1		/* not operator, operand, column, function */
#define STACK_UNDERFLOW 2	/* missing operators */
#define STACK_OVERFLOW 3	/* extra stuff */
#define DIV_BY_ZERO 4		/* cannot divide by zero */
#define OUT_OF_STORAGE 5	/* computer limitation */
#define ILLEGAL_TYPE 6		/* cannot do with given operand(s) */
#define NEED_GE_0 7		/* need operand >= 0 */
#define NEED_GT_0 8		/* need operand > 0 */
#define RANGE_1 9		/* need operand in range -1 to 1 */
#define NEED_GT_1 10		/* need operand > 1  */
#define COMPUTER_LIMITATION 11	/* can't do on this machine */
#define GENERAL_ERROR  12	/* some other error */
/*
 * Substitute an rpn expression.  Return 1 if found an expression.  This is
 * called repeatedly by other functions, until it returns 0, at which time
 * all the rpn expressions will have been converted.
 * 
 * NOTE: nesting not allowed.
 */
bool
substitute_rpn_expressions(const char *s, char *sout)
{
    bool            found = false;
    int             i, nword;
    int             rpn_start, rpn_end;
    // Copy s to a buffer, to avoid destroying  it when chopping into words
    GriString sCopy(s);
    chop_into_words(sCopy.getValue(), _Words2, &nword, MAX_nword);
    if (nword < 2) {
	strcpy(sout, _Words2[0]);
	return false;
    }
    strcpy(sout, "");		// initialize
    /* Search for `BEGIN_MATH rpn ... END_MATH' */
    for (i = 0; i < nword; i++) {
	char           *result;
	int             ii;
	rpn_start = -1;
	rpn_end = -1;
	// If at beginning of expression, parse it and put result into next
	// word of sout.
	if (!strcmp(_Words2[i], BEGIN_MATH)) {
	    int             error;
	    rpn_start = i;
	    /* Check for { "string" == "string" } or {\syn == "string"} etc */
	    if ((i + 4) <= nword && !strcmp(_Words2[i + 2], "==")) {
		char           *p1, *p2;
		int             len;
		p1 = _Words2[i + 1];
		p2 = _Words2[i + 3];
		/*
		 * Give warning msg if detect statement of the form `if {\syn
		 * == "string"}'
		 */
		if (*p1 == '\\' || *p2 == '\\') {
		    err("Synonyms must be contained in quotes to compare them to strings.");
		    return false;
		}
		if (*p1 == '"')
		    p1++;
		if (*(p1 + (len = strlen(p1)) - 1) == '"')
		    *(p1 + len - 1) = '\0';
		if (*p2 == '"')
		    p2++;
		if (*(p2 + (len = strlen(p2)) - 1) == '"')
		    *(p2 + len - 1) = '\0';
		if (!strcmp(p1, p2))
		    strcat(sout, "1");
		else
		    strcat(sout, "0");
		for (i += 5; i < nword; i++) {	/* bug: change when
						 * generalized */
		    strcat(sout, _Words2[i]);
		    strcat(sout, " ");
		}
		return true;
	    } else if ((i + 3 > nword) || strcmp(_Words2[i + 1], "rpn")) {
		/* It's not an rpn expression. */
		strcpy(sout, s);
		return false;
	    }
	    /* Find the matching END_MATH bug: can't nest () in math */
	    for (ii = rpn_start + 2; ii < nword; ii++) {
		if (!strcmp(_Words2[ii], END_MATH)) {
		    rpn_end = ii;
		    break;
		}
	    }
	    /* Assure that END_MATH existed. */
	    if (rpn_end < 0) {
		err("Missing close-brace on RPN expression.  Proper: { rpn ... }");
		_error_in_cmd = true;
		return false;
	    }
	    error = rpn(rpn_end - rpn_start - 2, &_Words2[rpn_start + 2], &result);
	    switch (error) {
	    case BAD_WORD:
		err("unknown item in rpn expression");
		_error_in_cmd = true;
		return false;
	    case STACK_UNDERFLOW:
		err("\
final rpn stack has no operands.  Did you give an extra operator?");
		_error_in_cmd = true;
		return false;
	    case STACK_OVERFLOW:
		err("\
final rpn stack has more than 1 operand.  Did you forget an operator?");
		print_rpn_stack();
		_error_in_cmd = true;
		return false;
	    case DIV_BY_ZERO:
		err("rpn cannot divide by 0.");
		_error_in_cmd = true;
		return false;
	    case OUT_OF_STORAGE:
		err("rpn calculation ran out of storage.  Too many words in rpn expression.");
		_error_in_cmd = true;
		return false;
	    case ILLEGAL_TYPE:
		err("rpn inappropriate operator for operand[s] on the stack");
		_error_in_cmd = true;
		return false;
	    case NEED_GE_0:
		err("rpn operator requires operand >= 0");
		_error_in_cmd = true;
		return false;
	    case NEED_GT_0:
		err("rpn operator requires operand > 0");
		_error_in_cmd = true;
		return false;
	    case RANGE_1:
		err("rpn operator requires operand in range -1 to 1 inclusive");
		_error_in_cmd = true;
		return false;
	    case NEED_GT_1:
		err("rpn operator requires operand >= 1");
		_error_in_cmd = true;
		return false;
	    case COMPUTER_LIMITATION:
		err("rpn: acosh(),asinh(),atanh() not available on this machine");
		_error_in_cmd = true;
		return false;
	    case GENERAL_ERROR:
		err("rpn: general error");
		_error_in_cmd = true;
		return false;
	    }
	    // Everything is OK. Compute value, change it to, a character
	    // string, and put it as next word of sout. Then increment it to
	    // point to next word after the `END_MATH'.
	    strcat(sout, result);
	    delete [] result;	// was allocated in rpn function
	    strcat(sout, " ");
	    i = rpn_end;
	    found = true;
	} else {
	    strcat(sout, _Words2[i]);
	    strcat(sout, " ");
	}
    }
    return found;
}