openbcm

Git mirror of https://github.com/Broadcom-Network-Switching-Software/OpenBCM
git clone git://git.finwo.net/mirror/broadcom/openbcm
Log | Files | Refs | README

infix.c (6427B)


      1 /*
      2  * 
      3  *
      4  * This license is set out in https://raw.githubusercontent.com/Broadcom-Network-Switching-Software/OpenBCM/master/Legal/LICENSE file.
      5  * 
      6  * Copyright 2007-2019 Broadcom Inc. All rights reserved.
      7  */
      8 
      9 /*
     10  * 
     11  * $Copyright: $
     12  */
     13 #include <appl/diag/infix.h>
     14 
     15 #include <assert.h>
     16 #include <sal/core/libc.h>
     17 #include <appl/diag/system.h>
     18 
     19 typedef struct infix_data_s {
     20     INFIX_TYPE        astk[INFIX_ASTK_SIZE], *asp;
     21     int            ostk[INFIX_OSTK_SIZE], *osp;
     22     int            err;
     23 } infix_data_t;
     24 
     25 typedef struct infix_op_s {
     26     char        *str;
     27     int            op;
     28 } infix_op_t;
     29 
     30 #define OP_LPAR        '('
     31 #define OP_RPAR        ')'
     32 #define OP_BNOT        '~'
     33 #define OP_CNOT        'N'
     34 #define OP_UNEG        'U'
     35 #define OP_UPLUS    'P'
     36 #define OP_MUL        '*'
     37 #define OP_DIV        '/'
     38 #define OP_MOD        '%'
     39 #define OP_ADD        '+'
     40 #define OP_SUB        '-'
     41 #define OP_LSH        'l'    /* << */
     42 #define OP_RSH        'r'    /* >> */
     43 #define OP_LT        '<'    /* < */
     44 #define OP_LE        '['    /* <= */
     45 #define OP_GT        '>'    /* > */
     46 #define OP_GE        ']'    /* >= */
     47 #define OP_EQ        '='    /* == */
     48 #define OP_NE        '!'    /* != */
     49 #define OP_BAND        '&'
     50 #define OP_BOR        '|'
     51 #define OP_BXOR        '^'
     52 #define OP_CAND        'A'    /* && */
     53 #define OP_COR        'O'    /* || */
     54 #define OP_ERR        'x'
     55 
     56 static infix_op_t infix_ops[] = {
     57     /* Two-char operators first */
     58     {    "<<",        OP_LSH        },
     59     {    ">>",        OP_RSH        },
     60     {    "<=",        OP_LE        },
     61     {    ">=",        OP_GE        },
     62     {    "!=",        OP_NE        },
     63     {    "==",        OP_EQ        },
     64     {    "&&",        OP_CAND        },
     65     {    "||",        OP_COR        },
     66     {    "(",        OP_LPAR        },
     67     {    ")",        OP_RPAR        },
     68     {    "~",        OP_BNOT        },
     69     {    "!",        OP_CNOT        },
     70     {    "*",        OP_MUL        },
     71     {    "/",        OP_DIV        },
     72     {    "%",        OP_MOD        },
     73     {    "+",        OP_ADD        },
     74     {    "-",        OP_SUB        },
     75     {    "&",        OP_BAND        },
     76     {    "|",        OP_BOR        },
     77     {    "^",        OP_BXOR        },
     78     {    "<",        OP_LT        },
     79     {    ">",        OP_GT        },
     80     {    NULL,        0        },
     81 };
     82 
     83 static int infix_pri(infix_data_t *id, int op)
     84 {
     85     switch (op) {
     86     case OP_LPAR:            return 0;
     87     case OP_BNOT:   case OP_CNOT:
     88     case OP_UNEG:   case OP_UPLUS:    return 1;
     89     case OP_MUL:    case OP_DIV:
     90     case OP_MOD:            return 2;
     91     case OP_ADD:    case OP_SUB:    return 3;
     92     case OP_LSH:    case OP_RSH:    return 4;
     93     case OP_LT:     case OP_LE:
     94     case OP_GT:     case OP_GE:        return 5;
     95     case OP_EQ:     case OP_NE:        return 6;
     96     case OP_BAND:            return 7;
     97     case OP_BXOR:            return 8;
     98     case OP_BOR:            return 9;
     99     case OP_CAND:            return 10;
    100     case OP_COR:            return 11;
    101     case OP_RPAR:            return 12;
    102     }
    103 
    104     id->err = 1;
    105 
    106     return 0;
    107 }
    108 
    109 static void infix_push(infix_data_t *id, INFIX_TYPE v)
    110 {
    111     if (id->asp == &id->astk[INFIX_ASTK_SIZE])
    112         { id->err = -1; }
    113     else
    114         { *id->asp++ = v; }
    115 }
    116 
    117 static INFIX_TYPE infix_pop(infix_data_t *id)
    118 {
    119     if (id->asp == &id->astk[0]) {
    120     id->err = -1;
    121     return 0;
    122     } else {
    123     --id->asp;
    124     return *id->asp;
    125     }
    126 }
    127 
    128 static void infix_doop(infix_data_t *id, int op)
    129 {
    130     INFIX_TYPE v;
    131 
    132     if (op == OP_LPAR || op == OP_RPAR)
    133         { return; }
    134 
    135     v = infix_pop(id);
    136 
    137     switch (op) {
    138     case OP_BNOT:    v = ~v;                break;
    139     case OP_UNEG:    v = 0 - v;            break;
    140     case OP_CNOT:    v = ! v;            break;
    141     case OP_MUL:    v = infix_pop(id) * v;        break;
    142     case OP_DIV:    if (v == 0) { id->err = 1; }
    143                 else { v = infix_pop(id) / v; }  break;
    144     case OP_MOD:    if (v == 0) { id->err = 1; }
    145                 else { v = infix_pop(id) % v; }  break;
    146     case OP_ADD:    v = infix_pop(id) + v;        break;
    147     case OP_SUB:    v = infix_pop(id) - v;        break;
    148     case OP_LSH:    v = infix_pop(id) << v;        break;
    149     case OP_RSH:    v = infix_pop(id) >> v;        break;
    150     case OP_BAND:    v = infix_pop(id) & v;        break;
    151     case OP_BXOR:    v = infix_pop(id) ^ v;        break;
    152     case OP_BOR:    v = infix_pop(id) | v;        break;
    153     case OP_LT:        v = infix_pop(id) < v;        break;
    154     case OP_GT:        v = infix_pop(id) > v;        break;
    155     case OP_LE:        v = infix_pop(id) <= v;        break;
    156     case OP_GE:        v = infix_pop(id) >= v;        break;
    157     case OP_NE:        v = infix_pop(id) != v;        break;
    158     case OP_EQ:        v = infix_pop(id) == v;        break;
    159     case OP_CAND:    v = infix_pop(id) && v;        break;
    160     case OP_COR:    v = infix_pop(id) || v;        break;
    161     }
    162 
    163     infix_push(id, v);
    164 }
    165 
    166 int infix_getop(char **s)
    167 {
    168     int            i;
    169 
    170     for (i = 0; infix_ops[i].str != NULL; i++) {
    171     if (infix_ops[i].str[1] == 0) {
    172         if (infix_ops[i].str[0] == (*s)[0]) {
    173         (*s)++;
    174         return infix_ops[i].op;
    175         }
    176     } else if (infix_ops[i].str[0] == (*s)[0] &&
    177            infix_ops[i].str[1] == (*s)[1]) {
    178         (*s) += 2;
    179         return infix_ops[i].op;
    180     }
    181     }
    182 
    183     return OP_ERR;
    184 }
    185 
    186 int infix_eval(char *s, INFIX_TYPE *v)
    187 {
    188     int            i, p, prev_was_op = 1;
    189     infix_data_t    id;
    190 
    191     id.asp = &id.astk[0];
    192     id.osp = &id.ostk[0];
    193     id.err = 0;
    194 
    195     while ((i = *s) != 0) {
    196     if (isspace(i))
    197         { s++; }
    198     else if (isdigit(i)) {
    199         infix_push(&id, sal_ctoi(s, &s));
    200         prev_was_op = 0;
    201     } else {
    202         i = infix_getop(&s);
    203         if (i == OP_ERR) {
    204         id.err = 1;
    205         break;
    206         }
    207         if (i == OP_SUB && prev_was_op)
    208             { i = OP_UNEG; }
    209         else if (i == OP_ADD && prev_was_op)
    210         i = OP_UPLUS;
    211         else if ((i == OP_CNOT || i == OP_BNOT) && prev_was_op) {
    212         /* skip */
    213         } else {
    214         p = infix_pri(&id, i);
    215         while (id.osp > id.ostk && infix_pri(&id, id.osp[-1]) <= p)
    216             infix_doop(&id, *--id.osp);
    217         }
    218         *id.osp++ = i;
    219         prev_was_op = (i != OP_RPAR);
    220     }
    221     }
    222 
    223     while (id.osp > id.ostk)
    224     infix_doop(&id, *--id.osp);
    225 
    226     *v = infix_pop(&id);
    227 
    228     if (id.asp != id.astk)
    229         { id.err = -1; }
    230 
    231     return id.err;
    232 }