~clint-fewbar/ubuntu/precise/squid3/ignore-sighup-early

« back to all changes in this revision

Viewing changes to src/esi/Expression.cc

  • Committer: Bazaar Package Importer
  • Author(s): Luigi Gangitano
  • Date: 2010-05-04 11:15:49 UTC
  • mfrom: (1.3.1 upstream)
  • mto: (20.3.1 squeeze) (21.2.1 sid)
  • mto: This revision was merged to the branch mainline in revision 21.
  • Revision ID: james.westby@ubuntu.com-20100504111549-1apjh2g5sndki4te
Tags: upstream-3.1.3
ImportĀ upstreamĀ versionĀ 3.1.3

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
 
 
2
/*
 
3
 * $Id$
 
4
 *
 
5
 * DEBUG: section 86    ESI processing
 
6
 * AUTHOR: Robert Collins
 
7
 *
 
8
 * SQUID Web Proxy Cache          http://www.squid-cache.org/
 
9
 * ----------------------------------------------------------
 
10
 *
 
11
 *  Squid is the result of efforts by numerous individuals from
 
12
 *  the Internet community; see the CONTRIBUTORS file for full
 
13
 *  details.   Many organizations have provided support for Squid's
 
14
 *  development; see the SPONSORS file for full details.  Squid is
 
15
 *  Copyrighted (C) 2001 by the Regents of the University of
 
16
 *  California; see the COPYRIGHT file for full details.  Squid
 
17
 *  incorporates software developed and/or copyrighted by other
 
18
 *  sources; see the CREDITS file for full details.
 
19
 *
 
20
 *  This program is free software; you can redistribute it and/or modify
 
21
 *  it under the terms of the GNU General Public License as published by
 
22
 *  the Free Software Foundation; either version 2 of the License, or
 
23
 *  (at your option) any later version.
 
24
 *
 
25
 *  This program is distributed in the hope that it will be useful,
 
26
 ;  but WITHOUT ANY WARRANTY; without even the implied warranty of
 
27
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
28
 *  GNU General Public License for more details.
 
29
 *
 
30
 *  You should have received a copy of the GNU General Public License
 
31
 *  along with this program; if not, write to the Free Software
 
32
 *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111, USA.
 
33
 *
 
34
 */
 
35
 
 
36
#include "squid.h"
 
37
#include "esi/Expression.h"
 
38
 
 
39
/* stack precedence rules:
 
40
 * before pushing an operator onto the stack, the
 
41
 * top 2 elements are checked. if either has a higher
 
42
 * or equal precedence than the current operator, they
 
43
 * are evaluated.
 
44
 * Start of expression has 5 precedence,
 
45
 * end of expression has 0 precedence
 
46
 * literal has 1 as does expression results
 
47
 * | has 2
 
48
 * & has 3
 
49
 * ! has 4
 
50
 * == != < > <= >= has 5
 
51
 * ( has 5
 
52
 * ) has 0
 
53
 */
 
54
 
 
55
typedef struct _stackmember stackmember;
 
56
 
 
57
typedef int evaluate (stackmember * stack, int *depth, int whereAmI,
 
58
                      stackmember * candidate);
 
59
 
 
60
typedef enum {
 
61
    ESI_EXPR_INVALID,
 
62
    ESI_EXPR_LITERAL,
 
63
    ESI_EXPR_OR,
 
64
    ESI_EXPR_AND,
 
65
    ESI_EXPR_NOT,
 
66
    ESI_EXPR_START,
 
67
    ESI_EXPR_END,
 
68
    ESI_EXPR_EQ,
 
69
    ESI_EXPR_NOTEQ,
 
70
    ESI_EXPR_LESS,
 
71
    ESI_EXPR_LESSEQ,
 
72
    ESI_EXPR_MORE,
 
73
    ESI_EXPR_MOREEQ,
 
74
    ESI_EXPR_EXPR                       /* the result of an expr PRI 1 */
 
75
} evaltype;
 
76
 
 
77
typedef enum {
 
78
    ESI_LITERAL_STRING,
 
79
    ESI_LITERAL_FLOAT,
 
80
    ESI_LITERAL_INT,
 
81
    ESI_LITERAL_BOOL,
 
82
    ESI_LITERAL_INVALID
 
83
} literalhint;
 
84
 
 
85
struct _stackmember {
 
86
    evaluate *eval;
 
87
    union {
 
88
        char *string;
 
89
        double floating;
 
90
        int integral;
 
91
    } value;
 
92
    literalhint valuestored;
 
93
    evaltype valuetype;
 
94
    int precedence;
 
95
};
 
96
 
 
97
static void cleanmember (stackmember *);
 
98
static void stackpop (stackmember * s, int *depth);
 
99
 
 
100
void
 
101
cleanmember (stackmember * s)
 
102
{
 
103
    if (s->valuetype == ESI_EXPR_LITERAL
 
104
            && s->valuestored == ESI_LITERAL_STRING) {
 
105
        safe_free (s->value.string);
 
106
        s->value.string = NULL;
 
107
    }
 
108
 
 
109
}
 
110
 
 
111
void
 
112
stackpop (stackmember * s, int *depth)
 
113
{
 
114
    if (!(*depth)--)
 
115
        return;
 
116
 
 
117
    cleanmember (&s[*depth]);
 
118
}
 
119
 
 
120
static evaluate evalnegate;
 
121
static evaluate evalliteral;
 
122
static evaluate evalor;
 
123
static evaluate evaland;
 
124
static evaluate evallesseq;
 
125
static evaluate evallessthan;
 
126
static evaluate evalmoreeq;
 
127
static evaluate evalmorethan;
 
128
static evaluate evalequals;
 
129
static evaluate evalnotequals;
 
130
static evaluate evalstartexpr;
 
131
static evaluate evalendexpr;
 
132
static evaluate evalexpr;
 
133
static void dumpstack (stackmember * stack, int depth);
 
134
static int addmember (stackmember * stack, int *stackdepth,
 
135
                      stackmember * candidate);
 
136
static int membercompare (stackmember a, stackmember b);
 
137
static char const *trim (char const *s);
 
138
static stackmember getsymbol (const char *s, char const **endptr);
 
139
static void printliteral (stackmember s);
 
140
static void printmember (stackmember s);
 
141
 
 
142
/* -2 = failed to compate
 
143
 * -1 = a less than b
 
144
 * 0 = a equal b
 
145
 * 2 - a more than b
 
146
 */
 
147
int
 
148
membercompare (stackmember a, stackmember b)
 
149
{
 
150
    /* we can compare: sub expressions to sub expressions ,
 
151
     * literals to literals
 
152
     */
 
153
 
 
154
    if (!((a.valuetype == ESI_EXPR_LITERAL && b.valuetype == ESI_EXPR_LITERAL &&
 
155
            a.valuestored != ESI_LITERAL_INVALID && b.valuestored != ESI_LITERAL_INVALID) ||
 
156
            (a.valuetype == ESI_EXPR_EXPR && b.valuetype == ESI_EXPR_EXPR)))
 
157
        return -2;
 
158
 
 
159
    if (a.valuetype == ESI_EXPR_EXPR) {
 
160
        if (a.value.integral == b.value.integral)
 
161
            return 0;
 
162
        else
 
163
            return 1;
 
164
    } else if (a.valuestored == ESI_LITERAL_STRING) {
 
165
        if (b.valuestored == ESI_LITERAL_STRING) {
 
166
            int i =strcmp (a.value.string, b.value.string);
 
167
 
 
168
            if (i < 0)
 
169
                return -1;
 
170
 
 
171
            if (i > 0)
 
172
                return 1;
 
173
 
 
174
            return 0;
 
175
        } else {
 
176
            /* TODO: numeric to string conversion ? */
 
177
            debugs(86, 1, "strcmp with non-string");
 
178
            return -2;
 
179
        }
 
180
    } else if (a.valuestored == ESI_LITERAL_FLOAT) {
 
181
        if (b.valuestored == ESI_LITERAL_INT) {
 
182
            if (fabs(a.value.floating - b.value.integral) < 0.00001)
 
183
                return 0;
 
184
            else if (a.value.floating < b.value.integral)
 
185
                return -1;
 
186
            else
 
187
                return 1;
 
188
        } else if (b.valuestored == ESI_LITERAL_FLOAT) {
 
189
            if (a.value.floating == b.value.floating)
 
190
                return 0;
 
191
            else if (a.value.floating < b.value.floating)
 
192
                return -1;
 
193
            else
 
194
                return 1;
 
195
        } else {
 
196
            /* TODO: attempt numeric converson again? */
 
197
            debugs(86, 1, "floatcomp with non float or int");
 
198
            return -2;
 
199
        }
 
200
    } else if (a.valuestored == ESI_LITERAL_INT) {
 
201
        if (b.valuestored == ESI_LITERAL_INT) {
 
202
            if (a.value.integral == b.value.integral)
 
203
                return 0;
 
204
            else if (a.value.integral < b.value.integral)
 
205
                return -1;
 
206
            else
 
207
                return 1;
 
208
        } else if (b.valuestored == ESI_LITERAL_FLOAT) {
 
209
            if (fabs(a.value.integral - b.value.floating) < 0.00001)
 
210
                return 0;
 
211
            else if (a.value.integral < b.value.floating)
 
212
                return -1;
 
213
            else
 
214
                return 1;
 
215
        } else {
 
216
            /* TODO: attempt numeric converson again? */
 
217
            debugs(86, 1, "intcomp vs non float non int");
 
218
            return -2;
 
219
        }
 
220
    }
 
221
 
 
222
    return -2;
 
223
}
 
224
 
 
225
/* return 0 on success, 1 on failure */
 
226
int evalnegate
 
227
(stackmember * stack, int *depth, int whereAmI, stackmember * candidate)
 
228
{
 
229
    if (whereAmI != *depth - 2)
 
230
        /* invalid stack */
 
231
        return 1;
 
232
 
 
233
    if (stack[whereAmI + 1].valuetype != ESI_EXPR_EXPR)
 
234
        /* invalid operand */
 
235
        return 1;
 
236
 
 
237
    /* copy down */
 
238
    --(*depth);
 
239
 
 
240
    stack[whereAmI] = stack[(*depth)];
 
241
 
 
242
    cleanmember (candidate);
 
243
 
 
244
    if (stack[whereAmI].value.integral == 1)
 
245
        stack[whereAmI].value.integral = 0;
 
246
    else
 
247
        stack[whereAmI].value.integral = 1;
 
248
 
 
249
    return 0;
 
250
}
 
251
 
 
252
int evalliteral
 
253
(stackmember * stack, int *depth, int whereAmI, stackmember * candidate)
 
254
{
 
255
    debugs(86, 1, "attempt to evaluate a literal");
 
256
    /* literals can't be evaluated */
 
257
    return 1;
 
258
}
 
259
 
 
260
int evalexpr
 
261
(stackmember * stack, int *depth, int whereAmI, stackmember * candidate)
 
262
{
 
263
    debugs(86, 1, "attempt to evaluate a sub-expression result");
 
264
    /* sub-scpr's can't be evaluated */
 
265
    return 1;
 
266
}
 
267
 
 
268
 
 
269
int evalor
 
270
(stackmember * stack, int *depth, int whereAmI, stackmember * candidate)
 
271
{
 
272
    int rv;
 
273
    stackmember srv;
 
274
 
 
275
    if (*depth < 3)
 
276
        /* Not enough operands */
 
277
        return 1;
 
278
 
 
279
    if (whereAmI != *depth - 2)
 
280
        /* invalid stack */
 
281
        return 1;
 
282
 
 
283
    if (stack[whereAmI + 1].valuetype != ESI_EXPR_EXPR ||
 
284
            stack[whereAmI - 1].valuetype != ESI_EXPR_EXPR)
 
285
        /* invalid operand */
 
286
        return 1;
 
287
 
 
288
    rv = stack[whereAmI - 1].value.integral || stack[whereAmI + 1].value.integral;
 
289
 
 
290
    if (rv == -2)
 
291
        /* invalid comparison */
 
292
        return 1;
 
293
 
 
294
    stackpop (stack, depth);      /* arg rhs */
 
295
 
 
296
    stackpop (stack, depth);      /* me */
 
297
 
 
298
    stackpop (stack, depth);      /* arg lhs */
 
299
 
 
300
    srv.valuetype = ESI_EXPR_EXPR;
 
301
 
 
302
    srv.eval = evalliteral;
 
303
 
 
304
    srv.valuestored = ESI_LITERAL_BOOL;
 
305
 
 
306
    srv.value.integral = rv ? 1 : 0;
 
307
 
 
308
    srv.precedence = 1;
 
309
 
 
310
    stack[(*depth)++] = srv;
 
311
 
 
312
    /* we're out of way, try adding now */
 
313
    if (!addmember (stack, depth, candidate))
 
314
        /* Something wrong upstream */
 
315
        return 1;
 
316
 
 
317
    return 0;
 
318
}
 
319
 
 
320
int evaland
 
321
(stackmember * stack, int *depth, int whereAmI, stackmember * candidate)
 
322
{
 
323
    int rv;
 
324
    stackmember srv;
 
325
 
 
326
    if (*depth < 3)
 
327
        /* Not enough operands */
 
328
        return 1;
 
329
 
 
330
    if (whereAmI != *depth - 2)
 
331
        /* invalid stack */
 
332
        return 1;
 
333
 
 
334
    if (stack[whereAmI + 1].valuetype != ESI_EXPR_EXPR ||
 
335
            stack[whereAmI - 1].valuetype != ESI_EXPR_EXPR)
 
336
        /* invalid operand */
 
337
        return 1;
 
338
 
 
339
    rv = stack[whereAmI - 1].value.integral && stack[whereAmI + 1].value.integral;
 
340
 
 
341
    if (rv == -2)
 
342
        /* invalid comparison */
 
343
        return 1;
 
344
 
 
345
    stackpop (stack, depth);      /* arg rhs */
 
346
 
 
347
    stackpop (stack, depth);      /* me */
 
348
 
 
349
    stackpop (stack, depth);      /* arg lhs */
 
350
 
 
351
    srv.valuetype = ESI_EXPR_EXPR;
 
352
 
 
353
    srv.eval = evalexpr;
 
354
 
 
355
    srv.valuestored = ESI_LITERAL_BOOL;
 
356
 
 
357
    srv.value.integral = rv ? 1 : 0;
 
358
 
 
359
    srv.precedence = 1;
 
360
 
 
361
    stack[(*depth)++] = srv;
 
362
 
 
363
    /* we're out of way, try adding now */
 
364
    if (!addmember (stack, depth, candidate))
 
365
        /* Something wrong upstream */
 
366
        return 1;
 
367
 
 
368
    return 0;
 
369
}
 
370
 
 
371
int evallesseq
 
372
(stackmember * stack, int *depth, int whereAmI, stackmember * candidate)
 
373
{
 
374
    int rv;
 
375
    stackmember srv;
 
376
 
 
377
    if (*depth < 3)
 
378
        /* Not enough operands */
 
379
        return 1;
 
380
 
 
381
    if (whereAmI != *depth - 2)
 
382
        /* invalid stack */
 
383
        return 1;
 
384
 
 
385
    rv = membercompare (stack[whereAmI - 1], stack[whereAmI + 1]);
 
386
 
 
387
    if (rv == -2)
 
388
        /* invalid comparison */
 
389
        return 1;
 
390
 
 
391
    stackpop (stack, depth);      /* arg rhs */
 
392
 
 
393
    stackpop (stack, depth);      /* me */
 
394
 
 
395
    stackpop (stack, depth);      /* arg lhs */
 
396
 
 
397
    srv.valuetype = ESI_EXPR_EXPR;
 
398
 
 
399
    srv.eval = evalexpr;
 
400
 
 
401
    srv.valuestored = ESI_LITERAL_BOOL;
 
402
 
 
403
    srv.value.integral = rv <= 0 ? 1 : 0;
 
404
 
 
405
    srv.precedence = 1;
 
406
 
 
407
    stack[(*depth)++] = srv;
 
408
 
 
409
    /* we're out of way, try adding now */
 
410
    if (!addmember (stack, depth, candidate))
 
411
        /* Something wrong upstream */
 
412
        return 1;
 
413
 
 
414
    /*  debugs(86, 1, "?= " << srv.value.integral << " "); */
 
415
    return 0;
 
416
 
 
417
 
 
418
}
 
419
 
 
420
int evallessthan
 
421
(stackmember * stack, int *depth, int whereAmI, stackmember * candidate)
 
422
{
 
423
    int rv;
 
424
    stackmember srv;
 
425
 
 
426
    if (*depth < 3)
 
427
        /* Not enough operands */
 
428
        return 1;
 
429
 
 
430
    if (whereAmI != *depth - 2)
 
431
        /* invalid stack */
 
432
        return 1;
 
433
 
 
434
    rv = membercompare (stack[whereAmI - 1], stack[whereAmI + 1]);
 
435
 
 
436
    if (rv == -2)
 
437
        /* invalid comparison */
 
438
        return 1;
 
439
 
 
440
    stackpop (stack, depth);      /* arg rhs */
 
441
 
 
442
    stackpop (stack, depth);      /* me */
 
443
 
 
444
    stackpop (stack, depth);      /* arg lhs */
 
445
 
 
446
    srv.valuetype = ESI_EXPR_EXPR;
 
447
 
 
448
    srv.eval = evalexpr;
 
449
 
 
450
    srv.valuestored = ESI_LITERAL_BOOL;
 
451
 
 
452
    srv.value.integral = rv < 0 ? 1 : 0;
 
453
 
 
454
    srv.precedence = 1;
 
455
 
 
456
    stack[(*depth)++] = srv;
 
457
 
 
458
    /* we're out of way, try adding now */
 
459
    if (!addmember (stack, depth, candidate))
 
460
        /* Something wrong upstream */
 
461
        return 1;
 
462
 
 
463
    /* debugs(86, 1, "?= " << srv.value.integral << " "); */
 
464
    return 0;
 
465
 
 
466
 
 
467
}
 
468
 
 
469
int evalmoreeq
 
470
(stackmember * stack, int *depth, int whereAmI, stackmember * candidate)
 
471
{
 
472
    int rv;
 
473
    stackmember srv;
 
474
 
 
475
    if (*depth < 3)
 
476
        /* Not enough operands */
 
477
        return 1;
 
478
 
 
479
    if (whereAmI != *depth - 2)
 
480
        /* invalid stack */
 
481
        return 1;
 
482
 
 
483
    rv = membercompare (stack[whereAmI - 1], stack[whereAmI + 1]);
 
484
 
 
485
    if (rv == -2)
 
486
        /* invalid comparison */
 
487
        return 1;
 
488
 
 
489
    stackpop (stack, depth);      /* arg rhs */
 
490
 
 
491
    stackpop (stack, depth);      /* me */
 
492
 
 
493
    stackpop (stack, depth);      /* arg lhs */
 
494
 
 
495
    srv.valuetype = ESI_EXPR_EXPR;
 
496
 
 
497
    srv.eval = evalexpr;
 
498
 
 
499
    srv.valuestored = ESI_LITERAL_BOOL;
 
500
 
 
501
    srv.value.integral = rv >= 0 ? 1 : 0;
 
502
 
 
503
    srv.precedence = 1;
 
504
 
 
505
    stack[(*depth)++] = srv;
 
506
 
 
507
    /* we're out of way, try adding now */
 
508
    if (!addmember (stack, depth, candidate))
 
509
        /* Something wrong upstream */
 
510
        return 1;
 
511
 
 
512
    /* debugs(86, 1, "?= " << srv.value.integral << " "); */
 
513
    return 0;
 
514
 
 
515
 
 
516
}
 
517
 
 
518
int evalmorethan
 
519
(stackmember * stack, int *depth, int whereAmI, stackmember * candidate)
 
520
{
 
521
    int rv;
 
522
    stackmember srv;
 
523
 
 
524
    if (*depth < 3)
 
525
        /* Not enough operands */
 
526
        return 1;
 
527
 
 
528
    if (whereAmI != *depth - 2)
 
529
        /* invalid stack */
 
530
        return 1;
 
531
 
 
532
    rv = membercompare (stack[whereAmI - 1], stack[whereAmI + 1]);
 
533
 
 
534
    if (rv == -2)
 
535
        /* invalid comparison */
 
536
        return 1;
 
537
 
 
538
    stackpop (stack, depth);    /* arg rhs */
 
539
 
 
540
    stackpop (stack, depth);    /* me */
 
541
 
 
542
    stackpop (stack, depth);    /* arg lhs */
 
543
 
 
544
    srv.valuetype = ESI_EXPR_EXPR;
 
545
 
 
546
    srv.eval = evalexpr;
 
547
 
 
548
    srv.valuestored = ESI_LITERAL_BOOL;
 
549
 
 
550
    srv.value.integral = rv > 0 ? 1 : 0;
 
551
 
 
552
    srv.precedence = 1;
 
553
 
 
554
    stack[(*depth)++] = srv;
 
555
 
 
556
    /* we're out of way, try adding now */
 
557
    if (!addmember (stack, depth, candidate))
 
558
        /* Something wrong upstream */
 
559
        return 1;
 
560
 
 
561
    /* debugs(86, 1, "?= " << srv.value.integral << " "); */
 
562
    return 0;
 
563
 
 
564
}
 
565
 
 
566
int
 
567
evalequals (stackmember * stack, int *depth, int whereAmI,
 
568
            stackmember * candidate)
 
569
{
 
570
    int rv;
 
571
    stackmember srv;
 
572
 
 
573
    if (*depth < 3)
 
574
        /* Not enough operands */
 
575
        return 1;
 
576
 
 
577
    if (whereAmI != *depth - 2)
 
578
        /* invalid stack */
 
579
        return 1;
 
580
 
 
581
    rv = membercompare (stack[whereAmI - 1], stack[whereAmI + 1]);
 
582
 
 
583
    if (rv == -2)
 
584
        /* invalid comparison */
 
585
        return 1;
 
586
 
 
587
    stackpop (stack, depth);    /* arg rhs */
 
588
 
 
589
    stackpop (stack, depth);    /* me */
 
590
 
 
591
    stackpop (stack, depth);    /* arg lhs */
 
592
 
 
593
    srv.valuetype = ESI_EXPR_EXPR;
 
594
 
 
595
    srv.eval = evalexpr;
 
596
 
 
597
    srv.valuestored = ESI_LITERAL_BOOL;
 
598
 
 
599
    srv.value.integral = rv ? 0 : 1;
 
600
 
 
601
    srv.precedence = 1;
 
602
 
 
603
    stack[(*depth)++] = srv;
 
604
 
 
605
    /* we're out of way, try adding now */
 
606
    if (!addmember (stack, depth, candidate))
 
607
        /* Something wrong upstream */
 
608
        return 1;
 
609
 
 
610
    /* debugs(86, 1, "?= " << srv.value.integral << " "); */
 
611
    return 0;
 
612
}
 
613
 
 
614
int evalnotequals
 
615
(stackmember * stack, int *depth, int whereAmI, stackmember * candidate)
 
616
{
 
617
    int rv;
 
618
    stackmember srv;
 
619
 
 
620
    if (*depth < 3)
 
621
        /* Not enough operands */
 
622
        return 1;
 
623
 
 
624
    if (whereAmI != *depth - 2)
 
625
        /* invalid stack */
 
626
        return 1;
 
627
 
 
628
    rv = membercompare (stack[whereAmI - 1], stack[whereAmI + 1]);
 
629
 
 
630
    if (rv == -2)
 
631
        /* invalid comparison */
 
632
        return 1;
 
633
 
 
634
    stackpop (stack, depth);    /* arg rhs */
 
635
 
 
636
    stackpop (stack, depth);    /* me */
 
637
 
 
638
    stackpop (stack, depth);    /* arg lhs */
 
639
 
 
640
    srv.valuetype = ESI_EXPR_EXPR;
 
641
 
 
642
    srv.eval = evalexpr;
 
643
 
 
644
    srv.valuestored = ESI_LITERAL_BOOL;
 
645
 
 
646
    srv.value.integral = rv ? 1 : 0;
 
647
 
 
648
    srv.precedence = 1;
 
649
 
 
650
    stack[(*depth)++] = srv;
 
651
 
 
652
    /* we're out of way, try adding now */
 
653
    if (!addmember (stack, depth, candidate))
 
654
        /* Something wrong upstream */
 
655
        return 1;
 
656
 
 
657
    /* debugs(86, 1, "?= " << srv.value.integral << " "); */
 
658
    return 0;
 
659
}
 
660
 
 
661
int evalstartexpr
 
662
(stackmember * stack, int *depth, int whereAmI, stackmember * candidate)
 
663
{
 
664
    /* debugs(86, 1, "?("); */
 
665
 
 
666
    if (whereAmI != *depth - 2)
 
667
        /* invalid stack */
 
668
        return 1;
 
669
 
 
670
    /* Only valid when RHS is an end bracket */
 
671
    if (candidate->valuetype != ESI_EXPR_END)
 
672
        return 1;
 
673
 
 
674
    --(*depth);
 
675
 
 
676
    stack[whereAmI] = stack[(*depth)];
 
677
 
 
678
    cleanmember (candidate);
 
679
 
 
680
    return 0;
 
681
}
 
682
 
 
683
int evalendexpr
 
684
(stackmember * stack, int *depth, int whereAmI, stackmember * candidate)
 
685
{
 
686
    /* Can't evaluate ) brackets */
 
687
    return 1;
 
688
}
 
689
 
 
690
char const *
 
691
trim (char const *s)
 
692
{
 
693
    while (*s == ' ')
 
694
        ++s;
 
695
 
 
696
    return s;
 
697
}
 
698
 
 
699
stackmember
 
700
getsymbol (const char *s, char const **endptr)
 
701
{
 
702
    stackmember rv;
 
703
    char *end;
 
704
    char const *origs = s;
 
705
    /* trim whitespace */
 
706
    s = trim (s);
 
707
    rv.eval = NULL;             /* A literal */
 
708
    rv.valuetype = ESI_EXPR_INVALID;
 
709
    rv.valuestored = ESI_LITERAL_INVALID;
 
710
 
 
711
    if (('0' <= *s && *s <= '9') || *s == '-') {
 
712
        size_t length = strspn (s, "0123456789.");
 
713
        char const *point;
 
714
 
 
715
        if ((point = strchr (s, '.')) && point - s < (ssize_t)length) {
 
716
            /* floating point */
 
717
            errno=0; /* reset errno */
 
718
            rv.value.floating = strtod (s, &end);
 
719
 
 
720
            if (s == end || errno) {
 
721
                /* Couldn't convert to float */
 
722
                debugs(86, 1, "failed to convert '" << s << "' to float ");
 
723
                *endptr = origs;
 
724
            } else {
 
725
                debugs (86,6, "found " << rv.value.floating << " of length " << end - s);
 
726
                *endptr = end;
 
727
                rv.eval = evalliteral;
 
728
                rv.valuestored = ESI_LITERAL_FLOAT;
 
729
                rv.valuetype = ESI_EXPR_LITERAL;
 
730
                rv.precedence = 1;
 
731
            }
 
732
        } else {
 
733
            /* INT */
 
734
            errno=0; /* reset errno */
 
735
            rv.value.integral = strtol (s, &end, 0);
 
736
 
 
737
            if (s == end || errno) {
 
738
                /* Couldn't convert to int */
 
739
                debugs(86, 1, "failed to convert '" << s << "' to int ");
 
740
                *endptr = origs;
 
741
            } else {
 
742
                debugs (86,6, "found " << rv.value.integral << " of length " << end - s);
 
743
                *endptr = end;
 
744
                rv.eval = evalliteral;
 
745
                rv.valuestored = ESI_LITERAL_INT;
 
746
                rv.valuetype = ESI_EXPR_LITERAL;
 
747
                rv.precedence = 1;
 
748
            }
 
749
        }
 
750
    } else if ('!' == *s) {
 
751
        if ('=' == *(s + 1)) {
 
752
            debugs(86, 6, "found !=");
 
753
            *endptr = s + 2;
 
754
            rv.eval = evalnotequals;
 
755
            rv.valuetype = ESI_EXPR_NOTEQ;
 
756
            rv.precedence = 5;
 
757
        } else {
 
758
            debugs(86, 6, "found !");
 
759
            *endptr = s + 1;
 
760
            rv.valuetype = ESI_EXPR_NOT;
 
761
            rv.precedence = 4;
 
762
            rv.eval = evalnegate;
 
763
        }
 
764
    } else if ('\'' == *s) {
 
765
        char const *t = s + 1;
 
766
        debugs(86, 6, "found \'");
 
767
 
 
768
        while (*t != '\'' && *t)
 
769
            ++t;
 
770
 
 
771
        if (!*t) {
 
772
            debugs(86, 1, "missing end \' in '" << s << "'");
 
773
            *endptr = origs;
 
774
        } else {
 
775
            *endptr = t + 1;
 
776
            /* Special case for zero length strings */
 
777
 
 
778
            if (t - s - 1)
 
779
                rv.value.string = xstrndup (s + 1, t - s - 1);
 
780
            else
 
781
                rv.value.string = static_cast<char *>(xcalloc (1,1));
 
782
 
 
783
            rv.eval = evalliteral;
 
784
 
 
785
            rv.valuestored = ESI_LITERAL_STRING;
 
786
 
 
787
            rv.valuetype = ESI_EXPR_LITERAL;
 
788
 
 
789
            rv.precedence = 1;
 
790
 
 
791
            debugs(86, 6, "found  string '" << rv.value.string << "'");
 
792
        }
 
793
    } else if ('(' == *s) {
 
794
        debugs(86, 6, "found subexpr start");
 
795
        *endptr = s + 1;
 
796
        rv.valuetype = ESI_EXPR_START;
 
797
        rv.precedence = 5;
 
798
        rv.eval = evalstartexpr;
 
799
    } else if (')' == *s) {
 
800
        debugs(86, 6, "found subexpr end");
 
801
        *endptr = s + 1;
 
802
        rv.valuetype = ESI_EXPR_END;
 
803
        rv.precedence = 0;
 
804
        rv.eval = evalendexpr;
 
805
    } else if ('&' == *s) {
 
806
        debugs(86, 6, "found AND");
 
807
        *endptr = s + 1;
 
808
        rv.valuetype = ESI_EXPR_AND;
 
809
        rv.precedence = 3;
 
810
        rv.eval = evaland;
 
811
    } else if ('|' == *s) {
 
812
        debugs(86, 6, "found OR");
 
813
        *endptr = s + 1;
 
814
        rv.valuetype = ESI_EXPR_OR;
 
815
        rv.precedence = 2;
 
816
        rv.eval = evalor;
 
817
    } else if ('=' == *s) {
 
818
        if ('=' == *(s + 1)) {
 
819
            debugs(86, 6, "found equals");
 
820
            *endptr = s + 2;
 
821
            rv.valuetype = ESI_EXPR_EQ;
 
822
            rv.precedence = 5;
 
823
            rv.eval = evalequals;
 
824
        } else {
 
825
            debugs(86, 1, "invalid expr '" << s << "'");
 
826
            *endptr = origs;
 
827
        }
 
828
    } else if ('<' == *s) {
 
829
        if ('=' == *(s + 1)) {
 
830
            debugs(86, 6, "found less-equals");
 
831
            *endptr = s + 2;
 
832
            rv.valuetype = ESI_EXPR_LESSEQ;
 
833
            rv.precedence = 5;
 
834
            rv.eval = evallesseq;
 
835
        } else {
 
836
            debugs(86, 6, "found less than");
 
837
            *endptr = s + 1;
 
838
            rv.valuetype = ESI_EXPR_LESS;
 
839
            rv.precedence = 5;
 
840
            rv.eval = evallessthan;
 
841
        }
 
842
    } else if ('>' == *s) {
 
843
        if ('=' == *(s + 1)) {
 
844
            debugs(86, 6, "found more-equals");
 
845
            *endptr = s + 2;
 
846
            rv.valuetype = ESI_EXPR_MOREEQ;
 
847
            rv.precedence = 5;
 
848
            rv.eval = evalmoreeq;
 
849
        } else {
 
850
            debugs(86, 6, "found more than");
 
851
            *endptr = s + 1;
 
852
            rv.valuetype = ESI_EXPR_MORE;
 
853
            rv.precedence = 5;
 
854
            rv.eval = evalmorethan;
 
855
        }
 
856
    } else if (!strncmp (s, "false", 5)) {
 
857
        debugs(86, 5, "getsymbol: found variable result 'false'");
 
858
        *endptr = s + 5;
 
859
        rv.valuetype = ESI_EXPR_EXPR;
 
860
        rv.valuestored = ESI_LITERAL_BOOL;
 
861
        rv.value.integral = 0;
 
862
        rv.precedence = 1;
 
863
        rv.eval = evalexpr;
 
864
    } else if (!strncmp (s, "true", 4)) {
 
865
        debugs(86, 5, "getsymbol: found variable result 'true'");
 
866
        *endptr = s + 4;
 
867
        rv.valuetype = ESI_EXPR_EXPR;
 
868
        rv.valuestored = ESI_LITERAL_BOOL;
 
869
        rv.value.integral = 1;
 
870
        rv.precedence = 1;
 
871
        rv.eval = evalexpr;
 
872
    } else {
 
873
        debugs(86, 1, "invalid expr '" << s << "'");
 
874
        *endptr = origs;
 
875
    }
 
876
 
 
877
    return rv;
 
878
}
 
879
 
 
880
void
 
881
printliteral (stackmember s)
 
882
{
 
883
    switch (s.valuestored) {
 
884
 
 
885
    case ESI_LITERAL_INVALID:
 
886
        debug(86, 1) ( " Invalid " );
 
887
        break;
 
888
 
 
889
    case ESI_LITERAL_FLOAT:
 
890
        debug (86,1) ("%f", s.value.floating);
 
891
        break;
 
892
 
 
893
    case ESI_LITERAL_STRING:
 
894
        debug (86,1) ("'%s'", s.value.string);
 
895
        break;
 
896
 
 
897
    case ESI_LITERAL_INT:
 
898
        debug (86,1) ("%d", s.value.integral);
 
899
        break;
 
900
 
 
901
    case ESI_LITERAL_BOOL:
 
902
        debug (86,1)("%s",s.value.integral ? "true" : "false");
 
903
    }
 
904
}
 
905
 
 
906
void
 
907
printmember (stackmember s)
 
908
{
 
909
    switch (s.valuetype) {
 
910
 
 
911
    case ESI_EXPR_INVALID:
 
912
        debug (86,1) (" Invalid ");
 
913
        break;
 
914
 
 
915
    case ESI_EXPR_LITERAL:
 
916
        printliteral (s);
 
917
        break;
 
918
 
 
919
    case ESI_EXPR_EXPR:
 
920
        debug (86,1) ("%s", s.value.integral ? "true" : "false");
 
921
        break;
 
922
 
 
923
    case ESI_EXPR_OR:
 
924
        debug (86,1) ("|");
 
925
        break;
 
926
 
 
927
    case ESI_EXPR_AND:
 
928
        debug (86,1) ("&");
 
929
        break;
 
930
 
 
931
    case ESI_EXPR_NOT:
 
932
        debug (86,1) ("!");
 
933
        break;
 
934
 
 
935
    case ESI_EXPR_START:
 
936
        debug (86,1) ("(");
 
937
        break;
 
938
 
 
939
    case ESI_EXPR_END:
 
940
        debug (86,1) (")");
 
941
        break;
 
942
 
 
943
    case ESI_EXPR_EQ:
 
944
        debug (86,1) ("==");
 
945
        break;
 
946
 
 
947
    case ESI_EXPR_NOTEQ:
 
948
        debug (86,1) ("!=");
 
949
        break;
 
950
 
 
951
    case ESI_EXPR_LESS:
 
952
        debug (86,1) ("<");
 
953
        break;
 
954
 
 
955
    case ESI_EXPR_LESSEQ:
 
956
        debug (86,1) ("<=");
 
957
        break;
 
958
 
 
959
    case ESI_EXPR_MORE:
 
960
        debug (86,1) (">");
 
961
        break;
 
962
 
 
963
    case ESI_EXPR_MOREEQ:
 
964
        debug (86,1) (">=");
 
965
        break;
 
966
    }
 
967
}
 
968
 
 
969
void
 
970
dumpstack (stackmember * stack, int depth)
 
971
{
 
972
    int i;
 
973
 
 
974
    for (i = 0; i < depth; ++i)
 
975
        printmember (stack[i]);
 
976
 
 
977
    if (depth)
 
978
        debug (86,1) ("\n");
 
979
}
 
980
 
 
981
int
 
982
addmember (stackmember * stack, int *stackdepth, stackmember * candidate)
 
983
{
 
984
    if (candidate->valuetype != ESI_EXPR_LITERAL && *stackdepth > 1) {
 
985
        /* !(!(a==b))) is why thats safe */
 
986
        /* strictly less than until we unwind */
 
987
 
 
988
        if (candidate->precedence < stack[*stackdepth - 1].precedence ||
 
989
                candidate->precedence < stack[*stackdepth - 2].precedence) {
 
990
            /* must be an operator */
 
991
 
 
992
            if (stack[*stackdepth - 2].valuetype == ESI_EXPR_LITERAL ||
 
993
                    stack[*stackdepth - 2].valuetype == ESI_EXPR_INVALID ||
 
994
                    stack[*stackdepth - 2].eval (stack, stackdepth,
 
995
                                                 *stackdepth - 2, candidate)) {
 
996
                /* cleanup candidate and stack */
 
997
                dumpstack (stack, *stackdepth);
 
998
                cleanmember (candidate);
 
999
                debugs(86, 1, "invalid expression");
 
1000
                return 0;
 
1001
            }
 
1002
        } else {
 
1003
            stack[(*stackdepth)++] = *candidate;
 
1004
        }
 
1005
    } else if (candidate->valuetype != ESI_EXPR_INVALID)
 
1006
        stack[(*stackdepth)++] = *candidate;
 
1007
 
 
1008
    return 1;
 
1009
}
 
1010
 
 
1011
int
 
1012
ESIExpression::Evaluate (char const *s)
 
1013
{
 
1014
    stackmember stack[20];
 
1015
    int stackdepth = 0;
 
1016
    char const *end;
 
1017
    PROF_start(esiExpressionEval);
 
1018
 
 
1019
    while (*s) {
 
1020
        stackmember candidate = getsymbol (s, &end);
 
1021
 
 
1022
        if (candidate.valuetype != ESI_EXPR_INVALID) {
 
1023
            assert (s != end);
 
1024
 
 
1025
            if (!addmember (stack, &stackdepth, &candidate)) {
 
1026
                PROF_stop(esiExpressionEval);
 
1027
                return 0;
 
1028
            }
 
1029
 
 
1030
            s = end;
 
1031
        } else {
 
1032
            assert (s == end);
 
1033
            debugs(86, 1, "failed parsing expression");
 
1034
            PROF_stop(esiExpressionEval);
 
1035
            return 0;
 
1036
        }
 
1037
    }
 
1038
 
 
1039
    if (stackdepth > 1) {
 
1040
        stackmember rv;
 
1041
        rv.valuetype = ESI_EXPR_INVALID;
 
1042
        rv.precedence = 0;
 
1043
 
 
1044
        if (stack[stackdepth - 2].
 
1045
                eval (stack, &stackdepth, stackdepth - 2, &rv)) {
 
1046
            /* special case - leading operator failed */
 
1047
            debugs(86, 1, "invalid expression");
 
1048
            PROF_stop(esiExpressionEval);
 
1049
            return 0;
 
1050
        }
 
1051
    }
 
1052
 
 
1053
    if (stackdepth == 0) {
 
1054
        /* Empty expression - evaluate to false */
 
1055
        PROF_stop(esiExpressionEval);
 
1056
        return 0;
 
1057
    }
 
1058
 
 
1059
    /* if we hit here, we think we have a valid result */
 
1060
    assert (stackdepth == 1);
 
1061
 
 
1062
    assert (stack[0].valuetype == ESI_EXPR_EXPR);
 
1063
 
 
1064
    PROF_stop(esiExpressionEval);
 
1065
 
 
1066
    return stack[0].value.integral ? 1 : 0;
 
1067
}