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