Annotation of gcc/objc/encoding.c, revision 1.1.1.1

1.1       root        1: /* Encoding of types for Objective C.
                      2:    Copyright (C) 1993 Free Software Foundation, Inc.
                      3: 
                      4: Author: Kresten Krab Thorup
                      5: 
                      6: This file is part of GNU CC.
                      7: 
                      8: GNU CC is free software; you can redistribute it and/or modify
                      9: it under the terms of the GNU General Public License as published by
                     10: the Free Software Foundation; either version 2, or (at your option)
                     11: any later version.
                     12: 
                     13: GNU CC is distributed in the hope that it will be useful,
                     14: but WITHOUT ANY WARRANTY; without even the implied warranty of
                     15: MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
                     16: GNU General Public License for more details.
                     17: 
                     18: You should have received a copy of the GNU General Public License
                     19: along with GNU CC; see the file COPYING.  If not, write to
                     20: the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
                     21: 
                     22: /* As a special exception, if you link this library with files
                     23:    compiled with GCC to produce an executable, this does not cause
                     24:    the resulting executable to be covered by the GNU General Public License.
                     25:    This exception does not however invalidate any other reasons why
                     26:    the executable file might be covered by the GNU General Public License.  */
                     27: 
                     28: #include "encoding.h"
                     29: 
                     30: #define MAX(X, Y)                    \
                     31:   ({ typeof(X) __x = (X), __y = (Y); \
                     32:      (__x > __y ? __x : __y); })
                     33: 
                     34: #define MIN(X, Y)                    \
                     35:   ({ typeof(X) __x = (X), __y = (Y); \
                     36:      (__x < __y ? __x : __y); })
                     37: 
                     38: 
                     39: static inline int
                     40: atoi (const char* str)
                     41: {
                     42:   int res = 0;
                     43:   
                     44:   while (isdigit (*str))
                     45:     res *= 10, res += (*str++ - '0');
                     46: 
                     47:   return res;
                     48: }
                     49: 
                     50: /*
                     51:   return the size of an object specified by type 
                     52: */
                     53: 
                     54: int
                     55: objc_sizeof_type(const char* type)
                     56: {
                     57:   switch(*type) {
                     58:   case _C_ID:
                     59:     return sizeof(id);
                     60:     break;
                     61: 
                     62:   case _C_CLASS:
                     63:     return sizeof(Class*);
                     64:     break;
                     65: 
                     66:   case _C_SEL:
                     67:     return sizeof(SEL);
                     68:     break;
                     69: 
                     70:   case _C_CHR:
                     71:     return sizeof(char);
                     72:     break;
                     73:     
                     74:   case _C_UCHR:
                     75:     return sizeof(unsigned char);
                     76:     break;
                     77: 
                     78:   case _C_SHT:
                     79:     return sizeof(short);
                     80:     break;
                     81: 
                     82:   case _C_USHT:
                     83:     return sizeof(unsigned short);
                     84:     break;
                     85: 
                     86:   case _C_INT:
                     87:     return sizeof(int);
                     88:     break;
                     89: 
                     90:   case _C_UINT:
                     91:     return sizeof(unsigned int);
                     92:     break;
                     93: 
                     94:   case _C_LNG:
                     95:     return sizeof(long);
                     96:     break;
                     97: 
                     98:   case _C_ULNG:
                     99:     return sizeof(unsigned long);
                    100:     break;
                    101: 
                    102:   case _C_PTR:
                    103:   case _C_ATOM:
                    104:   case _C_CHARPTR:
                    105:     return sizeof(char*);
                    106:     break;
                    107: 
                    108:   case _C_ARY_B:
                    109:     {
                    110:       int len = atoi(type+1);
                    111:       while (isdigit(*++type));
                    112:       return len*objc_aligned_size (type);
                    113:     }
                    114:     break; 
                    115: 
                    116:   case _C_STRUCT_B:
                    117:     {
                    118:       int acc_size = 0;
                    119:       int align;
                    120:       while (*type != _C_STRUCT_E && *type++ != '='); /* skip "<name>=" */
                    121:       while (*type != _C_STRUCT_E);
                    122:        {
                    123:          align = objc_alignof_type (type);       /* padd to alignment */
                    124:          if ((acc_size % align) != 0)
                    125:            acc_size += align - (acc_size % align);
                    126:          acc_size += objc_sizeof_type (type);   /* add component size */
                    127:          type = objc_skip_typespec (type);              /* skip component */
                    128:        }
                    129:       return acc_size;
                    130:     }
                    131: 
                    132:   case _C_UNION_B:
                    133:     {
                    134:       int max_size = 0;
                    135:       while (*type != _C_UNION_E && *type++ != '=') /* do nothing */;
                    136:       while (*type != _C_UNION_E)
                    137:        {
                    138:          max_size = MAX (max_size, objc_sizeof_type (type));
                    139:          type = objc_skip_typespec (type);
                    140:        }
                    141:       return max_size;
                    142:     }
                    143:     
                    144:   default:
                    145:     abort();
                    146:   }
                    147: }
                    148: 
                    149: 
                    150: /*
                    151:   Return the alignment of an object specified by type 
                    152: */
                    153: 
                    154: int
                    155: objc_alignof_type(const char* type)
                    156: {
                    157:   switch(*type) {
                    158:   case _C_ID:
                    159:     return __alignof__(id);
                    160:     break;
                    161: 
                    162:   case _C_CLASS:
                    163:     return __alignof__(Class*);
                    164:     break;
                    165:     
                    166:   case _C_SEL:
                    167:     return __alignof__(SEL);
                    168:     break;
                    169: 
                    170:   case _C_CHR:
                    171:     return __alignof__(char);
                    172:     break;
                    173:     
                    174:   case _C_UCHR:
                    175:     return __alignof__(unsigned char);
                    176:     break;
                    177: 
                    178:   case _C_SHT:
                    179:     return __alignof__(short);
                    180:     break;
                    181: 
                    182:   case _C_USHT:
                    183:     return __alignof__(unsigned short);
                    184:     break;
                    185: 
                    186:   case _C_INT:
                    187:     return __alignof__(int);
                    188:     break;
                    189: 
                    190:   case _C_UINT:
                    191:     return __alignof__(unsigned int);
                    192:     break;
                    193: 
                    194:   case _C_LNG:
                    195:     return __alignof__(long);
                    196:     break;
                    197: 
                    198:   case _C_ULNG:
                    199:     return __alignof__(unsigned long);
                    200:     break;
                    201: 
                    202:   case _C_ATOM:
                    203:   case _C_CHARPTR:
                    204:     return __alignof__(char*);
                    205:     break;
                    206: 
                    207:   case _C_ARY_B:
                    208:     while (isdigit(*++type)) /* do nothing */;
                    209:     return objc_alignof_type (type);
                    210:       
                    211:   case _C_STRUCT_B:
                    212:     {
                    213:       struct { int x; double y; } fooalign;
                    214:       while(*type != _C_STRUCT_E && *type++ != '=') /* do nothing */;
                    215:       if (*type != _C_STRUCT_E)
                    216:        return MAX (objc_alignof_type (type), __alignof__ (fooalign));
                    217:       else
                    218:        return __alignof__ (fooalign);
                    219:     }
                    220: 
                    221:   case _C_UNION_B:
                    222:     {
                    223:       int maxalign = 0;
                    224:       while (*type != _C_UNION_E && *type++ != '=') /* do nothing */;
                    225:       while (*type != _C_UNION_E)
                    226:        {
                    227:          maxalign = MAX (maxalign, objc_alignof_type (type));
                    228:          type = objc_skip_typespec (type);
                    229:        }
                    230:       return maxalign;
                    231:     }
                    232:     
                    233:   default:
                    234:     abort();
                    235:   }
                    236: }
                    237: 
                    238: /*
                    239:   The aligned size if the size rounded up to the nearest alignment.
                    240: */
                    241: 
                    242: int
                    243: objc_aligned_size (const char* type)
                    244: {
                    245:   int size = objc_sizeof_type (type);
                    246:   int align = objc_alignof_type (type);
                    247: 
                    248:   if ((size % align) != 0)
                    249:     return size + align - (size % align);
                    250:   else
                    251:     return size;
                    252: }
                    253: 
                    254: /*
                    255:   The size rounded up to the nearest integral of the wordsize, taken
                    256:   to be the size of a void*.
                    257: */
                    258: 
                    259: int 
                    260: objc_promoted_size (const char* type)
                    261: {
                    262:   int size = objc_sizeof_type (type);
                    263:   int wordsize = sizeof (void*);
                    264: 
                    265:   if ((size % wordsize) != 0)
                    266:     return size + wordsize - (size % wordsize);
                    267:   else
                    268:     return size;
                    269: }
                    270: 
                    271: /*
                    272:   Skip type qualifiers.  These may eventually precede typespecs
                    273:   occuring in method prototype encodings.
                    274: */
                    275: 
                    276: inline const char*
                    277: objc_skip_type_qualifiers (const char* type)
                    278: {
                    279:   while (*type == _C_CONST
                    280:         || *type == _C_IN 
                    281:         || *type == _C_INOUT
                    282:         || *type == _C_OUT 
                    283:         || *type == _C_BYCOPY
                    284:         || *type == _C_ONEWAY)
                    285:     {
                    286:       type += 1;
                    287:     }
                    288:   return type;
                    289: }
                    290: 
                    291:   
                    292: /*
                    293:   Skip one typespec element.  If the typespec is prepended by type
                    294:   qualifiers, these are skipped as well.
                    295: */
                    296: 
                    297: const char* 
                    298: objc_skip_typespec (const char* type)
                    299: {
                    300:   type = objc_skip_type_qualifiers (type);
                    301:   
                    302:   switch (*type) {
                    303: 
                    304:   case _C_ID:
                    305:     /* An id may be annotated by the actual type if it is known
                    306:        with the @"ClassName" syntax */
                    307: 
                    308:     if (*++type != '"')
                    309:       return type;
                    310:     else
                    311:       {
                    312:        while (*++type != '"') /* do nothing */;
                    313:        return type + 1;
                    314:       }
                    315: 
                    316:     /* The following are one character type codes */
                    317:   case _C_CLASS:
                    318:   case _C_SEL:
                    319:   case _C_CHR:
                    320:   case _C_UCHR:
                    321:   case _C_CHARPTR:
                    322:   case _C_ATOM:
                    323:   case _C_SHT:
                    324:   case _C_USHT:
                    325:   case _C_INT:
                    326:   case _C_UINT:
                    327:   case _C_LNG:
                    328:   case _C_ULNG:
                    329:   case _C_FLT:
                    330:   case _C_DBL:
                    331:   case _C_VOID:
                    332:     return ++type;
                    333:     break;
                    334: 
                    335:   case _C_ARY_B:
                    336:     /* skip digits, typespec and closing ']' */
                    337:     
                    338:     while(isdigit(*++type));
                    339:     type = objc_skip_typespec(type);
                    340:     if (*type == _C_ARY_E)
                    341:       return ++type;
                    342:     else
                    343:       abort();
                    344: 
                    345:   case _C_STRUCT_B:
                    346:     /* skip name, and elements until closing '}'  */
                    347:     
                    348:     while (*type != _C_STRUCT_E && *type++ != '=');
                    349:     while (*type != _C_STRUCT_E) { type = objc_skip_typespec (type); }
                    350:     return ++type;
                    351: 
                    352:   case _C_UNION_B:
                    353:     /* skip name, and elements until closing ')'  */
                    354:     
                    355:     while (*type != _C_UNION_E && *type++ != '=');
                    356:     while (*type != _C_UNION_E) { type = objc_skip_typespec (type); }
                    357:     return ++type;
                    358: 
                    359:   case _C_PTR:
                    360:     /* Just skip the following typespec */
                    361:     
                    362:     return objc_skip_typespec (++type);
                    363:     
                    364:   default:
                    365:     abort();
                    366:   }
                    367: }
                    368: 
                    369: /*
                    370:   Skip an offset as part of a method encoding.  This is prepended by a
                    371:   '+' if the argument is passed in registers.
                    372: */
                    373: inline const char* 
                    374: objc_skip_offset (const char* type)
                    375: {
                    376:   if (*type == '+') type++;
                    377:   while(isdigit(*++type));
                    378:   return type;
                    379: }
                    380: 
                    381: /*
                    382:   Skip an argument specification of a method encoding.
                    383: */
                    384: const char*
                    385: objc_skip_argspec (const char* type)
                    386: {
                    387:   type = objc_skip_typespec (type);
                    388:   type = objc_skip_offset (type);
                    389:   return type;
                    390: }
                    391: 
                    392: /*
                    393:   Return the number of arguments that the method MTH expects.
                    394:   Note that all methods need two implicit arguments `self' and
                    395:   `_cmd'. 
                    396: */
                    397: int
                    398: method_get_number_of_arguments (struct objc_method* mth)
                    399: {
                    400:   int i = 0;
                    401:   const char* type = mth->method_types;
                    402:   while (*type)
                    403:     {
                    404:       type = objc_skip_argspec (type);
                    405:       i += 1;
                    406:     }
                    407:   return i - 1;
                    408: }
                    409: 
                    410: /*
                    411:   Return the size of the argument block needed on the stack to invoke
                    412:   the method MTH.  This may be zero, if all arguments are passed in
                    413:   registers.
                    414: */
                    415: 
                    416: int
                    417: method_get_sizeof_arguments (struct objc_method* mth)
                    418: {
                    419:   const char* type = objc_skip_typespec (mth->method_types);
                    420:   return atoi (type);
                    421: }
                    422: 
                    423: /*
                    424:   Return a pointer to the next argument of ARGFRAME.  type points to
                    425:   the last argument.  Typical use of this look like:
                    426: 
                    427:   {
                    428:     char *datum, *type; 
                    429:     for (datum = method_get_first_argument (method, argframe, &type);
                    430:          datum; datum = method_get_next_argument (argframe, &type))
                    431:       {
                    432:         unsigned flags = objc_get_type_qualifiers (type);
                    433:         type = objc_skip_type_qualifiers (type);
                    434:        if (*type != _C_PTR)
                    435:           [portal encodeData: datum ofType: type];
                    436:        else
                    437:          {
                    438:            if ((flags & _F_IN) == _F_IN)
                    439:               [portal encodeData: *(char**)datum ofType: ++type];
                    440:          }
                    441:       }
                    442:   }
                    443: */  
                    444: 
                    445: char*
                    446: method_get_next_argument (arglist_t argframe,
                    447:                          const char **type)
                    448: {
                    449:   const char *t = objc_skip_argspec (*type);
                    450: 
                    451:   if (*t == '\0')
                    452:     return 0;
                    453: 
                    454:   *type = t;
                    455:   t = objc_skip_typespec (t);
                    456: 
                    457:   if (*t == '+')
                    458:     return argframe->arg_regs + atoi (++t);
                    459:   else
                    460:     return argframe->arg_ptr + atoi (t);
                    461: }
                    462: 
                    463: /*
                    464:   Return a pointer to the value of the first argument of the method 
                    465:   described in M with the given argumentframe ARGFRAME.  The type
                    466:   is returned in TYPE.  type must be passed to successive calls of 
                    467:   method_get_next_argument.
                    468: */
                    469: char*
                    470: method_get_first_argument (struct objc_method* m,
                    471:                           arglist_t argframe, 
                    472:                           const char** type)
                    473: {
                    474:   *type = m->method_types;
                    475:   return method_get_next_argument (argframe, type);
                    476: }
                    477: 
                    478: /*
                    479:    Return a pointer to the ARGth argument of the method
                    480:    M from the frame ARGFRAME.  The type of the argument
                    481:    is returned in the value-result argument TYPE 
                    482: */
                    483: 
                    484: char*
                    485: method_get_nth_argument (struct objc_method* m,
                    486:                         arglist_t argframe, int arg, 
                    487:                         const char **type)
                    488: {
                    489:   const char* t = objc_skip_argspec (m->method_types);
                    490: 
                    491:   if (arg > method_get_number_of_arguments (m))
                    492:     return 0;
                    493: 
                    494:   while (arg--)
                    495:     t = objc_skip_argspec (t);
                    496:   
                    497:   *type = t;
                    498:   t = objc_skip_typespec (t);
                    499: 
                    500:   if (*t == '+')
                    501:     return argframe->arg_regs + atoi (++t);
                    502:   else
                    503:     return argframe->arg_ptr + atoi (t);
                    504: }
                    505: 
                    506: unsigned
                    507: objc_get_type_qualifiers (const char* type)
                    508: {
                    509:   unsigned res = 0;
                    510:   BOOL flag = YES;
                    511: 
                    512:   while (flag)
                    513:     switch (*type++)
                    514:       {
                    515:       case _C_CONST:  res |= _F_CONST; break;
                    516:       case _C_IN:     res |= _F_IN; break;
                    517:       case _C_INOUT:  res |= _F_INOUT; break;
                    518:       case _C_OUT:    res |= _F_OUT; break;
                    519:       case _C_BYCOPY: res |= _F_BYCOPY; break;
                    520:       case _C_ONEWAY: res |= _F_ONEWAY; break;
                    521:       default: flag = NO;
                    522:     }
                    523: 
                    524:   return res;
                    525: }

unix.superglobalmegacorp.com

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