Subversion Repositories filter_foundry

Rev

Rev 18 | Rev 71 | 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
2 toby 3
    Copyright (C) 2003-5 Toby Thain, toby@telegraphics.com.au
4
 
5
    This program is free software; you can redistribute it and/or modify
6
    it under the terms of the GNU General Public License as published by  
7
    the Free Software Foundation; either version 2 of the License, or
8
    (at your option) any later version.
9
 
10
    This program is distributed in the hope that it will be useful,
11
    but WITHOUT ANY WARRANTY; without even the implied warranty of
12
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13
    GNU General Public License for more details.
14
 
15
    You should have received a copy of the GNU General Public License  
16
    along with this program; if not, write to the Free Software
17
    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
18
*/
19
 
20
#include <stdlib.h>
21
#include <stdio.h>
22
#include <math.h>
23
 
24
// The following ugly workaround is obviated by Carbon StdCLib headers;
25
// see: http://developer.apple.com/tools/mpw-tools/relnotes/carbonstdclib.html
26
// (via http://developer.apple.com/tools/mpw-tools/updates.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(NEW(p)){
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(
62 toby 138
                                                                eval(root->child[0]),
139
                                                                eval(root->child[1]) );
2 toby 140
                case TOK_FN3: return root->v.sym->fn(
62 toby 141
                                                                eval(root->child[0]),
142
                                                                eval(root->child[1]),
143
                                                                eval(root->child[2]) );
2 toby 144
                case TOK_FN4: return root->v.sym->fn(
62 toby 145
                                                                eval(root->child[0]),
146
                                                                eval(root->child[1]),
147
                                                                eval(root->child[2]),
148
                                                                eval(root->child[3]) );
2 toby 149
                case TOK_FN5: return root->v.sym->fn(
62 toby 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]) );
2 toby 155
                case TOK_FN10: return root->v.sym->fn(
62 toby 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]) );
2 toby 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 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
        return 0.;
198
}
199
 
200
/* free the memory for a tree's nodes */
201
 
202
void freetree(struct node *root){
203
        int i;
204
 
205
        if(root){
206
                for( i = 0 ; i < MAXCHILDREN ; ++i )
207
                        freetree(root->child[i]);
208
                free(root);
209
        }
210
}
211
 
212
/* tabulate usage of special variables, or any invocations of src()/rad()/cnv(), in the tree */
213
 
214
void checkvars(struct node*p,int f[],int *srcrad /* ,int *mapused */ ){
215
        int i;
216
 
217
        if(p){
218
                if(p->kind==TOK_SPECIALVAR)
219
                        f[p->v.specialvar] = 1;
220
                else if( (p->kind==TOK_FN3 && (p->v.sym->fn == (pfunc_type)ff_src || p->v.sym->fn == (pfunc_type)ff_rad ) )
62 toby 221
                          || (p->kind==TOK_FN10 && p->v.sym->fn == (pfunc_type)ff_cnv) )
2 toby 222
                        *srcrad = 1;
223
//              else if(p->kind==TOK_FN2 && (p->v.sym->fn == (pfunc_type)ff_map))
224
//                      *mapused = 1;
225
                for( i = 0 ; i < MAXCHILDREN ; ++i )
226
                        checkvars(p->child[i],f,srcrad);
227
        }
228
}