Annotation of 43BSDReno/contrib/emacs-18.55/gdb/valops.c, revision 1.1

1.1     ! root        1: /* Perform non-arithmetic operations on values, for GDB.
        !             2:    Copyright (C) 1986, 1987 Free Software Foundation, Inc.
        !             3: 
        !             4: GDB is distributed in the hope that it will be useful, but WITHOUT ANY
        !             5: WARRANTY.  No author or distributor accepts responsibility to anyone
        !             6: for the consequences of using it or for whether it serves any
        !             7: particular purpose or works at all, unless he says so in writing.
        !             8: Refer to the GDB General Public License for full details.
        !             9: 
        !            10: Everyone is granted permission to copy, modify and redistribute GDB,
        !            11: but only under the conditions described in the GDB General Public
        !            12: License.  A copy of this license is supposed to have been given to you
        !            13: along with GDB so you can know your rights and responsibilities.  It
        !            14: should be in a file named COPYING.  Among other things, the copyright
        !            15: notice and this notice must be preserved on all copies.
        !            16: 
        !            17: In other words, go ahead and share GDB, but don't try to stop
        !            18: anyone else from sharing it farther.  Help stamp out software hoarding!
        !            19: */
        !            20: 
        !            21: #include "defs.h"
        !            22: #include "initialize.h"
        !            23: #include "param.h"
        !            24: #include "symtab.h"
        !            25: #include "value.h"
        !            26: 
        !            27: START_FILE
        !            28: 
        !            29: /* Cast value ARG2 to type TYPE and return as a value.
        !            30:    More general than a C cast: accepts any two types of the same length,
        !            31:    and if ARG2 is an lvalue it can be cast into anything at all.  */
        !            32: 
        !            33: value
        !            34: value_cast (type, arg2)
        !            35:      struct type *type;
        !            36:      register value arg2;
        !            37: {
        !            38:   register enum type_code code1;
        !            39:   register enum type_code code2;
        !            40:   register int scalar;
        !            41: 
        !            42:   /* Coerce arrays but not enums.  Enums will work as-is
        !            43:      and coercing them would cause an infinite recursion.  */
        !            44:   if (TYPE_CODE (VALUE_TYPE (arg2)) != TYPE_CODE_ENUM)
        !            45:     COERCE_ARRAY (arg2);
        !            46: 
        !            47:   code1 = TYPE_CODE (type);
        !            48:   code2 = TYPE_CODE (VALUE_TYPE (arg2));
        !            49:   scalar = (code2 == TYPE_CODE_INT || code2 == TYPE_CODE_FLT
        !            50:            || code2 == TYPE_CODE_ENUM);
        !            51: 
        !            52:   if (code1 == TYPE_CODE_FLT && scalar)
        !            53:     return value_from_double (type, value_as_double (arg2));
        !            54:   else if ((code1 == TYPE_CODE_INT || code1 == TYPE_CODE_ENUM)
        !            55:           && (scalar || code2 == TYPE_CODE_PTR))
        !            56:     return value_from_long (type, value_as_long (arg2));
        !            57:   else if (TYPE_LENGTH (type) == TYPE_LENGTH (VALUE_TYPE (arg2)))
        !            58:     {
        !            59:       VALUE_TYPE (arg2) = type;
        !            60:       return arg2;
        !            61:     }
        !            62:   else if (VALUE_LVAL (arg2) == lval_memory)
        !            63:     return value_at (type, VALUE_ADDRESS (arg2) + VALUE_OFFSET (arg2));
        !            64:   else
        !            65:     error ("Invalid cast.");
        !            66: }
        !            67: 
        !            68: /* Return the value with a specified type located at specified address.  */
        !            69: 
        !            70: value
        !            71: value_at (type, addr)
        !            72:      struct type *type;
        !            73:      CORE_ADDR addr;
        !            74: {
        !            75:   register value val = allocate_value (type);
        !            76: 
        !            77:   read_memory (addr, VALUE_CONTENTS (val), TYPE_LENGTH (type));
        !            78:   VALUE_LVAL (val) = lval_memory;
        !            79:   VALUE_ADDRESS (val) = addr;
        !            80: 
        !            81:   return val;
        !            82: }
        !            83: 
        !            84: /* Store the contents of FROMVAL into the location of TOVAL.
        !            85:    Return a new value with the location of TOVAL and contents of FROMVAL.  */
        !            86: 
        !            87: value
        !            88: value_assign (toval, fromval)
        !            89:      register value toval, fromval;
        !            90: {
        !            91:   register struct type *type = VALUE_TYPE (toval);
        !            92:   register value val;
        !            93:   char raw_buffer[MAX_REGISTER_RAW_SIZE];
        !            94:   char virtual_buffer[MAX_REGISTER_VIRTUAL_SIZE];
        !            95:   int use_buffer = 0;
        !            96: 
        !            97:   COERCE_ARRAY (fromval);
        !            98: 
        !            99:   if (VALUE_LVAL (toval) != lval_internalvar)
        !           100:     fromval = value_cast (type, fromval);
        !           101: 
        !           102:   /* If TOVAL is a special machine register requiring conversion
        !           103:      of program values to a special raw format,
        !           104:      convert FROMVAL's contents now, with result in `raw_buffer',
        !           105:      and set USE_BUFFER to the number of bytes to write.  */
        !           106:      
        !           107:   if (VALUE_REGNO (toval) >= 0
        !           108:       && REGISTER_CONVERTIBLE (VALUE_REGNO (toval)))
        !           109:     {
        !           110:       int regno = VALUE_REGNO (toval);
        !           111:       if (VALUE_TYPE (fromval) != REGISTER_VIRTUAL_TYPE (regno))
        !           112:        fromval = value_cast (REGISTER_VIRTUAL_TYPE (regno), fromval);
        !           113:       bcopy (VALUE_CONTENTS (fromval), virtual_buffer,
        !           114:             REGISTER_VIRTUAL_SIZE (regno));
        !           115:       REGISTER_CONVERT_TO_RAW (regno, virtual_buffer, raw_buffer);
        !           116:       use_buffer = REGISTER_RAW_SIZE (regno);
        !           117:     }
        !           118: 
        !           119:   switch (VALUE_LVAL (toval))
        !           120:     {
        !           121:     case lval_internalvar:
        !           122:       set_internalvar (VALUE_INTERNALVAR (toval), fromval);
        !           123:       break;
        !           124: 
        !           125:     case lval_internalvar_component:
        !           126:       set_internalvar_component (VALUE_INTERNALVAR (toval),
        !           127:                                 VALUE_OFFSET (toval),
        !           128:                                 VALUE_BITPOS (toval),
        !           129:                                 VALUE_BITSIZE (toval),
        !           130:                                 fromval);
        !           131:       break;
        !           132: 
        !           133:     case lval_memory:
        !           134:       if (VALUE_BITSIZE (toval))
        !           135:        {
        !           136:          int val;
        !           137:          read_memory (VALUE_ADDRESS (toval) + VALUE_OFFSET (toval),
        !           138:                       &val, sizeof val);
        !           139:          modify_field (&val, value_as_long (fromval),
        !           140:                        VALUE_BITPOS (toval), VALUE_BITSIZE (toval));
        !           141:          write_memory (VALUE_ADDRESS (toval) + VALUE_OFFSET (toval),
        !           142:                        &val, sizeof val);
        !           143:        }
        !           144:       else if (use_buffer)
        !           145:        write_memory (VALUE_ADDRESS (toval) + VALUE_OFFSET (toval),
        !           146:                      raw_buffer, use_buffer);
        !           147:       else
        !           148:        write_memory (VALUE_ADDRESS (toval) + VALUE_OFFSET (toval),
        !           149:                      VALUE_CONTENTS (fromval), TYPE_LENGTH (type));
        !           150:       break;
        !           151: 
        !           152:     case lval_register:
        !           153:       if (VALUE_BITSIZE (toval))
        !           154:        {
        !           155:          int val;
        !           156: 
        !           157:          read_register_bytes (VALUE_ADDRESS (toval) + VALUE_OFFSET (toval),
        !           158:                               &val, sizeof val);
        !           159:          modify_field (&val, value_as_long (fromval),
        !           160:                        VALUE_BITPOS (toval), VALUE_BITSIZE (toval));
        !           161:          write_register_bytes (VALUE_ADDRESS (toval) + VALUE_OFFSET (toval),
        !           162:                                &val, sizeof val);
        !           163:        }
        !           164:       else if (use_buffer)
        !           165:        write_register_bytes (VALUE_ADDRESS (toval) + VALUE_OFFSET (toval),
        !           166:                              raw_buffer, use_buffer);
        !           167:       else
        !           168:        write_register_bytes (VALUE_ADDRESS (toval) + VALUE_OFFSET (toval),
        !           169:                              VALUE_CONTENTS (fromval), TYPE_LENGTH (type));
        !           170:       break;
        !           171: 
        !           172:     default:
        !           173:       error ("Left side of = operation is not an lvalue.");
        !           174:     }
        !           175: 
        !           176:   /* Return a value just like TOVAL except with the contents of FROMVAL.  */
        !           177: 
        !           178:   val = allocate_value (type);
        !           179:   bcopy (toval, val, VALUE_CONTENTS (val) - (char *) val);
        !           180:   bcopy (VALUE_CONTENTS (fromval), VALUE_CONTENTS (val), TYPE_LENGTH (type));
        !           181: 
        !           182:   return val;
        !           183: }
        !           184: 
        !           185: /* Extend a value VAL to COUNT repetitions of its type.  */
        !           186: 
        !           187: value
        !           188: value_repeat (arg1, count)
        !           189:      value arg1;
        !           190:      int count;
        !           191: {
        !           192:   register value val;
        !           193: 
        !           194:   if (VALUE_LVAL (arg1) != lval_memory)
        !           195:     error ("Only values in memory can be extended with '@'.");
        !           196:   if (count < 1)
        !           197:     error ("Invalid number %d of repetitions.", count);
        !           198: 
        !           199:   val = allocate_repeat_value (VALUE_TYPE (arg1), count);
        !           200: 
        !           201:   read_memory (VALUE_ADDRESS (arg1) + VALUE_OFFSET (arg1),
        !           202:               VALUE_CONTENTS (val),
        !           203:               TYPE_LENGTH (VALUE_TYPE (val)) * count);
        !           204:   VALUE_LVAL (val) = lval_memory;
        !           205:   VALUE_ADDRESS (val) = VALUE_ADDRESS (arg1) + VALUE_OFFSET (arg1);
        !           206: 
        !           207:   return val;
        !           208: }
        !           209: 
        !           210: value
        !           211: value_of_variable (var)
        !           212:      struct symbol *var;
        !           213: {
        !           214:   return read_var_value (var, (CORE_ADDR) 0);
        !           215: }
        !           216: 
        !           217: /* Given a value which is an array, return a value which is
        !           218:    a pointer to its first element.  */
        !           219: 
        !           220: value
        !           221: value_coerce_array (arg1)
        !           222:      value arg1;
        !           223: {
        !           224:   register struct type *type;
        !           225:   register value val;
        !           226: 
        !           227:   if (VALUE_LVAL (arg1) != lval_memory)
        !           228:     error ("Attempt to take address of value not located in memory.");
        !           229: 
        !           230:   /* Get type of elements.  */
        !           231:   if (TYPE_CODE (VALUE_TYPE (arg1)) == TYPE_CODE_ARRAY)
        !           232:     type = TYPE_TARGET_TYPE (VALUE_TYPE (arg1));
        !           233:   else
        !           234:     /* A phony array made by value_repeat.
        !           235:        Its type is the type of the elements, not an array type.  */
        !           236:     type = VALUE_TYPE (arg1);
        !           237: 
        !           238:   /* Get the type of the result.  */
        !           239:   type = lookup_pointer_type (type);
        !           240:   val = value_from_long (builtin_type_long,
        !           241:                         VALUE_ADDRESS (arg1) + VALUE_OFFSET (arg1));
        !           242:   VALUE_TYPE (val) = type;
        !           243:   return val;
        !           244: }
        !           245: 
        !           246: /* Return a pointer value for the object for which ARG1 is the contents.  */
        !           247: 
        !           248: value
        !           249: value_addr (arg1)
        !           250:      value arg1;
        !           251: {
        !           252:   register struct type *type;
        !           253:   register value val, arg1_coerced;
        !           254: 
        !           255:   /* Taking the address of an array is really a no-op
        !           256:      once the array is coerced to a pointer to its first element.  */
        !           257:   arg1_coerced = arg1;
        !           258:   COERCE_ARRAY (arg1_coerced);
        !           259:   if (arg1 != arg1_coerced)
        !           260:     return arg1_coerced;
        !           261: 
        !           262:   if (VALUE_LVAL (arg1) != lval_memory)
        !           263:     error ("Attempt to take address of value not located in memory.");
        !           264: 
        !           265:   /* Get the type of the result.  */
        !           266:   type = lookup_pointer_type (VALUE_TYPE (arg1));
        !           267:   val = value_from_long (builtin_type_long,
        !           268:                         VALUE_ADDRESS (arg1) + VALUE_OFFSET (arg1));
        !           269:   VALUE_TYPE (val) = type;
        !           270:   return val;
        !           271: }
        !           272: 
        !           273: /* Given a value of a pointer type, apply the C unary * operator to it.  */
        !           274: 
        !           275: value
        !           276: value_ind (arg1)
        !           277:      value arg1;
        !           278: {
        !           279:   COERCE_ARRAY (arg1);
        !           280: 
        !           281:   /* Allow * on an integer so we can cast it to whatever we want.  */
        !           282:   if (TYPE_CODE (VALUE_TYPE (arg1)) == TYPE_CODE_INT)
        !           283:     return value_at (builtin_type_long, 
        !           284:                     (CORE_ADDR) value_as_long (arg1));
        !           285:   else if (TYPE_CODE (VALUE_TYPE (arg1)) == TYPE_CODE_PTR)
        !           286:     return value_at (TYPE_TARGET_TYPE (VALUE_TYPE (arg1)),
        !           287:                     (CORE_ADDR) value_as_long (arg1));
        !           288:   error ("Attempt to take contents of a non-pointer value.");
        !           289: }
        !           290: 
        !           291: /* Pushing small parts of stack frames.  */
        !           292: 
        !           293: /* Push one word (the size of object that a register holds).  */
        !           294: 
        !           295: CORE_ADDR
        !           296: push_word (sp, buffer)
        !           297:      CORE_ADDR sp;
        !           298:      REGISTER_TYPE buffer;
        !           299: {
        !           300:   register int len = sizeof (REGISTER_TYPE);
        !           301: 
        !           302: #if 1 INNER_THAN 2
        !           303:   sp -= len;
        !           304:   write_memory (sp, &buffer, len);
        !           305: #else /* stack grows upward */
        !           306:   write_memory (sp, &buffer, len);
        !           307:   sp += len;
        !           308: #endif /* stack grows upward */
        !           309: 
        !           310:   return sp;
        !           311: }
        !           312: 
        !           313: /* Push LEN bytes with data at BUFFER.  */
        !           314: 
        !           315: CORE_ADDR
        !           316: push_bytes (sp, buffer, len)
        !           317:      CORE_ADDR sp;
        !           318:      char *buffer;
        !           319:      int len;
        !           320: {
        !           321: #if 1 INNER_THAN 2
        !           322:   sp -= len;
        !           323:   write_memory (sp, buffer, len);
        !           324: #else /* stack grows upward */
        !           325:   write_memory (sp, buffer, len);
        !           326:   sp += len;
        !           327: #endif /* stack grows upward */
        !           328: 
        !           329:   return sp;
        !           330: }
        !           331: 
        !           332: /* Push onto the stack the specified value VALUE.  */
        !           333: 
        !           334: CORE_ADDR
        !           335: value_push (sp, arg)
        !           336:      register CORE_ADDR sp;
        !           337:      value arg;
        !           338: {
        !           339:   register int len = TYPE_LENGTH (VALUE_TYPE (arg));
        !           340: 
        !           341: #if 1 INNER_THAN 2
        !           342:   sp -= len;
        !           343:   write_memory (sp, VALUE_CONTENTS (arg), len);
        !           344: #else /* stack grows upward */
        !           345:   write_memory (sp, VALUE_CONTENTS (arg), len);
        !           346:   sp += len;
        !           347: #endif /* stack grows upward */
        !           348: 
        !           349:   return sp;
        !           350: }
        !           351: 
        !           352: /* Perform the standard coercions that are specified
        !           353:    for arguments to be passed to C functions.  */
        !           354: 
        !           355: value
        !           356: value_arg_coerce (arg)
        !           357:      value arg;
        !           358: {
        !           359:   register struct type *type;
        !           360: 
        !           361:   COERCE_ENUM (arg);
        !           362: 
        !           363:   type = VALUE_TYPE (arg);
        !           364: 
        !           365:   if (TYPE_CODE (type) == TYPE_CODE_INT
        !           366:       && TYPE_LENGTH (type) < sizeof (int))
        !           367:     return value_cast (builtin_type_int, arg);
        !           368: 
        !           369:   if (type == builtin_type_float)
        !           370:     return value_cast (builtin_type_double, arg);
        !           371: 
        !           372:   return arg;
        !           373: }
        !           374: 
        !           375: /* Push the value ARG, first coercing it as an argument
        !           376:    to a C function.  */
        !           377: 
        !           378: CORE_ADDR
        !           379: value_arg_push (sp, arg)
        !           380:      register CORE_ADDR sp;
        !           381:      value arg;
        !           382: {
        !           383:   return value_push (sp, value_arg_coerce (arg));
        !           384: }
        !           385: 
        !           386: /* Perform a function call in the inferior.
        !           387:    ARGS is a vector of values of arguments (NARGS of them).
        !           388:    FUNCTION is a value, the function to be called.
        !           389:    Returns a value representing what the function returned.
        !           390:    May fail to return, if a breakpoint or signal is hit
        !           391:    during the execution of the function.  */
        !           392: 
        !           393: value
        !           394: call_function (function, nargs, args)
        !           395:      value function;
        !           396:      int nargs;
        !           397:      value *args;
        !           398: {
        !           399:   register CORE_ADDR sp;
        !           400:   register int i;
        !           401:   CORE_ADDR start_sp;
        !           402:   static REGISTER_TYPE dummy[] = CALL_DUMMY;
        !           403:   REGISTER_TYPE dummy1[sizeof dummy / sizeof (REGISTER_TYPE)];
        !           404:   CORE_ADDR old_sp;
        !           405:   struct type *value_type;
        !           406: 
        !           407:   PUSH_DUMMY_FRAME;
        !           408: 
        !           409:   {
        !           410:     register CORE_ADDR funaddr;
        !           411:     register struct type *ftype = VALUE_TYPE (function);
        !           412:     register enum type_code code = TYPE_CODE (ftype);
        !           413: 
        !           414:     /* Determine address to call.  */
        !           415:     if (code == TYPE_CODE_FUNC)
        !           416:       {
        !           417:        funaddr = VALUE_ADDRESS (function);
        !           418:        value_type = TYPE_TARGET_TYPE (ftype);
        !           419:       }
        !           420:     else if (code == TYPE_CODE_PTR)
        !           421:       {
        !           422:        funaddr = value_as_long (function);
        !           423:        if (TYPE_CODE (TYPE_TARGET_TYPE (ftype))
        !           424:            == TYPE_CODE_FUNC)
        !           425:          value_type = TYPE_TARGET_TYPE (TYPE_TARGET_TYPE (ftype));
        !           426:        else
        !           427:          value_type = builtin_type_int;
        !           428:       }
        !           429:     else if (code == TYPE_CODE_INT)
        !           430:       {
        !           431:        /* Handle the case of functions lacking debugging info.
        !           432:           Their values are characters since their addresses are char */
        !           433:        if (TYPE_LENGTH (ftype) == 1)
        !           434:          funaddr = value_as_long (value_addr (function));
        !           435:        else
        !           436:          /* Handle integer used as address of a function.  */
        !           437:          funaddr = value_as_long (function);
        !           438: 
        !           439:        value_type = builtin_type_int;
        !           440:       }
        !           441:     else
        !           442:       error ("Invalid data type for function to be called.");
        !           443: 
        !           444:     /* Create a call sequence customized for this function
        !           445:        and the number of arguments for it.  */
        !           446:     bcopy (dummy, dummy1, sizeof dummy);
        !           447:     FIX_CALL_DUMMY (dummy1, funaddr, nargs);
        !           448:   }
        !           449: 
        !           450:   old_sp = sp = read_register (SP_REGNUM);
        !           451: 
        !           452: #if 1 INNER_THAN 2  /* Stack grows down */
        !           453:   sp -= sizeof dummy;
        !           454:   write_memory (sp, dummy1, sizeof dummy);
        !           455:   start_sp = sp;
        !           456:   for (i = nargs - 1; i >= 0; i--)
        !           457:     sp = value_arg_push (sp, args[i]);
        !           458: #else  /* Stack grows up */
        !           459:   start_sp = sp;
        !           460:   write_memory (sp, dummy1, sizeof dummy);
        !           461:   sp += sizeof dummy;
        !           462:   for (i = 0; i < nargs; i++)
        !           463:     sp = value_arg_push (sp, args[i]);
        !           464: #endif  /* Stack grows up */
        !           465: 
        !           466:   write_register (SP_REGNUM, sp);
        !           467: 
        !           468:   /* Figure out the value returned by the function.  */
        !           469:   {
        !           470:     char retbuf[REGISTER_BYTES];
        !           471: 
        !           472:     /* Execute the stack dummy routine, calling FUNCTION.
        !           473:        When it is done, discard the empty frame
        !           474:        after storing the contents of all regs into retbuf.  */
        !           475:     run_stack_dummy (start_sp + CALL_DUMMY_START_OFFSET, retbuf);
        !           476: 
        !           477:     return value_being_returned (value_type, retbuf);
        !           478:   }
        !           479: }
        !           480: 
        !           481: /* Create a value for a string constant:
        !           482:    Call the function malloc in the inferior to get space for it,
        !           483:    then copy the data into that space
        !           484:    and then return the address with type char *.
        !           485:    PTR points to the string constant data; LEN is number of characters.  */
        !           486: 
        !           487: value
        !           488: value_string (ptr, len)
        !           489:      char *ptr;
        !           490:      int len;
        !           491: {
        !           492:   register value val;
        !           493:   register struct symbol *sym;
        !           494:   value blocklen;
        !           495:   register char *copy = (char *) alloca (len + 1);
        !           496:   char *i = ptr;
        !           497:   register char *o = copy, *ibeg = ptr;
        !           498:   register int c;
        !           499: 
        !           500:   /* Copy the string into COPY, processing escapes.
        !           501:      We could not conveniently process them in expread
        !           502:      because the string there wants to be a substring of the input.  */
        !           503: 
        !           504:   while (i - ibeg < len)
        !           505:     {
        !           506:       c = *i++;
        !           507:       if (c == '\\')
        !           508:        {
        !           509:          c = parse_escape (&i);
        !           510:          if (c == -1)
        !           511:            continue;
        !           512:        }
        !           513:       *o++ = c;
        !           514:     }
        !           515:   *o = 0;
        !           516: 
        !           517:   /* Get the length of the string after escapes are processed.  */
        !           518: 
        !           519:   len = o - copy;
        !           520: 
        !           521:   /* Find the address of malloc in the inferior.  */
        !           522: 
        !           523:   sym = lookup_symbol ("malloc", 0, VAR_NAMESPACE);
        !           524:   if (sym != 0)
        !           525:     {
        !           526:       if (SYMBOL_CLASS (sym) != LOC_BLOCK)
        !           527:        error ("\"malloc\" exists in this program but is not a function.");
        !           528:       val = value_of_variable (sym);
        !           529:     }
        !           530:   else
        !           531:     {
        !           532:       register int i;
        !           533:       for (i = 0; i < misc_function_count; i++)
        !           534:        if (!strcmp (misc_function_vector[i].name, "malloc"))
        !           535:          break;
        !           536:       if (i < misc_function_count)
        !           537:        val = value_from_long (builtin_type_long,
        !           538:                               misc_function_vector[i].address);
        !           539:       else
        !           540:        error ("String constants require the program to have a function \"malloc\".");
        !           541:     }
        !           542: 
        !           543:   blocklen = value_from_long (builtin_type_int, len + 1);
        !           544:   val = call_function (val, 1, &blocklen);
        !           545:   if (value_zerop (val))
        !           546:     error ("No memory available for string constant.");
        !           547:   write_memory (value_as_long (val), copy, len + 1);
        !           548:   VALUE_TYPE (val) = lookup_pointer_type (builtin_type_char);
        !           549:   return val;
        !           550: }
        !           551: 
        !           552: /* Given ARG1, a value of type (pointer to a)* structure/union,
        !           553:    extract the component named NAME from the ultimate target structure/union
        !           554:    and return it as a value with its appropriate type.
        !           555:    ERR is used in the error message if ARG1's type is wrong.  */
        !           556:    
        !           557: value
        !           558: value_struct_elt (arg1, name, err)
        !           559:      register value arg1;
        !           560:      char *name;
        !           561:      char *err;
        !           562: {
        !           563:   register struct type *t;
        !           564:   register int i;
        !           565: 
        !           566:   COERCE_ARRAY (arg1);
        !           567: 
        !           568:   t = VALUE_TYPE (arg1);
        !           569: 
        !           570:   /* Follow pointers until we get to a non-pointer.  */
        !           571: 
        !           572:   while (TYPE_CODE (t) == TYPE_CODE_PTR)
        !           573:     {
        !           574:       arg1 = value_ind (arg1);
        !           575:       COERCE_ARRAY (arg1);
        !           576:       t = VALUE_TYPE (arg1);
        !           577:     }
        !           578: 
        !           579:   if (TYPE_CODE (t) != TYPE_CODE_STRUCT
        !           580:       &&
        !           581:       TYPE_CODE (t) != TYPE_CODE_UNION)
        !           582:     error ("Attempt to extract a component of a value that is not a %s.", err);
        !           583: 
        !           584:   for (i = TYPE_NFIELDS (t) - 1; i >= 0; i--)
        !           585:     {
        !           586:       if (!strcmp (TYPE_FIELD_NAME (t, i), name))
        !           587:        break;
        !           588:     }
        !           589: 
        !           590:   if (i < 0)
        !           591:     error ("Structure has no component named %s.", name);
        !           592: 
        !           593:   return value_field (arg1, i);
        !           594: }
        !           595: 
        !           596: static
        !           597: initialize ()
        !           598: { }
        !           599: 
        !           600: END_FILE

unix.superglobalmegacorp.com

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