Subversion Repositories filter_foundry

Rev

Rev 237 | Rev 268 | Go to most recent revision | 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
3
    Copyright (C) 2003-2009 Toby Thain, toby@telegraphics.com.au
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))) ){
51
#ifdef DEBUG
52
//              fprintf(stderr,"NEW(%#x)\n",p);
53
                ++allocs;
54
#endif
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);
71
#ifdef DEBUG
72
//              fprintf(stderr,"FREE(%#x)\n",p);
73
                --allocs;
74
#endif
75
        }
76
}
77
void freeallnodes(){
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:
95
#ifdef FP_VALUE
96
                                printf("constant: %g\n",root->v.value);
97
#else
98
                                printf("constant: %ld\n",root->v.value);
99
#endif
100
                                break;
101
                        case TOK_SPECIALVAR:
102
                                printf("special variable: %c\n",root->v.specialvar);
103
                                break;
104
                        case TOK_VAR:
105
#ifdef FP_VALUE
106
                                printf("variable: %s (%g)\n",root->v.sym->name,*root->v.sym->pvar);
107
#else
108
                                printf("variable: %s (%ld)\n",root->v.sym->name,*root->v.sym->pvar);
109
#endif
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(
138
                                                                eval(root->child[0]),
139
                                                                eval(root->child[1]) );
140
                case TOK_FN3: return root->v.sym->fn(
141
                                                                eval(root->child[0]),
142
                                                                eval(root->child[1]),
143
                                                                eval(root->child[2]) );
144
                case TOK_FN4: return root->v.sym->fn(
145
                                                                eval(root->child[0]),
146
                                                                eval(root->child[1]),
147
                                                                eval(root->child[2]),
148
                                                                eval(root->child[3]) );
149
                case TOK_FN5: return root->v.sym->fn(
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]) );
155
                case TOK_FN10: return root->v.sym->fn(
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]) );
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;
201
#endif
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) ||
231
                         (p->kind==TOK_FN1 && p->v.sym->fn == (pfunc_type)ff_rnd) ||
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
}