Subversion Repositories filter_foundry

Rev

Rev 185 | Rev 198 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed

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