Rev 532 | Details | Compare with Previous | Last modification | View Log | RSS feed
Rev | Author | Line No. | Line |
---|---|---|---|
259 | daniel-mar | 1 | /* |
2 | This file is part of "Filter Foundry", a filter plugin for Adobe Photoshop |
||
536 | daniel-mar | 3 | Copyright (C) 2003-2009 Toby Thain, toby@telegraphics.net |
259 | daniel-mar | 4 | Copyright (C) 2018-2021 Daniel Marschall, ViaThinkSoft |
5 | |||
6 | This program is free software; you can redistribute it and/or modify |
||
7 | it under the terms of the GNU General Public License as published by |
||
8 | the Free Software Foundation; either version 2 of the License, or |
||
9 | (at your option) any later version. |
||
10 | |||
11 | This program is distributed in the hope that it will be useful, |
||
12 | but WITHOUT ANY WARRANTY; without even the implied warranty of |
||
13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
||
14 | GNU General Public License for more details. |
||
15 | |||
16 | You should have received a copy of the GNU General Public License |
||
17 | along with this program; if not, write to the Free Software |
||
18 | Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
||
19 | */ |
||
20 | |||
21 | #include <stdlib.h> |
||
22 | #include <stdio.h> |
||
23 | #include <math.h> |
||
24 | |||
25 | // The following ugly workaround is obviated by Carbon StdCLib headers; |
||
26 | // see: https://web.archive.org/web/20041031134219/http://developer.apple.com/tools/mpw-tools/relnotes/carbonstdclib.html |
||
27 | |||
28 | //#ifdef TARGET_API_MAC_CARBON |
||
29 | // /* can't use StdCLib ctype.h, it refers to symbols which aren't in OS X stdclib */ |
||
30 | // int isprint(int); |
||
31 | //#else |
||
32 | #include <ctype.h> |
||
33 | //#endif |
||
34 | |||
35 | #include "node.h" |
||
36 | #include "y.tab.h" |
||
37 | #include "funcs.h" |
||
38 | |||
39 | void freenodes(struct node *p); |
||
40 | |||
41 | int varused[0x100],allocs; /* one flag per special variable, indicating if it's used */ |
||
42 | value_type var[0x100]; |
||
43 | |||
44 | struct node *node_list; |
||
45 | |||
46 | struct node *newnode(int k){ |
||
47 | struct node *p; |
||
48 | int i; |
||
49 | |||
50 | if( (p = (struct node*)malloc(sizeof(struct node))) ){ |
||
268 | daniel-mar | 51 | #ifdef DEBUG |
52 | //fprintf(stderr,"NEW(%#x)\n",p); |
||
259 | daniel-mar | 53 | ++allocs; |
268 | daniel-mar | 54 | #endif |
259 | daniel-mar | 55 | p->kind = k; |
56 | for( i = 0 ; i < MAXCHILDREN ; ++i ) |
||
57 | p->child[i] = 0; |
||
58 | |||
59 | /* add this new node to the list of allocated nodes */ |
||
60 | p->next = node_list; |
||
61 | node_list = p; |
||
62 | } |
||
63 | return p; |
||
64 | } |
||
65 | |||
66 | void freenodes(struct node *p){ |
||
67 | /* undo recorded allocations */ |
||
68 | if(p){ |
||
69 | freenodes(p->next); |
||
70 | free(p); |
||
268 | daniel-mar | 71 | #ifdef DEBUG |
72 | //fprintf(stderr,"FREE(%#x)\n",p); |
||
259 | daniel-mar | 73 | --allocs; |
268 | daniel-mar | 74 | #endif |
259 | daniel-mar | 75 | } |
76 | } |
||
532 | daniel-mar | 77 | void freeallnodes(void){ |
259 | daniel-mar | 78 | freenodes(node_list); |
79 | node_list = 0; |
||
80 | } |
||
81 | |||
82 | /* pretty-print the tree */ |
||
83 | |||
84 | void dumptree(struct node *root,int level){ |
||
85 | int i; |
||
86 | |||
87 | if(level>20) |
||
88 | puts("## dumptree: sorry, not going deeper than this."); |
||
89 | else |
||
90 | if(root){ |
||
91 | for(i=level;i--;) |
||
92 | putchar('\t'); |
||
93 | switch(root->kind){ |
||
94 | case TOK_NUM: |
||
268 | daniel-mar | 95 | #ifdef FP_VALUE |
259 | daniel-mar | 96 | printf("constant: %g\n",root->v.value); |
268 | daniel-mar | 97 | #else |
301 | daniel-mar | 98 | printf("constant: %d\n",root->v.value); |
268 | daniel-mar | 99 | #endif |
259 | daniel-mar | 100 | break; |
101 | case TOK_SPECIALVAR: |
||
102 | printf("special variable: %c\n",root->v.specialvar); |
||
103 | break; |
||
104 | case TOK_VAR: |
||
268 | daniel-mar | 105 | #ifdef FP_VALUE |
259 | daniel-mar | 106 | printf("variable: %s (%g)\n",root->v.sym->name,*root->v.sym->pvar); |
268 | daniel-mar | 107 | #else |
301 | daniel-mar | 108 | printf("variable: %s (%d)\n",root->v.sym->name,*root->v.sym->pvar); |
268 | daniel-mar | 109 | #endif |
259 | daniel-mar | 110 | break; |
111 | case TOK_FN1: |
||
112 | case TOK_FN2: |
||
113 | case TOK_FN3: |
||
114 | printf("function: %s\n",root->v.sym->name); |
||
115 | break; |
||
116 | default: |
||
117 | printf(isprint(root->kind) ? "operator: %c\n" : "operator: %d\n",root->kind); |
||
118 | break; |
||
119 | } |
||
120 | ++level; |
||
121 | for( i = 0 ; i < MAXCHILDREN ; ++i ) |
||
122 | dumptree(root->child[i],level); |
||
123 | } |
||
124 | |||
125 | } |
||
126 | |||
127 | /* evaluate the expression tree (using current values of variables) */ |
||
128 | |||
129 | value_type eval(struct node *root){ |
||
130 | value_type t; |
||
131 | if(root){ |
||
132 | switch(root->kind){ |
||
133 | case TOK_NUM: return root->v.value; |
||
134 | case TOK_SPECIALVAR: return var[root->v.specialvar]; |
||
135 | case TOK_VAR: return *root->v.sym->pvar; |
||
136 | case TOK_FN1: return root->v.sym->fn(eval(root->child[0])); |
||
137 | case TOK_FN2: return root->v.sym->fn( |
||
268 | daniel-mar | 138 | eval(root->child[0]), |
139 | eval(root->child[1]) ); |
||
259 | daniel-mar | 140 | case TOK_FN3: return root->v.sym->fn( |
268 | daniel-mar | 141 | eval(root->child[0]), |
142 | eval(root->child[1]), |
||
143 | eval(root->child[2]) ); |
||
259 | daniel-mar | 144 | case TOK_FN4: return root->v.sym->fn( |
268 | daniel-mar | 145 | eval(root->child[0]), |
146 | eval(root->child[1]), |
||
147 | eval(root->child[2]), |
||
148 | eval(root->child[3]) ); |
||
259 | daniel-mar | 149 | case TOK_FN5: return root->v.sym->fn( |
268 | daniel-mar | 150 | eval(root->child[0]), |
151 | eval(root->child[1]), |
||
152 | eval(root->child[2]), |
||
153 | eval(root->child[3]), |
||
154 | eval(root->child[4]) ); |
||
259 | daniel-mar | 155 | case TOK_FN10: return root->v.sym->fn( |
268 | daniel-mar | 156 | eval(root->child[0]), |
157 | eval(root->child[1]), |
||
158 | eval(root->child[2]), |
||
159 | eval(root->child[3]), |
||
160 | eval(root->child[4]), |
||
161 | eval(root->child[5]), |
||
162 | eval(root->child[6]), |
||
163 | eval(root->child[7]), |
||
164 | eval(root->child[8]), |
||
165 | eval(root->child[9]) ); |
||
259 | daniel-mar | 166 | |
167 | case '+': return eval(root->child[0]) + eval(root->child[1]); |
||
168 | case '-': return eval(root->child[0]) - eval(root->child[1]); |
||
169 | case '*': return eval(root->child[0]) * eval(root->child[1]); |
||
170 | case '/': t = eval(root->child[1]); return t ? eval(root->child[0]) / t : 0; |
||
171 | case '%': t = eval(root->child[1]); return t ? eval(root->child[0]) % t : 0; |
||
172 | case EXP: return (value_type)(pow(eval(root->child[0]), eval(root->child[1]))); |
||
173 | |||
174 | case EQ: return eval(root->child[0]) == eval(root->child[1]); |
||
175 | case NE: return eval(root->child[0]) != eval(root->child[1]); |
||
176 | case '<': return eval(root->child[0]) < eval(root->child[1]); |
||
177 | case LE: return eval(root->child[0]) <= eval(root->child[1]); |
||
178 | case '>': return eval(root->child[0]) > eval(root->child[1]); |
||
179 | case GE: return eval(root->child[0]) >= eval(root->child[1]); |
||
180 | |||
181 | case LOGAND: return eval(root->child[0]) && eval(root->child[1]); |
||
182 | case LOGOR: return eval(root->child[0]) || eval(root->child[1]); |
||
183 | case '!': return !eval(root->child[0]); |
||
184 | |||
185 | case '?': return eval(root->child[0]) ? eval(root->child[1]) : eval(root->child[2]); |
||
186 | |||
187 | case '&': return eval(root->child[0]) & eval(root->child[1]); |
||
188 | case '^': return eval(root->child[0]) ^ eval(root->child[1]); |
||
189 | case '|': return eval(root->child[0]) | eval(root->child[1]); |
||
190 | case SHLEFT: return eval(root->child[0]) << eval(root->child[1]); |
||
191 | case SHRIGHT: return eval(root->child[0]) >> eval(root->child[1]); |
||
192 | case '~': return ~eval(root->child[0]); |
||
193 | |||
194 | case ',': eval(root->child[0]); return eval(root->child[1]); |
||
195 | } |
||
196 | } |
||
197 | #ifdef FP_VALUE |
||
198 | return 0.; |
||
199 | #else |
||
200 | return 0; |
||
268 | daniel-mar | 201 | #endif |
259 | daniel-mar | 202 | } |
203 | |||
204 | /* free the memory for a tree's nodes */ |
||
205 | |||
206 | void freetree(struct node *root){ |
||
207 | int i; |
||
208 | |||
209 | if(root){ |
||
210 | for( i = 0 ; i < MAXCHILDREN ; ++i ) |
||
211 | freetree(root->child[i]); |
||
212 | free(root); |
||
213 | } |
||
214 | } |
||
215 | |||
216 | /* tabulate usage of special variables, or any invocations of src()/rad()/cnv(), in the tree */ |
||
217 | |||
218 | void checkvars(struct node*p,int f[],int *cnv,int *srcrad /* ,int *mapused */, int *state_changing_funcs_used ){ |
||
219 | int i; |
||
220 | |||
221 | if(p){ |
||
222 | if(p->kind==TOK_SPECIALVAR) |
||
223 | f[p->v.specialvar] = 1; |
||
224 | else if(p->kind==TOK_FN3 && (p->v.sym->fn == (pfunc_type)ff_src || p->v.sym->fn == (pfunc_type)ff_rad)) |
||
225 | *srcrad = 1; |
||
226 | else if(p->kind==TOK_FN10 && p->v.sym->fn == (pfunc_type)ff_cnv) |
||
227 | *cnv = 1; |
||
228 | // else if(p->kind==TOK_FN2 && (p->v.sym->fn == (pfunc_type)ff_map)) |
||
229 | // *mapused = 1; |
||
230 | else if ((p->kind==TOK_FN2 && p->v.sym->fn == (pfunc_type)ff_put) || |
||
288 | daniel-mar | 231 | (p->kind==TOK_FN2 && p->v.sym->fn == (pfunc_type)ff_rnd) || |
259 | daniel-mar | 232 | (p->kind==TOK_FN1 && p->v.sym->fn == (pfunc_type)ff_rst)) |
233 | *state_changing_funcs_used = 1; |
||
234 | for( i = 0 ; i < MAXCHILDREN ; ++i ) |
||
235 | checkvars(p->child[i],f,cnv,srcrad/*,mapused*/,state_changing_funcs_used); |
||
236 | } |
||
237 | } |