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

unix.superglobalmegacorp.com

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