SmallInt.st
changeset 1 a27a279701f8
child 2 6526dde5f3ac
equal deleted inserted replaced
0:aa2498ef6470 1:a27a279701f8
       
     1 "
       
     2  COPYRIGHT (c) 1988-93 by Claus Gittinger
       
     3               All Rights Reserved
       
     4 
       
     5  This software is furnished under a license and may be used
       
     6  only in accordance with the terms of that license and with the
       
     7  inclusion of the above copyright notice.   This software may not
       
     8  be provided or otherwise made available to, or used by, any
       
     9  other person.  No title to or ownership of the software is
       
    10  hereby transferred.
       
    11 "
       
    12 
       
    13 Integer subclass:#SmallInteger
       
    14        instanceVariableNames:''
       
    15        classVariableNames:''
       
    16        poolDictionaries:''
       
    17        category:'Magnitude-Numbers'
       
    18 !
       
    19 
       
    20 SmallInteger comment:'
       
    21 
       
    22 COPYRIGHT (c) 1988-93 by Claus Gittinger
       
    23               All Rights Reserved
       
    24 
       
    25 %W% %E%
       
    26 
       
    27 SmallIntegers are Integers in the range of +/- 2^30 (i.e. 31 bits).
       
    28 These are no real objects - they have no instances (not even storage !)
       
    29 and cannot be subclassed (sorry)
       
    30 
       
    31 The reason is to save both storage and runtime by not collecting
       
    32 SmallIntegers in the system. SmallInts are marked by having the TAG_INT 
       
    33 bit set in contrast to Objects which have not. Since this knowledge is 
       
    34 hardwired into the system (an there is no class-field stored with
       
    35 SmallIntegers) there can be no subclass of SmallInteger (sorry).
       
    36 '!
       
    37 
       
    38 !SmallInteger class methodsFor:'instance creation'!
       
    39 
       
    40 basicNew
       
    41     "catch instance creation
       
    42      - SmallIntegers cannot be created with new"
       
    43 
       
    44     self error:'instances of SmallInteger cannot be created with new'
       
    45 !
       
    46 
       
    47 basicNew:size
       
    48     "catch instance creation
       
    49      - SmallIntegers cannot be created with new"
       
    50 
       
    51     self error:'instances of SmallInteger cannot be created with new'
       
    52 ! !
       
    53 
       
    54 !SmallInteger class methodsFor:'constants'!
       
    55 
       
    56 maxBits
       
    57     "return the number of bits in instances of me"
       
    58 
       
    59 %{  /* NOCONTEXT */
       
    60     RETURN ( _MKSMALLINT(N_INT_BITS) );
       
    61 %}
       
    62 !
       
    63 
       
    64 maxBytes
       
    65     "return the number of bytes in instances of me"
       
    66 
       
    67 %{  /* NOCONTEXT */
       
    68     RETURN ( _MKSMALLINT(N_INT_BITS / 8 + 1) );
       
    69 %}
       
    70 !
       
    71 
       
    72 minVal
       
    73     "return the smallest Integer representable as SmallInteger"
       
    74 
       
    75 %{  /* NOCONTEXT */
       
    76     RETURN ( _MKSMALLINT(_MIN_INT) );
       
    77 %}
       
    78 !
       
    79 
       
    80 maxVal
       
    81     "return the largest Integer representable as SmallInteger"
       
    82 
       
    83 %{  /* NOCONTEXT */
       
    84     RETURN ( _MKSMALLINT(_MAX_INT) );
       
    85 %}
       
    86 ! !
       
    87 
       
    88 !SmallInteger methodsFor:'error catching'!
       
    89 
       
    90 at:index
       
    91     "catch indexed access - report an error
       
    92      defined here since at: in Object ommits the SmallInteger check"
       
    93 
       
    94     self notIndexed
       
    95 !
       
    96 
       
    97 basicAt:index
       
    98     "catch indexed access - report an error
       
    99      defined here since basicAt: in Object ommits the SmallInteger check"
       
   100 
       
   101     self notIndexed
       
   102 !
       
   103 
       
   104 at:index put:anObject
       
   105     "catch indexed access - report an error
       
   106      defined here since at:put: in Object ommits the SmallInteger check"
       
   107 
       
   108     self notIndexed
       
   109 !
       
   110 
       
   111 basicAt:index put:anObject
       
   112     "catch indexed access - report an error
       
   113      defined here since basicAt:put: in Object ommits the SmallInteger check"
       
   114 
       
   115     self notIndexed
       
   116 !
       
   117 
       
   118 size
       
   119     "return the number of indexed instvars - SmallIntegers have none
       
   120      defined here since size in Object ommits the SmallInteger check"
       
   121 
       
   122     ^ 0
       
   123 !
       
   124 
       
   125 basicSize
       
   126     "return the number of indexed instvars - SmallIntegers have none
       
   127      defined here since basicSize in Object ommits the SmallInteger check"
       
   128 
       
   129     ^ 0
       
   130 ! !
       
   131 
       
   132 !SmallInteger methodsFor:'copying'!
       
   133 
       
   134 shallowCopy
       
   135     "return a shallow copy of myself
       
   136      - reimplemented here since numbers are unique"
       
   137 
       
   138     ^ self
       
   139 !
       
   140 
       
   141 deepCopy
       
   142     "return a deep copy of myself
       
   143      - reimplemented here since numbers are unique"
       
   144 
       
   145     ^ self
       
   146 ! !
       
   147 
       
   148 !SmallInteger methodsFor:'comparing'!
       
   149 
       
   150 = aNumber
       
   151     "return true, if the arguments value is equal to mine"
       
   152 
       
   153 %{  /* NOCONTEXT */
       
   154 
       
   155     if (aNumber == self) {
       
   156         RETURN ( true );
       
   157     }
       
   158     if (! _isNonNilObject(aNumber)) {
       
   159         RETURN ( false );
       
   160     }
       
   161 
       
   162     if (_qClass(aNumber) == Float) {
       
   163         RETURN ( ((double)_intVal(self) == _floatVal(aNumber)) ? true : false );
       
   164     }
       
   165 %}
       
   166 .
       
   167     aNumber respondsToArithmetic ifFalse:[^ false].
       
   168     ^ self retry:#= coercing:aNumber
       
   169 !
       
   170 
       
   171 ~= aNumber
       
   172     "return true, if the arguments value is not equal to mine"
       
   173 
       
   174 %{  /* NOCONTEXT */
       
   175 
       
   176     if (aNumber == self) {
       
   177         RETURN ( false );
       
   178     }
       
   179     if (! _isNonNilObject(aNumber)) {
       
   180         RETURN ( true );
       
   181     }
       
   182 
       
   183     if (_qClass(aNumber) == Float) {
       
   184         RETURN ( ((double)_intVal(self) == _floatVal(aNumber)) ? false : true );
       
   185     }
       
   186 %}
       
   187 .
       
   188     aNumber respondsToArithmetic ifFalse:[^ true].
       
   189     ^ self retry:#~= coercing:aNumber
       
   190 !
       
   191 
       
   192 < aNumber
       
   193     "return true, if the argument is greater than the receiver"
       
   194 
       
   195 %{  /* NOCONTEXT */
       
   196 
       
   197     if (_isSmallInteger(aNumber)) {
       
   198 #ifdef POSITIVE_ADDRESSES
       
   199         RETURN ( (_intVal(self) < _intVal(aNumber)) ? true : false );
       
   200 #else
       
   201         /* tag bit does not change ordering */
       
   202         RETURN ( ((INT)self < (INT)aNumber) ? true : false );
       
   203 #endif
       
   204     }
       
   205     if (_isFloat(aNumber)) {
       
   206         RETURN ( ((double)_intVal(self) < _floatVal(aNumber)) ? true : false );
       
   207     }
       
   208 %}
       
   209 .
       
   210     ^ aNumber lessFromInteger:self
       
   211     "^ self retry:#< coercing:aNumber"
       
   212 !
       
   213 
       
   214 > aNumber
       
   215     "return true, if the argument is less than the receiver"
       
   216 
       
   217 %{  /* NOCONTEXT */
       
   218 
       
   219     if (_isSmallInteger(aNumber)) {
       
   220 #ifdef POSITIVE_ADDRESSES
       
   221         RETURN ( (_intVal(self) > _intVal(aNumber)) ? true : false );
       
   222 #else
       
   223         /* tag bit does not change ordering */
       
   224         RETURN ( ((INT)self > (INT)aNumber) ? true : false );
       
   225 #endif
       
   226     }
       
   227     if (_isFloat(aNumber)) {
       
   228         RETURN ( ((double)_intVal(self) > _floatVal(aNumber)) ? true : false );
       
   229     }
       
   230 %}
       
   231 .
       
   232     ^ self retry:#> coercing:aNumber
       
   233 !
       
   234 
       
   235 >= aNumber
       
   236     "return true, if the argument is less or equal"
       
   237 
       
   238 %{  /* NOCONTEXT */
       
   239 
       
   240     if (_isSmallInteger(aNumber)) {
       
   241 #ifdef POSITIVE_ADDRESSES
       
   242         RETURN ( (_intVal(self) >= _intVal(aNumber)) ? true : false );
       
   243 #else
       
   244         /* tag bit does not change ordering */
       
   245         RETURN ( ((INT)self >= (INT)aNumber) ? true : false );
       
   246 #endif
       
   247     }
       
   248     if (_isFloat(aNumber)) {
       
   249         RETURN ( ((double)_intVal(self) >= _floatVal(aNumber)) ? true : false );
       
   250     }
       
   251 %}
       
   252 .
       
   253     ^ self retry:#>= coercing:aNumber
       
   254 !
       
   255 
       
   256 <= aNumber
       
   257     "return true, if the argument is greater or equal"
       
   258 
       
   259 %{  /* NOCONTEXT */
       
   260 
       
   261     if (_isSmallInteger(aNumber)) {
       
   262 #ifdef POSITIVE_ADDRESSES
       
   263         RETURN ( (_intVal(self) <= _intVal(aNumber)) ? true : false );
       
   264 #else
       
   265         /* tag bit does not change ordering */
       
   266         RETURN ( ((INT)self <= (INT)aNumber) ? true : false );
       
   267 #endif
       
   268     }
       
   269     if (_isFloat(aNumber)) {
       
   270         RETURN ( ((double)_intVal(self) <= _floatVal(aNumber)) ? true : false );
       
   271     }
       
   272 %}
       
   273 .
       
   274     ^ self retry:#<= coercing:aNumber
       
   275 !
       
   276 
       
   277 identityHash
       
   278     "return an integer useful for hashing on identity"
       
   279 
       
   280     self > 0 ifTrue:[
       
   281         ^ self + 8192
       
   282     ].
       
   283     ^ self negated + 8192
       
   284 !
       
   285 
       
   286 min:aNumber
       
   287     "return the receiver or the argument, whichever is smaller"
       
   288 
       
   289 %{  /* NOCONTEXT */
       
   290 
       
   291     if (_isSmallInteger(aNumber)) {
       
   292 #ifdef POSITIVE_ADDRESSES
       
   293         if (_intVal(self) < _intVal(aNumber)) {
       
   294 #else
       
   295         /* tag bit does not change ordering */
       
   296         if ((INT)(self) < (INT)(aNumber)) {
       
   297 #endif
       
   298             RETURN ( self );
       
   299         }
       
   300         RETURN ( aNumber );
       
   301     }
       
   302     if (_isFloat(aNumber)) {
       
   303         if ( (double)_intVal(self) < _floatVal(aNumber) ) {
       
   304             RETURN ( self );
       
   305         }
       
   306         RETURN ( aNumber );
       
   307     }
       
   308 %}
       
   309 .
       
   310     (self < aNumber) ifTrue:[^ self].
       
   311     ^ aNumber
       
   312 !
       
   313 
       
   314 max:aNumber
       
   315     "return the receiver or the argument, whichever is greater"
       
   316 
       
   317 %{  /* NOCONTEXT */
       
   318 
       
   319     if (_isSmallInteger(aNumber)) {
       
   320 #ifdef POSITIVE_ADDRESSES
       
   321         if (_intVal(self) > _intVal(aNumber)) {
       
   322 #else
       
   323         /* tag bit does not change ordering */
       
   324         if ((INT)(self) > (INT)(aNumber)) {
       
   325 #endif
       
   326             RETURN ( self );
       
   327         }
       
   328         RETURN ( aNumber );
       
   329     }
       
   330     if (_isFloat(aNumber)) {
       
   331         if ( (double)_intVal(self) > _floatVal(aNumber) ) {
       
   332             RETURN ( self );
       
   333         }
       
   334         RETURN ( aNumber );
       
   335     }
       
   336 %}
       
   337 .
       
   338     (self > aNumber) ifTrue:[^ self].
       
   339     ^ aNumber
       
   340 ! !
       
   341 
       
   342 !SmallInteger methodsFor:'testing'!
       
   343 
       
   344 negative
       
   345     "return true, if the receiver is less than zero
       
   346      reimplemented here for speed"
       
   347 
       
   348 %{  /* NOCONTEXT */
       
   349 
       
   350 #ifdef POSITIVE_ADDRESSES
       
   351     RETURN ( (_intVal(self) < 0) ? true : false );
       
   352 #else
       
   353     /* tag bit does not change sign */
       
   354     RETURN ( ((INT)(self) < 0) ? true : false );
       
   355 #endif
       
   356 %}
       
   357 !
       
   358 
       
   359 positive
       
   360     "return true, if the receiver is not negative
       
   361      reimplemented here for speed"
       
   362 
       
   363 %{  /* NOCONTEXT */
       
   364 
       
   365 #ifdef POSITIVE_ADDRESSES
       
   366     RETURN ( (_intVal(self) >= 0) ? true : false );
       
   367 #else
       
   368     /* tag bit does not change sign */
       
   369     RETURN ( ((INT)(self) >= 0) ? true : false );
       
   370 #endif
       
   371 %}
       
   372 !
       
   373 
       
   374 strictlyPositive
       
   375     "return true, if the receiver is greater than zero
       
   376      reimplemented here for speed"
       
   377 
       
   378 %{  /* NOCONTEXT */
       
   379 
       
   380 #ifdef POSITIVE_ADDRESSES
       
   381     RETURN ( (_intVal(self) > 0) ? true : false );
       
   382 #else
       
   383     /* tag bit does not change sign */
       
   384     RETURN ( ((INT)(self) > 0) ? true : false );
       
   385 #endif
       
   386 %}
       
   387 !
       
   388 
       
   389 sign
       
   390     "return the sign of the receiver
       
   391      reimplemented here for speed"
       
   392 
       
   393 %{  /* NOCONTEXT */
       
   394 
       
   395     INT val = _intVal(self);
       
   396 
       
   397     if (val < 0) {
       
   398         RETURN ( _MKSMALLINT(-1) ); 
       
   399     }
       
   400     if (val > 0) {
       
   401         RETURN ( _MKSMALLINT(1) );
       
   402     }
       
   403     RETURN ( _MKSMALLINT(0) );
       
   404 %}
       
   405 !
       
   406 
       
   407 between:min and:max
       
   408     "return true if the receiver is less than or equal to the argument max
       
   409      and greater than or equal to the argument min.
       
   410      - reimplemented here for speed"
       
   411 
       
   412 %{  /* NOCONTEXT */
       
   413 
       
   414     if (_isSmallInteger(min) && _isSmallInteger(max)) {
       
   415 	REGISTER INT selfVal;
       
   416 
       
   417 	selfVal = _intVal(self);
       
   418         if (selfVal < _intVal(min)) {
       
   419              RETURN ( false );
       
   420         }
       
   421         if (selfVal > _intVal(max)) {
       
   422              RETURN ( false );
       
   423         }
       
   424         RETURN ( true );
       
   425     }
       
   426 %}
       
   427 .
       
   428     (self < min) ifTrue:[^ false].
       
   429     (self > max) ifTrue:[^ false].
       
   430     ^ true
       
   431 !
       
   432 
       
   433 even
       
   434     "return true, if the receiver is even"
       
   435 
       
   436 %{  /* NOCONTEXT */
       
   437 
       
   438 #ifdef POSITIVE_ADDRESSES
       
   439     RETURN ( ((INT)self & 1) ? false : true );
       
   440 #else    
       
   441     RETURN ( ((INT)self & ((INT)_MKSMALLINT(1) & ~TAG_INT)) ? false : true );
       
   442 #endif
       
   443 %}
       
   444 !
       
   445 
       
   446 odd
       
   447     "return true, if the receiver is odd"
       
   448 
       
   449 %{  /* NOCONTEXT */
       
   450 
       
   451 #ifdef POSITIVE_ADDRESSES
       
   452     RETURN ( ((INT)self & 1) ? true : false );
       
   453 #else    
       
   454     RETURN ( ((INT)self & ((INT)_MKSMALLINT(1) & ~TAG_INT)) ? true : false );
       
   455 #endif
       
   456 %}
       
   457 ! !
       
   458 
       
   459 !SmallInteger methodsFor:'arithmetic'!
       
   460 
       
   461 + aNumber
       
   462     "return the sum of the receivers value and the arguments value"
       
   463 
       
   464 %{  /* NOCONTEXT */
       
   465 
       
   466     if (_isSmallInteger(aNumber)) {
       
   467 #ifdef _ADD_IO_IO
       
   468 	RETURN ( _ADD_IO_IO(self, aNumber) );
       
   469 #else
       
   470         REGISTER INT sum;
       
   471 	extern OBJ _makeLarge();
       
   472 
       
   473         sum =  _intVal(self) + _intVal(aNumber);
       
   474         if ((sum >= _MIN_INT) && (sum <= _MAX_INT)) {
       
   475             RETURN ( _MKSMALLINT(sum) );
       
   476         }
       
   477 	RETURN ( _makeLarge(sum) );
       
   478 #endif
       
   479     }
       
   480     if ((aNumber != nil) && (_qClass(aNumber) == Float)) {
       
   481         extern char *newNextPtr, *newEndPtr;
       
   482         OBJ newFloat;
       
   483 	double val;
       
   484 
       
   485 	val = _floatVal(aNumber);
       
   486         _qAlignedNew(newFloat, sizeof(struct floatstruct), SENDER);
       
   487         _InstPtr(newFloat)->o_class = Float;
       
   488         _FloatInstPtr(newFloat)->f_floatvalue = (double)(_intVal(self)) + val;
       
   489         RETURN ( newFloat );
       
   490     }
       
   491 %}
       
   492 .
       
   493     ^ aNumber sumFromInteger:self
       
   494 !
       
   495 
       
   496 - aNumber
       
   497     "return the difference of the receivers value and the arguments value"
       
   498 
       
   499 %{  /* NOCONTEXT */
       
   500 
       
   501     if (_isSmallInteger(aNumber)) {
       
   502 #ifdef _SUB_IO_IO
       
   503 	RETURN ( _SUB_IO_IO(self, aNumber) );
       
   504 #else
       
   505         REGISTER INT diff;
       
   506 	extern OBJ _makeLarge();
       
   507 
       
   508         diff =  _intVal(self) - _intVal(aNumber);
       
   509         if ((diff >= _MIN_INT) && (diff <= _MAX_INT)) {
       
   510             RETURN ( _MKSMALLINT(diff) );
       
   511         }
       
   512 	RETURN ( _makeLarge(diff) );
       
   513 #endif
       
   514     }
       
   515     if ((aNumber != nil) && (_qClass(aNumber) == Float)) {
       
   516         extern char *newNextPtr, *newEndPtr;
       
   517         OBJ newFloat;
       
   518 	double val;
       
   519 
       
   520 	val = _floatVal(aNumber);
       
   521         _qAlignedNew(newFloat, sizeof(struct floatstruct), SENDER);
       
   522         _InstPtr(newFloat)->o_class = Float;
       
   523         _FloatInstPtr(newFloat)->f_floatvalue = (double)(_intVal(self)) - val;
       
   524         RETURN ( newFloat );
       
   525     }
       
   526 %}
       
   527 .
       
   528     ^ aNumber differenceFromInteger:self
       
   529 !
       
   530 
       
   531 * aNumber
       
   532     "return the product of the receivers value and the arguments value"
       
   533 
       
   534     |aLarge|
       
   535 
       
   536 %{  /* NOCONTEXT */
       
   537 
       
   538     REGISTER INT myValue, otherValue;
       
   539     unsigned INT pHH, pHL, pLH, pLL;
       
   540 
       
   541     if (_isSmallInteger(aNumber)) {
       
   542         /* this is too slow:
       
   543          * since most machines can do 32*32 to 64 bit multiply,
       
   544          * (or at least 32*32 with Overflow check)
       
   545          * its better to do it this way .. - need an assembler (inline) function here 
       
   546          */
       
   547         myValue = _intVal(self);
       
   548         if (myValue < 0) myValue = -myValue;
       
   549         otherValue = _intVal(aNumber);
       
   550         if (otherValue < 0) otherValue = -otherValue;
       
   551 #ifdef NOTDEF
       
   552         if (! ((myValue & ~0x7FFF) || (otherValue & ~0x7FFF))) {
       
   553 #else
       
   554         pHH = ((myValue >> 16) & 0xFFFF) * ((otherValue >> 16) & 0xFFFF);
       
   555         pHL = ((myValue >> 16) & 0xFFFF) * (otherValue & 0xFFFF);
       
   556         pLH = (myValue & 0xFFFF) * ((otherValue >> 16) & 0xFFFF);
       
   557         pLL = (myValue & 0xFFFF) * (otherValue & 0xFFFF);
       
   558         if (! (pHH || (pHL & 0xFFFFc000) || (pLH & 0xFFFFc000) || (pLL & 0xc0000000))) {
       
   559 #endif
       
   560             RETURN ( _MKSMALLINT(_intVal(self) * _intVal(aNumber)) );
       
   561         }
       
   562     } else if ((aNumber != nil) && (_qClass(aNumber) == Float)) {
       
   563         extern char *newNextPtr, *newEndPtr;
       
   564         OBJ newFloat;
       
   565 	double val;
       
   566 
       
   567 	val = _floatVal(aNumber);
       
   568         _qAlignedNew(newFloat, sizeof(struct floatstruct), SENDER);
       
   569         _InstPtr(newFloat)->o_class = Float;
       
   570         _FloatInstPtr(newFloat)->f_floatvalue = (double)(_intVal(self)) * val;
       
   571         RETURN ( newFloat );
       
   572     }
       
   573 %}
       
   574 .
       
   575 %{
       
   576     extern OBJ LargeInteger, __mu, _value_;
       
   577     static struct inlineCache val = _ILC1;
       
   578     static struct inlineCache mu = _ILC1;
       
   579 
       
   580     if (_isSmallInteger(aNumber)) {
       
   581         /*
       
   582          * non overflow case has already been checked
       
   583          */
       
   584 #ifdef PASS_ARG_REF
       
   585         aLarge = (*val.ilc_func)(LargeInteger, _value_, CON_COMMA nil, &val, &self);
       
   586         RETURN ( (*mu.ilc_func)(aLarge, __mu, CON_COMMA nil, &mu, &aNumber) );
       
   587 #else
       
   588         aLarge = (*val.ilc_func)(LargeInteger, _value_, CON_COMMA nil, &val, self);
       
   589         RETURN ( (*mu.ilc_func)(aLarge, __mu, CON_COMMA nil, &mu, aNumber) );
       
   590 #endif
       
   591     }
       
   592 %}
       
   593 .
       
   594     ^ aNumber productFromInteger:self
       
   595 !
       
   596 
       
   597 / aNumber
       
   598     "return the quotient of the receivers value and the arguments value"
       
   599 
       
   600 %{  /* NOCONTEXT */
       
   601 
       
   602     INT me, t, val;
       
   603     double dval;
       
   604 
       
   605     if (_isSmallInteger(aNumber)) {
       
   606         val = _intVal(aNumber);
       
   607         if (val != 0) {
       
   608             me = _intVal(self);
       
   609             t = me / val;
       
   610 #ifdef GOOD_OPTIMIZER
       
   611             if (me % val) {
       
   612 #else
       
   613             /* this is stupid - all I want is to look for a remainder ... 
       
   614                but most compilers are too stupid and generate an extra mod instr.
       
   615                for "if (me % val)" even if most div instructions also compute
       
   616                the remainder.
       
   617                therefore I use a multiplication which is faster than a modulu
       
   618                on most machines
       
   619             */
       
   620             if ((t * val) == me) {
       
   621 #endif
       
   622                 RETURN ( _MKSMALLINT(t) );
       
   623             }
       
   624 /*
       
   625  * now disabled - Fractions work
       
   626  *
       
   627             RETURN ( _MKFLOAT((double)_intVal(self) / (double)val, __context) );
       
   628 */
       
   629         }
       
   630     } else {
       
   631         if (_isFloat(aNumber)) {
       
   632             dval = _floatVal(aNumber);
       
   633             if (dval != 0.0) {
       
   634                 me = _intVal(self);
       
   635                 RETURN ( _MKFLOAT((double)me / dval COMMA_CON) );
       
   636             }
       
   637         }
       
   638     }
       
   639 %}
       
   640 .
       
   641     aNumber isInteger ifTrue:[
       
   642         aNumber = 0 ifTrue:[
       
   643             DivisionByZeroSignal raise.
       
   644             ^ self
       
   645         ].
       
   646         ^ Fraction numerator:self denominator:aNumber
       
   647     ].
       
   648     ^ aNumber quotientFromInteger:self
       
   649 !
       
   650 
       
   651 // anInteger
       
   652     "return the integer part of the quotient of the receivers value
       
   653      and the arguments value"
       
   654 
       
   655 %{  /* NOCONTEXT */
       
   656     INT val;
       
   657 
       
   658     if (_isSmallInteger(anInteger)) {
       
   659         val = _intVal(anInteger);
       
   660         if (val != 0) {
       
   661             RETURN ( _MKSMALLINT(_intVal(self) / val) );
       
   662         }
       
   663     }
       
   664 %}
       
   665 .
       
   666     (anInteger = 0) ifTrue:[
       
   667         DivisionByZeroSignal raise.
       
   668         ^ self
       
   669     ].
       
   670     ^ self retry:#// coercing:anInteger
       
   671 !
       
   672 
       
   673 \\ anInteger
       
   674     "return the integer rest of the receivers value
       
   675      divided by the arguments value"
       
   676 
       
   677 %{  /* NOCONTEXT */
       
   678     INT mySelf, val;
       
   679 
       
   680     if (_isSmallInteger(anInteger)) {
       
   681         mySelf = _intVal(self);
       
   682         if (mySelf < 0) mySelf = -mySelf;
       
   683         val = _intVal(anInteger);
       
   684         if (val != 0) {
       
   685             if (val < 0) {
       
   686                 RETURN ( _MKSMALLINT(-(mySelf % -val)) );
       
   687             }
       
   688             RETURN ( _MKSMALLINT(mySelf % val) );
       
   689         }
       
   690     }
       
   691 %}
       
   692 .
       
   693     (anInteger = 0) ifTrue:[
       
   694         DivisionByZeroSignal raise.
       
   695         ^ self
       
   696     ].
       
   697     ^ self retry:#\\ coercing:anInteger
       
   698 !
       
   699 
       
   700 abs
       
   701     "return the absolute value of the receiver
       
   702      reimplemented here for speed"
       
   703 
       
   704 %{  /* NOCONTEXT */
       
   705 
       
   706     INT val = _intVal(self);
       
   707 
       
   708     if (val != _MIN_INT) {
       
   709         RETURN ( (val < 0) ? _MKSMALLINT(-val) : self );
       
   710     }
       
   711 %}
       
   712 .
       
   713     "only reached for minVal"
       
   714     ^ self negated
       
   715 !
       
   716 
       
   717 negated
       
   718     "return the negative value of the receiver
       
   719      reimplemented here for speed"
       
   720 
       
   721 %{  /* NOCONTEXT */
       
   722 
       
   723     INT val = _intVal(self);
       
   724 
       
   725     if (val != _MIN_INT) {
       
   726         RETURN ( _MKSMALLINT(- val) );
       
   727     }
       
   728 %}
       
   729 .
       
   730     ^ (LargeInteger value:(SmallInteger maxVal)) + 1
       
   731 ! !
       
   732 
       
   733 !SmallInteger methodsFor:'modulu arithmetic'!
       
   734 
       
   735 times:aNumber
       
   736     "return the product of the receiver and the argument as SmallInteger. 
       
   737      If the result overflows integer range the value modulu the SmallInteger 
       
   738      range is returned.
       
   739      This is of course not always correct, but some code does a modulu anyway
       
   740      and can therefore speed things up by not going through LargeIntegers."
       
   741 
       
   742 %{  /* NOCONTEXT */
       
   743 
       
   744     if (_isSmallInteger(aNumber)) {
       
   745         RETURN ( _MKSMALLINT((_intVal(self) * _intVal(aNumber)) & 0x7FFFFFFF) );
       
   746     }
       
   747 %}
       
   748 .
       
   749     self primitiveFailed
       
   750 !
       
   751 
       
   752 plus:aNumber
       
   753     "return the sum of the receiver and the argument as SmallInteger.
       
   754      If the result overflows integer range, the value modulu the SmallInteger
       
   755      range is returned.
       
   756      This is of course not always correct, but some code does a modulu anyway
       
   757      and can therefore speed things up by not going through LargeIntegers."
       
   758 
       
   759 %{  /* NOCONTEXT */
       
   760 
       
   761     if (_isSmallInteger(aNumber)) {
       
   762         RETURN ( _MKSMALLINT((_intVal(self) + _intVal(aNumber)) & 0x7FFFFFFF) );
       
   763     }
       
   764 %}
       
   765 .
       
   766     self primitiveFailed
       
   767 ! !
       
   768 
       
   769 !SmallInteger class methodsFor:'bit mask constants'!
       
   770 
       
   771 bitMaskFor:index
       
   772     "return a bitmask for the index's bit (index starts at 1)"
       
   773 
       
   774     (index between:1 and:SmallInteger maxBits) ifFalse:[
       
   775         ^ self error:'index out of bounds'
       
   776     ].
       
   777     ^ 1 bitShift:(index - 1)
       
   778 ! !
       
   779 
       
   780 !SmallInteger methodsFor:'bit operators'!
       
   781 
       
   782 bitAt:index
       
   783     "return the value of the index's bit (index starts at 1)"
       
   784 
       
   785     |mask|
       
   786 
       
   787     (index between:1 and:SmallInteger maxBits) ifFalse:[
       
   788         ^ self error:'index out of bounds'
       
   789     ].
       
   790     mask := 1 bitShift:(index - 1).
       
   791     ((self bitAnd:mask) == 0) ifTrue:[^ 0].
       
   792     ^ 1
       
   793 !
       
   794 
       
   795 allMask:anInteger
       
   796     "True if all bits in anInteger are 1 in the receiver"
       
   797 
       
   798     ^(self bitAnd:anInteger) == anInteger
       
   799 !
       
   800 
       
   801 anyMask:anInteger
       
   802     "True if any 1 bits in anInteger are 1 in the receiver"
       
   803 
       
   804     ^(self bitAnd:anInteger) ~~ 0
       
   805 !
       
   806 
       
   807 noMask:anInteger
       
   808     "True if no 1 bits in anInteger are 1 in the receiver"
       
   809 
       
   810     ^(self bitAnd:anInteger) == 0
       
   811 !
       
   812 
       
   813 highBit
       
   814     "return the bitIndex of the highest bit set"
       
   815 
       
   816 %{  /* NOCONTEXT */
       
   817 
       
   818     INT mask, index, bits;
       
   819 
       
   820     bits = _intVal(self);
       
   821     if (bits == 0) {
       
   822         RETURN ( _MKSMALLINT(-1) );
       
   823     }
       
   824 #ifdef alpha
       
   825     mask = 0x2000000000000000;
       
   826     index = 62;
       
   827 #else
       
   828     mask = 0x20000000;
       
   829     index = 30;
       
   830 #endif
       
   831     while (index) {
       
   832         if (bits & mask) break;
       
   833         mask = mask >> 1;
       
   834         index--;
       
   835     }
       
   836     RETURN ( _MKSMALLINT(index) );
       
   837 %}
       
   838 !
       
   839 
       
   840 lowBit
       
   841     "return the bitIndex of the lowest bit set"
       
   842 %{  /* NOCONTEXT */
       
   843 
       
   844     INT mask, index, bits;
       
   845 
       
   846     bits = _intVal(self);
       
   847     if (bits == 0) {
       
   848         RETURN ( _MKSMALLINT(-1) );
       
   849     }
       
   850     mask = 1;
       
   851     index = 1;
       
   852 #ifdef alpha
       
   853     while (index != 63) {
       
   854 #else
       
   855     while (index != 31) {
       
   856 #endif
       
   857         if (bits & mask) {
       
   858             RETURN ( _MKSMALLINT(index) );
       
   859         }
       
   860         mask = mask << 1;
       
   861         index++;
       
   862     }
       
   863     RETURN ( _MKSMALLINT(-1) );
       
   864     /* notreached */
       
   865 %}
       
   866 !
       
   867 
       
   868 bitShift:shiftCount
       
   869     "return the value of the receiver shifted by shiftCount bits;
       
   870      leftShift if shiftCount > 0; rightShift otherwise"
       
   871 
       
   872 %{  /* NOCONTEXT */
       
   873 
       
   874     INT bits, count;
       
   875 
       
   876     if (_isSmallInteger(shiftCount)) {
       
   877         count = _intVal(shiftCount);
       
   878         bits = _intVal(self);
       
   879         if (count > 0) {
       
   880             RETURN ( _MKSMALLINT(bits << count) );
       
   881         }
       
   882         if (count < 0) {
       
   883             RETURN ( _MKSMALLINT(bits >> -count) );
       
   884         }
       
   885         RETURN (self );
       
   886     }
       
   887 %}
       
   888 .
       
   889     ^ self bitShift:(shiftCount coerce:1)
       
   890 !
       
   891 
       
   892 bitOr:anInteger
       
   893     "return the bit-or of the receiver and the argument, anInteger"
       
   894 
       
   895 %{  /* NOCONTEXT */
       
   896 
       
   897     /* oring the tags doesn't change it */
       
   898     if (_isSmallInteger(anInteger)) {
       
   899         RETURN ( ((OBJ) ((INT)self | (INT)anInteger)) );
       
   900     }
       
   901 %}
       
   902 .
       
   903     ^ self retry:#bitOr coercing:anInteger
       
   904 !
       
   905 
       
   906 bitAnd:anInteger
       
   907     "return the bit-and of the receiver and the argument, anInteger"
       
   908 
       
   909 %{  /* NOCONTEXT */
       
   910 
       
   911     /* anding the tags doesn't change it */
       
   912     if (_isSmallInteger(anInteger)) {
       
   913         RETURN ( ((OBJ) ((INT)self & (INT)anInteger)) );
       
   914     }
       
   915 %}
       
   916 .
       
   917     ^ self retry:#bitAnd coercing:anInteger
       
   918 !
       
   919 
       
   920 bitXor:anInteger
       
   921     "return the bit-exclusive-or of the receiver and the argument, anInteger"
       
   922 
       
   923 %{  /* NOCONTEXT */
       
   924 
       
   925     /* xoring the tags turns it off - or it in again */
       
   926     if (_isSmallInteger(anInteger)) {
       
   927         RETURN ( (OBJ)( ((INT)self ^ (INT)anInteger) | TAG_INT) );
       
   928     }
       
   929 %}
       
   930 .
       
   931     ^ self retry:#bitXor coercing:anInteger
       
   932 !
       
   933 
       
   934 bitInvert
       
   935     "return the value of the receiver with all bits inverted"
       
   936 
       
   937 %{  /* NOCONTEXT */
       
   938 
       
   939     /* invert anything except tag bits */
       
   940     RETURN ( ((OBJ) ((INT)self ^ ~TAG_MASK)) );
       
   941 %}
       
   942 !
       
   943 
       
   944 bitTest:aMask
       
   945     "return true, if any bit from aMask is set in the receiver"
       
   946 
       
   947 %{  /* NOCONTEXT */
       
   948 
       
   949     /* and all bits except tag */
       
   950     if (_isSmallInteger(aMask)) {
       
   951         RETURN ( ((INT)self & ((INT)aMask & ~TAG_MASK)) ? true : false );
       
   952     }
       
   953 %}
       
   954 .
       
   955     ^ self retry:#bitTest coercing:aMask
       
   956 ! !
       
   957 
       
   958 !SmallInteger methodsFor:'byte access'!
       
   959 
       
   960 digitLength
       
   961     "return the number bytes used by this Integer"
       
   962 
       
   963     ^ self abs highBit - 1 // 8 + 1
       
   964 !
       
   965 
       
   966 digitAt:index
       
   967     "return 8 bits of value, starting at byte index"
       
   968 
       
   969 %{  /* NOCONTEXT */
       
   970 
       
   971     INT val;
       
   972 
       
   973     if (_isSmallInteger(index)) {
       
   974         val = _intVal(self);
       
   975         if (val < 0)
       
   976             val = -val;
       
   977         switch (_intVal(index)) {
       
   978             case 1:
       
   979                 RETURN ( _MKSMALLINT( val & 0xFF) );
       
   980             case 2:
       
   981                 RETURN ( _MKSMALLINT( (val >> 8) & 0xFF) );
       
   982             case 3:
       
   983                 RETURN ( _MKSMALLINT( (val >> 16) & 0xFF) );
       
   984             case 4:
       
   985                 RETURN ( _MKSMALLINT( (val >> 24) & 0xFF) );
       
   986 #ifdef alpha
       
   987             case 5:
       
   988                 RETURN ( _MKSMALLINT( (val >> 32) & 0xFF) );
       
   989             case 6:
       
   990                 RETURN ( _MKSMALLINT( (val >> 40) & 0xFF) );
       
   991             case 7:
       
   992                 RETURN ( _MKSMALLINT( (val >> 48) & 0xFF) );
       
   993             case 8:
       
   994                 RETURN ( _MKSMALLINT( (val >> 56) & 0xFF) );
       
   995 #endif
       
   996         }
       
   997     }
       
   998 %}
       
   999 .
       
  1000     self primitiveFailed
       
  1001 ! !
       
  1002 
       
  1003 !SmallInteger methodsFor:'misc math functions'!
       
  1004 
       
  1005 gcd:anInteger
       
  1006     "return the greatest common divisor (Euclid's algorithm).
       
  1007      This has been redefined here for more speed since due to the
       
  1008      use of gcd in Fraction code, it has become time-critical for
       
  1009      some code. (thanx to MessageTally)"
       
  1010 
       
  1011 %{  /* NOCONTEXT */
       
  1012 
       
  1013     if (_isSmallInteger(anInteger)) {
       
  1014         INT orgArg, ttt, selfInt, temp;
       
  1015 
       
  1016         ttt = orgArg = _intVal(anInteger);
       
  1017 	if (ttt) {
       
  1018             selfInt = _intVal(self);
       
  1019             while (ttt != 0) {
       
  1020                 temp = selfInt % ttt;
       
  1021                 selfInt = ttt;
       
  1022                 ttt = temp;
       
  1023             }
       
  1024 	    /*
       
  1025 	     * since its not defined in what the sign of
       
  1026 	     * a modulu result is when the arg is negative,
       
  1027 	     * change it explicitely here ...
       
  1028 	     */
       
  1029 	    if (orgArg < 0) {
       
  1030 		/* result should be negative */
       
  1031                 if (selfInt > 0) selfInt = -selfInt;
       
  1032 	    } else {
       
  1033 		/* result should be positive */
       
  1034 		if (selfInt < 0) selfInt = -selfInt;
       
  1035 	    }
       
  1036             RETURN ( _MKSMALLINT(selfInt) );
       
  1037         }
       
  1038     }
       
  1039 %}
       
  1040 .
       
  1041     ^ super gcd:anInteger
       
  1042 !
       
  1043 
       
  1044 intlog10
       
  1045     "return the truncation of log10 of the receiver -
       
  1046      stupid implementation; used to find out the number of digits needed
       
  1047      to print a number/and for conversion to a LargeInteger"
       
  1048 
       
  1049     self <= 0 ifTrue:[
       
  1050         self error:'logarithm of negative integer'
       
  1051     ].
       
  1052     self < 10 ifTrue:[^ 1].
       
  1053     self < 100 ifTrue:[^ 2].
       
  1054     self < 1000 ifTrue:[^ 3].
       
  1055     self < 10000 ifTrue:[^ 4].
       
  1056     self < 100000 ifTrue:[^ 5].
       
  1057     self < 1000000 ifTrue:[^ 6].
       
  1058     self < 10000000 ifTrue:[^ 7].
       
  1059     self < 100000000 ifTrue:[^ 8].
       
  1060     self < 1000000000 ifTrue:[^ 9].
       
  1061     ^ 10
       
  1062 ! !
       
  1063 
       
  1064 !SmallInteger methodsFor:'coercing and converting'!
       
  1065 
       
  1066 coerce:aNumber
       
  1067     ^ aNumber asInteger
       
  1068 !
       
  1069 
       
  1070 generality
       
  1071     ^ 20
       
  1072 !
       
  1073 
       
  1074 asFloat
       
  1075     "return a Float with same value as receiver"
       
  1076 
       
  1077 %{  /* NOCONTEXT */
       
  1078 
       
  1079     OBJ newFloat;
       
  1080 
       
  1081     _qAlignedNew(newFloat, sizeof(struct floatstruct), SENDER);
       
  1082     _InstPtr(newFloat)->o_class = Float;
       
  1083     _FloatInstPtr(newFloat)->f_floatvalue = _intVal(self);
       
  1084     RETURN ( newFloat );
       
  1085 %}
       
  1086 !
       
  1087 
       
  1088 asLargeInteger
       
  1089     "return a LargeInteger with same value as receiver"
       
  1090 
       
  1091     ^ LargeInteger value:self
       
  1092 !
       
  1093 
       
  1094 asCharacter
       
  1095     "Return self as an ascii character"
       
  1096 
       
  1097     ^ Character value:self
       
  1098 ! !
       
  1099 
       
  1100 !SmallInteger methodsFor:'iterators'!
       
  1101 
       
  1102 timesRepeat:aBlock
       
  1103     "evaluate the argument, aBlock self times"
       
  1104 
       
  1105     |count "{ Class: SmallInteger }" |
       
  1106 
       
  1107     count := self.
       
  1108     [count > 0] whileTrue:[
       
  1109         aBlock value.
       
  1110         count := count - 1
       
  1111     ]
       
  1112 !
       
  1113 
       
  1114 to:stop do:aBlock
       
  1115     "reimplemented for speed"
       
  1116 
       
  1117     |home index|
       
  1118 %{
       
  1119     REGISTER INT tmp;
       
  1120     INT final;
       
  1121     REGISTER OBJFUNC code;
       
  1122     extern OBJ Block, _value_;
       
  1123     static struct inlineCache blockVal = _ILC1;
       
  1124 #ifdef UPDATE_WHOLE_STACK
       
  1125     REGISTER OBJ rHome;
       
  1126 #   undef home
       
  1127 #   define home rHome
       
  1128 #endif
       
  1129 
       
  1130     if (_isSmallInteger(stop)) {
       
  1131         tmp = _intVal(self);
       
  1132         final = _intVal(stop);
       
  1133         if (_isBlock(aBlock)
       
  1134          && ((code = _BlockInstPtr(aBlock)->b_code) != (OBJFUNC)nil)
       
  1135          && (_BlockInstPtr(aBlock)->b_nargs == _MKSMALLINT(1))) {
       
  1136             /*
       
  1137 	     * arg is a compiled block - 
       
  1138              * directly call it without going through "Block-value"
       
  1139              */
       
  1140             home = _BlockInstPtr(aBlock)->b_home;
       
  1141             while (tmp <= final) {
       
  1142                 if (InterruptPending != nil) interrupt(CONARG);
       
  1143 
       
  1144                 index = _MKSMALLINT(tmp);
       
  1145 #ifdef PASS_ARG_REF
       
  1146                 (*code)(home, CON_COMMA &index);
       
  1147 #else
       
  1148                 (*code)(home, CON_COMMA index);
       
  1149 #endif
       
  1150                 tmp++;
       
  1151             }
       
  1152         } else {
       
  1153             /*
       
  1154 	     * arg is something else - call it with Block-value"
       
  1155              */
       
  1156             while (tmp <= final) {
       
  1157                 if (InterruptPending != nil) interrupt(CONARG);
       
  1158 
       
  1159                 index = _MKSMALLINT(tmp);
       
  1160 #ifdef PASS_ARG_REF
       
  1161                 (*blockVal.ilc_func)(aBlock, _value_, CON_COMMA nil, &blockVal, &index);
       
  1162 #else
       
  1163                 (*blockVal.ilc_func)(aBlock, _value_, CON_COMMA nil, &blockVal, index);
       
  1164 #endif
       
  1165                 tmp++;
       
  1166             }
       
  1167         }
       
  1168         RETURN ( self );
       
  1169     }
       
  1170 %}
       
  1171 .
       
  1172     ^super to:stop do:aBlock
       
  1173 !
       
  1174 
       
  1175 to:stop by:incr do:aBlock
       
  1176     "reimplemented for speed"
       
  1177 
       
  1178     |home index|
       
  1179 %{
       
  1180     REGISTER INT tmp, step;
       
  1181     REGISTER INT final;
       
  1182     REGISTER OBJFUNC code;
       
  1183     extern OBJ Block, _value_;
       
  1184     static struct inlineCache blockVal = _ILC1;
       
  1185 #ifdef UPDATE_WHOLE_STACK
       
  1186     REGISTER OBJ rHome;
       
  1187 #   undef home
       
  1188 #   define home rHome
       
  1189 #endif
       
  1190 
       
  1191     if (_isSmallInteger(incr)
       
  1192      && _isSmallInteger(stop)) {
       
  1193         tmp = _intVal(self);
       
  1194         final = _intVal(stop);
       
  1195         step = _intVal(incr);
       
  1196         if (_isBlock(aBlock)
       
  1197          && ((code = _BlockInstPtr(aBlock)->b_code) != (OBJFUNC)nil)
       
  1198          && (_BlockInstPtr(aBlock)->b_nargs == _MKSMALLINT(1))) {
       
  1199             /*
       
  1200 	     * arg is a compiled block - 
       
  1201              * directly call it without going through "Block-value"
       
  1202              */
       
  1203             home = _BlockInstPtr(aBlock)->b_home;
       
  1204 	    if (step < 0) {
       
  1205                 while (tmp >= final) {
       
  1206                     if (InterruptPending != nil) interrupt(CONARG);
       
  1207 
       
  1208                     index = _MKSMALLINT(tmp);
       
  1209 #ifdef PASS_ARG_REF
       
  1210                     (*code)(home, CON_COMMA &index);
       
  1211 #else
       
  1212                     (*code)(home, CON_COMMA index);
       
  1213 #endif
       
  1214                     tmp += step;
       
  1215                 }
       
  1216 	    } else {
       
  1217                 while (tmp <= final) {
       
  1218                     if (InterruptPending != nil) interrupt(CONARG);
       
  1219 
       
  1220                     index = _MKSMALLINT(tmp);
       
  1221 #ifdef PASS_ARG_REF
       
  1222                     (*code)(home, CON_COMMA &index);
       
  1223 #else
       
  1224                     (*code)(home, CON_COMMA index);
       
  1225 #endif
       
  1226                     tmp += step;
       
  1227                 }
       
  1228             }
       
  1229         } else {
       
  1230             /*
       
  1231 	     * arg is something else - call it with Block-value"
       
  1232              */
       
  1233 	    if (step < 0) {
       
  1234                 while (tmp >= final) {
       
  1235                     if (InterruptPending != nil) interrupt(CONARG);
       
  1236 
       
  1237                     index = _MKSMALLINT(tmp);
       
  1238 #ifdef PASS_ARG_REF
       
  1239                     (*blockVal.ilc_func)(aBlock, _value_, CON_COMMA nil, &blockVal, &index);
       
  1240 #else
       
  1241                     (*blockVal.ilc_func)(aBlock, _value_, CON_COMMA nil, &blockVal, index);
       
  1242 #endif
       
  1243                     tmp += step;
       
  1244                 }
       
  1245 	    } else {
       
  1246                 while (tmp <= final) {
       
  1247                     if (InterruptPending != nil) interrupt(CONARG);
       
  1248 
       
  1249                     index = _MKSMALLINT(tmp);
       
  1250 #ifdef PASS_ARG_REF
       
  1251                     (*blockVal.ilc_func)(aBlock, _value_, CON_COMMA nil, &blockVal, &index);
       
  1252 #else
       
  1253                     (*blockVal.ilc_func)(aBlock, _value_, CON_COMMA nil, &blockVal, index);
       
  1254 #endif
       
  1255                     tmp += step;
       
  1256                 }
       
  1257 	    }
       
  1258         }
       
  1259         RETURN ( self );
       
  1260     }
       
  1261 %}
       
  1262 .
       
  1263     ^super to:stop do:aBlock
       
  1264 ! !
       
  1265 
       
  1266 !SmallInteger methodsFor:'printing & storing'!
       
  1267 
       
  1268 printString
       
  1269     "return my printstring (base 10)"
       
  1270 
       
  1271 %{  /* NOCONTEXT */
       
  1272 
       
  1273     extern char *newNextPtr, *newEndPtr;
       
  1274     char buffer[30];
       
  1275     OBJ newString;
       
  1276 #ifdef THIS_CONTEXT
       
  1277     OBJ sav = __thisContext;
       
  1278 #endif
       
  1279 
       
  1280     sprintf(buffer, "%d", _intVal(self));
       
  1281 #ifdef THIS_CONTEXT
       
  1282     __thisContext = sav;
       
  1283 #endif
       
  1284     _qNew(newString, sizeof(struct stringheader) + strlen(buffer) + 1, SENDER);
       
  1285     _InstPtr(newString)->o_class = String;
       
  1286     strcpy(_stringVal(newString), buffer);
       
  1287     RETURN (newString);
       
  1288 %}
       
  1289 !
       
  1290 
       
  1291 printStringRadix:radix
       
  1292     "return my printstring (base 10)"
       
  1293 
       
  1294 %{  /* NOCONTEXT */
       
  1295 
       
  1296     extern char *newNextPtr, *newEndPtr;
       
  1297     char *format = (char *)0;
       
  1298     char buffer[30];
       
  1299     OBJ newString;
       
  1300 
       
  1301     if (_isSmallInteger(radix)) {
       
  1302         switch (_intVal(radix)) {
       
  1303 	    case 10:
       
  1304 		format = "%d";
       
  1305 		break;
       
  1306 	    case 16:
       
  1307 		format = "%x";
       
  1308 		break;
       
  1309 	    case 8:
       
  1310 		format = "%o";
       
  1311 		break;
       
  1312 	}
       
  1313     }
       
  1314 
       
  1315     if (format) {
       
  1316 #ifdef THIS_CONTEXT
       
  1317         OBJ sav = __thisContext;
       
  1318 #endif
       
  1319         sprintf(buffer, format, _intVal(self));
       
  1320 #ifdef THIS_CONTEXT
       
  1321         __thisContext = sav;
       
  1322 #endif
       
  1323         _qNew(newString, sizeof(struct stringheader) + strlen(buffer) + 1, SENDER);
       
  1324         _InstPtr(newString)->o_class = String;
       
  1325         strcpy(_stringVal(newString), buffer);
       
  1326         RETURN (newString);
       
  1327     }
       
  1328 %}
       
  1329 .
       
  1330     ^ super printStringRadix:radix
       
  1331 !
       
  1332 
       
  1333 printfPrintString:formatString
       
  1334     "non-portable, but sometimes useful.
       
  1335      return a printed representation of the receiver
       
  1336      as specified by formatString, which is defined by printf.
       
  1337      No checking for string overrun - must be shorter than 256 chars or else ..."
       
  1338 
       
  1339 %{  /* NOCONTEXT */
       
  1340 
       
  1341     char buffer[256];
       
  1342 
       
  1343     if (_isString(formatString)) {
       
  1344 #ifdef THIS_CONTEXT
       
  1345         OBJ sav = __thisContext;
       
  1346 #endif
       
  1347         sprintf(buffer, _stringVal(formatString), _intVal(self));
       
  1348 #ifdef THIS_CONTEXT
       
  1349         __thisContext = sav;
       
  1350 #endif
       
  1351         RETURN ( _MKSTRING(buffer COMMA_SND) );
       
  1352     }
       
  1353 %}
       
  1354 .
       
  1355     self primitiveFailed
       
  1356 
       
  1357     "123 printfPrintString:'%%d -> %d'"
       
  1358     "123 printfPrintString:'%%6d -> %6d'"
       
  1359     "123 printfPrintString:'%%x -> %x'"
       
  1360     "123 printfPrintString:'%%4x -> %4x'"
       
  1361     "123 printfPrintString:'%%04x -> %04x'"
       
  1362 ! !