~ubuntu-branches/ubuntu/karmic/gnustep-base/karmic

« back to all changes in this revision

Viewing changes to Source/objc-gnu2next.m

  • Committer: Bazaar Package Importer
  • Author(s): Eric Heintzmann
  • Date: 2005-04-17 00:14:38 UTC
  • mfrom: (1.2.1 upstream) (2.1.2 hoary)
  • Revision ID: james.westby@ubuntu.com-20050417001438-enf0y07c9tku85z1
Tags: 1.10.3-1
New upstream release.

Show diffs side-by-side

added added

removed removed

Lines of Context:
11
11
   modify it under the terms of the GNU Library General Public
12
12
   License as published by the Free Software Foundation; either
13
13
   version 2 of the License, or (at your option) any later version.
14
 
   
 
14
 
15
15
   This library is distributed in the hope that it will be useful,
16
16
   but WITHOUT ANY WARRANTY; without even the implied warranty of
17
17
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
20
20
   You should have received a copy of the GNU Library General Public
21
21
   License along with this library; if not, write to the Free
22
22
   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111 USA.
23
 
*/ 
 
23
*/
24
24
 
25
25
#include "config.h"
26
26
#include <stdio.h>
27
 
#include <base/preface.h>
 
27
#include "GNUstepBase/preface.h"
28
28
#include "mframe.h"
29
29
 
30
 
#ifndef ROUND
31
 
#define ROUND(V, A) \
32
 
  ({ typeof(V) __v=(V); typeof(A) __a=(A); \
33
 
     __a*((__v+__a-1)/__a); })
34
 
#endif
35
 
 
36
 
/*
37
 
  return the size of an object specified by type 
38
 
*/
39
 
 
40
 
int
41
 
objc_sizeof_type(const char* type)
42
 
{
43
 
  switch(*type) {
44
 
  case _C_ID:
45
 
    return sizeof(id);
46
 
    break;
47
 
 
48
 
  case _C_CLASS:
49
 
    return sizeof(Class);
50
 
    break;
51
 
 
52
 
  case _C_SEL:
53
 
    return sizeof(SEL);
54
 
    break;
55
 
 
56
 
  case _C_CHR:
57
 
    return sizeof(char);
58
 
    break;
59
 
    
60
 
  case _C_UCHR:
61
 
    return sizeof(unsigned char);
62
 
    break;
63
 
 
64
 
  case _C_SHT:
65
 
    return sizeof(short);
66
 
    break;
67
 
 
68
 
  case _C_USHT:
69
 
    return sizeof(unsigned short);
70
 
    break;
71
 
 
72
 
  case _C_INT:
73
 
    return sizeof(int);
74
 
    break;
75
 
 
76
 
  case _C_UINT:
77
 
    return sizeof(unsigned int);
78
 
    break;
79
 
 
80
 
  case _C_LNG:
81
 
    return sizeof(long);
82
 
    break;
83
 
 
84
 
  case _C_ULNG:
85
 
    return sizeof(unsigned long);
86
 
    break;
87
 
 
88
 
  case _C_FLT:
89
 
    return sizeof(float);
90
 
    break;
91
 
 
92
 
  case _C_DBL:
93
 
    return sizeof(double);
94
 
    break;
95
 
 
96
 
  case _C_PTR:
97
 
  case _C_ATOM:
98
 
  case _C_CHARPTR:
99
 
    return sizeof(char*);
100
 
    break;
101
 
 
102
 
  case _C_ARY_B:
103
 
    {
104
 
      int len = atoi(type+1);
105
 
      while (isdigit(*++type));
106
 
      return len*objc_aligned_size (type);
107
 
    }
108
 
    break; 
109
 
 
110
 
  case _C_STRUCT_B:
111
 
    {
112
 
      int acc_size = 0;
113
 
      int align;
114
 
      while (*type != _C_STRUCT_E && *type++ != '='); /* skip "<name>=" */
115
 
      while (*type != _C_STRUCT_E)
116
 
        {
117
 
          align = objc_alignof_type (type);       /* padd to alignment */
118
 
          acc_size = ROUND (acc_size, align);
119
 
          acc_size += objc_sizeof_type (type);   /* add component size */
120
 
          type = objc_skip_typespec (type);              /* skip component */
121
 
        }
122
 
      return acc_size;
123
 
    }
124
 
 
125
 
  case _C_UNION_B:
126
 
    {
127
 
      int max_size = 0;
128
 
      while (*type != _C_UNION_E && *type++ != '=') /* do nothing */;
129
 
      while (*type != _C_UNION_E)
130
 
        {
131
 
          max_size = MAX (max_size, objc_sizeof_type (type));
132
 
          type = objc_skip_typespec (type);
133
 
        }
134
 
      return max_size;
135
 
    }
136
 
    
137
 
  default:
138
 
    abort();
139
 
  }
140
 
}
141
 
 
142
 
 
143
 
/*
144
 
  Return the alignment of an object specified by type 
145
 
*/
146
 
 
147
 
int
148
 
objc_alignof_type(const char* type)
149
 
{
150
 
  switch(*type) {
151
 
  case _C_ID:
152
 
    return __alignof__(id);
153
 
    break;
154
 
 
155
 
  case _C_CLASS:
156
 
    return __alignof__(Class);
157
 
    break;
158
 
    
159
 
  case _C_SEL:
160
 
    return __alignof__(SEL);
161
 
    break;
162
 
 
163
 
  case _C_CHR:
164
 
    return __alignof__(char);
165
 
    break;
166
 
    
167
 
  case _C_UCHR:
168
 
    return __alignof__(unsigned char);
169
 
    break;
170
 
 
171
 
  case _C_SHT:
172
 
    return __alignof__(short);
173
 
    break;
174
 
 
175
 
  case _C_USHT:
176
 
    return __alignof__(unsigned short);
177
 
    break;
178
 
 
179
 
  case _C_INT:
180
 
    return __alignof__(int);
181
 
    break;
182
 
 
183
 
  case _C_UINT:
184
 
    return __alignof__(unsigned int);
185
 
    break;
186
 
 
187
 
  case _C_LNG:
188
 
    return __alignof__(long);
189
 
    break;
190
 
 
191
 
  case _C_ULNG:
192
 
    return __alignof__(unsigned long);
193
 
    break;
194
 
 
195
 
  case _C_FLT:
196
 
    return __alignof__(float);
197
 
    break;
198
 
 
199
 
  case _C_DBL:
200
 
    return __alignof__(double);
201
 
    break;
202
 
 
203
 
  case _C_ATOM:
204
 
  case _C_CHARPTR:
205
 
    return __alignof__(char*);
206
 
    break;
207
 
 
208
 
  case _C_ARY_B:
209
 
    while (isdigit(*++type)) /* do nothing */;
210
 
    return objc_alignof_type (type);
211
 
      
212
 
  case _C_STRUCT_B:
213
 
    {
214
 
      struct { int x; double y; } fooalign;
215
 
      while(*type != _C_STRUCT_E && *type++ != '=') /* do nothing */;
216
 
      if (*type != _C_STRUCT_E)
217
 
        return MAX (objc_alignof_type (type), __alignof__ (fooalign));
218
 
      else
219
 
        return __alignof__ (fooalign);
220
 
    }
221
 
 
222
 
  case _C_UNION_B:
223
 
    {
224
 
      int maxalign = 0;
225
 
      while (*type != _C_UNION_E && *type++ != '=') /* do nothing */;
226
 
      while (*type != _C_UNION_E)
227
 
        {
228
 
          maxalign = MAX (maxalign, objc_alignof_type (type));
229
 
          type = objc_skip_typespec (type);
230
 
        }
231
 
      return maxalign;
232
 
    }
233
 
    
234
 
  default:
235
 
    abort();
236
 
  }
237
 
}
238
 
 
239
 
/*
240
 
  The aligned size if the size rounded up to the nearest alignment.
241
 
*/
242
 
 
243
 
int
244
 
objc_aligned_size (const char* type)
245
 
{
246
 
  int size = objc_sizeof_type (type);
247
 
  int align = objc_alignof_type (type);
248
 
  return ROUND (size, align);
249
 
}
250
 
 
251
 
/*
252
 
  The size rounded up to the nearest integral of the wordsize, taken
253
 
  to be the size of a void*.
254
 
*/
255
 
 
256
 
int 
257
 
objc_promoted_size (const char* type)
258
 
{
259
 
  int size = objc_sizeof_type (type);
260
 
  int wordsize = sizeof (void*);
261
 
 
262
 
  return ROUND (size, wordsize);
263
 
}
264
 
 
265
 
/*
266
 
  Skip type qualifiers.  These may eventually precede typespecs
267
 
  occuring in method prototype encodings.
268
 
*/
269
 
 
270
 
const char*
271
 
objc_skip_type_qualifiers (const char* type)
272
 
{
273
 
  while (*type == _C_CONST
274
 
         || *type == _C_IN 
275
 
         || *type == _C_INOUT
276
 
         || *type == _C_OUT 
277
 
         || *type == _C_BYCOPY
278
 
#ifdef  _C_BYREF
279
 
         || *type == _C_BYREF
280
 
#endif
281
 
#ifdef  _C_GCINVISIBLE
282
 
         || *type == _C_GCINVISIBLE
283
 
#endif
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
 
  if (*type == '-') type++;
378
 
  while(isdigit(*++type));
379
 
  return type;
380
 
}
381
 
 
382
 
/*
383
 
  Skip an argument specification of a method encoding.
384
 
*/
385
 
const char*
386
 
objc_skip_argspec (const char* type)
387
 
{
388
 
  type = objc_skip_typespec (type);
389
 
  type = objc_skip_offset (type);
390
 
  return type;
391
 
}
392
 
 
393
 
unsigned
394
 
objc_get_type_qualifiers (const char* type)
395
 
{
396
 
  unsigned res = 0;
397
 
  BOOL flag = YES;
398
 
 
399
 
  while (flag)
400
 
    switch (*type++)
401
 
      {
402
 
      case _C_CONST:  res |= _F_CONST; break;
403
 
      case _C_IN:     res |= _F_IN; break;
404
 
      case _C_INOUT:  res |= _F_INOUT; break;
405
 
      case _C_OUT:    res |= _F_OUT; break;
406
 
      case _C_BYCOPY: res |= _F_BYCOPY; break;
407
 
#ifdef  _C_BYREF
408
 
      case _C_BYREF:  res |= _F_BYREF; break;
409
 
#endif
410
 
      case _C_ONEWAY: res |= _F_ONEWAY; break;
411
 
#ifdef  _C_GCINVISIBLE
412
 
      case _C_GCINVISIBLE:  res |= _F_GCINVISIBLE; break;
413
 
#endif
414
 
      default: flag = NO;
415
 
    }
416
 
 
417
 
  return res;
418
 
}
419
 
 
420
 
/* Returns YES iff t1 and t2 have same method types, but we ignore
421
 
   the argframe layout */
422
 
BOOL
423
 
sel_types_match (const char* t1, const char* t2)
424
 
{
425
 
  if (!t1 || !t2)
426
 
    return NO;
427
 
  while (*t1 && *t2)
428
 
    {
429
 
      if (*t1 == '+') t1++;
430
 
      if (*t1 == '-') t1++;
431
 
      if (*t2 == '+') t2++;
432
 
      if (*t2 == '-') t2++;
433
 
      while (isdigit(*t1)) t1++;
434
 
      while (isdigit(*t2)) t2++;
435
 
      /* xxx Remove these next two lines when qualifiers are put in
436
 
          all selectors, not just Protocol selectors. */
437
 
      t1 = objc_skip_type_qualifiers(t1);
438
 
      t2 = objc_skip_type_qualifiers(t2);
439
 
      if (!*t1 && !*t2)
440
 
        return YES;
441
 
      if (*t1 != *t2)
442
 
        return NO;
443
 
      t1++;
444
 
      t2++;
445
 
    }
446
 
  return NO;
447
 
}
448
 
 
449
30
id next_objc_msg_sendv(id object, SEL op, void* frame)
450
31
{
451
32
  arglist_t  argFrame = __builtin_apply_args();
465
46
       stack on i386 machines. This happens with NeXT runtime and 2.7.2
466
47
       compiler. If the result value is floating point don't call
467
48
       __builtin_return anymore. */
468
 
    if(*m->method_types == _C_FLT || *m->method_types == _C_DBL) {
 
49
    if (*m->method_types == _C_FLT || *m->method_types == _C_DBL) {
469
50
        long double value = *(long double*)(((char*)result) + 8);
470
51
        asm("fld %0" : : "f" (value));
471
52
    }
473
54
#endif
474
55
  __builtin_return(result);
475
56
}
476
 
 
477
 
/*
478
 
** Hook functions for memory allocation and disposal.
479
 
** This makes it easy to substitute garbage collection systems
480
 
** such as Boehm's GC by assigning these function pointers
481
 
** to the GC's allocation routines.  By default these point
482
 
** to the ANSI standard malloc, realloc, free, etc.
483
 
**
484
 
** Users should call the normal objc routines above for
485
 
** memory allocation and disposal within their programs.
486
 
*/
487
 
 
488
 
void *(*_objc_malloc)(size_t) = malloc;
489
 
void *(*_objc_atomic_malloc)(size_t) = malloc;
490
 
void *(*_objc_valloc)(size_t) = malloc;
491
 
void *(*_objc_realloc)(void *, size_t) = realloc;
492
 
void *(*_objc_calloc)(size_t, size_t) = calloc;
493
 
void (*_objc_free)(void *) = free;
494
 
 
495
 
/*
496
 
** Standard functions for memory allocation and disposal.
497
 
** Users should use these functions in their ObjC programs so
498
 
** that they work properly with garbage collectors as well as
499
 
** can take advantage of the exception/error handling available.
500
 
*/
501
 
 
502
 
void *
503
 
objc_malloc(size_t size)
504
 
{
505
 
  void* res = (void*) (*_objc_malloc)(size);
506
 
  if(!res)
507
 
    objc_error(nil, OBJC_ERR_MEMORY, "Virtual memory exhausted\n");
508
 
  return res;
509
 
}
510
 
 
511
 
void *
512
 
objc_atomic_malloc(size_t size)
513
 
{
514
 
  void* res = (void*) (*_objc_atomic_malloc)(size);
515
 
  if(!res)
516
 
    objc_error(nil, OBJC_ERR_MEMORY, "Virtual memory exhausted\n");
517
 
  return res;
518
 
}
519
 
 
520
 
void *
521
 
objc_valloc(size_t size)
522
 
{
523
 
  void* res = (void*) (*_objc_valloc)(size);
524
 
  if(!res)
525
 
    objc_error(nil, OBJC_ERR_MEMORY, "Virtual memory exhausted\n");
526
 
  return res;
527
 
}
528
 
 
529
 
void *
530
 
objc_realloc(void *mem, size_t size)
531
 
{
532
 
  void* res = (void*) (*_objc_realloc)(mem, size);
533
 
  if(!res)
534
 
    objc_error(nil, OBJC_ERR_MEMORY, "Virtual memory exhausted\n");
535
 
  return res;
536
 
}
537
 
 
538
 
void *
539
 
objc_calloc(size_t nelem, size_t size)
540
 
{
541
 
  void* res = (void*) (*_objc_calloc)(nelem, size);
542
 
  if(!res)
543
 
    objc_error(nil, OBJC_ERR_MEMORY, "Virtual memory exhausted\n");
544
 
  return res;
545
 
}
546
 
 
547
 
void
548
 
objc_free(void *mem)
549
 
{
550
 
  (*_objc_free)(mem);
551
 
}
552
 
 
553
 
/*
554
 
** Error handler function
555
 
** NULL so that default is to just print to stderr
556
 
*/
557
 
static objc_error_handler _objc_error_handler = NULL;
558
 
 
559
 
/* Trigger an objc error */
560
 
void
561
 
objc_error(id object, int code, const char* fmt, ...)
562
 
{
563
 
  va_list ap;
564
 
 
565
 
  va_start(ap, fmt);
566
 
  objc_verror(object, code, fmt, ap);
567
 
  va_end(ap);
568
 
}
569
 
 
570
 
/* Trigger an objc error */
571
 
void
572
 
objc_verror(id object, int code, const char* fmt, va_list ap)
573
 
{
574
 
  BOOL result = NO;
575
 
 
576
 
  /* Call the error handler if its there
577
 
     Otherwise print to stderr */
578
 
  if (_objc_error_handler)
579
 
    result = (*_objc_error_handler)(object, code, fmt, ap);
580
 
  else
581
 
    vfprintf (stderr, fmt, ap);
582
 
 
583
 
  /* Continue if the error handler says its ok
584
 
     Otherwise abort the program */
585
 
  if (result)
586
 
    return;
587
 
  else
588
 
    abort();
589
 
}
590
 
 
591
 
/* Set the error handler */
592
 
objc_error_handler
593
 
objc_set_error_handler(objc_error_handler func)
594
 
{
595
 
  objc_error_handler temp = _objc_error_handler;
596
 
  _objc_error_handler = func;
597
 
  return temp;
598
 
}
599