merge the formfield patch from ooo-build
[ooovba.git] / filter / source / xsltfilter / fla.cxx
blob93b0213c7619d59e7e361aa15f4b63065f5719c3
1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: fla.cxx,v $
10 * $Revision: 1.8 $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 // MARKER(update_precomp.py): autogen include statement, do not remove
32 #include "precompiled_filter.hxx"
35 This file include an implementation of FLA - a simple Funtional Language for Attributes.
36 The language is LISP-like and has the following grammar:
37 FLA_Expression ::= '(' FLA_Operation FLA_Attribute+ ')'
38 FLA_Attribtute ::= FLA_Constant | FLA_Expression
39 FLA_Constant ::= '[' String ']'
40 The language currently supports the following operations:
41 "+"-Operation, e.g. (+[1][2]) = [3]
42 "-"-Operation, e.g. (-[3][2]) = [1]
43 "*"-Operation, e.g. (*[3][2]) = [6]
44 "/"-Operation, e.g. (-[6][2]) = [3]
45 "<"-Operation, e.g. (<[3][4]) = [t] resp. (<[4][3]) = []
46 "<="-Operation, e.g. (<=[3][4]) = [t] resp. (<=[4][3]) = []
47 ">"-Operation, e.g. (>[3][4]) = [] resp. (>[4][3]) = [t]
48 ">="-Operation, e.g. (>=[3][4]) = [] resp. (>=[4][3]) = [t]
49 Variable assignment, e.g. ($var1[4])
50 Variable access, e.g. (+($var1[4])($var1)($var1)) = [8]
51 Condition, e.g. (?[t][3][4])=[3] resp. (?[][3][4])=4
52 Priorized Choice, e.g. (|[4][5])=[4] resp. (|[][5])=[5]; i.e. result is the first occurrence of a non-[].
55 #include "fla.hxx"
56 #include "sal/main.h"
59 namespace FLA {
62 sal_Int32 Evaluator::evalFunc(const sal_Unicode*op, sal_Int32 opLen, sal_Int32 args, sal_Unicode* argv[10], sal_Unicode *result)
64 if (opLen==1 && op[0]==L'+')
66 double res=0;
67 for(sal_Int32 i=0;i<args;i++)
69 double v=rtl_ustr_toDouble(argv[i]);
70 res+=v;
72 return rtl_ustr_valueOfDouble(result, res);
74 else if (opLen==1 && op[0]==L'-' && args>0)
76 double res=rtl_ustr_toDouble(argv[0]);
77 for(sal_Int32 i=1;i<args;i++)
79 double v=rtl_ustr_toDouble(argv[i]);
80 res-=v;
82 sal_Int32 _len= rtl_ustr_valueOfDouble(result, res);
83 return _len;
85 else if (opLen==1 && op[0]==L'*')
87 double res=1;
88 for(sal_Int32 i=0;i<args;i++)
90 double v=rtl_ustr_toDouble(argv[i]);
91 res*=v;
93 return rtl_ustr_valueOfDouble(result, res);
95 else if (opLen==1 && op[0]==L'/' && args>0)
97 double res=rtl_ustr_toDouble(argv[0]);
98 for(sal_Int32 i=1;i<args;i++)
100 double v=rtl_ustr_toDouble(argv[i]);
101 res/=v;
103 return rtl_ustr_valueOfDouble(result, res);
105 else if (opLen==1 && op[0]==L'>' && args==2)
107 double p1=rtl_ustr_toDouble(argv[0]);
108 double p2=rtl_ustr_toDouble(argv[1]);
109 if (p1>p2)
111 result[0]=L't';
112 return 1;
114 else
116 return 0;
119 else if (opLen==1 && op[0]==L'<' && args==2)
121 double p1=rtl_ustr_toDouble(argv[0]);
122 double p2=rtl_ustr_toDouble(argv[1]);
123 if (p1<p2)
125 result[0]=L't';
126 return 1;
128 else
130 return 0;
133 else if (opLen==2 && op[0]==L'<' && op[1]==L'=' && args==2)
135 double p1=rtl_ustr_toDouble(argv[0]);
136 double p2=rtl_ustr_toDouble(argv[1]);
137 if (p1<=p2)
139 result[0]=L't';
140 return 1;
142 else
144 return 0;
147 else if (opLen==2 && op[0]==L'>' && op[1]==L'=' && args==2)
149 double p1=rtl_ustr_toDouble(argv[0]);
150 double p2=rtl_ustr_toDouble(argv[1]);
151 if (p1>=p2)
153 result[0]=L't';
154 return 1;
156 else
158 return 0;
161 else if (opLen>1 && op[0]==L'$' && args==0)
163 sal_Int32 reg=rtl_ustr_toInt32(op+1, 10);
164 int i=0; while(i<99 && environment[reg][i]!=L'\0') { result[i]=environment[reg][i]; i++; }
165 result[i]=0;
166 return i;
168 else if (opLen>1 && op[0]==L'$' && args==1)
170 sal_Int32 reg=rtl_ustr_toInt32(op+1, 10);
171 int i=0; while(i<99 && argv[0]!=NULL) { result[i]=argv[0][i]; environment[reg][i]=argv[0][i]; i++; }
172 environment[reg][i]=0; result[i]=0;
173 return i;
175 else if (opLen==1 && op[0]==L'?' && args==3)
177 sal_Unicode *source;
178 if (argv[0][0]==L'\0')
180 source=argv[2];
182 else
184 source=argv[1];
186 int len=0; while (*source!=L'\0') result[len++]=*source++;
187 result[len]=0;
188 return len;
190 else if (opLen==1 && op[0]==L'|' && args>0)
192 sal_Unicode *source;
193 int i=0; while (i<args && argv[i][0]==L'\0') i++;
194 if (i<args)
196 source=argv[i];
197 int len=0; while (*source!=L'\0') result[len++]=*source++;
198 result[len]=0;
199 return len;
201 else
203 result[0]=0;
204 return 0;
207 else if (opLen==1 && op[0]==L'.' && args>0)
209 sal_Unicode *source;
210 int len=0;
211 for(sal_Int32 i=0;i<args;i++)
213 source=argv[i];
214 while (*source!=L'\0') result[len++]=*source++;
216 result[len]=0;
217 return len;
219 else if (opLen==8 && op[0]=='t' && op[1]=='w' && op[2]=='i' && op[3]=='p' && op[4]=='s' && op[5]=='2' && op[6]=='c' && op[7]=='m' && args==1)
221 double v=rtl_ustr_toDouble(argv[0]);
222 return rtl_ustr_valueOfDouble(result, (v/567.0));
224 else if (opLen==6 && op[0]=='s' && op[1]=='w' && op[2]=='i' && op[3]=='t' && op[4]=='c' && op[5]=='h' && args>2)
226 sal_Unicode *source;
227 for(int i=1;i<args-1;i+=2)
229 if (rtl_ustr_compare(argv[0], argv[i])==0)
231 source=argv[i+1]; int len=0; while (*source!=L'\0') result[len++]=*source++;
232 result[len]=0;
233 return len;
236 source=argv[args-1]; int len=0; while (*source!=L'\0') result[len++]=*source++;
237 result[len]=0;
238 return len;
239 // double v=rtl_ustr_toDouble(argv[0]);
240 // return rtl_ustr_valueOfDouble(result, (v/567.0L));
242 else
244 return 0;
249 sal_Int32 Evaluator::evalExp(const sal_Unicode *expr, sal_Int32 exprLen, sal_Unicode *buf, sal_Int32 *bufLen)
251 sal_Unicode ch;
252 sal_Unicode* argv[10];
253 sal_Int32 args=0;
254 int offset=0; while(offset<exprLen && expr[offset]==' ') offset++;
255 sal_Int32 startBuf=*bufLen;
256 if(expr[offset]==L'(')
258 offset++;
259 while(offset<exprLen && expr[offset]==' ') offset++;
260 int op=offset;
261 while(offset<exprLen && expr[offset]!=' ' && expr[offset]!='[' && expr[offset]!='('&& expr[offset]!=']' && expr[offset]!=')') offset++;
262 int opLen=offset-op;
263 bool done=false;
264 while(offset<exprLen && !done)
266 switch(expr[offset])
268 case '(':
269 case '[':
270 argv[args++]=buf+*bufLen;
271 offset+=evalExp(expr+offset, exprLen, buf, bufLen);
272 buf[(*bufLen)++]=0;
273 break;
274 case ')':
275 offset++;
276 done=true;
277 break;
278 case ' ': /* skip */
279 offset++;
280 break;
281 default: /* skip */
282 offset++;
283 break;
286 if (done)
288 sal_Int32 len=evalFunc(expr+op, opLen, args, argv, buf+startBuf);
289 *bufLen=startBuf+len;
293 else if(expr[offset]==L'[')
295 offset++;
296 argv[args++]=buf+*bufLen;
297 while (offset<exprLen && (ch=expr[offset++])!=']')
299 buf[(*bufLen)++]=ch;
301 buf[(*bufLen)++]=0;
303 return offset;
306 const sal_Unicode *Evaluator::eval(const sal_Unicode *expr, sal_Int32 exprLen)
309 sal_Int32 len=0;
310 evalExp(expr, exprLen, _buf, &len);
311 OSL_ASSERT(len<1024);
312 return _buf;
318 SAL_IMPLEMENT_MAIN_WITH_ARGS(argc, argv)
320 FLA::Evaluator ev;
321 for(int i=1;i<argc;i++)
323 rtl_uString *param=NULL;
324 rtl_uString_newFromAscii(&param, argv[i]);
325 ::rtl::OUString _param(param);
326 const sal_Unicode *res=ev.eval(_param.getStr(), _param.getLength());
328 return 0;