| 1 |
/********************************************************************** |
| 2 |
|
| 3 |
sprintf.c - |
| 4 |
|
| 5 |
Author: knu |
| 6 |
Date: 2001/05/11 14:55:58 |
| 7 |
created at: Fri Oct 15 10:39:26 JST 1993 |
| 8 |
|
| 9 |
Copyright (C) 1993-2000 Yukihiro Matsumoto |
| 10 |
Copyright (C) 2000 Network Applied Communication Laboratory, Inc. |
| 11 |
Copyright (C) 2000 Information-technology Promotion Agency, Japan |
| 12 |
|
| 13 |
**********************************************************************/ |
| 14 |
/* |
| 15 |
Copyright(C) 2001-2002 arton |
| 16 |
|
| 17 |
Permission is granted for use, copying, modification, distribution, |
| 18 |
and distribution of modified versions of this work as long as the |
| 19 |
above copyright notice is included. |
| 20 |
*/ |
| 21 |
|
| 22 |
using System; |
| 23 |
using System.Diagnostics; |
| 24 |
using System.Collections; |
| 25 |
using System.IO; |
| 26 |
using System.Text; |
| 27 |
using System.Threading; |
| 28 |
using System.Reflection; |
| 29 |
using System.Reflection.Emit; |
| 30 |
|
| 31 |
namespace arton.NETRuby |
| 32 |
{ |
| 33 |
public class RKernel : RModule |
| 34 |
{ |
| 35 |
internal RKernel(NetRuby rb, string name) : |
| 36 |
base(rb, name) |
| 37 |
{ |
| 38 |
|
| 39 |
} |
| 40 |
|
| 41 |
public object IsInstanceOf(RBasic r, params object[] args) |
| 42 |
{ |
| 43 |
object o = args[0]; |
| 44 |
if (o == null) |
| 45 |
{ |
| 46 |
return (r == ruby.oNil) ? true : false; |
| 47 |
} |
| 48 |
else if (o is bool) |
| 49 |
{ |
| 50 |
return ((bool)o) ? r == ruby.oTrue : r == ruby.oFalse; |
| 51 |
} |
| 52 |
else if (o is RMetaObject == false) |
| 53 |
{ |
| 54 |
throw new eTypeError("class or module required"); |
| 55 |
} |
| 56 |
return r.Class == o; |
| 57 |
} |
| 58 |
|
| 59 |
public object IsKindOf(RBasic obj, params object[] o) |
| 60 |
{ |
| 61 |
RMetaObject cl = ruby.ClassOf(obj); |
| 62 |
object c = o[0]; |
| 63 |
if (c is RMetaObject == false) |
| 64 |
{ |
| 65 |
throw new eTypeError("class or module required"); |
| 66 |
} |
| 67 |
while (cl != null) |
| 68 |
{ |
| 69 |
if (cl == c || cl.m_tbl == ((RMetaObject)c).m_tbl) |
| 70 |
return true; |
| 71 |
cl = cl.super; |
| 72 |
} |
| 73 |
return false; |
| 74 |
} |
| 75 |
|
| 76 |
public object ruby_array(RBasic r, params object[] o) |
| 77 |
{ |
| 78 |
RBasic x = ruby.InstanceOf(o[0]); |
| 79 |
object val; |
| 80 |
uint to_ary = ruby.intern("to_ary"); |
| 81 |
if (x.RespondTo(to_ary, false)) |
| 82 |
val = ruby.Funcall(x, to_ary, null); |
| 83 |
else |
| 84 |
val = ruby.Funcall(x, ruby.intern("to_a"), null); |
| 85 |
if (val is RArray == false) |
| 86 |
throw new eTypeError("`to_a' did not return Array"); |
| 87 |
return (RArray)val; |
| 88 |
} |
| 89 |
public object ruby_string(RBasic r, params object[] o) |
| 90 |
{ |
| 91 |
RBasic x = ruby.InstanceOf(o[0]); |
| 92 |
return (RString)ruby.ConvertType(x, typeof(RString), "String", "to_s"); |
| 93 |
} |
| 94 |
public object ruby_integer(RBasic r, params object[] o) |
| 95 |
{ |
| 96 |
RBasic x = ruby.InstanceOf(o[0]); |
| 97 |
return (RInteger)ruby.ConvertType(x, typeof(RInteger), "Integer", "to_int"); |
| 98 |
} |
| 99 |
public object ruby_float(RBasic r, params object[] o) |
| 100 |
{ |
| 101 |
if (o[0] == null || o[0] == ruby.oNil) return new RFloat(ruby, 0.0); |
| 102 |
|
| 103 |
RBasic x = ruby.InstanceOf(o[0]); |
| 104 |
return (RFloat)ruby.ConvertType(x, typeof(RFloat), "Float", "to_f"); |
| 105 |
} |
| 106 |
public object ruby_new(RBasic r, params object[] o) |
| 107 |
{ |
| 108 |
return ((RClass)r).NewInstance(o); |
| 109 |
} |
| 110 |
public object ruby_superclass(RBasic r, params object[] o) |
| 111 |
{ |
| 112 |
return ((RClass)r).Superclass; |
| 113 |
} |
| 114 |
public object ruby_s_new(RBasic r, params object[] o) |
| 115 |
{ |
| 116 |
object[] args = new object[1]; |
| 117 |
if (ruby.ScanArgs(o, "01", args) == 0) |
| 118 |
{ |
| 119 |
args[0] = ruby.cObject; |
| 120 |
} |
| 121 |
RMetaObject spr = (RMetaObject)args[0]; |
| 122 |
return RClass.ClassNew(ruby, spr, o); |
| 123 |
} |
| 124 |
public object extend(RBasic r, params object[] o) |
| 125 |
{ |
| 126 |
if (o == null || o.Length == 0) |
| 127 |
throw new eArgError("wrong # of arguments(0 for 1)"); |
| 128 |
for (int i = 0; i < o.Length; i++) |
| 129 |
ruby.CheckType(o[i], typeof(RModule)); |
| 130 |
uint id = ruby.intern("extend_object"); |
| 131 |
for (int i = 0; i < o.Length; i++) |
| 132 |
{ |
| 133 |
ruby.Funcall(o[i], id, r); |
| 134 |
} |
| 135 |
return r; |
| 136 |
} |
| 137 |
public object attr(RBasic r, params object[] o) |
| 138 |
{ |
| 139 |
object[] argv = new object[2]; |
| 140 |
ruby.ScanArgs(o, "11", argv); |
| 141 |
uint id = ruby.ToID(argv[0]); |
| 142 |
((RMetaObject)r).Attribute(ruby.ToID(argv[0]), true, RBasic.RTest(argv[1]), true); |
| 143 |
return null; |
| 144 |
} |
| 145 |
public object attr_reader(RBasic r, params object[] o) |
| 146 |
{ |
| 147 |
for (int i = 0; i < o.Length; i++) |
| 148 |
{ |
| 149 |
((RMetaObject)r).Attribute(ruby.ToID(o[i]), true, false, true); |
| 150 |
} |
| 151 |
return null; |
| 152 |
} |
| 153 |
public object attr_writer(RBasic r, params object[] o) |
| 154 |
{ |
| 155 |
for (int i = 0; i < o.Length; i++) |
| 156 |
{ |
| 157 |
((RMetaObject)r).Attribute(ruby.ToID(o[i]), false, true, true); |
| 158 |
} |
| 159 |
return null; |
| 160 |
} |
| 161 |
public object attr_accessor(RBasic r, params object[] o) |
| 162 |
{ |
| 163 |
for (int i = 0; i < o.Length; i++) |
| 164 |
{ |
| 165 |
((RMetaObject)r).Attribute(ruby.ToID(o[i]), true, true, true); |
| 166 |
} |
| 167 |
return null; |
| 168 |
} |
| 169 |
|
| 170 |
enum PFlag { |
| 171 |
NONE = 0, |
| 172 |
SHARP = 1, |
| 173 |
MINUS = 2, |
| 174 |
PLUS = 4, |
| 175 |
ZERO = 8, |
| 176 |
SPACE = 16, |
| 177 |
WIDTH = 32, |
| 178 |
PREC = 64, |
| 179 |
} |
| 180 |
public object ruby_sleep(RBasic r, params object[] o) |
| 181 |
{ |
| 182 |
long beg = DateTime.Now.Ticks; |
| 183 |
if (o.Length == 0) |
| 184 |
{ |
| 185 |
Thread.Sleep(Timeout.Infinite); |
| 186 |
} |
| 187 |
else if (o.Length == 1) |
| 188 |
{ |
| 189 |
int slp = 0; |
| 190 |
if (o[0] is int) |
| 191 |
{ |
| 192 |
slp = (int)o[0] * 1000; |
| 193 |
} |
| 194 |
Thread.Sleep(slp); |
| 195 |
} |
| 196 |
else |
| 197 |
{ |
| 198 |
throw new ArgumentException("wrong # of arguments"); |
| 199 |
} |
| 200 |
long end = DateTime.Now.Ticks - beg; |
| 201 |
end /= 1000; |
| 202 |
return (int)end; |
| 203 |
} |
| 204 |
|
| 205 |
internal object initialize(RBasic r, params object[] o) |
| 206 |
{ |
| 207 |
return null; |
| 208 |
} |
| 209 |
internal object s_new(RBasic r, params object[] o) |
| 210 |
{ |
| 211 |
RModule mod = new RModule(ruby, null, (RMetaObject)r); |
| 212 |
ruby.CallInit(r, o); |
| 213 |
return mod; |
| 214 |
} |
| 215 |
private static int getarg(object[] args, int index, out object arg) |
| 216 |
{ |
| 217 |
if (index >= args.Length) |
| 218 |
throw new ArgumentException("too few argument."); |
| 219 |
arg = args[index++]; |
| 220 |
return index; |
| 221 |
} |
| 222 |
private static int getaster(string fmt, ref int i, ref int nextarg, object[] args) |
| 223 |
{ |
| 224 |
int t = i++; |
| 225 |
int n = 0; |
| 226 |
for (; i < fmt.Length && Char.IsDigit(fmt[i]); i++) |
| 227 |
{ |
| 228 |
n = 10 * n + (int)Char.GetNumericValue(fmt[i]); |
| 229 |
} |
| 230 |
if (i >= fmt.Length) |
| 231 |
throw new ArgumentException("malformed format string - %%*[0-9]"); |
| 232 |
object temp; |
| 233 |
if (fmt[i] == '$') |
| 234 |
{ |
| 235 |
int curarg = nextarg; |
| 236 |
nextarg = n; |
| 237 |
nextarg = getarg(args, nextarg, out temp); |
| 238 |
nextarg = curarg; |
| 239 |
} |
| 240 |
else |
| 241 |
{ |
| 242 |
nextarg = getarg(args, nextarg, out temp); |
| 243 |
i = t; |
| 244 |
} |
| 245 |
return Convert.ToInt32(temp); |
| 246 |
} |
| 247 |
|
| 248 |
private static string remove_sign_bits(string str, int bas) |
| 249 |
{ |
| 250 |
StringBuilder sb = new StringBuilder(str); |
| 251 |
int i = 0; |
| 252 |
if (bas == 16) |
| 253 |
{ |
| 254 |
x_retry: |
| 255 |
switch (sb[i]) |
| 256 |
{ |
| 257 |
case 'c': case 'C': |
| 258 |
sb[i] = '4'; |
| 259 |
break; |
| 260 |
case 'd': case 'D': |
| 261 |
sb[i] = '5'; |
| 262 |
break; |
| 263 |
case 'e': case 'E': |
| 264 |
sb[i] = '2'; |
| 265 |
break; |
| 266 |
case 'f': case 'F': |
| 267 |
if (sb[i + 1] > '8') { |
| 268 |
i++; |
| 269 |
goto x_retry; |
| 270 |
} |
| 271 |
sb[i] = '1'; |
| 272 |
break; |
| 273 |
case '1': |
| 274 |
case '3': |
| 275 |
case '7': |
| 276 |
if (sb[i + 1] > '8') { |
| 277 |
i++; |
| 278 |
goto x_retry; |
| 279 |
} |
| 280 |
break; |
| 281 |
} |
| 282 |
switch (sb[i]) { |
| 283 |
case '1': sb[i] = 'f'; break; |
| 284 |
case '2': sb[i] = 'e'; break; |
| 285 |
case '3': sb[i] = 'f'; break; |
| 286 |
case '4': sb[i] = 'c'; break; |
| 287 |
case '5': sb[i] = 'd'; break; |
| 288 |
case '6': sb[i] = 'e'; break; |
| 289 |
case '7': sb[i] = 'f'; break; |
| 290 |
} |
| 291 |
} |
| 292 |
else if (bas == 8) { |
| 293 |
o_retry: |
| 294 |
switch (sb[i]) { |
| 295 |
case '6': |
| 296 |
sb[i] = '2'; |
| 297 |
break; |
| 298 |
case '7': |
| 299 |
if (sb[i + 1] > '3') { |
| 300 |
i++; |
| 301 |
goto o_retry; |
| 302 |
} |
| 303 |
sb[i] = '1'; |
| 304 |
break; |
| 305 |
case '1': |
| 306 |
case '3': |
| 307 |
if (sb[i + 1] > '3') { |
| 308 |
i++; |
| 309 |
goto o_retry; |
| 310 |
} |
| 311 |
break; |
| 312 |
} |
| 313 |
switch (sb[i]) { |
| 314 |
case '1': sb[i] = '7'; break; |
| 315 |
case '2': sb[i] = '6'; break; |
| 316 |
case '3': sb[i] = '7'; break; |
| 317 |
} |
| 318 |
} |
| 319 |
else if (bas == 2) { |
| 320 |
while (i < sb.Length && sb[i] == '1') i++; |
| 321 |
i--; |
| 322 |
} |
| 323 |
int i2 = 0; |
| 324 |
while (i < sb.Length) |
| 325 |
sb[i2++] = sb[i++]; |
| 326 |
sb.Length = i2; |
| 327 |
|
| 328 |
return sb.ToString(); |
| 329 |
} |
| 330 |
|
| 331 |
internal static object sprintf(RBasic r, params object[] args) |
| 332 |
{ |
| 333 |
NetRuby ruby = r.ruby; |
| 334 |
|
| 335 |
PFlag flags = PFlag.NONE; |
| 336 |
bool tainted = false; |
| 337 |
object ofmt; |
| 338 |
int nextarg = getarg(args, 0, out ofmt); |
| 339 |
if (ofmt is RBasic) |
| 340 |
{ |
| 341 |
tainted = ((RBasic)ofmt).IsTainted; |
| 342 |
} |
| 343 |
string fmt = ofmt.ToString(); |
| 344 |
StringBuilder result = new StringBuilder(); |
| 345 |
int width, prec; |
| 346 |
for (int i = 0; i < fmt.Length; i++) |
| 347 |
{ |
| 348 |
int n, ix; |
| 349 |
for (ix = i; ix < fmt.Length && fmt[ix] != '%'; ix++) ; |
| 350 |
result.Append(fmt.Substring(i, ix - i)); |
| 351 |
if (ix >= fmt.Length) break; |
| 352 |
i = ix + 1; |
| 353 |
width = prec = -1; |
| 354 |
retry: |
| 355 |
switch (fmt[i]) { |
| 356 |
case ' ': |
| 357 |
flags |= PFlag.SPACE; |
| 358 |
i++; |
| 359 |
goto retry; |
| 360 |
case '#': |
| 361 |
flags |= PFlag.SHARP; |
| 362 |
i++; |
| 363 |
goto retry; |
| 364 |
case '+': |
| 365 |
flags |= PFlag.PLUS; |
| 366 |
i++; |
| 367 |
goto retry; |
| 368 |
case '-': |
| 369 |
flags |= PFlag.MINUS; |
| 370 |
i++; |
| 371 |
goto retry; |
| 372 |
case '0': |
| 373 |
flags |= PFlag.ZERO; |
| 374 |
i++; |
| 375 |
goto retry; |
| 376 |
case '1': case '2': case '3': case '4': |
| 377 |
case '5': case '6': case '7': case '8': case '9': |
| 378 |
n = 0; |
| 379 |
for (; i < fmt.Length && Char.IsDigit(fmt[i]); i++) |
| 380 |
{ |
| 381 |
n = 10 * n + (int)Char.GetNumericValue(fmt[i]); |
| 382 |
} |
| 383 |
if (i >= fmt.Length) |
| 384 |
{ |
| 385 |
throw new ArgumentException("malformed format string - %%[0-9]"); |
| 386 |
} |
| 387 |
if (fmt[i] == '$') |
| 388 |
{ |
| 389 |
nextarg = n; |
| 390 |
i++; |
| 391 |
goto retry; |
| 392 |
} |
| 393 |
width = n; |
| 394 |
flags |= PFlag.WIDTH; |
| 395 |
goto retry; |
| 396 |
case '*': |
| 397 |
if ((flags & PFlag.WIDTH) != 0) |
| 398 |
{ |
| 399 |
throw new ArgumentException("width given twice"); |
| 400 |
} |
| 401 |
flags |= PFlag.WIDTH; |
| 402 |
width = getaster(fmt, ref i, ref nextarg, args); |
| 403 |
if (width < 0) |
| 404 |
{ |
| 405 |
flags |= PFlag.MINUS; |
| 406 |
width = -width; |
| 407 |
} |
| 408 |
i++; |
| 409 |
goto retry; |
| 410 |
case '.': |
| 411 |
if ((flags & PFlag.PREC) != 0) |
| 412 |
{ |
| 413 |
throw new ArgumentException("precision given twice"); |
| 414 |
} |
| 415 |
flags |= PFlag.PREC; |
| 416 |
prec = 0; |
| 417 |
i++; |
| 418 |
if (fmt[i] == '*') |
| 419 |
{ |
| 420 |
prec = getaster(fmt, ref i, ref nextarg, args); |
| 421 |
if (prec < 0) { /* ignore negative precision */ |
| 422 |
flags &= ~PFlag.PREC; |
| 423 |
} |
| 424 |
i++; |
| 425 |
goto retry; |
| 426 |
} |
| 427 |
for (; i < fmt.Length && Char.IsDigit(fmt[i]); i++) |
| 428 |
{ |
| 429 |
prec = 10 * prec + (int)Char.GetNumericValue(fmt[i]); |
| 430 |
} |
| 431 |
if (i >= fmt.Length) |
| 432 |
{ |
| 433 |
throw new ArgumentException("malformed format string - %%.[0-9]"); |
| 434 |
} |
| 435 |
goto retry; |
| 436 |
case '\n': |
| 437 |
i--; |
| 438 |
goto case '%'; |
| 439 |
case '\0': |
| 440 |
case '%': |
| 441 |
if (flags != PFlag.NONE) |
| 442 |
{ |
| 443 |
throw new ArgumentException("illegal format character - %%"); |
| 444 |
} |
| 445 |
result.Append('%'); |
| 446 |
break; |
| 447 |
case 'c': { |
| 448 |
object val; |
| 449 |
nextarg = getarg(args, nextarg, out val); |
| 450 |
if ((flags & PFlag.MINUS) == 0) |
| 451 |
{ |
| 452 |
if (width > 0) result.Append(new String(' ', width)); |
| 453 |
width = 0; |
| 454 |
} |
| 455 |
char c = (char)Convert.ToInt32(val); |
| 456 |
if (width > 0) |
| 457 |
result.AppendFormat("{0}{1}", c, new String(' ', width)); |
| 458 |
break; |
| 459 |
} |
| 460 |
case 's': { |
| 461 |
object arg; |
| 462 |
nextarg = getarg(args, nextarg, out arg); |
| 463 |
RString rs = RString.AsRString(ruby, arg); |
| 464 |
if (rs.IsTainted) tainted = true; |
| 465 |
int len = rs.Length; |
| 466 |
if ((flags & PFlag.PREC) != 0) |
| 467 |
{ |
| 468 |
if (prec < len) |
| 469 |
{ |
| 470 |
len = prec; |
| 471 |
} |
| 472 |
} |
| 473 |
if ((flags & PFlag.WIDTH) != 0) |
| 474 |
{ |
| 475 |
if (width > len) |
| 476 |
{ |
| 477 |
width -= len; |
| 478 |
if ((flags & PFlag.MINUS) == 0) |
| 479 |
{ |
| 480 |
if (width > 0) result.Append(new String(' ', width)); |
| 481 |
width = 0; |
| 482 |
} |
| 483 |
result.Append(rs.ToString()); |
| 484 |
if ((flags & PFlag.MINUS) != 0) |
| 485 |
{ |
| 486 |
if (width > 0) result.Append(new String(' ', width)); |
| 487 |
} |
| 488 |
break; |
| 489 |
} |
| 490 |
} |
| 491 |
result.Append(rs.ToString().Substring(0, len)); |
| 492 |
break; |
| 493 |
} |
| 494 |
case 'd': |
| 495 |
case 'i': |
| 496 |
case 'o': |
| 497 |
case 'x': |
| 498 |
case 'X': |
| 499 |
case 'b': |
| 500 |
case 'u': { |
| 501 |
char sc = '\0'; |
| 502 |
char ch = fmt[i]; |
| 503 |
object val; |
| 504 |
nextarg = getarg(args, nextarg, out val); |
| 505 |
bool sign = false; |
| 506 |
bool bignum = false; |
| 507 |
long num = 0; |
| 508 |
string prefix = String.Empty; |
| 509 |
string s = String.Empty; |
| 510 |
switch (ch) |
| 511 |
{ |
| 512 |
case 'd': |
| 513 |
case 'i': |
| 514 |
sign = true; break; |
| 515 |
case 'o': |
| 516 |
case 'x': |
| 517 |
case 'X': |
| 518 |
case 'b': |
| 519 |
case 'u': |
| 520 |
default: |
| 521 |
if ((flags & (PFlag.PLUS|PFlag.SPACE)) != 0) sign = true; |
| 522 |
break; |
| 523 |
} |
| 524 |
if ((flags & PFlag.SHARP) != 0) |
| 525 |
{ |
| 526 |
if (fmt[i] == 'o') prefix = "0"; |
| 527 |
else if (fmt[i] == 'x') prefix = "0x"; |
| 528 |
else if (fmt[i] == 'X') prefix = "0X"; |
| 529 |
else if (fmt[i] == 'b') prefix = "0b"; |
| 530 |
if (prefix.Length > 0) |
| 531 |
{ |
| 532 |
width -= prefix.Length; |
| 533 |
} |
| 534 |
} |
| 535 |
bin_retry: |
| 536 |
if (val is RFloat) |
| 537 |
{ |
| 538 |
val = ((RFloat)val).ToInteger(); |
| 539 |
goto bin_retry; |
| 540 |
} |
| 541 |
else if (val is double) |
| 542 |
{ |
| 543 |
val = RFloat.ToInteger(ruby, (double)val); |
| 544 |
goto bin_retry; |
| 545 |
} |
| 546 |
else if (val is string) |
| 547 |
{ |
| 548 |
val = RInteger.StringToInteger(ruby, (string)val, 0); |
| 549 |
goto bin_retry; |
| 550 |
} |
| 551 |
else if (val is RString) |
| 552 |
{ |
| 553 |
val = ((RString)val).ToInteger(); |
| 554 |
goto bin_retry; |
| 555 |
} |
| 556 |
else if (val is int) |
| 557 |
{ |
| 558 |
num = (long)(int)val; |
| 559 |
} |
| 560 |
else if (val is long) |
| 561 |
{ |
| 562 |
num = (long)val; |
| 563 |
} |
| 564 |
else if (val is uint) |
| 565 |
{ |
| 566 |
num = (long)(uint)val; |
| 567 |
} |
| 568 |
else if (val is RBignum) |
| 569 |
{ |
| 570 |
bignum = true; |
| 571 |
} |
| 572 |
else |
| 573 |
{ |
| 574 |
num = RInteger.ToLong(ruby, val); |
| 575 |
} |
| 576 |
int bas = 0; |
| 577 |
if (ch == 'u' || ch == 'd' || ch == 'i') bas = 10; |
| 578 |
else if (ch == 'x' || ch == 'X') bas = 16; |
| 579 |
else if (ch == 'o') bas = 8; |
| 580 |
else if (ch == 'b') bas = 2; |
| 581 |
if (!bignum) |
| 582 |
{ |
| 583 |
if (sign) |
| 584 |
{ |
| 585 |
if (ch == 'i') ch = 'd'; /* %d and %i are identical */ |
| 586 |
if (num < 0) |
| 587 |
{ |
| 588 |
num = -num; |
| 589 |
sc = '-'; |
| 590 |
width--; |
| 591 |
} |
| 592 |
else if ((flags & PFlag.PLUS) != 0) |
| 593 |
{ |
| 594 |
sc = '+'; |
| 595 |
width--; |
| 596 |
} |
| 597 |
else if ((flags & PFlag.SPACE) != 0) |
| 598 |
{ |
| 599 |
sc = ' '; |
| 600 |
width--; |
| 601 |
} |
| 602 |
s = Convert.ToString(num, bas); |
| 603 |
goto format_integer; |
| 604 |
} |
| 605 |
else |
| 606 |
{ |
| 607 |
s = Convert.ToString(num, bas); |
| 608 |
goto format_integer; |
| 609 |
} |
| 610 |
} |
| 611 |
// bignum |
| 612 |
RBignum big = (RBignum)val; |
| 613 |
if (sign) { |
| 614 |
s = big.ToRString(bas).ToString(); |
| 615 |
if (s[0] == '-') { |
| 616 |
s = s.Substring(1); |
| 617 |
sc = '-'; |
| 618 |
width--; |
| 619 |
} |
| 620 |
else if ((flags & PFlag.PLUS) != 0) { |
| 621 |
sc = '+'; |
| 622 |
width--; |
| 623 |
} |
| 624 |
else if ((flags & PFlag.SPACE) != 0) { |
| 625 |
sc = ' '; |
| 626 |
width--; |
| 627 |
} |
| 628 |
goto format_integer; |
| 629 |
} |
| 630 |
if (big.Sign == false) |
| 631 |
{ |
| 632 |
big = (RBignum)big.Clone(); |
| 633 |
big.TwoComp(); |
| 634 |
} |
| 635 |
s = big.ToRString(bas).ToString(); |
| 636 |
if (s[0] == '-') { |
| 637 |
s = remove_sign_bits(s.Substring(1), bas); |
| 638 |
StringBuilder sb = new StringBuilder(s.Length + 3); |
| 639 |
sb.Append(".."); |
| 640 |
switch (bas) |
| 641 |
{ |
| 642 |
case 16: |
| 643 |
if (s[0] != 'f') sb.Append('f'); break; |
| 644 |
case 8: |
| 645 |
if (s[0] != '7') sb.Append('7'); break; |
| 646 |
} |
| 647 |
sb.Append(s); |
| 648 |
s = sb.ToString(); |
| 649 |
} |
| 650 |
|
| 651 |
format_integer: |
| 652 |
int pos = -1; |
| 653 |
int len = s.Length; |
| 654 |
|
| 655 |
if (ch == 'X') |
| 656 |
{ |
| 657 |
s = s.ToUpper(); |
| 658 |
} |
| 659 |
if (prec < len) |
| 660 |
prec = len; |
| 661 |
width -= prec; |
| 662 |
if ((flags & (PFlag.ZERO|PFlag.MINUS)) == 0 && s[0] != '.') |
| 663 |
{ |
| 664 |
if (width > 0) s = s.PadLeft(s.Length + width); |
| 665 |
width = 0; |
| 666 |
} |
| 667 |
if (sc != '\0') result.Append(sc); |
| 668 |
if (prefix.Length > 0) |
| 669 |
{ |
| 670 |
result.Append(prefix); |
| 671 |
if (pos != 0) pos += prefix.Length; |
| 672 |
} |
| 673 |
if ((flags & PFlag.MINUS) == 0) |
| 674 |
{ |
| 675 |
char c = ' '; |
| 676 |
|
| 677 |
if (s[0] == '.') |
| 678 |
{ |
| 679 |
c = '.'; |
| 680 |
if ((flags & PFlag.PREC) != 0 && prec > len) |
| 681 |
{ |
| 682 |
pos = result.Length; |
| 683 |
} |
| 684 |
else |
| 685 |
{ |
| 686 |
pos = result.Length + 2; |
| 687 |
} |
| 688 |
} |
| 689 |
else if ((flags & PFlag.ZERO) != 0) c = '0'; |
| 690 |
if (width > 0) |
| 691 |
{ |
| 692 |
result.Append(new String(c, width)); |
| 693 |
width = 0; |
| 694 |
} |
| 695 |
} |
| 696 |
if (len < prec) |
| 697 |
{ |
| 698 |
result.Append(new String((s[0]=='.'?'.':'0'), (prec - len))); |
| 699 |
} |
| 700 |
result.Append(s); |
| 701 |
if (width > 0) |
| 702 |
{ |
| 703 |
result.Append(new String(' ', width)); |
| 704 |
} |
| 705 |
break; } |
| 706 |
|
| 707 |
case 'f': |
| 708 |
case 'g': |
| 709 |
case 'G': |
| 710 |
case 'e': |
| 711 |
case 'E': { |
| 712 |
object val; |
| 713 |
nextarg = getarg(args, nextarg, out val); |
| 714 |
double fval = 0.0; |
| 715 |
|
| 716 |
if (val is RString || val is string) |
| 717 |
{ |
| 718 |
fval = Convert.ToDouble(((RString)val).ToString()); |
| 719 |
} |
| 720 |
else if (val is int || val is long || val is uint) |
| 721 |
{ |
| 722 |
fval = Convert.ToDouble(val); |
| 723 |
} |
| 724 |
else if (val is RFloat) |
| 725 |
{ |
| 726 |
fval = ((RFloat)val).Double; |
| 727 |
} |
| 728 |
else if (val is double) |
| 729 |
{ |
| 730 |
fval = (double)val; |
| 731 |
} |
| 732 |
|
| 733 |
string buf; |
| 734 |
if (fmt[i] != 'e' && fmt[i] != 'E') |
| 735 |
{ |
| 736 |
buf = new String(fmt[i], 1); |
| 737 |
if ((flags & PFlag.PREC) != 0) |
| 738 |
buf += prec.ToString(); |
| 739 |
else |
| 740 |
buf += '6'; |
| 741 |
} |
| 742 |
else |
| 743 |
{ |
| 744 |
buf = "#"; |
| 745 |
if ((flags & PFlag.SHARP) != 0) |
| 746 |
buf += ".0"; |
| 747 |
buf += fmt[i]; |
| 748 |
if ((flags & PFlag.PLUS) != 0) |
| 749 |
buf += '+'; |
| 750 |
if ((flags & PFlag.PREC) != 0) |
| 751 |
buf += new String('0', prec); |
| 752 |
else |
| 753 |
buf += '0'; |
| 754 |
} |
| 755 |
buf = fval.ToString(buf); |
| 756 |
if ((flags & PFlag.WIDTH) != 0) |
| 757 |
{ |
| 758 |
} |
| 759 |
result.Append(buf); |
| 760 |
break; } |
| 761 |
default: |
| 762 |
throw new ArgumentException(String.Format("malformed format string - %{0}", fmt[i])); |
| 763 |
} |
| 764 |
flags = PFlag.NONE; |
| 765 |
} |
| 766 |
if (tainted) |
| 767 |
return new RString(ruby, result.ToString(), true); |
| 768 |
return result.ToString(); |
| 769 |
} |
| 770 |
|
| 771 |
internal void Init(NetRuby rb) |
| 772 |
{ |
| 773 |
BindingFlags bf = BindingFlags.InvokeMethod |
| 774 |
| BindingFlags.Static | BindingFlags.Public |
| 775 |
| BindingFlags.NonPublic | BindingFlags.FlattenHierarchy |
| 776 |
| BindingFlags.Instance; |
| 777 |
|
| 778 |
RMethod rmDummy = new RMethod(ruby_dummy); |
| 779 |
rb.cObject.DefinePrivateMethod("initialize", rmDummy, 0); |
| 780 |
rb.cClass.DefinePrivateMethod("inherited", rmDummy, 1); |
| 781 |
|
| 782 |
DefineMethod("nil?", new RMethod(ruby_isnil), 0); |
| 783 |
DefineMethod("==", new RMethod(ruby_equals), 1); |
| 784 |
DefineAlias("equal?", "=="); |
| 785 |
DefineAlias("===", "=="); |
| 786 |
DefineMethod("=~", new RMethod(ruby_false), 1); |
| 787 |
DefineMethod("eql?", new RMethod(ruby_eql), 1); |
| 788 |
|
| 789 |
Type obj = GetType(); |
| 790 |
|
| 791 |
RMethod rm = new RMethod(ruby_id); |
| 792 |
DefineMethod("hash", rm, 0); |
| 793 |
DefineMethod("id", rm, 0); |
| 794 |
DefineMethod("__id__", rm, 0); |
| 795 |
rm = new RMethod(ruby_class); |
| 796 |
DefineMethod("type", rm, 0); |
| 797 |
DefineMethod("class", rm, 0); |
| 798 |
|
| 799 |
DefineMethod("clone", new RMethod(ruby_clone), 0); |
| 800 |
DefineMethod("dup", new RMethod(ruby_dup), 0); |
| 801 |
DefineMethod("taint", new RMethod(ruby_taint), 0); |
| 802 |
DefineMethod("tainted?", new RMethod(ruby_istainted), 0); |
| 803 |
|
| 804 |
DefineMethod("Untaint", new RMethod(ruby_untaint), 0); |
| 805 |
DefineMethod("freeze", new RMethod(ruby_freeze), 0); |
| 806 |
DefineMethod("frozen?", new RMethod(ruby_isfrozen), 0); |
| 807 |
|
| 808 |
DefineMethod("to_a", new RMethod(ruby_to_a), 0); |
| 809 |
DefineMethod("to_s", new RMethod(ruby_to_s), 0); |
| 810 |
DefineMethod("inspect", new RMethod(ruby_inspect), 0); |
| 811 |
rm = new RMethod(ruby_methods); |
| 812 |
DefineMethod("methods", rm, 0); |
| 813 |
DefineMethod("public_methods", rm, 0); |
| 814 |
DefineMethod("singleton_methods", new RMethod(ruby_singleton_methods), 0); |
| 815 |
DefineMethod("protected_methods", new RMethod(ruby_protected_methods), 0); |
| 816 |
DefineMethod("private_methods", new RMethod(ruby_private_methods), 0); |
| 817 |
DefineMethod("instance_variables", new RMethod(ruby_instance_variables), 0); |
| 818 |
DefinePrivateMethod("remove_instance_variable", |
| 819 |
new RMethod(ruby_remove_instance_variable), 1); |
| 820 |
DefineMethod("instance_of?", new RMethod(IsInstanceOf), 1); |
| 821 |
rm = new RMethod(IsKindOf); |
| 822 |
DefineMethod("kind_of?", rm, 1); |
| 823 |
DefineMethod("is_a?", rm, 1); |
| 824 |
|
| 825 |
rb.DefineGlobalFunction("singleton_method_added", rmDummy, 1); |
| 826 |
rb.DefineGlobalFunction("sprintf", new RMethod(sprintf), -1); |
| 827 |
rb.DefineGlobalFunction("format", new RMethod(sprintf), -1); |
| 828 |
|
| 829 |
rb.DefineGlobalFunction("Integer", new RMethod(ruby_integer), 1); |
| 830 |
rb.DefineGlobalFunction("Float", new RMethod(ruby_float), 1); |
| 831 |
rb.DefineGlobalFunction("String", new RMethod(ruby_string), 1); |
| 832 |
rb.DefineGlobalFunction("Array", new RMethod(ruby_array), 1); |
| 833 |
|
| 834 |
rb.DefineGlobalFunction("sleep", new RMethod(ruby_sleep), -1); |
| 835 |
|
| 836 |
rb.oNil = new RNil(rb); |
| 837 |
rb.oNil.Init(rb); |
| 838 |
|
| 839 |
Symbol.Init(rb); |
| 840 |
|
| 841 |
obj = typeof(RMetaObject); |
| 842 |
rb.cModule.DefineMethod("===", obj.GetMethod("Eqq")); |
| 843 |
rb.cModule.DefineMethod("<=>", obj.GetMethod("CompareTo")); |
| 844 |
rb.cModule.DefineMethod("<", obj.GetMethod("lt")); |
| 845 |
rb.cModule.DefineMethod("<=", obj.GetMethod("le")); |
| 846 |
rb.cModule.DefineMethod(">", obj.GetMethod("gt")); |
| 847 |
rb.cModule.DefineMethod(">=", obj.GetMethod("ge")); |
| 848 |
|
| 849 |
rb.cModule.DefineMethod("included_modules", obj.GetMethod("IncludedModules")); |
| 850 |
rb.cModule.DefineMethod("name", obj.GetMethod("get_ModuleName")); |
| 851 |
|
| 852 |
rb.cModule.DefineMethod("attr", new RMethod(attr), -1); |
| 853 |
rb.cModule.DefineMethod("attr_reader", new RMethod(attr_reader), -1); |
| 854 |
rb.cModule.DefineMethod("attr_writer", new RMethod(attr_writer), -1); |
| 855 |
rb.cModule.DefineMethod("attr_accessor", new RMethod(attr_accessor), -1); |
| 856 |
|
| 857 |
rb.cModule.DefineSingletonMethod("new", new RMethod(s_new), 0); |
| 858 |
rb.cModule.DefineMethod("initialize", new RMethod(initialize), -1); |
| 859 |
|
| 860 |
rb.cModule.DefineMethod("instance_methods", obj.GetMethod("ClassInstanceMethods", bf)); |
| 861 |
rb.cModule.DefineMethod("public_instance_methods", obj.GetMethod("ClassInstanceMethods", bf)); |
| 862 |
rb.cModule.DefineMethod("protected_instance_methods", obj.GetMethod("ClassProtectedInstanceMethods", bf)); |
| 863 |
rb.cModule.DefineMethod("private_instance_methods", obj.GetMethod("ClassPrivateInstanceMethods", bf)); |
| 864 |
|
| 865 |
rb.cModule.DefineMethod("constants", new RMethod(rb.cModule.constants), 0); |
| 866 |
rb.cModule.DefineMethod("const_get", new RMethod(rb.cModule.const_get), 1); |
| 867 |
rb.cModule.DefineMethod("const_set", new RMethod(rb.cModule.const_set), 2); |
| 868 |
rb.cModule.DefineMethod("const_defined?", new RMethod(rb.cModule.is_const_defined), 1); |
| 869 |
rb.cModule.DefineMethod("remove_const", new RMethod(rb.cModule.remove_const), 1); |
| 870 |
rb.cModule.DefineMethod("method_added", rmDummy, 1); |
| 871 |
|
| 872 |
obj = rb.cClass.GetType(); |
| 873 |
rb.cClass.DefineMethod("new", new RMethod(ruby_new), -1); |
| 874 |
rb.cClass.DefineMethod("superclass", new RMethod(ruby_superclass), 0); |
| 875 |
rb.cClass.DefineSingletonMethod("new", new RMethod(ruby_s_new), -1); |
| 876 |
rb.cClass.UndefMethod("extend_object"); |
| 877 |
rb.cClass.UndefMethod("append_feartures"); |
| 878 |
rb.cClass.DefineSingletonMethod("inherited", new RMethod(RClass.Inherited), 1); |
| 879 |
|
| 880 |
rb.cData = rb.DefineClass("Data", rb.cObject); |
| 881 |
rb.ClassOf(rb.cData).UndefMethod("new"); |
| 882 |
|
| 883 |
rb.topSelf = new RMainObject(rb); |
| 884 |
|
| 885 |
rb.oTrue = new RTrue(rb); |
| 886 |
rb.oTrue.Init(rb); |
| 887 |
rb.oFalse = new RFalse(rb); |
| 888 |
rb.oFalse.Init(rb); |
| 889 |
} |
| 890 |
|
| 891 |
internal void evalInit() |
| 892 |
{ |
| 893 |
DefineMethod("respond_to?", new RMethod(ruby_respond_to), -1); |
| 894 |
|
| 895 |
DefineMethod("send", new RMethod(ruby_send), -1); |
| 896 |
DefineMethod("__send__", new RMethod(ruby_send), -1); |
| 897 |
DefineMethod("instance_eval", new RMethod(instance_eval), -1); |
| 898 |
} |
| 899 |
} |
| 900 |
} |
| 901 |
|