Annotation of GNUtools/cctools/as/expr.c, revision 1.1.1.1

1.1       root        1: /* expr.c -operands, expressions-
                      2:    Copyright (C) 1987 Free Software Foundation, Inc.
                      3: 
                      4: This file is part of GAS, the GNU Assembler.
                      5: 
                      6: GAS is free software; you can redistribute it and/or modify
                      7: it under the terms of the GNU General Public License as published by
                      8: the Free Software Foundation; either version 1, or (at your option)
                      9: any later version.
                     10: 
                     11: GAS is distributed in the hope that it will be useful,
                     12: but WITHOUT ANY WARRANTY; without even the implied warranty of
                     13: MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
                     14: GNU General Public License for more details.
                     15: 
                     16: You should have received a copy of the GNU General Public License
                     17: along with GAS; see the file COPYING.  If not, write to
                     18: the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
                     19: 
                     20: /*
                     21:  * This is really a branch office of as-read.c. I split it out to clearly
                     22:  * distinguish the world of expressions from the world of statements.
                     23:  * (It also gives smaller files to re-compile.)
                     24:  * Here, "operand"s are of expressions, not instructions.
                     25:  */
                     26: 
                     27: #include <ctype.h>
                     28: #include <string.h>
                     29: #include "stuff/round.h"
                     30: #include "as.h"
                     31: #include "flonum.h"
                     32: #include "struc-symbol.h"
                     33: #include "expr.h"
                     34: #include "read.h"
                     35: #include "obstack.h"
                     36: #include "symbols.h"
                     37: #include "hex_value.h"
                     38: #include "md.h"
                     39: #include "messages.h"
                     40: #include "sections.h"
                     41: 
                     42: char *seg_name[] = {
                     43:     "absolute",
                     44:     "section",
                     45:     "difference",
                     46:     "unknown",
                     47:     "absent",
                     48:     "bignum/flonum",
                     49: };
                     50: 
                     51: #ifdef SUSPECT
                     52: static int seg_N_TYPE[] = {
                     53:     N_ABS,     /* absolute */
                     54:     N_SECT,    /* section */
                     55:     -1,                /* difference */
                     56:     N_UNDF,    /* unknown */
                     57:     -1,                /* absent */
                     58:     -1         /* bignum/flonum */
                     59: };
                     60: #endif
                     61: 
                     62: segT N_TYPE_seg[] =
                     63: {
                     64:  /* N_UNDF == 0,     N_ABS == 2 */
                     65:     SEG_UNKNOWN, -1, SEG_ABSOLUTE, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
                     66:  /* N_SECT == 0xe */
                     67:     SEG_SECT, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1
                     68: };
                     69: 
                     70: /*
                     71:  * SEG_BIG expressions encode either a floating point number or an integer
                     72:  * larger than 32 bits in this manner:
                     73:  *   For a floating point number:
                     74:  *     X_add_number is < 0
                     75:  *         The result is in the global variable generic_floating_point_number.
                     76:  *         The value in X_add_number is -'c' where c is the character that
                     77:  *         introduced the constant.  e.g. "0f6.9" will have  -'f' as a
                     78:  *         X_add_number value.
                     79:  *   For an integer larger than 32 bits:
                     80:  *     X_add_number > 0
                     81:  *         The result is in the global variable generic_bignum.
                     82:  *         The value in X_add_number is a count of how many littlenums it
                     83:  *         took to represent the bignum.
                     84:  */
                     85: 
                     86: /* LITTLENUM_TYPE      generic_buffer [6];     JF this is a hack */
                     87: /* Seems atof_machine can backscan through generic_bignum and hit whatever
                     88:    happens to be loaded before it in memory.  And its way too complicated
                     89:    for me to fix right.  Thus a hack.  JF:  Just make generic_bignum bigger,
                     90:    and never write into the early words, thus they'll always be zero.
                     91:    I hate Dean's floating-point code.  Bleh.
                     92:  */
                     93: LITTLENUM_TYPE generic_bignum[SIZE_OF_LARGE_NUMBER + 6] = { 0 };
                     94: 
                     95: FLONUM_TYPE generic_floating_point_number = {
                     96:     &generic_bignum[6],                                  /* low (JF: Was 0) */
                     97:     &generic_bignum[SIZE_OF_LARGE_NUMBER + 6 - 1],/* high JF: (added +6) */
                     98:     0,                                           /* leader */
                     99:     0,                                           /* exponent */
                    100:     0                                            /* sign */
                    101: };
                    102: 
                    103: /*
                    104:  * The type operatorT is for the types of operators in expressions.
                    105:  */
                    106: typedef enum {
                    107:     O_illegal,                 /* (0)  what we get for illegal op */
                    108: 
                    109:     O_multiply,                        /* (1)  *  Ordered by rank*/
                    110:     O_divide,                  /* (2)  /  */
                    111:     O_modulus,                 /* (3)  %  */
                    112: 
                    113:     O_add,                     /* (4)  +  */
                    114:     O_subtract,                        /* (5)  -  */
                    115: 
                    116:     O_right_shift,             /* (6)  >> */
                    117:     O_left_shift,              /* (7)  << */
                    118: 
                    119:     O_less_than,               /* (8)  <  */
                    120:     O_greater_than,            /* (9)  >  */
                    121:     O_less_than_or_equal,      /* (10) <= */
                    122:     O_greater_than_or_equal,   /* (11) >= */
                    123: 
                    124:     O_equal,                   /* (12) == */
                    125:     O_not_equal,               /* (13) != */ /* or <> */
                    126: 
                    127:     O_bit_and,                 /* (14) &  */
                    128: 
                    129:     O_bit_exclusive_or,                /* (15) ^  */
                    130: 
                    131:     O_bit_inclusive_or,                /* (16) |  */
                    132:     O_bit_or_not,              /* (17) !  */
                    133:     two_char_operator          /* (18) encoding for two char operator */
                    134: } operatorT;
                    135: 
                    136: /*
                    137:  * op_size is indexed by an operatorT and tells the size of the operator
                    138:  * which is used to advance the input_line_pointer over the operator.
                    139:  */
                    140: static int op_size [] =
                    141:     { 0, 1, 1, 1, 1, 1, 2, 2, 1, 1, 2, 2, 2, 2, 1, 1, 1, 1 };
                    142: 
                    143: /*
                    144:  * op_rank is indexed by an operatorT and tells the rank of the operator.
                    145:  *
                    146:  *     Rank    Examples
                    147:  *     8       * / %
                    148:  *     7       + -
                    149:  *     6       >> <<
                    150:  *     5       < > <= >=
                    151:  *     4       == !=
                    152:  *     3       &
                    153:  *     2       ^
                    154:  *     1       | !
                    155:  *     0       operand, (expression)
                    156:  */
                    157: typedef char operator_rankT;
                    158: static operator_rankT op_rank [] =
                    159:     { 0, 8, 8, 8, 7, 7, 6, 6, 5, 5, 5, 5, 4, 4, 3, 2, 1, 1 };
                    160: 
                    161: /*
                    162:  * op_encoding is indexed by a an ASCII character and maps it to an operator.
                    163:  */
                    164: #define __ O_illegal
                    165: static const operatorT op_encoding [256] = {
                    166:     __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __,
                    167:     __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __,
                    168: 
                    169:     __, two_char_operator, __, __, __, O_modulus, O_bit_and, __,
                    170:     __, __, O_multiply, O_add, __, O_subtract, __, O_divide,
                    171:     __, __, __, __, __, __, __, __,
                    172:     __, __, __, __, two_char_operator, two_char_operator, two_char_operator, __,
                    173:     __, __, __, __, __, __, __, __,
                    174:     __, __, __, __, __, __, __, __,
                    175:     __, __, __, __, __, __, __, __,
                    176:     __, __, __, __, __, __, O_bit_exclusive_or, __,
                    177:     __, __, __, __, __, __, __, __,
                    178:     __, __, __, __, __, __, __, __,
                    179:     __, __, __, __, __, __, __, __,
                    180:     __, __, __, __, O_bit_inclusive_or, __, __, __,
                    181: 
                    182:     __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __,
                    183:     __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __,
                    184:     __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __,
                    185:     __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __,
                    186:     __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __,
                    187:     __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __,
                    188:     __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __,
                    189:     __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __
                    190: };
                    191: 
                    192: static segT expr(
                    193:     operator_rankT rank,
                    194:     expressionS *resultP);
                    195: 
                    196: static segT operand(
                    197:     expressionS *expressionP);
                    198: 
                    199: static void clean_up_expression(
                    200:     expressionS *expressionP);
                    201: 
                    202: static segT expr_part(
                    203:     struct symbol **symbol_1_PP,
                    204:     struct symbol *symbol_2_P);
                    205: 
                    206: static operatorT two_char_op_encoding(
                    207:     char first_op_char);
                    208: 
                    209: segT   /* Return resultP -> X_seg */
                    210: expression(
                    211: expressionS *resultP) /* deliver result here */
                    212: {
                    213:     segT segment;
                    214: 
                    215:        segment = expr(0, resultP);
                    216: 
                    217: /* what about caller's that just want to ignore this and print the're own
                    218:    error message? ok I guess */
                    219:        if(segment == SEG_DIFFSECT &&
                    220:           resultP->X_add_symbol == NULL &&
                    221:           (resultP->X_subtract_symbol->sy_type & N_TYPE) != N_UNDF){
                    222:            as_warn("Subtracting symbol \"%s\"(segment\"%s\") is too "
                    223:                    "hard. Absolute segment assumed.",
                    224:                    resultP->X_subtract_symbol->sy_name,
                    225:                    seg_name[(int)N_TYPE_seg[
                    226:                        resultP->X_subtract_symbol->sy_type & N_TYPE]]);
                    227:            segment = SEG_ABSOLUTE;
                    228:            /* Leave exp .X_add_number alone. */
                    229:        }
                    230:        return(segment);
                    231: }
                    232: 
                    233: /* Expression parser. */
                    234: 
                    235: /*
                    236:  * We allow an empty expression, and just assume (absolute,0) silently.
                    237:  * Unary operators and parenthetical expressions are treated as operands.
                    238:  * As usual, Q==quantity==operand, O==operator, X==expression mnemonics.
                    239:  *
                    240:  * Most expressions are either register (which does not even reach here)
                    241:  * or 1 symbol. Then "symbol+constant" and "symbol-symbol" are common.
                    242:  *
                    243:  * After expr(RANK,resultP) input_line_pointer -> operator of rank <= RANK.
                    244:  * Also, we have consumed any leading or trailing spaces (operand does that)
                    245:  * and done all intervening operators.
                    246:  */
                    247: static
                    248: segT   /* Return resultP -> X_seg */
                    249: expr(
                    250: operator_rankT rank, /* larger # is higher rank */
                    251: expressionS *resultP) /* deliver result here */
                    252: {
                    253:     expressionS        right;
                    254:     operatorT  op_left;
                    255:     char       c_left; /* 1st operator character. */
                    256:     operatorT  op_right;
                    257:     char       c_right;
                    258: 
                    259:        know(rank >= 0);
                    260: 
                    261:        (void)operand(resultP);
                    262:        know(*input_line_pointer != ' '); /* Operand() gobbles spaces. */
                    263: 
                    264:        c_left = *input_line_pointer; /* Potential operator character. */
                    265:        op_left = (operatorT)op_encoding[(int)c_left];
                    266:        if(op_left == two_char_operator)
                    267:            op_left = two_char_op_encoding(c_left);
                    268: 
                    269:        while(op_left != O_illegal && op_rank[op_left] > rank){
                    270: 
                    271:            input_line_pointer += op_size[op_left];
                    272:            /* -> after 1st character of operator. */
                    273: 
                    274:            if(SEG_NONE == expr(op_rank[op_left], &right)){
                    275:                as_warn("Missing operand value assumed absolute 0.");
                    276:                resultP->X_add_number           = 0;
                    277:                resultP->X_subtract_symbol      = NULL;
                    278:                resultP->X_add_symbol           = NULL;
                    279:                resultP->X_seg                  = SEG_ABSOLUTE;
                    280:            }
                    281:            know(*input_line_pointer != ' ');
                    282: 
                    283:            c_right = *input_line_pointer;
                    284:            op_right = (operatorT)op_encoding[(int)c_right];
                    285:            if(op_right == two_char_operator)
                    286:                op_right = two_char_op_encoding(c_right);
                    287: 
                    288:            /* -> after 1st character of operator. */
                    289:            know(op_right == 0 || op_rank [op_right] <= op_rank[op_left]);
                    290: 
                    291:            /* input_line_pointer -> after right-hand quantity. */
                    292:            /* left-hand quantity in resultP */
                    293:            /* right-hand quantity in right. */
                    294:            /* operator in op_left. */
                    295: 
                    296:            /*
                    297:             * Operations are not supported on bignums or floating-point
                    298:             * operands.
                    299:             */
                    300:            if(resultP->X_seg == SEG_BIG){
                    301:                as_warn("Left operand of %c is a %s integer 0 assumed",
                    302:                        c_left, resultP->X_add_number > 0 ? "bignum" :
                    303:                        "float");
                    304:                resultP->X_seg = SEG_ABSOLUTE;
                    305:                resultP->X_add_symbol = 0;
                    306:                resultP->X_subtract_symbol = 0;
                    307:                resultP->X_add_number = 0;
                    308:            }
                    309:            if(right.X_seg == SEG_BIG){
                    310:                as_warn("Right operand of %c is a %s integer 0 assumed",
                    311:                        c_left, right.X_add_number > 0 ? "bignum" :
                    312:                        "float");
                    313:                right.X_seg = SEG_ABSOLUTE;
                    314:                right.X_add_symbol = 0;
                    315:                right.X_subtract_symbol = 0;
                    316:                right.X_add_number = 0;
                    317:            }
                    318:            if(op_left == O_subtract){
                    319:                /*
                    320:                 * Convert - into + by exchanging symbols and negating
                    321:                 * number. I know -infinity can't be negated in 2's
                    322:                 * complement: but then it can't be subtracted either.
                    323:                 * This trick does not cause any further inaccuracy.
                    324:                 */
                    325:                struct symbol *symbolP;
                    326: 
                    327:                right.X_add_number      = - right.X_add_number;
                    328:                symbolP                 = right.X_add_symbol;
                    329:                right.X_add_symbol          = right.X_subtract_symbol;
                    330:                right.X_subtract_symbol = symbolP;
                    331:                if(symbolP){
                    332: /* This is not used, as it drops in to the next if */
                    333:                    right.X_seg     = SEG_DIFFSECT;
                    334:                }
                    335:                op_left = O_add;
                    336:            }
                    337:            if(op_left == O_add){
                    338:                segT seg1;
                    339:                segT seg2;
                    340:                
                    341: /* not SEG_NONE and not SEG_BIG */
                    342:                know(resultP->X_seg == SEG_SECT ||
                    343:                     resultP->X_seg == SEG_UNKNOWN ||
                    344:                     resultP->X_seg == SEG_DIFFSECT ||
                    345:                     resultP->X_seg == SEG_ABSOLUTE);
                    346: /* not SEG_NONE and not SEG_BIG */
                    347:                know(right.X_seg == SEG_SECT ||
                    348:                     right.X_seg == SEG_UNKNOWN ||
                    349:                     right.X_seg == SEG_DIFFSECT ||
                    350:                     right.X_seg == SEG_ABSOLUTE);
                    351:                
                    352:                clean_up_expression(&right);
                    353:                clean_up_expression(resultP);
                    354: 
                    355: /* could this just return -1 instead of SEG_PASS1? and tested in the below if
                    356: statement */
                    357:                seg1 = expr_part(&resultP->X_add_symbol,
                    358:                                 right.X_add_symbol);
                    359:                seg2 = expr_part(&resultP->X_subtract_symbol,
                    360:                                 right.X_subtract_symbol);
                    361:                if(seg1 == -1 || seg2 == -1){
                    362:                    as_warn("Can't relocate expression. Absolute 0 assumed.");
                    363:                    resultP->X_seg        = SEG_ABSOLUTE;
                    364:                    resultP->X_add_number = 0;
                    365:                }
                    366:                else{
                    367:                    if(seg2 == SEG_ABSOLUTE){
                    368:                        resultP->X_seg = seg1;
                    369:                    }
                    370:                    else{
                    371: /* also know seg2 != -1 (SEG_PASS1) */
                    372:                        know(seg2 != SEG_ABSOLUTE);
                    373: /* seg2 is for the subtract symbols, since seg2 != SEG_ABSOLUTE as would be
                    374: returned when there is no subtract symbols then expr_part() must have
                    375: combined a symbol into resultP->X_subtract_symbol that is either undefined
                    376: or defined in a section. */
                    377:                        know(resultP->X_subtract_symbol);
                    378:                        /*
                    379:                         * If we are not to use the new incompatible features
                    380:                         * then "symbol1 - symbol2" must both be in the same
                    381:                         * section and will turn out as absolute.
                    382:                         */
                    383:                        if(!flagseen['k']){
                    384:                            if(seg1 != SEG_UNKNOWN &&
                    385:                               seg1 != SEG_ABSOLUTE &&
                    386:                               seg2 != SEG_UNKNOWN &&
                    387:                               seg1 != seg2 &&
                    388:                               resultP->X_add_symbol->sy_other !=
                    389:                               resultP->X_subtract_symbol->sy_other){
                    390:                                know(seg1 == SEG_SECT);
                    391:                                know(seg2 == SEG_SECT);
                    392:                                know(resultP->X_add_symbol);
                    393:                                know(resultP->X_subtract_symbol);
                    394:                                as_warn("Expression too complex: "
                    395:                                       "forgetting %s - %s",
                    396:                                       resultP->X_add_symbol->sy_name,
                    397:                                       resultP->X_subtract_symbol->sy_name);
                    398:                                resultP->X_seg = SEG_ABSOLUTE;
                    399:                                /* Clean_up_expression() will do the rest */
                    400:                            }
                    401:                            else{
                    402: /* this can result in returning an expression that is NULL - symbol and the
                    403: caller must deal with this being illegal.  maybe this should be put in
                    404: expression() routine (not a macro).  Note the code in cons() */
                    405:                                resultP->X_seg = SEG_DIFFSECT;
                    406:                            }   /* If relocation too complex. */
                    407:                        }
                    408:                        else{
                    409:                            resultP->X_seg = SEG_DIFFSECT;
                    410:                        }
                    411: 
                    412:                    }           /* If seg2 == SEG_ABSOLUTE. */
                    413:                }               /* If need pass 2. */
                    414:                resultP->X_add_number += right.X_add_number;
                    415:                clean_up_expression(resultP);
                    416:            }
                    417:            else{       /* Not +. */
                    418:                if(resultP->X_seg == SEG_UNKNOWN ||
                    419:                   right.X_seg == SEG_UNKNOWN){
                    420:                    as_warn("Can't relocate expression. Absolute 0 assumed.");
                    421:                    resultP->X_seg        = SEG_ABSOLUTE;
                    422:                    resultP->X_add_number = 0;
                    423:                }
                    424:                else{
                    425:                    /*
                    426:                     * Will be SEG_ABSOLUTE. (or error)
                    427:                     */
                    428:                    try_to_make_absolute(resultP);
                    429:                    try_to_make_absolute(&right);
                    430:                    resultP->X_subtract_symbol = NULL;
                    431:                    resultP->X_add_symbol = NULL;
                    432:                    if(resultP->X_seg != SEG_ABSOLUTE ||
                    433:                       right.X_seg != SEG_ABSOLUTE){
                    434:                        as_warn("Relocation error. Absolute 0 assumed");
                    435:                        resultP->X_seg        = SEG_ABSOLUTE;
                    436:                        resultP->X_add_number = 0;
                    437:                    }
                    438:                    else{
                    439:                        /*
                    440:                         * Both are absolute so perform the operation
                    441:                         * on the constants.
                    442:                         */
                    443:                        switch(op_left){
                    444:                        case O_bit_inclusive_or:
                    445:                            resultP->X_add_number |= right.X_add_number;
                    446:                            break;
                    447:                          
                    448:                        case O_modulus:
                    449:                            if(right.X_add_number){
                    450:                                resultP->X_add_number %=
                    451:                                        right.X_add_number;
                    452:                            }
                    453:                            else{
                    454:                                as_warn("Division by 0. 0 assumed.");
                    455:                                resultP->X_add_number = 0;
                    456:                            }
                    457:                            break;
                    458:                          
                    459:                        case O_bit_and:
                    460:                            resultP->X_add_number &= right.X_add_number;
                    461:                            break;
                    462:                          
                    463:                        case O_multiply:
                    464:                            resultP->X_add_number *= right.X_add_number;
                    465:                            break;
                    466:                          
                    467:                        case O_divide:
                    468:                            if(right.X_add_number){
                    469:                                resultP->X_add_number /=
                    470:                                        right.X_add_number;
                    471:                            }
                    472:                            else{
                    473:                                as_warn("Division by 0. 0 assumed.");
                    474:                                resultP->X_add_number = 0;
                    475:                            }
                    476:                            break;
                    477:                          
                    478:                        case O_left_shift:
                    479:                            resultP->X_add_number <<=
                    480:                                right.X_add_number;
                    481:                            break;
                    482:                          
                    483:                        case O_right_shift:
                    484:                            resultP->X_add_number >>=
                    485:                                right.X_add_number;
                    486:                            break;
                    487:                          
                    488:                        case O_bit_exclusive_or:
                    489:                            resultP->X_add_number ^= right.X_add_number;
                    490:                            break;
                    491:                          
                    492:                        case O_bit_or_not:
                    493:                            resultP->X_add_number |=
                    494:                                ~right.X_add_number;
                    495:                            break;
                    496: 
                    497:                        case O_less_than:
                    498:                            resultP->X_add_number =
                    499:                               (resultP->X_add_number <
                    500:                                  right.X_add_number);
                    501:                            break;
                    502:                      
                    503:                        case O_greater_than:
                    504:                            resultP->X_add_number =
                    505:                               (resultP->X_add_number >
                    506:                                  right.X_add_number);
                    507:                            break;
                    508:                      
                    509:                        case O_less_than_or_equal:
                    510:                            resultP->X_add_number =
                    511:                               (resultP->X_add_number <=
                    512:                                  right.X_add_number);
                    513:                            break;
                    514:                      
                    515:                        case O_greater_than_or_equal:
                    516:                            resultP->X_add_number =
                    517:                               (resultP->X_add_number >=
                    518:                                  right.X_add_number);
                    519:                            break;
                    520:                      
                    521:                        case O_equal:
                    522:                            resultP->X_add_number =
                    523:                               (resultP->X_add_number ==
                    524:                                  right.X_add_number);
                    525:                            break;
                    526:                      
                    527:                        case O_not_equal:
                    528:                            resultP->X_add_number =
                    529:                               (resultP->X_add_number !=
                    530:                                  right.X_add_number);
                    531:                            break;
                    532:                          
                    533:                        default:
                    534:                            BAD_CASE( op_left );
                    535:                            break;
                    536:                        }       /* switch(op_left) */
                    537:                    }
                    538:                }               /* If we have to force need_pass_2 */
                    539:            }           /* If operator was + */
                    540:            op_left = op_right;
                    541:        }                       /* While next operator is >= this rank */
                    542:        return(resultP->X_seg);
                    543: }
                    544: 
                    545: /*
                    546:  * Summary of operand().
                    547:  *
                    548:  * in: Input_line_pointer points to 1st char of operand, which may
                    549:  *     be a space.
                    550:  *
                    551:  * out:        A expressionS. X_seg determines how to understand the rest of the
                    552:  *     expressionS.
                    553:  *     The operand may have been empty: in this case X_seg == SEG_NONE.
                    554:  *     Input_line_pointer -> (next non-blank) char after operand.
                    555:  *
                    556:  */
                    557: static
                    558: segT
                    559: operand(
                    560: expressionS *expressionP)
                    561: {
                    562:     char c, q;
                    563:     char *name;        /* points to name of symbol */
                    564:     struct symbol *symbolP; /* Points to symbol */
                    565: 
                    566: 
                    567:        SKIP_WHITESPACE();      /* Leading whitespace is part of operand. */
                    568:        c = *input_line_pointer++;/* Input_line_pointer -> past char in c. */
                    569: 
                    570:        if(isdigit(c)){
                    571:            valueT number;      /* offset or (absolute) value */
                    572:            int digit;          /* value of next digit in current radix */
                    573:                                /* invented for humans only, hope */
                    574:                                /* optimising compiler flushes it! */
                    575:            int radix;          /* 8, 10 or 16 */
                    576:                                /* 0 means we saw start of a floating- */
                    577:                                /* point constant. */
                    578:            int maxdig;         /* Highest permitted digit value. */
                    579:            int too_many_digits;/* If we see >= this number of */
                    580:                                /* digits, assume it is a bignum. */
                    581:            char *digit_2;      /* -> 2nd digit of number. */
                    582:            int small;          /* TRUE if fits in 32 bits. */
                    583:            int force_bignum;   /* TRUE if number is 0xb...  */
                    584: 
                    585:            force_bignum = FALSE;
                    586:            /*
                    587:             * These two initiaizations are to shut up compiler warning as the
                    588:             * may be used with out being set.  There used only if radix != 0
                    589:             * when the number is not a floating-point number.
                    590:             */
                    591:            maxdig = 0;
                    592:            too_many_digits = 0;
                    593: 
                    594:            if(c == '0'){ /* non-decimal radix */
                    595:                c = *input_line_pointer++;
                    596:                if(c == 'x' || c=='X'){
                    597:                    c = *input_line_pointer++; /* read past "0x" or "0X" */
                    598:                    maxdig = 16;
                    599:                    radix = 16;
                    600:                    too_many_digits = 9;
                    601:                }
                    602:                /*
                    603:                 * If we have "0b" and some hex digits then treat it as a hex
                    604:                 * number and return a bignum.   This is for hex immediate
                    605:                 * bit-patterns for floating-point immediate constants.
                    606:                 */
                    607:                else if((c == 'b' || c == 'B') &&
                    608:                        (*input_line_pointer != '\0') &&
                    609:                        strchr("0123456789abcdefABCDEF",
                    610:                               *input_line_pointer) != NULL){
                    611:                    force_bignum = TRUE;
                    612:                    c = *input_line_pointer++; /* read past "0b" or "0B" */
                    613:                    maxdig = 16;
                    614:                    radix = 16;
                    615:                    too_many_digits = 9;
                    616:                }
                    617:                else{
                    618:                    /*
                    619:                     * If it says '0f' and the line ends or it DOESN'T look like
                    620:                     * a floating point #, its a local label ref.
                    621:                     */
                    622:                    if(c == 'f' &&
                    623:                       (*input_line_pointer == '\0' ||
                    624:                        (strchr("+-.0123456789", *input_line_pointer) == NULL &&
                    625:                         strchr(md_EXP_CHARS, *input_line_pointer) == NULL) )){
                    626:                        maxdig = 10;
                    627:                        radix = 10;
                    628:                        too_many_digits = 11;
                    629:                        c = '0';
                    630:                        input_line_pointer -= 2;
                    631:                    }
                    632:                    else if(c != '\0' && strchr(md_FLT_CHARS, c) != NULL){
                    633:                        radix = 0;/* Start of floating-point constant. */
                    634:                                  /* input_line_pointer -> 1st char of number */
                    635:                        expressionP->X_add_number =
                    636:                                - (isupper(c) ? tolower(c) : c);
                    637:                    }
                    638:                    else{       /* By elimination, assume octal radix. */
                    639:                        radix = 8;
                    640:                        maxdig = 10;    /* Un*x sux. Compatibility. */
                    641:                        too_many_digits = 11;
                    642:                    }
                    643:                }
                    644:                /* c == char after "0" or "0x" or "0X" or "0e" etc.*/
                    645:            }
                    646:            else{
                    647:                maxdig = 10;
                    648:                radix = 10;
                    649:                too_many_digits = 11;
                    650:            }
                    651:            if(radix != 0){ /* Fixed-point integer constant. */
                    652:                            /* May be bignum, or may fit in 32 bits. */
                    653:                /*
                    654:                 * Most numbers fit into 32 bits, and we want this case to be
                    655:                 * fast.  So we pretend it will fit into 32 bits. If, after
                    656:                 * making up a 32 bit number, we realize that we have scanned
                    657:                 * more digits than comfortably fit into 32 bits, we re-scan the
                    658:                 * digits coding them into a bignum.  For decimal and octal
                    659:                 * numbers we are conservative: some numbers may be assumed
                    660:                 * bignums when in fact they do fit into 32 bits.  Numbers of
                    661:                 * any radix can have excess leading zeros: we strive to
                    662:                 * recognise this and cast them back into 32 bits.  We must
                    663:                 * check that the bignum really is more than 32 bits, and
                    664:                 * change it back to a 32-bit number if it fits.  The number we
                    665:                 * are looking for is expected to be positive, but if it fits
                    666:                 * into 32 bits as an unsigned number, we let it be a 32-bit
                    667:                 * number. The cavalier approach is for speed in ordinary cases.
                    668:                 */
                    669:                digit_2 = input_line_pointer;
                    670:                for(number = 0;
                    671:                    (digit = hex_value[(int)c]) < maxdig;
                    672:                    c = *input_line_pointer++){
                    673:                    number = number * radix + digit;
                    674:                }
                    675:                /* c contains character after number. */
                    676:                /* Input_line_pointer -> char after c. */
                    677:                small = input_line_pointer - digit_2 < too_many_digits;
                    678:                if(force_bignum == TRUE)
                    679:                      small = FALSE;
                    680:                if(small == FALSE){
                    681:                    /*
                    682:                     * Manufacture a bignum.
                    683:                     */
                    684:                    /* -> high order littlenum of the bignum. */
                    685:                    LITTLENUM_TYPE *leader;
                    686:                    /* -> littlenum we are frobbing now. */
                    687:                    LITTLENUM_TYPE *pointer;
                    688:                    long carry;
                    689: 
                    690:                    leader = generic_bignum;
                    691:                    generic_bignum [0] = 0;
                    692:                    /* We could just use digit_2, but lets be mnemonic. */
                    693:                    input_line_pointer = --digit_2; /* -> 1st digit. */
                    694:                    c = *input_line_pointer++;
                    695:                    for( ;
                    696:                        (carry = hex_value[(int)c]) < maxdig;
                    697:                        c = * input_line_pointer++){
                    698:                        for(pointer = generic_bignum;
                    699:                            pointer <= leader;
                    700:                            pointer++){
                    701:                            long work;
                    702: 
                    703:                            work = carry + radix * *pointer;
                    704:                            *pointer = work & LITTLENUM_MASK;
                    705:                            carry = work >> LITTLENUM_NUMBER_OF_BITS;
                    706:                        }
                    707:                        if(carry){
                    708:                            if(leader < generic_bignum +
                    709:                                        SIZE_OF_LARGE_NUMBER - 1){
                    710:                                        /* Room to grow a longer bignum. */
                    711:                                *++leader = carry;
                    712:                            }
                    713:                        }
                    714:                    }
                    715:                    /* Again, C is char after number, */
                    716:                    /* input_line_pointer -> after C. */
                    717:                    /* know(BITS_PER_INT == 32); */
                    718:                    know(LITTLENUM_NUMBER_OF_BITS == 16);
                    719:                    /* Hence the constant "2" in the next line. */
                    720:                    if(leader < generic_bignum + 2 && force_bignum == FALSE)
                    721:                    {           /* Will fit into 32 bits. */
                    722:                        number = ((generic_bignum[1] & LITTLENUM_MASK) <<
                    723:                                   LITTLENUM_NUMBER_OF_BITS) |
                    724:                                  (generic_bignum[0] & LITTLENUM_MASK);
                    725:                        small = TRUE;
                    726:                    }
                    727:                    else{
                    728:                        /* Number of littlenums in the bignum. */
                    729:                        number = leader - generic_bignum + 1;
                    730:                    }
                    731:                }
                    732:                if(small){
                    733:                    /*
                    734:                     * Here with number, in correct radix. c is the next char.
                    735:                     * Note that unlike Un*x, we allow "011f" "0x9f" to both
                    736:                     * mean the same as the (conventional) "9f". This is simply
                    737:                     * easier than checking for strict canonical form.
                    738:                     */
                    739:                    if(number < 10){
                    740:                        if(c == 'b'){
                    741:                            /*
                    742:                             * Backward ref to local label.
                    743:                             * Because it is backward, expect it to be DEFINED.
                    744:                             */
                    745:                            /*
                    746:                             * Construct a local label.
                    747:                             */
                    748:                            name = local_label_name((int)number, 0);
                    749:                            symbolP = symbol_table_lookup(name);
                    750:                            if((symbolP != NULL) &&
                    751:                               (symbolP->sy_type & N_TYPE) != N_UNDF){
                    752:                                /* Expected path: symbol defined. */
                    753:                                /* Local labels are never absolute. Don't waste
                    754:                                   time checking absoluteness. */
                    755:                                know((symbolP->sy_type & N_TYPE) == N_SECT);
                    756:                                expressionP->X_add_symbol = symbolP;
                    757:                                expressionP->X_add_number = 0;
                    758:                                expressionP->X_seg        = SEG_SECT;
                    759:                            }
                    760:                            else{ /* Either not seen or not defined. */
                    761:                                as_warn("Backw. ref to unknown label \"%d:\", 0"
                    762:                                        " assumed.", number);
                    763:                                expressionP->X_add_number = 0;
                    764:                                expressionP->X_seg        = SEG_ABSOLUTE;
                    765:                            }
                    766:                        }
                    767:                        else if(c == 'f'){
                    768:                            /*
                    769:                             * Forward reference. Expect symbol to be
                    770:                             * undefined or unknown. Undefined: seen it
                    771:                             * before. Unknown: never seen it in this pass.
                    772:                             * Construct a local label name, then an
                    773:                             * undefined symbol.  Don't create a XSEG frag
                    774:                             * for it: caller may do that.
                    775:                             * Just return it as never seen before.
                    776:                             */
                    777:                            name = local_label_name((int)number, 1);
                    778:                            symbolP = symbol_table_lookup(name);
                    779:                            if(symbolP != NULL){
                    780:                                /* We have no need to check symbol
                    781:                                   properties. */
                    782:                                know((symbolP->sy_type & N_TYPE) == N_UNDF ||
                    783:                                     (symbolP->sy_type & N_TYPE) == N_SECT);
                    784:                            }
                    785:                            else{
                    786:                                symbolP = symbol_new(name, N_UNDF, 0,0,0,
                    787:                                                     &zero_address_frag);
                    788:                                symbol_table_insert(symbolP);
                    789:                            }
                    790:                            expressionP->X_add_symbol      = symbolP;
                    791:                            expressionP->X_seg             = SEG_UNKNOWN;
                    792:                            expressionP->X_subtract_symbol = NULL;
                    793:                            expressionP->X_add_number      = 0;
                    794:                        }
                    795:                        else{   /* Really a number, not a local label. */
                    796:                            expressionP->X_add_number = number;
                    797:                            expressionP->X_seg        = SEG_ABSOLUTE;
                    798:                            input_line_pointer--; /* restore following char */
                    799:                        }
                    800:                    }
                    801:                    else{ /* a number >= 10 */
                    802:                        expressionP->X_add_number = number;
                    803:                        expressionP->X_seg        = SEG_ABSOLUTE;
                    804:                        input_line_pointer--; /* restore following char */
                    805:                    }
                    806:                } /* not a small number encode returning a bignum */
                    807:                else{
                    808:                    expressionP->X_add_number = number;
                    809:                    expressionP->X_seg = SEG_BIG;
                    810:                    input_line_pointer--; /* -> char following number. */
                    811:                } /* if (small) */
                    812:            } /* (If integer constant) */
                    813:            else{ /* input_line_pointer -> floating-point constant. */
                    814: 
                    815:                int error_code;
                    816: 
                    817:                error_code = atof_generic(&input_line_pointer, ".", md_EXP_CHARS,
                    818:                                          &generic_floating_point_number);
                    819: 
                    820:                if(error_code){
                    821:                    if(error_code == ERROR_EXPONENT_OVERFLOW){
                    822:                        as_warn("Bad floating-point constant: exponent "
                    823:                                "overflow, probably assembling junk" );
                    824:                    }
                    825:                    else{             
                    826:                        as_warn("Bad floating-point constant: unknown error "
                    827:                                "code=%d.", error_code);
                    828:                    }
                    829:                }
                    830:                expressionP->X_seg = SEG_BIG;
                    831:                /* input_line_pointer -> just after constant, */
                    832:                /* which may point to whitespace. */
                    833:                know(expressionP->X_add_number < 0);
                    834:                /* < 0 means "floating point". */
                    835:            }                   /* if (not floating-point constant) */
                    836:        }
                    837:        else if(c == '.' && !is_part_of_name(*input_line_pointer)){
                    838:            /*
                    839:             JF:  '.' is pseudo symbol with value of current location in current
                    840:             segment. . .
                    841:             */
                    842:            symbolP = symbol_new("L0\001",
                    843:                                 N_SECT,
                    844:                                 frchain_now->frch_nsect,
                    845:                                 0,
                    846:                                 (valueT)(obstack_next_free(&frags) -
                    847:                                          frag_now->fr_literal),
                    848:                                 frag_now);
                    849:            expressionP->X_add_number = 0;
                    850:            expressionP->X_add_symbol = symbolP;
                    851:            expressionP->X_seg = SEG_SECT;
                    852:        }
                    853:        /* here if did not begin with a digit */
                    854:        else if(is_name_beginner(c) || c == '"'){
                    855:            /*
                    856:             * Identifier begins here.
                    857:             * This is kludged for speed, so code is repeated.
                    858:             */
                    859:            q = c;
                    860:            if(q == '"')
                    861:                name = input_line_pointer-- ;
                    862:            else
                    863:            name =  -- input_line_pointer;
                    864:            c = get_symbol_end();
                    865:            symbolP = symbol_table_lookup(name);
                    866:            if(symbolP != NULL){
                    867:                /*
                    868:                 * If we have an absolute symbol, then we know it's value now.
                    869:                 */
                    870:                segT seg;
                    871: 
                    872:                seg = N_TYPE_seg[(int)symbolP->sy_type & N_TYPE];
                    873:                expressionP->X_seg = seg;
                    874:                if(seg == SEG_ABSOLUTE){
                    875:                    expressionP->X_add_number = symbolP->sy_value;
                    876:                }
                    877:                else{
                    878:                    expressionP->X_add_number = 0;
                    879:                    expressionP->X_add_symbol = symbolP;
                    880:                }
                    881:            }
                    882:            else{
                    883:                symbolP = symbol_new(name, N_UNDF, 0,0,0, &zero_address_frag);
                    884:                expressionP->X_add_symbol  = symbolP;
                    885:                expressionP->X_add_number  = 0;
                    886:                expressionP->X_seg         = SEG_UNKNOWN;
                    887:                symbol_table_insert(symbolP);
                    888:            }
                    889:            *input_line_pointer = c;
                    890:            if(q == '"')
                    891:                input_line_pointer[-1] = '"';
                    892:            expressionP->X_subtract_symbol = NULL;
                    893:        }
                    894:        /* didn't begin with digit & not a name */
                    895:        else if (c == '('){
                    896:            (void)expression(expressionP);
                    897:            /* Expression() will pass trailing whitespace */
                    898:            if(*input_line_pointer++ != ')'){
                    899:                as_warn("Missing ')' assumed");
                    900:                input_line_pointer--;
                    901:            }
                    902:            /* here with input_line_pointer -> char after "(...)" */
                    903:        }
                    904:        /* unary operator: hope for SEG_ABSOLUTE */
                    905:        else if(c == '~' || c == '-' || c == '!'){
                    906:            switch(operand(expressionP)){
                    907:            case SEG_ABSOLUTE:
                    908:                /* input_line_pointer -> char after operand */
                    909:                if(c == '-' ){
                    910:                   /*
                    911:                    * Notice: '-' may  overflow: no warning is given. This is
                    912:                    * compatible with other people's assemblers.
                    913:                    */
                    914:                    expressionP->X_add_number = - expressionP->X_add_number;
                    915:                }
                    916:                else if(c == '!'){
                    917:                    expressionP->X_add_number = ! expressionP->X_add_number;
                    918:                }
                    919:                else{
                    920:                    expressionP->X_add_number = ~ expressionP->X_add_number;
                    921:                }
                    922:                break;
                    923:            case SEG_SECT:
                    924:            case SEG_UNKNOWN:
                    925:                if(c == '-'){           /* JF I hope this hack works */
                    926:                    expressionP->X_subtract_symbol = expressionP->X_add_symbol;
                    927:                    expressionP->X_add_symbol = 0;
                    928:                    expressionP->X_seg = SEG_DIFFSECT;
                    929:                    break;
                    930:                }
                    931:            default: /* unary on non-absolute is unsuported */
                    932:                as_warn("Unary operator %c ignored because bad operand follows",
                    933:                        c);
                    934:                break;
                    935:                /* Expression undisturbed from operand(). */
                    936:            }
                    937:        }
                    938:        /*
                    939:         * Warning: to conform to other people's assemblers NO ESCAPEMENT is
                    940:         * permitted for a single quote.  The next character, parity errors and
                    941:         * all, is taken as the value of the operand. VERY KINKY.
                    942:         */
                    943:        else if(c == '\''){
                    944:            expressionP->X_add_number = *input_line_pointer++;
                    945:            expressionP->X_seg        = SEG_ABSOLUTE;
                    946:        }
                    947:        /* can't imagine any other kind of operand */
                    948:        else{
                    949:            expressionP->X_seg = SEG_NONE;
                    950:            input_line_pointer--;
                    951:        }
                    952:        /*
                    953:         * It is more 'efficient' to clean up the expressions when they are
                    954:         * created.  Doing it here saves lines of code.
                    955:         */
                    956:        clean_up_expression(expressionP);
                    957:        SKIP_WHITESPACE();              /* -> 1st char after operand. */
                    958:        know(*input_line_pointer != ' ');
                    959:        return(expressionP->X_seg);
                    960: }
                    961: 
                    962: /* Internal. Simplify a struct expression for use by expr() */
                    963: 
                    964: /*
                    965:  * In: address of a expressionS.
                    966:  *     The X_seg field of the expressionS may only take certain values.
                    967:  *     Now, we permit SEG_NONE to make code smaller & faster.
                    968:  *     Elsewise we waste time special-case testing. Sigh.
                    969:  * Out:        expressionS may have been modified:
                    970:  *     'foo-foo' symbol references cancelled to 0,
                    971:  *             which changes X_seg from SEG_DIFFSECT to SEG_ABSOLUTE;
                    972:  *     Unused fields zeroed to help expr().
                    973:  */
                    974: static
                    975: void
                    976: clean_up_expression(
                    977: expressionS *expressionP)
                    978: {
                    979:        switch(expressionP->X_seg){
                    980:        case SEG_NONE:
                    981:            expressionP->X_add_symbol           = NULL;
                    982:            expressionP->X_subtract_symbol      = NULL;
                    983:            expressionP->X_add_number           = 0;
                    984:            break;
                    985: 
                    986:        case SEG_BIG:
                    987:        case SEG_ABSOLUTE:
                    988:            expressionP->X_subtract_symbol      = NULL;
                    989:            expressionP->X_add_symbol           = NULL;
                    990:            break;
                    991: 
                    992:        case SEG_SECT:
                    993:        case SEG_UNKNOWN:
                    994:            expressionP->X_subtract_symbol      = NULL;
                    995:            break;
                    996: 
                    997:        case SEG_DIFFSECT:
                    998:            /*
                    999:             * It does not hurt to 'cancel' NULL==NULL
                   1000:             * when comparing symbols for 'eq'ness.
                   1001:             * It is faster to re-cancel them to NULL
                   1002:             * than to check for this special case.
                   1003:             */
                   1004:            if(expressionP->X_subtract_symbol == expressionP->X_add_symbol){
                   1005:                expressionP->X_subtract_symbol  = NULL;
                   1006:                expressionP->X_add_symbol       = NULL;
                   1007:                expressionP->X_seg              = SEG_ABSOLUTE;
                   1008:            }
                   1009:            break;
                   1010: 
                   1011:        default:
                   1012:            BAD_CASE(expressionP->X_seg);
                   1013:            break;
                   1014:        }
                   1015: }
                   1016: 
                   1017: /*
                   1018:  *                     expr_part ()
                   1019:  *
                   1020:  * Internal. Made a function because this code is used in 2 places.
                   1021:  * Generate error or correct X_?????_symbol of expressionS.
                   1022:  */
                   1023: 
                   1024: /*
                   1025: Combine and subsume symbol2 into symbol1 where the symbols come from
                   1026:     expression's add or subtract symbols.
                   1027: The combining always occurs even if it would be an error.
                   1028: Either symbol maybe NULL which means there is no symbol.
                   1029:     In that case symbol1 is set to the non NULL symbol.
                   1030:     If both are NULL then SEG_ABSOLUTE is returned.
                   1031: Either symbol maybe undefined.
                   1032: The only combinations that are not errors are when one symbol does not exist.
                   1033:     if one symbol is undefined and the other doesn't exist SEG_UNKNOWN is
                   1034:      returned.
                   1035: For errant combinations symbol1 is set to NULL and SEG_ABSOLUTE (or -1
                   1036:     (SEG_PASS1) when one of the symbols is undefined and the other exists)
                   1037: 
                   1038:  * symbol_1 += symbol_2 ... well ... sort of.
                   1039:  * symbol_1 -= symbol_2 ... well ... sort of.
                   1040:  */
                   1041: 
                   1042: static
                   1043: segT
                   1044: expr_part(
                   1045: struct symbol **symbol_1_PP,
                   1046: struct symbol *symbol_2_P)
                   1047: {
                   1048:     segT return_value;
                   1049: 
                   1050: /* The symbols can't be N_ABS as they are in expressions and whould just have
                   1051:    their value copied into the X_add_number part. */
                   1052:        know( (*symbol_1_PP)                    == NULL   ||
                   1053:             ((*symbol_1_PP)->sy_type & N_TYPE) == N_SECT ||
                   1054:             ((*symbol_1_PP)->sy_type & N_TYPE) == N_UNDF);
                   1055: 
                   1056:        know( symbol_2_P                    == NULL   ||
                   1057:             (symbol_2_P->sy_type & N_TYPE) == N_SECT ||
                   1058:             (symbol_2_P->sy_type & N_TYPE) == N_UNDF);
                   1059: 
                   1060:        /* check to see if there is a symbol1 */
                   1061:        if(*symbol_1_PP != NULL){
                   1062:            /* there is a symbol1 */
                   1063: 
                   1064:            /* check to see if symbol1 is undefined */
                   1065:            if(((*symbol_1_PP)->sy_type & N_TYPE) == N_UNDF){
                   1066:                /* symbol1 is undefined */
                   1067: 
                   1068:                /* check to see if there is a symbol2 */
                   1069:                if(symbol_2_P != NULL){
                   1070:                    /* symbol1 is undefined and there is a symbol2 */
                   1071:                    *symbol_1_PP = NULL;
                   1072:                    return_value = -1;
                   1073:                }
                   1074:                else{
                   1075:                    /* symbol1 is undefined and there is no symbol2 */
                   1076:                    return_value = SEG_UNKNOWN;
                   1077:                }
                   1078:            }
                   1079:            else{
                   1080:                /* there is a defined symbol1 */
                   1081: 
                   1082:                /* check to see if there is a symbol2 */
                   1083:                if(symbol_2_P != NULL){
                   1084:                    /* there is a symbol2 */
                   1085: 
                   1086:                    /* check to see if symbol2 is undefined */
                   1087:                    if((symbol_2_P->sy_type & N_TYPE) == N_UNDF){
                   1088:                        /* symbol2 is undefined and symbol1 is defined */
                   1089:                        *symbol_1_PP = NULL;
                   1090:                        return_value = -1;
                   1091:                    }
                   1092:                    else{
                   1093:                        /* symbol1 is defined and symbol2 is defined */
                   1094:                        /* + {symbol1} + {symbol2}  or */
                   1095:                        /* - {symbol1} - {symbol2} */
                   1096:                        as_warn("Expression too complex, 2 symbols forgotten: "
                   1097:                                "\"%s\" \"%s\"", (*symbol_1_PP)->sy_name,
                   1098:                                symbol_2_P->sy_name);
                   1099:                        *symbol_1_PP = NULL;
                   1100:                        return_value = SEG_ABSOLUTE;
                   1101:                    }
                   1102:                }
                   1103:                else{
                   1104:                    /* symbol1 is defined and there is no symbol2 */
                   1105:                    return_value = N_TYPE_seg[(*symbol_1_PP)->sy_type & N_TYPE];
                   1106:                }
                   1107:            }
                   1108:        }
                   1109:        else{
                   1110:            /* there is no symbol1 */
                   1111: 
                   1112:            /* check to see if there is a symbol2 */
                   1113:            if(symbol_2_P != NULL){
                   1114:                /* symbol2 is defined and there is no symbol1 */
                   1115:                *symbol_1_PP = symbol_2_P;
                   1116:                return_value = N_TYPE_seg[(symbol_2_P)->sy_type & N_TYPE];
                   1117:            }
                   1118:            else{
                   1119:                /* there is no symbol1 or symbol2 */
                   1120: /* ??? why not SEG_UNKNOWN or SEG_NONE */
                   1121:                return_value = SEG_ABSOLUTE;
                   1122:            }
                   1123:        }
                   1124: 
                   1125:        know(return_value == SEG_ABSOLUTE ||
                   1126:             return_value == SEG_SECT     ||
                   1127:             return_value == SEG_UNKNOWN  ||
                   1128:             return_value == -1);
                   1129:        know((*symbol_1_PP) == NULL ||
                   1130:             ((*symbol_1_PP)->sy_type & N_TYPE) ==
                   1131:                seg_N_TYPE[(int)return_value]);
                   1132: 
                   1133:        return(return_value);
                   1134: }
                   1135: 
                   1136: /*
                   1137:  *  DJA -- Here we make a last ditch effort to turn expressions into
                   1138:  *     absolutes.  This is particularly useful for doing arithemtic
                   1139:  *     on already declared labels, for example in going through the
                   1140:  *     following table the moveq can really be evaluated.
                   1141:  *
                   1142:  *     start:  .word   1
                   1143:  *             .word   2
                   1144:  *             .word   3
                   1145:  *     end:
                   1146:  *             lea     start,a0
                   1147:  *             moveq   #((end-start) / 2) + 1,d0
                   1148:  *     loop:   cmpw    d1,a0@+
                   1149:  *             dbra    d0,loop
                   1150:  */
                   1151: segT /* Return expressionP->X_seg. */
                   1152: try_to_make_absolute(
                   1153: expressionS *expressionP) /* Deliver result here. */
                   1154: {
                   1155:     symbolS *add_symbol;
                   1156:     symbolS *subtract_symbol;
                   1157: 
                   1158:        if(expressionP->X_seg == SEG_DIFFSECT){
                   1159: 
                   1160:            add_symbol = expressionP->X_add_symbol;
                   1161:            if(add_symbol == NULL)
                   1162:                goto giveup;
                   1163:            if((add_symbol->sy_type & N_TYPE) != N_SECT)
                   1164:                goto giveup;
                   1165: 
                   1166:            subtract_symbol = expressionP->X_subtract_symbol;
                   1167:            if(subtract_symbol == NULL)
                   1168:                goto giveup;
                   1169:            if((subtract_symbol->sy_type & N_TYPE) != N_SECT)
                   1170:                goto giveup;
                   1171: 
                   1172:            if(add_symbol->sy_frag == subtract_symbol->sy_frag){
                   1173:                if(add_symbol->sy_frag != NULL &&
                   1174:                   expressionP->X_add_number +
                   1175:                   (int)add_symbol->sy_value -
                   1176:                   (int)subtract_symbol->sy_value >= 0){
                   1177:                    expressionP->X_add_number += add_symbol->sy_value -
                   1178:                                                 subtract_symbol->sy_value;
                   1179:                    expressionP->X_seg = SEG_ABSOLUTE;
                   1180:                    expressionP->X_add_symbol = NULL;
                   1181:                    expressionP->X_subtract_symbol = NULL;
                   1182: 
                   1183:                }
                   1184:            }
                   1185:            else{
                   1186:                /*
                   1187:                 * This logic works only if the chain of frags can't later be
                   1188:                 * separated by scattered loading.  To make sure that this can't
                   1189:                 * happen we would have to make sure all symbols associated with
                   1190:                 * frags in the chain are of the Lx form and the -L flag is not
                   1191:                 * see so they will not appear in the output (if they are not in
                   1192:                 * the output then the link editor can't separate the chain of
                   1193:                 * frags by scattered loading).  Since this code does not make
                   1194:                 * sure of this it is broken.  But this is a known bug in the
                   1195:                 * NeXT 3.2 and earilier releases so this code is if'ed
                   1196:                 * !flagseen['k'] which will make it compatable with 3.2 and
                   1197:                 * previous releases.
                   1198:                 */
                   1199:                if(!flagseen['k']){
                   1200:                    /*
                   1201:                     * Try to see if the chain of frags between the subtract
                   1202:                     * symbol and the add symbol is made up of only rs_fill and
                   1203:                     * rs_align frags and then calculate the difference.  This
                   1204:                     * will always work on RISC machines since they won't have
                   1205:                     * any machine dependent frags of variable length in the
                   1206:                     * chain.
                   1207:                     */
                   1208:                    unsigned long size, fail;
                   1209:                    struct frag *frag;
                   1210: 
                   1211:                    if(add_symbol->sy_frag != NULL &&
                   1212:                       subtract_symbol->sy_frag != NULL){
                   1213:                        fail = 0;
                   1214:                        size = 0;
                   1215:                        frag = subtract_symbol->sy_frag;
                   1216:                        while(!fail && frag != NULL &&
                   1217:                              frag != add_symbol->sy_frag){
                   1218:                            if(frag->fr_type == rs_align)
                   1219:                                size = round(size + frag->fr_fix,
                   1220:                                             1 << frag->fr_offset);
                   1221:                            else if(frag->fr_type == rs_fill)
                   1222:                                size += frag->fr_fix +
                   1223:                                        frag->fr_var * frag->fr_offset;
                   1224:                            else
                   1225:                                fail = 1;
                   1226:                            frag = frag->fr_next;
                   1227:                        }
                   1228: 
                   1229:                        if(!fail && frag == add_symbol->sy_frag){
                   1230:                            expressionP->X_add_number = size +
                   1231:                                add_symbol->sy_value -
                   1232:                                subtract_symbol->sy_value;
                   1233:                            expressionP->X_seg = SEG_ABSOLUTE;
                   1234:                            expressionP->X_add_symbol = NULL;
                   1235:                            expressionP->X_subtract_symbol = NULL;
                   1236:                        }
                   1237:                    }
                   1238:                }
                   1239:            }
                   1240:        }
                   1241: giveup:
                   1242: 
                   1243:        return(expressionP->X_seg);
                   1244: }
                   1245: 
                   1246: /*
                   1247:  * two_char_op_encoding() return the operator type for two character operators.
                   1248:  * The first_op_char is part of a two character operator and this routine is
                   1249:  * then used to determine the operator type looking at the second character.
                   1250:  */
                   1251: static
                   1252: operatorT
                   1253: two_char_op_encoding(
                   1254: char first_op_char)
                   1255: {
                   1256:     char second_op_char;
                   1257: 
                   1258:        second_op_char = input_line_pointer[1];
                   1259:        switch(first_op_char){
                   1260:        case '<':
                   1261:            if(second_op_char == '<')
                   1262:                return(O_left_shift);
                   1263:            if(second_op_char == '=')
                   1264:                return(O_less_than_or_equal);
                   1265:            if(second_op_char == '>')
                   1266:                return(O_not_equal);
                   1267:            return(O_less_than);
                   1268:        case '>':
                   1269:            if(second_op_char == '>')
                   1270:                return(O_right_shift);
                   1271:            if(second_op_char == '=')
                   1272:                return(O_greater_than_or_equal);
                   1273:            return(O_greater_than);
                   1274:        case '=':
                   1275:            if(second_op_char == '=')
                   1276:                return(O_equal);
                   1277:            return(O_illegal);
                   1278:        case '!':
                   1279:            if(second_op_char == '=')
                   1280:                return(O_not_equal);
                   1281:            return O_not_equal;
                   1282:        default:
                   1283:            BAD_CASE(first_op_char);
                   1284:            return O_illegal;
                   1285:        }
                   1286: }
                   1287: 
                   1288: /*
                   1289:  *                     get_symbol_end()
                   1290:  *
                   1291:  * This lives here because it belongs equally in expr.c & read.c.
                   1292:  * Expr.c is just a branch office read.c anyway, and putting it
                   1293:  * here lessens the crowd at read.c.
                   1294:  *
                   1295:  * Assume input_line_pointer is at start of symbol name.
                   1296:  * Advance input_line_pointer past symbol name.
                   1297:  * Turn that character into a '\0', returning its former value.
                   1298:  * This allows a string compare (RMS wants symbol names to be strings)
                   1299:  * of the symbol name.
                   1300:  * There will always be a char following symbol name, because all good
                   1301:  * lines end in end-of-line.
                   1302:  */
                   1303: char
                   1304: get_symbol_end(
                   1305: void)
                   1306: {
                   1307:     register char c;
                   1308: 
                   1309:        /*
                   1310:         * Symbol names are allowed to have surrounding ""s so that names can
                   1311:         * have any characters in them (including spacesi, colons, etc).  This
                   1312:         * is done so names like "[Foo bar:fuz:]" can be used as symbol names.
                   1313:         */
                   1314:        if(*input_line_pointer == '"'){
                   1315:            input_line_pointer++;
                   1316:            do{
                   1317:                c = *input_line_pointer++ ;
                   1318:            }while(c != '"' && c != '\0' && c != '\n');
                   1319:            if(c == '"'){
                   1320:                *(input_line_pointer - 1) = 0;
                   1321:                c = *input_line_pointer++;
                   1322:            }
                   1323:        }
                   1324:        else{
                   1325:            while(is_part_of_name(c = *input_line_pointer++))
                   1326:                ;
                   1327:        }
                   1328:        *--input_line_pointer = 0;
                   1329:        return(c);
                   1330: }

unix.superglobalmegacorp.com

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