Annotation of GNUtools/cctools/as/expr.c, revision 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.