Annotation of hatari/src/debug/evaluate.c, revision 1.1.1.6

1.1       root        1: /*
1.1.1.4   root        2:   Hatari - evaluate.c
1.1       root        3: 
1.1.1.4   root        4:   Copyright (C) 1994, 2009-2014 by Eero Tamminen
1.1       root        5: 
1.1.1.3   root        6:   This file is distributed under the GNU General Public License, version 2
                      7:   or at your option any later version. Read the file gpl.txt for details.
1.1       root        8: 
                      9:   calculate.c - parse numbers, number ranges and expressions. Supports
1.1.1.2   root       10:   most unary and binary operations. Parenthesis are used for indirect
                     11:   ST RAM value addressing.
                     12: 
1.1       root       13:   Originally based on code from my Clac calculator MiNT filter version.
                     14: */
                     15: const char Eval_fileid[] = "Hatari calculate.c : " __DATE__ " " __TIME__;
                     16: 
                     17: #include <ctype.h>
                     18: #include <limits.h>
                     19: #include <errno.h>
                     20: #include <stdio.h>
                     21: #include <stdlib.h>
                     22: #include <stdbool.h>
                     23: #include <SDL_types.h>
1.1.1.5   root       24: #include <inttypes.h>
1.1       root       25: #include "configuration.h"
                     26: #include "dsp.h"
                     27: #include "debugcpu.h"
                     28: #include "evaluate.h"
                     29: #include "main.h"
                     30: #include "m68000.h"
1.1.1.2   root       31: #include "stMemory.h"
1.1       root       32: #include "symbols.h"
1.1.1.6 ! root       33: #include "vars.h"
        !            34: 
1.1       root       35: 
                     36: /* define which character indicates which type of number on expression  */
1.1.1.2   root       37: #define PREFIX_BIN '%'                            /* binary decimal     */
                     38: #define PREFIX_DEC '#'                             /* normal decimal    */
                     39: #define PREFIX_HEX '$'                             /* hexadecimal       */
1.1       root       40: 
                     41: /* define error codes                                                   */
                     42: #define CLAC_EXP_ERR "No expression given"
                     43: #define CLAC_GEN_ERR "Syntax error"
                     44: #define CLAC_PAR_ERR "Mismatched parenthesis"
                     45: #define CLAC_DEF_ERR "Undefined result (1/0)"
                     46: #define CLAC_STK_ERR "Operation/value stack full"
                     47: #define CLAC_OVF_ERR "Overflow"
                     48: #define CLAC_OVR_ERR "Mode overflow"
                     49: #define CLAC_PRG_ERR "Internal program error"
                     50: 
                     51: /* define internal allocation sizes (should be enough ;-)              */
1.1.1.2   root       52: #define PARDEPTH_MAX   16              /* max. parenth. nesting depth  */
                     53: #define OSTACK_MAX     64              /* size of the operator stack   */
                     54: #define VSTACK_MAX     64              /* size of the value stack      */
1.1       root       55: 
                     56: /* operation with lowest precedence, used to finish calculations */
                     57: #define LOWEST_PREDECENCE '|'
                     58: 
                     59: /* globals + function identifier stack(s)                              */
                     60: static struct {
                     61:        const char *error;              /* global error code            */
                     62:        bool valid;                     /* value validation             */
1.1.1.6 ! root       63: } id = { NULL, 0 };
1.1       root       64: 
                     65: /* parenthesis and function stacks                                     */
                     66: static struct {
                     67:        int idx;                        /* parenthesis level            */
                     68:        int max;                        /* maximum idx                  */
                     69:        int opx[PARDEPTH_MAX + 1];      /* current op index for par     */
                     70:        int vax[PARDEPTH_MAX + 1];      /* current val index for par    */
                     71: } par = {0, PARDEPTH_MAX, {0}, {0}};
                     72: 
                     73: static struct {                                        /* operator stack       */
                     74:        int idx;
                     75:        int max;
                     76:        char buf[OSTACK_MAX + 1];
                     77: } op = {0, OSTACK_MAX, ""};
                     78: 
                     79: static struct value_stk {                      /* value stack  */
                     80:        int idx;
                     81:        int max;
                     82:        long long buf[VSTACK_MAX + 1];
                     83: } val = {0, VSTACK_MAX, {0}};
                     84: 
                     85: /* -------------------------------------------------------------------- */
                     86: /* macros                                                              */
                     87: 
                     88: /* increment stack index and put value on stack (ie. PUSH)             */
                     89: #define PUSH(stk,val) \
                     90:        if((stk).idx < (stk).max) {             \
                     91:                (stk).idx += 1;                 \
                     92:                (stk).buf[(stk).idx] = (val);   \
                     93:        } else {                                \
                     94:                id.error = CLAC_STK_ERR;        \
                     95:        }
                     96: 
                     97: /* -------------------------------------------------------------------- */
                     98: /* declare subfunctions                                                        */
                     99: 
                    100: /* parse in-between operations */
                    101: static void operation(long long value, char op);
                    102: /* parse unary operators       */
                    103: static void unary (char op);
                    104: /* apply a prefix to a value */
                    105: static void apply_prefix(void);
                    106: /* juggle stacks, if possible  */
                    107: static void eval_stack(void);
                    108: /* operator -> operator level  */
                    109: static int get_level(int stk_offset);
                    110: /* evaluate operation          */
                    111: static long long apply_op(char op, long long x, long long y);
                    112: 
                    113: /* increase parenthesis level  */
                    114: static void open_bracket(void);
                    115: /* decrease parenthesis level  */
                    116: static long long close_bracket(long long x);
                    117: 
                    118: 
                    119: /**
                    120:  * Parse & set an (unsigned) number, assuming it's in the configured
                    121:  * default number base unless it has a prefix:
                    122:  * - '$' / '0x' / '0h' => hexadecimal
                    123:  * - '#' / '0d' => normal decimal
                    124:  * - '%' / '0b' => binary decimal
                    125:  * - '0o' => octal decimal
                    126:  * Return how many characters were parsed or zero for error.
                    127:  */
                    128: static int getNumber(const char *str, Uint32 *number, int *nbase)
                    129: {
                    130:        char *end;
1.1.1.3   root      131:        const char *start = str;
1.1       root      132:        int base = ConfigureParams.Debugger.nNumberBase;
                    133:        unsigned long int value;
                    134: 
                    135:        if (!str[0]) {
                    136:                fprintf(stderr, "Value missing!\n");
                    137:                return 0;
                    138:        }
                    139:        
                    140:        /* determine correct number base */
                    141:        if (str[0] == '0') {
                    142: 
                    143:                /* 0x & 0h = hex, 0d = dec, 0o = oct, 0b = bin ? */
                    144:                switch(str[1]) {
                    145:                case 'b':
                    146:                        base = 2;
                    147:                        break;
                    148:                case 'o':
                    149:                        base = 8;
                    150:                        break;
                    151:                case 'd':
                    152:                        base = 10;
                    153:                        break;
                    154:                case 'h':
                    155:                case 'x':
                    156:                        base = 16;
                    157:                        break;
                    158:                default:
                    159:                        str -= 2;
                    160:                }
                    161:                str += 2;
                    162:        }
1.1.1.4   root      163:        else if (!isxdigit((unsigned char)str[0])) {
1.1       root      164: 
                    165:                /* doesn't start with (hex) number -> is it prefix? */
                    166:                switch (*str++) {
                    167:                case PREFIX_BIN:
                    168:                        base = 2;
                    169:                        break;
                    170:                case PREFIX_DEC:
                    171:                        base = 10;
                    172:                        break;
                    173:                case PREFIX_HEX:
                    174:                        base = 16;
                    175:                        break;
                    176:                default:
                    177:                        fprintf(stderr, "Unrecognized number prefix in '%s'!\n", start);
                    178:                        return 0;
                    179:                }
                    180:        }
                    181:        *nbase = base;
                    182: 
                    183:        /* parse number */
                    184:        errno = 0;
                    185:        value = strtoul(str, &end, base);
                    186:        if (errno == ERANGE && value == LONG_MAX) {
                    187:                fprintf(stderr, "Overflow with value '%s'!\n", start);
                    188:                return 0;
                    189:        }
                    190:        if ((errno != 0 && value == 0) || end == str) {
                    191:                fprintf(stderr, "Invalid value '%s'!\n", start);
                    192:                return 0;
                    193:        }
                    194:        *number = value;
                    195:        return end - start;
                    196: }
                    197: 
                    198: 
                    199: /**
1.1.1.2   root      200:  * Parse unsigned register/symbol/number value and set it to "number"
                    201:  * and the number base used for parsing to "base".
1.1       root      202:  * Return how many characters were parsed or zero for error.
                    203:  */
1.1.1.2   root      204: static int getValue(const char *str, Uint32 *number, int *base, bool bForDsp)
1.1       root      205: {
                    206:        char name[64];
                    207:        const char *end;
                    208:        Uint32 mask, *addr;
1.1.1.2   root      209:        int len;
1.1       root      210: 
1.1.1.4   root      211:        for (end = str; *end == '_' || isalnum((unsigned char)*end); end++);
                    212: 
1.1       root      213:        len = end-str;
                    214:        if (len >= (int)sizeof(name)) {
                    215:                fprintf(stderr, "ERROR: symbol name at '%s' too long (%d chars)\n", str, len);
                    216:                return 0;
                    217:        }
                    218:        memcpy(name, str, len);
                    219:        name[len] = '\0';
                    220: 
1.1.1.2   root      221:        *base = 0; /* no base (e.g. variable) */
                    222: 
                    223:        /* internal Hatari variable? */
1.1.1.6 ! root      224:        if (Vars_GetVariableValue(name, number)) {
1.1.1.2   root      225:                return len;
                    226:        }
                    227: 
1.1       root      228:        if (bForDsp) {
1.1.1.3   root      229:                int regsize = DSP_GetRegisterAddress(name, &addr, &mask);
1.1       root      230:                /* DSP register or symbol? */
1.1.1.3   root      231:                switch (regsize) {
                    232:                case 16:
                    233:                        *number = (*((Uint16*)addr) & mask);
1.1       root      234:                        return len;
1.1.1.3   root      235:                case 32:
                    236:                        *number = (*addr & mask);
1.1       root      237:                        return len;
1.1.1.3   root      238:                default:
                    239:                        if (Symbols_GetDspAddress(SYMTYPE_ALL, name, number)) {
                    240:                                return len;
                    241:                        }
1.1       root      242:                }
                    243:        } else {
                    244:                /* a special case CPU register? */
                    245:                if (strcasecmp(name, "PC") == 0) {
                    246:                        *number = M68000_GetPC();
                    247:                        return len;
                    248:                }
                    249:                if (strcasecmp(name, "SR") == 0) {
                    250:                        *number = M68000_GetSR();
                    251:                        return len;
                    252:                }
                    253:                /* a normal CPU  register or symbol? */
                    254:                if (DebugCpu_GetRegisterAddress(name, &addr)) {
                    255:                        *number = *addr;
                    256:                        return len;
                    257:                }
                    258:                if (Symbols_GetCpuAddress(SYMTYPE_ALL, name, number)) {
                    259:                        return len;
                    260:                }
                    261:        }
                    262: 
                    263:        /* none of above, assume it's a number */
1.1.1.2   root      264:        return getNumber(str, number, base);
1.1       root      265: }
                    266: 
                    267: 
1.1.1.2   root      268: /* Check that number string is OK and isn't followed by unrecognized
                    269:  * character (last char char is zero). If not, complain about it.
1.1       root      270:  * Return true for success and false for failure.
                    271:  */
1.1.1.2   root      272: static bool isNumberOK(const char *str, int offset, int base)
1.1       root      273: {
1.1.1.2   root      274:        const char *basestr;
                    275: 
1.1       root      276:        if (!offset) {
                    277:                return false;
                    278:        }
1.1.1.2   root      279:        if (!str[offset]) {
                    280:                /* no extra chars after the parsed part */
                    281:                return true;
1.1       root      282:        }
1.1.1.2   root      283:        switch (base) {
                    284:        case 0:
                    285:                fprintf(stderr, "Name '%s' contains non-alphanumeric characters!\n", str);
1.1       root      286:                return false;
1.1.1.2   root      287:        case 2:
                    288:                basestr = "binary";
                    289:                break;
                    290:        case 8:
                    291:                basestr = "octal";
                    292:                break;
                    293:        case 10:
                    294:                basestr = "decimal";
                    295:                break;
                    296:        case 16:
                    297:                basestr = "hexadecimal";
                    298:                break;
                    299:        default:
                    300:                basestr = "unknown";
1.1       root      301:        }
1.1.1.2   root      302:        fprintf(stderr, "Extra characters in %s based number '%s'!\n", basestr, str);
                    303:        return false;
                    304: }
                    305: 
                    306: /**
                    307:  * Parse & set an (unsigned) number, assume it's in the configured
                    308:  * default number base unless it has a suitable prefix.
                    309:  * Return true for success and false for failure.
                    310:  */
                    311: bool Eval_Number(const char *str, Uint32 *number)
                    312: {
                    313:        int offset, base;
                    314:        /* TODO: add CPU/DSP flag and use getValue() instead of getNumber()
                    315:         * like getRange() does, so that user can use variable names in
                    316:         * addition to numbers.
                    317:         */
                    318:        offset = getNumber(str, number, &base);
1.1.1.4   root      319:        if (!offset)
                    320:                return false;
                    321:        else
                    322:                return isNumberOK(str, offset, base);
1.1       root      323: }
                    324: 
                    325: 
                    326: /**
1.1.1.2   root      327:  * Parse an address range, eg. "$fa0000[-$fa0100]" or "pc[-a0]" and
                    328:  * output appropriate warnings if range or values are invalid.
                    329:  * Address can also be a register/variable/symbol name.
1.1       root      330:  * returns:
1.1.1.2   root      331:  * -1 if invalid address or range,
                    332:  *  0 if single address,
                    333:  * +1 if a range.
1.1       root      334:  */
1.1.1.2   root      335: int Eval_Range(char *str1, Uint32 *lower, Uint32 *upper, bool fordsp)
1.1       root      336: {
1.1.1.2   root      337:        int offset, base, ret;
1.1       root      338:        bool fDash = false;
                    339:        char *str2 = str1;
                    340: 
                    341:        while (*str2) {
                    342:                if (*str2 == '-') {
                    343:                        *str2++ = '\0';
                    344:                        fDash = true;
                    345:                        break;
                    346:                }
                    347:                str2++;
                    348:        }
                    349: 
1.1.1.2   root      350:        offset = getValue(str1, lower, &base, fordsp);
1.1.1.4   root      351:        if (offset == 0 || !isNumberOK(str1, offset, base)) {
1.1.1.2   root      352:                /* first number not OK */
                    353:                fprintf(stderr,"Invalid address value '%s'!\n", str1);
                    354:                ret = -1;
                    355:        } else {
                    356:                /* first number OK */
                    357:                ret = 0;
1.1       root      358:        }
1.1.1.2   root      359:        if (fDash) {
                    360:                offset = getValue(str2, upper, &base, fordsp);
1.1.1.4   root      361:                if (offset == 0 || !isNumberOK(str2, offset, base)) {
1.1.1.2   root      362:                        /* second number not OK */
                    363:                        fprintf(stderr, "Invalid address value '%s'!\n", str2);
                    364:                        ret = -1;
                    365:                } else {
                    366:                        if (*lower > *upper) {
                    367:                                fprintf(stderr,"Invalid range ($%x > $%x)!\n", *lower, *upper);
                    368:                                /* not a range */
                    369:                                ret = -1;
                    370:                        } else {
                    371:                                /* second number & range OK */
                    372:                                ret = 1;
                    373:                        }
                    374:                }
                    375:                *--str2 = '-';
                    376:        }
                    377:        return ret;
1.1       root      378: }
                    379: 
                    380: 
                    381: /**
                    382:  * Evaluate expression. bForDsp determines which registers and symbols
                    383:  * are interpreted. Sets given value and parsing offset.
                    384:  * Return error string or NULL for success.
                    385:  */
                    386: const char* Eval_Expression(const char *in, Uint32 *out, int *erroff, bool bForDsp)
                    387: {
                    388:        /* in    : expression to evaluate                               */
                    389:        /* out   : final parsed value                                   */
                    390:        /* value : current parsed value                                 */
                    391:        /* mark  : current character in expression                      */
                    392:        /* valid : expression validation flag, set when number parsed   */
                    393:        /* end   : 'expression end' flag                                */
                    394:        /* offset: character offset in expression                       */
                    395: 
                    396:        long long value;
1.1.1.2   root      397:        int dummy, offset = 0;
1.1       root      398:        char mark;
                    399:        
                    400:        /* Uses global variables:       */
                    401: 
                    402:        par.idx = 0;                    /* parenthesis stack pointer    */
                    403:        par.opx[0] = par.vax[0] = 0;    /* additional stack pointers    */
                    404:        op.idx = val.idx = -1;
                    405: 
                    406:        id.error = NULL;
                    407:        id.valid = false;               /* value validation             */
                    408:        value = 0;
                    409: 
                    410:        /* parsing loop, repeated until expression ends */
                    411:        do {
                    412:                mark = in[offset];
                    413:                switch(mark) {
                    414:                case '\0':
                    415:                        break;
                    416:                case ' ':
                    417:                case '\t':
                    418:                        offset ++;              /* jump over white space */
                    419:                        break;
                    420:                case '~':                       /* prefixes */
                    421:                        unary(mark);
                    422:                        offset ++;
                    423:                        break;
                    424:                case '>':                       /* operators  */
                    425:                case '<':
                    426:                        offset ++;
                    427:                        /* check that it's '>>' or '<<' */
                    428:                        if (in[offset] != mark)
                    429:                        {
                    430:                                id.error = CLAC_GEN_ERR;
                    431:                                break;
                    432:                        }
                    433:                        operation (value, mark);
                    434:                        offset ++;
                    435:                        break;
                    436:                case '|':
                    437:                case '&':
                    438:                case '^':
                    439:                case '+':
                    440:                case '-':
                    441:                case '*':
                    442:                case '/':
                    443:                        operation (value, mark);
                    444:                        offset ++;
                    445:                        break;
                    446:                case '(':
                    447:                        open_bracket ();
                    448:                        offset ++;
                    449:                        break;
                    450:                case ')':
                    451:                        value = close_bracket (value);
                    452:                        offset ++;
                    453:                        break;
                    454:                default:
                    455:                        /* register/symbol/number value needed? */
                    456:                        if (id.valid == false) {
                    457:                                Uint32 tmp;
                    458:                                int consumed;
1.1.1.2   root      459:                                consumed = getValue(&(in[offset]), &tmp, &dummy, bForDsp);
1.1       root      460:                                /* number parsed? */
                    461:                                if (consumed) {
                    462:                                        offset += consumed;
                    463:                                        id.valid = true;
                    464:                                        value = tmp;
                    465:                                        break;
                    466:                                }
                    467:                        }
                    468:                        id.error = CLAC_GEN_ERR;
                    469:                }
                    470: 
                    471:        /* until exit or error message                                  */
                    472:        } while(mark && !id.error);
                    473: 
                    474:         /* result of evaluation                                        */
                    475:         if (val.idx >= 0)
                    476:                *out = val.buf[val.idx];
                    477: 
                    478:        /* something to return?                                         */
                    479:        if (!id.error) {
                    480:                if (id.valid) {
                    481: 
                    482:                        /* evaluate rest of the expression              */
                    483:                        operation (value, LOWEST_PREDECENCE);
                    484:                        if (par.idx)                    /* mismatched   */
                    485:                                id.error = CLAC_PAR_ERR;
                    486:                        else                            /* result out   */
                    487:                                *out = val.buf[val.idx];
                    488: 
                    489:                } else {
                    490:                        if ((val.idx < 0) && (op.idx < 0)) {
                    491:                                id.error = CLAC_EXP_ERR;
                    492:                        } else                  /* trailing operators   */
                    493:                                id.error = CLAC_GEN_ERR;
                    494:                }
                    495:        }
                    496: 
                    497:        *erroff = offset;
                    498:        if (id.error) {
                    499:                *out = 0;
                    500:                return id.error;
                    501:        }
                    502:        return NULL;
                    503: }
                    504: 
                    505: 
                    506: /* ==================================================================== */
                    507: /*                     expression evaluation                           */
                    508: /* ==================================================================== */
                    509: 
                    510: static void operation (long long value, char oper)
                    511: {
                    512:        /* uses globals par[], id.error[], op[], val[]
                    513:         * operation executed if the next one is on same or lower level
                    514:         */
                    515:        /* something to calc? */
                    516:        if(id.valid == true) {
                    517:                
                    518:                /* add new items to stack */
                    519:                PUSH(op, oper);
                    520:                PUSH(val, value);
                    521:                
                    522:                /* more than 1 operator  */
                    523:                if(op.idx > par.opx[par.idx]) {
                    524: 
                    525:                        /* but only one value */
                    526:                        if(val.idx == par.vax[par.idx]) {
                    527:                                apply_prefix();
                    528:                        } else {
                    529:                                /* evaluate all possible operations */
                    530:                                eval_stack();
                    531:                        }
                    532:                }
                    533:                /* next a number needed */
                    534:                id.valid = false;
                    535:        } else {
                    536:                /* pre- or post-operators instead of in-betweens? */
                    537:                unary(oper);
                    538:        }
                    539: }
                    540: 
                    541: /**
                    542:  * handle unary operators
                    543:  */
                    544: static void unary (char oper)
                    545: {
                    546:        /* check pre-value operators
                    547:         * have to be parenthesised
                    548:         */
                    549:        if(id.valid == false && op.idx < par.opx[par.idx])
                    550:        {
                    551:                switch(oper) {
                    552:                case '+':               /* not needed */
                    553:                        break;
                    554:                case '-':
                    555:                case '~':
                    556:                        PUSH(op, oper);
                    557:                        break;
                    558:                default:
                    559:                        id.error = CLAC_GEN_ERR;
                    560:                }
                    561:        }
                    562:        else
                    563:                id.error = CLAC_GEN_ERR;
                    564: }
                    565: 
                    566: /**
                    567:  * apply a prefix to the current value
                    568:  */
                    569: static void apply_prefix(void)
                    570: {
                    571:        long long value = val.buf[val.idx];
                    572: 
                    573:        op.idx--;
                    574:        switch(op.buf[op.idx]) {
                    575:        case '-':
                    576:                value = (-value);
                    577:                break;
                    578:        case '~':
                    579:                value = (~value);
                    580:                break;
                    581:        default:
                    582:                id.error = CLAC_PRG_ERR;
                    583:        }
                    584:        val.buf[val.idx] = value;
                    585:        op.buf[op.idx] = op.buf[op.idx + 1];
                    586: }
                    587: 
                    588: /* -------------------------------------------------------------------- */
                    589: /**
                    590:  * evaluate operators if precedence allows it
                    591:  */
                    592: /* evaluate all possible (according to order of precedence) operators  */
                    593: static void eval_stack (void)
                    594: {
                    595:        /* uses globals par[], op[], val[]      */
                    596: 
                    597:        /* # of operators >= 2 and prev. op-level >= current op-level ? */
                    598:        while ((op.idx > par.opx[par.idx]) && get_level (-1) >= get_level (0)) {
                    599: 
                    600:                /* shorten value stacks by one  */
                    601:                /* + calculate resulting value  */
                    602:                op.idx -= 1;
                    603:                val.idx -= 1;
                    604:                val.buf[val.idx] = apply_op(op.buf[op.idx],
                    605:                        val.buf[val.idx], val.buf[val.idx + 1]);
                    606: 
                    607:                /* pull the just used operator out of the stack         */
                    608:                op.buf[op.idx] = op.buf[op.idx + 1];
                    609:        }
                    610: }
                    611: 
                    612: /* -------------------------------------------------------------------- */
                    613: /**
                    614:  * return the precedence level of a given operator
                    615:  */
                    616: static int get_level (int offset)
                    617: {
                    618:        /* used globals par[], op[]
                    619:         * returns operator level of: operator[stack idx + offset]
                    620:         */
                    621:        switch(op.buf[op.idx + offset]) {
                    622:        case '|':      /* binary operations  */
                    623:        case '&':
                    624:        case '^':
                    625:                return 0;
                    626:                
                    627:        case '>':      /* bit shifting    */
                    628:        case '<':
                    629:                return 1;
                    630:                
                    631:        case '+':
                    632:        case '-':
                    633:                return 2;
                    634:                
                    635:        case '*':
                    636:        case '/':
                    637:                return 3;
                    638:                
                    639:        default:
                    640:                id.error = CLAC_PRG_ERR;
                    641:        }
                    642:        return 6;
                    643: }
                    644: 
                    645: /* -------------------------------------------------------------------- */
                    646: /**
                    647:  * apply operator to given values, return the result
                    648:  */
                    649: static long long apply_op (char opcode, long long value1, long long value2)
                    650: {
                    651:        /* uses global id.error[]               */
                    652:        /* returns the result of operation      */
                    653: 
                    654:        switch (opcode) {
                    655:         case '|':
                    656:                value1 |= value2;
                    657:                break;
                    658:         case '&':
                    659:                value1 &= value2;
                    660:                break;
                    661:         case '^':
                    662:                value1 ^= value2;
                    663:                break;
                    664:         case '>':
                    665:                value1 >>= value2;
                    666:         case '<':
                    667:                value1 <<= value2;
                    668:                break;
                    669:        case '+':
                    670:                value1 += value2;
                    671:                break;
                    672:        case '-':
                    673:                value1 -= value2;
                    674:                break;
                    675:        case '*':
                    676:                value1 *= value2;
                    677:                break;
                    678:        case '/':
                    679:                /* don't divide by zero */
                    680:                if (value2)
                    681:                        value1 /= value2;
                    682:                else
                    683:                        id.error = CLAC_DEF_ERR;
                    684:                break;
                    685:         default:
                    686:                id.error = CLAC_PRG_ERR;
                    687:        }
                    688:        return value1;                          /* return result        */
                    689: }
                    690: 
                    691: 
                    692: /* ==================================================================== */
                    693: /*                     parenthesis and help                            */
                    694: /* ==================================================================== */
                    695: 
                    696: /**
1.1.1.4   root      697:  * open parenthesis, push values & operators to stack
1.1       root      698:  */
                    699: static void open_bracket (void)
                    700: {
                    701:        if (id.valid == false) {                /* preceded by operator */
                    702:                if (par.idx < PARDEPTH_MAX) {   /* not nested too deep  */
                    703:                        par.idx ++;
                    704:                        par.opx[par.idx] = op.idx + 1;
                    705:                        par.vax[par.idx] = val.idx + 1;
                    706:                } else
                    707:                        id.error = CLAC_STK_ERR;
                    708:        } else
                    709:                id.error = CLAC_GEN_ERR;
                    710: }
                    711: 
                    712: /* -------------------------------------------------------------------- */
                    713: /**
1.1.1.4   root      714:  * close parenthesis, and evaluate / pop stacks
1.1       root      715:  */
                    716: /* last parsed value, last param. flag, trigonometric mode     */
                    717: static long long close_bracket (long long value)
                    718: {
                    719:        /* returns the value of the parenthesised expression    */
                    720: 
                    721:        if (id.valid) {                 /* preceded by an operator      */
1.1.1.4   root      722:                if (par.idx > 0) {      /* parenthesis has a pair       */
1.1.1.2   root      723:                        Uint32 addr;
                    724: 
1.1       root      725:                        /* calculate the value of parenthesised exp.    */
                    726:                        operation (value, LOWEST_PREDECENCE);
1.1.1.2   root      727:                        /* fetch the indirect ST RAM value */
                    728:                        addr = val.buf[val.idx];
                    729:                        value = STMemory_ReadLong(addr);
1.1.1.5   root      730:                        fprintf(stderr, "  value in RAM at ($%x).l = $%"PRIx64"\n",
                    731:                                addr, (uint64_t)value);
1.1.1.2   root      732:                        /* restore state before parenthesis */
                    733:                        op.idx = par.opx[par.idx] - 1;
1.1       root      734:                        val.idx = par.vax[par.idx] - 1;
                    735:                        par.idx --;
                    736: 
                    737:                        /* next operator */
                    738:                        id.valid = true;
                    739:                } else
                    740:                        id.error = CLAC_PAR_ERR;
                    741:        } else
                    742:                id.error = CLAC_GEN_ERR;
                    743: 
                    744:        return value;
                    745: }

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.