1
0
Fork 0
mirror of https://github.com/ruby/ruby.git synced 2022-11-09 12:17:21 -05:00
ruby--ruby/pack.c

2237 lines
58 KiB
C
Raw Normal View History

/**********************************************************************
pack.c -
$Author$
created at: Thu Feb 10 15:17:05 JST 1994
* encoding.c: provide basic features for M17N. * parse.y: encoding aware parsing. * parse.y (pragma_encoding): encoding specification pragma. * parse.y (rb_intern3): encoding specified symbols. * string.c (rb_str_length): length based on characters. for older behavior, bytesize method added. * string.c (rb_str_index_m): index based on characters. rindex as well. * string.c (succ_char): encoding aware succeeding string. * string.c (rb_str_reverse): reverse based on characters. * string.c (rb_str_inspect): encoding aware string description. * string.c (rb_str_upcase_bang): encoding aware case conversion. downcase, capitalize, swapcase as well. * string.c (rb_str_tr_bang): tr based on characters. delete, squeeze, tr_s, count as well. * string.c (rb_str_split_m): split based on characters. * string.c (rb_str_each_line): encoding aware each_line. * string.c (rb_str_each_char): added. iteration based on characters. * string.c (rb_str_strip_bang): encoding aware whitespace stripping. lstrip, rstrip as well. * string.c (rb_str_justify): encoding aware justifying (ljust, rjust, center). * string.c (str_encoding): get encoding attribute from a string. * re.c (rb_reg_initialize): encoding aware regular expression * sprintf.c (rb_str_format): formatting (i.e. length count) based on characters. * io.c (rb_io_getc): getc to return one-character string. for older behavior, getbyte method added. * ext/stringio/stringio.c (strio_getc): ditto. * io.c (rb_io_ungetc): allow pushing arbitrary string at the current reading point. * ext/stringio/stringio.c (strio_ungetc): ditto. * ext/strscan/strscan.c: encoding support. git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@13261 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2007-08-24 23:29:39 -04:00
Copyright (C) 1993-2007 Yukihiro Matsumoto
**********************************************************************/
#include "ruby/ruby.h"
#include "ruby/encoding.h"
#include "internal.h"
#include <sys/types.h>
#include <ctype.h>
#include <errno.h>
/*
* It is intentional that the condition for natstr is HAVE_TRUE_LONG_LONG
* instead of HAVE_LONG_LONG or LONG_LONG.
* This means q! and Q! means always the standard long long type and
* causes ArgumentError for platforms which has no long long type,
* even if the platform has an implementation specific 64bit type.
* This behavior is consistent with the document of pack/unpack.
*/
#ifdef HAVE_TRUE_LONG_LONG
static const char natstr[] = "sSiIlLqQ";
#else
static const char natstr[] = "sSiIlL";
#endif
static const char endstr[] = "sSiIlLqQ";
#ifdef HAVE_TRUE_LONG_LONG
/* It is intentional to use long long instead of LONG_LONG. */
# define NATINT_LEN_Q NATINT_LEN(long long, 8)
#else
# define NATINT_LEN_Q 8
#endif
#if SIZEOF_SHORT != 2 || SIZEOF_LONG != 4 || (defined(HAVE_TRUE_LONG_LONG) && SIZEOF_LONG_LONG != 8)
# define NATINT_PACK
#endif
#ifdef DYNAMIC_ENDIAN
/* for universal binary of NEXTSTEP and MacOS X */
/* useless since autoconf 2.63? */
static int
is_bigendian(void)
{
static int init = 0;
static int endian_value;
char *p;
if (init) return endian_value;
init = 1;
p = (char*)&init;
return endian_value = p[0]?0:1;
}
# define BIGENDIAN_P() (is_bigendian())
#elif defined(WORDS_BIGENDIAN)
# define BIGENDIAN_P() 1
#else
# define BIGENDIAN_P() 0
#endif
#ifdef NATINT_PACK
# define NATINT_LEN(type,len) (natint?(int)sizeof(type):(int)(len))
#else
# define NATINT_LEN(type,len) ((int)sizeof(type))
#endif
#if SIZEOF_LONG == 8
# define INT64toNUM(x) LONG2NUM(x)
# define UINT64toNUM(x) ULONG2NUM(x)
#elif defined(HAVE_LONG_LONG) && SIZEOF_LONG_LONG == 8
# define INT64toNUM(x) LL2NUM(x)
# define UINT64toNUM(x) ULL2NUM(x)
#endif
#define define_swapx(x, xtype) \
static xtype \
TOKEN_PASTE(swap,x)(xtype z) \
{ \
xtype r; \
xtype *zp; \
unsigned char *s, *t; \
int i; \
\
zp = xmalloc(sizeof(xtype)); \
*zp = z; \
s = (unsigned char*)zp; \
t = xmalloc(sizeof(xtype)); \
for (i=0; i<sizeof(xtype); i++) { \
t[sizeof(xtype)-i-1] = s[i]; \
} \
r = *(xtype *)t; \
xfree(t); \
xfree(zp); \
return r; \
}
#ifndef swap32
# if GCC_VERSION_SINCE(4,3,0)
# define swap32(x) __builtin_bswap32(x)
# endif
#endif
#ifndef swap64
# if GCC_VERSION_SINCE(4,3,0)
# define swap64(x) __builtin_bswap64(x)
# endif
#endif
#ifndef swap16
# define swap16(x) ((uint16_t)((((x)&0xFF)<<8) | (((x)>>8)&0xFF)))
#endif
#ifndef swap32
# define swap32(x) ((uint32_t)((((x)&0xFF)<<24) \
|(((x)>>24)&0xFF) \
|(((x)&0x0000FF00)<<8) \
|(((x)&0x00FF0000)>>8) ))
#endif
#ifndef swap64
# ifdef HAVE_INT64_T
# define byte_in_64bit(n) ((uint64_t)0xff << (n))
# define swap64(x) ((uint64_t)((((x)&byte_in_64bit(0))<<56) \
|(((x)>>56)&0xFF) \
|(((x)&byte_in_64bit(8))<<40) \
|(((x)&byte_in_64bit(48))>>40) \
|(((x)&byte_in_64bit(16))<<24) \
|(((x)&byte_in_64bit(40))>>24) \
|(((x)&byte_in_64bit(24))<<8) \
|(((x)&byte_in_64bit(32))>>8)))
# endif
#endif
#if SIZEOF_SHORT == 2
# define swaps(x) swap16(x)
#elif SIZEOF_SHORT == 4
# define swaps(x) swap32(x)
#else
define_swapx(s,short)
#endif
#if SIZEOF_INT == 2
# define swapi(x) swap16(x)
#elif SIZEOF_INT == 4
# define swapi(x) swap32(x)
#else
define_swapx(i,int)
#endif
#if SIZEOF_LONG == 4
# define swapl(x) swap32(x)
#elif SIZEOF_LONG == 8
# define swapl(x) swap64(x)
#else
define_swapx(l,long)
#endif
#ifdef HAVE_LONG_LONG
# if SIZEOF_LONG_LONG == 8
# define swapll(x) swap64(x)
# else
define_swapx(ll,LONG_LONG)
# endif
#endif
#if SIZEOF_FLOAT == 4 && defined(HAVE_INT32_T)
# define swapf(x) swap32(x)
# define FLOAT_SWAPPER uint32_t
#else
define_swapx(f,float)
#endif
#if SIZEOF_DOUBLE == 8 && defined(HAVE_INT64_T)
# define swapd(x) swap64(x)
# define DOUBLE_SWAPPER uint64_t
#elif SIZEOF_DOUBLE == 8 && defined(HAVE_INT32_T)
static double
swapd(const double d)
{
double dtmp = d;
uint32_t utmp[2];
uint32_t utmp0;
utmp[0] = 0; utmp[1] = 0;
memcpy(utmp,&dtmp,sizeof(double));
utmp0 = utmp[0];
utmp[0] = swap32(utmp[1]);
utmp[1] = swap32(utmp0);
memcpy(&dtmp,utmp,sizeof(double));
return dtmp;
}
#else
define_swapx(d, double)
#endif
#undef define_swapx
#define rb_ntohf(x) (BIGENDIAN_P()?(x):swapf(x))
#define rb_ntohd(x) (BIGENDIAN_P()?(x):swapd(x))
#define rb_htonf(x) (BIGENDIAN_P()?(x):swapf(x))
#define rb_htond(x) (BIGENDIAN_P()?(x):swapd(x))
#define rb_htovf(x) (BIGENDIAN_P()?swapf(x):(x))
#define rb_htovd(x) (BIGENDIAN_P()?swapd(x):(x))
#define rb_vtohf(x) (BIGENDIAN_P()?swapf(x):(x))
#define rb_vtohd(x) (BIGENDIAN_P()?swapd(x):(x))
#ifdef FLOAT_SWAPPER
# define FLOAT_CONVWITH(y) FLOAT_SWAPPER y;
# define HTONF(x,y) (memcpy(&(y),&(x),sizeof(float)), \
(y) = rb_htonf((FLOAT_SWAPPER)(y)), \
memcpy(&(x),&(y),sizeof(float)), \
(x))
# define HTOVF(x,y) (memcpy(&(y),&(x),sizeof(float)), \
(y) = rb_htovf((FLOAT_SWAPPER)(y)), \
memcpy(&(x),&(y),sizeof(float)), \
(x))
# define NTOHF(x,y) (memcpy(&(y),&(x),sizeof(float)), \
(y) = rb_ntohf((FLOAT_SWAPPER)(y)), \
memcpy(&(x),&(y),sizeof(float)), \
(x))
# define VTOHF(x,y) (memcpy(&(y),&(x),sizeof(float)), \
(y) = rb_vtohf((FLOAT_SWAPPER)(y)), \
memcpy(&(x),&(y),sizeof(float)), \
(x))
#else
# define FLOAT_CONVWITH(y)
# define HTONF(x,y) rb_htonf(x)
# define HTOVF(x,y) rb_htovf(x)
# define NTOHF(x,y) rb_ntohf(x)
# define VTOHF(x,y) rb_vtohf(x)
#endif
#ifdef DOUBLE_SWAPPER
# define DOUBLE_CONVWITH(y) DOUBLE_SWAPPER y;
# define HTOND(x,y) (memcpy(&(y),&(x),sizeof(double)), \
(y) = rb_htond((DOUBLE_SWAPPER)(y)), \
memcpy(&(x),&(y),sizeof(double)), \
(x))
# define HTOVD(x,y) (memcpy(&(y),&(x),sizeof(double)), \
(y) = rb_htovd((DOUBLE_SWAPPER)(y)), \
memcpy(&(x),&(y),sizeof(double)), \
(x))
# define NTOHD(x,y) (memcpy(&(y),&(x),sizeof(double)), \
(y) = rb_ntohd((DOUBLE_SWAPPER)(y)), \
memcpy(&(x),&(y),sizeof(double)), \
(x))
# define VTOHD(x,y) (memcpy(&(y),&(x),sizeof(double)), \
(y) = rb_vtohd((DOUBLE_SWAPPER)(y)), \
memcpy(&(x),&(y),sizeof(double)), \
(x))
#else
# define DOUBLE_CONVWITH(y)
# define HTOND(x,y) rb_htond(x)
# define HTOVD(x,y) rb_htovd(x)
# define NTOHD(x,y) rb_ntohd(x)
# define VTOHD(x,y) rb_vtohd(x)
#endif
static unsigned long
num2i32(VALUE x)
{
x = rb_to_int(x); /* is nil OK? (should not) */
if (FIXNUM_P(x)) return FIX2LONG(x);
if (RB_TYPE_P(x, T_BIGNUM)) {
return rb_big2ulong_pack(x);
}
* array.c: replace rb_protect_inspect() and rb_inspecting_p() by rb_exec_recursive() in eval.c. * eval.c (rb_exec_recursive): new function. * array.c (rb_ary_join): use rb_exec_recursive(). * array.c (rb_ary_inspect, rb_ary_hash): ditto. * file.c (rb_file_join): ditto. * hash.c (rb_hash_inspect, rb_hash_to_s, rb_hash_hash): ditto. * io.c (rb_io_puts): ditto. * object.c (rb_obj_inspect): ditto * struct.c (rb_struct_inspect): ditto. * lib/set.rb (SortedSet::setup): a hack to shut up warning. [ruby-talk:132866] * lib/time.rb (Time::strptime): add new function. inspired by [ruby-talk:132815]. * lib/parsedate.rb (ParseDate::strptime): ditto. * regparse.c: move st_*_strend() functions from st.c. fixed some potential memory leaks. * exception error messages updated. [ruby-core:04497] * ext/socket/socket.c (Init_socket): add bunch of Socket constants. Patch from Sam Roberts <sroberts@uniserve.com>. [ruby-core:04409] * array.c (rb_ary_s_create): no need for negative argc check. [ruby-core:04463] * array.c (rb_ary_unshift_m): ditto. * lib/xmlrpc/parser.rb (XMLRPC::FaultException): make it subclass of StandardError class, not Exception class. [ruby-core:04429] * parse.y (fcall_gen): lvar(arg) will be evaluated as lvar.call(arg) when lvar is a defined local variable. [new] * object.c (rb_class_initialize): call inherited method before calling initializing block. * eval.c (rb_thread_start_1): initialize newly pushed frame. * lib/open3.rb (Open3::popen3): $? should not be EXIT_FAILURE. fixed: [ruby-core:04444] * eval.c (is_defined): NODE_IASGN is an assignment. * ext/readline/readline.c (Readline.readline): use rl_outstream and rl_instream. [ruby-dev:25699] * ext/etc/etc.c (Init_etc): sGroup needs HAVE_ST_GR_PASSWD check [ruby-dev:25675] * misc/ruby-mode.el: [ruby-core:04415] * lib/rdoc/generators/html_generator.rb: [ruby-core:04412] * lib/rdoc/generators/ri_generator.rb: ditto. * struct.c (make_struct): fixed: [ruby-core:04402] * ext/curses/curses.c (window_color_set): [ruby-core:04393] * ext/socket/socket.c (Init_socket): SO_REUSEPORT added. [ruby-talk:130092] * object.c: [ruby-doc:818] * parse.y (open_args): fix too verbose warnings for the space before argument parentheses. [ruby-dev:25492] * parse.y (parser_yylex): ditto. * parse.y (parser_yylex): the first expression in the parentheses should not be a command. [ruby-dev:25492] * lib/irb/context.rb (IRB::Context::initialize): [ruby-core:04330] * object.c (Init_Object): remove Object#type. [ruby-core:04335] * st.c (st_foreach): report success/failure by return value. [ruby-Bugs-1396] * parse.y: forgot to initialize parser struct. [ruby-dev:25492] * parse.y (parser_yylex): no tLABEL on EXPR_BEG. [ruby-talk:127711] * document updates - [ruby-core:04296], [ruby-core:04301], [ruby-core:04302], [ruby-core:04307] * dir.c (rb_push_glob): should work for NUL delimited patterns. * dir.c (rb_glob2): should aware of offset in the pattern. * string.c (rb_str_new4): should propagate taintedness. * env.h: rename member names in struct FRAME; last_func -> callee, orig_func -> this_func, last_class -> this_class. * struct.c (rb_struct_set): use original method name, not callee name, to retrieve member slot. [ruby-core:04268] * time.c (time_strftime): protect from format modification from GC finalizers. * object.c (Init_Object): remove rb_obj_id_obsolete() * eval.c (rb_mod_define_method): incomplete subclass check. [ruby-dev:25464] * gc.c (rb_data_object_alloc): klass may be NULL. [ruby-list:40498] * bignum.c (rb_big_rand): should return positive random number. [ruby-dev:25401] * bignum.c (rb_big_rand): do not use rb_big_modulo to generate random bignums. [ruby-dev:25396] * variable.c (rb_autoload): [ruby-dev:25373] * eval.c (svalue_to_avalue): [ruby-dev:25366] * string.c (rb_str_justify): [ruby-dev:25367] * io.c (rb_f_select): [ruby-dev:25312] * ext/socket/socket.c (sock_s_getservbyport): [ruby-talk:124072] * struct.c (make_struct): [ruby-dev:25249] * dir.c (dir_open_dir): new function. [ruby-dev:25242] * io.c (rb_f_open): add type check for return value from to_open. * lib/pstore.rb (PStore#transaction): Use the empty content when a file is not found. [ruby-dev:24561] git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@8068 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2005-03-04 01:47:45 -05:00
rb_raise(rb_eTypeError, "can't convert %s to `integer'", rb_obj_classname(x));
2012-04-13 20:36:26 -04:00
UNREACHABLE;
}
#define MAX_INTEGER_PACK_SIZE 8
/* #define FORCE_BIG_PACK */
static const char toofew[] = "too few arguments";
static void encodes(VALUE,const char*,long,int,int);
static void qpencode(VALUE,VALUE,long);
static unsigned long utf8_to_uv(const char*,long*);
/*
* call-seq:
* arr.pack ( aTemplateString ) -> aBinaryString
*
* Packs the contents of <i>arr</i> into a binary sequence according to
* the directives in <i>aTemplateString</i> (see the table below)
* Directives ``A,'' ``a,'' and ``Z'' may be followed by a count,
* which gives the width of the resulting field. The remaining
* directives also may take a count, indicating the number of array
* elements to convert. If the count is an asterisk
* (``<code>*</code>''), all remaining array elements will be
* converted. Any of the directives ``<code>sSiIlL</code>'' may be
* followed by an underscore (``<code>_</code>'') or
* exclamation mark (``<code>!</code>'') to use the underlying
* platform's native size for the specified type; otherwise, they use a
* platform-independent size. Spaces are ignored in the template
* string. See also <code>String#unpack</code>.
*
* a = [ "a", "b", "c" ]
* n = [ 65, 66, 67 ]
* a.pack("A3A3A3") #=> "a b c "
* a.pack("a3a3a3") #=> "a\000\000b\000\000c\000\000"
* n.pack("ccc") #=> "ABC"
*
* Directives for +pack+.
*
* Integer | Array |
* Directive | Element | Meaning
* ---------------------------------------------------------------------------
* C | Integer | 8-bit unsigned (unsigned char)
* S | Integer | 16-bit unsigned, native endian (uint16_t)
* L | Integer | 32-bit unsigned, native endian (uint32_t)
* Q | Integer | 64-bit unsigned, native endian (uint64_t)
* | |
* c | Integer | 8-bit signed (signed char)
* s | Integer | 16-bit signed, native endian (int16_t)
* l | Integer | 32-bit signed, native endian (int32_t)
* q | Integer | 64-bit signed, native endian (int64_t)
* | |
* S_, S! | Integer | unsigned short, native endian
* I, I_, I! | Integer | unsigned int, native endian
* L_, L! | Integer | unsigned long, native endian
* Q_, Q! | Integer | unsigned long long, native endian (ArgumentError
* | | if the platform has no long long type.)
* | | (Q_ and Q! is available since Ruby 2.1.)
* | |
* s_, s! | Integer | signed short, native endian
* i, i_, i! | Integer | signed int, native endian
* l_, l! | Integer | signed long, native endian
* q_, q! | Integer | signed long long, native endian (ArgumentError
* | | if the platform has no long long type.)
* | | (q_ and q! is available since Ruby 2.1.)
* | |
* S> L> Q> | Integer | same as the directives without ">" except
* s> l> q> | | big endian
* S!> I!> | | (available since Ruby 1.9.3)
* L!> Q!> | | "S>" is same as "n"
* s!> i!> | | "L>" is same as "N"
* l!> q!> | |
* | |
* S< L< Q< | Integer | same as the directives without "<" except
* s< l< q< | | little endian
* S!< I!< | | (available since Ruby 1.9.3)
* L!< Q!< | | "S<" is same as "v"
* s!< i!< | | "L<" is same as "V"
* l!< q!< | |
* | |
* n | Integer | 16-bit unsigned, network (big-endian) byte order
* N | Integer | 32-bit unsigned, network (big-endian) byte order
* v | Integer | 16-bit unsigned, VAX (little-endian) byte order
* V | Integer | 32-bit unsigned, VAX (little-endian) byte order
* | |
* U | Integer | UTF-8 character
* w | Integer | BER-compressed integer
*
* Float | |
* Directive | | Meaning
* ---------------------------------------------------------------------------
* D, d | Float | double-precision, native format
* F, f | Float | single-precision, native format
* E | Float | double-precision, little-endian byte order
* e | Float | single-precision, little-endian byte order
* G | Float | double-precision, network (big-endian) byte order
* g | Float | single-precision, network (big-endian) byte order
*
* String | |
* Directive | | Meaning
* ---------------------------------------------------------------------------
* A | String | arbitrary binary string (space padded, count is width)
* a | String | arbitrary binary string (null padded, count is width)
* Z | String | same as ``a'', except that null is added with *
* B | String | bit string (MSB first)
* b | String | bit string (LSB first)
* H | String | hex string (high nibble first)
* h | String | hex string (low nibble first)
* u | String | UU-encoded string
* M | String | quoted printable, MIME encoding (see RFC2045)
* m | String | base64 encoded string (see RFC 2045, count is width)
* | | (if count is 0, no line feed are added, see RFC 4648)
* P | String | pointer to a structure (fixed-length string)
* p | String | pointer to a null-terminated string
*
* Misc. | |
* Directive | | Meaning
* ---------------------------------------------------------------------------
* @ | --- | moves to absolute position
* X | --- | back up a byte
* x | --- | null byte
*/
static VALUE
pack_pack(VALUE ary, VALUE fmt)
{
static const char nul10[] = "\0\0\0\0\0\0\0\0\0\0";
static const char spc10[] = " ";
const char *p, *pend;
VALUE res, from, associates = 0;
char type;
long items, len, idx, plen;
const char *ptr;
int enc_info = 1; /* 0 - BINARY, 1 - US-ASCII, 2 - UTF-8 */
#ifdef NATINT_PACK
int natint; /* native integer */
#endif
int integer_size, bigendian_p;
* eval.c (block_pass): should not downgrade safe level. * ext/dbm/extconf.rb: allow specifying dbm-type explicitly. * ext/dbm/extconf.rb: avoid gdbm if possible, because it leaks memory, whereas gdbm.so doesn't. potential incompatibility. * string.c (rb_str_insert): new method. * parse.y (yylex): lex_state after RESCUE_MOD should be EXPR_BEG. * array.c (rb_ary_insert): new method. * array.c (rb_ary_update): new utility function. * io.c (set_outfile): should check if closed before assignment. * eval.c (rb_eval): should preserve value of ruby_errinfo. * eval.c (rb_thread_schedule): infinite sleep should not cause dead lock. * array.c (rb_ary_flatten_bang): proper recursive detection. * eval.c (yield_under): need not to prohibit at safe level 4. * pack.c (pack_pack): p/P packs nil into NULL. * pack.c (pack_unpack): p/P unpacks NULL into nil. * pack.c (pack_pack): size check for P template. * ruby.c (set_arg0): wrong predicate when new $0 value is bigger than original space. * gc.c (id2ref): should use NUM2ULONG() * object.c (rb_mod_const_get): check whether name is a class variable name. * object.c (rb_mod_const_set): ditto. * object.c (rb_mod_const_defined): ditto. * marshal.c (w_float): precision changed to "%.16g" * eval.c (rb_call0): wrong retry behavior. * numeric.c (fix_aref): a bug on long>int architecture. * eval.c (rb_eval_string_wrap): should restore ruby_wrapper. * regex.c (re_compile_pattern): char class at either edge of range should be invalid. * eval.c (handle_rescue): use === to compare exception match. * error.c (syserr_eqq): comparison between SytemCallErrors should based on their error numbers. * eval.c (safe_getter): should use INT2NUM(). * bignum.c (rb_big2long): 2**31 cannot fit in 31 bit long. * regex.c (calculate_must_string): wrong length calculation. * eval.c (rb_thread_start_0): fixed memory leak. * parse.y (none): should clear cmdarg_stack too. * io.c (rb_fopen): use setvbuf() to avoid recursive malloc() on some platforms. * file.c (rb_stat_dev): device functions should honor stat field types (except long long such as dev_t). * eval.c (rb_mod_nesting): should not push nil for nesting array. * eval.c (rb_mod_s_constants): should not search array by rb_mod_const_at() for nil (happens for singleton class). * class.c (rb_singleton_class_attached): should modify iv_tbl by itself, no longer use rb_iv_set() to avoid freeze check error. * variable.c (rb_const_get): error message "uninitialized constant Foo at Bar::Baz" instead of "uninitialized constantBar::Baz::Foo". * eval.c (rb_mod_included): new hook called from rb_mod_include(). * io.c (opt_i_set): should strdup() inplace_edit string. * eval.c (exec_under): need to push cref too. * eval.c (rb_f_missing): raise NameError for "undefined local variable or method". * error.c (Init_Exception): new exception NoMethodError. NameError moved under ScriptError again. * eval.c (rb_f_missing): use NoMethodError instead of NameError. * file.c (Init_File): should redifine "new" class method. * eval.c (PUSH_CREF): sharing cref node was problematic. maintain runtime cref list instead. * eval.c (rb_eval): copy defn node before registering. * eval.c (rb_load): clear ruby_cref before loading. * variable.c (rb_const_get): no recursion to show full class path for modules. * eval.c (rb_set_safe_level): should set safe level in curr_thread as well. * eval.c (safe_setter): ditto. * object.c (rb_obj_is_instance_of): nil belongs to false, not true. * time.c (make_time_t): proper (I hope) daylight saving time handling for both US and Europe. I HATE DST! * eval.c (rb_thread_wait_for): non blocked signal interrupt should stop the interval. * eval.c (proc_eq): class check aded. * eval.c (proc_eq): typo fixed ("return" was ommitted). * error.c (Init_Exception): move NameError under StandardError. * class.c (rb_mod_clone): should copy method bodies too. * bignum.c (bigdivrem): should trim trailing zero bdigits of remainder, even if dd == 0. * file.c (check3rdbyte): safe string check moved here. * time.c (make_time_t): remove HAVE_TM_ZONE code since it sometimes reports wrong time. * time.c (make_time_t): remove unnecessary range check for platforms where negative time_t is available. * process.c (proc_waitall): should push Process::Status instead of Finuxm status. * process.c (waitall_each): should add all entries in pid_tbl. these changes are inspired by Koji Arai. Thanks. * process.c (proc_wait): should not iterate if pid_tbl is 0. * process.c (proc_waitall): ditto. * numeric.c (flodivmod): a bug in no fmod case. * process.c (pst_wifsignaled): should apply WIFSIGNALED for status (int), not st (VALUE). * io.c (Init_IO): value of $/ and $\ are no longer restricted to strings. type checks are done on demand. * class.c (rb_include_module): module inclusion should be check taints. * ruby.h (STR2CSTR): replace to StringType() and StringTypePtr(). * ruby.h (rb_str2cstr): ditto. * eval.c (rb_load): should not copy topleve local variables. It cause variable/method ambiguity. Thanks to L. Peter Deutsch. * class.c (rb_include_module): freeze check at first. * eval.c (rb_attr): sprintf() and rb_intern() moved into conditional body. git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@1356 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2001-05-02 00:22:21 -04:00
StringValue(fmt);
p = RSTRING_PTR(fmt);
pend = p + RSTRING_LEN(fmt);
res = rb_str_buf_new(0);
items = RARRAY_LEN(ary);
idx = 0;
#define TOO_FEW (rb_raise(rb_eArgError, toofew), 0)
#define THISFROM (items > 0 ? RARRAY_AREF(ary, idx) : TOO_FEW)
#define NEXTFROM (items-- > 0 ? RARRAY_AREF(ary, idx++) : TOO_FEW)
while (p < pend) {
int explicit_endian = 0;
if (RSTRING_PTR(fmt) + RSTRING_LEN(fmt) != pend) {
rb_raise(rb_eRuntimeError, "format string modified");
}
type = *p++; /* get data type */
#ifdef NATINT_PACK
natint = 0;
#endif
if (ISSPACE(type)) continue;
if (type == '#') {
while ((p < pend) && (*p != '\n')) {
p++;
}
continue;
}
{
modifiers:
switch (*p) {
case '_':
case '!':
if (strchr(natstr, type)) {
#ifdef NATINT_PACK
natint = 1;
#endif
p++;
}
else {
rb_raise(rb_eArgError, "'%c' allowed only after types %s", *p, natstr);
}
goto modifiers;
case '<':
case '>':
if (!strchr(endstr, type)) {
rb_raise(rb_eArgError, "'%c' allowed only after types %s", *p, endstr);
}
if (explicit_endian) {
rb_raise(rb_eRangeError, "Can't use both '<' and '>'");
}
explicit_endian = *p++;
goto modifiers;
}
}
if (*p == '*') { /* set data length */
len = strchr("@Xxu", type) ? 0
: strchr("PMm", type) ? 1
: items;
p++;
}
else if (ISDIGIT(*p)) {
errno = 0;
len = STRTOUL(p, (char**)&p, 10);
if (errno) {
rb_raise(rb_eRangeError, "pack length too big");
}
}
else {
len = 1;
}
switch (type) {
case 'U':
/* if encoding is US-ASCII, upgrade to UTF-8 */
if (enc_info == 1) enc_info = 2;
break;
case 'm': case 'M': case 'u':
/* keep US-ASCII (do nothing) */
break;
default:
/* fall back to BINARY */
enc_info = 0;
break;
}
switch (type) {
case 'A': case 'a': case 'Z':
case 'B': case 'b':
case 'H': case 'h':
from = NEXTFROM;
if (NIL_P(from)) {
ptr = "";
plen = 0;
}
else {
* eval.c (block_pass): should not downgrade safe level. * ext/dbm/extconf.rb: allow specifying dbm-type explicitly. * ext/dbm/extconf.rb: avoid gdbm if possible, because it leaks memory, whereas gdbm.so doesn't. potential incompatibility. * string.c (rb_str_insert): new method. * parse.y (yylex): lex_state after RESCUE_MOD should be EXPR_BEG. * array.c (rb_ary_insert): new method. * array.c (rb_ary_update): new utility function. * io.c (set_outfile): should check if closed before assignment. * eval.c (rb_eval): should preserve value of ruby_errinfo. * eval.c (rb_thread_schedule): infinite sleep should not cause dead lock. * array.c (rb_ary_flatten_bang): proper recursive detection. * eval.c (yield_under): need not to prohibit at safe level 4. * pack.c (pack_pack): p/P packs nil into NULL. * pack.c (pack_unpack): p/P unpacks NULL into nil. * pack.c (pack_pack): size check for P template. * ruby.c (set_arg0): wrong predicate when new $0 value is bigger than original space. * gc.c (id2ref): should use NUM2ULONG() * object.c (rb_mod_const_get): check whether name is a class variable name. * object.c (rb_mod_const_set): ditto. * object.c (rb_mod_const_defined): ditto. * marshal.c (w_float): precision changed to "%.16g" * eval.c (rb_call0): wrong retry behavior. * numeric.c (fix_aref): a bug on long>int architecture. * eval.c (rb_eval_string_wrap): should restore ruby_wrapper. * regex.c (re_compile_pattern): char class at either edge of range should be invalid. * eval.c (handle_rescue): use === to compare exception match. * error.c (syserr_eqq): comparison between SytemCallErrors should based on their error numbers. * eval.c (safe_getter): should use INT2NUM(). * bignum.c (rb_big2long): 2**31 cannot fit in 31 bit long. * regex.c (calculate_must_string): wrong length calculation. * eval.c (rb_thread_start_0): fixed memory leak. * parse.y (none): should clear cmdarg_stack too. * io.c (rb_fopen): use setvbuf() to avoid recursive malloc() on some platforms. * file.c (rb_stat_dev): device functions should honor stat field types (except long long such as dev_t). * eval.c (rb_mod_nesting): should not push nil for nesting array. * eval.c (rb_mod_s_constants): should not search array by rb_mod_const_at() for nil (happens for singleton class). * class.c (rb_singleton_class_attached): should modify iv_tbl by itself, no longer use rb_iv_set() to avoid freeze check error. * variable.c (rb_const_get): error message "uninitialized constant Foo at Bar::Baz" instead of "uninitialized constantBar::Baz::Foo". * eval.c (rb_mod_included): new hook called from rb_mod_include(). * io.c (opt_i_set): should strdup() inplace_edit string. * eval.c (exec_under): need to push cref too. * eval.c (rb_f_missing): raise NameError for "undefined local variable or method". * error.c (Init_Exception): new exception NoMethodError. NameError moved under ScriptError again. * eval.c (rb_f_missing): use NoMethodError instead of NameError. * file.c (Init_File): should redifine "new" class method. * eval.c (PUSH_CREF): sharing cref node was problematic. maintain runtime cref list instead. * eval.c (rb_eval): copy defn node before registering. * eval.c (rb_load): clear ruby_cref before loading. * variable.c (rb_const_get): no recursion to show full class path for modules. * eval.c (rb_set_safe_level): should set safe level in curr_thread as well. * eval.c (safe_setter): ditto. * object.c (rb_obj_is_instance_of): nil belongs to false, not true. * time.c (make_time_t): proper (I hope) daylight saving time handling for both US and Europe. I HATE DST! * eval.c (rb_thread_wait_for): non blocked signal interrupt should stop the interval. * eval.c (proc_eq): class check aded. * eval.c (proc_eq): typo fixed ("return" was ommitted). * error.c (Init_Exception): move NameError under StandardError. * class.c (rb_mod_clone): should copy method bodies too. * bignum.c (bigdivrem): should trim trailing zero bdigits of remainder, even if dd == 0. * file.c (check3rdbyte): safe string check moved here. * time.c (make_time_t): remove HAVE_TM_ZONE code since it sometimes reports wrong time. * time.c (make_time_t): remove unnecessary range check for platforms where negative time_t is available. * process.c (proc_waitall): should push Process::Status instead of Finuxm status. * process.c (waitall_each): should add all entries in pid_tbl. these changes are inspired by Koji Arai. Thanks. * process.c (proc_wait): should not iterate if pid_tbl is 0. * process.c (proc_waitall): ditto. * numeric.c (flodivmod): a bug in no fmod case. * process.c (pst_wifsignaled): should apply WIFSIGNALED for status (int), not st (VALUE). * io.c (Init_IO): value of $/ and $\ are no longer restricted to strings. type checks are done on demand. * class.c (rb_include_module): module inclusion should be check taints. * ruby.h (STR2CSTR): replace to StringType() and StringTypePtr(). * ruby.h (rb_str2cstr): ditto. * eval.c (rb_load): should not copy topleve local variables. It cause variable/method ambiguity. Thanks to L. Peter Deutsch. * class.c (rb_include_module): freeze check at first. * eval.c (rb_attr): sprintf() and rb_intern() moved into conditional body. git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@1356 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2001-05-02 00:22:21 -04:00
StringValue(from);
ptr = RSTRING_PTR(from);
plen = RSTRING_LEN(from);
OBJ_INFECT(res, from);
}
if (p[-1] == '*')
len = plen;
switch (type) {
case 'a': /* arbitrary binary string (null padded) */
case 'A': /* arbitrary binary string (ASCII space padded) */
case 'Z': /* null terminated string */
if (plen >= len) {
rb_str_buf_cat(res, ptr, len);
if (p[-1] == '*' && type == 'Z')
rb_str_buf_cat(res, nul10, 1);
}
else {
rb_str_buf_cat(res, ptr, plen);
len -= plen;
while (len >= 10) {
rb_str_buf_cat(res, (type == 'A')?spc10:nul10, 10);
len -= 10;
}
rb_str_buf_cat(res, (type == 'A')?spc10:nul10, len);
}
break;
#define castchar(from) (char)((from) & 0xff)
case 'b': /* bit string (ascending) */
{
int byte = 0;
long i, j = 0;
if (len > plen) {
j = (len - plen + 1)/2;
len = plen;
}
for (i=0; i++ < len; ptr++) {
if (*ptr & 1)
byte |= 128;
if (i & 7)
byte >>= 1;
else {
char c = castchar(byte);
rb_str_buf_cat(res, &c, 1);
byte = 0;
}
}
if (len & 7) {
char c;
byte >>= 7 - (len & 7);
c = castchar(byte);
rb_str_buf_cat(res, &c, 1);
}
len = j;
goto grow;
}
break;
case 'B': /* bit string (descending) */
{
int byte = 0;
long i, j = 0;
if (len > plen) {
j = (len - plen + 1)/2;
len = plen;
}
for (i=0; i++ < len; ptr++) {
byte |= *ptr & 1;
if (i & 7)
byte <<= 1;
else {
char c = castchar(byte);
rb_str_buf_cat(res, &c, 1);
byte = 0;
}
}
if (len & 7) {
char c;
byte <<= 7 - (len & 7);
c = castchar(byte);
rb_str_buf_cat(res, &c, 1);
}
len = j;
goto grow;
}
break;
case 'h': /* hex string (low nibble first) */
{
int byte = 0;
long i, j = 0;
if (len > plen) {
j = (len + 1) / 2 - (plen + 1) / 2;
len = plen;
}
for (i=0; i++ < len; ptr++) {
if (ISALPHA(*ptr))
byte |= (((*ptr & 15) + 9) & 15) << 4;
else
byte |= (*ptr & 15) << 4;
if (i & 1)
byte >>= 4;
else {
char c = castchar(byte);
rb_str_buf_cat(res, &c, 1);
byte = 0;
}
}
if (len & 1) {
char c = castchar(byte);
rb_str_buf_cat(res, &c, 1);
}
len = j;
goto grow;
}
break;
case 'H': /* hex string (high nibble first) */
{
int byte = 0;
long i, j = 0;
if (len > plen) {
j = (len + 1) / 2 - (plen + 1) / 2;
len = plen;
}
for (i=0; i++ < len; ptr++) {
if (ISALPHA(*ptr))
byte |= ((*ptr & 15) + 9) & 15;
else
byte |= *ptr & 15;
if (i & 1)
byte <<= 4;
else {
char c = castchar(byte);
rb_str_buf_cat(res, &c, 1);
byte = 0;
}
}
if (len & 1) {
char c = castchar(byte);
rb_str_buf_cat(res, &c, 1);
}
len = j;
goto grow;
}
break;
}
break;
case 'c': /* signed char */
case 'C': /* unsigned char */
while (len-- > 0) {
char c;
from = NEXTFROM;
c = (char)num2i32(from);
rb_str_buf_cat(res, &c, sizeof(char));
}
break;
case 's': /* s for int16_t, s! for signed short */
integer_size = NATINT_LEN(short, 2);
bigendian_p = BIGENDIAN_P();
goto pack_integer;
case 'S': /* S for uint16_t, S! for unsigned short */
integer_size = NATINT_LEN(short, 2);
bigendian_p = BIGENDIAN_P();
goto pack_integer;
case 'i': /* i and i! for signed int */
integer_size = (int)sizeof(int);
bigendian_p = BIGENDIAN_P();
goto pack_integer;
case 'I': /* I and I! for unsigned int */
integer_size = (int)sizeof(int);
bigendian_p = BIGENDIAN_P();
goto pack_integer;
case 'l': /* l for int32_t, l! for signed long */
integer_size = NATINT_LEN(long, 4);
bigendian_p = BIGENDIAN_P();
goto pack_integer;
case 'L': /* L for uint32_t, L! for unsigned long */
integer_size = NATINT_LEN(long, 4);
bigendian_p = BIGENDIAN_P();
goto pack_integer;
case 'q': /* q for int64_t, q! for signed long long */
integer_size = NATINT_LEN_Q;
bigendian_p = BIGENDIAN_P();
goto pack_integer;
case 'Q': /* Q for uint64_t, Q! for unsigned long long */
integer_size = NATINT_LEN_Q;
bigendian_p = BIGENDIAN_P();
goto pack_integer;
case 'n': /* 16 bit (2 bytes) integer (network byte-order) */
integer_size = 2;
bigendian_p = 1;
goto pack_integer;
case 'N': /* 32 bit (4 bytes) integer (network byte-order) */
integer_size = 4;
bigendian_p = 1;
goto pack_integer;
case 'v': /* 16 bit (2 bytes) integer (VAX byte-order) */
integer_size = 2;
bigendian_p = 0;
goto pack_integer;
case 'V': /* 32 bit (4 bytes) integer (VAX byte-order) */
integer_size = 4;
bigendian_p = 0;
goto pack_integer;
pack_integer:
if (explicit_endian) {
bigendian_p = explicit_endian == '>';
}
switch (integer_size) {
#if defined(HAVE_INT16_T) && !defined(FORCE_BIG_PACK)
case SIZEOF_INT16_T:
while (len-- > 0) {
union {
int16_t i;
char a[sizeof(int16_t)];
} v;
from = NEXTFROM;
v.i = (int16_t)num2i32(from);
if (bigendian_p != BIGENDIAN_P()) v.i = swap16(v.i);
rb_str_buf_cat(res, v.a, sizeof(int16_t));
}
break;
#endif
#if defined(HAVE_INT32_T) && !defined(FORCE_BIG_PACK)
case SIZEOF_INT32_T:
while (len-- > 0) {
union {
int32_t i;
char a[sizeof(int32_t)];
} v;
from = NEXTFROM;
v.i = (int32_t)num2i32(from);
if (bigendian_p != BIGENDIAN_P()) v.i = swap32(v.i);
rb_str_buf_cat(res, v.a, sizeof(int32_t));
}
break;
#endif
#if defined(HAVE_INT64_T) && SIZEOF_LONG == SIZEOF_INT64_T && !defined(FORCE_BIG_PACK)
case SIZEOF_INT64_T:
while (len-- > 0) {
union {
int64_t i;
char a[sizeof(int64_t)];
} v;
from = NEXTFROM;
v.i = num2i32(from); /* can return 64bit value if SIZEOF_LONG == SIZEOF_INT64_T */
if (bigendian_p != BIGENDIAN_P()) v.i = swap64(v.i);
rb_str_buf_cat(res, v.a, sizeof(int64_t));
}
break;
#endif
default:
if (integer_size > MAX_INTEGER_PACK_SIZE)
rb_bug("unexpected intger size for pack: %d", integer_size);
while (len-- > 0) {
char intbuf[MAX_INTEGER_PACK_SIZE];
from = NEXTFROM;
rb_integer_pack_2comp(from, intbuf, integer_size, 1, 0,
bigendian_p ? INTEGER_PACK_BIG_ENDIAN : INTEGER_PACK_LITTLE_ENDIAN);
rb_str_buf_cat(res, intbuf, integer_size);
}
break;
}
break;
case 'f': /* single precision float in native format */
case 'F': /* ditto */
while (len-- > 0) {
float f;
from = NEXTFROM;
f = (float)RFLOAT_VALUE(rb_to_float(from));
rb_str_buf_cat(res, (char*)&f, sizeof(float));
}
break;
case 'e': /* single precision float in VAX byte-order */
while (len-- > 0) {
float f;
FLOAT_CONVWITH(ftmp);
from = NEXTFROM;
f = (float)RFLOAT_VALUE(rb_to_float(from));
f = HTOVF(f,ftmp);
rb_str_buf_cat(res, (char*)&f, sizeof(float));
}
break;
case 'E': /* double precision float in VAX byte-order */
while (len-- > 0) {
double d;
DOUBLE_CONVWITH(dtmp);
from = NEXTFROM;
d = RFLOAT_VALUE(rb_to_float(from));
d = HTOVD(d,dtmp);
rb_str_buf_cat(res, (char*)&d, sizeof(double));
}
break;
case 'd': /* double precision float in native format */
case 'D': /* ditto */
while (len-- > 0) {
double d;
from = NEXTFROM;
d = RFLOAT_VALUE(rb_to_float(from));
rb_str_buf_cat(res, (char*)&d, sizeof(double));
}
break;
case 'g': /* single precision float in network byte-order */
while (len-- > 0) {
float f;
FLOAT_CONVWITH(ftmp);
from = NEXTFROM;
f = (float)RFLOAT_VALUE(rb_to_float(from));
f = HTONF(f,ftmp);
rb_str_buf_cat(res, (char*)&f, sizeof(float));
}
break;
case 'G': /* double precision float in network byte-order */
while (len-- > 0) {
double d;
DOUBLE_CONVWITH(dtmp);
from = NEXTFROM;
d = RFLOAT_VALUE(rb_to_float(from));
d = HTOND(d,dtmp);
rb_str_buf_cat(res, (char*)&d, sizeof(double));
}
break;
case 'x': /* null byte */
grow:
while (len >= 10) {
rb_str_buf_cat(res, nul10, 10);
len -= 10;
}
rb_str_buf_cat(res, nul10, len);
break;
case 'X': /* back up byte */
shrink:
plen = RSTRING_LEN(res);
if (plen < len)
rb_raise(rb_eArgError, "X outside of string");
rb_str_set_len(res, plen - len);
break;
case '@': /* null fill to absolute position */
len -= RSTRING_LEN(res);
if (len > 0) goto grow;
len = -len;
if (len > 0) goto shrink;
break;
case '%':
rb_raise(rb_eArgError, "%% is not supported");
break;
case 'U': /* Unicode character */
while (len-- > 0) {
SIGNED_VALUE l;
char buf[8];
int le;
from = NEXTFROM;
from = rb_to_int(from);
l = NUM2LONG(from);
if (l < 0) {
rb_raise(rb_eRangeError, "pack(U): value out of range");
}
le = rb_uv_to_utf8(buf, l);
rb_str_buf_cat(res, (char*)buf, le);
}
break;
case 'u': /* uuencoded string */
case 'm': /* base64 encoded string */
* eval.c (block_pass): should not downgrade safe level. * ext/dbm/extconf.rb: allow specifying dbm-type explicitly. * ext/dbm/extconf.rb: avoid gdbm if possible, because it leaks memory, whereas gdbm.so doesn't. potential incompatibility. * string.c (rb_str_insert): new method. * parse.y (yylex): lex_state after RESCUE_MOD should be EXPR_BEG. * array.c (rb_ary_insert): new method. * array.c (rb_ary_update): new utility function. * io.c (set_outfile): should check if closed before assignment. * eval.c (rb_eval): should preserve value of ruby_errinfo. * eval.c (rb_thread_schedule): infinite sleep should not cause dead lock. * array.c (rb_ary_flatten_bang): proper recursive detection. * eval.c (yield_under): need not to prohibit at safe level 4. * pack.c (pack_pack): p/P packs nil into NULL. * pack.c (pack_unpack): p/P unpacks NULL into nil. * pack.c (pack_pack): size check for P template. * ruby.c (set_arg0): wrong predicate when new $0 value is bigger than original space. * gc.c (id2ref): should use NUM2ULONG() * object.c (rb_mod_const_get): check whether name is a class variable name. * object.c (rb_mod_const_set): ditto. * object.c (rb_mod_const_defined): ditto. * marshal.c (w_float): precision changed to "%.16g" * eval.c (rb_call0): wrong retry behavior. * numeric.c (fix_aref): a bug on long>int architecture. * eval.c (rb_eval_string_wrap): should restore ruby_wrapper. * regex.c (re_compile_pattern): char class at either edge of range should be invalid. * eval.c (handle_rescue): use === to compare exception match. * error.c (syserr_eqq): comparison between SytemCallErrors should based on their error numbers. * eval.c (safe_getter): should use INT2NUM(). * bignum.c (rb_big2long): 2**31 cannot fit in 31 bit long. * regex.c (calculate_must_string): wrong length calculation. * eval.c (rb_thread_start_0): fixed memory leak. * parse.y (none): should clear cmdarg_stack too. * io.c (rb_fopen): use setvbuf() to avoid recursive malloc() on some platforms. * file.c (rb_stat_dev): device functions should honor stat field types (except long long such as dev_t). * eval.c (rb_mod_nesting): should not push nil for nesting array. * eval.c (rb_mod_s_constants): should not search array by rb_mod_const_at() for nil (happens for singleton class). * class.c (rb_singleton_class_attached): should modify iv_tbl by itself, no longer use rb_iv_set() to avoid freeze check error. * variable.c (rb_const_get): error message "uninitialized constant Foo at Bar::Baz" instead of "uninitialized constantBar::Baz::Foo". * eval.c (rb_mod_included): new hook called from rb_mod_include(). * io.c (opt_i_set): should strdup() inplace_edit string. * eval.c (exec_under): need to push cref too. * eval.c (rb_f_missing): raise NameError for "undefined local variable or method". * error.c (Init_Exception): new exception NoMethodError. NameError moved under ScriptError again. * eval.c (rb_f_missing): use NoMethodError instead of NameError. * file.c (Init_File): should redifine "new" class method. * eval.c (PUSH_CREF): sharing cref node was problematic. maintain runtime cref list instead. * eval.c (rb_eval): copy defn node before registering. * eval.c (rb_load): clear ruby_cref before loading. * variable.c (rb_const_get): no recursion to show full class path for modules. * eval.c (rb_set_safe_level): should set safe level in curr_thread as well. * eval.c (safe_setter): ditto. * object.c (rb_obj_is_instance_of): nil belongs to false, not true. * time.c (make_time_t): proper (I hope) daylight saving time handling for both US and Europe. I HATE DST! * eval.c (rb_thread_wait_for): non blocked signal interrupt should stop the interval. * eval.c (proc_eq): class check aded. * eval.c (proc_eq): typo fixed ("return" was ommitted). * error.c (Init_Exception): move NameError under StandardError. * class.c (rb_mod_clone): should copy method bodies too. * bignum.c (bigdivrem): should trim trailing zero bdigits of remainder, even if dd == 0. * file.c (check3rdbyte): safe string check moved here. * time.c (make_time_t): remove HAVE_TM_ZONE code since it sometimes reports wrong time. * time.c (make_time_t): remove unnecessary range check for platforms where negative time_t is available. * process.c (proc_waitall): should push Process::Status instead of Finuxm status. * process.c (waitall_each): should add all entries in pid_tbl. these changes are inspired by Koji Arai. Thanks. * process.c (proc_wait): should not iterate if pid_tbl is 0. * process.c (proc_waitall): ditto. * numeric.c (flodivmod): a bug in no fmod case. * process.c (pst_wifsignaled): should apply WIFSIGNALED for status (int), not st (VALUE). * io.c (Init_IO): value of $/ and $\ are no longer restricted to strings. type checks are done on demand. * class.c (rb_include_module): module inclusion should be check taints. * ruby.h (STR2CSTR): replace to StringType() and StringTypePtr(). * ruby.h (rb_str2cstr): ditto. * eval.c (rb_load): should not copy topleve local variables. It cause variable/method ambiguity. Thanks to L. Peter Deutsch. * class.c (rb_include_module): freeze check at first. * eval.c (rb_attr): sprintf() and rb_intern() moved into conditional body. git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@1356 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2001-05-02 00:22:21 -04:00
from = NEXTFROM;
StringValue(from);
ptr = RSTRING_PTR(from);
plen = RSTRING_LEN(from);
if (len == 0 && type == 'm') {
encodes(res, ptr, plen, type, 0);
ptr += plen;
break;
}
if (len <= 2)
len = 45;
else if (len > 63 && type == 'u')
len = 63;
else
len = len / 3 * 3;
while (plen > 0) {
long todo;
if (plen > len)
todo = len;
else
todo = plen;
encodes(res, ptr, todo, type, 1);
plen -= todo;
ptr += todo;
}
break;
case 'M': /* quoted-printable encoded string */
from = rb_obj_as_string(NEXTFROM);
if (len <= 1)
len = 72;
qpencode(res, from, len);
break;
case 'P': /* pointer to packed byte string */
* eval.c (block_pass): should not downgrade safe level. * ext/dbm/extconf.rb: allow specifying dbm-type explicitly. * ext/dbm/extconf.rb: avoid gdbm if possible, because it leaks memory, whereas gdbm.so doesn't. potential incompatibility. * string.c (rb_str_insert): new method. * parse.y (yylex): lex_state after RESCUE_MOD should be EXPR_BEG. * array.c (rb_ary_insert): new method. * array.c (rb_ary_update): new utility function. * io.c (set_outfile): should check if closed before assignment. * eval.c (rb_eval): should preserve value of ruby_errinfo. * eval.c (rb_thread_schedule): infinite sleep should not cause dead lock. * array.c (rb_ary_flatten_bang): proper recursive detection. * eval.c (yield_under): need not to prohibit at safe level 4. * pack.c (pack_pack): p/P packs nil into NULL. * pack.c (pack_unpack): p/P unpacks NULL into nil. * pack.c (pack_pack): size check for P template. * ruby.c (set_arg0): wrong predicate when new $0 value is bigger than original space. * gc.c (id2ref): should use NUM2ULONG() * object.c (rb_mod_const_get): check whether name is a class variable name. * object.c (rb_mod_const_set): ditto. * object.c (rb_mod_const_defined): ditto. * marshal.c (w_float): precision changed to "%.16g" * eval.c (rb_call0): wrong retry behavior. * numeric.c (fix_aref): a bug on long>int architecture. * eval.c (rb_eval_string_wrap): should restore ruby_wrapper. * regex.c (re_compile_pattern): char class at either edge of range should be invalid. * eval.c (handle_rescue): use === to compare exception match. * error.c (syserr_eqq): comparison between SytemCallErrors should based on their error numbers. * eval.c (safe_getter): should use INT2NUM(). * bignum.c (rb_big2long): 2**31 cannot fit in 31 bit long. * regex.c (calculate_must_string): wrong length calculation. * eval.c (rb_thread_start_0): fixed memory leak. * parse.y (none): should clear cmdarg_stack too. * io.c (rb_fopen): use setvbuf() to avoid recursive malloc() on some platforms. * file.c (rb_stat_dev): device functions should honor stat field types (except long long such as dev_t). * eval.c (rb_mod_nesting): should not push nil for nesting array. * eval.c (rb_mod_s_constants): should not search array by rb_mod_const_at() for nil (happens for singleton class). * class.c (rb_singleton_class_attached): should modify iv_tbl by itself, no longer use rb_iv_set() to avoid freeze check error. * variable.c (rb_const_get): error message "uninitialized constant Foo at Bar::Baz" instead of "uninitialized constantBar::Baz::Foo". * eval.c (rb_mod_included): new hook called from rb_mod_include(). * io.c (opt_i_set): should strdup() inplace_edit string. * eval.c (exec_under): need to push cref too. * eval.c (rb_f_missing): raise NameError for "undefined local variable or method". * error.c (Init_Exception): new exception NoMethodError. NameError moved under ScriptError again. * eval.c (rb_f_missing): use NoMethodError instead of NameError. * file.c (Init_File): should redifine "new" class method. * eval.c (PUSH_CREF): sharing cref node was problematic. maintain runtime cref list instead. * eval.c (rb_eval): copy defn node before registering. * eval.c (rb_load): clear ruby_cref before loading. * variable.c (rb_const_get): no recursion to show full class path for modules. * eval.c (rb_set_safe_level): should set safe level in curr_thread as well. * eval.c (safe_setter): ditto. * object.c (rb_obj_is_instance_of): nil belongs to false, not true. * time.c (make_time_t): proper (I hope) daylight saving time handling for both US and Europe. I HATE DST! * eval.c (rb_thread_wait_for): non blocked signal interrupt should stop the interval. * eval.c (proc_eq): class check aded. * eval.c (proc_eq): typo fixed ("return" was ommitted). * error.c (Init_Exception): move NameError under StandardError. * class.c (rb_mod_clone): should copy method bodies too. * bignum.c (bigdivrem): should trim trailing zero bdigits of remainder, even if dd == 0. * file.c (check3rdbyte): safe string check moved here. * time.c (make_time_t): remove HAVE_TM_ZONE code since it sometimes reports wrong time. * time.c (make_time_t): remove unnecessary range check for platforms where negative time_t is available. * process.c (proc_waitall): should push Process::Status instead of Finuxm status. * process.c (waitall_each): should add all entries in pid_tbl. these changes are inspired by Koji Arai. Thanks. * process.c (proc_wait): should not iterate if pid_tbl is 0. * process.c (proc_waitall): ditto. * numeric.c (flodivmod): a bug in no fmod case. * process.c (pst_wifsignaled): should apply WIFSIGNALED for status (int), not st (VALUE). * io.c (Init_IO): value of $/ and $\ are no longer restricted to strings. type checks are done on demand. * class.c (rb_include_module): module inclusion should be check taints. * ruby.h (STR2CSTR): replace to StringType() and StringTypePtr(). * ruby.h (rb_str2cstr): ditto. * eval.c (rb_load): should not copy topleve local variables. It cause variable/method ambiguity. Thanks to L. Peter Deutsch. * class.c (rb_include_module): freeze check at first. * eval.c (rb_attr): sprintf() and rb_intern() moved into conditional body. git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@1356 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2001-05-02 00:22:21 -04:00
from = THISFROM;
if (!NIL_P(from)) {
StringValue(from);
if (RSTRING_LEN(from) < len) {
rb_raise(rb_eArgError, "too short buffer for P(%ld for %ld)",
RSTRING_LEN(from), len);
* eval.c (block_pass): should not downgrade safe level. * ext/dbm/extconf.rb: allow specifying dbm-type explicitly. * ext/dbm/extconf.rb: avoid gdbm if possible, because it leaks memory, whereas gdbm.so doesn't. potential incompatibility. * string.c (rb_str_insert): new method. * parse.y (yylex): lex_state after RESCUE_MOD should be EXPR_BEG. * array.c (rb_ary_insert): new method. * array.c (rb_ary_update): new utility function. * io.c (set_outfile): should check if closed before assignment. * eval.c (rb_eval): should preserve value of ruby_errinfo. * eval.c (rb_thread_schedule): infinite sleep should not cause dead lock. * array.c (rb_ary_flatten_bang): proper recursive detection. * eval.c (yield_under): need not to prohibit at safe level 4. * pack.c (pack_pack): p/P packs nil into NULL. * pack.c (pack_unpack): p/P unpacks NULL into nil. * pack.c (pack_pack): size check for P template. * ruby.c (set_arg0): wrong predicate when new $0 value is bigger than original space. * gc.c (id2ref): should use NUM2ULONG() * object.c (rb_mod_const_get): check whether name is a class variable name. * object.c (rb_mod_const_set): ditto. * object.c (rb_mod_const_defined): ditto. * marshal.c (w_float): precision changed to "%.16g" * eval.c (rb_call0): wrong retry behavior. * numeric.c (fix_aref): a bug on long>int architecture. * eval.c (rb_eval_string_wrap): should restore ruby_wrapper. * regex.c (re_compile_pattern): char class at either edge of range should be invalid. * eval.c (handle_rescue): use === to compare exception match. * error.c (syserr_eqq): comparison between SytemCallErrors should based on their error numbers. * eval.c (safe_getter): should use INT2NUM(). * bignum.c (rb_big2long): 2**31 cannot fit in 31 bit long. * regex.c (calculate_must_string): wrong length calculation. * eval.c (rb_thread_start_0): fixed memory leak. * parse.y (none): should clear cmdarg_stack too. * io.c (rb_fopen): use setvbuf() to avoid recursive malloc() on some platforms. * file.c (rb_stat_dev): device functions should honor stat field types (except long long such as dev_t). * eval.c (rb_mod_nesting): should not push nil for nesting array. * eval.c (rb_mod_s_constants): should not search array by rb_mod_const_at() for nil (happens for singleton class). * class.c (rb_singleton_class_attached): should modify iv_tbl by itself, no longer use rb_iv_set() to avoid freeze check error. * variable.c (rb_const_get): error message "uninitialized constant Foo at Bar::Baz" instead of "uninitialized constantBar::Baz::Foo". * eval.c (rb_mod_included): new hook called from rb_mod_include(). * io.c (opt_i_set): should strdup() inplace_edit string. * eval.c (exec_under): need to push cref too. * eval.c (rb_f_missing): raise NameError for "undefined local variable or method". * error.c (Init_Exception): new exception NoMethodError. NameError moved under ScriptError again. * eval.c (rb_f_missing): use NoMethodError instead of NameError. * file.c (Init_File): should redifine "new" class method. * eval.c (PUSH_CREF): sharing cref node was problematic. maintain runtime cref list instead. * eval.c (rb_eval): copy defn node before registering. * eval.c (rb_load): clear ruby_cref before loading. * variable.c (rb_const_get): no recursion to show full class path for modules. * eval.c (rb_set_safe_level): should set safe level in curr_thread as well. * eval.c (safe_setter): ditto. * object.c (rb_obj_is_instance_of): nil belongs to false, not true. * time.c (make_time_t): proper (I hope) daylight saving time handling for both US and Europe. I HATE DST! * eval.c (rb_thread_wait_for): non blocked signal interrupt should stop the interval. * eval.c (proc_eq): class check aded. * eval.c (proc_eq): typo fixed ("return" was ommitted). * error.c (Init_Exception): move NameError under StandardError. * class.c (rb_mod_clone): should copy method bodies too. * bignum.c (bigdivrem): should trim trailing zero bdigits of remainder, even if dd == 0. * file.c (check3rdbyte): safe string check moved here. * time.c (make_time_t): remove HAVE_TM_ZONE code since it sometimes reports wrong time. * time.c (make_time_t): remove unnecessary range check for platforms where negative time_t is available. * process.c (proc_waitall): should push Process::Status instead of Finuxm status. * process.c (waitall_each): should add all entries in pid_tbl. these changes are inspired by Koji Arai. Thanks. * process.c (proc_wait): should not iterate if pid_tbl is 0. * process.c (proc_waitall): ditto. * numeric.c (flodivmod): a bug in no fmod case. * process.c (pst_wifsignaled): should apply WIFSIGNALED for status (int), not st (VALUE). * io.c (Init_IO): value of $/ and $\ are no longer restricted to strings. type checks are done on demand. * class.c (rb_include_module): module inclusion should be check taints. * ruby.h (STR2CSTR): replace to StringType() and StringTypePtr(). * ruby.h (rb_str2cstr): ditto. * eval.c (rb_load): should not copy topleve local variables. It cause variable/method ambiguity. Thanks to L. Peter Deutsch. * class.c (rb_include_module): freeze check at first. * eval.c (rb_attr): sprintf() and rb_intern() moved into conditional body. git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@1356 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2001-05-02 00:22:21 -04:00
}
}
len = 1;
/* FALL THROUGH */
case 'p': /* pointer to string */
while (len-- > 0) {
char *t;
from = NEXTFROM;
if (NIL_P(from)) {
* eval.c (block_pass): should not downgrade safe level. * ext/dbm/extconf.rb: allow specifying dbm-type explicitly. * ext/dbm/extconf.rb: avoid gdbm if possible, because it leaks memory, whereas gdbm.so doesn't. potential incompatibility. * string.c (rb_str_insert): new method. * parse.y (yylex): lex_state after RESCUE_MOD should be EXPR_BEG. * array.c (rb_ary_insert): new method. * array.c (rb_ary_update): new utility function. * io.c (set_outfile): should check if closed before assignment. * eval.c (rb_eval): should preserve value of ruby_errinfo. * eval.c (rb_thread_schedule): infinite sleep should not cause dead lock. * array.c (rb_ary_flatten_bang): proper recursive detection. * eval.c (yield_under): need not to prohibit at safe level 4. * pack.c (pack_pack): p/P packs nil into NULL. * pack.c (pack_unpack): p/P unpacks NULL into nil. * pack.c (pack_pack): size check for P template. * ruby.c (set_arg0): wrong predicate when new $0 value is bigger than original space. * gc.c (id2ref): should use NUM2ULONG() * object.c (rb_mod_const_get): check whether name is a class variable name. * object.c (rb_mod_const_set): ditto. * object.c (rb_mod_const_defined): ditto. * marshal.c (w_float): precision changed to "%.16g" * eval.c (rb_call0): wrong retry behavior. * numeric.c (fix_aref): a bug on long>int architecture. * eval.c (rb_eval_string_wrap): should restore ruby_wrapper. * regex.c (re_compile_pattern): char class at either edge of range should be invalid. * eval.c (handle_rescue): use === to compare exception match. * error.c (syserr_eqq): comparison between SytemCallErrors should based on their error numbers. * eval.c (safe_getter): should use INT2NUM(). * bignum.c (rb_big2long): 2**31 cannot fit in 31 bit long. * regex.c (calculate_must_string): wrong length calculation. * eval.c (rb_thread_start_0): fixed memory leak. * parse.y (none): should clear cmdarg_stack too. * io.c (rb_fopen): use setvbuf() to avoid recursive malloc() on some platforms. * file.c (rb_stat_dev): device functions should honor stat field types (except long long such as dev_t). * eval.c (rb_mod_nesting): should not push nil for nesting array. * eval.c (rb_mod_s_constants): should not search array by rb_mod_const_at() for nil (happens for singleton class). * class.c (rb_singleton_class_attached): should modify iv_tbl by itself, no longer use rb_iv_set() to avoid freeze check error. * variable.c (rb_const_get): error message "uninitialized constant Foo at Bar::Baz" instead of "uninitialized constantBar::Baz::Foo". * eval.c (rb_mod_included): new hook called from rb_mod_include(). * io.c (opt_i_set): should strdup() inplace_edit string. * eval.c (exec_under): need to push cref too. * eval.c (rb_f_missing): raise NameError for "undefined local variable or method". * error.c (Init_Exception): new exception NoMethodError. NameError moved under ScriptError again. * eval.c (rb_f_missing): use NoMethodError instead of NameError. * file.c (Init_File): should redifine "new" class method. * eval.c (PUSH_CREF): sharing cref node was problematic. maintain runtime cref list instead. * eval.c (rb_eval): copy defn node before registering. * eval.c (rb_load): clear ruby_cref before loading. * variable.c (rb_const_get): no recursion to show full class path for modules. * eval.c (rb_set_safe_level): should set safe level in curr_thread as well. * eval.c (safe_setter): ditto. * object.c (rb_obj_is_instance_of): nil belongs to false, not true. * time.c (make_time_t): proper (I hope) daylight saving time handling for both US and Europe. I HATE DST! * eval.c (rb_thread_wait_for): non blocked signal interrupt should stop the interval. * eval.c (proc_eq): class check aded. * eval.c (proc_eq): typo fixed ("return" was ommitted). * error.c (Init_Exception): move NameError under StandardError. * class.c (rb_mod_clone): should copy method bodies too. * bignum.c (bigdivrem): should trim trailing zero bdigits of remainder, even if dd == 0. * file.c (check3rdbyte): safe string check moved here. * time.c (make_time_t): remove HAVE_TM_ZONE code since it sometimes reports wrong time. * time.c (make_time_t): remove unnecessary range check for platforms where negative time_t is available. * process.c (proc_waitall): should push Process::Status instead of Finuxm status. * process.c (waitall_each): should add all entries in pid_tbl. these changes are inspired by Koji Arai. Thanks. * process.c (proc_wait): should not iterate if pid_tbl is 0. * process.c (proc_waitall): ditto. * numeric.c (flodivmod): a bug in no fmod case. * process.c (pst_wifsignaled): should apply WIFSIGNALED for status (int), not st (VALUE). * io.c (Init_IO): value of $/ and $\ are no longer restricted to strings. type checks are done on demand. * class.c (rb_include_module): module inclusion should be check taints. * ruby.h (STR2CSTR): replace to StringType() and StringTypePtr(). * ruby.h (rb_str2cstr): ditto. * eval.c (rb_load): should not copy topleve local variables. It cause variable/method ambiguity. Thanks to L. Peter Deutsch. * class.c (rb_include_module): freeze check at first. * eval.c (rb_attr): sprintf() and rb_intern() moved into conditional body. git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@1356 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2001-05-02 00:22:21 -04:00
t = 0;
}
else {
t = StringValuePtr(from);
}
if (!associates) {
associates = rb_ary_new();
}
rb_ary_push(associates, from);
rb_obj_taint(from);
rb_str_buf_cat(res, (char*)&t, sizeof(char*));
}
break;
case 'w': /* BER compressed integer */
while (len-- > 0) {
VALUE buf = rb_str_new(0, 0);
size_t numbytes;
int sign;
char *cp;
from = NEXTFROM;
from = rb_to_int(from);
numbytes = rb_absint_numwords(from, 7, NULL);
if (numbytes == 0)
numbytes = 1;
buf = rb_str_new(NULL, numbytes);
sign = rb_integer_pack(from, RSTRING_PTR(buf), RSTRING_LEN(buf), 1, 1, INTEGER_PACK_BIG_ENDIAN);
if (sign < 0)
rb_raise(rb_eArgError, "can't compress negative numbers");
if (sign == 2)
rb_bug("buffer size problem?");
cp = RSTRING_PTR(buf);
while (1 < numbytes) {
*cp |= 0x80;
cp++;
numbytes--;
}
rb_str_buf_cat(res, RSTRING_PTR(buf), RSTRING_LEN(buf));
}
break;
default:
rb_warning("unknown pack directive '%c' in '%s'",
type, RSTRING_PTR(fmt));
break;
}
}
if (associates) {
rb_str_associate(res, associates);
}
OBJ_INFECT(res, fmt);
switch (enc_info) {
case 1:
ENCODING_CODERANGE_SET(res, rb_usascii_encindex(), ENC_CODERANGE_7BIT);
break;
case 2:
rb_enc_set_index(res, rb_utf8_encindex());
break;
default:
/* do nothing, keep ASCII-8BIT */
break;
}
return res;
}
static const char uu_table[] =
"`!\"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_";
static const char b64_table[] =
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
static void
encodes(VALUE str, const char *s, long len, int type, int tail_lf)
{
char buff[4096];
long i = 0;
const char *trans = type == 'u' ? uu_table : b64_table;
char padding;
if (type == 'u') {
buff[i++] = (char)len + ' ';
padding = '`';
}
else {
padding = '=';
}
while (len >= 3) {
while (len >= 3 && sizeof(buff)-i >= 4) {
buff[i++] = trans[077 & (*s >> 2)];
buff[i++] = trans[077 & (((*s << 4) & 060) | ((s[1] >> 4) & 017))];
buff[i++] = trans[077 & (((s[1] << 2) & 074) | ((s[2] >> 6) & 03))];
buff[i++] = trans[077 & s[2]];
s += 3;
len -= 3;
}
if (sizeof(buff)-i < 4) {
rb_str_buf_cat(str, buff, i);
i = 0;
}
}
if (len == 2) {
buff[i++] = trans[077 & (*s >> 2)];
buff[i++] = trans[077 & (((*s << 4) & 060) | ((s[1] >> 4) & 017))];
buff[i++] = trans[077 & (((s[1] << 2) & 074) | (('\0' >> 6) & 03))];
buff[i++] = padding;
}
else if (len == 1) {
buff[i++] = trans[077 & (*s >> 2)];
buff[i++] = trans[077 & (((*s << 4) & 060) | (('\0' >> 4) & 017))];
buff[i++] = padding;
buff[i++] = padding;
}
if (tail_lf) buff[i++] = '\n';
rb_str_buf_cat(str, buff, i);
}
static const char hex_table[] = "0123456789ABCDEF";
static void
qpencode(VALUE str, VALUE from, long len)
{
char buff[1024];
long i = 0, n = 0, prev = EOF;
unsigned char *s = (unsigned char*)RSTRING_PTR(from);
unsigned char *send = s + RSTRING_LEN(from);
while (s < send) {
if ((*s > 126) ||
(*s < 32 && *s != '\n' && *s != '\t') ||
(*s == '=')) {
buff[i++] = '=';
buff[i++] = hex_table[*s >> 4];
buff[i++] = hex_table[*s & 0x0f];
n += 3;
prev = EOF;
}
else if (*s == '\n') {
if (prev == ' ' || prev == '\t') {
buff[i++] = '=';
buff[i++] = *s;
}
buff[i++] = *s;
n = 0;
prev = *s;
}
else {
buff[i++] = *s;
n++;
prev = *s;
}
if (n > len) {
buff[i++] = '=';
buff[i++] = '\n';
n = 0;
prev = '\n';
}
if (i > 1024 - 5) {
rb_str_buf_cat(str, buff, i);
i = 0;
}
s++;
}
if (n > 0) {
buff[i++] = '=';
buff[i++] = '\n';
}
if (i > 0) {
rb_str_buf_cat(str, buff, i);
}
}
static inline int
hex2num(char c)
{
switch (c) {
case '0': case '1': case '2': case '3': case '4':
case '5': case '6': case '7': case '8': case '9':
return c - '0';
case 'a': case 'b': case 'c':
case 'd': case 'e': case 'f':
return c - 'a' + 10;
case 'A': case 'B': case 'C':
case 'D': case 'E': case 'F':
return c - 'A' + 10;
default:
return -1;
}
}
#define PACK_LENGTH_ADJUST_SIZE(sz) do { \
tmp_len = 0; \
if (len > (long)((send-s)/(sz))) { \
if (!star) { \
tmp_len = len-(send-s)/(sz); \
} \
len = (send-s)/(sz); \
} \
} while (0)
#define PACK_ITEM_ADJUST() do { \
if (tmp_len > 0 && !block_p) \
rb_ary_store(ary, RARRAY_LEN(ary)+tmp_len-1, Qnil); \
} while (0)
static VALUE
infected_str_new(const char *ptr, long len, VALUE str)
{
VALUE s = rb_str_new(ptr, len);
OBJ_INFECT(s, str);
return s;
}
/*
* call-seq:
* str.unpack(format) -> anArray
*
* Decodes <i>str</i> (which may contain binary data) according to the
* format string, returning an array of each value extracted. The
* format string consists of a sequence of single-character directives,
* summarized in the table at the end of this entry.
* Each directive may be followed
* by a number, indicating the number of times to repeat with this
* directive. An asterisk (``<code>*</code>'') will use up all
* remaining elements. The directives <code>sSiIlL</code> may each be
* followed by an underscore (``<code>_</code>'') or
* exclamation mark (``<code>!</code>'') to use the underlying
* platform's native size for the specified type; otherwise, it uses a
* platform-independent consistent size. Spaces are ignored in the
* format string. See also <code>Array#pack</code>.
*
* "abc \0\0abc \0\0".unpack('A6Z6') #=> ["abc", "abc "]
* "abc \0\0".unpack('a3a3') #=> ["abc", " \000\000"]
* "abc \0abc \0".unpack('Z*Z*') #=> ["abc ", "abc "]
* "aa".unpack('b8B8') #=> ["10000110", "01100001"]
* "aaa".unpack('h2H2c') #=> ["16", "61", 97]
* "\xfe\xff\xfe\xff".unpack('sS') #=> [-2, 65534]
* "now=20is".unpack('M*') #=> ["now is"]
* "whole".unpack('xax2aX2aX1aX2a') #=> ["h", "e", "l", "l", "o"]
*
* This table summarizes the various formats and the Ruby classes
* returned by each.
*
* Integer | |
* Directive | Returns | Meaning
* -----------------------------------------------------------------
* C | Integer | 8-bit unsigned (unsigned char)
* S | Integer | 16-bit unsigned, native endian (uint16_t)
* L | Integer | 32-bit unsigned, native endian (uint32_t)
* Q | Integer | 64-bit unsigned, native endian (uint64_t)
* | |
* c | Integer | 8-bit signed (signed char)
* s | Integer | 16-bit signed, native endian (int16_t)
* l | Integer | 32-bit signed, native endian (int32_t)
* q | Integer | 64-bit signed, native endian (int64_t)
* | |
* S_, S! | Integer | unsigned short, native endian
* I, I_, I! | Integer | unsigned int, native endian
* L_, L! | Integer | unsigned long, native endian
* Q_, Q! | Integer | unsigned long long, native endian (ArgumentError
* | | if the platform has no long long type.)
* | | (Q_ and Q! is available since Ruby 2.1.)
* | |
* s_, s! | Integer | signed short, native endian
* i, i_, i! | Integer | signed int, native endian
* l_, l! | Integer | signed long, native endian
* q_, q! | Integer | signed long long, native endian (ArgumentError
* | | if the platform has no long long type.)
* | | (q_ and q! is available since Ruby 2.1.)
* | |
* S> L> Q> | Integer | same as the directives without ">" except
* s> l> q> | | big endian
* S!> I!> | | (available since Ruby 1.9.3)
* L!> Q!> | | "S>" is same as "n"
* s!> i!> | | "L>" is same as "N"
* l!> q!> | |
* | |
* S< L< Q< | Integer | same as the directives without "<" except
* s< l< q< | | little endian
* S!< I!< | | (available since Ruby 1.9.3)
* L!< Q!< | | "S<" is same as "v"
* s!< i!< | | "L<" is same as "V"
* l!< q!< | |
* | |
* n | Integer | 16-bit unsigned, network (big-endian) byte order
* N | Integer | 32-bit unsigned, network (big-endian) byte order
* v | Integer | 16-bit unsigned, VAX (little-endian) byte order
* V | Integer | 32-bit unsigned, VAX (little-endian) byte order
* | |
* U | Integer | UTF-8 character
* w | Integer | BER-compressed integer (see Array.pack)
*
* Float | |
* Directive | Returns | Meaning
* -----------------------------------------------------------------
* D, d | Float | double-precision, native format
* F, f | Float | single-precision, native format
* E | Float | double-precision, little-endian byte order
* e | Float | single-precision, little-endian byte order
* G | Float | double-precision, network (big-endian) byte order
* g | Float | single-precision, network (big-endian) byte order
*
* String | |
* Directive | Returns | Meaning
* -----------------------------------------------------------------
* A | String | arbitrary binary string (remove trailing nulls and ASCII spaces)
* a | String | arbitrary binary string
* Z | String | null-terminated string
* B | String | bit string (MSB first)
* b | String | bit string (LSB first)
* H | String | hex string (high nibble first)
* h | String | hex string (low nibble first)
* u | String | UU-encoded string
* M | String | quoted-printable, MIME encoding (see RFC2045)
* m | String | base64 encoded string (RFC 2045) (default)
* | | base64 encoded string (RFC 4648) if followed by 0
* P | String | pointer to a structure (fixed-length string)
* p | String | pointer to a null-terminated string
*
* Misc. | |
* Directive | Returns | Meaning
* -----------------------------------------------------------------
* @ | --- | skip to the offset given by the length argument
* X | --- | skip backward one byte
* x | --- | skip forward one byte
*/
static VALUE
pack_unpack(VALUE str, VALUE fmt)
{
static const char hexdigits[] = "0123456789abcdef";
char *s, *send;
char *p, *pend;
VALUE ary;
char type;
long len, tmp_len;
int star;
#ifdef NATINT_PACK
int natint; /* native integer */
#endif
int block_p = rb_block_given_p();
int signed_p, integer_size, bigendian_p;
#define UNPACK_PUSH(item) do {\
VALUE item_val = (item);\
if (block_p) {\
rb_yield(item_val);\
}\
else {\
rb_ary_push(ary, item_val);\
}\
} while (0)
* eval.c (block_pass): should not downgrade safe level. * ext/dbm/extconf.rb: allow specifying dbm-type explicitly. * ext/dbm/extconf.rb: avoid gdbm if possible, because it leaks memory, whereas gdbm.so doesn't. potential incompatibility. * string.c (rb_str_insert): new method. * parse.y (yylex): lex_state after RESCUE_MOD should be EXPR_BEG. * array.c (rb_ary_insert): new method. * array.c (rb_ary_update): new utility function. * io.c (set_outfile): should check if closed before assignment. * eval.c (rb_eval): should preserve value of ruby_errinfo. * eval.c (rb_thread_schedule): infinite sleep should not cause dead lock. * array.c (rb_ary_flatten_bang): proper recursive detection. * eval.c (yield_under): need not to prohibit at safe level 4. * pack.c (pack_pack): p/P packs nil into NULL. * pack.c (pack_unpack): p/P unpacks NULL into nil. * pack.c (pack_pack): size check for P template. * ruby.c (set_arg0): wrong predicate when new $0 value is bigger than original space. * gc.c (id2ref): should use NUM2ULONG() * object.c (rb_mod_const_get): check whether name is a class variable name. * object.c (rb_mod_const_set): ditto. * object.c (rb_mod_const_defined): ditto. * marshal.c (w_float): precision changed to "%.16g" * eval.c (rb_call0): wrong retry behavior. * numeric.c (fix_aref): a bug on long>int architecture. * eval.c (rb_eval_string_wrap): should restore ruby_wrapper. * regex.c (re_compile_pattern): char class at either edge of range should be invalid. * eval.c (handle_rescue): use === to compare exception match. * error.c (syserr_eqq): comparison between SytemCallErrors should based on their error numbers. * eval.c (safe_getter): should use INT2NUM(). * bignum.c (rb_big2long): 2**31 cannot fit in 31 bit long. * regex.c (calculate_must_string): wrong length calculation. * eval.c (rb_thread_start_0): fixed memory leak. * parse.y (none): should clear cmdarg_stack too. * io.c (rb_fopen): use setvbuf() to avoid recursive malloc() on some platforms. * file.c (rb_stat_dev): device functions should honor stat field types (except long long such as dev_t). * eval.c (rb_mod_nesting): should not push nil for nesting array. * eval.c (rb_mod_s_constants): should not search array by rb_mod_const_at() for nil (happens for singleton class). * class.c (rb_singleton_class_attached): should modify iv_tbl by itself, no longer use rb_iv_set() to avoid freeze check error. * variable.c (rb_const_get): error message "uninitialized constant Foo at Bar::Baz" instead of "uninitialized constantBar::Baz::Foo". * eval.c (rb_mod_included): new hook called from rb_mod_include(). * io.c (opt_i_set): should strdup() inplace_edit string. * eval.c (exec_under): need to push cref too. * eval.c (rb_f_missing): raise NameError for "undefined local variable or method". * error.c (Init_Exception): new exception NoMethodError. NameError moved under ScriptError again. * eval.c (rb_f_missing): use NoMethodError instead of NameError. * file.c (Init_File): should redifine "new" class method. * eval.c (PUSH_CREF): sharing cref node was problematic. maintain runtime cref list instead. * eval.c (rb_eval): copy defn node before registering. * eval.c (rb_load): clear ruby_cref before loading. * variable.c (rb_const_get): no recursion to show full class path for modules. * eval.c (rb_set_safe_level): should set safe level in curr_thread as well. * eval.c (safe_setter): ditto. * object.c (rb_obj_is_instance_of): nil belongs to false, not true. * time.c (make_time_t): proper (I hope) daylight saving time handling for both US and Europe. I HATE DST! * eval.c (rb_thread_wait_for): non blocked signal interrupt should stop the interval. * eval.c (proc_eq): class check aded. * eval.c (proc_eq): typo fixed ("return" was ommitted). * error.c (Init_Exception): move NameError under StandardError. * class.c (rb_mod_clone): should copy method bodies too. * bignum.c (bigdivrem): should trim trailing zero bdigits of remainder, even if dd == 0. * file.c (check3rdbyte): safe string check moved here. * time.c (make_time_t): remove HAVE_TM_ZONE code since it sometimes reports wrong time. * time.c (make_time_t): remove unnecessary range check for platforms where negative time_t is available. * process.c (proc_waitall): should push Process::Status instead of Finuxm status. * process.c (waitall_each): should add all entries in pid_tbl. these changes are inspired by Koji Arai. Thanks. * process.c (proc_wait): should not iterate if pid_tbl is 0. * process.c (proc_waitall): ditto. * numeric.c (flodivmod): a bug in no fmod case. * process.c (pst_wifsignaled): should apply WIFSIGNALED for status (int), not st (VALUE). * io.c (Init_IO): value of $/ and $\ are no longer restricted to strings. type checks are done on demand. * class.c (rb_include_module): module inclusion should be check taints. * ruby.h (STR2CSTR): replace to StringType() and StringTypePtr(). * ruby.h (rb_str2cstr): ditto. * eval.c (rb_load): should not copy topleve local variables. It cause variable/method ambiguity. Thanks to L. Peter Deutsch. * class.c (rb_include_module): freeze check at first. * eval.c (rb_attr): sprintf() and rb_intern() moved into conditional body. git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@1356 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2001-05-02 00:22:21 -04:00
StringValue(str);
StringValue(fmt);
s = RSTRING_PTR(str);
send = s + RSTRING_LEN(str);
p = RSTRING_PTR(fmt);
pend = p + RSTRING_LEN(fmt);
ary = block_p ? Qnil : rb_ary_new();
while (p < pend) {
int explicit_endian = 0;
type = *p++;
#ifdef NATINT_PACK
natint = 0;
#endif
if (ISSPACE(type)) continue;
if (type == '#') {
while ((p < pend) && (*p != '\n')) {
p++;
}
continue;
}
star = 0;
{
modifiers:
switch (*p) {
case '_':
case '!':
if (strchr(natstr, type)) {
#ifdef NATINT_PACK
natint = 1;
#endif
p++;
}
else {
rb_raise(rb_eArgError, "'%c' allowed only after types %s", *p, natstr);
}
goto modifiers;
case '<':
case '>':
if (!strchr(endstr, type)) {
rb_raise(rb_eArgError, "'%c' allowed only after types %s", *p, endstr);
}
if (explicit_endian) {
rb_raise(rb_eRangeError, "Can't use both '<' and '>'");
}
explicit_endian = *p++;
goto modifiers;
}
}
if (p >= pend)
len = 1;
else if (*p == '*') {
star = 1;
len = send - s;
p++;
}
else if (ISDIGIT(*p)) {
errno = 0;
len = STRTOUL(p, (char**)&p, 10);
if (errno) {
rb_raise(rb_eRangeError, "pack length too big");
}
}
else {
len = (type != '@');
}
switch (type) {
case '%':
rb_raise(rb_eArgError, "%% is not supported");
break;
case 'A':
if (len > send - s) len = send - s;
{
long end = len;
char *t = s + len - 1;
while (t >= s) {
if (*t != ' ' && *t != '\0') break;
t--; len--;
}
UNPACK_PUSH(infected_str_new(s, len, str));
s += end;
}
break;
case 'Z':
{
char *t = s;
if (len > send-s) len = send-s;
while (t < s+len && *t) t++;
UNPACK_PUSH(infected_str_new(s, t-s, str));
if (t < send) t++;
s = star ? t : s+len;
}
break;
case 'a':
if (len > send - s) len = send - s;
UNPACK_PUSH(infected_str_new(s, len, str));
s += len;
break;
case 'b':
{
VALUE bitstr;
char *t;
int bits;
long i;
if (p[-1] == '*' || len > (send - s) * 8)
len = (send - s) * 8;
bits = 0;
UNPACK_PUSH(bitstr = rb_usascii_str_new(0, len));
t = RSTRING_PTR(bitstr);
for (i=0; i<len; i++) {
if (i & 7) bits >>= 1;
else bits = *s++;
*t++ = (bits & 1) ? '1' : '0';
}
}
break;
case 'B':
{
VALUE bitstr;
char *t;
int bits;
long i;
if (p[-1] == '*' || len > (send - s) * 8)
len = (send - s) * 8;
bits = 0;
UNPACK_PUSH(bitstr = rb_usascii_str_new(0, len));
t = RSTRING_PTR(bitstr);
for (i=0; i<len; i++) {
if (i & 7) bits <<= 1;
else bits = *s++;
*t++ = (bits & 128) ? '1' : '0';
}
}
break;
case 'h':
{
VALUE bitstr;
char *t;
int bits;
long i;
if (p[-1] == '*' || len > (send - s) * 2)
len = (send - s) * 2;
bits = 0;
UNPACK_PUSH(bitstr = rb_usascii_str_new(0, len));
t = RSTRING_PTR(bitstr);
for (i=0; i<len; i++) {
if (i & 1)
bits >>= 4;
else
bits = *s++;
*t++ = hexdigits[bits & 15];
}
}
break;
case 'H':
{
VALUE bitstr;
char *t;
int bits;
long i;
if (p[-1] == '*' || len > (send - s) * 2)
len = (send - s) * 2;
bits = 0;
UNPACK_PUSH(bitstr = rb_usascii_str_new(0, len));
t = RSTRING_PTR(bitstr);
for (i=0; i<len; i++) {
if (i & 1)
bits <<= 4;
else
bits = *s++;
*t++ = hexdigits[(bits >> 4) & 15];
}
}
break;
case 'c':
PACK_LENGTH_ADJUST_SIZE(sizeof(char));
while (len-- > 0) {
int c = *s++;
if (c > (char)127) c-=256;
UNPACK_PUSH(INT2FIX(c));
}
PACK_ITEM_ADJUST();
break;
case 'C':
PACK_LENGTH_ADJUST_SIZE(sizeof(unsigned char));
while (len-- > 0) {
unsigned char c = *s++;
UNPACK_PUSH(INT2FIX(c));
}
PACK_ITEM_ADJUST();
break;
case 's':
signed_p = 1;
integer_size = NATINT_LEN(short, 2);
bigendian_p = BIGENDIAN_P();
goto unpack_integer;
case 'S':
signed_p = 0;
integer_size = NATINT_LEN(short, 2);
bigendian_p = BIGENDIAN_P();
goto unpack_integer;
case 'i':
signed_p = 1;
integer_size = (int)sizeof(int);
bigendian_p = BIGENDIAN_P();
goto unpack_integer;
case 'I':
signed_p = 0;
integer_size = (int)sizeof(int);
bigendian_p = BIGENDIAN_P();
goto unpack_integer;
case 'l':
signed_p = 1;
integer_size = NATINT_LEN(long, 4);
bigendian_p = BIGENDIAN_P();
goto unpack_integer;
case 'L':
signed_p = 0;
integer_size = NATINT_LEN(long, 4);
bigendian_p = BIGENDIAN_P();
goto unpack_integer;
case 'q':
signed_p = 1;
integer_size = NATINT_LEN_Q;
bigendian_p = BIGENDIAN_P();
goto unpack_integer;
case 'Q':
signed_p = 0;
integer_size = NATINT_LEN_Q;
bigendian_p = BIGENDIAN_P();
goto unpack_integer;
case 'n':
signed_p = 0;
integer_size = 2;
bigendian_p = 1;
goto unpack_integer;
case 'N':
signed_p = 0;
integer_size = 4;
bigendian_p = 1;
goto unpack_integer;
case 'v':
signed_p = 0;
integer_size = 2;
bigendian_p = 0;
goto unpack_integer;
case 'V':
signed_p = 0;
integer_size = 4;
bigendian_p = 0;
goto unpack_integer;
unpack_integer:
if (explicit_endian) {
bigendian_p = explicit_endian == '>';
}
switch (integer_size) {
#if defined(HAVE_INT16_T) && !defined(FORCE_BIG_PACK)
case SIZEOF_INT16_T:
if (signed_p) {
PACK_LENGTH_ADJUST_SIZE(sizeof(int16_t));
while (len-- > 0) {
union {
int16_t i;
char a[sizeof(int16_t)];
} v;
memcpy(v.a, s, sizeof(int16_t));
if (bigendian_p != BIGENDIAN_P()) v.i = swap16(v.i);
s += sizeof(int16_t);
UNPACK_PUSH(INT2FIX(v.i));
}
PACK_ITEM_ADJUST();
}
else {
PACK_LENGTH_ADJUST_SIZE(sizeof(uint16_t));
while (len-- > 0) {
union {
uint16_t i;
char a[sizeof(uint16_t)];
} v;
memcpy(v.a, s, sizeof(uint16_t));
if (bigendian_p != BIGENDIAN_P()) v.i = swap16(v.i);
s += sizeof(uint16_t);
UNPACK_PUSH(INT2FIX(v.i));
}
PACK_ITEM_ADJUST();
}
break;
#endif
#if defined(HAVE_INT32_T) && !defined(FORCE_BIG_PACK)
case SIZEOF_INT32_T:
if (signed_p) {
PACK_LENGTH_ADJUST_SIZE(sizeof(int32_t));
while (len-- > 0) {
union {
int32_t i;
char a[sizeof(int32_t)];
} v;
memcpy(v.a, s, sizeof(int32_t));
if (bigendian_p != BIGENDIAN_P()) v.i = swap32(v.i);
s += sizeof(int32_t);
UNPACK_PUSH(INT2NUM(v.i));
}
PACK_ITEM_ADJUST();
}
else {
PACK_LENGTH_ADJUST_SIZE(sizeof(uint32_t));
while (len-- > 0) {
union {
uint32_t i;
char a[sizeof(uint32_t)];
} v;
memcpy(v.a, s, sizeof(uint32_t));
if (bigendian_p != BIGENDIAN_P()) v.i = swap32(v.i);
s += sizeof(uint32_t);
UNPACK_PUSH(UINT2NUM(v.i));
}
PACK_ITEM_ADJUST();
}
break;
#endif
#if defined(HAVE_INT64_T) && !defined(FORCE_BIG_PACK)
case SIZEOF_INT64_T:
if (signed_p) {
PACK_LENGTH_ADJUST_SIZE(sizeof(int64_t));
while (len-- > 0) {
union {
int64_t i;
char a[sizeof(int64_t)];
} v;
memcpy(v.a, s, sizeof(int64_t));
if (bigendian_p != BIGENDIAN_P()) v.i = swap64(v.i);
s += sizeof(int64_t);
UNPACK_PUSH(INT64toNUM(v.i));
}
PACK_ITEM_ADJUST();
}
else {
PACK_LENGTH_ADJUST_SIZE(sizeof(uint64_t));
while (len-- > 0) {
union {
uint64_t i;
char a[sizeof(uint64_t)];
} v;
memcpy(v.a, s, sizeof(uint64_t));
if (bigendian_p != BIGENDIAN_P()) v.i = swap64(v.i);
s += sizeof(uint64_t);
UNPACK_PUSH(UINT64toNUM(v.i));
}
PACK_ITEM_ADJUST();
}
break;
#endif
default:
PACK_LENGTH_ADJUST_SIZE(integer_size);
while (len-- > 0) {
int flags = bigendian_p ? INTEGER_PACK_BIG_ENDIAN : INTEGER_PACK_LITTLE_ENDIAN;
VALUE val;
if (signed_p)
val = rb_integer_unpack_2comp(s, integer_size, 1, 0, flags);
else
val = rb_integer_unpack(s, integer_size, 1, 0, flags);
UNPACK_PUSH(val);
s += integer_size;
}
PACK_ITEM_ADJUST();
break;
}
break;
case 'f':
case 'F':
PACK_LENGTH_ADJUST_SIZE(sizeof(float));
while (len-- > 0) {
float tmp;
memcpy(&tmp, s, sizeof(float));
s += sizeof(float);
UNPACK_PUSH(DBL2NUM((double)tmp));
}
PACK_ITEM_ADJUST();
break;
case 'e':
PACK_LENGTH_ADJUST_SIZE(sizeof(float));
while (len-- > 0) {
float tmp;
FLOAT_CONVWITH(ftmp);
memcpy(&tmp, s, sizeof(float));
s += sizeof(float);
tmp = VTOHF(tmp,ftmp);
UNPACK_PUSH(DBL2NUM((double)tmp));
}
PACK_ITEM_ADJUST();
break;
case 'E':
PACK_LENGTH_ADJUST_SIZE(sizeof(double));
while (len-- > 0) {
double tmp;
DOUBLE_CONVWITH(dtmp);
memcpy(&tmp, s, sizeof(double));
s += sizeof(double);
tmp = VTOHD(tmp,dtmp);
UNPACK_PUSH(DBL2NUM(tmp));
}
PACK_ITEM_ADJUST();
break;
case 'D':
case 'd':
PACK_LENGTH_ADJUST_SIZE(sizeof(double));
while (len-- > 0) {
double tmp;
memcpy(&tmp, s, sizeof(double));
s += sizeof(double);
UNPACK_PUSH(DBL2NUM(tmp));
}
PACK_ITEM_ADJUST();
break;
case 'g':
PACK_LENGTH_ADJUST_SIZE(sizeof(float));
while (len-- > 0) {
float tmp;
FLOAT_CONVWITH(ftmp);
memcpy(&tmp, s, sizeof(float));
s += sizeof(float);
tmp = NTOHF(tmp,ftmp);
UNPACK_PUSH(DBL2NUM((double)tmp));
}
PACK_ITEM_ADJUST();
break;
case 'G':
PACK_LENGTH_ADJUST_SIZE(sizeof(double));
while (len-- > 0) {
double tmp;
DOUBLE_CONVWITH(dtmp);
memcpy(&tmp, s, sizeof(double));
s += sizeof(double);
tmp = NTOHD(tmp,dtmp);
UNPACK_PUSH(DBL2NUM(tmp));
}
PACK_ITEM_ADJUST();
break;
case 'U':
if (len > send - s) len = send - s;
while (len > 0 && s < send) {
long alen = send - s;
unsigned long l;
l = utf8_to_uv(s, &alen);
s += alen; len--;
UNPACK_PUSH(ULONG2NUM(l));
}
break;
case 'u':
{
VALUE buf = infected_str_new(0, (send - s)*3/4, str);
char *ptr = RSTRING_PTR(buf);
long total = 0;
while (s < send && *s > ' ' && *s < 'a') {
long a,b,c,d;
char hunk[4];
hunk[3] = '\0';
len = (*s++ - ' ') & 077;
total += len;
if (total > RSTRING_LEN(buf)) {
len -= total - RSTRING_LEN(buf);
total = RSTRING_LEN(buf);
}
while (len > 0) {
long mlen = len > 3 ? 3 : len;
if (s < send && *s >= ' ')
a = (*s++ - ' ') & 077;
else
a = 0;
if (s < send && *s >= ' ')
b = (*s++ - ' ') & 077;
else
b = 0;
if (s < send && *s >= ' ')
c = (*s++ - ' ') & 077;
else
c = 0;
if (s < send && *s >= ' ')
d = (*s++ - ' ') & 077;
else
d = 0;
hunk[0] = (char)(a << 2 | b >> 4);
hunk[1] = (char)(b << 4 | c >> 2);
hunk[2] = (char)(c << 6 | d);
memcpy(ptr, hunk, mlen);
ptr += mlen;
len -= mlen;
}
if (*s == '\r') s++;
if (*s == '\n') s++;
else if (s < send && (s+1 == send || s[1] == '\n'))
s += 2; /* possible checksum byte */
}
rb_str_set_len(buf, total);
UNPACK_PUSH(buf);
}
break;
case 'm':
{
VALUE buf = infected_str_new(0, (send - s + 3)*3/4, str); /* +3 is for skipping paddings */
char *ptr = RSTRING_PTR(buf);
int a = -1,b = -1,c = 0,d = 0;
static signed char b64_xtable[256];
if (b64_xtable['/'] <= 0) {
int i;
for (i = 0; i < 256; i++) {
b64_xtable[i] = -1;
}
for (i = 0; i < 64; i++) {
b64_xtable[(unsigned char)b64_table[i]] = (char)i;
}
}
if (len == 0) {
while (s < send) {
a = b = c = d = -1;
a = b64_xtable[(unsigned char)*s++];
if (s >= send || a == -1) rb_raise(rb_eArgError, "invalid base64");
b = b64_xtable[(unsigned char)*s++];
if (s >= send || b == -1) rb_raise(rb_eArgError, "invalid base64");
if (*s == '=') {
if (s + 2 == send && *(s + 1) == '=') break;
rb_raise(rb_eArgError, "invalid base64");
}
c = b64_xtable[(unsigned char)*s++];
if (s >= send || c == -1) rb_raise(rb_eArgError, "invalid base64");
if (s + 1 == send && *s == '=') break;
d = b64_xtable[(unsigned char)*s++];
if (d == -1) rb_raise(rb_eArgError, "invalid base64");
*ptr++ = castchar(a << 2 | b >> 4);
*ptr++ = castchar(b << 4 | c >> 2);
*ptr++ = castchar(c << 6 | d);
}
if (c == -1) {
*ptr++ = castchar(a << 2 | b >> 4);
if (b & 0xf) rb_raise(rb_eArgError, "invalid base64");
}
else if (d == -1) {
*ptr++ = castchar(a << 2 | b >> 4);
*ptr++ = castchar(b << 4 | c >> 2);
if (c & 0x3) rb_raise(rb_eArgError, "invalid base64");
}
}
else {
while (s < send) {
a = b = c = d = -1;
while ((a = b64_xtable[(unsigned char)*s]) == -1 && s < send) {s++;}
if (s >= send) break;
s++;
while ((b = b64_xtable[(unsigned char)*s]) == -1 && s < send) {s++;}
if (s >= send) break;
s++;
while ((c = b64_xtable[(unsigned char)*s]) == -1 && s < send) {if (*s == '=') break; s++;}
if (*s == '=' || s >= send) break;
s++;
while ((d = b64_xtable[(unsigned char)*s]) == -1 && s < send) {if (*s == '=') break; s++;}
if (*s == '=' || s >= send) break;
s++;
*ptr++ = castchar(a << 2 | b >> 4);
*ptr++ = castchar(b << 4 | c >> 2);
*ptr++ = castchar(c << 6 | d);
a = -1;
}
if (a != -1 && b != -1) {
if (c == -1)
*ptr++ = castchar(a << 2 | b >> 4);
else {
*ptr++ = castchar(a << 2 | b >> 4);
*ptr++ = castchar(b << 4 | c >> 2);
}
}
}
rb_str_set_len(buf, ptr - RSTRING_PTR(buf));
UNPACK_PUSH(buf);
}
break;
case 'M':
{
VALUE buf = infected_str_new(0, send - s, str);
char *ptr = RSTRING_PTR(buf), *ss = s;
int c1, c2;
while (s < send) {
if (*s == '=') {
if (++s == send) break;
if (s+1 < send && *s == '\r' && *(s+1) == '\n')
s++;
if (*s != '\n') {
if ((c1 = hex2num(*s)) == -1) break;
if (++s == send) break;
if ((c2 = hex2num(*s)) == -1) break;
*ptr++ = castchar(c1 << 4 | c2);
}
}
else {
*ptr++ = *s;
}
s++;
ss = s;
}
rb_str_set_len(buf, ptr - RSTRING_PTR(buf));
rb_str_buf_cat(buf, ss, send-ss);
ENCODING_CODERANGE_SET(buf, rb_ascii8bit_encindex(), ENC_CODERANGE_VALID);
UNPACK_PUSH(buf);
}
break;
case '@':
if (len > RSTRING_LEN(str))
rb_raise(rb_eArgError, "@ outside of string");
s = RSTRING_PTR(str) + len;
break;
case 'X':
if (len > s - RSTRING_PTR(str))
rb_raise(rb_eArgError, "X outside of string");
s -= len;
break;
case 'x':
if (len > send - s)
rb_raise(rb_eArgError, "x outside of string");
s += len;
break;
case 'P':
if (sizeof(char *) <= (size_t)(send - s)) {
VALUE tmp = Qnil;
char *t;
memcpy(&t, s, sizeof(char *));
s += sizeof(char *);
if (t) {
* eval.c (block_pass): should not downgrade safe level. * ext/dbm/extconf.rb: allow specifying dbm-type explicitly. * ext/dbm/extconf.rb: avoid gdbm if possible, because it leaks memory, whereas gdbm.so doesn't. potential incompatibility. * string.c (rb_str_insert): new method. * parse.y (yylex): lex_state after RESCUE_MOD should be EXPR_BEG. * array.c (rb_ary_insert): new method. * array.c (rb_ary_update): new utility function. * io.c (set_outfile): should check if closed before assignment. * eval.c (rb_eval): should preserve value of ruby_errinfo. * eval.c (rb_thread_schedule): infinite sleep should not cause dead lock. * array.c (rb_ary_flatten_bang): proper recursive detection. * eval.c (yield_under): need not to prohibit at safe level 4. * pack.c (pack_pack): p/P packs nil into NULL. * pack.c (pack_unpack): p/P unpacks NULL into nil. * pack.c (pack_pack): size check for P template. * ruby.c (set_arg0): wrong predicate when new $0 value is bigger than original space. * gc.c (id2ref): should use NUM2ULONG() * object.c (rb_mod_const_get): check whether name is a class variable name. * object.c (rb_mod_const_set): ditto. * object.c (rb_mod_const_defined): ditto. * marshal.c (w_float): precision changed to "%.16g" * eval.c (rb_call0): wrong retry behavior. * numeric.c (fix_aref): a bug on long>int architecture. * eval.c (rb_eval_string_wrap): should restore ruby_wrapper. * regex.c (re_compile_pattern): char class at either edge of range should be invalid. * eval.c (handle_rescue): use === to compare exception match. * error.c (syserr_eqq): comparison between SytemCallErrors should based on their error numbers. * eval.c (safe_getter): should use INT2NUM(). * bignum.c (rb_big2long): 2**31 cannot fit in 31 bit long. * regex.c (calculate_must_string): wrong length calculation. * eval.c (rb_thread_start_0): fixed memory leak. * parse.y (none): should clear cmdarg_stack too. * io.c (rb_fopen): use setvbuf() to avoid recursive malloc() on some platforms. * file.c (rb_stat_dev): device functions should honor stat field types (except long long such as dev_t). * eval.c (rb_mod_nesting): should not push nil for nesting array. * eval.c (rb_mod_s_constants): should not search array by rb_mod_const_at() for nil (happens for singleton class). * class.c (rb_singleton_class_attached): should modify iv_tbl by itself, no longer use rb_iv_set() to avoid freeze check error. * variable.c (rb_const_get): error message "uninitialized constant Foo at Bar::Baz" instead of "uninitialized constantBar::Baz::Foo". * eval.c (rb_mod_included): new hook called from rb_mod_include(). * io.c (opt_i_set): should strdup() inplace_edit string. * eval.c (exec_under): need to push cref too. * eval.c (rb_f_missing): raise NameError for "undefined local variable or method". * error.c (Init_Exception): new exception NoMethodError. NameError moved under ScriptError again. * eval.c (rb_f_missing): use NoMethodError instead of NameError. * file.c (Init_File): should redifine "new" class method. * eval.c (PUSH_CREF): sharing cref node was problematic. maintain runtime cref list instead. * eval.c (rb_eval): copy defn node before registering. * eval.c (rb_load): clear ruby_cref before loading. * variable.c (rb_const_get): no recursion to show full class path for modules. * eval.c (rb_set_safe_level): should set safe level in curr_thread as well. * eval.c (safe_setter): ditto. * object.c (rb_obj_is_instance_of): nil belongs to false, not true. * time.c (make_time_t): proper (I hope) daylight saving time handling for both US and Europe. I HATE DST! * eval.c (rb_thread_wait_for): non blocked signal interrupt should stop the interval. * eval.c (proc_eq): class check aded. * eval.c (proc_eq): typo fixed ("return" was ommitted). * error.c (Init_Exception): move NameError under StandardError. * class.c (rb_mod_clone): should copy method bodies too. * bignum.c (bigdivrem): should trim trailing zero bdigits of remainder, even if dd == 0. * file.c (check3rdbyte): safe string check moved here. * time.c (make_time_t): remove HAVE_TM_ZONE code since it sometimes reports wrong time. * time.c (make_time_t): remove unnecessary range check for platforms where negative time_t is available. * process.c (proc_waitall): should push Process::Status instead of Finuxm status. * process.c (waitall_each): should add all entries in pid_tbl. these changes are inspired by Koji Arai. Thanks. * process.c (proc_wait): should not iterate if pid_tbl is 0. * process.c (proc_waitall): ditto. * numeric.c (flodivmod): a bug in no fmod case. * process.c (pst_wifsignaled): should apply WIFSIGNALED for status (int), not st (VALUE). * io.c (Init_IO): value of $/ and $\ are no longer restricted to strings. type checks are done on demand. * class.c (rb_include_module): module inclusion should be check taints. * ruby.h (STR2CSTR): replace to StringType() and StringTypePtr(). * ruby.h (rb_str2cstr): ditto. * eval.c (rb_load): should not copy topleve local variables. It cause variable/method ambiguity. Thanks to L. Peter Deutsch. * class.c (rb_include_module): freeze check at first. * eval.c (rb_attr): sprintf() and rb_intern() moved into conditional body. git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@1356 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2001-05-02 00:22:21 -04:00
VALUE a, *p, *pend;
* eval.c (block_pass): should not downgrade safe level. * ext/dbm/extconf.rb: allow specifying dbm-type explicitly. * ext/dbm/extconf.rb: avoid gdbm if possible, because it leaks memory, whereas gdbm.so doesn't. potential incompatibility. * string.c (rb_str_insert): new method. * parse.y (yylex): lex_state after RESCUE_MOD should be EXPR_BEG. * array.c (rb_ary_insert): new method. * array.c (rb_ary_update): new utility function. * io.c (set_outfile): should check if closed before assignment. * eval.c (rb_eval): should preserve value of ruby_errinfo. * eval.c (rb_thread_schedule): infinite sleep should not cause dead lock. * array.c (rb_ary_flatten_bang): proper recursive detection. * eval.c (yield_under): need not to prohibit at safe level 4. * pack.c (pack_pack): p/P packs nil into NULL. * pack.c (pack_unpack): p/P unpacks NULL into nil. * pack.c (pack_pack): size check for P template. * ruby.c (set_arg0): wrong predicate when new $0 value is bigger than original space. * gc.c (id2ref): should use NUM2ULONG() * object.c (rb_mod_const_get): check whether name is a class variable name. * object.c (rb_mod_const_set): ditto. * object.c (rb_mod_const_defined): ditto. * marshal.c (w_float): precision changed to "%.16g" * eval.c (rb_call0): wrong retry behavior. * numeric.c (fix_aref): a bug on long>int architecture. * eval.c (rb_eval_string_wrap): should restore ruby_wrapper. * regex.c (re_compile_pattern): char class at either edge of range should be invalid. * eval.c (handle_rescue): use === to compare exception match. * error.c (syserr_eqq): comparison between SytemCallErrors should based on their error numbers. * eval.c (safe_getter): should use INT2NUM(). * bignum.c (rb_big2long): 2**31 cannot fit in 31 bit long. * regex.c (calculate_must_string): wrong length calculation. * eval.c (rb_thread_start_0): fixed memory leak. * parse.y (none): should clear cmdarg_stack too. * io.c (rb_fopen): use setvbuf() to avoid recursive malloc() on some platforms. * file.c (rb_stat_dev): device functions should honor stat field types (except long long such as dev_t). * eval.c (rb_mod_nesting): should not push nil for nesting array. * eval.c (rb_mod_s_constants): should not search array by rb_mod_const_at() for nil (happens for singleton class). * class.c (rb_singleton_class_attached): should modify iv_tbl by itself, no longer use rb_iv_set() to avoid freeze check error. * variable.c (rb_const_get): error message "uninitialized constant Foo at Bar::Baz" instead of "uninitialized constantBar::Baz::Foo". * eval.c (rb_mod_included): new hook called from rb_mod_include(). * io.c (opt_i_set): should strdup() inplace_edit string. * eval.c (exec_under): need to push cref too. * eval.c (rb_f_missing): raise NameError for "undefined local variable or method". * error.c (Init_Exception): new exception NoMethodError. NameError moved under ScriptError again. * eval.c (rb_f_missing): use NoMethodError instead of NameError. * file.c (Init_File): should redifine "new" class method. * eval.c (PUSH_CREF): sharing cref node was problematic. maintain runtime cref list instead. * eval.c (rb_eval): copy defn node before registering. * eval.c (rb_load): clear ruby_cref before loading. * variable.c (rb_const_get): no recursion to show full class path for modules. * eval.c (rb_set_safe_level): should set safe level in curr_thread as well. * eval.c (safe_setter): ditto. * object.c (rb_obj_is_instance_of): nil belongs to false, not true. * time.c (make_time_t): proper (I hope) daylight saving time handling for both US and Europe. I HATE DST! * eval.c (rb_thread_wait_for): non blocked signal interrupt should stop the interval. * eval.c (proc_eq): class check aded. * eval.c (proc_eq): typo fixed ("return" was ommitted). * error.c (Init_Exception): move NameError under StandardError. * class.c (rb_mod_clone): should copy method bodies too. * bignum.c (bigdivrem): should trim trailing zero bdigits of remainder, even if dd == 0. * file.c (check3rdbyte): safe string check moved here. * time.c (make_time_t): remove HAVE_TM_ZONE code since it sometimes reports wrong time. * time.c (make_time_t): remove unnecessary range check for platforms where negative time_t is available. * process.c (proc_waitall): should push Process::Status instead of Finuxm status. * process.c (waitall_each): should add all entries in pid_tbl. these changes are inspired by Koji Arai. Thanks. * process.c (proc_wait): should not iterate if pid_tbl is 0. * process.c (proc_waitall): ditto. * numeric.c (flodivmod): a bug in no fmod case. * process.c (pst_wifsignaled): should apply WIFSIGNALED for status (int), not st (VALUE). * io.c (Init_IO): value of $/ and $\ are no longer restricted to strings. type checks are done on demand. * class.c (rb_include_module): module inclusion should be check taints. * ruby.h (STR2CSTR): replace to StringType() and StringTypePtr(). * ruby.h (rb_str2cstr): ditto. * eval.c (rb_load): should not copy topleve local variables. It cause variable/method ambiguity. Thanks to L. Peter Deutsch. * class.c (rb_include_module): freeze check at first. * eval.c (rb_attr): sprintf() and rb_intern() moved into conditional body. git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@1356 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2001-05-02 00:22:21 -04:00
if (!(a = rb_str_associated(str))) {
rb_raise(rb_eArgError, "no associated pointer");
}
p = RARRAY_PTR(a);
pend = p + RARRAY_LEN(a);
while (p < pend) {
if (RB_TYPE_P(*p, T_STRING) && RSTRING_PTR(*p) == t) {
if (len < RSTRING_LEN(*p)) {
tmp = rb_tainted_str_new(t, len);
rb_str_associate(tmp, a);
}
else {
tmp = *p;
}
break;
}
p++;
}
if (p == pend) {
rb_raise(rb_eArgError, "non associated pointer");
}
}
UNPACK_PUSH(tmp);
}
break;
case 'p':
if (len > (long)((send - s) / sizeof(char *)))
len = (send - s) / sizeof(char *);
while (len-- > 0) {
if ((size_t)(send - s) < sizeof(char *))
break;
else {
VALUE tmp = Qnil;
char *t;
memcpy(&t, s, sizeof(char *));
s += sizeof(char *);
if (t) {
VALUE a, *p, *pend;
* eval.c (block_pass): should not downgrade safe level. * ext/dbm/extconf.rb: allow specifying dbm-type explicitly. * ext/dbm/extconf.rb: avoid gdbm if possible, because it leaks memory, whereas gdbm.so doesn't. potential incompatibility. * string.c (rb_str_insert): new method. * parse.y (yylex): lex_state after RESCUE_MOD should be EXPR_BEG. * array.c (rb_ary_insert): new method. * array.c (rb_ary_update): new utility function. * io.c (set_outfile): should check if closed before assignment. * eval.c (rb_eval): should preserve value of ruby_errinfo. * eval.c (rb_thread_schedule): infinite sleep should not cause dead lock. * array.c (rb_ary_flatten_bang): proper recursive detection. * eval.c (yield_under): need not to prohibit at safe level 4. * pack.c (pack_pack): p/P packs nil into NULL. * pack.c (pack_unpack): p/P unpacks NULL into nil. * pack.c (pack_pack): size check for P template. * ruby.c (set_arg0): wrong predicate when new $0 value is bigger than original space. * gc.c (id2ref): should use NUM2ULONG() * object.c (rb_mod_const_get): check whether name is a class variable name. * object.c (rb_mod_const_set): ditto. * object.c (rb_mod_const_defined): ditto. * marshal.c (w_float): precision changed to "%.16g" * eval.c (rb_call0): wrong retry behavior. * numeric.c (fix_aref): a bug on long>int architecture. * eval.c (rb_eval_string_wrap): should restore ruby_wrapper. * regex.c (re_compile_pattern): char class at either edge of range should be invalid. * eval.c (handle_rescue): use === to compare exception match. * error.c (syserr_eqq): comparison between SytemCallErrors should based on their error numbers. * eval.c (safe_getter): should use INT2NUM(). * bignum.c (rb_big2long): 2**31 cannot fit in 31 bit long. * regex.c (calculate_must_string): wrong length calculation. * eval.c (rb_thread_start_0): fixed memory leak. * parse.y (none): should clear cmdarg_stack too. * io.c (rb_fopen): use setvbuf() to avoid recursive malloc() on some platforms. * file.c (rb_stat_dev): device functions should honor stat field types (except long long such as dev_t). * eval.c (rb_mod_nesting): should not push nil for nesting array. * eval.c (rb_mod_s_constants): should not search array by rb_mod_const_at() for nil (happens for singleton class). * class.c (rb_singleton_class_attached): should modify iv_tbl by itself, no longer use rb_iv_set() to avoid freeze check error. * variable.c (rb_const_get): error message "uninitialized constant Foo at Bar::Baz" instead of "uninitialized constantBar::Baz::Foo". * eval.c (rb_mod_included): new hook called from rb_mod_include(). * io.c (opt_i_set): should strdup() inplace_edit string. * eval.c (exec_under): need to push cref too. * eval.c (rb_f_missing): raise NameError for "undefined local variable or method". * error.c (Init_Exception): new exception NoMethodError. NameError moved under ScriptError again. * eval.c (rb_f_missing): use NoMethodError instead of NameError. * file.c (Init_File): should redifine "new" class method. * eval.c (PUSH_CREF): sharing cref node was problematic. maintain runtime cref list instead. * eval.c (rb_eval): copy defn node before registering. * eval.c (rb_load): clear ruby_cref before loading. * variable.c (rb_const_get): no recursion to show full class path for modules. * eval.c (rb_set_safe_level): should set safe level in curr_thread as well. * eval.c (safe_setter): ditto. * object.c (rb_obj_is_instance_of): nil belongs to false, not true. * time.c (make_time_t): proper (I hope) daylight saving time handling for both US and Europe. I HATE DST! * eval.c (rb_thread_wait_for): non blocked signal interrupt should stop the interval. * eval.c (proc_eq): class check aded. * eval.c (proc_eq): typo fixed ("return" was ommitted). * error.c (Init_Exception): move NameError under StandardError. * class.c (rb_mod_clone): should copy method bodies too. * bignum.c (bigdivrem): should trim trailing zero bdigits of remainder, even if dd == 0. * file.c (check3rdbyte): safe string check moved here. * time.c (make_time_t): remove HAVE_TM_ZONE code since it sometimes reports wrong time. * time.c (make_time_t): remove unnecessary range check for platforms where negative time_t is available. * process.c (proc_waitall): should push Process::Status instead of Finuxm status. * process.c (waitall_each): should add all entries in pid_tbl. these changes are inspired by Koji Arai. Thanks. * process.c (proc_wait): should not iterate if pid_tbl is 0. * process.c (proc_waitall): ditto. * numeric.c (flodivmod): a bug in no fmod case. * process.c (pst_wifsignaled): should apply WIFSIGNALED for status (int), not st (VALUE). * io.c (Init_IO): value of $/ and $\ are no longer restricted to strings. type checks are done on demand. * class.c (rb_include_module): module inclusion should be check taints. * ruby.h (STR2CSTR): replace to StringType() and StringTypePtr(). * ruby.h (rb_str2cstr): ditto. * eval.c (rb_load): should not copy topleve local variables. It cause variable/method ambiguity. Thanks to L. Peter Deutsch. * class.c (rb_include_module): freeze check at first. * eval.c (rb_attr): sprintf() and rb_intern() moved into conditional body. git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@1356 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2001-05-02 00:22:21 -04:00
if (!(a = rb_str_associated(str))) {
rb_raise(rb_eArgError, "no associated pointer");
}
p = RARRAY_PTR(a);
pend = p + RARRAY_LEN(a);
while (p < pend) {
if (RB_TYPE_P(*p, T_STRING) && RSTRING_PTR(*p) == t) {
tmp = *p;
break;
}
p++;
}
if (p == pend) {
rb_raise(rb_eArgError, "non associated pointer");
}
}
UNPACK_PUSH(tmp);
}
}
break;
case 'w':
{
char *s0 = s;
while (len > 0 && s < send) {
if (*s & 0x80) {
s++;
}
else {
s++;
UNPACK_PUSH(rb_integer_unpack(s0, s-s0, 1, 1, INTEGER_PACK_BIG_ENDIAN));
len--;
s0 = s;
}
}
}
break;
default:
rb_warning("unknown unpack directive '%c' in '%s'",
type, RSTRING_PTR(fmt));
break;
}
}
return ary;
}
#define BYTEWIDTH 8
int
rb_uv_to_utf8(char buf[6], unsigned long uv)
{
if (uv <= 0x7f) {
buf[0] = (char)uv;
return 1;
}
if (uv <= 0x7ff) {
buf[0] = castchar(((uv>>6)&0xff)|0xc0);
buf[1] = castchar((uv&0x3f)|0x80);
return 2;
}
if (uv <= 0xffff) {
buf[0] = castchar(((uv>>12)&0xff)|0xe0);
buf[1] = castchar(((uv>>6)&0x3f)|0x80);
buf[2] = castchar((uv&0x3f)|0x80);
return 3;
}
if (uv <= 0x1fffff) {
buf[0] = castchar(((uv>>18)&0xff)|0xf0);
buf[1] = castchar(((uv>>12)&0x3f)|0x80);
buf[2] = castchar(((uv>>6)&0x3f)|0x80);
buf[3] = castchar((uv&0x3f)|0x80);
return 4;
}
if (uv <= 0x3ffffff) {
buf[0] = castchar(((uv>>24)&0xff)|0xf8);
buf[1] = castchar(((uv>>18)&0x3f)|0x80);
buf[2] = castchar(((uv>>12)&0x3f)|0x80);
buf[3] = castchar(((uv>>6)&0x3f)|0x80);
buf[4] = castchar((uv&0x3f)|0x80);
return 5;
}
if (uv <= 0x7fffffff) {
buf[0] = castchar(((uv>>30)&0xff)|0xfc);
buf[1] = castchar(((uv>>24)&0x3f)|0x80);
buf[2] = castchar(((uv>>18)&0x3f)|0x80);
buf[3] = castchar(((uv>>12)&0x3f)|0x80);
buf[4] = castchar(((uv>>6)&0x3f)|0x80);
buf[5] = castchar((uv&0x3f)|0x80);
return 6;
}
rb_raise(rb_eRangeError, "pack(U): value out of range");
* encoding.c (rb_enc_codepoint_len): Use UNREACHABLE to avoid "control reaches end of non-void function" warnings. [ruby-trunk - Bug #6066] * re.c (name_to_backref_number): ditto. * object.c (rb_Float): ditto. * io.c (io_readpartial): ditto. * io.c (io_read_nonblock): ditto. * pack.c (rb_uv_to_utf8): ditto. * proc.c (rb_method_entry_arity): ditto. * vm_method.c (rb_f_notimplement): ditto. * struct.c (rb_struct_aset_id): ditto. * class.c (rb_scan_args): ditto. * process.c (rlimit_resource_type): ditto. * process.c (rlimit_resource_value): ditto. * process.c (p_uid_switch): ditto. * process.c (p_gid_switch): ditto. * ext/digest/digest.c (rb_digest_instance_update): ditto. * ext/digest/digest.c (rb_digest_instance_finish): ditto. * ext/digest/digest.c (rb_digest_instance_reset): ditto. * ext/digest/digest.c (rb_digest_instance_block_length): ditto. * ext/bigdecimal/bigdecimal.c (BigDecimalCmp): ditto. * ext/dl/handle.c (rb_dlhandle_close): ditto. * ext/tk/tcltklib.c (pending_exception_check0): ditto. * ext/tk/tcltklib.c (pending_exception_check1): ditto. * ext/tk/tcltklib.c (ip_cancel_eval_core): ditto. * ext/tk/tcltklib.c (lib_get_reltype_name): ditto. * ext/tk/tcltklib.c (create_dummy_encoding_for_tk_core): ditto. * ext/tk/tkutil/tkutil.c (tk_hash_kv): ditto. * ext/openssl/ossl_ssl.c (ossl_ssl_session_reused): ditto. * ext/openssl/ossl_pkey_ec.c (ossl_ec_key_dsa_verify_asn1): ditto. * ext/openssl/ossl_pkey_ec.c (ossl_ec_point_is_at_infinit): ditto. * ext/openssl/ossl_pkey_ec.c (ossl_ec_point_is_on_curve): ditto. * ext/fiddle/conversions.c (generic_to_value): ditto. * ext/socket/raddrinfo.c (rsock_io_socket_addrinfo): ditto. * ext/socket/socket.c (sock_s_getnameinfo): ditto. * ext/ripper/eventids2.c (ripper_token2eventid): ditto. * cont.c (return_fiber): ditto. * dmydln.c (dln_load): ditto. * vm_insnhelper.c (vm_search_normal_superclass): ditto. * bignum.c (big_fdiv): ditto. * marshal.c (r_symlink): ditto. * marshal.c (r_symbol): ditto. git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@35321 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2012-04-13 19:45:37 -04:00
UNREACHABLE;
}
static const unsigned long utf8_limits[] = {
0x0, /* 1 */
0x80, /* 2 */
0x800, /* 3 */
0x10000, /* 4 */
0x200000, /* 5 */
0x4000000, /* 6 */
0x80000000, /* 7 */
};
static unsigned long
utf8_to_uv(const char *p, long *lenp)
{
int c = *p++ & 0xff;
unsigned long uv = c;
long n;
if (!(uv & 0x80)) {
*lenp = 1;
return uv;
}
if (!(uv & 0x40)) {
*lenp = 1;
rb_raise(rb_eArgError, "malformed UTF-8 character");
}
if (!(uv & 0x20)) { n = 2; uv &= 0x1f; }
else if (!(uv & 0x10)) { n = 3; uv &= 0x0f; }
else if (!(uv & 0x08)) { n = 4; uv &= 0x07; }
else if (!(uv & 0x04)) { n = 5; uv &= 0x03; }
else if (!(uv & 0x02)) { n = 6; uv &= 0x01; }
else {
*lenp = 1;
rb_raise(rb_eArgError, "malformed UTF-8 character");
}
if (n > *lenp) {
rb_raise(rb_eArgError, "malformed UTF-8 character (expected %ld bytes, given %ld bytes)",
n, *lenp);
}
*lenp = n--;
if (n != 0) {
while (n--) {
c = *p++ & 0xff;
if ((c & 0xc0) != 0x80) {
*lenp -= n + 1;
rb_raise(rb_eArgError, "malformed UTF-8 character");
}
else {
c &= 0x3f;
uv = uv << 6 | c;
}
}
}
n = *lenp - 1;
if (uv < utf8_limits[n]) {
rb_raise(rb_eArgError, "redundant UTF-8 sequence");
}
return uv;
}
void
Init_pack(void)
{
rb_define_method(rb_cArray, "pack", pack_pack, 1);
rb_define_method(rb_cString, "unpack", pack_unpack, 1);
}