D7net
Home
Console
Upload
information
Create File
Create Folder
About
Tools
:
/
proc
/
thread-self
/
root
/
proc
/
self
/
root
/
home
/
vblioqus
/
karachi777.vip
/
in
/
106014
/
900508
/
Filename :
ruby33.tar
back
Copy
include/ruby.h 0000644 00000002543 15152150470 0007325 0 ustar 00 #ifndef RUBY_H /*-*-C++-*-vi:se ft=cpp:*/ #define RUBY_H 1 /** * @author $Author$ * @date Sun 10 12:06:15 Jun JST 2007 * @copyright 2007-2008 Yukihiro Matsumoto * @copyright This file is a part of the programming language Ruby. * Permission is hereby granted, to either redistribute and/or * modify this file, provided that the conditions mentioned in the * file COPYING are met. Consult the file for details. */ #define HAVE_RUBY_ATOMIC_H 1 #define HAVE_RUBY_DEBUG_H 1 #define HAVE_RUBY_DEFINES_H 1 #define HAVE_RUBY_ENCODING_H 1 #define HAVE_RUBY_FIBER_SCHEDULER_H 1 #define HAVE_RUBY_INTERN_H 1 #define HAVE_RUBY_IO_H 1 #define HAVE_RUBY_MEMORY_VIEW_H 1 #define HAVE_RUBY_MISSING_H 1 #define HAVE_RUBY_ONIGMO_H 1 #define HAVE_RUBY_ONIGURUMA_H 1 #define HAVE_RUBY_RACTOR_H 1 #define HAVE_RUBY_RANDOM_H 1 #define HAVE_RUBY_RE_H 1 #define HAVE_RUBY_REGEX_H 1 #define HAVE_RUBY_RUBY_H 1 #define HAVE_RUBY_ST_H 1 #define HAVE_RUBY_THREAD_H 1 #define HAVE_RUBY_THREAD_NATIVE_H 1 #define HAVE_RUBY_UTIL_H 1 #define HAVE_RUBY_VERSION_H 1 #define HAVE_RUBY_VM_H 1 #ifdef _WIN32 #define HAVE_RUBY_WIN32_H 1 #endif #include "ruby/ruby.h" #endif /* RUBY_H */ include/ruby/ractor.h 0000644 00000021332 15152150470 0010614 0 ustar 00 #ifndef RUBY_RACTOR_H /*-*-C++-*-vi:se ft=cpp:*/ #define RUBY_RACTOR_H 1 /** * @file * @author Koichi Sasada * @date Tue Nov 17 16:39:15 2020 * @copyright Copyright (C) 2020 Yukihiro Matsumoto * @copyright This file is a part of the programming language Ruby. * Permission is hereby granted, to either redistribute and/or * modify this file, provided that the conditions mentioned in the * file COPYING are met. Consult the file for details. */ #include "internal/dllexport.h" /* RUBY_EXTERN is here */ #include "internal/fl_type.h" /* FL_TEST_RAW is here */ #include "internal/special_consts.h" /* RB_SPECIAL_CONSTS_P is here */ #include "internal/stdbool.h" /* bool is here */ #include "internal/value.h" /* VALUE is here */ /** Type that defines a ractor-local storage. */ struct rb_ractor_local_storage_type { /** * A function to mark a ractor-local storage. * * @param[out] ptr A ractor-local storage. * @post Ruby objects inside of `ptr` are marked. */ void (*mark)(void *ptr); /** * A function to destruct a ractor-local storage. * * @param[out] ptr A ractor-local storage. * @post `ptr` is not a valid pointer. */ void (*free)(void *ptr); // TODO: update }; /** (Opaque) struct that holds a ractor-local storage key. */ typedef struct rb_ractor_local_key_struct *rb_ractor_local_key_t; RBIMPL_SYMBOL_EXPORT_BEGIN() /** * `Ractor` class. * * @ingroup object */ RUBY_EXTERN VALUE rb_cRactor; /** * Queries the standard input of the current Ractor that is calling this * function. * * @return An IO. * @note This can be different from the process-global one. */ VALUE rb_ractor_stdin(void); /** * Queries the standard output of the current Ractor that is calling this * function. * * @return An IO. * @note This can be different from the process-global one. */ VALUE rb_ractor_stdout(void); /** * Queries the standard error of the current Ractor that is calling this * function. * * @return An IO. * @note This can be different from the process-global one. */ VALUE rb_ractor_stderr(void); /** * Assigns an IO to the standard input of the Ractor that is calling this * function. * * @param[in] io An IO. * @post `io` is the standard input of the current ractor. * @post In case the calling Ractor is the main Ractor, it also updates * the process global ::rb_stdin. */ void rb_ractor_stdin_set(VALUE io); /** * Assigns an IO to the standard output of the Ractor that is calling this * function. * * @param[in] io An IO. * @post `io` is the standard input of the current ractor. * @post In case the calling Ractor is the main Ractor, it also updates * the process global ::rb_stdout. */ void rb_ractor_stdout_set(VALUE io); /** * Assigns an IO to the standard error of the Ractor that is calling this * function. * * @param[in] io An IO. * @post `io` is the standard input of the current ractor. * @post In case the calling Ractor is the main Ractor, it also updates * the process global ::rb_stderr. */ void rb_ractor_stderr_set(VALUE io); /** * Issues a new key. * * @return A newly issued ractor-local storage key. Keys issued using this * key can be associated to a Ruby object per Ractor. */ rb_ractor_local_key_t rb_ractor_local_storage_value_newkey(void); /** * Queries the key. * * @param[in] key A ractor-local storage key to lookup. * @retval RUBY_Qnil No such key. * @retval otherwise A value corresponds to `key` in the current Ractor. * @note This cannot distinguish between a nonexistent key and a key * exists and corresponds to ::RUBY_Qnil. */ VALUE rb_ractor_local_storage_value(rb_ractor_local_key_t key); /** * Queries the key. * * @param[in] key A ractor-local storage key to lookup. * @param[out] val Return value buffer. * @retval false `key` not found. * @retval true `key` found. * @post `val` is updated so that it has the value corresponds to `key` * in the current Ractor. */ bool rb_ractor_local_storage_value_lookup(rb_ractor_local_key_t key, VALUE *val); /** * Associates the passed value to the passed key. * * @param[in] key A ractor-local storage key. * @param[in] val Arbitrary ruby object. * @post `val` corresponds to `key` in the current Ractor. */ void rb_ractor_local_storage_value_set(rb_ractor_local_key_t key, VALUE val); /** * A type of ractor-local storage that destructs itself using ::ruby_xfree. * * @internal * * Why it is visible from 3rd party extension libraries is not obvious to * @shyouhei. */ RUBY_EXTERN const struct rb_ractor_local_storage_type rb_ractor_local_storage_type_free; /** @alias{rb_ractor_local_storage_type_free} */ #define RB_RACTOR_LOCAL_STORAGE_TYPE_FREE (&rb_ractor_local_storage_type_free) /** * Extended version of rb_ractor_local_storage_value_newkey(). It additionally * takes the type of the issuing key. * * @param[in] type How the value associated with the issuing key should * behave. * @return A newly issued ractor-local storage key, of type `type`. */ rb_ractor_local_key_t rb_ractor_local_storage_ptr_newkey(const struct rb_ractor_local_storage_type *type); /** * Identical to rb_ractor_local_storage_value() except the return type. * * @param[in] key A ractor-local storage key to lookup. * @retval NULL No such key. * @retval otherwise A value corresponds to `key` in the current Ractor. */ void *rb_ractor_local_storage_ptr(rb_ractor_local_key_t key); /** * Identical to rb_ractor_local_storage_value_set() except the parameter type. * * @param[in] key A ractor-local storage key. * @param[in] ptr A pointer that conforms `key`'s type. * @post `ptr` corresponds to `key` in the current Ractor. */ void rb_ractor_local_storage_ptr_set(rb_ractor_local_key_t key, void *ptr); /** * Destructively transforms the passed object so that multiple Ractors can * share it. What is a shareable object and what is not is a nuanced concept, * and @ko1 says the definition can still change. However extension library * authors might interest to learn how to use #RUBY_TYPED_FROZEN_SHAREABLE. * * @param[out] obj Arbitrary ruby object to modify. * @exception rb_eRactorError Ractors cannot share `obj` by nature. * @return Passed `obj`. * @post Multiple Ractors can share `obj`. * * @internal * * In case an exception is raised, `obj` remains in an intermediate state where * some of its part is frozen and others are not. @shyouhei is not sure if it * is either an intended behaviour, current implementation limitation, or * simply a bug. Note also that there is no way to "melt" a frozen object. */ VALUE rb_ractor_make_shareable(VALUE obj); /** * Identical to rb_ractor_make_shareable(), except it returns a (deep) copy of * the passed one instead of modifying it in-place. * * @param[in] obj Arbitrary ruby object to duplicate. * @exception rb_eRactorError Ractors cannot share `obj` by nature. * @return A deep copy of `obj` which is sharable among Ractors. */ VALUE rb_ractor_make_shareable_copy(VALUE obj); RBIMPL_SYMBOL_EXPORT_END() /** * Queries if the passed object has previously classified as shareable or not. * This doesn't mean anything in practice... Objects can be shared later. * Always use rb_ractor_shareable_p() instead. * * @param[in] obj Object in question. * @retval RUBY_FL_SHAREABLE It once was shareable before. * @retval 0 Otherwise. */ #define RB_OBJ_SHAREABLE_P(obj) FL_TEST_RAW((obj), RUBY_FL_SHAREABLE) /** * Queries if multiple Ractors can share the passed object or not. Ractors run * without protecting each other. Sharing an object among them is basically * dangerous, disabled by default. However there are objects that are * extremely carefully implemented to be Ractor-safe; for instance integers * have such property. This function can classify that. * * @param[in] obj Arbitrary ruby object. * @retval true `obj` is capable of shared across ractors. * @retval false `obj` cannot travel across ractor boundaries. */ static inline bool rb_ractor_shareable_p(VALUE obj) { bool rb_ractor_shareable_p_continue(VALUE obj); if (RB_SPECIAL_CONST_P(obj)) { return true; } else if (RB_OBJ_SHAREABLE_P(obj)) { return true; } else { return rb_ractor_shareable_p_continue(obj); } } #endif /* RUBY_RACTOR_H */ include/ruby/util.h 0000644 00000021111 15152150470 0010272 0 ustar 00 #ifndef RUBY_UTIL_H /*-*-C++-*-vi:se ft=cpp:*/ #define RUBY_UTIL_H 1 /** * @file * @author $Author$ * @date Thu Mar 9 11:55:53 JST 1995 * @copyright Copyright (C) 1993-2007 Yukihiro Matsumoto * @copyright This file is a part of the programming language Ruby. * Permission is hereby granted, to either redistribute and/or * modify this file, provided that the conditions mentioned in the * file COPYING are met. Consult the file for details. * @warning DO NOT ADD RANDOM GARBAGES IN THIS FILE! Contents of this file * reside here for historical reasons. Find a right place for your * API! */ #include "ruby/internal/config.h" #ifdef STDC_HEADERS # include <stddef.h> /* size_t */ #endif #ifdef HAVE_SYS_TYPES_H # include <sys/types.h> /* ssize_t */ #endif #include "ruby/internal/attr/noalias.h" #include "ruby/internal/attr/nodiscard.h" #include "ruby/internal/attr/nonnull.h" #include "ruby/internal/attr/restrict.h" #include "ruby/internal/attr/returns_nonnull.h" #include "ruby/internal/dllexport.h" #include "ruby/defines.h" RBIMPL_SYMBOL_EXPORT_BEGIN() /** an approximation of ceil(n * log10(2)), up to 1,048,576 (1<<20) * without overflow within 32-bit calculation */ #define DECIMAL_SIZE_OF_BITS(n) (((n) * 3010 + 9998) / 9999) /** an approximation of decimal representation size for n-bytes */ #define DECIMAL_SIZE_OF_BYTES(n) DECIMAL_SIZE_OF_BITS((n) * CHAR_BIT) /** * An approximation of decimal representation size. `expr` may be a * type name */ #define DECIMAL_SIZE_OF(expr) DECIMAL_SIZE_OF_BYTES(sizeof(expr)) /** * Character to number mapping like `'a'` -> `10`, `'b'` -> `11` etc. For * punctuation etc., the value is -1. "36" terminology comes from the fact * that this is the table behind `str.to_i(36)`. */ RUBY_EXTERN const signed char ruby_digit36_to_number_table[]; /** * Characters that Ruby accepts as hexadecimal digits. This is `/\h/` expanded * into an array. */ RUBY_EXTERN const char ruby_hexdigits[]; /** * Scans the passed string, assuming the string is a textual representation of * an integer. Stops when encountering something non-digit for the passed * base. * * @note This does not understand minus sign. * @note This does not understand e.g. `0x` prefix. * @note It is a failure to pass `0` to `base`, unlike ruby_strtoul(). * @param[in] str Target string of digits to interpret. * @param[in] len Number of bytes of `str`, or -1 to detect `NUL`. * @param[in] base Base, `2` to `36` inclusive. * @param[out] retlen Return value buffer. * @param[out] overflow Return value buffer. * @return Interpreted numeric representation of `str`. * @post `retlen` is the number of bytes scanned so far. * @post `overflow` is set to true if the string represents something * bigger than `ULONG_MAX`. Something meaningful still returns; * which is the designed belabour of C's unsigned arithmetic. */ unsigned long ruby_scan_digits(const char *str, ssize_t len, int base, size_t *retlen, int *overflow); /** @old{ruby_scan_oct} */ #define scan_oct(s,l,e) ((int)ruby_scan_oct((s),(l),(e))) RBIMPL_ATTR_NOALIAS() RBIMPL_ATTR_NONNULL(()) /** * Interprets the passed string as an octal unsigned integer. Stops when * encounters something not understood. * * @param[in] str C string to scan. * @param[in] len Length of `str`. * @param[out] consumed Return value buffer. * @return Parsed integer. * @post `ret` is the number of characters read. * * @internal * * No consideration is made for integer overflows. As the return value is * unsigned this function has fully defined behaviour, but you cannot know if * there was an integer wrap-around or not. */ unsigned long ruby_scan_oct(const char *str, size_t len, size_t *consumed); /** @old{ruby_scan_hex} */ #define scan_hex(s,l,e) ((int)ruby_scan_hex((s),(l),(e))) RBIMPL_ATTR_NONNULL(()) /** * Interprets the passed string a hexadecimal unsigned integer. Stops when * encounters something not understood. * * @param[in] str C string to scan. * @param[in] len Length of `str`. * @param[out] ret Return value buffer. * @return Parsed integer. * @post `ret` is the number of characters read. * * @internal * * No consideration is made for integer overflows. As the return value is * unsigned this function has fully defined behaviour, but you cannot know if * there was an integer wrap-around or not. */ unsigned long ruby_scan_hex(const char *str, size_t len, size_t *ret); /** * Reentrant implementation of quick sort. If your system provides something * (like C11 qsort_s), this is a thin wrapper of that routine. Otherwise * resorts to our own version. */ #ifdef HAVE_GNU_QSORT_R # define ruby_qsort qsort_r #else void ruby_qsort(void *, const size_t, const size_t, int (*)(const void *, const void *, void *), void *); #endif RBIMPL_ATTR_NONNULL((1)) /** * Sets an environment variable. In case of POSIX this is a wrapper of * `setenv(3)`. But there are systems which lack one. We try hard emulating. * * @param[in] key An environment variable. * @param[in] val A value to be associated with `key`, or 0. * @exception rb_eSystemCallError `setenv(3)` failed for some reason. * @post Environment variable `key` is created if necessary. Its value * is updated to be `val`. */ void ruby_setenv(const char *key, const char *val); RBIMPL_ATTR_NONNULL(()) /** * Deletes the passed environment variable, if any. * * @param[in] key An environment variable. * @exception rb_eSystemCallError `unsetenv(3)` failed for some reason. * @post Environment variable `key` does not exist. */ void ruby_unsetenv(const char *key); RBIMPL_ATTR_NODISCARD() RBIMPL_ATTR_RESTRICT() RBIMPL_ATTR_RETURNS_NONNULL() RBIMPL_ATTR_NONNULL(()) /** * This is our own version of `strdup(3)` that uses ruby_xmalloc() instead of * system malloc (benefits our GC). * * @param[in] str Target C string to duplicate. * @return An allocated C string holding the identical contents. * @note Return value must be discarded using ruby_xfree(). */ char *ruby_strdup(const char *str); #undef strdup /** * @alias{ruby_strdup} * * @internal * * @shyouhei doesn't think it is a wise idea. ruby_strdup()'s return value * must be passed to ruby_xfree(), but this macro makes it almost impossible. */ #define strdup(s) ruby_strdup(s) RBIMPL_ATTR_NODISCARD() RBIMPL_ATTR_RESTRICT() RBIMPL_ATTR_RETURNS_NONNULL() /** * This is our own version of `getcwd(3)` that uses ruby_xmalloc() instead of * system malloc (benefits our GC). * * @return An allocated C string holding the process working directory. * @note Return value must be discarded using ruby_xfree(). */ char *ruby_getcwd(void); RBIMPL_ATTR_NONNULL((1)) /** * Our own locale-insensitive version of `strtod(3)`. The conversion is done * as if the current locale is set to the "C" locale, no matter actual runtime * locale settings. * * @param[in] str Decimal or hexadecimal representation of a floating * point number. * @param[out] endptr NULL, or an arbitrary pointer (overwritten on return). * @return Converted number. * @post If `endptr` is not NULL, it is updated to point the first such * byte where conversion failed. * @note This function sets `errno` on failure. * - `ERANGE`: Converted integer is out of range of `double`. * @see William D. Clinger, "How to Read Floating Point Numbers * Accurately" in Proc. ACM SIGPLAN '90, pp. 92-101. * https://doi.org/10.1145/93542.93557 */ double ruby_strtod(const char *str, char **endptr); #undef strtod /** @alias{ruby_strtod} */ #define strtod(s,e) ruby_strtod((s),(e)) RBIMPL_ATTR_NONNULL((2)) /** * Scans the passed string, with calling the callback function every time it * encounters a "word". A word here is a series of characters separated by * either a space (of IEEE 1003.1 section 7.3.1.1), or a `','`. * * @param[in] str Target string to split into each words. * @param[in] func Callback function. * @param[in,out] argv Passed as-is to `func`. */ void ruby_each_words(const char *str, void (*func)(const char *word, int len, void *argv), void *argv); RBIMPL_SYMBOL_EXPORT_END() #endif /* RUBY_UTIL_H */ include/ruby/re.h 0000644 00000015222 15152150470 0007731 0 ustar 00 #ifndef RUBY_RE_H /*-*-C++-*-vi:se ft=cpp:*/ #define RUBY_RE_H 1 /** * @file * @author $Author$ * @date Thu Sep 30 14:18:32 JST 1993 * @copyright Copyright (C) 1993-2007 Yukihiro Matsumoto * @copyright This file is a part of the programming language Ruby. * Permission is hereby granted, to either redistribute and/or * modify this file, provided that the conditions mentioned in the * file COPYING are met. Consult the file for details. */ #include "ruby/internal/config.h" #ifdef HAVE_SYS_TYPES_H # include <sys/types.h> #endif #include <stdio.h> #include "ruby/onigmo.h" #include "ruby/regex.h" #include "ruby/internal/core/rmatch.h" #include "ruby/internal/dllexport.h" struct re_registers; /* Defined in onigmo.h */ RBIMPL_SYMBOL_EXPORT_BEGIN() /** * Creates a new instance of ::rb_cRegexp. It can be seen as a specialised * version of rb_reg_new_str() where it does not take options. * * @param[in] str Source code in String. * @return Allocated new instance of ::rb_cRegexp. */ VALUE rb_reg_regcomp(VALUE str); /** * Runs the passed regular expression over the passed string. Unlike * rb_reg_search() this function also takes position and direction of the * search, which make it possible for this function to run from in middle of * the string. * * @param[in] re Regular expression to execute. * @param[in] str Target string to search. * @param[in] pos Offset in `str` to start searching, in bytes. * @param[in] dir `pos`' direction; 0 means left-to-right, 1 for * the opposite. * @exception rb_eArgError `re` is broken. * @exception rb_eRegexpError `re` is malformed. * @retval -1 Match failed. * @retval otherwise Offset of first such byte where match happened. * @post `Regexp.last_match` is updated. * @post `$&`, `$~`, etc., are updated. * * @internal * * Distinction between raising ::rb_eArgError and ::rb_eRegexpError is not * obvious, at least to @shyouhei. */ long rb_reg_search(VALUE re, VALUE str, long pos, int dir); /** * Substitution. This is basically the implementation of `String#sub`. Also * `String#gsub` repeatedly calls this function. * * @param[in] repl Replacement string, e.g. `"\\1\\2"` * @param[in] src Source string, to be replaced. * @param[in] regs Matched data generated by applying `rexp` to `src`. * @param[in] rexp Regular expression. * @return A substituted string. * * @internal * * This function does not check for encoding compatibility. `String#sub!` * etc. employ their own checker. * * `regs` should have been `const struct re_registers *` because it is read * only. Kept as-is for compatibility. */ VALUE rb_reg_regsub(VALUE repl, VALUE src, struct re_registers *regs, VALUE rexp); /** * Tell us if this is a wrong idea, but it seems this function has no usage at * all. Just remains here for theoretical backwards compatibility. * * @param[in] re Regular expression to execute. * @param[in] str Target string to search. * @param[in] pos Offset in `str` to start searching, in bytes. * @param[in] dir `pos`' direction; 0 means left-to-right, 1 for * the opposite. * @return Adjusted nearest offset to `pos` inside of `str`, where is a * character boundary. * */ long rb_reg_adjust_startpos(VALUE re, VALUE str, long pos, int dir); /** * Escapes any characters that would have special meaning in a regular * expression. * * @param[in] str Target string to escape. * @return A copy of `str` whose contents are escaped. */ VALUE rb_reg_quote(VALUE str); /** * Exercises various checks and preprocesses so that the given regular * expression can be applied to the given string. The preprocess here includes * (but not limited to) for instance encoding conversion. * * @param[in] re Target regular expression. * @param[in] str What `re` is about to run on. * @exception rb_eArgError `re` does not fit for `str`. * @exception rb_eEncCompatError `re` and `str` are incompatible. * @exception rb_eRegexpError `re` is malformed. * @return A preprocessesed pattern buffer ready to be applied to `str`. * @note The return value is manages by our GC. Don't free. * * @internal * * The return type, `regex_t *`, is defined in `<ruby/onigmo.h>`, _and_ * _conflicts_ with POSIX's `<regex.h>`. We can no longer save the situation * at this point. Just don't mix the two. */ regex_t *rb_reg_prepare_re(VALUE re, VALUE str); /** * Runs a regular expression match using function `match`. Performs preparation, * error handling, and memory cleanup. * * @param[in] re Target regular expression. * @param[in] str What `re` is about to run on. * @param[in] match The function to run to match `str` against `re`. * @param[in] args Pointer to arguments to pass into `match`. * @param[out] regs Registers on a successful match. * @exception rb_eArgError `re` does not fit for `str`. * @exception rb_eEncCompatError `re` and `str` are incompatible. * @exception rb_eRegexpError `re` is malformed. * @return Match position on a successful match, `ONIG_MISMATCH` otherwise. * * @internal * * The type `regex_t *` is defined in `<ruby/onigmo.h>`, _and_ * _conflicts_ with POSIX's `<regex.h>`. We can no longer save the situation * at this point. Just don't mix the two. */ OnigPosition rb_reg_onig_match(VALUE re, VALUE str, OnigPosition (*match)(regex_t *reg, VALUE str, struct re_registers *regs, void *args), void *args, struct re_registers *regs); /** * Duplicates a match data. This is roughly the same as `onig_region_copy()`, * except it tries to GC when there is not enough memory. * * @param[out] dst Target registers to fill. * @param[in] src Source registers to duplicate. * @exception rb_eNoMemError Not enough memory. * @retval 0 Successful * @retval ONIGERR_MEMORY Not enough memory, even after GC (unlikely). * @post `dst` has identical contents to `src`. * * @internal * * It seems this function is here for `ext/strscan` and nothing else. */ int rb_reg_region_copy(struct re_registers *dst, const struct re_registers *src); RBIMPL_SYMBOL_EXPORT_END() #endif /* RUBY_RE_H */ include/ruby/thread.h 0000644 00000026430 15152150470 0010575 0 ustar 00 #ifndef RUBY_THREAD_H /*-*-C++-*-vi:se ft=cpp:*/ #define RUBY_THREAD_H 1 /** * @file * @author $Author: matz $ * @date Tue Jul 10 17:35:43 JST 2012 * @copyright Copyright (C) 2007 Yukihiro Matsumoto * @copyright This file is a part of the programming language Ruby. * Permission is hereby granted, to either redistribute and/or * modify this file, provided that the conditions mentioned in the * file COPYING are met. Consult the file for details. */ #include "ruby/internal/attr/nonnull.h" #include "ruby/internal/intern/thread.h" /* rb_unblock_function_t */ #include "ruby/internal/dllexport.h" /** * @name Flags for rb_nogvl() * * @{ */ /** * Passing this flag to rb_nogvl() prevents it from checking interrupts. * Interrupts can impact your program negatively. For instance consider * following callback function: * * ```CXX * static inline int fd; // set elsewhere. * static inline auto callback(auto buf) { * auto tmp = ruby_xmalloc(BUFSIZ); * auto ret = ruby_xmalloc(sizeof(ssize_t)); // (a) * auto n = read(fd, tmp, BUFSIZ); // (b) * memcpy(buf, tmp, n); // (c) * memcpy(ret, n, sizeof(n)); * ruby_xfree(tmp); * return ret; * } * ``` * * Here, if it gets interrupted at (a) or (b), `read(2)` is cancelled and this * function leaks memory (which is not a good thing of course, but...). But if * it gets interrupted at (c), where `read(2)` is already done, interruption is * way more catastrophic because what was read gets lost. To reroute this kind * of problem you should set this flag. And check interrupts elsewhere at your * own risk. */ #define RB_NOGVL_INTR_FAIL (0x1) /** * Passing this flag to rb_nogvl() indicates that the passed UBF is * async-signal-safe. An UBF could be async safe, and that makes things * simpler. However async unsafe UBFs are just okay. If unsure, you can * safely leave it unspecified. * * @internal * * This makes sense only in case of POSIX threads. */ #define RB_NOGVL_UBF_ASYNC_SAFE (0x2) /** @} */ RBIMPL_SYMBOL_EXPORT_BEGIN() RBIMPL_ATTR_NONNULL((1)) /** * (Re-)acquires the GVL. This manoeuvre makes it possible for an out-of-GVL * routine to one-shot call a ruby method. * * What this function does: * * 1. Blocks until it acquires the GVL. * 2. Calls the passed function. * 3. Releases the GVL. * 4. Returns what was returned form the passed function. * * @param[in] func What to call with GVL. * @param[in,out] data1 Passed as-is to `func`. * @return What was returned from `func`. * @warning `func` must not return a Ruby object. If it did such return * value would escape from GC's scope; would not be marked. * @warning Global escapes from this function just yield whatever fatal * undefined behaviours. You must make sure that `func` does * not raise, by properly rescuing everything using * e.g. rb_protect(). * @warning You cannot convert a non-Ruby thread into a Ruby thread * using this API. This function makes sense only from inside * of a rb_thread_call_without_gvl()'s callback. */ void *rb_thread_call_with_gvl(void *(*func)(void *), void *data1); RBIMPL_ATTR_NONNULL((1)) /** * Allows the passed function to run in parallel with other Ruby threads. * * What this function does: * * 1. Checks (and handles) pending interrupts. * 2. Releases the GVL. (Others can run here in parallel...) * 3. Calls the passed function. * 4. Blocks until it re-acquires the GVL. * 5. Checks interrupts that happened between 2 to 4. * * In case other threads interfaced with this thread using rb_thread_kill() * etc., the passed UBF is additionally called. See ::rb_unblock_function_t * for details. * * Unlike rb_thread_call_without_gvl2() this function also reacts to signals * etc. * * @param[in] func A function to call without GVL. * @param[in,out] data1 Passed as-is to `func`. * @param[in] ubf An UBF to cancel `func`. * @param[in,out] data2 Passed as-is to `ubf`. * @return What `func` returned, or 0 in case `ubf` cancelled `func`. * @warning You cannot use most of Ruby C APIs like calling methods or * raising exceptions from any of the functions passed to it. * If that is dead necessary use rb_thread_call_with_gvl() to * re-acquire the GVL. * @warning In short, this API is difficult. @ko1 recommends you to use * other ways if any. We lack experiences to use this API. If * you find any corner cases etc., please report it to the * devs. * @warning Releasing and re-acquiring the GVL are expensive operations. * For a short-running `func`, it might be faster to just call * `func` with blocking everything else. Be sure to benchmark * your code to see if it is actually worth releasing the GVL. */ void *rb_thread_call_without_gvl(void *(*func)(void *), void *data1, rb_unblock_function_t *ubf, void *data2); RBIMPL_ATTR_NONNULL((1)) /** * Identical to rb_thread_call_without_gvl(), except it does not interface with * signals etc. As described in #RB_NOGVL_INTR_FAIL, interrupts can hurt you. * In case this function detects an interrupt, it returns immediately. You can * record progress of your callback and check it after returning from this * function. * * What this function does: * * 1. Checks for pending interrupts and if any, just returns. * 2. Releases the GVL. (Others can run here in parallel...) * 3. Calls the passed function. * 4. Blocks until it re-acquires the GVL. * * @param[in] func A function to call without GVL. * @param[in,out] data1 Passed as-is to `func`. * @param[in] ubf An UBF to cancel `func`. * @param[in,out] data2 Passed as-is to `ubf`. * @return What `func` returned, or 0 in case `func` did not return. */ void *rb_thread_call_without_gvl2(void *(*func)(void *), void *data1, rb_unblock_function_t *ubf, void *data2); /* * XXX: unstable/unapproved - out-of-tree code should NOT not depend * on this until it hits Ruby 2.6.1 */ RBIMPL_ATTR_NONNULL((1)) /** * Identical to rb_thread_call_without_gvl(), except it additionally takes * "flags" that change the behaviour. * * @param[in] func A function to call without GVL. * @param[in,out] data1 Passed as-is to `func`. * @param[in] ubf An UBF to cancel `func`. * @param[in,out] data2 Passed as-is to `ubf`. * @param[in] flags Flags. * @return What `func` returned, or 0 in case `func` did not return. */ void *rb_nogvl(void *(*func)(void *), void *data1, rb_unblock_function_t *ubf, void *data2, int flags); /** * @private * * @deprecated This macro once was a thing in the old days, but makes no sense * any longer today. Exists here for backwards compatibility * only. You can safely forget about it. */ #define RUBY_CALL_WO_GVL_FLAG_SKIP_CHECK_INTS_AFTER 0x01 /** * @private * @deprecated It seems even in the old days it made no sense...? */ #define RUBY_CALL_WO_GVL_FLAG_SKIP_CHECK_INTS_ /** * Triggered when a new thread is started. * * @note The callback will be called *without* the GVL held. */ #define RUBY_INTERNAL_THREAD_EVENT_STARTED 1 << 0 /** * Triggered when a thread attempt to acquire the GVL. * * @note The callback will be called *without* the GVL held. */ #define RUBY_INTERNAL_THREAD_EVENT_READY 1 << 1 /** acquiring GVL */ /** * Triggered when a thread successfully acquired the GVL. * * @note The callback will be called *with* the GVL held. */ #define RUBY_INTERNAL_THREAD_EVENT_RESUMED 1 << 2 /** acquired GVL */ /** * Triggered when a thread released the GVL. * * @note The callback will be called *without* the GVL held. */ #define RUBY_INTERNAL_THREAD_EVENT_SUSPENDED 1 << 3 /** released GVL */ /** * Triggered when a thread exits. * * @note The callback will be called *without* the GVL held. */ #define RUBY_INTERNAL_THREAD_EVENT_EXITED 1 << 4 /** thread terminated */ #define RUBY_INTERNAL_THREAD_EVENT_MASK 0xff /** All Thread events */ typedef struct rb_internal_thread_event_data { VALUE thread; } rb_internal_thread_event_data_t; typedef void (*rb_internal_thread_event_callback)(rb_event_flag_t event, const rb_internal_thread_event_data_t *event_data, void *user_data); typedef struct rb_internal_thread_event_hook rb_internal_thread_event_hook_t; /** * Registers a thread event hook function. * * @param[in] func A callback. * @param[in] events A set of events that `func` should run. * @param[in] data Passed as-is to `func`. * @return An opaque pointer to the hook, to unregister it later. * @note This functionality is a noop on Windows and WebAssembly. * @note The callback will be called without the GVL held, except for the * RESUMED event. * @note Callbacks are not guaranteed to be executed on the native threads * that corresponds to the Ruby thread. To identify which Ruby thread * the event refers to, you must use `event_data->thread`. * @warning This function MUST not be called from a thread event callback. */ rb_internal_thread_event_hook_t *rb_internal_thread_add_event_hook( rb_internal_thread_event_callback func, rb_event_flag_t events, void *data); /** * Unregister the passed hook. * * @param[in] hook. The hook to unregister. * @return Whether the hook was found and unregistered. * @note This functionality is a noop on Windows and WebAssembly. * @warning This function MUST not be called from a thread event callback. */ bool rb_internal_thread_remove_event_hook( rb_internal_thread_event_hook_t * hook); typedef int rb_internal_thread_specific_key_t; #define RB_INTERNAL_THREAD_SPECIFIC_KEY_MAX 8 /** * Create a key to store thread specific data. * * These APIs are designed for tools using * rb_internal_thread_event_hook APIs. * * Note that only `RB_INTERNAL_THREAD_SPECIFIC_KEY_MAX` keys * can be created. raises `ThreadError` if exceeded. * * Usage: * // at initialize time: * int tool_key; // gvar * Init_tool() { * tool_key = rb_internal_thread_specific_key_create(); * } * * // at any timing: * rb_internal_thread_specific_set(thread, tool_key, per_thread_data); * ... * per_thread_data = rb_internal_thread_specific_get(thread, tool_key); */ rb_internal_thread_specific_key_t rb_internal_thread_specific_key_create(void); /** * Get thread and tool specific data. * * This function is async signal safe and thread safe. */ void *rb_internal_thread_specific_get(VALUE thread_val, rb_internal_thread_specific_key_t key); /** * Set thread and tool specific data. * * This function is async signal safe and thread safe. */ void rb_internal_thread_specific_set(VALUE thread_val, rb_internal_thread_specific_key_t key, void *data); RBIMPL_SYMBOL_EXPORT_END() #endif /* RUBY_THREAD_H */ include/ruby/vm.h 0000644 00000004126 15152150470 0007746 0 ustar 00 #ifndef RUBY_VM_H /*-*-C++-*-vi:se ft=cpp:*/ #define RUBY_VM_H 1 /** * @file * @author $Author$ * @date Sat May 31 15:17:36 2008 * @copyright Copyright (C) 2008 Yukihiro Matsumoto * @copyright This file is a part of the programming language Ruby. * Permission is hereby granted, to either redistribute and/or * modify this file, provided that the conditions mentioned in the * file COPYING are met. Consult the file for details. * * We planned to have multiple VMs run side-by-side. The API here was a * preparation of that feature. The topic branch was eventually abandoned, and * we now have Ractor. This file is kind of obsolescent. */ #include "ruby/internal/dllexport.h" RBIMPL_SYMBOL_EXPORT_BEGIN() /** * The opaque struct to hold VM internals. Its fields are intentionally hidden * from extension libraries because it changes drastically time to time. */ typedef struct rb_vm_struct ruby_vm_t; /** * Destructs the passed VM. You don't have to call this API directly now, * because there is no way to create one. There is only one VM at one time. * ruby_stop() should just suffice. */ int ruby_vm_destruct(ruby_vm_t *vm); /** * ruby_vm_at_exit registers a function _func_ to be invoked when a VM * passed away. Functions registered this way runs in reverse order * of registration, just like END {} block does. The difference is * its timing to be triggered. ruby_vm_at_exit functions runs when a * VM _passed_ _away_, while END {} blocks runs just _before_ a VM * _is_ _passing_ _away_. * * You cannot register a function to another VM than where you are in. * So where to register is intuitive, omitted. OTOH the argument * _func_ cannot know which VM it is in because at the time of * invocation, the VM has already died and there is no execution * context. The VM itself is passed as the first argument to it. * * @param[in] func the function to register. */ void ruby_vm_at_exit(void(*func)(ruby_vm_t *)); RBIMPL_SYMBOL_EXPORT_END() #endif /* RUBY_VM_H */ include/ruby/oniguruma.h 0000644 00000000406 15152150470 0011327 0 ustar 00 #ifndef ONIGURUMA_H #define ONIGURUMA_H #include "onigmo.h" #define ONIGURUMA #define ONIGURUMA_VERSION_MAJOR ONIGMO_VERSION_MAJOR #define ONIGURUMA_VERSION_MINOR ONIGMO_VERSION_MINOR #define ONIGURUMA_VERSION_TEENY ONIGMO_VERSION_TEENY #endif /* ONIGURUMA_H */ include/ruby/onigmo.h 0000644 00000127627 15152150470 0010630 0 ustar 00 #ifndef ONIGMO_H #define ONIGMO_H /********************************************************************** onigmo.h - Onigmo (Oniguruma-mod) (regular expression library) **********************************************************************/ /*- * Copyright (c) 2002-2009 K.Kosako <sndgk393 AT ybb DOT ne DOT jp> * Copyright (c) 2011-2017 K.Takata <kentkt AT csc DOT jp> * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ #ifdef __cplusplus extern "C" { # if 0 } /* satisfy cc-mode */ # endif #endif #define ONIGMO_VERSION_MAJOR 6 #define ONIGMO_VERSION_MINOR 1 #define ONIGMO_VERSION_TEENY 3 #ifndef ONIG_EXTERN # ifdef RUBY_EXTERN # define ONIG_EXTERN RUBY_EXTERN # else # if defined(_WIN32) && !defined(__GNUC__) # if defined(EXPORT) || defined(RUBY_EXPORT) # define ONIG_EXTERN extern __declspec(dllexport) # else # define ONIG_EXTERN extern __declspec(dllimport) # endif # endif # endif #endif #ifndef ONIG_EXTERN # define ONIG_EXTERN extern #endif #ifndef RUBY # ifndef RUBY_SYMBOL_EXPORT_BEGIN # define RUBY_SYMBOL_EXPORT_BEGIN # define RUBY_SYMBOL_EXPORT_END # endif #endif RUBY_SYMBOL_EXPORT_BEGIN #include <stddef.h> /* for size_t */ /* PART: character encoding */ #ifndef ONIG_ESCAPE_UCHAR_COLLISION # define UChar OnigUChar #endif typedef unsigned char OnigUChar; typedef unsigned int OnigCodePoint; typedef unsigned int OnigCtype; typedef size_t OnigDistance; typedef ptrdiff_t OnigPosition; #define ONIG_INFINITE_DISTANCE ~((OnigDistance )0) /* * Onig casefold/case mapping flags and related definitions * * Subfields (starting with 0 at LSB): * 0-2: Code point count in casefold.h * 3-12: Index into SpecialCaseMapping array in casefold.h * 13-22: Case folding/mapping flags */ typedef unsigned int OnigCaseFoldType; /* case fold flag */ ONIG_EXTERN OnigCaseFoldType OnigDefaultCaseFoldFlag; /* bits for actual code point count; 3 bits is more than enough, currently only 2 used */ #define OnigCodePointMaskWidth 3 #define OnigCodePointMask ((1<<OnigCodePointMaskWidth)-1) #define OnigCodePointCount(n) ((n)&OnigCodePointMask) #define OnigCaseFoldFlags(n) ((n)&~OnigCodePointMask) /* #define ONIGENC_CASE_FOLD_HIRAGANA_KATAKANA (1<<1) */ /* no longer usable with these values! */ /* #define ONIGENC_CASE_FOLD_KATAKANA_WIDTH (1<<2) */ /* no longer usable with these values! */ /* bits for index into table with separate titlecase mappings */ /* 10 bits provide 1024 values */ #define OnigSpecialIndexShift 3 #define OnigSpecialIndexWidth 10 #define ONIGENC_CASE_UPCASE (1<<13) /* has/needs uppercase mapping */ #define ONIGENC_CASE_DOWNCASE (1<<14) /* has/needs lowercase mapping */ #define ONIGENC_CASE_TITLECASE (1<<15) /* has/needs (special) titlecase mapping */ #define ONIGENC_CASE_SPECIAL_OFFSET 3 /* offset in bits from ONIGENC_CASE to ONIGENC_CASE_SPECIAL */ #define ONIGENC_CASE_UP_SPECIAL (1<<16) /* has special upcase mapping */ #define ONIGENC_CASE_DOWN_SPECIAL (1<<17) /* has special downcase mapping */ #define ONIGENC_CASE_MODIFIED (1<<18) /* data has been modified */ #define ONIGENC_CASE_FOLD (1<<19) /* has/needs case folding */ #define ONIGENC_CASE_FOLD_TURKISH_AZERI (1<<20) /* needs mapping specific to Turkic languages; better not change original value! */ #define ONIGENC_CASE_FOLD_LITHUANIAN (1<<21) /* needs Lithuanian-specific mapping */ #define ONIGENC_CASE_ASCII_ONLY (1<<22) /* only modify ASCII range */ #define ONIGENC_CASE_IS_TITLECASE (1<<23) /* character itself is already titlecase */ #define INTERNAL_ONIGENC_CASE_FOLD_MULTI_CHAR (1<<30) /* better not change original value! */ #define ONIGENC_CASE_FOLD_MIN INTERNAL_ONIGENC_CASE_FOLD_MULTI_CHAR #define ONIGENC_CASE_FOLD_DEFAULT OnigDefaultCaseFoldFlag #define ONIGENC_MAX_COMP_CASE_FOLD_CODE_LEN 3 #define ONIGENC_GET_CASE_FOLD_CODES_MAX_NUM 13 /* 13 => Unicode:0x1ffc */ /* code range */ #define ONIGENC_CODE_RANGE_NUM(range) ((int )range[0]) #define ONIGENC_CODE_RANGE_FROM(range,i) range[((i)*2) + 1] #define ONIGENC_CODE_RANGE_TO(range,i) range[((i)*2) + 2] typedef struct { int byte_len; /* argument(original) character(s) byte length */ int code_len; /* number of code */ OnigCodePoint code[ONIGENC_MAX_COMP_CASE_FOLD_CODE_LEN]; } OnigCaseFoldCodeItem; typedef struct { OnigCodePoint esc; OnigCodePoint anychar; OnigCodePoint anytime; OnigCodePoint zero_or_one_time; OnigCodePoint one_or_more_time; OnigCodePoint anychar_anytime; } OnigMetaCharTableType; typedef int (*OnigApplyAllCaseFoldFunc)(OnigCodePoint from, OnigCodePoint* to, int to_len, void* arg); typedef struct OnigEncodingTypeST { int (*precise_mbc_enc_len)(const OnigUChar* p,const OnigUChar* e, const struct OnigEncodingTypeST* enc); const char* name; int max_enc_len; int min_enc_len; int (*is_mbc_newline)(const OnigUChar* p, const OnigUChar* end, const struct OnigEncodingTypeST* enc); OnigCodePoint (*mbc_to_code)(const OnigUChar* p, const OnigUChar* end, const struct OnigEncodingTypeST* enc); int (*code_to_mbclen)(OnigCodePoint code, const struct OnigEncodingTypeST* enc); int (*code_to_mbc)(OnigCodePoint code, OnigUChar *buf, const struct OnigEncodingTypeST* enc); int (*mbc_case_fold)(OnigCaseFoldType flag, const OnigUChar** pp, const OnigUChar* end, OnigUChar* to, const struct OnigEncodingTypeST* enc); int (*apply_all_case_fold)(OnigCaseFoldType flag, OnigApplyAllCaseFoldFunc f, void* arg, const struct OnigEncodingTypeST* enc); int (*get_case_fold_codes_by_str)(OnigCaseFoldType flag, const OnigUChar* p, const OnigUChar* end, OnigCaseFoldCodeItem acs[], const struct OnigEncodingTypeST* enc); int (*property_name_to_ctype)(const struct OnigEncodingTypeST* enc, const OnigUChar* p, const OnigUChar* end); int (*is_code_ctype)(OnigCodePoint code, OnigCtype ctype, const struct OnigEncodingTypeST* enc); int (*get_ctype_code_range)(OnigCtype ctype, OnigCodePoint* sb_out, const OnigCodePoint* ranges[], const struct OnigEncodingTypeST* enc); OnigUChar* (*left_adjust_char_head)(const OnigUChar* start, const OnigUChar* p, const OnigUChar* end, const struct OnigEncodingTypeST* enc); int (*is_allowed_reverse_match)(const OnigUChar* p, const OnigUChar* end, const struct OnigEncodingTypeST* enc); int (*case_map)(OnigCaseFoldType* flagP, const OnigUChar** pp, const OnigUChar* end, OnigUChar* to, OnigUChar* to_end, const struct OnigEncodingTypeST* enc); int ruby_encoding_index; unsigned int flags; } OnigEncodingType; typedef const OnigEncodingType* OnigEncoding; ONIG_EXTERN const OnigEncodingType OnigEncodingASCII; #ifndef RUBY ONIG_EXTERN const OnigEncodingType OnigEncodingISO_8859_1; ONIG_EXTERN const OnigEncodingType OnigEncodingISO_8859_2; ONIG_EXTERN const OnigEncodingType OnigEncodingISO_8859_3; ONIG_EXTERN const OnigEncodingType OnigEncodingISO_8859_4; ONIG_EXTERN const OnigEncodingType OnigEncodingISO_8859_5; ONIG_EXTERN const OnigEncodingType OnigEncodingISO_8859_6; ONIG_EXTERN const OnigEncodingType OnigEncodingISO_8859_7; ONIG_EXTERN const OnigEncodingType OnigEncodingISO_8859_8; ONIG_EXTERN const OnigEncodingType OnigEncodingISO_8859_9; ONIG_EXTERN const OnigEncodingType OnigEncodingISO_8859_10; ONIG_EXTERN const OnigEncodingType OnigEncodingISO_8859_11; ONIG_EXTERN const OnigEncodingType OnigEncodingISO_8859_13; ONIG_EXTERN const OnigEncodingType OnigEncodingISO_8859_14; ONIG_EXTERN const OnigEncodingType OnigEncodingISO_8859_15; ONIG_EXTERN const OnigEncodingType OnigEncodingISO_8859_16; ONIG_EXTERN const OnigEncodingType OnigEncodingUTF_8; ONIG_EXTERN const OnigEncodingType OnigEncodingUTF_16BE; ONIG_EXTERN const OnigEncodingType OnigEncodingUTF_16LE; ONIG_EXTERN const OnigEncodingType OnigEncodingUTF_32BE; ONIG_EXTERN const OnigEncodingType OnigEncodingUTF_32LE; ONIG_EXTERN const OnigEncodingType OnigEncodingEUC_JP; ONIG_EXTERN const OnigEncodingType OnigEncodingEUC_TW; ONIG_EXTERN const OnigEncodingType OnigEncodingEUC_KR; ONIG_EXTERN const OnigEncodingType OnigEncodingEUC_CN; ONIG_EXTERN const OnigEncodingType OnigEncodingShift_JIS; ONIG_EXTERN const OnigEncodingType OnigEncodingWindows_31J; /* ONIG_EXTERN const OnigEncodingType OnigEncodingKOI8; */ ONIG_EXTERN const OnigEncodingType OnigEncodingKOI8_R; ONIG_EXTERN const OnigEncodingType OnigEncodingKOI8_U; ONIG_EXTERN const OnigEncodingType OnigEncodingWindows_1250; ONIG_EXTERN const OnigEncodingType OnigEncodingWindows_1251; ONIG_EXTERN const OnigEncodingType OnigEncodingWindows_1252; ONIG_EXTERN const OnigEncodingType OnigEncodingWindows_1253; ONIG_EXTERN const OnigEncodingType OnigEncodingWindows_1254; ONIG_EXTERN const OnigEncodingType OnigEncodingWindows_1257; ONIG_EXTERN const OnigEncodingType OnigEncodingBIG5; ONIG_EXTERN const OnigEncodingType OnigEncodingGB18030; #endif /* RUBY */ #define ONIG_ENCODING_ASCII (&OnigEncodingASCII) #ifndef RUBY # define ONIG_ENCODING_ISO_8859_1 (&OnigEncodingISO_8859_1) # define ONIG_ENCODING_ISO_8859_2 (&OnigEncodingISO_8859_2) # define ONIG_ENCODING_ISO_8859_3 (&OnigEncodingISO_8859_3) # define ONIG_ENCODING_ISO_8859_4 (&OnigEncodingISO_8859_4) # define ONIG_ENCODING_ISO_8859_5 (&OnigEncodingISO_8859_5) # define ONIG_ENCODING_ISO_8859_6 (&OnigEncodingISO_8859_6) # define ONIG_ENCODING_ISO_8859_7 (&OnigEncodingISO_8859_7) # define ONIG_ENCODING_ISO_8859_8 (&OnigEncodingISO_8859_8) # define ONIG_ENCODING_ISO_8859_9 (&OnigEncodingISO_8859_9) # define ONIG_ENCODING_ISO_8859_10 (&OnigEncodingISO_8859_10) # define ONIG_ENCODING_ISO_8859_11 (&OnigEncodingISO_8859_11) # define ONIG_ENCODING_ISO_8859_13 (&OnigEncodingISO_8859_13) # define ONIG_ENCODING_ISO_8859_14 (&OnigEncodingISO_8859_14) # define ONIG_ENCODING_ISO_8859_15 (&OnigEncodingISO_8859_15) # define ONIG_ENCODING_ISO_8859_16 (&OnigEncodingISO_8859_16) # define ONIG_ENCODING_UTF_8 (&OnigEncodingUTF_8) # define ONIG_ENCODING_UTF_16BE (&OnigEncodingUTF_16BE) # define ONIG_ENCODING_UTF_16LE (&OnigEncodingUTF_16LE) # define ONIG_ENCODING_UTF_32BE (&OnigEncodingUTF_32BE) # define ONIG_ENCODING_UTF_32LE (&OnigEncodingUTF_32LE) # define ONIG_ENCODING_EUC_JP (&OnigEncodingEUC_JP) # define ONIG_ENCODING_EUC_TW (&OnigEncodingEUC_TW) # define ONIG_ENCODING_EUC_KR (&OnigEncodingEUC_KR) # define ONIG_ENCODING_EUC_CN (&OnigEncodingEUC_CN) # define ONIG_ENCODING_SHIFT_JIS (&OnigEncodingShift_JIS) # define ONIG_ENCODING_WINDOWS_31J (&OnigEncodingWindows_31J) /* # define ONIG_ENCODING_KOI8 (&OnigEncodingKOI8) */ # define ONIG_ENCODING_KOI8_R (&OnigEncodingKOI8_R) # define ONIG_ENCODING_KOI8_U (&OnigEncodingKOI8_U) # define ONIG_ENCODING_WINDOWS_1250 (&OnigEncodingWindows_1250) # define ONIG_ENCODING_WINDOWS_1251 (&OnigEncodingWindows_1251) # define ONIG_ENCODING_WINDOWS_1252 (&OnigEncodingWindows_1252) # define ONIG_ENCODING_WINDOWS_1253 (&OnigEncodingWindows_1253) # define ONIG_ENCODING_WINDOWS_1254 (&OnigEncodingWindows_1254) # define ONIG_ENCODING_WINDOWS_1257 (&OnigEncodingWindows_1257) # define ONIG_ENCODING_BIG5 (&OnigEncodingBIG5) # define ONIG_ENCODING_GB18030 (&OnigEncodingGB18030) /* old names */ # define ONIG_ENCODING_SJIS ONIG_ENCODING_SHIFT_JIS # define ONIG_ENCODING_CP932 ONIG_ENCODING_WINDOWS_31J # define ONIG_ENCODING_CP1250 ONIG_ENCODING_WINDOWS_1250 # define ONIG_ENCODING_CP1251 ONIG_ENCODING_WINDOWS_1251 # define ONIG_ENCODING_CP1252 ONIG_ENCODING_WINDOWS_1252 # define ONIG_ENCODING_CP1253 ONIG_ENCODING_WINDOWS_1253 # define ONIG_ENCODING_CP1254 ONIG_ENCODING_WINDOWS_1254 # define ONIG_ENCODING_CP1257 ONIG_ENCODING_WINDOWS_1257 # define ONIG_ENCODING_UTF8 ONIG_ENCODING_UTF_8 # define ONIG_ENCODING_UTF16_BE ONIG_ENCODING_UTF_16BE # define ONIG_ENCODING_UTF16_LE ONIG_ENCODING_UTF_16LE # define ONIG_ENCODING_UTF32_BE ONIG_ENCODING_UTF_32BE # define ONIG_ENCODING_UTF32_LE ONIG_ENCODING_UTF_32LE #endif /* RUBY */ #define ONIG_ENCODING_UNDEF ((OnigEncoding )0) /* this declaration needs to be here because it is used in string.c in Ruby */ ONIG_EXTERN int onigenc_ascii_only_case_map(OnigCaseFoldType* flagP, const OnigUChar** pp, const OnigUChar* end, OnigUChar* to, OnigUChar* to_end, const struct OnigEncodingTypeST* enc); /* work size */ #define ONIGENC_CODE_TO_MBC_MAXLEN 7 #define ONIGENC_MBC_CASE_FOLD_MAXLEN 18 /* 18: 6(max-byte) * 3(case-fold chars) */ /* character types */ #define ONIGENC_CTYPE_NEWLINE 0 #define ONIGENC_CTYPE_ALPHA 1 #define ONIGENC_CTYPE_BLANK 2 #define ONIGENC_CTYPE_CNTRL 3 #define ONIGENC_CTYPE_DIGIT 4 #define ONIGENC_CTYPE_GRAPH 5 #define ONIGENC_CTYPE_LOWER 6 #define ONIGENC_CTYPE_PRINT 7 #define ONIGENC_CTYPE_PUNCT 8 #define ONIGENC_CTYPE_SPACE 9 #define ONIGENC_CTYPE_UPPER 10 #define ONIGENC_CTYPE_XDIGIT 11 #define ONIGENC_CTYPE_WORD 12 #define ONIGENC_CTYPE_ALNUM 13 /* alpha || digit */ #define ONIGENC_CTYPE_ASCII 14 #define ONIGENC_MAX_STD_CTYPE ONIGENC_CTYPE_ASCII /* flags */ #define ONIGENC_FLAG_NONE 0U #define ONIGENC_FLAG_UNICODE 1U #define onig_enc_len(enc,p,e) ONIGENC_MBC_ENC_LEN(enc, p, e) #define ONIGENC_IS_UNDEF(enc) ((enc) == ONIG_ENCODING_UNDEF) #define ONIGENC_IS_SINGLEBYTE(enc) (ONIGENC_MBC_MAXLEN(enc) == 1) #define ONIGENC_IS_MBC_HEAD(enc,p,e) (ONIGENC_MBC_ENC_LEN(enc,p,e) != 1) #define ONIGENC_IS_MBC_ASCII(p) (*(p) < 128) #define ONIGENC_IS_CODE_ASCII(code) ((code) < 128) #define ONIGENC_IS_MBC_WORD(enc,s,end) \ ONIGENC_IS_CODE_WORD(enc,ONIGENC_MBC_TO_CODE(enc,s,end)) #define ONIGENC_IS_MBC_ASCII_WORD(enc,s,end) \ onigenc_ascii_is_code_ctype( \ ONIGENC_MBC_TO_CODE(enc,s,end),ONIGENC_CTYPE_WORD,enc) #define ONIGENC_IS_UNICODE(enc) ((enc)->flags & ONIGENC_FLAG_UNICODE) #define ONIGENC_NAME(enc) ((enc)->name) #define ONIGENC_MBC_CASE_FOLD(enc,flag,pp,end,buf) \ (enc)->mbc_case_fold(flag,(const OnigUChar** )pp,end,buf,enc) #define ONIGENC_IS_ALLOWED_REVERSE_MATCH(enc,s,end) \ (enc)->is_allowed_reverse_match(s,end,enc) #define ONIGENC_LEFT_ADJUST_CHAR_HEAD(enc,start,s,end) \ (enc)->left_adjust_char_head(start, s, end, enc) #define ONIGENC_APPLY_ALL_CASE_FOLD(enc,case_fold_flag,f,arg) \ (enc)->apply_all_case_fold(case_fold_flag,f,arg,enc) #define ONIGENC_GET_CASE_FOLD_CODES_BY_STR(enc,case_fold_flag,p,end,acs) \ (enc)->get_case_fold_codes_by_str(case_fold_flag,p,end,acs,enc) #define ONIGENC_STEP_BACK(enc,start,s,end,n) \ onigenc_step_back((enc),(start),(s),(end),(n)) #define ONIGENC_CONSTRUCT_MBCLEN_CHARFOUND(n) (n) #define ONIGENC_MBCLEN_CHARFOUND_P(r) (0 < (r)) #define ONIGENC_MBCLEN_CHARFOUND_LEN(r) (r) #define ONIGENC_CONSTRUCT_MBCLEN_INVALID() (-1) #define ONIGENC_MBCLEN_INVALID_P(r) ((r) == -1) #define ONIGENC_CONSTRUCT_MBCLEN_NEEDMORE(n) (-1-(n)) #define ONIGENC_MBCLEN_NEEDMORE_P(r) ((r) < -1) #define ONIGENC_MBCLEN_NEEDMORE_LEN(r) (-1-(r)) #define ONIGENC_PRECISE_MBC_ENC_LEN(enc,p,e) (enc)->precise_mbc_enc_len(p,e,enc) ONIG_EXTERN int onigenc_mbclen(const OnigUChar* p,const OnigUChar* e, const struct OnigEncodingTypeST* enc); #define ONIGENC_MBC_ENC_LEN(enc,p,e) onigenc_mbclen(p,e,enc) #define ONIGENC_MBC_MAXLEN(enc) ((enc)->max_enc_len) #define ONIGENC_MBC_MAXLEN_DIST(enc) ONIGENC_MBC_MAXLEN(enc) #define ONIGENC_MBC_MINLEN(enc) ((enc)->min_enc_len) #define ONIGENC_IS_MBC_NEWLINE(enc,p,end) (enc)->is_mbc_newline((p),(end),enc) #define ONIGENC_MBC_TO_CODE(enc,p,end) (enc)->mbc_to_code((p),(end),enc) #define ONIGENC_CODE_TO_MBCLEN(enc,code) (enc)->code_to_mbclen(code,enc) #define ONIGENC_CODE_TO_MBC(enc,code,buf) (enc)->code_to_mbc(code,buf,enc) #define ONIGENC_PROPERTY_NAME_TO_CTYPE(enc,p,end) \ (enc)->property_name_to_ctype(enc,p,end) #define ONIGENC_IS_CODE_CTYPE(enc,code,ctype) (enc)->is_code_ctype(code,ctype,enc) #define ONIGENC_IS_CODE_NEWLINE(enc,code) \ ONIGENC_IS_CODE_CTYPE(enc,code,ONIGENC_CTYPE_NEWLINE) #define ONIGENC_IS_CODE_GRAPH(enc,code) \ ONIGENC_IS_CODE_CTYPE(enc,code,ONIGENC_CTYPE_GRAPH) #define ONIGENC_IS_CODE_PRINT(enc,code) \ ONIGENC_IS_CODE_CTYPE(enc,code,ONIGENC_CTYPE_PRINT) #define ONIGENC_IS_CODE_ALNUM(enc,code) \ ONIGENC_IS_CODE_CTYPE(enc,code,ONIGENC_CTYPE_ALNUM) #define ONIGENC_IS_CODE_ALPHA(enc,code) \ ONIGENC_IS_CODE_CTYPE(enc,code,ONIGENC_CTYPE_ALPHA) #define ONIGENC_IS_CODE_LOWER(enc,code) \ ONIGENC_IS_CODE_CTYPE(enc,code,ONIGENC_CTYPE_LOWER) #define ONIGENC_IS_CODE_UPPER(enc,code) \ ONIGENC_IS_CODE_CTYPE(enc,code,ONIGENC_CTYPE_UPPER) #define ONIGENC_IS_CODE_CNTRL(enc,code) \ ONIGENC_IS_CODE_CTYPE(enc,code,ONIGENC_CTYPE_CNTRL) #define ONIGENC_IS_CODE_PUNCT(enc,code) \ ONIGENC_IS_CODE_CTYPE(enc,code,ONIGENC_CTYPE_PUNCT) #define ONIGENC_IS_CODE_SPACE(enc,code) \ ONIGENC_IS_CODE_CTYPE(enc,code,ONIGENC_CTYPE_SPACE) #define ONIGENC_IS_CODE_BLANK(enc,code) \ ONIGENC_IS_CODE_CTYPE(enc,code,ONIGENC_CTYPE_BLANK) #define ONIGENC_IS_CODE_DIGIT(enc,code) \ ONIGENC_IS_CODE_CTYPE(enc,code,ONIGENC_CTYPE_DIGIT) #define ONIGENC_IS_CODE_XDIGIT(enc,code) \ ONIGENC_IS_CODE_CTYPE(enc,code,ONIGENC_CTYPE_XDIGIT) #define ONIGENC_IS_CODE_WORD(enc,code) \ ONIGENC_IS_CODE_CTYPE(enc,code,ONIGENC_CTYPE_WORD) #define ONIGENC_GET_CTYPE_CODE_RANGE(enc,ctype,sbout,ranges) \ (enc)->get_ctype_code_range(ctype,sbout,ranges,enc) ONIG_EXTERN OnigUChar* onigenc_step_back(OnigEncoding enc, const OnigUChar* start, const OnigUChar* s, const OnigUChar* end, int n); /* encoding API */ ONIG_EXTERN int onigenc_init(void); ONIG_EXTERN int onigenc_set_default_encoding(OnigEncoding enc); ONIG_EXTERN OnigEncoding onigenc_get_default_encoding(void); ONIG_EXTERN OnigUChar* onigenc_get_right_adjust_char_head_with_prev(OnigEncoding enc, const OnigUChar* start, const OnigUChar* s, const OnigUChar* end, const OnigUChar** prev); ONIG_EXTERN OnigUChar* onigenc_get_prev_char_head(OnigEncoding enc, const OnigUChar* start, const OnigUChar* s, const OnigUChar* end); ONIG_EXTERN OnigUChar* onigenc_get_left_adjust_char_head(OnigEncoding enc, const OnigUChar* start, const OnigUChar* s, const OnigUChar* end); ONIG_EXTERN OnigUChar* onigenc_get_right_adjust_char_head(OnigEncoding enc, const OnigUChar* start, const OnigUChar* s, const OnigUChar* end); ONIG_EXTERN int onigenc_strlen(OnigEncoding enc, const OnigUChar* p, const OnigUChar* end); ONIG_EXTERN int onigenc_strlen_null(OnigEncoding enc, const OnigUChar* p); ONIG_EXTERN int onigenc_str_bytelen_null(OnigEncoding enc, const OnigUChar* p); /* PART: regular expression */ /* config parameters */ #define ONIG_NREGION 4 #define ONIG_MAX_CAPTURE_GROUP_NUM 32767 #define ONIG_MAX_BACKREF_NUM 1000 #define ONIG_MAX_REPEAT_NUM 100000 #define ONIG_MAX_MULTI_BYTE_RANGES_NUM 10000 /* constants */ #define ONIG_MAX_ERROR_MESSAGE_LEN 90 typedef unsigned int OnigOptionType; #define ONIG_OPTION_DEFAULT ONIG_OPTION_NONE /* options */ #define ONIG_OPTION_NONE 0U #define ONIG_OPTION_IGNORECASE 1U #define ONIG_OPTION_EXTEND (ONIG_OPTION_IGNORECASE << 1) #define ONIG_OPTION_MULTILINE (ONIG_OPTION_EXTEND << 1) #define ONIG_OPTION_DOTALL ONIG_OPTION_MULTILINE #define ONIG_OPTION_SINGLELINE (ONIG_OPTION_MULTILINE << 1) #define ONIG_OPTION_FIND_LONGEST (ONIG_OPTION_SINGLELINE << 1) #define ONIG_OPTION_FIND_NOT_EMPTY (ONIG_OPTION_FIND_LONGEST << 1) #define ONIG_OPTION_NEGATE_SINGLELINE (ONIG_OPTION_FIND_NOT_EMPTY << 1) #define ONIG_OPTION_DONT_CAPTURE_GROUP (ONIG_OPTION_NEGATE_SINGLELINE << 1) #define ONIG_OPTION_CAPTURE_GROUP (ONIG_OPTION_DONT_CAPTURE_GROUP << 1) /* options (search time) */ #define ONIG_OPTION_NOTBOL (ONIG_OPTION_CAPTURE_GROUP << 1) #define ONIG_OPTION_NOTEOL (ONIG_OPTION_NOTBOL << 1) #define ONIG_OPTION_NOTBOS (ONIG_OPTION_NOTEOL << 1) #define ONIG_OPTION_NOTEOS (ONIG_OPTION_NOTBOS << 1) /* options (ctype range) */ #define ONIG_OPTION_ASCII_RANGE (ONIG_OPTION_NOTEOS << 1) #define ONIG_OPTION_POSIX_BRACKET_ALL_RANGE (ONIG_OPTION_ASCII_RANGE << 1) #define ONIG_OPTION_WORD_BOUND_ALL_RANGE (ONIG_OPTION_POSIX_BRACKET_ALL_RANGE << 1) /* options (newline) */ #define ONIG_OPTION_NEWLINE_CRLF (ONIG_OPTION_WORD_BOUND_ALL_RANGE << 1) #define ONIG_OPTION_MAXBIT ONIG_OPTION_NEWLINE_CRLF /* limit */ #define ONIG_OPTION_ON(options,regopt) ((options) |= (regopt)) #define ONIG_OPTION_OFF(options,regopt) ((options) &= ~(regopt)) #define ONIG_IS_OPTION_ON(options,option) ((options) & (option)) /* syntax */ typedef struct { unsigned int op; unsigned int op2; unsigned int behavior; OnigOptionType options; /* default option */ OnigMetaCharTableType meta_char_table; } OnigSyntaxType; ONIG_EXTERN const OnigSyntaxType OnigSyntaxASIS; ONIG_EXTERN const OnigSyntaxType OnigSyntaxPosixBasic; ONIG_EXTERN const OnigSyntaxType OnigSyntaxPosixExtended; ONIG_EXTERN const OnigSyntaxType OnigSyntaxEmacs; ONIG_EXTERN const OnigSyntaxType OnigSyntaxGrep; ONIG_EXTERN const OnigSyntaxType OnigSyntaxGnuRegex; ONIG_EXTERN const OnigSyntaxType OnigSyntaxJava; ONIG_EXTERN const OnigSyntaxType OnigSyntaxPerl58; ONIG_EXTERN const OnigSyntaxType OnigSyntaxPerl58_NG; ONIG_EXTERN const OnigSyntaxType OnigSyntaxPerl; ONIG_EXTERN const OnigSyntaxType OnigSyntaxRuby; ONIG_EXTERN const OnigSyntaxType OnigSyntaxPython; /* predefined syntaxes (see regsyntax.c) */ #define ONIG_SYNTAX_ASIS (&OnigSyntaxASIS) #define ONIG_SYNTAX_POSIX_BASIC (&OnigSyntaxPosixBasic) #define ONIG_SYNTAX_POSIX_EXTENDED (&OnigSyntaxPosixExtended) #define ONIG_SYNTAX_EMACS (&OnigSyntaxEmacs) #define ONIG_SYNTAX_GREP (&OnigSyntaxGrep) #define ONIG_SYNTAX_GNU_REGEX (&OnigSyntaxGnuRegex) #define ONIG_SYNTAX_JAVA (&OnigSyntaxJava) #define ONIG_SYNTAX_PERL58 (&OnigSyntaxPerl58) #define ONIG_SYNTAX_PERL58_NG (&OnigSyntaxPerl58_NG) #define ONIG_SYNTAX_PERL (&OnigSyntaxPerl) #define ONIG_SYNTAX_RUBY (&OnigSyntaxRuby) #define ONIG_SYNTAX_PYTHON (&OnigSyntaxPython) /* default syntax */ ONIG_EXTERN const OnigSyntaxType* OnigDefaultSyntax; #define ONIG_SYNTAX_DEFAULT OnigDefaultSyntax /* syntax (operators) */ #define ONIG_SYN_OP_VARIABLE_META_CHARACTERS (1U<<0) #define ONIG_SYN_OP_DOT_ANYCHAR (1U<<1) /* . */ #define ONIG_SYN_OP_ASTERISK_ZERO_INF (1U<<2) /* * */ #define ONIG_SYN_OP_ESC_ASTERISK_ZERO_INF (1U<<3) #define ONIG_SYN_OP_PLUS_ONE_INF (1U<<4) /* + */ #define ONIG_SYN_OP_ESC_PLUS_ONE_INF (1U<<5) #define ONIG_SYN_OP_QMARK_ZERO_ONE (1U<<6) /* ? */ #define ONIG_SYN_OP_ESC_QMARK_ZERO_ONE (1U<<7) #define ONIG_SYN_OP_BRACE_INTERVAL (1U<<8) /* {lower,upper} */ #define ONIG_SYN_OP_ESC_BRACE_INTERVAL (1U<<9) /* \{lower,upper\} */ #define ONIG_SYN_OP_VBAR_ALT (1U<<10) /* | */ #define ONIG_SYN_OP_ESC_VBAR_ALT (1U<<11) /* \| */ #define ONIG_SYN_OP_LPAREN_SUBEXP (1U<<12) /* (...) */ #define ONIG_SYN_OP_ESC_LPAREN_SUBEXP (1U<<13) /* \(...\) */ #define ONIG_SYN_OP_ESC_AZ_BUF_ANCHOR (1U<<14) /* \A, \Z, \z */ #define ONIG_SYN_OP_ESC_CAPITAL_G_BEGIN_ANCHOR (1U<<15) /* \G */ #define ONIG_SYN_OP_DECIMAL_BACKREF (1U<<16) /* \num */ #define ONIG_SYN_OP_BRACKET_CC (1U<<17) /* [...] */ #define ONIG_SYN_OP_ESC_W_WORD (1U<<18) /* \w, \W */ #define ONIG_SYN_OP_ESC_LTGT_WORD_BEGIN_END (1U<<19) /* \<. \> */ #define ONIG_SYN_OP_ESC_B_WORD_BOUND (1U<<20) /* \b, \B */ #define ONIG_SYN_OP_ESC_S_WHITE_SPACE (1U<<21) /* \s, \S */ #define ONIG_SYN_OP_ESC_D_DIGIT (1U<<22) /* \d, \D */ #define ONIG_SYN_OP_LINE_ANCHOR (1U<<23) /* ^, $ */ #define ONIG_SYN_OP_POSIX_BRACKET (1U<<24) /* [:xxxx:] */ #define ONIG_SYN_OP_QMARK_NON_GREEDY (1U<<25) /* ??,*?,+?,{n,m}? */ #define ONIG_SYN_OP_ESC_CONTROL_CHARS (1U<<26) /* \n,\r,\t,\a ... */ #define ONIG_SYN_OP_ESC_C_CONTROL (1U<<27) /* \cx */ #define ONIG_SYN_OP_ESC_OCTAL3 (1U<<28) /* \OOO */ #define ONIG_SYN_OP_ESC_X_HEX2 (1U<<29) /* \xHH */ #define ONIG_SYN_OP_ESC_X_BRACE_HEX8 (1U<<30) /* \x{7HHHHHHH} */ #define ONIG_SYN_OP_ESC_O_BRACE_OCTAL (1U<<31) /* \o{OOO} */ #define ONIG_SYN_OP2_ESC_CAPITAL_Q_QUOTE (1U<<0) /* \Q...\E */ #define ONIG_SYN_OP2_QMARK_GROUP_EFFECT (1U<<1) /* (?...) */ #define ONIG_SYN_OP2_OPTION_PERL (1U<<2) /* (?imsxadlu), (?-imsx), (?^imsxalu) */ #define ONIG_SYN_OP2_OPTION_RUBY (1U<<3) /* (?imxadu), (?-imx) */ #define ONIG_SYN_OP2_PLUS_POSSESSIVE_REPEAT (1U<<4) /* ?+,*+,++ */ #define ONIG_SYN_OP2_PLUS_POSSESSIVE_INTERVAL (1U<<5) /* {n,m}+ */ #define ONIG_SYN_OP2_CCLASS_SET_OP (1U<<6) /* [...&&..[..]..] */ #define ONIG_SYN_OP2_QMARK_LT_NAMED_GROUP (1U<<7) /* (?<name>...) */ #define ONIG_SYN_OP2_ESC_K_NAMED_BACKREF (1U<<8) /* \k<name> */ #define ONIG_SYN_OP2_ESC_G_SUBEXP_CALL (1U<<9) /* \g<name>, \g<n> */ #define ONIG_SYN_OP2_ATMARK_CAPTURE_HISTORY (1U<<10) /* (?@..),(?@<x>..) */ #define ONIG_SYN_OP2_ESC_CAPITAL_C_BAR_CONTROL (1U<<11) /* \C-x */ #define ONIG_SYN_OP2_ESC_CAPITAL_M_BAR_META (1U<<12) /* \M-x */ #define ONIG_SYN_OP2_ESC_V_VTAB (1U<<13) /* \v as VTAB */ #define ONIG_SYN_OP2_ESC_U_HEX4 (1U<<14) /* \uHHHH */ #define ONIG_SYN_OP2_ESC_GNU_BUF_ANCHOR (1U<<15) /* \`, \' */ #define ONIG_SYN_OP2_ESC_P_BRACE_CHAR_PROPERTY (1U<<16) /* \p{...}, \P{...} */ #define ONIG_SYN_OP2_ESC_P_BRACE_CIRCUMFLEX_NOT (1U<<17) /* \p{^..}, \P{^..} */ /* #define ONIG_SYN_OP2_CHAR_PROPERTY_PREFIX_IS (1U<<18) */ #define ONIG_SYN_OP2_ESC_H_XDIGIT (1U<<19) /* \h, \H */ #define ONIG_SYN_OP2_INEFFECTIVE_ESCAPE (1U<<20) /* \ */ #define ONIG_SYN_OP2_ESC_CAPITAL_R_LINEBREAK (1U<<21) /* \R as (?>\x0D\x0A|[\x0A-\x0D\x{85}\x{2028}\x{2029}]) */ #define ONIG_SYN_OP2_ESC_CAPITAL_X_EXTENDED_GRAPHEME_CLUSTER (1U<<22) /* \X */ #define ONIG_SYN_OP2_ESC_V_VERTICAL_WHITESPACE (1U<<23) /* \v, \V -- Perl */ /* NOTIMPL */ #define ONIG_SYN_OP2_ESC_H_HORIZONTAL_WHITESPACE (1U<<24) /* \h, \H -- Perl */ /* NOTIMPL */ #define ONIG_SYN_OP2_ESC_CAPITAL_K_KEEP (1U<<25) /* \K */ #define ONIG_SYN_OP2_ESC_G_BRACE_BACKREF (1U<<26) /* \g{name}, \g{n} */ #define ONIG_SYN_OP2_QMARK_SUBEXP_CALL (1U<<27) /* (?&name), (?n), (?R), (?0) */ #define ONIG_SYN_OP2_QMARK_VBAR_BRANCH_RESET (1U<<28) /* (?|...) */ /* NOTIMPL */ #define ONIG_SYN_OP2_QMARK_LPAREN_CONDITION (1U<<29) /* (?(cond)yes...|no...) */ #define ONIG_SYN_OP2_QMARK_CAPITAL_P_NAMED_GROUP (1U<<30) /* (?P<name>...), (?P=name), (?P>name) -- Python/PCRE */ #define ONIG_SYN_OP2_QMARK_TILDE_ABSENT (1U<<31) /* (?~...) */ /* #define ONIG_SYN_OP2_OPTION_JAVA (1U<<xx) */ /* (?idmsux), (?-idmsux) */ /* NOTIMPL */ /* syntax (behavior) */ #define ONIG_SYN_CONTEXT_INDEP_ANCHORS (1U<<31) /* not implemented */ #define ONIG_SYN_CONTEXT_INDEP_REPEAT_OPS (1U<<0) /* ?, *, +, {n,m} */ #define ONIG_SYN_CONTEXT_INVALID_REPEAT_OPS (1U<<1) /* error or ignore */ #define ONIG_SYN_ALLOW_UNMATCHED_CLOSE_SUBEXP (1U<<2) /* ...)... */ #define ONIG_SYN_ALLOW_INVALID_INTERVAL (1U<<3) /* {??? */ #define ONIG_SYN_ALLOW_INTERVAL_LOW_ABBREV (1U<<4) /* {,n} => {0,n} */ #define ONIG_SYN_STRICT_CHECK_BACKREF (1U<<5) /* /(\1)/,/\1()/ ..*/ #define ONIG_SYN_DIFFERENT_LEN_ALT_LOOK_BEHIND (1U<<6) /* (?<=a|bc) */ #define ONIG_SYN_CAPTURE_ONLY_NAMED_GROUP (1U<<7) /* see doc/RE */ #define ONIG_SYN_ALLOW_MULTIPLEX_DEFINITION_NAME (1U<<8) /* (?<x>)(?<x>) */ #define ONIG_SYN_FIXED_INTERVAL_IS_GREEDY_ONLY (1U<<9) /* a{n}?=(?:a{n})? */ #define ONIG_SYN_ALLOW_MULTIPLEX_DEFINITION_NAME_CALL (1U<<10) /* (?<x>)(?<x>)(?&x) */ #define ONIG_SYN_USE_LEFT_MOST_NAMED_GROUP (1U<<11) /* (?<x>)(?<x>)\k<x> */ /* syntax (behavior) in char class [...] */ #define ONIG_SYN_NOT_NEWLINE_IN_NEGATIVE_CC (1U<<20) /* [^...] */ #define ONIG_SYN_BACKSLASH_ESCAPE_IN_CC (1U<<21) /* [..\w..] etc.. */ #define ONIG_SYN_ALLOW_EMPTY_RANGE_IN_CC (1U<<22) #define ONIG_SYN_ALLOW_DOUBLE_RANGE_OP_IN_CC (1U<<23) /* [0-9-a]=[0-9\-a] */ /* syntax (behavior) warning */ #define ONIG_SYN_WARN_CC_OP_NOT_ESCAPED (1U<<24) /* [,-,] */ #define ONIG_SYN_WARN_REDUNDANT_NESTED_REPEAT (1U<<25) /* (?:a*)+ */ #define ONIG_SYN_WARN_CC_DUP (1U<<26) /* [aa] */ /* meta character specifiers (onig_set_meta_char()) */ #define ONIG_META_CHAR_ESCAPE 0 #define ONIG_META_CHAR_ANYCHAR 1 #define ONIG_META_CHAR_ANYTIME 2 #define ONIG_META_CHAR_ZERO_OR_ONE_TIME 3 #define ONIG_META_CHAR_ONE_OR_MORE_TIME 4 #define ONIG_META_CHAR_ANYCHAR_ANYTIME 5 #define ONIG_INEFFECTIVE_META_CHAR 0 /* error codes */ #define ONIG_IS_PATTERN_ERROR(ecode) ((ecode) <= -100 && (ecode) > -1000) /* normal return */ #define ONIG_NORMAL 0 #define ONIG_MISMATCH -1 #define ONIG_NO_SUPPORT_CONFIG -2 /* internal error */ #define ONIGERR_MEMORY -5 #define ONIGERR_TYPE_BUG -6 #define ONIGERR_PARSER_BUG -11 #define ONIGERR_STACK_BUG -12 #define ONIGERR_UNDEFINED_BYTECODE -13 #define ONIGERR_UNEXPECTED_BYTECODE -14 #define ONIGERR_MATCH_STACK_LIMIT_OVER -15 #define ONIGERR_PARSE_DEPTH_LIMIT_OVER -16 #define ONIGERR_DEFAULT_ENCODING_IS_NOT_SET -21 #define ONIGERR_SPECIFIED_ENCODING_CANT_CONVERT_TO_WIDE_CHAR -22 #define ONIGERR_TIMEOUT -23 /* general error */ #define ONIGERR_INVALID_ARGUMENT -30 /* syntax error */ #define ONIGERR_END_PATTERN_AT_LEFT_BRACE -100 #define ONIGERR_END_PATTERN_AT_LEFT_BRACKET -101 #define ONIGERR_EMPTY_CHAR_CLASS -102 #define ONIGERR_PREMATURE_END_OF_CHAR_CLASS -103 #define ONIGERR_END_PATTERN_AT_ESCAPE -104 #define ONIGERR_END_PATTERN_AT_META -105 #define ONIGERR_END_PATTERN_AT_CONTROL -106 #define ONIGERR_META_CODE_SYNTAX -108 #define ONIGERR_CONTROL_CODE_SYNTAX -109 #define ONIGERR_CHAR_CLASS_VALUE_AT_END_OF_RANGE -110 #define ONIGERR_CHAR_CLASS_VALUE_AT_START_OF_RANGE -111 #define ONIGERR_UNMATCHED_RANGE_SPECIFIER_IN_CHAR_CLASS -112 #define ONIGERR_TARGET_OF_REPEAT_OPERATOR_NOT_SPECIFIED -113 #define ONIGERR_TARGET_OF_REPEAT_OPERATOR_INVALID -114 #define ONIGERR_NESTED_REPEAT_OPERATOR -115 #define ONIGERR_UNMATCHED_CLOSE_PARENTHESIS -116 #define ONIGERR_END_PATTERN_WITH_UNMATCHED_PARENTHESIS -117 #define ONIGERR_END_PATTERN_IN_GROUP -118 #define ONIGERR_UNDEFINED_GROUP_OPTION -119 #define ONIGERR_INVALID_POSIX_BRACKET_TYPE -121 #define ONIGERR_INVALID_LOOK_BEHIND_PATTERN -122 #define ONIGERR_INVALID_REPEAT_RANGE_PATTERN -123 #define ONIGERR_INVALID_CONDITION_PATTERN -124 /* values error (syntax error) */ #define ONIGERR_TOO_BIG_NUMBER -200 #define ONIGERR_TOO_BIG_NUMBER_FOR_REPEAT_RANGE -201 #define ONIGERR_UPPER_SMALLER_THAN_LOWER_IN_REPEAT_RANGE -202 #define ONIGERR_EMPTY_RANGE_IN_CHAR_CLASS -203 #define ONIGERR_MISMATCH_CODE_LENGTH_IN_CLASS_RANGE -204 #define ONIGERR_TOO_MANY_MULTI_BYTE_RANGES -205 #define ONIGERR_TOO_SHORT_MULTI_BYTE_STRING -206 #define ONIGERR_TOO_BIG_BACKREF_NUMBER -207 #define ONIGERR_INVALID_BACKREF -208 #define ONIGERR_NUMBERED_BACKREF_OR_CALL_NOT_ALLOWED -209 #define ONIGERR_TOO_MANY_CAPTURE_GROUPS -210 #define ONIGERR_TOO_SHORT_DIGITS -211 #define ONIGERR_TOO_LONG_WIDE_CHAR_VALUE -212 #define ONIGERR_EMPTY_GROUP_NAME -214 #define ONIGERR_INVALID_GROUP_NAME -215 #define ONIGERR_INVALID_CHAR_IN_GROUP_NAME -216 #define ONIGERR_UNDEFINED_NAME_REFERENCE -217 #define ONIGERR_UNDEFINED_GROUP_REFERENCE -218 #define ONIGERR_MULTIPLEX_DEFINED_NAME -219 #define ONIGERR_MULTIPLEX_DEFINITION_NAME_CALL -220 #define ONIGERR_NEVER_ENDING_RECURSION -221 #define ONIGERR_GROUP_NUMBER_OVER_FOR_CAPTURE_HISTORY -222 #define ONIGERR_INVALID_CHAR_PROPERTY_NAME -223 #define ONIGERR_INVALID_CODE_POINT_VALUE -400 #define ONIGERR_INVALID_WIDE_CHAR_VALUE -400 #define ONIGERR_TOO_BIG_WIDE_CHAR_VALUE -401 #define ONIGERR_NOT_SUPPORTED_ENCODING_COMBINATION -402 #define ONIGERR_INVALID_COMBINATION_OF_OPTIONS -403 /* errors related to thread */ /* #define ONIGERR_OVER_THREAD_PASS_LIMIT_COUNT -1001 */ /* must be smaller than BIT_STATUS_BITS_NUM (unsigned int * 8) */ #define ONIG_MAX_CAPTURE_HISTORY_GROUP 31 #define ONIG_IS_CAPTURE_HISTORY_GROUP(r, i) \ ((i) <= ONIG_MAX_CAPTURE_HISTORY_GROUP && (r)->list && (r)->list[i]) #ifdef USE_CAPTURE_HISTORY typedef struct OnigCaptureTreeNodeStruct { int group; /* group number */ OnigPosition beg; OnigPosition end; int allocated; int num_childs; struct OnigCaptureTreeNodeStruct** childs; } OnigCaptureTreeNode; #endif /* match result region type */ struct re_registers { int allocated; int num_regs; OnigPosition* beg; OnigPosition* end; #ifdef USE_CAPTURE_HISTORY /* extended */ OnigCaptureTreeNode* history_root; /* capture history tree root */ #endif }; /* capture tree traverse */ #define ONIG_TRAVERSE_CALLBACK_AT_FIRST 1 #define ONIG_TRAVERSE_CALLBACK_AT_LAST 2 #define ONIG_TRAVERSE_CALLBACK_AT_BOTH \ ( ONIG_TRAVERSE_CALLBACK_AT_FIRST | ONIG_TRAVERSE_CALLBACK_AT_LAST ) #define ONIG_REGION_NOTPOS -1 typedef struct re_registers OnigRegion; typedef struct { OnigEncoding enc; OnigUChar* par; OnigUChar* par_end; } OnigErrorInfo; typedef struct { int lower; int upper; } OnigRepeatRange; typedef void (*OnigWarnFunc)(const char* s); extern void onig_null_warn(const char* s); #define ONIG_NULL_WARN onig_null_warn #define ONIG_CHAR_TABLE_SIZE 256 typedef struct re_pattern_buffer { /* common members of BBuf(bytes-buffer) */ unsigned char* p; /* compiled pattern */ unsigned int used; /* used space for p */ unsigned int alloc; /* allocated space for p */ int num_mem; /* used memory(...) num counted from 1 */ int num_repeat; /* OP_REPEAT/OP_REPEAT_NG id-counter */ int num_null_check; /* OP_NULL_CHECK_START/END id counter */ int num_comb_exp_check; /* combination explosion check */ int num_call; /* number of subexp call */ unsigned int capture_history; /* (?@...) flag (1-31) */ unsigned int bt_mem_start; /* need backtrack flag */ unsigned int bt_mem_end; /* need backtrack flag */ int stack_pop_level; int repeat_range_alloc; OnigOptionType options; OnigRepeatRange* repeat_range; OnigEncoding enc; const OnigSyntaxType* syntax; void* name_table; OnigCaseFoldType case_fold_flag; /* optimization info (string search, char-map and anchors) */ int optimize; /* optimize flag */ int threshold_len; /* search str-length for apply optimize */ int anchor; /* BEGIN_BUF, BEGIN_POS, (SEMI_)END_BUF */ OnigDistance anchor_dmin; /* (SEMI_)END_BUF anchor distance */ OnigDistance anchor_dmax; /* (SEMI_)END_BUF anchor distance */ int sub_anchor; /* start-anchor for exact or map */ unsigned char *exact; unsigned char *exact_end; unsigned char map[ONIG_CHAR_TABLE_SIZE]; /* used as BM skip or char-map */ int *int_map; /* BM skip for exact_len > 255 */ int *int_map_backward; /* BM skip for backward search */ OnigDistance dmin; /* min-distance of exact or map */ OnigDistance dmax; /* max-distance of exact or map */ /* rb_hrtime_t from hrtime.h */ #ifdef MY_RUBY_BUILD_MAY_TIME_TRAVEL int128_t timelimit; #else uint64_t timelimit; #endif /* regex_t link chain */ struct re_pattern_buffer* chain; /* escape compile-conflict */ } OnigRegexType; typedef OnigRegexType* OnigRegex; #ifndef ONIG_ESCAPE_REGEX_T_COLLISION typedef OnigRegexType regex_t; #endif typedef struct { int num_of_elements; OnigEncoding pattern_enc; OnigEncoding target_enc; const OnigSyntaxType* syntax; OnigOptionType option; OnigCaseFoldType case_fold_flag; } OnigCompileInfo; /* Oniguruma Native API */ ONIG_EXTERN int onig_initialize(OnigEncoding encodings[], int n); ONIG_EXTERN int onig_init(void); ONIG_EXTERN int onig_error_code_to_str(OnigUChar* s, OnigPosition err_code, ...); ONIG_EXTERN void onig_set_warn_func(OnigWarnFunc f); ONIG_EXTERN void onig_set_verb_warn_func(OnigWarnFunc f); ONIG_EXTERN int onig_new(OnigRegex*, const OnigUChar* pattern, const OnigUChar* pattern_end, OnigOptionType option, OnigEncoding enc, const OnigSyntaxType* syntax, OnigErrorInfo* einfo); ONIG_EXTERN int onig_reg_init(OnigRegex reg, OnigOptionType option, OnigCaseFoldType case_fold_flag, OnigEncoding enc, const OnigSyntaxType* syntax); ONIG_EXTERN int onig_new_without_alloc(OnigRegex, const OnigUChar* pattern, const OnigUChar* pattern_end, OnigOptionType option, OnigEncoding enc, const OnigSyntaxType* syntax, OnigErrorInfo* einfo); ONIG_EXTERN int onig_new_deluxe(OnigRegex* reg, const OnigUChar* pattern, const OnigUChar* pattern_end, OnigCompileInfo* ci, OnigErrorInfo* einfo); ONIG_EXTERN void onig_free(OnigRegex); ONIG_EXTERN void onig_free_body(OnigRegex); ONIG_EXTERN int onig_reg_copy(OnigRegex* reg, OnigRegex orig_reg); ONIG_EXTERN OnigPosition onig_scan(OnigRegex reg, const OnigUChar* str, const OnigUChar* end, OnigRegion* region, OnigOptionType option, int (*scan_callback)(OnigPosition, OnigPosition, OnigRegion*, void*), void* callback_arg); ONIG_EXTERN OnigPosition onig_search(OnigRegex, const OnigUChar* str, const OnigUChar* end, const OnigUChar* start, const OnigUChar* range, OnigRegion* region, OnigOptionType option); ONIG_EXTERN OnigPosition onig_search_gpos(OnigRegex, const OnigUChar* str, const OnigUChar* end, const OnigUChar* global_pos, const OnigUChar* start, const OnigUChar* range, OnigRegion* region, OnigOptionType option); ONIG_EXTERN OnigPosition onig_match(OnigRegex, const OnigUChar* str, const OnigUChar* end, const OnigUChar* at, OnigRegion* region, OnigOptionType option); ONIG_EXTERN int onig_check_linear_time(OnigRegex reg); ONIG_EXTERN OnigRegion* onig_region_new(void); ONIG_EXTERN void onig_region_init(OnigRegion* region); ONIG_EXTERN void onig_region_free(OnigRegion* region, int free_self); ONIG_EXTERN void onig_region_copy(OnigRegion* to, const OnigRegion* from); ONIG_EXTERN void onig_region_clear(OnigRegion* region); ONIG_EXTERN int onig_region_resize(OnigRegion* region, int n); ONIG_EXTERN int onig_region_set(OnigRegion* region, int at, int beg, int end); ONIG_EXTERN int onig_name_to_group_numbers(OnigRegex reg, const OnigUChar* name, const OnigUChar* name_end, int** nums); ONIG_EXTERN int onig_name_to_backref_number(OnigRegex reg, const OnigUChar* name, const OnigUChar* name_end, const OnigRegion *region); ONIG_EXTERN int onig_foreach_name(OnigRegex reg, int (*func)(const OnigUChar*, const OnigUChar*,int,int*,OnigRegex,void*), void* arg); ONIG_EXTERN int onig_number_of_names(const OnigRegexType *reg); ONIG_EXTERN int onig_number_of_captures(const OnigRegexType *reg); ONIG_EXTERN int onig_number_of_capture_histories(const OnigRegexType *reg); #ifdef USE_CAPTURE_HISTORY ONIG_EXTERN OnigCaptureTreeNode* onig_get_capture_tree(OnigRegion* region); #endif ONIG_EXTERN int onig_capture_tree_traverse(OnigRegion* region, int at, int(*callback_func)(int,OnigPosition,OnigPosition,int,int,void*), void* arg); ONIG_EXTERN int onig_noname_group_capture_is_active(const OnigRegexType *reg); ONIG_EXTERN OnigEncoding onig_get_encoding(const OnigRegexType *reg); ONIG_EXTERN OnigOptionType onig_get_options(const OnigRegexType *reg); ONIG_EXTERN OnigCaseFoldType onig_get_case_fold_flag(const OnigRegexType *reg); ONIG_EXTERN const OnigSyntaxType* onig_get_syntax(const OnigRegexType *reg); ONIG_EXTERN int onig_set_default_syntax(const OnigSyntaxType* syntax); ONIG_EXTERN void onig_copy_syntax(OnigSyntaxType* to, const OnigSyntaxType* from); ONIG_EXTERN unsigned int onig_get_syntax_op(const OnigSyntaxType* syntax); ONIG_EXTERN unsigned int onig_get_syntax_op2(const OnigSyntaxType* syntax); ONIG_EXTERN unsigned int onig_get_syntax_behavior(const OnigSyntaxType* syntax); ONIG_EXTERN OnigOptionType onig_get_syntax_options(const OnigSyntaxType* syntax); ONIG_EXTERN void onig_set_syntax_op(OnigSyntaxType* syntax, unsigned int op); ONIG_EXTERN void onig_set_syntax_op2(OnigSyntaxType* syntax, unsigned int op2); ONIG_EXTERN void onig_set_syntax_behavior(OnigSyntaxType* syntax, unsigned int behavior); ONIG_EXTERN void onig_set_syntax_options(OnigSyntaxType* syntax, OnigOptionType options); ONIG_EXTERN int onig_set_meta_char(OnigSyntaxType* syntax, unsigned int what, OnigCodePoint code); ONIG_EXTERN void onig_copy_encoding(OnigEncodingType *to, OnigEncoding from); ONIG_EXTERN OnigCaseFoldType onig_get_default_case_fold_flag(void); ONIG_EXTERN int onig_set_default_case_fold_flag(OnigCaseFoldType case_fold_flag); ONIG_EXTERN unsigned int onig_get_match_stack_limit_size(void); ONIG_EXTERN int onig_set_match_stack_limit_size(unsigned int size); ONIG_EXTERN unsigned int onig_get_parse_depth_limit(void); ONIG_EXTERN int onig_set_parse_depth_limit(unsigned int depth); ONIG_EXTERN int onig_end(void); ONIG_EXTERN const char* onig_version(void); ONIG_EXTERN const char* onig_copyright(void); RUBY_SYMBOL_EXPORT_END #ifdef __cplusplus # if 0 { /* satisfy cc-mode */ # endif } #endif #endif /* ONIGMO_H */ include/ruby/backward.h 0000644 00000002166 15152150470 0011104 0 ustar 00 #ifndef RUBY_RUBY_BACKWARD_H /*-*-C++-*-vi:se ft=cpp:*/ #define RUBY_RUBY_BACKWARD_H 1 /** * @author Ruby developers <ruby-core@ruby-lang.org> * @copyright This file is a part of the programming language Ruby. * Permission is hereby granted, to either redistribute and/or * modify this file, provided that the conditions mentioned in the * file COPYING are met. Consult the file for details. */ #include "ruby/internal/value.h" #include "ruby/internal/interpreter.h" #include "ruby/backward/2/attributes.h" #define RBIMPL_ATTR_DEPRECATED_SINCE(ver) RBIMPL_ATTR_DEPRECATED(("since " #ver)) #define RBIMPL_ATTR_DEPRECATED_INTERNAL(ver) RBIMPL_ATTR_DEPRECATED(("since "#ver", also internal")) #define RBIMPL_ATTR_DEPRECATED_INTERNAL_ONLY() RBIMPL_ATTR_DEPRECATED(("only for internal use")) RBIMPL_ATTR_DEPRECATED_INTERNAL_ONLY() void rb_clear_constant_cache(void); /* from version.c */ #if defined(RUBY_SHOW_COPYRIGHT_TO_DIE) && !!(RUBY_SHOW_COPYRIGHT_TO_DIE+0) # error RUBY_SHOW_COPYRIGHT_TO_DIE is deprecated #endif #endif /* RUBY_RUBY_BACKWARD_H */ include/ruby/backward/2/stdarg.h 0000644 00000004606 15152150470 0012532 0 ustar 00 #ifndef RUBY_BACKWARD2_STDARG_H /*-*-C++-*-vi:se ft=cpp:*/ #define RUBY_BACKWARD2_STDARG_H /** * @file * @author Ruby developers <ruby-core@ruby-lang.org> * @copyright This file is a part of the programming language Ruby. * Permission is hereby granted, to either redistribute and/or * modify this file, provided that the conditions mentioned in the * file COPYING are met. Consult the file for details. * @warning Symbols prefixed with either `RBIMPL` or `rbimpl` are * implementation details. Don't take them as canon. They could * rapidly appear then vanish. The name (path) of this header file * is also an implementation detail. Do not expect it to persist * at the place it is now. Developers are free to move it anywhere * anytime at will. * @note To ruby-core: remember that this header can be possibly * recursively included from extension libraries written in C++. * Do not expect for instance `__VA_ARGS__` is always available. * We assume C99 for ruby itself but we don't assume languages of * extension libraries. They could be written in C++98. * @brief Defines old #_ * * Nobody should ever use these macros any longer. No known compilers lack * prototypes today. It's 21st century. Just forget them. */ #undef _ /** * @deprecated Nobody practically needs this macro any longer. * @brief This was a transition path from K&R to ANSI. */ #ifdef HAVE_PROTOTYPES # define _(args) args #else # define _(args) () #endif #undef __ /** * @deprecated Nobody practically needs this macro any longer. * @brief This was a transition path from K&R to ANSI. */ #ifdef HAVE_STDARG_PROTOTYPES # define __(args) args #else # define __(args) () #endif /** * Functions declared using this macro take arbitrary arguments, including * void. * * ```CXX * void func(ANYARGS); * ``` * * This was a necessary evil when there was no such thing like function * overloading. But it is the 21st century today. People generally need not * use this. Just use a granular typed function. * * @see ruby::backward::cxxanyargs */ #ifdef __cplusplus #define ANYARGS ... #else #define ANYARGS #endif #endif /* RUBY_BACKWARD2_STDARG_H */ include/ruby/backward/2/inttypes.h 0000644 00000010046 15152150470 0013120 0 ustar 00 #ifndef RUBY_BACKWARD2_INTTYPES_H /*-*-C++-*-vi:se ft=cpp:*/ #define RUBY_BACKWARD2_INTTYPES_H /** * @author Ruby developers <ruby-core@ruby-lang.org> * @copyright This file is a part of the programming language Ruby. * Permission is hereby granted, to either redistribute and/or * modify this file, provided that the conditions mentioned in the * file COPYING are met. Consult the file for details. * @warning Symbols prefixed with either `RBIMPL` or `rbimpl` are * implementation details. Don't take them as canon. They could * rapidly appear then vanish. The name (path) of this header file * is also an implementation detail. Do not expect it to persist * at the place it is now. Developers are free to move it anywhere * anytime at will. * @note To ruby-core: remember that this header can be possibly * recursively included from extension libraries written in C++. * Do not expect for instance `__VA_ARGS__` is always available. * We assume C99 for ruby itself but we don't assume languages of * extension libraries. They could be written in C++98. * @brief C99 shim for `<inttypes.h>` */ #include "ruby/internal/config.h" /* PRI_LL_PREFIX etc. are here */ #ifdef HAVE_INTTYPES_H # include <inttypes.h> #endif #include "ruby/internal/value.h" /* PRI_VALUE_PREFIX is here. */ #ifndef PRI_INT_PREFIX # define PRI_INT_PREFIX "" #endif #ifndef PRI_LONG_PREFIX # define PRI_LONG_PREFIX "l" #endif #ifndef PRI_SHORT_PREFIX # define PRI_SHORT_PREFIX "h" #endif #ifdef PRI_64_PREFIX # /* Take that. */ #elif SIZEOF_LONG == 8 # define PRI_64_PREFIX PRI_LONG_PREFIX #elif SIZEOF_LONG_LONG == 8 # define PRI_64_PREFIX PRI_LL_PREFIX #endif #ifndef PRIdPTR # define PRIdPTR PRI_PTR_PREFIX"d" # define PRIiPTR PRI_PTR_PREFIX"i" # define PRIoPTR PRI_PTR_PREFIX"o" # define PRIuPTR PRI_PTR_PREFIX"u" # define PRIxPTR PRI_PTR_PREFIX"x" # define PRIXPTR PRI_PTR_PREFIX"X" #endif #ifndef RUBY_PRI_VALUE_MARK # define RUBY_PRI_VALUE_MARK "\v" #endif #if defined PRIdPTR && !defined PRI_VALUE_PREFIX # define PRIdVALUE PRIdPTR # define PRIoVALUE PRIoPTR # define PRIuVALUE PRIuPTR # define PRIxVALUE PRIxPTR # define PRIXVALUE PRIXPTR # define PRIsVALUE PRIiPTR"" RUBY_PRI_VALUE_MARK #else # define PRIdVALUE PRI_VALUE_PREFIX"d" # define PRIoVALUE PRI_VALUE_PREFIX"o" # define PRIuVALUE PRI_VALUE_PREFIX"u" # define PRIxVALUE PRI_VALUE_PREFIX"x" # define PRIXVALUE PRI_VALUE_PREFIX"X" # define PRIsVALUE PRI_VALUE_PREFIX"i" RUBY_PRI_VALUE_MARK #endif #ifndef PRI_VALUE_PREFIX # define PRI_VALUE_PREFIX "" #endif #ifdef PRI_TIMET_PREFIX # /* Take that. */ #elif SIZEOF_TIME_T == SIZEOF_INT # define PRI_TIMET_PREFIX #elif SIZEOF_TIME_T == SIZEOF_LONG # define PRI_TIMET_PREFIX "l" #elif SIZEOF_TIME_T == SIZEOF_LONG_LONG # define PRI_TIMET_PREFIX PRI_LL_PREFIX #endif #ifdef PRI_PTRDIFF_PREFIX # /* Take that. */ #elif SIZEOF_PTRDIFF_T == SIZEOF_INT # define PRI_PTRDIFF_PREFIX "" #elif SIZEOF_PTRDIFF_T == SIZEOF_LONG # define PRI_PTRDIFF_PREFIX "l" #elif SIZEOF_PTRDIFF_T == SIZEOF_LONG_LONG # define PRI_PTRDIFF_PREFIX PRI_LL_PREFIX #endif #ifndef PRIdPTRDIFF # define PRIdPTRDIFF PRI_PTRDIFF_PREFIX"d" # define PRIiPTRDIFF PRI_PTRDIFF_PREFIX"i" # define PRIoPTRDIFF PRI_PTRDIFF_PREFIX"o" # define PRIuPTRDIFF PRI_PTRDIFF_PREFIX"u" # define PRIxPTRDIFF PRI_PTRDIFF_PREFIX"x" # define PRIXPTRDIFF PRI_PTRDIFF_PREFIX"X" #endif #ifdef PRI_SIZE_PREFIX # /* Take that. */ #elif SIZEOF_SIZE_T == SIZEOF_INT # define PRI_SIZE_PREFIX "" #elif SIZEOF_SIZE_T == SIZEOF_LONG # define PRI_SIZE_PREFIX "l" #elif SIZEOF_SIZE_T == SIZEOF_LONG_LONG # define PRI_SIZE_PREFIX PRI_LL_PREFIX #endif #ifndef PRIdSIZE # define PRIdSIZE PRI_SIZE_PREFIX"d" # define PRIiSIZE PRI_SIZE_PREFIX"i" # define PRIoSIZE PRI_SIZE_PREFIX"o" # define PRIuSIZE PRI_SIZE_PREFIX"u" # define PRIxSIZE PRI_SIZE_PREFIX"x" # define PRIXSIZE PRI_SIZE_PREFIX"X" #endif #endif /* RUBY_BACKWARD2_INTTYPES_H */ include/ruby/backward/2/r_cast.h 0000644 00000003170 15152150470 0012514 0 ustar 00 #ifndef RUBY_BACKWARD2_R_CAST_H /*-*-C++-*-vi:se ft=cpp:*/ #define RUBY_BACKWARD2_R_CAST_H /** * @author Ruby developers <ruby-core@ruby-lang.org> * @copyright This file is a part of the programming language Ruby. * Permission is hereby granted, to either redistribute and/or * modify this file, provided that the conditions mentioned in the * file COPYING are met. Consult the file for details. * @warning Symbols prefixed with either `RBIMPL` or `rbimpl` are * implementation details. Don't take them as canon. They could * rapidly appear then vanish. The name (path) of this header file * is also an implementation detail. Do not expect it to persist * at the place it is now. Developers are free to move it anywhere * anytime at will. * @note To ruby-core: remember that this header can be possibly * recursively included from extension libraries written in C++. * Do not expect for instance `__VA_ARGS__` is always available. * We assume C99 for ruby itself but we don't assume languages of * extension libraries. They could be written in C++98. * @brief Defines old R_CAST * * Nobody is actively using this macro. */ #define R_CAST(st) (struct st*) #define RMOVED(obj) (R_CAST(RMoved)(obj)) #if defined(__GNUC__) # warning R_CAST and RMOVED are deprecated #elif defined(_MSC_VER) # pragma message("warning: R_CAST and RMOVED are deprecated") #endif #endif /* RUBY_BACKWARD2_R_CAST_H */ include/ruby/backward/2/stdalign.h 0000644 00000003127 15152150470 0013050 0 ustar 00 #ifndef RUBY_BACKWARD2_STDALIGN_H /*-*-C++-*-vi:se ft=cpp:*/ #define RUBY_BACKWARD2_STDALIGN_H /** * @file * @author Ruby developers <ruby-core@ruby-lang.org> * @copyright This file is a part of the programming language Ruby. * Permission is hereby granted, to either redistribute and/or * modify this file, provided that the conditions mentioned in the * file COPYING are met. Consult the file for details. * @warning Symbols prefixed with either `RBIMPL` or `rbimpl` are * implementation details. Don't take them as canon. They could * rapidly appear then vanish. The name (path) of this header file * is also an implementation detail. Do not expect it to persist * at the place it is now. Developers are free to move it anywhere * anytime at will. * @note To ruby-core: remember that this header can be possibly * recursively included from extension libraries written in C++. * Do not expect for instance `__VA_ARGS__` is always available. * We assume C99 for ruby itself but we don't assume languages of * extension libraries. They could be written in C++98. * @brief Defines #RUBY_ALIGNAS / #RUBY_ALIGNOF */ #include "ruby/internal/stdalign.h" #undef RUBY_ALIGNAS #undef RUBY_ALIGNOF #define RUBY_ALIGNAS RBIMPL_ALIGNAS /**< @copydoc RBIMPL_ALIGNAS */ #define RUBY_ALIGNOF RBIMPL_ALIGNOF /**< @copydoc RBIMPL_ALIGNOF */ #endif /* RUBY_BACKWARD2_STDALIGN_H */ include/ruby/backward/2/gcc_version_since.h 0000644 00000003555 15152150470 0014732 0 ustar 00 #ifndef RUBY_BACKWARD2_GCC_VERSION_SINCE_H /*-*-C++-*-vi:se ft=cpp:*/ #define RUBY_BACKWARD2_GCC_VERSION_SINCE_H /** * @author Ruby developers <ruby-core@ruby-lang.org> * @copyright This file is a part of the programming language Ruby. * Permission is hereby granted, to either redistribute and/or * modify this file, provided that the conditions mentioned in the * file COPYING are met. Consult the file for details. * @warning Symbols prefixed with either `RBIMPL` or `rbimpl` are * implementation details. Don't take them as canon. They could * rapidly appear then vanish. The name (path) of this header file * is also an implementation detail. Do not expect it to persist * at the place it is now. Developers are free to move it anywhere * anytime at will. * @note To ruby-core: remember that this header can be possibly * recursively included from extension libraries written in C++. * Do not expect for instance `__VA_ARGS__` is always available. * We assume C99 for ruby itself but we don't assume languages of * extension libraries. They could be written in C++98. * @brief Defines old GCC_VERSION_SINCE */ #include "ruby/internal/compiler_since.h" #ifndef GCC_VERSION_SINCE #define GCC_VERSION_SINCE(x, y, z) RBIMPL_COMPILER_SINCE(GCC, (x), (y), (z)) #endif #ifndef GCC_VERSION_BEFORE #define GCC_VERSION_BEFORE(x, y, z) \ (RBIMPL_COMPILER_BEFORE(GCC, (x), (y), (z)) || \ (RBIMPL_COMPILER_IS(GCC) && \ ((RBIMPL_COMPILER_VERSION_MAJOR == (x)) && \ ((RBIMPL_COMPILER_VERSION_MINOR == (y)) && \ (RBIMPL_COMPILER_VERSION_PATCH == (z)))))) #endif #endif /* RUBY_BACKWARD2_GCC_VERSION_SINCE_H */ include/ruby/backward/2/limits.h 0000644 00000005763 15152150470 0012554 0 ustar 00 #ifndef RUBY_BACKWARD2_LIMITS_H /*-*-C++-*-vi:se ft=cpp:*/ #define RUBY_BACKWARD2_LIMITS_H /** * @author Ruby developers <ruby-core@ruby-lang.org> * @copyright This file is a part of the programming language Ruby. * Permission is hereby granted, to either redistribute and/or * modify this file, provided that the conditions mentioned in the * file COPYING are met. Consult the file for details. * @warning Symbols prefixed with either `RBIMPL` or `rbimpl` are * implementation details. Don't take them as canon. They could * rapidly appear then vanish. The name (path) of this header file * is also an implementation detail. Do not expect it to persist * at the place it is now. Developers are free to move it anywhere * anytime at will. * @note To ruby-core: remember that this header can be possibly * recursively included from extension libraries written in C++. * Do not expect for instance `__VA_ARGS__` is always available. * We assume C99 for ruby itself but we don't assume languages of * extension libraries. They could be written in C++98. * @brief Historical shim for `<limits.h>`. * * The macros in this header file are obsolescent. Does anyone really need our * own definition of `CHAR_BIT` today? */ #include "ruby/internal/config.h" #ifdef HAVE_LIMITS_H # include <limits.h> #endif #include "ruby/backward/2/long_long.h" #ifndef LONG_MAX # /* assuming 32bit(2's complement) long */ # define LONG_MAX 2147483647L #endif #ifndef LONG_MIN # define LONG_MIN (-LONG_MAX-1) #endif #ifndef CHAR_BIT # define CHAR_BIT 8 #endif #ifdef LLONG_MAX # /* Take that. */ #elif defined(LONG_LONG_MAX) # define LLONG_MAX LONG_LONG_MAX #elif defined(_I64_MAX) # define LLONG_MAX _I64_MAX #else # /* assuming 64bit(2's complement) long long */ # define LLONG_MAX 9223372036854775807LL #endif #ifdef LLONG_MIN # /* Take that. */ #elif defined(LONG_LONG_MIN) # define LLONG_MIN LONG_LONG_MIN #elif defined(_I64_MAX) # define LLONG_MIN _I64_MIN #else # define LLONG_MIN (-LLONG_MAX-1) #endif #ifdef SIZE_MAX # /* Take that. */ #elif SIZEOF_SIZE_T == SIZEOF_LONG_LONG # define SIZE_MAX ULLONG_MAX # define SIZE_MIN ULLONG_MIN #elif SIZEOF_SIZE_T == SIZEOF_LONG # define SIZE_MAX ULONG_MAX # define SIZE_MIN ULONG_MIN #elif SIZEOF_SIZE_T == SIZEOF_INT # define SIZE_MAX UINT_MAX # define SIZE_MIN UINT_MIN #else # define SIZE_MAX USHRT_MAX # define SIZE_MIN USHRT_MIN #endif #ifdef SSIZE_MAX # /* Take that. */ #elif SIZEOF_SIZE_T == SIZEOF_LONG_LONG # define SSIZE_MAX LLONG_MAX # define SSIZE_MIN LLONG_MIN #elif SIZEOF_SIZE_T == SIZEOF_LONG # define SSIZE_MAX LONG_MAX # define SSIZE_MIN LONG_MIN #elif SIZEOF_SIZE_T == SIZEOF_INT # define SSIZE_MAX INT_MAX # define SSIZE_MIN INT_MIN #else # define SSIZE_MAX SHRT_MAX # define SSIZE_MIN SHRT_MIN #endif #endif /* RUBY_BACKWARD2_LIMITS_H */ include/ruby/backward/2/rmodule.h 0000644 00000003631 15152150471 0012713 0 ustar 00 #ifndef RUBY_BACKWARD2_RMODULE_H /*-*-C++-*-vi:se ft=cpp:*/ #define RUBY_BACKWARD2_RMODULE_H /** * @author Ruby developers <ruby-core@ruby-lang.org> * @copyright This file is a part of the programming language Ruby. * Permission is hereby granted, to either redistribute and/or * modify this file, provided that the conditions mentioned in the * file COPYING are met. Consult the file for details. * @warning Symbols prefixed with either `RBIMPL` or `rbimpl` are * implementation details. Don't take them as canon. They could * rapidly appear then vanish. The name (path) of this header file * is also an implementation detail. Do not expect it to persist * at the place it is now. Developers are free to move it anywhere * anytime at will. * @note To ruby-core: remember that this header can be possibly * recursively included from extension libraries written in C++. * Do not expect for instance `__VA_ARGS__` is always available. * We assume C99 for ruby itself but we don't assume languages of * extension libraries. They could be written in C++98. * @brief Orphan macros. * * These macros seems broken since at least 2011. Nobody (except ruby itself * who is implementing the internals) could have used those macros for a while. * Kept public as-is here to keep some theoretical backwards compatibility. */ #define RMODULE_IV_TBL(m) RCLASS_IV_TBL(m) #define RMODULE_CONST_TBL(m) RCLASS_CONST_TBL(m) #define RMODULE_M_TBL(m) RCLASS_M_TBL(m) #define RMODULE_SUPER(m) RCLASS_SUPER(m) #if defined(__GNUC__) # warning RMODULE_* macros are deprecated #elif defined(_MSC_VER) # pragma message("warning: RMODULE_* macros are deprecated") #endif #endif /* RUBY_BACKWARD2_RMODULE_H */ include/ruby/backward/2/assume.h 0000644 00000005005 15152150471 0012536 0 ustar 00 #ifndef RUBY_BACKWARD2_ASSUME_H /*-*-C++-*-vi:se ft=cpp:*/ #define RUBY_BACKWARD2_ASSUME_H /** * @file * @author Ruby developers <ruby-core@ruby-lang.org> * @copyright This file is a part of the programming language Ruby. * Permission is hereby granted, to either redistribute and/or * modify this file, provided that the conditions mentioned in the * file COPYING are met. Consult the file for details. * @warning Symbols prefixed with either `RBIMPL` or `rbimpl` are * implementation details. Don't take them as canon. They could * rapidly appear then vanish. The name (path) of this header file * is also an implementation detail. Do not expect it to persist * at the place it is now. Developers are free to move it anywhere * anytime at will. * @note To ruby-core: remember that this header can be possibly * recursively included from extension libraries written in C++. * Do not expect for instance `__VA_ARGS__` is always available. * We assume C99 for ruby itself but we don't assume languages of * extension libraries. They could be written in C++98. * @brief Defines #ASSUME / #RB_LIKELY / #UNREACHABLE */ #include "ruby/internal/config.h" #include "ruby/internal/assume.h" #include "ruby/internal/has/builtin.h" #define ASSUME RBIMPL_ASSUME /**< @old{RBIMPL_ASSUME} */ #define UNREACHABLE RBIMPL_UNREACHABLE() /**< @old{RBIMPL_UNREACHABLE} */ #define UNREACHABLE_RETURN RBIMPL_UNREACHABLE_RETURN /**< @old{RBIMPL_UNREACHABLE_RETURN} */ /* likely */ #if RBIMPL_HAS_BUILTIN(__builtin_expect) /** * Asserts that the given Boolean expression likely holds. * * @param x An expression that likely holds. * * @note Consider this macro carefully. It has been here since when CPUs were * like babies, but contemporary processors are beasts. They are * smarter than mare mortals like us today. Their branch predictions * highly expectedly outperform your use of this macro. */ # define RB_LIKELY(x) (__builtin_expect(!!(x), 1)) /** * Asserts that the given Boolean expression likely doesn't hold. * * @param x An expression that likely doesn't hold. */ # define RB_UNLIKELY(x) (__builtin_expect(!!(x), 0)) #else # define RB_LIKELY(x) (x) # define RB_UNLIKELY(x) (x) #endif #endif /* RUBY_BACKWARD2_ASSUME_H */ include/ruby/backward/2/long_long.h 0000644 00000005720 15152150471 0013223 0 ustar 00 #ifndef RUBY_BACKWARD2_LONG_LONG_H /*-*-C++-*-vi:se ft=cpp:*/ #define RUBY_BACKWARD2_LONG_LONG_H /** * @file * @author Ruby developers <ruby-core@ruby-lang.org> * @copyright This file is a part of the programming language Ruby. * Permission is hereby granted, to either redistribute and/or * modify this file, provided that the conditions mentioned in the * file COPYING are met. Consult the file for details. * @warning Symbols prefixed with either `RBIMPL` or `rbimpl` are * implementation details. Don't take them as canon. They could * rapidly appear then vanish. The name (path) of this header file * is also an implementation detail. Do not expect it to persist * at the place it is now. Developers are free to move it anywhere * anytime at will. * @note To ruby-core: remember that this header can be possibly * recursively included from extension libraries written in C++. * Do not expect for instance `__VA_ARGS__` is always available. * We assume C99 for ruby itself but we don't assume languages of * extension libraries. They could be written in C++98. * @brief Defines old #LONG_LONG * * No known compiler that can compile today's ruby lacks long long. * Historically MSVC was one of such compiler, but it implemented long long a * while ago (some time back in 2013). The macros are for backwards * compatibility only. */ #include "ruby/internal/config.h" #include "ruby/internal/has/warning.h" #include "ruby/internal/warning_push.h" #if defined(__DOXYGEN__) # /** @cond INTERNAL_MACRO */ # define HAVE_LONG_LONG 1 # define HAVE_TRUE_LONG_LONG 1 # /** @endcond */ # /** @deprecated Just use `long long` directly. */ # define LONG_LONG long long. #elif RBIMPL_HAS_WARNING("-Wc++11-long-long") # define HAVE_TRUE_LONG_LONG 1 # define LONG_LONG \ RBIMPL_WARNING_PUSH() \ RBIMPL_WARNING_IGNORED(-Wc++11-long-long) \ long long \ RBIMPL_WARNING_POP() #elif RBIMPL_HAS_WARNING("-Wlong-long") # define HAVE_TRUE_LONG_LONG 1 # define LONG_LONG \ RBIMPL_WARNING_PUSH() \ RBIMPL_WARNING_IGNORED(-Wlong-long) \ long long \ RBIMPL_WARNING_POP() #elif defined(HAVE_LONG_LONG) # define HAVE_TRUE_LONG_LONG 1 # define LONG_LONG long long #elif SIZEOF___INT64 > 0 # define HAVE_LONG_LONG 1 # define LONG_LONG __int64 # undef SIZEOF_LONG_LONG # define SIZEOF_LONG_LONG SIZEOF___INT64 #else # error Hello! Ruby developers believe this message must not happen. # error If you encounter this message, can you file a bug report? # error Remember to attach a detailed description of your environment. # error Thank you! #endif #endif /* RBIMPL_BACKWARD2_LONG_LONG_H */ include/ruby/backward/2/attributes.h 0000644 00000012616 15152150471 0013435 0 ustar 00 #ifndef RUBY_BACKWARD2_ATTRIBUTES_H /*-*-C++-*-vi:se ft=cpp:*/ #define RUBY_BACKWARD2_ATTRIBUTES_H /** * @author Ruby developers <ruby-core@ruby-lang.org> * @copyright This file is a part of the programming language Ruby. * Permission is hereby granted, to either redistribute and/or * modify this file, provided that the conditions mentioned in the * file COPYING are met. Consult the file for details. * @warning Symbols prefixed with either `RBIMPL` or `rbimpl` are * implementation details. Don't take them as canon. They could * rapidly appear then vanish. The name (path) of this header file * is also an implementation detail. Do not expect it to persist * at the place it is now. Developers are free to move it anywhere * anytime at will. * @note To ruby-core: remember that this header can be possibly * recursively included from extension libraries written in C++. * Do not expect for instance `__VA_ARGS__` is always available. * We assume C99 for ruby itself but we don't assume languages of * extension libraries. They could be written in C++98. * @brief Various attribute-related macros. * * ### Q&A ### * * - Q: Why are the macros defined in this header file so inconsistent in * style? * * - A: Don't know. Don't blame me. Backward compatibility is the key here. * I'm just preserving what they have been. */ #include "ruby/internal/config.h" #include "ruby/internal/attr/alloc_size.h" #include "ruby/internal/attr/cold.h" #include "ruby/internal/attr/const.h" #include "ruby/internal/attr/deprecated.h" #include "ruby/internal/attr/error.h" #include "ruby/internal/attr/forceinline.h" #include "ruby/internal/attr/format.h" #include "ruby/internal/attr/maybe_unused.h" #include "ruby/internal/attr/noinline.h" #include "ruby/internal/attr/nonnull.h" #include "ruby/internal/attr/noreturn.h" #include "ruby/internal/attr/packed_struct.h" #include "ruby/internal/attr/pure.h" #include "ruby/internal/attr/restrict.h" #include "ruby/internal/attr/returns_nonnull.h" #include "ruby/internal/attr/warning.h" #include "ruby/internal/has/attribute.h" /* function attributes */ #undef CONSTFUNC #define CONSTFUNC(x) RBIMPL_ATTR_CONST() x #undef PUREFUNC #define PUREFUNC(x) RBIMPL_ATTR_PURE() x #undef DEPRECATED #define DEPRECATED(x) RBIMPL_ATTR_DEPRECATED(("")) x #undef DEPRECATED_BY #define DEPRECATED_BY(n,x) RBIMPL_ATTR_DEPRECATED(("by: " # n)) x #undef DEPRECATED_TYPE #if defined(__GNUC__) # define DEPRECATED_TYPE(mesg, decl) \ _Pragma("message \"DEPRECATED_TYPE is deprecated\""); \ decl RBIMPL_ATTR_DEPRECATED(mseg) #elif defined(_MSC_VER) # pragma deprecated(DEPRECATED_TYPE) # define DEPRECATED_TYPE(mesg, decl) \ __pragma(message(__FILE__"("STRINGIZE(__LINE__)"): warning: " \ "DEPRECATED_TYPE is deprecated")) \ decl RBIMPL_ATTR_DEPRECATED(mseg) #else # define DEPRECATED_TYPE(mesg, decl) \ <-<-"DEPRECATED_TYPE is deprecated"->-> #endif #undef RUBY_CXX_DEPRECATED #define RUBY_CXX_DEPRECATED(mseg) RBIMPL_ATTR_DEPRECATED((mseg)) #undef NOINLINE #define NOINLINE(x) RBIMPL_ATTR_NOINLINE() x #undef ALWAYS_INLINE #define ALWAYS_INLINE(x) RBIMPL_ATTR_FORCEINLINE() x #undef ERRORFUNC #define ERRORFUNC(mesg, x) RBIMPL_ATTR_ERROR(mesg) x #if RBIMPL_HAS_ATTRIBUTE(error) # define HAVE_ATTRIBUTE_ERRORFUNC 1 #endif #undef WARNINGFUNC #define WARNINGFUNC(mesg, x) RBIMPL_ATTR_WARNING(mesg) x #if RBIMPL_HAS_ATTRIBUTE(warning) # define HAVE_ATTRIBUTE_WARNINGFUNC 1 #endif /* cold attribute for code layout improvements RUBY_FUNC_ATTRIBUTE not used because MSVC does not like nested func macros */ #undef COLDFUNC #define COLDFUNC RBIMPL_ATTR_COLD() #define PRINTF_ARGS(decl, string_index, first_to_check) \ RBIMPL_ATTR_FORMAT(RBIMPL_PRINTF_FORMAT, (string_index), (first_to_check)) \ decl #undef RUBY_ATTR_ALLOC_SIZE #define RUBY_ATTR_ALLOC_SIZE RBIMPL_ATTR_ALLOC_SIZE #undef RUBY_ATTR_MALLOC #define RUBY_ATTR_MALLOC RBIMPL_ATTR_RESTRICT() #undef RUBY_ATTR_RETURNS_NONNULL #define RUBY_ATTR_RETURNS_NONNULL RBIMPL_ATTR_RETURNS_NONNULL() #ifndef FUNC_MINIMIZED #define FUNC_MINIMIZED(x) x #endif #ifndef FUNC_UNOPTIMIZED #define FUNC_UNOPTIMIZED(x) x #endif #ifndef RUBY_ALIAS_FUNCTION_TYPE #define RUBY_ALIAS_FUNCTION_TYPE(type, prot, name, args) \ FUNC_MINIMIZED(type prot) {return (type)name args;} #endif #ifndef RUBY_ALIAS_FUNCTION_VOID #define RUBY_ALIAS_FUNCTION_VOID(prot, name, args) \ FUNC_MINIMIZED(void prot) {name args;} #endif #ifndef RUBY_ALIAS_FUNCTION #define RUBY_ALIAS_FUNCTION(prot, name, args) \ RUBY_ALIAS_FUNCTION_TYPE(VALUE, prot, name, args) #endif #undef RUBY_FUNC_NONNULL #define RUBY_FUNC_NONNULL(n, x) RBIMPL_ATTR_NONNULL(n) x #undef NORETURN #define NORETURN(x) RBIMPL_ATTR_NORETURN() x #define NORETURN_STYLE_NEW #undef PACKED_STRUCT #define PACKED_STRUCT(x) \ RBIMPL_ATTR_PACKED_STRUCT_BEGIN() x RBIMPL_ATTR_PACKED_STRUCT_END() #undef PACKED_STRUCT_UNALIGNED #define PACKED_STRUCT_UNALIGNED(x) \ RBIMPL_ATTR_PACKED_STRUCT_UNALIGNED_BEGIN() x \ RBIMPL_ATTR_PACKED_STRUCT_UNALIGNED_END() #undef RB_UNUSED_VAR #define RB_UNUSED_VAR(x) x RBIMPL_ATTR_MAYBE_UNUSED() #endif /* RUBY_BACKWARD2_ATTRIBUTES_H */ include/ruby/backward/2/bool.h 0000644 00000003051 15152150471 0012173 0 ustar 00 #ifndef RUBY_BACKWARD2_BOOL_H /*-*-C++-*-vi:se ft=cpp:*/ #define RUBY_BACKWARD2_BOOL_H /** * @author Ruby developers <ruby-core@ruby-lang.org> * @copyright This file is a part of the programming language Ruby. * Permission is hereby granted, to either redistribute and/or * modify this file, provided that the conditions mentioned in the * file COPYING are met. Consult the file for details. * @warning Symbols prefixed with either `RBIMPL` or `rbimpl` are * implementation details. Don't take them as canon. They could * rapidly appear then vanish. The name (path) of this header file * is also an implementation detail. Do not expect it to persist * at the place it is now. Developers are free to move it anywhere * anytime at will. * @note To ruby-core: remember that this header can be possibly * recursively included from extension libraries written in C++. * Do not expect for instance `__VA_ARGS__` is always available. * We assume C99 for ruby itself but we don't assume languages of * extension libraries. They could be written in C++98. * @brief Defines old TRUE / FALSE */ #include "ruby/internal/stdbool.h" #ifndef FALSE # define FALSE false #elif FALSE # error FALSE must be false #endif #ifndef TRUE # define TRUE true #elif ! TRUE # error TRUE must be true #endif #endif /* RUBY_BACKWARD2_BOOL_H */ include/ruby/backward/cxxanyargs.hpp 0000644 00000074055 15152150471 0013642 0 ustar 00 #ifndef RUBY_BACKWARD_CXXANYARGS_HPP //-*-C++-*-vi:ft=cpp #define RUBY_BACKWARD_CXXANYARGS_HPP /// @file /// @author @shyouhei /// @copyright This file is a part of the programming language Ruby. /// Permission is hereby granted, to either redistribute and/or /// modify this file, provided that the conditions mentioned in the /// file COPYING are met. Consult the file for details. /// @note DO NOT MODERNISE THIS FILE! As the file name implies it is /// meant to be a backwards compatibility shim. Please stick to /// C++ 98 and never use newer features, like `constexpr`. /// @brief Provides old prototypes for C++ programs. #include "ruby/internal/config.h" #include "ruby/internal/intern/class.h" #include "ruby/internal/intern/cont.h" #include "ruby/internal/intern/hash.h" #include "ruby/internal/intern/proc.h" #include "ruby/internal/intern/thread.h" #include "ruby/internal/intern/variable.h" #include "ruby/internal/intern/vm.h" #include "ruby/internal/iterator.h" #include "ruby/internal/method.h" #include "ruby/internal/value.h" #include "ruby/internal/variable.h" #include "ruby/backward/2/stdarg.h" #include "ruby/st.h" extern "C++" { #ifdef HAVE_NULLPTR #include <cstddef> #endif /// @brief The main namespace. /// @note The name "ruby" might already be taken, but that must not be a /// problem because namespaces are allowed to reopen. namespace ruby { /// Backwards compatibility layer. namespace backward { /// Provides ANYARGS deprecation warnings. In C, ANYARGS means there is no /// function prototype. Literally anything, even including nothing, can be a /// valid ANYARGS. So passing a correctly prototyped function pointer to an /// ANYARGS-ed function parameter is valid, at the same time passing an /// ANYARGS-ed function pointer to a granular typed function parameter is also /// valid. However on the other hand in C++, ANYARGS doesn't actually mean any /// number of arguments. C++'s ANYARGS means _variadic_ number of arguments. /// This is incompatible with ordinal, correct function prototypes. /// /// Luckily, function prototypes being distinct each other means they can be /// overloaded. We can provide a compatibility layer for older Ruby APIs which /// used to have ANYARGS. This namespace includes such attempts. namespace cxxanyargs { typedef VALUE type(ANYARGS); ///< ANYARGS-ed function type. typedef void void_type(ANYARGS); ///< ANYARGS-ed function type, void variant. typedef int int_type(ANYARGS); ///< ANYARGS-ed function type, int variant. typedef VALUE onearg_type(VALUE); ///< Single-argumented function type. /// @name Hooking global variables /// @{ RUBY_CXX_DEPRECATED("Use of ANYARGS in this function is deprecated") /// @brief Define a function-backended global variable. /// @param[in] q Name of the variable. /// @param[in] w Getter function. /// @param[in] e Setter function. /// @note Both functions can be nullptr. /// @see rb_define_hooked_variable() /// @deprecated Use granular typed overload instead. inline void rb_define_virtual_variable(const char *q, type *w, void_type *e) { rb_gvar_getter_t *r = reinterpret_cast<rb_gvar_getter_t*>(w); rb_gvar_setter_t *t = reinterpret_cast<rb_gvar_setter_t*>(e); ::rb_define_virtual_variable(q, r, t); } RUBY_CXX_DEPRECATED("Use of ANYARGS in this function is deprecated") inline void rb_define_virtual_variable(const char *q, rb_gvar_getter_t *w, void_type *e) { rb_gvar_setter_t *t = reinterpret_cast<rb_gvar_setter_t*>(e); ::rb_define_virtual_variable(q, w, t); } RUBY_CXX_DEPRECATED("Use of ANYARGS in this function is deprecated") inline void rb_define_virtual_variable(const char *q, type *w, rb_gvar_setter_t *e) { rb_gvar_getter_t *r = reinterpret_cast<rb_gvar_getter_t*>(w); ::rb_define_virtual_variable(q, r, e); } #ifdef HAVE_NULLPTR inline void rb_define_virtual_variable(const char *q, rb_gvar_getter_t *w, std::nullptr_t e) { ::rb_define_virtual_variable(q, w, e); } RUBY_CXX_DEPRECATED("Use of ANYARGS in this function is deprecated") inline void rb_define_virtual_variable(const char *q, type *w, std::nullptr_t e) { rb_gvar_getter_t *r = reinterpret_cast<rb_gvar_getter_t *>(w); ::rb_define_virtual_variable(q, r, e); } inline void rb_define_virtual_variable(const char *q, std::nullptr_t w, rb_gvar_setter_t *e) { ::rb_define_virtual_variable(q, w, e); } RUBY_CXX_DEPRECATED("Use of ANYARGS in this function is deprecated") inline void rb_define_virtual_variable(const char *q, std::nullptr_t w, void_type *e) { rb_gvar_setter_t *r = reinterpret_cast<rb_gvar_setter_t *>(e); ::rb_define_virtual_variable(q, w, r); } #endif RUBY_CXX_DEPRECATED("Use of ANYARGS in this function is deprecated") /// @brief Define a function-backended global variable. /// @param[in] q Name of the variable. /// @param[in] w Variable storage. /// @param[in] e Getter function. /// @param[in] r Setter function. /// @note Both functions can be nullptr. /// @see rb_define_virtual_variable() /// @deprecated Use granular typed overload instead. inline void rb_define_hooked_variable(const char *q, VALUE *w, type *e, void_type *r) { rb_gvar_getter_t *t = reinterpret_cast<rb_gvar_getter_t*>(e); rb_gvar_setter_t *y = reinterpret_cast<rb_gvar_setter_t*>(r); ::rb_define_hooked_variable(q, w, t, y); } RUBY_CXX_DEPRECATED("Use of ANYARGS in this function is deprecated") inline void rb_define_hooked_variable(const char *q, VALUE *w, rb_gvar_getter_t *e, void_type *r) { rb_gvar_setter_t *y = reinterpret_cast<rb_gvar_setter_t*>(r); ::rb_define_hooked_variable(q, w, e, y); } RUBY_CXX_DEPRECATED("Use of ANYARGS in this function is deprecated") inline void rb_define_hooked_variable(const char *q, VALUE *w, type *e, rb_gvar_setter_t *r) { rb_gvar_getter_t *t = reinterpret_cast<rb_gvar_getter_t*>(e); ::rb_define_hooked_variable(q, w, t, r); } #ifdef HAVE_NULLPTR inline void rb_define_hooked_variable(const char *q, VALUE *w, rb_gvar_getter_t *e, std::nullptr_t r) { ::rb_define_hooked_variable(q, w, e, r); } RUBY_CXX_DEPRECATED("Use of ANYARGS in this function is deprecated") inline void rb_define_hooked_variable(const char *q, VALUE *w, type *e, std::nullptr_t r) { rb_gvar_getter_t *y = reinterpret_cast<rb_gvar_getter_t *>(e); ::rb_define_hooked_variable(q, w, y, r); } inline void rb_define_hooked_variable(const char *q, VALUE *w, std::nullptr_t e, rb_gvar_setter_t *r) { ::rb_define_hooked_variable(q, w, e, r); } RUBY_CXX_DEPRECATED("Use of ANYARGS in this function is deprecated") inline void rb_define_hooked_variable(const char *q, VALUE *w, std::nullptr_t e, void_type *r) { rb_gvar_setter_t *y = reinterpret_cast<rb_gvar_setter_t *>(r); ::rb_define_hooked_variable(q, w, e, y); } #endif /// @} /// @name Exceptions and tag jumps /// @{ // RUBY_CXX_DEPRECATED("by rb_block_call since 1.9") RUBY_CXX_DEPRECATED("Use of ANYARGS in this function is deprecated") /// @brief Old way to implement iterators. /// @param[in] q A function that can yield. /// @param[in] w Passed to `q`. /// @param[in] e What is to be yielded. /// @param[in] r Passed to `e`. /// @return The return value of `q`. /// @note `e` can be nullptr. /// @deprecated This function is obsoleted since long before 2.x era. Do not /// use it any longer. rb_block_call() is provided instead. inline VALUE rb_iterate(onearg_type *q, VALUE w, type *e, VALUE r) { rb_block_call_func_t t = reinterpret_cast<rb_block_call_func_t>(e); return backward::rb_iterate_deprecated(q, w, t, r); } #ifdef HAVE_NULLPTR RUBY_CXX_DEPRECATED("by rb_block_call since 1.9") inline VALUE rb_iterate(onearg_type *q, VALUE w, std::nullptr_t e, VALUE r) { return backward::rb_iterate_deprecated(q, w, e, r); } #endif RUBY_CXX_DEPRECATED("Use of ANYARGS in this function is deprecated") /// @brief Call a method with a block. /// @param[in] q The self. /// @param[in] w The method. /// @param[in] e The # of elems of `r` /// @param[in] r The arguments. /// @param[in] t What is to be yielded. /// @param[in] y Passed to `t` /// @return Return value of `q#w(*r,&t)` /// @note 't' can be nullptr. /// @deprecated Use granular typed overload instead. inline VALUE rb_block_call(VALUE q, ID w, int e, const VALUE *r, type *t, VALUE y) { rb_block_call_func_t u = reinterpret_cast<rb_block_call_func_t>(t); return ::rb_block_call(q, w, e, r, u, y); } #ifdef HAVE_NULLPTR inline VALUE rb_block_call(VALUE q, ID w, int e, const VALUE *r, std::nullptr_t t, VALUE y) { return ::rb_block_call(q, w, e, r, t, y); } #endif RUBY_CXX_DEPRECATED("Use of ANYARGS in this function is deprecated") /// @brief An equivalent of `rescue` clause. /// @param[in] q A function that can raise. /// @param[in] w Passed to `q`. /// @param[in] e A function that cleans-up. /// @param[in] r Passed to `e`. /// @return The return value of `q` if no exception occurs, or the return /// value of `e` if otherwise. /// @note `e` can be nullptr. /// @see rb_ensure() /// @see rb_rescue2() /// @see rb_protect() /// @deprecated Use granular typed overload instead. inline VALUE rb_rescue(type *q, VALUE w, type *e, VALUE r) { typedef VALUE func1_t(VALUE); typedef VALUE func2_t(VALUE, VALUE); func1_t *t = reinterpret_cast<func1_t*>(q); func2_t *y = reinterpret_cast<func2_t*>(e); return ::rb_rescue(t, w, y, r); } RUBY_CXX_DEPRECATED("Use of ANYARGS in this function is deprecated") /// @brief An equivalent of `rescue` clause. /// @param[in] q A function that can raise. /// @param[in] w Passed to `q`. /// @param[in] e A function that cleans-up. /// @param[in] r Passed to `e`. /// @param[in] ... 0-terminated list of subclass of @ref rb_eException. /// @return The return value of `q` if no exception occurs, or the return /// value of `e` if otherwise. /// @note `e` can be nullptr. /// @see rb_ensure() /// @see rb_rescue() /// @see rb_protect() /// @deprecated Use granular typed overload instead. inline VALUE rb_rescue2(type *q, VALUE w, type *e, VALUE r, ...) { typedef VALUE func1_t(VALUE); typedef VALUE func2_t(VALUE, VALUE); func1_t *t = reinterpret_cast<func1_t*>(q); func2_t *y = reinterpret_cast<func2_t*>(e); va_list ap; va_start(ap, r); VALUE ret = ::rb_vrescue2(t, w, y, r, ap); va_end(ap); return ret; } RUBY_CXX_DEPRECATED("Use of ANYARGS in this function is deprecated") /// @brief An equivalent of `ensure` clause. /// @param[in] q A function that can raise. /// @param[in] w Passed to `q`. /// @param[in] e A function that ensures. /// @param[in] r Passed to `e`. /// @return The return value of `q`. /// @note It makes no sense to pass nullptr to `e`. /// @see rb_rescue() /// @see rb_rescue2() /// @see rb_protect() /// @deprecated Use granular typed overload instead. inline VALUE rb_ensure(type *q, VALUE w, type *e, VALUE r) { typedef VALUE func1_t(VALUE); func1_t *t = reinterpret_cast<func1_t*>(q); func1_t *y = reinterpret_cast<func1_t*>(e); return ::rb_ensure(t, w, y, r); } RUBY_CXX_DEPRECATED("Use of ANYARGS in this function is deprecated") /// @brief An equivalent of `Kernel#catch`. /// @param[in] q The "tag" string. /// @param[in] w A function that can throw. /// @param[in] e Passed to `w`. /// @return What was thrown. /// @note `q` can be a nullptr but makes no sense to pass nullptr to`w`. /// @see rb_block_call() /// @see rb_protect() /// @see rb_rb_catch_obj() /// @see rb_rescue() /// @deprecated Use granular typed overload instead. inline VALUE rb_catch(const char *q, type *w, VALUE e) { rb_block_call_func_t r = reinterpret_cast<rb_block_call_func_t>(w); return ::rb_catch(q, r, e); } #ifdef HAVE_NULLPTR inline VALUE rb_catch(const char *q, std::nullptr_t w, VALUE e) { return ::rb_catch(q, w, e); } #endif RUBY_CXX_DEPRECATED("Use of ANYARGS in this function is deprecated") /// @brief An equivalent of `Kernel#catch`. /// @param[in] q The "tag" object. /// @param[in] w A function that can throw. /// @param[in] e Passed to `w`. /// @return What was thrown. /// @note It makes no sense to pass nullptr to`w`. /// @see rb_block_call() /// @see rb_protect() /// @see rb_rb_catch_obj() /// @see rb_rescue() /// @deprecated Use granular typed overload instead. inline VALUE rb_catch_obj(VALUE q, type *w, VALUE e) { rb_block_call_func_t r = reinterpret_cast<rb_block_call_func_t>(w); return ::rb_catch_obj(q, r, e); } /// @} /// @name Procs, Fibers and Threads /// @{ RUBY_CXX_DEPRECATED("Use of ANYARGS in this function is deprecated") /// @brief Creates a rb_cFiber instance. /// @param[in] q The fiber body. /// @param[in] w Passed to `q`. /// @return What was allocated. /// @note It makes no sense to pass nullptr to`q`. /// @see rb_proc_new() /// @see rb_thread_create() /// @deprecated Use granular typed overload instead. inline VALUE rb_fiber_new(type *q, VALUE w) { rb_block_call_func_t e = reinterpret_cast<rb_block_call_func_t>(q); return ::rb_fiber_new(e, w); } RUBY_CXX_DEPRECATED("Use of ANYARGS in this function is deprecated") /// @brief Creates a @ref rb_cProc instance. /// @param[in] q The proc body. /// @param[in] w Passed to `q`. /// @return What was allocated. /// @note It makes no sense to pass nullptr to`q`. /// @see rb_fiber_new() /// @see rb_thread_create() /// @deprecated Use granular typed overload instead. inline VALUE rb_proc_new(type *q, VALUE w) { rb_block_call_func_t e = reinterpret_cast<rb_block_call_func_t>(q); return ::rb_proc_new(e, w); } RUBY_CXX_DEPRECATED("Use of ANYARGS in this function is deprecated") /// @brief Creates a @ref rb_cThread instance. /// @param[in] q The thread body. /// @param[in] w Passed to `q`. /// @return What was allocated. /// @note It makes no sense to pass nullptr to`q`. /// @see rb_proc_new() /// @see rb_fiber_new() /// @deprecated Use granular typed overload instead. inline VALUE rb_thread_create(type *q, void *w) { typedef VALUE ptr_t(void*); ptr_t *e = reinterpret_cast<ptr_t*>(q); return ::rb_thread_create(e, w); } /// @} /// @name Hash and st_table /// @{ RUBY_CXX_DEPRECATED("Use of ANYARGS in this function is deprecated") /// @brief Iteration over the given table. /// @param[in] q A table to scan. /// @param[in] w A function to iterate. /// @param[in] e Passed to `w`. /// @retval 0 Always returns 0. /// @note It makes no sense to pass nullptr to`w`. /// @see st_foreach_check() /// @see rb_hash_foreach() /// @deprecated Use granular typed overload instead. inline int st_foreach(st_table *q, int_type *w, st_data_t e) { st_foreach_callback_func *r = reinterpret_cast<st_foreach_callback_func*>(w); return ::st_foreach(q, r, e); } RUBY_CXX_DEPRECATED("Use of ANYARGS in this function is deprecated") /// @brief Iteration over the given table. /// @param[in] q A table to scan. /// @param[in] w A function to iterate. /// @param[in] e Passed to `w`. /// @retval 0 Successful end of iteration. /// @retval 1 Element removed during traversing. /// @note It makes no sense to pass nullptr to`w`. /// @see st_foreach() /// @deprecated Use granular typed overload instead. inline int st_foreach_check(st_table *q, int_type *w, st_data_t e, st_data_t) { st_foreach_check_callback_func *t = reinterpret_cast<st_foreach_check_callback_func*>(w); return ::st_foreach_check(q, t, e, 0); } RUBY_CXX_DEPRECATED("Use of ANYARGS in this function is deprecated") /// @brief Iteration over the given table. /// @param[in] q A table to scan. /// @param[in] w A function to iterate. /// @param[in] e Passed to `w`. /// @note It makes no sense to pass nullptr to`w`. /// @see st_foreach_check() /// @deprecated Use granular typed overload instead. inline void st_foreach_safe(st_table *q, int_type *w, st_data_t e) { st_foreach_callback_func *r = reinterpret_cast<st_foreach_callback_func*>(w); ::st_foreach_safe(q, r, e); } RUBY_CXX_DEPRECATED("Use of ANYARGS in this function is deprecated") /// @brief Iteration over the given hash. /// @param[in] q A hash to scan. /// @param[in] w A function to iterate. /// @param[in] e Passed to `w`. /// @note It makes no sense to pass nullptr to`w`. /// @see st_foreach() /// @deprecated Use granular typed overload instead. inline void rb_hash_foreach(VALUE q, int_type *w, VALUE e) { st_foreach_callback_func *r = reinterpret_cast<st_foreach_callback_func*>(w); ::rb_hash_foreach(q, r, e); } RUBY_CXX_DEPRECATED("Use of ANYARGS in this function is deprecated") /// @brief Iteration over each instance variable of the object. /// @param[in] q An object. /// @param[in] w A function to iterate. /// @param[in] e Passed to `w`. /// @note It makes no sense to pass nullptr to`w`. /// @see st_foreach() /// @deprecated Use granular typed overload instead. inline void rb_ivar_foreach(VALUE q, int_type *w, VALUE e) { st_foreach_callback_func *r = reinterpret_cast<st_foreach_callback_func*>(w); ::rb_ivar_foreach(q, r, e); } /// @} /// Driver for *_define_method. ::rb_define_method function for instance takes /// a pointer to ANYARGS-ed functions, which in fact varies 18 different /// prototypes. We still need to preserve ANYARGS for storages but why not /// check the consistencies if possible. In C++ a function has its own /// prototype, which is a compile-time constant (static type) by nature. We /// can list up all the possible input types and provide warnings for other /// cases. This is such attempt. namespace define_method { /// Type of ::rb_f_notimplement(). typedef VALUE notimpl_type(int, const VALUE *, VALUE, VALUE); /// @brief Template metaprogramming to generate function prototypes. /// @tparam T Type of method id (`ID` or `const char*` in practice). /// @tparam F Definition driver e.g. ::rb_define_method. template<typename T, void (*F)(VALUE klass, T mid, type *func, int arity)> struct driver { /// @brief Defines a method /// @tparam N Arity of the function. /// @tparam U The function in question template<int N, typename U> struct engine { /* :TODO: Following deprecation attribute renders tons of warnings (one * per every method definitions), which is annoying. Of course * annoyance is the core feature of deprecation warnings... But that * could be too much, especially when the warnings happen inside of * machine-generated programs. And SWIG is known to do such thing. * The new (granular) API was introduced in API version 2.7. As of * this writing the version is 2.8. Let's warn this later, some time * during 3.x. Hopefully codes in old (ANYARGS-ed) format should be * less than now. */ #if (RUBY_API_VERSION_MAJOR * 100 + RUBY_API_VERSION_MINOR) >= 301 RUBY_CXX_DEPRECATED("use of ANYARGS is deprecated") #endif /// @copydoc define(VALUE klass, T mid, U func) /// @deprecated Pass correctly typed function instead. static inline void define(VALUE klass, T mid, type func) { F(klass, mid, func, N); } /// @brief Defines klass#mid as func, whose arity is N. /// @param[in] klass Where the method lives. /// @param[in] mid Name of the method to define. /// @param[in] func Function that implements klass#mid. static inline void define(VALUE klass, T mid, U func) { F(klass, mid, reinterpret_cast<type *>(func), N); } /// @copydoc define(VALUE klass, T mid, U func) static inline void define(VALUE klass, T mid, notimpl_type func) { F(klass, mid, reinterpret_cast<type *>(func), N); } }; /// @cond INTERNAL_MACRO template<int N, bool = false> struct specific : public engine<N, type *> {}; template<bool b> struct specific<15, b> : public engine<15, VALUE(*)(VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE)> {}; template<bool b> struct specific<14, b> : public engine<14, VALUE(*)(VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE)> {}; template<bool b> struct specific<13, b> : public engine<13, VALUE(*)(VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE)> {}; template<bool b> struct specific<12, b> : public engine<12, VALUE(*)(VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE)> {}; template<bool b> struct specific<11, b> : public engine<11, VALUE(*)(VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE)> {}; template<bool b> struct specific<10, b> : public engine<10, VALUE(*)(VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE)> {}; template<bool b> struct specific< 9, b> : public engine< 9, VALUE(*)(VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE)> {}; template<bool b> struct specific< 8, b> : public engine< 8, VALUE(*)(VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE)> {}; template<bool b> struct specific< 7, b> : public engine< 7, VALUE(*)(VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE)> {}; template<bool b> struct specific< 6, b> : public engine< 6, VALUE(*)(VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE)> {}; template<bool b> struct specific< 5, b> : public engine< 5, VALUE(*)(VALUE, VALUE, VALUE, VALUE, VALUE, VALUE)> {}; template<bool b> struct specific< 4, b> : public engine< 4, VALUE(*)(VALUE, VALUE, VALUE, VALUE, VALUE)> {}; template<bool b> struct specific< 3, b> : public engine< 3, VALUE(*)(VALUE, VALUE, VALUE, VALUE)> {}; template<bool b> struct specific< 2, b> : public engine< 2, VALUE(*)(VALUE, VALUE, VALUE)> {}; template<bool b> struct specific< 1, b> : public engine< 1, VALUE(*)(VALUE, VALUE)> {}; template<bool b> struct specific< 0, b> : public engine< 0, VALUE(*)(VALUE)> {}; template<bool b> struct specific<-1, b> : public engine<-1, VALUE(*)(int argc, VALUE *argv, VALUE self)> { using engine<-1, VALUE(*)(int argc, VALUE *argv, VALUE self)>::define; static inline void define(VALUE c, T m, VALUE(*f)(int argc, const VALUE *argv, VALUE self)) { F(c, m, reinterpret_cast<type *>(f), -1); } }; template<bool b> struct specific<-2, b> : public engine<-2, VALUE(*)(VALUE, VALUE)> {}; /// @endcond }; /* We could perhaps merge this struct into the one above using variadic * template parameters if we could assume C++11, but sadly we cannot. */ /// @copydoc ruby::backward::cxxanyargs::define_method::driver template<typename T, void (*F)(T mid, type func, int arity)> struct driver0 { /// @brief Defines a method /// @tparam N Arity of the function. /// @tparam U The function in question template<int N, typename U> struct engine { RUBY_CXX_DEPRECATED("use of ANYARGS is deprecated") /// @copydoc define(T mid, U func) /// @deprecated Pass correctly typed function instead. static inline void define(T mid, type func) { F(mid, func, N); } /// @brief Defines Kernel#mid as func, whose arity is N. /// @param[in] mid Name of the method to define. /// @param[in] func Function that implements klass#mid. static inline void define(T mid, U func) { F(mid, reinterpret_cast<type *>(func), N); } /// @copydoc define(T mid, U func) /// @deprecated Pass correctly typed function instead. static inline void define(T mid, notimpl_type func) { F(mid, reinterpret_cast<type *>(func), N); } }; /// @cond INTERNAL_MACRO template<int N, bool = false> struct specific : public engine<N, type *> {}; template<bool b> struct specific<15, b> : public engine<15, VALUE(*)(VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE)> {}; template<bool b> struct specific<14, b> : public engine<14, VALUE(*)(VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE)> {}; template<bool b> struct specific<13, b> : public engine<13, VALUE(*)(VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE)> {}; template<bool b> struct specific<12, b> : public engine<12, VALUE(*)(VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE)> {}; template<bool b> struct specific<11, b> : public engine<11, VALUE(*)(VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE)> {}; template<bool b> struct specific<10, b> : public engine<10, VALUE(*)(VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE)> {}; template<bool b> struct specific< 9, b> : public engine< 9, VALUE(*)(VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE)> {}; template<bool b> struct specific< 8, b> : public engine< 8, VALUE(*)(VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE)> {}; template<bool b> struct specific< 7, b> : public engine< 7, VALUE(*)(VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE)> {}; template<bool b> struct specific< 6, b> : public engine< 6, VALUE(*)(VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE)> {}; template<bool b> struct specific< 5, b> : public engine< 5, VALUE(*)(VALUE, VALUE, VALUE, VALUE, VALUE, VALUE)> {}; template<bool b> struct specific< 4, b> : public engine< 4, VALUE(*)(VALUE, VALUE, VALUE, VALUE, VALUE)> {}; template<bool b> struct specific< 3, b> : public engine< 3, VALUE(*)(VALUE, VALUE, VALUE, VALUE)> {}; template<bool b> struct specific< 2, b> : public engine< 2, VALUE(*)(VALUE, VALUE, VALUE)> {}; template<bool b> struct specific< 1, b> : public engine< 1, VALUE(*)(VALUE, VALUE)> {}; template<bool b> struct specific< 0, b> : public engine< 0, VALUE(*)(VALUE)> {}; template<bool b> struct specific<-1, b> : public engine<-1, VALUE(*)(int argc, VALUE *argv, VALUE self)> { using engine<-1, VALUE(*)(int argc, VALUE *argv, VALUE self)>::define; static inline void define(T m, VALUE(*f)(int argc, const VALUE *argv, VALUE self)) { F(m, reinterpret_cast<type *>(f), -1); } }; template<bool b> struct specific<-2, b> : public engine<-2, VALUE(*)(VALUE, VALUE)> {}; /// @endcond }; struct rb_define_method : public driver <const char *, ::rb_define_method> {}; ///< Dispatches appropriate driver for ::rb_define_method. struct rb_define_method_id : public driver <ID, ::rb_define_method_id> {}; ///< Dispatches appropriate driver for ::rb_define_method_id. struct rb_define_private_method : public driver <const char *, ::rb_define_private_method> {}; ///< Dispatches appropriate driver for ::rb_define_private_method. struct rb_define_protected_method : public driver <const char *, ::rb_define_protected_method> {}; ///< Dispatches appropriate driver for ::rb_define_protected_method. struct rb_define_singleton_method : public driver <const char *, ::rb_define_singleton_method> {}; ///< Dispatches appropriate driver for ::rb_define_singleton_method. struct rb_define_module_function : public driver <const char *, ::rb_define_module_function> {}; ///< Dispatches appropriate driver for ::rb_define_module_function. struct rb_define_global_function : public driver0<const char *, ::rb_define_global_function> {}; ///< Dispatches appropriate driver for ::rb_define_global_function. /// @brief Defines klass\#mid. /// @param klass Where the method lives. /// @copydetails #rb_define_global_function(mid, func, arity) #define rb_define_method(klass, mid, func, arity) ::ruby::backward::cxxanyargs::define_method::rb_define_method::specific<arity>::define(klass, mid, func) /// @copydoc #rb_define_method(klass, mid, func, arity) #define rb_define_method_id(klass, mid, func, arity) ::ruby::backward::cxxanyargs::define_method::rb_define_method_id::specific<arity>::define(klass, mid, func) /// @brief Defines klass\#mid and makes it private. /// @copydetails #rb_define_method(klass, mid, func, arity) #define rb_define_private_method(klass, mid, func, arity) ::ruby::backward::cxxanyargs::define_method::rb_define_private_method::specific<arity>::define(klass, mid, func) /// @brief Defines klass\#mid and makes it protected. /// @copydetails #rb_define_method #define rb_define_protected_method(klass, mid, func, arity) ::ruby::backward::cxxanyargs::define_method::rb_define_protected_method::specific<arity>::define(klass, mid, func) /// @brief Defines klass.mid.(klass, mid, func, arity) /// @copydetails #rb_define_method #define rb_define_singleton_method(klass, mid, func, arity) ::ruby::backward::cxxanyargs::define_method::rb_define_singleton_method::specific<arity>::define(klass, mid, func) /// @brief Defines klass\#mid and makes it a module function. /// @copydetails #rb_define_method(klass, mid, func, arity) #define rb_define_module_function(klass, mid, func, arity) ::ruby::backward::cxxanyargs::define_method::rb_define_module_function::specific<arity>::define(klass, mid, func) /// @brief Defines ::rb_mKernel \#mid. /// @param mid Name of the defining method. /// @param func Implementation of \#mid. /// @param arity Arity of \#mid. #define rb_define_global_function(mid, func, arity) ::ruby::backward::cxxanyargs::define_method::rb_define_global_function::specific<arity>::define(mid, func) }}}}} using namespace ruby::backward::cxxanyargs; #endif // RUBY_BACKWARD_CXXANYARGS_HPP include/ruby/intern.h 0000644 00000004465 15152150471 0010632 0 ustar 00 #ifndef RUBY_INTERN_H /*-*-C++-*-vi:se ft=cpp:*/ #define RUBY_INTERN_H 1 /** * @file * @author $Author$ * @date Thu Jun 10 14:22:17 JST 1993 * @copyright Copyright (C) 1993-2007 Yukihiro Matsumoto * @copyright Copyright (C) 2000 Network Applied Communication Laboratory, Inc. * @copyright Copyright (C) 2000 Information-technology Promotion Agency, Japan * @copyright This file is a part of the programming language Ruby. * Permission is hereby granted, to either redistribute and/or * modify this file, provided that the conditions mentioned in the * file COPYING are met. Consult the file for details. */ #include "ruby/internal/config.h" #include "ruby/defines.h" #include <stdarg.h> #include "ruby/st.h" /* * Functions and variables that are used by more than one source file of * the kernel. */ #include "ruby/internal/intern/array.h" #include "ruby/internal/intern/bignum.h" #include "ruby/internal/intern/class.h" #include "ruby/internal/intern/compar.h" #include "ruby/internal/intern/complex.h" #include "ruby/internal/intern/cont.h" #include "ruby/internal/intern/dir.h" #include "ruby/internal/intern/enum.h" #include "ruby/internal/intern/enumerator.h" #include "ruby/internal/intern/error.h" #include "ruby/internal/intern/eval.h" #include "ruby/internal/intern/file.h" #include "ruby/internal/intern/hash.h" #include "ruby/internal/intern/io.h" #include "ruby/internal/intern/load.h" #include "ruby/internal/intern/marshal.h" #include "ruby/internal/intern/numeric.h" #include "ruby/internal/intern/object.h" #include "ruby/internal/intern/parse.h" #include "ruby/internal/intern/proc.h" #include "ruby/internal/intern/process.h" #include "ruby/internal/intern/random.h" #include "ruby/internal/intern/range.h" #include "ruby/internal/intern/rational.h" #include "ruby/internal/intern/re.h" #include "ruby/internal/intern/ruby.h" #include "ruby/internal/intern/select.h" #include "ruby/internal/intern/signal.h" #include "ruby/internal/intern/sprintf.h" #include "ruby/internal/intern/string.h" #include "ruby/internal/intern/struct.h" #include "ruby/internal/intern/thread.h" #include "ruby/internal/intern/time.h" #include "ruby/internal/intern/variable.h" #include "ruby/internal/intern/vm.h" #endif /* RUBY_INTERN_H */ include/ruby/encoding.h 0000644 00000002440 15152150471 0011110 0 ustar 00 #ifndef RUBY_ENCODING_H /*-*-C++-*-vi:se ft=cpp:*/ #define RUBY_ENCODING_H 1 /** * @file * @author $Author: matz $ * @date Thu May 24 11:49:41 JST 2007 * @copyright Copyright (C) 2007 Yukihiro Matsumoto * @copyright This file is a part of the programming language Ruby. * Permission is hereby granted, to either redistribute and/or * modify this file, provided that the conditions mentioned in the * file COPYING are met. Consult the file for details. * @brief Encoding relates APIs. * * These APIs are mainly for implementing encodings themselves. Encodings are * built on top of Ruby's core CAPIs. Though not prohibited, there can be * relatively less rooms for things in this header file be useful when writing * an extension library. */ #include "ruby/ruby.h" #include "ruby/internal/encoding/coderange.h" #include "ruby/internal/encoding/ctype.h" #include "ruby/internal/encoding/encoding.h" #include "ruby/internal/encoding/pathname.h" #include "ruby/internal/encoding/re.h" #include "ruby/internal/encoding/sprintf.h" #include "ruby/internal/encoding/string.h" #include "ruby/internal/encoding/symbol.h" #include "ruby/internal/encoding/transcode.h" #endif /* RUBY_ENCODING_H */ include/ruby/memory_view.h 0000644 00000025436 15152150471 0011676 0 ustar 00 #ifndef RUBY_MEMORY_VIEW_H /*-*-C++-*-vi:se ft=cpp:*/ #define RUBY_MEMORY_VIEW_H 1 /** * @file * @author Ruby developers <ruby-core@ruby-lang.org> * @copyright This file is a part of the programming language Ruby. * Permission is hereby granted, to either redistribute and/or * modify this file, provided that the conditions mentioned in the * file COPYING are met. Consult the file for details. * @brief Memory View. */ #include "ruby/internal/config.h" #ifdef STDC_HEADERS # include <stddef.h> /* size_t */ #endif #ifdef HAVE_SYS_TYPES_H # include <sys/types.h> /* ssize_t */ #endif #include "ruby/internal/attr/pure.h" /* RBIMPL_ATTR_PURE */ #include "ruby/internal/core/rtypeddata.h" /* rb_data_type_t */ #include "ruby/internal/dllexport.h" /* RUBY_EXTERN */ #include "ruby/internal/stdbool.h" /* bool */ #include "ruby/internal/value.h" /* VALUE */ /** * Flags passed to rb_memory_view_get(), then to ::rb_memory_view_get_func_t. */ enum ruby_memory_view_flags { RUBY_MEMORY_VIEW_SIMPLE = 0, RUBY_MEMORY_VIEW_WRITABLE = (1<<0), RUBY_MEMORY_VIEW_FORMAT = (1<<1), RUBY_MEMORY_VIEW_MULTI_DIMENSIONAL = (1<<2), RUBY_MEMORY_VIEW_STRIDES = (1<<3) | RUBY_MEMORY_VIEW_MULTI_DIMENSIONAL, RUBY_MEMORY_VIEW_ROW_MAJOR = (1<<4) | RUBY_MEMORY_VIEW_STRIDES, RUBY_MEMORY_VIEW_COLUMN_MAJOR = (1<<5) | RUBY_MEMORY_VIEW_STRIDES, RUBY_MEMORY_VIEW_ANY_CONTIGUOUS = RUBY_MEMORY_VIEW_ROW_MAJOR | RUBY_MEMORY_VIEW_COLUMN_MAJOR, RUBY_MEMORY_VIEW_INDIRECT = (1<<6) | RUBY_MEMORY_VIEW_STRIDES, }; /** Memory view component metadata. */ typedef struct { /** @see ::rb_memory_view_t::format */ char format; /** :FIXME: what is a "native" size is unclear. */ bool native_size_p; /** Endian of the component */ bool little_endian_p; /** The component's offset. */ size_t offset; /** The component's size. */ size_t size; /** * How many numbers of components are there. For instance "CCC"'s repeat is * 3. */ size_t repeat; } rb_memory_view_item_component_t; /** * A MemoryView structure, `rb_memory_view_t`, is used for exporting objects' * MemoryView. * * This structure contains the reference of the object, which is the owner of * the MemoryView, the pointer to the head of exported memory, and the metadata * that describes the structure of the memory. The metadata can describe * multidimensional arrays with strides. */ typedef struct { /** * The original object that has the memory exported via this memory view. */ VALUE obj; /** The pointer to the exported memory. */ void *data; /** The number of bytes in data. */ ssize_t byte_size; /** true for readonly memory, false for writable memory. */ bool readonly; /** * A string to describe the format of an element, or NULL for unsigned bytes. * The format string is a sequence of the following pack-template specifiers: * * c, C, s, s!, S, S!, n, v, i, i!, I, I!, l, l!, L, L!, * N, V, f, e, g, q, q!, Q, Q!, d, E, G, j, J, x * * For example, "dd" for an element that consists of two double values, * and "CCC" for an element that consists of three bytes, such as * an RGB color triplet. * * Also, the value endianness can be explicitly specified by '<' or '>' * following a value type specifier. * * The items are packed contiguously. When you emulate the alignment of * structure members, put '|' at the beginning of the format string, * like "|iqc". On x86_64 Linux ABI, the size of the item by this format * is 24 bytes instead of 13 bytes. */ const char *format; /** * The number of bytes in each element. * item_size should equal to rb_memory_view_item_size_from_format(format). */ ssize_t item_size; /** Description of each components. */ struct { /** * The array of rb_memory_view_item_component_t that describes the * item structure. rb_memory_view_prepare_item_desc and * rb_memory_view_get_item allocate this memory if needed, * and rb_memory_view_release frees it. */ const rb_memory_view_item_component_t *components; /** The number of components in an item. */ size_t length; } item_desc; /** The number of dimension. */ ssize_t ndim; /** * ndim size array indicating the number of elements in each dimension. * This can be NULL when ndim == 1. */ const ssize_t *shape; /** * ndim size array indicating the number of bytes to skip to go to the * next element in each dimension. */ const ssize_t *strides; /** * The offset in each dimension when this memory view exposes a nested array. * Or, NULL when this memory view exposes a flat array. */ const ssize_t *sub_offsets; /** The private data for managing this exported memory */ void *private_data; /** DO NOT TOUCH THIS: The memory view entry for the internal use */ const struct rb_memory_view_entry *_memory_view_entry; } rb_memory_view_t; /** Type of function of ::rb_memory_view_entry_t::get_func. */ typedef bool (* rb_memory_view_get_func_t)(VALUE obj, rb_memory_view_t *view, int flags); /** Type of function of ::rb_memory_view_entry_t::release_func. */ typedef bool (* rb_memory_view_release_func_t)(VALUE obj, rb_memory_view_t *view); /** Type of function of ::rb_memory_view_entry_t::available_p_func. */ typedef bool (* rb_memory_view_available_p_func_t)(VALUE obj); /** Operations applied to a specific kind of a memory view. */ typedef struct rb_memory_view_entry { /** * Exports a memory view from a Ruby object. */ rb_memory_view_get_func_t get_func; /** * Releases a memory view that was previously generated using * ::rb_memory_view_entry_t::get_func. */ rb_memory_view_release_func_t release_func; /** * Queries if an object understands memory view protocol. */ rb_memory_view_available_p_func_t available_p_func; } rb_memory_view_entry_t; RBIMPL_SYMBOL_EXPORT_BEGIN() /* memory_view.c */ /** * Associates the passed class with the passed memory view entry. This has to * be called before actually creating a memory view from an instance. */ bool rb_memory_view_register(VALUE klass, const rb_memory_view_entry_t *entry); RBIMPL_ATTR_PURE() /** * Return `true` if the data in the MemoryView `view` is row-major contiguous. * * Return `false` otherwise. */ bool rb_memory_view_is_row_major_contiguous(const rb_memory_view_t *view); RBIMPL_ATTR_PURE() /** * Return `true` if the data in the MemoryView `view` is column-major * contiguous. * * Return `false` otherwise. */ bool rb_memory_view_is_column_major_contiguous(const rb_memory_view_t *view); RBIMPL_ATTR_NOALIAS() /** * Fill the `strides` array with byte-Strides of a contiguous array of the * given shape with the given element size. */ void rb_memory_view_fill_contiguous_strides(const ssize_t ndim, const ssize_t item_size, const ssize_t *const shape, const bool row_major_p, ssize_t *const strides); RBIMPL_ATTR_NOALIAS() /** * Fill the members of `view` as an 1-dimensional byte array. */ bool rb_memory_view_init_as_byte_array(rb_memory_view_t *view, VALUE obj, void *data, const ssize_t len, const bool readonly); /** * Deconstructs the passed format string, as describe in * ::rb_memory_view_t::format. */ ssize_t rb_memory_view_parse_item_format(const char *format, rb_memory_view_item_component_t **members, size_t *n_members, const char **err); /** * Calculate the number of bytes occupied by an element. * * When the calculation fails, the failed location in `format` is stored into * `err`, and returns `-1`. */ ssize_t rb_memory_view_item_size_from_format(const char *format, const char **err); /** * Calculate the location of the item indicated by the given `indices`. * * The length of `indices` must equal to `view->ndim`. * * This function initializes `view->item_desc` if needed. */ void *rb_memory_view_get_item_pointer(rb_memory_view_t *view, const ssize_t *indices); /** * Return a value that consists of item members. * * When an item is a single member, the return value is a single value. * * When an item consists of multiple members, an array will be returned. */ VALUE rb_memory_view_extract_item_members(const void *ptr, const rb_memory_view_item_component_t *members, const size_t n_members); /** Fill the `item_desc` member of `view`. */ void rb_memory_view_prepare_item_desc(rb_memory_view_t *view); /** * Return a value that consists of item members in the given memory view. */ VALUE rb_memory_view_get_item(rb_memory_view_t *view, const ssize_t *indices); /** * Return `true` if `obj` supports to export a MemoryView. Return `false` * otherwise. * * If this function returns `true`, it doesn't mean the function * `rb_memory_view_get` will succeed. */ bool rb_memory_view_available_p(VALUE obj); /** * If the given `obj` supports to export a MemoryView that conforms the given * `flags`, this function fills `view` by the information of the MemoryView and * returns `true`. In this case, the reference count of `obj` is increased. * * If the given combination of `obj` and `flags` cannot export a MemoryView, * this function returns `false`. The content of `view` is not touched in this * case. * * The exported MemoryView must be released by `rb_memory_view_release` when * the MemoryView is no longer needed. */ bool rb_memory_view_get(VALUE obj, rb_memory_view_t* memory_view, int flags); /** * Release the given MemoryView `view` and decrement the reference count of * `memory_view->obj`. * * Consumers must call this function when the MemoryView is no longer needed. * Missing to call this function leads memory leak. */ bool rb_memory_view_release(rb_memory_view_t* memory_view); /* for testing */ /** @cond INTERNAL_MACRO */ RUBY_EXTERN VALUE rb_memory_view_exported_object_registry; RUBY_EXTERN const rb_data_type_t rb_memory_view_exported_object_registry_data_type; /** @endcond */ RBIMPL_SYMBOL_EXPORT_END() RBIMPL_ATTR_PURE() /** * Return `true` if the data in the MemoryView `view` is row-major or * column-major contiguous. * * Return `false` otherwise. */ static inline bool rb_memory_view_is_contiguous(const rb_memory_view_t *view) { if (rb_memory_view_is_row_major_contiguous(view)) { return true; } else if (rb_memory_view_is_column_major_contiguous(view)) { return true; } else { return false; } } #endif /* RUBY_BUFFER_H */ include/ruby/defines.h 0000644 00000005406 15152150471 0010744 0 ustar 00 #ifndef RUBY_DEFINES_H /*-*-C++-*-vi:se ft=cpp:*/ #define RUBY_DEFINES_H 1 /** * @file * @author $Author$ * @date Wed May 18 00:21:44 JST 1994 * @copyright This file is a part of the programming language Ruby. * Permission is hereby granted, to either redistribute and/or * modify this file, provided that the conditions mentioned in the * file COPYING are met. Consult the file for details. */ #include "ruby/internal/config.h" /* AC_INCLUDES_DEFAULT */ #include <stdio.h> #ifdef HAVE_SYS_TYPES_H # include <sys/types.h> #endif #ifdef HAVE_SYS_STAT_H # include <sys/stat.h> #endif #ifdef STDC_HEADERS # include <stdlib.h> # include <stddef.h> #else # ifdef HAVE_STDLIB_H # include <stdlib.h> # endif #endif #ifdef HAVE_STRING_H # if !defined STDC_HEADERS && defined HAVE_MEMORY_H # include <memory.h> # endif # include <string.h> #endif #ifdef HAVE_STRINGS_H # include <strings.h> #endif #ifdef HAVE_INTTYPES_H # include <inttypes.h> #endif #ifdef HAVE_STDINT_H # include <stdint.h> #endif #ifdef HAVE_STDALIGN_H # include <stdalign.h> #endif #ifdef HAVE_UNISTD_H # include <unistd.h> #endif #ifdef HAVE_SYS_SELECT_H # include <sys/select.h> #endif #ifdef RUBY_USE_SETJMPEX # include <setjmpex.h> #endif #include "ruby/internal/dllexport.h" #include "ruby/internal/xmalloc.h" #include "ruby/backward/2/assume.h" #include "ruby/backward/2/attributes.h" #include "ruby/backward/2/bool.h" #include "ruby/backward/2/long_long.h" #include "ruby/backward/2/stdalign.h" #include "ruby/backward/2/stdarg.h" #include "ruby/internal/dosish.h" #include "ruby/missing.h" /** * Asserts that the compilation unit includes Ruby's CAPI. This has been here * since the very beginning (at least since version 0.49). */ #define RUBY #ifdef __GNUC__ # /** This is expanded to nothing for non-GCC compilers. */ # define RB_GNUC_EXTENSION __extension__ # /** This is expanded to the passed token for non-GCC compilers. */ # define RB_GNUC_EXTENSION_BLOCK(x) __extension__ ({ x; }) #else # define RB_GNUC_EXTENSION # define RB_GNUC_EXTENSION_BLOCK(x) (x) #endif /** @cond INTERNAL_MACRO */ /* :FIXME: Can someone tell us why is this macro defined here? @shyouhei * thinks this is a truly internal macro but cannot move around because he * doesn't understand the reason of this arrangement. */ #ifndef RUBY_MBCHAR_MAXSIZE # define RUBY_MBCHAR_MAXSIZE INT_MAX # /* MB_CUR_MAX will not work well in C locale */ #endif #if defined(__sparc) RBIMPL_SYMBOL_EXPORT_BEGIN() void rb_sparc_flush_register_windows(void); RBIMPL_SYMBOL_EXPORT_END() # define FLUSH_REGISTER_WINDOWS rb_sparc_flush_register_windows() #else # define FLUSH_REGISTER_WINDOWS ((void)0) #endif /** @endcond */ #endif /* RUBY_DEFINES_H */ include/ruby/io.h 0000644 00000110722 15152150471 0007734 0 ustar 00 #ifndef RUBY_IO_H /*-*-C++-*-vi:se ft=cpp:*/ #define RUBY_IO_H 1 /** * @file * @author $Author$ * @date Fri Nov 12 16:47:09 JST 1993 * @copyright Copyright (C) 1993-2007 Yukihiro Matsumoto * @copyright This file is a part of the programming language Ruby. * Permission is hereby granted, to either redistribute and/or * modify this file, provided that the conditions mentioned in the * file COPYING are met. Consult the file for details. */ #include "ruby/internal/config.h" #include <stdio.h> #include "ruby/encoding.h" #if defined(HAVE_STDIO_EXT_H) #include <stdio_ext.h> #endif #include <errno.h> /** @cond INTERNAL_MACRO */ #if defined(HAVE_POLL) # ifdef _AIX # define reqevents events # define rtnevents revents # endif # include <poll.h> # ifdef _AIX # undef reqevents # undef rtnevents # undef events # undef revents # endif # define RB_WAITFD_IN POLLIN # if defined(POLLPRI) # define RB_WAITFD_PRI POLLPRI # else # define RB_WAITFD_PRI 0 # endif # define RB_WAITFD_OUT POLLOUT #else # define RB_WAITFD_IN 0x001 # define RB_WAITFD_PRI 0x002 # define RB_WAITFD_OUT 0x004 #endif /** @endcond */ #include "ruby/internal/attr/const.h" #include "ruby/internal/attr/packed_struct.h" #include "ruby/internal/attr/pure.h" #include "ruby/internal/attr/noreturn.h" #include "ruby/internal/dllexport.h" #include "ruby/internal/value.h" // IO#wait, IO#wait_readable, IO#wait_writable, IO#wait_priority are defined by this implementation. #define RUBY_IO_WAIT_METHODS // Used as the default timeout argument to `rb_io_wait` to use the `IO#timeout` value. #define RUBY_IO_TIMEOUT_DEFAULT Qnil RBIMPL_SYMBOL_EXPORT_BEGIN() struct stat; struct timeval; /** * Indicates that a timeout has occurred while performing an IO operation. */ RUBY_EXTERN VALUE rb_eIOTimeoutError; /** * Type of events that an IO can wait. * * @internal * * This is visible from extension libraries because `io/wait` wants it. */ enum rb_io_event { RUBY_IO_READABLE = RB_WAITFD_IN, /**< `IO::READABLE` */ RUBY_IO_WRITABLE = RB_WAITFD_OUT, /**< `IO::WRITABLE` */ RUBY_IO_PRIORITY = RB_WAITFD_PRI, /**< `IO::PRIORITY` */ }; typedef enum rb_io_event rb_io_event_t; /** * IO buffers. This is an implementation detail of ::rb_io_t::wbuf and * ::rb_io_t::rbuf. People don't manipulate it directly. */ RBIMPL_ATTR_PACKED_STRUCT_UNALIGNED_BEGIN() struct rb_io_internal_buffer { /** Pointer to the underlying memory region, of at least `capa` bytes. */ char *ptr; /* off + len <= capa */ /** Offset inside of `ptr`. */ int off; /** Length of the buffer. */ int len; /** Designed capacity of the buffer. */ int capa; } RBIMPL_ATTR_PACKED_STRUCT_UNALIGNED_END(); /** @alias{rb_io_buffer_t} */ typedef struct rb_io_internal_buffer rb_io_buffer_t; /** Decomposed encoding flags (e.g. `"enc:enc2""`). */ /* * enc enc2 read action write action * NULL NULL force_encoding(default_external) write the byte sequence of str * e1 NULL force_encoding(e1) convert str.encoding to e1 * e1 e2 convert from e2 to e1 convert str.encoding to e2 */ struct rb_io_encoding { /** Internal encoding. */ rb_encoding *enc; /** External encoding. */ rb_encoding *enc2; /** * Flags. * * @see enum ::ruby_econv_flag_type */ int ecflags; /** * Flags as Ruby hash. * * @internal * * This is set. But used from nowhere maybe? */ VALUE ecopts; }; #ifndef HAVE_RB_IO_T #define HAVE_RB_IO_T 1 /** Ruby's IO, metadata and buffers. */ struct rb_io { /** The IO's Ruby level counterpart. */ RBIMPL_ATTR_DEPRECATED(("with no replacement")) VALUE self; /** stdio ptr for read/write, if available. */ RBIMPL_ATTR_DEPRECATED(("with no replacement")) FILE *stdio_file; /** file descriptor. */ RBIMPL_ATTR_DEPRECATED(("rb_io_descriptor")) int fd; /** mode flags: FMODE_XXXs */ RBIMPL_ATTR_DEPRECATED(("rb_io_mode")) int mode; /** child's pid (for pipes) */ RBIMPL_ATTR_DEPRECATED(("with no replacement")) rb_pid_t pid; /** number of lines read */ RBIMPL_ATTR_DEPRECATED(("with no replacement")) int lineno; /** pathname for file */ RBIMPL_ATTR_DEPRECATED(("rb_io_path")) VALUE pathv; /** finalize proc */ RBIMPL_ATTR_DEPRECATED(("with no replacement")) void (*finalize)(struct rb_io*,int); /** Write buffer. */ RBIMPL_ATTR_DEPRECATED(("with no replacement")) rb_io_buffer_t wbuf; /** * (Byte) read buffer. Note also that there is a field called * ::rb_io_t::cbuf, which also concerns read IO. */ RBIMPL_ATTR_DEPRECATED(("with no replacement")) rb_io_buffer_t rbuf; /** * Duplex IO object, if set. * * @see rb_io_set_write_io() */ RBIMPL_ATTR_DEPRECATED(("rb_io_get_write_io")) VALUE tied_io_for_writing; RBIMPL_ATTR_DEPRECATED(("with no replacement")) struct rb_io_encoding encs; /**< Decomposed encoding flags. */ /** Encoding converter used when reading from this IO. */ RBIMPL_ATTR_DEPRECATED(("with no replacement")) rb_econv_t *readconv; /** * rb_io_ungetc() destination. This buffer is read before checking * ::rb_io_t::rbuf */ RBIMPL_ATTR_DEPRECATED(("with no replacement")) rb_io_buffer_t cbuf; /** Encoding converter used when writing to this IO. */ RBIMPL_ATTR_DEPRECATED(("with no replacement")) rb_econv_t *writeconv; /** * This is, when set, an instance of ::rb_cString which holds the "common" * encoding. Write conversion can convert strings twice... In case * conversion from encoding X to encoding Y does not exist, Ruby finds an * encoding Z that bridges the two, so that X to Z to Y conversion happens. */ RBIMPL_ATTR_DEPRECATED(("with no replacement")) VALUE writeconv_asciicompat; /** Whether ::rb_io_t::writeconv is already set up. */ RBIMPL_ATTR_DEPRECATED(("with no replacement")) int writeconv_initialized; /** * Value of ::rb_io_t::rb_io_enc_t::ecflags stored right before * initialising ::rb_io_t::writeconv. */ RBIMPL_ATTR_DEPRECATED(("with no replacement")) int writeconv_pre_ecflags; /** * Value of ::rb_io_t::rb_io_enc_t::ecopts stored right before initialising * ::rb_io_t::writeconv. */ RBIMPL_ATTR_DEPRECATED(("with no replacement")) VALUE writeconv_pre_ecopts; /** * This is a Ruby level mutex. It avoids multiple threads to write to an * IO at once; helps for instance rb_io_puts() to ensure newlines right * next to its arguments. * * This of course doesn't help inter-process IO interleaves, though. */ RBIMPL_ATTR_DEPRECATED(("with no replacement")) VALUE write_lock; /** * The timeout associated with this IO when performing blocking operations. */ RBIMPL_ATTR_DEPRECATED(("rb_io_timeout/rb_io_set_timeout")) VALUE timeout; }; #endif typedef struct rb_io rb_io_t; /** @alias{rb_io_enc_t} */ typedef struct rb_io_encoding rb_io_enc_t; /** * @name Possible flags for ::rb_io_t::mode * * @{ */ /** The IO is opened for reading. */ #define FMODE_READABLE 0x00000001 /** The IO is opened for writing. */ #define FMODE_WRITABLE 0x00000002 /** The IO is opened for both read/write. */ #define FMODE_READWRITE (FMODE_READABLE|FMODE_WRITABLE) /** * The IO is in "binary mode". This is not what everything rb_io_binmode() * concerns. This low-level flag is to stop CR <-> CRLF conversions that would * happen in the underlying operating system. * * Setting this one and #FMODE_TEXTMODE at the same time is a contradiction. * Setting this one and #ECONV_NEWLINE_DECORATOR_MASK at the same time is also * a contradiction. */ #define FMODE_BINMODE 0x00000004 /** * The IO is in "sync mode". All output is immediately flushed to the * underlying operating system then. Can be set via rb_io_synchronized(), but * there is no way except calling `IO#sync=` to reset. */ #define FMODE_SYNC 0x00000008 /** * The IO is a TTY. What is a TTY and what isn't depends on the underlying * operating system's `isatty(3)` output. You cannot change this. */ #define FMODE_TTY 0x00000010 /** * Ruby eventually detects that the IO is bidirectional. For instance a TTY * has such property. There are several other things known to be duplexed. * Additionally you (extension library authors) can also implement your own * bidirectional IO subclasses. One of such example is `Socket`. */ #define FMODE_DUPLEX 0x00000020 /** * The IO is opened for appending. This mode always writes at the end of the * IO. Ruby manages this flag for record but basically the logic behind this * mode is at the underlying operating system. We almost do nothing. */ #define FMODE_APPEND 0x00000040 /** * The IO is opened for creating. This makes sense only when the destination * file does not exist at the time the IO object was created. This is the * default mode for writing, but you can pass `"r+"` to `IO.open` etc., to * reroute this creation. */ #define FMODE_CREATE 0x00000080 /* #define FMODE_NOREVLOOKUP 0x00000100 */ /** * This flag amends the effect of #FMODE_CREATE, so that if there already is a * file at the given path the operation fails. Using this you can be sure that * the file you get is a fresh new one. */ #define FMODE_EXCL 0x00000400 /** * This flag amends the effect of #FMODE_CREATE, so that if there already is a * file at the given path it gets truncated. */ #define FMODE_TRUNC 0x00000800 /** * The IO is in "text mode". On systems where such mode make sense, this flag * changes the way the IO handles the contents. On POSIX systems it is * basically a no-op, but with this flag set you can optionally let Ruby * manually convert newlines, unlike when in binary mode: * * ```ruby * IO.open("/p/a/t/h", "wt", crlf_newline: true) # "wb" is NG. * ``` * * Setting this one and #FMODE_BINMODE at the same time is a contradiction. */ #define FMODE_TEXTMODE 0x00001000 /** * This flag means that an IO object is wrapping an "external" file descriptor, * which is owned by something outside the Ruby interpreter (usually a C extension). * Ruby will not close this file when the IO object is garbage collected. * If this flag is set, then IO#autoclose? is false, and vice-versa. * * This flag was previously called FMODE_PREP internally. */ #define FMODE_EXTERNAL 0x00010000 /* #define FMODE_SIGNAL_ON_EPIPE 0x00020000 */ /** * This flag amends the encoding of the IO so that the BOM of the contents of * the IO takes effect. */ #define FMODE_SETENC_BY_BOM 0x00100000 /* #define FMODE_UNIX 0x00200000 */ /* #define FMODE_INET 0x00400000 */ /* #define FMODE_INET6 0x00800000 */ /** @} */ /** * Allocate a new IO object, with the given file descriptor. */ VALUE rb_io_open_descriptor(VALUE klass, int descriptor, int mode, VALUE path, VALUE timeout, struct rb_io_encoding *encoding); /** * Returns whether or not the underlying IO is closed. * * @return Whether the underlying IO is closed. */ VALUE rb_io_closed_p(VALUE io); /** * Queries the underlying IO pointer. * * @param[in] obj An IO object. * @param[out] fp A variable of type ::rb_io_t. * @exception rb_eFrozenError `obj` is frozen. * @exception rb_eIOError `obj` is closed. * @post `fp` holds `obj`'s underlying IO. */ #define RB_IO_POINTER(obj,fp) rb_io_check_closed((fp) = RFILE(rb_io_taint_check(obj))->fptr) /** * This is an old name of #RB_IO_POINTER. Not sure if we want to deprecate * this macro. There still are tons of usages out there in the wild. */ #define GetOpenFile RB_IO_POINTER /** * Fills an IO object. This makes the best sense when called from inside of an * `#initialize` method of a 3rd party extension library that inherits * ::rb_cIO. * * If the passed IO is already opened for something it first closes that and * opens a new one instead. * * @param[out] obj An IO object to fill in. * @param[out] fp A variable of type ::rb_io_t. * @exception rb_eTypeError `obj` is not ::RUBY_T_FILE. * @post `fp` holds `obj`'s underlying IO. */ #define RB_IO_OPEN(obj, fp) do {\ (fp) = rb_io_make_open_file(obj);\ } while (0) /** * This is an old name of #RB_IO_OPEN. Not sure if we want to deprecate this * macro. There still are usages out there in the wild. */ #define MakeOpenFile RB_IO_OPEN /** * @private * * This is an implementation detail of #RB_IO_OPEN. People don't use it * directly. * * @param[out] obj An IO object to fill in. * @exception rb_eTypeError `obj` is not ::RUBY_T_FILE. * @return `obj`'s backend IO. * @post `obj` is initialised. */ rb_io_t *rb_io_make_open_file(VALUE obj); /** * Finds or creates a stdio's file structure from a Ruby's one. This can be * handy if you want to call an external API that accepts `FILE *`. * * @note Note however, that `FILE`s can have their own buffer. Mixing Ruby's * and stdio's file are basically dangerous. Use with care. * * @param[in,out] fptr Target IO. * @return A stdio's file, created if absent. * @post `fptr` has its corresponding stdio's file. * * @internal * * We had rich support for `FILE` before! In the days of 1.8.x ::rb_io_t was * like this: * * ```CXX * typedef struct rb_io { * FILE *f; // stdio ptr for read/write * FILE *f2; // additional ptr for rw pipes * int mode; // mode flags * int pid; // child's pid (for pipes) * int lineno; // number of lines read * char *path; // pathname for file * void (*finalize) _((struct rb_io*,int)); // finalize proc * } rb_io_t; *``` * * But we eventually abandoned this layout. It was too difficult. We could * not have fine-grained control over the `f` field. * * - `FILE` tends to be an opaque struct. It does not interface well with * `select(2)` etc. This makes IO multiplexing quite hard. Using stdio, * there is arguably no portable way to know if `fwrite(3)` blocks. * * - Nonblocking mode, which is another core concept that enables IO * multiplexing, does not interface with stdio routines at all. * * - Detection of duplexed IO is also hard for the same reason. * * - `feof(3)` is not portable. * https://mail.python.org/pipermail/python-dev/2001-January/011390.html * * - Solaris was a thing back then. They could not have more than 256 `FILE` * structures at a time. Their file descriptors ware stored in an * `unsigned char`. * * - It is next to impossible to avoid SEGV, especially when a thread tries to * `ungetc(3)`-ing from a `FILE` which is `fread(3)`-ed by another one. * * In short, it is a bad idea to let someone else manage IO buffers, especially * someone you cannot control. This still applies to extension libraries * methinks. Ruby doesn't prevent you from shooting yourself in the foot, but * consider yourself warned here. */ FILE *rb_io_stdio_file(rb_io_t *fptr); /** * Identical to rb_io_stdio_file(), except it takes file descriptors instead of * Ruby's IO. It can also be seen as a compatibility layer to wrap * `fdopen(3)`. Nowadays all supporting systems, including Windows, have * `fdopen`. Why not use them. * * @param[in] fd A file descriptor. * @param[in] modestr C string, something like `"r+"`. * @exception rb_eSystemCallError `fdopen` failed for some reason. * @return A stdio's file associated with `fd`. * @note Interpretation of `modestr` depends on the underlying operating * system. On glibc you might be able to pass e.g. `"rm"`, but * that's an extension to POSIX. */ FILE *rb_fdopen(int fd, const char *modestr); /** * Maps a file mode string (that rb_file_open() takes) into a mixture of * `FMODE_` flags. This for instance returns * `FMODE_WRITABLE | FMODE_TRUNC | FMODE_CREATE | FMODE_EXCL` for `"wx"`. * * @note You cannot pass this return value to OS provided `open(2)` etc. * * @param[in] modestr File mode, in C's string. * @exception rb_eArgError `modestr` is broken. * @return A set of flags. * * @internal * * rb_io_modestr_fmode() is not a pure function because it raises. */ int rb_io_modestr_fmode(const char *modestr); /** * Identical to rb_io_modestr_fmode(), except it returns a mixture of `O_` * flags. This for instance returns `O_WRONLY | O_TRUNC | O_CREAT | O_EXCL` for * `"wx"`. * * @param[in] modestr File mode, in C's string. * @exception rb_eArgError `modestr` is broken. * @return A set of flags. * * @internal * * rb_io_modestr_oflags() is not a pure function because it raises. */ int rb_io_modestr_oflags(const char *modestr); RBIMPL_ATTR_CONST() /** * Converts an oflags (that rb_io_modestr_oflags() returns) to a fmode (that * rb_io_mode_flags() returns). This is a purely functional operation. * * @param[in] oflags A set of `O_` flags. * @return Corresponding set of `FMODE_` flags. */ int rb_io_oflags_fmode(int oflags); /** * Asserts that an IO is opened for writing. * * @param[in] fptr An IO you want to write to. * @exception rb_eIOError `fptr` is not for writing. * @post Upon successful return `fptr` is ready for writing. * * @internal * * The parameter must have been `const rb_io_t *`. */ void rb_io_check_writable(rb_io_t *fptr); /** @alias{rb_io_check_byte_readable} */ void rb_io_check_readable(rb_io_t *fptr); /** * Asserts that an IO is opened for character-based reading. A character can * be wider than a byte. Because of this we have to buffer reads from * descriptors. This fiction checks if that is possible. * * @param[in] fptr An IO you want to read characters from. * @exception rb_eIOError `fptr` is not for reading. * @post Upon successful return `fptr` is ready for reading characters. * * @internal * * Unlike rb_io_check_writable() the parameter cannot be `const rb_io_t *`. * Behind the scene this operation flushes its write buffers. This is because * of OpenSSL. They mandate this way. * * @see "Can I use OpenSSL's SSL library with non-blocking I/O?" * https://www.openssl.org/docs/faq.html */ void rb_io_check_char_readable(rb_io_t *fptr); /** * Asserts that an IO is opened for byte-based reading. Byte-based and * character-based reading operations cannot be mixed at a time. * * @param[in] fptr An IO you want to read characters from. * @exception rb_eIOError `fptr` is not for reading. * @post Upon successful return `fptr` is ready for reading bytes. */ void rb_io_check_byte_readable(rb_io_t *fptr); /** * Destroys the given IO. Any pending operations are flushed. * * @note It makes no sense to call this function from anywhere outside of your * class' ::rb_data_type_struct::dfree. * * @param[out] fptr IO to close. * @post `fptr` is no longer a valid pointer. */ int rb_io_fptr_finalize(rb_io_t *fptr); /** * Sets #FMODE_SYNC. * * @note There is no way for C extensions to undo this operation. * * @param[out] fptr IO to set the flag. * @exception rb_eIOError `fptr` is not opened. * @post `fptr` is in sync mode. */ void rb_io_synchronized(rb_io_t *fptr); /** * Asserts that the passed IO is initialised. * * @param[in] fptr IO that you expect be initialised. * @exception rb_eIOError `fptr` is not initialised. * @post `fptr` is initialised. */ void rb_io_check_initialized(rb_io_t *fptr); /** * This badly named function asserts that the passed IO is _open_. * * @param[in] fptr An IO * @exception rb_eIOError `fptr` is closed. * @post `fptr` is open. */ void rb_io_check_closed(rb_io_t *fptr); /** * Identical to rb_io_check_io(), except it raises exceptions on conversion * failures. * * @param[in] io Target object. * @exception rb_eTypeError No implicit conversion to IO. * @return Return value of `obj.to_io`. * @see rb_str_to_str * @see rb_ary_to_ary */ VALUE rb_io_get_io(VALUE io); /** * Try converting an object to its IO representation using its `to_io` method, * if any. If there is no such thing, returns ::RUBY_Qnil. * * @param[in] io Arbitrary ruby object to convert. * @exception rb_eTypeError `obj.to_io` returned something non-IO. * @retval RUBY_Qnil No conversion from `obj` to IO defined. * @retval otherwise Converted IO representation of `obj`. * @see rb_check_array_type * @see rb_check_string_type * @see rb_check_hash_type */ VALUE rb_io_check_io(VALUE io); /** * Queries the tied IO for writing. An IO can be duplexed. Fine. The thing * is, that characteristics could sometimes be achieved by the underlying * operating system (for instance a socket's duplexity is by nature) but * sometimes by us. Notable example is a bidirectional pipe. Suppose you * have: * * ```ruby * fp = IO.popen("-", "r+") * ``` * * This pipe is duplexed (the `"r+"`). You can both read from/write to it. * However your operating system may or may not implement bidirectional pipes. * FreeBSD is one of such operating systems known to have one; OTOH Linux is * known to lack such things. So to achieve maximum portability, Ruby's * bidirectional pipes are done purely in user land. A pipe in ruby can have * multiple file descriptors; one for reading and the other for writing. This * API is to obtain the IO port which corresponds to the passed one, for * writing. * * @param[in] io An IO. * @return Its tied IO for writing, if any, or `io` itself otherwise. */ VALUE rb_io_get_write_io(VALUE io); /** * Assigns the tied IO for writing. See rb_io_get_write_io() for what a "tied * IO for writing" is. * * @param[out] io An IO. * @param[in] w Another IO. * @retval RUBY_Qnil There was no tied IO for writing for `io`. * @retval otherwise The IO formerly tied to `io`. * @post `io` ties `w` for writing. * * @internal * * @shyouhei doesn't think there is any needs of this function for 3rd party * extension libraries. */ VALUE rb_io_set_write_io(VALUE io, VALUE w); /** * Instructs the OS to put its internal file structure into "nonblocking mode". * This is an in-Kernel concept. Reading from/writing to that file using C * function calls would return -1 with errno set. However when it comes to a * ruby program, we hide that error behind our `IO#read` method. Ruby level * `IO#read` blocks regardless of this flag. If you want to avoid blocking, * you should consider using methods like `IO#readpartial`. * * ```ruby * require 'io/nonblock' * STDIN.nonblock = true * STDIN.gets # blocks. * ``` * * As of writing there is a room of this API in Fiber schedulers. A Fiber * scheduler could be written in a way its behaviour depends on this property. * You need an in-depth understanding of how schedulers work to properly * leverage this, though. * * @note Note however that nonblocking-ness propagates across process * boundaries. You must really carefully watch your step when turning * for instance `stderr` into nonblock mode (it tends to be shared * across many processes). Also it is a complete disaster to mix a * nonblocking file and stdio, and `stderr` tends to be under control of * stdio in other processes. * * @param[out] fptr An IO that is to ne nonblocking. * @post Descriptor that `fptr` describes is under nonblocking mode. * * @internal * * There is `O_NONBLOCK` but not `FMODE_NONBLOCK`. You cannot atomically * create a nonblocking file descriptor using our API. */ void rb_io_set_nonblock(rb_io_t *fptr); /** * Returns the path for the given IO. * */ VALUE rb_io_path(VALUE io); /** * Returns an integer representing the numeric file descriptor for * <em>io</em>. * * @param[in] io An IO. * @retval int A file descriptor. */ int rb_io_descriptor(VALUE io); /** * Get the mode of the IO. * */ int rb_io_mode(VALUE io); /** * This function breaks down the option hash that `IO#initialize` takes into * components. This is an implementation detail of rb_io_extract_modeenc() * today. People prefer that API instead. * * @param[in] opt The hash to decompose. * @param[out] enc_p Return value buffer. * @param[out] enc2_p Return value buffer. * @param[out] fmode_p Return value buffer. * @exception rb_eTypeError `opt` is broken. * @exception rb_eArgError Specified encoding does not exist. * @retval 1 Components got extracted. * @retval 0 Otherwise. * @post `enc_p` is the specified internal encoding. * @post `enc2_p` is the specified external encoding. * @post `fmode_p` is the specified set of `FMODE_` modes. */ int rb_io_extract_encoding_option(VALUE opt, rb_encoding **enc_p, rb_encoding **enc2_p, int *fmode_p); /** * This function can be seen as an extended version of * rb_io_extract_encoding_option() that not only concerns the option hash but * also mode string and so on. This should be mixed with rb_scan_args() like: * * ```CXX * // This method mimics File.new * static VALUE * your_method(int argc, const VALUE *argv, VALUE self) * { * VALUE f; // file name * VALUE m; // open mode * VALUE p; // permission (O_CREAT) * VALUE k; // keywords * rb_io_enc_t c; // converter * int oflags; * int fmode; * * int n = rb_scan_args(argc, argv, "12:", &f, &m, &p, &k); * rb_io_extract_modeenc(&m, &p, k, &oflags, &fmode, &c); * * // Every local variables declared so far has been properly filled here. * ... * } * ``` * * @param[in,out] vmode_p Pointer to a mode object. * @param[in,out] vperm_p Pointer to a permission object. * @param[in] opthash Keyword arguments * @param[out] oflags_p `O_` flags return buffer. * @param[out] fmode_p `FMODE_` flags return buffer. * @param[out] convconfig_p Encoding config return buffer. * @exception rb_eTypeError Unexpected object (e.g. Time) passed. * @exception rb_eArgError Contradiction inside of params. * @post `*vmode_p` is a mode object (filled if any). * @post `*vperm_p` is a permission object (filled if any). * @post `*oflags_p` is filled with `O_` flags. * @post `*fmode_p` is filled with `FMODE_` flags. * @post `*convconfig_p` is filled with conversion instructions. * * @internal * * ```rbs * class File * def initialize: ( * (String | int) path, * ?(String | int) fmode, * ?(String | int) perm, * ?mode: (String | int), * ?flags: int, * ?external_encoding: (Encoding | String), * ?internal_encoding: (Encoding | String), * ?encoding: String, * ?textmode: bool, * ?binmode: bool, * ?autoclose: bool, * ?invalid: :replace, * ?undef: :replace, * ?replace: String, * ?fallback: (Hash | Proc | Method), * ?xml: (:text | :attr), * ?crlf_newline: bool, * ?cr_newline: bool, * ?universal_newline: bool * ) -> void * ``` */ void rb_io_extract_modeenc(VALUE *vmode_p, VALUE *vperm_p, VALUE opthash, int *oflags_p, int *fmode_p, rb_io_enc_t *convconfig_p); /* :TODO: can this function be __attribute__((warn_unused_result)) or not? */ /** * Buffered write to the passed IO. * * @param[out] io Destination IO. * @param[in] buf Contents to go to `io`. * @param[in] size Number of bytes of `buf`. * @exception rb_eFrozenError `io` is frozen. * @exception rb_eIOError `io` is not open for writing. * @exception rb_eSystemCallError `writev(2)` failed for some reason. * @retval -1 Write failed. * @retval otherwise Number of bytes actually written. * @post `buf` is written to `io`. * @note Partial write is a thing. It is a failure not to check the * return value. */ ssize_t rb_io_bufwrite(VALUE io, const void *buf, size_t size); //RBIMPL_ATTR_DEPRECATED(("use rb_io_maybe_wait_readable")) /** * Blocks until the passed file descriptor gets readable. * * @deprecated We now prefer rb_io_maybe_wait_readable() over this one. * @param[in] fd The file descriptor to wait. * @exception rb_eIOError Bad file descriptor. * @return 0 or 1 (meaning unclear). * @post `fd` is ready for reading. */ int rb_io_wait_readable(int fd); //RBIMPL_ATTR_DEPRECATED(("use rb_io_maybe_wait_writable")) /** * Blocks until the passed file descriptor gets writable. * * @deprecated We now prefer rb_io_maybe_wait_writable() over this one. * @param[in] fd The file descriptor to wait. * @exception rb_eIOError Bad file descriptor. * @return 0 or 1 (meaning unclear). */ int rb_io_wait_writable(int fd); //RBIMPL_ATTR_DEPRECATED(("use rb_io_wait")) /** * Blocks until the passed file descriptor is ready for the passed events. * * @deprecated We now prefer rb_io_maybe_wait() over this one. * @param[in] fd The file descriptor to wait. * @param[in] events A set of enum ::rb_io_event_t. * @param[in,out] tv Timeout. * @retval 0 Operation timed out. * @retval -1 `select(2)` failed for some reason. * @retval otherwise A set of enum ::rb_io_event_t. * @note Depending on your operating system `tv` might or might not * be updated (POSIX permits both). Portable programs must * have no assumptions. */ int rb_wait_for_single_fd(int fd, int events, struct timeval *tv); /** * Get the timeout associated with the specified io object. * * @param[in] io An IO object. * @retval RUBY_Qnil There is no associated timeout. * @retval Otherwise The timeout value. */ VALUE rb_io_timeout(VALUE io); /** * Set the timeout associated with the specified io object. This timeout is * used as a best effort timeout to prevent operations from blocking forever. * * @param[in] io An IO object. * @param[in] timeout A timeout value. Must respond to #to_f. * @ */ VALUE rb_io_set_timeout(VALUE io, VALUE timeout); /** * Blocks until the passed IO is ready for the passed events. The "events" * here is a Ruby level integer, which is an OR-ed value of `IO::READABLE`, * `IO::WRITable`, and `IO::PRIORITY`. * * If timeout is `Qnil`, it will use the default timeout as given by * `rb_io_timeout(io)`. * * @param[in] io An IO object to wait. * @param[in] events See above. * @param[in] timeout Time, or numeric seconds since UNIX epoch. * If Qnil, use the default timeout. If Qfalse * or Qundef, wait forever. * @exception rb_eIOError `io` is not open. * @exception rb_eRangeError `timeout` is out of range. * @exception rb_eSystemCallError `select(2)` failed for some reason. * @retval RUBY_Qfalse Operation timed out. * @retval Otherwise Actual events reached. */ VALUE rb_io_wait(VALUE io, VALUE events, VALUE timeout); /** * Identical to rb_io_wait() except it additionally takes previous errno. If * the passed errno indicates for instance `EINTR`, this function returns * immediately. This is expected to be called in a loop. * * ```CXX * while (true) { * * ... // Your interesting operation here * // `errno` could be updated * * rb_io_maybe_wait(errno, io, ev, Qnil); * } * ``` * * @param[in] error System errno. * @param[in] io An IO object to wait. * @param[in] events An integer set of interests. * @param[in] timeout Time, or numeric seconds since UNIX epoch. * @exception rb_eIOError `io` is not open. * @exception rb_eRangeError `timeout` is out of range. * @exception rb_eSystemCallError `select(2)` failed for some reason. * @retval RUBY_Qfalse Operation timed out. * @retval Otherwise Actual events reached. * * @internal * * This function to return ::RUBY_Qfalse on timeout could be unintended. It * seems timeout feature has some rough edge. */ VALUE rb_io_maybe_wait(int error, VALUE io, VALUE events, VALUE timeout); /** * Blocks until the passed IO is ready for reading, if that makes sense for the * passed errno. This is a special case of rb_io_maybe_wait() that only * concerns for reading. * * @param[in] error System errno. * @param[in] io An IO object to wait. * @param[in] timeout Time, or numeric seconds since UNIX epoch. * @exception rb_eIOError `io` is not open. * @exception rb_eRangeError `timeout` is out of range. * @exception rb_eSystemCallError `select(2)` failed for some reason. * @retval 0 Operation timed out. * @retval Otherwise Always returns ::RUBY_IO_READABLE. */ int rb_io_maybe_wait_readable(int error, VALUE io, VALUE timeout); /** * Blocks until the passed IO is ready for writing, if that makes sense for the * passed errno. This is a special case of rb_io_maybe_wait() that only * concernsfor writing. * * @param[in] error System errno. * @param[in] io An IO object to wait. * @param[in] timeout Time, or numeric seconds since UNIX epoch. * @exception rb_eIOError `io` is not open. * @exception rb_eRangeError `timeout` is out of range. * @exception rb_eSystemCallError `select(2)` failed for some reason. * @retval 0 Operation timed out. * @retval Otherwise Always returns ::RUBY_IO_WRITABLE. */ int rb_io_maybe_wait_writable(int error, VALUE io, VALUE timeout); /** @cond INTERNAL_MACRO */ /* compatibility for ruby 1.8 and older */ #define rb_io_mode_flags(modestr) [<"rb_io_mode_flags() is obsolete; use rb_io_modestr_fmode()">] #define rb_io_modenum_flags(oflags) [<"rb_io_modenum_flags() is obsolete; use rb_io_oflags_fmode()">] /** @endcond */ /** * @deprecated This function once was a thing in the old days, but makes no * sense any longer today. Exists here for backwards * compatibility only. You can safely forget about it. * * @param[in] obj Object in question. * @exception rb_eFrozenError obj is frozen. * @return The passed `obj` */ VALUE rb_io_taint_check(VALUE obj); RBIMPL_ATTR_NORETURN() /** * Utility function to raise ::rb_eEOFError. * * @exception rb_eEOFError End of file situation. * @note It never returns. */ void rb_eof_error(void); /** * Blocks until there is a pending read in the passed IO. If there already is * it just returns. * * @param[out] fptr An IO to wait for reading. * @post The are bytes to be read. */ void rb_io_read_check(rb_io_t *fptr); RBIMPL_ATTR_PURE() /** * Queries if the passed IO has any pending reads. Unlike rb_io_read_check() * this doesn't block; has no side effects. * * @param[in] fptr An IO which can have pending reads. * @retval 0 The IO is empty. * @retval 1 There is something buffered. */ int rb_io_read_pending(rb_io_t *fptr); /** * Constructs an instance of ::rb_cStat from the passed information. * * @param[in] st A stat. * @return Allocated new instance of ::rb_cStat. */ VALUE rb_stat_new(const struct stat *st); /* gc.c */ RBIMPL_SYMBOL_EXPORT_END() #endif /* RUBY_IO_H */ include/ruby/subst.h 0000644 00000001446 15152150472 0010470 0 ustar 00 #ifndef RUBY_SUBST_H /*-*-C++-*-vi:se ft=cpp:*/ #define RUBY_SUBST_H 1 /** * @author Ruby developers <ruby-core@ruby-lang.org> * @copyright This file is a part of the programming language Ruby. * Permission is hereby granted, to either redistribute and/or * modify this file, provided that the conditions mentioned in the * file COPYING are met. Consult the file for details. */ #undef snprintf #undef vsnprintf #define snprintf ruby_snprintf #define vsnprintf ruby_vsnprintf #ifdef BROKEN_CLOSE #undef getpeername #define getpeername ruby_getpeername #undef getsockname #define getsockname ruby_getsockname #undef shutdown #define shutdown ruby_shutdown #undef close #define close ruby_close #endif #endif include/ruby/debug.h 0000644 00000072443 15152150472 0010423 0 ustar 00 #ifndef RB_DEBUG_H /*-*-C++-*-vi:se ft=cpp:*/ #define RB_DEBUG_H 1 /** * @file * @author $Author: ko1 $ * @date Tue Nov 20 20:35:08 2012 * @copyright Copyright (C) 2012 Yukihiro Matsumoto * @copyright This file is a part of the programming language Ruby. * Permission is hereby granted, to either redistribute and/or * modify this file, provided that the conditions mentioned in the * file COPYING are met. Consult the file for details. */ #include "ruby/internal/attr/deprecated.h" #include "ruby/internal/attr/nonnull.h" #include "ruby/internal/attr/returns_nonnull.h" #include "ruby/internal/dllexport.h" #include "ruby/internal/event.h" #include "ruby/internal/value.h" RBIMPL_SYMBOL_EXPORT_BEGIN() /* Note: This file contains experimental APIs. */ /* APIs can be replaced at Ruby 2.0.1 or later */ /** * @name Frame-profiling APIs * * @{ */ RBIMPL_ATTR_NONNULL((3)) /** * Queries mysterious "frame"s of the given range. * * The returned values are opaque backtrace pointers, which you are allowed to * issue a very limited set of operations listed below. Don't call arbitrary * ruby methods. * * @param[in] start Start position (0 means the topmost). * @param[in] limit Number objects of `buff`. * @param[out] buff Return buffer. * @param[out] lines Return buffer. * @return Number of objects filled into `buff`. * @post `buff` is filled with backtrace pointers. * @post `lines` is filled with `__LINE__` of each backtraces. * * @internal * * @shyouhei doesn't like this abuse of ::VALUE. It should have been * `const struct rb_callable_method_entry_struct *`. */ int rb_profile_frames(int start, int limit, VALUE *buff, int *lines); /** * Queries mysterious "frame"s of the given range. * * A per-thread version of rb_profile_frames(). * Arguments and return values are the same with rb_profile_frames() with the * exception of the first argument _thread_, which accepts the Thread to be * profiled/queried. * * @param[in] thread The Ruby Thread to be profiled. * @param[in] start Start position (0 means the topmost). * @param[in] limit Number objects of `buff`. * @param[out] buff Return buffer. * @param[out] lines Return buffer. * @return Number of objects filled into `buff`. * @post `buff` is filled with backtrace pointers. * @post `lines` is filled with `__LINE__` of each backtraces. */ int rb_profile_thread_frames(VALUE thread, int start, int limit, VALUE *buff, int *lines); /** * Queries the path of the passed backtrace. * * @param[in] frame What rb_profile_frames() returned. * @retval RUBY_Qnil The frame is implemented in C etc. * @retval otherwise Where `frame` is running. */ VALUE rb_profile_frame_path(VALUE frame); /** * Identical to rb_profile_frame_path(), except it tries to expand the * returning path. In case the path is `require`-d from something else * rb_profile_frame_path() can return relative paths. This one tries to avoid * that. * * @param[in] frame What rb_profile_frames() returned. * @retval "<cfunc>" The frame is in C. * @retval RUBY_Qnil Can't infer real path (inside of `eval` etc.). * @retval otherwise Where `frame` is running. */ VALUE rb_profile_frame_absolute_path(VALUE frame); /** * Queries human-readable "label" string. This is `"<main>"` for the toplevel, * `"<compiled>"` for evaluated ones, method name for methods, class name for * classes. * * @param[in] frame What rb_profile_frames() returned. * @retval RUBY_Qnil Can't infer the label (C etc.). * @retval "<main>" The frame is global toplevel. * @retval "<compiled>" The frame is dynamic. * @retval otherwise Label of the frame. */ VALUE rb_profile_frame_label(VALUE frame); /** * Identical to rb_profile_frame_label(), except it does not "qualify" the * result. Consider the following backtrace: * * ```ruby * def bar * caller_locations * end * * def foo * [1].map { bar }.first * end * * obj = foo.first * obj.label # => "block in foo" * obj.base_label # => "foo" * ``` * * @param[in] frame What rb_profile_frames() returned. * @retval RUBY_Qnil Can't infer the label (C etc.). * @retval "<main>" The frame is global toplevel. * @retval "<compiled>" The frame is dynamic. * @retval otherwise Base label of the frame. */ VALUE rb_profile_frame_base_label(VALUE frame); /** * Identical to rb_profile_frame_label(), except it returns a qualified result. * * @param[in] frame What rb_profile_frames() returned. * @retval RUBY_Qnil Can't infer the label (C etc.). * @retval "<main>" The frame is global toplevel. * @retval "<compiled>" The frame is dynamic. * @retval otherwise Qualified label of the frame. * * @internal * * As of writing there is no way to obtain this return value from a Ruby * script. This may change in future (it took 8 years and still no progress, * though). */ VALUE rb_profile_frame_full_label(VALUE frame); /** * Queries the first line of the method of the passed frame pointer. Can be * handy when for instance a debugger want to display the frame in question. * * @param[in] frame What rb_profile_frames() returned. * @retval RUBY_Qnil Can't infer the line (C etc.). * @retval otherwise Line number of the method in question. */ VALUE rb_profile_frame_first_lineno(VALUE frame); /** * Queries the class path of the method that the passed frame represents. * * @param[in] frame What rb_profile_frames() returned. * @retval RUBY_Qnil Can't infer the class (global toplevel etc.). * @retval otherwise Class path as in rb_class_path(). */ VALUE rb_profile_frame_classpath(VALUE frame); /** * Queries if the method of the passed frame is a singleton class. * * @param[in] frame What rb_profile_frames() returned. * @retval RUBY_Qtrue It is a singleton method. * @retval RUBY_Qfalse Otherwise (normal method/non-method). */ VALUE rb_profile_frame_singleton_method_p(VALUE frame); /** * Queries the name of the method of the passed frame. * * @param[in] frame What rb_profile_frames() returned. * @retval RUBY_Qnil The frame in question is not a method. * @retval otherwise Name of the method of the frame. */ VALUE rb_profile_frame_method_name(VALUE frame); /** * Identical to rb_profile_frame_method_name(), except it "qualifies" the * return value with its defining class. * * @param[in] frame What rb_profile_frames() returned. * @retval RUBY_Qnil The frame in question is not a method. * @retval otherwise Qualified name of the method of the frame. */ VALUE rb_profile_frame_qualified_method_name(VALUE frame); /** @} */ /** * @name Debug inspector APIs * * @{ */ /** Opaque struct representing a debug inspector. */ typedef struct rb_debug_inspector_struct rb_debug_inspector_t; /** * Type of the callback function passed to rb_debug_inspector_open(). * Inspection shall happen only inside of them. The passed pointers gets * invalidated once after the callback returns. * * @param[in] dc A debug context. * @param[in,out] data What was passed to rb_debug_inspector_open(). * @return What would be the return value of rb_debug_inspector_open(). */ typedef VALUE (*rb_debug_inspector_func_t)(const rb_debug_inspector_t *dc, void *data); /** * Prepares, executes, then cleans up a debug session. * * @param[in] func A callback to run inside of a debug session. * @param[in,out] data Passed as-is to `func`. * @return What was returned from `func`. */ VALUE rb_debug_inspector_open(rb_debug_inspector_func_t func, void *data); /** * Queries the backtrace object of the context. This is as if you call * `caller_locations` at the point of debugger. * * @param[in] dc A debug context. * @return An array of `Thread::Backtrace::Location` which represents the * current point of execution at `dc`. */ VALUE rb_debug_inspector_backtrace_locations(const rb_debug_inspector_t *dc); /** * Queries the current receiver of the passed context's upper frame. * * @param[in] dc A debug context. * @param[in] index Index of the frame from top to bottom. * @exception rb_eArgError `index` out of range. * @return The current receiver at `index`-th frame. */ VALUE rb_debug_inspector_frame_self_get(const rb_debug_inspector_t *dc, long index); /** * Queries the current class of the passed context's upper frame. * * @param[in] dc A debug context. * @param[in] index Index of the frame from top to bottom. * @exception rb_eArgError `index` out of range. * @return The current class at `index`-th frame. */ VALUE rb_debug_inspector_frame_class_get(const rb_debug_inspector_t *dc, long index); /** * Queries the binding of the passed context's upper frame. * * @param[in] dc A debug context. * @param[in] index Index of the frame from top to bottom. * @exception rb_eArgError `index` out of range. * @return The binding at `index`-th frame. */ VALUE rb_debug_inspector_frame_binding_get(const rb_debug_inspector_t *dc, long index); /** * Queries the instruction sequence of the passed context's upper frame. * * @param[in] dc A debug context. * @param[in] index Index of the frame from top to bottom. * @exception rb_eArgError `index` out of range. * @retval RUBY_Qnil `index`-th frame is not in Ruby (C etc.). * @retval otherwise An instance of `RubyVM::InstructionSequence` which * represents the instruction sequence at `index`-th * frame. */ VALUE rb_debug_inspector_frame_iseq_get(const rb_debug_inspector_t *dc, long index); /** * Queries the depth of the passed context's upper frame. * * Note that the depth is not same as the frame index because debug_inspector * skips some special frames but the depth counts all frames. * * @param[in] dc A debug context. * @param[in] index Index of the frame from top to bottom. * @exception rb_eArgError `index` out of range. * @retval The depth at `index`-th frame in Integer. */ VALUE rb_debug_inspector_frame_depth(const rb_debug_inspector_t *dc, long index); // A macro to recognize `rb_debug_inspector_frame_depth()` is available or not #define RB_DEBUG_INSPECTOR_FRAME_DEPTH(dc, index) rb_debug_inspector_frame_depth(dc, index) /** * Return current frmae depth. * * @retval The depth of the current frame in Integer. */ VALUE rb_debug_inspector_current_depth(void); /** @} */ /** * @name Old style set_trace_func APIs * * @{ */ /* duplicated def of include/ruby/ruby.h */ #include "ruby/internal/event.h" /** * Identical to rb_remove_event_hook(), except it additionally takes the data * argument. This extra argument is the same as that of rb_add_event_hook(), * and this function removes the hook which matches both arguments at once. * * @param[in] func A callback. * @param[in] data What to be passed to `func`. * @return Number of deleted event hooks. * @note As multiple events can share the same `func` it is quite * possible for the return value to become more than one. */ int rb_remove_event_hook_with_data(rb_event_hook_func_t func, VALUE data); /** * Identical to rb_add_event_hook(), except its effect is limited to the passed * thread. Other threads are not affected by this. * * @param[in] thval An instance of ::rb_cThread. * @param[in] func A callback. * @param[in] events A set of events that `func` should run. * @param[in] data Passed as-is to `func`. * @exception rb_eTypeError `thval` is not a thread. */ void rb_thread_add_event_hook(VALUE thval, rb_event_hook_func_t func, rb_event_flag_t events, VALUE data); /** * Identical to rb_remove_event_hook(), except it additionally takes a thread * argument. This extra argument is the same as that of * rb_thread_add_event_hook(), and this function removes the hook which matches * both arguments at once. * * @param[in] thval An instance of ::rb_cThread. * @param[in] func A callback. * @exception rb_eTypeError `thval` is not a thread. * @return Number of deleted event hooks. * @note As multiple events can share the same `func` it is quite * possible for the return value to become more than one. */ int rb_thread_remove_event_hook(VALUE thval, rb_event_hook_func_t func); /** * Identical to rb_thread_remove_event_hook(), except it additionally takes the * data argument. It can also be seen as a routine identical to * rb_remove_event_hook_with_data(), except it additionally takes the thread. * This function deletes hooks that satisfy all three criteria. * * @param[in] thval An instance of ::rb_cThread. * @param[in] func A callback. * @param[in] data What to be passed to `func`. * @exception rb_eTypeError `thval` is not a thread. * @return Number of deleted event hooks. * @note As multiple events can share the same `func` it is quite * possible for the return value to become more than one. */ int rb_thread_remove_event_hook_with_data(VALUE thval, rb_event_hook_func_t func, VALUE data); /** @} */ /** * @name TracePoint APIs * * @{ */ /** * Creates a tracepoint by registering a callback function for one or more * tracepoint events. Once the tracepoint is created, you can use * rb_tracepoint_enable to enable the tracepoint. * * @param[in] target_thread_not_supported_yet Meant for picking the * thread in which the tracepoint is to be created. * However, current implementation ignore this * parameter, tracepoint is created for all threads. * Simply specify Qnil. * @param[in] events Event(s) to listen to. * @param[in] func A callback function. * @param[in,out] data Void pointer that will be passed to the callback * function. * * When the callback function is called, it will be passed 2 parameters: * 1. `VALUE tpval` - the TracePoint object from which trace args can be * extracted. * 1. `void *data` - A void pointer which helps to share scope with the * callback function. * * It is important to note that you cannot register callbacks for normal events * and internal events simultaneously because they are different purpose. You * can use any Ruby APIs (calling methods and so on) on normal event hooks. * However, in internal events, you can not use any Ruby APIs (even object * creations). This is why we can't specify internal events by TracePoint * directly. Limitations are MRI version specific. * * Example: * * ```CXX * rb_tracepoint_new( * Qnil, * RUBY_INTERNAL_EVENT_NEWOBJ | RUBY_INTERNAL_EVENT_FREEOBJ, * obj_event_i, * data); * ``` * * In this example, a callback function `obj_event_i` will be registered for * internal events #RUBY_INTERNAL_EVENT_NEWOBJ and * #RUBY_INTERNAL_EVENT_FREEOBJ. */ VALUE rb_tracepoint_new(VALUE target_thread_not_supported_yet, rb_event_flag_t events, void (*func)(VALUE, void *), void *data); /** * Starts (enables) trace(s) defined by the passed object. A TracePoint object * does not immediately take effect on creation. You have to explicitly call * this API. * * @param[in] tpval An instance of TracePoint. * @exception rb_eArgError A trace is already running. * @return Undefined value. Forget this. It should have returned `void`. * @post Trace(s) defined by `tpval` start. */ VALUE rb_tracepoint_enable(VALUE tpval); /** * Stops (disables) an already running instance of TracePoint. * * @param[in] tpval An instance of TracePoint. * @return Undefined value. Forget this. It should have returned `void`. * @post Trace(s) defined by `tpval` stop. */ VALUE rb_tracepoint_disable(VALUE tpval); /** * Queries if the passed TracePoint is up and running. * * @param[in] tpval An instance of TracePoint. * @retval RUBY_Qtrue It is. * @retval RUBY_Qfalse It isn't. */ VALUE rb_tracepoint_enabled_p(VALUE tpval); /** * Type that represents a specific trace event. Roughly resembles the * tracepoint object that is passed to the block of `TracePoint.new`: * * ```ruby * TracePoint.new(*events) do |obj| * ... # ^^^^^ Resembles this object. * end * ``` */ typedef struct rb_trace_arg_struct rb_trace_arg_t; RBIMPL_ATTR_RETURNS_NONNULL() /** * Queries the current event of the passed tracepoint. * * @param[in] tpval An instance of TracePoint. * @exception rb_eRuntimeError `tpval` is disabled. * @return The current event. * * @internal * * `tpval` is a fake. There is only one instance of ::rb_trace_arg_t at one * time. This function just returns that global variable. */ rb_trace_arg_t *rb_tracearg_from_tracepoint(VALUE tpval); RBIMPL_ATTR_NONNULL(()) /** * Queries the event of the passed trace. * * @param[in] trace_arg A trace instance. * @return Its event. */ rb_event_flag_t rb_tracearg_event_flag(rb_trace_arg_t *trace_arg); RBIMPL_ATTR_NONNULL(()) /** * Identical to rb_tracearg_event_flag(), except it returns the name of the * event in Ruby's symbol. * * @param[in] trace_arg A trace instance. * @return Its event, in Ruby level Symbol object. */ VALUE rb_tracearg_event(rb_trace_arg_t *trace_arg); RBIMPL_ATTR_NONNULL(()) /** * Queries the line of the point where the trace is at. * * @param[in] trace_arg A trace instance. * @retval 0 The trace is not at Ruby frame. * @return otherwise Its line number. */ VALUE rb_tracearg_lineno(rb_trace_arg_t *trace_arg); RBIMPL_ATTR_NONNULL(()) /** * Queries the file name of the point where the trace is at. * * @param[in] trace_arg A trace instance. * @retval RUBY_Qnil The trace is not at Ruby frame. * @retval otherwise Its path. */ VALUE rb_tracearg_path(rb_trace_arg_t *trace_arg); RBIMPL_ATTR_NONNULL(()) /** * Queries the method name of the point where the trace is at. * * @param[in] trace_arg A trace instance. * @retval RUBY_Qnil There is no method. * @retval otherwise Its method name, in Ruby level Symbol. */ VALUE rb_tracearg_method_id(rb_trace_arg_t *trace_arg); RBIMPL_ATTR_NONNULL(()) /** * Identical to rb_tracearg_method_id(), except it returns callee id like * rb_frame_callee(). * * @param[in] trace_arg A trace instance. * @retval RUBY_Qnil There is no method. * @retval otherwise Its method name, in Ruby level Symbol. */ VALUE rb_tracearg_callee_id(rb_trace_arg_t *trace_arg); RBIMPL_ATTR_NONNULL(()) /** * Queries the class that defines the method that the passed trace is at. This * can be different from the class of rb_tracearg_self()'s return value because * of inheritance(s). * * @param[in] trace_arg A trace instance. * @retval RUBY_Qnil There is no method. * @retval otherwise Its method's class. */ VALUE rb_tracearg_defined_class(rb_trace_arg_t *trace_arg); RBIMPL_ATTR_NONNULL(()) /** * Creates a binding object of the point where the trace is at. * * @param[in] trace_arg A trace instance. * @retval RUBY_Qnil The point has no binding. * @retval otherwise Its binding. * * @internal * * @shyouhei has no idea on which situation shall this function return * ::RUBY_Qnil. */ VALUE rb_tracearg_binding(rb_trace_arg_t *trace_arg); RBIMPL_ATTR_NONNULL(()) /** * Queries the receiver of the point trace is at. * * @param[in] trace_arg A trace instance. * @return Its receiver. */ VALUE rb_tracearg_self(rb_trace_arg_t *trace_arg); RBIMPL_ATTR_NONNULL(()) /** * Queries the return value that the trace represents. * * @param[in] trace_arg A trace instance. * @exception rb_eRuntimeError The tracing event is not return-related. * @return The return value. */ VALUE rb_tracearg_return_value(rb_trace_arg_t *trace_arg); RBIMPL_ATTR_NONNULL(()) /** * Queries the raised exception that the trace represents. * * @param[in] trace_arg A trace instance. * @exception rb_eRuntimeError The tracing event is not exception-related. * @return The raised exception. */ VALUE rb_tracearg_raised_exception(rb_trace_arg_t *trace_arg); RBIMPL_ATTR_NONNULL(()) /** * Queries the allocated/deallocated object that the trace represents. * * @param[in] trace_arg A trace instance. * @exception rb_eRuntimeError The tracing event is not GC-related. * @return The allocated/deallocated object. */ VALUE rb_tracearg_object(rb_trace_arg_t *trace_arg); /** @} */ /** * @name Postponed Job API * * @{ */ /* * Postponed Job API * * This API is designed to be called from contexts where it is not safe to run Ruby * code (e.g. because they do not hold the GVL or because GC is in progress), and * defer a callback to run in a context where it _is_ safe. The primary intended * users of this API is for sampling profilers like the "stackprof" gem; these work * by scheduling the periodic delivery of a SIGPROF signal, and inside the C-level * signal handler, deferring a job to collect a Ruby backtrace when it is next safe * to do so. * * Ruby maintains a small, fixed-size postponed job table. An extension using this * API should first call `rb_postponed_job_preregister` to register a callback * function in this table and obtain a handle of type `rb_postponed_job_handle_t` * to it. Subsequently, the callback can be triggered by calling * `rb_postponed_job_trigger` with that handle, or the `data` associated with the * callback function can be changed by calling `rb_postponed_job_preregister` again. * * Because the postponed job table is quite small (it only has 32 entries on most * common systems), extensions should generally only preregister one or two `func` * values. * * Historically, this API provided two functions `rb_postponed_job_register` and * `rb_postponed_job_register_one`, which claimed to be fully async-signal-safe and * would call back the provided `func` and `data` at an appropriate time. However, * these functions were subject to race conditions which could cause crashes when * racing with Ruby's internal use of them. These two functions are still present, * but are marked as deprecated and have slightly changed semantics: * * * rb_postponed_job_register now works like rb_postponed_job_register_one i.e. * `func` will only be executed at most one time each time Ruby checks for * interrupts, no matter how many times it is registered * * They are also called with the last `data` to be registered, not the first * (which is how rb_postponed_job_register_one previously worked) */ /** * Type of postponed jobs. * * @param[in,out] arg What was passed to `rb_postponed_job_preregister` */ typedef void (*rb_postponed_job_func_t)(void *arg); /** * The type of a handle returned from `rb_postponed_job_preregister` and * passed to `rb_postponed_job_trigger` */ typedef unsigned int rb_postponed_job_handle_t; #define POSTPONED_JOB_HANDLE_INVALID ((rb_postponed_job_handle_t)UINT_MAX) /** * Pre-registers a func in Ruby's postponed job preregistration table, * returning an opaque handle which can be used to trigger the job later. Generally, * this function will be called during the initialization routine of an extension. * * The returned handle can be used later to call `rb_postponed_job_trigger`. This will * cause Ruby to call back into the registered `func` with `data` at a later time, in * a context where the GVL is held and it is safe to perform Ruby allocations. * * If the given `func` was already pre-registered, this function will overwrite the * stored data with the newly passed data, and return the same handle instance as * was previously returned. * * If this function is called concurrently with the same `func`, then the stored data * could be the value from either call (but will definitely be one of them). * * If this function is called to update the data concurrently with a call to * `rb_postponed_job_trigger` on the same handle, it's undefined whether `func` will * be called with the old data or the new data. * * Although the current implementation of this function is in fact async-signal-safe and * has defined semantics when called concurrently on the same `func`, a future Ruby * version might require that this method be called under the GVL; thus, programs which * aim to be forward-compatible should call this method whilst holding the GVL. * * @param[in] flags Unused and ignored * @param[in] func The function to be pre-registered * @param[in] data The data to be pre-registered * @retval POSTPONED_JOB_HANDLE_INVALID The job table is full; this registration * did not succeed and no further registration will do so for * the lifetime of the program. * @retval otherwise A handle which can be passed to `rb_postponed_job_trigger` */ rb_postponed_job_handle_t rb_postponed_job_preregister(unsigned int flags, rb_postponed_job_func_t func, void *data); /** * Triggers a pre-registered job registered with rb_postponed_job_preregister, * scheduling it for execution the next time the Ruby VM checks for interrupts. * The context in which the job is called in holds the GVL and is safe to perform * Ruby allocations within (i.e. it is not during GC). * * This method is async-signal-safe and can be called from any thread, at any * time, including in signal handlers. * * If this method is called multiple times, Ruby will coalesce this into only * one call to the job the next time it checks for interrupts. * * @params[in] h A handle returned from rb_postponed_job_preregister */ void rb_postponed_job_trigger(rb_postponed_job_handle_t h); /** * Schedules the given `func` to be called with `data` when Ruby next checks for * interrupts. If this function is called multiple times in between Ruby checking * for interrupts, then `func` will be called only once with the `data` value from * the first call to this function. * * Like `rb_postponed_job_trigger`, the context in which the job is called * holds the GVL and can allocate Ruby objects. * * This method essentially has the same semantics as: * * ``` * rb_postponed_job_trigger(rb_postponed_job_preregister(func, data)); * ``` * * @note Previous versions of Ruby promised that the (`func`, `data`) pairs would * be executed as many times as they were registered with this function; in * reality this was always subject to race conditions and this function no * longer provides this guarantee. Instead, multiple calls to this function * can be coalesced into a single execution of the passed `func`, with the * most recent `data` registered at that time passed in. * * @deprecated This interface implies that arbitrarily many `func`'s can be enqueued * over the lifetime of the program, whilst in reality the registration * slots for postponed jobs are a finite resource. This is made clearer * by the `rb_postponed_job_preregister` and `rb_postponed_job_trigger` * functions, and a future version of Ruby might delete this function. * * @param[in] flags Unused and ignored. * @param[in] func Job body. * @param[in,out] data Passed as-is to `func`. * @retval 0 Postponed job registration table is full. Failed. * @retval 1 Registration succeeded. * @post The passed job will run on the next interrupt check. */ RBIMPL_ATTR_DEPRECATED(("use rb_postponed_job_preregister and rb_postponed_job_trigger")) int rb_postponed_job_register(unsigned int flags, rb_postponed_job_func_t func, void *data); /** * Identical to `rb_postponed_job_register` * * @deprecated This is deprecated for the same reason as `rb_postponed_job_register` * * @param[in] flags Unused and ignored. * @param[in] func Job body. * @param[in,out] data Passed as-is to `func`. * @retval 0 Postponed job registration table is full. Failed. * @retval 1 Registration succeeded. * @post The passed job will run on the next interrupt check. */ RBIMPL_ATTR_DEPRECATED(("use rb_postponed_job_preregister and rb_postponed_job_trigger")) int rb_postponed_job_register_one(unsigned int flags, rb_postponed_job_func_t func, void *data); /** @} */ /** * @cond INTERNAL_MACRO * * Anything after this are intentionally left undocumented, to honour the * comment below. */ /* undocumented advanced tracing APIs */ typedef enum { RUBY_EVENT_HOOK_FLAG_SAFE = 0x01, RUBY_EVENT_HOOK_FLAG_DELETED = 0x02, RUBY_EVENT_HOOK_FLAG_RAW_ARG = 0x04 } rb_event_hook_flag_t; void rb_add_event_hook2(rb_event_hook_func_t func, rb_event_flag_t events, VALUE data, rb_event_hook_flag_t hook_flag); void rb_thread_add_event_hook2(VALUE thval, rb_event_hook_func_t func, rb_event_flag_t events, VALUE data, rb_event_hook_flag_t hook_flag); /** @endcond */ RBIMPL_SYMBOL_EXPORT_END() #endif /* RUBY_DEBUG_H */ include/ruby/config.h 0000644 00000034023 15152150472 0010572 0 ustar 00 #ifndef INCLUDE_RUBY_CONFIG_H #define INCLUDE_RUBY_CONFIG_H 1 /* confdefs.h */ #define STDC_HEADERS 1 #define HAVE_SYS_TYPES_H 1 #define HAVE_SYS_STAT_H 1 #define HAVE_STDLIB_H 1 #define HAVE_STRING_H 1 #define HAVE_MEMORY_H 1 #define HAVE_STRINGS_H 1 #define HAVE_INTTYPES_H 1 #define HAVE_STDINT_H 1 #define HAVE_UNISTD_H 1 #define __EXTENSIONS__ 1 #define _ALL_SOURCE 1 #define _GNU_SOURCE 1 #define _POSIX_PTHREAD_SEMANTICS 1 #define _TANDEM_SOURCE 1 #define RUBY_SYMBOL_EXPORT_BEGIN _Pragma("GCC visibility push(default)") #define RUBY_SYMBOL_EXPORT_END _Pragma("GCC visibility pop") #define HAVE_STMT_AND_DECL_IN_EXPR 1 #define HAVE_PTHREAD_H 1 #define _REENTRANT 1 #define _THREAD_SAFE 1 #define HAVE_LIBPTHREAD 1 #define THREAD_IMPL_H "thread_pthread.h" #define THREAD_IMPL_SRC "thread_pthread.c" #define HAVE_LIBCRYPT 1 #define HAVE_LIBDL 1 #define HAVE_DIRENT_H 1 #define HAVE__BOOL 1 #define HAVE_STDBOOL_H 1 #define HAVE_SYS_WAIT_H 1 #define HAVE_GRP_H 1 #define HAVE_FCNTL_H 1 #define HAVE_FLOAT_H 1 #define HAVE_LANGINFO_H 1 #define HAVE_LIMITS_H 1 #define HAVE_LOCALE_H 1 #define HAVE_MALLOC_H 1 #define HAVE_PWD_H 1 #define HAVE_SANITIZER_ASAN_INTERFACE_H 1 #define HAVE_STDALIGN_H 1 #define HAVE_STDIO_H 1 #define HAVE_SYS_EVENTFD_H 1 #define HAVE_SYS_FCNTL_H 1 #define HAVE_SYS_FILE_H 1 #define HAVE_SYS_IOCTL_H 1 #define HAVE_SYS_PARAM_H 1 #define HAVE_SYS_PRCTL_H 1 #define HAVE_SYS_RANDOM_H 1 #define HAVE_SYS_RESOURCE_H 1 #define HAVE_SYS_SELECT_H 1 #define HAVE_SYS_SENDFILE_H 1 #define HAVE_SYS_SOCKET_H 1 #define HAVE_SYS_SYSCALL_H 1 #define HAVE_SYS_SYSMACROS_H 1 #define HAVE_SYS_TIME_H 1 #define HAVE_SYS_TIMES_H 1 #define HAVE_SYS_UIO_H 1 #define HAVE_SYSCALL_H 1 #define HAVE_TIME_H 1 #define HAVE_UCONTEXT_H 1 #define HAVE_UTIME_H 1 #define HAVE_SYS_EPOLL_H 1 #define HAVE_STDATOMIC_H 1 #define HAVE_X86INTRIN_H 1 #if defined(__x86_64__) #define HAVE_X86INTRIN_H 1 #endif #define HAVE_GMP_H 1 #define HAVE_LIBGMP 1 #define HAVE_TYPEOF 1 #define restrict __restrict #define HAVE_LONG_LONG 1 #define HAVE_OFF_T 1 #define SIZEOF_INT 4 #define SIZEOF_SHORT 2 #define SIZEOF_LONG 8 #define SIZEOF_LONG_LONG 8 #define SIZEOF___INT64 0 #define SIZEOF___INT128 16 #define SIZEOF_OFF_T 8 #define SIZEOF_VOIDP 8 #define SIZEOF_FLOAT 4 #define SIZEOF_DOUBLE 8 #define SIZEOF_TIME_T 8 #define SIZEOF_CLOCK_T 8 #define RBIMPL_ATTR_PACKED_STRUCT_BEGIN() #define RBIMPL_ATTR_PACKED_STRUCT_END() __attribute__((packed)) #define USE_UNALIGNED_MEMBER_ACCESS 1 #define PRI_LL_PREFIX "ll" #define HAVE_PID_T 1 #define rb_pid_t pid_t #define SIGNEDNESS_OF_PID_T -1 #define PIDT2NUM(v) INT2NUM(v) #define NUM2PIDT(v) NUM2INT(v) #define PRI_PIDT_PREFIX PRI_INT_PREFIX #define HAVE_UID_T 1 #define rb_uid_t uid_t #define SIGNEDNESS_OF_UID_T +1 #define UIDT2NUM(v) UINT2NUM(v) #define NUM2UIDT(v) NUM2UINT(v) #define PRI_UIDT_PREFIX PRI_INT_PREFIX #define HAVE_GID_T 1 #define rb_gid_t gid_t #define SIGNEDNESS_OF_GID_T +1 #define GIDT2NUM(v) UINT2NUM(v) #define NUM2GIDT(v) NUM2UINT(v) #define PRI_GIDT_PREFIX PRI_INT_PREFIX #define HAVE_TIME_T 1 #define rb_time_t time_t #define SIGNEDNESS_OF_TIME_T -1 #define TIMET2NUM(v) LONG2NUM(v) #define NUM2TIMET(v) NUM2LONG(v) #define PRI_TIMET_PREFIX PRI_LONG_PREFIX #define HAVE_DEV_T 1 #define rb_dev_t dev_t #define SIGNEDNESS_OF_DEV_T +1 #define DEVT2NUM(v) ULONG2NUM(v) #define NUM2DEVT(v) NUM2ULONG(v) #define PRI_DEVT_PREFIX PRI_LONG_PREFIX #define HAVE_MODE_T 1 #define rb_mode_t mode_t #define SIGNEDNESS_OF_MODE_T +1 #define MODET2NUM(v) UINT2NUM(v) #define NUM2MODET(v) NUM2UINT(v) #define PRI_MODET_PREFIX PRI_INT_PREFIX #define HAVE_RLIM_T 1 #define rb_rlim_t rlim_t #define SIGNEDNESS_OF_RLIM_T +1 #define RLIM2NUM(v) ULONG2NUM(v) #define NUM2RLIM(v) NUM2ULONG(v) #define PRI_RLIM_PREFIX PRI_LONG_PREFIX #define HAVE_OFF_T 1 #define rb_off_t off_t #define SIGNEDNESS_OF_OFF_T -1 #define OFFT2NUM(v) LONG2NUM(v) #define NUM2OFFT(v) NUM2LONG(v) #define PRI_OFFT_PREFIX PRI_LONG_PREFIX #define HAVE_CLOCKID_T 1 #define rb_clockid_t clockid_t #define SIGNEDNESS_OF_CLOCKID_T -1 #define CLOCKID2NUM(v) INT2NUM(v) #define NUM2CLOCKID(v) NUM2INT(v) #define PRI_CLOCKID_PREFIX PRI_INT_PREFIX #define HAVE_VA_ARGS_MACRO 1 #define HAVE__ALIGNOF 1 #define CONSTFUNC(x) __attribute__ ((__const__)) x #define PUREFUNC(x) __attribute__ ((__pure__)) x #define NORETURN(x) __attribute__ ((__noreturn__)) x #define DEPRECATED(x) __attribute__ ((__deprecated__)) x #define DEPRECATED_BY(n,x) __attribute__ ((__deprecated__("by "#n))) x #define NOINLINE(x) __attribute__ ((__noinline__)) x #define ALWAYS_INLINE(x) __attribute__ ((__always_inline__)) x #define NO_SANITIZE(san, x) __attribute__ ((__no_sanitize__(san))) x #define NO_SANITIZE_ADDRESS(x) __attribute__ ((__no_sanitize_address__)) x #define NO_ADDRESS_SAFETY_ANALYSIS(x) __attribute__ ((__no_address_safety_analysis__)) x #define WARN_UNUSED_RESULT(x) __attribute__ ((__warn_unused_result__)) x #define MAYBE_UNUSED(x) __attribute__ ((__unused__)) x #define ERRORFUNC(mesg,x) __attribute__ ((__error__ mesg)) x #define WARNINGFUNC(mesg,x) __attribute__ ((__warning__ mesg)) x #define WEAK(x) __attribute__ ((__weak__)) x #define HAVE_FUNC_WEAK 1 #define RUBY_CXX_DEPRECATED(msg) __attribute__((__deprecated__(msg))) #define HAVE_NULLPTR 1 #define FUNC_UNOPTIMIZED(x) __attribute__ ((__optimize__("O0"))) x #define FUNC_MINIMIZED(x) __attribute__ ((__optimize__("-Os","-fomit-frame-pointer"))) x #define HAVE_ATTRIBUTE_FUNCTION_ALIAS 1 #define RUBY_ALIAS_FUNCTION_TYPE(type, prot, name, args) type prot __attribute__((alias(#name))); #define RUBY_ALIAS_FUNCTION_VOID(prot, name, args) RUBY_ALIAS_FUNCTION_TYPE(void, prot, name, args) #define HAVE_GCC_ATOMIC_BUILTINS 1 #define HAVE_GCC_SYNC_BUILTINS 1 #define HAVE___BUILTIN_UNREACHABLE 1 #define RUBY_FUNC_EXPORTED __attribute__ ((__visibility__("default"))) extern #define RUBY_FUNC_NONNULL(n,x) __attribute__ ((__nonnull__(n))) x #define RUBY_FUNCTION_NAME_STRING __func__ #define ENUM_OVER_INT 1 #define HAVE_DECL_SYS_NERR 1 #define HAVE_DECL_GETENV 1 #define SIZEOF_SIZE_T 8 #define SIZEOF_PTRDIFF_T 8 #define SIZEOF_DEV_T 8 #define PRI_SIZE_PREFIX "z" #define PRI_PTRDIFF_PREFIX "t" #define HAVE_STRUCT_STAT_ST_BLKSIZE 1 #define HAVE_STRUCT_STAT_ST_BLOCKS 1 #define HAVE_STRUCT_STAT_ST_RDEV 1 #define SIZEOF_STRUCT_STAT_ST_SIZE SIZEOF_OFF_T #define SIZEOF_STRUCT_STAT_ST_BLOCKS SIZEOF_OFF_T #define SIZEOF_STRUCT_STAT_ST_INO SIZEOF_LONG #define SIZEOF_STRUCT_STAT_ST_DEV SIZEOF_DEV_T #define SIZEOF_STRUCT_STAT_ST_RDEV SIZEOF_DEV_T #define HAVE_STRUCT_STAT_ST_ATIM 1 #define HAVE_STRUCT_STAT_ST_MTIM 1 #define HAVE_STRUCT_STAT_ST_CTIM 1 #define HAVE_STRUCT_STATX_STX_BTIME 1 #define HAVE_STRUCT_TIMEVAL 1 #define SIZEOF_STRUCT_TIMEVAL_TV_SEC SIZEOF_TIME_T #define HAVE_STRUCT_TIMESPEC 1 #define HAVE_STRUCT_TIMEZONE 1 #define HAVE_RB_FD_INIT 1 #define HAVE_INT8_T 1 #define SIZEOF_INT8_T 1 #define HAVE_UINT8_T 1 #define SIZEOF_UINT8_T 1 #define HAVE_INT16_T 1 #define SIZEOF_INT16_T 2 #define HAVE_UINT16_T 1 #define SIZEOF_UINT16_T 2 #define HAVE_INT32_T 1 #define SIZEOF_INT32_T 4 #define HAVE_UINT32_T 1 #define SIZEOF_UINT32_T 4 #define HAVE_INT64_T 1 #define SIZEOF_INT64_T 8 #define HAVE_UINT64_T 1 #define SIZEOF_UINT64_T 8 #define HAVE_INT128_T 1 #define int128_t __int128 #define SIZEOF_INT128_T SIZEOF___INT128 #define HAVE_UINT128_T 1 #define uint128_t unsigned __int128 #define SIZEOF_UINT128_T SIZEOF___INT128 #define HAVE_INTPTR_T 1 #define SIZEOF_INTPTR_T 8 #define HAVE_UINTPTR_T 1 #define SIZEOF_UINTPTR_T 8 #define HAVE_SSIZE_T 1 #define SIZEOF_SSIZE_T 8 #define STACK_END_ADDRESS __libc_stack_end #define GETGROUPS_T gid_t #define HAVE_ALLOCA_H 1 #define HAVE_ALLOCA 1 #define HAVE_DUP 1 #define HAVE_DUP2 1 #define HAVE_ACOSH 1 #define HAVE_CBRT 1 #define HAVE_CRYPT 1 #define HAVE_ERF 1 #define HAVE_EXPLICIT_BZERO 1 #define HAVE_FFS 1 #define HAVE_FLOCK 1 #define HAVE_HYPOT 1 #define HAVE_LGAMMA_R 1 #define HAVE_MEMMOVE 1 #define HAVE_NAN 1 #define HAVE_NEXTAFTER 1 #define HAVE_STRCHR 1 #define HAVE_STRERROR 1 #define HAVE_STRSTR 1 #define HAVE_TGAMMA 1 #define HAVE_ISFINITE 1 #define SPT_TYPE SPT_REUSEARGV #define HAVE_SIGNBIT 1 #define HAVE_FORK 1 #define HAVE_VFORK 1 #define HAVE_WORKING_VFORK 1 #define HAVE_WORKING_FORK 1 #define HAVE__LONGJMP 1 #define HAVE_ATAN2L 1 #define HAVE_ATAN2F 1 #define HAVE_DECL_ATOMIC_SIGNAL_FENCE 1 #define HAVE_CHMOD 1 #define HAVE_CHOWN 1 #define HAVE_CHROOT 1 #define HAVE_CLOCK_GETTIME 1 #define HAVE_COPY_FILE_RANGE 1 #define HAVE_COSH 1 #define HAVE_CRYPT_R 1 #define HAVE_DIRFD 1 #define HAVE_DL_ITERATE_PHDR 1 #define HAVE_DLOPEN 1 #define HAVE_DLADDR 1 #define HAVE_DUP3 1 #define HAVE_EACCESS 1 #define HAVE_ENDGRENT 1 #define HAVE_EVENTFD 1 #define HAVE_EXECL 1 #define HAVE_EXECLE 1 #define HAVE_EXECV 1 #define HAVE_EXECVE 1 #define HAVE_FCHDIR 1 #define HAVE_FCHMOD 1 #define HAVE_FCHOWN 1 #define HAVE_FCNTL 1 #define HAVE_FDATASYNC 1 #define HAVE_FDOPENDIR 1 #define HAVE_FMOD 1 #define HAVE_FSTATAT 1 #define HAVE_FSYNC 1 #define HAVE_FTRUNCATE 1 #define HAVE_FTRUNCATE64 1 #define HAVE_GETCWD 1 #define HAVE_GETEGID 1 #define HAVE_GETENTROPY 1 #define HAVE_GETEUID 1 #define HAVE_GETGID 1 #define HAVE_GETGRNAM 1 #define HAVE_GETGRNAM_R 1 #define HAVE_GETGROUPS 1 #define HAVE_GETLOGIN 1 #define HAVE_GETLOGIN_R 1 #define HAVE_GETPGID 1 #define HAVE_GETPGRP 1 #define HAVE_GETPPID 1 #define HAVE_GETPRIORITY 1 #define HAVE_GETPWNAM 1 #define HAVE_GETPWNAM_R 1 #define HAVE_GETPWUID 1 #define HAVE_GETPWUID_R 1 #define HAVE_GETRANDOM 1 #define HAVE_GETRESGID 1 #define HAVE_GETRESUID 1 #define HAVE_GETRLIMIT 1 #define HAVE_GETSID 1 #define HAVE_GETTIMEOFDAY 1 #define HAVE_GETUID 1 #define HAVE_GMTIME_R 1 #define HAVE_GRANTPT 1 #define HAVE_INITGROUPS 1 #define HAVE_IOCTL 1 #define HAVE_KILL 1 #define HAVE_KILLPG 1 #define HAVE_LCHOWN 1 #define HAVE_LINK 1 #define HAVE_LLABS 1 #define HAVE_LOCKF 1 #define HAVE_LOG2 1 #define HAVE_LSTAT 1 #define HAVE_LUTIMES 1 #define HAVE_MALLOC_USABLE_SIZE 1 #define HAVE_MALLOC_TRIM 1 #define HAVE_MBLEN 1 #define HAVE_MEMALIGN 1 #define HAVE_WRITEV 1 #define HAVE_MEMRCHR 1 #define HAVE_MEMMEM 1 #define HAVE_MKFIFO 1 #define HAVE_MKNOD 1 #define HAVE_MKTIME 1 #define HAVE_MMAP 1 #define HAVE_MREMAP 1 #define HAVE_OPENAT 1 #define HAVE_PCLOSE 1 #define HAVE_PIPE 1 #define HAVE_PIPE2 1 #define HAVE_POLL 1 #define HAVE_POPEN 1 #define HAVE_POSIX_FADVISE 1 #define HAVE_POSIX_MADVISE 1 #define HAVE_POSIX_MEMALIGN 1 #define HAVE_PPOLL 1 #define HAVE_PREAD 1 #define HAVE_PWRITE 1 #define HAVE_QSORT_R 1 #define HAVE_READLINK 1 #define HAVE_REALPATH 1 #define HAVE_ROUND 1 #define HAVE_SCHED_GETAFFINITY 1 #define HAVE_SEEKDIR 1 #define HAVE_SENDFILE 1 #define HAVE_SETEGID 1 #define HAVE_SETENV 1 #define HAVE_SETEUID 1 #define HAVE_SETGID 1 #define HAVE_SETGROUPS 1 #define HAVE_SETPGID 1 #define HAVE_SETPGRP 1 #define HAVE_SETREGID 1 #define HAVE_SETRESGID 1 #define HAVE_SETRESUID 1 #define HAVE_SETREUID 1 #define HAVE_SETRLIMIT 1 #define HAVE_SETSID 1 #define HAVE_SETUID 1 #define HAVE_SHUTDOWN 1 #define HAVE_SIGACTION 1 #define HAVE_SIGALTSTACK 1 #define HAVE_SIGPROCMASK 1 #define HAVE_SINH 1 #define HAVE_SNPRINTF 1 #define HAVE_SYMLINK 1 #define HAVE_SYSCALL 1 #define HAVE_SYSCONF 1 #define HAVE_SYSTEM 1 #define HAVE_TANH 1 #define HAVE_TELLDIR 1 #define HAVE_TIMEGM 1 #define HAVE_TIMES 1 #define HAVE_TRUNCATE 1 #define HAVE_TRUNCATE64 1 #define HAVE_TZSET 1 #define HAVE_UMASK 1 #define HAVE_UNSETENV 1 #define HAVE_UTIMENSAT 1 #define HAVE_UTIMES 1 #define HAVE_WAIT4 1 #define HAVE_WAITPID 1 #define HAVE_STATX 1 #define HAVE_CRYPT_H 1 #define HAVE_STRUCT_CRYPT_DATA_INITIALIZED 1 #define HAVE_BUILTIN___BUILTIN_ALLOCA_WITH_ALIGN 1 #define HAVE_BUILTIN___BUILTIN_ASSUME_ALIGNED 1 #define HAVE_BUILTIN___BUILTIN_BSWAP16 1 #define HAVE_BUILTIN___BUILTIN_BSWAP32 1 #define HAVE_BUILTIN___BUILTIN_BSWAP64 1 #define HAVE_BUILTIN___BUILTIN_POPCOUNT 1 #define HAVE_BUILTIN___BUILTIN_POPCOUNTLL 1 #define HAVE_BUILTIN___BUILTIN_CLZ 1 #define HAVE_BUILTIN___BUILTIN_CLZL 1 #define HAVE_BUILTIN___BUILTIN_CLZLL 1 #define HAVE_BUILTIN___BUILTIN_CTZ 1 #define HAVE_BUILTIN___BUILTIN_CTZLL 1 #define HAVE_BUILTIN___BUILTIN_ADD_OVERFLOW 1 #define HAVE_BUILTIN___BUILTIN_SUB_OVERFLOW 1 #define HAVE_BUILTIN___BUILTIN_MUL_OVERFLOW 1 #define HAVE_BUILTIN___BUILTIN_MUL_OVERFLOW_P 1 #define HAVE_BUILTIN___BUILTIN_CONSTANT_P 1 #define HAVE_BUILTIN___BUILTIN_CHOOSE_EXPR 1 #define HAVE_BUILTIN___BUILTIN_CHOOSE_EXPR_CONSTANT_P 1 #define HAVE_BUILTIN___BUILTIN_TYPES_COMPATIBLE_P 1 #define HAVE_BUILTIN___BUILTIN_TRAP 1 #define HAVE_BUILTIN___BUILTIN_EXPECT 1 #define USE___BUILTIN_MUL_OVERFLOW_LONG_LONG 1 #define HAVE_GNU_QSORT_R 1 #define ATAN2_INF_C99 1 #define HAVE_CLOCK_GETRES 1 #define HAVE_LIBRT 1 #define HAVE_LIBRT 1 #define HAVE_TIMER_CREATE 1 #define HAVE_TIMER_SETTIME 1 #define HAVE_STRUCT_TM_TM_ZONE 1 #define HAVE_TM_ZONE 1 #define HAVE_STRUCT_TM_TM_GMTOFF 1 #define HAVE_DAYLIGHT 1 #define NEGATIVE_TIME_T 1 #define POSIX_SIGNAL 1 #define HAVE_SIG_T 1 #define RSHIFT(x,y) ((x)>>(int)(y)) #define USE_COPY_FILE_RANGE 1 #define HAVE__SC_CLK_TCK 1 #define STACK_GROW_DIRECTION -1 #define COROUTINE_H "coroutine/amd64/Context.h" #define HAVE_SCHED_YIELD 1 #define HAVE_PTHREAD_ATTR_SETINHERITSCHED 1 #define HAVE_PTHREAD_ATTR_GETSTACK 1 #define HAVE_PTHREAD_ATTR_GETGUARDSIZE 1 #define HAVE_PTHREAD_CONDATTR_SETCLOCK 1 #define HAVE_PTHREAD_SETNAME_NP 1 #define HAVE_PTHREAD_SIGMASK 1 #define HAVE_PTHREAD_GETATTR_NP 1 #define SET_CURRENT_THREAD_NAME(name) pthread_setname_np(pthread_self(), name) #define SET_ANOTHER_THREAD_NAME(thid,name) pthread_setname_np(thid, name) #define RB_THREAD_LOCAL_SPECIFIER _Thread_local #define DEFINE_MCONTEXT_PTR(mc, uc) mcontext_t *mc = &(uc)->uc_mcontext #define HAVE_GETCONTEXT 1 #define HAVE_SETCONTEXT 1 #define HAVE_SYS_USER_H 1 #define HAVE_CONST_PAGE_SIZE 1 #define IOCTL_REQ_TYPE unsigned long #define NUM2IOCTLREQ(num) NUM2ULONG(num) #define USE_ELF 1 #define HAVE_ELF_H 1 #define HAVE_LIBZ 1 #define HAVE_BACKTRACE 1 #define DLEXT_MAXLEN 3 #define DLEXT ".so" #define ENABLE_MULTIARCH 1 #define LIBDIR_BASENAME "lib64" #define HAVE__SETJMP 1 #define RUBY_SETJMP(env) _setjmp((env)) #define RUBY_LONGJMP(env,val) _longjmp((env),val) #define RUBY_JMP_BUF jmp_buf #define USE_YJIT 0 #define USE_RJIT 1 #define RUBY_LIB_VERSION_BLANK 1 #define RUBY_PLATFORM "x86_64-linux" #endif /* INCLUDE_RUBY_CONFIG_H */ include/ruby/st.h 0000644 00000017406 15152150472 0007761 0 ustar 00 /* This is a public domain general purpose hash table package originally written by Peter Moore @ UCB. The hash table data structures were redesigned and the package was rewritten by Vladimir Makarov <vmakarov@redhat.com>. */ #ifndef RUBY_ST_H #define RUBY_ST_H 1 #if defined(__cplusplus) extern "C" { #if 0 } /* satisfy cc-mode */ #endif #endif #include "ruby/defines.h" RUBY_SYMBOL_EXPORT_BEGIN #if SIZEOF_LONG == SIZEOF_VOIDP typedef unsigned long st_data_t; #elif SIZEOF_LONG_LONG == SIZEOF_VOIDP typedef unsigned LONG_LONG st_data_t; #else # error ---->> st.c requires sizeof(void*) == sizeof(long) or sizeof(LONG_LONG) to be compiled. <<---- #endif #define ST_DATA_T_DEFINED #ifndef CHAR_BIT # ifdef HAVE_LIMITS_H # include <limits.h> # else # define CHAR_BIT 8 # endif #endif #ifndef _ # define _(args) args #endif #ifndef ANYARGS # ifdef __cplusplus # define ANYARGS ... # else # define ANYARGS # endif #endif typedef struct st_table st_table; typedef st_data_t st_index_t; /* Maximal value of unsigned integer type st_index_t. */ #define MAX_ST_INDEX_VAL (~(st_index_t) 0) typedef int st_compare_func(st_data_t, st_data_t); typedef st_index_t st_hash_func(st_data_t); typedef char st_check_for_sizeof_st_index_t[SIZEOF_VOIDP == (int)sizeof(st_index_t) ? 1 : -1]; #define SIZEOF_ST_INDEX_T SIZEOF_VOIDP struct st_hash_type { int (*compare)(st_data_t, st_data_t); /* st_compare_func* */ st_index_t (*hash)(st_data_t); /* st_hash_func* */ }; #define ST_INDEX_BITS (SIZEOF_ST_INDEX_T * CHAR_BIT) #if defined(HAVE_BUILTIN___BUILTIN_CHOOSE_EXPR) && defined(HAVE_BUILTIN___BUILTIN_TYPES_COMPATIBLE_P) # define ST_DATA_COMPATIBLE_P(type) \ __builtin_choose_expr(__builtin_types_compatible_p(type, st_data_t), 1, 0) #else # define ST_DATA_COMPATIBLE_P(type) 0 #endif typedef struct st_table_entry st_table_entry; struct st_table_entry; /* defined in st.c */ struct st_table { /* Cached features of the table -- see st.c for more details. */ unsigned char entry_power, bin_power, size_ind; /* How many times the table was rebuilt. */ unsigned int rebuilds_num; const struct st_hash_type *type; /* Number of entries currently in the table. */ st_index_t num_entries; /* Array of bins used for access by keys. */ st_index_t *bins; /* Start and bound index of entries in array entries. entries_starts and entries_bound are in interval [0,allocated_entries]. */ st_index_t entries_start, entries_bound; /* Array of size 2^entry_power. */ st_table_entry *entries; }; #define st_is_member(table,key) st_lookup((table),(key),(st_data_t *)0) enum st_retval {ST_CONTINUE, ST_STOP, ST_DELETE, ST_CHECK, ST_REPLACE}; size_t rb_st_table_size(const struct st_table *tbl); #define st_table_size rb_st_table_size st_table *rb_st_init_table(const struct st_hash_type *); #define st_init_table rb_st_init_table st_table *rb_st_init_table_with_size(const struct st_hash_type *, st_index_t); #define st_init_table_with_size rb_st_init_table_with_size st_table *rb_st_init_existing_table_with_size(st_table *tab, const struct st_hash_type *type, st_index_t size); #define st_init_existing_table_with_size rb_st_init_existing_table_with_size st_table *rb_st_init_numtable(void); #define st_init_numtable rb_st_init_numtable st_table *rb_st_init_numtable_with_size(st_index_t); #define st_init_numtable_with_size rb_st_init_numtable_with_size st_table *rb_st_init_strtable(void); #define st_init_strtable rb_st_init_strtable st_table *rb_st_init_strtable_with_size(st_index_t); #define st_init_strtable_with_size rb_st_init_strtable_with_size st_table *rb_st_init_strcasetable(void); #define st_init_strcasetable rb_st_init_strcasetable st_table *rb_st_init_strcasetable_with_size(st_index_t); #define st_init_strcasetable_with_size rb_st_init_strcasetable_with_size int rb_st_delete(st_table *, st_data_t *, st_data_t *); /* returns 0:notfound 1:deleted */ #define st_delete rb_st_delete int rb_st_delete_safe(st_table *, st_data_t *, st_data_t *, st_data_t); #define st_delete_safe rb_st_delete_safe int rb_st_shift(st_table *, st_data_t *, st_data_t *); /* returns 0:notfound 1:deleted */ #define st_shift rb_st_shift int rb_st_insert(st_table *, st_data_t, st_data_t); #define st_insert rb_st_insert int rb_st_insert2(st_table *, st_data_t, st_data_t, st_data_t (*)(st_data_t)); #define st_insert2 rb_st_insert2 int rb_st_lookup(st_table *, st_data_t, st_data_t *); #define st_lookup rb_st_lookup int rb_st_get_key(st_table *, st_data_t, st_data_t *); #define st_get_key rb_st_get_key typedef int st_update_callback_func(st_data_t *key, st_data_t *value, st_data_t arg, int existing); /* *key may be altered, but must equal to the old key, i.e., the * results of hash() are same and compare() returns 0, otherwise the * behavior is undefined */ int rb_st_update(st_table *table, st_data_t key, st_update_callback_func *func, st_data_t arg); #define st_update rb_st_update typedef int st_foreach_callback_func(st_data_t, st_data_t, st_data_t); typedef int st_foreach_check_callback_func(st_data_t, st_data_t, st_data_t, int); int rb_st_foreach_with_replace(st_table *tab, st_foreach_check_callback_func *func, st_update_callback_func *replace, st_data_t arg); #define st_foreach_with_replace rb_st_foreach_with_replace int rb_st_foreach(st_table *, st_foreach_callback_func *, st_data_t); #define st_foreach rb_st_foreach int rb_st_foreach_check(st_table *, st_foreach_check_callback_func *, st_data_t, st_data_t); #define st_foreach_check rb_st_foreach_check st_index_t rb_st_keys(st_table *table, st_data_t *keys, st_index_t size); #define st_keys rb_st_keys st_index_t rb_st_keys_check(st_table *table, st_data_t *keys, st_index_t size, st_data_t never); #define st_keys_check rb_st_keys_check st_index_t rb_st_values(st_table *table, st_data_t *values, st_index_t size); #define st_values rb_st_values st_index_t rb_st_values_check(st_table *table, st_data_t *values, st_index_t size, st_data_t never); #define st_values_check rb_st_values_check void rb_st_add_direct(st_table *, st_data_t, st_data_t); #define st_add_direct rb_st_add_direct void rb_st_free_table(st_table *); #define st_free_table rb_st_free_table void rb_st_cleanup_safe(st_table *, st_data_t); #define st_cleanup_safe rb_st_cleanup_safe void rb_st_clear(st_table *); #define st_clear rb_st_clear st_table *rb_st_replace(st_table *new_tab, st_table *old_tab); #define st_replace rb_st_replace st_table *rb_st_copy(st_table *); #define st_copy rb_st_copy CONSTFUNC(int rb_st_numcmp(st_data_t, st_data_t)); #define st_numcmp rb_st_numcmp CONSTFUNC(st_index_t rb_st_numhash(st_data_t)); #define st_numhash rb_st_numhash PUREFUNC(int rb_st_locale_insensitive_strcasecmp(const char *s1, const char *s2)); #define st_locale_insensitive_strcasecmp rb_st_locale_insensitive_strcasecmp PUREFUNC(int rb_st_locale_insensitive_strncasecmp(const char *s1, const char *s2, size_t n)); #define st_locale_insensitive_strncasecmp rb_st_locale_insensitive_strncasecmp #define st_strcasecmp rb_st_locale_insensitive_strcasecmp #define st_strncasecmp rb_st_locale_insensitive_strncasecmp PUREFUNC(size_t rb_st_memsize(const st_table *)); #define st_memsize rb_st_memsize PUREFUNC(st_index_t rb_st_hash(const void *ptr, size_t len, st_index_t h)); #define st_hash rb_st_hash CONSTFUNC(st_index_t rb_st_hash_uint32(st_index_t h, uint32_t i)); #define st_hash_uint32 rb_st_hash_uint32 CONSTFUNC(st_index_t rb_st_hash_uint(st_index_t h, st_index_t i)); #define st_hash_uint rb_st_hash_uint CONSTFUNC(st_index_t rb_st_hash_end(st_index_t h)); #define st_hash_end rb_st_hash_end CONSTFUNC(st_index_t rb_st_hash_start(st_index_t h)); #define st_hash_start(h) ((st_index_t)(h)) void rb_hash_bulk_insert_into_st_table(long, const VALUE *, VALUE); RUBY_SYMBOL_EXPORT_END #if defined(__cplusplus) #if 0 { /* satisfy cc-mode */ #endif } /* extern "C" { */ #endif #endif /* RUBY_ST_H */ include/ruby/internal/glob.h 0000644 00000011756 15152150472 0012074 0 ustar 00 #ifndef RBIMPL_GLOB_H /*-*-C++-*-vi:se ft=cpp:*/ #define RBIMPL_GLOB_H /** * @file * @author Ruby developers <ruby-core@ruby-lang.org> * @copyright This file is a part of the programming language Ruby. * Permission is hereby granted, to either redistribute and/or * modify this file, provided that the conditions mentioned in the * file COPYING are met. Consult the file for details. * @warning Symbols prefixed with either `RBIMPL` or `rbimpl` are * implementation details. Don't take them as canon. They could * rapidly appear then vanish. The name (path) of this header file * is also an implementation detail. Do not expect it to persist * at the place it is now. Developers are free to move it anywhere * anytime at will. * @note To ruby-core: remember that this header can be possibly * recursively included from extension libraries written in C++. * Do not expect for instance `__VA_ARGS__` is always available. * We assume C99 for ruby itself but we don't assume languages of * extension libraries. They could be written in C++98. * @brief Declares ::rb_glob(). */ #include "ruby/internal/attr/nonnull.h" #include "ruby/internal/dllexport.h" #include "ruby/internal/value.h" RBIMPL_SYMBOL_EXPORT_BEGIN() /** * Type of a glob callback function. Called every time glob scans a path. * * @param[in] path The path in question. * @param[in] arg The argument passed to rb_glob(). * @param[in] enc Encoding of the path. * @retval -1 Not enough memory to do the operation. * @retval 0 Operation successful. * @retval otherwise Opaque exception state. * @note You can use rb_protect() to generate the return value. * * @internal * * This is a wrong design. Type of `enc` should have been `rb_encoding*` * instead of just `void*`. But we cannot change the API any longer. * * Though not a part of our public API, the "opaque exception state" is in fact * an enum ruby_tag_type. You can see the potential "otherwise" values by * looking at vm_core.h. */ typedef int ruby_glob_func(const char *path, VALUE arg, void *enc); RBIMPL_ATTR_NONNULL(()) /** * The "glob" operator. Expands the given pattern against the actual local * filesystem, then iterates over the expanded filenames by calling the * callback function. * * @param[in] pattern A glob pattern. * @param[in] func Identical to ruby_glob_func, except it can raise * exceptions instead of returning opaque state. * @param[in] arg Extra argument passed to func. * @exception rb_eException Can propagate what `func` raises. * @note The language accepted as the pattern is not a regular * expression. It resembles shell's glob. */ void rb_glob(const char *pattern, void (*func)(const char *path, VALUE arg, void *enc), VALUE arg); RBIMPL_ATTR_NONNULL(()) /** * Identical to rb_glob(), except it returns opaque exception states instead of * raising exceptions. * * @param[in] pattern A glob pattern. * @param[in] flags No, you are not allowed to use this. Just pass 0. * @param[in] func A callback function. * @param[in] arg Extra argument passed to func. * @return Return value of `func`. * * @internal * * This function is completely broken by design... Not only is there no sane * way to pass flags, but there also is no sane way to know what a return value * is meant to be. * * Though not a part of our public API, and @shyouhei thinks it's a failure not * to be a public API, the flags can be `FNM_EXTGLOB`, `FNM_DOTMATCH` etc. * Look at dir.c for the list. * * Though not a part of our public API, the return value is in fact an * enum ruby_tag_type. You can see the potential values by looking at * vm_core.h. */ int ruby_glob(const char *pattern, int flags, ruby_glob_func *func, VALUE arg); RBIMPL_ATTR_NONNULL(()) /** * Identical to ruby_glob(), @shyouhei currently suspects. Historically you * had to call this function instead of ruby_glob() if the pattern included * "{x,y,...}" syntax. However since commit 0f63d961169989a7f6dcf7c0487fe29da, * ruby_glob() also supports that syntax. It seems as of writing these two * functions provide basically the same functionality in a different * implementation. Is this analysis right? Correct me! :FIXME: * * @param[in] pattern A glob pattern. * @param[in] flags No, you are not allowed to use this. Just pass 0. * @param[in] func A callback function. * @param[in] arg Extra argument passed to func. * @return Return value of `func`. */ int ruby_brace_glob(const char *pattern, int flags, ruby_glob_func *func, VALUE arg); RBIMPL_SYMBOL_EXPORT_END() #endif /* RBIMPL_GLOB_H */ include/ruby/internal/value.h 0000644 00000010410 15152150472 0012247 0 ustar 00 #ifndef RBIMPL_VALUE_H /*-*-C++-*-vi:se ft=cpp:*/ #define RBIMPL_VALUE_H /** * @file * @author Ruby developers <ruby-core@ruby-lang.org> * @copyright This file is a part of the programming language Ruby. * Permission is hereby granted, to either redistribute and/or * modify this file, provided that the conditions mentioned in the * file COPYING are met. Consult the file for details. * @warning Symbols prefixed with either `RBIMPL` or `rbimpl` are * implementation details. Don't take them as canon. They could * rapidly appear then vanish. The name (path) of this header file * is also an implementation detail. Do not expect it to persist * at the place it is now. Developers are free to move it anywhere * anytime at will. * @note To ruby-core: remember that this header can be possibly * recursively included from extension libraries written in C++. * Do not expect for instance `__VA_ARGS__` is always available. * We assume C99 for ruby itself but we don't assume languages of * extension libraries. They could be written in C++98. * @brief Defines ::VALUE and ::ID. */ #include "ruby/internal/static_assert.h" #include "ruby/backward/2/long_long.h" #include "ruby/backward/2/limits.h" #if defined(__DOXYGEN__) /** * Type that represents a Ruby object. It is an unsigned integer of some kind, * depending on platforms. * * ```CXX * VALUE value = rb_eval_string("ARGF.readlines.map.with_index"); * ``` * * @warning ::VALUE is not a pointer. * @warning ::VALUE can be wider than `long`. */ typedef uintptr_t VALUE; /** * Type that represents a Ruby identifier such as a variable name. * * ```CXX * ID method = rb_intern("method"); * VALUE result = rb_funcall(obj, method, 0); * ``` * * @note ::rb_cSymbol is a Ruby-level data type for the same thing. */ typedef uintptr_t ID; /** * A signed integer type that has the same width with ::VALUE. * * @internal * * @shyouhei wonders: is it guaranteed that `uintptr_t` and `intptr_t` are the * same width? As far as I read ISO/IEC 9899:2018 section 7.20.1.4 paragraph 1 * no such description is given... or defined elsewhere? */ typedef intptr_t SIGNED_VALUE; /** * Identical to `sizeof(VALUE)`, except it is a macro that can also be used * inside of preprocessor directives such as `#if`. Handy on occasions. */ #define SIZEOF_VALUE SIZEOF_UINTPTR_T /** * @private * * A compile-time constant of type ::VALUE whose value is 0. */ #define RBIMPL_VALUE_NULL UINTPTR_C(0) /** * @private * * A compile-time constant of type ::VALUE whose value is 1. */ #define RBIMPL_VALUE_ONE UINTPTR_C(1) /** * @private * * Maximum possible value that a ::VALUE can take. */ #define RBIMPL_VALUE_FULL UINTPTR_MAX #elif defined HAVE_UINTPTR_T && 0 typedef uintptr_t VALUE; typedef uintptr_t ID; # define SIGNED_VALUE intptr_t # define SIZEOF_VALUE SIZEOF_UINTPTR_T # undef PRI_VALUE_PREFIX # define RBIMPL_VALUE_NULL UINTPTR_C(0) # define RBIMPL_VALUE_ONE UINTPTR_C(1) # define RBIMPL_VALUE_FULL UINTPTR_MAX #elif SIZEOF_LONG == SIZEOF_VOIDP typedef unsigned long VALUE; typedef unsigned long ID; # define SIGNED_VALUE long # define SIZEOF_VALUE SIZEOF_LONG # define PRI_VALUE_PREFIX "l" # define RBIMPL_VALUE_NULL 0UL # define RBIMPL_VALUE_ONE 1UL # define RBIMPL_VALUE_FULL ULONG_MAX #elif SIZEOF_LONG_LONG == SIZEOF_VOIDP typedef unsigned LONG_LONG VALUE; typedef unsigned LONG_LONG ID; # define SIGNED_VALUE LONG_LONG # define LONG_LONG_VALUE 1 # define SIZEOF_VALUE SIZEOF_LONG_LONG # define PRI_VALUE_PREFIX PRI_LL_PREFIX # define RBIMPL_VALUE_NULL 0ULL # define RBIMPL_VALUE_ONE 1ULL # define RBIMPL_VALUE_FULL ULLONG_MAX #else # error ---->> ruby requires sizeof(void*) == sizeof(long) or sizeof(LONG_LONG) to be compiled. <<---- #endif /** @cond INTERNAL_MACRO */ RBIMPL_STATIC_ASSERT(sizeof_int, SIZEOF_INT == sizeof(int)); RBIMPL_STATIC_ASSERT(sizeof_long, SIZEOF_LONG == sizeof(long)); RBIMPL_STATIC_ASSERT(sizeof_long_long, SIZEOF_LONG_LONG == sizeof(LONG_LONG)); RBIMPL_STATIC_ASSERT(sizeof_voidp, SIZEOF_VOIDP == sizeof(void *)); /** @endcond */ #endif /* RBIMPL_VALUE_H */ include/ruby/internal/gc.h 0000644 00000071232 15152150472 0011535 0 ustar 00 #ifndef RBIMPL_GC_H /*-*-C++-*-vi:se ft=cpp:*/ #define RBIMPL_GC_H /** * @file * @author Ruby developers <ruby-core@ruby-lang.org> * @copyright This file is a part of the programming language Ruby. * Permission is hereby granted, to either redistribute and/or * modify this file, provided that the conditions mentioned in the * file COPYING are met. Consult the file for details. * @warning Symbols prefixed with either `RBIMPL` or `rbimpl` are * implementation details. Don't take them as canon. They could * rapidly appear then vanish. The name (path) of this header file * is also an implementation detail. Do not expect it to persist * at the place it is now. Developers are free to move it anywhere * anytime at will. * @note To ruby-core: remember that this header can be possibly * recursively included from extension libraries written in C++. * Do not expect for instance `__VA_ARGS__` is always available. * We assume C99 for ruby itself but we don't assume languages of * extension libraries. They could be written in C++98. * @brief Registering values to the GC. */ #include "ruby/internal/config.h" #ifdef STDC_HEADERS # include <stddef.h> /* size_t */ #endif #ifdef HAVE_SYS_TYPES_H # include <sys/types.h> /* ssize_t */ #endif #include "ruby/assert.h" #include "ruby/internal/attr/cold.h" #include "ruby/internal/attr/nonnull.h" #include "ruby/internal/attr/noreturn.h" #include "ruby/internal/attr/artificial.h" #include "ruby/internal/attr/maybe_unused.h" #include "ruby/internal/attr/pure.h" #include "ruby/internal/dllexport.h" #include "ruby/internal/special_consts.h" #include "ruby/internal/stdbool.h" #include "ruby/internal/value.h" RBIMPL_SYMBOL_EXPORT_BEGIN() #define RUBY_REF_EDGE(s, p) offsetof(s, p) #define RUBY_REFS_LIST_PTR(l) (RUBY_DATA_FUNC)(l) #define RUBY_REF_END SIZE_MAX #define RUBY_REFERENCES(t) static const size_t t[] #define RUBY_REFERENCES_START(t) RUBY_REFERENCES(t) = { #define RUBY_REFERENCES_END RUBY_REF_END, }; /* gc.c */ RBIMPL_ATTR_COLD() RBIMPL_ATTR_NORETURN() /** * Triggers out-of-memory error. If possible it raises ::rb_eNoMemError. But * because we are running out of memory that is not always doable. This * function tries hard to show something, but ultimately can die silently. * * @exception rb_eNoMemError Raises it if possible. */ void rb_memerror(void); RBIMPL_ATTR_PURE() /** * Queries if the GC is busy. * * @retval 0 It isn't. * @retval 1 It is. */ int rb_during_gc(void); RBIMPL_ATTR_NONNULL((1)) /** * Marks objects between the two pointers. This is one of the GC utility * functions that you can call when you design your own * ::rb_data_type_struct::dmark. * * @pre Continuous memory region from `start` to `end` shall be fully * addressable. * @param[out] start Pointer to an array of objects. * @param[out] end Pointer that terminates the array of objects. * @post Objects from `start` (included) to `end` (excluded) are marked. * * @internal * * `end` can be NULL... But that just results in no-op. */ void rb_gc_mark_locations(const VALUE *start, const VALUE *end); /** * Identical to rb_mark_hash(), except it marks only values of the table and * leave their associated keys unmarked. This is one of the GC utility * functions that you can call when you design your own * ::rb_data_type_struct::dmark. * * @warning Of course it can break GC. Leave it unused if unsure. * @param[in] tbl A table to mark. * @post Values stored in `tbl` are marked. */ void rb_mark_tbl(struct st_table *tbl); /** * Identical to rb_mark_tbl(), except it marks objects using * rb_gc_mark_movable(). This is one of the GC utility functions that you can * call when you design your own ::rb_data_type_struct::dmark. * * @warning Of course it can break GC. Leave it unused if unsure. * @param[in] tbl A table to mark. * @post Values stored in `tbl` are marked. */ void rb_mark_tbl_no_pin(struct st_table *tbl); /** * Identical to rb_mark_hash(), except it marks only keys of the table and * leave their associated values unmarked. This is one of the GC utility * functions that you can call when you design your own * ::rb_data_type_struct::dmark. * * @warning Of course it can break GC. Leave it unused if unsure. * @param[in] tbl A table to mark. * @post Keys stored in `tbl` are marked. */ void rb_mark_set(struct st_table *tbl); /** * Marks keys and values associated inside of the given table. This is one of * the GC utility functions that you can call when you design your own * ::rb_data_type_struct::dmark. * * @param[in] tbl A table to mark. * @post Objects stored in `tbl` are marked. */ void rb_mark_hash(struct st_table *tbl); /** * Updates references inside of tables. After you marked values using * rb_mark_tbl_no_pin(), the objects inside of the table could of course be * moved. This function is to fixup those references. You can call this from * your ::rb_data_type_struct::dcompact. * * @param[out] ptr A table that potentially includes moved references. * @post Moved references, if any, are corrected. */ void rb_gc_update_tbl_refs(st_table *ptr); /** * Identical to rb_gc_mark(), except it allows the passed value be a * non-object. For instance pointers to different type of memory regions are * allowed here. Such values are silently ignored. This is one of the GC * utility functions that you can call when you design your own * ::rb_data_type_struct::dmark. * * @param[out] obj A possible object. * @post `obj` is marked, if possible. */ void rb_gc_mark_maybe(VALUE obj); /** * Marks an object. This is one of the GC utility functions that you can call * when you design your own ::rb_data_type_struct::dmark. * * @param[out] obj Arbitrary Ruby object. * @post `obj` is marked. */ void rb_gc_mark(VALUE obj); /** * Maybe this is the only function provided for C extensions to control the * pinning of objects, so let us describe it in detail. These days Ruby's GC * is copying. As far as an object's physical address is guaranteed unused, it * can move around the object space. Our GC engine rearranges these objects * after it reclaims unreachable objects from our object space, so that the * space is compact (improves memory locality). This is called the * "compaction" phase, and works well most of the time... as far as there are * no C extensions. C extensions complicate the scenario because Ruby core * cannot detect any use of the physical address of an object inside of C * functions. In order to prevent memory corruptions, objects observable from * C extensions are "pinned"; they stick to where they are born until they die, * just in case any C extensions touch their raw pointers. This variant of * scheme is called "Mostly-Copying" garbage collector. Authors of C * extensions, however, can extremely carefully write them to become * compaction-aware. To do so avoid referring to a Ruby object from inside of * your struct in the first place. But if that is not possible, use this * function from your ::rb_data_type_struct::dmark then. This way objects * marked using it are considered movable. If you chose this way you have to * manually fix up locations of such moved pointers using rb_gc_location(). * * @see Bartlett, Joel F., "Compacting Garbage Collection with Ambiguous * Roots", ACM SIGPLAN Lisp Pointers Volume 1 Issue 6 pp. 3-12, * April-May-June, 1988. https://doi.org/10.1145/1317224.1317225 * * @param[in] obj Object that is movable. * @post Values stored in `tbl` are marked. */ void rb_gc_mark_movable(VALUE obj); /** * Finds a new "location" of an object. An object can be moved on compaction. * This function projects its new abode, or just returns the passed object if * not moved. This is one of the GC utility functions that you can call when * you design your own ::rb_data_type_struct::dcompact. * * @param[in] obj An object, possibly already moved to somewhere else. * @return An object, which holds the current contents of former `obj`. */ VALUE rb_gc_location(VALUE obj); /** * Asserts that the passed object is no longer needed. Such objects are * reclaimed sooner or later so this function is not mandatory. But sometimes * you can know from your application knowledge that an object is surely dead * at some point. Calling this as a hint can be a polite way. * * @param[out] obj Object, dead. * @pre `obj` have never been passed to this function before. * @post `obj` could be invalidated. * @warning It is a failure to pass an object multiple times to this * function. * @deprecated This is now a no-op function. */ RBIMPL_ATTR_DEPRECATED(("this is now a no-op function")) void rb_gc_force_recycle(VALUE obj); /** * Triggers a GC process. This was the only GC entry point that we had at the * beginning. Over time our GC evolved. Now what this function does is just a * very simplified variation of the entire GC algorithms. A series of * procedures kicked by this API is called a "full" GC. * * - It immediately scans the entire object space to sort the dead. * - It immediately reclaims any single dead bodies to reuse later. * * It is worth noting that the procedures above do not include evaluations of * finalisers. They run later. * * @internal * * Finalisers are deferred until we can handle interrupts. See * `rb_postponed_job_flush` in vm_trace.c. * * Of course there are GC that are not "full". For instance this one and the * GC which runs when we are running out of memory are different. See * `gc_profile_record_flag` defined in gc.c for the kinds of GC. * * In spite of the name this is not what everything that a GC can trigger. As * of writing it seems this function does not trigger compaction. But this * might change in future. */ void rb_gc(void); /** * Copy&paste an object's finaliser to another. This is one of the GC utility * functions that you can call when you design your own `initialize_copy`, * `initialize_dup`, `initialize_clone`. * * @param[out] dst Destination object. * @param[in] src Source object. * @post `dst` and `src` share the same finaliser. * * @internal * * But isn't it easier for you to call super, and let `Object#initialize_copy` * call this function instead? */ void rb_gc_copy_finalizer(VALUE dst, VALUE src); /** * (Re-) enables GC. This makes sense only after you called rb_gc_disable(). * * @retval RUBY_Qtrue GC was disabled before. * @retval RUBY_Qfalse GC was enabled before. * @post GC is enabled. * * @internal * * This is one of such exceptional functions that does not raise both Ruby * exceptions and C++ exceptions. */ VALUE rb_gc_enable(void); /** * Disables GC. This prevents automatic GC runs when the process is running * out of memory. Such situations shall result in rb_memerror(). However this * does not prevent users from manually invoking rb_gc(). That should work. * People abused this by disabling GC at the beginning of an event loop, * process events without GC overheads, then manually force reclaiming garbage * at the bottom of the loop. However because our GC is now much smarter than * just calling rb_gc(), this technique is proven to be sub-optimal these days. * It is believed that there is currently practically no needs of this * function. * * @retval RUBY_Qtrue GC was disabled before. * @retval RUBY_Qfalse GC was enabled before. * @post GC is disabled. */ VALUE rb_gc_disable(void); /** * Identical to rb_gc(), except the return value. * * @return Always returns ::RUBY_Qnil. */ VALUE rb_gc_start(void); /** * Assigns a finaliser for an object. Each objects can have objects (typically * blocks) that run immediately after that object dies. They are called * finalisers of an object. This function associates a finaliser object with a * target object. * * @note Note that finalisers run _after_ the object they finalise dies. You * cannot for instance call its methods. * @note If your finaliser references the object it finalises that object * loses any chance to become a garbage; effectively leaks memory until * the end of the process. * * @param[in] obj Target to finalise. * @param[in] block Something `call`able. * @exception rb_eRuntimeError Somehow `obj` cannot have finalisers. * @exception rb_eFrozenError `obj` is frozen. * @exception rb_eArgError `block` doesn't respond to `call`. * @return The passed `block`. * @post `block` runs after `obj` dies. */ VALUE rb_define_finalizer(VALUE obj, VALUE block); /** * Modifies the object so that it has no finalisers at all. This function is * mainly provided for symmetry. No practical usages can be thought of. * * @param[out] obj Object to clear its finalisers. * @exception rb_eFrozenError `obj` is frozen. * @return The passed `obj`. * @post `obj` has no finalisers. * @note There is no way to undefine a specific part of many finalisers * that `obj` could have. All you can do is to clear them all. */ VALUE rb_undefine_finalizer(VALUE obj); /** * Identical to rb_gc_stat(), with "count" parameter. * * @return Lifetime total number of runs of GC. */ size_t rb_gc_count(void); /** * Obtains various GC related profiles. The parameter can be either a Symbol * or a Hash. If a Hash is passed, it is filled with everything currently * available. If a Symbol is passed just that portion is returned. * * Possible variations of keys you can pass here change from version to * version. You can get the list of known keys by passing an empty hash and * let it be filled. * * @param[in,out] key_or_buf A Symbol, or a Hash. * @exception rb_eTypeError Neither Symbol nor Hash. * @exception rb_eFrozenError Frozen hash is passed. * @return In case a Hash is passed it returns 0. Otherwise the * profile value associated with the given key is returned. * @post In case a Hash is passed it is filled with values. */ size_t rb_gc_stat(VALUE key_or_buf); /** * Obtains various info regarding the most recent GC run. This includes for * instance the reason of the GC. The parameter can be either a Symbol or a * Hash. If a Hash is passed, it is filled with everything currently * available. If a Symbol is passed just that portion is returned. * * Possible variations of keys you can pass here change from version to * version. You can get the list of known keys by passing an empty hash and * let it be filled. * * @param[in,out] key_or_buf A Symbol, or a Hash. * @exception rb_eTypeError Neither Symbol nor Hash. * @exception rb_eFrozenError Frozen hash is passed. * @return In case a Hash is passed it returns that hash. Otherwise * the profile value associated with the given key is returned. * @post In case a Hash is passed it is filled with values. */ VALUE rb_gc_latest_gc_info(VALUE key_or_buf); /** * Informs that there are external memory usages. Our GC runs when we are * running out of memory. The amount of memory, however, can increase/decrease * behind-the-scene. For instance DLLs can allocate memories using `mmap(2)` * etc, which are opaque to us. Registering such external allocations using * this function enables proper detection of how much memories an object used * as a whole. That will trigger GCs more often than it would otherwise. You * can also pass negative numbers here, to indicate that such external * allocations are gone. * * @param[in] diff Amount of memory increased(+)/decreased(-). */ void rb_gc_adjust_memory_usage(ssize_t diff); /** * Inform the garbage collector that the global or static variable pointed by * `valptr` stores a live Ruby object that should not be moved. Note that * extensions should use this API on global constants instead of assuming * constants defined in Ruby are always alive. Ruby code can remove global * constants. * * Because this registration itself has a possibility to trigger a GC, this * function must be called before any GC-able objects is assigned to the * address pointed by `valptr`. */ void rb_gc_register_address(VALUE *valptr); /** * An alias for `rb_gc_register_address()`. */ void rb_global_variable(VALUE *); /** * Inform the garbage collector that a pointer previously passed to * `rb_gc_register_address()` no longer points to a live Ruby object. */ void rb_gc_unregister_address(VALUE *valptr); /** * Inform the garbage collector that `object` is a live Ruby object that should * not be moved. * * See also: rb_gc_register_address() */ void rb_gc_register_mark_object(VALUE object); RBIMPL_SYMBOL_EXPORT_END() /** * @private * * @deprecated This macro once was a thing in the old days, but makes no sense * any longer today. Exists here for backwards compatibility * only. You can safely forget about it. */ #undef USE_RGENGC #define USE_RGENGC 1 /** * @deprecated This macro seems broken. Setting this to anything other than * zero just doesn't compile. We need to KonMari. */ #ifndef USE_RGENGC_LOGGING_WB_UNPROTECT # define USE_RGENGC_LOGGING_WB_UNPROTECT 0 #endif /** * @private * * This is a compile-time flag to enable/disable write barrier for * struct ::RArray. It has to be set at the time ruby itself compiles. Makes * no sense for 3rd parties. */ #ifndef RGENGC_WB_PROTECTED_ARRAY # define RGENGC_WB_PROTECTED_ARRAY 1 #endif /** * @private * * This is a compile-time flag to enable/disable write barrier for * struct ::RHash. It has to be set at the time ruby itself compiles. Makes * no sense for 3rd parties. */ #ifndef RGENGC_WB_PROTECTED_HASH # define RGENGC_WB_PROTECTED_HASH 1 #endif /** * @private * * This is a compile-time flag to enable/disable write barrier for * struct ::RStruct. It has to be set at the time ruby itself compiles. Makes * no sense for 3rd parties. */ #ifndef RGENGC_WB_PROTECTED_STRUCT # define RGENGC_WB_PROTECTED_STRUCT 1 #endif /** * @private * * This is a compile-time flag to enable/disable write barrier for * struct ::RString. It has to be set at the time ruby itself compiles. Makes * no sense for 3rd parties. */ #ifndef RGENGC_WB_PROTECTED_STRING # define RGENGC_WB_PROTECTED_STRING 1 #endif /** * @private * * This is a compile-time flag to enable/disable write barrier for * struct ::RObject. It has to be set at the time ruby itself compiles. Makes * no sense for 3rd parties. */ #ifndef RGENGC_WB_PROTECTED_OBJECT # define RGENGC_WB_PROTECTED_OBJECT 1 #endif /** * @private * * This is a compile-time flag to enable/disable write barrier for * struct ::RRegexp. It has to be set at the time ruby itself compiles. Makes * no sense for 3rd parties. */ #ifndef RGENGC_WB_PROTECTED_REGEXP # define RGENGC_WB_PROTECTED_REGEXP 1 #endif /** * @private * * This is a compile-time flag to enable/disable write barrier for * struct ::RMatch. It has to be set at the time ruby itself compiles. Makes * no sense for 3rd parties. */ #ifndef RGENGC_WB_PROTECTED_MATCH # define RGENGC_WB_PROTECTED_MATCH 1 #endif /** * @private * * This is a compile-time flag to enable/disable write barrier for * struct ::RClass. It has to be set at the time ruby itself compiles. Makes * no sense for 3rd parties. */ #ifndef RGENGC_WB_PROTECTED_CLASS # define RGENGC_WB_PROTECTED_CLASS 1 #endif /** * @private * * This is a compile-time flag to enable/disable write barrier for * struct ::RFloat. It has to be set at the time ruby itself compiles. Makes * no sense for 3rd parties. */ #ifndef RGENGC_WB_PROTECTED_FLOAT # define RGENGC_WB_PROTECTED_FLOAT 1 #endif /** * @private * * This is a compile-time flag to enable/disable write barrier for * struct ::RComplex. It has to be set at the time ruby itself compiles. * Makes no sense for 3rd parties. */ #ifndef RGENGC_WB_PROTECTED_COMPLEX # define RGENGC_WB_PROTECTED_COMPLEX 1 #endif /** * @private * * This is a compile-time flag to enable/disable write barrier for * struct ::RRational. It has to be set at the time ruby itself compiles. * Makes no sense for 3rd parties. */ #ifndef RGENGC_WB_PROTECTED_RATIONAL # define RGENGC_WB_PROTECTED_RATIONAL 1 #endif /** * @private * * This is a compile-time flag to enable/disable write barrier for * struct ::RBignum. It has to be set at the time ruby itself compiles. Makes * no sense for 3rd parties. */ #ifndef RGENGC_WB_PROTECTED_BIGNUM # define RGENGC_WB_PROTECTED_BIGNUM 1 #endif /** * @private * * @deprecated This macro once was a thing in the old days, but makes no sense * any longer today. Exists here for backwards compatibility * only. You can safely forget about it. * * @internal * * @shyouhei doesn't think anybody uses this right now. */ #ifndef RGENGC_WB_PROTECTED_NODE_CREF # define RGENGC_WB_PROTECTED_NODE_CREF 1 #endif /** * @defgroup rgengc Write barrier (WB) interfaces: * * @note The following core interfaces can be changed in the future. Please * catch up if you want to insert WB into C-extensions correctly. * * @{ */ /** * Declaration of a "back" pointer. This is a write barrier for new reference * from "old" generation to "young" generation. It writes `young` into * `*slot`, which is a pointer inside of `old`. * * @param[in] old An old object. * @param[in] slot A pointer inside of `old`. * @param[out] young A young object. */ #define RB_OBJ_WRITE(old, slot, young) \ RBIMPL_CAST(rb_obj_write((VALUE)(old), (VALUE *)(slot), (VALUE)(young), __FILE__, __LINE__)) /** * Identical to #RB_OBJ_WRITE(), except it doesn't write any values, but only a * WB declaration. `oldv` is replaced value with `b` (not used in current * Ruby). * * @param[in] old An old object. * @param[in] oldv An object previously stored inside of `old`. * @param[out] young A young object. */ #define RB_OBJ_WRITTEN(old, oldv, young) \ RBIMPL_CAST(rb_obj_written((VALUE)(old), (VALUE)(oldv), (VALUE)(young), __FILE__, __LINE__)) /** @} */ #define OBJ_PROMOTED_RAW RB_OBJ_PROMOTED_RAW /**< @old{RB_OBJ_PROMOTED_RAW} */ #define OBJ_PROMOTED RB_OBJ_PROMOTED /**< @old{RB_OBJ_PROMOTED} */ #define OBJ_WB_UNPROTECT RB_OBJ_WB_UNPROTECT /**< @old{RB_OBJ_WB_UNPROTECT} */ /** * Asserts that the passed object is not fenced by write barriers. Objects of * such property do not contribute to generational GCs. They are scanned * always. * * @param[out] x An object that would not be protected by the barrier. */ #define RB_OBJ_WB_UNPROTECT(x) rb_obj_wb_unprotect(x, __FILE__, __LINE__) /** * Identical to #RB_OBJ_WB_UNPROTECT(), except it can also assert that the * given object is of given type. * * @param[in] type One of `ARRAY`, `STRING`, etc. * @param[out] obj An object of `type` that would not be protected. * * @internal * * @shyouhei doesn't understand why this has to be visible from extensions. */ #define RB_OBJ_WB_UNPROTECT_FOR(type, obj) \ (RGENGC_WB_PROTECTED_##type ? OBJ_WB_UNPROTECT(obj) : obj) /** * @private * * This is an implementation detail of rb_obj_wb_unprotect(). People don't use * it directly. */ #define RGENGC_LOGGING_WB_UNPROTECT rb_gc_unprotect_logging /** @cond INTERNAL_MACRO */ #define RB_OBJ_PROMOTED_RAW RB_OBJ_PROMOTED_RAW #define RB_OBJ_PROMOTED RB_OBJ_PROMOTED /** @endcond */ RBIMPL_SYMBOL_EXPORT_BEGIN() /** * This is the implementation of #RB_OBJ_WRITE(). People don't use it * directly. * * @param[in] old An object that points to `young`. * @param[out] young An object that is referenced from `old`. */ void rb_gc_writebarrier(VALUE old, VALUE young); /** * This is the implementation of #RB_OBJ_WB_UNPROTECT(). People don't use it * directly. * * @param[out] obj An object that does not participate in WB. */ void rb_gc_writebarrier_unprotect(VALUE obj); #if USE_RGENGC_LOGGING_WB_UNPROTECT /** * @private * * This is the implementation of #RGENGC_LOGGING_WB_UNPROTECT(). People * don't use it directly. * * @param[in] objptr Don't know why this is a pointer to void but in * reality this is a pointer to an object that is about * to be un-protected. * @param[in] filename Pass C's `__FILE__` here. * @param[in] line Pass C's `__LINE__` here. */ void rb_gc_unprotect_logging(void *objptr, const char *filename, int line); #endif RBIMPL_SYMBOL_EXPORT_END() RBIMPL_ATTR_PURE_UNLESS_DEBUG() RBIMPL_ATTR_ARTIFICIAL() /** * This is the implementation of #RB_OBJ_PROMOTED(). People don't use it * directly. * * @param[in] obj An object to query. * @retval true The object is "promoted". * @retval false The object is young. Have not experienced GC at all. */ static inline bool RB_OBJ_PROMOTED_RAW(VALUE obj) { RBIMPL_ASSERT_OR_ASSUME(RB_FL_ABLE(obj)); return RB_FL_ANY_RAW(obj, RUBY_FL_PROMOTED); } RBIMPL_ATTR_PURE_UNLESS_DEBUG() RBIMPL_ATTR_ARTIFICIAL() /** * Tests if the object is "promoted" -- that is, whether the object experienced * one or more GC marks. * * @param[in] obj An object to query. * @retval true The object is "promoted". * @retval false The object is young. Have not experienced GC at all. * @note Hello, is anyone actively calling this function? @shyouhei have * never seen any actual usages outside of the GC implementation * itself. */ static inline bool RB_OBJ_PROMOTED(VALUE obj) { if (! RB_FL_ABLE(obj)) { return false; } else { return RB_OBJ_PROMOTED_RAW(obj); } } /** * This is the implementation of #RB_OBJ_WB_UNPROTECT(). People don't use it * directly. * * @param[out] x An object that does not participate in WB. * @param[in] filename C's `__FILE__` of the caller function. * @param[in] line C's `__LINE__` of the caller function. * @return x */ static inline VALUE rb_obj_wb_unprotect( VALUE x, RBIMPL_ATTR_MAYBE_UNUSED() const char *filename, RBIMPL_ATTR_MAYBE_UNUSED() int line) { #if USE_RGENGC_LOGGING_WB_UNPROTECT RGENGC_LOGGING_WB_UNPROTECT(RBIMPL_CAST((void *)x), filename, line); #endif rb_gc_writebarrier_unprotect(x); return x; } /** * @private * * This is the implementation of #RB_OBJ_WRITTEN(). People don't use it * directly. * * @param[in] a An old object. * @param[in] oldv An object previously stored inside of `old`. * @param[out] b A young object. * @param[in] filename C's `__FILE__` of the caller function. * @param[in] line C's `__LINE__` of the caller function. * @return a */ static inline VALUE rb_obj_written( VALUE a, RBIMPL_ATTR_MAYBE_UNUSED() VALUE oldv, VALUE b, RBIMPL_ATTR_MAYBE_UNUSED() const char *filename, RBIMPL_ATTR_MAYBE_UNUSED() int line) { #if USE_RGENGC_LOGGING_WB_UNPROTECT RGENGC_LOGGING_OBJ_WRITTEN(a, oldv, b, filename, line); #endif if (!RB_SPECIAL_CONST_P(b)) { rb_gc_writebarrier(a, b); } return a; } /** * @private * * This is the implementation of #RB_OBJ_WRITE(). People don't use it * directly. * * @param[in] a An old object. * @param[in] slot A pointer inside of `old`. * @param[out] b A young object. * @param[in] filename C's `__FILE__` of the caller function. * @param[in] line C's `__LINE__` of the caller function. * @return a */ static inline VALUE rb_obj_write( VALUE a, VALUE *slot, VALUE b, RBIMPL_ATTR_MAYBE_UNUSED() const char *filename, RBIMPL_ATTR_MAYBE_UNUSED() int line) { #ifdef RGENGC_LOGGING_WRITE RGENGC_LOGGING_WRITE(a, slot, b, filename, line); #endif *slot = b; rb_obj_written(a, RUBY_Qundef /* ignore `oldv' now */, b, filename, line); return a; } #endif /* RBIMPL_GC_H */ include/ruby/internal/intern/proc.h 0000644 00000033044 15152150472 0013405 0 ustar 00 #ifndef RBIMPL_INTERN_PROC_H /*-*-C++-*-vi:se ft=cpp:*/ #define RBIMPL_INTERN_PROC_H /** * @file * @author Ruby developers <ruby-core@ruby-lang.org> * @copyright This file is a part of the programming language Ruby. * Permission is hereby granted, to either redistribute and/or * modify this file, provided that the conditions mentioned in the * file COPYING are met. Consult the file for details. * @warning Symbols prefixed with either `RBIMPL` or `rbimpl` are * implementation details. Don't take them as canon. They could * rapidly appear then vanish. The name (path) of this header file * is also an implementation detail. Do not expect it to persist * at the place it is now. Developers are free to move it anywhere * anytime at will. * @note To ruby-core: remember that this header can be possibly * recursively included from extension libraries written in C++. * Do not expect for instance `__VA_ARGS__` is always available. * We assume C99 for ruby itself but we don't assume languages of * extension libraries. They could be written in C++98. * @brief Public APIs related to ::rb_cProc. */ #include "ruby/internal/dllexport.h" #include "ruby/internal/iterator.h" #include "ruby/internal/value.h" RBIMPL_SYMBOL_EXPORT_BEGIN() /* proc.c */ /** * Constructs a Proc object from implicitly passed components. When a ruby * method is called with a block, that block is not explicitly passed around * using C level function parameters. This function gathers all the necessary * info to turn them into a Ruby level instance of ::rb_cProc. * * @exception rb_eArgError There is no passed block. * @return An instance of ::rb_cProc. */ VALUE rb_block_proc(void); /** * Identical to rb_proc_new(), except it returns a lambda. * * @exception rb_eArgError There is no passed block. * @return An instance of ::rb_cProc. */ VALUE rb_block_lambda(void); /** * This is an rb_iterate() + rb_block_proc() combo. * * ```CXX * VALUE * my_own_iterator(RB_BLOCK_CALL_FUNC_ARGLIST(y, c)) * { * const auto plus = rb_intern("+"); * return rb_funcall(c, plus, 1, y); * } * * VALUE * my_own_method(VALUE self) * { * return rb_proc_new(my_own_iterator, self); * } * ``` * * @param[in] func A backend function of a proc. * @param[in] callback_arg Passed to `func`'s callback_arg. * @return A C-backended proc object. * */ VALUE rb_proc_new(rb_block_call_func_t func, VALUE callback_arg); /** * Queries if the given object is a proc. * * @note This is about the object's data structure, not its class etc. * @param[in] recv Object in question. * @retval RUBY_Qtrue It is a proc. * @retval RUBY_Qfalse Otherwise. */ VALUE rb_obj_is_proc(VALUE recv); /** * Evaluates the passed proc with the passed arguments. * * @param[in] recv The proc to call. * @param[in] args An instance of ::RArray which is the arguments. * @exception rb_eException Any exceptions happen inside. * @return What the proc evaluates to. */ VALUE rb_proc_call(VALUE recv, VALUE args); /** * Identical to rb_proc_call(), except you can specify how to handle the last * element of the given array. * * @param[in] recv The proc to call. * @param[in] args An instance of ::RArray which is the arguments. * @param[in] kw_splat Handling of keyword parameters: * - RB_NO_KEYWORDS `args`' last is not a keyword argument. * - RB_PASS_KEYWORDS `args`' last is a keyword argument. * - RB_PASS_CALLED_KEYWORDS it depends if there is a passed block. * @exception rb_eException Any exceptions happen inside. * @return What the proc evaluates to. */ VALUE rb_proc_call_kw(VALUE recv, VALUE args, int kw_splat); /** * Identical to rb_proc_call(), except you can additionally pass another proc * object, as a block. Nowadays procs can take blocks: * * ```ruby * l = -> (positional, optional=nil, *rest, kwarg:, **kwrest, &block) { * # ... how can we pass this `&block`? ^^^^^^ * } * ``` * * And this function is to pass one to such procs. * * @param[in] recv The proc to call. * @param[in] argc Number of arguments. * @param[in] argv Arbitrary number of proc arguments. * @param[in] proc Proc as a passed block. * @exception rb_eException Any exceptions happen inside. * @return What the proc evaluates to. */ VALUE rb_proc_call_with_block(VALUE recv, int argc, const VALUE *argv, VALUE proc); /** * Identical to rb_proc_call_with_block(), except you can specify how to handle * the last element of the given array. It can also be seen as a routine * identical to rb_proc_call_kw(), except you can additionally pass another * proc object as a block. * * @param[in] recv The proc to call. * @param[in] argc Number of arguments. * @param[in] argv Arbitrary number of proc arguments. * @param[in] proc Proc as a passed block. * @param[in] kw_splat Handling of keyword parameters: * - RB_NO_KEYWORDS `args`' last is not a keyword argument. * - RB_PASS_KEYWORDS `args`' last is a keyword argument. * - RB_PASS_CALLED_KEYWORDS it depends if there is a passed block. * @exception rb_eException Any exceptions happen inside. * @return What the proc evaluates to. */ VALUE rb_proc_call_with_block_kw(VALUE recv, int argc, const VALUE *argv, VALUE proc, int kw_splat); /** * Queries the number of mandatory arguments of the given Proc. If its block * is declared to take no arguments, returns `0`. If the block is known to * take exactly `n` arguments, returns `n`. If the block has optional * arguments, returns `-n-1`, where `n` is the number of mandatory arguments, * with the exception for blocks that are not lambdas and have only a finite * number of optional arguments; in this latter case, returns `n`. Keyword * arguments will be considered as a single additional argument, that argument * being mandatory if any keyword argument is mandatory. * * @param[in] recv Target Proc object. * @retval 0 It takes no arguments. * @retval >0 It takes exactly this number of arguments. * @retval <0 It takes optional arguments. */ int rb_proc_arity(VALUE recv); /** * Queries if the given object is a lambda. Instances of ::rb_cProc are either * lambda or proc. They differ in several points. This function can * distinguish them without actually evaluating their contents. * * @param[in] recv Target proc object. * @retval RUBY_Qtrue It is a lambda. * @retval RUBY_Qfalse Otherwise. */ VALUE rb_proc_lambda_p(VALUE recv); /** * Snapshots the current execution context and turn it into an instance of * ::rb_cBinding. * * @return An instance of ::rb_cBinding. */ VALUE rb_binding_new(void); /** * Creates a method object. A method object is a proc-like object that you can * "call". Note that a method object snapshots the method at the time the * object is created: * * ```ruby * class Foo * def foo * return 1 * end * end * * obj = Foo.new.method(:foo) * * class Foo * def foo * return 2 * end * end * * obj.call # => 1, not 2. * ``` * * @param[in] recv Receiver of the method. * @param[in] mid Method name, in either String or Symbol. * @exception rb_eNoMethodError No such method. * @return An instance of ::rb_cMethod. */ VALUE rb_obj_method(VALUE recv, VALUE mid); /** * Queries if the given object is a method. * * @note This is about the object's data structure, not its class etc. * @param[in] recv Object in question. * @retval RUBY_Qtrue It is a method. * @retval RUBY_Qfalse Otherwise. */ VALUE rb_obj_is_method(VALUE recv); /** * Evaluates the passed method with the passed arguments. * * @param[in] argc Number of objects of `argv`. * @param[in] argv Arbitrary number of method arguments. * @param[in] recv The method object to call. * @exception rb_eTypeError `recv` is not a method. * @exception rb_eException Any exceptions happen inside. * @return What the method returns. */ VALUE rb_method_call(int argc, const VALUE *argv, VALUE recv); /** * Identical to rb_method_call(), except you can specify how to handle the last * element of the given array. * * @param[in] argc Number of objects of `argv`. * @param[in] argv Arbitrary number of method arguments. * @param[in] recv The method object to call. * @param[in] kw_splat Handling of keyword parameters: * - RB_NO_KEYWORDS `args`' last is not a keyword argument. * - RB_PASS_KEYWORDS `args`' last is a keyword argument. * - RB_PASS_CALLED_KEYWORDS it depends if there is a passed block. * @exception rb_eTypeError `recv` is not a method. * @exception rb_eException Any exceptions happen inside. * @return What the method returns. */ VALUE rb_method_call_kw(int argc, const VALUE *argv, VALUE recv, int kw_splat); /** * Identical to rb_proc_call(), except you can additionally pass a proc as a * block. * * @param[in] argc Number of objects of `argv`. * @param[in] argv Arbitrary number of method arguments. * @param[in] recv The method object to call. * @param[in] proc Proc as a passed block. * @exception rb_eTypeError `recv` is not a method. * @exception rb_eException Any exceptions happen inside. * @return What the method returns. */ VALUE rb_method_call_with_block(int argc, const VALUE *argv, VALUE recv, VALUE proc); /** * Identical to rb_method_call_with_block(), except you can specify how to * handle the last element of the given array. It can also be seen as a * routine identical to rb_method_call_kw(), except you can additionally pass * another proc object as a block. * * @param[in] argc Number of objects of `argv`. * @param[in] argv Arbitrary number of method arguments. * @param[in] recv The method object to call. * @param[in] proc Proc as a passed block. * @param[in] kw_splat Handling of keyword parameters: * - RB_NO_KEYWORDS `args`' last is not a keyword argument. * - RB_PASS_KEYWORDS `args`' last is a keyword argument. * - RB_PASS_CALLED_KEYWORDS it depends if there is a passed block. * @exception rb_eTypeError `recv` is not a method. * @exception rb_eException Any exceptions happen inside. * @return What the method returns. */ VALUE rb_method_call_with_block_kw(int argc, const VALUE *argv, VALUE recv, VALUE proc, int kw_splat); /** * Queries the number of mandatory arguments of the method defined in the given * module. If it is declared to take no arguments, returns `0`. If it takes * exactly `n` arguments, returns `n`. If it has optional arguments, returns * `-n-1`, where `n` is the number of mandatory arguments. Keyword arguments * will be considered as a single additional argument, that argument being * mandatory if any keyword argument is mandatory. * * @param[in] mod Namespace to search a method for. * @param[in] mid Method id. * @retval 0 It takes no arguments. * @retval >0 It takes exactly this number of arguments. * @retval <0 It takes optional arguments. */ int rb_mod_method_arity(VALUE mod, ID mid); /** * Identical to rb_mod_method_arity(), except it searches for singleton methods * rather than instance methods. * * @param[in] obj Object to search for a singleton method. * @param[in] mid Method id. * @retval 0 It takes no arguments. * @retval >0 It takes exactly this number of arguments. * @retval <0 It takes optional arguments. */ int rb_obj_method_arity(VALUE obj, ID mid); /* eval.c */ RBIMPL_ATTR_NONNULL((1)) /** * Protects a function call from potential global escapes from the function. * Such global escapes include exceptions, `throw`, `break`, for example. * * It first calls the function func with `args` as the argument. If no global * escape occurred during the function, it returns the result and `*state` is * zero. Otherwise, it returns ::RUBY_Qnil and sets `*state` to nonzero. If * `state` is `NULL`, it is not set in both cases. * * @param[in] func A function that potentially escapes globally. * @param[in] args Passed as-is to `func`. * @param[out] state State of execution. * @return What `func` returns, or an undefined value when it did not * return. * @post `*state` is set to zero if succeeded. Nonzero otherwise. * @warning You have to clear the error info with `rb_set_errinfo(Qnil)` if * you decide to ignore the caught exception. * @see rb_eval_string_protect() * @see rb_load_protect() * * @internal * * The "undefined value" described above is in fact ::RUBY_Qnil for now. But * @shyouhei doesn't think that we would never change that. * * Though not a part of our public API, `state` is in fact an * enum ruby_tag_type. You can see the potential "nonzero" values by looking * at vm_core.h. */ VALUE rb_protect(VALUE (*func)(VALUE args), VALUE args, int *state); RBIMPL_SYMBOL_EXPORT_END() #endif /* RBIMPL_INTERN_PROC_H */ include/ruby/internal/intern/re.h 0000644 00000021030 15152150472 0013040 0 ustar 00 #ifndef RBIMPL_INTERN_RE_H /*-*-C++-*-vi:se ft=cpp:*/ #define RBIMPL_INTERN_RE_H /** * @file * @author Ruby developers <ruby-core@ruby-lang.org> * @copyright This file is a part of the programming language Ruby. * Permission is hereby granted, to either redistribute and/or * modify this file, provided that the conditions mentioned in the * file COPYING are met. Consult the file for details. * @warning Symbols prefixed with either `RBIMPL` or `rbimpl` are * implementation details. Don't take them as canon. They could * rapidly appear then vanish. The name (path) of this header file * is also an implementation detail. Do not expect it to persist * at the place it is now. Developers are free to move it anywhere * anytime at will. * @note To ruby-core: remember that this header can be possibly * recursively included from extension libraries written in C++. * Do not expect for instance `__VA_ARGS__` is always available. * We assume C99 for ruby itself but we don't assume languages of * extension libraries. They could be written in C++98. * @brief Public APIs related to ::rb_cRegexp. */ #include "ruby/internal/attr/nonnull.h" #include "ruby/internal/dllexport.h" #include "ruby/internal/value.h" RBIMPL_SYMBOL_EXPORT_BEGIN() /* re.c */ /** * @deprecated This macro once was a thing in the old days, but makes no sense * any longer today. Exists here for backwards compatibility * only. You can safely forget about it. * * @internal * * This was a function that switched between memcmp and rb_memcicmp depending * on then-called `ruby_ignorecase`, or the `$=` global variable. That feature * was abandoned in sometime around version 1.9.0. */ #define rb_memcmp memcmp /** * Identical to st_locale_insensitive_strcasecmp(), except it is timing safe * and returns something different. * * @param[in] s1 Comparison LHS. * @param[in] s2 Comparison RHS. * @param[in] n Comparison shall stop after first `n` bytes are scanned. * @retval <0 `s1` is "less" than `s2`. * @retval 0 Both sides converted into lowercase would be identical. * @retval >0 `s1` is "greater" than `s2`. * @note The "case" here means that of the POSIX Locale. * * @internal * * Can accept NULLs as long as n is also 0, and returns 0. */ int rb_memcicmp(const void *s1,const void *s2, long n); /** * Asserts that the given MatchData is "occupied". MatchData shares its * backend storages with its Regexp object. But programs can destructively * tamper its contents. Calling this function beforehand shall prevent such * modifications to spill over into other objects. * * @param[out] md Target instance of ::rb_cMatch. * @post The object is "busy". * * @internal * * There is rb_match_unbusy internally, but extension libraries are left unable * to do so. */ void rb_match_busy(VALUE md); /** * Identical to rb_reg_nth_match(), except it just returns Boolean. This could * skip allocating a returning string, resulting in reduced memory footprints * if applicable. * * @param[in] n Match index. * @param[in] md An instance of ::rb_cMatch. * @exception rb_eTypeError `md` is not initialised. * @retval RUBY_Qnil There is no `n`-th capture. * @retval RUBY_Qfalse There is a `n`-th capture and is empty. * @retval RUBY_Qtrue There is a `n`-th capture that has something. * */ VALUE rb_reg_nth_defined(int n, VALUE md); /** * Queries the nth captured substring. * * @param[in] n Match index. * @param[in] md An instance of ::rb_cMatch. * @exception rb_eTypeError `md` is not initialised. * @retval RUBY_Qnil There is no `n`-th capture. * @retval otherwise An allocated instance of ::rb_cString containing * the contents captured. */ VALUE rb_reg_nth_match(int n, VALUE md); /** * Queries the index of the given named capture. Captures could be named. But * that doesn't mean named ones are not indexed. A regular expression can mix * named and non-named captures, and they are all indexed. This function * converts from a name to its index. * * @param[in] match An instance of ::rb_cMatch. * @param[in] backref Capture name, in String, Symbol, or Numeric. * @exception rb_eIndexError No such named capture. * @return The index of the given name. */ int rb_reg_backref_number(VALUE match, VALUE backref); /** * This just returns the argument, stringified. What a poor name. * * @param[in] md An instance of ::rb_cMatch. * @return Its 0th capture (i.e. entire matched string). */ VALUE rb_reg_last_match(VALUE md); /** * The portion of the original string before the given match. * * @param[in] md An instance of ::rb_cMatch. * @return Its "prematch". This is perl's ``$```. */ VALUE rb_reg_match_pre(VALUE md); /** * The portion of the original string after the given match. * * @param[in] md An instance of ::rb_cMatch. * @return Its "postmatch". This is perl's `$'`. */ VALUE rb_reg_match_post(VALUE md); /** * The portion of the original string that captured at the very last. * * @param[in] md An instance of ::rb_cMatch. * @return Its "lastmatch". This is perl's `$+`. */ VALUE rb_reg_match_last(VALUE md); /** * @private * * @deprecated This macro once was a thing in the old days, but makes no sense * any longer today. Exists here for backwards compatibility * only. You can safely forget about it. */ #define HAVE_RB_REG_NEW_STR 1 /** * Identical to rb_reg_new(), except it takes the expression in Ruby's string * instead of C's. * * @param[in] src Source code in String. * @param[in] opts Options e.g. ONIG_OPTION_MULTILINE. * @exception rb_eRegexpError `src` and `opts` do not interface. * @return Allocated new instance of ::rb_cRegexp. */ VALUE rb_reg_new_str(VALUE src, int opts); RBIMPL_ATTR_NONNULL(()) /** * Creates a new Regular expression. * * @param[in] src Source code. * @param[in] len `strlen(src)`. * @param[in] opts Options e.g. ONIG_OPTION_MULTILINE. * @return Allocated new instance of ::rb_cRegexp. */ VALUE rb_reg_new(const char *src, long len, int opts); /** * Allocates an instance of ::rb_cRegexp. * * @private * * Nobody should call this function. Regular expressions that are not * initialised must not exist in the wild. */ VALUE rb_reg_alloc(void); /** * Initialises an instance of ::rb_cRegexp. * * @private * * This just raises for ordinal regexp objects. Extension libraries must not * use. */ VALUE rb_reg_init_str(VALUE re, VALUE s, int options); /** * This is the match operator. * * @param[in] re An instance of ::rb_cRegexp. * @param[in] str An instance of ::rb_cString. * @exception rb_eTypeError `str` is not a string. * @exception rb_eRegexpError Error inside of Onigmo (unlikely). * @retval RUBY_Qnil Match failed. * @retval otherwise Matched position (character index inside of * `str`). * @post `Regexp.last_match` is updated. * @post `$&`, `$~`, etc., are updated. * @note If you do this in ruby, named captures are assigned to local * variable of the local scope. But that doesn't happen here. The * assignment is done by the interpreter. */ VALUE rb_reg_match(VALUE re, VALUE str); /** * Identical to rb_reg_match(), except it matches against rb_lastline_get() * (or, the `$_`). * * @param[in] re An instance of ::rb_cRegexp. * @exception rb_eRegexpError Error inside of Onigmo (unlikely). * @retval RUBY_Qnil Match failed or `$_` is absent. * @retval otherwise Matched position (character index inside of * `$_`). * @post `Regexp.last_match` is updated. * @post `$&`, `$~`, etc., are updated. */ VALUE rb_reg_match2(VALUE re); /** * Queries the options of the passed regular expression. * * @param[in] re An instance of ::rb_cRegexp. * @return Its options. * @note Possible return values are defined in Onigmo.h. */ int rb_reg_options(VALUE re); RBIMPL_SYMBOL_EXPORT_END() #endif /* RBIMPL_INTERN_RE_H */ include/ruby/internal/intern/thread.h 0000644 00000044034 15152150472 0013712 0 ustar 00 #ifndef RBIMPL_INTERN_THREAD_H /*-*-C++-*-vi:se ft=cpp:*/ #define RBIMPL_INTERN_THREAD_H /** * @file * @author Ruby developers <ruby-core@ruby-lang.org> * @copyright This file is a part of the programming language Ruby. * Permission is hereby granted, to either redistribute and/or * modify this file, provided that the conditions mentioned in the * file COPYING are met. Consult the file for details. * @warning Symbols prefixed with either `RBIMPL` or `rbimpl` are * implementation details. Don't take them as canon. They could * rapidly appear then vanish. The name (path) of this header file * is also an implementation detail. Do not expect it to persist * at the place it is now. Developers are free to move it anywhere * anytime at will. * @note To ruby-core: remember that this header can be possibly * recursively included from extension libraries written in C++. * Do not expect for instance `__VA_ARGS__` is always available. * We assume C99 for ruby itself but we don't assume languages of * extension libraries. They could be written in C++98. * @brief Public APIs related to ::rb_cThread. */ #include "ruby/internal/attr/nonnull.h" #include "ruby/internal/cast.h" #include "ruby/internal/config.h" #include "ruby/internal/dllexport.h" #include "ruby/internal/value.h" RBIMPL_SYMBOL_EXPORT_BEGIN() struct timeval; /* thread.c */ /** * Tries to switch to another thread. This function blocks until the current * thread re-acquires the GVL. * * @exception rb_eInterrupt Operation interrupted. */ void rb_thread_schedule(void); /** * Blocks the current thread until the given file descriptor is ready to be * read. * * @param[in] fd A file descriptor. * @exception rb_eIOError Closed stream. * @exception rb_eSystemCallError Situations like EBADF. */ int rb_thread_wait_fd(int fd); /** * Identical to rb_thread_wait_fd(), except it blocks the current thread until * the given file descriptor is ready to be written. * * @param[in] fd A file descriptor. * @exception rb_eIOError Closed stream. * @exception rb_eSystemCallError Situations like EBADF. */ int rb_thread_fd_writable(int fd); /** * Notifies a closing of a file descriptor to other threads. Multiple threads * can wait for the given file descriptor at once. If such file descriptor is * closed, threads need to start propagating their exceptions. This is the API * to kick that process. * * @param[in] fd A file descriptor. * @note This function blocks until all the threads waiting for such fd * have woken up. */ void rb_thread_fd_close(int fd); /** * Checks if the thread this function is running is the only thread that is * currently alive. * * @retval 1 Yes it is. * @retval 0 No it isn't. * * @internal * * Above description is in fact inaccurate. There are Ractors these days. */ int rb_thread_alone(void); /** * Blocks for the given period of time. * * @warning This function can be interrupted by signals. * @param[in] sec Duration in seconds. * @exception rb_eInterrupt Interrupted. */ void rb_thread_sleep(int sec); /** * Blocks indefinitely. * * @exception rb_eInterrupt Interrupted. */ void rb_thread_sleep_forever(void); /** * Identical to rb_thread_sleep_forever(), except the thread calling this * function is considered "dead" when our deadlock checker is triggered. * * @exception rb_eInterrupt Interrupted. */ void rb_thread_sleep_deadly(void); /** * Stops the current thread. This is not the end of the thread's lifecycle. A * stopped thread can later be woken up. * * @exception rb_eThreadError Stopping this thread would deadlock. * @retval ::RUBY_Qnil Always. * * @internal * * The return value makes no sense at all. */ VALUE rb_thread_stop(void); /** * Marks a given thread as eligible for scheduling. * * @note It may still remain blocked on I/O. * @note This does not invoke the scheduler itself. * * @param[out] thread Thread in question to wake up. * @exception rb_eThreadError Stop flogging a dead horse. * @return The passed thread. * @post The passed thread is made runnable. */ VALUE rb_thread_wakeup(VALUE thread); /** * Identical to rb_thread_wakeup(), except it doesn't raise on an already * killed thread. * * @param[out] thread A thread to wake up. * @retval RUBY_Qnil `thread` is already killed. * @retval otherwise `thread` is alive. * @post The passed thread is made runnable, unless killed. */ VALUE rb_thread_wakeup_alive(VALUE thread); /** * This is a rb_thread_wakeup() + rb_thread_schedule() combo. * * @note There is no guarantee that this function yields to the passed * thread. It may still remain blocked on I/O. * @param[out] thread Thread in question to wake up. * @exception rb_eThreadError Stop flogging a dead horse. * @return The passed thread. */ VALUE rb_thread_run(VALUE thread); /** * Terminates the given thread. Unlike a stopped thread, a killed thread could * never be revived. This function does return, when passed e.g. an already * killed thread. But if the passed thread is the only one, or a special * thread called "main", then it also terminates the entire process. * * @param[out] thread The thread to terminate. * @exception rb_eFatal The passed thread is the running thread. * @exception rb_eSystemExit The passed thread is the last thread. * @return The passed thread. * @post Either the passed thread, or the process entirely, is killed. * * @internal * * It seems killing the main thread also kills the entire process even if there * are multiple running ractors. No idea why. */ VALUE rb_thread_kill(VALUE thread); RBIMPL_ATTR_NONNULL((1)) /** * Creates a Ruby thread that is backended by a C function. * * @param[in] f The function to run on a thread. * @param[in,out] g Passed through to `f`. * @exception rb_eThreadError Could not create a ruby thread. * @exception rb_eSystemCallError Situations like `EPERM`. * @return Allocated instance of ::rb_cThread. * @note This doesn't wait for anything. */ VALUE rb_thread_create(VALUE (*f)(void *g), void *g); /** * Identical to rb_thread_sleep(), except it takes struct `timeval` instead. * * @warning This function can be interrupted by signals. * @param[in] time Duration. * @exception rb_eInterrupt Interrupted. */ void rb_thread_wait_for(struct timeval time); /** * Obtains the "current" thread. * * @return The current thread of the current ractor of the current execution * context. * @pre This function must be called from a thread controlled by ruby. */ VALUE rb_thread_current(void); /** * Obtains the "main" thread. There are threads called main. Historically the * (only) main thread was the one which runs when the process boots. Now that * we have Ractor, there are more than one main threads. * * @return The main thread of the current ractor of the current execution * context. * @pre This function must be called from a thread controlled by ruby. */ VALUE rb_thread_main(void); /** * This badly named function reads from a Fiber local storage. When this * function was born there was no such thing like a Fiber. The world was * innocent. But now... This is a Fiber local storage. Sorry. * * @param[in] thread Thread that the target Fiber is running. * @param[in] key The name of the Fiber local storage to read. * @retval RUBY_Qnil No such storage. * @retval otherwise The value stored at `key`. * @note There in fact are "true" thread local storage, but Ruby doesn't * provide any interface of them to you, C programmers. */ VALUE rb_thread_local_aref(VALUE thread, ID key); /** * This badly named function writes to a Fiber local storage. When this * function was born there was no such thing like a Fiber. The world was * innocent. But now... This is a Fiber local storage. Sorry. * * @param[in] thread Thread that the target Fiber is running. * @param[in] key The name of the Fiber local storage to write. * @param[in] val The new value of the storage. * @exception rb_eFrozenError `thread` is frozen. * @return The passed `val` as-is. * @post Fiber local storage `key` has value of `val`. * @note There in fact are "true" thread local storage, but Ruby doesn't * provide any interface of them to you, C programmers. */ VALUE rb_thread_local_aset(VALUE thread, ID key, VALUE val); /** * A `pthread_atfork(3posix)`-like API. Ruby expects its child processes to * call this function at the very beginning of their processes. If you plan to * fork a process don't forget to call it. */ void rb_thread_atfork(void); /** * :FIXME: situation of this function is unclear. It seems nobody uses it. * Maybe a good idea to KonMari. */ void rb_thread_atfork_before_exec(void); /** * "Recursion" API entry point. This basically calls the given function with * the given arguments, but additionally with recursion flag. The flag is set * to 1 if the execution have already experienced the passed `g` parameter * before. * * @param[in] f The function that possibly recurs. * @param[in,out] g Passed as-is to `f`. * @param[in,out] h Passed as-is to `f`. * @return The return value of f. */ VALUE rb_exec_recursive(VALUE (*f)(VALUE g, VALUE h, int r), VALUE g, VALUE h); /** * Identical to rb_exec_recursive(), except it checks for the recursion on the * ordered pair of `{ g, p }` instead of just `g`. * * @param[in] f The function that possibly recurs. * @param[in,out] g Passed as-is to `f`. * @param[in] p Paired object for recursion detection. * @param[in,out] h Passed as-is to `f`. */ VALUE rb_exec_recursive_paired(VALUE (*f)(VALUE g, VALUE h, int r), VALUE g, VALUE p, VALUE h); /** * Identical to rb_exec_recursive(), except it calls `f` for outermost * recursion only. Inner recursions yield calls to rb_throw_obj(). * * @param[in] f The function that possibly recurs. * @param[in,out] g Passed as-is to `f`. * @param[in,out] h Passed as-is to `f`. * @return The return value of f. * * @internal * * It seems nobody uses the "it calls rb_throw_obj()" part of this function. * @shyouhei doesn't understand the needs. */ VALUE rb_exec_recursive_outer(VALUE (*f)(VALUE g, VALUE h, int r), VALUE g, VALUE h); /** * Identical to rb_exec_recursive_outer(), except it checks for the recursion * on the ordered pair of `{ g, p }` instead of just `g`. It can also be seen * as a routine identical to rb_exec_recursive_paired(), except it calls `f` * for outermost recursion only. Inner recursions yield calls to * rb_throw_obj(). * * @param[in] f The function that possibly recurs. * @param[in,out] g Passed as-is to `f`. * @param[in] p Paired object for recursion detection. * @param[in,out] h Passed as-is to `f`. * * @internal * * It seems nobody uses the "it calls rb_throw_obj()" part of this function. * @shyouhei doesn't understand the needs. */ VALUE rb_exec_recursive_paired_outer(VALUE (*f)(VALUE g, VALUE h, int r), VALUE g, VALUE p, VALUE h); /** * This is the type of UBFs. An UBF is a function that unblocks a blocking * region. For instance when a thread is blocking due to `pselect(3posix)`, it * is highly expected that `pthread_kill(3posix)` can interrupt the system call * and the thread could revive. Or when a thread is blocking due to * `waitpid(3posix)`, it is highly expected that killing the waited process * should suffice. An UBF is a function that does such things. Designing your * own UBF needs deep understanding of why your blocking region blocks, how * threads work in ruby, and a matter of luck. It often is the case you simply * cannot cancel something that had already begun. * * @see rb_thread_call_without_gvl() */ typedef void rb_unblock_function_t(void *); /** * @private * * This is an implementation detail. Must be a mistake to be here. * * @internal * * Why is this function type different from what rb_thread_call_without_gvl() * takes? */ typedef VALUE rb_blocking_function_t(void *); /** * Checks for interrupts. In ruby, signals are masked by default. You can * call this function at will to check if there are pending signals. In case * there are, they would be handled in this function. * * If your extension library has a function that takes a long time, consider * calling it periodically. * * @note It might switch to another thread. */ void rb_thread_check_ints(void); /** * Checks if the thread's execution was recently interrupted. If called from * that thread, this function can be used to detect spurious wake-ups. * * @param[in] thval Thread in question. * @retval 0 The thread was not interrupted. * @retval otherwise The thread was interrupted recently. * * @internal * * Above description is not a lie. But actually the return value is an opaque * trap vector. If you know which bit means which, you can know what happened. */ int rb_thread_interrupted(VALUE thval); /** * A special UBF for blocking IO operations. You need deep understanding of * what this actually do before using. Basically you should not use it from * extension libraries. It is too easy to mess up. */ #define RUBY_UBF_IO RBIMPL_CAST((rb_unblock_function_t *)-1) /** * A special UBF for blocking process operations. You need deep understanding * of what this actually do before using. Basically you should not use it from * extension libraries. It is too easy to mess up. */ #define RUBY_UBF_PROCESS RBIMPL_CAST((rb_unblock_function_t *)-1) /* thread_sync.c */ /** * Creates a mutex. * * @return An allocated instance of rb_cMutex. */ VALUE rb_mutex_new(void); /** * Queries if there are any threads that holds the lock. * * @param[in] mutex The mutex in question. * @retval RUBY_Qtrue The mutex is locked by someone. * @retval RUBY_Qfalse The mutex is not locked by anyone. */ VALUE rb_mutex_locked_p(VALUE mutex); /** * Attempts to lock the mutex, without waiting for other threads to unlock it. * Failure in locking the mutex can be detected by the return value. * * @param[out] mutex The mutex to lock. * @retval RUBY_Qtrue Successfully locked by the current thread. * @retval RUBY_Qfalse Otherwise. * @note This function also returns ::RUBY_Qfalse when the mutex is * already owned by the calling thread itself. */ VALUE rb_mutex_trylock(VALUE mutex); /** * Attempts to lock the mutex. It waits until the mutex gets available. * * @param[out] mutex The mutex to lock. * @exception rb_eThreadError Recursive deadlock situation. * @return The passed mutex. * @post The mutex is owned by the current thread. */ VALUE rb_mutex_lock(VALUE mutex); /** * Releases the mutex. * * @param[out] mutex The mutex to unlock. * @exception rb_eThreadError The mutex is not owned by the current thread. * @return The passed mutex. * @post Upon successful return the passed mutex is no longer owned by * the current thread. */ VALUE rb_mutex_unlock(VALUE mutex); /** * Releases the lock held in the mutex and waits for the period of time; * reacquires the lock on wakeup. * * @pre The lock has to be owned by the current thread beforehand. * @param[out] self The target mutex. * @param[in] timeout Duration, in seconds, in ::rb_cNumeric. * @exception rb_eArgError `timeout` is negative. * @exception rb_eRangeError `timeout` is out of range of `time_t`. * @exception rb_eThreadError The mutex is not owned by the current thread. * @return Number of seconds it actually slept. * @warning It is a failure not to check the return value. This function * can return spuriously for various reasons. Maybe other threads * can rb_thread_wakeup(). Maybe an end user can press the * Control and C key from the interactive console. On the other * hand it can also take longer than the specified. The mutex * could be locked by someone else. It waits then. * @post Upon successful return the passed mutex is owned by the current * thread. * * @internal * * This function is called from `ConditionVariable#wait`. So it is not a * deprecated feature. However @shyouhei have never seen any similar mutex * primitive available in any other languages than Ruby. * * EDIT: In 2021, @shyouhei asked @ko1 in person about this API. He answered * that it is his invention. The motivation behind its design is to eliminate * needs of condition variables as primitives. Unlike other languages, Ruby's * `ConditionVariable` class was written in pure-Ruby initially. We don't have * to implement machine-native condition variables in assembly each time we * port Ruby to a new architecture. This function made it possible. "I felt I * was a genius when this idea came to me", said @ko1. * * `rb_cConditionVariable` is now written in C for speed, though. */ VALUE rb_mutex_sleep(VALUE self, VALUE timeout); /** * Obtains the lock, runs the passed function, and releases the lock when it * completes. * * @param[out] mutex The mutex to lock. * @param[in] func What to do during the mutex is locked. * @param[in,out] arg Passed as-is to `func`. */ VALUE rb_mutex_synchronize(VALUE mutex, VALUE (*func)(VALUE arg), VALUE arg); RBIMPL_SYMBOL_EXPORT_END() #endif /* RBIMPL_INTERN_THREAD_H */ include/ruby/internal/intern/cont.h 0000644 00000026665 15152150472 0013420 0 ustar 00 #ifndef RBIMPL_INTERN_CONT_H /*-*-C++-*-vi:se ft=cpp:*/ #define RBIMPL_INTERN_CONT_H /** * @file * @author Ruby developers <ruby-core@ruby-lang.org> * @copyright This file is a part of the programming language Ruby. * Permission is hereby granted, to either redistribute and/or * modify this file, provided that the conditions mentioned in the * file COPYING are met. Consult the file for details. * @warning Symbols prefixed with either `RBIMPL` or `rbimpl` are * implementation details. Don't take them as canon. They could * rapidly appear then vanish. The name (path) of this header file * is also an implementation detail. Do not expect it to persist * at the place it is now. Developers are free to move it anywhere * anytime at will. * @note To ruby-core: remember that this header can be possibly * recursively included from extension libraries written in C++. * Do not expect for instance `__VA_ARGS__` is always available. * We assume C99 for ruby itself but we don't assume languages of * extension libraries. They could be written in C++98. * @brief Public APIs related to rb_cFiber. */ #include "ruby/internal/dllexport.h" #include "ruby/internal/value.h" #include "ruby/internal/iterator.h" RBIMPL_SYMBOL_EXPORT_BEGIN() /* cont.c */ /** * Creates a Fiber instance from a C-backended block. * * @param[in] func A function, to become the fiber's body. * @param[in] callback_obj Passed as-is to `func`. * @return An allocated new instance of rb_cFiber, which is ready to be * "resume"d. */ VALUE rb_fiber_new(rb_block_call_func_t func, VALUE callback_obj); /** * Creates a Fiber instance from a C-backended block with the specified * storage. * * If the given storage is Qundef or Qtrue, this function is equivalent to * rb_fiber_new() which inherits storage from the current fiber. * * Specifying Qtrue is experimental and may be changed in the future. * * If the given storage is Qnil, this function will lazy initialize the * internal storage which starts of empty (without any inheritance). * * Otherwise, the given storage is used as the internal storage. * * @param[in] func A function, to become the fiber's body. * @param[in] callback_obj Passed as-is to `func`. * @param[in] storage The way to set up the storage for the fiber. * @return An allocated new instance of rb_cFiber, which is ready to be * "resume"d. */ VALUE rb_fiber_new_storage(rb_block_call_func_t func, VALUE callback_obj, VALUE storage); /** * Queries the fiber which is calling this function. Any ruby execution * context has its fiber, either explicitly or implicitly. * * @return The current fiber. */ VALUE rb_fiber_current(void); /** * Queries the liveness of the passed fiber. "Alive" in this context means * that the fiber can still be resumed. Once it reaches is its end of * execution, this function returns ::RUBY_Qfalse. * * @param[in] fiber A target fiber. * @retval RUBY_Qtrue It is. * @retval RUBY_Qfalse It isn't. */ VALUE rb_fiber_alive_p(VALUE fiber); /** * Queries if an object is a fiber. * * @param[in] obj Arbitrary ruby object. * @retval RUBY_Qtrue It is. * @retval RUBY_Qfalse It isn't. */ VALUE rb_obj_is_fiber(VALUE obj); /** * Resumes the execution of the passed fiber, either from the point at which * the last rb_fiber_yield() was called if any, or at the beginning of the * fiber body if it is the first call to this function. * * Other arguments are passed into the fiber's body, either as return values of * rb_fiber_yield() in case it switches to there, or as the block parameter of * the fiber body if it switches to the beginning of the fiber. * * The return value of this function is either the value passed to previous * rb_fiber_yield() call, or the ultimate evaluated value of the entire fiber * body if the execution reaches the end of it. * * When an exception happens inside of a fiber it propagates to this function. * * ```ruby * f = Fiber.new do |i| * puts "<x> =>> #{i}" * puts "<y> <-- #{i + 1}" * j = Fiber.yield(i + 1) * puts "<z> =>> #{j}" * puts "<w> <-- #{j + 1}" * next j + 1 * end * * puts "[a] <-- 1" * p = f.resume(1) * puts "[b] =>> #{p}" * puts "[c] <-- #{p + 1}" * q = f.resume(p + 1) * puts "[d] =>> #{q}" * ``` * * Above program executes in `[a] <x> <y> [b] [c] <z> <w> [d]`. * * @param[out] fiber The fiber to resume. * @param[in] argc Number of objects of `argv`. * @param[in] argv Passed (somehow) to `fiber`. * @exception rb_eFiberError `fib` is terminated etc. * @exception rb_eException Any exceptions happen in `fiber`. * @return (See above) * @note This function _does_ return. * * @internal * * @shyouhei expected this function to raise ::rb_eFrozenError for frozen * fibers but it doesn't in practice. Intentional or ...? */ VALUE rb_fiber_resume(VALUE fiber, int argc, const VALUE *argv); /** * Identical to rb_fiber_resume(), except you can specify how to handle the * last element of the given array. * * @param[out] fiber The fiber to resume. * @param[in] argc Number of objects of `argv`. * @param[in] argv Passed (somehow) to `fiber`. * @param[in] kw_splat Handling of keyword parameters: * - RB_NO_KEYWORDS `argv`'s last is not a keyword argument. * - RB_PASS_KEYWORDS `argv`'s last is a keyword argument. * - RB_PASS_CALLED_KEYWORDS it depends if there is a passed block. * @exception rb_eFiberError `fiber` is terminated etc. * @exception rb_eException Any exceptions happen in `fiber`. * @return Either what was yielded or the last value of the fiber body. */ VALUE rb_fiber_resume_kw(VALUE fiber, int argc, const VALUE *argv, int kw_splat); /** * Yields the control back to the point where the current fiber was resumed. * The passed objects would be the return value of rb_fiber_resume(). This * fiber then suspends its execution until next time it is resumed. * * This function can also raise arbitrary exceptions injected from outside of * the fiber using rb_fiber_raise(). * * ```ruby * exc = Class.new Exception * * f = Fiber.new do * Fiber.yield * rescue exc => e * puts e.message * end * * f.resume * f.raise exc, "Hi!" * ``` * * @param[in] argc Number of objects of `argv`. * @param[in] argv Passed to rb_fiber_resume(). * @exception rb_eException (See above) * @return (See rb_fiber_resume() for details) */ VALUE rb_fiber_yield(int argc, const VALUE *argv); /** * Identical to rb_fiber_yield(), except you can specify how to handle the last * element of the given array. * * @param[in] argc Number of objects of `argv`. * @param[in] argv Passed to rb_fiber_resume(). * @param[in] kw_splat Handling of keyword parameters: * - RB_NO_KEYWORDS `argv`'s last is not a keyword argument. * - RB_PASS_KEYWORDS `argv`'s last is a keyword argument. * - RB_PASS_CALLED_KEYWORDS it depends if there is a passed block. * @exception rb_eException What was raised using `Fiber#raise`. * @return (See rb_fiber_resume() for details) */ VALUE rb_fiber_yield_kw(int argc, const VALUE *argv, int kw_splat); /** * Transfers control to another fiber, resuming it from where it last stopped * or starting it if it was not resumed before. The calling fiber will be * suspended much like in a call to rb_fiber_yield(). * * The fiber which receives the transfer call treats it much like a resume * call. Arguments passed to transfer are treated like those passed to resume. * * The two style of control passing to and from fiber (one is rb_fiber_resume() * and rb_fiber_yield(), another is rb_fiber_transfer() to and from fiber) * can't be freely mixed. * * - If the Fiber's lifecycle had started with transfer, it will never be * able to yield or be resumed control passing, only finish or transfer * back. (It still can resume other fibers that are allowed to be * resumed.) * * - If the Fiber's lifecycle had started with resume, it can yield or * transfer to another Fiber, but can receive control back only the way * compatible with the way it was given away: if it had transferred, it * only can be transferred back, and if it had yielded, it only can be * resumed back. After that, it again can transfer or yield. * * If those rules are broken, rb_eFiberError is raised. * * For an individual Fiber design, yield/resume is easier to use (the Fiber * just gives away control, it doesn't need to think about who the control is * given to), while transfer is more flexible for complex cases, allowing to * build arbitrary graphs of Fibers dependent on each other. * * @param[out] fiber Explicit control destination. * @param[in] argc Number of objects of `argv`. * @param[in] argv Passed to rb_fiber_resume(). * @exception rb_eFiberError (See above) * @exception rb_eException What was raised using `Fiber#raise`. * @return (See rb_fiber_resume() for details) */ VALUE rb_fiber_transfer(VALUE fiber, int argc, const VALUE *argv); /** * Identical to rb_fiber_transfer(), except you can specify how to handle the * last element of the given array. * * @param[out] fiber Explicit control destination. * @param[in] argc Number of objects of `argv`. * @param[in] argv Passed to rb_fiber_resume(). * @param[in] kw_splat Handling of keyword parameters: * - RB_NO_KEYWORDS `argv`'s last is not a keyword argument. * - RB_PASS_KEYWORDS `argv`'s last is a keyword argument. * - RB_PASS_CALLED_KEYWORDS it depends if there is a passed block. * @exception rb_eFiberError (See above) * @exception rb_eException What was raised using `Fiber#raise`. * @return (See rb_fiber_resume() for details) */ VALUE rb_fiber_transfer_kw(VALUE fiber, int argc, const VALUE *argv, int kw_splat); /** * Identical to rb_fiber_resume() but instead of resuming normal execution of * the passed fiber, it raises the given exception in it. From inside of the * fiber this would be seen as if rb_fiber_yield() raised. * * This function does return in case the passed fiber gracefully handled the * passed exception. But if it does not, the raised exception propagates out * of the passed fiber; this function then does not return. * * Parameters are passed to rb_make_exception() to create an exception object. * See its document for what are allowed here. * * It is a failure to call this function against a fiber which is resuming, * have never run yet, or has already finished running. * * @param[out] fiber Where exception is raised. * @param[in] argc Passed as-is to rb_make_exception(). * @param[in] argv Passed as-is to rb_make_exception(). * @exception rb_eFiberError `fiber` is terminated etc. * @return (See rb_fiber_resume() for details) */ VALUE rb_fiber_raise(VALUE fiber, int argc, const VALUE *argv); RBIMPL_SYMBOL_EXPORT_END() #endif /* RBIMPL_INTERN_CONT_H */ include/ruby/internal/intern/vm.h 0000644 00000040750 15152150472 0013066 0 ustar 00 #ifndef RBIMPL_INTERN_VM_H /*-*-C++-*-vi:se ft=cpp:*/ #define RBIMPL_INTERN_VM_H /** * @file * @author Ruby developers <ruby-core@ruby-lang.org> * @copyright This file is a part of the programming language Ruby. * Permission is hereby granted, to either redistribute and/or * modify this file, provided that the conditions mentioned in the * file COPYING are met. Consult the file for details. * @warning Symbols prefixed with either `RBIMPL` or `rbimpl` are * implementation details. Don't take them as canon. They could * rapidly appear then vanish. The name (path) of this header file * is also an implementation detail. Do not expect it to persist * at the place it is now. Developers are free to move it anywhere * anytime at will. * @note To ruby-core: remember that this header can be possibly * recursively included from extension libraries written in C++. * Do not expect for instance `__VA_ARGS__` is always available. * We assume C99 for ruby itself but we don't assume languages of * extension libraries. They could be written in C++98. * @brief Public APIs related to rb_cRubyVM. */ #include "ruby/internal/attr/nonnull.h" #include "ruby/internal/attr/noreturn.h" #include "ruby/internal/dllexport.h" #include "ruby/internal/value.h" RBIMPL_SYMBOL_EXPORT_BEGIN() /* vm.c */ /** * Resembles `__LINE__`. * * @retval 0 Current execution context not in a ruby method. * @retval otherwise The current line number of the current thread of the * current ractor of the current execution context. */ int rb_sourceline(void); /** * Resembles `__FILE__`. * * @retval 0 Current execution context not in a ruby method. * @retval otherwise The current source path of the current thread of the * current ractor of the current execution context. * @note This may or may not be an absolute path. */ const char *rb_sourcefile(void); /** * Resembles `__method__`. * * @param[out] idp Return buffer for method id. * @param[out] klassp Return buffer for class. * @retval 0 Current execution context not in a method. * @retval 1 Successful return. * @post Upon successful return `*idp` and `*klassp` are updated to have * the current method name and its defined class respectively. * @note Both parameters can be `NULL`. */ int rb_frame_method_id_and_class(ID *idp, VALUE *klassp); /* vm_eval.c */ /** * Identical to rb_funcallv(), except it returns ::RUBY_Qundef instead of * raising ::rb_eNoMethodError. * * @param[in,out] recv Receiver of the method. * @param[in] mid Name of the method to call. * @param[in] argc Number of arguments. * @param[in] argv Arbitrary number of method arguments. * @retval RUBY_Qundef `recv` doesn't respond to `mid`. * @retval otherwise What the method evaluates to. */ VALUE rb_check_funcall(VALUE recv, ID mid, int argc, const VALUE *argv); /** * Identical to rb_check_funcall(), except you can specify how to handle the * last element of the given array. It can also be seen as a routine identical * to rb_funcallv_kw(), except it returns ::RUBY_Qundef instead of raising * ::rb_eNoMethodError. * * @param[in,out] recv Receiver of the method. * @param[in] mid Name of the method to call. * @param[in] argc Number of arguments. * @param[in] argv Arbitrary number of method arguments. * @param[in] kw_splat Handling of keyword parameters: * - RB_NO_KEYWORDS `argv`'s last is not a keyword argument. * - RB_PASS_KEYWORDS `argv`'s last is a keyword argument. * - RB_PASS_CALLED_KEYWORDS it depends if there is a passed block. * @retval RUBY_Qundef `recv` doesn't respond to `mid`. * @retval otherwise What the method evaluates to. */ VALUE rb_check_funcall_kw(VALUE recv, ID mid, int argc, const VALUE *argv, int kw_splat); /** * This API is practically a variant of rb_proc_call_kw() now. Historically * when there still was a concept called `$SAFE`, this was an API for that. * But we no longer have that. This function basically ended its role. It * just remains here because of no harm. * * @param[in] cmd A string, or something callable. * @param[in] arg Argument passed to the call. * @param[in] kw_splat Handling of keyword parameters: * - RB_NO_KEYWORDS `arg`'s last is not a keyword argument. * - RB_PASS_KEYWORDS `arg`'s last is a keyword argument. * - RB_PASS_CALLED_KEYWORDS it depends if there is a passed block. * @return What the command evaluates to. */ VALUE rb_eval_cmd_kw(VALUE cmd, VALUE arg, int kw_splat); /** * Identical to rb_funcallv(), except it takes Ruby's array instead of C's. * @param[in,out] recv Receiver of the method. * @param[in] mid Name of the method to call. * @param[in] args An instance of ::RArray. * @exception rb_eNoMethodError No such method. * @exception rb_eException Any exceptions happen inside. * @return What the method evaluates to. * @pre `args` must be an ::RArray. Call `to_ary` beforehand when * necessary. */ VALUE rb_apply(VALUE recv, ID mid, VALUE args); /** * Evaluates a string containing Ruby source code, or the given block, within * the context of the receiver. In order to set the context, the variable * `self` is set to `recv` while the code is executing, giving the code access * to `recv`'s instance variables and private methods. * * When given a block, `recv` is also passed in as the block's only argument. * * When given a string, the optional second and third parameters supply a * filename and starting line number that are used when reporting compilation * errors. * * @param[in] argc Number of objects in `argv` * @param[in] argv C array of 0 up to 3 elements. * @param[in] recv The object in question. * @return What was evaluated. */ VALUE rb_obj_instance_eval(int argc, const VALUE *argv, VALUE recv); /** * Executes the given block within the context of the receiver. In order to * set the context, the variable `self` is set to `recv` while the code is * executing, giving the code access to `recv`'s instance variables. Arguments * are passed as block parameters. * * @param[in] argc Number of objects in `argv` * @param[in] argv Arbitrary parameters to be passed to the block. * @param[in] recv The object in question. * @return What was evaluated. * @note Don't confuse this with rb_obj_instance_eval(). The key * difference is whether you can pass arbitrary parameters to the * block, like this: * * ```ruby * class Foo * def initialize * @foo = 5 * end * end * Foo.new.instance_exec(7) {|i| @foo + i } # => 12 * ``` */ VALUE rb_obj_instance_exec(int argc, const VALUE *argv, VALUE recv); /** * Identical to rb_obj_instance_eval(), except it evaluates within the context * of module. * * @param[in] argc Number of objects in `argv` * @param[in] argv C array of 0 up to 3 elements. * @param[in] mod The module in question. * @pre `mod` must be a Module. * @return What was evaluated. */ VALUE rb_mod_module_eval(int argc, const VALUE *argv, VALUE mod); /** * Identical to rb_obj_instance_exec(), except it evaluates within the context * of module. * * @param[in] argc Number of objects in `argv` * @param[in] argv Arbitrary parameters to be passed to the block. * @param[in] mod The module in question. * @pre `mod` must be a Module. * @return What was evaluated. */ VALUE rb_mod_module_exec(int argc, const VALUE *argv, VALUE mod); /* vm_method.c */ /** * @private * * @deprecated This macro once was a thing in the old days, but makes no sense * any longer today. Exists here for backwards compatibility * only. You can safely forget about it. */ #define HAVE_RB_DEFINE_ALLOC_FUNC 1 /** * This is the type of functions that ruby calls when trying to allocate an * object. It is sometimes necessary to allocate extra memory regions for an * object. When you define a class that uses ::RTypedData, it is typically the * case. On such situations define a function of this type and pass it to * rb_define_alloc_func(). * * @param[in] klass The class that this function is registered. * @return A newly allocated instance of `klass`. */ typedef VALUE (*rb_alloc_func_t)(VALUE klass); /** * Sets the allocator function of a class. * * @param[out] klass The class to modify. * @param[in] func An allocator function for the class. * @pre `klass` must be an instance of Class. */ void rb_define_alloc_func(VALUE klass, rb_alloc_func_t func); /** * Deletes the allocator function of a class. It is sometimes desirable to * restrict creation of an instance of a class. For example it rarely makes * sense for a DB adaptor class to allow programmers creating DB row objects * without querying the DB itself. You can kill sporadic creation of such * objects then, by nullifying the allocator function using this API. Your * object shall be allocated using #RB_NEWOBJ_OF() directly. * * @param[out] klass The class to modify. * @pre `klass` must be an instance of Class. */ void rb_undef_alloc_func(VALUE klass); /** * Queries the allocator function of a class. * * @param[in] klass The class in question. * @pre `klass` must be an instance of Class. * @retval 0 No allocator function is registered. * @retval otherwise The allocator function. * * @internal * * Who cares? @shyouhei finds no practical usage of the return value. Maybe we * need KonMari. */ rb_alloc_func_t rb_get_alloc_func(VALUE klass); /** * Clears the inline constant caches associated with a particular ID. Extension * libraries should not bother with such things. Just forget about this API (or * even, the presence of constant caches). */ void rb_clear_constant_cache_for_id(ID id); /** * Resembles `alias`. * * @param[out] klass Where to define an alias. * @param[in] dst New name. * @param[in] src Existing name. * @exception rb_eTypeError `klass` is not a class. * @exception rb_eFrozenError `klass` is frozen. * @exception rb_eNameError No such method named `src`. * @post `klass` has a method named `dst`, which is the identical to its * method named `src`. */ void rb_alias(VALUE klass, ID dst, ID src); /** * This function resembles now-deprecated `Module#attr`. * * @param[out] klass Where to define an attribute. * @param[in] name Name of an instance variable. * @param[in] need_reader Whether attr_reader is needed. * @param[in] need_writer Whether attr_writer is needed. * @param[in] honour_visibility Whether to use the current visibility. * @exception rb_eTypeError `klass` is not a class. * @exception rb_eFrozenError `klass` is frozen. * @post If `need_reader` is set `klass` has a method named `name`. * @post If `need_writer` is set `klass` has a method named `name=`. * * @internal * * The three `int` arguments should have been bool, but there was no such thing * like a bool when K&R was used in this project. */ void rb_attr(VALUE klass, ID name, int need_reader, int need_writer, int honour_visibility); RBIMPL_ATTR_NONNULL(()) /** * Removes a method. Don't confuse this to rb_undef_method(), which doesn't * remove a method. This one resembles `Module#remove_method`. * * @param[out] klass The class to remove a method. * @param[in] name Name of a method to be removed. * @exception rb_eTypeError `klass` is a non-module. * @exception rb_eFrozenError `klass` is frozen. * @exception rb_eNameError No such method. * @see rb_undef_method */ void rb_remove_method(VALUE klass, const char *name); /** * Identical to rb_remove_method(), except it accepts the method name as ::ID. * * @param[out] klass The class to remove a method. * @param[in] mid Name of a method to be removed. * @exception rb_eTypeError `klass` is a non-module. * @exception rb_eFrozenError `klass` is frozen. * @exception rb_eNameError No such method. * @see rb_undef */ void rb_remove_method_id(VALUE klass, ID mid); /** * Queries if the klass has this method. This function has only one line of * document in the implementation that states "// deprecated". Don't know what * that means though. * * @param[in] klass The class in question. * @param[in] id The method name to query. * @param[in] ex Undocumented magic value. * @retval false Method not found. * @retval true There is a method. * @pre `klass` must be a module. * * @internal * * @shyouhei has no motivation to describe what should be passed to `ex`. It * seems this function should just be trashed. */ int rb_method_boundp(VALUE klass, ID id, int ex); /** * Well... Let us hesitate from describing what a "basic definition" is. This * nuanced concept should have been kept private. Just please. Don't touch * it. This function is a badly distributed random number generator. Right? * * @param[in] klass The class in question. * @param[in] mid The method name in question. * @retval 1 It is. * @retval 0 It isn't. */ int rb_method_basic_definition_p(VALUE klass, ID mid); /** * Identical to rb_respond_to(), except it additionally takes the visibility * parameter. This does not make difference unless the object has * `respond_to?` undefined, but has `respond_to_missing?` defined. That case * the passed argument becomes the second argument of `respond_to_missing?`. * * @param[in] obj The object in question. * @param[in] mid The method name in question. * @param[in] private_p This is the second argument of `obj`'s * `respond_to_missing?`. * @retval 1 Yes it does. * @retval 0 No it doesn't. */ int rb_obj_respond_to(VALUE obj, ID mid, int private_p); /** * Queries if the object responds to the method. This involves calling the * object's `respond_to?` method. * * @param[in] obj The object in question. * @param[in] mid The method name in question. * @retval 1 Yes it does. * @retval 0 No it doesn't. */ int rb_respond_to(VALUE obj, ID mid); RBIMPL_ATTR_NORETURN() /** * Raises ::rb_eNotImpError. This function is used as an argument to * rb_define_method() etc. * * ```CXX * rb_define_method(rb_cFoo, "foo", rb_f_notimplement, -1); * ``` * * @param argc Unused parameter. * @param argv Unused parameter. * @param obj Unused parameter. * @param marker Unused parameter. * @exception rb_eNotImpError Always. * @return Never returns. * * @internal * * See also the Q&A section of include/ruby/internal/anyargs.h. */ VALUE rb_f_notimplement(int argc, const VALUE *argv, VALUE obj, VALUE marker); #if !defined(RUBY_EXPORT) && defined(_WIN32) RUBY_EXTERN VALUE (*const rb_f_notimplement_)(int, const VALUE *, VALUE, VALUE marker); #define rb_f_notimplement (*rb_f_notimplement_) #endif /* vm_backtrace.c */ /** * Prints the backtrace out to the standard error. This just confuses people * for no reason. Evil souls must only use it. * * @internal * * Actually it is very useful when called from an interactive GDB session. */ void rb_backtrace(void); /** * Creates the good old fashioned array-of-strings style backtrace info. * * @return An array which contains strings, which are the textual * representations of the backtrace locations of the current thread of * the current ractor of the current execution context. * @note Ruby scripts can access more sophisticated * `Thread::Backtrace::Location`. But it seems there is no way for C * extensions to use that API. */ VALUE rb_make_backtrace(void); RBIMPL_SYMBOL_EXPORT_END() #endif /* RBIMPL_INTERN_VM_H */ include/ruby/internal/intern/error.h 0000644 00000023135 15152150472 0013573 0 ustar 00 #ifndef RBIMPL_INTERN_ERROR_H /*-*-C++-*-vi:se ft=cpp:*/ #define RBIMPL_INTERN_ERROR_H /** * @file * @author Ruby developers <ruby-core@ruby-lang.org> * @copyright This file is a part of the programming language Ruby. * Permission is hereby granted, to either redistribute and/or * modify this file, provided that the conditions mentioned in the * file COPYING are met. Consult the file for details. * @warning Symbols prefixed with either `RBIMPL` or `rbimpl` are * implementation details. Don't take them as canon. They could * rapidly appear then vanish. The name (path) of this header file * is also an implementation detail. Do not expect it to persist * at the place it is now. Developers are free to move it anywhere * anytime at will. * @note To ruby-core: remember that this header can be possibly * recursively included from extension libraries written in C++. * Do not expect for instance `__VA_ARGS__` is always available. * We assume C99 for ruby itself but we don't assume languages of * extension libraries. They could be written in C++98. * @brief Public APIs related to ::rb_eException. */ #include "ruby/internal/attr/format.h" #include "ruby/internal/attr/noreturn.h" #include "ruby/internal/dllexport.h" #include "ruby/internal/value.h" #include "ruby/internal/fl_type.h" #include "ruby/backward/2/assume.h" /** * This macro is used in conjunction with rb_check_arity(). If you pass it to * the function's last (max) argument, that means the function does not check * upper limit. */ #define UNLIMITED_ARGUMENTS (-1) #define rb_exc_new2 rb_exc_new_cstr /**< @old{rb_exc_new_cstr} */ #define rb_exc_new3 rb_exc_new_str /**< @old{rb_exc_new_str} */ /** @cond INTERNAL_MACRO */ #define rb_check_arity rb_check_arity /** @endcond */ RBIMPL_SYMBOL_EXPORT_BEGIN() /* error.c */ /** * Creates an instance of the passed exception class. * * @param[in] etype A subclass of ::rb_eException. * @param[in] ptr Buffer contains error message. * @param[in] len Length of `ptr`, in bytes, not including the * terminating NUL character. * @exception rb_eTypeError `etype` is not a class. * @exception rb_eArgError `len` is negative. * @return An instance of `etype`. * @pre At least `len` bytes of continuous memory region shall be * accessible via `ptr`. * * @internal * * This function works for non-exception classes as well, as long as they take * one string argument. */ VALUE rb_exc_new(VALUE etype, const char *ptr, long len); RBIMPL_ATTR_NONNULL(()) /** * Identical to rb_exc_new(), except it assumes the passed pointer is a pointer * to a C string. * * @param[in] etype A subclass of ::rb_eException. * @param[in] str A C string (becomes an error message). * @exception rb_eTypeError `etype` is not a class. * @return An instance of `etype`. */ VALUE rb_exc_new_cstr(VALUE etype, const char *str); /** * Identical to rb_exc_new_cstr(), except it takes a Ruby's string instead of * C's. * * @param[in] etype A subclass of ::rb_eException. * @param[in] str An instance of ::rb_cString. * @exception rb_eTypeError `etype` is not a class. * @return An instance of `etype`. */ VALUE rb_exc_new_str(VALUE etype, VALUE str); RBIMPL_ATTR_NORETURN() RBIMPL_ATTR_NONNULL((1)) RBIMPL_ATTR_FORMAT(RBIMPL_PRINTF_FORMAT, 1, 2) /** * Raises an instance of ::rb_eLoadError. * * @param[in] fmt Format specifier string compatible with rb_sprintf(). * @exception rb_eLoadError Always raises this. * @note It never returns. * * @internal * * Who needs this? Except ruby itself? */ void rb_loaderror(const char *fmt, ...); RBIMPL_ATTR_NORETURN() RBIMPL_ATTR_NONNULL((2)) RBIMPL_ATTR_FORMAT(RBIMPL_PRINTF_FORMAT, 2, 3) /** * Identical to rb_loaderror(), except it additionally takes which file is * unable to load. The path can be obtained later using `LoadError#path` of * the raising exception. * * @param[in] path What failed. * @param[in] fmt Format specifier string compatible with rb_sprintf(). * @exception rb_eLoadError Always raises this. * @note It never returns. */ void rb_loaderror_with_path(VALUE path, const char *fmt, ...); RBIMPL_ATTR_NORETURN() RBIMPL_ATTR_NONNULL((2)) RBIMPL_ATTR_FORMAT(RBIMPL_PRINTF_FORMAT, 2, 3) /** * Raises an instance of ::rb_eNameError. The name can be obtained later using * `NameError#name` of the raising exception. * * @param[in] name What failed. * @param[in] fmt Format specifier string compatible with rb_sprintf(). * @exception rb_eNameError Always raises this. * @note It never returns. */ void rb_name_error(ID name, const char *fmt, ...); RBIMPL_ATTR_NORETURN() RBIMPL_ATTR_NONNULL((2)) RBIMPL_ATTR_FORMAT(RBIMPL_PRINTF_FORMAT, 2, 3) /** * Identical to rb_name_error(), except it takes a ::VALUE instead of ::ID. * * @param[in] name What failed. * @param[in] fmt Format specifier string compatible with rb_sprintf(). * @exception rb_eNameError Always raises this. * @note It never returns. */ void rb_name_error_str(VALUE name, const char *fmt, ...); RBIMPL_ATTR_NORETURN() RBIMPL_ATTR_NONNULL((2)) RBIMPL_ATTR_FORMAT(RBIMPL_PRINTF_FORMAT, 2, 3) /** * Raises an instance of ::rb_eFrozenError. The object can be obtained later * using `FrozenError#receiver` of the raising exception. * * @param[in] recv What is frozen. * @param[in] fmt Format specifier string compatible with rb_sprintf(). * @exception rb_eFrozenError Always raises this. * @note It never returns. * * @internal * * Note however, that it is often not possible to inspect a frozen object, * because the inspection itself could be forbidden by the frozen-ness. */ void rb_frozen_error_raise(VALUE recv, const char *fmt, ...); RBIMPL_ATTR_NORETURN() RBIMPL_ATTR_NONNULL(()) /** * Honestly I don't understand the name, but it raises an instance of * ::rb_eArgError. * * @param[in] str A message. * @param[in] type Another message. * @exception rb_eArgError Always raises this. * @note It never returns. */ void rb_invalid_str(const char *str, const char *type); RBIMPL_ATTR_NORETURN() RBIMPL_ATTR_NONNULL(()) /** * Identical to rb_frozen_error_raise(), except its raising exception has a * message like "can't modify frozen /what/". * * @param[in] what What was frozen. * @exception rb_eFrozenError Always raises this. * @note It never returns. */ void rb_error_frozen(const char *what); RBIMPL_ATTR_NORETURN() /** * Identical to rb_error_frozen(), except it takes arbitrary Ruby object * instead of C's string. * * @param[in] what What was frozen. * @exception rb_eFrozenError Always raises this. * @note It never returns. */ void rb_error_frozen_object(VALUE what); /** * Queries if the passed object is frozen. * * @param[in] obj Target object to test frozen-ness. * @exception rb_eFrozenError It is frozen. * @post Upon successful return it is guaranteed _not_ frozen. */ void rb_check_frozen(VALUE obj); /** * Ensures that the passed object can be `initialize_copy` relationship. When * you implement your own one you would better call this at the right beginning * of your implementation. * * @param[in] obj Destination object. * @param[in] orig Source object. * @exception rb_eFrozenError `obj` is frozen. * @post Upon successful return obj is guaranteed safe to copy orig. */ void rb_check_copyable(VALUE obj, VALUE orig); RBIMPL_ATTR_NORETURN() /** * @private * * This is an implementation detail of rb_scan_args(). You don't have to * bother. * * @pre `argc` is out of range of `min`..`max`, both inclusive. * @param[in] argc Arbitrary integer. * @param[in] min Minimum allowed `argc`. * @param[in] max Maximum allowed `argc`. * @exception rb_eArgError Always. */ void rb_error_arity(int argc, int min, int max); RBIMPL_SYMBOL_EXPORT_END() /** * @deprecated * * Does anyone use this? Remain not deleted for compatibility. */ #define rb_check_frozen_internal(obj) do { \ VALUE frozen_obj = (obj); \ if (RB_UNLIKELY(RB_OBJ_FROZEN(frozen_obj))) { \ rb_error_frozen_object(frozen_obj); \ } \ } while (0) /** @alias{rb_check_frozen} */ static inline void rb_check_frozen_inline(VALUE obj) { if (RB_UNLIKELY(RB_OBJ_FROZEN(obj))) { rb_error_frozen_object(obj); } } /** @alias{rb_check_frozen} */ #define rb_check_frozen rb_check_frozen_inline /** * Ensures that the passed integer is in the passed range. When you can use * rb_scan_args() that is preferred over this one (powerful, descriptive). But * it can have its own application area. * * @param[in] argc Arbitrary integer. * @param[in] min Minimum allowed `argv`. * @param[in] max Maximum allowed `argv`, or `UNLIMITED_ARGUMENTS`. * @exception rb_eArgError `argc` out of range. * @return The passed `argc`. * @post Upon successful return `argc` is in range of `min`..`max`, both * inclusive. */ static inline int rb_check_arity(int argc, int min, int max) { if ((argc < min) || (max != UNLIMITED_ARGUMENTS && argc > max)) rb_error_arity(argc, min, max); return argc; } #endif /* RBIMPL_INTERN_ERROR_H */ include/ruby/internal/intern/bignum.h 0000644 00000074054 15152150473 0013732 0 ustar 00 #ifndef RBIMPL_INTERN_BIGNUM_H /*-*-C++-*-vi:se ft=cpp:*/ #define RBIMPL_INTERN_BIGNUM_H /** * @file * @author Ruby developers <ruby-core@ruby-lang.org> * @copyright This file is a part of the programming language Ruby. * Permission is hereby granted, to either redistribute and/or * modify this file, provided that the conditions mentioned in the * file COPYING are met. Consult the file for details. * @warning Symbols prefixed with either `RBIMPL` or `rbimpl` are * implementation details. Don't take them as canon. They could * rapidly appear then vanish. The name (path) of this header file * is also an implementation detail. Do not expect it to persist * at the place it is now. Developers are free to move it anywhere * anytime at will. * @note To ruby-core: remember that this header can be possibly * recursively included from extension libraries written in C++. * Do not expect for instance `__VA_ARGS__` is always available. * We assume C99 for ruby itself but we don't assume languages of * extension libraries. They could be written in C++98. * @brief Public APIs related to so-called rb_cBignum. */ #include "ruby/internal/config.h" #ifdef STDC_HEADERS # include <stddef.h> #endif #include "ruby/internal/attr/nonnull.h" #include "ruby/internal/dllexport.h" #include "ruby/internal/value.h" #include "ruby/backward/2/long_long.h" RBIMPL_SYMBOL_EXPORT_BEGIN() /* bignum.c */ /** * Allocates a bignum object. * * @param[in] len Length of the bignum's backend storage, in words. * @param[in] sign Sign of the bignum. * @return An allocated new bignum instance. * @note This only allocates an object, doesn't fill its value in. * * @internal * * @shyouhei finds it hard to use from extension libraries. `len` is per * `BDIGIT` but its definition is hidden. */ VALUE rb_big_new(size_t len, int sign); /** * Queries if the passed bignum instance is a "bigzero". What is a bigzero? * Well, bignums are for very big integers, but can also represent tiny ones * like -1, 0, 1. Bigzero are instances of bignums whose values are zero. * Knowing if a bignum is bigzero can be handy on occasions, like for instance * detecting division by zero situation. * * @param[in] x A bignum. * @retval 1 It is a bigzero. * @retval 0 Otherwise. */ int rb_bigzero_p(VALUE x); /** * Duplicates the given bignum. * * @param[in] num A bignum. * @return An allocated bignum, who is equivalent to `num`. */ VALUE rb_big_clone(VALUE num); /** * Destructively modify the passed bignum into 2's complement representation. * * @note By default bignums are in signed magnitude system. * * @param[out] num A bignum to modify. */ void rb_big_2comp(VALUE num); /** * Normalises the passed bignum. It for instance returns a fixnum of the same * value if fixnum can represent that number. * * @param[out] x Target bignum (can be destructively modified). * @return An integer of the identical value (can be `x` itself). */ VALUE rb_big_norm(VALUE x); /** * Destructively resizes the backend storage of the passed bignum. * * @param[out] big A bignum. * @param[in] len New length of `big`'s backend, in words. */ void rb_big_resize(VALUE big, size_t len); RBIMPL_ATTR_NONNULL(()) /** * Parses C's string to convert into a Ruby's integer. It understands prefixes * (e.g. `0x`) and underscores. * * @param[in] str Stringised representation of the return value. * @param[in] base Base of conversion. Must be `-36..36` inclusive, * except `1`. `2..36` means the conversion is done * according to it, with unmatched prefix understood * as a part of the result. `-36..-2` means the * conversion honours prefix when present, or use * `-base` when absent. `0` is equivalent to `-10`. * `-1` mandates a prefix. `1` is an error. * @param[in] badcheck Whether to raise ::rb_eArgError on failure. If * `0` is passed here this function can return * `INT2FIX(0)` for parse errors. * @exception rb_eArgError Failed to parse (and `badcheck` is truthy). * @return An instance of ::rb_cInteger, which is a numeric interpretation * of what is written in `str`. * * @internal * * Not sure if it intentionally accepts `base == -1` or is just buggy. Nobody * practically uses negative bases these days. */ VALUE rb_cstr_to_inum(const char *str, int base, int badcheck); /** * Identical to rb_cstr2inum(), except it takes Ruby's strings instead of C's. * * @param[in] str Stringised representation of the return * value. * @param[in] base Base of conversion. Must be `-36..36` * inclusive, except `1`. `2..36` means the * conversion is done according to it, with * unmatched prefix understood as a part of the * result. `-36..-2` means the conversion * honours prefix when present, or use `-base` * when absent. `0` is equivalent to `-10`. * `-1` mandates a prefix. `1` is an error. * @param[in] badcheck Whether to raise ::rb_eArgError on failure. * If `0` is passed here this function can * return `INT2FIX(0)` for parse errors. * @exception rb_eArgError Failed to parse (and `badcheck` is truthy). * @exception rb_eTypeError `str` is not a string. * @exception rb_eEncCompatError `str` is not ASCII compatible. * @return An instance of ::rb_cInteger, which is a numeric interpretation * of what is written in `str`. */ VALUE rb_str_to_inum(VALUE str, int base, int badcheck); RBIMPL_ATTR_NONNULL(()) /** * Identical to rb_cstr_to_inum(), except the second argument controls the base * and badcheck at once. It basically doesn't raise for parse errors, unless * the base is zero. * * This is an older API. New codes might prefer rb_cstr_to_inum(). * * @param[in] str Stringised representation of the return value. * @param[in] base Base of conversion. Must be `-36..36` inclusive, * except `1`. `2..36` means the conversion is done * according to it, with unmatched prefix understood * as a part of the result. `-36..-2` means the * conversion honours prefix when present, or use * `-base` when absent. `0` is equivalent to `-10`. * `-1` mandates a prefix. `1` is an error. * @exception rb_eArgError Failed to parse (and `base` is zero). * @return An instance of ::rb_cInteger, which is a numeric interpretation * of what is written in `str`. */ VALUE rb_cstr2inum(const char *str, int base); /** * Identical to rb_str_to_inum(), except the second argument controls the base * and badcheck at once. It can also be seen as a routine identical to * rb_cstr2inum(), except it takes Ruby's strings instead of C's. * * This is an older API. New codes might prefer rb_cstr_to_inum(). * * @param[in] str Stringised representation of the return * value. * @param[in] base Base of conversion. Must be `-36..36` * inclusive, except `1`. `2..36` means the * conversion is done according to it, with * unmatched prefix understood as a part of the * result. `-36..-2` means the conversion * honours prefix when present, or use `-base` * when absent. `0` is equivalent to `-10`. * `-1` mandates a prefix. `1` is an error. * @exception rb_eArgError Failed to parse (and `base` is zero). * @exception rb_eTypeError `str` is not a string. * @exception rb_eEncCompatError `str` is not ASCII compatible. * @return An instance of ::rb_cInteger, which is a numeric interpretation * of what is written in `str`. */ VALUE rb_str2inum(VALUE str, int base); /** * Generates a place-value representation of the passed integer. * * @param[in] x An integer to stringify. * @param[in] base `2` to `36` inclusive for each radix. * @exception rb_eArgError `base` is out of range. * @exception rb_eRangeError `x` is too big, cannot represent in string. * @return An instance of ::rb_cString which represents `x`. */ VALUE rb_big2str(VALUE x, int base); /** * Converts a bignum into C's `long`. * * @param[in] x A bignum. * @exception rb_eRangeError `x` is out of range of `long`. * @return The passed value converted into C's `long`. */ long rb_big2long(VALUE x); /** @alias{rb_big2long} */ #define rb_big2int(x) rb_big2long(x) /** * Converts a bignum into C's `unsigned long`. * * @param[in] x A bignum. * @exception rb_eRangeError `x` is out of range of `unsigned long`. * @return The passed value converted into C's `unsigned long`. * * @internal * * This function can generate a very large positive integer for a negative * input. For instance applying Ruby's -4,611,686,018,427,387,905 to this * function yields C's 13,835,058,055,282,163,711 on my machine. This is how * it has been. Cannot change any longer. */ unsigned long rb_big2ulong(VALUE x); /** @alias{rb_big2long} */ #define rb_big2uint(x) rb_big2ulong(x) #if HAVE_LONG_LONG /** * Converts a bignum into C's `long long`. * * @param[in] x A bignum. * @exception rb_eRangeError `x` is out of range of `long long`. * @return The passed value converted into C's `long long`. */ LONG_LONG rb_big2ll(VALUE); /** * Converts a bignum into C's `unsigned long long`. * * @param[in] x A bignum. * @exception rb_eRangeError `x` is out of range of `unsigned long long`. * @return The passed value converted into C's `unsigned long long`. * * @internal * * This function can generate a very large positive integer for a negative * input. For instance applying Ruby's -4,611,686,018,427,387,905 to this * function yields C's 13,835,058,055,282,163,711 on my machine. This is how * it has been. Cannot change any longer. */ unsigned LONG_LONG rb_big2ull(VALUE); #endif /* HAVE_LONG_LONG */ RBIMPL_ATTR_NONNULL(()) /** * Converts a bignum into a series of its parts. * * @param[in] val An integer. * @param[out] buf Return buffer. * @param[in] num_longs Number of words of `buf`. * @exception rb_eTypeError `val` doesn't respond to `#to_int`. * @post `buf` is filled with `val`'s 2's complement representation, in * the host CPU's native byte order, from least significant word * towards the most significant one, for `num_longs` words. * @note The "pack" terminology comes from `Array#pack`. */ void rb_big_pack(VALUE val, unsigned long *buf, long num_longs); RBIMPL_ATTR_NONNULL(()) /** * Constructs a (possibly very big) bignum from a series of integers. `buf[0]` * would be the return value's least significant word; `buf[num_longs-1]` would * be that of most significant. * * @param[in] buf A series of integers. * @param[in] num_longs Number of words of `buf`. * @exception rb_eArgError Result would be too big. * @return An instance of ::rb_cInteger which is an "unpack"-ed value of * the parameters. * @note The "unpack" terminology comes from `String#pack`. */ VALUE rb_big_unpack(unsigned long *buf, long num_longs); /* pack.c */ RBIMPL_ATTR_NONNULL(()) /** * Encodes a Unicode codepoint into its UTF-8 representation. * * @param[out] buf Return buffer, must at least be 6 bytes width. * @param[in] uv An Unicode codepoint. * @exception rb_eRangeError `uv` is out of Unicode. * @return Number of bytes written to `buf` * @post `buf` holds a UTF-8 representation of `uv`. */ int rb_uv_to_utf8(char buf[6], unsigned long uv); /* bignum.c */ /** * Converts a C's `double` into a bignum. * * @param[in] d A value to convert. * @exception rb_eFloatDomainError `d` is Inf/NaN. * @return An instance of ::rb_cInteger whose value is approximately `d`. * * @internal * * @shyouhei is not sure if the result is guaranteed to be the nearest integer * of `d`. */ VALUE rb_dbl2big(double d); /** * Converts a bignum into C's `double`. * * @param[in] x A bignum. * @return The passed value converted into C's `double`. * * @internal * * @shyouhei is not sure if the result is guaranteed to be `x`'s nearest value * that a `double` can represent. */ double rb_big2dbl(VALUE x); /** * Compares the passed two bignums. * * @param[in] lhs Comparison LHS. * @param[in] rhs Comparison RHS. * @retval -1 `rhs` is bigger than `lhs`. * @retval 0 They are identical. * @retval 1 `lhs` is bigger than `rhs`. * @see rb_num_coerce_cmp() */ VALUE rb_big_cmp(VALUE lhs, VALUE rhs); /** * Equality, in terms of `==`. This checks if the _value_ is the same, not the * identity. For instance `1 == 1.0` must hold. * * @param[in] lhs Comparison LHS. * @param[in] rhs Comparison RHS. * @retval RUBY_Qtrue They are the same. * @retval RUBY_Qfalse They are different. */ VALUE rb_big_eq(VALUE lhs, VALUE rhs); /** * Equality, in terms of `eql?`. Unlike rb_big_eq() it does not convert * ::rb_cFloat etc. This function returns ::RUBY_Qtrue if and only if both * parameters are bignums, which represent the identical numerical value. * * @param[in] lhs Comparison LHS. * @param[in] rhs Comparison RHS. * @retval RUBY_Qtrue They are identical. * @retval RUBY_Qfalse They are distinct. */ VALUE rb_big_eql(VALUE lhs, VALUE rhs); /** * Performs addition of the passed two objects. * * @param[in] x A bignum. * @param[in] y Arbitrary ruby object. * @return What `x + y` evaluates to. * @see rb_num_coerce_bin() */ VALUE rb_big_plus(VALUE x, VALUE y); /** * Performs subtraction of the passed two objects. * * @param[in] x A bignum. * @param[in] y Arbitrary ruby object. * @return What `x - y` evaluates to. * @see rb_num_coerce_bin() */ VALUE rb_big_minus(VALUE x, VALUE y); /** * Performs multiplication of the passed two objects. * * @param[in] x A bignum. * @param[in] y Arbitrary ruby object. * @return What `x * y` evaluates to. * @see rb_num_coerce_bin() */ VALUE rb_big_mul(VALUE x, VALUE y); /** * Performs division of the passed two objects. * * @param[in] x A bignum. * @param[in] y Arbitrary ruby object. * @return What `x / y` evaluates to. * @see rb_num_coerce_bin() */ VALUE rb_big_div(VALUE x, VALUE y); /** * Performs "integer division". This is different from rb_big_div(). * * @param[in] x A bignum. * @param[in] y Arbitrary ruby object. * @return What `x.div y` evaluates to. * @see rb_num_coerce_bin() */ VALUE rb_big_idiv(VALUE x, VALUE y); /** * Performs modulo of the passed two objects. * * @param[in] x A bignum. * @param[in] y Arbitrary ruby object. * @return What `x % y` evaluates to. * @see rb_num_coerce_bin() * * @internal * * There also is `rb_big_remainder()` internally, which is different from this * one. */ VALUE rb_big_modulo(VALUE x, VALUE y); /** * Performs "divmod" operation. The operation in bignum's context is that it * calculates rb_big_idiv() and rb_big_modulo() at once. * * @param[in] x A bignum. * @param[in] y Arbitrary ruby object. * @return What `x.divmod y` evaluates to. * @see rb_num_coerce_bin() */ VALUE rb_big_divmod(VALUE x, VALUE y); /** * Raises `x` to the powerof `y`. * * @param[in] x A bignum. * @param[in] y Arbitrary ruby object. * @return What `x ** y` evaluates to. * @see rb_num_coerce_bin() * @note This can return an instance of ::rb_cFloat, even when both `x` * and `y` are bignums. Or an instance of ::rb_cRational, when for * instance `y` is negative. */ VALUE rb_big_pow(VALUE x, VALUE y); /** * Performs bitwise and of the passed two objects. * * @param[in] x A bignum. * @param[in] y Arbitrary ruby object. * @return What `x & y` evaluates to. * @see rb_num_coerce_bit() */ VALUE rb_big_and(VALUE x, VALUE y); /** * Performs bitwise or of the passed two objects. * * @param[in] x A bignum. * @param[in] y Arbitrary ruby object. * @return What `x | y` evaluates to. * @see rb_num_coerce_bit() */ VALUE rb_big_or(VALUE x, VALUE y); /** * Performs exclusive or of the passed two objects. * * @param[in] x A bignum. * @param[in] y Arbitrary ruby object. * @return What `x ^ y` evaluates to. * @see rb_num_coerce_bit() */ VALUE rb_big_xor(VALUE x, VALUE y); /** * Performs shift left. * * @param[in] x A bignum. * @param[in] y Shift amount. * @exception rb_eTypeError `y` is not an integer. * @exception rb_eArgError `y` is too big. * @return `x` shifted left to `y` bits. * @note `y` can be negative. Shifts right then. */ VALUE rb_big_lshift(VALUE x, VALUE y); /** * Performs shift right. * * @param[in] x A bignum. * @param[in] y Shift amount. * @exception rb_eTypeError `y` is not an integer. * @return `x` shifted right to `y` bits. * @note This is arithmetic. Because bignums are not bitfields there is * no shift right logical operator. */ VALUE rb_big_rshift(VALUE x, VALUE y); /** * @name Flags for rb_integer_pack()/rb_integer_unpack() * @{ */ /** Stores/interprets the most significant word as the first word. */ #define INTEGER_PACK_MSWORD_FIRST 0x01 /** Stores/interprets the least significant word as the first word. */ #define INTEGER_PACK_LSWORD_FIRST 0x02 /** * Stores/interprets the most significant byte in a word as the first byte in * the word. */ #define INTEGER_PACK_MSBYTE_FIRST 0x10 /** * Stores/interprets the least significant byte in a word as the first byte in * the word. */ #define INTEGER_PACK_LSBYTE_FIRST 0x20 /** * Means either #INTEGER_PACK_MSBYTE_FIRST or #INTEGER_PACK_LSBYTE_FIRST, * depending on the host processor's endian. */ #define INTEGER_PACK_NATIVE_BYTE_ORDER 0x40 /** Uses 2's complement representation. */ #define INTEGER_PACK_2COMP 0x80 /** Uses "generic" implementation (handy on test). */ #define INTEGER_PACK_FORCE_GENERIC_IMPLEMENTATION 0x400 /** * Always generates a bignum object even if the integer can be representable * using fixnum scheme (unpack only) */ #define INTEGER_PACK_FORCE_BIGNUM 0x100 /** * Interprets the input as a signed negative number (unpack only). If not * specified returns a positive number. */ #define INTEGER_PACK_NEGATIVE 0x200 /** Little endian combination. */ #define INTEGER_PACK_LITTLE_ENDIAN \ (INTEGER_PACK_LSWORD_FIRST | \ INTEGER_PACK_LSBYTE_FIRST) /** Big endian combination */ #define INTEGER_PACK_BIG_ENDIAN \ (INTEGER_PACK_MSWORD_FIRST | \ INTEGER_PACK_MSBYTE_FIRST) /** @} */ RBIMPL_ATTR_NONNULL(()) /** * Exports an integer into a buffer. This function fills the buffer specified * by `words` and `numwords` as `val` in the format specified by `wordsize`, * `nails` and `flags`. * * @param[in] val Integer or integer-like object which has * `#to_int` method. * @param[out] words Return buffer. * @param[in] numwords Number of words of `words`. * @param[in] wordsize Number of bytes per word. * @param[in] nails Number of padding bits in a word. Most * significant nails bits of each word are filled * by zero. * @param[in] flags Bitwise or of constants whose name starts * "INTEGER_PACK_". * @exception rb_eTypeError `val` doesn't respond to `#to_int`. * * Possible flags are: * * - #INTEGER_PACK_MSWORD_FIRST: * Stores the most significant word as the first word. * * - #INTEGER_PACK_LSWORD_FIRST: * Stores the least significant word as the first word. * * - #INTEGER_PACK_MSBYTE_FIRST: * Stores the most significant byte in a word as the first byte in the * word. * * - #INTEGER_PACK_LSBYTE_FIRST: * Stores the least significant byte in a word as the first byte in the * word. * * - #INTEGER_PACK_NATIVE_BYTE_ORDER: * Either #INTEGER_PACK_MSBYTE_FIRST or #INTEGER_PACK_LSBYTE_FIRST * corresponding to the host's endian. * * - #INTEGER_PACK_2COMP: * Uses 2's complement representation. * * - #INTEGER_PACK_LITTLE_ENDIAN: Shorthand of * `INTEGER_PACK_LSWORD_FIRST|INTEGER_PACK_LSBYTE_FIRST`. * * - #INTEGER_PACK_BIG_ENDIAN: Shorthand of * `INTEGER_PACK_MSWORD_FIRST|INTEGER_PACK_MSBYTE_FIRST`. * * - #INTEGER_PACK_FORCE_GENERIC_IMPLEMENTATION: * Uses generic implementation (for test and debug). * * This function fills the buffer specified by `words` as `val`'s 2's * complement representation if #INTEGER_PACK_2COMP is specified in `flags`. * Otherwise it fills `words` as `abs(val)` and signedness is returned via the * return value. * * @return The signedness and overflow condition. The overflow condition * depends on #INTEGER_PACK_2COMP. * * When #INTEGER_PACK_2COMP is not specified: * * - `-2` : * Negative overflow. `val <= -2**(numwords*(wordsize*CHAR_BIT-nails))` * * - `-1` : * Negative without overflow. * `-2**(numwords*(wordsize*CHAR_BIT-nails)) < val < 0` * * - `0` : zero. `val == 0` * * - `1` : * Positive without overflow. * `0 < val < 2**(numwords*(wordsize*CHAR_BIT-nails))` * * - `2` : * Positive overflow. `2**(numwords*(wordsize*CHAR_BIT-nails)) <= val` * * When #INTEGER_PACK_2COMP is specified: * * - `-2` : * Negative overflow. `val < -2**(numwords*(wordsize*CHAR_BIT-nails))` * * - `-1` : * Negative without overflow. * `-2**(numwords*(wordsize*CHAR_BIT-nails)) <= val < 0` * * - `0` : zero. `val == 0` * * - `1` : * Positive without overflow. * `0 < val < 2**(numwords*(wordsize*CHAR_BIT-nails))` * * - `2` : * Positive overflow. `2**(numwords*(wordsize*CHAR_BIT-nails)) <= val` * * The value, `-2**(numwords*(wordsize*CHAR_BIT-nails))`, is representable in * 2's complement representation but not representable in absolute value. So * `-1` is returned for the value if #INTEGER_PACK_2COMP is specified but * returns `-2` if #INTEGER_PACK_2COMP is not specified. * * The least significant words are filled in the buffer when overflow occur. */ int rb_integer_pack(VALUE val, void *words, size_t numwords, size_t wordsize, size_t nails, int flags); RBIMPL_ATTR_NONNULL(()) /** * Import an integer from a buffer. * * @param[in] words Buffer to import. * @param[in] numwords Number of words of `words`. * @param[in] wordsize Number of bytes per word. * @param[in] nails Number of padding bits in a word. Most * significant nails bits of each word are ignored. * @param[in] flags Bitwise or of constants whose name starts * "INTEGER_PACK_". * @exception rb_eArgError `numwords * wordsize` too big. * * Possible flags are: * * - #INTEGER_PACK_MSWORD_FIRST: * Interpret the first word as the most significant word. * * - #INTEGER_PACK_LSWORD_FIRST: * Interpret the first word as the least significant word. * * - #INTEGER_PACK_MSBYTE_FIRST: * Interpret the first byte in a word as the most significant byte in the * word. * * - #INTEGER_PACK_LSBYTE_FIRST: * Interpret the first byte in a word as the least significant byte in * the word. * * - #INTEGER_PACK_NATIVE_BYTE_ORDER: * Either #INTEGER_PACK_MSBYTE_FIRST or #INTEGER_PACK_LSBYTE_FIRST * corresponding to the host's endian. * * - #INTEGER_PACK_2COMP: * Uses 2's complement representation. * * - #INTEGER_PACK_LITTLE_ENDIAN: Shorthand of * `INTEGER_PACK_LSWORD_FIRST|INTEGER_PACK_LSBYTE_FIRST` * * - #INTEGER_PACK_BIG_ENDIAN: Shorthand of * `INTEGER_PACK_MSWORD_FIRST|INTEGER_PACK_MSBYTE_FIRST` * * - #INTEGER_PACK_FORCE_BIGNUM: * Returns a bignum even if its value is representable as a fixnum. * * - #INTEGER_PACK_NEGATIVE: * Returns a non-positive value. (Returns a non-negative value if not * specified.) * * - #INTEGER_PACK_FORCE_GENERIC_IMPLEMENTATION: * Uses generic implementation (for test and debug). * * @return An instance of ::rb_cInteger whose value is the interpreted * `words`. The range of the result value depends on * #INTEGER_PACK_2COMP and #INTEGER_PACK_NEGATIVE. * * When #INTEGER_PACK_2COMP is not set: * * - `0 <= val < 2**(numwords*(wordsize*CHAR_BIT-nails))` if * `!INTEGER_PACK_NEGATIVE` * * - `-2**(numwords*(wordsize*CHAR_BIT-nails)) < val <= 0` if * `INTEGER_PACK_NEGATIVE` * * When #INTEGER_PACK_2COMP is set: * * - `-2**(numwords*(wordsize*CHAR_BIT-nails)-1)` `<= val <=` * `2**(numwords*(wordsize*CHAR_BIT-nails)-1)-1` if * `!INTEGER_PACK_NEGATIVE` * * - `-2**(numwords*(wordsize*CHAR_BIT-nails)) <= val <= -1` if * `INTEGER_PACK_NEGATIVE` * * Passing #INTEGER_PACK_2COMP without #INTEGER_PACK_NEGATIVE means sign * extension. #INTEGER_PACK_2COMP with #INTEGER_PACK_NEGATIVE means assuming * the higher bits are `1`. * * Note that this function returns 0 when `numwords` is zero and * #INTEGER_PACK_2COMP is set but #INTEGER_PACK_NEGATIVE is not set. */ VALUE rb_integer_unpack(const void *words, size_t numwords, size_t wordsize, size_t nails, int flags); /** * Calculates the number of bytes needed to represent the absolute value of the * passed integer. * * @param[in] val Integer or integer-like object which has * `#to_int` method. * @param[out] nlz_bits_ret Number of leading zero bits in the most * significant byte is returned if not `NULL`. * @exception rb_eTypeError `val` doesn't respond to `#to_int`. * @return `((val_numbits * CHAR_BIT + CHAR_BIT - 1) / CHAR_BIT)`, where * val_numbits is the number of bits of `abs(val)`. * @post If `nlz_bits_ret` is not `NULL`, * `(return_value * CHAR_BIT - val_numbits)` is stored in * `*nlz_bits_ret`. In this case, * `0 <= *nlz_bits_ret < CHAR_BIT`. * * This function should not overflow. */ size_t rb_absint_size(VALUE val, int *nlz_bits_ret); /** * Calculates the number of words needed represent the absolute value of the * passed integer. Unlike rb_absint_size() this function can overflow. It * returns `(size_t)-1` then. * * @param[in] val Integer or integer-like object which has * `#to_int` method. * @param[in] word_numbits Number of bits per word. * @param[out] nlz_bits_ret Number of leading zero bits in the most * significant word is returned if not `NULL`. * @exception rb_eTypeError `val` doesn't respond to `#to_int`. * @retval (size_t)-1 Overflowed. * @retval otherwise * `((val_numbits * CHAR_BIT + word_numbits - 1) / word_numbits)`, * where val_numbits is the number of bits of `abs(val)`. * @post If `nlz_bits_ret` is not `NULL` and there is no overflow, * `(return_value * word_numbits - val_numbits)` is stored in * `*nlz_bits_ret`. In this case, * `0 <= *nlz_bits_ret < word_numbits.` * */ size_t rb_absint_numwords(VALUE val, size_t word_numbits, size_t *nlz_bits_ret); /** * Tests `abs(val)` consists only of a bit or not. * * @param[in] val Integer or integer-like object which has * `#to_int` method. * @exception rb_eTypeError `val` doesn't respond to `#to_int`. * @retval 1 `abs(val) == 1 << n` for some `n >= 0`. * @retval 0 Otherwise. * * rb_absint_singlebit_p() can be used to determine required buffer size for * rb_integer_pack() used with #INTEGER_PACK_2COMP (two's complement). * * Following example calculates number of bits required to represent val in * two's complement number, without sign bit. * * ```CXX * size_t size; * int neg = FIXNUM_P(val) ? FIX2LONG(val) < 0 : BIGNUM_NEGATIVE_P(val); * size = rb_absint_numwords(val, 1, NULL) * if (size == (size_t)-1) ...overflow... * if (neg && rb_absint_singlebit_p(val)) * size--; * ``` * * Following example calculates number of bytes required to represent val in * two's complement number, with sign bit. * * ```CXX * size_t size; * int neg = FIXNUM_P(val) ? FIX2LONG(val) < 0 : BIGNUM_NEGATIVE_P(val); * int nlz_bits; * size = rb_absint_size(val, &nlz_bits); * if (nlz_bits == 0 && !(neg && rb_absint_singlebit_p(val))) * size++; * ``` */ int rb_absint_singlebit_p(VALUE val); RBIMPL_SYMBOL_EXPORT_END() #endif /* RBIMPL_INTERN_BIGNUM_H */ include/ruby/internal/intern/array.h 0000644 00000062233 15152150473 0013563 0 ustar 00 #ifndef RBIMPL_INTERN_ARRAY_H /*-*-C++-*-vi:se ft=cpp:*/ #define RBIMPL_INTERN_ARRAY_H /** * @file * @author Ruby developers <ruby-core@ruby-lang.org> * @copyright This file is a part of the programming language Ruby. * Permission is hereby granted, to either redistribute and/or * modify this file, provided that the conditions mentioned in the * file COPYING are met. Consult the file for details. * @warning Symbols prefixed with either `RBIMPL` or `rbimpl` are * implementation details. Don't take them as canon. They could * rapidly appear then vanish. The name (path) of this header file * is also an implementation detail. Do not expect it to persist * at the place it is now. Developers are free to move it anywhere * anytime at will. * @note To ruby-core: remember that this header can be possibly * recursively included from extension libraries written in C++. * Do not expect for instance `__VA_ARGS__` is always available. * We assume C99 for ruby itself but we don't assume languages of * extension libraries. They could be written in C++98. * @brief Public APIs related to ::rb_cArray. */ #include "ruby/internal/attr/noalias.h" #include "ruby/internal/attr/noexcept.h" #include "ruby/internal/attr/nonnull.h" #include "ruby/internal/attr/pure.h" #include "ruby/internal/dllexport.h" #include "ruby/internal/value.h" RBIMPL_SYMBOL_EXPORT_BEGIN() /* array.c */ RBIMPL_ATTR_NONNULL(()) RBIMPL_ATTR_NOALIAS() /** * Fills the memory region with a series of ::RUBY_Qnil. * * @param[out] buf Buffer to squash. * @param[in] len Number of objects of `buf`. * @post `buf` is filled with ::RUBY_Qnil. */ void rb_mem_clear(VALUE *buf, long len) RBIMPL_ATTR_NOEXCEPT(true) ; /** * Identical to rb_ary_new_from_values(), except it expects exactly two * parameters. * * @param[in] car Arbitrary ruby object. * @param[in] cdr Arbitrary ruby object. * @return An allocated new array, of length 2, whose contents are the * passed objects. */ VALUE rb_assoc_new(VALUE car, VALUE cdr); /** * Try converting an object to its array representation using its `to_ary` * method, if any. If there is no such thing, returns ::RUBY_Qnil. * * @param[in] obj Arbitrary ruby object to convert. * @exception rb_eTypeError `obj.to_ary` returned something non-Array. * @retval RUBY_Qnil No conversion from `obj` to array defined. * @retval otherwise Converted array representation of `obj`. * @see rb_io_check_io * @see rb_check_string_type * @see rb_check_hash_type */ VALUE rb_check_array_type(VALUE obj); /** * Allocates a new, empty array. * * @return An allocated new array, whose length is 0. */ VALUE rb_ary_new(void); /** * Identical to rb_ary_new(), except it additionally specifies how many rooms * of objects it should allocate. This way you can create an array whose * capacity is bigger than the length of it. If you can say that an array * grows to a specific amount, this could be effective than resizing an array * over and over again and again. * * @param[in] capa Designed capacity of the generating array. * @return An empty array, whose capacity is `capa`. */ VALUE rb_ary_new_capa(long capa); /** * Constructs an array from the passed objects. * * @param[in] n Number of passed objects. * @param[in] ... Arbitrary ruby objects, filled into the returning array. * @return An array of size `n`, whose contents are the passed objects. */ VALUE rb_ary_new_from_args(long n, ...); /** * Identical to rb_ary_new_from_args(), except how objects are passed. * * @param[in] n Number of objects of `elts`. * @param[in] elts Arbitrary ruby objects, filled into the returning array. * @return An array of size `n`, whose contents are the passed objects. */ VALUE rb_ary_new_from_values(long n, const VALUE *elts); /** * Allocates a hidden (no class) empty array. * * @param[in] capa Designed capacity of the array. * @return A hidden, empty array. * @see rb_obj_hide() */ VALUE rb_ary_hidden_new(long capa); #define rb_ary_tmp_new rb_ary_hidden_new /** * Destroys the given array for no reason. * * @warning DO NOT USE IT. * @warning Leave this task to our GC. * @warning It was a wrong indea at the first place to let you know about it. * * @param[out] ary The array to be executed. * @post The given array no longer exists. * @note Maybe `Array#clear` could be what you want. * * @internal * * Should have moved this to `internal/array.h`. */ void rb_ary_free(VALUE ary); /** * Declares that the array is about to be modified. This for instance let the * array have a dedicated backend storage. * * @param[out] ary Array about to be modified. * @exception rb_eFrozenError `ary` is frozen. * @post Upon successful return the passed array is eligible to be * modified. */ void rb_ary_modify(VALUE ary); /** @alias{rb_obj_freeze} */ VALUE rb_ary_freeze(VALUE obj); RBIMPL_ATTR_PURE() /** * Queries if the passed two arrays share the same backend storage. A use-case * for knowing such property is to take a snapshot of an array (using * e.g. rb_ary_replace()), then check later if that snapshot still shares the * storage with the original. Taking a snapshot is ultra-cheap. If nothing * happens the impact shall be minimal. But if someone modifies the original, * that entity shall pay the cost of copy-on-write. You can detect that using * this API. * * @param[in] lhs Comparison LHS. * @param[in] rhs Comparison RHS. * @retval RUBY_Qtrue They share the same backend storage. * @retval RUBY_Qfalse They are distinct. * @pre Both arguments must be of ::RUBY_T_ARRAY. */ VALUE rb_ary_shared_with_p(VALUE lhs, VALUE rhs); /** * Queries element(s) of an array. This is complicated! Refer `Array#slice` * document for the complete description of how it behaves. * * @param[in] argc Number of objects of `argv`. * @param[in] argv Up to 2 objects. * @param[in] ary Target array. * @exception rb_eTypeError `argv` (or its part) includes non-Integer. * @exception rb_eRangeError rb_cArithSeq is passed, and is OOB. * @return An element (if requested), or an array of elements (if * requested), or ::RUBY_Qnil (if index OOB). * * @internal * * ```rbs * # "int" is ::Integer or `#to_int`, defined in builtin.rbs * * class ::Array[unchecked out T] * def slice * : (int i) -> T? * | (int beg, int len) -> ::Array[T]? * | (Range[int] r) -> ::Array[T]? * | (ArithmeticSequence as) -> ::Array[T]? # This also raises RangeError. * end * ``` */ VALUE rb_ary_aref(int argc, const VALUE *argv, VALUE ary); /** * Obtains a part of the passed array. * * @param[in] ary Target array. * @param[in] beg Subpart index. * @param[in] len Requested length of returning array. * @retval RUBY_Qnil Requested range out of bounds of `ary`. * @retval otherwise An allocated new array whose contents are `ary`'s * `beg` to `len`. * @note Return array can be shorter than `len` when for instance * `[0, 1, 2, 3]`'s 4th to 1,000,000,000th is requested. */ VALUE rb_ary_subseq(VALUE ary, long beg, long len); /** * Destructively stores the passed value to the passed array's passed index. * It also resizes the array's backend storage so that the requested index is * not out of bounds. * * @param[out] ary Target array to modify. * @param[in] key Where to store `val`. * @param[in] val What to store at `key`. * @exception rb_eFrozenError `ary` is frozen. * @exception rb_eIndexError `key` is negative. * @post `ary`'s `key`th position is occupied with `val`. * @post Depending on `key` and previous length of `ary` this operation * can also create a series of "hole" positions inside of the * backend storage. They are filled with ::RUBY_Qnil. */ void rb_ary_store(VALUE ary, long key, VALUE val); /** * Duplicates an array. * * @param[in] ary Target to duplicate. * @return An allocated new array whose contents are identical to `ary`. * * @internal * * Not sure why this has to be something different from `ary_make_shared_copy`, * which seems much efficient. */ VALUE rb_ary_dup(VALUE ary); /** * I guess there is no use case of this function in extension libraries, but * this is a routine identical to rb_ary_dup(). This makes the most sense when * the passed array is formerly hidden by rb_obj_hide(). * * @param[in] ary An array, possibly hidden. * @return A duplicated new instance of ::rb_cArray. */ VALUE rb_ary_resurrect(VALUE ary); /** * Force converts an object to an array. It first tries its `#to_ary` method. * Takes the result if any. Otherwise creates an array of size 1 whose sole * element is the passed object. * * @param[in] obj Arbitrary ruby object. * @return An array representation of `obj`. * @note Unlike rb_str_to_str() which is a variant of * rb_check_string_type(), rb_ary_to_ary() is not a variant of * rb_check_array_type(). */ VALUE rb_ary_to_ary(VALUE obj); /** * Converts an array into a human-readable string. Historically its behaviour * changed over time. Currently it is identical to calling `inspect` method. * This behaviour is from that of python (!!) circa 2006. * * @param[in] ary Array to inspect. * @return Recursively inspected representation of `ary`. * @see `[ruby-dev:29520]` */ VALUE rb_ary_to_s(VALUE ary); /** * Destructively appends multiple elements at the end of the array. * * @param[out] ary Where to push `train`. * @param[in] train Arbitrary ruby objects to push to `ary`. * @param[in] len Number of objects of `train`. * @exception rb_eIndexError `len` too large. * @exception rb_eFrozenError `ary` is frozen. * @return The passed `ary`. * @post `ary` has contents from `train` appended at its end. */ VALUE rb_ary_cat(VALUE ary, const VALUE *train, long len); /** * Special case of rb_ary_cat() that it adds only one element. * * @param[out] ary Where to push `elem`. * @param[in] elem Arbitrary ruby object to push. * @exception rb_eFrozenError `ary` is frozen. * @return The passed `ary`. * @post `ary` has `elem` appended at its end. */ VALUE rb_ary_push(VALUE ary, VALUE elem); /** * Destructively deletes an element from the end of the passed array and * returns what was deleted. * * @param[out] ary Target array to modify. * @exception rb_eFrozenError `ary` is frozen. * @return What was at the end of `ary`, or ::RUBY_Qnil if there is * nothing to remove. * @post `ary`'s last element, if any, is removed. * @note There is no way to distinguish whether `ary` was an 1-element * array whose content was ::RUBY_Qnil, or was empty. */ VALUE rb_ary_pop(VALUE ary); /** * Destructively deletes an element from the beginning of the passed array and * returns what was deleted. It can also be seen as a routine identical to * rb_ary_pop(), except which side of the array to scrub. * * @param[out] ary Target array to modify. * @exception rb_eFrozenError `ary` is frozen. * @return What was at the beginning of `ary`, or ::RUBY_Qnil if there is * nothing to remove. * @post `ary`'s first element, if any, is removed. As the name implies * everything else remaining in `ary` gets moved towards `ary`'s * beginning. * @note There is no way to distinguish whether `ary` was an 1-element * array whose content was ::RUBY_Qnil, or was empty. */ VALUE rb_ary_shift(VALUE ary); /** * Destructively prepends the passed item at the beginning of the passed array. * It can also be seen as a routine identical to rb_ary_push(), except which * side of the array to modify. * * @param[out] ary Target array to modify. * @param[in] elem Arbitrary ruby object to unshift. * @exception rb_eFrozenError `ary` is frozen. * @return The passed `ary`. * @post `ary` has `elem` prepended at this beginning. */ VALUE rb_ary_unshift(VALUE ary, VALUE elem); RBIMPL_ATTR_PURE() /** * Queries an element of an array. When passed offset is negative it counts * backwards. * * @param[in] ary An array to look into. * @param[in] off Offset (can be negative). * @return ::RUBY_Qnil when `off` is out of bounds of `ary`. Otherwise * what is stored at `off`-th position of `ary`. * @note `ary`'s `off`-th element can happen to be ::RUBY_Qnil. */ VALUE rb_ary_entry(VALUE ary, long off); /** * Iteratively yields each element of the passed array to the implicitly passed * block if any. In case there is no block given, an enumerator that does the * thing is generated instead. * * @param[in] ary Array to iterate over. * @retval ary Passed block was evaluated. * @retval otherwise An instance of ::rb_cEnumerator for `Array#each`. */ VALUE rb_ary_each(VALUE ary); /** * Recursively stringises the elements of the passed array, flattens that * result, then joins the sequence using the passed separator. * * @param[in] ary Target array to convert. * @param[in] sep Separator. Either a string, or ::RUBY_Qnil * if you want no separator. * @exception rb_eArgError Infinite recursion in `ary`. * @exception rb_eTypeError `sep` is not a string. * @exception rb_eEncCompatError Strings do not agree with their encodings. * @return An instance of ::rb_cString which concatenates stringised * contents of `ary`, using `sep` as separator. */ VALUE rb_ary_join(VALUE ary, VALUE sep); /** * _Destructively_ reverses the passed array in-place. * * @warning This is `Array#reverse!`, not `Array#reverse`. * @param[out] ary Target array to modify. * @exception rb_eFrozenError `ary` is frozen. * @return Passed `ary`. * @post `ary` is reversed. */ VALUE rb_ary_reverse(VALUE ary); /** * _Destructively_ rotates the passed array in-place to towards its end. The * amount can be negative. Would rotate to the opposite direction then. * * @warning This is `Array#rotate!`, not `Array#rotate`. * @param[out] ary Target array to modify. * @param[in] rot Amount of rotation. * @exception rb_eFrozenError `ary` is frozen. * @retval RUBY_Qnil Not rotated. * @retval ary Rotated. * @post `ary` is rotated. */ VALUE rb_ary_rotate(VALUE ary, long rot); /** * Creates a copy of the passed array, whose elements are sorted according to * their `<=>` result. * * @param[in] ary Array to sort. * @exception rb_eArgError Comparison not defined among elements. * @exception rb_eRuntimeError Infinite recursion in `<=>`. * @return A copy of `ary`, sorted. * @note As of writing this function uses `qsort` as backend algorithm, * which means the result is unstable (in terms of sort stability). */ VALUE rb_ary_sort(VALUE ary); /** * Destructively sorts the passed array in-place, according to each elements' * `<=>` result. * * @param[in] ary Target array to modify. * @exception rb_eArgError Comparison not defined among elements. * @exception rb_eRuntimeError Infinite recursion in `<=>`. * @return Passed `ary`. * @post `ary` is sorted. * @note As of writing this function uses `qsort` as backend algorithm, * which means the result is unstable (in terms of sort stability). */ VALUE rb_ary_sort_bang(VALUE ary); /** * Destructively removes elements from the passed array, so that there would be * no elements inside that satisfy `==` relationship with the passed object. * Returns the last deleted element if any. But in case there was nothing to * delete it gets complicated. It checks for the implicitly passed block. If * there is a block the return value would be what the block evaluates to. * Otherwise it resorts to ::RUBY_Qnil. * * @param[out] ary Target array to modify. * @param[in] elem Template object to match against each element. * @exception rb_eFrozenError `ary` is frozen. * @return What was deleted, or what was the block returned, or * ::RUBY_Qnil (see above). * @post All elements that have `==` relationship with `elem` are purged * from `ary`. Elements shift their positions so that `ary` gets * compact. * * @internal * * Internally there also is `rb_ary_delete_same`, which compares by identity. */ VALUE rb_ary_delete(VALUE ary, VALUE elem); /** * Destructively removes an element which resides at the specific index of the * passed array. Unlike rb_ary_stre() the index can be negative, which means * the index counts backwards from the array's tail. * * @param[out] ary Target array to modify. * @param[in] pos Position (can be negative). * @exception rb_eFrozenError `ary` is frozen. * @return What was deleted, or ::RUBY_Qnil in case of OOB. * @post `ary`'s `pos`-th element is deleted if any. * @note There is no way to distinguish whether `pos` is out of bound, * or `pos` did exist but stored ::RUBY_Qnil as an ordinal value. */ VALUE rb_ary_delete_at(VALUE ary, long pos); /** * Destructively removes everything form an array. * * @param[out] ary Target array to modify. * @exception rb_eFrozenError `ary` is frozen. * @return The passed `ary`. * @post `ary` is an empty array. */ VALUE rb_ary_clear(VALUE ary); /** * Creates a new array, concatenating the former to the latter. * * @param[in] lhs Source array #1. * @param[in] rhs Source array #2. * @exception rb_eIndexError Result array too big. * @return A new array containing `rhs` concatenated to `lhs`. * @note This operation doesn't commute. Don't get confused by the * "plus" terminology. For historical reasons there are some * noncommutative `+`s in Ruby. This is one of such things. There * has been a long discussion around `+`s in programming languages. * * @internal * * rb_ary_concat() is not a destructive version of rb_ary_plus(). They raise * different exceptions. Don't know why though. */ VALUE rb_ary_plus(VALUE lhs, VALUE rhs); /** * Destructively appends the contents of latter into the end of former. * * @param[out] lhs Destination array. * @param[in] rhs Source array. * @exception rb_eFrozenError `lhs` is frozen. * @exception rb_eIndexError Result array too big. * @exception rb_eTypeError `rhs` doesn't respond to `#to_ary`. * @return The passed `lhs`. * @post `lhs` has contents of `rhs` appended to its end. */ VALUE rb_ary_concat(VALUE lhs, VALUE rhs); /** * Looks up the passed key, assuming the passed array is an alist. An "alist" * here is a list of "association"s, much like that of Emacs. Emacs has * `assoc` function that behaves exactly the same as this one. * * ```ruby * # This is an example of aliist. * auto_mode_alist = [ * [ /\.[ch]\z/, :"c-mode" ], * [ /\.[ch]pp\z/, :"c++-mode" ], * [ /\.awk\z/, :"awk-mode" ], * [ /\.cs\z/, :"csharp-mode" ], * [ /\.go\z/, :"go-mode" ], * [ /\.java\z/, :"java-mode" ], * [ /\.pas\z/, :"pascal-mode" ], * [ /\.rs\z/, :"rust-mode" ], * [ /\.txt\z/, :"text-mode" ], * ] * ``` * * This function scans the passed array looking for an element, which itself is * an array, whose first element is the passed key. If no such element is * found, returns ::RUBY_Qnil. * * Although this function expects the passed array be an array of arrays, it * can happily accept non-array elements; it just ignores such things. * * @param[in] alist An array of arrays. * @param[in] key Needle. * @retval RUBY_Qnil Nothing was found. * @retval otherwise An element in `alist` whose first element is in `==` * relationship with `key`. */ VALUE rb_ary_assoc(VALUE alist, VALUE key); /** * Identical to rb_ary_assoc(), except it scans the passed array from the * opposite direction. * * @param[in] alist An array of arrays. * @param[in] key Needle. * @retval RUBY_Qnil Nothing was found. * @retval otherwise An element in `alist` whose first element is in `==` * relationship with `key`. */ VALUE rb_ary_rassoc(VALUE alist, VALUE key); /** * Queries if the passed array has the passed entry. * * @param[in] ary Target array to scan. * @param[in] elem Target array to find. * @retval RUBY_Qfalse No element in `ary` is in `==` relationship with * `elem`. * @retval RUBY_Qtrue There is at least one element in `ary` which is in * `==` relationship with `elem`. * * @internal * * This is the only function in the entire C API that is named using third * person singular form of a verb (except #ISASCII etc., which are not our * naming). The counterpart Ruby API of this function is `Array#include?`. */ VALUE rb_ary_includes(VALUE ary, VALUE elem); /** * Recursively compares each elements of the two arrays one-by-one using `<=>`. * * @param[in] lhs Comparison LHS. * @param[in] rhs Comparison RHS. * @retval RUBY_Qnil `lhs` and `rhs` are not comparable. * @retval -1 `lhs` is less than `rhs`. * @retval 0 They are equal. * @retval 1 `rhs` is less then `lhs`. */ VALUE rb_ary_cmp(VALUE lhs, VALUE rhs); /** * Replaces the contents of the former object with the contents of the latter. * * @param[out] copy Destination object. * @param[in] orig Source object. * @exception rb_eTypeError `orig` has no implicit conversion to Array. * @exception rb_eFrozenError `copy` is frozen. * @return The passed `copy`. * @post `copy`'s former components are abandoned. It now has the * identical length and contents to `orig`. */ VALUE rb_ary_replace(VALUE copy, VALUE orig); /** * This _was_ a generalisation of `Array#values_at`, `Struct#values_at`, and * `MatchData#values_at`. It begun its life as a refactoring effort. However * as Ruby evolves over time, as of writing none of aforementioned methods * share their implementations at all. This function is not deprecated; still * works as it has been. But it is now kind of like a rudimentum. * * This function takes an object, which is a receiver, and a series of * "indices", which are either integers, or ranges of integers. Calls the * passed callback for each of those indices, along with the receiver. This * callback is expected to do something like rb_ary_aref(), rb_struct_aref(), * etc. In case of a range index rb_range_beg_len() expands the range. * Finally return values of the callback are gathered as an array, then * returned. * * @param[in] obj Arbitrary ruby object. * @param[in] olen "Length" of `obj`. * @param[in] argc Number of objects of `argv`. * @param[in] argv List of "indices", described above. * @param[in] func Callback function. * @return A new instance of ::rb_cArray gathering `func`outputs. * * @internal * * `Array#values_at` no longer uses this function. There is no reason apart * from historical ones to list this function here. */ VALUE rb_get_values_at(VALUE obj, long olen, int argc, const VALUE *argv, VALUE (*func)(VALUE obj, long oidx)); /** * Expands or shrinks the passed array to the passed length. * * @param[out] ary An array to modify. * @param[in] len Desired length of `ary`. * @exception rb_eFrozenError `ary` is frozen. * @exception rb_eIndexError `len` too long. * @return The passed `ary`. * @post `ary`'s length is `len`. * @post Depending on `len` and previous length of `ary` this operation * can also create a series of "hole" positions inside of the * backend storage. They are filled with ::RUBY_Qnil. * * @internal * * `len` is signed. Intentional or...? */ VALUE rb_ary_resize(VALUE ary, long len); #define rb_ary_new2 rb_ary_new_capa /**< @old{rb_ary_new_capa} */ #define rb_ary_new3 rb_ary_new_from_args /**< @old{rb_ary_new_from_args} */ #define rb_ary_new4 rb_ary_new_from_values /**< @old{rb_ary_new_from_values} */ RBIMPL_SYMBOL_EXPORT_END() #endif /* RBIMPL_INTERN_ARRAY_H */ include/ruby/internal/intern/marshal.h 0000644 00000012712 15152150473 0014071 0 ustar 00 #ifndef RBIMPL_INTERN_MARSHAL_H /*-*-C++-*-vi:se ft=cpp:*/ #define RBIMPL_INTERN_MARSHAL_H /** * @file * @author Ruby developers <ruby-core@ruby-lang.org> * @copyright This file is a part of the programming language Ruby. * Permission is hereby granted, to either redistribute and/or * modify this file, provided that the conditions mentioned in the * file COPYING are met. Consult the file for details. * @warning Symbols prefixed with either `RBIMPL` or `rbimpl` are * implementation details. Don't take them as canon. They could * rapidly appear then vanish. The name (path) of this header file * is also an implementation detail. Do not expect it to persist * at the place it is now. Developers are free to move it anywhere * anytime at will. * @note To ruby-core: remember that this header can be possibly * recursively included from extension libraries written in C++. * Do not expect for instance `__VA_ARGS__` is always available. * We assume C99 for ruby itself but we don't assume languages of * extension libraries. They could be written in C++98. * @brief Public APIs related to rb_mMarshal. */ #include "ruby/internal/dllexport.h" #include "ruby/internal/value.h" RBIMPL_SYMBOL_EXPORT_BEGIN() /* marshal.c */ /** * Serialises the given object and all its referring objects, to write them * down to the passed port. * * @param[in] obj Target object to dump. * @param[out] port IO-like destination buffer. * @exception rb_eTypeError `obj` cannot be dumped for some reason. * @exception rb_eRuntimeError `obj` was tampered during dumping. * @exception rb_eArgError Traversal too deep. * @return The passed `port` as-is. * @post Serialised representation of `obj` is written to `port`. * @note `port` is basically an IO but StringIO is also possible. */ VALUE rb_marshal_dump(VALUE obj, VALUE port); /** * Deserialises a previous output of rb_marshal_dump() into a network of * objects. * * @param[in,out] port Either IO or String. * @exception rb_eTypeError `port` is in unexpected type. * @exception rb_eArgError Contents of `port` is broken. * @return Object(s) rebuilt using the info from `port`. * * SECURITY CONSIDERATIONS * ======================== * * @warning By design, rb_marshal_load() can deserialise almost any * class loaded into the Ruby process. In many cases this can * lead to remote code execution if the Marshal data is loaded * from an untrusted source. * @warning As a result, rb_marshal_load() is not suitable as a general * purpose serialisation format and you should never unmarshal * user supplied input or other untrusted data. * @warning If you need to deserialise untrusted data, use JSON or * another serialisation format that is only able to load * simple, 'primitive' types such as String, Array, Hash, etc. * Never allow user input to specify arbitrary types to * deserialise into. */ VALUE rb_marshal_load(VALUE port); /** * Marshal format compatibility layer. Over time, classes evolve, so that * their internal data structure change drastically. For instance an instance * of ::rb_cRange was made of ::RUBY_T_OBJECT in 1.x., but in 3.x it is a * ::RUBY_T_STRUCT now. In order to keep binary compatibility, we "fake" the * marshalled representation to stick to old types. This is the API to enable * that manoeuvre. Here is how: * * First, because you are going to keep backwards compatibility, you need to * retain the old implementation of your class. Rename it, and keep the class * somewhere (for instance rb_register_global_address() could help). Next * create your new class. Do whatever you want. * * Then, this is the key point. Create two new "bridge" functions that convert * the structs back and forth: * * - the "dumper" function that takes an instance of the new class, and * returns an instance of the old one. This is called from * rb_marshal_dump(), to keep it possible for old programs to read your new * data. * * - the "loader" function that takes two arguments, new one and old one, in * that order. rb_marshal_load() calls this function when it finds a * representation of the retained old class. The old one passed to this * function is the reconstructed instance of the old class. * Reverse-engineer that to modify the new one, to have the identical * contents. * * Finally, connect all of them using this function. * * @param[in] newclass The class that needs conversion. * @param[in] oldclass Old implementation of `newclass`. * @param[in] dumper Function that converts `newclass` to `oldclass`. * @param[in] loader Function that converts `oldclass` to `newclass`. * @exception rb_eTypeError `newclass` has no allocator. */ void rb_marshal_define_compat(VALUE newclass, VALUE oldclass, VALUE (*dumper)(VALUE), VALUE (*loader)(VALUE, VALUE)); RBIMPL_SYMBOL_EXPORT_END() #endif /* RBIMPL_INTERN_MARSHAL_H */ include/ruby/internal/intern/complex.h 0000644 00000020326 15152150473 0014111 0 ustar 00 #ifndef RBIMPL_INTERN_COMPLEX_H /*-*-C++-*-vi:se ft=cpp:*/ #define RBIMPL_INTERN_COMPLEX_H /** * @file * @author Ruby developers <ruby-core@ruby-lang.org> * @copyright This file is a part of the programming language Ruby. * Permission is hereby granted, to either redistribute and/or * modify this file, provided that the conditions mentioned in the * file COPYING are met. Consult the file for details. * @warning Symbols prefixed with either `RBIMPL` or `rbimpl` are * implementation details. Don't take them as canon. They could * rapidly appear then vanish. The name (path) of this header file * is also an implementation detail. Do not expect it to persist * at the place it is now. Developers are free to move it anywhere * anytime at will. * @note To ruby-core: remember that this header can be possibly * recursively included from extension libraries written in C++. * Do not expect for instance `__VA_ARGS__` is always available. * We assume C99 for ruby itself but we don't assume languages of * extension libraries. They could be written in C++98. * @brief Public APIs related to ::rb_cComplex. */ #include "ruby/internal/attr/deprecated.h" #include "ruby/internal/attr/pure.h" #include "ruby/internal/dllexport.h" #include "ruby/internal/value.h" #include "ruby/internal/arithmetic/long.h" /* INT2FIX is here. */ RBIMPL_SYMBOL_EXPORT_BEGIN() /* complex.c */ /** * Identical to rb_complex_new(), except it assumes both arguments are not * instances of ::rb_cComplex. It is thus dangerous for extension libraries. * * @param[in] real Real part, in any numeric except Complex. * @param[in] imag Imaginary part, in any numeric except Complex. * @return An instance of ::rb_cComplex whose value is `real + (imag)i`. */ VALUE rb_complex_raw(VALUE real, VALUE imag); /** * Shorthand of `x+0i`. It practically converts `x` into a Complex of the * identical value. * * @param[in] x Any numeric except Complex. * @return An instance of ::rb_cComplex, whose value is `x + 0i`. */ #define rb_complex_raw1(x) rb_complex_raw((x), INT2FIX(0)) /** @alias{rb_complex_raw} */ #define rb_complex_raw2(x,y) rb_complex_raw((x), (y)) /** * Constructs a Complex, by first multiplying the imaginary part with `1i` then * adds it to the real part. This definition doesn't need both arguments be * real numbers. It can happily combine two instances of ::rb_cComplex (with * rotating the latter one). * * @param[in] real An instance of ::rb_cNumeric. * @param[in] imag Another instance of ::rb_cNumeric. * @return An instance of ::rb_cComplex whose value is `imag * 1i + real`. */ VALUE rb_complex_new(VALUE real, VALUE imag); /** * Shorthand of `x+0i`. It practically converts `x` into a Complex of the * identical value. * * @param[in] x Any numeric value. * @return An instance of ::rb_cComplex, whose value is `x + 0i`. */ #define rb_complex_new1(x) rb_complex_new((x), INT2FIX(0)) /** @alias{rb_complex_new} */ #define rb_complex_new2(x,y) rb_complex_new((x), (y)) /** * Constructs a Complex using polar representations. Unlike rb_complex_new() * it makes no sense to pass non-real instances to this function. * * @param[in] abs Magnitude, in any numeric except Complex. * @param[in] arg Angle, in radians, in any numeric except Complex. * @return An instance of ::rb_cComplex which denotes the given polar * coordinates. */ VALUE rb_complex_new_polar(VALUE abs, VALUE arg); RBIMPL_ATTR_DEPRECATED(("by: rb_complex_new_polar")) /** @old{rb_complex_new_polar} */ VALUE rb_complex_polar(VALUE abs, VALUE arg); RBIMPL_ATTR_PURE() /** * Queries the real part of the passed Complex. * * @param[in] z An instance of ::rb_cComplex. * @return Its real part, which is an instance of ::rb_cNumeric. */ VALUE rb_complex_real(VALUE z); RBIMPL_ATTR_PURE() /** * Queries the imaginary part of the passed Complex. * * @param[in] z An instance of ::rb_cComplex. * @return Its imaginary part, which is an instance of ::rb_cNumeric. */ VALUE rb_complex_imag(VALUE z); /** * Performs addition of the passed two objects. * * @param[in] x An instance of ::rb_cComplex. * @param[in] y Arbitrary ruby object. * @return What `x + y` evaluates to. * @see rb_num_coerce_bin() */ VALUE rb_complex_plus(VALUE x, VALUE y); /** * Performs subtraction of the passed two objects. * * @param[in] x An instance of ::rb_cComplex. * @param[in] y Arbitrary ruby object. * @return What `x - y` evaluates to. * @see rb_num_coerce_bin() */ VALUE rb_complex_minus(VALUE x, VALUE y); /** * Performs multiplication of the passed two objects. * * @param[in] x An instance of ::rb_cComplex. * @param[in] y Arbitrary ruby object. * @return What `x * y` evaluates to. * @see rb_num_coerce_bin() */ VALUE rb_complex_mul(VALUE x, VALUE y); /** * Performs division of the passed two objects. * * @param[in] x An instance of ::rb_cComplex. * @param[in] y Arbitrary ruby object. * @return What `x / y` evaluates to. * @see rb_num_coerce_bin() */ VALUE rb_complex_div(VALUE x, VALUE y); /** * Performs negation of the passed object. * * @param[in] z An instance of ::rb_cComplex. * @return What `-z` evaluates to. */ VALUE rb_complex_uminus(VALUE z); /** * Performs complex conjugation of the passed object. * * @param[in] z An instance of ::rb_cComplex. * @return Its complex conjugate, in ::rb_cComplex. */ VALUE rb_complex_conjugate(VALUE z); /** * Queries the absolute (or the magnitude) of the passed object. * * @param[in] z An instance of ::rb_cComplex. * @return Its magnitude, in ::rb_cFloat. */ VALUE rb_complex_abs(VALUE z); /** * Queries the argument (or the angle) of the passed object. * * @param[in] z An instance of ::rb_cComplex. * @return Its magnitude, in ::rb_cFloat. */ VALUE rb_complex_arg(VALUE z); /** * Performs exponentiation of the passed two objects. * * @param[in] base An instance of ::rb_cComplex. * @param[in] exp Arbitrary ruby object. * @return What `base ** exp` evaluates to. * @see rb_num_coerce_bin() */ VALUE rb_complex_pow(VALUE base, VALUE exp); /** * Identical to rb_complex_new(), except it takes the arguments as C's double * instead of Ruby's object. * * @param[in] real Real part. * @param[in] imag Imaginary part. * @return An instance of ::rb_cComplex whose value is `real + (imag)i`. */ VALUE rb_dbl_complex_new(double real, double imag); /** @alias{rb_complex_plus} */ #define rb_complex_add rb_complex_plus /** @alias{rb_complex_minus} */ #define rb_complex_sub rb_complex_minus /** @alias{rb_complex_uminus} */ #define rb_complex_nagate rb_complex_uminus /** * Converts various values into a Complex. This function accepts: * * - Instances of ::rb_cComplex (taken as-is), * - Instances of ::rb_cNumeric (adds `0i`), * - Instances of ::rb_cString (parses), * - Other objects that respond to `#to_c`. * * It (possibly recursively) applies `#to_c` until both sides become a Complex * value, then computes `imag * 1i + real`. * * As a special case, passing ::RUBY_Qundef to `imag` is the same as passing * `RB_INT2NUM(0)`. * * @param[in] real Real part (see above). * @param[in] imag Imaginary part (see above). * @exception rb_eTypeError Passed something not described above. * @return An instance of ::rb_cComplex whose value is `1i * imag + real`. * * @internal * * This was the implementation of `Kernel#Complex` before, but they diverged. */ VALUE rb_Complex(VALUE real, VALUE imag); /** * Shorthand of `x+0i`. It practically converts `x` into a Complex of the * identical value. * * @param[in] x ::rb_cNumeric, ::rb_cString, or something that responds to * `#to_c`. * @return An instance of ::rb_cComplex, whose value is `x + 0i`. */ #define rb_Complex1(x) rb_Complex((x), INT2FIX(0)) /** @alias{rb_Complex} */ #define rb_Complex2(x,y) rb_Complex((x), (y)) RBIMPL_SYMBOL_EXPORT_END() #endif /* RBIMPL_INTERN_COMPLEX_H */ include/ruby/internal/intern/select/posix.h 0000644 00000010335 15152150473 0015062 0 ustar 00 #ifndef RBIMPL_INTERN_SELECT_POSIX_H /*-*-C++-*-vi:se ft=cpp:*/ #define RBIMPL_INTERN_SELECT_POSIX_H /** * @file * @author Ruby developers <ruby-core@ruby-lang.org> * @copyright This file is a part of the programming language Ruby. * Permission is hereby granted, to either redistribute and/or * modify this file, provided that the conditions mentioned in the * file COPYING are met. Consult the file for details. * @warning Symbols prefixed with either `RBIMPL` or `rbimpl` are * implementation details. Don't take them as canon. They could * rapidly appear then vanish. The name (path) of this header file * is also an implementation detail. Do not expect it to persist * at the place it is now. Developers are free to move it anywhere * anytime at will. * @note To ruby-core: remember that this header can be possibly * recursively included from extension libraries written in C++. * Do not expect for instance `__VA_ARGS__` is always available. * We assume C99 for ruby itself but we don't assume languages of * extension libraries. They could be written in C++98. * @brief Public APIs to provide ::rb_fd_select(). */ #include "ruby/internal/config.h" #ifdef HAVE_SYS_SELECT_H # include <sys/select.h> /* for select(2) (modern POSIX) */ #endif #ifdef HAVE_UNISTD_H # include <unistd.h> /* for select(2) (archaic UNIX) */ #endif #include "ruby/internal/attr/const.h" #include "ruby/internal/attr/noalias.h" #include "ruby/internal/attr/nonnull.h" #include "ruby/internal/attr/pure.h" /** * The data structure which wraps the fd_set bitmap used by `select(2)`. This * allows Ruby to use FD sets larger than what has been historically allowed on * modern platforms. * * @internal * * ... but because this header file is included only when the system is with * that "historic restrictions", this is nothing more than an alias of fd_set. */ typedef fd_set rb_fdset_t; /** Clears the given ::rb_fdset_t. */ #define rb_fd_zero FD_ZERO /** Sets the given fd to the ::rb_fdset_t. */ #define rb_fd_set FD_SET /** Unsets the given fd from the ::rb_fdset_t. */ #define rb_fd_clr FD_CLR /** Queries if the given fd is in the ::rb_fdset_t. */ #define rb_fd_isset FD_ISSET /** Initialises the :given :rb_fdset_t. */ #define rb_fd_init FD_ZERO /** Waits for multiple file descriptors at once. */ #define rb_fd_select select /**@cond INTERNAL_MACRO */ #define rb_fd_copy rb_fd_copy #define rb_fd_dup rb_fd_dup #define rb_fd_ptr rb_fd_ptr #define rb_fd_max rb_fd_max /** @endcond */ RBIMPL_ATTR_NONNULL(()) RBIMPL_ATTR_NOALIAS() /** * Destructively overwrites an fdset with another. * * @param[out] dst Target fdset. * @param[in] src Source fdset. * @param[in] n Unused parameter. * @post `dst` is a copy of `src`. */ static inline void rb_fd_copy(rb_fdset_t *dst, const fd_set *src, int n) { *dst = *src; } RBIMPL_ATTR_NONNULL(()) RBIMPL_ATTR_NOALIAS() /** * Destructively overwrites an fdset with another. * * @param[out] dst Target fdset. * @param[in] src Source fdset. * @post `dst` is a copy of `src`. */ static inline void rb_fd_dup(rb_fdset_t *dst, const fd_set *src) { *dst = *src; } RBIMPL_ATTR_PURE() /* :TODO: can this function be __attribute__((returns_nonnull)) or not? */ /** * Raw pointer to `fd_set`. * * @param[in] f Target fdset. * @return Underlying fd_set. * * @internal * * Extension library must not touch raw pointers. It was a bad idea to let * them use it. */ static inline fd_set * rb_fd_ptr(rb_fdset_t *f) { return f; } RBIMPL_ATTR_CONST() /** * It seems this function has no use. Maybe just remove? * * @param[in] f A set. * @return Number of file descriptors stored. */ static inline int rb_fd_max(const rb_fdset_t *f) { return FD_SETSIZE; } /** @cond INTERNAL_MACRO */ /* :FIXME: What are these? They don't exist for sibling implementations. */ #define rb_fd_init_copy(d, s) (*(d) = *(s)) #define rb_fd_term(f) ((void)(f)) /** @endcond */ #endif /* RBIMPL_INTERN_SELECT_POSIX_H */ include/ruby/internal/intern/select/largesize.h 0000644 00000015750 15152150473 0015713 0 ustar 00 #ifndef RBIMPL_INTERN_SELECT_LARGESIZE_H /*-*-C++-*-vi:se ft=cpp:*/ #define RBIMPL_INTERN_SELECT_LARGESIZE_H /** * @file * @author Ruby developers <ruby-core@ruby-lang.org> * @copyright This file is a part of the programming language Ruby. * Permission is hereby granted, to either redistribute and/or * modify this file, provided that the conditions mentioned in the * file COPYING are met. Consult the file for details. * @warning Symbols prefixed with either `RBIMPL` or `rbimpl` are * implementation details. Don't take them as canon. They could * rapidly appear then vanish. The name (path) of this header file * is also an implementation detail. Do not expect it to persist * at the place it is now. Developers are free to move it anywhere * anytime at will. * @note To ruby-core: remember that this header can be possibly * recursively included from extension libraries written in C++. * Do not expect for instance `__VA_ARGS__` is always available. * We assume C99 for ruby itself but we don't assume languages of * extension libraries. They could be written in C++98. * @brief Public APIs to provide ::rb_fd_select(). * * Several Unix platforms support file descriptors bigger than FD_SETSIZE in * `select(2)` system call. * * - Linux 2.2.12 (?) * * - NetBSD 1.2 (src/sys/kern/sys_generic.c:1.25) * `select(2)` documents how to allocate fd_set dynamically. * http://netbsd.gw.com/cgi-bin/man-cgi?select++NetBSD-4.0 * * - FreeBSD 2.2 (src/sys/kern/sys_generic.c:1.19) * * - OpenBSD 2.0 (src/sys/kern/sys_generic.c:1.4) * `select(2)` documents how to allocate fd_set dynamically. * http://www.openbsd.org/cgi-bin/man.cgi?query=select&manpath=OpenBSD+4.4 * * - Solaris 8 has `select_large_fdset` * * - Mac OS X 10.7 (Lion) * `select(2)` returns `EINVAL` if `nfds` is greater than `FD_SET_SIZE` and * `_DARWIN_UNLIMITED_SELECT` (or `_DARWIN_C_SOURCE`) isn't defined. * http://developer.apple.com/library/mac/#releasenotes/Darwin/SymbolVariantsRelNotes/_index.html * * When `fd_set` is not big enough to hold big file descriptors, it should be * allocated dynamically. Note that this assumes `fd_set` is structured as * bitmap. * * `rb_fd_init` allocates the memory. * `rb_fd_term` frees the memory. * `rb_fd_set` may re-allocate bitmap. * * So `rb_fd_set` doesn't reject file descriptors bigger than `FD_SETSIZE`. */ #include "ruby/internal/attr/nonnull.h" #include "ruby/internal/attr/pure.h" #include "ruby/internal/dllexport.h" /**@cond INTERNAL_MACRO */ #define rb_fd_ptr rb_fd_ptr #define rb_fd_max rb_fd_max /** @endcond */ struct timeval; /** * The data structure which wraps the fd_set bitmap used by select(2). This * allows Ruby to use FD sets larger than that allowed by historic limitations * on modern platforms. */ typedef struct { int maxfd; /**< Maximum allowed number of FDs. */ fd_set *fdset; /**< File descriptors buffer */ } rb_fdset_t; RBIMPL_SYMBOL_EXPORT_BEGIN() RBIMPL_ATTR_NONNULL(()) /** * (Re-)initialises a fdset. One must be initialised before other `rb_fd_*` * operations. Analogous to calling `malloc(3)` to allocate an `fd_set`. * * @param[out] f An fdset to squash. * @post `f` holds no file descriptors. */ void rb_fd_init(rb_fdset_t *f); RBIMPL_ATTR_NONNULL(()) /** * Destroys the ::rb_fdset_t, releasing any memory and resources it used. It * must be reinitialised using rb_fd_init() before future use. Analogous to * calling `free(3)` to release memory for an `fd_set`. * * @param[out] f An fdset to squash. * @post `f` holds no file descriptors. */ void rb_fd_term(rb_fdset_t *f); RBIMPL_ATTR_NONNULL(()) /** * Wipes out the current set of FDs. * * @param[out] f The fdset to clear. * @post `f` has no FDs. */ void rb_fd_zero(rb_fdset_t *f); RBIMPL_ATTR_NONNULL(()) /** * Sets an fd to a fdset. * * @param[in] fd A file descriptor. * @param[out] f Target fdset. * @post `f` holds `fd`. */ void rb_fd_set(int fd, rb_fdset_t *f); RBIMPL_ATTR_NONNULL(()) /** * Releases a specific FD from the given fdset. * * @param[in] fd Target FD. * @param[out] f The fdset that holds `fd`. * @post `f` doesn't hold n. */ void rb_fd_clr(int fd, rb_fdset_t *f); RBIMPL_ATTR_NONNULL(()) RBIMPL_ATTR_PURE() /** * Queries if the given FD is in the given set. * * @param[in] fd Target FD. * @param[in] f The fdset to scan. * @retval 1 Yes there is. * @retval 0 No there isn't. * @see http://www.freebsd.org/cgi/query-pr.cgi?pr=91421 */ int rb_fd_isset(int fd, const rb_fdset_t *f); /** * Destructively overwrites an fdset with another. * * @param[out] dst Target fdset. * @param[in] src Source fdset. * @param[in] max Maximum number of file descriptors to copy. * @post `dst` is a copy of `src`. */ void rb_fd_copy(rb_fdset_t *dst, const fd_set *src, int max); /** * Identical to rb_fd_copy(), except it copies unlimited number of file * descriptors. * * @param[out] dst Target fdset. * @param[in] src Source fdset. * @post `dst` is a copy of `src`. */ void rb_fd_dup(rb_fdset_t *dst, const rb_fdset_t *src); /** * Waits for multiple file descriptors at once. * * @param[in] nfds Max FD in everything passed, plus one. * @param[in,out] rfds Set of FDs to wait for reads. * @param[in,out] wfds Set of FDs to wait for writes. * @param[in,out] efds Set of FDs to wait for OOBs. * @param[in,out] timeout Max blocking duration. * @retval -1 Failed, errno set. * @retval 0 Timeout exceeded. * @retval otherwise Total number of file descriptors returned. * @post `rfds` contains readable FDs. * @post `wfds` contains writable FDs. * @post `efds` contains exceptional FDs. * @post `timeout` is the time left. * @note All pointers are allowed to be null pointers. */ int rb_fd_select(int nfds, rb_fdset_t *rfds, rb_fdset_t *wfds, rb_fdset_t *efds, struct timeval *timeout); RBIMPL_SYMBOL_EXPORT_END() RBIMPL_ATTR_NONNULL(()) RBIMPL_ATTR_PURE() /** * Raw pointer to `fd_set`. * * @param[in] f Target fdset. * @retval NULL `f` is already terminated by rb_fd_term(). * @retval otherwise Underlying fd_set. * * @internal * * Extension library must not touch raw pointers. It was a bad idea to let * them use it. */ static inline fd_set * rb_fd_ptr(const rb_fdset_t *f) { return f->fdset; } RBIMPL_ATTR_NONNULL(()) RBIMPL_ATTR_PURE() /** * It seems this function has no use. Maybe just remove? * * @param[in] f A set. * @return Number of file descriptors stored. */ static inline int rb_fd_max(const rb_fdset_t *f) { return f->maxfd; } #endif /* RBIMPL_INTERN_SELECT_LARGESIZE_H */ include/ruby/internal/intern/eval.h 0000644 00000020770 15152150473 0013374 0 ustar 00 #ifndef RBIMPL_INTERN_EVAL_H /*-*-C++-*-vi:se ft=cpp:*/ #define RBIMPL_INTERN_EVAL_H /** * @file * @author Ruby developers <ruby-core@ruby-lang.org> * @copyright This file is a part of the programming language Ruby. * Permission is hereby granted, to either redistribute and/or * modify this file, provided that the conditions mentioned in the * file COPYING are met. Consult the file for details. * @warning Symbols prefixed with either `RBIMPL` or `rbimpl` are * implementation details. Don't take them as canon. They could * rapidly appear then vanish. The name (path) of this header file * is also an implementation detail. Do not expect it to persist * at the place it is now. Developers are free to move it anywhere * anytime at will. * @note To ruby-core: remember that this header can be possibly * recursively included from extension libraries written in C++. * Do not expect for instance `__VA_ARGS__` is always available. * We assume C99 for ruby itself but we don't assume languages of * extension libraries. They could be written in C++98. * @brief Pre-1.9 era evaluator APIs (now considered miscellaneous). */ #include "ruby/internal/attr/noreturn.h" #include "ruby/internal/dllexport.h" #include "ruby/internal/value.h" RBIMPL_SYMBOL_EXPORT_BEGIN() /* eval.c */ RBIMPL_ATTR_NORETURN() /** * Identical to rb_raise(), except it raises the passed exception instance as- * is instead of creating new one. * * @param[in] exc An instance of a subclass of ::rb_eException. * @exception exc What is passed. * @exception rb_eTypeError `exc` is not an exception. * @note It never returns. * * @internal * * Wellll actually, it can take more than what is described above. This * function tries to call `exception` method of the passed object. If that * function returns an exception object that is used instead. */ void rb_exc_raise(VALUE exc); RBIMPL_ATTR_NORETURN() /** * Identical to rb_fatal(), except it raises the passed exception instance as- * is instead of creating new one. * * @param[in] exc An instance of a subclass of ::rb_eException. * @exception exc What is passed. * @note It never returns. * * @internal * * You know what...? Using this API you can make arbitrary exceptions, like * `RuntimeError`, that doesn't interface with `rescue` clause. This is very * confusing. */ void rb_exc_fatal(VALUE exc); /* process.c */ RBIMPL_ATTR_NORETURN() /** * Identical to rb_exit(), except how arguments are passed. * * @param[in] argc Number of objects of `argv`. * @param[in] argv Contains at most one of the following: * - ::RUBY_Qtrue - means `EXIT_SUCCESS`. * - ::RUBY_Qfalse - means `EXIT_FAILURE`. * - Numerical value - takes that value. * @exception rb_eArgError Wrong `argc`. * @exception rb_eSystemExit Exception representing the exit status. * @note It never returns. */ VALUE rb_f_exit(int argc, const VALUE *argv); RBIMPL_ATTR_NORETURN() /** * This is similar to rb_f_exit(). In fact on some situation it internally * calls rb_exit(). But can be very esoteric on occasions. * * It takes up to one argument. If an argument is passed, it tries to display * that. Otherwise if there is `$!`, displays that exception instead. It * finally raise ::rb_eSystemExit in both cases. * * @param[in] argc Number of objects of `argv`. * @param[in] argv Contains at most one string-ish object. * @exception rb_eArgError Wrong `argc`. * @exception rb_eTypeError No conversion from `argv[0]` to String. * @exception rb_eSystemExit Exception representing `EXIT_FAILURE`. * @note It never returns. */ VALUE rb_f_abort(int argc, const VALUE *argv); /* eval.c*/ RBIMPL_ATTR_NORETURN() /** * Raises an instance of ::rb_eInterrupt. * * @exception rb_eInterrupt Always raises this exception. * @note It never returns. */ void rb_interrupt(void); /** * Queries the name of the Ruby level method that is calling this function. * The "name" in this context is the one assigned to the function for the first * time (note that methods can have multiple names via aliases). * * @retval 0 There is no method (e.g. toplevel context). * @retval otherwise The name of the current method. */ ID rb_frame_this_func(void); RBIMPL_ATTR_NORETURN() /** * This function is to re-throw global escapes. Such global escapes include * exceptions, `throw`, `break`, for example. * * It makes sense only when used in conjunction with "protect" series APIs * e.g. rb_protect(), rb_load_protect(), rb_eval_string_protect(), etc. In * case these functions experience global escapes, they fill their opaque * `state` return buffer. You can ignore such escapes. But if you decide * otherwise, you have to somehow escape globally again. This function is used * for that purpose. * * @param[in] state Opaque state of execution. * @note It never returns. * * @internal * * Though not a part of our public API, `state` is in fact an enum * ruby_tag_type. You can see the potential values by looking at vm_core.h. */ void rb_jump_tag(int state); /** * Calls `initialize` method of the passed object with the passed arguments. * It also forwards the implicitly passed block to the method. * * @param[in] obj Receiver object. * @param[in] argc Number of objects of `argv`. * @param[in] argv Passed as-is to `obj.initialize`. * @exception rb_eException Any exceptions happen inside. */ void rb_obj_call_init(VALUE obj, int argc, const VALUE *argv); /** * Identical to rb_obj_call_init(), except you can specify how to handle the * last element of the given array. * * @param[in] obj Receiver object. * @param[in] argc Number of objects of `argv`. * @param[in] argv Passed as-is to `obj.initialize`. * @param[in] kw_splat Handling of keyword parameters: * - RB_NO_KEYWORDS `argv`'s last is not a keyword argument. * - RB_PASS_KEYWORDS `argv`'s last is a keyword argument. * - RB_PASS_CALLED_KEYWORDS it depends if there is a passed block. * @exception rb_eNoMethodError No such method. * @exception rb_eException Any exceptions happen inside. */ void rb_obj_call_init_kw(VALUE, int, const VALUE*, int); /** * Identical to rb_frame_this_func(), except it returns the named used to call * the method. * * @retval 0 There is no method (e.g. toplevel context). * @retval otherwise The name of the current method. */ ID rb_frame_callee(void); /** * Constructs an exception object from the list of arguments, in a manner * similar to Ruby's `raise`. This function can take: * * - No arguments at all, i.e. `argc == 0`. This is not a failure. It * returns ::RUBY_Qnil then. * * - An object, which is an instance of ::rb_cString. In this case an * instance of ::rb_eRuntimeError whose message is the passed string is * created then returned. * * - An object, which responds to `exception` method, and optionally its * argument, and optionally its backtrace. For example instances of * subclasses of ::rb_eException have this method. What is returned from * the method is returned. * * @param[in] argc Number of objects of `argv`. * @param[in] argv 0 up to 3 objects. * @exception rb_eArgError Wrong `argc`. * @exception rb_eTypeError `argv[0].exception` returned non-exception. * @return An instance of a subclass of ::rb_eException. * * @internal * * Historically this was _the_ way `raise` converted its arguments to an * exception. However they diverged. */ VALUE rb_make_exception(int argc, const VALUE *argv); /* eval_jump.c */ /** * Registers a function that shall run on process exit. Registered functions * run in reverse-chronological order, mixed with syntactic `END` block and * `Kernel#at_exit`. * * @param[in] func Function to run at process exit. * @param[in] arg Passed as-is to `func`. */ void rb_set_end_proc(void (*func)(VALUE arg), VALUE arg); RBIMPL_SYMBOL_EXPORT_END() #endif /* RBIMPL_INTERN_EVAL_H */ include/ruby/internal/intern/string.h 0000644 00000206571 15152150473 0013760 0 ustar 00 #ifndef RBIMPL_INTERN_STRING_H /*-*-C++-*-vi:se ft=cpp:*/ #define RBIMPL_INTERN_STRING_H /** * @file * @author Ruby developers <ruby-core@ruby-lang.org> * @copyright This file is a part of the programming language Ruby. * Permission is hereby granted, to either redistribute and/or * modify this file, provided that the conditions mentioned in the * file COPYING are met. Consult the file for details. * @warning Symbols prefixed with either `RBIMPL` or `rbimpl` are * implementation details. Don't take them as canon. They could * rapidly appear then vanish. The name (path) of this header file * is also an implementation detail. Do not expect it to persist * at the place it is now. Developers are free to move it anywhere * anytime at will. * @note To ruby-core: remember that this header can be possibly * recursively included from extension libraries written in C++. * Do not expect for instance `__VA_ARGS__` is always available. * We assume C99 for ruby itself but we don't assume languages of * extension libraries. They could be written in C++98. * @brief Public APIs related to ::rb_cString. */ #include "ruby/internal/config.h" #ifdef STDC_HEADERS # include <stddef.h> #endif #ifdef HAVE_STRING_H # include <string.h> #endif #ifdef HAVE_STDINT_H # include <stdint.h> #endif #include "ruby/internal/attr/deprecated.h" #include "ruby/internal/attr/nonnull.h" #include "ruby/internal/attr/pure.h" #include "ruby/internal/constant_p.h" #include "ruby/internal/dllexport.h" #include "ruby/internal/value.h" #include "ruby/internal/variable.h" /* rb_gvar_setter_t */ #include "ruby/st.h" /* st_index_t */ RBIMPL_SYMBOL_EXPORT_BEGIN() /* string.c */ /** * Allocates an instance of ::rb_cString. * * @param[in] ptr A memory region of `len` bytes length. * @param[in] len Length of `ptr`, in bytes, not including the * terminating NUL character. * @exception rb_eNoMemError Failed to allocate `len+1` bytes. * @exception rb_eArgError `len` is negative. * @return An instance of ::rb_cString, of `len` bytes length, of * "binary" encoding, whose contents are verbatim copy of `ptr`. * @pre At least `len` bytes of continuous memory region shall be * accessible via `ptr`. */ VALUE rb_str_new(const char *ptr, long len); /** * Identical to rb_str_new(), except it assumes the passed pointer is a pointer * to a C string. * * @param[in] ptr A C string. * @exception rb_eNoMemError Failed to allocate memory. * @exception rb_eArgError `ptr` is a null pointer. * @return An instance of ::rb_cString, of "binary" encoding, whose * contents are verbatim copy of `ptr`. * @pre `ptr` must not be a null pointer. */ VALUE rb_str_new_cstr(const char *ptr); /** * Identical to rb_str_new_cstr(), except it takes a Ruby's string instead of * C's. Implementation wise it creates a string that shares the backend memory * region with the receiver. So the name. But there is no way for extension * libraries to know if a string is of such variant. * * @param[in] str An object of ::RString. * @return An allocated instance of ::rb_cString, which shares the * encoding, length, and contents with the passed string. * @pre `str` must not be any arbitrary object except ::RString. * @note Use #StringValue to enforce the precondition. */ VALUE rb_str_new_shared(VALUE str); /** * Creates a frozen copy of the string, if necessary. This function does * nothing when the passed string is already frozen. Otherwise, it allocates a * copy of it, which is frozen. The passed string is untouched either ways. * * @param[in] str An object of ::RString. * @return Something frozen. * @pre `str` must not be any arbitrary object except ::RString. * @note Use #StringValue to enforce the precondition. */ VALUE rb_str_new_frozen(VALUE str); /** * Identical to rb_str_new(), except it takes the class of the allocating * object. * * @param[in] obj A string-ish object. * @param[in] ptr A memory region of `len` bytes length. * @param[in] len Length of `ptr`, in bytes, not including the * terminating NUL character. * @exception rb_eNoMemError Failed to allocate `len+1` bytes. * @exception rb_eArgError `len` is negative. * @return An instance of the class of `obj`, of `len` bytes length, of * "binary" encoding, whose contents are verbatim copy of `ptr`. * @pre At least `len` bytes of continuous memory region shall be * accessible via `ptr`. * * @internal * * Why it doesn't take an instance of ::rb_cClass? */ VALUE rb_str_new_with_class(VALUE obj, const char *ptr, long len); /** * Identical to rb_str_new(), except it generates a string of "default * external" encoding. * * @param[in] ptr A memory region of `len` bytes length. * @param[in] len Length of `ptr`, in bytes, not including the * terminating NUL character. * @exception rb_eNoMemError Failed to allocate `len+1` bytes. * @exception rb_eArgError `len` is negative. * @return An instance of ::rb_cString. In case encoding conversion from * "default internal" to "default external" is fully defined over * the given contents, then the return value is a string of * "default external" encoding, whose contents are the converted * ones. Otherwise the string is a junk. * @warning It doesn't raise on a conversion failure and silently ends up in * a corrupted output. You can know the failure by querying * `valid_encoding?` of the result object. */ VALUE rb_external_str_new(const char *ptr, long len); RBIMPL_ATTR_NONNULL(()) /** * Identical to rb_external_str_new(), except it assumes the passed pointer is * a pointer to a C string. It can also be seen as a routine identical to * rb_str_new_cstr(), except it generates a string of "default external" * encoding. * * @param[in] ptr A C string. * @exception rb_eNoMemError Failed to allocate memory. * @return An instance of ::rb_cString. In case encoding conversion from * "default internal" to "default external" is fully defined over * the given contents, then the return value is a string of * "default external" encoding, whose contents are the converted * ones. Otherwise the string is a junk. * @warning It doesn't raise on a conversion failure and silently ends up in * a corrupted output. You can know the failure by querying * `valid_encoding?` of the result object. * @pre `ptr` must not be a null pointer. */ VALUE rb_external_str_new_cstr(const char *ptr); /** * Identical to rb_str_new(), except it generates a string of "locale" * encoding. It can also be seen as a routine identical to * rb_external_str_new(), except it generates a string of "locale" encoding * instead of "default external" encoding. * * @param[in] ptr A memory region of `len` bytes length. * @param[in] len Length of `ptr`, in bytes, not including the * terminating NUL character. * @exception rb_eNoMemError Failed to allocate `len+1` bytes. * @exception rb_eArgError `len` is negative. * @return An instance of ::rb_cString. In case encoding conversion from * "default internal" to "locale" is fully defined over the given * contents, then the return value is a string of "locale" * encoding, whose contents are the converted ones. Otherwise the * string is a junk. * @warning It doesn't raise on a conversion failure and silently ends up in * a corrupted output. You can know the failure by querying * `valid_encoding?` of the result object. */ VALUE rb_locale_str_new(const char *ptr, long len); RBIMPL_ATTR_NONNULL(()) /** * Identical to rb_locale_str_new(), except it assumes the passed pointer is a * pointer to a C string. It can also be seen as a routine identical to * rb_external_str_new_cstr(), except it generates a string of "locale" * encoding instead of "default external". * * @param[in] ptr A C string. * @exception rb_eNoMemError Failed to allocate memory. * @return An instance of ::rb_cString. In case encoding conversion from * "default internal" to "locale" is fully defined over the given * contents, then the return value is a string of "locale" * encoding, whose contents are the converted ones. Otherwise the * string is a junk. * @warning It doesn't raise on a conversion failure and silently ends up in * a corrupted output. You can know the failure by querying * `valid_encoding?` of the result object. * @pre `ptr` must not be a null pointer. */ VALUE rb_locale_str_new_cstr(const char *ptr); /** * Identical to rb_str_new(), except it generates a string of "filesystem" * encoding. It can also be seen as a routine identical to * rb_external_str_new(), except it generates a string of "filesystem" encoding * instead of "default external" encoding. * * @param[in] ptr A memory region of `len` bytes length. * @param[in] len Length of `ptr`, in bytes, not including the * terminating NUL character. * @exception rb_eNoMemError Failed to allocate `len+1` bytes. * @exception rb_eArgError `len` is negative. * @return An instance of ::rb_cString. In case encoding conversion from * "default internal" to "filesystem" is fully defined over the * given contents, then the return value is a string of * "filesystem" encoding, whose contents are the converted ones. * Otherwise the string is a junk. * @warning It doesn't raise on a conversion failure and silently ends up in * a corrupted output. You can know the failure by querying * `valid_encoding?` of the result object. */ VALUE rb_filesystem_str_new(const char *ptr, long len); RBIMPL_ATTR_NONNULL(()) /** * Identical to rb_filesystem_str_new(), except it assumes the passed pointer * is a pointer to a C string. It can also be seen as a routine identical to * rb_external_str_new_cstr(), except it generates a string of "filesystem" * encoding instead of "default external". * * @param[in] ptr A C string. * @exception rb_eNoMemError Failed to allocate memory. * @return An instance of ::rb_cString. In case encoding conversion from * "default internal" to "filesystem" is fully defined over the * given contents, then the return value is a string of * "filesystem" encoding, whose contents are the converted ones. * Otherwise the string is a junk. * @warning It doesn't raise on a conversion failure and silently ends up in * a corrupted output. You can know the failure by querying * `valid_encoding?` of the result object. * @pre `ptr` must not be a null pointer. */ VALUE rb_filesystem_str_new_cstr(const char *ptr); /** * Allocates a "string buffer". A string buffer here is an instance of * ::rb_cString, whose capacity is bigger than the length of it. If you can * say that a string grows to a specific amount of bytes, this could be * effective than resizing a string over and over again and again. * * @param[in] capa Designed capacity of the generating string. * @return An empty string, of "binary" encoding, whose capacity is `capa`. */ VALUE rb_str_buf_new(long capa); RBIMPL_ATTR_NONNULL(()) /** * This is a rb_str_buf_new() + rb_str_buf_cat() combo. * * @param[in] ptr A C string. * @exception rb_eNoMemError Failed to allocate memory. * @return An instance of ::rb_cString, of "binary" encoding, whose * contents are verbatim copy of `ptr`. * @pre `ptr` must not be a null pointer. * * @internal * * This must be identical to rb_str_new_cstr(), except done in inefficient way? * @shyouhei doesn't understand why this is not a simple alias. */ VALUE rb_str_buf_new_cstr(const char *ptr); /** * Allocates a "temporary" string. This is a hidden empty string. Handy on * occasions. * * @param[in] len Designed length of the string. * @return A hidden, empty string. * @see rb_obj_hide() */ VALUE rb_str_tmp_new(long len); /** * Identical to rb_str_new(), except it generates a string of "US ASCII" * encoding. This is different from rb_external_str_new(), not only for the * output encoding, but also it doesn't convert the contents. * * @param[in] ptr A memory region of `len` bytes length. * @param[in] len Length of `ptr`, in bytes, not including the * terminating NUL character. * @exception rb_eNoMemError Failed to allocate `len+1` bytes. * @exception rb_eArgError `len` is negative. * @return An instance of ::rb_cString, of `len` bytes length, of * "US ASCII" encoding, whose contents are verbatim copy of `ptr`. */ VALUE rb_usascii_str_new(const char *ptr, long len); /** * Identical to rb_str_new_cstr(), except it generates a string of "US ASCII" * encoding. It can also be seen as a routine Identical to * rb_usascii_str_new(), except it assumes the passed pointer is a pointer to a * C string. * * @param[in] ptr A C string. * @exception rb_eNoMemError Failed to allocate memory. * @exception rb_eArgError `ptr` is a null pointer. * @return An instance of ::rb_cString, of "US ASCII" encoding, whose * contents are verbatim copy of `ptr`. * @pre `ptr` must not be a null pointer. */ VALUE rb_usascii_str_new_cstr(const char *ptr); /** * Identical to rb_str_new(), except it generates a string of "UTF-8" encoding. * * @param[in] ptr A memory region of `len` bytes length. * @param[in] len Length of `ptr`, in bytes, not including the * terminating NUL character. * @exception rb_eNoMemError Failed to allocate `len+1` bytes. * @exception rb_eArgError `len` is negative. * @return An instance of ::rb_cString, of `len` bytes length, of * "UTF-8" encoding, whose contents are verbatim copy of `ptr`. */ VALUE rb_utf8_str_new(const char *ptr, long len); /** * Identical to rb_str_new_cstr(), except it generates a string of "UTF-8" * encoding. It can also be seen as a routine Identical to * rb_usascii_str_new(), except it assumes the passed pointer is a pointer to a * C string. * * @param[in] ptr A C string. * @exception rb_eNoMemError Failed to allocate memory. * @exception rb_eArgError `ptr` is a null pointer. * @return An instance of ::rb_cString, of "UTF-8" encoding, whose contents * are verbatim copy of `ptr`. * @pre `ptr` must not be a null pointer. */ VALUE rb_utf8_str_new_cstr(const char *ptr); /** * @name Special strings that are backended by C string literals. * * *_str_new_static functions are intended for C string literals. * They require memory in the range [ptr, ptr+len] to always be readable. * Note that this range covers a total of len + 1 bytes. * * @{ */ /** * Identical to rb_str_new(), except it takes a C string literal. * * @param[in] ptr A C string literal. * @param[in] len `strlen(ptr)`. * @exception rb_eArgError `len` out of range of `size_t`. * @pre `ptr` must be a C string constant. * @return An instance of ::rb_cString, of "binary" encoding, whose backend * storage is the passed C string literal. * @warning It is a very bad idea to write to a C string literal (often * immediate SEGV shall occur). Consider return values of this * function be read-only. * * @internal * * Surprisingly it can take NULL, and generates an empty string. */ VALUE rb_str_new_static(const char *ptr, long len); /** * Identical to rb_str_new_static(), except it generates a string of "US ASCII" * encoding instead of "binary". It can also be seen as a routine identical to * rb_usascii_str_new(), except it takes a C string literal. * * @param[in] ptr A C string literal. * @param[in] len `strlen(ptr)`. * @exception rb_eArgError `len` out of range of `size_t`. * @pre `ptr` must be a C string constant. * @return An instance of ::rb_cString, of "US ASCII" encoding, whose * backend storage is the passed C string literal. * @warning It is a very bad idea to write to a C string literal (often * immediate SEGV shall occur). Consider return values of this * function be read-only. */ VALUE rb_usascii_str_new_static(const char *ptr, long len); /** * Identical to rb_str_new_static(), except it generates a string of "UTF-8" * encoding instead of "binary". It can also be seen as a routine identical to * rb_utf8_str_new(), except it takes a C string literal. * * @param[in] ptr A C string literal. * @param[in] len `strlen(ptr)`. * @exception rb_eArgError `len` out of range of `size_t`. * @pre `ptr` must be a C string constant. * @return An instance of ::rb_cString, of "UTF-8" encoding, whose backend * storage is the passed C string literal. * @warning It is a very bad idea to write to a C string literal (often * immediate SEGV shall occur). Consider return values of this * function be read-only. */ VALUE rb_utf8_str_new_static(const char *ptr, long len); /** @} */ /** * Identical to rb_interned_str(), except it takes a Ruby's string instead of * C's. It can also be seen as a routine identical to to rb_str_new_shared(), * except it returns an infamous "f"string. * * @param[in] str An object of ::RString. * @return An instance of ::rb_cString, either cached or allocated, which * has the identical encoding, length, and contents with the passed * string. * @pre `str` must not be any arbitrary object except ::RString. * @note Use #StringValue to enforce the precondition. * * @internal * * It actually finds or creates a fstring of the needed property, and * destructively modifies the receiver behind-the-scene so that it becomes a * shared string whose parent is the returning fstring. */ VALUE rb_str_to_interned_str(VALUE str); /** * Identical to rb_str_new(), except it returns an infamous "f"string. What is * a fstring? Well it is a special subkind of strings that is immutable, * deduped globally, and managed by our GC. It is much like a Symbol (in fact * Symbols are dynamic these days and are backended using fstrings). This * concept has been silently introduced at some point in 2.x era. Since then * it gained wider acceptance in the core. Starting from 3.x extension * libraries can also generate ones. * * @param[in] ptr A memory region of `len` bytes length. * @param[in] len Length of `ptr`, in bytes, not including the * terminating NUL character. * @exception rb_eArgError `len` is negative. * @return A found or created instance of ::rb_cString, of `len` bytes * length, of "binary" encoding, whose contents are identical to * that of `ptr`. * @pre At least `len` bytes of continuous memory region shall be * accessible via `ptr`. */ VALUE rb_interned_str(const char *ptr, long len); RBIMPL_ATTR_NONNULL(()) /** * Identical to rb_interned_str(), except it assumes the passed pointer is a * pointer to a C's string. It can also be seen as a routine identical to to * rb_str_to_interned_str(), except it takes a C's string instead of Ruby's. * Or it can also be seen as a routine identical to rb_str_new_cstr(), except * it returns an infamous "f"string. * * @param[in] ptr A C string. * @exception rb_eNoMemError Failed to allocate memory. * @return An instance of ::rb_cString, of "binary" encoding, whose * contents are verbatim copy of `ptr`. * @pre `ptr` must not be a null pointer. */ VALUE rb_interned_str_cstr(const char *ptr); /** * Destroys the given string for no reason. * * @warning DO NOT USE IT. * @warning Leave this task to our GC. * @warning It was a bad idea at the first place to let you know about it. * * @param[out] str The string to be executed. * @post The given string no longer exists. * @note Maybe `String#clear` could be what you want. * * @internal * * Should have moved this to `internal/string.h`. */ void rb_str_free(VALUE str); /** * Replaces the contents of the former with the latter. * * @param[out] dst Destination object. * @param[in] src Source object. * @pre Both objects must not be any arbitrary objects except * ::RString. * @post `dst`'s former components are abandoned. It now has the * identical encoding, length, and contents to `src`. * @see rb_str_replace() * * @internal * * @shyouhei doesn't understand why this is useful to extension libraries. * Just use rb_str_replace(). What's wrong with that? */ void rb_str_shared_replace(VALUE dst, VALUE src); /** * Identical to rb_str_cat_cstr(), except it takes Ruby's string instead of * C's. It can also be seen as a routine identical to rb_str_shared_replace(), * except it appends instead of replaces. * * @param[out] dst Destination object. * @param[in] src Source object. * @exception rb_eEncCompatError Can't mix the encodings. * @exception rb_eArgError Result string too big. * @return The passed `dst`. * @pre Both objects must not be any arbitrary objects except * ::RString. * @post `dst` has the contents of `src` appended, with encoding * converted into `dst`'s one, into the end of `dst`. */ VALUE rb_str_buf_append(VALUE dst, VALUE src); /** @alias{rb_str_cat} */ VALUE rb_str_buf_cat(VALUE, const char*, long); /** @alias{rb_str_cat_cstr} */ VALUE rb_str_buf_cat2(VALUE, const char*); RBIMPL_ATTR_NONNULL(()) /** * Identical to rb_str_cat_cstr(), except it additionally assumes the source * string be a NUL terminated ASCII string. * * @param[out] dst Destination object. * @param[in] src Source string. * @exception rb_eArgError Result string too big. * @return The passed `dst`. * @pre `dst` must not be any arbitrary object except ::RString. * @pre `src` must be a NUL terminated ASCII string. * @post `dst` has the contents of `src` appended, with encoding * converted into `dst`'s one, into the end of `dst`. */ VALUE rb_str_buf_cat_ascii(VALUE dst, const char *src); /** * Try converting an object to its stringised representation using its `to_s` * method, if any. If there is no such thing, it resorts to rb_any_to_s() * output. * * @param[in] obj Arbitrary ruby object to stringise. * @return An instance of ::rb_cString. */ VALUE rb_obj_as_string(VALUE obj); /** * Try converting an object to its stringised representation using its `to_str` * method, if any. If there is no such thing, returns ::RUBY_Qnil. * * @param[in] obj Arbitrary ruby object to stringise. * @exception rb_eTypeError `obj.to_str` returned something non-String. * @retval RUBY_Qnil No conversion from obj to String defined. * @return otherwise Stringised representation of `obj`. * @see rb_io_check_io * @see rb_check_array_type * @see rb_check_hash_type */ VALUE rb_check_string_type(VALUE obj); /** * Asserts that the given string's encoding is (Ruby's definition of) ASCII * compatible. * * @param[in] obj An instance of ::rb_cString. * @exception rb_eEncCompatError `obj` is ASCII incompatible. * * @internal * * @shyouhei doesn't know if this is an Easter egg or an official feature, but * this function can in fact take non-strings such as Symbols, Regexps, IOs, * etc. However if something unsupported is passed, it causes SEGV. It seems * the feature is kind of untested. */ void rb_must_asciicompat(VALUE obj); /** * Duplicates a string. * * @param[in] str String in question to duplicate. * @return A duplicated new instance. * @pre `str` must be of ::RString. */ VALUE rb_str_dup(VALUE str); /** * I guess there is no use case of this function in extension libraries, but * this is a routine identical to rb_str_dup(), except it always creates an * instance of ::rb_cString regardless of the given object's class. This makes * the most sense when the passed string is formerly hidden by rb_obj_hide(). * * @param[in] str A string, possibly hidden. * @return A duplicated new instance of ::rb_cString. */ VALUE rb_str_resurrect(VALUE str); /** * Obtains a "temporary lock" of the string. This advisory locking mechanism * prevents other cooperating threads from tampering the receiver. The same * thing could be done via freeze mechanism, but this one can also be unlocked * using rb_str_unlocktmp(). * * @param[out] str String to lock. * @exception rb_eRuntimeError `str` already locked. * @return The given string. * @post The string is locked. */ VALUE rb_str_locktmp(VALUE str); /** * Releases a lock formerly obtained by rb_str_locktmp(). * * @param[out] str String to unlock. * @exception rb_eRuntimeError `str` already unlocked. * @return The given string. * @post The string is locked. */ VALUE rb_str_unlocktmp(VALUE str); /** @alias{rb_str_new_frozen} */ VALUE rb_str_dup_frozen(VALUE); /** @alias{rb_str_new_frozen} */ #define rb_str_dup_frozen rb_str_new_frozen /** * Generates a new string, concatenating the former to the latter. It can also * be seen as a routine identical to rb_str_append(), except it doesn't tamper * the passed strings to create a new one instead. * * @param[in] lhs Source string #1. * @param[in] rhs Source string #2. * @exception rb_eEncCompatError Can't mix the encodings. * @exception rb_eArgError Result string too big. * @return A new string containing `rhs` concatenated to `lhs`. * @pre Both objects must not be any arbitrary objects except ::RString. * @note This operation doesn't commute. Don't get confused by the * "plus" terminology. For historical reasons there are some * noncommutative `+`s in Ruby. This is one of such things. There * has been a long discussion around `+`s in programming languages. */ VALUE rb_str_plus(VALUE lhs, VALUE rhs); /** * Repetition of a string. * * @param[in] str String to repeat. * @param[in] num Count, something numeric. * @exception rb_eArgError `num` is negative. * @return A new string repeating `num` times of `str`. */ VALUE rb_str_times(VALUE str, VALUE num); /** * Byte offset to character offset conversion. This makes sense when the * receiver is in a multibyte encoding. The string's i-th character does not * always sit at its i-th byte. This function scans the contents to find the * character index that matches the byte index. Generally speaking this is an * `O(n)` operation. Could be slow. * * @param[in] str The string to scan. * @param[in] pos Offset, in bytes. * @return Offset, in characters. */ long rb_str_sublen(VALUE str, long pos); /** * This is the implementation of two-argumented `String#slice`. * * - Returns the substring of the given `len` found in `str` at offset `beg`: * * ```ruby * 'foo'[0, 2] # => "fo" * 'foo'[0, 0] # => "" * ``` * * - Counts backward from the end of `str` if `beg` is negative: * * ```ruby * 'foo'[-2, 2] # => "oo" * ``` * * - Special case: returns a new empty string if `beg` is equal to the length * of `str`: * * ```ruby * 'foo'[3, 2] # => "" * ``` * * - Returns a null pointer if `beg` is out of range: * * ```ruby * 'foo'[4, 2] # => nil * 'foo'[-4, 2] # => nil * ``` * * - Returns the trailing substring of `str` if `len` is large: * * ```ruby * 'foo'[1, 50] # => "oo" * ``` * * - Returns a null pointer if `len` is negative: * * ```ruby * 'foo'[0, -1] # => nil * ``` * * @param[in] str The string to slice. * @param[in] beg Requested offset of the substring. * @param[in] len Requested length of the substring. * @retval RUBY_Qnil Parameters out of range. * @retval otherwise A new string whose contents is the specified * substring of `str`. * @pre `str` must not be any arbitrary objects except ::RString. */ VALUE rb_str_substr(VALUE str, long beg, long len); /** * Identical to rb_str_substr(), except the numbers are interpreted as byte * offsets instead of character offsets. * * @param[in] str The string to slice. * @param[in] beg Requested offset of the substring. * @param[in] len Requested length of the substring. * @return A new string whose contents is the specified substring of `str`. * @pre `str` must not be any arbitrary objects except ::RString. * @pre `beg` and `len` must not point to OOB contents. */ VALUE rb_str_subseq(VALUE str, long beg, long len); /** * Identical to rb_str_substr(), except it returns a C's string instead of * Ruby's. * * @param[in] str The string to slice. * @param[in] beg Requested offset of the substring. * @param[in,out] len Requested length of the substring. * @retval NULL Parameters out of range. * @retval otherwise A pointer inside of `str`'s backend storage where * the specified substring exist. * @pre `str` must not be any arbitrary objects except ::RString. * @post `len` is updated to have the length of the return value. */ char *rb_str_subpos(VALUE str, long beg, long *len); /** * Declares that the string is about to be modified. This for instance let the * string have a dedicated backend storage. * * @param[out] str String about to be modified. * @exception rb_eRuntimeError `str` is `locktmp`-ed. * @exception rb_eFrozenError `str` is frozen. * @pre `str` must not be any arbitrary objects except ::RString. * @post Upon successful return the passed string is eligible to be * modified. */ void rb_str_modify(VALUE str); /** * Identical to rb_str_modify(), except it additionally expands the capacity of * the receiver. * * @param[out] str Target string to modify. * @param[in] capa Additional capacity to add. * @exception rb_eArgError `capa` is negative. * @exception rb_eRuntimeError `str` is `locktmp`-ed. * @exception rb_eFrozenError `str` is frozen. * @pre `str` must not be any arbitrary objects except ::RString. * @post Upon successful return the passed string is modified so that * its capacity is increased for `capa` bytes. */ void rb_str_modify_expand(VALUE str, long capa); /** * This is the implementation of `String#freeze`. * * @param[out] str Target string to freeze. * @return The passed string. * @post Upon successful return the passed string is frozen. */ VALUE rb_str_freeze(VALUE str); /** * Overwrites the length of the string. Typically this is used to shrink a * string that was formerly expanded. * * ```CXX * extern int fd; * auto str = rb_eval_string("'...'"); * rb_str_modify_expand(str, BUFSIZ); * if (auto len = recv(fd, RSTRING_PTR(str), BUFSIZ, 0); len >= 0) { * rb_str_set_len(str, len); * } * else { * rb_sys_fail("recv(2)"); * } * ``` * * @param[out] str String to shrink. * @param[in] len New length of the string. * @exception rb_eRuntimeError `str` is `locktmp`-ed. * @exception rb_eFrozenError `str` is frozen. * @pre `str` must not be any arbitrary objects except ::RString. * @post Upon successful return `str`'s length is set to `len`. */ void rb_str_set_len(VALUE str, long len); /** * Overwrites the length of the string. In contrast to rb_str_set_len(), this * function can also expand a string. * * @param[out] str String to shrink. * @param[in] len New length of the string. * @exception rb_eArgError `len` is negative. * @exception rb_eRuntimeError `str` is `locktmp`-ed. * @exception rb_eFrozenError `str` is frozen. * @return The passed `str`. * @pre `str` must not be any arbitrary objects except ::RString. * @post Upon successful return `str` is either expanded or shrunken to * have its length be `len`. */ VALUE rb_str_resize(VALUE str, long len); /** * Destructively appends the passed contents to the string. * * @param[out] dst Destination object. * @param[in] src Contents to append. * @param[in] srclen Length of `src`. * @exception rb_eArgError `srclen` is negative. * @return The passed `dst`. * @pre `dst` must not be any arbitrary objects except ::RString. * @post `dst` has the contents of `ptr` appended. */ VALUE rb_str_cat(VALUE dst, const char *src, long srclen); /** * Identical to rb_str_cat(), except it assumes the passed pointer is a pointer * to a C string. * * @param[out] dst Destination object. * @param[in] src Contents to append. * @exception rb_eArgError Result string too big. * @exception rb_eArgError `src` is a null pointer. * @return The passed `dst`. * @pre `dst` must not be any arbitrary objects except ::RString. * @pre `src` must not be a null pointer. * @post `dst` has the contents of `src` appended. */ VALUE rb_str_cat_cstr(VALUE dst, const char *src); /** @alias{rb_str_cat_cstr} */ VALUE rb_str_cat2(VALUE, const char*); /** * Identical to rb_str_buf_append(), except it converts the right hand side * before concatenating. * * @param[out] dst Destination object. * @param[in] src Source object. * @exception rb_eEncCompatError Can't mix the encodings. * @exception rb_eArgError Result string too big. * @return The passed `dst`. * @pre `dst` must not be any arbitrary objects except ::RString. * @post `dst` has the contents of `src` appended, with encoding * converted into `dst`'s one, into the end of `dst`. */ VALUE rb_str_append(VALUE dst, VALUE src); /** * Identical to rb_str_append(), except it also accepts an integer as a * codepoint. This resembles `String#<<`. * * @param[out] dst Destination object. * @param[in] src Source object, String or Numeric. * @exception rb_eRangeError Source numeric is out of range. * @exception rb_eEncCompatError Source string too long. * @exception rb_eArgError Result string too big. * @return The passed `dst`. * @pre `dst` must not be any arbitrary objects except ::RString. * @post `dst` has the contents of `src` appended, with encoding * converted into `dst`'s one, into the end of `dst`. */ VALUE rb_str_concat(VALUE dst, VALUE src); /* random.c */ /** * This is a universal hash function. * * @warning This function changes its value per process. * @param[in] ptr Target message. * @param[in] len Length of `ptr` in bytes. * @return A pseudorandom number suitable for Hash's hash value. * @see Aumasson, JP., Bernstein, D.J., "SipHash: A Fast Short-Input * PRF", In proceedings of 13th International Conference on * Cryptology in India (INDOCRYPT 2012), LNCS 7668, pp. 489-508, * 2012. http://doi.org/10.1007/978-3-642-34931-7_28 */ st_index_t rb_memhash(const void *ptr, long len); /** * Starts a series of hashing. Suppose you have a struct: * * ```CXX * struct foo_tag { * unsigned char bar; * uint32_t baz; * }; * ``` * * It is not a wise idea to call rb_memhash() over it, because there could be * padding bits. Instead you should explicitly iterate over each fields: * * ```CXX * foo_tag foo = { 0, 0, }; * st_index_t hash = 0; * * hash = rb_hash_start(0); * hash = rb_hash_uint(hash, foo.bar); * hash = rb_hash_uint32(hash, foo.baz); * hash = rb_hash_end(hash); * ``` * * @param[in] i Initial value. * @return A hash value. */ st_index_t rb_hash_start(st_index_t i); /** @alias{st_hash_uint32} */ #define rb_hash_uint32(h, i) st_hash_uint32((h), (i)) /** @alias{st_hash_uint} */ #define rb_hash_uint(h, i) st_hash_uint((h), (i)) /** @alias{st_hash_end} */ #define rb_hash_end(h) st_hash_end(h) /* string.c */ /** * Calculates a hash value of a string. This is one of the two functions that * constructs struct ::st_hash_type. * * @param[in] str An object of ::RString. * @return A hash value. * @pre `str` must not be any arbitrary object except ::RString. * * @internal * * Although safe to call, there must be no particular use case of this function * for extension libraries. Only ruby internals must know about it. * * This is not a simple alias of rb_memhash(), because it considers the passed * string's encoding as well as its contents. */ st_index_t rb_str_hash(VALUE str); /** * Compares two strings. This is one of the two functions that constructs * struct ::st_hash_type. * * @param[in] str1 A string. * @param[in] str2 Another string. * @retval 1 They have identical contents, length, and encodings. * @retval 0 Otherwise. * @pre Both objects must not be any arbitrary objects except * ::RString. * * @internal * * In contrast to rb_str_hash(), this could be handy for comparison that only * concerns equality. rb_str_cmp() returns 1, 0, -1. */ int rb_str_hash_cmp(VALUE str1, VALUE str2); /** * Checks if two strings are comparable each other or not. Because * rb_str_cmp() must return "lesser than" or "greater than" information, * comparing two strings needs a stricter restriction. Both sides must be in a * same set of strings which have total order. This is to check that property. * Intuitive it sounds? But they can have different encodings. A character * and another might or might not appear in the same order in their codepoints. * It is complicated than you think. * * @param[in] str1 A string. * @param[in] str2 Another string. * @retval 1 They agree on a total order. * @retval 0 Otherwise. * @pre Both objects must not be any arbitrary objects except * ::RString. */ int rb_str_comparable(VALUE str1, VALUE str2); /** * Compares two strings, as in `strcmp(3)`. This does not consider the current * locale, but considers the encodings of both sides instead. * * @param[in] lhs A string. * @param[in] rhs Another string. * @retval -1 `lhs` is "bigger than" `rhs`. * @retval 1 `rhs` is "bigger than" `lhs`. * @retval 0 Otherwise, e.g. not comparable. * @pre Both objects must not be any arbitrary objects except * ::RString. */ int rb_str_cmp(VALUE lhs, VALUE rhs); /** * Equality of two strings. * * If `str2` is not a String, it resorts to `str2 == str1`. Otherwise if they * are not comparable, returns ::RUBY_Qfalse. Otherwise if they have the same * contents and the length, returns ::RUBY_Qtrue. Otherwise, returns * ::RUBY_Qfalse. * * @param[in] str1 A string. * @param[in] str2 Another string. * @retval RUBY_Qtrue They are equal. * @retval RUBY_Qfalse They are either different, or not comparable. */ VALUE rb_str_equal(VALUE str1, VALUE str2); /** * Shrinks the given string for the given number of bytes. * * @param[out] str String to squash. * @param[in] len Number of bytes to reduce. * @exception rb_eRuntimeError `str` is `locktmp`-ed. * @exception rb_eFrozenError `str` is frozen. * @return The passed `str`. * @pre `str` must not be any arbitrary objects except ::RString. * @post `str` is shrunken. * @warning Can break a multibyte character in middle. * * @internal * * What if `len` is negative? */ VALUE rb_str_drop_bytes(VALUE str, long len); /** * Replaces some (or all) of the contents of the given string. This is the * implementation of three-argumented `String#[]=`. * * @param[out] dst Target string to update. * @param[in] beg Offset of the affected portion. * @param[in] len Length of the affected portion. * @param[in] src Object to be assigned. * @exception rb_eTypeError `src` has no implicit conversion to String. * @exception rb_eIndexError `len` is negative, or `beg` is OOB. * @exception rb_eRuntimeError `dst` is `locktmp`-ed. * @exception rb_eFrozenError `dst` is frozen. * @note Unlike rb_str_substr(), this function raises. * @post A portion of `dst` from `beg` to `len` is the stringised * representation of `src`. If that replacement string is not the * same length as the portion it is replacing, `dst` will be * resized accordingly. */ void rb_str_update(VALUE dst, long beg, long len, VALUE src); /** * Replaces the contents of the former object with the stringised contents of * the latter. * * @param[out] dst Destination object. * @param[in] src Source object. * @exception rb_eTypeError `src` has no implicit conversion to String. * @exception rb_eRuntimeError `dst` is `locktmp`-ed. * @exception rb_eFrozenError `dst` is frozen. * @return The passed `dst`. * @pre `dst` must not be any arbitrary object except ::RString. * @post `dst`'s former components are abandoned. It now has the * identical encoding, length, and contents to `src`. */ VALUE rb_str_replace(VALUE dst, VALUE src); /** * Generates a "readable" version of the receiver. * * @warning The output is _insecure_. Never feed one to `eval`. * @warning The output is not always in the same encoding as the given one. * @warning A character might or might not be escaped, depending on the * result encoding. * @param[in] str String to inspect. * @return Its inspection, either in default internal encoding if any, or * in default external encoding otherwise. * @see rb_str_dump() * * @internal * * This is a (silent) fix of an actual vulnerability feeding `inspect` output * strings to `eval`: * https://github.com/hiki/hiki/commit/8771a6e25198e264a2bf9dc1c102fea2cc8ff975 * * ... and its advisory: * http://hikiwiki.org/en/advisory20040712.html */ VALUE rb_str_inspect(VALUE str); /** * "Inverse" of rb_eval_string(). Returns a quoted version of the string. All * non-printing characters are replaced by `\uNNNN` or `\xHH` notation and all * special characters are escaped. The result string is guaranteed to render a * string of the same contents when passed to `eval` and friends. * * @param[in] str String to dump. * @exception rb_eRuntimeError Too many escape sequences causes integer * overflow on the length of the string. * @return An US-ASCII string that includes all the necessary info to * reconstruct the original string. */ VALUE rb_str_dump(VALUE str); /** * Divides the given string based on the given delimiter. This is the * 1-argument 0-block version of `String#split`. * * @param[in] str Object in question to split. * @param[in] delim Delimiter, in C string. * @exception rb_eTypeError `str` has no implicit conversion to String. * @exception rb_eArgError `delim` is a null pointer. * @return An array of strings, which are substrings of the passed `str`. * If `delim` is an empty C string (i.e. `""`), `str` is split into * each characters. If `delim` is a C string whose sole content is * a whitespace (i.e. `" "`), `str` is split on whitespaces, with * leading and trailing whitespace and runs of contiguous * whitespace characters ignored. Otherwise, `str` is split * according to `delim`. */ VALUE rb_str_split(VALUE str, const char *delim); /** * This is a ::rb_gvar_setter_t that refutes non-string assignments. * * @exception rb_eTypeError Passed something non-string. */ rb_gvar_setter_t rb_str_setter; /* symbol.c */ /** * Identical to rb_to_symbol(), except it assumes the receiver being an * instance of ::RString. * * @param[in] str The name of the id. * @exception rb_eRuntimeError Too many symbols. * @return A (possibly new) id whose value is the given `str`. * @pre `str` must not be any arbitrary object except ::RString. * @note These days Ruby internally has two kinds of symbols * (static/dynamic). Symbols created using this function would * become dynamic ones; i.e. would be garbage collected. It could * be safer for you to use it than alternatives, when applicable. */ VALUE rb_str_intern(VALUE str); /* string.c */ /** * This is an rb_sym2str() + rb_str_dup() combo. * * @param[in] sym A symbol to query. * @return A string duplicating the symbol's backend storage. * * @internal * * This function causes SEGV when the passed value is a static symbol that * doesn't exist. */ VALUE rb_sym_to_s(VALUE sym); /** * Counts the number of characters (not bytes) that are stored inside of the * given string. This of course depends on its encoding. Also this function * generally runs in O(n), because for instance you have to scan the entire * string to know how many characters are there in a UTF-8 string. * * @param[in] str Target string to query. * @return Its number of characters. */ long rb_str_strlen(VALUE str); /** * Identical to rb_str_strlen(), except it returns the value in ::rb_cInteger. * * @param[in] str Target string to query. * @return Its number of characters. */ VALUE rb_str_length(VALUE); /** * "Inverse" of rb_str_sublen(). This function scans the contents to find the * byte index that matches the character index. Generally speaking this is an * `O(n)` operation. Could be slow. * * @param[in] str The string to scan. * @param[in] pos Offset, in characters. * @return Offset, in bytes. */ long rb_str_offset(VALUE str, long pos); RBIMPL_ATTR_PURE() /** * Queries the capacity of the given string. * * @see ::RString::capa * @param[in] str String in question. * @return Its capacity. */ size_t rb_str_capacity(VALUE str); /** * Shortens `str` and adds three dots, an ellipsis, if it is longer than `len` * characters. The length of the returned string in characters is less than or * equal to `len`. If the length of `str` is less than or equal `len`, returns * `str` itself. The encoding of returned string is equal to that of passed * one. The class of returned string is equal to that of passed one. * * @param[in] str The string to shorten. * @param[in] len The maximum string length. * @exception rb_eIndexError `len` is negative. * @retval str No need to add ellipsis. * @retval otherwise A new, shortened string. * @note The length is counted in characters. */ VALUE rb_str_ellipsize(VALUE str, long len); /** * "Cleanses" the string. A string has its encoding and its contents. They, * in practice, do not always fit. There are strings in the wild that are * "broken"; include bit patterns that are not allowed by its encoding. That * can happen when a user copy&pasted something bad, network input got * clobbered by a middleman, cosmic rays hit the physical memory, and many more * occasions. This function takes such strings, and fills the "broken" portion * with the passed replacement bit pattern. * * This function also takes a ruby block. That is a neat way to do things, but * can be annoying when the caller function want to use a block for another * purpose. * * @param[in] str Target string to scrub. * @param[in] repl Replacement string. When it is a string, * this function takes that as a replacement. * When it is ::RUBY_Qnil, this function tries * to yield a block (if any) and takes its * evaluated value as a replacement. In case * of ::RUBY_Qnil without a block, this * function takes an encoding-specific default * character (`U+FFFD`, for instance) as a last * resort. * @exception rb_eTypeError `repl` is neither string nor nil. * @exception rb_eArgError `repl` itself is broken. * @exception rb_eEncCompatError `repl` and `str` are incompatible. * @retval RUBY_Qnil `str` is already clean. * @retval otherwise A new, clean string. */ VALUE rb_str_scrub(VALUE str, VALUE repl); /** * Searches for the "successor" of a string. This function is complicated! * This is the only function in the entire ruby API (either C or Ruby) that * generates a string out of thin air. First, the successor to an empty string * is a new empty string: * * ```ruby * ''.succ # => "" * ``` * * Otherwise the successor is calculated by "incrementing" characters. The * first character to be incremented is the rightmost alphanumeric: or, if no * alphanumerics, the rightmost character: * * ```ruby * 'THX1138'.succ # => "THX1139" * '<<koala>>'.succ # => "<<koalb>>" * '***'.succ # => '**+' * ``` * * The successor to a digit is another digit, "carrying" to the next-left * character for a "rollover" from 9 to 0, and prepending another digit if * necessary: * * ```ruby * '00'.succ # => "01" * '09'.succ # => "10" * '99'.succ # => "100" * '-9'.succ # => "-10" * ``` * * The successor to a letter is another letter of the same case, carrying to * the next-left character for a rollover, and prepending another same-case * letter if necessary: * * ```ruby * 'aa'.succ # => "ab" * 'az'.succ # => "ba" * 'zz'.succ # => "aaa" * 'AA'.succ # => "AB" * 'AZ'.succ # => "BA" * 'ZZ'.succ # => "AAA" * ``` * * The successor to a non-alphanumeric character is the next character in the * underlying character set's collating sequence, carrying to the next-left * character for a rollover, and prepending another character if necessary: * * ```ruby * s = "\u03A1" * s.succ # => "\u03A3" # There is no such thing like \u03A2. * s = 255.chr * 3 * s # => "\xFF\xFF\xFF" * s.succ # => "\x01\x00\x00\x00" * ``` * * Carrying can occur between and among mixtures of alphanumeric characters: * * ```ruby * s = 'zz99zz99' * s.succ # => "aaa00aa00" * s = '99zz99zz' * s.succ # => "100aa00aa" * s = '1.9.9' * s.succ # => "2.0.0" * ``` * * @param[in] orig Predecessor string. * @return Successor string. */ VALUE rb_str_succ(VALUE orig); RBIMPL_ATTR_NONNULL(()) /** * @private * * This is an implementation detail. Don't bother. * * @param[in] str A C string. * @return `strlen`, casted to `long`. */ static inline long rbimpl_strlen(const char *str) { return RBIMPL_CAST((long)strlen(str)); } RBIMPL_ATTR_NONNULL(()) /** * @private * * This is an implementation detail. Don't bother. * * @param[in] str A C string literal. * @return Corresponding Ruby string. */ static inline VALUE rbimpl_str_new_cstr(const char *str) { long len = rbimpl_strlen(str); return rb_str_new_static(str, len); } RBIMPL_ATTR_NONNULL(()) /** * @private * * This is an implementation detail. Don't bother. * * @param[in] str A C string literal. * @return Corresponding Ruby string. */ static inline VALUE rbimpl_usascii_str_new_cstr(const char *str) { long len = rbimpl_strlen(str); return rb_usascii_str_new_static(str, len); } RBIMPL_ATTR_NONNULL(()) /** * @private * * This is an implementation detail. Don't bother. * * @param[in] str A C string literal. * @return Corresponding Ruby string. */ static inline VALUE rbimpl_utf8_str_new_cstr(const char *str) { long len = rbimpl_strlen(str); return rb_utf8_str_new_static(str, len); } RBIMPL_ATTR_NONNULL(()) /** * @private * * This is an implementation detail. Don't bother. * * @param[in] str A C string literal. * @return Corresponding Ruby string. */ static inline VALUE rbimpl_external_str_new_cstr(const char *str) { long len = rbimpl_strlen(str); return rb_external_str_new(str, len); } RBIMPL_ATTR_NONNULL(()) /** * @private * * This is an implementation detail. Don't bother. * * @param[in] str A C string literal. * @return Corresponding Ruby string. */ static inline VALUE rbimpl_locale_str_new_cstr(const char *str) { long len = rbimpl_strlen(str); return rb_locale_str_new(str, len); } RBIMPL_ATTR_NONNULL(()) /** * @private * * This is an implementation detail. Don't bother. * * @param[in] str A C string literal. * @return Corresponding Ruby string. */ static inline VALUE rbimpl_str_buf_new_cstr(const char *str) { long len = rbimpl_strlen(str); VALUE buf = rb_str_buf_new(len); return rb_str_buf_cat(buf, str, len); } RBIMPL_ATTR_NONNULL(()) /** * @private * * This is an implementation detail. Don't bother. * * @param[out] buf A string buffer. * @param[in] str A C string literal. * @return `buf` itself. */ static inline VALUE rbimpl_str_cat_cstr(VALUE buf, const char *str) { long len = rbimpl_strlen(str); return rb_str_cat(buf, str, len); } RBIMPL_ATTR_NONNULL(()) /** * @private * * This is an implementation detail. Don't bother. * * @param[in] exc An exception class. * @param[in] str A C string literal. * @return An instance of `exc`. */ static inline VALUE rbimpl_exc_new_cstr(VALUE exc, const char *str) { long len = rbimpl_strlen(str); return rb_exc_new(exc, str, len); } /** * Allocates an instance of ::rb_cString. * * @param[in] str A memory region of `len` bytes length. * @param[in] len Length of `ptr`, in bytes, not including the * terminating NUL character. * @exception rb_eNoMemError Failed to allocate `len+1` bytes. * @exception rb_eArgError `len` is negative. * @return An instance of ::rb_cString, of `len` bytes length, of * "binary" encoding, whose contents are verbatim copy of `str`. * @pre At least `len` bytes of continuous memory region shall be * accessible via `str`. */ #define rb_str_new(str, len) \ ((RBIMPL_CONSTANT_P(str) && \ RBIMPL_CONSTANT_P(len) ? \ rb_str_new_static : \ rb_str_new) ((str), (len))) /** * Identical to #rb_str_new, except it assumes the passed pointer is a pointer * to a C string. * * @param[in] str A C string. * @exception rb_eNoMemError Failed to allocate memory. * @return An instance of ::rb_cString, of "binary" encoding, whose * contents are verbatim copy of `str`. * @pre `str` must not be a null pointer. */ #define rb_str_new_cstr(str) \ ((RBIMPL_CONSTANT_P(str) ? \ rbimpl_str_new_cstr : \ rb_str_new_cstr) (str)) /** * Identical to #rb_str_new, except it generates a string of "US ASCII" * encoding. This is different from rb_external_str_new(), not only for the * output encoding, but also it doesn't convert the contents. * * @param[in] str A memory region of `len` bytes length. * @param[in] len Length of `str`, in bytes, not including the * terminating NUL character. * @exception rb_eNoMemError Failed to allocate `len+1` bytes. * @exception rb_eArgError `len` is negative. * @return An instance of ::rb_cString, of `len` bytes length, of * "US ASCII" encoding, whose contents are verbatim copy of `str`. */ #define rb_usascii_str_new(str, len) \ ((RBIMPL_CONSTANT_P(str) && \ RBIMPL_CONSTANT_P(len) ? \ rb_usascii_str_new_static : \ rb_usascii_str_new) ((str), (len))) /** * Identical to #rb_str_new, except it generates a string of "UTF-8" encoding. * * @param[in] str A memory region of `len` bytes length. * @param[in] len Length of `str`, in bytes, not including the * terminating NUL character. * @exception rb_eNoMemError Failed to allocate `len+1` bytes. * @exception rb_eArgError `len` is negative. * @return An instance of ::rb_cString, of `len` bytes length, of * "UTF-8" encoding, whose contents are verbatim copy of `str`. */ #define rb_utf8_str_new(str, len) \ ((RBIMPL_CONSTANT_P(str) && \ RBIMPL_CONSTANT_P(len) ? \ rb_utf8_str_new_static : \ rb_utf8_str_new) ((str), (len))) /** * Identical to #rb_str_new_cstr, except it generates a string of "US ASCII" * encoding. It can also be seen as a routine Identical to * #rb_usascii_str_new, except it assumes the passed pointer is a pointer to a * C string. * * @param[in] str A C string. * @exception rb_eNoMemError Failed to allocate memory. * @return An instance of ::rb_cString, of "US ASCII" encoding, whose * contents are verbatim copy of `str`. * @pre `str` must not be a null pointer. */ #define rb_usascii_str_new_cstr(str) \ ((RBIMPL_CONSTANT_P(str) ? \ rbimpl_usascii_str_new_cstr : \ rb_usascii_str_new_cstr) (str)) /** * Identical to #rb_str_new_cstr, except it generates a string of "UTF-8" * encoding. It can also be seen as a routine Identical to #rb_utf8_str_new, * except it assumes the passed pointer is a pointer to a C string. * * @param[in] str A C string. * @exception rb_eNoMemError Failed to allocate memory. * @return An instance of ::rb_cString, of "UTF-8" encoding, whose contents * are verbatim copy of `str`. * @pre `str` must not be a null pointer. */ #define rb_utf8_str_new_cstr(str) \ ((RBIMPL_CONSTANT_P(str) ? \ rbimpl_utf8_str_new_cstr : \ rb_utf8_str_new_cstr) (str)) /** * Identical to #rb_str_new_cstr, except it generates a string of "default * external" encoding. * * @param[in] str A C string. * @exception rb_eNoMemError Failed to allocate memory. * @return An instance of ::rb_cString. In case encoding conversion from * "default internal" to "default external" is fully defined over * the given contents, then the return value is a string of * "default external" encoding, whose contents are the converted * ones. Otherwise the string is a junk. * @warning It doesn't raise on a conversion failure and silently ends up in * a corrupted output. You can know the failure by querying * `valid_encoding?` of the result object. * @pre `str` must not be a null pointer. */ #define rb_external_str_new_cstr(str) \ ((RBIMPL_CONSTANT_P(str) ? \ rbimpl_external_str_new_cstr : \ rb_external_str_new_cstr) (str)) /** * Identical to #rb_external_str_new_cstr, except it generates a string of * "locale" encoding instead of "default external". * * @param[in] str A C string. * @exception rb_eNoMemError Failed to allocate memory. * @return An instance of ::rb_cString. In case encoding conversion from * "default internal" to "locale" is fully defined over the given * contents, then the return value is a string of "locale" * encoding, whose contents are the converted ones. Otherwise the * string is a junk. * @warning It doesn't raise on a conversion failure and silently ends up in * a corrupted output. You can know the failure by querying * `valid_encoding?` of the result object. * @pre `str` must not be a null pointer. */ #define rb_locale_str_new_cstr(str) \ ((RBIMPL_CONSTANT_P(str) ? \ rbimpl_locale_str_new_cstr : \ rb_locale_str_new_cstr) (str)) /** * Identical to #rb_str_new_cstr, except done differently. * * @param[in] str A C string. * @exception rb_eNoMemError Failed to allocate memory. * @return An instance of ::rb_cString, of "binary" encoding, whose * contents are verbatim copy of `str`. * @pre `str` must not be a null pointer. */ #define rb_str_buf_new_cstr(str) \ ((RBIMPL_CONSTANT_P(str) ? \ rbimpl_str_buf_new_cstr : \ rb_str_buf_new_cstr) (str)) /** * Identical to rb_str_cat(), except it assumes the passed pointer is a pointer * to a C string. * * @param[out] buf Destination object. * @param[in] str Contents to append. * @exception rb_eArgError Result string too big. * @return The passed `buf`. * @pre `buf` must not be any arbitrary objects except ::RString. * @pre `str` must not be a null pointer. * @post `buf` has the contents of `str` appended. */ #define rb_str_cat_cstr(buf, str) \ ((RBIMPL_CONSTANT_P(str) ? \ rbimpl_str_cat_cstr : \ rb_str_cat_cstr) ((buf), (str))) /** * Identical to rb_exc_new(), except it assumes the passed pointer is a pointer * to a C string. * * @param[out] exc A subclass of ::rb_eException. * @param[in] str Message to raise. * @return An instance of `exc` whose message is `str`. * @pre `str` must not be a null pointer. */ #define rb_exc_new_cstr(exc, str) \ ((RBIMPL_CONSTANT_P(str) ? \ rbimpl_exc_new_cstr : \ rb_exc_new_cstr) ((exc), (str))) #define rb_str_new2 rb_str_new_cstr /**< @old{rb_str_new_cstr} */ #define rb_str_new3 rb_str_new_shared /**< @old{rb_str_new_shared} */ #define rb_str_new4 rb_str_new_frozen /**< @old{rb_str_new_frozen} */ #define rb_str_new5 rb_str_new_with_class /**< @old{rb_str_new_with_class} */ #define rb_str_buf_new2 rb_str_buf_new_cstr /**< @old{rb_str_buf_new_cstr} */ #define rb_usascii_str_new2 rb_usascii_str_new_cstr /**< @old{rb_usascii_str_new_cstr} */ #define rb_str_buf_cat rb_str_cat /**< @alias{rb_str_cat} */ #define rb_str_buf_cat2 rb_str_cat_cstr /**< @old{rb_usascii_str_new_cstr} */ #define rb_str_cat2 rb_str_cat_cstr /**< @old{rb_str_cat_cstr} */ /** * Length of a string literal. * * @param[in] str A C String literal. * @return An integer constant expression that represents `str`'s length, * in bytes, not including the terminating NUL character. */ #define rb_strlen_lit(str) (sizeof(str "") - 1) /** * Identical to rb_str_new_static(), except it cannot take string variables. * * @param[in] str A C string literal. * @pre `str` must not be a variable. * @return An instance of ::rb_cString, of "binary" encoding, whose backend * storage is the passed C string literal. * @warning It is a very bad idea to write to a C string literal (often * immediate SEGV shall occur). Consider return values of this * function be read-only. */ #define rb_str_new_lit(str) rb_str_new_static((str), rb_strlen_lit(str)) /** * Identical to rb_usascii_str_new_static(), except it cannot take string * variables. * * @param[in] str A C string literal. * @pre `str` must not be a variable. * @return An instance of ::rb_cString, of "US ASCII" encoding, whose * backend storage is the passed C string literal. * @warning It is a very bad idea to write to a C string literal (often * immediate SEGV shall occur). Consider return values of this * function be read-only. */ #define rb_usascii_str_new_lit(str) rb_usascii_str_new_static((str), rb_strlen_lit(str)) /** * Identical to rb_utf8_str_new_static(), except it cannot take string * variables. * * @param[in] str A C string literal. * @pre `str` must not be a variable. * @return An instance of ::rb_cString, of "UTF-8" encoding, whose backend * storage is the passed C string literal. * @warning It is a very bad idea to write to a C string literal (often * immediate SEGV shall occur). Consider return values of this * function be read-only. */ #define rb_utf8_str_new_lit(str) rb_utf8_str_new_static((str), rb_strlen_lit(str)) /** * Identical to rb_enc_str_new_static(), except it cannot take string * variables. * * @param[in] str A C string literal. * @param[in] enc A pointer to an encoding. * @pre `str` must not be a variable. * @return An instance of ::rb_cString, of the passed encoding, whose * backend storage is the passed C string literal. * @warning It is a very bad idea to write to a C string literal (often * immediate SEGV shall occur). Consider return values of this * function be read-only. */ #define rb_enc_str_new_lit(str, enc) rb_enc_str_new_static((str), rb_strlen_lit(str), (enc)) #define rb_str_new_literal(str) rb_str_new_lit(str) /**< @alias{rb_str_new_lit} */ #define rb_usascii_str_new_literal(str) rb_usascii_str_new_lit(str) /**< @alias{rb_usascii_str_new_lit} */ #define rb_utf8_str_new_literal(str) rb_utf8_str_new_lit(str) /**< @alias{rb_utf8_str_new_lit} */ #define rb_enc_str_new_literal(str, enc) rb_enc_str_new_lit(str, enc) /**< @alias{rb_enc_str_new_lit} */ RBIMPL_SYMBOL_EXPORT_END() #endif /* RBIMPL_INTERN_STRING_H */ include/ruby/internal/intern/hash.h 0000644 00000027170 15152150473 0013371 0 ustar 00 #ifndef RBIMPL_INTERN_HASH_H /*-*-C++-*-vi:se ft=cpp:*/ #define RBIMPL_INTERN_HASH_H /** * @file * @author Ruby developers <ruby-core@ruby-lang.org> * @copyright This file is a part of the programming language Ruby. * Permission is hereby granted, to either redistribute and/or * modify this file, provided that the conditions mentioned in the * file COPYING are met. Consult the file for details. * @warning Symbols prefixed with either `RBIMPL` or `rbimpl` are * implementation details. Don't take them as canon. They could * rapidly appear then vanish. The name (path) of this header file * is also an implementation detail. Do not expect it to persist * at the place it is now. Developers are free to move it anywhere * anytime at will. * @note To ruby-core: remember that this header can be possibly * recursively included from extension libraries written in C++. * Do not expect for instance `__VA_ARGS__` is always available. * We assume C99 for ruby itself but we don't assume languages of * extension libraries. They could be written in C++98. * @brief Public APIs related to ::rb_cHash. */ #include "ruby/internal/attr/nonnull.h" #include "ruby/internal/dllexport.h" #include "ruby/internal/value.h" #include "ruby/st.h" RBIMPL_SYMBOL_EXPORT_BEGIN() /* hash.c */ RBIMPL_ATTR_NONNULL(()) /** * Identical to rb_st_foreach(), except it raises exceptions when the callback * function tampers the table during iterating over it. * * @param[in] st Table to iterate over. * @param[in] func Callback function to apply. * @param[in] arg Passed as-is to `func`. * @exception rb_eRuntimeError `st` was tampered during iterating. * * @internal * * This is declared here because exceptions are Ruby level concept. * * This is in fact a very thin wrapper of rb_st_foreach_check(). */ void rb_st_foreach_safe(struct st_table *st, st_foreach_callback_func *func, st_data_t arg); /** @alias{rb_st_foreach_safe} */ #define st_foreach_safe rb_st_foreach_safe /** * Try converting an object to its hash representation using its `to_hash` * method, if any. If there is no such thing, returns ::RUBY_Qnil. * * @param[in] obj Arbitrary ruby object to convert. * @exception rb_eTypeError `obj.to_hash` returned something non-Hash. * @retval RUBY_Qnil No conversion from `obj` to hash defined. * @retval otherwise Converted hash representation of `obj`. * @see rb_io_check_io * @see rb_check_array_type * @see rb_check_string_type * * @internal * * There is no rb_hash_to_hash() that analogous to rb_str_to_str(). * Intentional or ...? */ VALUE rb_check_hash_type(VALUE obj); RBIMPL_ATTR_NONNULL(()) /** * Iterates over a hash. This basically does the same thing as * rb_st_foreach(). But because the passed hash is a Ruby object, its keys and * values are both Ruby objects. * * @param[in] hash An instance of ::rb_cHash to iterate over. * @param[in] func Callback function to yield. * @param[in] arg Passed as-is to `func`. * @exception rb_eRuntimeError `hash` was tampered during iterating. */ void rb_hash_foreach(VALUE hash, int (*func)(VALUE key, VALUE val, VALUE arg), VALUE arg); /** * Calculates a message authentication code of the passed object. The return * value is a very small integer used as an index of a key of a table. In * order to calculate the value this function calls `#hash` method of the * passed object. Ruby provides you a default implementation. But if you * implement your class in C, that default implementation cannot know the * underlying data structure. You must implement your own `#hash` method then, * which must return an integer of uniform distribution in a sufficiently * instant manner. * * @param[in] obj Arbitrary Ruby object. * @exception rb_eTypeError `obj.hash` returned something non-Integer. * @return A small integer. * @note `#hash` can return very big integers, but they get truncated. */ VALUE rb_hash(VALUE obj); /** * Creates a new, empty hash object. * * @return An allocated new instance of ::rb_cHash. */ VALUE rb_hash_new(void); /** * Identical to rb_hash_new(), except it additionally specifies how many keys * it is expected to contain. This way you can create a hash that is large enough * for your need. For large hashes it means it won't need to be reallocated and * rehashed as much, improving performance. * * @param[in] capa Designed capacity of the hash. * @return An empty Hash, whose capacity is `capa`. */ VALUE rb_hash_new_capa(long capa); /** * Duplicates a hash. * * @param[in] hash An instance of ::rb_cHash. * @return An allocated new instance of ::rb_cHash, whose contents are * a verbatim copy of from `hash`. */ VALUE rb_hash_dup(VALUE hash); /** @alias{rb_obj_freeze} */ VALUE rb_hash_freeze(VALUE obj); /** * Queries the given key in the given hash table. If there is the key in the * hash, returns the value associated with the key. Otherwise it returns the * "default" value (defined per hash table). * * @param[in] hash Hash table to look into. * @param[in] key Hash key to look for. * @return Either the value associated with the key, or the default one if * absent. */ VALUE rb_hash_aref(VALUE hash, VALUE key); /** * Identical to rb_hash_aref(), except it always returns ::RUBY_Qnil for * misshits. * * @param[in] hash Hash table to look into. * @param[in] key Hash key to look for. * @return Either the value associated with the key, or ::RUBY_Qnil if * absent. * @note A hash can store ::RUBY_Qnil as an ordinary value. You cannot * distinguish whether the key is missing, or just its associated * value happens to be ::RUBY_Qnil, as far as you use this API. */ VALUE rb_hash_lookup(VALUE hash, VALUE key); /** * Identical to rb_hash_lookup(), except you can specify what to return on * misshits. This is much like 2-arguments version of `Hash#fetch`. * * ```CXX * VALUE hash; * VALUE key; * VALUE tmp = rb_obj_alloc(rb_cObject); * VALUE val = rb_hash_lookup2(hash, key, tmp); * if (val == tmp) { * printf("misshit"); * } * else { * printf("hit"); * } * ``` * * @param[in] hash Hash table to look into. * @param[in] key Hash key to look for. * @param[in] def Default value. * @retval def `hash` does not have `key`. * @retval otherwise The value associated with `key`. */ VALUE rb_hash_lookup2(VALUE hash, VALUE key, VALUE def); /** * Identical to rb_hash_lookup(), except it yields the (implicitly) passed * block instead of returning ::RUBY_Qnil. * * @param[in] hash Hash table to look into. * @param[in] key Hash key to look for. * @exception rb_eKeyError No block given. * @return Either the value associated with the key, or what the block * evaluates to if absent. */ VALUE rb_hash_fetch(VALUE hash, VALUE key); /** * Inserts or replaces ("upsert"s) the objects into the given hash table. This * basically associates the given value with the given key. On duplicate key * this function updates its associated value with the given one. Otherwise it * inserts the association at the end of the table. * * @param[out] hash Target hash table to modify. * @param[in] key Arbitrary Ruby object. * @param[in] val A value to be associated with `key`. * @exception rb_eFrozenError `hash` is frozen. * @return The passed `val` * @post `val` is associated with `key` in `hash`. */ VALUE rb_hash_aset(VALUE hash, VALUE key, VALUE val); /** * Swipes everything out of the passed hash table. * * @param[out] hash Target to clear. * @exception rb_eFrozenError `hash`is frozen. * @return The passed `hash` * @post `hash` has no contents. */ VALUE rb_hash_clear(VALUE hash); /** * Deletes each entry for which the block returns a truthy value. If there is * no block given, it returns an enumerator that does the thing. * * @param[out] hash Target hash to modify. * @exception rb_eFrozenError `hash` is frozen. * @retval hash The hash is modified. * @retval otherwise An instance of ::rb_cEnumerator that does it. */ VALUE rb_hash_delete_if(VALUE hash); /** * Deletes the passed key from the passed hash table, if any. * * @param[out] hash Target hash to modify. * @param[in] key Key to delete. * @retval RUBY_Qnil `hash` has no such key as `key`. * @retval otherwise What was associated with `key`. * @post `hash` has no such key as `key`. */ VALUE rb_hash_delete(VALUE hash, VALUE key); /** * Inserts a list of key-value pairs into a hash table at once. It is * semantically identical to repeatedly calling rb_hash_aset(), but can be * faster than that. * * @param[in] argc Length of `argv`, must be even. * @param[in] argv A list of key, value, key, value, ... * @param[out] hash Target hash table to modify. * @post `hash` has contents from `argv`. * @note `argv` is allowed to be NULL as long as `argc` is zero. * * @internal * * What happens for duplicated keys? Well it silently discards older ones to * accept the newest (rightmost) one. This behaviour also mimics repeated call * of rb_hash_aset(). */ void rb_hash_bulk_insert(long argc, const VALUE *argv, VALUE hash); /** * Type of callback functions to pass to rb_hash_update_by(). * * @param[in] newkey A key of the table. * @param[in] oldkey Value associated with `key` in hash1. * @param[in] value Value associated with `key` in hash2. * @return Either one of the passed values to take. */ typedef VALUE rb_hash_update_func(VALUE newkey, VALUE oldkey, VALUE value); /** * Destructively merges two hash tables into one. It resolves key conflicts by * calling the passed function and take its return value. * * @param[out] hash1 Target hash to be modified. * @param[in] hash2 A hash to merge into `hash1`. * @param[in] func Conflict reconciler. * @exception rb_eFrozenError `hash1` is frozen. * @exception rb_eRuntimeError `hash2` is updated instead. * @return The passed `hash1`. * @post Contents of `hash2` is merged into `hash1`. * @note You can pass zero to `func`. This means values from `hash2` * are always taken. */ VALUE rb_hash_update_by(VALUE hash1, VALUE hash2, rb_hash_update_func *func); /* file.c */ /** * This function is mysterious. What it does is not immediately obvious. Also * what it does seems platform dependent. * * @param[in] path A local path. * @retval 0 The "check" succeeded. * @retval otherwise The "check" failed. */ int rb_path_check(const char *path); /* hash.c */ /** * Destructively removes every environment variables of the running process. * * @return The `ENV` object. * @post The process has no environment variables. */ VALUE rb_env_clear(void); /** * Identical to #RHASH_SIZE(), except it returns the size in Ruby's integer * instead of C's. * * @param[in] hash A hash object. * @return The size of the hash. */ VALUE rb_hash_size(VALUE hash); RBIMPL_SYMBOL_EXPORT_END() #endif /* RBIMPL_INTERN_HASH_H */ include/ruby/internal/intern/parse.h 0000644 00000014266 15152150473 0013562 0 ustar 00 #ifndef RBIMPL_INTERN_PARSE_H /*-*-C++-*-vi:se ft=cpp:*/ #define RBIMPL_INTERN_PARSE_H /** * @file * @author Ruby developers <ruby-core@ruby-lang.org> * @copyright This file is a part of the programming language Ruby. * Permission is hereby granted, to either redistribute and/or * modify this file, provided that the conditions mentioned in the * file COPYING are met. Consult the file for details. * @warning Symbols prefixed with either `RBIMPL` or `rbimpl` are * implementation details. Don't take them as canon. They could * rapidly appear then vanish. The name (path) of this header file * is also an implementation detail. Do not expect it to persist * at the place it is now. Developers are free to move it anywhere * anytime at will. * @note To ruby-core: remember that this header can be possibly * recursively included from extension libraries written in C++. * Do not expect for instance `__VA_ARGS__` is always available. * We assume C99 for ruby itself but we don't assume languages of * extension libraries. They could be written in C++98. * @brief Public APIs related to ::rb_cSymbol. */ #include "ruby/internal/attr/const.h" #include "ruby/internal/attr/nonnull.h" #include "ruby/internal/dllexport.h" #include "ruby/internal/value.h" RBIMPL_SYMBOL_EXPORT_BEGIN() /* symbol.c */ /** * Calculates an ID of attribute writer. For instance it returns `:foo=` when * passed `:foo`. * * @param[in] id An id. * @exception rb_eNameError `id` is not for attributes (e.g. operator). * @return Calculated name of attribute writer. */ ID rb_id_attrset(ID id); RBIMPL_ATTR_CONST() /** * Classifies the given ID, then sees if it is a constant. In case an ID is in * Unicode (likely), its "constant"-ness is determined if its first character * is either upper case or title case. Otherwise it is detected if case- * folding the first character changes its case or not. * * @param[in] id An id to classify. * @retval 1 It is a constant. * @retval 0 It isn't. */ int rb_is_const_id(ID id); RBIMPL_ATTR_CONST() /** * Classifies the given ID, then sees if it is a global variable. A global * variable must start with `$`. * * @param[in] id An id to classify. * @retval 1 It is a global variable. * @retval 0 It isn't. */ int rb_is_global_id(ID id); RBIMPL_ATTR_CONST() /** * Classifies the given ID, then sees if it is an instance variable. An * instance variable must start with `@`, but not `@@`. * * @param[in] id An id to classify. * @retval 1 It is an instance variable. * @retval 0 It isn't. */ int rb_is_instance_id(ID id); RBIMPL_ATTR_CONST() /** * Classifies the given ID, then sees if it is an attribute writer. An * attribute writer is otherwise a local variable, except it ends with `=`. * * @param[in] id An id to classify. * @retval 1 It is an attribute writer. * @retval 0 It isn't. */ int rb_is_attrset_id(ID id); RBIMPL_ATTR_CONST() /** * Classifies the given ID, then sees if it is a class variable. A class * variable is must start with `@@`. * * @param[in] id An id to classify. * @retval 1 It is a class variable. * @retval 0 It isn't. */ int rb_is_class_id(ID id); RBIMPL_ATTR_CONST() /** * Classifies the given ID, then sees if it is a local variable. A local * variable starts with a lowercase character, followed by some alphanumeric * characters or `_`, then ends with anything other than `!`, `?`, or `=`. * * @param[in] id An id to classify. * @retval 1 It is a local variable. * @retval 0 It isn't. */ int rb_is_local_id(ID id); RBIMPL_ATTR_CONST() /** * Classifies the given ID, then sees if it is a junk ID. An ID with no * special syntactic structure is considered junk. This category includes for * instance punctuation. * * @param[in] id An id to classify. * @retval 1 It is a junk. * @retval 0 It isn't. */ int rb_is_junk_id(ID); RBIMPL_ATTR_NONNULL(()) /** * Sees if the passed C string constructs a valid syntactic symbol. Invalid * ones for instance includes whitespaces. * * @param[in] str A C string to check. * @retval 1 It is a valid symbol name. * @retval 0 It is invalid as a symbol name. */ int rb_symname_p(const char *str); /* vm.c */ /** * Queries the last match, or `Regexp.last_match`, or the `$~`. You don't have * to use it, because in reality you can get `$~` using rb_gv_get() as usual. * * @retval RUBY_Qnil The method has not ran a regular expression. * @retval otherwise An instance of ::rb_cMatch. */ VALUE rb_backref_get(void); /** * Updates `$~`. You don't have to use it, because in reality you can set `$~` * using rb_gv_set() as usual. * * @param[in] md Arbitrary Ruby object. * @post The passed object is assigned to `$~`. * * @internal * * Yes, this function bypasses the Check_Type() that would normally prevent * evil souls from assigning evil objects to `$~`. Use of this function is a * really bad smell. */ void rb_backref_set(VALUE md); /** * Queries the last line, or the `$_`. You don't have to use it, because in * reality you can get `$_` using rb_gv_get() as usual. * * @retval RUBY_Qnil There has never been a "line" yet. * @retval otherwise The last set `$_` value. */ VALUE rb_lastline_get(void); /** * Updates `$_`. You don't have to use it, because in reality you can set `$_` * using rb_gv_set() as usual. * * @param[in] str Arbitrary Ruby object. * @post The passed object is assigned to `$_`. * * @internal * * Unlike `$~`, you can assign non-strings to `$_`, even from ruby scripts. */ void rb_lastline_set(VALUE str); /* symbol.c */ /** * Collects every single bits of symbols that have ever interned in the entire * history of the current process. * * @return An array that contains all symbols that have ever existed. */ VALUE rb_sym_all_symbols(void); RBIMPL_SYMBOL_EXPORT_END() #endif /* RBIMPL_INTERN_PARSE_H */ include/ruby/internal/intern/io.h 0000644 00000064364 15152150474 0013064 0 ustar 00 #ifndef RBIMPL_INTERN_IO_H /*-*-C++-*-vi:se ft=cpp:*/ #define RBIMPL_INTERN_IO_H /** * @file * @author Ruby developers <ruby-core@ruby-lang.org> * @copyright This file is a part of the programming language Ruby. * Permission is hereby granted, to either redistribute and/or * modify this file, provided that the conditions mentioned in the * file COPYING are met. Consult the file for details. * @warning Symbols prefixed with either `RBIMPL` or `rbimpl` are * implementation details. Don't take them as canon. They could * rapidly appear then vanish. The name (path) of this header file * is also an implementation detail. Do not expect it to persist * at the place it is now. Developers are free to move it anywhere * anytime at will. * @note To ruby-core: remember that this header can be possibly * recursively included from extension libraries written in C++. * Do not expect for instance `__VA_ARGS__` is always available. * We assume C99 for ruby itself but we don't assume languages of * extension libraries. They could be written in C++98. * @brief Public APIs related to ::rb_cIO. */ #include "ruby/internal/dllexport.h" #include "ruby/internal/value.h" RBIMPL_SYMBOL_EXPORT_BEGIN() /* io.c */ /** * @private * * @deprecated This macro once was a thing in the old days, but makes no sense * any longer today. Exists here for backwards compatibility * only. You can safely forget about it. */ #define rb_defout rb_stdout /* string.c */ /* ...why? moved in commit de7161526014b781468cea5d84411e23be */ /** * The field separator character for inputs, or the `$;`. This affects how * `String#split` works. You can set this via the `-F` command line option. * You can also assign arbitrary ruby objects programmatically, but it makes * best sense for you to assign a regular expression here. * * @internal * * Tidbit: "fs" comes from AWK's `FS` variable. */ RUBY_EXTERN VALUE rb_fs; /* io.c */ /* ...why? given rb_fs is in string.c? */ /** * The field separator character for outputs, or the `$,`. This affects how * `Array#join` works. * * @deprecated Assigning anything other than ::RUBY_Qnil to this variable is * deprecated. */ RUBY_EXTERN VALUE rb_output_fs; /** * The record separator character for inputs, or the `$/`. This affects how * `IO#gets` works. You can set this via the `-0` command line option. * * @deprecated Assigning anything other than ::RUBY_Qnil to this variable is * deprecated. * * @internal * * Tidbit: "rs" comes from AWK's `RS` variable. */ RUBY_EXTERN VALUE rb_rs; /** * This is the default value of ::rb_rs, i.e. `"\n"`. It seems it has always * been just a newline string since the beginning. Not sure why C codes has to * use this, given there is no way for ruby programs to interface. * * Also it has not been deprecated for unknown reasons. */ RUBY_EXTERN VALUE rb_default_rs; /** * The record separator character for outputs, or the `$\`. This affects how * `IO#print` works. * * @deprecated Assigning anything other than ::RUBY_Qnil to this variable is * deprecated. */ RUBY_EXTERN VALUE rb_output_rs; /** * Writes the given string to the given IO. * * @param[out] io An IO, opened for writing. * @param[in] str A String-like object to write to `io`. * @exception rb_eIOError `io` isn't opened for writing. * @exception rb_eFrozenError `io` is frozen. * @exception rb_eTypeError No conversion from `str` to String. * @exception rb_eSystemCallError `write(2)` failed for some reason. * @return The number of bytes written to the `io`. * @post `str` (up to the length of return value) is written to `io`. * @note This function blocks. * @note Partial write is a thing. It must be at least questionable not * to check the return value. * * @internal * * Above description is in fact inaccurate. This function can take arbitrary * objects, and calls their `write` method. What is written above in fact * describes how `IO#write` works. You can pass StringIO etc. here, and would * work completely differently. */ VALUE rb_io_write(VALUE io, VALUE str); /** * Reads a "line" from the given IO. A line here means a chunk of characters * which is terminated by either `"\n"` or an EOF. * * @param[in,out] io An IO, opened for reading. * @exception rb_eIOError `io` isn't opened for reading. * @exception rb_eFrozenError `io` is frozen. * @retval RUBY_Qnil `io` is at EOF. * @retval otherwise An instance of ::rb_cString. * @post `io` is read. * @note Unlike `IO#gets` it doesn't set `$_`. * @note Unlike `IO#gets` it doesn't consider `$/`. */ VALUE rb_io_gets(VALUE io); /** * Reads a byte from the given IO. * * @note In Ruby a "byte" always means an 8 bit integer ranging from * 0 to 255 inclusive. * @param[in,out] io An IO, opened for reading. * @exception rb_eIOError `io` is not opened for reading. * @exception rb_eFrozenError `io` is frozen. * @retval RUBY_Qnil `io` is at EOF. * @retval otherwise An instance of ::rb_cInteger. * @post `io` is read. * * @internal * * Of course there was a function called `rb_io_getc()`. It was removed in * commit a25fbe3b3e531bbe479f344af24eaf9d2eeae6ea. */ VALUE rb_io_getbyte(VALUE io); /** * "Unget"s a string. This function pushes back the passed string onto the * passed IO, such that a subsequent buffered read will return it. If the * passed content is in fact an integer, a single character string of that * codepoint of the encoding of the IO will be pushed back instead. * * It might be counter-intuitive but this function can push back multiple * characters at once. Also this function can be called multiple times on a * same IO. Also a "character" can be wider than a byte, depending on the * encoding of the IO. * * @param[out] io An IO, opened for reading. * @param[in] c Either a String, or an Integer. * @exception rb_eIOError `io` is not opened for reading. * @exception rb_eFrozenError `io` is frozen. * @exception rb_eTypeError No conversion from `c` to ::rb_cString. * @return Always returns ::RUBY_Qnil. * * @internal * * Why there is ungetc, given there is no getc? */ VALUE rb_io_ungetc(VALUE io, VALUE c); /** * Identical to rb_io_ungetc(), except it doesn't take the encoding of the * passed IO into account. When an integer is passed, it just casts that value * to C's `unsigned char`, and pushes that back. * * @param[out] io An IO, opened for reading. * @param[in] b Either a String, or an Integer. * @exception rb_eIOError `io` is not opened for reading. * @exception rb_eFrozenError `io` is frozen. * @exception rb_eTypeError No conversion from `b` to ::rb_cString. * @return Always returns ::RUBY_Qnil. */ VALUE rb_io_ungetbyte(VALUE io, VALUE b); /** * Closes the IO. Any buffered contents are flushed to the operating system. * Any future operations against the IO would raise ::rb_eIOError. In case the * io was created using `IO.popen`, it also sets the `$?`. * * @param[out] io Target IO to close. * @return Always returns ::RUBY_Qnil. * @post `$?` is set in case IO is a pipe. * @post No operations are possible against `io` any further. * @note This can block to flush the contents. * @note This can wake other threads up, especially those who are * `select()`-ing the passed IO. * @note Multiple invocations of this function over the same IO again * and again is not an error, since Ruby 2.3. * * @internal * * You can close a frozen IO... Is this intentional? */ VALUE rb_io_close(VALUE io); /** * Flushes any buffered data within the passed IO to the underlying operating * system. * * @param[out] io Target IO to flush. * @exception rb_eIOError `io` is closed. * @exception rb_eFrozenError `io` is frozen. * @exception rb_eSystemCallError `write(2)` failed for some reason. * @return The passed `io`. * @post `io`'s buffers are empty. * @note This operation also discards the read buffer. Should basically * be harmless, but in an esoteric situation like when user pushed * something different from what was read using `ungetc`, this * operation in fact changes the behaviour of the `io`. * @note Buffering is difficult. This operation flushes the data from * our userspace to the kernel, but that doesn't always mean you * can expect them stored persistently onto your hard drive. */ VALUE rb_io_flush(VALUE io); /** * Queries if the passed IO is at the end of file. "The end of file" here mans * that there are no more data to read. This function blocks until the read * buffer is filled in, and if that operation reached the end of file, it still * returns ::RUBY_Qfalse (because there are data yet in that buffer). It * returns ::RUBY_Qtrue once after the buffer is cleared. * * @param[in,out] io Target io to query. * @exception rb_eIOError `io` is not opened for reading. * @exception rb_eFrozenError `io` is frozen. * @retval RUBY_Qfalse There are things yet to be read. * @retval RUBY_Qtrue "The end of file" situation. */ VALUE rb_io_eof(VALUE io); /** * Sets the binmode. This operation nullifies the effect of textmode (newline * conversion from `"\r\n"` to `"\n"` or vice versa). Note that it doesn't * stop character encodings conversions. For instance an IO created using: * * ```ruby * File.open( * "/dev/urandom", * textmode: true, * external_encoding: Encoding::GB18030, * internal_encoding: Encoding::Windows_31J) * ``` * * has both newline and character conversions. If you pass such IO to this * function, only the `textmode:true` part is cancelled. Texts read through * the IO would still be encoded in Windows-31J; texts written to the IO will * be encoded in GB18030. * * @param[out] io Target IO to modify. * @exception rb_eFrozenError `io` is frozen. * @return The passed `io`. * @post `io` is in binmode. * @note There is no equivalent operation in Ruby. You can do this only * in C. */ VALUE rb_io_binmode(VALUE io); /** * Forces no conversions be applied to the passed IO. Unlike rb_io_binmode(), * this cancels any newline conversions as well as encoding conversions. Any * texts read/written through the IO will be the verbatim binary contents. * * @param[out] io Target IO to modify. * @exception rb_eFrozenError `io` is frozen. * @return The passed `io`. * @post `io` is in binmode. Both external/internal encoding are set to * rb_ascii8bit_encoding(). * @note This is the implementation of `IO#binmode`. */ VALUE rb_io_ascii8bit_binmode(VALUE io); /** * Identical to rb_io_write(), except it always returns the passed IO. * * @param[out] io An IO, opened for writing. * @param[in] str A String-like object to write to `io`. * @exception rb_eIOError `io` isn't opened for writing. * @exception rb_eFrozenError `io` is frozen. * @exception rb_eTypeError No conversion from `str` to String. * @exception rb_eSystemCallError `write(2)` failed. * @return The passed `io`. * @post `str` is written to `io`. * @note This function blocks. * * @internal * * As rb_io_write(), above description is a fake. */ VALUE rb_io_addstr(VALUE io, VALUE str); /** * This is a rb_f_sprintf() + rb_io_write() combo. * * @param[in] argc Number of objects of `argv`. * @param[in] argv A format string followed by its arguments. * @param[out] io An IO, opened for writing. * @exception rb_eIOError `io` isn't opened for writing. * @exception rb_eFrozenError `io` is frozen. * @exception rb_eTypeError No conversion from `str` to String. * @exception rb_eSystemCallError `write(2)` failed. * @return Always returns ::RUBY_Qnil. * @post `argv` is formatted, then written to `io`. * @note This function blocks. * * @internal * * As rb_io_write(), above descriptions include fakes. */ VALUE rb_io_printf(int argc, const VALUE *argv, VALUE io); /** * Iterates over the passed array to apply rb_io_write() individually. If * there is `$,`, this function inserts the string in middle of each * iterations. If there is `$\`, this function appends the string at the end. * If the array is empty, this function outputs `$_`. * * @param[in] argc Number of objects of `argv`. * @param[in] argv An array of strings to display. * @param[out] io An IO, opened for writing. * @exception rb_eIOError `io` isn't opened for writing. * @exception rb_eFrozenError `io` is frozen. * @exception rb_eTypeError No conversion from `str` to String. * @exception rb_eSystemCallError `write(2)` failed. * @return Always returns ::RUBY_Qnil. * @post `argv` is written to `io`. * @note This function blocks. * @note This function calls rb_io_write() multiple times. Which means, * it is not an atomic operation. Outputs from multiple threads * can interleave. * * @internal * * As rb_io_write(), above descriptions include fakes. */ VALUE rb_io_print(int argc, const VALUE *argv, VALUE io); /** * Iterates over the passed array to apply rb_io_write() individually. Unlike * rb_io_print(), this function prints a newline per each element. It also * flattens the passed array (OTOH rb_io_print() just resorts to * rb_ary_to_s()). * * @param[in] argc Number of objects of `argv`. * @param[in] argv An array of strings to display. * @param[out] io An IO, opened for writing. * @exception rb_eIOError `io` isn't opened for writing. * @exception rb_eFrozenError `io` is frozen. * @exception rb_eTypeError No conversion from `str` to String. * @exception rb_eSystemCallError `write(2)` failed. * @return Always returns ::RUBY_Qnil. * @post `argv` is written to `io`. * @note This function blocks. * @note This function calls rb_io_write() multiple times. Which means, * it is not an atomic operation. Outputs from multiple threads * can interleave. * * @internal * * As rb_io_write(), above descriptions include fakes. */ VALUE rb_io_puts(int argc, const VALUE *argv, VALUE io); /** * Creates an IO instance whose backend is the given file descriptor. C * extension libraries sometimes have file descriptors created elsewhere (maybe * deep inside of another shared library), which they want ruby programs to * handle. This function is handy for such situations. * * @param[in] fd Target file descriptor. * @param[in] flags Flags, e.g. `O_CREAT|O_EXCL` * @param[in] path The path of the file that backs `fd`, for diagnostics. * @return An allocated instance of ::rb_cIO. * @note Leave `path` NULL if you don't know. */ VALUE rb_io_fdopen(int fd, int flags, const char *path); RBIMPL_ATTR_NONNULL(()) /** * Opens a file located at the given path. * * `fmode` is a C string that represents the open mode. It can be one of: * * - `r` (means `O_RDONLY`), * - `w` (means `O_WRONLY | O_TRUNC | O_CREAT`), * - `a` (means `O_WRONLY | O_APPEND | O_CREAT`), * * Followed by zero or more combinations of: * * - `b` (means `_O_BINARY`), * - `t` (means `_O_TEXT`), * - `+` (means `O_RDWR`), * - `x` (means `O_TRUNC`), or * - `:[BOM|]enc[:enc]` (see below). * * This last one specifies external (and internal if any) encodings, * respectively. If optional `BOM|` is specified and the specified external * encoding is capable of expressing BOMs, opening file's contents' byte order * is auto-detected using the mechanism. * * So for instance, fmode of `"rt|BOM:utf-16le:utf-8"` specifies that... * * - the physical representation of the contents of the file is in UTF-16; * - honours its BOM but assumes little endian if absent; * - opens the file for reading; * - what is read is converted into UTF-8; * - with newlines cannibalised to `\n`. * * @param[in] fname Path to open. * @param[in] fmode Mode specifier much like `fopen(3)`. * @exception rb_eArgError `fmode` contradicted (e.g. `"bt"`). * @exception rb_eSystemCallError `open(2)` failed for some reason. * @return An instance of ::rb_cIO. */ VALUE rb_file_open(const char *fname, const char *fmode); RBIMPL_ATTR_NONNULL(()) /** * Identical to rb_file_open(), except it takes the pathname as a Ruby's string * instead of C's. In case the passed Ruby object is a non-String it tries to * call `#to_path`. * * @param[in] fname Path to open. * @param[in] fmode Mode specifier much like `fopen(3)`. * @exception rb_eTypeError `fname` is not a String. * @exception rb_eEncCompatError `fname` is not ASCII-compatible. * @exception rb_eArgError `fmode` contradicted (e.g. `"bt"`). * @exception rb_eSystemCallError `open(2)` failed for some reason. * @return An instance of ::rb_cIO. */ VALUE rb_file_open_str(VALUE fname, const char *fmode); /** * Much like rb_io_gets(), but it reads from the mysterious ARGF object. ARGF * in this context can be seen as a virtual IO which concatenates contents of * the files passed to the process via the ARGV, or just STDIN if there are no * such files. * * Unlike rb_io_gets() this function sets `$_`. * * @exception rb_eFrozenError ARGF resorts to STDIN but it is frozen. * @retval RUBY_Qnil ARGF is at EOF. * @retval otherwise An instance of ::rb_cString. * @post ARGF is read. * @post `$_` is set. * * @internal * * In reality, this function can call `ARGF.gets`. Its redefinition can affect * the behaviour. * * Also, you can tamper ARGV on-the-fly in middle of ARGF usages: * * ``` * gets # Reads the first file. * ARGV << '/proc/self/limits' # Adds a file. * gets # Can read from /proc/self/limits. * ``` */ VALUE rb_gets(void); RBIMPL_ATTR_NONNULL(()) /** * Writes the given error message to somewhere applicable. On Windows it goes * to the console. On POSIX environments it goes to the standard error. * * @warning IT IS A BAD IDEA to use this function form your C extensions. * It is often annoying when GUI applications write to consoles; * users don't want to look at there. Programmers also want to * control the cause of the message itself, like by rescuing an * exception. Just let ruby handle errors. That must be better than * going your own way. * * @param[in] str Error message to display. * @post `str` is written to somewhere. * * @internal * * AFAIK this function is listed here without marked deprecated because there * are usages of this function in the wild. */ void rb_write_error(const char *str); /** * Identical to rb_write_error(), except it additionally takes the message's * length. Necessary when you want to handle wide characters. * * @param[in] str Error message to display. * @param[in] len Length of `str`, in bytes. * @post `str` is written to somewhere. */ void rb_write_error2(const char *str, long len); /** * Closes everything. In case of POSIX environments, a child process inherits * its parent's opened file descriptors. Which is nowadays considered as one * of the UNIX mistakes. This function closes such inherited file descriptors. * When your C extension needs to have a child process, don't forget to call * this from your child process right before exec. * * @param[in] lowfd Lower bound of FDs (you want STDIN to remain, no?). * @param[in] maxhint Hint of max FDs. * @param[in] noclose_fds A hash, whose keys are an allowlist. * * @internal * * As of writing, in spite of the name, this function does not actually close * anything. It just sets `FD_CLOEXEC` for everything and let `execve(2)` to * atomically close them at once. This is because as far as we know there are * no such platform that has `fork(2)` but lacks `FD_CLOEXEC`. * * Because this function is expected to run on a forked process it is entirely * async-signal-safe. */ void rb_close_before_exec(int lowfd, int maxhint, VALUE noclose_fds); RBIMPL_ATTR_NONNULL(()) /** * This is an rb_cloexec_pipe() + rb_update_max_fd() combo. * * @param[out] pipes Return buffer. Must at least hold 2 elements. * @retval 0 Successful creation of a pipe. * @retval -1 Failure in underlying system call(s). * @post `pipes` is filled with file descriptors. * @post `errno` is set on failure. */ int rb_pipe(int *pipes); /** * Queries if the given FD is reserved or not. Occasionally Ruby interpreter * opens files for its own purposes. Use this function to prevent touching * such behind-the-scene descriptors. * * @param[in] fd Target file descriptor. * @retval 1 `fd` is reserved. * @retval 0 Otherwise. */ int rb_reserved_fd_p(int fd); /** @alias{rb_reserved_fd_p} */ #define RB_RESERVED_FD_P(fd) rb_reserved_fd_p(fd) /** * Opens a file that closes on exec. In case of POSIX environments, a child * process inherits its parent's opened file descriptors. Which is nowadays * considered as one of the UNIX mistakes. This function opens a file * descriptor as `open(2)` does, but additionally instructs the operating * system that we don't want it be seen from child processes. * * @param[in] pathname File path to open. * @param[in] flags Open mode, as in `open(2)`. * @param[in] mode File mode, in case of `O_CREAT`. * @retval -1 `open(2)` failed for some reason. * @retval otherwise An allocated new file descriptor. * @note This function does not raise. * * @internal * * Whether this function can take NULL or not depends on the underlying open(2) * system call implementation but @shyouhei doesn't think it's worth trying. */ int rb_cloexec_open(const char *pathname, int flags, mode_t mode); /** * Identical to rb_cloexec_fcntl_dupfd(), except it implies minfd is 3. * * @param[in] oldfd File descriptor to duplicate. * @retval -1 `dup2(2)` failed for some reason. * @retval otherwise An allocated new file descriptor. * @note This function does not raise. */ int rb_cloexec_dup(int oldfd); /** * Identical to rb_cloexec_dup(), except you can specify the destination file * descriptor. If the destination is already squatted by another file * descriptor that gets silently closed without any warnings. (This is a spec * requested by POSIX.) * * @param[in] oldfd File descriptor to duplicate. * @param[in] newfd Return value destination. * @retval -1 `dup2(2)` failed for some reason. * @retval newfd An allocated new file descriptor. * @post Whatever sat at `newfd` gets closed with no notifications. * @post In case return value is -1 `newfd` is untouched. * @note This function does not raise. */ int rb_cloexec_dup2(int oldfd, int newfd); RBIMPL_ATTR_NONNULL(()) /** * Opens a pipe with closing on exec. In case of POSIX environments, a child * process inherits its parent's opened file descriptors. Which is nowadays * considered as one of the UNIX mistakes. This function opens a pipe as * `pipe(2)` does, but additionally instructs the operating system that we * don't want the duplicated FDs be seen from child processes. * * @param[out] fildes Return buffer. Must at least hold 2 elements. * @retval 0 Successful creation of a pipe. * @retval -1 Failure in underlying system call(s). * @post `pipes` is filled with file descriptors. * @post `errno` is set on failure. */ int rb_cloexec_pipe(int fildes[2]); /** * Duplicates a file descriptor with closing on exec. In case of POSIX * environments, a child process inherits its parent's opened file descriptors. * Which is nowadays considered as one of the UNIX mistakes. This function * duplicates a file descriptor as `dup(2)` does, but additionally instructs * the operating system that we don't want the duplicated FD be seen from child * processes. * * @param[in] fd File descriptor to duplicate. * @param[in] minfd Minimum allowed FD to return. * @retval -1 `dup(2)` failed for some reason. * @retval otherwise An allocated new file descriptor. * @note This function does not raise. * * `minfd` is handy when for instance STDERR is closed but you don't want to * use fd 2. */ int rb_cloexec_fcntl_dupfd(int fd, int minfd); /** * Informs the interpreter that the passed fd can be the max. This information * is used from rb_close_before_exec(). * * @param[in] fd An open FD, which can be large. */ void rb_update_max_fd(int fd); /** * Sets or clears the close-on-exec flag of the passed file descriptor to the * desired state. STDIN, STDOUT, STDERR are the exceptional file descriptors * that shall remain open. All others are to be closed on exec. When a C * extension library opens a file descriptor using anything other than * rb_cloexec_open() etc., that file descriptor shall experience this function. * * @param[in] fd An open file descriptor. */ void rb_fd_fix_cloexec(int fd); RBIMPL_SYMBOL_EXPORT_END() #endif /* RBIMPL_INTERN_IO_H */ include/ruby/internal/intern/dir.h 0000644 00000003626 15152150474 0013225 0 ustar 00 #ifndef RBIMPL_INTERN_DIR_H /*-*-C++-*-vi:se ft=cpp:*/ #define RBIMPL_INTERN_DIR_H /** * @file * @author Ruby developers <ruby-core@ruby-lang.org> * @copyright This file is a part of the programming language Ruby. * Permission is hereby granted, to either redistribute and/or * modify this file, provided that the conditions mentioned in the * file COPYING are met. Consult the file for details. * @warning Symbols prefixed with either `RBIMPL` or `rbimpl` are * implementation details. Don't take them as canon. They could * rapidly appear then vanish. The name (path) of this header file * is also an implementation detail. Do not expect it to persist * at the place it is now. Developers are free to move it anywhere * anytime at will. * @note To ruby-core: remember that this header can be possibly * recursively included from extension libraries written in C++. * Do not expect for instance `__VA_ARGS__` is always available. * We assume C99 for ruby itself but we don't assume languages of * extension libraries. They could be written in C++98. * @brief Public APIs related to ::rb_cDir. */ #include "ruby/internal/dllexport.h" #include "ruby/internal/value.h" RBIMPL_SYMBOL_EXPORT_BEGIN() /* dir.c */ /** * Queries the path of the current working directory of the current process. * * @return An instance of ::rb_cString that holds the working directory. * @note The returned string is in "filesystem" encoding. Most notably on * Linux this is an alias of default external encoding. Most notably * on Windows it can be an alias of OS codepage. */ VALUE rb_dir_getwd(void); RBIMPL_SYMBOL_EXPORT_END() #endif /* RBIMPL_INTERN_DIR_H */ include/ruby/internal/intern/numeric.h 0000644 00000016770 15152150474 0014115 0 ustar 00 #ifndef RBIMPL_INTERN_NUMERIC_H /*-*-C++-*-vi:se ft=cpp:*/ #define RBIMPL_INTERN_NUMERIC_H /** * @file * @author Ruby developers <ruby-core@ruby-lang.org> * @copyright This file is a part of the programming language Ruby. * Permission is hereby granted, to either redistribute and/or * modify this file, provided that the conditions mentioned in the * file COPYING are met. Consult the file for details. * @warning Symbols prefixed with either `RBIMPL` or `rbimpl` are * implementation details. Don't take them as canon. They could * rapidly appear then vanish. The name (path) of this header file * is also an implementation detail. Do not expect it to persist * at the place it is now. Developers are free to move it anywhere * anytime at will. * @note To ruby-core: remember that this header can be possibly * recursively included from extension libraries written in C++. * Do not expect for instance `__VA_ARGS__` is always available. * We assume C99 for ruby itself but we don't assume languages of * extension libraries. They could be written in C++98. * @brief Public APIs related to ::rb_cNumeric. */ #include "ruby/internal/attr/cold.h" #include "ruby/internal/attr/noreturn.h" #include "ruby/internal/dllexport.h" #include "ruby/internal/value.h" /** * @private * * @deprecated This macro once was a thing in the old days, but makes no sense * any longer today. Exists here for backwards compatibility * only. You can safely forget about it. */ #define RB_NUM_COERCE_FUNCS_NEED_OPID 1 RBIMPL_SYMBOL_EXPORT_BEGIN() /* numeric.c */ RBIMPL_ATTR_NORETURN() RBIMPL_ATTR_COLD() /** * Just always raises an exception. * * @exception rb_eZeroDivError Division by zero error. */ void rb_num_zerodiv(void); /** * @name Coercion operators. * * What is a coercion? Well Ruby is basically an OOPL but it also has * arithmetic operators. They are implemented in OO manners. For instance * `a+b` is a binary operation `+`, whose receiver is `a`, and whose (sole) * argument is `b`. * * The problem is, you often want `a+b == b+a` to hold. That is easy if both * `a` and `b` belongs to the same class... Ensuring `1 + 2 == 2 + 1` is kind * of intuitive. But if you want `1.0 + 2 == 2 + 1.0`, things start getting * complicated. `1.0+2` is `Float#+`, while `2+1.0` is `Integer#+`. In order * to achieve the equality Float's and Integer's methods must agree with their * behaviours. * * Now. Floats versus Integers situation is still controllable because they * are both built-in. But in Ruby you can define your own numeric classes. * BigDecimal, which is a rubygems gem distributed along with the interpreter, * is one of such examples. Rational was another such example before. In * short you cannot create list of all possible combination of the classes that * could be the operand of `+` operator. Then how do we achieve the * commutativity? * * Here comes the concept of coercion. If a definition of an operator * encounters an object which is unknown to the author, just assumes that the * unknown object knows how to handle the situation. So for instance when * `1+x` has unknown `x`, it lets the `x` handle this. * * ```ruby * class Foo * def +(x) * if we_know_what_is_x? then * ... # handle here * else * y, z = x.coerce self * return y + z * end * end * end * ``` * * The `x.coerce` method returns a 2-element array which are "casted" versions * of `x` and `self`. * * @{ */ /** * Coerced binary operation. This function first coerces the two objects, then * applies the operation. * * @param[in] lhs LHS operand. * @param[in] rhs RHS operand. * @param[in] op Operator method name. * @exception rb_eTypeError Coercion failed for some reason. * @return `lhs op rhs`, in a coerced way. */ VALUE rb_num_coerce_bin(VALUE lhs, VALUE rhs, ID op); /** * Identical to rb_num_coerce_bin(), except for return values. This function * best suits for comparison operators e.g. `<=>`. * * @param[in] lhs LHS operand. * @param[in] rhs RHS operand. * @param[in] op Operator method name. * @retval RUBY_Qnil Coercion failed for some reason. * @retval otherwise `lhs op rhs`, in a coerced way. */ VALUE rb_num_coerce_cmp(VALUE lhs, VALUE rhs, ID op); /** * Identical to rb_num_coerce_cmp(), except for return values. This function * best suits for relationship operators e.g. `<=`. * * @param[in] lhs LHS operand. * @param[in] rhs RHS operand. * @param[in] op Operator method name. * @exception rb_eArgError Coercion failed for some reason. * @return `lhs op rhs`, in a coerced way. */ VALUE rb_num_coerce_relop(VALUE lhs, VALUE rhs, ID op); /** * This one is optimised for bitwise operations, but the API is identical to * rb_num_coerce_bin(). * * @param[in] lhs LHS operand. * @param[in] rhs RHS operand. * @param[in] op Operator method name. * @exception rb_eArgError Coercion failed for some reason. * @return `lhs op rhs`, in a coerced way. */ VALUE rb_num_coerce_bit(VALUE lhs, VALUE rhs, ID op); /** @} */ /** * Converts a numeric value into a Fixnum. This is not a preserving * conversion; for instance 1.5 would be converted into 1. * * @param[in] val A numeric object. * @exception rb_eTypeError No conversion from `val` to Integer. * @exception rb_eRangeError `val` out of range. * @return A fixnum converted from `val`. * * @internal * * This seems used from nowhere? */ VALUE rb_num2fix(VALUE val); /** * Generates a place-value representation of the given Fixnum, with given * radix. * * @param[in] val A fixnum to stringify. * @param[in] base `2` to `36` inclusive for each radix. * @exception rb_eArgError `base` is out of range. * @return An instance of ::rb_cString representing `val`. * @pre `val` must be a Fixnum (no checks performed). */ VALUE rb_fix2str(VALUE val, int base); RBIMPL_ATTR_CONST() /** * Compares two `double`s. Handy when implementing a spaceship operator. * * @param[in] lhs A value. * @param[in] rhs Another value. * @retval RB_INT2FIX(-1) `lhs` is "bigger than" `rhs`. * @retval RB_INT2FIX(1) `rhs` is "bigger than" `lhs`. * @retval RB_INT2FIX(0) They are equal. * @retval RUBY_Qnil Not comparable, e.g. NaN. */ VALUE rb_dbl_cmp(double lhs, double rhs); /** * Raises the passed `x` to the power of `y`. * * @note The return value can be really big. * @note Also the return value can be really small, in case `x` is a * negative number. * @param[in] x A number. * @param[in] y Another number. * @retval Inf Cannot express the result. * @retval 1 Either `y` is 0 or `x` is 1. * @retval otherwise An instance of ::rb_cInteger whose value is `x ** y`. * * @internal * * This function returns Infinity when `y` is big enough not to fit into a * Fixnum. Warning is issued then. */ RUBY_EXTERN VALUE rb_int_positive_pow(long x, unsigned long y); RBIMPL_SYMBOL_EXPORT_END() #endif /* RBIMPL_INTERN_NUMERIC_H */ include/ruby/internal/intern/rational.h 0000644 00000014533 15152150474 0014257 0 ustar 00 #ifndef RBIMPL_INTERN_RATIONAL_H /*-*-C++-*-vi:se ft=cpp:*/ #define RBIMPL_INTERN_RATIONAL_H /** * @file * @author Ruby developers <ruby-core@ruby-lang.org> * @copyright This file is a part of the programming language Ruby. * Permission is hereby granted, to either redistribute and/or * modify this file, provided that the conditions mentioned in the * file COPYING are met. Consult the file for details. * @warning Symbols prefixed with either `RBIMPL` or `rbimpl` are * implementation details. Don't take them as canon. They could * rapidly appear then vanish. The name (path) of this header file * is also an implementation detail. Do not expect it to persist * at the place it is now. Developers are free to move it anywhere * anytime at will. * @note To ruby-core: remember that this header can be possibly * recursively included from extension libraries written in C++. * Do not expect for instance `__VA_ARGS__` is always available. * We assume C99 for ruby itself but we don't assume languages of * extension libraries. They could be written in C++98. * @brief Public APIs related to ::rb_cRational. */ #include "ruby/internal/attr/pure.h" #include "ruby/internal/dllexport.h" #include "ruby/internal/value.h" #include "ruby/internal/arithmetic/long.h" /* INT2FIX is here. */ RBIMPL_SYMBOL_EXPORT_BEGIN() /* rational.c */ /** * Identical to rb_rational_new(), except it skips argument validations. It is * thus dangerous for extension libraries. For instance `1/0r` could be * constructed using this. * * @param[in] num Numerator, an instance of ::rb_cInteger. * @param[in] den Denominator, an instance of ::rb_cInteger. * @exception rb_eTypeError Either argument is not an Integer. * @return An instance of ::rb_cRational whose value is `(num/den)r`. */ VALUE rb_rational_raw(VALUE num, VALUE den); /** * Shorthand of `(x/1)r`. As `x` is already an Integer, it practically * converts it into a Rational of the identical value. * * @param[in] x An instance of ::rb_cInteger. * @return An instance of ::rb_cRational, whose value is `(x/1)r`. */ #define rb_rational_raw1(x) rb_rational_raw((x), INT2FIX(1)) /** @alias{rb_rational_raw} */ #define rb_rational_raw2(x,y) rb_rational_raw((x), (y)) /** * Constructs a Rational, with reduction. This returns for instance `(2/3)r` * for `rb_rational_new(INT2NUM(-384), INT2NUM(-576))`. * * @param[in] num Numerator, an instance of ::rb_cInteger. * @param[in] den Denominator, an instance of ::rb_cInteger. * @exception rb_eZeroDivError `den` is zero. * @return An instance of ::rb_cRational whose value is `(num/den)r`. */ VALUE rb_rational_new(VALUE num, VALUE den); /** * Shorthand of `(x/1)r`. As `x` is already an Integer, it practically * converts it into a Rational of the identical value. * * @param[in] x An instance of ::rb_cInteger. * @return An instance of ::rb_cRational, whose value is `(x/1)r`. */ #define rb_rational_new1(x) rb_rational_new((x), INT2FIX(1)) /** @alias{rb_rational_new} */ #define rb_rational_new2(x,y) rb_rational_new((x), (y)) /** * Converts various values into a Rational. This function accepts: * * - Instances of ::rb_cInteger (taken as-is), * - Instances of ::rb_cRational (taken as-is), * - Instances of ::rb_cFloat (applies `#to_r`), * - Instances of ::rb_cComplex (applies `#to_r`), * - Instances of ::rb_cString (applies `#to_r`), * - Other objects that respond to `#to_r`. * * It (possibly recursively) applies `#to_r` until both sides become either * Integer or Rational, then divides them. * * As a special case, passing ::RUBY_Qundef to `den` is the same as passing * `RB_INT2NUM(1)`. * * @param[in] num Numerator (see above). * @param[in] den Denominator (see above). * @exception rb_eTypeError Passed something not described above. * @exception rb_eFloatDomainError `#to_r` produced Nan/Inf. * @exception rb_eZeroDivError `#to_r` produced zero for `den`. * @return An instance of ::rb_cRational whose value is `(num/den)r`. * * @internal * * This was the implementation of `Kernel#Rational` before, but they diverged. */ VALUE rb_Rational(VALUE num, VALUE den); /** * Shorthand of `(x/1)r`. It practically converts it into a Rational of the * identical value. * * @param[in] x ::rb_cInteger, ::rb_cRational, or something that responds to * `#to_r`. * @return An instance of ::rb_cRational, whose value is `(x/1)r`. */ #define rb_Rational1(x) rb_Rational((x), INT2FIX(1)) /** @alias{rb_Rational} */ #define rb_Rational2(x,y) rb_Rational((x), (y)) RBIMPL_ATTR_PURE() /** * Queries the numerator of the passed Rational. * * @param[in] rat An instance of ::rb_cRational. * @return Its numerator part, which is an instance of ::rb_cInteger. */ VALUE rb_rational_num(VALUE rat); RBIMPL_ATTR_PURE() /** * Queries the denominator of the passed Rational. * * @param[in] rat An instance of ::rb_cRational. * @return Its denominator part, which is an instance of ::rb_cInteger * greater than or equal to one.. */ VALUE rb_rational_den(VALUE rat); /** * Simplified approximation of a float. It returns a rational `rat` which * satisfies: * * ``` * flt - |prec| <= rat <= flt + |prec| * ``` * * ```ruby * 3.141592.rationalize(0.001) # => (201/64)r * 3.141592.rationalize(0.01)' # => (22/7)r * 3.141592.rationalize(0.1)' # => (16/5)r * 3.141592.rationalize(1)' # => (3/1)r * ``` * * @param[in] flt An instance of ::rb_cFloat to rationalise. * @param[in] prec Another ::rb_cFloat, which is the "precision". * @return Approximation of `flt`, in ::rb_cRational. */ VALUE rb_flt_rationalize_with_prec(VALUE flt, VALUE prec); /** * Identical to rb_flt_rationalize_with_prec(), except it auto-detects * appropriate precision depending on the passed value. * * @param[in] flt An instance of ::rb_cFloat to rationalise. * @return Approximation of `flt`, in ::rb_cRational. */ VALUE rb_flt_rationalize(VALUE flt); RBIMPL_SYMBOL_EXPORT_END() #endif /* RBIMPL_INTERN_RATIONAL_H */ include/ruby/internal/intern/process.h 0000644 00000026461 15152150474 0014127 0 ustar 00 #ifndef RBIMPL_INTERN_PROCESS_H /*-*-C++-*-vi:se ft=cpp:*/ #define RBIMPL_INTERN_PROCESS_H /** * @file * @author Ruby developers <ruby-core@ruby-lang.org> * @copyright This file is a part of the programming language Ruby. * Permission is hereby granted, to either redistribute and/or * modify this file, provided that the conditions mentioned in the * file COPYING are met. Consult the file for details. * @warning Symbols prefixed with either `RBIMPL` or `rbimpl` are * implementation details. Don't take them as canon. They could * rapidly appear then vanish. The name (path) of this header file * is also an implementation detail. Do not expect it to persist * at the place it is now. Developers are free to move it anywhere * anytime at will. * @note To ruby-core: remember that this header can be possibly * recursively included from extension libraries written in C++. * Do not expect for instance `__VA_ARGS__` is always available. * We assume C99 for ruby itself but we don't assume languages of * extension libraries. They could be written in C++98. * @brief Public APIs related to ::rb_mProcess. */ #include "ruby/internal/attr/nonnull.h" #include "ruby/internal/attr/noreturn.h" #include "ruby/internal/config.h" /* rb_pid_t is defined here. */ #include "ruby/internal/dllexport.h" #include "ruby/internal/value.h" RBIMPL_SYMBOL_EXPORT_BEGIN() /* process.c */ /** * Wait for the specified process to terminate, reap it, and return its status. * * @param[in] pid The process ID to wait for. * @param[in] flags The flags to pass to waitpid(2). * @return VALUE An instance of Process::Status. */ VALUE rb_process_status_wait(rb_pid_t pid, int flags); /** * Sets the "last status", or the `$?`. * * @param[in] status The termination status, as defined in `waitpid(3posix)`. * @param[in] pid The last child of the current process. * @post `$?` is updated. */ void rb_last_status_set(int status, rb_pid_t pid); /** * Queries the "last status", or the `$?`. * * @retval RUBY_Qnil The current thread has no dead children. * @retval otherwise An instance of Process::Status describing the status of * the child that was most recently `wait`-ed. */ VALUE rb_last_status_get(void); RBIMPL_ATTR_NONNULL(()) /** * Executes a shell command. * * @warning THIS FUNCTION RETURNS on error! * @param[in] cmd Passed to the shell. * @retval -1 Something prevented the command execution. * @post Upon successful execution this function doesn't return. * @post In case it returns the `errno` is set properly. */ int rb_proc_exec(const char *cmd); RBIMPL_ATTR_NORETURN() /** * Replaces the current process by running the given external command. This is * the implementation of `Kernel#exec`. * * @param[in] argc Number of objects in `argv`. * @param[in] argv Command and its options to execute. * @exception rb_eTypeError Invalid options e.g. non-String argv. * @exception rb_eArgError Invalid options e.g. redirection cycle. * @exception rb_eNotImpError Not implemented e.g. no `setuid(2)`. * @exception rb_eRuntimeError `Process::UID.switch` in operation. * @exception rb_eSystemCallError `execve(2)` failed. * @warning This function doesn't return. * @warning On failure it raises. On success the process is replaced. * * @internal * * @shyouhei have to say that the rdoc for `Kernel#exec` is fairly incomplete. * AFAIK this function ultimately takes the following signature: * * ```rbs * type boolx = bool | nil # != `boolish` * * type rlim_t = Integer # rlim_cur * | [ Integer, Integer ] # rlim_cur, rlim_max * * type uid_t = String # e.g. "root" * | Integer # e.g. 0 * * type gid_t = String # e.g. "wheel" * | Integer # e.g. 0 * * type fmode = String # e.g. "rb" * | Integer # e.g. O_RDONLY | O_BINARY * * type mode_t = Integer # e.g. 0644 * * type pgrp = true # Creates a dedicated pgroup * | 0 # ditto * | nil # Uses the current one * | Integer # Uses this specific pgroup * * type fd = :in # STDIN * | :out # STDOUT * | :err # STDERR * | IO # This specific IO * | Integer # A file descriptor of this # * * type src = fd | [ fd ] * type dst = :close # Intuitive * | fd # Intuitive * | String # Open a file at this path * | [ String ] # ... using O_RDONLY * | [ String, fmode ] # ... using this mode * | [ String, fmode, mode_t ] # ... with a permission * | [ :child, fd ] # fd of child side * * type redir = Hash[ src, dst ] * * # ---- * * # Key-value pair of environment variables * type envp = Hash[ String, String ] * * # Actual name (and the name passed to the subprocess if any) * type arg0 = String | [ String, String ] * * # Arbitrary string parameters * type argv = String * * # Exec options: * type argh = redir | { * chdir: String, # Working directory * close_others: boolx, # O_CLOEXEC like behaviour * gid: gid_t, # setegid(2) * pgrooup: pgrp, # setpgrp(2) * rlimit_as: rlim_t, # setrlimit(2) * rlimit_core: rlim_t, # ditto * rlimit_cpu: rlim_t, # ditto * rlimit_data: rlim_t, # ditto * rlimit_fsize: rlim_t, # ditto * rlimit_memlock: rlim_t, # ditto * rlimit_msgqueue: rlim_t, # ditto * rlimit_nice: rlim_t, # ditto * rlimit_nofile: rlim_t, # ditto * rlimit_nproc: rlim_t, # ditto * rlimit_rss: rlim_t, # ditto * rlimit_rtprio: rlim_t, # ditto * rlimit_rttime: rlim_t, # ditto * rlimit_sbsize: rlim_t, # ditto * rlimit_sigpending: rlim_t, # ditto * rlimit_stack: rlim_t, # ditto * uid: uid_t, # seteuid(2) * umask: mode_t, # umask(2) * unsetenv_others: boolx # Unset everything except the passed envp * } * * # ==== * * class Kernel * def self?.exec * : ( arg0 cmd, *argv args ) -> void * | ( arg0 cmd, *argv args, argh opts) -> void * | (envp env, arg0 cmd, *argv args ) -> void * | (envp env, arg0 cmd, *argv args, argh opts) -> void * end * ``` */ VALUE rb_f_exec(int argc, const VALUE *argv); /** * Waits for a process, with releasing GVL. * * @param[in] pid Process ID. * @param[out] status The wait status is filled back. * @param[in] flags Wait options. * @retval -1 System call failed, errno set. * @retval 0 WNOHANG but no waitable children. * @retval otherwise A process ID that was `wait()`-ed. * @post Upon successful return `status` is updated to have the process' * status. * @note `status` can be NULL. * @note The arguments are passed through to underlying system call(s). * Can have special meanings. For instance passing `(rb_pid_t)-1` * to `pid` means it waits for any processes, under * POSIX-compliant situations. */ rb_pid_t rb_waitpid(rb_pid_t pid, int *status, int flags); /** * This is a shorthand of rb_waitpid without status and flags. It has been * like this since the very beginning. The initial revision already did the * same thing. Not sure why, then, it has been named `syswait`. AFAIK this is * different from how `wait(3posix)` works. * * @param[in] pid Passed to rb_waitpid(). */ void rb_syswait(rb_pid_t pid); /** * Identical to rb_f_exec(), except it spawns a child process instead of * replacing the current one. * * @param[in] argc Number of objects in `argv`. * @param[in] argv Command and its options to execute. * @exception rb_eTypeError Invalid options e.g. non-String argv. * @exception rb_eArgError Invalid options e.g. redirection cycle. * @exception rb_eNotImpError Not implemented e.g. no `setuid(2)`. * @exception rb_eRuntimeError `Process::UID.switch` in operation. * @retval -1 Child process died for some reason. * @retval otherwise The ID of the born child. * * @internal * * This is _really_ identical to rb_f_exec() until ultimately calling the * system call. Almost everything are shared among these two (and * rb_f_system()). */ rb_pid_t rb_spawn(int argc, const VALUE *argv); /** * Identical to rb_spawn(), except you can additionally know the detailed * situation in case of abnormal parturitions. * * @param[in] argc Number of objects in `argv`. * @param[in] argv Command and its options to execute. * @param[out] errbuf Error description write-back buffer. * @param[in] buflen Number of bytes of `errbuf`, including NUL. * @exception rb_eTypeError Invalid options e.g. non-String argv. * @exception rb_eArgError Invalid options e.g. redirection cycle. * @exception rb_eNotImpError Not implemented e.g. no `setuid(2)`. * @exception rb_eRuntimeError `Process::UID.switch` in operation. * @retval -1 Child process died for some reason. * @retval otherwise The ID of the born child. * @post In case of `-1`, at most `buflen` bytes of the reason why is * written back to `errbuf`. */ rb_pid_t rb_spawn_err(int argc, const VALUE *argv, char *errbuf, size_t buflen); /** * Gathers info about resources consumed by the current process. * * @param[in] _ Not used. Pass anything. * @return An instance of `Process::Tms`. * * @internal * * This function might or might not exist depending on `./configure` result. * It must be a portability hell. Better not use. */ VALUE rb_proc_times(VALUE _); /** * "Detaches" a subprocess. In POSIX systems every child processes that a * process creates must be `wait(2)`-ed. A child process that died yet has not * been waited so far is called a "zombie", which more or less consumes * resources. This function automates reclamation of such processes. Once * after this function successfully returns you can basically forget about the * child process. * * @param[in] pid Process to wait. * @return An instance of ::rb_cThread which is `waitpid(2)`-ing `pid`. * @post You can just forget about the return value. GC reclaims it. * @post You can know the exit status by querying `#value` of the * return value (which is a blocking operation). */ VALUE rb_detach_process(rb_pid_t pid); RBIMPL_SYMBOL_EXPORT_END() #endif /* RBIMPL_INTERN_PROCESS_H */ include/ruby/internal/intern/signal.h 0000644 00000014623 15152150474 0013723 0 ustar 00 #ifndef RBIMPL_INTERN_SIGNAL_H /*-*-C++-*-vi:se ft=cpp:*/ #define RBIMPL_INTERN_SIGNAL_H /** * @file * @author Ruby developers <ruby-core@ruby-lang.org> * @copyright This file is a part of the programming language Ruby. * Permission is hereby granted, to either redistribute and/or * modify this file, provided that the conditions mentioned in the * file COPYING are met. Consult the file for details. * @warning Symbols prefixed with either `RBIMPL` or `rbimpl` are * implementation details. Don't take them as canon. They could * rapidly appear then vanish. The name (path) of this header file * is also an implementation detail. Do not expect it to persist * at the place it is now. Developers are free to move it anywhere * anytime at will. * @note To ruby-core: remember that this header can be possibly * recursively included from extension libraries written in C++. * Do not expect for instance `__VA_ARGS__` is always available. * We assume C99 for ruby itself but we don't assume languages of * extension libraries. They could be written in C++98. * @brief Signal handling APIs. */ #include "ruby/internal/attr/nonnull.h" #include "ruby/internal/attr/pure.h" #include "ruby/internal/dllexport.h" #include "ruby/internal/value.h" RBIMPL_SYMBOL_EXPORT_BEGIN() /* signal.c */ RBIMPL_ATTR_NONNULL(()) /** * Sends a signal ("kills") to processes. * * The first argument is the signal, either in: * * - Numerical representation (e.g. `9`), or * - Textual representation of canonical (e.g. `:SIGKILL`) name or * abbreviated (e.g. `:KILL`) name, either in ::rb_cSymbol or ::rb_cString. * * All the remaining arguments are numerical representations of process IDs. * This function iterates over them to send the specified signal. * * You can specify both negative PIDs and negative signo to this function: * * ``` * sig \ pid | >= 1 | == 0 | == -1 | <= -2 * ===========+======+======+=======+======= * > 0 | #1 | #2 | #3 | #4 * == 0 | #5 | #6 | #7 | #8 * < 0 | #9 | #10 | #11 * ``` * * - Case #1: When signo and PID are both positive, this function sends the * specified signal to the specified process (intuitive). * * - Case #2: When signo is positive and PID is zero, this function sends * that signal to the current process group. * * - Case #3: When signo is positive and PID is -1, this function sends that * signal to everything that the current process is allowed to kill. * * - Case #4: When signo is positive and PID is negative (but not -1), this * function sends that signal to every processes in a process group, whose * process group ID is the absolute value of the passed PID. * * - Case #5: When signo is zero and PID is positive, this function just * checks for the existence of the specified process and doesn't send * anything to anyone. In case the process is absent `Errno::ESRCH` is * raised. * * - Case #6: When signo and PID are both zero, this function checks for the * existence of the current process group. And it must do. This function * is effectively a no-op then. * * - Case #7: When signo is zero and PID is -1, this function checks if there * is any other process that the current process can kill. At least init * (PID 1) must exist, so this must not fail. * * - Case #8: When signo is zero and PID is negative (but not -1), this * function checks if there is a process group whose process group ID is * the absolute value of the passed PID. In case the process group is * absent `Errno::ESRCH` is raised. * * - Case #9: When signo is negative and PID is positive, this function sends * the absolute value of the passed signo to the process group specified as * the PID. * * - Case #10: When signo is negative and PID is zero, it is highly expected * that this function sends the absolute value of the passed signo to the * current process group. Strictly speaking, IEEE Std 1003.1-2017 * specifies that this (`killpg(3posix)` with an argument of zero) is an * undefined behaviour. But no operating system is known so far that does * things differently. * * - Case #11: When signo and PID are both negative, the behaviour of this * function depends on how `killpg(3)` works. On Linux, it seems such * attempt is strictly prohibited and `Errno::EINVAL` is raised. But on * macOS, it seems it tries to to send the signal actually to the process * group. * * @note Above description is in fact different from how `kill(2)` works. * We interpret the passed arguments before passing them through to * system calls. * @param[in] argc Number of objects in `argv`. * @param[in] argv Signal, followed by target PIDs. * @exception rb_eArgError Unknown signal name. * @exception rb_eSystemCallError Various errors sending signal to processes. * @return Something numeric. The meaning of this return value is unclear. * It seems in case of #1 above, this could be the body count. But * other cases remain mysterious. */ VALUE rb_f_kill(int argc, const VALUE *argv); RBIMPL_ATTR_PURE() /** * Queries the name of the signal. It returns for instance `"KILL"` for * SIGKILL. * * @param[in] signo Signal number to query. * @retval 0 No such signal. * @retval otherwise A pointer to a static C string that is the name of * the signal. * @warning Don't free the return value. */ const char *ruby_signal_name(int signo); /** * Pretends as if there was no custom signal handler. This function sets the * signal action to SIG_DFL, then kills itself. * * @param[in] sig The signal. * @post Previous signal handler is lost. * @post Passed signal is sent to the current process. * * @internal * * @shyouhei doesn't understand the needs of this function being visible from * extension libraries. */ void ruby_default_signal(int sig); RBIMPL_SYMBOL_EXPORT_END() #endif /* RBIMPL_INTERN_SIGNAL_H */ include/ruby/internal/intern/struct.h 0000644 00000021362 15152150474 0013770 0 ustar 00 #ifndef RBIMPL_INTERN_STRUCT_H /*-*-C++-*-vi:se ft=cpp:*/ #define RBIMPL_INTERN_STRUCT_H /** * @file * @author Ruby developers <ruby-core@ruby-lang.org> * @copyright This file is a part of the programming language Ruby. * Permission is hereby granted, to either redistribute and/or * modify this file, provided that the conditions mentioned in the * file COPYING are met. Consult the file for details. * @warning Symbols prefixed with either `RBIMPL` or `rbimpl` are * implementation details. Don't take them as canon. They could * rapidly appear then vanish. The name (path) of this header file * is also an implementation detail. Do not expect it to persist * at the place it is now. Developers are free to move it anywhere * anytime at will. * @note To ruby-core: remember that this header can be possibly * recursively included from extension libraries written in C++. * Do not expect for instance `__VA_ARGS__` is always available. * We assume C99 for ruby itself but we don't assume languages of * extension libraries. They could be written in C++98. * @brief Public APIs related to ::rb_cStruct. */ #include "ruby/internal/attr/nonnull.h" #include "ruby/internal/dllexport.h" #include "ruby/internal/intern/vm.h" /* rb_alloc_func_t */ #include "ruby/internal/value.h" RBIMPL_SYMBOL_EXPORT_BEGIN() /* struct.c */ /** * Creates an instance of the given struct. * * @param[in] klass The class of the instance to allocate. * @param[in] ... The fields. * @return Allocated instance of `klass`. * @pre `klass` must be a subclass of ::rb_cStruct. * @note Number of variadic arguments must much that of the passed klass' * fields. */ VALUE rb_struct_new(VALUE klass, ...); /** * Defines a struct class. * * @param[in] name Name of the class. * @param[in] ... Arbitrary number of `const char*`, terminated by * NULL. Each of which are the name of fields. * @exception rb_eNameError `name` is not a constant name. * @exception rb_eTypeError `name` is already taken. * @exception rb_eArgError Duplicated field name. * @return The defined class. * @post Global toplevel constant `name` is defined. * @note `name` is allowed to be a null pointer. This function creates * an anonymous struct class then. * * @internal * * Not seriously checked but it seems this function does not share its * implementation with how `Struct.new` is implemented...? */ VALUE rb_struct_define(const char *name, ...); RBIMPL_ATTR_NONNULL((2)) /** * Identical to rb_struct_define(), except it defines the class under the * specified namespace instead of global toplevel. * * @param[out] space Namespace that the defining class shall reside. * @param[in] name Name of the class. * @param[in] ... Arbitrary number of `const char*`, terminated by * NULL. Each of which are the name of fields. * @exception rb_eNameError `name` is not a constant name. * @exception rb_eTypeError `name` is already taken. * @exception rb_eArgError Duplicated field name. * @return The defined class. * @post `name` is a constant under `space`. * @note In contrast to rb_struct_define(), it doesn't make any sense to * pass a null pointer to this function. */ VALUE rb_struct_define_under(VALUE space, const char *name, ...); /** * Identical to rb_struct_new(), except it takes the field values as a Ruby * array. * * @param[in] klass The class of the instance to allocate. * @param[in] values Field values. * @return Allocated instance of `klass`. * @pre `klass` must be a subclass of ::rb_cStruct. * @pre `values` must be an instance of struct ::RArray. */ VALUE rb_struct_alloc(VALUE klass, VALUE values); /** * Mass-assigns a struct's fields. * * @param[out] self An instance of a struct class to squash. * @param[in] values New values. * @return ::RUBY_Qnil. */ VALUE rb_struct_initialize(VALUE self, VALUE values); /** * Identical to rb_struct_aref(), except it takes ::ID instead of ::VALUE. * * @param[in] self An instance of a struct class. * @param[in] key Key to query. * @exception rb_eTypeError `self` is not a struct. * @exception rb_eNameError No such field. * @return The value stored at `key` in `self`. */ VALUE rb_struct_getmember(VALUE self, ID key); /** * Queries the list of the names of the fields of the given struct class. * * @param[in] klass A subclass of ::rb_cStruct. * @return The list of the names of the fields of `klass`. */ VALUE rb_struct_s_members(VALUE klass); /** * Queries the list of the names of the fields of the class of the given struct * object. This is almost the same as calling rb_struct_s_members() over the * class of the receiver. * * @internal * * "Almost"? What exactly is the difference? * * @endinternal * * @param[in] self An instance of a subclass of ::rb_cStruct. * @return The list of the names of the fields. */ VALUE rb_struct_members(VALUE self); /** * Allocates an instance of the given class. This consequential name is of * course because rb_struct_alloc() not only allocates but also initialises an * instance. The API design is broken. * * @param[in] klass A subclass of ::rb_cStruct. * @return An allocated instance of `klass`, not initialised. */ VALUE rb_struct_alloc_noinit(VALUE klass); /** * Identical to rb_struct_define(), except it does not define accessor methods. * You have to define them yourself. Forget about the allocator function * parameter; it is for internal use only. Extension libraries are unable to * properly allocate a ruby struct, because `RStruct` is opaque. * * @internal * * Several flags must be set up properly for ::RUBY_T_STRUCT objects, which are * also missing for extension libraries. * * @endinternal * * @param[in] name Name of the class. * @param[in] super Superclass of the defining class. * @param[in] func Must be 0 for extension libraries. * @param[in] ... Arbitrary number of `const char*`, terminated by * NULL. Each of which are the name of fields. * @exception rb_eNameError `name` is not a constant name. * @exception rb_eTypeError `name` is already taken. * @exception rb_eArgError Duplicated field name. * @return The defined class. * @post Global toplevel constant `name` is defined. * @note `name` is allowed to be a null pointer. This function creates * an anonymous struct class then. */ VALUE rb_struct_define_without_accessor(const char *name, VALUE super, rb_alloc_func_t func, ...); RBIMPL_ATTR_NONNULL((2)) /** * Identical to rb_struct_define_without_accessor(), except it defines the * class under the specified namespace instead of global toplevel. It can also * be seen as a routine identical to rb_struct_define_under(), except it does * not define accessor methods. * * @param[out] outer Namespace that the defining class shall reside. * @param[in] class_name Name of the class. * @param[in] super Superclass of the defining class. * @param[in] alloc Must be 0 for extension libraries. * @param[in] ... Arbitrary number of `const char*`, terminated by * NULL. Each of which are the name of fields. * @exception rb_eNameError `class_name` is not a constant name. * @exception rb_eTypeError `class_name` is already taken. * @exception rb_eArgError Duplicated field name. * @return The defined class. * @post `class_name` is a constant under `outer`. * @note In contrast to rb_struct_define_without_accessor(), it doesn't * make any sense to pass a null name. */ VALUE rb_struct_define_without_accessor_under(VALUE outer, const char *class_name, VALUE super, rb_alloc_func_t alloc, ...); /** * Defines an anonymous data class. * * @endinternal * * @param[in] super Superclass of the defining class. Must be a * descendant of ::rb_cData, or 0 as ::rb_cData. * @param[in] ... Arbitrary number of `const char*`, terminated by * NULL. Each of which are the name of fields. * @exception rb_eArgError Duplicated field name. * @return The defined class. */ VALUE rb_data_define(VALUE super, ...); RBIMPL_SYMBOL_EXPORT_END() #endif /* RBIMPL_INTERN_STRUCT_H */ include/ruby/internal/intern/object.h 0000644 00000046201 15152150474 0013711 0 ustar 00 #ifndef RBIMPL_INTERN_OBJECT_H /*-*-C++-*-vi:se ft=cpp:*/ #define RBIMPL_INTERN_OBJECT_H /** * @file * @author Ruby developers <ruby-core@ruby-lang.org> * @copyright This file is a part of the programming language Ruby. * Permission is hereby granted, to either redistribute and/or * modify this file, provided that the conditions mentioned in the * file COPYING are met. Consult the file for details. * @warning Symbols prefixed with either `RBIMPL` or `rbimpl` are * implementation details. Don't take them as canon. They could * rapidly appear then vanish. The name (path) of this header file * is also an implementation detail. Do not expect it to persist * at the place it is now. Developers are free to move it anywhere * anytime at will. * @note To ruby-core: remember that this header can be possibly * recursively included from extension libraries written in C++. * Do not expect for instance `__VA_ARGS__` is always available. * We assume C99 for ruby itself but we don't assume languages of * extension libraries. They could be written in C++98. * @brief Public APIs related to ::rb_cObject. */ #include "ruby/internal/attr/const.h" #include "ruby/internal/attr/deprecated.h" #include "ruby/internal/attr/nonnull.h" #include "ruby/internal/attr/pure.h" #include "ruby/internal/dllexport.h" #include "ruby/internal/value.h" RBIMPL_SYMBOL_EXPORT_BEGIN() /** * This macro is (used but) mysterious. Why on earth do we need this? * * - `obj != orig` check is done anyways inside of rb_obj_init_copy(). * - rb_obj_init_copy() returns something. No need are there to add `, 1`. */ #define RB_OBJ_INIT_COPY(obj, orig) \ ((obj) != (orig) && (rb_obj_init_copy((obj), (orig)), 1)) /** @old{RB_OBJ_INIT_COPY} */ #define OBJ_INIT_COPY(obj, orig) RB_OBJ_INIT_COPY(obj, orig) /* object.c */ /** * Identical to rb_class_new_instance(), except it passes the passed keywords * if any to the `#initialize` method. * * @param[in] argc Number of objects of `argv`. * @param[in] argv Arbitrary number of method arguments. * @param[in] klass An instance of ::rb_cClass. * @exception rb_eTypeError `klass`'s allocator is undefined. * @exception rb_eException Any exceptions can happen inside. * @return An allocated new instance of `klass`. * @note This is _the_ implementation of `Object.new`. */ VALUE rb_class_new_instance_pass_kw(int argc, const VALUE *argv, VALUE klass); /** * Allocates, then initialises an instance of the given class. It first calls * the passed class' allocator to obtain an uninitialised object, then calls * its initialiser with the remaining arguments. * * @param[in] argc Number of objects of `argv`. * @param[in] argv Arguments passed to `#initialize`. * @param[in] klass An instance of ::rb_cClass. * @exception rb_eTypeError `klass`'s allocator is undefined. * @exception rb_eException Any exceptions can happen inside. * @return An allocated new instance of `klass`. */ VALUE rb_class_new_instance(int argc, const VALUE *argv, VALUE klass); /** * Identical to rb_class_new_instance(), except you can specify how to handle * the last element of the given array. * * @param[in] argc Number of objects of `argv`. * @param[in] argv Arbitrary number of method arguments. * @param[in] klass An instance of ::rb_cClass. * @param[in] kw_splat Handling of keyword parameters: * - RB_NO_KEYWORDS `argv`'s last is not a keyword argument. * - RB_PASS_KEYWORDS `argv`'s last is a keyword argument. * - RB_PASS_CALLED_KEYWORDS it depends if there is a passed block. * @exception rb_eTypeError `klass`'s allocator is undefined. * @exception rb_eException Any exceptions can happen inside. * @return An allocated new instance of `klass`. */ VALUE rb_class_new_instance_kw(int argc, const VALUE *argv, VALUE klass, int kw_splat); /** * Checks for equality of the passed objects, in terms of `Object#eql?`. * * @param[in] lhs Comparison left hand side. * @param[in] rhs Comparison right hand side. * @retval non-zero They are equal. * @retval 0 Otherwise. * @note This function actually calls `lhs.eql?(rhs)` so you cannot * implement your class' `#eql?` method using it. */ int rb_eql(VALUE lhs, VALUE rhs); /** * Generates a textual representation of the given object. * * @param[in] obj Arbitrary ruby object. * @return An instance of ::rb_cString that represents `obj`. * @note This is the default implementation of `Object#to_s` that each * subclasses want to override. */ VALUE rb_any_to_s(VALUE obj); /** * Generates a human-readable textual representation of the given object. This * is largely similar to Ruby level `Object#inspect` but not the same; it * additionally escapes the inspection result so that the string be compatible * with that of default internal (or default external, if absent). * * @param[in] obj Arbitrary ruby object. * @return An instance of ::rb_cString that represents `obj`. */ VALUE rb_inspect(VALUE obj); /** * Queries if the given object is a direct instance of the given class. * * @param[in] obj Arbitrary ruby object. * @param[in] klass An instance of ::rb_cModule. * @exception rb_eTypeError `klass` is neither module nor class. * @retval RUBY_Qtrue `obj` is an instance of `klass`. * @retval RUBY_Qfalse Otherwise. */ VALUE rb_obj_is_instance_of(VALUE obj, VALUE klass); /** * Queries if the given object is an instance (of possibly descendants) of the * given class. * * @param[in] obj Arbitrary ruby object. * @param[in] klass An instance of ::rb_cModule. * @exception rb_eTypeError `klass` is neither module nor class. * @retval RUBY_Qtrue `obj` is a `klass`. * @retval RUBY_Qfalse Otherwise. */ VALUE rb_obj_is_kind_of(VALUE obj, VALUE klass); /** * Allocates an instance of the given class. * * @param[in] klass A class to instantiate. * @exception rb_eTypeError `klass` is not a class. * @return An allocated, not yet initialised instance of `klass`. * @note It calls the allocator defined by rb_define_alloc_func(). You * cannot use this function to define an allocator. Use * rb_newobj_of(), #TypedData_Make_Struct or others, instead. * @note Usually prefer rb_class_new_instance() to rb_obj_alloc() and * rb_obj_call_init(). * @see rb_class_new_instance() * @see rb_obj_call_init() * @see rb_define_alloc_func() * @see rb_newobj_of() * @see #TypedData_Make_Struct */ VALUE rb_obj_alloc(VALUE klass); /** * Produces a shallow copy of the given object. Its list of instance variables * are copied, but not the objects they reference. It also copies the frozen * value state. * * @param[in] obj Arbitrary ruby object. * @exception rb_eException `#initialize_copy` can raise anything. * @return A "clone" of `obj`. * * @internal * * Unlike ruby-level `Object#clone`, there is no way to control the frozen-ness * of the return value. */ VALUE rb_obj_clone(VALUE obj); /** * Duplicates the given object. This does almost the same thing as * rb_obj_clone() do. However it does not copy the singleton class (if any). * It also doesn't copy frozen-ness. * * @param[in] obj Arbitrary ruby object. * @exception rb_eException `#initialize_copy` can raise anything. * @return A shallow copy of `obj`. */ VALUE rb_obj_dup(VALUE obj); /** * Default implementation of `#initialize_copy`, `#initialize_dup` and * `#initialize_clone`. It does almost nothing. Just raises exceptions for * checks. * * @param[in] dst The destination object. * @param[in] src The source object. * @exception rb_eFrozenError `dst` is frozen. * @exception rb_eTypeError `dst` and `src` have different classes. * @return Always returns `dst`. */ VALUE rb_obj_init_copy(VALUE src, VALUE dst); /** * Just calls rb_obj_freeze_inline() inside. Does this make any sens to * extension libraries? * * @param[out] obj Object to freeze. * @return Verbatim `obj`. */ VALUE rb_obj_freeze(VALUE obj); RBIMPL_ATTR_PURE() /** * Just calls RB_OBJ_FROZEN() inside. Does this make any sens to extension * libraries? * * @param[in] obj Object in question. * @retval RUBY_Qtrue Yes it is. * @retval RUBY_Qfalse No it isn't. */ VALUE rb_obj_frozen_p(VALUE obj); /* gc.c */ /** * Finds or creates an integer primary key of the given object. In the old * days this function was a purely arithmetic operation that maps the * underlying memory address where the object resides into a Ruby's integer. * Some time around 2.x this changed. It no longer relates its return values * to C level pointers. This function assigns some random number to the given * object if absent. The same number will be returned on all subsequent * requests. No two active objects share a number. * * @param[in] obj Arbitrary ruby object. * @return An instance of ::rb_cInteger which is an "identifier" of `obj`. * * @internal * * The "some random number" is in fact a monotonic-increasing process-global * unique integer, much like an `INTEGER AUTO_INCREMENT PRIMARY KEY` column in * a MySQL table. */ VALUE rb_obj_id(VALUE obj); RBIMPL_ATTR_CONST() /** * Identical to rb_obj_id(), except it hesitates from allocating a new instance * of ::rb_cInteger. rb_obj_id() could allocate ::RUBY_T_BIGNUM objects. That * allocation might perhaps impact negatively. On such situations, this * function instead returns one-shot temporary small integers that need no * allocations at all. The values are guaranteed unique at the moment, but no * future promise is made; could be reused. Use of this API should be very * instant. It is a failure to store the returned integer to somewhere else. * * In short it is difficult to use. * * @param[in] obj Arbitrary ruby object. * @return An instance of ::rb_cInteger unique at the moment. * * @internal * * This is roughly the old behaviour of rb_obj_id(). */ VALUE rb_memory_id(VALUE obj); /* object.c */ RBIMPL_ATTR_PURE() /** * Finds a "real" class. As the name implies there are class objects that are * surreal. This function takes a class, traverses its ancestry tree, and * returns its nearest ancestor which is neither a module nor a singleton * class. * * @param[in] klass An instance of ::rb_cClass. * @retval RUBY_Qfalse No real class in `klass`' ancestry tree. * @retval klass `klass` itself is a real class. * @retval otherwise Nearest ancestor of `klass` who is real. */ VALUE rb_class_real(VALUE klass); RBIMPL_ATTR_PURE() /** * Determines if the given two modules are relatives. * * @param[in] scion Possible subclass. * @param[in] ascendant Possible superclass. * @exception rb_eTypeError `ascendant` is not a module. * @retval RUBY_Qtrue `scion` inherits, or is equal to `ascendant`. * @retval RUBY_Qfalse `ascendant` inherits `scion`. * @retval RUBY_Qnil They are not relatives. */ VALUE rb_class_inherited_p(VALUE scion, VALUE ascendant); RBIMPL_ATTR_PURE() /** * Queries the parent of the given class. * * @param[in] klass A child class. * @exception rb_eTypeError `klass` is a `Class.allocate`. * @retval RUBY_Qfalse `klass` has no superclass. * @retval otherwise `klass`' superclass. * * @internal * * Is there any class except ::rb_cBasicObject, that has no superclass? */ VALUE rb_class_superclass(VALUE klass); RBIMPL_ATTR_NONNULL(()) /** * Converts an object into another type. Calls the specified conversion method * if necessary. * * @param[in] val An object to convert. * @param[in] type A value of enum ::ruby_value_type. * @param[in] name Name to display on error (e.g. "Array"). * @param[in] mid Conversion method (e.g. "to_ary"). * @exception rb_eTypeError Failed to convert. * @return An object of the specified type. */ VALUE rb_convert_type(VALUE val, int type, const char *name, const char *mid); RBIMPL_ATTR_NONNULL(()) /** * Identical to rb_convert_type(), except it returns ::RUBY_Qnil instead of * raising exceptions, in case of conversion failure. It still raises * exceptions for various reasons, like when the conversion method itself * raises, though. * * @param[in] val An object to convert. * @param[in] type A value of enum ::ruby_value_type. * @param[in] name Name to display on error (e.g. "Array"). * @param[in] mid Conversion method (e.g. "to_ary"). * @exception rb_eTypeError The `mid` does not generate `type`. * @retval RUBY_Qnil No conversion defined. * @retval otherwise An object of the specified type. */ VALUE rb_check_convert_type(VALUE val, int type, const char *name, const char *mid); RBIMPL_ATTR_NONNULL(()) /** * Identical to rb_check_convert_type(), except the return value type is fixed * to ::rb_cInteger. * * @param[in] val An object to convert. * @param[in] mid Conversion method (e.g. "to_ary"). * @exception rb_eTypeError The `mid` does not generate an integer. * @retval RUBY_Qnil No conversion defined. * @retval otherwise An instance of ::rb_cInteger. */ VALUE rb_check_to_integer(VALUE val, const char *mid); /** * This is complicated. * * - When the passed object is already an instance of ::rb_cFloat, just * returns it as-is. * * - When the passed object is something numeric, the function tries to * convert it using `#to_f` method. * * - If that conversion fails (this happens for instance when the numeric * is a complex) it returns ::RUBY_Qnil. * * - Otherwise returns the conversion result. * * - Otherwise it also returns ::RUBY_Qnil. * * @param[in] val An object to convert. * @retval RUBY_Qnil Conversion from `val` to float is undefined. * @retval otherwise Converted result. */ VALUE rb_check_to_float(VALUE val); /** * Identical to rb_check_to_int(), except it raises in case of conversion * mismatch. * * @param[in] val An object to convert. * @exception rb_eTypeError `#to_int` does not generate an integer. * @return An instance of ::rb_cInteger. */ VALUE rb_to_int(VALUE val); /** * Identical to rb_check_to_integer(), except it uses `#to_int` for conversion. * * @param[in] val An object to convert. * @exception rb_eTypeError `#to_int` does not return an integer. * @retval RUBY_Qnil No conversion defined. * @retval otherwise An instance of ::rb_cInteger. */ VALUE rb_check_to_int(VALUE val); /** * This is the logic behind `Kernel#Integer`. Numeric types are converted * directly, with floating point numbers being truncated. Strings are * interpreted strictly; only leading/trailing whitespaces, plus/minus sign, * radix indicators such as `0x`, digits, and underscores are allowed. * Anything else are converted by first trying `#to_int`, then `#to_i`. * * This is slightly stricter than `String#to_i`. * * @param[in] val An object to convert. * @exception rb_eArgError Malformed `val` passed. * @exception rb_eTypeError No conversion defined. * @return An instance of ::rb_cInteger. */ VALUE rb_Integer(VALUE val); /** * Identical to rb_check_to_float(), except it raises on error. * * @param[in] val An object to convert. * @exception rb_eTypeError No conversion defined. * @return An instance of ::rb_cFloat. */ VALUE rb_to_float(VALUE val); /** * This is the logic behind `Kernel#Float`. Numeric types are converted * directly to the nearest value that a Float can represent. Strings are * interpreted strictly; only leading/trailing whitespaces are allowed except * what `strtod` understands. Anything else are converted using `#to_f`. * * This is slightly stricter than `String#to_f`. * * @param[in] val An object to convert. * @exception rb_eArgError Malformed `val` passed. * @exception rb_eTypeError No conversion defined. * @return An instance of ::rb_cFloat. */ VALUE rb_Float(VALUE val); /** * This is the logic behind `Kernel#String`. Arguments are converted by first * trying `#to_str`, then `#to_s`. * * @param[in] val An object to convert. * @exception rb_eTypeError No conversion defined. * @return An instance of ::rb_cString. */ VALUE rb_String(VALUE val); /** * This is the logic behind `Kernel#Array`. Arguments are converted by first * trying `#to_ary`, then `#to_a`, and if both failed, returns an array of * length 1 that contains the passed argument as the sole contents. * * @param[in] val An object to convert. * @return An instance of ::rb_cArray. */ VALUE rb_Array(VALUE val); /** * This is the logic behind `Kernel#Hash`. Arguments are converted by first * trying `#to_hash`. if it failed, and the argument is either ::RUBY_Qnil or * an empty array, returns an empty hash. Otherwise an exception is raised. * * @param[in] val An object to convert. * @exception rb_eTypeError No conversion defined. * @return An instance of ::rb_cHash. */ VALUE rb_Hash(VALUE val); RBIMPL_ATTR_NONNULL(()) /** * Converts a textual representation of a real number into a numeric, which is * the nearest value that the return type can represent, of the value that the * argument represents. This is in fact a 2-in-1 function whose behaviour can * be controlled using the second (mode) argument. If the mode is zero, this * function is in "historical" mode which only understands "floating-constant" * defined at ISO/IEC 9899:1990 section 6.1.3.1. If the mode is nonzero, it is * in "extended" mode, which also accepts "hexadecimal-floating-constant" * defined at ISO/IEC 9899:2018 section 6.4.4.2. * * @param[in] str A textual representation of a real number. * @param[in] mode Conversion mode, as described above. * @exception rb_eArgError Malformed `str` passed. * @see https://bugs.ruby-lang.org/issues/2969 * @note Null pointers are allowed, and it returns 0.0 then. */ double rb_cstr_to_dbl(const char *str, int mode); /** * Identical to rb_cstr_to_dbl(), except it accepts a Ruby's string instead of * C's. * * @param[in] str A textual representation of a real number. * @param[in] mode Conversion mode, as described in rb_cstr_to_dbl(). * @exception rb_eArgError Malformed `str` passed. * @see https://bugs.ruby-lang.org/issues/2969 */ double rb_str_to_dbl(VALUE str, int mode); RBIMPL_SYMBOL_EXPORT_END() #endif /* RBIMPL_INTERN_OBJECT_H */ include/ruby/internal/intern/class.h 0000644 00000037263 15152150474 0013560 0 ustar 00 #ifndef RBIMPL_INTERN_CLASS_H /*-*-C++-*-vi:se ft=cpp:*/ #define RBIMPL_INTERN_CLASS_H /** * @file * @author Ruby developers <ruby-core@ruby-lang.org> * @copyright This file is a part of the programming language Ruby. * Permission is hereby granted, to either redistribute and/or * modify this file, provided that the conditions mentioned in the * file COPYING are met. Consult the file for details. * @warning Symbols prefixed with either `RBIMPL` or `rbimpl` are * implementation details. Don't take them as canon. They could * rapidly appear then vanish. The name (path) of this header file * is also an implementation detail. Do not expect it to persist * at the place it is now. Developers are free to move it anywhere * anytime at will. * @note To ruby-core: remember that this header can be possibly * recursively included from extension libraries written in C++. * Do not expect for instance `__VA_ARGS__` is always available. * We assume C99 for ruby itself but we don't assume languages of * extension libraries. They could be written in C++98. * @brief Public APIs related to ::rb_cClass/::rb_cModule. */ #include "ruby/internal/dllexport.h" #include "ruby/internal/value.h" #include "ruby/backward/2/stdarg.h" RBIMPL_SYMBOL_EXPORT_BEGIN() /* class.c */ /** * Creates a new, anonymous class. * * @param[in] super What would become a parent class. * @exception rb_eTypeError `super` is not something inheritable. * @return An anonymous class that inherits `super`. */ VALUE rb_class_new(VALUE super); /** * The comment that comes with this function says `:nodoc:`. Not sure what * that means though. * * @param[out] clone Destination object. * @param[in] orig Source object. * @exception rb_eTypeError Cannot copy `orig`. * @return The passed `clone`. */ VALUE rb_mod_init_copy(VALUE clone, VALUE orig); /** * Asserts that the given class can derive a child class. A class might or * might not be able to do so; for instance a singleton class cannot. * * @param[in] super Possible super class. * @exception rb_eTypeError No it cannot. * @post Upon successful return `super` can derive. */ void rb_check_inheritable(VALUE super); /** * This is a very badly designed API that creates an anonymous class. * * @param[in] id Discarded for no reason (why...). * @param[in] super What would become a parent class. 0 means * ::rb_cObject. * @exception rb_eTypeError `super` is not something inheritable. * @return An anonymous class that inherits `super`. * @warning You must explicitly name the return value. */ VALUE rb_define_class_id(ID id, VALUE super); /** * Identical to rb_define_class_under(), except it takes the name in ::ID * instead of C's string. * * @param[out] outer A class which contains the new class. * @param[in] id Name of the new class * @param[in] super A class from which the new class will derive. * 0 means ::rb_cObject. * @exception rb_eTypeError The constant name `id` is already taken but the * constant is not a class. * @exception rb_eTypeError The class is already defined but the class can * not be reopened because its superclass is not * `super`. * @exception rb_eArgError `super` is NULL. * @return The created class. * @post `outer::id` refers the returned class. * @note If a class named `id` is already defined and its superclass is * `super`, the function just returns the defined class. * @note The compaction GC does not move classes returned by this * function. */ VALUE rb_define_class_id_under(VALUE outer, ID id, VALUE super); /** * Creates a new, anonymous module. * * @return An anonymous module. */ VALUE rb_module_new(void); /** * Creates a new, anonymous refinement. * * @return An anonymous refinement. */ VALUE rb_refinement_new(void); /** * This is a very badly designed API that creates an anonymous module. * * @param[in] id Discarded for no reason (why...). * @return An anonymous module. * @warning You must explicitly name the return value. */ VALUE rb_define_module_id(ID id); /** * Identical to rb_define_module_under(), except it takes the name in ::ID * instead of C's string. * * @param[out] outer A class which contains the new module. * @param[in] id Name of the new module * @exception rb_eTypeError The constant name `id` is already taken but the * constant is not a module. * @return The created module. * @post `outer::id` refers the returned module. * @note The compaction GC does not move classes returned by this * function. */ VALUE rb_define_module_id_under(VALUE outer, ID id); /** * Queries the list of included modules. It can also be seen as a routine to * first call rb_mod_ancestors(), then rejects non-modules from the return * value. * * @param[in] mod Class or Module. * @return An array of modules that are either included or prepended in any * of `mod`'s ancestry tree (including itself). */ VALUE rb_mod_included_modules(VALUE mod); /** * Queries if the passed module is included by the module. It can also be seen * as a routine to first call rb_mod_included_modules(), then see if the return * value contains the passed module. * * @param[in] child A Module. * @param[in] parent Another Module. * @exception rb_eTypeError `child` is not an instance of ::rb_cModule. * @retval RUBY_Qtrue `parent` is either included or prepended in any * of `child`'s ancestry tree (including itself). * @return RUBY_Qfalse Otherwise. */ VALUE rb_mod_include_p(VALUE child, VALUE parent); /** * Queries the module's ancestors. This routine gathers classes and modules * that the passed module either inherits, includes, or prepends, then * recursively applies that routine again and again to the collected entries * until the list doesn't grow up. * * @param[in] mod A module or a class. * @return An array of classes or modules that `mod` possibly recursively * inherits, includes, or prepends. * * @internal * * Above description is written in a recursive language but in practice it * computes the return value iteratively. */ VALUE rb_mod_ancestors(VALUE mod); /** * Queries the class's descendants. This routine gathers classes that are * subclasses of the given class (or subclasses of those subclasses, etc.), * returning an array of classes that have the given class as an ancestor. * The returned array does not include the given class or singleton classes. * * @param[in] klass A class. * @return An array of classes where `klass` is an ancestor. * * @internal */ VALUE rb_class_descendants(VALUE klass); /** * Queries the class's direct descendants. This routine gathers classes that are * direct subclasses of the given class, * returning an array of classes that have the given class as a superclass. * The returned array does not include singleton classes. * * @param[in] klass A class. * @return An array of classes where `klass` is the `superclass`. * * @internal */ VALUE rb_class_subclasses(VALUE klass); /** * Returns the attached object for a singleton class. * If the given class is not a singleton class, raises a TypeError. * * @param[in] klass A class. * @return The object which has the singleton class `klass`. * * @internal */ VALUE rb_class_attached_object(VALUE klass); /** * Generates an array of symbols, which are the list of method names defined in * the passed class. * * @param[in] argc Number of objects of `argv`. * @param[in] argv Array of at most one object, which controls (if * any) whether the return array includes the names * of methods defined in ancestors or not. * @param[in] mod A module or a class. * @exception rb_eArgError `argc` out of range. * @return An array of symbols collecting names of instance methods that * are not private, defined at `mod`. */ VALUE rb_class_instance_methods(int argc, const VALUE *argv, VALUE mod); /** * Identical to rb_class_instance_methods(), except it returns names of methods * that are public only. * * @param[in] argc Number of objects of `argv`. * @param[in] argv Array of at most one object, which controls (if * any) whether the return array includes the names * of methods defined in ancestors or not. * @param[in] mod A module or a class. * @exception rb_eArgError `argc` out of range. * @return An array of symbols collecting names of instance methods that * are public, defined at `mod`. */ VALUE rb_class_public_instance_methods(int argc, const VALUE *argv, VALUE mod); /** * Identical to rb_class_instance_methods(), except it returns names of methods * that are protected only. * * @param[in] argc Number of objects of `argv`. * @param[in] argv Array of at most one object, which controls (if * any) whether the return array includes the names * of methods defined in ancestors or not. * @param[in] mod A module or a class. * @exception rb_eArgError `argc` out of range. * @return An array of symbols collecting names of instance methods that * are protected, defined at `mod`. */ VALUE rb_class_protected_instance_methods(int argc, const VALUE *argv, VALUE mod); /** * Identical to rb_class_instance_methods(), except it returns names of methods * that are private only. * * @param[in] argc Number of objects of `argv`. * @param[in] argv Array of at most one object, which controls (if * any) whether the return array includes the names * of methods defined in ancestors or not. * @param[in] mod A module or a class. * @exception rb_eArgError `argc` out of range. * @return An array of symbols collecting names of instance methods that * are protected, defined at `mod`. */ VALUE rb_class_private_instance_methods(int argc, const VALUE *argv, VALUE mod); /** * Identical to rb_class_instance_methods(), except it returns names of * singleton methods instead of instance methods. * * @param[in] argc Number of objects of `argv`. * @param[in] argv Array of at most one object, which controls (if * any) whether the return array includes the names * of methods defined in ancestors or not. * @param[in] obj Arbitrary ruby object. * @exception rb_eArgError `argc` out of range. * @return An array of symbols collecting names of instance methods that * are not private, defined at the singleton class of `obj`. */ VALUE rb_obj_singleton_methods(int argc, const VALUE *argv, VALUE obj); /** * Identical to rb_define_method(), except it takes the name of the method in * ::ID instead of C's string. * * @param[out] klass A module or a class. * @param[in] mid Name of the function. * @param[in] func The method body. * @param[in] arity The number of parameters. See @ref defmethod. * @note There are in fact 18 different prototypes for func. * @see ::ruby::backward::cxxanyargs::define_method::rb_define_method_id */ void rb_define_method_id(VALUE klass, ID mid, VALUE (*func)(ANYARGS), int arity); /* vm_method.c */ /** * Inserts a method entry that hides previous method definition of the given * name. This is not a deletion of a method. Method of the same name defined * in a parent class is kept invisible in this way. * * @param[out] mod The module to insert an undef. * @param[in] mid Name of the undef. * @exception rb_eTypeError `klass` is a non-module. * @exception rb_eFrozenError `klass` is frozen. * @exception rb_eNameError No such method named `klass#name`. * @post `klass#name` is undefined. * @see rb_undef_method * * @internal * * @shyouhei doesn't understand why this is not the ::ID -taking variant of * rb_undef_method(), given rb_remove_method() has its ::ID -taking counterpart * named rb_remove_method_id(). */ void rb_undef(VALUE mod, ID mid); /* class.c */ RBIMPL_ATTR_NONNULL(()) /** * Identical to rb_define_method(), except it defines a protected method. * * @param[out] klass A module or a class. * @param[in] mid Name of the function. * @param[in] func The method body. * @param[in] arity The number of parameters. See @ref defmethod. * @note There are in fact 18 different prototypes for func. * @see ::ruby::backward::cxxanyargs::define_method::rb_define_protected_method */ void rb_define_protected_method(VALUE klass, const char *mid, VALUE (*func)(ANYARGS), int arity); RBIMPL_ATTR_NONNULL(()) /** * Identical to rb_define_method(), except it defines a private method. * * @param[out] klass A module or a class. * @param[in] mid Name of the function. * @param[in] func The method body. * @param[in] arity The number of parameters. See @ref defmethod. * @note There are in fact 18 different prototypes for func. * @see ::ruby::backward::cxxanyargs::define_method::rb_define_protected_method */ void rb_define_private_method(VALUE klass, const char *mid, VALUE (*func)(ANYARGS), int arity); RBIMPL_ATTR_NONNULL(()) /** * Identical to rb_define_method(), except it defines a singleton method. * * @param[out] obj Arbitrary ruby object. * @param[in] mid Name of the function. * @param[in] func The method body. * @param[in] arity The number of parameters. See @ref defmethod. * @note There are in fact 18 different prototypes for func. * @see ::ruby::backward::cxxanyargs::define_method::rb_define_singleton_method */ void rb_define_singleton_method(VALUE obj, const char *mid, VALUE(*func)(ANYARGS), int arity); /** * Finds or creates the singleton class of the passed object. * * @param[out] obj Arbitrary ruby object. * @exception rb_eTypeError `obj` cannot have its singleton class. * @return A (possibly newly allocated) instance of ::rb_cClass. * @post `obj` has its singleton class, which is the return value. * @post In case `obj` is a class, the returned singleton class also has * its own singleton class in order to keep consistency of the * inheritance structure of metaclasses. * @note A new singleton class will be created if `obj` did not have * one. * @note The singleton classes for ::RUBY_Qnil, ::RUBY_Qtrue, and * ::RUBY_Qfalse are ::rb_cNilClass, ::rb_cTrueClass, and * ::rb_cFalseClass respectively. * * @internal * * You can _create_ a singleton class of a frozen object. Intentional or ...? * * Nowadays there are wider range of objects who cannot have singleton classes * than before. For instance some string instances cannot for some reason. */ VALUE rb_singleton_class(VALUE obj); RBIMPL_SYMBOL_EXPORT_END() #endif /* RBIMPL_INTERN_CLASS_H */ include/ruby/internal/intern/select.h 0000644 00000007552 15152150474 0013730 0 ustar 00 #ifndef RBIMPL_INTERN_SELECT_H /*-*-C++-*-vi:se ft=cpp:*/ #define RBIMPL_INTERN_SELECT_H /** * @file * @author Ruby developers <ruby-core@ruby-lang.org> * @copyright This file is a part of the programming language Ruby. * Permission is hereby granted, to either redistribute and/or * modify this file, provided that the conditions mentioned in the * file COPYING are met. Consult the file for details. * @warning Symbols prefixed with either `RBIMPL` or `rbimpl` are * implementation details. Don't take them as canon. They could * rapidly appear then vanish. The name (path) of this header file * is also an implementation detail. Do not expect it to persist * at the place it is now. Developers are free to move it anywhere * anytime at will. * @note To ruby-core: remember that this header can be possibly * recursively included from extension libraries written in C++. * Do not expect for instance `__VA_ARGS__` is always available. * We assume C99 for ruby itself but we don't assume languages of * extension libraries. They could be written in C++98. * @brief Public APIs to provide ::rb_fd_select(). * @note Functions and structs defined in this header file are not * necessarily ruby-specific. They don't need ::VALUE etc. */ #include "ruby/internal/config.h" #ifdef HAVE_SYS_TYPES_H # include <sys/types.h> /* for NFDBITS (BSD Net/2) */ #endif #include "ruby/internal/dllexport.h" /* thread.c */ #if defined(NFDBITS) && defined(HAVE_RB_FD_INIT) # include "ruby/internal/intern/select/largesize.h" #elif defined(_WIN32) # include "ruby/internal/intern/select/win32.h" # /** Does nothing (defined for compatibility). */ # define rb_fd_resize(n, f) ((void)(f)) #else # include "ruby/internal/intern/select/posix.h" # /** Does nothing (defined for compatibility). */ # define rb_fd_resize(n, f) ((void)(f)) #endif RBIMPL_SYMBOL_EXPORT_BEGIN() struct timeval; /** * Waits for multiple file descriptors at once. This is basically a wrapper of * system-provided select() with releasing GVL, to allow other Ruby threads run * in parallel. * * @param[in] nfds Max FD in everything passed, plus one. * @param[in,out] rfds Set of FDs to wait for reads. * @param[in,out] wfds Set of FDs to wait for writes. * @param[in,out] efds Set of FDs to wait for OOBs. * @param[in,out] timeout Max blocking duration. * @retval -1 Failed, errno set. * @retval 0 Timeout exceeded. * @retval otherwise Total number of file descriptors returned. * @post `rfds` contains readable FDs. * @post `wfds` contains writable FDs. * @post `efds` contains exceptional FDs. * @post `timeout` is the time left. * @note All pointers are allowed to be null pointers. * * Although backend threads can run in parallel of this function, touching a * file descriptor from multiple threads could be problematic. For instance * what happens when a thread closes a file descriptor that is selected by * someone else, vastly varies among operating systems. You would better avoid * touching an fd from more than one threads. * * @internal * * Although any file descriptors are possible here, it makes completely no * sense to pass a descriptor that is not `O_NONBLOCK`. If you want to know * the reason for this limitation in detail, you might find this thread super * interesting: https://lkml.org/lkml/2004/10/6/117 */ int rb_thread_fd_select(int nfds, rb_fdset_t *rfds, rb_fdset_t *wfds, rb_fdset_t *efds, struct timeval *timeout); RBIMPL_SYMBOL_EXPORT_END() #endif /* RBIMPL_INTERN_SELECT_H */ include/ruby/internal/intern/ruby.h 0000644 00000005440 15152150475 0013425 0 ustar 00 #ifndef RBIMPL_INTERN_RUBY_H /*-*-C++-*-vi:se ft=cpp:*/ #define RBIMPL_INTERN_RUBY_H /** * @file * @author Ruby developers <ruby-core@ruby-lang.org> * @copyright This file is a part of the programming language Ruby. * Permission is hereby granted, to either redistribute and/or * modify this file, provided that the conditions mentioned in the * file COPYING are met. Consult the file for details. * @warning Symbols prefixed with either `RBIMPL` or `rbimpl` are * implementation details. Don't take them as canon. They could * rapidly appear then vanish. The name (path) of this header file * is also an implementation detail. Do not expect it to persist * at the place it is now. Developers are free to move it anywhere * anytime at will. * @note To ruby-core: remember that this header can be possibly * recursively included from extension libraries written in C++. * Do not expect for instance `__VA_ARGS__` is always available. * We assume C99 for ruby itself but we don't assume languages of * extension libraries. They could be written in C++98. * @brief Process-global APIs. */ #include "ruby/internal/attr/nonnull.h" #include "ruby/internal/dllexport.h" #include "ruby/internal/value.h" RBIMPL_SYMBOL_EXPORT_BEGIN() /* ruby.c */ /** @alias{rb_get_argv} */ #define rb_argv rb_get_argv() /** * The value of `$0` at process bootup. * * @note This is just a snapshot of `$0`, not the backend storage of it. `$0` * could become something different because it is a writable global * variable. Modifying it for instance affects `ps(1)` output. Don't * assume they are synced. */ RUBY_EXTERN VALUE rb_argv0; /* io.c */ /** * Queries the arguments passed to the current process that you can access from * Ruby as `ARGV`. * * @return An array of strings containing arguments passed to the process. */ VALUE rb_get_argv(void); /* ruby.c */ RBIMPL_ATTR_NONNULL(()) /** * Loads the given file. This function opens the given pathname for reading, * parses the contents as a Ruby script, and returns an opaque "node" pointer. * You can then pass it to ruby_run_node() for evaluation. * * @param[in] file File name, or "-" to read from stdin. * @return Opaque "node" pointer. */ void *rb_load_file(const char *file); /** * Identical to rb_load_file(), except it takes the argument as a Ruby's string * instead of C's. * * @param[in] file File name, or "-" to read from stdin. * @return Opaque "node" pointer. */ void *rb_load_file_str(VALUE file); RBIMPL_SYMBOL_EXPORT_END() #endif /* RBIMPL_INTERN_RUBY_H */ include/ruby/internal/intern/random.h 0000644 00000010460 15152150475 0013722 0 ustar 00 #ifndef RBIMPL_INTERN_RANDOM_H /*-*-C++-*-vi:se ft=cpp:*/ #define RBIMPL_INTERN_RANDOM_H /** * @file * @author Ruby developers <ruby-core@ruby-lang.org> * @copyright This file is a part of the programming language Ruby. * Permission is hereby granted, to either redistribute and/or * modify this file, provided that the conditions mentioned in the * file COPYING are met. Consult the file for details. * @warning Symbols prefixed with either `RBIMPL` or `rbimpl` are * implementation details. Don't take them as canon. They could * rapidly appear then vanish. The name (path) of this header file * is also an implementation detail. Do not expect it to persist * at the place it is now. Developers are free to move it anywhere * anytime at will. * @note To ruby-core: remember that this header can be possibly * recursively included from extension libraries written in C++. * Do not expect for instance `__VA_ARGS__` is always available. * We assume C99 for ruby itself but we don't assume languages of * extension libraries. They could be written in C++98. * @brief MT19937 backended pseudo random number generator. * @see Matsumoto, M., Nishimura, T., "Mersenne Twister: A 623- * dimensionally equidistributed uniform pseudorandom number * generator", ACM Trans. on Modeling and Computer Simulation, 8 * (1): pp 3-30, 1998. https://doi.org/10.1145/272991.272995 */ #include "ruby/internal/dllexport.h" #include "ruby/internal/value.h" RBIMPL_SYMBOL_EXPORT_BEGIN() /* random.c */ /** * Generates a 32 bit random number. * * @return A random number. * @note Now that we have ractors, the RNG behind this function is * per-ractor. */ unsigned int rb_genrand_int32(void); /** * Generates a `double` random number. * * @return A random number. * @note This function shares the RNG with rb_genrand_int32(). */ double rb_genrand_real(void); /** * Resets the RNG behind rb_genrand_int32()/rb_genrand_real(). * * @post The (now per-ractor) default RNG's internal state is cleared. */ void rb_reset_random_seed(void); /** * Generates a String of random bytes. * * @param[in,out] rnd An instance of ::rb_cRandom. * @param[in] n Requested number of bytes. * @return An instance of ::rb_cString, of binary, of `n` bytes length, * whose contents are random bits. * * @internal * * @shyouhei doesn't know if this is an Easter egg or an official feature, but * this function can take a wider range of objects, such as `Socket::Ifaddr`. * The arguments are just silently ignored and the default RNG is used instead, * if they are non-RNG. */ VALUE rb_random_bytes(VALUE rnd, long n); /** * Identical to rb_genrand_int32(), except it generates using the passed RNG. * * @param[in,out] rnd An instance of ::rb_cRandom. * @return A random number. */ unsigned int rb_random_int32(VALUE rnd); /** * Identical to rb_genrand_real(), except it generates using the passed RNG. * * @param[in,out] rnd An instance of ::rb_cRandom. * @return A random number. */ double rb_random_real(VALUE rnd); /** * Identical to rb_genrand_ulong_limited(), except it generates using the * passed RNG. * * @param[in,out] rnd An instance of ::rb_cRandom. * @param[in] limit Max possible return value. * @return A random number, distributed in `[0, limit]` interval. * @note Note it can return `limit`. * @note Whether the return value distributes uniformly in the * interval or not depends on how the argument RNG behaves; at * least in case of MT19937 it does. */ unsigned long rb_random_ulong_limited(VALUE rnd, unsigned long limit); /** * Generates a random number whose upper limit is `i`. * * @param[in] i Max possible return value. * @return A random number, uniformly distributed in `[0, limit]` interval. * @note Note it can return `i`. */ unsigned long rb_genrand_ulong_limited(unsigned long i); RBIMPL_SYMBOL_EXPORT_END() #endif /* RBIMPL_INTERN_RANDOM_H */ include/ruby/internal/intern/variable.h 0000644 00000051474 15152150475 0014241 0 ustar 00 #ifndef RBIMPL_INTERN_VARIABLE_H /*-*-C++-*-vi:se ft=cpp:*/ #define RBIMPL_INTERN_VARIABLE_H /** * @file * @author Ruby developers <ruby-core@ruby-lang.org> * @copyright This file is a part of the programming language Ruby. * Permission is hereby granted, to either redistribute and/or * modify this file, provided that the conditions mentioned in the * file COPYING are met. Consult the file for details. * @warning Symbols prefixed with either `RBIMPL` or `rbimpl` are * implementation details. Don't take them as canon. They could * rapidly appear then vanish. The name (path) of this header file * is also an implementation detail. Do not expect it to persist * at the place it is now. Developers are free to move it anywhere * anytime at will. * @note To ruby-core: remember that this header can be possibly * recursively included from extension libraries written in C++. * Do not expect for instance `__VA_ARGS__` is always available. * We assume C99 for ruby itself but we don't assume languages of * extension libraries. They could be written in C++98. * @brief Public APIs related to names inside of a Ruby program. */ #include "ruby/internal/attr/nonnull.h" #include "ruby/internal/attr/noreturn.h" #include "ruby/internal/dllexport.h" #include "ruby/internal/value.h" #include "ruby/st.h" RBIMPL_SYMBOL_EXPORT_BEGIN() /* variable.c */ /** * Queries the name of a module. * * @param[in] mod An instance of ::rb_cModule. * @retval RUBY_Qnil `mod` is anonymous. * @retval otherwise `mod` is onymous. */ VALUE rb_mod_name(VALUE mod); /** * Identical to rb_mod_name(), except it returns `#<Class: ...>` style * inspection for anonymous modules. * * @param[in] mod An instance of ::rb_cModule. * @return An instance of ::rb_cString representing `mod`'s path. */ VALUE rb_class_path(VALUE mod); /** * @alias{rb_mod_name} * * @internal * * Am I missing something? Why we have the same thing in different names? */ VALUE rb_class_path_cached(VALUE mod); RBIMPL_ATTR_NONNULL(()) /** * Names a class. * * @param[out] klass Target module to name. * @param[out] space Namespace that `klass` shall reside. * @param[in] name Name of `klass`. * @post `klass` has `space::klass` name. */ void rb_set_class_path(VALUE klass, VALUE space, const char *name); /** * Identical to rb_set_class_path(), except it accepts the name as Ruby's * string instead of C's. * * @param[out] klass Target module to name. * @param[out] space Namespace that `klass` shall reside. * @param[in] name Name of `klass`. * @post `klass` has `space::klass` name. */ void rb_set_class_path_string(VALUE klass, VALUE space, VALUE name); /** * Identical to rb_path2class(), except it accepts the path as Ruby's string * instead of C's. * * @param[in] path Path to query. * @exception rb_eArgError No such constant. * @exception rb_eTypeError The path resolved to a non-module. * @return Resolved class. */ VALUE rb_path_to_class(VALUE path); RBIMPL_ATTR_NONNULL(()) /** * Resolves a `Q::W::E::R`-style path string to the actual class it points. * * @param[in] path Path to query. * @exception rb_eArgError No such constant. * @exception rb_eTypeError The path resolved to a non-module. * @return Resolved class. */ VALUE rb_path2class(const char *path); /** * Queries the name of the given object's class. * * @param[in] obj Arbitrary object. * @return An instance of ::rb_cString representing `obj`'s class' path. */ VALUE rb_class_name(VALUE obj); /** * Kicks the autoload procedure as if it was "touched". * * @param[out] space Namespace where autoload is defined. * @param[in] name Name of the autoloaded constant. * @retval RUBY_Qfalse No such autoload. * @retval RUBY_Qtrue Autoload successfully initiated. * @note As an autoloaded library is expected to define `space::name`, * it is a nature of this function to have process-global side * effects. * @note Multiple threads can simultaneously call this API. It blocks * then. That must not last indefinitely but can take longer than * you expect. * * @internal * * @shyouhei has no idea why extension libraries should use this API. */ VALUE rb_autoload_load(VALUE space, ID name); /** * Queries if an autoload is defined at a point. * * @param[in] space Namespace where autoload is defined. * @param[in] name Name of the autoloaded constant. * @retval RUBY_Qnil No such autoload. * @retval otherwise The feature (path) registered at `space::name`. */ VALUE rb_autoload_p(VALUE space, ID name); /** * Traces a global variable. * * @param[in] argc Either 1 or 2. * @param[in] argv Variable name, optionally a Proc. * @retval RUBY_Qnil No previous tracers. * @retval otherwise Previous tracers. * * @internal * * @shyouhei has no idea why extension libraries should use this API. */ VALUE rb_f_trace_var(int argc, const VALUE *argv); /** * Deletes the passed tracer from the passed global variable, or if omitted, * deletes everything. * * @param[in] argc Either 1 or 2. * @param[in] argv Variable name, optionally a Proc. * @retval RUBY_Qnil No previous tracers. * @retval otherwise Deleted tracers. * * @internal * * @shyouhei has no idea why extension libraries should use this API. */ VALUE rb_f_untrace_var(int argc, const VALUE *argv); /** * Queries the list of global variables. * * @return The list of the name of the global variables. * * @internal * * Above description is in fact inaccurate. This API interfaces with Ractors. */ VALUE rb_f_global_variables(void); /** * Aliases a global variable. Did you know that you can alias a global * variable? It is like aliasing methods: * * ```ruby * alias $dst $src * ``` * * This C function does the same thing. * * @param[in] dst Destination name. * @param[in] src Source name. * @post A global variable named `dst` is defined to be an alias of a * global variable named `src`. * * @internal * * Above description is in fact inaccurate. This API interfaces with Ractors. */ void rb_alias_variable(ID dst, ID src); /** * Frees the list of instance variables. 3rd parties need not know, but there * are several ways to store an object's instance variables, depending on its * internal structure. This function makes sense when the passed objects is * using so-called "generic" backend storage. People need not be aware of this * working behind-the-scenes. * * @param[out] obj The object in question. * * @internal * * This just destroys the given object. @shyouhei has no idea why extension * libraries should use this API. */ void rb_free_generic_ivar(VALUE obj); /** * Identical to rb_iv_get(), except it accepts the name as an ::ID instead of a * C string. * * @param[in] obj Target object. * @param[in] name Target instance variable to query. * @retval RUBY_nil No such instance variable. * @retval otherwise The value assigned to the instance variable. */ VALUE rb_ivar_get(VALUE obj, ID name); /** * Identical to rb_iv_set(), except it accepts the name as an ::ID instead of a * C string. * * @param[out] obj Target object. * @param[in] name Target instance variable. * @param[in] val Value to assign. * @exception rb_eFrozenError Can't modify `obj`. * @exception rb_eArgError `obj` has too many instance variables. * @return Passed value. * @post An instance variable named `name` is defined if absent on * `obj`, whose value is set to `val`. */ VALUE rb_ivar_set(VALUE obj, ID name, VALUE val); /** * Queries if the instance variable is defined at the object. This roughly * resembles `defined?(@name)` in `obj`'s context. * * @param[in] obj Target object. * @param[in] name Target instance variable to query. * @retval RUBY_Qtrue There is an instance variable. * @retval RUBY_Qfalse No such instance variable. */ VALUE rb_ivar_defined(VALUE obj, ID name); /** * Iterates over an object's instance variables. * * @param[in] obj Target object. * @param[in] func Callback function. * @param[in] arg Passed as-is to the last argument of `func`. */ void rb_ivar_foreach(VALUE obj, int (*func)(ID name, VALUE val, st_data_t arg), st_data_t arg); /** * Number of instance variables defined on an object. * * @param[in] obj Target object. * @return Number of instance variables defined on `obj`. */ st_index_t rb_ivar_count(VALUE obj); /** * Identical to rb_ivar_get() * * @param[in] obj Target object. * @param[in] name Target instance variable to query. * @retval RUBY_nil No such instance variable. * @retval otherwise The value assigned to the instance variable. * * @internal * * Am I missing something? Why we have the same thing in different names? */ VALUE rb_attr_get(VALUE obj, ID name); /** * Resembles `Object#instance_variables`. * * @param[in] obj Target object to query. * @return An array of instance variable names for the receiver. * @note Simply defining an accessor does not create the corresponding * instance variable. */ VALUE rb_obj_instance_variables(VALUE obj); /** * Resembles `Object#remove_instance_variable`. * * @param[out] obj Target object. * @param[in] name Variable name to remove, either in Symbol or String. * @return What was removed. * @pre Instance variable named `name` is deleted from `obj`. */ VALUE rb_obj_remove_instance_variable(VALUE obj, VALUE name); /** * This API is mysterious. It has been there since the initial revision. No * single bits of documents has ever been written. The function name doesn't * describe anything. What should be passed to the argument, or what should be * the return value, are not obvious. Yet it has evolved over time. The * source code is written in counter-intuitive way (as of 3.0). * * Simply put, don't try to understand this API. */ void *rb_mod_const_at(VALUE, void*); /** * This is a variant of rb_mod_const_at(). As a result, it is also mysterious. * It _seems_ it iterates over the ancestry tree of the module. But what that * means is beyond a human brain. */ void *rb_mod_const_of(VALUE, void*); /** * This is another mysterious API that comes with no documents at all. It * seems it expects some specific data structure for the passed pointer. But * the details has never been made explicit. It seems nobody should use this * API. */ VALUE rb_const_list(void*); /** * Resembles `Module#constants`. List up the constants defined at the * receiver. This includes the names of constants in any included modules, * unless `argv[0]` is ::RUBY_Qfalse. * * The implementation makes no guarantees about the order in which the * constants are yielded. * * @param[in] argc Either 0 or 1. * @param[in] argv Pointer to ::RUBY_Qfalse, if `argc == 1`. * @param[in] recv Target namespace. * @return An array of symbols, which are constant names under `recv`. */ VALUE rb_mod_constants(int argc, const VALUE *argv, VALUE recv); /** * Resembles `Module#remove_const`. * * @param[out] space Target namespace. * @param[in] name Variable name to remove, either in Symbol or String. * @return What was removed. * @pre Constant named `space::name` is deleted. * @note In case what was removed was in fact a module or a class, this * operation does not affect its name. Which means when people * for instance look at it using `p` etc., it still introduces * itself using the deleted name. Can confuse people. */ VALUE rb_mod_remove_const(VALUE space, VALUE name); /** * Queries if the constant is defined at the namespace. * * @param[in] space Target namespace. * @param[in] name Target name to query. * @retval RUBY_Qtrue There is a constant. * @retval RUBY_Qfalse No such constant. * * @internal * * The return values are not typo! This function returns ruby values casted to * `int`. Completely brain-damaged design. */ int rb_const_defined(VALUE space, ID name); /** * Identical to rb_const_defined(), except it doesn't look for parent classes. * For instance `Array` is a toplevel constant, which is visible from * everywhere. But this function does not take such things into account. It * concerns only what is directly defined inside of the given namespace. * * @param[in] space Target namespace. * @param[in] name Target name to query. * @retval RUBY_Qtrue There is a constant. * @retval RUBY_Qfalse No such constant. * * @internal * * The return values are not typo! This function returns ruby values casted to * `int`. Completely brain-damaged design. */ int rb_const_defined_at(VALUE space, ID name); /** * Identical to rb_const_defined(), except it returns false for private * constants. * * @param[in] space Target namespace. * @param[in] name Target name to query. * @retval RUBY_Qtrue There is a constant. * @retval RUBY_Qfalse No such constant. * * @internal * * What does "from" mean? The name sounds quite cryptic. * * The return values are not typo! This function returns ruby values casted to * `int`. Completely brain-damaged design. */ int rb_const_defined_from(VALUE space, ID name); /** * Identical to rb_const_defined(), except it returns the actual defined value. * * @param[in] space Target namespace. * @param[in] name Target name to query. * @exception rb_eNameError No such constant. * @return The defined constant. * * @internal * * Above description is in fact inaccurate. This API interfaces with Ractors. */ VALUE rb_const_get(VALUE space, ID name); /** * Identical to rb_const_defined_at(), except it returns the actual defined * value. It can also be seen as a routine identical to rb_const_get(), except * it doesn't look for parent classes. * * @param[in] space Target namespace. * @param[in] name Target name to query. * @exception rb_eNameError No such constant. * @return The defined constant. * * @internal * * Above description is in fact inaccurate. This API interfaces with Ractors. */ VALUE rb_const_get_at(VALUE space, ID name); /** * Identical to rb_const_defined_at(), except it returns the actual defined * value. It can also be seen as a routine identical to rb_const_get(), except * it doesn't return a private constant. * * @param[in] space Target namespace. * @param[in] name Target name to query. * @exception rb_eNameError No such constant. * @return The defined constant. * * @internal * * Above description is in fact inaccurate. This API interfaces with Ractors. */ VALUE rb_const_get_from(VALUE space, ID name); /** * Names a constant. * * @param[out] space Target namespace. * @param[in] name Target name to query. * @param[in] val Value to define. * @exception rb_eTypeError `space` is not a module. * @post `name` is a constant under `space`, whose value is `val`. * @note You can reassign. * * @internal * * Above description is in fact inaccurate. This API interfaces with Ractors. */ void rb_const_set(VALUE space, ID name, VALUE val); /** * Identical to rb_mod_remove_const(), except it takes the name as ::ID instead * of ::VALUE. * * @param[out] space Target namespace. * @param[in] name Variable name to remove, either in Symbol or String. * @return What was removed. * @pre Constant named `space::name` is deleted. * @note In case what was removed was in fact a module or a class, this * operation does not affect its name. Which means when people * for instance look at it using `p` etc., it still introduces * itself using the deleted name. Can confuse people. */ VALUE rb_const_remove(VALUE space, ID name); #if 0 /* EXPERIMENTAL: remove if no problem */ RBIMPL_ATTR_NORETURN() /** * This is the default implementation of `Module#const_missing`. * * @param[in] space Target namespace. * @param[in] name Target name that is nonexistent. * @exception rb_eNameError Always. */ VALUE rb_mod_const_missing(VALUE space, VALUE name); #endif /** * Queries if the given class has the given class variable. * * @param[in] klass Target class. * @param[in] name Name to query. * @return RUBY_Qtrue Yes there is. * @return RUBY_Qfalse No there isn't. * @pre `klass` must be an instance of rb_cModule. * * @internal * * Above description is in fact inaccurate. This API interfaces with Ractors. */ VALUE rb_cvar_defined(VALUE klass, ID name); /** * Assigns a value to a class variable. * * @param[out] klass Target class. * @param[in] name Variable name. * @param[in] val Value to be assigned. * @post `klass` has a class variable named `name` whose value is `val`. * * @internal * * Above description is in fact inaccurate. This API interfaces with Ractors. */ void rb_cvar_set(VALUE klass, ID name, VALUE val); /** * Obtains a value from a class variable. * * @param[in] klass Target class. * @param[in] name Variable name. * @exception rb_eNameError Uninitialised class variable. * @exception rb_eRuntimeError `[Bug#14541]` situation. * @return Class variable named `name` under `klass`. * * @internal * * Above description is in fact inaccurate. This API interfaces with Ractors. */ VALUE rb_cvar_get(VALUE klass, ID name); RBIMPL_ATTR_NONNULL(()) /** * Identical to rb_cvar_get(), except it takes additional "front" pointer. * This extra parameter is a buffer, which will have the class where the * queried class variable actually resides. * * @param[in] klass Target class. * @param[in] name Variable name. * @param[out] front Return buffer. * @exception rb_eNameError Uninitialised class variable. * @exception rb_eRuntimeError `[Bug#14541]` situation. * @return Class variable named `name` under `klass`. * @post `front` has the class object, which is an ancestor of `klass`, * where the queried class variable actually resides. * * @internal * * Above description is in fact inaccurate. This API interfaces with Ractors. */ VALUE rb_cvar_find(VALUE klass, ID name, VALUE *front); RBIMPL_ATTR_NONNULL(()) /** * Identical to rb_cvar_set(), except it accepts C's string instead of ::ID. * * @param[out] klass Target class. * @param[in] name Variable name. * @param[in] val Value to be assigned. * @post `klass` has a class variable named `name` whose value is `val`. */ void rb_cv_set(VALUE klass, const char *name, VALUE val); RBIMPL_ATTR_NONNULL(()) /** * Identical to rb_cvar_get(), except it accepts C's string instead of ::ID. * * @param[in] klass Target class. * @param[in] name Variable name. * @exception rb_eNameError Uninitialised class variable. * @exception rb_eRuntimeError `[Bug#14541]` situation. * @return Class variable named `name` under `klass`. */ VALUE rb_cv_get(VALUE klass, const char *name); RBIMPL_ATTR_NONNULL(()) /** * @alias{rb_cv_set} * * @internal * * Am I missing something? Why we have the same thing in different names? */ void rb_define_class_variable(VALUE, const char*, VALUE); /** * Resembles `Module#class_variables`. List up the variables defined at the * receiver. This includes the names of constants in any included modules, * unless `argv[0]` is ::RUBY_Qfalse. * * The implementation makes no guarantees about the order in which the * constants are yielded. * * @param[in] argc Either 0 or 1. * @param[in] argv Pointer to ::RUBY_Qfalse, if `argc == 1`. * @param[in] recv Target class. * @return An array of symbols, which are class variable names under * `recv`. */ VALUE rb_mod_class_variables(int argc, const VALUE *argv, VALUE recv); /** * Resembles `Module#remove_class_variable`. * * @param[out] mod Target class. * @param[in] name Variable name to remove, either in Symbol or String. * @return What was removed. * @pre Instance variable named `name` is deleted from `obj`. */ VALUE rb_mod_remove_cvar(VALUE mod, VALUE name); RBIMPL_SYMBOL_EXPORT_END() #endif /* RBIMPL_INTERN_VARIABLE_H */ include/ruby/internal/intern/sprintf.h 0000644 00000014504 15152150475 0014132 0 ustar 00 #ifndef RBIMPL_INTERN_SPRINTF_H /*-*-C++-*-vi:se ft=cpp:*/ #define RBIMPL_INTERN_SPRINTF_H /** * @file * @author Ruby developers <ruby-core@ruby-lang.org> * @copyright This file is a part of the programming language Ruby. * Permission is hereby granted, to either redistribute and/or * modify this file, provided that the conditions mentioned in the * file COPYING are met. Consult the file for details. * @warning Symbols prefixed with either `RBIMPL` or `rbimpl` are * implementation details. Don't take them as canon. They could * rapidly appear then vanish. The name (path) of this header file * is also an implementation detail. Do not expect it to persist * at the place it is now. Developers are free to move it anywhere * anytime at will. * @note To ruby-core: remember that this header can be possibly * recursively included from extension libraries written in C++. * Do not expect for instance `__VA_ARGS__` is always available. * We assume C99 for ruby itself but we don't assume languages of * extension libraries. They could be written in C++98. * @brief Our own private `printf(3)`. */ #include "ruby/internal/attr/format.h" #include "ruby/internal/attr/nonnull.h" #include "ruby/internal/dllexport.h" #include "ruby/internal/value.h" RBIMPL_SYMBOL_EXPORT_BEGIN() /* sprintf.c */ /** * Identical to rb_str_format(), except how the arguments are arranged. * * @param[in] argc Number of objects of `argv`. * @param[in] argv A format string, followed by its arguments. * @return A rendered new instance of ::rb_cString. * * @internal * * You can safely pass NULL to `argv`. Doesn't make any sense though. */ VALUE rb_f_sprintf(int argc, const VALUE *argv); RBIMPL_ATTR_NONNULL((1)) RBIMPL_ATTR_FORMAT(RBIMPL_PRINTF_FORMAT, 1, 2) /** * Ruby's extended `sprintf(3)`. We ended up reinventing the entire `printf` * business because we don't want to depend on locales. OS-provided `printf` * routines might or might not, which caused instabilities of the result * strings. * * The format sequence is a mixture of format specifiers and other verbatim * contents. Each format specifier starts with a `%`, and has the following * structure: * * ``` * %[flags][width][.precision][length]conversion * ``` * * This function supports flags of ` `, `#`, `+`, `-`, `0`, width of * non-negative decimal integer and `*`, precision of non-negative decimal * integers and `*`, length of `L`, `h`, `t`, `z`, `l`, `ll`, `q`, conversions * of `A`, `D`, `E`, `G`, `O`, `U`, `X`, `a`, `c`, `d`, `e`, `f`, `g`, `i`, * `n`, `o`, `p`, `s`, `u`, `x`, and `%`. In case of `_WIN32` it also supports * `I`. And additionally, it supports magical `PRIsVALUE` macro that can * stringise arbitrary Ruby objects: * * ```CXX * rb_sprintf("|%"PRIsVALUE"|", RUBY_Qtrue); // => "|true|" * rb_sprintf("%+"PRIsVALUE, rb_stdin); // => "#<IO:<STDIN>>" * ``` * * @param[in] fmt A `printf`-like format specifier. * @param[in] ... Variadic number of contents to format. * @return A rendered new instance of ::rb_cString. * * @internal * * :FIXME: We can improve this document. */ VALUE rb_sprintf(const char *fmt, ...); RBIMPL_ATTR_NONNULL((1)) RBIMPL_ATTR_FORMAT(RBIMPL_PRINTF_FORMAT, 1, 0) /** * Identical to rb_sprintf(), except it takes a `va_list`. * * @param[in] fmt A `printf`-like format specifier. * @param[in] ap Contents to format. * @return A rendered new instance of ::rb_cString. */ VALUE rb_vsprintf(const char *fmt, va_list ap); RBIMPL_ATTR_NONNULL((2)) RBIMPL_ATTR_FORMAT(RBIMPL_PRINTF_FORMAT, 2, 3) /** * Identical to rb_sprintf(), except it renders the output to the specified * object rather than creating a new one. * * @param[out] dst String to modify. * @param[in] fmt A `printf`-like format specifier. * @param[in] ... Variadic number of contents to format. * @exception rb_eTypeError `dst` is not a String. * @return Passed `dst`. * @post `dst` has the rendered output appended to its end. */ VALUE rb_str_catf(VALUE dst, const char *fmt, ...); RBIMPL_ATTR_NONNULL((2)) RBIMPL_ATTR_FORMAT(RBIMPL_PRINTF_FORMAT, 2, 0) /** * Identical to rb_str_catf(), except it takes a `va_list`. It can also be * seen as a routine identical to rb_vsprintf(), except it renders the output * to the specified object rather than creating a new one. * * @param[out] dst String to modify. * @param[in] fmt A `printf`-like format specifier. * @param[in] ap Contents to format. * @exception rb_eTypeError `dst` is not a String. * @return Passed `dst`. * @post `dst` has the rendered output appended to its end. */ VALUE rb_str_vcatf(VALUE dst, const char *fmt, va_list ap); /** * Formats a string. * * Returns the string resulting from applying `fmt` to `argv`. The format * sequence is a mixture of format specifiers and other verbatim contents. * Each format specifier starts with a `%`, and has the following structure: * * ``` * %[flags][width][.precision]type * ``` * * ... which is different from that of rb_sprintf(). Because ruby has no * `short` or `long`, there is no way to specify a "length" of an argument. * * This function supports flags of ` `, `#`, `+`, `-`, `<>`, `{}`, with of * non-negative decimal integer and `$`, `*`, precision of non-negative decimal * integer and `$`, `*`, type of `A`, `B`, `E`, `G`, `X`, `a`, `b`, `c`, `d`, * `e`, `f`, `g`, `i`, `o`, `p`, `s`, `u`, `x`, `%`. This list is also * (largely the same but) not identical to that of rb_sprintf(). * * @param[in] argc Number of objects in `argv`. * @param[in] argv Format arguments. * @param[in] fmt A printf-like format specifier. * @exception rb_eTypeError `fmt` is not a string. * @exception rb_eArgError Failed to parse `fmt`. * @return A rendered new instance of ::rb_cString. * @note Everything it takes must be Ruby objects. * */ VALUE rb_str_format(int argc, const VALUE *argv, VALUE fmt); RBIMPL_SYMBOL_EXPORT_END() #endif /* RBIMPL_INTERN_SPRINTF_H */ include/ruby/internal/intern/load.h 0000644 00000024656 15152150475 0013375 0 ustar 00 #ifndef RBIMPL_INTERN_LOAD_H /*-*-C++-*-vi:se ft=cpp:*/ #define RBIMPL_INTERN_LOAD_H /** * @file * @author Ruby developers <ruby-core@ruby-lang.org> * @copyright This file is a part of the programming language Ruby. * Permission is hereby granted, to either redistribute and/or * modify this file, provided that the conditions mentioned in the * file COPYING are met. Consult the file for details. * @warning Symbols prefixed with either `RBIMPL` or `rbimpl` are * implementation details. Don't take them as canon. They could * rapidly appear then vanish. The name (path) of this header file * is also an implementation detail. Do not expect it to persist * at the place it is now. Developers are free to move it anywhere * anytime at will. * @note To ruby-core: remember that this header can be possibly * recursively included from extension libraries written in C++. * Do not expect for instance `__VA_ARGS__` is always available. * We assume C99 for ruby itself but we don't assume languages of * extension libraries. They could be written in C++98. * @brief Public APIs related to ::rb_f_require(). */ #include "ruby/internal/attr/nonnull.h" #include "ruby/internal/dllexport.h" #include "ruby/internal/value.h" RBIMPL_SYMBOL_EXPORT_BEGIN() /* load.c */ /** * Loads and executes the Ruby program in the given file. * * If the path is an absolute path (e.g. starts with `'/'`), the file will be * loaded directly using the absolute path. If the path is an explicit * relative path (e.g. starts with `'./'` or `'../'`), the file will be loaded * using the relative path from the current directory. Otherwise, the file * will be searched for in the library directories listed in the `$LOAD_PATH`. * If the file is found in a directory, this function will attempt to load the * file relative to that directory. If the file is not found in any of the * directories in the `$LOAD_PATH`, the file will be loaded using the relative * path from the current directory. * * If the file doesn't exist when there is an attempt to load it, a LoadError * will be raised. * * If the `wrap` parameter is true, the loaded script will be executed under an * anonymous module, protecting the calling program's global namespace. In no * circumstance will any local variables in the loaded file be propagated to * the loading environment. * * @param[in] path Pathname of a file to load. * @param[in] wrap Either to load under an anonymous module. * @exception rb_eTypeError `path` is not a string. * @exception rb_eArgError `path` is broken as a pathname. * @exception rb_eEncCompatError `path` is incompatible with pathnames. * @exception rb_eLoadError `path` not found. * @exception rb_eException Any exceptions while loading the contents. * * @internal * * It seems this function is under the rule of bootsnap's regime? */ void rb_load(VALUE path, int wrap); /** * Identical to rb_load(), except it avoids potential global escapes. Such * global escapes include exceptions, `throw`, `break`, for example. * * It first evaluates the given file as rb_load() does. If no global escape * occurred during the evaluation, it `*state` is set to zero on return. * Otherwise, it sets `*state` to nonzero. If state is `NULL`, it is not set * in both cases. * * @param[in] path Pathname of a file to load. * @param[in] wrap Either to load under an anonymous module. * @param[out] state State of execution. * @post `*state` is set to zero if succeeded. Nonzero otherwise. * @warning You have to clear the error info with `rb_set_errinfo(Qnil)` if * you decide to ignore the caught exception. * @see rb_load * @see rb_protect * * @internal * * Though not a part of our public API, `state` is in fact an * enum ruby_tag_type. You can see the potential "nonzero" values by looking * at vm_core.h. */ void rb_load_protect(VALUE path, int wrap, int *state); RBIMPL_ATTR_NONNULL(()) /** * Queries if the given feature has already been loaded into the execution * context. The "feature" head are things like `"json"` or `"socket"`. * * @param[in] feature Name of a library you want to know about. * @retval 1 Yes there is. * @retval 0 Not yet. */ int rb_provided(const char *feature); RBIMPL_ATTR_NONNULL((1)) /** * Identical to rb_provided(), except it additionally returns the "canonical" * name of the loaded feature. This can be handy when for instance you want to * know the actually loaded library is either `foo.rb` or `foo.so`. * * @param[in] feature Name of a library you want to know about. * @param[out] loading Return buffer. * @retval 1 Yes there is. * @retval 0 Not yet. */ int rb_feature_provided(const char *feature, const char **loading); RBIMPL_ATTR_NONNULL(()) /** * Declares that the given feature is already provided by someone else. This * API can be handy when you have an extension called `foo.so` which, when * required, also provides functionality of `bar.so`. * * @param[in] feature Name of a library which had already been provided. * @post No further `require` would search `feature`. */ void rb_provide(const char *feature); /** * Identical to rb_require_string(), except it ignores the first argument for * no reason. There seems to be no reason for 3rd party extension libraries to * use it. * * @param[in] self Ignored. Can be anything. * @param[in] feature Name of a feature, e.g. `"json"`. * @exception rb_eLoadError No such feature. * @exception rb_eRuntimeError `$"` is frozen; unable to push. * @retval RUBY_Qtrue The feature is loaded for the first time. * @retval RUBY_Qfalse The feature has already been loaded. * @post `$"` is updated. */ VALUE rb_f_require(VALUE self, VALUE feature); /** * Finds and loads the given feature, if absent. * * If the feature is an absolute path (e.g. starts with `'/'`), the feature * will be loaded directly using the absolute path. If the feature is an * explicit relative path (e.g. starts with `'./'` or `'../'`), the feature * will be loaded using the relative path from the current directory. * Otherwise, the feature will be searched for in the library directories * listed in the `$LOAD_PATH`. * * If the feature has the extension `".rb"`, it is loaded as a source file; if * the extension is `".so"`, `".o"`, or `".dll"`, or the default shared library * extension on the current platform, Ruby loads the shared library as a Ruby * extension. Otherwise, Ruby tries adding `".rb"`, `".so"`, and so on to the * name until found. If the file named cannot be found, a LoadError will be * raised. * * For extension libraries the given feature may use any shared library * extension. For example, on Linux you can require `"socket.dll"` to actually * load `socket.so`. * * The absolute path of the loaded file is added to `$LOADED_FEATURES`. A file * will not be loaded again if its path already appears in there. * * Any constants or globals within the loaded source file will be available in * the calling program's global namespace. However, local variables will not * be propagated to the loading environment. * * @param[in] feature Name of a feature, e.g. `"json"`. * @exception rb_eLoadError No such feature. * @exception rb_eRuntimeError `$"` is frozen; unable to push. * @retval RUBY_Qtrue The feature is loaded for the first time. * @retval RUBY_Qfalse The feature has already been loaded. * @post `$"` is updated. */ VALUE rb_require_string(VALUE feature); /** * Resolves and returns a symbol of a function in the native extension * specified by the feature and symbol names. Extensions will use this function * to access the symbols provided by other native extensions. * * @param[in] feature Name of a feature, e.g. `"json"`. * @param[in] symbol Name of a symbol defined by the feature. * @return The resolved symbol of a function, defined and externed by the * specified feature. It may be NULL if the feature is not loaded, * the feature is not extension, or the symbol is not found. */ void *rb_ext_resolve_symbol(const char *feature, const char *symbol); /** * This macro is to provide backwards compatibility. It provides a way to * define function prototypes and resolving function symbols in a safe way. * * ```CXX * // prototypes * #ifdef HAVE_RB_EXT_RESOLVE_SYMBOL * VALUE *(*other_extension_func)(VALUE,VALUE); * #else * VALUE other_extension_func(VALUE); * #endif * * // in Init_xxx() * #ifdef HAVE_RB_EXT_RESOLVE_SYMBOL * other_extension_func = \ * (VALUE(*)(VALUE,VALUE))rb_ext_resolve_symbol(fname, sym_name); * if (other_extension_func == NULL) { * // raise your own error * } * #endif * ``` */ #define HAVE_RB_EXT_RESOLVE_SYMBOL 1 /** * @name extension configuration * @{ */ /** * Asserts that the extension library that calls this function is aware of * Ractor. Multiple Ractors run without protecting each other. This doesn't * interface well with C programs, unless designed with an in-depth * understanding of how Ractors work. Extension libraries are shut out from * Ractors by default. This API is to bypass that restriction. Once after it * was called, successive calls to rb_define_method() etc. become definitions * of methods that are aware of Ractors. The amendment would be in effect * until the end of rb_require_string() etc. * * @param[in] flag Either the library is aware of Ractors or not. * @post Methods would be callable form Ractors, if `flag` is true. */ void rb_ext_ractor_safe(bool flag); /** @alias{rb_ext_ractor_safe} */ #define RB_EXT_RACTOR_SAFE(f) rb_ext_ractor_safe(f) /** * This macro is to provide backwards compatibility. It must be safe to do * something like: * * ```CXX * #ifdef HAVE_RB_EXT_RACTOR_SAFE * rb_ext_ractor_safe(true); * #endif * ``` */ #define HAVE_RB_EXT_RACTOR_SAFE 1 /** @} */ RBIMPL_SYMBOL_EXPORT_END() #endif /* RBIMPL_INTERN_LOAD_H */ include/ruby/internal/intern/compar.h 0000644 00000005015 15152150475 0013723 0 ustar 00 #ifndef RBIMPL_INTERN_COMPAR_H /*-*-C++-*-vi:se ft=cpp:*/ #define RBIMPL_INTERN_COMPAR_H /** * @file * @author Ruby developers <ruby-core@ruby-lang.org> * @copyright This file is a part of the programming language Ruby. * Permission is hereby granted, to either redistribute and/or * modify this file, provided that the conditions mentioned in the * file COPYING are met. Consult the file for details. * @warning Symbols prefixed with either `RBIMPL` or `rbimpl` are * implementation details. Don't take them as canon. They could * rapidly appear then vanish. The name (path) of this header file * is also an implementation detail. Do not expect it to persist * at the place it is now. Developers are free to move it anywhere * anytime at will. * @note To ruby-core: remember that this header can be possibly * recursively included from extension libraries written in C++. * Do not expect for instance `__VA_ARGS__` is always available. * We assume C99 for ruby itself but we don't assume languages of * extension libraries. They could be written in C++98. * @brief Public APIs related to ::rb_mComparable. */ #include "ruby/internal/attr/cold.h" #include "ruby/internal/attr/noreturn.h" #include "ruby/internal/dllexport.h" #include "ruby/internal/value.h" RBIMPL_SYMBOL_EXPORT_BEGIN() /* bignum.c */ /** * Canonicalises the passed `val`, which is the return value of `a <=> b`, into * C's `{-1, 0, 1}`. This can be handy when you implement a callback function * to pass to `qsort(3)` etc. * * @param[in] val Return value of a space ship operator. * @param[in] a Comparison LHS. * @param[in] b Comparison RHS. * @exception rb_eArgError `a` and `b` are not comparable each other. * @retval -1 `val` is less than zero. * @retval 0 `val` is equal to zero. * @retval 1 `val` is greater than zero. */ int rb_cmpint(VALUE val, VALUE a, VALUE b); /* compar.c */ RBIMPL_ATTR_COLD() RBIMPL_ATTR_NORETURN() /** * Raises "comparison failed" error. * * @param[in] a Comparison LHS. * @param[in] b Comparison RHS. * @exception rb_eArgError `a` and `b` are not comparable each other. */ void rb_cmperr(VALUE a, VALUE b); RBIMPL_SYMBOL_EXPORT_END() #endif /* RBIMPL_INTERN_COMPAR_H */ include/ruby/internal/intern/time.h 0000644 00000014526 15152150475 0013407 0 ustar 00 #ifndef RBIMPL_INTERN_TIME_H /*-*-C++-*-vi:se ft=cpp:*/ #define RBIMPL_INTERN_TIME_H /** * @file * @author Ruby developers <ruby-core@ruby-lang.org> * @copyright This file is a part of the programming language Ruby. * Permission is hereby granted, to either redistribute and/or * modify this file, provided that the conditions mentioned in the * file COPYING are met. Consult the file for details. * @warning Symbols prefixed with either `RBIMPL` or `rbimpl` are * implementation details. Don't take them as canon. They could * rapidly appear then vanish. The name (path) of this header file * is also an implementation detail. Do not expect it to persist * at the place it is now. Developers are free to move it anywhere * anytime at will. * @note To ruby-core: remember that this header can be possibly * recursively included from extension libraries written in C++. * Do not expect for instance `__VA_ARGS__` is always available. * We assume C99 for ruby itself but we don't assume languages of * extension libraries. They could be written in C++98. * @brief Public APIs related to ::rb_cTime. */ #include "ruby/internal/config.h" #ifdef HAVE_TIME_H # include <time.h> /* for time_t */ #endif #include "ruby/internal/attr/nonnull.h" #include "ruby/internal/dllexport.h" #include "ruby/internal/value.h" RBIMPL_SYMBOL_EXPORT_BEGIN() struct timespec; struct timeval; /* time.c */ RBIMPL_ATTR_NONNULL(()) /** * Fills the current time into the given struct. * * @param[out] ts Return buffer. * @exception rb_eSystemCallError Access denied for hardware clock. * @post Current time is stored in `*ts`. */ void rb_timespec_now(struct timespec *ts); /** * Creates an instance of ::rb_cTime with the given time and the local * timezone. * * @param[in] sec Seconds since the UNIX epoch. * @param[in] usec Subsecond part, in microseconds resolution. * @exception rb_eRangeError Cannot express the time. * @return An allocated instance of ::rb_cTime. */ VALUE rb_time_new(time_t sec, long usec); /** * Identical to rb_time_new(), except it accepts the time in nanoseconds * resolution. * * @param[in] sec Seconds since the UNIX epoch. * @param[in] nsec Subsecond part, in nanoseconds resolution. * @exception rb_eRangeError Cannot express the time. * @return An allocated instance of ::rb_cTime. */ VALUE rb_time_nano_new(time_t sec, long nsec); RBIMPL_ATTR_NONNULL(()) /** * Creates an instance of ::rb_cTime, with given time and offset. * * @param[in] ts Time specifier. * @param[in] offset Offset specifier, can take following values: * - `INT_MAX`: `ts` is in local time. * - `INT_MAX - 1`: `ts` is in UTC. * - `-86400` to `86400`: fixed timezone. * @exception rb_eArgError Malformed `offset`. * @return An allocated instance of ::rb_cTime. */ VALUE rb_time_timespec_new(const struct timespec *ts, int offset); /** * Identical to rb_time_timespec_new(), except it takes Ruby values instead of * C structs. * * @param[in] timev Something numeric. Currently Integers, Rationals, * and Floats are accepted. * @param[in] off Offset specifier. As of 2.7 this argument is * heavily extended to take following kinds of * objects: * - ::RUBY_Qundef ... means UTC. * - ::rb_cString ... "+12:34" etc. * - A mysterious "zone" object. This is largely * undocumented. However the initial intent was * that we want to accept * `ActiveSupport::TimeZone` here. Other gems * could also be possible... But how to make an * acceptable class is beyond this document. * @exception rb_eArgError Malformed `off`. * @return An allocated instance of ::rb_cTime. */ VALUE rb_time_num_new(VALUE timev, VALUE off); /** * Creates a "time interval". This basically converts an instance of * ::rb_cNumeric into a struct `timeval`, but for instance negative time * interval must not exist. * * @param[in] num An instance of ::rb_cNumeric. * @exception rb_eArgError `num` is negative. * @exception rb_eRangeError `num` is out of range of `timeval::tv_sec`. * @return A struct that represents the identical time to `num`. */ struct timeval rb_time_interval(VALUE num); /** * Converts an instance of rb_cTime to a struct timeval that represents the * identical point of time. It can also take something numeric; would consider * it as a UNIX time then. * * @param[in] time Instance of either ::rb_cTime or ::rb_cNumeric. * @exception rb_eRangeError `time` is out of range of `timeval::tv_sec`. * @return A struct that represents the identical time to `num`. */ struct timeval rb_time_timeval(VALUE time); /** * Identical to rb_time_timeval(), except for return type. * * @param[in] time Instance of either ::rb_cTime or ::rb_cNumeric. * @exception rb_eRangeError `time` is out of range of `timeval::tv_sec`. * @return A struct that represents the identical time to `num`. */ struct timespec rb_time_timespec(VALUE time); /** * Identical to rb_time_interval(), except for return type. * * @param[in] num An instance of ::rb_cNumeric. * @exception rb_eArgError `num` is negative. * @exception rb_eRangeError `num` is out of range of `timespec::tv_sec`. * @return A struct that represents the identical time to `num`. */ struct timespec rb_time_timespec_interval(VALUE num); /** * Queries the offset, in seconds between the time zone of the time and the * UTC. * * @param[in] time An instance of ::rb_cTime. * @return Numeric offset. */ VALUE rb_time_utc_offset(VALUE time); RBIMPL_SYMBOL_EXPORT_END() #endif /* RBIMPL_INTERN_TIME_H */ include/ruby/internal/intern/file.h 0000644 00000022576 15152150475 0013374 0 ustar 00 #ifndef RBIMPL_INTERN_FILE_H /*-*-C++-*-vi:se ft=cpp:*/ #define RBIMPL_INTERN_FILE_H /** * @file * @author Ruby developers <ruby-core@ruby-lang.org> * @copyright This file is a part of the programming language Ruby. * Permission is hereby granted, to either redistribute and/or * modify this file, provided that the conditions mentioned in the * file COPYING are met. Consult the file for details. * @warning Symbols prefixed with either `RBIMPL` or `rbimpl` are * implementation details. Don't take them as canon. They could * rapidly appear then vanish. The name (path) of this header file * is also an implementation detail. Do not expect it to persist * at the place it is now. Developers are free to move it anywhere * anytime at will. * @note To ruby-core: remember that this header can be possibly * recursively included from extension libraries written in C++. * Do not expect for instance `__VA_ARGS__` is always available. * We assume C99 for ruby itself but we don't assume languages of * extension libraries. They could be written in C++98. * @brief Public APIs related to ::rb_cFile. */ #include "ruby/internal/attr/nonnull.h" #include "ruby/internal/attr/pure.h" #include "ruby/internal/dllexport.h" #include "ruby/internal/value.h" RBIMPL_SYMBOL_EXPORT_BEGIN() /* file.c */ RBIMPL_ATTR_NONNULL(()) /** * Identical to rb_file_expand_path(), except how arguments are passed. * * @param[in] argc Number of objects of `argv`. * @param[in] argv Filename, and base directory, in that order. * @exception rb_eArgError Wrong `argc`. * @exception rb_eTypeError Non-string passed. * @exception rb_eEncCompatError No conversion from arguments to a path. * @return Expanded path. * * @internal * * It seems nobody actually uses this function right now. Maybe delete it? */ VALUE rb_file_s_expand_path(int argc, const VALUE *argv); /** * Identical to rb_file_absolute_path(), except it additionally understands * `~`. If a given pathname starts with `~someone/`, that part expands to the * user's home directory (or that of current process' owner's in case of `~/`). * * @param[in] fname Relative file name. * @param[in] dname Lookup base directory name, or in case * ::RUBY_Qnil is passed the process' current * working directory is assumed. * @exception rb_eArgError Home directory is not absolute. * @exception rb_eTypeError Non-string passed. * @exception rb_eEncCompatError No conversion from arguments to a path. * @return Expanded path. */ VALUE rb_file_expand_path(VALUE fname, VALUE dname); RBIMPL_ATTR_NONNULL(()) /** * Identical to rb_file_absolute_path(), except how arguments are passed. * * @param[in] argc Number of objects of `argv`. * @param[in] argv Filename, and base directory, in that order. * @exception rb_eArgError Wrong `argc`. * @exception rb_eTypeError Non-string passed. * @exception rb_eEncCompatError No conversion from arguments to a path. * @return Expanded path. * * @internal * * It seems nobody actually uses this function right now. Maybe delete it? */ VALUE rb_file_s_absolute_path(int argc, const VALUE *argv); /** * Maps a relative path to its absolute representation. Relative paths are * referenced from the passed directory name, or from the process' current * working directory in case ::RUBY_Qnil is passed. * * @param[in] fname Relative file name. * @param[in] dname Lookup base directory name, or in case * ::RUBY_Qnil is passed the process' current * working directory is assumed. * @exception rb_eArgError Strings contain NUL bytes. * @exception rb_eTypeError Non-string passed. * @exception rb_eEncCompatError No conversion from arguments to a path. * @return Expanded path. */ VALUE rb_file_absolute_path(VALUE fname, VALUE dname); /** * Strips a file path's last component (and trailing separators if any). This * function is relatively simple on POSIX environments; just splits the input * with `/`, strips the last one, if something remains joins them again, * otherwise the return value is `"."`. However when it comes to Windows this * function is quite very much complicated. We have to take UNC etc. into * account. So for instance `"C:foo"`'s dirname is `"C:."`. * * @param[in] fname File name to strip. * @exception rb_eTypeError `fname` is not a String. * @exception rb_eArgError `fname` contains NUL bytes. * @exception rb_eEncCompatError `fname`'s encoding is not path-compat. * @return A dirname of `fname`. * @note This is a "pure" operation; it computes the return value solely * from the passed object and never does any file IO. */ VALUE rb_file_dirname(VALUE fname); RBIMPL_ATTR_NONNULL(()) /** * Resolves a feature's path. This function takes for instance `"json"` and * `[".so", ".rb"]`, and iterates over the `$LOAD_PATH` to see if there is * either `json.so` or `json.rb` in the directory. * * This is not what everything `require` does, but at least `require` is built * on top of it. * * @param[in,out] feature File to search, and return buffer. * @param[in] exts List of file extensions. * @exception rb_eTypeError `feature` is not a String. * @exception rb_eArgError `feature` contains NUL bytes. * @exception rb_eEncCompatError `feature`'s encoding is not path-compat. * @retval 0 Not found * @retval otherwise Found index in `ext`, plus one. * @post `*feature` is a resolved path. */ int rb_find_file_ext(VALUE *feature, const char *const *exts); /** * Identical to rb_find_file_ext(), except it takes a feature name and is * extension at once, e.g. `"json.rb"`. This difference is much like how * `require` and `load` are different. * * @param[in] path A path relative to `$LOAD_PATH`. * @exception rb_eTypeError `path` is not a String. * @exception rb_eArgError `path` contains NUL bytes. * @exception rb_eEncCompatError `path`'s encoding is not path-compat. * @return Expanded path. */ VALUE rb_find_file(VALUE path); /** * Queries if the given path is either a directory, or a symlink that * (potentially recursively) points to such thing. * * @param[in] _ Ignored (why...?) * @param[in] path String, or IO. In case of IO it issues * `fstat(2)` instead of `stat(2)`. * @exception rb_eFrozenError `path` is a frozen IO (why...?) * @exception rb_eTypeError `path` is neither String nor IO. * @exception rb_eArgError `path` contains NUL bytes. * @exception rb_eEncCompatError `path`'s encoding is not path-compat. * @retval RUBY_Qtrue `path` is a directory. * @retval RUBY_Qfalse Otherwise. */ VALUE rb_file_directory_p(VALUE _, VALUE path); /** * Converts a string into an "OS Path" encoding, if any. In most operating * systems there are no such things like per-OS default encoding of filename. * For them this function is no-op. However most notably on MacOS, pathnames * are UTF-8 encoded. It converts the given string into such encoding. * * @param[in] path An instance of ::rb_cString. * @exception rb_eEncCompatError `path`'s encoding is not path-compat. * @return `path`'s contents converted to the OS' path encoding. */ VALUE rb_str_encode_ospath(VALUE path); RBIMPL_ATTR_NONNULL(()) RBIMPL_ATTR_PURE() /** * Queries if the given path is an absolute path. On POSIX environments it is * as easy as `path[0] == '/'`. However on Windows, drive letters and UNC * paths are also taken into account. * * @param[in] path A possibly relative path string. * @retval 1 `path` is absolute. * @retval 0 `path` is relative. */ int rb_is_absolute_path(const char *path); /** * Queries the file size of the given file. Because this function calls * `fstat(2)` internally, it is a failure to pass a closed file to this * function. * * This function flushes the passed file's buffer if any. Can take time. * * @param[in] file A file object. * @exception rb_eFrozenError `file` is frozen. * @exception rb_eIOError `file` is closed. * @exception rb_eSystemCallError Permission denied etc. * @exception rb_eNoMethodError The given non-file object doesn't respond * to `#size`. * @return The size of the passed file. * @note Passing a non-regular file such as a UNIX domain socket to this * function is not a failure. But the return value is * unpredictable. POSIX's `<sys/stat.h>` states that "the use of * this field is unspecified" then. */ rb_off_t rb_file_size(VALUE file); RBIMPL_SYMBOL_EXPORT_END() #endif /* RBIMPL_INTERN_FILE_H */ include/ruby/internal/intern/enumerator.h 0000644 00000030206 15152150475 0014623 0 ustar 00 #ifndef RBIMPL_INTERN_ENUMERATOR_H /*-*-C++-*-vi:se ft=cpp:*/ #define RBIMPL_INTERN_ENUMERATOR_H /** * @file * @author Ruby developers <ruby-core@ruby-lang.org> * @copyright This file is a part of the programming language Ruby. * Permission is hereby granted, to either redistribute and/or * modify this file, provided that the conditions mentioned in the * file COPYING are met. Consult the file for details. * @warning Symbols prefixed with either `RBIMPL` or `rbimpl` are * implementation details. Don't take them as canon. They could * rapidly appear then vanish. The name (path) of this header file * is also an implementation detail. Do not expect it to persist * at the place it is now. Developers are free to move it anywhere * anytime at will. * @note To ruby-core: remember that this header can be possibly * recursively included from extension libraries written in C++. * Do not expect for instance `__VA_ARGS__` is always available. * We assume C99 for ruby itself but we don't assume languages of * extension libraries. They could be written in C++98. * @brief Public APIs related to ::rb_cEnumerator. */ #include "ruby/internal/attr/nonnull.h" #include "ruby/internal/dllexport.h" #include "ruby/internal/intern/eval.h" /* rb_frame_this_func */ #include "ruby/internal/iterator.h" /* rb_block_given_p */ #include "ruby/internal/symbol.h" #include "ruby/internal/value.h" RBIMPL_SYMBOL_EXPORT_BEGIN() /** * This is the type of functions that rb_enumeratorize_with_size() expects. In * theory an enumerator can have indefinite number of elements, but in practice * it often is the case we can compute the size of an enumerator beforehand. * If your enumerator has such property, supply a function that calculates such * values. * * @param[in] recv The original receiver of the enumerator. * @param[in] argv Arguments passed to `Object#enum_for` etc. * @param[in] eobj The enumerator object. * @return The size of `eobj`, in ::rb_cNumeric, or ::RUBY_Qnil if the size * is not known until we actually iterate. */ typedef VALUE rb_enumerator_size_func(VALUE recv, VALUE argv, VALUE eobj); /** * Decomposed `Enumerator::ArithmeicSequence`. This is a subclass of * ::rb_cEnumerator, which represents a sequence of numbers with common * difference. Internal data structure of the class is opaque to users, but * you can obtain a decomposed one using rb_arithmetic_sequence_extract(). */ typedef struct { VALUE begin; /**< "Left" or "lowest" endpoint of the sequence. */ VALUE end; /**< "Right" or "highest" endpoint of the sequence.*/ VALUE step; /**< Step between a sequence. */ int exclude_end; /**< Whether the endpoint is open or closed. */ } rb_arithmetic_sequence_components_t; /* enumerator.c */ /** * Constructs an enumerator. This roughly resembles `Object#enum_for`. * * @param[in] recv A receiver of `meth`. * @param[in] meth Method ID in a symbol object. * @param[in] argc Number of objects of `argv`. * @param[in] argv Arguments passed to `meth`. * @exception rb_eTypeError `meth` is not an instance of ::rb_cSymbol. * @return A new instance of ::rb_cEnumerator which, when yielded, * enumerates by calling `meth` on `recv` with `argv`. */ VALUE rb_enumeratorize(VALUE recv, VALUE meth, int argc, const VALUE *argv); /** * Identical to rb_enumeratorize(), except you can additionally specify the * size function of return value. * * @param[in] recv A receiver of `meth`. * @param[in] meth Method ID in a symbol object. * @param[in] argc Number of objects of `argv`. * @param[in] argv Arguments passed to `meth`. * @param[in] func Size calculator. * @exception rb_eTypeError `meth` is not an instance of ::rb_cSymbol. * @return A new instance of ::rb_cEnumerator which, when yielded, * enumerates by calling `meth` on `recv` with `argv`. * @note `func` can be zero, which means the size is unknown. */ VALUE rb_enumeratorize_with_size(VALUE recv, VALUE meth, int argc, const VALUE *argv, rb_enumerator_size_func *func); /** * Identical to rb_enumeratorize_with_func(), except you can specify how to * handle the last element of the given array. * * @param[in] recv A receiver of `meth`. * @param[in] meth Method ID in a symbol object. * @param[in] argc Number of objects of `argv`. * @param[in] argv Arguments passed to `meth`. * @param[in] func Size calculator. * @param[in] kw_splat Handling of keyword parameters: * - RB_NO_KEYWORDS `argv`'s last is not a keyword argument. * - RB_PASS_KEYWORDS `argv`'s last is a keyword argument. * - RB_PASS_CALLED_KEYWORDS it depends if there is a passed block. * @exception rb_eTypeError `meth` is not an instance of ::rb_cSymbol. * @return A new instance of ::rb_cEnumerator which, when yielded, * enumerates by calling `meth` on `recv` with `argv`. * @note `func` can be zero, which means the size is unknown. */ VALUE rb_enumeratorize_with_size_kw(VALUE recv, VALUE meth, int argc, const VALUE *argv, rb_enumerator_size_func *func, int kw_splat); RBIMPL_ATTR_NONNULL(()) /** * Extracts components of the passed arithmetic sequence. This can be seen as * an extended version of rb_range_values(). * * @param[in] as Target instance of `Enumerator::ArithmericSequence`. * @param[out] buf Decomposed results buffer. * @return 0 `as` is not `Enumerator::ArithmericSequence`. * @return 1 Success. * @post `buf` is filled. */ int rb_arithmetic_sequence_extract(VALUE as, rb_arithmetic_sequence_components_t *buf); RBIMPL_ATTR_NONNULL(()) /** * Identical to rb_range_beg_len(), except it takes an instance of * `Enumerator::ArithmericSequence`. * * @param[in] as An `Enumerator::ArithmericSequence` instance. * @param[out] begp Return value buffer. * @param[out] lenp Return value buffer. * @param[out] stepp Return value buffer. * @param[in] len Updated length. * @param[in] err In case `len` is out of range... * - `0`: returns ::RUBY_Qnil. * - `1`: raises ::rb_eRangeError. * - `2`: `beg` and `len` expanded accordingly. * @exception rb_eRangeError `as` cannot fit into `long`. * @retval RUBY_Qfalse `as` is not `Enumerator::ArithmericSequence`. * @retval RUBY_Qnil `len` is out of `as` but `err` is zero. * @retval RUBY_Qtrue Otherwise. * @post `beg` is the (possibly updated) left endpoint. * @post `len` is the (possibly updated) length of the range. * * @internal * * Currently no 3rd party applications of this function is found. But that can * be because this function is relatively new. */ VALUE rb_arithmetic_sequence_beg_len_step(VALUE as, long *begp, long *lenp, long *stepp, long len, int err); RBIMPL_SYMBOL_EXPORT_END() /** @cond INTERNAL_MACRO */ #ifndef RUBY_EXPORT # define rb_enumeratorize_with_size(obj, id, argc, argv, size_fn) \ rb_enumeratorize_with_size(obj, id, argc, argv, (rb_enumerator_size_func *)(size_fn)) # define rb_enumeratorize_with_size_kw(obj, id, argc, argv, size_fn, kw_splat) \ rb_enumeratorize_with_size_kw(obj, id, argc, argv, (rb_enumerator_size_func *)(size_fn), kw_splat) #endif /** @endcond */ /** * This is an implementation detail of #RETURN_SIZED_ENUMERATOR(). You could * use it directly, but can hardly be handy. * * @param[in] obj A receiver. * @param[in] argc Number of objects of `argv`. * @param[in] argv Arguments passed to the current method. * @param[in] size_fn Size calculator. * @return A new instance of ::rb_cEnumerator which, when yielded, * enumerates by calling the current method on `recv` with `argv`. */ #define SIZED_ENUMERATOR(obj, argc, argv, size_fn) \ rb_enumeratorize_with_size((obj), ID2SYM(rb_frame_this_func()), \ (argc), (argv), (size_fn)) /** * This is an implementation detail of #RETURN_SIZED_ENUMERATOR_KW(). You * could use it directly, but can hardly be handy. * * @param[in] obj A receiver. * @param[in] argc Number of objects of `argv`. * @param[in] argv Arguments passed to the current method. * @param[in] size_fn Size calculator. * @param[in] kw_splat Handling of keyword parameters: * - RB_NO_KEYWORDS `argv`'s last is not a keyword argument. * - RB_PASS_KEYWORDS `argv`'s last is a keyword argument. * - RB_PASS_CALLED_KEYWORDS it depends if there is a passed block. * @return A new instance of ::rb_cEnumerator which, when yielded, * enumerates by calling the current method on `recv` with `argv`. */ #define SIZED_ENUMERATOR_KW(obj, argc, argv, size_fn, kw_splat) \ rb_enumeratorize_with_size_kw((obj), ID2SYM(rb_frame_this_func()), \ (argc), (argv), (size_fn), (kw_splat)) /** * This roughly resembles `return enum_for(__callee__) unless block_given?`. * * @param[in] obj A receiver. * @param[in] argc Number of objects of `argv`. * @param[in] argv Arguments passed to the current method. * @param[in] size_fn Size calculator. * @note This macro may return inside. */ #define RETURN_SIZED_ENUMERATOR(obj, argc, argv, size_fn) do { \ if (!rb_block_given_p()) \ return SIZED_ENUMERATOR(obj, argc, argv, size_fn); \ } while (0) /** * Identical to #RETURN_SIZED_ENUMERATOR(), except you can specify how to * handle the last element of the given array. * * @param[in] obj A receiver. * @param[in] argc Number of objects of `argv`. * @param[in] argv Arguments passed to the current method. * @param[in] size_fn Size calculator. * @param[in] kw_splat Handling of keyword parameters: * - RB_NO_KEYWORDS `argv`'s last is not a keyword argument. * - RB_PASS_KEYWORDS `argv`'s last is a keyword argument. * - RB_PASS_CALLED_KEYWORDS it depends if there is a passed block. * @note This macro may return inside. */ #define RETURN_SIZED_ENUMERATOR_KW(obj, argc, argv, size_fn, kw_splat) do { \ if (!rb_block_given_p()) \ return SIZED_ENUMERATOR_KW(obj, argc, argv, size_fn, kw_splat); \ } while (0) /** * Identical to #RETURN_SIZED_ENUMERATOR(), except its size is unknown. * * @param[in] obj A receiver. * @param[in] argc Number of objects of `argv`. * @param[in] argv Arguments passed to the current method. * @note This macro may return inside. */ #define RETURN_ENUMERATOR(obj, argc, argv) \ RETURN_SIZED_ENUMERATOR(obj, argc, argv, 0) /** * Identical to #RETURN_SIZED_ENUMERATOR_KW(), except its size is unknown. It * can also be seen as a routine identical to #RETURN_ENUMERATOR(), except you * can specify how to handle the last element of the given array. * * @param[in] obj A receiver. * @param[in] argc Number of objects of `argv`. * @param[in] argv Arguments passed to the current method. * @param[in] kw_splat Handling of keyword parameters: * - RB_NO_KEYWORDS `argv`'s last is not a keyword argument. * - RB_PASS_KEYWORDS `argv`'s last is a keyword argument. * - RB_PASS_CALLED_KEYWORDS it depends if there is a passed block. * @note This macro may return inside. */ #define RETURN_ENUMERATOR_KW(obj, argc, argv, kw_splat) \ RETURN_SIZED_ENUMERATOR_KW(obj, argc, argv, 0, kw_splat) #endif /* RBIMPL_INTERN_ENUMERATOR_H */ include/ruby/internal/intern/range.h 0000644 00000007747 15152150475 0013554 0 ustar 00 #ifndef RBIMPL_INTERN_RANGE_H /*-*-C++-*-vi:se ft=cpp:*/ #define RBIMPL_INTERN_RANGE_H /** * @file * @author Ruby developers <ruby-core@ruby-lang.org> * @copyright This file is a part of the programming language Ruby. * Permission is hereby granted, to either redistribute and/or * modify this file, provided that the conditions mentioned in the * file COPYING are met. Consult the file for details. * @warning Symbols prefixed with either `RBIMPL` or `rbimpl` are * implementation details. Don't take them as canon. They could * rapidly appear then vanish. The name (path) of this header file * is also an implementation detail. Do not expect it to persist * at the place it is now. Developers are free to move it anywhere * anytime at will. * @note To ruby-core: remember that this header can be possibly * recursively included from extension libraries written in C++. * Do not expect for instance `__VA_ARGS__` is always available. * We assume C99 for ruby itself but we don't assume languages of * extension libraries. They could be written in C++98. * @brief Public APIs related to ::rb_cRange. */ #include "ruby/internal/attr/nonnull.h" #include "ruby/internal/dllexport.h" #include "ruby/internal/value.h" RBIMPL_SYMBOL_EXPORT_BEGIN() /* range.c */ /** * Creates a new Range. * * @param[in] beg "Left" or "lowest" endpoint of the range. * @param[in] end "Right" or "highest" endpoint of the range. * @param[in] excl Whether the range is open-ended. * @exception rb_eArgError `beg` and `end` are not comparable. * @note These days both endpoints can be ::RUBY_Qnil, which means that * endpoint is unbound. */ VALUE rb_range_new(VALUE beg, VALUE end, int excl); RBIMPL_ATTR_NONNULL(()) /** * Deconstructs a numerical range. As the arguments are `long` based, it * expects everything are in the `long` domain. * * @param[in] range A range of numerical endpoints. * @param[out] begp Return value buffer. * @param[out] lenp Return value buffer. * @param[in] len Updated length. * @param[in] err In case `len` is out of range... * - `0`: returns ::RUBY_Qnil. * - `1`: raises ::rb_eRangeError. * - `2`: `beg` and `len` expanded accordingly. * @exception rb_eTypeError `range` is not a numerical range. * @exception rb_eRangeError `range` cannot fit into `long`. * @retval RUBY_Qfalse `range` is not an ::rb_cRange. * @retval RUBY_Qnil `len` is out of `range` but `err` is zero. * @retval RUBY_Qtrue Otherwise. * @post `beg` is the (possibly updated) left endpoint. * @post `len` is the (possibly updated) length of the range. * * @internal * * The complex error handling switch reflects the fact that `Array#[]=` and * `String#[]=` behave differently when they take ranges. */ VALUE rb_range_beg_len(VALUE range, long *begp, long *lenp, long len, int err); RBIMPL_ATTR_NONNULL(()) /** * Deconstructs a range into its components. * * @param[in] range Range or range-ish object. * @param[out] begp Return value buffer. * @param[out] endp Return value buffer. * @param[out] exclp Return value buffer. * @retval RUBY_Qfalse `range` is not an instance of ::rb_cRange. * @retval RUBY_Qtrue Argument pointers are updated. * @post `*begp` is the left endpoint of the range. * @post `*endp` is the right endpoint of the range. * @post `*exclp` is whether the range is open-ended or not. */ int rb_range_values(VALUE range, VALUE *begp, VALUE *endp, int *exclp); RBIMPL_SYMBOL_EXPORT_END() #endif /* RBIMPL_INTERN_RANGE_H */ include/ruby/internal/intern/enum.h 0000644 00000005513 15152150475 0013411 0 ustar 00 #ifndef RBIMPL_INTERN_ENUM_H /*-*-C++-*-vi:se ft=cpp:*/ #define RBIMPL_INTERN_ENUM_H /** * @file * @author Ruby developers <ruby-core@ruby-lang.org> * @copyright This file is a part of the programming language Ruby. * Permission is hereby granted, to either redistribute and/or * modify this file, provided that the conditions mentioned in the * file COPYING are met. Consult the file for details. * @warning Symbols prefixed with either `RBIMPL` or `rbimpl` are * implementation details. Don't take them as canon. They could * rapidly appear then vanish. The name (path) of this header file * is also an implementation detail. Do not expect it to persist * at the place it is now. Developers are free to move it anywhere * anytime at will. * @note To ruby-core: remember that this header can be possibly * recursively included from extension libraries written in C++. * Do not expect for instance `__VA_ARGS__` is always available. * We assume C99 for ruby itself but we don't assume languages of * extension libraries. They could be written in C++98. * @brief Public APIs related to ::rb_mEnumerable. */ #include "ruby/internal/dllexport.h" #include "ruby/internal/value.h" RBIMPL_SYMBOL_EXPORT_BEGIN() /* enum.c */ /** * Basically identical to rb_ary_new_form_values(), except it returns something * different when `argc` < 2. * * @param[in] argc Number of objects of `argv`. * @param[in] argv Arbitrary objects. * @retval RUBY_Qnil `argc` is zero. * @retval argv[0] `argc` is one. * @retval otherwise Otherwise. * * @internal * * What is this business? Well, this function is about `yield`'s taking * multiple values. Consider following user-defined class: * * ```ruby * class Foo * include Enumerable * * def each * yield :q, :w, :e, :r * end * end * * Foo.new.each_with_object([]) do |i, j| * j << i # ^^^ <- What to expect for `i`? * end * ``` * * Here, `Foo#each_with_object` is in fact `Enumerable#each_with_object`, which * doesn't know what would be yielded. Yet, it has to take a block of arity 2. * This function is used here, to "pack" arbitrary number of yielded objects * into one. * * If people want to implement their own `Enumerable#each_with_object` this API * can be handy. Though @shyouhei suspects it is relatively rare for 3rd party * extension libraries to have such things. Also `Enumerable#each_entry` is * basically this function exposed as a Ruby method. */ VALUE rb_enum_values_pack(int argc, const VALUE *argv); RBIMPL_SYMBOL_EXPORT_END() #endif /* RBIMPL_INTERN_ENUM_H */ include/ruby/internal/anyargs.h 0000644 00000110607 15152150475 0012613 0 ustar 00 #ifndef RBIMPL_ANYARGS_H /*-*-C++-*-vi:se ft=cpp:*/ #define RBIMPL_ANYARGS_H /** * @file * @author Ruby developers <ruby-core@ruby-lang.org> * @copyright This file is a part of the programming language Ruby. * Permission is hereby granted, to either redistribute and/or * modify this file, provided that the conditions mentioned in the * file COPYING are met. Consult the file for details. * @warning Symbols prefixed with either `RBIMPL` or `rbimpl` are * implementation details. Don't take them as canon. They could * rapidly appear then vanish. The name (path) of this header file * is also an implementation detail. Do not expect it to persist * at the place it is now. Developers are free to move it anywhere * anytime at will. * @note To ruby-core: remember that this header can be possibly * recursively included from extension libraries written in C++. * Do not expect for instance `__VA_ARGS__` is always available. * We assume C99 for ruby itself but we don't assume languages of * extension libraries. They could be written in C++98. * @brief Function overloads to issue warnings around #ANYARGS. * * For instance ::rb_define_method takes a pointer to #ANYARGS -ed functions, * which in fact varies 18 different prototypes. We still need to preserve * #ANYARGS for storages but why not check the consistencies if possible. With * those complex macro overlays defined in this header file, use of a function * pointer gets checked against the corresponding arity argument. * * ### Q&A ### * * - Q: Where did the magic number "18" came from in the description above? * * - A: Count the case branch of `vm_method.c:call_cfunc_invoker_func()`. Note * also that the 18 branches has lasted for at least 25 years. See also * commit 200e0ee2fd3c1c006c528874a88f684447215524. * * - Q: What is this `__weakref__` thing? * * - A: That is a kind of function overloading mechanism that GCC provides. In * this case for instance `rb_define_method_00` is an alias of * ::rb_define_method, with a strong type. * * - Q: What is this `__transparent_union__` thing? * * A: That is another kind of function overloading mechanism that GCC * provides. In this case the attributed function pointer is either * `VALUE(*)(int,VALUE*,VALUE)` or `VALUE(*)(int,const VALUE*,VALUE)`. * * This is better than `void*` or #ANYARGS because we can reject all other * possibilities than the two. * * - Q: What does this #rb_define_method macro mean? * * - A: It selects appropriate alias of the ::rb_define_method function, * depending on the last (arity) argument. * * - Q: Why the special case for ::rb_f_notimplement ? * * - A: Function pointer to ::rb_f_notimplement is special cased in * `vm_method.c:rb_add_method_cfunc()`. That should be handled by the * `__builtin_choose_expr` chain inside of #rb_define_method macro * expansion. In order to do so, comparison like * `(func == rb_f_notimplement)` is inappropriate for * `__builtin_choose_expr`'s expression (which must be a compile-time * integer constant but the address of ::rb_f_notimplement is not fixed * until the linker). Instead we are using * `__builtin_types_compatible_p`, and in doing so we need to distinguish * ::rb_f_notimplement from others, by type. */ #include "ruby/internal/attr/maybe_unused.h" #include "ruby/internal/attr/nonnull.h" #include "ruby/internal/attr/weakref.h" #include "ruby/internal/cast.h" #include "ruby/internal/config.h" #include "ruby/internal/has/attribute.h" #include "ruby/internal/intern/class.h" #include "ruby/internal/intern/vm.h" #include "ruby/internal/method.h" #include "ruby/internal/value.h" #include "ruby/backward/2/stdarg.h" #if defined(__cplusplus) # include "ruby/backward/cxxanyargs.hpp" #elif defined(_WIN32) || defined(__CYGWIN__) # /* Skip due to [Bug #16134] */ #elif ! RBIMPL_HAS_ATTRIBUTE(transparent_union) # /* :TODO: improve here, please find a way to support. */ #elif ! defined(HAVE_VA_ARGS_MACRO) # /* :TODO: improve here, please find a way to support. */ #else # /** @cond INTERNAL_MACRO */ # if ! defined(HAVE_BUILTIN___BUILTIN_TYPES_COMPATIBLE_P) # define RBIMPL_CFUNC_IS_rb_f_notimplement(f) 0 # else # define RBIMPL_CFUNC_IS_rb_f_notimplement(f) \ __builtin_types_compatible_p( \ __typeof__(f), \ __typeof__(rb_f_notimplement)) # endif # if ! defined(HAVE_BUILTIN___BUILTIN_CHOOSE_EXPR_CONSTANT_P) # define RBIMPL_ANYARGS_DISPATCH(expr, truthy, falsy) (falsy) # else # define RBIMPL_ANYARGS_DISPATCH(expr, truthy, falsy) \ __builtin_choose_expr( \ __builtin_choose_expr( \ __builtin_constant_p(expr), \ (expr), 0), \ (truthy), (falsy)) # endif # define RBIMPL_ANYARGS_DISPATCH_rb_define_singleton_method_m2(n) RBIMPL_ANYARGS_DISPATCH((n) == -2, rb_define_singleton_method_m2, rb_define_singleton_method_m3) # define RBIMPL_ANYARGS_DISPATCH_rb_define_singleton_method_m1(n) RBIMPL_ANYARGS_DISPATCH((n) == -1, rb_define_singleton_method_m1, RBIMPL_ANYARGS_DISPATCH_rb_define_singleton_method_m2(n)) # define RBIMPL_ANYARGS_DISPATCH_rb_define_singleton_method_00(n) RBIMPL_ANYARGS_DISPATCH((n) == 0, rb_define_singleton_method_00, RBIMPL_ANYARGS_DISPATCH_rb_define_singleton_method_m1(n)) # define RBIMPL_ANYARGS_DISPATCH_rb_define_singleton_method_01(n) RBIMPL_ANYARGS_DISPATCH((n) == 1, rb_define_singleton_method_01, RBIMPL_ANYARGS_DISPATCH_rb_define_singleton_method_00(n)) # define RBIMPL_ANYARGS_DISPATCH_rb_define_singleton_method_02(n) RBIMPL_ANYARGS_DISPATCH((n) == 2, rb_define_singleton_method_02, RBIMPL_ANYARGS_DISPATCH_rb_define_singleton_method_01(n)) # define RBIMPL_ANYARGS_DISPATCH_rb_define_singleton_method_03(n) RBIMPL_ANYARGS_DISPATCH((n) == 3, rb_define_singleton_method_03, RBIMPL_ANYARGS_DISPATCH_rb_define_singleton_method_02(n)) # define RBIMPL_ANYARGS_DISPATCH_rb_define_singleton_method_04(n) RBIMPL_ANYARGS_DISPATCH((n) == 4, rb_define_singleton_method_04, RBIMPL_ANYARGS_DISPATCH_rb_define_singleton_method_03(n)) # define RBIMPL_ANYARGS_DISPATCH_rb_define_singleton_method_05(n) RBIMPL_ANYARGS_DISPATCH((n) == 5, rb_define_singleton_method_05, RBIMPL_ANYARGS_DISPATCH_rb_define_singleton_method_04(n)) # define RBIMPL_ANYARGS_DISPATCH_rb_define_singleton_method_06(n) RBIMPL_ANYARGS_DISPATCH((n) == 6, rb_define_singleton_method_06, RBIMPL_ANYARGS_DISPATCH_rb_define_singleton_method_05(n)) # define RBIMPL_ANYARGS_DISPATCH_rb_define_singleton_method_07(n) RBIMPL_ANYARGS_DISPATCH((n) == 7, rb_define_singleton_method_07, RBIMPL_ANYARGS_DISPATCH_rb_define_singleton_method_06(n)) # define RBIMPL_ANYARGS_DISPATCH_rb_define_singleton_method_08(n) RBIMPL_ANYARGS_DISPATCH((n) == 8, rb_define_singleton_method_08, RBIMPL_ANYARGS_DISPATCH_rb_define_singleton_method_07(n)) # define RBIMPL_ANYARGS_DISPATCH_rb_define_singleton_method_09(n) RBIMPL_ANYARGS_DISPATCH((n) == 9, rb_define_singleton_method_09, RBIMPL_ANYARGS_DISPATCH_rb_define_singleton_method_08(n)) # define RBIMPL_ANYARGS_DISPATCH_rb_define_singleton_method_10(n) RBIMPL_ANYARGS_DISPATCH((n) == 10, rb_define_singleton_method_10, RBIMPL_ANYARGS_DISPATCH_rb_define_singleton_method_09(n)) # define RBIMPL_ANYARGS_DISPATCH_rb_define_singleton_method_11(n) RBIMPL_ANYARGS_DISPATCH((n) == 11, rb_define_singleton_method_11, RBIMPL_ANYARGS_DISPATCH_rb_define_singleton_method_10(n)) # define RBIMPL_ANYARGS_DISPATCH_rb_define_singleton_method_12(n) RBIMPL_ANYARGS_DISPATCH((n) == 12, rb_define_singleton_method_12, RBIMPL_ANYARGS_DISPATCH_rb_define_singleton_method_11(n)) # define RBIMPL_ANYARGS_DISPATCH_rb_define_singleton_method_13(n) RBIMPL_ANYARGS_DISPATCH((n) == 13, rb_define_singleton_method_13, RBIMPL_ANYARGS_DISPATCH_rb_define_singleton_method_12(n)) # define RBIMPL_ANYARGS_DISPATCH_rb_define_singleton_method_14(n) RBIMPL_ANYARGS_DISPATCH((n) == 14, rb_define_singleton_method_14, RBIMPL_ANYARGS_DISPATCH_rb_define_singleton_method_13(n)) # define RBIMPL_ANYARGS_DISPATCH_rb_define_singleton_method_15(n) RBIMPL_ANYARGS_DISPATCH((n) == 15, rb_define_singleton_method_15, RBIMPL_ANYARGS_DISPATCH_rb_define_singleton_method_14(n)) # define RBIMPL_ANYARGS_DISPATCH_rb_define_protected_method_m2(n) RBIMPL_ANYARGS_DISPATCH((n) == -2, rb_define_protected_method_m2, rb_define_protected_method_m3) # define RBIMPL_ANYARGS_DISPATCH_rb_define_protected_method_m1(n) RBIMPL_ANYARGS_DISPATCH((n) == -1, rb_define_protected_method_m1, RBIMPL_ANYARGS_DISPATCH_rb_define_protected_method_m2(n)) # define RBIMPL_ANYARGS_DISPATCH_rb_define_protected_method_00(n) RBIMPL_ANYARGS_DISPATCH((n) == 0, rb_define_protected_method_00, RBIMPL_ANYARGS_DISPATCH_rb_define_protected_method_m1(n)) # define RBIMPL_ANYARGS_DISPATCH_rb_define_protected_method_01(n) RBIMPL_ANYARGS_DISPATCH((n) == 1, rb_define_protected_method_01, RBIMPL_ANYARGS_DISPATCH_rb_define_protected_method_00(n)) # define RBIMPL_ANYARGS_DISPATCH_rb_define_protected_method_02(n) RBIMPL_ANYARGS_DISPATCH((n) == 2, rb_define_protected_method_02, RBIMPL_ANYARGS_DISPATCH_rb_define_protected_method_01(n)) # define RBIMPL_ANYARGS_DISPATCH_rb_define_protected_method_03(n) RBIMPL_ANYARGS_DISPATCH((n) == 3, rb_define_protected_method_03, RBIMPL_ANYARGS_DISPATCH_rb_define_protected_method_02(n)) # define RBIMPL_ANYARGS_DISPATCH_rb_define_protected_method_04(n) RBIMPL_ANYARGS_DISPATCH((n) == 4, rb_define_protected_method_04, RBIMPL_ANYARGS_DISPATCH_rb_define_protected_method_03(n)) # define RBIMPL_ANYARGS_DISPATCH_rb_define_protected_method_05(n) RBIMPL_ANYARGS_DISPATCH((n) == 5, rb_define_protected_method_05, RBIMPL_ANYARGS_DISPATCH_rb_define_protected_method_04(n)) # define RBIMPL_ANYARGS_DISPATCH_rb_define_protected_method_06(n) RBIMPL_ANYARGS_DISPATCH((n) == 6, rb_define_protected_method_06, RBIMPL_ANYARGS_DISPATCH_rb_define_protected_method_05(n)) # define RBIMPL_ANYARGS_DISPATCH_rb_define_protected_method_07(n) RBIMPL_ANYARGS_DISPATCH((n) == 7, rb_define_protected_method_07, RBIMPL_ANYARGS_DISPATCH_rb_define_protected_method_06(n)) # define RBIMPL_ANYARGS_DISPATCH_rb_define_protected_method_08(n) RBIMPL_ANYARGS_DISPATCH((n) == 8, rb_define_protected_method_08, RBIMPL_ANYARGS_DISPATCH_rb_define_protected_method_07(n)) # define RBIMPL_ANYARGS_DISPATCH_rb_define_protected_method_09(n) RBIMPL_ANYARGS_DISPATCH((n) == 9, rb_define_protected_method_09, RBIMPL_ANYARGS_DISPATCH_rb_define_protected_method_08(n)) # define RBIMPL_ANYARGS_DISPATCH_rb_define_protected_method_10(n) RBIMPL_ANYARGS_DISPATCH((n) == 10, rb_define_protected_method_10, RBIMPL_ANYARGS_DISPATCH_rb_define_protected_method_09(n)) # define RBIMPL_ANYARGS_DISPATCH_rb_define_protected_method_11(n) RBIMPL_ANYARGS_DISPATCH((n) == 11, rb_define_protected_method_11, RBIMPL_ANYARGS_DISPATCH_rb_define_protected_method_10(n)) # define RBIMPL_ANYARGS_DISPATCH_rb_define_protected_method_12(n) RBIMPL_ANYARGS_DISPATCH((n) == 12, rb_define_protected_method_12, RBIMPL_ANYARGS_DISPATCH_rb_define_protected_method_11(n)) # define RBIMPL_ANYARGS_DISPATCH_rb_define_protected_method_13(n) RBIMPL_ANYARGS_DISPATCH((n) == 13, rb_define_protected_method_13, RBIMPL_ANYARGS_DISPATCH_rb_define_protected_method_12(n)) # define RBIMPL_ANYARGS_DISPATCH_rb_define_protected_method_14(n) RBIMPL_ANYARGS_DISPATCH((n) == 14, rb_define_protected_method_14, RBIMPL_ANYARGS_DISPATCH_rb_define_protected_method_13(n)) # define RBIMPL_ANYARGS_DISPATCH_rb_define_protected_method_15(n) RBIMPL_ANYARGS_DISPATCH((n) == 15, rb_define_protected_method_15, RBIMPL_ANYARGS_DISPATCH_rb_define_protected_method_14(n)) # define RBIMPL_ANYARGS_DISPATCH_rb_define_private_method_m2(n) RBIMPL_ANYARGS_DISPATCH((n) == -2, rb_define_private_method_m2, rb_define_private_method_m3) # define RBIMPL_ANYARGS_DISPATCH_rb_define_private_method_m1(n) RBIMPL_ANYARGS_DISPATCH((n) == -1, rb_define_private_method_m1, RBIMPL_ANYARGS_DISPATCH_rb_define_private_method_m2(n)) # define RBIMPL_ANYARGS_DISPATCH_rb_define_private_method_00(n) RBIMPL_ANYARGS_DISPATCH((n) == 0, rb_define_private_method_00, RBIMPL_ANYARGS_DISPATCH_rb_define_private_method_m1(n)) # define RBIMPL_ANYARGS_DISPATCH_rb_define_private_method_01(n) RBIMPL_ANYARGS_DISPATCH((n) == 1, rb_define_private_method_01, RBIMPL_ANYARGS_DISPATCH_rb_define_private_method_00(n)) # define RBIMPL_ANYARGS_DISPATCH_rb_define_private_method_02(n) RBIMPL_ANYARGS_DISPATCH((n) == 2, rb_define_private_method_02, RBIMPL_ANYARGS_DISPATCH_rb_define_private_method_01(n)) # define RBIMPL_ANYARGS_DISPATCH_rb_define_private_method_03(n) RBIMPL_ANYARGS_DISPATCH((n) == 3, rb_define_private_method_03, RBIMPL_ANYARGS_DISPATCH_rb_define_private_method_02(n)) # define RBIMPL_ANYARGS_DISPATCH_rb_define_private_method_04(n) RBIMPL_ANYARGS_DISPATCH((n) == 4, rb_define_private_method_04, RBIMPL_ANYARGS_DISPATCH_rb_define_private_method_03(n)) # define RBIMPL_ANYARGS_DISPATCH_rb_define_private_method_05(n) RBIMPL_ANYARGS_DISPATCH((n) == 5, rb_define_private_method_05, RBIMPL_ANYARGS_DISPATCH_rb_define_private_method_04(n)) # define RBIMPL_ANYARGS_DISPATCH_rb_define_private_method_06(n) RBIMPL_ANYARGS_DISPATCH((n) == 6, rb_define_private_method_06, RBIMPL_ANYARGS_DISPATCH_rb_define_private_method_05(n)) # define RBIMPL_ANYARGS_DISPATCH_rb_define_private_method_07(n) RBIMPL_ANYARGS_DISPATCH((n) == 7, rb_define_private_method_07, RBIMPL_ANYARGS_DISPATCH_rb_define_private_method_06(n)) # define RBIMPL_ANYARGS_DISPATCH_rb_define_private_method_08(n) RBIMPL_ANYARGS_DISPATCH((n) == 8, rb_define_private_method_08, RBIMPL_ANYARGS_DISPATCH_rb_define_private_method_07(n)) # define RBIMPL_ANYARGS_DISPATCH_rb_define_private_method_09(n) RBIMPL_ANYARGS_DISPATCH((n) == 9, rb_define_private_method_09, RBIMPL_ANYARGS_DISPATCH_rb_define_private_method_08(n)) # define RBIMPL_ANYARGS_DISPATCH_rb_define_private_method_10(n) RBIMPL_ANYARGS_DISPATCH((n) == 10, rb_define_private_method_10, RBIMPL_ANYARGS_DISPATCH_rb_define_private_method_09(n)) # define RBIMPL_ANYARGS_DISPATCH_rb_define_private_method_11(n) RBIMPL_ANYARGS_DISPATCH((n) == 11, rb_define_private_method_11, RBIMPL_ANYARGS_DISPATCH_rb_define_private_method_10(n)) # define RBIMPL_ANYARGS_DISPATCH_rb_define_private_method_12(n) RBIMPL_ANYARGS_DISPATCH((n) == 12, rb_define_private_method_12, RBIMPL_ANYARGS_DISPATCH_rb_define_private_method_11(n)) # define RBIMPL_ANYARGS_DISPATCH_rb_define_private_method_13(n) RBIMPL_ANYARGS_DISPATCH((n) == 13, rb_define_private_method_13, RBIMPL_ANYARGS_DISPATCH_rb_define_private_method_12(n)) # define RBIMPL_ANYARGS_DISPATCH_rb_define_private_method_14(n) RBIMPL_ANYARGS_DISPATCH((n) == 14, rb_define_private_method_14, RBIMPL_ANYARGS_DISPATCH_rb_define_private_method_13(n)) # define RBIMPL_ANYARGS_DISPATCH_rb_define_private_method_15(n) RBIMPL_ANYARGS_DISPATCH((n) == 15, rb_define_private_method_15, RBIMPL_ANYARGS_DISPATCH_rb_define_private_method_14(n)) # define RBIMPL_ANYARGS_DISPATCH_rb_define_module_function_m2(n) RBIMPL_ANYARGS_DISPATCH((n) == -2, rb_define_module_function_m2, rb_define_module_function_m3) # define RBIMPL_ANYARGS_DISPATCH_rb_define_module_function_m1(n) RBIMPL_ANYARGS_DISPATCH((n) == -1, rb_define_module_function_m1, RBIMPL_ANYARGS_DISPATCH_rb_define_module_function_m2(n)) # define RBIMPL_ANYARGS_DISPATCH_rb_define_module_function_00(n) RBIMPL_ANYARGS_DISPATCH((n) == 0, rb_define_module_function_00, RBIMPL_ANYARGS_DISPATCH_rb_define_module_function_m1(n)) # define RBIMPL_ANYARGS_DISPATCH_rb_define_module_function_01(n) RBIMPL_ANYARGS_DISPATCH((n) == 1, rb_define_module_function_01, RBIMPL_ANYARGS_DISPATCH_rb_define_module_function_00(n)) # define RBIMPL_ANYARGS_DISPATCH_rb_define_module_function_02(n) RBIMPL_ANYARGS_DISPATCH((n) == 2, rb_define_module_function_02, RBIMPL_ANYARGS_DISPATCH_rb_define_module_function_01(n)) # define RBIMPL_ANYARGS_DISPATCH_rb_define_module_function_03(n) RBIMPL_ANYARGS_DISPATCH((n) == 3, rb_define_module_function_03, RBIMPL_ANYARGS_DISPATCH_rb_define_module_function_02(n)) # define RBIMPL_ANYARGS_DISPATCH_rb_define_module_function_04(n) RBIMPL_ANYARGS_DISPATCH((n) == 4, rb_define_module_function_04, RBIMPL_ANYARGS_DISPATCH_rb_define_module_function_03(n)) # define RBIMPL_ANYARGS_DISPATCH_rb_define_module_function_05(n) RBIMPL_ANYARGS_DISPATCH((n) == 5, rb_define_module_function_05, RBIMPL_ANYARGS_DISPATCH_rb_define_module_function_04(n)) # define RBIMPL_ANYARGS_DISPATCH_rb_define_module_function_06(n) RBIMPL_ANYARGS_DISPATCH((n) == 6, rb_define_module_function_06, RBIMPL_ANYARGS_DISPATCH_rb_define_module_function_05(n)) # define RBIMPL_ANYARGS_DISPATCH_rb_define_module_function_07(n) RBIMPL_ANYARGS_DISPATCH((n) == 7, rb_define_module_function_07, RBIMPL_ANYARGS_DISPATCH_rb_define_module_function_06(n)) # define RBIMPL_ANYARGS_DISPATCH_rb_define_module_function_08(n) RBIMPL_ANYARGS_DISPATCH((n) == 8, rb_define_module_function_08, RBIMPL_ANYARGS_DISPATCH_rb_define_module_function_07(n)) # define RBIMPL_ANYARGS_DISPATCH_rb_define_module_function_09(n) RBIMPL_ANYARGS_DISPATCH((n) == 9, rb_define_module_function_09, RBIMPL_ANYARGS_DISPATCH_rb_define_module_function_08(n)) # define RBIMPL_ANYARGS_DISPATCH_rb_define_module_function_10(n) RBIMPL_ANYARGS_DISPATCH((n) == 10, rb_define_module_function_10, RBIMPL_ANYARGS_DISPATCH_rb_define_module_function_09(n)) # define RBIMPL_ANYARGS_DISPATCH_rb_define_module_function_11(n) RBIMPL_ANYARGS_DISPATCH((n) == 11, rb_define_module_function_11, RBIMPL_ANYARGS_DISPATCH_rb_define_module_function_10(n)) # define RBIMPL_ANYARGS_DISPATCH_rb_define_module_function_12(n) RBIMPL_ANYARGS_DISPATCH((n) == 12, rb_define_module_function_12, RBIMPL_ANYARGS_DISPATCH_rb_define_module_function_11(n)) # define RBIMPL_ANYARGS_DISPATCH_rb_define_module_function_13(n) RBIMPL_ANYARGS_DISPATCH((n) == 13, rb_define_module_function_13, RBIMPL_ANYARGS_DISPATCH_rb_define_module_function_12(n)) # define RBIMPL_ANYARGS_DISPATCH_rb_define_module_function_14(n) RBIMPL_ANYARGS_DISPATCH((n) == 14, rb_define_module_function_14, RBIMPL_ANYARGS_DISPATCH_rb_define_module_function_13(n)) # define RBIMPL_ANYARGS_DISPATCH_rb_define_module_function_15(n) RBIMPL_ANYARGS_DISPATCH((n) == 15, rb_define_module_function_15, RBIMPL_ANYARGS_DISPATCH_rb_define_module_function_14(n)) # define RBIMPL_ANYARGS_DISPATCH_rb_define_global_function_m2(n) RBIMPL_ANYARGS_DISPATCH((n) == -2, rb_define_global_function_m2, rb_define_global_function_m3) # define RBIMPL_ANYARGS_DISPATCH_rb_define_global_function_m1(n) RBIMPL_ANYARGS_DISPATCH((n) == -1, rb_define_global_function_m1, RBIMPL_ANYARGS_DISPATCH_rb_define_global_function_m2(n)) # define RBIMPL_ANYARGS_DISPATCH_rb_define_global_function_00(n) RBIMPL_ANYARGS_DISPATCH((n) == 0, rb_define_global_function_00, RBIMPL_ANYARGS_DISPATCH_rb_define_global_function_m1(n)) # define RBIMPL_ANYARGS_DISPATCH_rb_define_global_function_01(n) RBIMPL_ANYARGS_DISPATCH((n) == 1, rb_define_global_function_01, RBIMPL_ANYARGS_DISPATCH_rb_define_global_function_00(n)) # define RBIMPL_ANYARGS_DISPATCH_rb_define_global_function_02(n) RBIMPL_ANYARGS_DISPATCH((n) == 2, rb_define_global_function_02, RBIMPL_ANYARGS_DISPATCH_rb_define_global_function_01(n)) # define RBIMPL_ANYARGS_DISPATCH_rb_define_global_function_03(n) RBIMPL_ANYARGS_DISPATCH((n) == 3, rb_define_global_function_03, RBIMPL_ANYARGS_DISPATCH_rb_define_global_function_02(n)) # define RBIMPL_ANYARGS_DISPATCH_rb_define_global_function_04(n) RBIMPL_ANYARGS_DISPATCH((n) == 4, rb_define_global_function_04, RBIMPL_ANYARGS_DISPATCH_rb_define_global_function_03(n)) # define RBIMPL_ANYARGS_DISPATCH_rb_define_global_function_05(n) RBIMPL_ANYARGS_DISPATCH((n) == 5, rb_define_global_function_05, RBIMPL_ANYARGS_DISPATCH_rb_define_global_function_04(n)) # define RBIMPL_ANYARGS_DISPATCH_rb_define_global_function_06(n) RBIMPL_ANYARGS_DISPATCH((n) == 6, rb_define_global_function_06, RBIMPL_ANYARGS_DISPATCH_rb_define_global_function_05(n)) # define RBIMPL_ANYARGS_DISPATCH_rb_define_global_function_07(n) RBIMPL_ANYARGS_DISPATCH((n) == 7, rb_define_global_function_07, RBIMPL_ANYARGS_DISPATCH_rb_define_global_function_06(n)) # define RBIMPL_ANYARGS_DISPATCH_rb_define_global_function_08(n) RBIMPL_ANYARGS_DISPATCH((n) == 8, rb_define_global_function_08, RBIMPL_ANYARGS_DISPATCH_rb_define_global_function_07(n)) # define RBIMPL_ANYARGS_DISPATCH_rb_define_global_function_09(n) RBIMPL_ANYARGS_DISPATCH((n) == 9, rb_define_global_function_09, RBIMPL_ANYARGS_DISPATCH_rb_define_global_function_08(n)) # define RBIMPL_ANYARGS_DISPATCH_rb_define_global_function_10(n) RBIMPL_ANYARGS_DISPATCH((n) == 10, rb_define_global_function_10, RBIMPL_ANYARGS_DISPATCH_rb_define_global_function_09(n)) # define RBIMPL_ANYARGS_DISPATCH_rb_define_global_function_11(n) RBIMPL_ANYARGS_DISPATCH((n) == 11, rb_define_global_function_11, RBIMPL_ANYARGS_DISPATCH_rb_define_global_function_10(n)) # define RBIMPL_ANYARGS_DISPATCH_rb_define_global_function_12(n) RBIMPL_ANYARGS_DISPATCH((n) == 12, rb_define_global_function_12, RBIMPL_ANYARGS_DISPATCH_rb_define_global_function_11(n)) # define RBIMPL_ANYARGS_DISPATCH_rb_define_global_function_13(n) RBIMPL_ANYARGS_DISPATCH((n) == 13, rb_define_global_function_13, RBIMPL_ANYARGS_DISPATCH_rb_define_global_function_12(n)) # define RBIMPL_ANYARGS_DISPATCH_rb_define_global_function_14(n) RBIMPL_ANYARGS_DISPATCH((n) == 14, rb_define_global_function_14, RBIMPL_ANYARGS_DISPATCH_rb_define_global_function_13(n)) # define RBIMPL_ANYARGS_DISPATCH_rb_define_global_function_15(n) RBIMPL_ANYARGS_DISPATCH((n) == 15, rb_define_global_function_15, RBIMPL_ANYARGS_DISPATCH_rb_define_global_function_14(n)) # define RBIMPL_ANYARGS_DISPATCH_rb_define_method_id_m2(n) RBIMPL_ANYARGS_DISPATCH((n) == -2, rb_define_method_id_m2, rb_define_method_id_m3) # define RBIMPL_ANYARGS_DISPATCH_rb_define_method_id_m1(n) RBIMPL_ANYARGS_DISPATCH((n) == -1, rb_define_method_id_m1, RBIMPL_ANYARGS_DISPATCH_rb_define_method_id_m2(n)) # define RBIMPL_ANYARGS_DISPATCH_rb_define_method_id_00(n) RBIMPL_ANYARGS_DISPATCH((n) == 0, rb_define_method_id_00, RBIMPL_ANYARGS_DISPATCH_rb_define_method_id_m1(n)) # define RBIMPL_ANYARGS_DISPATCH_rb_define_method_id_01(n) RBIMPL_ANYARGS_DISPATCH((n) == 1, rb_define_method_id_01, RBIMPL_ANYARGS_DISPATCH_rb_define_method_id_00(n)) # define RBIMPL_ANYARGS_DISPATCH_rb_define_method_id_02(n) RBIMPL_ANYARGS_DISPATCH((n) == 2, rb_define_method_id_02, RBIMPL_ANYARGS_DISPATCH_rb_define_method_id_01(n)) # define RBIMPL_ANYARGS_DISPATCH_rb_define_method_id_03(n) RBIMPL_ANYARGS_DISPATCH((n) == 3, rb_define_method_id_03, RBIMPL_ANYARGS_DISPATCH_rb_define_method_id_02(n)) # define RBIMPL_ANYARGS_DISPATCH_rb_define_method_id_04(n) RBIMPL_ANYARGS_DISPATCH((n) == 4, rb_define_method_id_04, RBIMPL_ANYARGS_DISPATCH_rb_define_method_id_03(n)) # define RBIMPL_ANYARGS_DISPATCH_rb_define_method_id_05(n) RBIMPL_ANYARGS_DISPATCH((n) == 5, rb_define_method_id_05, RBIMPL_ANYARGS_DISPATCH_rb_define_method_id_04(n)) # define RBIMPL_ANYARGS_DISPATCH_rb_define_method_id_06(n) RBIMPL_ANYARGS_DISPATCH((n) == 6, rb_define_method_id_06, RBIMPL_ANYARGS_DISPATCH_rb_define_method_id_05(n)) # define RBIMPL_ANYARGS_DISPATCH_rb_define_method_id_07(n) RBIMPL_ANYARGS_DISPATCH((n) == 7, rb_define_method_id_07, RBIMPL_ANYARGS_DISPATCH_rb_define_method_id_06(n)) # define RBIMPL_ANYARGS_DISPATCH_rb_define_method_id_08(n) RBIMPL_ANYARGS_DISPATCH((n) == 8, rb_define_method_id_08, RBIMPL_ANYARGS_DISPATCH_rb_define_method_id_07(n)) # define RBIMPL_ANYARGS_DISPATCH_rb_define_method_id_09(n) RBIMPL_ANYARGS_DISPATCH((n) == 9, rb_define_method_id_09, RBIMPL_ANYARGS_DISPATCH_rb_define_method_id_08(n)) # define RBIMPL_ANYARGS_DISPATCH_rb_define_method_id_10(n) RBIMPL_ANYARGS_DISPATCH((n) == 10, rb_define_method_id_10, RBIMPL_ANYARGS_DISPATCH_rb_define_method_id_09(n)) # define RBIMPL_ANYARGS_DISPATCH_rb_define_method_id_11(n) RBIMPL_ANYARGS_DISPATCH((n) == 11, rb_define_method_id_11, RBIMPL_ANYARGS_DISPATCH_rb_define_method_id_10(n)) # define RBIMPL_ANYARGS_DISPATCH_rb_define_method_id_12(n) RBIMPL_ANYARGS_DISPATCH((n) == 12, rb_define_method_id_12, RBIMPL_ANYARGS_DISPATCH_rb_define_method_id_11(n)) # define RBIMPL_ANYARGS_DISPATCH_rb_define_method_id_13(n) RBIMPL_ANYARGS_DISPATCH((n) == 13, rb_define_method_id_13, RBIMPL_ANYARGS_DISPATCH_rb_define_method_id_12(n)) # define RBIMPL_ANYARGS_DISPATCH_rb_define_method_id_14(n) RBIMPL_ANYARGS_DISPATCH((n) == 14, rb_define_method_id_14, RBIMPL_ANYARGS_DISPATCH_rb_define_method_id_13(n)) # define RBIMPL_ANYARGS_DISPATCH_rb_define_method_id_15(n) RBIMPL_ANYARGS_DISPATCH((n) == 15, rb_define_method_id_15, RBIMPL_ANYARGS_DISPATCH_rb_define_method_id_14(n)) # define RBIMPL_ANYARGS_DISPATCH_rb_define_method_m2(n) RBIMPL_ANYARGS_DISPATCH((n) == -2, rb_define_method_m2, rb_define_method_m3) # define RBIMPL_ANYARGS_DISPATCH_rb_define_method_m1(n) RBIMPL_ANYARGS_DISPATCH((n) == -1, rb_define_method_m1, RBIMPL_ANYARGS_DISPATCH_rb_define_method_m2(n)) # define RBIMPL_ANYARGS_DISPATCH_rb_define_method_00(n) RBIMPL_ANYARGS_DISPATCH((n) == 0, rb_define_method_00, RBIMPL_ANYARGS_DISPATCH_rb_define_method_m1(n)) # define RBIMPL_ANYARGS_DISPATCH_rb_define_method_01(n) RBIMPL_ANYARGS_DISPATCH((n) == 1, rb_define_method_01, RBIMPL_ANYARGS_DISPATCH_rb_define_method_00(n)) # define RBIMPL_ANYARGS_DISPATCH_rb_define_method_02(n) RBIMPL_ANYARGS_DISPATCH((n) == 2, rb_define_method_02, RBIMPL_ANYARGS_DISPATCH_rb_define_method_01(n)) # define RBIMPL_ANYARGS_DISPATCH_rb_define_method_03(n) RBIMPL_ANYARGS_DISPATCH((n) == 3, rb_define_method_03, RBIMPL_ANYARGS_DISPATCH_rb_define_method_02(n)) # define RBIMPL_ANYARGS_DISPATCH_rb_define_method_04(n) RBIMPL_ANYARGS_DISPATCH((n) == 4, rb_define_method_04, RBIMPL_ANYARGS_DISPATCH_rb_define_method_03(n)) # define RBIMPL_ANYARGS_DISPATCH_rb_define_method_05(n) RBIMPL_ANYARGS_DISPATCH((n) == 5, rb_define_method_05, RBIMPL_ANYARGS_DISPATCH_rb_define_method_04(n)) # define RBIMPL_ANYARGS_DISPATCH_rb_define_method_06(n) RBIMPL_ANYARGS_DISPATCH((n) == 6, rb_define_method_06, RBIMPL_ANYARGS_DISPATCH_rb_define_method_05(n)) # define RBIMPL_ANYARGS_DISPATCH_rb_define_method_07(n) RBIMPL_ANYARGS_DISPATCH((n) == 7, rb_define_method_07, RBIMPL_ANYARGS_DISPATCH_rb_define_method_06(n)) # define RBIMPL_ANYARGS_DISPATCH_rb_define_method_08(n) RBIMPL_ANYARGS_DISPATCH((n) == 8, rb_define_method_08, RBIMPL_ANYARGS_DISPATCH_rb_define_method_07(n)) # define RBIMPL_ANYARGS_DISPATCH_rb_define_method_09(n) RBIMPL_ANYARGS_DISPATCH((n) == 9, rb_define_method_09, RBIMPL_ANYARGS_DISPATCH_rb_define_method_08(n)) # define RBIMPL_ANYARGS_DISPATCH_rb_define_method_10(n) RBIMPL_ANYARGS_DISPATCH((n) == 10, rb_define_method_10, RBIMPL_ANYARGS_DISPATCH_rb_define_method_09(n)) # define RBIMPL_ANYARGS_DISPATCH_rb_define_method_11(n) RBIMPL_ANYARGS_DISPATCH((n) == 11, rb_define_method_11, RBIMPL_ANYARGS_DISPATCH_rb_define_method_10(n)) # define RBIMPL_ANYARGS_DISPATCH_rb_define_method_12(n) RBIMPL_ANYARGS_DISPATCH((n) == 12, rb_define_method_12, RBIMPL_ANYARGS_DISPATCH_rb_define_method_11(n)) # define RBIMPL_ANYARGS_DISPATCH_rb_define_method_13(n) RBIMPL_ANYARGS_DISPATCH((n) == 13, rb_define_method_13, RBIMPL_ANYARGS_DISPATCH_rb_define_method_12(n)) # define RBIMPL_ANYARGS_DISPATCH_rb_define_method_14(n) RBIMPL_ANYARGS_DISPATCH((n) == 14, rb_define_method_14, RBIMPL_ANYARGS_DISPATCH_rb_define_method_13(n)) # define RBIMPL_ANYARGS_DISPATCH_rb_define_method_15(n) RBIMPL_ANYARGS_DISPATCH((n) == 15, rb_define_method_15, RBIMPL_ANYARGS_DISPATCH_rb_define_method_14(n)) # define RBIMPL_ANYARGS_DISPATCH_rb_define_singleton_method(n, f) RBIMPL_ANYARGS_DISPATCH(RBIMPL_CFUNC_IS_rb_f_notimplement(f), rb_define_singleton_method_notimpl, RBIMPL_ANYARGS_DISPATCH_rb_define_singleton_method_15(n)) # define RBIMPL_ANYARGS_DISPATCH_rb_define_protected_method(n, f) RBIMPL_ANYARGS_DISPATCH(RBIMPL_CFUNC_IS_rb_f_notimplement(f), rb_define_protected_method_notimpl, RBIMPL_ANYARGS_DISPATCH_rb_define_protected_method_15(n)) # define RBIMPL_ANYARGS_DISPATCH_rb_define_private_method(n, f) RBIMPL_ANYARGS_DISPATCH(RBIMPL_CFUNC_IS_rb_f_notimplement(f), rb_define_private_method_notimpl, RBIMPL_ANYARGS_DISPATCH_rb_define_private_method_15(n)) # define RBIMPL_ANYARGS_DISPATCH_rb_define_module_function(n, f) RBIMPL_ANYARGS_DISPATCH(RBIMPL_CFUNC_IS_rb_f_notimplement(f), rb_define_module_function_notimpl, RBIMPL_ANYARGS_DISPATCH_rb_define_module_function_15(n)) # define RBIMPL_ANYARGS_DISPATCH_rb_define_global_function(n, f) RBIMPL_ANYARGS_DISPATCH(RBIMPL_CFUNC_IS_rb_f_notimplement(f), rb_define_global_function_notimpl, RBIMPL_ANYARGS_DISPATCH_rb_define_global_function_15(n)) # define RBIMPL_ANYARGS_DISPATCH_rb_define_method_id(n, f) RBIMPL_ANYARGS_DISPATCH(RBIMPL_CFUNC_IS_rb_f_notimplement(f), rb_define_method_id_notimpl, RBIMPL_ANYARGS_DISPATCH_rb_define_method_id_15(n)) # define RBIMPL_ANYARGS_DISPATCH_rb_define_method(n, f) RBIMPL_ANYARGS_DISPATCH(RBIMPL_CFUNC_IS_rb_f_notimplement(f), rb_define_method_notimpl, RBIMPL_ANYARGS_DISPATCH_rb_define_method_15(n)) # define RBIMPL_ANYARGS_ATTRSET(sym) RBIMPL_ATTR_MAYBE_UNUSED() RBIMPL_ATTR_NONNULL(()) RBIMPL_ATTR_WEAKREF(sym) # define RBIMPL_ANYARGS_DECL(sym, ...) \ RBIMPL_ANYARGS_ATTRSET(sym) static void sym ## _notimpl(__VA_ARGS__, VALUE(*)(int, const VALUE *, VALUE, VALUE), int); \ RBIMPL_ANYARGS_ATTRSET(sym) static void sym ## _m3(__VA_ARGS__, VALUE(*)(ANYARGS), int); \ RBIMPL_ANYARGS_ATTRSET(sym) static void sym ## _m2(__VA_ARGS__, VALUE(*)(VALUE, VALUE), int); \ RBIMPL_ANYARGS_ATTRSET(sym) static void sym ## _m1(__VA_ARGS__, VALUE(*)(int, union { VALUE *x; const VALUE *y; } __attribute__((__transparent_union__)), VALUE), int); \ RBIMPL_ANYARGS_ATTRSET(sym) static void sym ## _00(__VA_ARGS__, VALUE(*)(VALUE), int); \ RBIMPL_ANYARGS_ATTRSET(sym) static void sym ## _01(__VA_ARGS__, VALUE(*)(VALUE, VALUE), int); \ RBIMPL_ANYARGS_ATTRSET(sym) static void sym ## _02(__VA_ARGS__, VALUE(*)(VALUE, VALUE, VALUE), int); \ RBIMPL_ANYARGS_ATTRSET(sym) static void sym ## _03(__VA_ARGS__, VALUE(*)(VALUE, VALUE, VALUE, VALUE), int); \ RBIMPL_ANYARGS_ATTRSET(sym) static void sym ## _04(__VA_ARGS__, VALUE(*)(VALUE, VALUE, VALUE, VALUE, VALUE), int); \ RBIMPL_ANYARGS_ATTRSET(sym) static void sym ## _05(__VA_ARGS__, VALUE(*)(VALUE, VALUE, VALUE, VALUE, VALUE, VALUE), int); \ RBIMPL_ANYARGS_ATTRSET(sym) static void sym ## _06(__VA_ARGS__, VALUE(*)(VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE), int); \ RBIMPL_ANYARGS_ATTRSET(sym) static void sym ## _07(__VA_ARGS__, VALUE(*)(VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE), int); \ RBIMPL_ANYARGS_ATTRSET(sym) static void sym ## _08(__VA_ARGS__, VALUE(*)(VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE), int); \ RBIMPL_ANYARGS_ATTRSET(sym) static void sym ## _09(__VA_ARGS__, VALUE(*)(VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE), int); \ RBIMPL_ANYARGS_ATTRSET(sym) static void sym ## _10(__VA_ARGS__, VALUE(*)(VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE), int); \ RBIMPL_ANYARGS_ATTRSET(sym) static void sym ## _11(__VA_ARGS__, VALUE(*)(VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE), int); \ RBIMPL_ANYARGS_ATTRSET(sym) static void sym ## _12(__VA_ARGS__, VALUE(*)(VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE), int); \ RBIMPL_ANYARGS_ATTRSET(sym) static void sym ## _13(__VA_ARGS__, VALUE(*)(VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE), int); \ RBIMPL_ANYARGS_ATTRSET(sym) static void sym ## _14(__VA_ARGS__, VALUE(*)(VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE), int); \ RBIMPL_ANYARGS_ATTRSET(sym) static void sym ## _15(__VA_ARGS__, VALUE(*)(VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE), int); RBIMPL_ANYARGS_DECL(rb_define_singleton_method, VALUE, const char *) RBIMPL_ANYARGS_DECL(rb_define_protected_method, VALUE, const char *) RBIMPL_ANYARGS_DECL(rb_define_private_method, VALUE, const char *) RBIMPL_ANYARGS_DECL(rb_define_module_function, VALUE, const char *) RBIMPL_ANYARGS_DECL(rb_define_global_function, const char *) RBIMPL_ANYARGS_DECL(rb_define_method_id, VALUE, ID) RBIMPL_ANYARGS_DECL(rb_define_method, VALUE, const char *) /** @endcond */ /** * @brief Defines klass\#mid. * @see ::rb_define_method * @param klass Where the method lives. * @param mid Name of the defining method. * @param func Implementation of klass\#mid. * @param arity Arity of klass\#mid. */ #define rb_define_method(klass, mid, func, arity) RBIMPL_ANYARGS_DISPATCH_rb_define_method((arity), (func))((klass), (mid), (func), (arity)) /** * @brief Defines klass\#mid. * @see ::rb_define_method_id * @param klass Where the method lives. * @param mid Name of the defining method. * @param func Implementation of klass\#mid. * @param arity Arity of klass\#mid. */ #define rb_define_method_id(klass, mid, func, arity) RBIMPL_ANYARGS_DISPATCH_rb_define_method_id((arity), (func))((klass), (mid), (func), (arity)) /** * @brief Defines obj.mid. * @see ::rb_define_singleton_method * @param obj Where the method lives. * @param mid Name of the defining method. * @param func Implementation of obj.mid. * @param arity Arity of obj.mid. */ #define rb_define_singleton_method(obj, mid, func, arity) RBIMPL_ANYARGS_DISPATCH_rb_define_singleton_method((arity), (func))((obj), (mid), (func), (arity)) /** * @brief Defines klass\#mid and make it protected. * @see ::rb_define_protected_method * @param klass Where the method lives. * @param mid Name of the defining method. * @param func Implementation of klass\#mid. * @param arity Arity of klass\#mid. */ #define rb_define_protected_method(klass, mid, func, arity) RBIMPL_ANYARGS_DISPATCH_rb_define_protected_method((arity), (func))((klass), (mid), (func), (arity)) /** * @brief Defines klass\#mid and make it private. * @see ::rb_define_private_method * @param klass Where the method lives. * @param mid Name of the defining method. * @param func Implementation of klass\#mid. * @param arity Arity of klass\#mid. */ #define rb_define_private_method(klass, mid, func, arity) RBIMPL_ANYARGS_DISPATCH_rb_define_private_method((arity), (func))((klass), (mid), (func), (arity)) /** * @brief Defines mod\#mid and make it a module function. * @see ::rb_define_module_function * @param mod Where the method lives. * @param mid Name of the defining method. * @param func Implementation of mod\#mid. * @param arity Arity of mod\#mid. */ #define rb_define_module_function(mod, mid, func, arity) RBIMPL_ANYARGS_DISPATCH_rb_define_module_function((arity), (func))((mod), (mid), (func), (arity)) /** * @brief Defines ::rb_mKerbel \#mid. * @see ::rb_define_global_function * @param mid Name of the defining method. * @param func Implementation of ::rb_mKernel \#mid. * @param arity Arity of ::rb_mKernel \#mid. */ #define rb_define_global_function(mid, func, arity) RBIMPL_ANYARGS_DISPATCH_rb_define_global_function((arity), (func))((mid), (func), (arity)) #endif /* __cplusplus */ /** * This macro is to properly cast a function parameter of *_define_method * family. It has been around since 1.x era so you can maximise backwards * compatibility by using it. * * ```CXX * rb_define_method(klass, "method", RUBY_METHOD_FUNC(func), arity); * ``` * * @param func A pointer to a function that implements a method. */ #if ! defined(RUBY_DEVEL) # define RUBY_METHOD_FUNC(func) RBIMPL_CAST((VALUE (*)(ANYARGS))(func)) #elif ! RUBY_DEVEL # define RUBY_METHOD_FUNC(func) RBIMPL_CAST((VALUE (*)(ANYARGS))(func)) #elif ! defined(rb_define_method) # define RUBY_METHOD_FUNC(func) RBIMPL_CAST((VALUE (*)(ANYARGS))(func)) #else # define RUBY_METHOD_FUNC(func) (func) #endif #endif /* RBIMPL_ANYARGS_H */ include/ruby/internal/dosish.h 0000644 00000006250 15152150475 0012436 0 ustar 00 #ifndef RBIMPL_DOSISH_H /*-*-C++-*-vi:se ft=cpp:*/ #define RBIMPL_DOSISH_H /** * @file * @author Ruby developers <ruby-core@ruby-lang.org> * @copyright This file is a part of the programming language Ruby. * Permission is hereby granted, to either redistribute and/or * modify this file, provided that the conditions mentioned in the * file COPYING are met. Consult the file for details. * @warning Symbols prefixed with either `RBIMPL` or `rbimpl` are * implementation details. Don't take them as canon. They could * rapidly appear then vanish. The name (path) of this header file * is also an implementation detail. Do not expect it to persist * at the place it is now. Developers are free to move it anywhere * anytime at will. * @note To ruby-core: remember that this header can be possibly * recursively included from extension libraries written in C++. * Do not expect for instance `__VA_ARGS__` is always available. * We assume C99 for ruby itself but we don't assume languages of * extension libraries. They could be written in C++98. * @brief Support for so-called dosish systems. */ #ifdef __CYGWIN__ #undef _WIN32 #endif #if defined(_WIN32) /* DOSISH mean MS-Windows style filesystem. But you should use more precise macros like DOSISH_DRIVE_LETTER, PATH_SEP, ENV_IGNORECASE or CASEFOLD_FILESYSTEM. */ #define DOSISH 1 # define DOSISH_DRIVE_LETTER #endif #ifdef _WIN32 #include "ruby/win32.h" #endif /** The delimiter of `PATH` environment variable. */ #if defined(DOSISH) #define PATH_SEP ";" #else #define PATH_SEP ":" #endif /** Identical to #PATH_SEP, except it is of type `char`. */ #define PATH_SEP_CHAR PATH_SEP[0] /** * @private * * @deprecated This macro once was a thing in the old days, but makes no sense * any longer today. Exists here for backwards compatibility * only. You can safely forget about it. * * @internal * * For historical interests: there was an operating system called Human68k * which used an environment variable called `"path"` for this purpose. */ #define PATH_ENV "PATH" #if defined(DOSISH) #define ENV_IGNORECASE #endif /** * Stone age assumption was that an operating system supports only one file * system at a moment. This macro was to detect if such (one and only) file * system has case sensitivity. This assumption is largely not true any * longer; most operating systems can mount many kinds of file systems side by * side. Also there are file systems that do or do not ignore cases depending * on configuration (e.g. EXT4's `casefold` feature). * * This macro is still used internally (for instance Ruby level constant * `File::FNM_SYSCASE` depends on it), but it is basically a wrong idea for you * to use it today. Please just find another way. */ #ifndef CASEFOLD_FILESYSTEM # if defined DOSISH # define CASEFOLD_FILESYSTEM 1 # else # define CASEFOLD_FILESYSTEM 0 # endif #endif #endif /* RBIMPL_DOSISH_H */ include/ruby/internal/warning_push.h 0000644 00000011644 15152150475 0013654 0 ustar 00 #ifndef RBIMPL_WARNING_PUSH_H /*-*-C++-*-vi:se ft=cpp:*/ #define RBIMPL_WARNING_PUSH_H /** * @file * @author Ruby developers <ruby-core@ruby-lang.org> * @copyright This file is a part of the programming language Ruby. * Permission is hereby granted, to either redistribute and/or * modify this file, provided that the conditions mentioned in the * file COPYING are met. Consult the file for details. * @warning Symbols prefixed with either `RBIMPL` or `rbimpl` are * implementation details. Don't take them as canon. They could * rapidly appear then vanish. The name (path) of this header file * is also an implementation detail. Do not expect it to persist * at the place it is now. Developers are free to move it anywhere * anytime at will. * @note To ruby-core: remember that this header can be possibly * recursively included from extension libraries written in C++. * Do not expect for instance `__VA_ARGS__` is always available. * We assume C99 for ruby itself but we don't assume languages of * extension libraries. They could be written in C++98. * @brief Defines #RBIMPL_WARNING_PUSH. * * ### Q&A ### * * Q: Why all the macros defined in this file are function-like macros? * * A: Sigh. This is because of Doxygen. Its `SKIP_FUNCTION_MACROS = YES` * configuration setting requests us that if we want it to ignore these * macros, then we have to do two things: (1) let them be defined as * function-like macros, and (2) place them separately in their own line, * like below: * * ```CXX * // NG -- foo's type considered something like `unsigned int`. * RBIMPL_WARNING_PUSH * int foo(void); * RBIMPL_WARNING_POP * * // OK -- the macros are ignored by Doxygen. * RBIMPL_WARNING_PUSH() * int foo(void); * RBIMPL_WARNING_POP() * ``` */ #include "ruby/internal/compiler_is.h" #include "ruby/internal/compiler_since.h" #if defined(__DOXYGEN__) /** * @private * * Pushes compiler warning state. */ #define RBIMPL_WARNING_PUSH() __pragma(warning(push)) /** * @private * * Pops compiler warning state. */ #define RBIMPL_WARNING_POP() __pragma(warning(pop)) /** * @private * * Turns a warning into a fatal error. * * @param flag A flag that represents the kind of warnings. */ #define RBIMPL_WARNING_ERROR(flag) __pragma(warning(error: flag)) /** * @private * * Suppresses a warning. * * @param flag A flag that represents the kind of warnings. */ #define RBIMPL_WARNING_IGNORED(flag) __pragma(warning(disable: flag)) #elif RBIMPL_COMPILER_SINCE(MSVC, 12, 0, 0) # /* Not sure exactly when but it seems VC++ 6.0 is a version with it.*/ # define RBIMPL_WARNING_PUSH() __pragma(warning(push)) # define RBIMPL_WARNING_POP() __pragma(warning(pop)) # define RBIMPL_WARNING_ERROR(flag) __pragma(warning(error: flag)) # define RBIMPL_WARNING_IGNORED(flag) __pragma(warning(disable: flag)) #elif RBIMPL_COMPILER_SINCE(Intel, 13, 0, 0) # define RBIMPL_WARNING_PUSH() __pragma(warning(push)) # define RBIMPL_WARNING_POP() __pragma(warning(pop)) # define RBIMPL_WARNING_ERROR(flag) __pragma(warning(error: flag)) # define RBIMPL_WARNING_IGNORED(flag) __pragma(warning(disable: flag)) #elif RBIMPL_COMPILER_IS(Clang) || RBIMPL_COMPILER_IS(Apple) # /* Not sure exactly when but it seems LLVM 2.6.0 is a version with it. */ # define RBIMPL_WARNING_PRAGMA0(x) _Pragma(# x) # define RBIMPL_WARNING_PRAGMA1(x) RBIMPL_WARNING_PRAGMA0(clang diagnostic x) # define RBIMPL_WARNING_PRAGMA2(x, y) RBIMPL_WARNING_PRAGMA1(x # y) # define RBIMPL_WARNING_PUSH() RBIMPL_WARNING_PRAGMA1(push) # define RBIMPL_WARNING_POP() RBIMPL_WARNING_PRAGMA1(pop) # define RBIMPL_WARNING_ERROR(flag) RBIMPL_WARNING_PRAGMA2(error, flag) # define RBIMPL_WARNING_IGNORED(flag) RBIMPL_WARNING_PRAGMA2(ignored, flag) #elif RBIMPL_COMPILER_SINCE(GCC, 4, 6, 0) # /* https://gcc.gnu.org/onlinedocs/gcc-4.6.0/gcc/Diagnostic-Pragmas.html */ # define RBIMPL_WARNING_PRAGMA0(x) _Pragma(# x) # define RBIMPL_WARNING_PRAGMA1(x) RBIMPL_WARNING_PRAGMA0(GCC diagnostic x) # define RBIMPL_WARNING_PRAGMA2(x, y) RBIMPL_WARNING_PRAGMA1(x # y) # define RBIMPL_WARNING_PUSH() RBIMPL_WARNING_PRAGMA1(push) # define RBIMPL_WARNING_POP() RBIMPL_WARNING_PRAGMA1(pop) # define RBIMPL_WARNING_ERROR(flag) RBIMPL_WARNING_PRAGMA2(error, flag) # define RBIMPL_WARNING_IGNORED(flag) RBIMPL_WARNING_PRAGMA2(ignored, flag) #else # /* :FIXME: improve here */ # define RBIMPL_WARNING_PUSH() /* void */ # define RBIMPL_WARNING_POP() /* void */ # define RBIMPL_WARNING_ERROR(flag) /* void */ # define RBIMPL_WARNING_IGNORED(flag) /* void */ #endif /* _MSC_VER */ /** @endcond */ #endif /* RBIMPL_WARNING_PUSH_H */ include/ruby/internal/module.h 0000644 00000016103 15152150475 0012430 0 ustar 00 #ifndef RBIMPL_MODULE_H /*-*-C++-*-vi:se ft=cpp:*/ #define RBIMPL_MODULE_H /** * @file * @author Ruby developers <ruby-core@ruby-lang.org> * @copyright This file is a part of the programming language Ruby. * Permission is hereby granted, to either redistribute and/or * modify this file, provided that the conditions mentioned in the * file COPYING are met. Consult the file for details. * @warning Symbols prefixed with either `RBIMPL` or `rbimpl` are * implementation details. Don't take them as canon. They could * rapidly appear then vanish. The name (path) of this header file * is also an implementation detail. Do not expect it to persist * at the place it is now. Developers are free to move it anywhere * anytime at will. * @note To ruby-core: remember that this header can be possibly * recursively included from extension libraries written in C++. * Do not expect for instance `__VA_ARGS__` is always available. * We assume C99 for ruby itself but we don't assume languages of * extension libraries. They could be written in C++98. * @brief Creation and modification of Ruby modules. */ #include "ruby/internal/dllexport.h" #include "ruby/internal/value.h" /** * @defgroup class Classes and their hierarchy. * * @par Terminology * - class: same as in Ruby. * - singleton class: class for a particular object. * - eigenclass: = singleton class * - metaclass: class of a class. Metaclass is a kind of singleton class. * - metametaclass: class of a metaclass. * - meta^(n)-class: class of a meta^(n-1)-class. * - attached object: A singleton class knows its unique instance. * The instance is called the attached object for the singleton class. * @{ */ RBIMPL_SYMBOL_EXPORT_BEGIN() RBIMPL_ATTR_NONNULL(()) /** * Defines a top-level class. * * @param[in] name Name of the class. * @param[in] super A class from which the new class will derive. * @exception rb_eTypeError The constant name `name` is already taken but the * constant is not a class. * @exception rb_eTypeError The class is already defined but the class can * not be reopened because its superclass is not * `super`. * @exception rb_eArgError `super` is NULL. * @return The created class. * @post Top-level constant named `name` refers the returned class. * @note If a class named `name` is already defined and its superclass is * `super`, the function just returns the defined class. * @note The compaction GC does not move classes returned by this * function. * * @internal * * There are classes without names, but you can't pass NULL here. You have to * use other ways to create one. */ VALUE rb_define_class(const char *name, VALUE super); RBIMPL_ATTR_NONNULL(()) /** * Defines a top-level module. * * @param[in] name Name of the module. * @exception rb_eTypeError The constant name `name` is already taken but the * constant is not a module. * @return The created module. * @post Top-level constant named `name` refers the returned module. * @note The compaction GC does not move classes returned by this * function. * * @internal * * There are modules without names, but you can't pass NULL here. You have to * use other ways to create one. */ VALUE rb_define_module(const char *name); RBIMPL_ATTR_NONNULL(()) /** * Defines a class under the namespace of `outer`. * * @param[out] outer A class which contains the new class. * @param[in] name Name of the new class * @param[in] super A class from which the new class will derive. * 0 means ::rb_cObject. * @exception rb_eTypeError The constant name `name` is already taken but * the constant is not a class. * @exception rb_eTypeError The class is already defined but the class can * not be reopened because its superclass is not * `super`. * @exception rb_eArgError `super` is NULL. * @return The created class. * @post `outer::name` refers the returned class. * @note If a class named `name` is already defined and its superclass * is `super`, the function just returns the defined class. * @note The compaction GC does not move classes returned by this * function. */ VALUE rb_define_class_under(VALUE outer, const char *name, VALUE super); RBIMPL_ATTR_NONNULL(()) /** * Defines a module under the namespace of `outer`. * * @param[out] outer A class which contains the new module. * @param[in] name Name of the new module * @exception rb_eTypeError The constant name `name` is already taken but * the constant is not a class. * @return The created module. * @post `outer::name` refers the returned module. * @note The compaction GC does not move classes returned by this * function. */ VALUE rb_define_module_under(VALUE outer, const char *name); /** * Includes a module to a class. * * @param[out] klass Inclusion destination. * @param[in] module Inclusion source. * @exception rb_eArgError Cyclic inclusion. * * @internal * * :FIXME: @shyouhei suspects this function lacks assertion that the arguments * being modules... Could silently SEGV if non-module was passed? */ void rb_include_module(VALUE klass, VALUE module); /** * Extend the object with the module. * * @warning This is the same as `Module#extend_object`, not * `Object#extend`! These two methods are very similar, but not * identical. The difference is the hook. `Module#extend_object` * does not invoke `Module#extended`, while `Object#extend` does. * @param[out] obj Object to extend. * @param[in] mod Module of extension. */ void rb_extend_object(VALUE obj, VALUE mod); /** * Identical to rb_include_module(), except it "prepends" the passed module to * the klass, instead of includes. This affects how `super` resolves. For * instance: * * ```ruby * class Q; def foo; "<q/>" end end * module W; def foo; "<w>#{super}</w>" end end * class E < Q; include W; def foo; "<e>#{super}</e>" end end * class R < Q; prepend W; def foo; "<r>#{super}</r>" end end * * E.new.foo # => "<e><w><q/></w></e>" * r.new.foo # => "<W><r><q/></r></w>" * ``` * * @param[out] klass Target class to modify. * @param[in] module Module to prepend. * @exception rb_eArgError Cyclic inclusion. */ void rb_prepend_module(VALUE klass, VALUE module); /** @} */ RBIMPL_SYMBOL_EXPORT_END() #endif /* RBIMPL_MODULE_H */ include/ruby/internal/error.h 0000644 00000051426 15152150476 0012304 0 ustar 00 #ifndef RBIMPL_ERROR_H /*-*-C++-*-vi:se ft=cpp:*/ #define RBIMPL_ERROR_H /** * @file * @author Ruby developers <ruby-core@ruby-lang.org> * @copyright This file is a part of the programming language Ruby. * Permission is hereby granted, to either redistribute and/or * modify this file, provided that the conditions mentioned in the * file COPYING are met. Consult the file for details. * @warning Symbols prefixed with either `RBIMPL` or `rbimpl` are * implementation details. Don't take them as canon. They could * rapidly appear then vanish. The name (path) of this header file * is also an implementation detail. Do not expect it to persist * at the place it is now. Developers are free to move it anywhere * anytime at will. * @note To ruby-core: remember that this header can be possibly * recursively included from extension libraries written in C++. * Do not expect for instance `__VA_ARGS__` is always available. * We assume C99 for ruby itself but we don't assume languages of * extension libraries. They could be written in C++98. * @brief Declares ::rb_raise(). */ #include "ruby/internal/attr/cold.h" #include "ruby/internal/attr/format.h" #include "ruby/internal/attr/noreturn.h" #include "ruby/internal/attr/nonnull.h" #include "ruby/internal/dllexport.h" #include "ruby/internal/value.h" /** * @defgroup exception Exception handlings * @{ */ /** * Warning categories. A warning issued using this API can be selectively * requested / suppressed by the end-users. For instance passing * `-W:no-deprecated` to the ruby process would suppress those warnings in * deprecated category. * * @warning There is no way to declare a new category (for now). */ typedef enum { /** Category unspecified. */ RB_WARN_CATEGORY_NONE, /** Warning is for deprecated features. */ RB_WARN_CATEGORY_DEPRECATED, /** Warning is for experimental features. */ RB_WARN_CATEGORY_EXPERIMENTAL, /** Warning is for performance issues (not enabled by -w). */ RB_WARN_CATEGORY_PERFORMANCE, RB_WARN_CATEGORY_DEFAULT_BITS = ( (1U << RB_WARN_CATEGORY_DEPRECATED) | (1U << RB_WARN_CATEGORY_EXPERIMENTAL) | 0), RB_WARN_CATEGORY_ALL_BITS = ( (1U << RB_WARN_CATEGORY_DEPRECATED) | (1U << RB_WARN_CATEGORY_EXPERIMENTAL) | (1U << RB_WARN_CATEGORY_PERFORMANCE) | 0) } rb_warning_category_t; /** for rb_readwrite_sys_fail first argument */ enum rb_io_wait_readwrite {RB_IO_WAIT_READABLE, RB_IO_WAIT_WRITABLE}; /** @cond INTERNAL_MACRO */ #define RB_IO_WAIT_READABLE RB_IO_WAIT_READABLE #define RB_IO_WAIT_WRITABLE RB_IO_WAIT_WRITABLE /** @endcond */ RBIMPL_SYMBOL_EXPORT_BEGIN() /** * This is the same as `$!` in Ruby. * * @retval RUBY_Qnil Not handling exceptions at the moment. * @retval otherwise The current exception in the current thread. * @ingroup exception */ VALUE rb_errinfo(void); /** * Sets the current exception (`$!`) to the given value. * * @param[in] err An instance of ::rb_eException, or ::RUBY_Qnil. * @exception rb_eTypeError What is given was neither ::rb_eException nor * ::RUBY_Qnil. * @note Use rb_raise() instead to raise `err`. This function just * assigns the given object to the global variable. * @ingroup exception */ void rb_set_errinfo(VALUE err); RBIMPL_ATTR_NORETURN() RBIMPL_ATTR_NONNULL((2)) RBIMPL_ATTR_FORMAT(RBIMPL_PRINTF_FORMAT, 2, 3) /** * Exception entry point. By calling this function the execution of your * program gets interrupted to "raise" an exception up to the callee entities. * Programs could "rescue" that exception, or could "ensure" some part of them. * If nobody cares about such things, the raised exception reaches at the top * of execution. This yields abnormal end of the process. * * @param[in] exc A subclass of ::rb_eException. * @param[in] fmt Format specifier string compatible with rb_sprintf(). * @exception exc The specified exception. * @note It never returns. */ void rb_raise(VALUE exc, const char *fmt, ...); RBIMPL_ATTR_NORETURN() RBIMPL_ATTR_NONNULL((1)) RBIMPL_ATTR_FORMAT(RBIMPL_PRINTF_FORMAT, 1, 2) /** * Raises the unsung "fatal" exception. This is considered severe. Nobody can * rescue the exception. Once raised, process termination is inevitable. * However ensure clauses still run, so that resources are properly cleaned up. * * @param[in] fmt Format specifier string compatible with rb_sprintf(). * @exception rb_eFatal An exception that you cannot rescue. * @note It never returns. */ void rb_fatal(const char *fmt, ...); RBIMPL_ATTR_COLD() RBIMPL_ATTR_NORETURN() RBIMPL_ATTR_NONNULL((1)) RBIMPL_ATTR_FORMAT(RBIMPL_PRINTF_FORMAT, 1, 2) /** * Interpreter panic switch. Immediate process termination without any * synchronisations shall occur. LOTS of internal states, stack traces, and * even machine registers are displayed if possible for debugging purposes * then. * * @warning Do not use this API. * @warning You are not expected to use this API. * @warning Why not just fix your code instead of calling this API? * @warning It was a bad idea to expose this API to extension libraries at * the first place. We just cannot delete it at this point for * backwards compatibility. That doesn't mean everyone are * welcomed to call this function at will. * @param[in] fmt Format specifier string compatible with rb_sprintf(). * @note It never returns. */ void rb_bug(const char *fmt, ...); RBIMPL_ATTR_NORETURN() RBIMPL_ATTR_NONNULL(()) /** * This is a wrapper of rb_bug() which automatically constructs appropriate * message from the passed errno. * * @param[in] msg Additional message to display. * @exception err C level errno. * @note It never returns. */ void rb_bug_errno(const char *msg, int err); RBIMPL_ATTR_NORETURN() /** * Converts a C errno into a Ruby exception, then raises it. For instance: * * ```CXX * static VALUE * foo(VALUE argv) * { * const auto cmd = StringValueCStr(argv); * const auto waitr = system(cmd); * if (waitr == -1) { * rb_sys_fail("system(3posix)"); // <-------------- this * } * else { * return INT2FIX(fd); * } * } * ``` * * @param[in] msg Additional message to raise. * @exception rb_eSystemCallError An exception representing errno. * @note It never returns. */ void rb_sys_fail(const char *msg); RBIMPL_ATTR_NORETURN() /** * Identical to rb_sys_fail(), except it takes the message in Ruby's String * instead of C's. * * @param[in] msg Additional message to raise. * @exception rb_eSystemCallError An exception representing errno. * @note It never returns. */ void rb_sys_fail_str(VALUE msg); RBIMPL_ATTR_NORETURN() RBIMPL_ATTR_NONNULL((2)) /** * Identical to rb_sys_fail(), except it takes additional module to extend the * exception object before raising. * * @param[in] mod A ::rb_cModule instance. * @param[in] msg Additional message to raise. * @exception rb_eSystemCallError An exception representing errno. * @note It never returns. * * @internal * * Does anybody use it? */ void rb_mod_sys_fail(VALUE mod, const char *msg); RBIMPL_ATTR_NORETURN() /** * Identical to rb_mod_sys_fail(), except it takes the message in Ruby's String * instead of C's. * * @param[in] mod A ::rb_cModule instance. * @param[in] msg Additional message to raise. * @exception rb_eSystemCallError An exception representing errno. * @note It never returns. */ void rb_mod_sys_fail_str(VALUE mod, VALUE msg); RBIMPL_ATTR_NORETURN() /** * Raises appropriate exception using the parameters. * * In Ruby level there are rb_eEAGAINWaitReadable etc. This function maps the * given parameter to an appropriate exception class, then raises it. * * @param[in] waiting Reason for the IO to wait. * @param[in] msg Additional message to raise. * @exception rb_eEAGAINWaitWritable * @exception rb_eEWOULDBLOCKWaitWritable * @exception rb_eEINPROGRESSWaitWritable * @exception rb_eEAGAINWaitReadable * @exception rb_eEWOULDBLOCKWaitReadable * @exception rb_eEINPROGRESSWaitReadable * @exception rb_eSystemCallError * @note It never returns. */ void rb_readwrite_sys_fail(enum rb_io_wait_readwrite waiting, const char *msg); RBIMPL_ATTR_NORETURN() /** * Breaks from a block. Because you are using a CAPI this is not as intuitive * as it sounds. In order for this function to properly work, make a * ::rb_block_call_func_t function that calls it internally, and pass that * function to rb_block_call(). * * @exception rb_eLocalJumpError Called from outside of a block. * @note It never returns. */ void rb_iter_break(void); RBIMPL_ATTR_NORETURN() /** * Identical to rb_iter_break(), except it additionally takes the "value" of * this breakage. It will be the evaluation result of the iterator. This is * kind of complicated; you cannot see this as a "return from a block" * behaviour. Take a look at this example: * * ```ruby * def foo(q) * puts(w = yield(q)) * puts(e = yield(w)) * puts(r = yield(e)) * puts(t = yield(r)) * puts(y = yield(t)) * return "howdy!" * end * * x = foo(0) {|i| * if i > 2 * break "hello!" * else * next i + 1 * end * } * * puts x * ``` * * This script outputs 1, 2, 3, and hello. Note that the value passed to break * becomes the return value of foo method, not the value of yield. This is * confusing, but can be handy on occasions e.g. when you want to bring a * local variable out of a block. * * @param[in] val The value of the iterator. * @exception rb_eLocalJumpError Called from outside of a block. * @note It never returns. */ void rb_iter_break_value(VALUE val); RBIMPL_ATTR_NORETURN() /** * Terminates the current execution context. This API is the entry point of a * "well-mannered" termination sequence. When called from an extension * library, it raises ::rb_eSystemExit exception. Programs could rescue that * exception. Can cancel process exit then. Otherwise, that exception results * in a process termination with the status passed to this function. * * @param[in] status Exit status, see also exit(3). * @exception rb_eSystemExit Exception representing the exit status. * @note It never returns. * * @internal * * "When called from an extension library"? You might wonder. In fact there * are chances for this function to be called from outside of it, for instance * when dlopen(3) failed. In case it is not possible for this function to * raise an exception, it does not (silently enters to process cleanup). But * that is a kind of implementation detail which extension library authors * should not bother. */ void rb_exit(int status); RBIMPL_ATTR_NORETURN() /** * @exception rb_eNotImpError * @note It never returns. */ void rb_notimplement(void); /** * Creates an exception object that represents the given C errno. * * @param[in] err C level errno. * @param[in] msg Additional message. * @retval rb_eSystemCallError An exception for the errno. */ VALUE rb_syserr_new(int err, const char * msg); /** * Identical to rb_syserr_new(), except it takes the message in Ruby's String * instead of C's. * * @param[in] n C level errno. * @param[in] arg Additional message. * @retval rb_eSystemCallError An exception for the errno. */ VALUE rb_syserr_new_str(int n, VALUE arg); RBIMPL_ATTR_NORETURN() /** * Raises appropriate exception that represents a C errno. * * @param[in] err C level errno. * @param[in] msg Additional message to raise. * @exception rb_eSystemCallError An exception representing `err`. * @note It never returns. */ void rb_syserr_fail(int err, const char *msg); RBIMPL_ATTR_NORETURN() /** * Identical to rb_syserr_fail(), except it takes the message in Ruby's String * instead of C's. * * @param[in] err C level errno. * @param[in] msg Additional message to raise. * @exception rb_eSystemCallError An exception representing `err`. * @note It never returns. */ void rb_syserr_fail_str(int err, VALUE msg); RBIMPL_ATTR_NORETURN() RBIMPL_ATTR_NONNULL(()) /** * Identical to rb_mod_sys_fail(), except it does not depend on C global * variable errno. Pass it explicitly. * * @param[in] mod A ::rb_cModule instance. * @param[in] err C level errno. * @param[in] msg Additional message to raise. * @exception rb_eSystemCallError An exception representing `err`. * @note It never returns. */ void rb_mod_syserr_fail(VALUE mod, int err, const char *msg); RBIMPL_ATTR_NORETURN() /** * Identical to rb_mod_syserr_fail(), except it takes the message in Ruby's * String instead of C's. * * @param[in] mod A ::rb_cModule instance. * @param[in] err C level errno. * @param[in] msg Additional message to raise. * @exception rb_eSystemCallError An exception representing `err`. * @note It never returns. */ void rb_mod_syserr_fail_str(VALUE mod, int err, VALUE msg); RBIMPL_ATTR_NORETURN() /** * Identical to rb_readwrite_sys_fail(), except it does not depend on C global * variable errno. Pass it explicitly. * * @param[in] waiting Reason for the IO to wait. * @param[in] err C level errno. * @param[in] msg Additional message to raise. * @exception rb_eEAGAINWaitWritable * @exception rb_eEWOULDBLOCKWaitWritable * @exception rb_eEINPROGRESSWaitWritable * @exception rb_eEAGAINWaitReadable * @exception rb_eEWOULDBLOCKWaitReadable * @exception rb_eEINPROGRESSWaitReadable * @exception rb_eSystemCallError * @note It never returns. */ void rb_readwrite_syserr_fail(enum rb_io_wait_readwrite waiting, int err, const char *msg); RBIMPL_ATTR_COLD() RBIMPL_ATTR_NORETURN() /** * Fails with the given object's type incompatibility to the type. * * It seems this function is visible from extension libraries only because * RTYPEDDATA_TYPE() uses it on RUBY_DEBUG. So you can basically ignore it; * use some other fine-grained method instead. * * @param[in] self The object in question. * @param[in] t Expected type of the object. * @exception rb_eTypeError `self` not in type `t`. * @note It never returns. * @note The second argument must have been an enum ::ruby_value_type, * but for historical reasons it remains to be an int (in other * words we see no benefits fixing this bug). */ void rb_unexpected_type(VALUE self, int t); /** * @private * * This is an implementation detail of #ruby_verbose. Please don't use it * directly. * * @retval Qnil Interpreter is quiet. * @retval Qfalse Interpreter is kind of chatty. * @retval otherwise Interpreter is very verbose. */ VALUE *rb_ruby_verbose_ptr(void); /** * @private * * This is an implementation detail of #ruby_debug. Please don't use it * directly. * * @retval Qnil Interpreter not in debug mode. * @retval Qfalse Interpreter not in debug mode. * @retval otherwise Interpreter is in debug mode. */ VALUE *rb_ruby_debug_ptr(void); /** * This variable controls whether the interpreter is in debug mode. Setting * this to some truthy value is equivalent to passing `-W` flag to the * interpreter. Setting this to ::Qfalse is equivalent to passing `-W1` flag * to the interpreter. Setting this to ::Qnil is equivalent to passing `-W0` * flag to the interpreter. * * @retval Qnil Interpreter is quiet. * @retval Qfalse Interpreter is kind of chatty. * @retval otherwise Interpreter is very verbose. */ #define ruby_verbose (*rb_ruby_verbose_ptr()) /** * This variable controls whether the interpreter is in debug mode. Setting * this to some truthy value is equivalent to passing `-d` flag to the * interpreter. * * @retval Qnil Interpreter not in debug mode. * @retval Qfalse Interpreter not in debug mode. * @retval otherwise Interpreter is in debug mode. */ #define ruby_debug (*rb_ruby_debug_ptr()) /* reports if $VERBOSE is true */ RBIMPL_ATTR_NONNULL((1)) RBIMPL_ATTR_FORMAT(RBIMPL_PRINTF_FORMAT, 1, 2) /** * Issues a warning. * * In ruby, warnings these days are tightly coupled with the rb_mWarning * constant and its `warn` singleton method. This CAPI is just a thin wrapper * of it; everything passed are formatted like what rb_sprintf() does, then * passed through to the method. Programs can have their own `def * Warning.warn` at will to do whatever they want, from ignoring the warnings * at all to sinking them to some BigQuery data set via a Fluentd cluster. By * default, the method just emits its passed contents to ::rb_stderr using * rb_io_write(). * * @note This function is affected by the value of $VERBOSE, it does * nothing unless $VERBOSE is true. * @param[in] fmt Format specifier string compatible with rb_sprintf(). * * @internal * * Above description is in fact inaccurate. This API interfaces with Ractors. */ void rb_warning(const char *fmt, ...); RBIMPL_ATTR_NONNULL((2)) RBIMPL_ATTR_FORMAT(RBIMPL_PRINTF_FORMAT, 2, 3) /** * Identical to rb_warning(), except it takes additional "category" parameter. * * @param[in] cat Name of a known category. * @param[in] fmt Format specifier string compatible with rb_sprintf(). */ void rb_category_warning(rb_warning_category_t cat, const char *fmt, ...); RBIMPL_ATTR_NONNULL((1, 3)) RBIMPL_ATTR_FORMAT(RBIMPL_PRINTF_FORMAT, 3, 4) /** * Issues a compile-time warning that happens at `__file__:__line__`. Purpose * of this function being exposed to CAPI is unclear. * * @note This function is affected by the value of $VERBOSE. * @param[in] file The path corresponding to Ruby level `__FILE__`. * @param[in] line The number corresponding to Ruby level `__LINE__`. * @param[in] fmt Format specifier string compatible with rb_sprintf(). */ void rb_compile_warning(const char *file, int line, const char *fmt, ...); RBIMPL_ATTR_NONNULL((1)) RBIMPL_ATTR_FORMAT(RBIMPL_PRINTF_FORMAT, 1, 2) /** * Identical to rb_sys_fail(), except it does not raise an exception to render * a warning instead. * * @note This function is affected by the value of $VERBOSE. * @param[in] fmt Format specifier string compatible with rb_sprintf(). */ void rb_sys_warning(const char *fmt, ...); /* reports if $VERBOSE is not nil (so if it is true or false) */ RBIMPL_ATTR_COLD() RBIMPL_ATTR_NONNULL((1)) RBIMPL_ATTR_FORMAT(RBIMPL_PRINTF_FORMAT, 1, 2) /** * Identical to rb_warning(), except it reports unless $VERBOSE is nil. * * @note This function is affected by the value of $VERBOSE, it does * nothing if $VERBOSE is nil. * @param[in] fmt Format specifier string compatible with rb_sprintf(). */ void rb_warn(const char *fmt, ...); RBIMPL_ATTR_COLD() RBIMPL_ATTR_NONNULL((2)) RBIMPL_ATTR_FORMAT(RBIMPL_PRINTF_FORMAT, 2, 3) /** * Identical to rb_category_warning(), except it reports unless $VERBOSE is nil. * * @param[in] cat Category e.g. deprecated. * @param[in] fmt Format specifier string compatible with rb_sprintf(). */ void rb_category_warn(rb_warning_category_t cat, const char *fmt, ...); RBIMPL_ATTR_NONNULL((1, 3)) RBIMPL_ATTR_FORMAT(RBIMPL_PRINTF_FORMAT, 3, 4) /** * Identical to rb_compile_warning(), except it reports unless $VERBOSE is nil. * * @param[in] file The path corresponding to Ruby level `__FILE__`. * @param[in] line The number corresponding to Ruby level `__LINE__`. * @param[in] fmt Format specifier string compatible with rb_sprintf(). */ void rb_compile_warn(const char *file, int line, const char *fmt, ...); RBIMPL_ATTR_NONNULL((2, 4)) RBIMPL_ATTR_FORMAT(RBIMPL_PRINTF_FORMAT, 4, 5) /** * Identical to rb_compile_warn(), except it also accepts category. * * @param[in] cat Category e.g. deprecated. * @param[in] file The path corresponding to Ruby level `__FILE__`. * @param[in] line The number corresponding to Ruby level `__LINE__`. * @param[in] fmt Format specifier string compatible with rb_sprintf(). */ void rb_category_compile_warn(rb_warning_category_t cat, const char *file, int line, const char *fmt, ...); /** @} */ RBIMPL_SYMBOL_EXPORT_END() #endif /* RBIMPL_ERROR_H */ include/ruby/internal/arithmetic/size_t.h 0000644 00000005524 15152150476 0014577 0 ustar 00 #ifndef RBIMPL_ARITHMETIC_SIZE_T_H /*-*-C++-*-vi:se ft=cpp:*/ #define RBIMPL_ARITHMETIC_SIZE_T_H /** * @file * @author Ruby developers <ruby-core@ruby-lang.org> * @copyright This file is a part of the programming language Ruby. * Permission is hereby granted, to either redistribute and/or * modify this file, provided that the conditions mentioned in the * file COPYING are met. Consult the file for details. * @warning Symbols prefixed with either `RBIMPL` or `rbimpl` are * implementation details. Don't take them as canon. They could * rapidly appear then vanish. The name (path) of this header file * is also an implementation detail. Do not expect it to persist * at the place it is now. Developers are free to move it anywhere * anytime at will. * @note To ruby-core: remember that this header can be possibly * recursively included from extension libraries written in C++. * Do not expect for instance `__VA_ARGS__` is always available. * We assume C99 for ruby itself but we don't assume languages of * extension libraries. They could be written in C++98. * @brief Arithmetic conversion between C's `size_t` and Ruby's. */ #include "ruby/internal/config.h" #include "ruby/internal/arithmetic/int.h" #include "ruby/internal/arithmetic/long.h" #include "ruby/internal/arithmetic/long_long.h" #include "ruby/backward/2/long_long.h" #if defined(__DOXYGEN__) # /** Converts a C's `size_t` into an instance of ::rb_cInteger. */ # define RB_SIZE2NUM RB_ULONG2NUM # /** Converts a C's `ssize_t` into an instance of ::rb_cInteger. */ # define RB_SSIZE2NUM RB_LONG2NUM #elif SIZEOF_SIZE_T == SIZEOF_LONG_LONG # define RB_SIZE2NUM RB_ULL2NUM # define RB_SSIZE2NUM RB_LL2NUM #elif SIZEOF_SIZE_T == SIZEOF_LONG # define RB_SIZE2NUM RB_ULONG2NUM # define RB_SSIZE2NUM RB_LONG2NUM #else # define RB_SIZE2NUM RB_UINT2NUM # define RB_SSIZE2NUM RB_INT2NUM #endif #if defined(__DOXYGEN__) # /** Converts an instance of ::rb_cInteger into C's `size_t`. */ # define RB_NUM2SIZE RB_NUM2ULONG # /** Converts an instance of ::rb_cInteger into C's `ssize_t`. */ # define RB_NUM2SSIZE RB_NUM2LONG #elif SIZEOF_SIZE_T == SIZEOF_LONG_LONG # define RB_NUM2SIZE RB_NUM2ULL # define RB_NUM2SSIZE RB_NUM2LL #elif SIZEOF_SIZE_T == SIZEOF_LONG # define RB_NUM2SIZE RB_NUM2ULONG # define RB_NUM2SSIZE RB_NUM2LONG #else # define RB_NUM2SIZE RB_NUM2UINT # define RB_NUM2SSIZE RB_NUM2INT #endif #define NUM2SIZET RB_NUM2SIZE /**< @old{RB_NUM2SIZE} */ #define SIZET2NUM RB_SIZE2NUM /**< @old{RB_SIZE2NUM} */ #define NUM2SSIZET RB_NUM2SSIZE /**< @old{RB_NUM2SSIZE} */ #define SSIZET2NUM RB_SSIZE2NUM /**< @old{RB_SSIZE2NUM} */ #endif /* RBIMPL_ARITHMETIC_SIZE_T_H */ include/ruby/internal/arithmetic/off_t.h 0000644 00000004704 15152150476 0014376 0 ustar 00 #ifndef RBIMPL_ARITHMETIC_OFF_T_H /*-*-C++-*-vi:se ft=cpp:*/ #define RBIMPL_ARITHMETIC_OFF_T_H /** * @file * @author Ruby developers <ruby-core@ruby-lang.org> * @copyright This file is a part of the programming language Ruby. * Permission is hereby granted, to either redistribute and/or * modify this file, provided that the conditions mentioned in the * file COPYING are met. Consult the file for details. * @warning Symbols prefixed with either `RBIMPL` or `rbimpl` are * implementation details. Don't take them as canon. They could * rapidly appear then vanish. The name (path) of this header file * is also an implementation detail. Do not expect it to persist * at the place it is now. Developers are free to move it anywhere * anytime at will. * @note To ruby-core: remember that this header can be possibly * recursively included from extension libraries written in C++. * Do not expect for instance `__VA_ARGS__` is always available. * We assume C99 for ruby itself but we don't assume languages of * extension libraries. They could be written in C++98. * @brief Arithmetic conversion between C's `off_t` and Ruby's. */ #include "ruby/internal/config.h" #include "ruby/internal/arithmetic/int.h" #include "ruby/internal/arithmetic/long.h" #include "ruby/internal/arithmetic/long_long.h" #include "ruby/backward/2/long_long.h" /** Converts a C's `off_t` into an instance of ::rb_cInteger. */ #ifdef OFFT2NUM # /* take that. */ #elif SIZEOF_OFF_T == SIZEOF_LONG_LONG # define OFFT2NUM RB_LL2NUM #elif SIZEOF_OFF_T == SIZEOF_LONG # define OFFT2NUM RB_LONG2NUM #else # define OFFT2NUM RB_INT2NUM #endif /** Converts an instance of ::rb_cNumeric into C's `off_t`. */ #ifdef NUM2OFFT # /* take that. */ #elif SIZEOF_OFF_T == SIZEOF_LONG_LONG # define NUM2OFFT RB_NUM2LL #elif SIZEOF_OFF_T == SIZEOF_LONG # define NUM2OFFT RB_NUM2LONG #else # define NUM2OFFT RB_NUM2INT #endif /** A rb_sprintf() format prefix to be used for an `off_t` parameter. */ #ifdef PRI_OFFT_PREFIX # /* take that. */ #elif SIZEOF_OFF_T == SIZEOF_LONG_LONG # define PRI_OFFT_PREFIX PRI_LL_PREFIX #elif SIZEOF_OFF_T == SIZEOF_LONG # define PRI_OFFT_PREFIX PRI_LONG_PREFIX #else # define PRI_OFFT_PREFIX PRI_INT_PREFIX #endif #endif /* RBIMPL_ARITHMETIC_OFF_T_H */ include/ruby/internal/arithmetic/st_data_t.h 0000644 00000005663 15152150476 0015250 0 ustar 00 #ifndef RBIMPL_ARITHMERIC_ST_DATA_T_H /*-*-C++-*-vi:se ft=cpp:*/ #define RBIMPL_ARITHMERIC_ST_DATA_T_H /** * @file * @author Ruby developers <ruby-core@ruby-lang.org> * @copyright This file is a part of the programming language Ruby. * Permission is hereby granted, to either redistribute and/or * modify this file, provided that the conditions mentioned in the * file COPYING are met. Consult the file for details. * @warning Symbols prefixed with either `RBIMPL` or `rbimpl` are * implementation details. Don't take them as canon. They could * rapidly appear then vanish. The name (path) of this header file * is also an implementation detail. Do not expect it to persist * at the place it is now. Developers are free to move it anywhere * anytime at will. * @note To ruby-core: remember that this header can be possibly * recursively included from extension libraries written in C++. * Do not expect for instance `__VA_ARGS__` is always available. * We assume C99 for ruby itself but we don't assume languages of * extension libraries. They could be written in C++98. * @brief Arithmetic conversion between C's `st_data_t` and Ruby's. */ #include "ruby/internal/arithmetic/fixnum.h" #include "ruby/internal/arithmetic/long.h" #include "ruby/internal/attr/artificial.h" #include "ruby/internal/attr/const.h" #include "ruby/internal/attr/constexpr.h" #include "ruby/internal/cast.h" #include "ruby/internal/value.h" #include "ruby/assert.h" #include "ruby/st.h" #define ST2FIX RB_ST2FIX /**< @old{RB_ST2FIX} */ /** @cond INTERNAL_MACRO */ #define RB_ST2FIX RB_ST2FIX /** @endcond */ RBIMPL_ATTR_CONST_UNLESS_DEBUG() RBIMPL_ATTR_CONSTEXPR_UNLESS_DEBUG(CXX14) RBIMPL_ATTR_ARTIFICIAL() /** * Converts a C's `st_data_t` into an instance of ::rb_cInteger. * * @param[in] i The data in question. * @return A converted result * @warning THIS CONVERSION LOSES DATA! Be warned. * @see https://bugs.ruby-lang.org/issues/13877 * @see https://bugs.ruby-lang.org/issues/14218 * * @internal * * This is needed because of hash functions. Hash functions return * `st_data_t`, which could theoretically be bigger than Fixnums. However * allocating Bignums for them every time we calculate hash values is just too * heavy. To avoid penalty we need to ignore some upper bit(s) and stick to * Fixnums. This function is used for that purpose. */ static inline VALUE RB_ST2FIX(st_data_t i) { SIGNED_VALUE x = i; if (x >= 0) { x &= RUBY_FIXNUM_MAX; } else { x |= RUBY_FIXNUM_MIN; } RBIMPL_ASSERT_OR_ASSUME(RB_FIXABLE(x)); unsigned long y = RBIMPL_CAST((unsigned long)x); return RB_LONG2FIX(y); } #endif /* RBIMPL_ARITHMETIC_ST_DATA_T_H */ include/ruby/internal/arithmetic/long.h 0000644 00000026273 15152150476 0014245 0 ustar 00 #ifndef RBIMPL_ARITHMETIC_LONG_H /*-*-C++-*-vi:se ft=cpp:*/ #define RBIMPL_ARITHMETIC_LONG_H /** * @file * @author Ruby developers <ruby-core@ruby-lang.org> * @copyright This file is a part of the programming language Ruby. * Permission is hereby granted, to either redistribute and/or * modify this file, provided that the conditions mentioned in the * file COPYING are met. Consult the file for details. * @warning Symbols prefixed with either `RBIMPL` or `rbimpl` are * implementation details. Don't take them as canon. They could * rapidly appear then vanish. The name (path) of this header file * is also an implementation detail. Do not expect it to persist * at the place it is now. Developers are free to move it anywhere * anytime at will. * @note To ruby-core: remember that this header can be possibly * recursively included from extension libraries written in C++. * Do not expect for instance `__VA_ARGS__` is always available. * We assume C99 for ruby itself but we don't assume languages of * extension libraries. They could be written in C++98. * @brief Arithmetic conversion between C's `long` and Ruby's. * * ### Q&A ### * * - Q: Why are INT2FIX etc. here, not in `int.h`? * * - A: Because they are in fact handling `long`. It seems someone did not * understand the difference of `int` and `long` when they designed those * macros. */ #include "ruby/internal/config.h" #include "ruby/internal/arithmetic/fixnum.h" /* FIXABLE */ #include "ruby/internal/arithmetic/intptr_t.h" /* rb_int2big etc.*/ #include "ruby/internal/assume.h" #include "ruby/internal/attr/artificial.h" #include "ruby/internal/attr/cold.h" #include "ruby/internal/attr/const.h" #include "ruby/internal/attr/constexpr.h" #include "ruby/internal/attr/noreturn.h" #include "ruby/internal/cast.h" #include "ruby/internal/dllexport.h" #include "ruby/internal/special_consts.h" /* FIXNUM_FLAG */ #include "ruby/internal/value.h" #include "ruby/assert.h" #define FIX2LONG RB_FIX2LONG /**< @old{RB_FIX2LONG} */ #define FIX2ULONG RB_FIX2ULONG /**< @old{RB_FIX2ULONG} */ #define INT2FIX RB_INT2FIX /**< @old{RB_INT2FIX} */ #define LONG2FIX RB_INT2FIX /**< @old{RB_INT2FIX} */ #define LONG2NUM RB_LONG2NUM /**< @old{RB_LONG2NUM} */ #define NUM2LONG RB_NUM2LONG /**< @old{RB_NUM2LONG} */ #define NUM2ULONG RB_NUM2ULONG /**< @old{RB_NUM2ULONG} */ #define RB_FIX2LONG rb_fix2long /**< @alias{rb_fix2long} */ #define RB_FIX2ULONG rb_fix2ulong /**< @alias{rb_fix2ulong} */ #define RB_LONG2FIX RB_INT2FIX /**< @alias{RB_INT2FIX} */ #define RB_LONG2NUM rb_long2num_inline /**< @alias{rb_long2num_inline} */ #define RB_NUM2LONG rb_num2long_inline /**< @alias{rb_num2long_inline} */ #define RB_NUM2ULONG rb_num2ulong_inline /**< @alias{rb_num2ulong_inline} */ #define RB_ULONG2NUM rb_ulong2num_inline /**< @alias{rb_ulong2num_inline} */ #define ULONG2NUM RB_ULONG2NUM /**< @old{RB_ULONG2NUM} */ #define rb_fix_new RB_INT2FIX /**< @alias{RB_INT2FIX} */ #define rb_long2int rb_long2int_inline /**< @alias{rb_long2int_inline} */ /** @cond INTERNAL_MACRO */ #define RB_INT2FIX RB_INT2FIX /** @endcond */ RBIMPL_SYMBOL_EXPORT_BEGIN() RBIMPL_ATTR_NORETURN() RBIMPL_ATTR_COLD() /** * This is an utility function to raise an ::rb_eRangeError. * * @param[in] num A signed value about to overflow. * @exception rb_eRangeError `num` is out of range of `int`. */ void rb_out_of_int(SIGNED_VALUE num); /** * Converts an instance of ::rb_cNumeric into C's `long`. * * @param[in] num Something numeric. * @exception rb_eTypeError `num` is not a numeric. * @exception rb_eRangeError `num` is out of range of `long`. * @return The passed value converted into C's `long`. */ long rb_num2long(VALUE num); /** * Converts an instance of ::rb_cNumeric into C's `unsigned long`. * * @param[in] num Something numeric. * @exception rb_eTypeError `num` is not a numeric. * @exception rb_eRangeError `num` is out of range of `unsigned long`. * @return The passed value converted into C's `unsigned long`. */ unsigned long rb_num2ulong(VALUE num); RBIMPL_SYMBOL_EXPORT_END() RBIMPL_ATTR_CONST_UNLESS_DEBUG() RBIMPL_ATTR_CONSTEXPR_UNLESS_DEBUG(CXX14) RBIMPL_ATTR_ARTIFICIAL() /** * Converts a C's `long` into an instance of ::rb_cInteger. * * @param[in] i Arbitrary `long` value. * @return An instance of ::rb_cInteger. */ static inline VALUE RB_INT2FIX(long i) { RBIMPL_ASSERT_OR_ASSUME(RB_FIXABLE(i)); /* :NOTE: VALUE can be wider than long. As j being unsigned, 2j+1 is fully * defined. Also it can be compiled into a single LEA instruction. */ const unsigned long j = i; const unsigned long k = (j << 1) + RUBY_FIXNUM_FLAG; const long l = k; const SIGNED_VALUE m = l; /* Sign extend */ const VALUE n = m; RBIMPL_ASSERT_OR_ASSUME(RB_FIXNUM_P(n)); return n; } /** * Checks if `int` can hold the given integer. * * @param[in] n Arbitrary `long` value. * @exception rb_eRangeError `n` is out of range of `int`. * @return Identical value of type `int` */ static inline int rb_long2int_inline(long n) { int i = RBIMPL_CAST((int)n); if /* constexpr */ (sizeof(long) <= sizeof(int)) { RBIMPL_ASSUME(i == n); } if (i != n) rb_out_of_int(n); return i; } RBIMPL_ATTR_CONST_UNLESS_DEBUG() RBIMPL_ATTR_CONSTEXPR_UNLESS_DEBUG(CXX14) /** * @private * * This is an implementation detail of rb_fix2long(). People don't use it * directly. * * @param[in] x A Fixnum. * @return Identical value of type `long` * @pre Must not pass anything other than a Fixnum. */ static inline long rbimpl_fix2long_by_idiv(VALUE x) { RBIMPL_ASSERT_OR_ASSUME(RB_FIXNUM_P(x)); /* :NOTE: VALUE can be wider than long. (x-1)/2 never overflows because * RB_FIXNUM_P(x) holds. Also it has no portability issue like y>>1 * below. */ const SIGNED_VALUE y = x - RUBY_FIXNUM_FLAG; const SIGNED_VALUE z = y / 2; const long w = RBIMPL_CAST((long)z); RBIMPL_ASSERT_OR_ASSUME(RB_FIXABLE(w)); return w; } RBIMPL_ATTR_CONST_UNLESS_DEBUG() RBIMPL_ATTR_CONSTEXPR_UNLESS_DEBUG(CXX14) /** * @private * * This is an implementation detail of rb_fix2long(). People don't use it * directly. * * @param[in] x A Fixnum. * @return Identical value of type `long` * @pre Must not pass anything other than a Fixnum. */ static inline long rbimpl_fix2long_by_shift(VALUE x) { RBIMPL_ASSERT_OR_ASSUME(RB_FIXNUM_P(x)); /* :NOTE: VALUE can be wider than long. If right shift is arithmetic, this * is noticeably faster than above. */ const SIGNED_VALUE y = x; const SIGNED_VALUE z = y >> 1; const long w = RBIMPL_CAST((long)z); RBIMPL_ASSERT_OR_ASSUME(RB_FIXABLE(w)); return w; } RBIMPL_ATTR_CONST() RBIMPL_ATTR_CONSTEXPR(CXX11) /** * @private * * This is an implementation detail of rb_fix2long(). People don't use it * directly. * * @retval true This C compiler's right shift operator is arithmetic. * @retval false This C compiler's right shift operator is logical. */ static inline bool rbimpl_right_shift_is_arithmetic_p(void) { return (-1 >> 1) == -1; } RBIMPL_ATTR_CONST_UNLESS_DEBUG() RBIMPL_ATTR_CONSTEXPR_UNLESS_DEBUG(CXX14) /** * Converts a Fixnum into C's `long`. * * @param[in] x Some Fixnum. * @pre Must not pass anything other than a Fixnum. * @return The passed value converted into C's `long`. */ static inline long rb_fix2long(VALUE x) { if /* constexpr */ (rbimpl_right_shift_is_arithmetic_p()) { return rbimpl_fix2long_by_shift(x); } else { return rbimpl_fix2long_by_idiv(x); } } RBIMPL_ATTR_CONST_UNLESS_DEBUG() RBIMPL_ATTR_CONSTEXPR_UNLESS_DEBUG(CXX14) /** * Converts a Fixnum into C's `unsigned long`. * * @param[in] x Some Fixnum. * @pre Must not pass anything other than a Fixnum. * @return The passed value converted into C's `unsigned long`. * @note Negative fixnums will be converted into large unsigned longs. */ static inline unsigned long rb_fix2ulong(VALUE x) { RBIMPL_ASSERT_OR_ASSUME(RB_FIXNUM_P(x)); return rb_fix2long(x); } /** * Converts an instance of ::rb_cNumeric into C's `long`. * * @param[in] x Something numeric. * @exception rb_eTypeError `x` is not a numeric. * @exception rb_eRangeError `x` is out of range of `long`. * @return The passed value converted into C's `long`. */ static inline long rb_num2long_inline(VALUE x) { if (RB_FIXNUM_P(x)) return RB_FIX2LONG(x); else return rb_num2long(x); } /** * Converts an instance of ::rb_cNumeric into C's `unsigned long`. * * @param[in] x Something numeric. * @exception rb_eTypeError `x` is not a numeric. * @exception rb_eRangeError `x` is out of range of `unsigned long`. * @return The passed value converted into C's `unsigned long`. * * @internal * * This (negative fixnum would become a large unsigned long while negative * bignum is an exception) has been THE behaviour of NUM2ULONG since the * beginning. It is strange, but we can no longer change how it works at this * moment. We have to get by with it. * * @see https://bugs.ruby-lang.org/issues/9089 */ static inline unsigned long rb_num2ulong_inline(VALUE x) { if (RB_FIXNUM_P(x)) return RB_FIX2ULONG(x); else return rb_num2ulong(x); } /** * Converts a C's `long` into an instance of ::rb_cInteger. * * @param[in] v Arbitrary `long` value. * @return An instance of ::rb_cInteger. */ static inline VALUE rb_long2num_inline(long v) { if (RB_FIXABLE(v)) return RB_LONG2FIX(v); else return rb_int2big(v); } /** * Converts a C's `unsigned long` into an instance of ::rb_cInteger. * * @param[in] v Arbitrary `unsigned long` value. * @return An instance of ::rb_cInteger. */ static inline VALUE rb_ulong2num_inline(unsigned long v) { if (RB_POSFIXABLE(v)) return RB_LONG2FIX(v); else return rb_uint2big(v); } /** * @cond INTERNAL_MACRO * * Following overload is necessary because sometimes INT2FIX is used as a enum * value (e.g. `enum { FOO = INT2FIX(0) };`). THIS IS NG in theory because a * VALUE does not fit into an enum (which must be a signed int). But we cannot * break existing codes. */ #if RBIMPL_HAS_ATTR_CONSTEXPR_CXX14 # /* C++ can write constexpr as enum values. */ #elif ! defined(HAVE_BUILTIN___BUILTIN_CHOOSE_EXPR_CONSTANT_P) # undef INT2FIX # define INT2FIX(i) (RBIMPL_CAST((VALUE)(i)) << 1 | RUBY_FIXNUM_FLAG) #else # undef INT2FIX # define INT2FIX(i) \ __builtin_choose_expr( \ __builtin_constant_p(i), \ RBIMPL_CAST((VALUE)(i)) << 1 | RUBY_FIXNUM_FLAG, \ RB_INT2FIX(i)) #endif /** @endcond */ #endif /* RBIMPL_ARITHMETIC_LONG_H */ include/ruby/internal/arithmetic/mode_t.h 0000644 00000003546 15152150476 0014553 0 ustar 00 #ifndef RBIMPL_ARITHMETIC_MODE_T_H /*-*-C++-*-vi:se ft=cpp:*/ #define RBIMPL_ARITHMETIC_MODE_T_H /** * @file * @author Ruby developers <ruby-core@ruby-lang.org> * @copyright This file is a part of the programming language Ruby. * Permission is hereby granted, to either redistribute and/or * modify this file, provided that the conditions mentioned in the * file COPYING are met. Consult the file for details. * @warning Symbols prefixed with either `RBIMPL` or `rbimpl` are * implementation details. Don't take them as canon. They could * rapidly appear then vanish. The name (path) of this header file * is also an implementation detail. Do not expect it to persist * at the place it is now. Developers are free to move it anywhere * anytime at will. * @note To ruby-core: remember that this header can be possibly * recursively included from extension libraries written in C++. * Do not expect for instance `__VA_ARGS__` is always available. * We assume C99 for ruby itself but we don't assume languages of * extension libraries. They could be written in C++98. * @brief Arithmetic conversion between C's `mode_t` and Ruby's. */ #include "ruby/internal/config.h" #include "ruby/internal/arithmetic/int.h" /** Converts a C's `mode_t` into an instance of ::rb_cInteger. */ #ifndef NUM2MODET # define NUM2MODET RB_NUM2INT #endif /** Converts an instance of ::rb_cNumeric into C's `mode_t`. */ #ifndef MODET2NUM # define MODET2NUM RB_INT2NUM #endif /** A rb_sprintf() format prefix to be used for a `mode_t` parameter. */ #ifndef PRI_MODET_PREFIX # define PRI_MODET_PREFIX PRI_INT_PREFIX #endif #endif /* RBIMPL_ARITHMETIC_MODE_T_H */ include/ruby/internal/arithmetic/char.h 0000644 00000006453 15152150476 0014221 0 ustar 00 #ifndef RBIMPL_ARITHMETIC_CHAR_H /*-*-C++-*-vi:se ft=cpp:*/ #define RBIMPL_ARITHMETIC_CHAR_H /** * @file * @author Ruby developers <ruby-core@ruby-lang.org> * @copyright This file is a part of the programming language Ruby. * Permission is hereby granted, to either redistribute and/or * modify this file, provided that the conditions mentioned in the * file COPYING are met. Consult the file for details. * @warning Symbols prefixed with either `RBIMPL` or `rbimpl` are * implementation details. Don't take them as canon. They could * rapidly appear then vanish. The name (path) of this header file * is also an implementation detail. Do not expect it to persist * at the place it is now. Developers are free to move it anywhere * anytime at will. * @note To ruby-core: remember that this header can be possibly * recursively included from extension libraries written in C++. * Do not expect for instance `__VA_ARGS__` is always available. * We assume C99 for ruby itself but we don't assume languages of * extension libraries. They could be written in C++98. * @brief Arithmetic conversion between C's `char` and Ruby's. */ #include "ruby/internal/arithmetic/int.h" /* NUM2INT is here, but */ #include "ruby/internal/arithmetic/long.h" /* INT2FIX is here.*/ #include "ruby/internal/attr/artificial.h" #include "ruby/internal/attr/const.h" #include "ruby/internal/attr/constexpr.h" #include "ruby/internal/cast.h" #include "ruby/internal/core/rstring.h" #include "ruby/internal/value_type.h" #define RB_NUM2CHR rb_num2char_inline /**< @alias{rb_num2char_inline} */ #define NUM2CHR RB_NUM2CHR /**< @old{RB_NUM2CHR} */ #define CHR2FIX RB_CHR2FIX /**< @old{RB_CHR2FIX} */ /** @cond INTERNAL_MACRO */ #define RB_CHR2FIX RB_CHR2FIX /** @endcond */ RBIMPL_ATTR_CONST_UNLESS_DEBUG() RBIMPL_ATTR_CONSTEXPR_UNLESS_DEBUG(CXX14) RBIMPL_ATTR_ARTIFICIAL() /** * Converts a C's `unsigned char` into an instance of ::rb_cInteger. * * @param[in] c Arbitrary `unsigned char` value. * @return An instance of ::rb_cInteger. * * @internal * * Nobody explicitly states this but in Ruby, a char means an unsigned integer * value of range 0..255. This is a general principle. AFAIK there is no * single line of code where char is signed. */ static inline VALUE RB_CHR2FIX(unsigned char c) { return RB_INT2FIX(c); } /** * Converts an instance of ::rb_cNumeric into C's `char`. At the same time it * accepts a String of more than one character, and returns its first byte. In * the early days there was a Ruby level "character" literal `?c`, which * roughly worked this way. * * @param[in] x Either a string or a numeric. * @exception rb_eTypeError `x` is not a numeric. * @exception rb_eRangeError `x` is out of range of `unsigned int`. * @return The passed value converted into C's `char`. */ static inline char rb_num2char_inline(VALUE x) { if (RB_TYPE_P(x, RUBY_T_STRING) && (RSTRING_LEN(x)>=1)) return RSTRING_PTR(x)[0]; else return RBIMPL_CAST((char)RB_NUM2INT(x)); } #endif /* RBIMPL_ARITHMETIC_CHAR_H */ include/ruby/internal/arithmetic/intptr_t.h 0000644 00000005421 15152150476 0015141 0 ustar 00 #ifndef RBIMPL_ARITHMETIC_INTPTR_T_H /*-*-C++-*-vi:se ft=cpp:*/ #define RBIMPL_ARITHMETIC_INTPTR_T_H /** * @file * @author Ruby developers <ruby-core@ruby-lang.org> * @copyright This file is a part of the programming language Ruby. * Permission is hereby granted, to either redistribute and/or * modify this file, provided that the conditions mentioned in the * file COPYING are met. Consult the file for details. * @warning Symbols prefixed with either `RBIMPL` or `rbimpl` are * implementation details. Don't take them as canon. They could * rapidly appear then vanish. The name (path) of this header file * is also an implementation detail. Do not expect it to persist * at the place it is now. Developers are free to move it anywhere * anytime at will. * @note To ruby-core: remember that this header can be possibly * recursively included from extension libraries written in C++. * Do not expect for instance `__VA_ARGS__` is always available. * We assume C99 for ruby itself but we don't assume languages of * extension libraries. They could be written in C++98. * @brief Arithmetic conversion between C's `intptr_t` and Ruby's. */ #include "ruby/internal/config.h" #ifdef HAVE_STDINT_H # include <stdint.h> #endif #include "ruby/internal/value.h" #include "ruby/internal/dllexport.h" #define rb_int_new rb_int2inum /**< @alias{rb_int2inum} */ #define rb_uint_new rb_uint2inum /**< @alias{rb_uint2inum} */ RBIMPL_SYMBOL_EXPORT_BEGIN() /** * Converts a C's `intptr_t` into an instance of ::rb_cInteger. * * @param[in] i Arbitrary `intptr_t` value. * @return An instance of ::rb_cInteger. * @note This function always allocates Bignums, even if the given number * is small enough to fit into a Fixnum. */ VALUE rb_int2big(intptr_t i); /** * Converts a C's `intptr_t` into an instance of ::rb_cInteger. * * @param[in] i Arbitrary `intptr_t` value. * @return An instance of ::rb_cInteger. */ VALUE rb_int2inum(intptr_t i); /** * Converts a C's `intptr_t` into an instance of ::rb_cInteger. * * @param[in] i Arbitrary `intptr_t` value. * @return An instance of ::rb_cInteger. * @note This function always allocates Bignums, even if the given number * is small enough to fit into a Fixnum. */ VALUE rb_uint2big(uintptr_t i); /** * Converts a C's `uintptr_t` into an instance of ::rb_cInteger. * * @param[in] i Arbitrary `uintptr_t` value. * @return An instance of ::rb_cInteger. */ VALUE rb_uint2inum(uintptr_t i); RBIMPL_SYMBOL_EXPORT_END() #endif /* RBIMPL_ARITHMETIC_INTPTR_T_H */ include/ruby/internal/arithmetic/fixnum.h 0000644 00000005573 15152150476 0014614 0 ustar 00 #ifndef RBIMPL_ARITHMETIC_FIXNUM_H /*-*-C++-*-vi:se ft=cpp:*/ #define RBIMPL_ARITHMETIC_FIXNUM_H /** * @file * @author Ruby developers <ruby-core@ruby-lang.org> * @copyright This file is a part of the programming language Ruby. * Permission is hereby granted, to either redistribute and/or * modify this file, provided that the conditions mentioned in the * file COPYING are met. Consult the file for details. * @warning Symbols prefixed with either `RBIMPL` or `rbimpl` are * implementation details. Don't take them as canon. They could * rapidly appear then vanish. The name (path) of this header file * is also an implementation detail. Do not expect it to persist * at the place it is now. Developers are free to move it anywhere * anytime at will. * @note To ruby-core: remember that this header can be possibly * recursively included from extension libraries written in C++. * Do not expect for instance `__VA_ARGS__` is always available. * We assume C99 for ruby itself but we don't assume languages of * extension libraries. They could be written in C++98. * @brief Handling of integers formerly known as Fixnums. */ #include "ruby/backward/2/limits.h" #define FIXABLE RB_FIXABLE /**< @old{RB_FIXABLE} */ #define FIXNUM_MAX RUBY_FIXNUM_MAX /**< @old{RUBY_FIXNUM_MAX} */ #define FIXNUM_MIN RUBY_FIXNUM_MIN /**< @old{RUBY_FIXNUM_MIN} */ #define NEGFIXABLE RB_NEGFIXABLE /**< @old{RB_NEGFIXABLE} */ #define POSFIXABLE RB_POSFIXABLE /**< @old{RB_POSFIXABLE} */ /** * Checks if the passed value is in range of fixnum, assuming it is a positive * number. Can sometimes be useful for C's unsigned integer types. * * @internal * * FIXABLE can be applied to anything, from double to intmax_t. The problem is * double. On a 64bit system RUBY_FIXNUM_MAX is 4,611,686,018,427,387,903, * which is not representable by a double. The nearest value that a double can * represent is 4,611,686,018,427,387,904, which is not fixable. The * seemingly-strange "< FIXNUM_MAX + 1" expression below is due to this. */ #define RB_POSFIXABLE(_) ((_) < RUBY_FIXNUM_MAX + 1) /** * Checks if the passed value is in range of fixnum, assuming it is a negative * number. This is an implementation of #RB_FIXABLE. Rarely used stand alone. */ #define RB_NEGFIXABLE(_) ((_) >= RUBY_FIXNUM_MIN) /** Checks if the passed value is in range of fixnum */ #define RB_FIXABLE(_) (RB_POSFIXABLE(_) && RB_NEGFIXABLE(_)) /** Maximum possible value that a fixnum can represent. */ #define RUBY_FIXNUM_MAX (LONG_MAX / 2) /** Minimum possible value that a fixnum can represent. */ #define RUBY_FIXNUM_MIN (LONG_MIN / 2) #endif /* RBIMPL_ARITHMETIC_FIXNUM_H */ include/ruby/internal/arithmetic/uid_t.h 0000644 00000003536 15152150476 0014407 0 ustar 00 #ifndef RBIMPL_ARITHMETIC_UID_T_H /*-*-C++-*-vi:se ft=cpp:*/ #define RBIMPL_ARITHMETIC_UID_T_H /** * @file * @author Ruby developers <ruby-core@ruby-lang.org> * @copyright This file is a part of the programming language Ruby. * Permission is hereby granted, to either redistribute and/or * modify this file, provided that the conditions mentioned in the * file COPYING are met. Consult the file for details. * @warning Symbols prefixed with either `RBIMPL` or `rbimpl` are * implementation details. Don't take them as canon. They could * rapidly appear then vanish. The name (path) of this header file * is also an implementation detail. Do not expect it to persist * at the place it is now. Developers are free to move it anywhere * anytime at will. * @note To ruby-core: remember that this header can be possibly * recursively included from extension libraries written in C++. * Do not expect for instance `__VA_ARGS__` is always available. * We assume C99 for ruby itself but we don't assume languages of * extension libraries. They could be written in C++98. * @brief Arithmetic conversion between C's `uid_t` and Ruby's. */ #include "ruby/internal/config.h" #include "ruby/internal/arithmetic/long.h" /** Converts a C's `uid_t` into an instance of ::rb_cInteger. */ #ifndef UIDT2NUM # define UIDT2NUM RB_LONG2NUM #endif /** Converts an instance of ::rb_cNumeric into C's `uid_t`. */ #ifndef NUM2UIDT # define NUM2UIDT RB_NUM2LONG #endif /** A rb_sprintf() format prefix to be used for a `uid_t` parameter. */ #ifndef PRI_UIDT_PREFIX # define PRI_UIDT_PREFIX PRI_LONG_PREFIX #endif #endif /* RBIMPL_ARITHMETIC_UID_T_H */ include/ruby/internal/arithmetic/gid_t.h 0000644 00000003536 15152150476 0014371 0 ustar 00 #ifndef RBIMPL_ARITHMETIC_GID_T_H /*-*-C++-*-vi:se ft=cpp:*/ #define RBIMPL_ARITHMETIC_GID_T_H /** * @file * @author Ruby developers <ruby-core@ruby-lang.org> * @copyright This file is a part of the programming language Ruby. * Permission is hereby granted, to either redistribute and/or * modify this file, provided that the conditions mentioned in the * file COPYING are met. Consult the file for details. * @warning Symbols prefixed with either `RBIMPL` or `rbimpl` are * implementation details. Don't take them as canon. They could * rapidly appear then vanish. The name (path) of this header file * is also an implementation detail. Do not expect it to persist * at the place it is now. Developers are free to move it anywhere * anytime at will. * @note To ruby-core: remember that this header can be possibly * recursively included from extension libraries written in C++. * Do not expect for instance `__VA_ARGS__` is always available. * We assume C99 for ruby itself but we don't assume languages of * extension libraries. They could be written in C++98. * @brief Arithmetic conversion between C's `gid_t` and Ruby's. */ #include "ruby/internal/config.h" #include "ruby/internal/arithmetic/long.h" /** Converts a C's `gid_t` into an instance of ::rb_cInteger. */ #ifndef GIDT2NUM # define GIDT2NUM RB_LONG2NUM #endif /** Converts an instance of ::rb_cNumeric into C's `gid_t`. */ #ifndef NUM2GIDT # define NUM2GIDT RB_NUM2LONG #endif /** A rb_sprintf() format prefix to be used for a `gid_t` parameter. */ #ifndef PRI_GIDT_PREFIX # define PRI_GIDT_PREFIX PRI_LONG_PREFIX #endif #endif /* RBIMPL_ARITHMETIC_GID_T_H */ include/ruby/internal/arithmetic/long_long.h 0000644 00000011463 15152150476 0015257 0 ustar 00 #ifndef RBIMPL_ARITHMETIC_LONG_LONG_H /*-*-C++-*-vi:se ft=cpp:*/ #define RBIMPL_ARITHMETIC_LONG_LONG_H /** * @file * @author Ruby developers <ruby-core@ruby-lang.org> * @copyright This file is a part of the programming language Ruby. * Permission is hereby granted, to either redistribute and/or * modify this file, provided that the conditions mentioned in the * file COPYING are met. Consult the file for details. * @warning Symbols prefixed with either `RBIMPL` or `rbimpl` are * implementation details. Don't take them as canon. They could * rapidly appear then vanish. The name (path) of this header file * is also an implementation detail. Do not expect it to persist * at the place it is now. Developers are free to move it anywhere * anytime at will. * @note To ruby-core: remember that this header can be possibly * recursively included from extension libraries written in C++. * Do not expect for instance `__VA_ARGS__` is always available. * We assume C99 for ruby itself but we don't assume languages of * extension libraries. They could be written in C++98. * @brief Arithmetic conversion between C's `long long` and Ruby's. */ #include "ruby/internal/value.h" #include "ruby/internal/dllexport.h" #include "ruby/internal/special_consts.h" #include "ruby/backward/2/long_long.h" #define RB_LL2NUM rb_ll2num_inline /**< @alias{rb_ll2num_inline} */ #define RB_ULL2NUM rb_ull2num_inline /**< @alias{rb_ull2num_inline} */ #define LL2NUM RB_LL2NUM /**< @old{RB_LL2NUM} */ #define ULL2NUM RB_ULL2NUM /**< @old{RB_ULL2NUM} */ #define RB_NUM2LL rb_num2ll_inline /**< @alias{rb_num2ll_inline} */ #define RB_NUM2ULL rb_num2ull_inline /**< @alias{rb_num2ull_inline} */ #define NUM2LL RB_NUM2LL /**< @old{RB_NUM2LL} */ #define NUM2ULL RB_NUM2ULL /**< @old{RB_NUM2ULL} */ RBIMPL_SYMBOL_EXPORT_BEGIN() /** * Converts a C's `long long` into an instance of ::rb_cInteger. * * @param[in] num Arbitrary `long long` value. * @return An instance of ::rb_cInteger. */ VALUE rb_ll2inum(LONG_LONG num); /** * Converts a C's `unsigned long long` into an instance of ::rb_cInteger. * * @param[in] num Arbitrary `unsigned long long` value. * @return An instance of ::rb_cInteger. */ VALUE rb_ull2inum(unsigned LONG_LONG num); /** * Converts an instance of ::rb_cNumeric into C's `long long`. * * @param[in] num Something numeric. * @exception rb_eTypeError `num` is not a numeric. * @exception rb_eRangeError `num` is out of range of `long long`. * @return The passed value converted into C's `long long`. */ LONG_LONG rb_num2ll(VALUE num); /** * Converts an instance of ::rb_cNumeric into C's `unsigned long long`. * * @param[in] num Something numeric. * @exception rb_eTypeError `num` is not a numeric. * @exception rb_eRangeError `num` is out of range of `unsigned long long`. * @return The passed value converted into C's `unsigned long long`. */ unsigned LONG_LONG rb_num2ull(VALUE num); RBIMPL_SYMBOL_EXPORT_END() /** * Converts a C's `long long` into an instance of ::rb_cInteger. * * @param[in] n Arbitrary `long long` value. * @return An instance of ::rb_cInteger */ static inline VALUE rb_ll2num_inline(LONG_LONG n) { if (FIXABLE(n)) return LONG2FIX((long)n); return rb_ll2inum(n); } /** * Converts a C's `unsigned long long` into an instance of ::rb_cInteger. * * @param[in] n Arbitrary `unsigned long long` value. * @return An instance of ::rb_cInteger */ static inline VALUE rb_ull2num_inline(unsigned LONG_LONG n) { if (POSFIXABLE(n)) return LONG2FIX((long)n); return rb_ull2inum(n); } /** * Converts an instance of ::rb_cNumeric into C's `long long`. * * @param[in] x Something numeric. * @exception rb_eTypeError `x` is not a numeric. * @exception rb_eRangeError `x` is out of range of `long long`. * @return The passed value converted into C's `long long`. */ static inline LONG_LONG rb_num2ll_inline(VALUE x) { if (RB_FIXNUM_P(x)) return RB_FIX2LONG(x); else return rb_num2ll(x); } /** * Converts an instance of ::rb_cNumeric into C's `unsigned long long`. * * @param[in] x Something numeric. * @exception rb_eTypeError `x` is not a numeric. * @exception rb_eRangeError `x` is out of range of `unsigned long long`. * @return The passed value converted into C's `unsigned long long`. */ static inline unsigned LONG_LONG rb_num2ull_inline(VALUE x) { if (RB_FIXNUM_P(x)) return RB_FIX2LONG(x); else return rb_num2ull(x); } #endif /* RBIMPL_ARITHMETIC_LONG_LONG_H */ include/ruby/internal/arithmetic/short.h 0000644 00000010523 15152150476 0014434 0 ustar 00 #ifndef RBIMPL_ARITHMETIC_SHORT_H /*-*-C++-*-vi:se ft=cpp:*/ #define RBIMPL_ARITHMETIC_SHORT_H /** * @file * @author Ruby developers <ruby-core@ruby-lang.org> * @copyright This file is a part of the programming language Ruby. * Permission is hereby granted, to either redistribute and/or * modify this file, provided that the conditions mentioned in the * file COPYING are met. Consult the file for details. * @warning Symbols prefixed with either `RBIMPL` or `rbimpl` are * implementation details. Don't take them as canon. They could * rapidly appear then vanish. The name (path) of this header file * is also an implementation detail. Do not expect it to persist * at the place it is now. Developers are free to move it anywhere * anytime at will. * @note To ruby-core: remember that this header can be possibly * recursively included from extension libraries written in C++. * Do not expect for instance `__VA_ARGS__` is always available. * We assume C99 for ruby itself but we don't assume languages of * extension libraries. They could be written in C++98. * @brief Arithmetic conversion between C's `short` and Ruby's. * * Shyouhei wonders: why there is no SHORT2NUM, given there are both * #USHORT2NUM and #CHR2FIX? */ #include "ruby/internal/value.h" #include "ruby/internal/dllexport.h" #include "ruby/internal/special_consts.h" #define RB_NUM2SHORT rb_num2short_inline /**< @alias{rb_num2short_inline} */ #define RB_NUM2USHORT rb_num2ushort /**< @alias{rb_num2ushort} */ #define NUM2SHORT RB_NUM2SHORT /**< @old{RB_NUM2SHORT} */ #define NUM2USHORT RB_NUM2USHORT /**< @old{RB_NUM2USHORT} */ #define USHORT2NUM RB_INT2FIX /**< @old{RB_INT2FIX} */ #define RB_FIX2SHORT rb_fix2short /**< @alias{rb_fix2ushort} */ #define FIX2SHORT RB_FIX2SHORT /**< @old{RB_FIX2SHORT} */ RBIMPL_SYMBOL_EXPORT_BEGIN() /** * Converts an instance of ::rb_cNumeric into C's `short`. * * @param[in] num Something numeric. * @exception rb_eTypeError `num` is not a numeric. * @exception rb_eRangeError `num` is out of range of `short`. * @return The passed value converted into C's `short`. */ short rb_num2short(VALUE num); /** * Converts an instance of ::rb_cNumeric into C's `unsigned short`. * * @param[in] num Something numeric. * @exception rb_eTypeError `num` is not a numeric. * @exception rb_eRangeError `num` is out of range of `unsigned short`. * @return The passed value converted into C's `unsigned short`. */ unsigned short rb_num2ushort(VALUE num); /** * Identical to rb_num2short(). * * @param[in] num Something numeric. * @exception rb_eTypeError `num` is not a numeric. * @exception rb_eRangeError `num` is out of range of `short`. * @return The passed value converted into C's `short`. * * @internal * * This function seems to be a complete waste of disk space. @shyouhei has no * idea why this is a different thing from rb_num2short(). */ short rb_fix2short(VALUE num); /** * Identical to rb_num2ushort(). * * @param[in] num Something numeric. * @exception rb_eTypeError `num` is not a numeric. * @exception rb_eRangeError `num` is out of range of `unsigned short`. * @return The passed value converted into C's `unsigned short`. * * @internal * * This function seems to be a complete waste of disk space. @shyouhei has no * idea why this is a different thing from rb_num2ushort(). */ unsigned short rb_fix2ushort(VALUE num); RBIMPL_SYMBOL_EXPORT_END() /** * Identical to rb_num2short(). * * @param[in] x Something numeric. * @exception rb_eTypeError `x` is not a numeric. * @exception rb_eRangeError `x` is out of range of `short`. * @return The passed value converted into C's `short`. * * @internal * * This function seems to be a complete waste of time. @shyouhei has no idea * why this is a different thing from rb_num2short(). */ static inline short rb_num2short_inline(VALUE x) { if (RB_FIXNUM_P(x)) return rb_fix2short(x); else return rb_num2short(x); } #endif /* RBIMPL_ARITHMETIC_SHORT_H */ include/ruby/internal/arithmetic/double.h 0000644 00000005366 15152150476 0014560 0 ustar 00 #ifndef RBIMPL_ARITHMETIC_DOUBLE_H /*-*-C++-*-vi:se ft=cpp:*/ #define RBIMPL_ARITHMETIC_DOUBLE_H /** * @file * @author Ruby developers <ruby-core@ruby-lang.org> * @copyright This file is a part of the programming language Ruby. * Permission is hereby granted, to either redistribute and/or * modify this file, provided that the conditions mentioned in the * file COPYING are met. Consult the file for details. * @warning Symbols prefixed with either `RBIMPL` or `rbimpl` are * implementation details. Don't take them as canon. They could * rapidly appear then vanish. The name (path) of this header file * is also an implementation detail. Do not expect it to persist * at the place it is now. Developers are free to move it anywhere * anytime at will. * @note To ruby-core: remember that this header can be possibly * recursively included from extension libraries written in C++. * Do not expect for instance `__VA_ARGS__` is always available. * We assume C99 for ruby itself but we don't assume languages of * extension libraries. They could be written in C++98. * @brief Arithmetic conversion between C's `double` and Ruby's. */ #include "ruby/internal/attr/pure.h" #include "ruby/internal/dllexport.h" #include "ruby/internal/value.h" #define NUM2DBL rb_num2dbl /**< @old{rb_num2dbl} */ #define RFLOAT_VALUE rb_float_value /**< @old{rb_float_value} */ #define DBL2NUM rb_float_new /**< @old{rb_float_new} */ RBIMPL_SYMBOL_EXPORT_BEGIN() /** * Converts an instance of ::rb_cNumeric into C's `double`. * * @param[in] num Something numeric. * @exception rb_eTypeError `num` is not a numeric. * @return The passed value converted into C's `double`. */ double rb_num2dbl(VALUE num); RBIMPL_ATTR_PURE() /** * Extracts its double value from an instance of ::rb_cFloat. * * @param[in] num An instance of ::rb_cFloat. * @pre Must not pass anything other than a Fixnum. * @return The passed value converted into C's `double`. */ double rb_float_value(VALUE num); /** * Converts a C's `double` into an instance of ::rb_cFloat. * * @param[in] d Arbitrary `double` value. * @return An instance of ::rb_cFloat. */ VALUE rb_float_new(double d); /** * Identical to rb_float_new(), except it does not generate Flonums. * * @param[in] d Arbitrary `double` value. * @return An instance of ::rb_cFloat. * * @internal * * @shyouhei has no idea why it is here. */ VALUE rb_float_new_in_heap(double d); RBIMPL_SYMBOL_EXPORT_END() #endif /* RBIMPL_ARITHMETIC_DOUBLE_H */ include/ruby/internal/arithmetic/pid_t.h 0000644 00000003536 15152150476 0014402 0 ustar 00 #ifndef RBIMPL_ARITHMETIC_PID_T_H /*-*-C++-*-vi:se ft=cpp:*/ #define RBIMPL_ARITHMETIC_PID_T_H /** * @file * @author Ruby developers <ruby-core@ruby-lang.org> * @copyright This file is a part of the programming language Ruby. * Permission is hereby granted, to either redistribute and/or * modify this file, provided that the conditions mentioned in the * file COPYING are met. Consult the file for details. * @warning Symbols prefixed with either `RBIMPL` or `rbimpl` are * implementation details. Don't take them as canon. They could * rapidly appear then vanish. The name (path) of this header file * is also an implementation detail. Do not expect it to persist * at the place it is now. Developers are free to move it anywhere * anytime at will. * @note To ruby-core: remember that this header can be possibly * recursively included from extension libraries written in C++. * Do not expect for instance `__VA_ARGS__` is always available. * We assume C99 for ruby itself but we don't assume languages of * extension libraries. They could be written in C++98. * @brief Arithmetic conversion between C's `pid_t` and Ruby's. */ #include "ruby/internal/config.h" #include "ruby/internal/arithmetic/long.h" /** Converts a C's `pid_t` into an instance of ::rb_cInteger. */ #ifndef PIDT2NUM # define PIDT2NUM RB_LONG2NUM #endif /** Converts an instance of ::rb_cNumeric into C's `pid_t`. */ #ifndef NUM2PIDT # define NUM2PIDT RB_NUM2LONG #endif /** A rb_sprintf() format prefix to be used for a `pid_t` parameter. */ #ifndef PRI_PIDT_PREFIX # define PRI_PIDT_PREFIX PRI_LONG_PREFIX #endif #endif /* RBIMPL_ARITHMETIC_PID_T_H */ include/ruby/internal/arithmetic/int.h 0000644 00000020062 15152150477 0014067 0 ustar 00 #ifndef RBIMPL_ARITHMETIC_INT_H /*-*-C++-*-vi:se ft=cpp:*/ #define RBIMPL_ARITHMETIC_INT_H /** * @file * @author Ruby developers <ruby-core@ruby-lang.org> * @copyright This file is a part of the programming language Ruby. * Permission is hereby granted, to either redistribute and/or * modify this file, provided that the conditions mentioned in the * file COPYING are met. Consult the file for details. * @warning Symbols prefixed with either `RBIMPL` or `rbimpl` are * implementation details. Don't take them as canon. They could * rapidly appear then vanish. The name (path) of this header file * is also an implementation detail. Do not expect it to persist * at the place it is now. Developers are free to move it anywhere * anytime at will. * @note To ruby-core: remember that this header can be possibly * recursively included from extension libraries written in C++. * Do not expect for instance `__VA_ARGS__` is always available. * We assume C99 for ruby itself but we don't assume languages of * extension libraries. They could be written in C++98. * @brief Arithmetic conversion between C's `int` and Ruby's. */ #include "ruby/internal/config.h" #include "ruby/internal/arithmetic/fixnum.h" #include "ruby/internal/arithmetic/intptr_t.h" #include "ruby/internal/arithmetic/long.h" #include "ruby/internal/attr/artificial.h" #include "ruby/internal/attr/const.h" #include "ruby/internal/attr/constexpr.h" #include "ruby/internal/compiler_is.h" #include "ruby/internal/dllexport.h" #include "ruby/internal/special_consts.h" #include "ruby/internal/value.h" #include "ruby/internal/warning_push.h" #include "ruby/assert.h" #define RB_INT2NUM rb_int2num_inline /**< @alias{rb_int2num_inline} */ #define RB_NUM2INT rb_num2int_inline /**< @alias{rb_num2int_inline} */ #define RB_UINT2NUM rb_uint2num_inline /**< @alias{rb_uint2num_inline} */ #define FIX2INT RB_FIX2INT /**< @old{RB_FIX2INT} */ #define FIX2UINT RB_FIX2UINT /**< @old{RB_FIX2UINT} */ #define INT2NUM RB_INT2NUM /**< @old{RB_INT2NUM} */ #define NUM2INT RB_NUM2INT /**< @old{RB_NUM2INT} */ #define NUM2UINT RB_NUM2UINT /**< @old{RB_NUM2UINT} */ #define UINT2NUM RB_UINT2NUM /**< @old{RB_UINT2NUM} */ /** @cond INTERNAL_MACRO */ #define RB_FIX2INT RB_FIX2INT #define RB_NUM2UINT RB_NUM2UINT #define RB_FIX2UINT RB_FIX2UINT /** @endcond */ RBIMPL_SYMBOL_EXPORT_BEGIN() /** * Converts an instance of ::rb_cNumeric into C's `long`. * * @param[in] num Something numeric. * @exception rb_eTypeError `num` is not a numeric. * @exception rb_eRangeError `num` is out of range of `int`. * @return The passed value converted into C's `long`. * * @internal * * Yes, the API is really strange. It returns `long`, but raises when the * value is out of `int`. This seems to be due to the fact that Matz favoured * K&R before, and his machine at that moment was an ILP32 architecture. */ long rb_num2int(VALUE num); /** * Identical to rb_num2int(). * * @param[in] num Something numeric. * @exception rb_eTypeError `num` is not a numeric. * @exception rb_eRangeError `num` is out of range of `int`. * @return The passed value converted into C's `long`. * * @internal * * This function seems to be a complete waste of disk space. @shyouhei has no * idea why this is a different thing from rb_num2short(). */ long rb_fix2int(VALUE num); /** * Converts an instance of ::rb_cNumeric into C's `unsigned long`. * * @param[in] num Something numeric. * @exception rb_eTypeError `num` is not a numeric. * @exception rb_eRangeError `num` is out of range of `unsigned int`. * @return The passed value converted into C's `unsigned long`. * * @internal * * Yes, the API is really strange. It returns `unsigned long`, but raises when * the value is out of `unsigned int`. This seems to be due to the fact that * Matz favoured K&R before, and his machine at that moment was an ILP32 * architecture. */ unsigned long rb_num2uint(VALUE num); /** * Identical to rb_num2uint(). * * @param[in] num Something numeric. * @exception rb_eTypeError `num` is not a numeric. * @exception rb_eRangeError `num` is out of range of `unsigned int`. * @return The passed value converted into C's `unsigned long`. * * @internal * * This function seems to be a complete waste of disk space. @shyouhei has no * idea why this is a different thing from rb_num2short(). */ unsigned long rb_fix2uint(VALUE num); RBIMPL_SYMBOL_EXPORT_END() RBIMPL_ATTR_ARTIFICIAL() /** * Converts a Fixnum into C's `int`. * * @param[in] x Some Fixnum. * @pre Must not pass anything other than a Fixnum. * @return The passed value converted into C's `int`. */ static inline int RB_FIX2INT(VALUE x) { /* "FIX2INT raises a TypeError if passed nil", says rubyspec. Not sure if * that is a desired behaviour but just preserve backwards compatilibily. */ #if 0 RBIMPL_ASSERT_OR_ASSUME(RB_FIXNUM_P(x)); #endif long ret; if /* constexpr */ (sizeof(int) < sizeof(long)) { ret = rb_fix2int(x); } else { ret = RB_FIX2LONG(x); } return RBIMPL_CAST((int)ret); } /** * Converts an instance of ::rb_cNumeric into C's `int`. * * @param[in] x Something numeric. * @exception rb_eTypeError `x` is not a numeric. * @exception rb_eRangeError `x` is out of range of `int`. * @return The passed value converted into C's `int`. */ static inline int rb_num2int_inline(VALUE x) { long ret; if /* constexpr */ (sizeof(int) == sizeof(long)) { ret = RB_NUM2LONG(x); } else if (RB_FIXNUM_P(x)) { ret = rb_fix2int(x); } else { ret = rb_num2int(x); } return RBIMPL_CAST((int)ret); } /** * Converts an instance of ::rb_cNumeric into C's `unsigned int`. * * @param[in] x Something numeric. * @exception rb_eTypeError `x` is not a numeric. * @exception rb_eRangeError `x` is out of range of `unsigned int`. * @return The passed value converted into C's `unsigned int`. */ RBIMPL_ATTR_ARTIFICIAL() static inline unsigned int RB_NUM2UINT(VALUE x) { unsigned long ret; if /* constexpr */ (sizeof(int) < sizeof(long)) { ret = rb_num2uint(x); } else { ret = RB_NUM2ULONG(x); } return RBIMPL_CAST((unsigned int)ret); } RBIMPL_ATTR_ARTIFICIAL() /** * Converts a Fixnum into C's `int`. * * @param[in] x Some Fixnum. * @pre Must not pass anything other than a Fixnum. * @return The passed value converted into C's `int`. */ static inline unsigned int RB_FIX2UINT(VALUE x) { #if 0 /* Ditto for RB_FIX2INT. */ RBIMPL_ASSERT_OR_ASSUME(RB_FIXNUM_P(x)); #endif unsigned long ret; if /* constexpr */ (sizeof(int) < sizeof(long)) { ret = rb_fix2uint(x); } else { ret = RB_FIX2ULONG(x); } return RBIMPL_CAST((unsigned int)ret); } RBIMPL_WARNING_PUSH() #if RBIMPL_COMPILER_IS(GCC) RBIMPL_WARNING_IGNORED(-Wtype-limits) /* We can ignore them here. */ #elif RBIMPL_HAS_WARNING("-Wtautological-constant-out-of-range-compare") RBIMPL_WARNING_IGNORED(-Wtautological-constant-out-of-range-compare) #endif /** * Converts a C's `int` into an instance of ::rb_cInteger. * * @param[in] v Arbitrary `int` value. * @return An instance of ::rb_cInteger. */ static inline VALUE rb_int2num_inline(int v) { if (RB_FIXABLE(v)) return RB_INT2FIX(v); else return rb_int2big(v); } /** * Converts a C's `unsigned int` into an instance of ::rb_cInteger. * * @param[in] v Arbitrary `unsigned int` value. * @return An instance of ::rb_cInteger. */ static inline VALUE rb_uint2num_inline(unsigned int v) { if (RB_POSFIXABLE(v)) return RB_LONG2FIX(v); else return rb_uint2big(v); } RBIMPL_WARNING_POP() #endif /* RBIMPL_ARITHMETIC_INT_H */ include/ruby/internal/scan_args.h 0000644 00000044751 15152150477 0013117 0 ustar 00 #ifndef RBIMPL_SCAN_ARGS_H /*-*-C++-*-vi:se ft=cpp:*/ #define RBIMPL_SCAN_ARGS_H /** * @file * @author Ruby developers <ruby-core@ruby-lang.org> * @copyright This file is a part of the programming language Ruby. * Permission is hereby granted, to either redistribute and/or * modify this file, provided that the conditions mentioned in the * file COPYING are met. Consult the file for details. * @warning Symbols prefixed with either `RBIMPL` or `rbimpl` are * implementation details. Don't take them as canon. They could * rapidly appear then vanish. The name (path) of this header file * is also an implementation detail. Do not expect it to persist * at the place it is now. Developers are free to move it anywhere * anytime at will. * @note To ruby-core: remember that this header can be possibly * recursively included from extension libraries written in C++. * Do not expect for instance `__VA_ARGS__` is always available. * We assume C99 for ruby itself but we don't assume languages of * extension libraries. They could be written in C++98. * @brief Compile-time static implementation of ::rb_scan_args(). * * This is a beast. It statically analyses the argument spec string, and * expands the assignment of variables into dedicated codes. */ #include "ruby/assert.h" #include "ruby/internal/attr/diagnose_if.h" #include "ruby/internal/attr/error.h" #include "ruby/internal/attr/forceinline.h" #include "ruby/internal/attr/nonnull.h" #include "ruby/internal/attr/noreturn.h" #include "ruby/internal/config.h" #include "ruby/internal/dllexport.h" #include "ruby/internal/has/attribute.h" #include "ruby/internal/intern/array.h" /* rb_ary_new_from_values */ #include "ruby/internal/intern/error.h" /* rb_error_arity */ #include "ruby/internal/intern/hash.h" /* rb_hash_dup */ #include "ruby/internal/intern/proc.h" /* rb_block_proc */ #include "ruby/internal/iterator.h" /* rb_block_given_p / rb_keyword_given_p */ #include "ruby/internal/static_assert.h" #include "ruby/internal/stdbool.h" #include "ruby/internal/value.h" /** * @name Possible values that you should pass to rb_scan_args_kw(). * @{ */ /** Same behaviour as rb_scan_args(). */ #define RB_SCAN_ARGS_PASS_CALLED_KEYWORDS 0 /** The final argument should be a hash treated as keywords.*/ #define RB_SCAN_ARGS_KEYWORDS 1 /** * Treat a final argument as keywords if it is a hash, and not as keywords * otherwise. */ #define RB_SCAN_ARGS_LAST_HASH_KEYWORDS 3 /** @} */ /** * @name Possible values that you should pass to rb_funcallv_kw(). * @{ */ /** Do not pass keywords. */ #define RB_NO_KEYWORDS 0 /** Pass keywords, final argument should be a hash of keywords. */ #define RB_PASS_KEYWORDS 1 /** * Pass keywords if current method is called with keywords, useful for argument * delegation */ #define RB_PASS_CALLED_KEYWORDS rb_keyword_given_p() /** @} */ /** * @private * * @deprecated This macro once was a thing in the old days, but makes no sense * any longer today. Exists here for backwards compatibility * only. You can safely forget about it. */ #define HAVE_RB_SCAN_ARGS_OPTIONAL_HASH 1 RBIMPL_SYMBOL_EXPORT_BEGIN() RBIMPL_ATTR_NONNULL((2, 3)) /** * Retrieves argument from argc and argv to given ::VALUE references according * to the format string. The format can be described in ABNF as follows: * * ``` * scan-arg-spec := param-arg-spec [keyword-arg-spec] [block-arg-spec] * * param-arg-spec := pre-arg-spec [post-arg-spec] / post-arg-spec / * pre-opt-post-arg-spec * pre-arg-spec := num-of-leading-mandatory-args * [num-of-optional-args] * post-arg-spec := sym-for-variable-length-args * [num-of-trailing-mandatory-args] * pre-opt-post-arg-spec := num-of-leading-mandatory-args num-of-optional-args * num-of-trailing-mandatory-args * keyword-arg-spec := sym-for-keyword-arg * block-arg-spec := sym-for-block-arg * * num-of-leading-mandatory-args := DIGIT ; The number of leading mandatory * ; arguments * num-of-optional-args := DIGIT ; The number of optional arguments * sym-for-variable-length-args := "*" ; Indicates that variable length * ; arguments are captured as a ruby * ; array * num-of-trailing-mandatory-args := DIGIT ; The number of trailing mandatory * ; arguments * sym-for-keyword-arg := ":" ; Indicates that keyword argument * ; captured as a hash. * ; If keyword arguments are not * ; provided, returns nil. * sym-for-block-arg := "&" ; Indicates that an iterator block * ; should be captured if given * ``` * * For example, "12" means that the method requires at least one argument, and * at most receives three (1+2) arguments. So, the format string must be * followed by three variable references, which are to be assigned to captured * arguments. For omitted arguments, variables are set to ::RUBY_Qnil. `NULL` * can be put in place of a variable reference, which means the corresponding * captured argument(s) should be just dropped. * * The number of given arguments, excluding an option hash or iterator block, * is returned. * * @param[in] argc Length of `argv`. * @param[in] argv Pointer to the arguments to parse. * @param[in] fmt Format, in the language described above. * @param[out] ... Variables to fill in. * @exception rb_eFatal Malformed `fmt`. * @exception rb_eArgError Arity mismatch. * @return Actually parsed number of given arguments. * @post Each values passed to `argv` is filled into the variadic * arguments, according to the format. */ int rb_scan_args(int argc, const VALUE *argv, const char *fmt, ...); RBIMPL_ATTR_NONNULL((3, 4)) /** * Identical to rb_scan_args(), except it also accepts `kw_splat`. * * @param[in] kw_splat How to understand the keyword arguments. * - RB_SCAN_ARGS_PASS_CALLED_KEYWORDS: Same behaviour as rb_scan_args(). * - RB_SCAN_ARGS_KEYWORDS: The final argument is a kwarg. * - RB_SCAN_ARGS_LAST_HASH_KEYWORDS: The final argument is a kwarg, iff it * is a hash. * @param[in] argc Length of `argv`. * @param[in] argv Pointer to the arguments to parse. * @param[in] fmt Format, in the language described above. * @param[out] ... Variables to fill in. * @exception rb_eFatal Malformed `fmt`. * @exception rb_eArgError Arity mismatch. * @return Actually parsed number of given arguments. * @post Each values passed to `argv` is filled into the variadic * arguments, according to the format. */ int rb_scan_args_kw(int kw_splat, int argc, const VALUE *argv, const char *fmt, ...); RBIMPL_ATTR_ERROR(("bad scan arg format")) /** * @private * * This is an implementation detail of rb_scan_args(). People don't use it * directly. */ void rb_scan_args_bad_format(const char*); RBIMPL_ATTR_ERROR(("variable argument length doesn't match")) /** * @private * * This is an implementation detail of rb_scan_args(). People don't use it * directly. */ void rb_scan_args_length_mismatch(const char*,int); RBIMPL_SYMBOL_EXPORT_END() /** @cond INTERNAL_MACRO */ /* If we could use constexpr the following macros could be inline functions * ... but sadly we cannot. */ #define rb_scan_args_isdigit(c) (RBIMPL_CAST((unsigned char)((c)-'0'))<10) #define rb_scan_args_count_end(fmt, ofs, vari) \ ((fmt)[ofs] ? -1 : (vari)) #define rb_scan_args_count_block(fmt, ofs, vari) \ ((fmt)[ofs]!='&' ? \ rb_scan_args_count_end(fmt, ofs, vari) : \ rb_scan_args_count_end(fmt, (ofs)+1, (vari)+1)) #define rb_scan_args_count_hash(fmt, ofs, vari) \ ((fmt)[ofs]!=':' ? \ rb_scan_args_count_block(fmt, ofs, vari) : \ rb_scan_args_count_block(fmt, (ofs)+1, (vari)+1)) #define rb_scan_args_count_trail(fmt, ofs, vari) \ (!rb_scan_args_isdigit((fmt)[ofs]) ? \ rb_scan_args_count_hash(fmt, ofs, vari) : \ rb_scan_args_count_hash(fmt, (ofs)+1, (vari)+((fmt)[ofs]-'0'))) #define rb_scan_args_count_var(fmt, ofs, vari) \ ((fmt)[ofs]!='*' ? \ rb_scan_args_count_trail(fmt, ofs, vari) : \ rb_scan_args_count_trail(fmt, (ofs)+1, (vari)+1)) #define rb_scan_args_count_opt(fmt, ofs, vari) \ (!rb_scan_args_isdigit((fmt)[ofs]) ? \ rb_scan_args_count_var(fmt, ofs, vari) : \ rb_scan_args_count_var(fmt, (ofs)+1, (vari)+(fmt)[ofs]-'0')) #define rb_scan_args_count_lead(fmt, ofs, vari) \ (!rb_scan_args_isdigit((fmt)[ofs]) ? \ rb_scan_args_count_var(fmt, ofs, vari) : \ rb_scan_args_count_opt(fmt, (ofs)+1, (vari)+(fmt)[ofs]-'0')) #define rb_scan_args_count(fmt) rb_scan_args_count_lead(fmt, 0, 0) #if RBIMPL_HAS_ATTRIBUTE(diagnose_if) # /* Assertions done in the attribute. */ # define rb_scan_args_verify(fmt, varc) RBIMPL_ASSERT_NOTHING #else # /* At one sight it _seems_ the expressions below could be written using # * static assertions. The reality is no, they don't. Because fmt is a # * string literal, any operations against fmt cannot produce the "integer # * constant expression"s, as defined in ISO/IEC 9899:2018 section 6.6 # * paragraph #6. Static assertions need such integer constant expressions as # * defined in ISO/IEC 9899:2018 section 6.7.10 paragraph #3. # * # * GCC nonetheless constant-folds this into a no-op, though. */ # define rb_scan_args_verify(fmt, varc) \ (sizeof(char[1-2*(rb_scan_args_count(fmt)<0)])!=1 ? \ rb_scan_args_bad_format(fmt) : \ sizeof(char[1-2*(rb_scan_args_count(fmt)!=(varc))])!=1 ? \ rb_scan_args_length_mismatch(fmt, varc) : \ RBIMPL_ASSERT_NOTHING) #endif static inline bool rb_scan_args_keyword_p(int kw_flag, VALUE last) { switch (kw_flag) { case RB_SCAN_ARGS_PASS_CALLED_KEYWORDS: return !! rb_keyword_given_p(); case RB_SCAN_ARGS_KEYWORDS: return true; case RB_SCAN_ARGS_LAST_HASH_KEYWORDS: return RB_TYPE_P(last, T_HASH); default: return false; } } RBIMPL_ATTR_FORCEINLINE() static bool rb_scan_args_lead_p(const char *fmt) { return rb_scan_args_isdigit(fmt[0]); } RBIMPL_ATTR_FORCEINLINE() static int rb_scan_args_n_lead(const char *fmt) { return (rb_scan_args_lead_p(fmt) ? fmt[0]-'0' : 0); } RBIMPL_ATTR_FORCEINLINE() static bool rb_scan_args_opt_p(const char *fmt) { return (rb_scan_args_lead_p(fmt) && rb_scan_args_isdigit(fmt[1])); } RBIMPL_ATTR_FORCEINLINE() static int rb_scan_args_n_opt(const char *fmt) { return (rb_scan_args_opt_p(fmt) ? fmt[1]-'0' : 0); } RBIMPL_ATTR_FORCEINLINE() static int rb_scan_args_var_idx(const char *fmt) { return (!rb_scan_args_lead_p(fmt) ? 0 : !rb_scan_args_isdigit(fmt[1]) ? 1 : 2); } RBIMPL_ATTR_FORCEINLINE() static bool rb_scan_args_f_var(const char *fmt) { return (fmt[rb_scan_args_var_idx(fmt)]=='*'); } RBIMPL_ATTR_FORCEINLINE() static int rb_scan_args_trail_idx(const char *fmt) { const int idx = rb_scan_args_var_idx(fmt); return idx+(fmt[idx]=='*'); } RBIMPL_ATTR_FORCEINLINE() static int rb_scan_args_n_trail(const char *fmt) { const int idx = rb_scan_args_trail_idx(fmt); return (rb_scan_args_isdigit(fmt[idx]) ? fmt[idx]-'0' : 0); } RBIMPL_ATTR_FORCEINLINE() static int rb_scan_args_hash_idx(const char *fmt) { const int idx = rb_scan_args_trail_idx(fmt); return idx+rb_scan_args_isdigit(fmt[idx]); } RBIMPL_ATTR_FORCEINLINE() static bool rb_scan_args_f_hash(const char *fmt) { return (fmt[rb_scan_args_hash_idx(fmt)]==':'); } RBIMPL_ATTR_FORCEINLINE() static int rb_scan_args_block_idx(const char *fmt) { const int idx = rb_scan_args_hash_idx(fmt); return idx+(fmt[idx]==':'); } RBIMPL_ATTR_FORCEINLINE() static bool rb_scan_args_f_block(const char *fmt) { return (fmt[rb_scan_args_block_idx(fmt)]=='&'); } # if 0 RBIMPL_ATTR_FORCEINLINE() static int rb_scan_args_end_idx(const char *fmt) { const int idx = rb_scan_args_block_idx(fmt); return idx+(fmt[idx]=='&'); } # endif /* NOTE: Use `char *fmt` instead of `const char *fmt` because of clang's bug*/ /* https://bugs.llvm.org/show_bug.cgi?id=38095 */ # define rb_scan_args0(argc, argv, fmt, varc, vars) \ rb_scan_args_set(RB_SCAN_ARGS_PASS_CALLED_KEYWORDS, argc, argv, \ rb_scan_args_n_lead(fmt), \ rb_scan_args_n_opt(fmt), \ rb_scan_args_n_trail(fmt), \ rb_scan_args_f_var(fmt), \ rb_scan_args_f_hash(fmt), \ rb_scan_args_f_block(fmt), \ (rb_scan_args_verify(fmt, varc), vars), (char *)fmt, varc) # define rb_scan_args_kw0(kw_flag, argc, argv, fmt, varc, vars) \ rb_scan_args_set(kw_flag, argc, argv, \ rb_scan_args_n_lead(fmt), \ rb_scan_args_n_opt(fmt), \ rb_scan_args_n_trail(fmt), \ rb_scan_args_f_var(fmt), \ rb_scan_args_f_hash(fmt), \ rb_scan_args_f_block(fmt), \ (rb_scan_args_verify(fmt, varc), vars), (char *)fmt, varc) RBIMPL_ATTR_FORCEINLINE() static int rb_scan_args_set(int kw_flag, int argc, const VALUE *argv, int n_lead, int n_opt, int n_trail, bool f_var, bool f_hash, bool f_block, VALUE *vars[], RB_UNUSED_VAR(const char *fmt), RB_UNUSED_VAR(int varc)) RBIMPL_ATTR_DIAGNOSE_IF(rb_scan_args_count(fmt) < 0, "bad scan arg format", "error") RBIMPL_ATTR_DIAGNOSE_IF(rb_scan_args_count(fmt) != varc, "variable argument length doesn't match", "error") { int i, argi = 0, vari = 0; VALUE *var, hash = Qnil; #define rb_scan_args_next_param() vars[vari++] const int n_mand = n_lead + n_trail; /* capture an option hash - phase 1: pop from the argv */ if (f_hash && argc > 0) { VALUE last = argv[argc - 1]; if (rb_scan_args_keyword_p(kw_flag, last)) { hash = rb_hash_dup(last); argc--; } } if (argc < n_mand) { goto argc_error; } /* capture leading mandatory arguments */ for (i = 0; i < n_lead; i++) { var = rb_scan_args_next_param(); if (var) *var = argv[argi]; argi++; } /* capture optional arguments */ for (i = 0; i < n_opt; i++) { var = rb_scan_args_next_param(); if (argi < argc - n_trail) { if (var) *var = argv[argi]; argi++; } else { if (var) *var = Qnil; } } /* capture variable length arguments */ if (f_var) { int n_var = argc - argi - n_trail; var = rb_scan_args_next_param(); if (0 < n_var) { if (var) *var = rb_ary_new_from_values(n_var, &argv[argi]); argi += n_var; } else { if (var) *var = rb_ary_new(); } } /* capture trailing mandatory arguments */ for (i = 0; i < n_trail; i++) { var = rb_scan_args_next_param(); if (var) *var = argv[argi]; argi++; } /* capture an option hash - phase 2: assignment */ if (f_hash) { var = rb_scan_args_next_param(); if (var) *var = hash; } /* capture iterator block */ if (f_block) { var = rb_scan_args_next_param(); if (rb_block_given_p()) { *var = rb_block_proc(); } else { *var = Qnil; } } if (argi == argc) { return argc; } argc_error: rb_error_arity(argc, n_mand, f_var ? UNLIMITED_ARGUMENTS : n_mand + n_opt); UNREACHABLE_RETURN(-1); #undef rb_scan_args_next_param } /** @endcond */ #if defined(__DOXYGEN__) # /* don't bother */ #elif ! defined(HAVE_BUILTIN___BUILTIN_CHOOSE_EXPR_CONSTANT_P) # /* skip */ #elif ! defined(HAVE_VA_ARGS_MACRO) # /* skip */ #elif ! defined(__OPTIMIZE__) # /* skip */ #elif defined(HAVE___VA_OPT__) # define rb_scan_args(argc, argvp, fmt, ...) \ __builtin_choose_expr( \ __builtin_constant_p(fmt), \ rb_scan_args0( \ argc, argvp, fmt, \ (sizeof((VALUE*[]){__VA_ARGS__})/sizeof(VALUE*)), \ ((VALUE*[]){__VA_ARGS__})), \ (rb_scan_args)(argc, argvp, fmt __VA_OPT__(, __VA_ARGS__))) # define rb_scan_args_kw(kw_flag, argc, argvp, fmt, ...) \ __builtin_choose_expr( \ __builtin_constant_p(fmt), \ rb_scan_args_kw0( \ kw_flag, argc, argvp, fmt, \ (sizeof((VALUE*[]){__VA_ARGS__})/sizeof(VALUE*)), \ ((VALUE*[]){__VA_ARGS__})), \ (rb_scan_args_kw)(kw_flag, argc, argvp, fmt __VA_OPT__(, __VA_ARGS__))) #elif defined(__STRICT_ANSI__) # /* skip */ #elif defined(__GNUC__) # define rb_scan_args(argc, argvp, fmt, ...) \ __builtin_choose_expr( \ __builtin_constant_p(fmt), \ rb_scan_args0( \ argc, argvp, fmt, \ (sizeof((VALUE*[]){__VA_ARGS__})/sizeof(VALUE*)), \ ((VALUE*[]){__VA_ARGS__})), \ (rb_scan_args)(argc, argvp, fmt, __VA_ARGS__)) # define rb_scan_args_kw(kw_flag, argc, argvp, fmt, ...) \ __builtin_choose_expr( \ __builtin_constant_p(fmt), \ rb_scan_args_kw0( \ kw_flag, argc, argvp, fmt, \ (sizeof((VALUE*[]){__VA_ARGS__})/sizeof(VALUE*)), \ ((VALUE*[]){__VA_ARGS__})), \ (rb_scan_args_kw)(kw_flag, argc, argvp, fmt, __VA_ARGS__ /**/)) #endif #endif /* RBIMPL_SCAN_ARGS_H */ include/ruby/internal/stdalign.h 0000644 00000011125 15152150477 0012751 0 ustar 00 #ifndef RBIMPL_STDALIGN_H /*-*-C++-*-vi:se ft=cpp:*/ #define RBIMPL_STDALIGN_H /** * @file * @author Ruby developers <ruby-core@ruby-lang.org> * @copyright This file is a part of the programming language Ruby. * Permission is hereby granted, to either redistribute and/or * modify this file, provided that the conditions mentioned in the * file COPYING are met. Consult the file for details. * @warning Symbols prefixed with either `RBIMPL` or `rbimpl` are * implementation details. Don't take them as canon. They could * rapidly appear then vanish. The name (path) of this header file * is also an implementation detail. Do not expect it to persist * at the place it is now. Developers are free to move it anywhere * anytime at will. * @note To ruby-core: remember that this header can be possibly * recursively included from extension libraries written in C++. * Do not expect for instance `__VA_ARGS__` is always available. * We assume C99 for ruby itself but we don't assume languages of * extension libraries. They could be written in C++98. * @brief Defines #RBIMPL_ALIGNAS / #RBIMPL_ALIGNOF */ #include "ruby/internal/config.h" #ifdef STDC_HEADERS # include <stddef.h> #endif #include "ruby/internal/compiler_is.h" #include "ruby/internal/has/attribute.h" #include "ruby/internal/has/declspec_attribute.h" #include "ruby/internal/has/feature.h" /** * Wraps (or simulates) `alignas`. This is C++11's `alignas` and is _different_ * from C11 `_Alignas`. For instance, * * ```CXX * typedef struct alignas(128) foo { int foo } foo; * ``` * * is a valid C++ while * * ```C * typedef struct _Alignas(128) foo { int foo } foo; * ``` * * is an invalid C because: * * - You cannot `struct _Alignas`. * - A `typedef` cannot have alignments. */ #if defined(__cplusplus) && RBIMPL_HAS_FEATURE(cxx_alignas) # define RBIMPL_ALIGNAS alignas #elif defined(__cplusplus) && (__cplusplus >= 201103L) # define RBIMPL_ALIGNAS alignas #elif defined(__INTEL_CXX11_MODE__) # define RBIMPL_ALIGNAS alignas #elif defined(__GXX_EXPERIMENTAL_CXX0X__) # define RBIMPL_ALIGNAS alignas #elif RBIMPL_HAS_DECLSPEC_ATTRIBUTE(align) # define RBIMPL_ALIGNAS(_) __declspec(align(_)) #elif RBIMPL_HAS_ATTRIBUTE(aligned) # define RBIMPL_ALIGNAS(_) __attribute__((__aligned__(_))) #else # define RBIMPL_ALIGNAS(_) /* void */ #endif /** * Wraps (or simulates) `alignof`. * * We want C11's `_Alignof`. However in spite of its clear language, compilers * (including GCC and clang) tend to have buggy implementations. We have to * avoid such things to resort to our own version. * * @see https://gcc.gnu.org/bugzilla/show_bug.cgi?id=52023 * @see https://gcc.gnu.org/bugzilla/show_bug.cgi?id=69560 * @see https://bugs.llvm.org/show_bug.cgi?id=26547 */ #if defined(__DOXYGEN__) # define RBIMPL_ALIGNOF alignof #elif defined(__cplusplus) # /* C++11 `alignof()` can be buggy. */ # /* see: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=69560 */ # /* But don't worry, we can use templates. */ # define RBIMPL_ALIGNOF(T) (static_cast<size_t>(ruby::rbimpl_alignof<T>::value)) namespace ruby { template<typename T> struct rbimpl_alignof { typedef struct { char _; T t; } type; enum { value = offsetof(type, t) }; }; } #elif RBIMPL_COMPILER_IS(MSVC) # /* Windows have no alignment glitch.*/ # define RBIMPL_ALIGNOF __alignof #elif defined(HAVE__ALIGNOF) # /* Autoconf detected availability of a sane `_Alignof()`. */ # define RBIMPL_ALIGNOF(T) RB_GNUC_EXTENSION(_Alignof(T)) #else # /* :BEWARE: This is the last resort. If your compiler somehow supports # * querying the alignment of a type, you definitely should use that instead. # * There are 2 known pitfalls for this fallback implementation: # * # * First, it is either an undefined behaviour (C) or an explicit error (C++) # * to define a struct inside of `offsetof`. C compilers tend to accept such # * things, but AFAIK C++ has no room to allow. # * # * Second, there exist T such that `struct { char _; T t; }` is invalid. A # * known example is when T is a struct with a flexible array member. Such # * struct cannot be enclosed into another one. # */ # /* see: http://www.open-std.org/jtc1/sc22/wg14/www/docs/n2083.htm */ # /* see: http://www.open-std.org/jtc1/sc22/wg14/www/docs/n2350.htm */ # define RBIMPL_ALIGNOF(T) offsetof(struct { char _; T t; }, t) #endif #endif /* RBIMPL_STDALIGN_H */ include/ruby/internal/core.h 0000644 00000003522 15152150477 0012076 0 ustar 00 #ifndef RBIMPL_CORE_H /*-*-C++-*-vi:se ft=cpp:*/ #define RBIMPL_CORE_H /** * @file * @author Ruby developers <ruby-core@ruby-lang.org> * @copyright This file is a part of the programming language Ruby. * Permission is hereby granted, to either redistribute and/or * modify this file, provided that the conditions mentioned in the * file COPYING are met. Consult the file for details. * @warning Symbols prefixed with either `RBIMPL` or `rbimpl` are * implementation details. Don't take them as canon. They could * rapidly appear then vanish. The name (path) of this header file * is also an implementation detail. Do not expect it to persist * at the place it is now. Developers are free to move it anywhere * anytime at will. * @note To ruby-core: remember that this header can be possibly * recursively included from extension libraries written in C++. * Do not expect for instance `__VA_ARGS__` is always available. * We assume C99 for ruby itself but we don't assume languages of * extension libraries. They could be written in C++98. * @brief Core data structures, definitions and manipulations. */ #include "ruby/internal/core/rarray.h" #include "ruby/internal/core/rbasic.h" #include "ruby/internal/core/rbignum.h" #include "ruby/internal/core/rclass.h" #include "ruby/internal/core/rdata.h" #include "ruby/internal/core/rfile.h" #include "ruby/internal/core/rhash.h" #include "ruby/internal/core/robject.h" #include "ruby/internal/core/rregexp.h" #include "ruby/internal/core/rstring.h" #include "ruby/internal/core/rstruct.h" #include "ruby/internal/core/rtypeddata.h" #endif /* RBIMPL_CORE_H */ include/ruby/internal/compiler_since.h 0000644 00000005337 15152150477 0014147 0 ustar 00 #ifndef RBIMPL_COMPILER_SINCE_H /*-*-C++-*-vi:se ft=cpp:*/ #define RBIMPL_COMPILER_SINCE_H /** * @file * @author Ruby developers <ruby-core@ruby-lang.org> * @copyright This file is a part of the programming language Ruby. * Permission is hereby granted, to either redistribute and/or * modify this file, provided that the conditions mentioned in the * file COPYING are met. Consult the file for details. * @warning Symbols prefixed with either `RBIMPL` or `rbimpl` are * implementation details. Don't take them as canon. They could * rapidly appear then vanish. The name (path) of this header file * is also an implementation detail. Do not expect it to persist * at the place it is now. Developers are free to move it anywhere * anytime at will. * @note To ruby-core: remember that this header can be possibly * recursively included from extension libraries written in C++. * Do not expect for instance `__VA_ARGS__` is always available. * We assume C99 for ruby itself but we don't assume languages of * extension libraries. They could be written in C++98. * @brief Defines #RBIMPL_COMPILER_SINCE. */ #include "ruby/internal/compiler_is.h" /** * @brief Checks if the compiler is of given brand and is newer than or equal * to the passed version. * @param cc Compiler brand, like `MSVC`. * @param x Major version. * @param y Minor version. * @param z Patchlevel. * @retval true cc >= x.y.z. * @retval false otherwise. */ #define RBIMPL_COMPILER_SINCE(cc, x, y, z) \ (RBIMPL_COMPILER_IS(cc) && \ ((RBIMPL_COMPILER_VERSION_MAJOR > (x)) || \ ((RBIMPL_COMPILER_VERSION_MAJOR == (x)) && \ ((RBIMPL_COMPILER_VERSION_MINOR > (y)) || \ ((RBIMPL_COMPILER_VERSION_MINOR == (y)) && \ (RBIMPL_COMPILER_VERSION_PATCH >= (z))))))) /** * @brief Checks if the compiler is of given brand and is older than the * passed version. * @param cc Compiler brand, like `MSVC`. * @param x Major version. * @param y Minor version. * @param z Patchlevel. * @retval true cc < x.y.z. * @retval false otherwise. */ #define RBIMPL_COMPILER_BEFORE(cc, x, y, z) \ (RBIMPL_COMPILER_IS(cc) && \ ((RBIMPL_COMPILER_VERSION_MAJOR < (x)) || \ ((RBIMPL_COMPILER_VERSION_MAJOR == (x)) && \ ((RBIMPL_COMPILER_VERSION_MINOR < (y)) || \ ((RBIMPL_COMPILER_VERSION_MINOR == (y)) && \ (RBIMPL_COMPILER_VERSION_PATCH < (z))))))) #endif /* RBIMPL_COMPILER_SINCE_H */ include/ruby/internal/ctype.h 0000644 00000055071 15152150477 0012300 0 ustar 00 #ifndef RBIMPL_CTYPE_H /*-*-C++-*-vi:se ft=cpp:*/ #define RBIMPL_CTYPE_H /** * @file * @author Ruby developers <ruby-core@ruby-lang.org> * @copyright This file is a part of the programming language Ruby. * Permission is hereby granted, to either redistribute and/or * modify this file, provided that the conditions mentioned in the * file COPYING are met. Consult the file for details. * @warning Symbols prefixed with either `RBIMPL` or `rbimpl` are * implementation details. Don't take them as canon. They could * rapidly appear then vanish. The name (path) of this header file * is also an implementation detail. Do not expect it to persist * at the place it is now. Developers are free to move it anywhere * anytime at will. * @note To ruby-core: remember that this header can be possibly * recursively included from extension libraries written in C++. * Do not expect for instance `__VA_ARGS__` is always available. * We assume C99 for ruby itself but we don't assume languages of * extension libraries. They could be written in C++98. * @brief Our own, locale independent, character handling routines. */ #include "ruby/internal/config.h" #ifdef STDC_HEADERS # include <ctype.h> #endif #include "ruby/internal/attr/artificial.h" #include "ruby/internal/attr/const.h" #include "ruby/internal/attr/constexpr.h" #include "ruby/internal/attr/nonnull.h" #include "ruby/internal/dllexport.h" /** * @name Old character classification macros * * What is this #ISPRINT business? Well, according to our VCS and some * internet surfing, it appears that the initial intent of these macros were to * mimic codes appear in common in several GNU projects. As far as @shyouhei * detects they seem to originate GNU regex (that standalone one rather than * Gnulib or Glibc), and at least date back to 1995. * * Let me lawfully quote from a GNU coreutils commit * https://git.savannah.gnu.org/cgit/coreutils.git/commit/?id=49803907f5dbd7646184a8912c9db9b09dcd0f22 * * > Jim Meyering writes: * > * > "... Some ctype macros are valid only for character codes that * > isascii says are ASCII (SGI's IRIX-4.0.5 is one such system --when * > using /bin/cc or gcc but without giving an ansi option). So, all * > ctype uses should be through macros like ISPRINT... If * > STDC_HEADERS is defined, then autoconf has verified that the ctype * > macros don't need to be guarded with references to isascii. ... * > Defining isascii to 1 should let any compiler worth its salt * > eliminate the && through constant folding." * > * > Bruno Haible adds: * > * > "... Furthermore, isupper(c) etc. have an undefined result if c is * > outside the range -1 <= c <= 255. One is tempted to write isupper(c) * > with c being of type `char', but this is wrong if c is an 8-bit * > character >= 128 which gets sign-extended to a negative value. * > The macro ISUPPER protects against this as well." * * So the intent was to reroute old problematic systems that no longer exist. * At the same time the problems described above no longer hurt us, because we * decided to completely avoid using system-provided isupper etc. to reinvent * the wheel. These macros are entirely legacy; please ignore them. * * But let me also put stress that GNU people are wise; they use those macros * only inside of their own implementations and never let them be public. On * the other hand ruby has thoughtlessly publicised them to 3rd party libraries * since its beginning, which is a very bad idea. These macros are too easy to * get conflicted with definitions elsewhere. * * New programs should stick to the `rb_` prefixed names. * * @note It seems we just mimic the API. We do not share their implementation * with GPL-ed programs. * * @{ */ #ifndef ISPRINT # define ISASCII rb_isascii /**< @old{rb_isascii}*/ # define ISPRINT rb_isprint /**< @old{rb_isprint}*/ # define ISGRAPH rb_isgraph /**< @old{rb_isgraph}*/ # define ISSPACE rb_isspace /**< @old{rb_isspace}*/ # define ISUPPER rb_isupper /**< @old{rb_isupper}*/ # define ISLOWER rb_islower /**< @old{rb_islower}*/ # define ISALNUM rb_isalnum /**< @old{rb_isalnum}*/ # define ISALPHA rb_isalpha /**< @old{rb_isalpha}*/ # define ISDIGIT rb_isdigit /**< @old{rb_isdigit}*/ # define ISXDIGIT rb_isxdigit /**< @old{rb_isxdigit}*/ # define ISBLANK rb_isblank /**< @old{rb_isblank}*/ # define ISCNTRL rb_iscntrl /**< @old{rb_iscntrl}*/ # define ISPUNCT rb_ispunct /**< @old{rb_ispunct}*/ #endif #define TOUPPER rb_toupper /**< @old{rb_toupper}*/ #define TOLOWER rb_tolower /**< @old{rb_tolower}*/ #define STRCASECMP st_locale_insensitive_strcasecmp /**< @old{st_locale_insensitive_strcasecmp}*/ #define STRNCASECMP st_locale_insensitive_strncasecmp /**< @old{st_locale_insensitive_strncasecmp}*/ #define STRTOUL ruby_strtoul /**< @old{ruby_strtoul}*/ /** @} */ RBIMPL_SYMBOL_EXPORT_BEGIN() /** @name locale insensitive functions * @{ */ /* In descriptions below, `the POSIX Locale` and `the "C" locale` are tactfully * used as to whether the described function mimics POSIX or C99. */ RBIMPL_ATTR_NONNULL(()) /** * Our own locale-insensitive version of `strcasecmp(3)`. The "case" here * always means that of the POSIX Locale. It doesn't depend on runtime locale * settings. * * @param[in] s1 Comparison LHS. * @param[in] s2 Comparison RHS. * @retval -1 `s1` is "less" than `s2`. * @retval 0 Both strings converted into lowercase would be identical. * @retval 1 `s1` is "greater" than `s2`. * @note Not only does this function works under the POSIX Locale, but * also assumes its execution character set be what ruby calls an * ASCII-compatible character set; which does not include for * instance EBCDIC or UTF-16LE. */ int st_locale_insensitive_strcasecmp(const char *s1, const char *s2); RBIMPL_ATTR_NONNULL(()) /** * Our own locale-insensitive version of `strcnasecmp(3)`. The "case" here * always means that of the POSIX Locale. It doesn't depend on runtime locale * settings. * * @param[in] s1 Comparison LHS. * @param[in] s2 Comparison RHS. * @param[in] n Comparison shall stop after first `n` bytes are scanned. * @retval -1 `s1` is "less" than `s2`. * @retval 0 Both strings converted into lowercase would be identical. * @retval 1 `s1` is "greater" than `s2`. * @note Not only does this function works under the POSIX Locale, but * also assumes its execution character set be what ruby calls an * ASCII-compatible character set; which does not include for * instance EBCDIC or UTF-16LE. * @warning This function is _not_ timing safe. */ int st_locale_insensitive_strncasecmp(const char *s1, const char *s2, size_t n); RBIMPL_ATTR_NONNULL((1)) /** * Our own locale-insensitive version of `strtoul(3)`. The conversion is done * as if the current locale is set to the "C" locale, no matter actual runtime * locale settings. * * @note This is needed because `strtoul("i", 0, 36)` would return zero * if it is locale sensitive and the current locale is `tr_TR`. * @param[in] str String of digits, optionally preceded with whitespaces * (ignored) and optionally `+` or `-` sign. * @param[out] endptr NULL, or an arbitrary pointer (overwritten on return). * @param[in] base `2` to `36` inclusive for each base, or special case * `0` to detect the base from the contents of the string. * @return Converted integer, casted to unsigned long. * @post If `endptr` is not NULL, it is updated to point the first such * byte where conversion failed. * @note This function sets `errno` on failure. * - `EINVAL`: Passed `base` is out of range. * - `ERANGE`: Converted integer is out of range of `long`. * @warning As far as @shyouhei reads ISO/IEC 9899:2018 section 7.22.1.4, a * conforming `strtoul` implementation shall render `ERANGE` * whenever it finds the input string represents a negative * integer. Such thing can never be representable using `unsigned * long`. However this implementation does not honour that * language. It just casts such negative value to the return * type, resulting a very big return value. This behaviour is at * least questionable. But we can no longer change that at this * point. * @note Not only does this function works under the "C" locale, but * also assumes its execution character set be what ruby calls an * ASCII-compatible character set; which does not include for * instance EBCDIC or UTF-16LE. */ unsigned long ruby_strtoul(const char *str, char **endptr, int base); RBIMPL_SYMBOL_EXPORT_END() /* * We are making the functions below to return `int` instead of `bool`. They * have been as such since their birth at 5f237d79033b2109afb768bc889611fa9630. */ RBIMPL_ATTR_CONST() RBIMPL_ATTR_CONSTEXPR(CXX11) RBIMPL_ATTR_ARTIFICIAL() /** * Our own locale-insensitive version of `isascii(3)`. * * @param[in] c Byte in question to query. * @retval false `c` is out of range of ASCII character set. * @retval true Yes it is. * @warning `c` is an int. This means that when you pass a `char` value * here, it experiences "integer promotion" as defined in ISO/IEC * 9899:2018 section 6.3.1.1 paragraph 1. */ static inline int rb_isascii(int c) { return '\0' <= c && c <= '\x7f'; } RBIMPL_ATTR_CONST() RBIMPL_ATTR_CONSTEXPR(CXX11) RBIMPL_ATTR_ARTIFICIAL() /** * Our own locale-insensitive version of `isupper(3)`. * * @param[in] c Byte in question to query. * @retval true `c` is listed in IEEE 1003.1 section 7.3.1.1 "upper". * @retval false Anything else. * @note Not only does this function works under the POSIX Locale, but * also assumes its execution character set be what ruby calls an * ASCII-compatible character set; which does not include for * instance EBCDIC or UTF-16LE. * @warning `c` is an int. This means that when you pass a `char` value * here, it experiences "integer promotion" as defined in ISO/IEC * 9899:2018 section 6.3.1.1 paragraph 1. */ static inline int rb_isupper(int c) { return 'A' <= c && c <= 'Z'; } RBIMPL_ATTR_CONST() RBIMPL_ATTR_CONSTEXPR(CXX11) RBIMPL_ATTR_ARTIFICIAL() /** * Our own locale-insensitive version of `islower(3)`. * * @param[in] c Byte in question to query. * @retval true `c` is listed in IEEE 1003.1 section 7.3.1.1 "lower". * @retval false Anything else. * @note Not only does this function works under the POSIX Locale, but * also assumes its execution character set be what ruby calls an * ASCII-compatible character set; which does not include for * instance EBCDIC or UTF-16LE. * @warning `c` is an int. This means that when you pass a `char` value * here, it experiences "integer promotion" as defined in ISO/IEC * 9899:2018 section 6.3.1.1 paragraph 1. */ static inline int rb_islower(int c) { return 'a' <= c && c <= 'z'; } RBIMPL_ATTR_CONST() RBIMPL_ATTR_CONSTEXPR(CXX11) RBIMPL_ATTR_ARTIFICIAL() /** * Our own locale-insensitive version of `isalpha(3)`. * * @param[in] c Byte in question to query. * @retval true `c` is listed in either IEEE 1003.1 section 7.3.1.1 * "upper" or "lower". * @retval false Anything else. * @note Not only does this function works under the POSIX Locale, but * also assumes its execution character set be what ruby calls an * ASCII-compatible character set; which does not include for * instance EBCDIC or UTF-16LE. * @warning `c` is an int. This means that when you pass a `char` value * here, it experiences "integer promotion" as defined in ISO/IEC * 9899:2018 section 6.3.1.1 paragraph 1. */ static inline int rb_isalpha(int c) { return rb_isupper(c) || rb_islower(c); } RBIMPL_ATTR_CONST() RBIMPL_ATTR_CONSTEXPR(CXX11) RBIMPL_ATTR_ARTIFICIAL() /** * Our own locale-insensitive version of `isdigit(3)`. * * @param[in] c Byte in question to query. * @retval true `c` is listed in IEEE 1003.1 section 7.3.1.1 "digit". * @retval false Anything else. * @note Not only does this function works under the POSIX Locale, but * also assumes its execution character set be what ruby calls an * ASCII-compatible character set; which does not include for * instance EBCDIC or UTF-16LE. * @warning `c` is an int. This means that when you pass a `char` value * here, it experiences "integer promotion" as defined in ISO/IEC * 9899:2018 section 6.3.1.1 paragraph 1. */ static inline int rb_isdigit(int c) { return '0' <= c && c <= '9'; } RBIMPL_ATTR_CONST() RBIMPL_ATTR_CONSTEXPR(CXX11) RBIMPL_ATTR_ARTIFICIAL() /** * Our own locale-insensitive version of `isalnum(3)`. * * @param[in] c Byte in question to query. * @retval true `c` is listed in either IEEE 1003.1 section 7.3.1.1 * "upper", "lower", or "digit". * @retval false Anything else. * @note Not only does this function works under the POSIX Locale, but * also assumes its execution character set be what ruby calls an * ASCII-compatible character set; which does not include for * instance EBCDIC or UTF-16LE. * @warning `c` is an int. This means that when you pass a `char` value * here, it experiences "integer promotion" as defined in ISO/IEC * 9899:2018 section 6.3.1.1 paragraph 1. */ static inline int rb_isalnum(int c) { return rb_isalpha(c) || rb_isdigit(c); } RBIMPL_ATTR_CONST() RBIMPL_ATTR_CONSTEXPR(CXX11) RBIMPL_ATTR_ARTIFICIAL() /** * Our own locale-insensitive version of `isxdigit(3)`. * * @param[in] c Byte in question to query. * @retval true `c` is listed in IEEE 1003.1 section 7.3.1.1 "xdigit". * @retval false Anything else. * @note Not only does this function works under the POSIX Locale, but * also assumes its execution character set be what ruby calls an * ASCII-compatible character set; which does not include for * instance EBCDIC or UTF-16LE. * @warning `c` is an int. This means that when you pass a `char` value * here, it experiences "integer promotion" as defined in ISO/IEC * 9899:2018 section 6.3.1.1 paragraph 1. */ static inline int rb_isxdigit(int c) { return rb_isdigit(c) || ('A' <= c && c <= 'F') || ('a' <= c && c <= 'f'); } RBIMPL_ATTR_CONST() RBIMPL_ATTR_CONSTEXPR(CXX11) RBIMPL_ATTR_ARTIFICIAL() /** * Our own locale-insensitive version of `isblank(3)`. * * @param[in] c Byte in question to query. * @retval true `c` is listed in IEEE 1003.1 section 7.3.1.1 "blank". * @retval false Anything else. * @note Not only does this function works under the POSIX Locale, but * also assumes its execution character set be what ruby calls an * ASCII-compatible character set; which does not include for * instance EBCDIC or UTF-16LE. * @warning `c` is an int. This means that when you pass a `char` value * here, it experiences "integer promotion" as defined in ISO/IEC * 9899:2018 section 6.3.1.1 paragraph 1. */ static inline int rb_isblank(int c) { return c == ' ' || c == '\t'; } RBIMPL_ATTR_CONST() RBIMPL_ATTR_CONSTEXPR(CXX11) RBIMPL_ATTR_ARTIFICIAL() /** * Our own locale-insensitive version of `isspace(3)`. * * @param[in] c Byte in question to query. * @retval true `c` is listed in IEEE 1003.1 section 7.3.1.1 "space". * @retval false Anything else. * @note Not only does this function works under the POSIX Locale, but * also assumes its execution character set be what ruby calls an * ASCII-compatible character set; which does not include for * instance EBCDIC or UTF-16LE. * @warning `c` is an int. This means that when you pass a `char` value * here, it experiences "integer promotion" as defined in ISO/IEC * 9899:2018 section 6.3.1.1 paragraph 1. */ static inline int rb_isspace(int c) { return c == ' ' || ('\t' <= c && c <= '\r'); } RBIMPL_ATTR_CONST() RBIMPL_ATTR_CONSTEXPR(CXX11) RBIMPL_ATTR_ARTIFICIAL() /** * Our own locale-insensitive version of `iscntrl(3)`. * * @param[in] c Byte in question to query. * @retval true `c` is listed in IEEE 1003.1 section 7.3.1.1 "cntrl". * @retval false Anything else. * @note Not only does this function works under the POSIX Locale, but * also assumes its execution character set be what ruby calls an * ASCII-compatible character set; which does not include for * instance EBCDIC or UTF-16LE. * @warning `c` is an int. This means that when you pass a `char` value * here, it experiences "integer promotion" as defined in ISO/IEC * 9899:2018 section 6.3.1.1 paragraph 1. */ static inline int rb_iscntrl(int c) { return ('\0' <= c && c < ' ') || c == '\x7f'; } RBIMPL_ATTR_CONST() RBIMPL_ATTR_CONSTEXPR(CXX11) RBIMPL_ATTR_ARTIFICIAL() /** * Identical to rb_isgraph(), except it also returns true for `' '`. * * @param[in] c Byte in question to query. * @retval true `c` is listed in either IEEE 1003.1 section 7.3.1.1 * "upper", "lower", "digit", "punct", or a `' '`. * @retval false Anything else. * @note Not only does this function works under the POSIX Locale, but * also assumes its execution character set be what ruby calls an * ASCII-compatible character set; which does not include for * instance EBCDIC or UTF-16LE. * @warning `c` is an int. This means that when you pass a `char` value * here, it experiences "integer promotion" as defined in ISO/IEC * 9899:2018 section 6.3.1.1 paragraph 1. */ static inline int rb_isprint(int c) { return ' ' <= c && c <= '\x7e'; } RBIMPL_ATTR_CONST() RBIMPL_ATTR_CONSTEXPR(CXX11) RBIMPL_ATTR_ARTIFICIAL() /** * Our own locale-insensitive version of `ispunct(3)`. * * @param[in] c Byte in question to query. * @retval true `c` is listed in IEEE 1003.1 section 7.3.1.1 "punct". * @retval false Anything else. * @note Not only does this function works under the POSIX Locale, but * also assumes its execution character set be what ruby calls an * ASCII-compatible character set; which does not include for * instance EBCDIC or UTF-16LE. * @warning `c` is an int. This means that when you pass a `char` value * here, it experiences "integer promotion" as defined in ISO/IEC * 9899:2018 section 6.3.1.1 paragraph 1. */ static inline int rb_ispunct(int c) { return !rb_isalnum(c); } RBIMPL_ATTR_CONST() RBIMPL_ATTR_CONSTEXPR(CXX11) RBIMPL_ATTR_ARTIFICIAL() /** * Our own locale-insensitive version of `isgraph(3)`. * * @param[in] c Byte in question to query. * @retval true `c` is listed in either IEEE 1003.1 section 7.3.1.1 * "upper", "lower", "digit", or "punct". * @retval false Anything else. * @note Not only does this function works under the POSIX Locale, but * also assumes its execution character set be what ruby calls an * ASCII-compatible character set; which does not include for * instance EBCDIC or UTF-16LE. * @warning `c` is an int. This means that when you pass a `char` value * here, it experiences "integer promotion" as defined in ISO/IEC * 9899:2018 section 6.3.1.1 paragraph 1. */ static inline int rb_isgraph(int c) { return '!' <= c && c <= '\x7e'; } RBIMPL_ATTR_CONST() RBIMPL_ATTR_CONSTEXPR(CXX11) RBIMPL_ATTR_ARTIFICIAL() /** * Our own locale-insensitive version of `tolower(3)`. * * @param[in] c Byte in question to convert. * @retval c The byte is not listed in in IEEE 1003.1 section * 7.3.1.1 "upper". * @retval otherwise Byte converted using the map defined in IEEE 1003.1 * section 7.3.1 "tolower". * @note Not only does this function works under the POSIX Locale, but * also assumes its execution character set be what ruby calls an * ASCII-compatible character set; which does not include for * instance EBCDIC or UTF-16LE. * @warning `c` is an int. This means that when you pass a `char` value * here, it experiences "integer promotion" as defined in ISO/IEC * 9899:2018 section 6.3.1.1 paragraph 1. */ static inline int rb_tolower(int c) { return rb_isupper(c) ? (c|0x20) : c; } RBIMPL_ATTR_CONST() RBIMPL_ATTR_CONSTEXPR(CXX11) RBIMPL_ATTR_ARTIFICIAL() /** * Our own locale-insensitive version of `toupper(3)`. * * @param[in] c Byte in question to convert. * @retval c The byte is not listed in in IEEE 1003.1 section * 7.3.1.1 "lower". * @retval otherwise Byte converted using the map defined in IEEE 1003.1 * section 7.3.1 "toupper". * @note Not only does this function works under the POSIX Locale, but * also assumes its execution character set be what ruby calls an * ASCII-compatible character set; which does not include for * instance EBCDIC or UTF-16LE. * @warning `c` is an int. This means that when you pass a `char` value * here, it experiences "integer promotion" as defined in ISO/IEC * 9899:2018 section 6.3.1.1 paragraph 1. */ static inline int rb_toupper(int c) { return rb_islower(c) ? (c&0x5f) : c; } /** @} */ #endif /* RBIMPL_CTYPE_H */ include/ruby/internal/eval.h 0000644 00000044315 15152150477 0012102 0 ustar 00 #ifndef RBIMPL_EVAL_H /*-*-C++-*-vi:se ft=cpp:*/ #define RBIMPL_EVAL_H /** * @file * @author Ruby developers <ruby-core@ruby-lang.org> * @copyright This file is a part of the programming language Ruby. * Permission is hereby granted, to either redistribute and/or * modify this file, provided that the conditions mentioned in the * file COPYING are met. Consult the file for details. * @warning Symbols prefixed with either `RBIMPL` or `rbimpl` are * implementation details. Don't take them as canon. They could * rapidly appear then vanish. The name (path) of this header file * is also an implementation detail. Do not expect it to persist * at the place it is now. Developers are free to move it anywhere * anytime at will. * @note To ruby-core: remember that this header can be possibly * recursively included from extension libraries written in C++. * Do not expect for instance `__VA_ARGS__` is always available. * We assume C99 for ruby itself but we don't assume languages of * extension libraries. They could be written in C++98. * @brief Declares ::rb_eval_string(). */ #include "ruby/internal/dllexport.h" #include "ruby/internal/attr/nonnull.h" #include "ruby/internal/value.h" RBIMPL_SYMBOL_EXPORT_BEGIN() RBIMPL_ATTR_NONNULL(()) /** * Evaluates the given string. * * In case it is called from within a C-backended method, the evaluation is * done under the current binding. However there can be no method. On such * situation this function evaluates in an isolated binding, like `require` * runs in a separate one. * * `__FILE__` will be `"(eval)"`, and `__LINE__` starts from 1 in the * evaluation. * * @param[in] str Ruby code to evaluate. * @exception rb_eException Raises an exception on error. * @return The evaluated result. * * @internal * * @shyouhei's old tale about the birth and growth of this function: * * At the beginning, there was no rb_eval_string(). @shyouhei heard that * @shugo, author of Apache httpd's mod_ruby module, requested @matz for this * API. He wanted a way so that mod_ruby can evaluate ruby scripts one by one, * separately, in each different contexts. So this function was made. It was * designed to be a global interpreter entry point like ruby_run_node(). * * The way it is implemented however allows extension libraries (not just * programs like Apache httpd) to call this function. Because its name says * nothing about the initial design, people started to think of it as an * orthodox way to call ruby level `eval` method from their extension * libraries. Even our `extension.rdoc` has had a description of this function * basically according to this understanding. * * The old (mod_ruby like) usage still works. But over time, usages of this * function from extension libraries got popular, while mod_ruby faded out; is * no longer maintained now. Devs decided to actively support both. This * function now auto-detects how it is called, and switches how it works * depending on it. * * @see https://bugs.ruby-lang.org/issues/18780 */ VALUE rb_eval_string(const char *str); RBIMPL_ATTR_NONNULL((1)) /** * Identical to rb_eval_string(), except it avoids potential global escapes. * Such global escapes include exceptions, `throw`, `break`, for example. * * It first evaluates the given string as rb_eval_string() does. If no global * escape occurred during the evaluation, it returns the result and `*state` is * zero. Otherwise, it returns some undefined value and sets `*state` to * nonzero. If state is `NULL`, it is not set in both cases. * * @param[in] str Ruby code to evaluate. * @param[out] state State of execution. * @return The evaluated result if succeeded, an undefined value if * otherwise. * @post `*state` is set to zero if succeeded. Nonzero otherwise. * @warning You have to clear the error info with `rb_set_errinfo(Qnil)` if * you decide to ignore the caught exception. * @see rb_eval_string * @see rb_protect * * @internal * * The "undefined value" described above is in fact ::RUBY_Qnil for now. But * @shyouhei doesn't think that we would never change that. * * Though not a part of our public API, `state` is in fact an * enum ruby_tag_type. You can see the potential "nonzero" values by looking * at vm_core.h. */ VALUE rb_eval_string_protect(const char *str, int *state); RBIMPL_ATTR_NONNULL((1)) /** * Identical to rb_eval_string_protect(), except it evaluates the given string * under a module binding in an isolated binding. This is the same as a * binding for loaded libraries on `rb_load(something, true)`. * * @param[in] str Ruby code to evaluate. * @param[out] state State of execution. * @return The evaluated result if succeeded, an undefined value if * otherwise. * @post `*state` is set to zero if succeeded. Nonzero otherwise. * @warning You have to clear the error info with `rb_set_errinfo(Qnil)` if * you decide to ignore the caught exception. * @see rb_eval_string */ VALUE rb_eval_string_wrap(const char *str, int *state); /** * Calls a method. Can call both public and private methods. * * @param[in,out] recv Receiver of the method. * @param[in] mid Name of the method to call. * @param[in] n Number of arguments that follow. * @param[in] ... Arbitrary number of method arguments. * @exception rb_eNoMethodError No such method. * @exception rb_eException Any exceptions happen inside. * @return What the method evaluates to. */ VALUE rb_funcall(VALUE recv, ID mid, int n, ...); /** * Identical to rb_funcall(), except it takes the method arguments as a C * array. * * @param[in,out] recv Receiver of the method. * @param[in] mid Name of the method to call. * @param[in] argc Number of arguments. * @param[in] argv Arbitrary number of method arguments. * @exception rb_eNoMethodError No such method. * @exception rb_eException Any exceptions happen inside. * @return What the method evaluates to. */ VALUE rb_funcallv(VALUE recv, ID mid, int argc, const VALUE *argv); /** * Identical to rb_funcallv(), except you can specify how to handle the last * element of the given array. * * @param[in,out] recv Receiver of the method. * @param[in] mid Name of the method to call. * @param[in] argc Number of arguments. * @param[in] argv Arbitrary number of method arguments. * @param[in] kw_splat Handling of keyword parameters: * - RB_NO_KEYWORDS `argv`'s last is not a keyword argument. * - RB_PASS_KEYWORDS `argv`'s last is a keyword argument. * - RB_PASS_CALLED_KEYWORDS it depends if there is a passed block. * @exception rb_eNoMethodError No such method. * @exception rb_eException Any exceptions happen inside. * @return What the method evaluates to. */ VALUE rb_funcallv_kw(VALUE recv, ID mid, int argc, const VALUE *argv, int kw_splat); /** * Identical to rb_funcallv(), except it only takes public methods into * account. This is roughly Ruby's `Object#public_send`. * * @param[in,out] recv Receiver of the method. * @param[in] mid Name of the method to call. * @param[in] argc Number of arguments. * @param[in] argv Arbitrary number of method arguments. * @exception rb_eNoMethodError No such method. * @exception rb_eNoMethodError The method is private or protected. * @exception rb_eException Any exceptions happen inside. * @return What the method evaluates to. */ VALUE rb_funcallv_public(VALUE recv, ID mid, int argc, const VALUE *argv); /** * Identical to rb_funcallv_public(), except you can specify how to handle the * last element of the given array. It can also be seen as a routine identical * to rb_funcallv_kw(), except it only takes public methods into account. * * @param[in,out] recv Receiver of the method. * @param[in] mid Name of the method to call. * @param[in] argc Number of arguments. * @param[in] argv Arbitrary number of method arguments. * @param[in] kw_splat Handling of keyword parameters: * - RB_NO_KEYWORDS `argv`'s last is not a keyword argument. * - RB_PASS_KEYWORDS `argv`'s last is a keyword argument. * - RB_PASS_CALLED_KEYWORDS it depends if there is a passed block. * @exception rb_eNoMethodError No such method. * @exception rb_eNoMethodError The method is private or protected. * @exception rb_eException Any exceptions happen inside. * @return What the method evaluates to. */ VALUE rb_funcallv_public_kw(VALUE recv, ID mid, int argc, const VALUE *argv, int kw_splat); /** * @deprecated This is an old name of rb_funcallv(). Provided here for * backwards compatibility to 2.x programs (introduced in 2.1). * It is not a good name. Please don't use it any longer. */ #define rb_funcall2 rb_funcallv /** * @deprecated This is an old name of rb_funcallv_public(). Provided here * for backwards compatibility to 2.x programs (introduced in * 2.1). It is not a good name. Please don't use it any longer. */ #define rb_funcall3 rb_funcallv_public /** * Identical to rb_funcallv_public(), except you can pass the passed block. * * Sometimes you want to "pass" a block parameter form one method to another. * Suppose you have this Ruby method `foo`: * * ```ruby * def foo(x, y, &z) * x.open(y, &z) * end * ``` * * And suppose you want to translate this into C. Then * rb_funcall_passing_block() function is usable in this situation. * * ```CXX * VALUE * foo_translated_into_C(VALUE self, VALUE x, VALUE y) * { * const auto open = rb_intern("open"); * * return rb_funcall_passing_block(x, open, 1, &y); * } * ``` * * @see rb_yield_block * @param[in,out] recv Receiver of the method. * @param[in] mid Name of the method to call. * @param[in] argc Number of arguments. * @param[in] argv Arbitrary number of method arguments. * @exception rb_eNoMethodError No such method. * @exception rb_eNoMethodError The method is private or protected. * @exception rb_eException Any exceptions happen inside. * @return What the method evaluates to. */ VALUE rb_funcall_passing_block(VALUE recv, ID mid, int argc, const VALUE *argv); /** * Identical to rb_funcallv_passing_block(), except you can specify how to * handle the last element of the given array. It can also be seen as a * routine identical to rb_funcallv_public_kw(), except you can pass the passed * block. * * @param[in,out] recv Receiver of the method. * @param[in] mid Name of the method to call. * @param[in] argc Number of arguments. * @param[in] argv Arbitrary number of method arguments. * @param[in] kw_splat Handling of keyword parameters: * - RB_NO_KEYWORDS `argv`'s last is not a keyword argument. * - RB_PASS_KEYWORDS `argv`'s last is a keyword argument. * - RB_PASS_CALLED_KEYWORDS it depends if there is a passed block. * @exception rb_eNoMethodError No such method. * @exception rb_eNoMethodError The method is private or protected. * @exception rb_eException Any exceptions happen inside. * @return What the method evaluates to. */ VALUE rb_funcall_passing_block_kw(VALUE recv, ID mid, int argc, const VALUE *argv, int kw_splat); /** * Identical to rb_funcallv_public(), except you can pass a block. A block * here basically is an instance of ::rb_cProc. If you want to exercise * `to_proc` conversion, do so before passing it here. However nil and symbols * are special-case allowed. * * @param[in,out] recv Receiver of the method. * @param[in] mid Name of the method to call. * @param[in] argc Number of arguments. * @param[in] argv Arbitrary number of method arguments. * @param[in] procval An instance of Proc, Symbol, or NilClass. * @exception rb_eNoMethodError No such method. * @exception rb_eNoMethodError The method is private or protected. * @exception rb_eException Any exceptions happen inside. * @return What the method evaluates to. * * @internal * * Implementation-wise, `procval` is in fact a "block handler" object. You * could also pass an IFUNC (block_handler_ifunc) here to say precise. --- But * AFAIK there is no 3rd party way to even know that there are objects called * IFUNC behind-the-scene. */ VALUE rb_funcall_with_block(VALUE recv, ID mid, int argc, const VALUE *argv, VALUE procval); /** * Identical to rb_funcallv_with_block(), except you can specify how to handle * the last element of the given array. It can also be seen as a routine * identical to rb_funcallv_public_kw(), except you can pass a block. * * @param[in,out] recv Receiver of the method. * @param[in] mid Name of the method to call. * @param[in] argc Number of arguments. * @param[in] argv Arbitrary number of method arguments. * @param[in] procval An instance of Proc, Symbol, or NilClass. * @param[in] kw_splat Handling of keyword parameters: * - RB_NO_KEYWORDS `argv`'s last is not a keyword argument. * - RB_PASS_KEYWORDS `argv`'s last is a keyword argument. * - RB_PASS_CALLED_KEYWORDS it depends if there is a passed block. * @exception rb_eNoMethodError No such method. * @exception rb_eNoMethodError The method is private or protected. * @exception rb_eException Any exceptions happen inside. * @return What the method evaluates to. */ VALUE rb_funcall_with_block_kw(VALUE recv, ID mid, int argc, const VALUE *argv, VALUE procval, int kw_splat); /** * This resembles ruby's `super`. * * @param[in] argc Number of arguments. * @param[in] argv Arbitrary number of method arguments. * @exception rb_eNoMethodError No super method are there. * @exception rb_eException Any exceptions happen inside. * @return What the super method evaluates to. */ VALUE rb_call_super(int argc, const VALUE *argv); /** * Identical to rb_call_super(), except you can specify how to handle the last * element of the given array. * * @param[in] argc Number of arguments. * @param[in] argv Arbitrary number of method arguments. * @param[in] kw_splat Handling of keyword parameters: * - RB_NO_KEYWORDS `argv`'s last is not a keyword argument. * - RB_PASS_KEYWORDS `argv`'s last is a keyword argument. * - RB_PASS_CALLED_KEYWORDS it depends if there is a passed block. * @exception rb_eNoMethodError No super method are there. * @exception rb_eException Any exceptions happen inside. * @return What the super method evaluates to. */ VALUE rb_call_super_kw(int argc, const VALUE *argv, int kw_splat); /** * This resembles ruby's `self`. * * @exception rb_eRuntimeError Called from outside of method context. * @return Current receiver. */ VALUE rb_current_receiver(void); RBIMPL_ATTR_NONNULL((2)) /** * Keyword argument deconstructor. * * Retrieves argument values bound to keywords, which directed by `table` into * `values`, deleting retrieved entries from `keyword_hash` along the way. * First `required` number of IDs referred by `table` are mandatory, and * succeeding `optional` (`-optional-1` if `optional` is negative) number of * IDs are optional. If a mandatory key is not contained in `keyword_hash`, * raises ::rb_eArgError. If an optional key is not present in `keyword_hash`, * the corresponding element in `values` is set to ::RUBY_Qundef. If * `optional` is negative, rest of `keyword_hash` are ignored, otherwise raises * ::rb_eArgError. * * @warning Handling keyword arguments in the C API is less efficient than * handling them in Ruby. Consider using a Ruby wrapper method * around a non-keyword C function. * @see https://bugs.ruby-lang.org/issues/11339 * @param[out] keyword_hash Target hash to deconstruct. * @param[in] table List of keywords that you are interested in. * @param[in] required Number of mandatory keywords. * @param[in] optional Number of optional keywords (can be negative). * @param[out] values Buffer to be filled. * @exception rb_eArgError Absence of a mandatory keyword. * @exception rb_eArgError Found an unknown keyword. * @return Number of found values that are stored into `values`. */ int rb_get_kwargs(VALUE keyword_hash, const ID *table, int required, int optional, VALUE *values); RBIMPL_ATTR_NONNULL(()) /** * Splits a hash into two. * * Takes a hash of various keys, and split it into symbol-keyed parts and * others. Symbol-keyed part becomes the return value. What remains are * returned as a new hash object stored at the argument pointer. * * @param[in,out] orighash Pointer to a target hash to split. * @return An extracted keyword hash. * @post Upon successful return `orighash` points to another hash * object, whose contents are the remainder of the operation. * @note The argument hash object is not modified. */ VALUE rb_extract_keywords(VALUE *orighash); RBIMPL_SYMBOL_EXPORT_END() #endif /* RBIMPL_EVAL_H */ include/ruby/internal/special_consts.h 0000644 00000027627 15152150477 0014173 0 ustar 00 #ifndef RBIMPL_SPECIAL_CONSTS_H /*-*-C++-*-vi:se ft=cpp:*/ #define RBIMPL_SPECIAL_CONSTS_H /** * @file * @author Ruby developers <ruby-core@ruby-lang.org> * @copyright This file is a part of the programming language Ruby. * Permission is hereby granted, to either redistribute and/or * modify this file, provided that the conditions mentioned in the * file COPYING are met. Consult the file for details. * @warning Symbols prefixed with either `RBIMPL` or `rbimpl` are * implementation details. Don't take them as canon. They could * rapidly appear then vanish. The name (path) of this header file * is also an implementation detail. Do not expect it to persist * at the place it is now. Developers are free to move it anywhere * anytime at will. * @note To ruby-core: remember that this header can be possibly * recursively included from extension libraries written in C++. * Do not expect for instance `__VA_ARGS__` is always available. * We assume C99 for ruby itself but we don't assume languages of * extension libraries. They could be written in C++98. * @brief Defines enum ::ruby_special_consts. * @see Sasada, K., "A Lightweight Representation of Floating-Point * Numbers on Ruby Interpreter", in proceedings of 10th JSSST * SIGPPL Workshop on Programming and Programming Languages * (PPL2008), pp. 9-16, 2008. */ #include "ruby/internal/attr/artificial.h" #include "ruby/internal/attr/const.h" #include "ruby/internal/attr/constexpr.h" #include "ruby/internal/attr/enum_extensibility.h" #include "ruby/internal/stdbool.h" #include "ruby/internal/value.h" /** * @private * @warning Do not touch this macro. * @warning It is an implementation detail. * @warning The value of this macro must match for ruby itself and all * extension libraries, otherwise serious memory corruption shall * occur. */ #if defined(USE_FLONUM) # /* Take that. */ #elif SIZEOF_VALUE >= SIZEOF_DOUBLE # define USE_FLONUM 1 #else # define USE_FLONUM 0 #endif /** This is an old name of #RB_TEST. Not sure which name is preferred. */ #define RTEST RB_TEST #define FIXNUM_P RB_FIXNUM_P /**< @old{RB_FIXNUM_P} */ #define IMMEDIATE_P RB_IMMEDIATE_P /**< @old{RB_IMMEDIATE_P} */ #define NIL_P RB_NIL_P /**< @old{RB_NIL_P} */ #define SPECIAL_CONST_P RB_SPECIAL_CONST_P /**< @old{RB_SPECIAL_CONST_P} */ #define STATIC_SYM_P RB_STATIC_SYM_P /**< @old{RB_STATIC_SYM_P} */ #define Qfalse RUBY_Qfalse /**< @old{RUBY_Qfalse} */ #define Qnil RUBY_Qnil /**< @old{RUBY_Qnil} */ #define Qtrue RUBY_Qtrue /**< @old{RUBY_Qtrue} */ #define Qundef RUBY_Qundef /**< @old{RUBY_Qundef} */ #define FIXNUM_FLAG RUBY_FIXNUM_FLAG /**< @old{RUBY_FIXNUM_FLAG} */ #define FLONUM_FLAG RUBY_FLONUM_FLAG /**< @old{RUBY_FLONUM_FLAG} */ #define FLONUM_MASK RUBY_FLONUM_MASK /**< @old{RUBY_FLONUM_MASK} */ #define FLONUM_P RB_FLONUM_P /**< @old{RB_FLONUM_P} */ #define IMMEDIATE_MASK RUBY_IMMEDIATE_MASK /**< @old{RUBY_IMMEDIATE_MASK} */ #define SYMBOL_FLAG RUBY_SYMBOL_FLAG /**< @old{RUBY_SYMBOL_FLAG} */ /** @cond INTERNAL_MACRO */ #define RB_FIXNUM_P RB_FIXNUM_P #define RB_FLONUM_P RB_FLONUM_P #define RB_IMMEDIATE_P RB_IMMEDIATE_P #define RB_NIL_P RB_NIL_P #define RB_SPECIAL_CONST_P RB_SPECIAL_CONST_P #define RB_STATIC_SYM_P RB_STATIC_SYM_P #define RB_TEST RB_TEST #define RB_UNDEF_P RB_UNDEF_P #define RB_NIL_OR_UNDEF_P RB_NIL_OR_UNDEF_P /** @endcond */ /** special constants - i.e. non-zero and non-fixnum constants */ enum RBIMPL_ATTR_ENUM_EXTENSIBILITY(closed) ruby_special_consts { #if defined(__DOXYGEN__) RUBY_Qfalse, /**< @see ::rb_cFalseClass */ RUBY_Qtrue, /**< @see ::rb_cTrueClass */ RUBY_Qnil, /**< @see ::rb_cNilClass */ RUBY_Qundef, /**< Represents so-called undef. */ RUBY_IMMEDIATE_MASK, /**< Bit mask detecting special consts. */ RUBY_FIXNUM_FLAG, /**< Flag to denote a fixnum. */ RUBY_FLONUM_MASK, /**< Bit mask detecting a flonum. */ RUBY_FLONUM_FLAG, /**< Flag to denote a flonum. */ RUBY_SYMBOL_FLAG, /**< Flag to denote a static symbol. */ #elif USE_FLONUM RUBY_Qfalse = 0x00, /* ...0000 0000 */ RUBY_Qnil = 0x04, /* ...0000 0100 */ RUBY_Qtrue = 0x14, /* ...0001 0100 */ RUBY_Qundef = 0x24, /* ...0010 0100 */ RUBY_IMMEDIATE_MASK = 0x07, /* ...0000 0111 */ RUBY_FIXNUM_FLAG = 0x01, /* ...xxxx xxx1 */ RUBY_FLONUM_MASK = 0x03, /* ...0000 0011 */ RUBY_FLONUM_FLAG = 0x02, /* ...xxxx xx10 */ RUBY_SYMBOL_FLAG = 0x0c, /* ...xxxx 1100 */ #else RUBY_Qfalse = 0x00, /* ...0000 0000 */ RUBY_Qnil = 0x02, /* ...0000 0010 */ RUBY_Qtrue = 0x06, /* ...0000 0110 */ RUBY_Qundef = 0x0a, /* ...0000 1010 */ RUBY_IMMEDIATE_MASK = 0x03, /* ...0000 0011 */ RUBY_FIXNUM_FLAG = 0x01, /* ...xxxx xxx1 */ RUBY_FLONUM_MASK = 0x00, /* any values ANDed with FLONUM_MASK cannot be FLONUM_FLAG */ RUBY_FLONUM_FLAG = 0x02, /* ...0000 0010 */ RUBY_SYMBOL_FLAG = 0x0e, /* ...xxxx 1110 */ #endif RUBY_SPECIAL_SHIFT = 8 /**< Least significant 8 bits are reserved. */ }; RBIMPL_ATTR_CONST() RBIMPL_ATTR_CONSTEXPR(CXX11) RBIMPL_ATTR_ARTIFICIAL() /** * Emulates Ruby's "if" statement. * * @param[in] obj An arbitrary ruby object. * @retval false `obj` is either ::RUBY_Qfalse or ::RUBY_Qnil. * @retval true Anything else. * * @internal * * It HAS to be `__attribute__((const))` in order for clang to properly deduce * `__builtin_assume()`. */ static inline bool RB_TEST(VALUE obj) { /* * if USE_FLONUM * Qfalse: ....0000 0000 * Qnil: ....0000 0100 * ~Qnil: ....1111 1011 * v ....xxxx xxxx * ---------------------------- * RTEST(v) ....xxxx x0xx * * if ! USE_FLONUM * Qfalse: ....0000 0000 * Qnil: ....0000 0010 * ~Qnil: ....1111 1101 * v ....xxxx xxxx * ---------------------------- * RTEST(v) ....xxxx xx0x * * RTEST(v) can be 0 if and only if (v == Qfalse || v == Qnil). */ return obj & ~RUBY_Qnil; } RBIMPL_ATTR_CONST() RBIMPL_ATTR_CONSTEXPR(CXX11) RBIMPL_ATTR_ARTIFICIAL() /** * Checks if the given object is nil. * * @param[in] obj An arbitrary ruby object. * @retval true `obj` is ::RUBY_Qnil. * @retval false Anything else. */ static inline bool RB_NIL_P(VALUE obj) { return obj == RUBY_Qnil; } RBIMPL_ATTR_CONST() RBIMPL_ATTR_CONSTEXPR(CXX11) RBIMPL_ATTR_ARTIFICIAL() /** * Checks if the given object is undef. * * @param[in] obj An arbitrary ruby object. * @retval true `obj` is ::RUBY_Qundef. * @retval false Anything else. */ static inline bool RB_UNDEF_P(VALUE obj) { return obj == RUBY_Qundef; } RBIMPL_ATTR_CONST() RBIMPL_ATTR_CONSTEXPR(CXX14) RBIMPL_ATTR_ARTIFICIAL() /** * Checks if the given object is nil or undef. Can be used to see if * a keyword argument is not given or given `nil`. * * @param[in] obj An arbitrary ruby object. * @retval true `obj` is ::RUBY_Qnil or ::RUBY_Qundef. * @retval false Anything else. */ static inline bool RB_NIL_OR_UNDEF_P(VALUE obj) { /* * if USE_FLONUM * Qundef: ....0010 0100 * Qnil: ....0000 0100 * mask: ....1101 1111 * common_bits: ....0000 0100 * --------------------------------- * Qnil & mask ....0000 0100 * Qundef & mask ....0000 0100 * * if ! USE_FLONUM * Qundef: ....0000 1010 * Qnil: ....0000 0010 * mask: ....1111 0111 * common_bits: ....0000 0010 * ---------------------------- * Qnil & mask ....0000 0010 * Qundef & mask ....0000 0010 * * NIL_OR_UNDEF_P(v) can be true only when v is Qundef or Qnil. */ const VALUE mask = ~(RUBY_Qundef ^ RUBY_Qnil); const VALUE common_bits = RUBY_Qundef & RUBY_Qnil; return (obj & mask) == common_bits; } RBIMPL_ATTR_CONST() RBIMPL_ATTR_CONSTEXPR(CXX11) RBIMPL_ATTR_ARTIFICIAL() /** * Checks if the given object is a so-called Fixnum. * * @param[in] obj An arbitrary ruby object. * @retval true `obj` is a Fixnum. * @retval false Anything else. * @note Fixnum was a thing in the 20th century, but it is rather an * implementation detail today. */ static inline bool RB_FIXNUM_P(VALUE obj) { return obj & RUBY_FIXNUM_FLAG; } RBIMPL_ATTR_CONST() RBIMPL_ATTR_CONSTEXPR(CXX14) RBIMPL_ATTR_ARTIFICIAL() /** * Checks if the given object is a static symbol. * * @param[in] obj An arbitrary ruby object. * @retval true `obj` is a static symbol * @retval false Anything else. * @see RB_DYNAMIC_SYM_P() * @see RB_SYMBOL_P() * @note These days there are static and dynamic symbols, just like we * once had Fixnum/Bignum back in the old days. */ static inline bool RB_STATIC_SYM_P(VALUE obj) { RBIMPL_ATTR_CONSTEXPR(CXX14) const VALUE mask = ~(RBIMPL_VALUE_FULL << RUBY_SPECIAL_SHIFT); return (obj & mask) == RUBY_SYMBOL_FLAG; } RBIMPL_ATTR_CONST() RBIMPL_ATTR_CONSTEXPR(CXX11) RBIMPL_ATTR_ARTIFICIAL() /** * Checks if the given object is a so-called Flonum. * * @param[in] obj An arbitrary ruby object. * @retval true `obj` is a Flonum. * @retval false Anything else. * @see RB_FLOAT_TYPE_P() * @note These days there are Flonums and non-Flonum floats, just like we * once had Fixnum/Bignum back in the old days. */ static inline bool RB_FLONUM_P(VALUE obj) { #if USE_FLONUM return (obj & RUBY_FLONUM_MASK) == RUBY_FLONUM_FLAG; #else return false; #endif } RBIMPL_ATTR_CONST() RBIMPL_ATTR_CONSTEXPR(CXX11) RBIMPL_ATTR_ARTIFICIAL() /** * Checks if the given object is an immediate i.e. an object which has no * corresponding storage inside of the object space. * * @param[in] obj An arbitrary ruby object. * @retval true `obj` is a Flonum. * @retval false Anything else. * @see RB_FLOAT_TYPE_P() * @note The concept of "immediate" is purely C specific. */ static inline bool RB_IMMEDIATE_P(VALUE obj) { return obj & RUBY_IMMEDIATE_MASK; } RBIMPL_ATTR_CONST() RBIMPL_ATTR_CONSTEXPR(CXX11) RBIMPL_ATTR_ARTIFICIAL() /** * Checks if the given object is of enum ::ruby_special_consts. * * @param[in] obj An arbitrary ruby object. * @retval true `obj` is a special constant. * @retval false Anything else. */ static inline bool RB_SPECIAL_CONST_P(VALUE obj) { return RB_IMMEDIATE_P(obj) || obj == RUBY_Qfalse; } RBIMPL_ATTR_CONST() RBIMPL_ATTR_CONSTEXPR(CXX11) /** * Identical to RB_SPECIAL_CONST_P, except it returns a ::VALUE. * * @param[in] obj An arbitrary ruby object. * @retval RUBY_Qtrue `obj` is a special constant. * @retval RUBY_Qfalse Anything else. * * @internal * * This function is to mimic old rb_special_const_p macro but have anyone * actually used its return value? Wasn't it just something no one needed? */ static inline VALUE rb_special_const_p(VALUE obj) { return RB_SPECIAL_CONST_P(obj) * RUBY_Qtrue; } /** * @cond INTERNAL_MACRO * See [ruby-dev:27513] for the following macros. */ #define RUBY_Qfalse RBIMPL_CAST((VALUE)RUBY_Qfalse) #define RUBY_Qtrue RBIMPL_CAST((VALUE)RUBY_Qtrue) #define RUBY_Qnil RBIMPL_CAST((VALUE)RUBY_Qnil) #define RUBY_Qundef RBIMPL_CAST((VALUE)RUBY_Qundef) /** @endcond */ #endif /* RBIMPL_SPECIAL_CONSTS_H */ include/ruby/internal/event.h 0000644 00000014326 15152150477 0012273 0 ustar 00 #ifndef RBIMPL_EVENT_H /*-*-C++-*-vi:se ft=cpp:*/ #define RBIMPL_EVENT_H /** * @file * @author Ruby developers <ruby-core@ruby-lang.org> * @copyright This file is a part of the programming language Ruby. * Permission is hereby granted, to either redistribute and/or * modify this file, provided that the conditions mentioned in the * file COPYING are met. Consult the file for details. * @warning Symbols prefixed with either `RBIMPL` or `rbimpl` are * implementation details. Don't take them as canon. They could * rapidly appear then vanish. The name (path) of this header file * is also an implementation detail. Do not expect it to persist * at the place it is now. Developers are free to move it anywhere * anytime at will. * @note To ruby-core: remember that this header can be possibly * recursively included from extension libraries written in C++. * Do not expect for instance `__VA_ARGS__` is always available. * We assume C99 for ruby itself but we don't assume languages of * extension libraries. They could be written in C++98. * @brief Debugging and tracing APIs. */ #include "ruby/internal/dllexport.h" #include "ruby/internal/value.h" #ifdef HAVE_STDINT_H #include <stdint.h> #endif /* These macros are not enums because they are wider than int.*/ /** * @name Traditional set_trace_func events * * @{ */ #define RUBY_EVENT_NONE 0x0000 /**< No events. */ #define RUBY_EVENT_LINE 0x0001 /**< Encountered a new line. */ #define RUBY_EVENT_CLASS 0x0002 /**< Encountered a new class. */ #define RUBY_EVENT_END 0x0004 /**< Encountered an end of a class clause. */ #define RUBY_EVENT_CALL 0x0008 /**< A method, written in Ruby, is called. */ #define RUBY_EVENT_RETURN 0x0010 /**< Encountered a `return` statement. */ #define RUBY_EVENT_C_CALL 0x0020 /**< A method, written in C, is called. */ #define RUBY_EVENT_C_RETURN 0x0040 /**< Return from a method, written in C. */ #define RUBY_EVENT_RAISE 0x0080 /**< Encountered a `raise` statement. */ #define RUBY_EVENT_ALL 0x00ff /**< Bitmask of traditional events. */ /** @} */ /** * @name TracePoint extended events * * @{ */ #define RUBY_EVENT_B_CALL 0x0100 /**< Encountered an `yield` statement. */ #define RUBY_EVENT_B_RETURN 0x0200 /**< Encountered a `next` statement. */ #define RUBY_EVENT_THREAD_BEGIN 0x0400 /**< Encountered a new thread. */ #define RUBY_EVENT_THREAD_END 0x0800 /**< Encountered an end of a thread. */ #define RUBY_EVENT_FIBER_SWITCH 0x1000 /**< Encountered a `Fiber#yield`. */ #define RUBY_EVENT_SCRIPT_COMPILED 0x2000 /**< Encountered an `eval`. */ #define RUBY_EVENT_RESCUE 0x4000 /**< Encountered a `rescue` statement. */ #define RUBY_EVENT_TRACEPOINT_ALL 0xffff /**< Bitmask of extended events. */ /** @} */ /** * @name Special events * * @internal * * These bits are actually used internally. See vm_core.h if you are curious. * * @endinternal * * @{ */ #define RUBY_EVENT_RESERVED_FOR_INTERNAL_USE 0x030000 /**< Opaque bits. */ /** @} */ /** * @name Internal events * * @shyouhei's understanding is that some of them are visible from extension * libraries because of `ext/objspace`. But it seems that doesn't describe * everything? The ultimate reason why they are here remains unclear. * * @{ */ #define RUBY_INTERNAL_EVENT_SWITCH 0x040000 /**< Thread switched. */ #define RUBY_EVENT_SWITCH 0x040000 /**< @old{RUBY_INTERNAL_EVENT_SWITCH} */ /* 0x080000 */ #define RUBY_INTERNAL_EVENT_NEWOBJ 0x100000 /**< Object allocated. */ #define RUBY_INTERNAL_EVENT_FREEOBJ 0x200000 /**< Object swept. */ #define RUBY_INTERNAL_EVENT_GC_START 0x400000 /**< GC started. */ #define RUBY_INTERNAL_EVENT_GC_END_MARK 0x800000 /**< GC ended mark phase. */ #define RUBY_INTERNAL_EVENT_GC_END_SWEEP 0x1000000 /**< GC ended sweep phase. */ #define RUBY_INTERNAL_EVENT_GC_ENTER 0x2000000 /**< `gc_enter()` is called. */ #define RUBY_INTERNAL_EVENT_GC_EXIT 0x4000000 /**< `gc_exit()` is called. */ #define RUBY_INTERNAL_EVENT_OBJSPACE_MASK 0x7f00000 /**< Bitmask of GC events. */ #define RUBY_INTERNAL_EVENT_MASK 0xffff0000 /**< Bitmask of internal events. */ /** @} */ /** * Represents event(s). As the name implies events are bit flags. */ typedef uint32_t rb_event_flag_t; /** * Type of event hooks. When an event happens registered functions are kicked * with appropriate parameters. * * @param[in] evflag The kind of event that happened. * @param[in] data The `data` passed to rb_add_event_hook(). * @param[in] self Current receiver. * @param[in] mid Name of the current method. * @param[in] klass Current class. */ typedef void (*rb_event_hook_func_t)(rb_event_flag_t evflag, VALUE data, VALUE self, ID mid, VALUE klass); /** * @private * * @deprecated This macro once was a thing in the old days, but makes no sense * any longer today. Exists here for backwards compatibility * only. You can safely forget about it. */ #define RB_EVENT_HOOKS_HAVE_CALLBACK_DATA 1 RBIMPL_SYMBOL_EXPORT_BEGIN() /** * Registers an event hook function. * * @param[in] func A callback. * @param[in] events A set of events that `func` should run. * @param[in] data Passed as-is to `func`. */ void rb_add_event_hook(rb_event_hook_func_t func, rb_event_flag_t events, VALUE data); /** * Removes the passed function from the list of event hooks. * * @param[in] func A callback. * @return Number of deleted event hooks. * @note As multiple events can share the same `func` it is quite * possible for the return value to become more than one. * * @internal * * @shyouhei doesn't know if this is an Easter egg or an official feature, but * you can pass 0 to the argument. That effectively swipes everything out from * the hook list. */ int rb_remove_event_hook(rb_event_hook_func_t func); RBIMPL_SYMBOL_EXPORT_END() #endif /* RBIMPL_EVENT_H */ include/ruby/internal/static_assert.h 0000644 00000006217 15152150477 0014022 0 ustar 00 #ifndef RBIMPL_STATIC_ASSERT_H /*-*-C++-*-vi:se ft=cpp:*/ #define RBIMPL_STATIC_ASSERT_H /** * @file * @author Ruby developers <ruby-core@ruby-lang.org> * @copyright This file is a part of the programming language Ruby. * Permission is hereby granted, to either redistribute and/or * modify this file, provided that the conditions mentioned in the * file COPYING are met. Consult the file for details. * @warning Symbols prefixed with either `RBIMPL` or `rbimpl` are * implementation details. Don't take them as canon. They could * rapidly appear then vanish. The name (path) of this header file * is also an implementation detail. Do not expect it to persist * at the place it is now. Developers are free to move it anywhere * anytime at will. * @note To ruby-core: remember that this header can be possibly * recursively included from extension libraries written in C++. * Do not expect for instance `__VA_ARGS__` is always available. * We assume C99 for ruby itself but we don't assume languages of * extension libraries. They could be written in C++98. * @brief Defines #RBIMPL_STATIC_ASSERT. */ #include <assert.h> #include "ruby/internal/has/extension.h" #include "ruby/internal/compiler_since.h" /** @cond INTERNAL_MACRO */ #if defined(__cplusplus) && defined(__cpp_static_assert) # /* https://isocpp.org/std/standing-documents/sd-6-sg10-feature-test-recommendations */ # define RBIMPL_STATIC_ASSERT0 static_assert #elif defined(__cplusplus) && RBIMPL_COMPILER_SINCE(MSVC, 16, 0, 0) # define RBIMPL_STATIC_ASSERT0 static_assert #elif defined(__INTEL_CXX11_MODE__) # define RBIMPL_STATIC_ASSERT0 static_assert #elif defined(__cplusplus) && __cplusplus >= 201103L # define RBIMPL_STATIC_ASSERT0 static_assert #elif defined(__cplusplus) && RBIMPL_HAS_EXTENSION(cxx_static_assert) # define RBIMPL_STATIC_ASSERT0 __extension__ static_assert #elif defined(__GXX_EXPERIMENTAL_CXX0X__) && __GXX_EXPERIMENTAL_CXX0X__ # define RBIMPL_STATIC_ASSERT0 __extension__ static_assert #elif defined(__STDC_VERSION__) && RBIMPL_HAS_EXTENSION(c_static_assert) # define RBIMPL_STATIC_ASSERT0 __extension__ _Static_assert #elif defined(__STDC_VERSION__) && RBIMPL_COMPILER_SINCE(GCC, 4, 6, 0) # define RBIMPL_STATIC_ASSERT0 __extension__ _Static_assert #elif defined(static_assert) # /* Take <assert.h> definition */ # define RBIMPL_STATIC_ASSERT0 static_assert #endif /** @endcond */ /** * @brief Wraps (or simulates) `static_assert` * @param name Valid C/C++ identifier, describing the assertion. * @param expr Expression to assert. * @note `name` shall not be a string literal. */ #if defined(__DOXYGEN__) # define RBIMPL_STATIC_ASSERT static_assert #elif defined(RBIMPL_STATIC_ASSERT0) # define RBIMPL_STATIC_ASSERT(name, expr) \ RBIMPL_STATIC_ASSERT0(expr, # name ": " # expr) #else # define RBIMPL_STATIC_ASSERT(name, expr) \ typedef int static_assert_ ## name ## _check[1 - 2 * !(expr)] #endif #endif /* RBIMPL_STATIC_ASSERT_H */ include/ruby/internal/stdbool.h 0000644 00000004007 15152150477 0012613 0 ustar 00 #ifndef RBIMPL_STDBOOL_H /*-*-C++-*-vi:se ft=cpp:*/ #define RBIMPL_STDBOOL_H /** * @file * @author Ruby developers <ruby-core@ruby-lang.org> * @copyright This file is a part of the programming language Ruby. * Permission is hereby granted, to either redistribute and/or * modify this file, provided that the conditions mentioned in the * file COPYING are met. Consult the file for details. * @warning Symbols prefixed with either `RBIMPL` or `rbimpl` are * implementation details. Don't take them as canon. They could * rapidly appear then vanish. The name (path) of this header file * is also an implementation detail. Do not expect it to persist * at the place it is now. Developers are free to move it anywhere * anytime at will. * @note To ruby-core: remember that this header can be possibly * recursively included from extension libraries written in C++. * Do not expect for instance `__VA_ARGS__` is always available. * We assume C99 for ruby itself but we don't assume languages of * extension libraries. They could be written in C++98. * @brief C99 shim for <stdbool.h> */ #include "ruby/internal/config.h" #if defined(__bool_true_false_are_defined) # /* Take that. */ #elif defined(__cplusplus) # /* bool is a keyword in C++. */ # if defined(HAVE_STDBOOL_H) && (__cplusplus >= 201103L) # include <cstdbool> # endif # # ifndef __bool_true_false_are_defined # define __bool_true_false_are_defined # endif #elif defined(HAVE_STDBOOL_H) # /* Take stdbool.h definition. */ # include <stdbool.h> #elif !defined(HAVE__BOOL) typedef unsigned char _Bool; # /* See also http://www.open-std.org/jtc1/sc22/wg14/www/docs/n2229.htm */ # define bool _Bool # define true ((_Bool)+1) # define false ((_Bool)+0) # define __bool_true_false_are_defined #endif #endif /* RBIMPL_STDBOOL_H */ include/ruby/internal/compiler_is/intel.h 0000644 00000004011 15152150477 0014560 0 ustar 00 #ifndef RBIMPL_COMPILER_IS_INTEL_H /*-*-C++-*-vi:se ft=cpp:*/ #define RBIMPL_COMPILER_IS_INTEL_H /** * @author Ruby developers <ruby-core@ruby-lang.org> * @copyright This file is a part of the programming language Ruby. * Permission is hereby granted, to either redistribute and/or * modify this file, provided that the conditions mentioned in the * file COPYING are met. Consult the file for details. * @warning Symbols prefixed with either `RBIMPL` or `rbimpl` are * implementation details. Don't take them as canon. They could * rapidly appear then vanish. The name (path) of this header file * is also an implementation detail. Do not expect it to persist * at the place it is now. Developers are free to move it anywhere * anytime at will. * @note To ruby-core: remember that this header can be possibly * recursively included from extension libraries written in C++. * Do not expect for instance `__VA_ARGS__` is always available. * We assume C99 for ruby itself but we don't assume languages of * extension libraries. They could be written in C++98. * @brief Defines RBIMPL_COMPILER_IS_Intel. */ #if ! defined(__INTEL_COMPILER) # define RBIMPL_COMPILER_IS_Intel 0 #elif ! defined(__INTEL_COMPILER_UPDATE) # define RBIMPL_COMPILER_IS_Intel 1 # /* __INTEL_COMPILER = XXYZ */ # define RBIMPL_COMPILER_VERSION_MAJOR (__INTEL_COMPILER / 100) # define RBIMPL_COMPILER_VERSION_MINOR (__INTEL_COMPILER % 100 / 10) # define RBIMPL_COMPILER_VERSION_PATCH (__INTEL_COMPILER % 10) #else # define RBIMPL_COMPILER_IS_Intel 1 # /* __INTEL_COMPILER = XXYZ */ # define RBIMPL_COMPILER_VERSION_MAJOR (__INTEL_COMPILER / 100) # define RBIMPL_COMPILER_VERSION_MINOR (__INTEL_COMPILER % 100 / 10) # define RBIMPL_COMPILER_VERSION_PATCH __INTEL_COMPILER_UPDATE #endif #endif /* RBIMPL_COMPILER_IS_INTEL_H */ include/ruby/internal/compiler_is/apple.h 0000644 00000003732 15152150477 0014557 0 ustar 00 #ifndef RBIMPL_COMPILER_IS_APPLE_H /*-*-C++-*-vi:se ft=cpp:*/ #define RBIMPL_COMPILER_IS_APPLE_H /** * @author Ruby developers <ruby-core@ruby-lang.org> * @copyright This file is a part of the programming language Ruby. * Permission is hereby granted, to either redistribute and/or * modify this file, provided that the conditions mentioned in the * file COPYING are met. Consult the file for details. * @warning Symbols prefixed with either `RBIMPL` or `rbimpl` are * implementation details. Don't take them as canon. They could * rapidly appear then vanish. The name (path) of this header file * is also an implementation detail. Do not expect it to persist * at the place it is now. Developers are free to move it anywhere * anytime at will. * @note To ruby-core: remember that this header can be possibly * recursively included from extension libraries written in C++. * Do not expect for instance `__VA_ARGS__` is always available. * We assume C99 for ruby itself but we don't assume languages of * extension libraries. They could be written in C++98. * @brief Defines RBIMPL_COMPILER_IS_Apple. * * Apple ships clang. Problem is, its `__clang_major__` etc. are not the * upstream LLVM version, but XCode's. We have to think Apple's is distinct * from LLVM's, when it comes to compiler detection business in this header * file. */ #if ! defined(__clang__) # define RBIMPL_COMPILER_IS_Apple 0 #elif ! defined(__apple_build_version__) # define RBIMPL_COMPILER_IS_Apple 0 #else # define RBIMPL_COMPILER_IS_Apple 1 # define RBIMPL_COMPILER_VERSION_MAJOR __clang_major__ # define RBIMPL_COMPILER_VERSION_MINOR __clang_minor__ # define RBIMPL_COMPILER_VERSION_PATCH __clang_patchlevel__ #endif #endif /* RBIMPL_COMPILER_IS_APPLE_H */ include/ruby/internal/compiler_is/msvc.h 0000644 00000004736 15152150477 0014433 0 ustar 00 #ifndef RBIMPL_COMPILER_IS_MSVC_H /*-*-C++-*-vi:se ft=cpp:*/ #define RBIMPL_COMPILER_IS_MSVC_H /** * @author Ruby developers <ruby-core@ruby-lang.org> * @copyright This file is a part of the programming language Ruby. * Permission is hereby granted, to either redistribute and/or * modify this file, provided that the conditions mentioned in the * file COPYING are met. Consult the file for details. * @warning Symbols prefixed with either `RBIMPL` or `rbimpl` are * implementation details. Don't take them as canon. They could * rapidly appear then vanish. The name (path) of this header file * is also an implementation detail. Do not expect it to persist * at the place it is now. Developers are free to move it anywhere * anytime at will. * @note To ruby-core: remember that this header can be possibly * recursively included from extension libraries written in C++. * Do not expect for instance `__VA_ARGS__` is always available. * We assume C99 for ruby itself but we don't assume languages of * extension libraries. They could be written in C++98. * @brief Defines RBIMPL_COMPILER_IS_MSVC. */ #include "ruby/internal/compiler_is/clang.h" #include "ruby/internal/compiler_is/intel.h" #if ! defined(_MSC_VER) # define RBIMPL_COMPILER_IS_MSVC 0 #elif RBIMPL_COMPILER_IS(Clang) # define RBIMPL_COMPILER_IS_MSVC 0 #elif RBIMPL_COMPILER_IS(Intel) # define RBIMPL_COMPILER_IS_MSVC 0 #elif _MSC_VER >= 1400 # define RBIMPL_COMPILER_IS_MSVC 1 # /* _MSC_FULL_VER = XXYYZZZZZ */ # define RBIMPL_COMPILER_VERSION_MAJOR (_MSC_FULL_VER / 10000000) # define RBIMPL_COMPILER_VERSION_MINOR (_MSC_FULL_VER % 10000000 / 100000) # define RBIMPL_COMPILER_VERSION_PATCH (_MSC_FULL_VER % 100000) #elif defined(_MSC_FULL_VER) # define RBIMPL_COMPILER_IS_MSVC 1 # /* _MSC_FULL_VER = XXYYZZZZ */ # define RBIMPL_COMPILER_VERSION_MAJOR (_MSC_FULL_VER / 1000000) # define RBIMPL_COMPILER_VERSION_MINOR (_MSC_FULL_VER % 1000000 / 10000) # define RBIMPL_COMPILER_VERSION_PATCH (_MSC_FULL_VER % 10000) #else # define RBIMPL_COMPILER_IS_MSVC 1 # /* _MSC_VER = XXYY */ # define RBIMPL_COMPILER_VERSION_MAJOR (_MSC_VER / 100) # define RBIMPL_COMPILER_VERSION_MINOR (_MSC_VER % 100) # define RBIMPL_COMPILER_VERSION_PATCH 0 #endif #endif /* RBIMPL_COMPILER_IS_MSVC_H */ include/ruby/internal/compiler_is/clang.h 0000644 00000003403 15152150477 0014535 0 ustar 00 #ifndef RBIMPL_COMPILER_IS_CLANG_H /*-*-C++-*-vi:se ft=cpp:*/ #define RBIMPL_COMPILER_IS_CLANG_H /** * @author Ruby developers <ruby-core@ruby-lang.org> * @copyright This file is a part of the programming language Ruby. * Permission is hereby granted, to either redistribute and/or * modify this file, provided that the conditions mentioned in the * file COPYING are met. Consult the file for details. * @warning Symbols prefixed with either `RBIMPL` or `rbimpl` are * implementation details. Don't take them as canon. They could * rapidly appear then vanish. The name (path) of this header file * is also an implementation detail. Do not expect it to persist * at the place it is now. Developers are free to move it anywhere * anytime at will. * @note To ruby-core: remember that this header can be possibly * recursively included from extension libraries written in C++. * Do not expect for instance `__VA_ARGS__` is always available. * We assume C99 for ruby itself but we don't assume languages of * extension libraries. They could be written in C++98. * @brief Defines RBIMPL_COMPILER_IS_Clang. */ #include "ruby/internal/compiler_is/apple.h" #if ! defined(__clang__) # define RBIMPL_COMPILER_IS_Clang 0 #elif RBIMPL_COMPILER_IS(Apple) # define RBIMPL_COMPILER_IS_Clang 0 #else # define RBIMPL_COMPILER_IS_Clang 1 # define RBIMPL_COMPILER_VERSION_MAJOR __clang_major__ # define RBIMPL_COMPILER_VERSION_MINOR __clang_minor__ # define RBIMPL_COMPILER_VERSION_PATCH __clang_patchlevel__ #endif #endif /* RBIMPL_COMPILER_IS_CLANG_H */ include/ruby/internal/compiler_is/sunpro.h 0000644 00000005223 15152150500 0014764 0 ustar 00 #ifndef RBIMPL_COMPILER_IS_SUNPRO_H /*-*-C++-*-vi:se ft=cpp:*/ #define RBIMPL_COMPILER_IS_SUNPRO_H /** * @author Ruby developers <ruby-core@ruby-lang.org> * @copyright This file is a part of the programming language Ruby. * Permission is hereby granted, to either redistribute and/or * modify this file, provided that the conditions mentioned in the * file COPYING are met. Consult the file for details. * @warning Symbols prefixed with either `RBIMPL` or `rbimpl` are * implementation details. Don't take them as canon. They could * rapidly appear then vanish. The name (path) of this header file * is also an implementation detail. Do not expect it to persist * at the place it is now. Developers are free to move it anywhere * anytime at will. * @note To ruby-core: remember that this header can be possibly * recursively included from extension libraries written in C++. * Do not expect for instance `__VA_ARGS__` is always available. * We assume C99 for ruby itself but we don't assume languages of * extension libraries. They could be written in C++98. * @brief Defines RBIMPL_COMPILER_IS_SunPro. */ #if ! (defined(__SUNPRO_C) || defined(__SUNPRO_CC)) # define RBIMPL_COMPILER_IS_SunPro 0 #elif defined(__SUNPRO_C) && __SUNPRO_C >= 0x5100 # define RBIMPL_COMPILER_IS_SunPro 1 # /* __SUNPRO_C = 0xXYYZ */ # define RBIMPL_COMPILER_VERSION_MAJOR (__SUNPRO_C >> 12) # define RBIMPL_COMPILER_VERSION_MINOR ((__SUNPRO_C >> 8 & 0xF) * 10 + (__SUNPRO_C >> 4 & 0xF)) # define RBIMPL_COMPILER_VERSION_PATCH (__SUNPRO_C & 0xF) #elif defined(__SUNPRO_CC) && __SUNPRO_CC >= 0x5100 # define RBIMPL_COMPILER_IS_SunPro 1 # /* __SUNPRO_CC = 0xXYYZ */ # define RBIMPL_COMPILER_VERSION_MAJOR (__SUNPRO_CC >> 12) # define RBIMPL_COMPILER_VERSION_MINOR ((__SUNPRO_CC >> 8 & 0xF) * 10 + (__SUNPRO_CC >> 4 & 0xF)) # define RBIMPL_COMPILER_VERSION_PATCH (__SUNPRO_CC & 0xF) #elif defined(__SUNPRO_C) # define RBIMPL_COMPILER_IS_SunPro 1 # /* __SUNPRO_C = 0xXYZ */ # define RBIMPL_COMPILER_VERSION_MAJOR (__SUNPRO_C >> 8) # define RBIMPL_COMPILER_VERSION_MINOR (__SUNPRO_C >> 4 & 0xF) # define RBIMPL_COMPILER_VERSION_PATCH (__SUNPRO_C & 0xF) #else # define RBIMPL_COMPILER_IS_SunPro 1 # /* __SUNPRO_CC = 0xXYZ */ # define RBIMPL_COMPILER_VERSION_MAJOR (__SUNPRO_CC >> 8) # define RBIMPL_COMPILER_VERSION_MINOR (__SUNPRO_CC >> 4 & 0xF) # define RBIMPL_COMPILER_VERSION_PATCH (__SUNPRO_CC & 0xF) #endif #endif /* RBIMPL_COMPILER_IS_SUNPRO_H */ include/ruby/internal/compiler_is/gcc.h 0000644 00000003715 15152150500 0014176 0 ustar 00 #ifndef RBIMPL_COMPILER_IS_GCC_H /*-*-C++-*-vi:se ft=cpp:*/ #define RBIMPL_COMPILER_IS_GCC_H /** * @author Ruby developers <ruby-core@ruby-lang.org> * @copyright This file is a part of the programming language Ruby. * Permission is hereby granted, to either redistribute and/or * modify this file, provided that the conditions mentioned in the * file COPYING are met. Consult the file for details. * @warning Symbols prefixed with either `RBIMPL` or `rbimpl` are * implementation details. Don't take them as canon. They could * rapidly appear then vanish. The name (path) of this header file * is also an implementation detail. Do not expect it to persist * at the place it is now. Developers are free to move it anywhere * anytime at will. * @note To ruby-core: remember that this header can be possibly * recursively included from extension libraries written in C++. * Do not expect for instance `__VA_ARGS__` is always available. * We assume C99 for ruby itself but we don't assume languages of * extension libraries. They could be written in C++98. * @brief Defines RBIMPL_COMPILER_IS_GCC. */ #include "ruby/internal/compiler_is/apple.h" #include "ruby/internal/compiler_is/clang.h" #include "ruby/internal/compiler_is/intel.h" #if ! defined(__GNUC__) # define RBIMPL_COMPILER_IS_GCC 0 #elif RBIMPL_COMPILER_IS(Apple) # define RBIMPL_COMPILER_IS_GCC 0 #elif RBIMPL_COMPILER_IS(Clang) # define RBIMPL_COMPILER_IS_GCC 0 #elif RBIMPL_COMPILER_IS(Intel) # define RBIMPL_COMPILER_IS_GCC 0 #else # define RBIMPL_COMPILER_IS_GCC 1 # define RBIMPL_COMPILER_VERSION_MAJOR __GNUC__ # define RBIMPL_COMPILER_VERSION_MINOR __GNUC_MINOR__ # define RBIMPL_COMPILER_VERSION_PATCH __GNUC_PATCHLEVEL__ #endif #endif /* RBIMPL_COMPILER_IS_GCC_H */ include/ruby/internal/encoding/re.h 0000644 00000004356 15152150500 0013333 0 ustar 00 #ifndef RUBY_INTERNAL_ENCODING_RE_H /*-*-C++-*-vi:se ft=cpp:*/ #define RUBY_INTERNAL_ENCODING_RE_H /** * @file * @author Ruby developers <ruby-core@ruby-lang.org> * @copyright This file is a part of the programming language Ruby. * Permission is hereby granted, to either redistribute and/or * modify this file, provided that the conditions mentioned in the * file COPYING are met. Consult the file for details. * @warning Symbols prefixed with either `RBIMPL` or `rbimpl` are * implementation details. Don't take them as canon. They could * rapidly appear then vanish. The name (path) of this header file * is also an implementation detail. Do not expect it to persist * at the place it is now. Developers are free to move it anywhere * anytime at will. * @note To ruby-core: remember that this header can be possibly * recursively included from extension libraries written in C++. * Do not expect for instance `__VA_ARGS__` is always available. * We assume C99 for ruby itself but we don't assume languages of * extension libraries. They could be written in C++98. * @brief Routines to manipulate encodings of symbols. */ #include "ruby/internal/dllexport.h" #include "ruby/internal/encoding/encoding.h" #include "ruby/internal/value.h" RBIMPL_SYMBOL_EXPORT_BEGIN() /** * Identical to rb_reg_new(), except it additionally takes an encoding. * * @param[in] ptr A memory region of `len` bytes length. * @param[in] len Length of `ptr`, in bytes, not including the * terminating NUL character. * @param[in] enc Encoding of `ptr`. * @param[in] opts Options e.g. ONIG_OPTION_MULTILINE. * @exception rb_eRegexpError Failed to compile `ptr`. * @return An allocated new instance of ::rb_cRegexp, of `enc` encoding, * whose expression is compiled according to `ptr`. */ VALUE rb_enc_reg_new(const char *ptr, long len, rb_encoding *enc, int opts); RBIMPL_SYMBOL_EXPORT_END() #endif /* RUBY_INTERNAL_ENCODING_RE_H */ include/ruby/internal/encoding/pathname.h 0000644 00000015420 15152150500 0014514 0 ustar 00 #ifndef RUBY_INTERNAL_ENCODING_PATHNAME_H /*-*-C++-*-vi:se ft=cpp:*/ #define RUBY_INTERNAL_ENCODING_PATHNAME_H /** * @file * @author Ruby developers <ruby-core@ruby-lang.org> * @copyright This file is a part of the programming language Ruby. * Permission is hereby granted, to either redistribute and/or * modify this file, provided that the conditions mentioned in the * file COPYING are met. Consult the file for details. * @warning Symbols prefixed with either `RBIMPL` or `rbimpl` are * implementation details. Don't take them as canon. They could * rapidly appear then vanish. The name (path) of this header file * is also an implementation detail. Do not expect it to persist * at the place it is now. Developers are free to move it anywhere * anytime at will. * @note To ruby-core: remember that this header can be possibly * recursively included from extension libraries written in C++. * Do not expect for instance `__VA_ARGS__` is always available. * We assume C99 for ruby itself but we don't assume languages of * extension libraries. They could be written in C++98. * @brief Routines to manipulate encodings of pathnames. */ #include "ruby/internal/attr/nonnull.h" #include "ruby/internal/dllexport.h" #include "ruby/internal/encoding/encoding.h" #include "ruby/internal/value.h" RBIMPL_SYMBOL_EXPORT_BEGIN() RBIMPL_ATTR_NONNULL(()) /** * Returns a path component directly adjacent to the passed pointer. * * ``` * "/multi/byte/encoded/pathname.txt" * ^ ^ ^ * | | +--- end * | +--- @return * +--- path * ``` * * @param[in] path Where to start scanning. * @param[in] end End of the path string. * @param[in] enc Encoding of the string. * @return A pointer in the passed string where the next path component * resides, or `end` if there is no next path component. */ char *rb_enc_path_next(const char *path, const char *end, rb_encoding *enc); RBIMPL_ATTR_NONNULL(()) /** * Seeks for non-prefix part of a pathname. This can be a no-op when the OS * has no such concept like a path prefix. But there are OSes where path * prefixes do exist. * * ``` * "C:\multi\byte\encoded\pathname.txt" * ^ ^ ^ * | | +--- end * | +--- @return * +--- path * ``` * * @param[in] path Where to start scanning. * @param[in] end End of the path string. * @param[in] enc Encoding of the string. * @return A pointer in the passed string where non-prefix part starts, or * `path` if the OS does not have path prefix. */ char *rb_enc_path_skip_prefix(const char *path, const char *end, rb_encoding *enc); RBIMPL_ATTR_NONNULL(()) /** * Returns the last path component. * * ``` * "/multi/byte/encoded/pathname.txt" * ^ ^ ^ * | | +--- end * | +--- @return * +--- path * ``` * * @param[in] path Where to start scanning. * @param[in] end End of the path string. * @param[in] enc Encoding of the string. * @return A pointer in the passed string where the last path component * resides, or `end` if there is no more path component. */ char *rb_enc_path_last_separator(const char *path, const char *end, rb_encoding *enc); RBIMPL_ATTR_NONNULL(()) /** * This just returns the passed end basically. It makes difference in case the * passed string ends with tons of path separators like the following: * * ``` * "/path/that/ends/with/lots/of/slashes//////////////" * ^ ^ ^ * | | +--- end * | +--- @return * +--- path * ``` * * @param[in] path Where to start scanning. * @param[in] end End of the path string. * @param[in] enc Encoding of the string. * @return A pointer in the passed string where the trailing path * separators start, or `end` if there is no trailing path * separators. * * @internal * * It seems this function was introduced to mimic what POSIX says about * `basename(3)`. */ char *rb_enc_path_end(const char *path, const char *end, rb_encoding *enc); RBIMPL_ATTR_NONNULL((1, 4)) /** * Our own encoding-aware version of `basename(3)`. Normally, this function * returns the last path component of the given name. However in case the * passed name ends with a path separator, it returns the name of the * directory, not the last (empty) component. Also if the passed name is a * root directory, it returns that root directory. Note however that Windows * filesystem have drive letters, which this function does not return. * * @param[in] name Target path. * @param[out] baselen Return buffer. * @param[in,out] alllen Number of bytes of `name`. * @param[enc] enc Encoding of `name`. * @return The rightmost component of `name`. * @post `baselen`, if passed, is updated to be the number of bytes * of the returned basename. * @post `alllen`, if passed, is updated to be the number of bytes of * strings not considered as the basename. */ const char *ruby_enc_find_basename(const char *name, long *baselen, long *alllen, rb_encoding *enc); RBIMPL_ATTR_NONNULL((1, 3)) /** * Our own encoding-aware version of `extname`. This function first applies * rb_enc_path_last_separator() to the passed name and only concerns its return * value (ignores any parent directories). This function returns complicated * results: * * ```CXX * auto path = "..."; * auto len = strlen(path); * auto ret = ruby_enc_find_extname(path, &len, rb_ascii8bit_encoding()); * * switch(len) { * case 0: * if (ret == 0) { * // `path` is a file without extensions. * } * else { * // `path` is a dotfile. * // `ret` is the file's name. * } * break; * * case 1: * // `path` _ends_ with a dot. * // `ret` is that dot. * break; * * default: * // `path` has an extension. * // `ret` is that extension. * } * ``` * * @param[in] name Target path. * @param[in,out] len Number of bytes of `name`. * @param[in] enc Encoding of `name`. * @return See above. * @post `len`, if passed, is updated (see above). */ const char *ruby_enc_find_extname(const char *name, long *len, rb_encoding *enc); RBIMPL_SYMBOL_EXPORT_END() #endif /* RUBY_INTERNAL_ENCODING_PATHNAME_H */ include/ruby/internal/encoding/encoding.h 0000644 00000107536 15152150500 0014517 0 ustar 00 #ifndef RUBY_INTERNAL_ENCODING_ENCODING_H /*-*-C++-*-vi:se ft=cpp:*/ #define RUBY_INTERNAL_ENCODING_ENCODING_H /** * @file * @author Ruby developers <ruby-core@ruby-lang.org> * @copyright This file is a part of the programming language Ruby. * Permission is hereby granted, to either redistribute and/or * modify this file, provided that the conditions mentioned in the * file COPYING are met. Consult the file for details. * @warning Symbols prefixed with either `RBIMPL` or `rbimpl` are * implementation details. Don't take them as canon. They could * rapidly appear then vanish. The name (path) of this header file * is also an implementation detail. Do not expect it to persist * at the place it is now. Developers are free to move it anywhere * anytime at will. * @note To ruby-core: remember that this header can be possibly * recursively included from extension libraries written in C++. * Do not expect for instance `__VA_ARGS__` is always available. * We assume C99 for ruby itself but we don't assume languages of * extension libraries. They could be written in C++98. * @brief Defines ::rb_encoding */ #include "ruby/oniguruma.h" #include "ruby/internal/attr/const.h" #include "ruby/internal/attr/deprecated.h" #include "ruby/internal/attr/noalias.h" #include "ruby/internal/attr/pure.h" #include "ruby/internal/attr/returns_nonnull.h" #include "ruby/internal/dllexport.h" #include "ruby/internal/value.h" #include "ruby/internal/core/rbasic.h" #include "ruby/internal/fl_type.h" RBIMPL_SYMBOL_EXPORT_BEGIN() /** * `Encoding` class. * * @ingroup object */ RUBY_EXTERN VALUE rb_cEncoding; /** * @private * * Bit constants used when embedding encodings into ::RBasic::flags. Extension * libraries must not bother such things. */ enum ruby_encoding_consts { /** Max possible number of embeddable encodings. */ RUBY_ENCODING_INLINE_MAX = 127, /** Where inline encodings reside. */ RUBY_ENCODING_SHIFT = (RUBY_FL_USHIFT+10), /** Bits we use to store inline encodings. */ RUBY_ENCODING_MASK = (RUBY_ENCODING_INLINE_MAX<<RUBY_ENCODING_SHIFT /* RUBY_FL_USER10..RUBY_FL_USER16 */), /** Max possible length of an encoding name. */ RUBY_ENCODING_MAXNAMELEN = 42 }; #define ENCODING_INLINE_MAX RUBY_ENCODING_INLINE_MAX /**< @old{RUBY_ENCODING_INLINE_MAX} */ #define ENCODING_SHIFT RUBY_ENCODING_SHIFT /**< @old{RUBY_ENCODING_SHIFT} */ #define ENCODING_MASK RUBY_ENCODING_MASK /**< @old{RUBY_ENCODING_MASK} */ /** * Destructively assigns the passed encoding to the passed object. The object * must be capable of having inline encoding. Using this macro needs deep * understanding of bit level object binary layout. * * @param[out] obj Target object to modify. * @param[in] ecindex Encoding in encindex format. * @post `obj`'s encoding is `encindex`. */ static inline void RB_ENCODING_SET_INLINED(VALUE obj, int encindex) { VALUE f = /* upcast */ encindex; f <<= RUBY_ENCODING_SHIFT; RB_FL_UNSET_RAW(obj, RUBY_ENCODING_MASK); RB_FL_SET_RAW(obj, f); } /** * Queries the encoding of the passed object. The encoding must be smaller * than ::RUBY_ENCODING_INLINE_MAX, which means you have some assumption on the * return value. This means the API is for internal use only. * * @param[in] obj Target object. * @return `obj`'s encoding index. */ static inline int RB_ENCODING_GET_INLINED(VALUE obj) { VALUE ret = RB_FL_TEST_RAW(obj, RUBY_ENCODING_MASK) >> RUBY_ENCODING_SHIFT; return RBIMPL_CAST((int)ret); } #define ENCODING_SET_INLINED(obj,i) RB_ENCODING_SET_INLINED(obj,i) /**< @old{RB_ENCODING_SET_INLINED} */ #define ENCODING_SET(obj,i) RB_ENCODING_SET(obj,i) /**< @old{RB_ENCODING_SET} */ #define ENCODING_GET_INLINED(obj) RB_ENCODING_GET_INLINED(obj) /**< @old{RB_ENCODING_GET_INLINED} */ #define ENCODING_GET(obj) RB_ENCODING_GET(obj) /**< @old{RB_ENCODING_GET} */ #define ENCODING_IS_ASCII8BIT(obj) RB_ENCODING_IS_ASCII8BIT(obj) /**< @old{RB_ENCODING_IS_ASCII8BIT} */ #define ENCODING_MAXNAMELEN RUBY_ENCODING_MAXNAMELEN /**< @old{RUBY_ENCODING_MAXNAMELEN} */ /** * The type of encoding. Our design here is we take Oniguruma/Onigmo's * multilingualisation schema as our base data structure. */ typedef const OnigEncodingType rb_encoding; RBIMPL_ATTR_NOALIAS() /** * Converts a character option to its encoding. It only supports a very * limited set of Japanese encodings due to its Japanese origin. Ruby still * has this in-core for backwards compatibility. But new codes must not bother * such concept like one-character encoding option. Consider deprecated in * practice. * * @param[in] c One of `['n', 'e', 's', 'u', 'i', 'x', 'm']`. * @param[out] option Return buffer. * @param[out] kcode Return buffer. * @retval 1 `c` understood properly. * @retval 0 `c` is not understood. * @post `option` is a ::OnigOptionType. * @post `kcode` is an enum `ruby_preserved_encindex`. * * @internal * * `kcode` is opaque because `ruby_preserved_encindex` is not visible from * extension libraries. But who cares? */ int rb_char_to_option_kcode(int c, int *option, int *kcode); /** * Creates a new "dummy" encoding. Roughly speaking, an encoding is dummy when * it is stateful. Notable example of dummy encoding are those defined in * ISO/IEC 2022 * * @param[in] name Name of the creating encoding. * @exception rb_eArgError Duplicated or malformed `name`. * @return New dummy encoding's index. * @post Encoding named `name` is created, whose index is the return * value. */ int rb_define_dummy_encoding(const char *name); RBIMPL_ATTR_PURE() /** * Queries if the passed encoding is dummy. * * @param[in] enc Encoding in question. * @retval 1 It is. * @retval 0 It isn't. */ int rb_enc_dummy_p(rb_encoding *enc); RBIMPL_ATTR_PURE() /** * Queries the index of the encoding. An encoding's index is a Ruby-local * concept. It is a (sequential) number assigned to each encoding. * * @param[in] enc Encoding in question. * @return Its index. * @note You can pass null pointers to this function. It is equivalent * to rb_usascii_encindex() then. */ int rb_enc_to_index(rb_encoding *enc); /** * Queries the index of the encoding of the passed object, if any. * * @param[in] obj Object in question. * @retval -1 `obj` is incapable of having an encoding. * @retval otherwise `obj`'s encoding's index. */ int rb_enc_get_index(VALUE obj); /** * @alias{rb_enc_get_index} * * @internal * * Implementation wise this is not a verbatim alias of rb_enc_get_index(). But * the API is consistent. Don't bother. */ static inline int RB_ENCODING_GET(VALUE obj) { int encindex = RB_ENCODING_GET_INLINED(obj); if (encindex == RUBY_ENCODING_INLINE_MAX) { return rb_enc_get_index(obj); } else { return encindex; } } /** * Destructively assigns an encoding (via its index) to an object. * * @param[out] obj Object in question. * @param[in] encindex An encoding index. * @exception rb_eFrozenError `obj` is frozen. * @exception rb_eArgError `obj` is incapable of having an encoding. * @exception rb_eEncodingError `encindex` is out of bounds. * @exception rb_eLoadError Failed to load the encoding. */ void rb_enc_set_index(VALUE obj, int encindex); /** @alias{rb_enc_set_index} */ static inline void RB_ENCODING_SET(VALUE obj, int encindex) { rb_enc_set_index(obj, encindex); } /** * This is #RB_ENCODING_SET + RB_ENC_CODERANGE_SET combo. The object must be * capable of having inline encoding. Using this macro needs deep * understanding of bit level object binary layout. * * @param[out] obj Target object. * @param[in] encindex Encoding in encindex format. * @param[in] cr An enum ::ruby_coderange_type. * @post `obj`'s encoding is `encindex`. * @post `obj`'s code range is `cr`. */ static inline void RB_ENCODING_CODERANGE_SET(VALUE obj, int encindex, enum ruby_coderange_type cr) { RB_ENCODING_SET(obj, encindex); RB_ENC_CODERANGE_SET(obj, cr); } RBIMPL_ATTR_PURE() /** * Queries if the passed object can have its encoding. * * @param[in] obj Object in question. * @retval 1 It can. * @retval 0 It cannot. */ int rb_enc_capable(VALUE obj); /** * Queries the index of the encoding. * * @param[in] name Name of the encoding to find. * @exception rb_eArgError No such encoding named `name`. * @retval -1 `name` exists, but unable to load. * @retval otherwise Index of encoding named `name`. */ int rb_enc_find_index(const char *name); /** * Registers an "alias" name. In the wild, an encoding can be called using * multiple names. For instance an encoding known as `"CP932"` is also called * `"SJIS"` on occasions. This API registers such relationships. * * @param[in] alias New name. * @param[in] orig Old name. * @exception rb_eArgError `alias` is duplicated or malformed. * @retval -1 Failed to load `orig`. * @retval otherwise The index of `orig` and `alias`. * @post `alias` is a synonym of `orig`. They refer to the identical * encoding. */ int rb_enc_alias(const char *alias, const char *orig); /** * Obtains a encoding index from a wider range of objects (than * rb_enc_find_index()). * * @param[in] obj An ::rb_cEncoding, or its name in ::rb_cString. * @retval -1 `obj` is unexpected type/contents. * @retval otherwise Index corresponding to `obj`. */ int rb_to_encoding_index(VALUE obj); /** * Identical to rb_find_encoding(), except it raises an exception instead of * returning NULL. * * @param[in] obj An ::rb_cEncoding, or its name in ::rb_cString. * @exception rb_eTypeError `obj` is neither ::rb_cEncoding nor ::rb_cString. * @exception rb_eArgError `obj` is an unknown encoding name. * @return Encoding of `obj`. */ rb_encoding *rb_to_encoding(VALUE obj); /** * Identical to rb_to_encoding_index(), except the return type. * * @param[in] obj An ::rb_cEncoding, or its name in ::rb_cString. * @exception rb_eTypeError `obj` is neither ::rb_cEncoding nor ::rb_cString. * @retval NULL No such encoding. * @return otherwise Encoding of `obj`. */ rb_encoding *rb_find_encoding(VALUE obj); /** * Identical to rb_enc_get_index(), except the return type. * * @param[in] obj Object in question. * @retval NULL Obj is incapable of having an encoding. * @retval otherwise `obj`'s encoding. */ rb_encoding *rb_enc_get(VALUE obj); /** * Look for the "common" encoding between the two. One character can or cannot * be expressed depending on an encoding. This function finds the super-set of * encodings that satisfy contents of both arguments. If that is impossible * returns NULL. * * @param[in] str1 An object. * @param[in] str2 Another object. * @retval NULL No encoding can satisfy both at once. * @retval otherwise Common encoding between the two. * @note Arguments can be non-string, e.g. Regexp. */ rb_encoding *rb_enc_compatible(VALUE str1, VALUE str2); /** * Identical to rb_enc_compatible(), except it raises an exception instead of * returning NULL. * * @param[in] str1 An object. * @param[in] str2 Another object. * @exception rb_eEncCompatError No encoding can satisfy both. * @return Common encoding between the two. * @note Arguments can be non-string, e.g. Regexp. */ rb_encoding *rb_enc_check(VALUE str1,VALUE str2); /** * Identical to rb_enc_set_index(), except it additionally does contents fix-up * depending on the passed object. It for instance changes the byte length of * terminating `U+0000` according to the passed encoding. * * @param[out] obj Object in question. * @param[in] encindex An encoding index. * @exception rb_eFrozenError `obj` is frozen. * @exception rb_eArgError `obj` is incapable of having an encoding. * @exception rb_eEncodingError `encindex` is out of bounds. * @exception rb_eLoadError Failed to load the encoding. * @return The passed `obj`. * @post `obj`'s contents might be fixed according to `encindex`. */ VALUE rb_enc_associate_index(VALUE obj, int encindex); /** * Identical to rb_enc_associate_index(), except it takes an encoding itself * instead of its index. * * @param[out] obj Object in question. * @param[in] enc An encoding. * @exception rb_eFrozenError `obj` is frozen. * @exception rb_eArgError `obj` is incapable of having an encoding. * @return The passed `obj`. * @post `obj`'s contents might be fixed according to `enc`. */ VALUE rb_enc_associate(VALUE obj, rb_encoding *enc); /** * Destructively copies the encoding of the latter object to that of former * one. It can also be seen as a routine identical to * rb_enc_associate_index(), except it takes an object's encoding instead of an * encoding's index. * * @param[out] dst Object to modify. * @param[in] src Object to reference. * @exception rb_eFrozenError `dst` is frozen. * @exception rb_eArgError `dst` is incapable of having an encoding. * @exception rb_eEncodingError `src` is incapable of having an encoding. * @post `dst`'s encoding is that of `src`'s. */ void rb_enc_copy(VALUE dst, VALUE src); /** * Identical to rb_find_encoding(), except it takes an encoding index instead * of a Ruby object. * * @param[in] idx An encoding index. * @retval NULL No such encoding. * @retval otherwise An encoding whose index is `idx`. */ rb_encoding *rb_enc_from_index(int idx); /** * Identical to rb_find_encoding(), except it takes a C's string instead of * Ruby's. * * @param[in] name Name of the encoding to query. * @retval NULL No such encoding. * @retval otherwise An encoding whose index is `idx`. */ rb_encoding *rb_enc_find(const char *name); /** * Queries the (canonical) name of the passed encoding. * * @param[in] enc An encoding. * @return Its name. */ static inline const char * rb_enc_name(rb_encoding *enc) { return enc->name; } /** * Queries the minimum number of bytes that the passed encoding needs to * represent a character. For ASCII and compatible encodings this is typically * 1. There are however encodings whose minimum is not 1; they are * historically called wide characters. * * @param[in] enc An encoding. * @return Its least possible number of bytes except 0. */ static inline int rb_enc_mbminlen(rb_encoding *enc) { return enc->min_enc_len; } /** * Queries the maximum number of bytes that the passed encoding needs to * represent a character. Fixed-width encodings have the same value for this * one and #rb_enc_mbminlen. However there are variable-width encodings. * UTF-8, for instance, takes from 1 up to 6 bytes. * * @param[in] enc An encoding. * @return Its maximum possible number of bytes of a character. */ static inline int rb_enc_mbmaxlen(rb_encoding *enc) { return enc->max_enc_len; } /** * Queries the number of bytes of the character at the passed pointer. * * @param[in] p Pointer to a character's first byte. * @param[in] e End of the string that has `p`. * @param[in] enc Encoding of the string. * @return If the character at `p` does not end until `e`, number of bytes * between `p` and `e`. Otherwise the number of bytes that the * character at `p` is encoded. * * @internal * * Strictly speaking there are chances when `p` points to a middle byte of a * wide character. This function returns "the number of bytes from `p` to * nearest of either `e` or the next character boundary", if you go strict. */ int rb_enc_mbclen(const char *p, const char *e, rb_encoding *enc); /** * Identical to rb_enc_mbclen() unless the character at `p` overruns `e`. That * can happen for instance when you read from a socket and its partial read * cuts a wide character in-between. In those situations this function * "estimates" theoretical length of the character in question. Typically it * tends to be possible to know how many bytes a character needs before * actually reaching its end; for instance UTF-8 encodes a character's length * in the first byte of it. This function returns that info. * * @note This implies that the string is not broken. * * @param[in] p Pointer to the character's first byte. * @param[in] e End of the string that has `p`. * @param[in] enc Encoding of the string. * @return Number of bytes of character at `p`, measured or estimated. */ int rb_enc_fast_mbclen(const char *p, const char *e, rb_encoding *enc); /** * Queries the number of bytes of the character at the passed pointer. This * function returns 3 different types of information: * * ```CXX * auto n = rb_enc_precise_mbclen(p, q, r); * * if (ONIGENC_MBCLEN_CHARFOUND_P(n)) { * // Character found. Normal return. * auto found_length = ONIGENC_MBCLEN_CHARFOUND_LEN(n); * } * else if (ONIGENC_MBCLEN_NEEDMORE_P(n)) { * // Character overruns past `q`; needs more. * auto requested_length = ONIGENC_MBCLEN_NEEDMORE_LEN(n); * } * else { * // `p` is broken. * assert(ONIGENC_MBCLEN_INVALID_P(n)); * } * ``` * * @param[in] p Pointer to the character's first byte. * @param[in] e End of the string that has `p`. * @param[in] enc Encoding of the string. * @return Encoded read/needed number of bytes (see above). */ int rb_enc_precise_mbclen(const char *p, const char *e, rb_encoding *enc); #define MBCLEN_CHARFOUND_P(ret) ONIGENC_MBCLEN_CHARFOUND_P(ret) /**< @old{ONIGENC_MBCLEN_CHARFOUND_P} */ #define MBCLEN_CHARFOUND_LEN(ret) ONIGENC_MBCLEN_CHARFOUND_LEN(ret) /**< @old{ONIGENC_MBCLEN_CHARFOUND_LEN} */ #define MBCLEN_INVALID_P(ret) ONIGENC_MBCLEN_INVALID_P(ret) /**< @old{ONIGENC_MBCLEN_INVALID_P} */ #define MBCLEN_NEEDMORE_P(ret) ONIGENC_MBCLEN_NEEDMORE_P(ret) /**< @old{ONIGENC_MBCLEN_NEEDMORE_P} */ #define MBCLEN_NEEDMORE_LEN(ret) ONIGENC_MBCLEN_NEEDMORE_LEN(ret) /**< @old{ONIGENC_MBCLEN_NEEDMORE_LEN} */ /** * Queries the code point of character pointed by the passed pointer. If that * code point is included in ASCII that code point is returned. Otherwise -1. * This can be different from just looking at the first byte. For instance it * reads 2 bytes in case of UTF-16BE. * * @param[in] p Pointer to the character's first byte. * @param[in] e End of the string that has `p`. * @param[in] len Return buffer. * @param[in] enc Encoding of the string. * @retval -1 The character at `p` is not i ASCII. * @retval otherwise A code point of the character at `p`. * @post `len` (if set) is the number of bytes of `p`. */ int rb_enc_ascget(const char *p, const char *e, int *len, rb_encoding *enc); /** * Queries the code point of character pointed by the passed pointer. * Exceptions happen in case of broken input. * * @param[in] p Pointer to the character's first byte. * @param[in] e End of the string that has `p`. * @param[in] len Return buffer. * @param[in] enc Encoding of the string. * @exception rb_eArgError `p` is broken. * @return Code point of the character pointed by `p`. * @post `len` (if set) is the number of bytes of `p`. */ unsigned int rb_enc_codepoint_len(const char *p, const char *e, int *len, rb_encoding *enc); /** * Queries the code point of character pointed by the passed pointer. * Exceptions happen in case of broken input. * * @deprecated Use rb_enc_codepoint_len() instead. * @param[in] p Pointer to the character's first byte. * @param[in] e End of the string that has `p`. * @param[in] enc Encoding of the string. * @exception rb_eArgError `p` is broken. * @return Code point of the character pointed by `p`. * * @internal * * @matz says in commit 91e5ba1cb865a2385d3e1cbfacd824496898e098 that the line * below is a "prototype for obsolete function". However even today there * still are some use cases of it throughout our repository. It seems it has * its own niche. */ static inline unsigned int rb_enc_codepoint(const char *p, const char *e, rb_encoding *enc) { return rb_enc_codepoint_len(p, e, 0, enc); /* ^^^ * This can be `NULL` in C, `nullptr` in C++, and `0` for both. * We choose the most portable one here. */ } /** * Identical to rb_enc_codepoint(), except it assumes the passed character is * not broken. * * @param[in] p Pointer to the character's first byte. * @param[in] e End of the string that has `p`. * @param[in] enc Encoding of the string. * @return Code point of the character pointed by `p`. */ static inline OnigCodePoint rb_enc_mbc_to_codepoint(const char *p, const char *e, rb_encoding *enc) { const OnigUChar *up = RBIMPL_CAST((const OnigUChar *)p); const OnigUChar *ue = RBIMPL_CAST((const OnigUChar *)e); return ONIGENC_MBC_TO_CODE(enc, up, ue); } /** * Queries the number of bytes requested to represent the passed code point * using the passed encoding. * * @param[in] code Code point in question. * @param[in] enc Encoding to convert the code into a byte sequence. * @exception rb_eArgError `enc` does not glean `code`. * @return Number of bytes requested to represent `code` using `enc`. */ int rb_enc_codelen(int code, rb_encoding *enc); /** * Identical to rb_enc_codelen(), except it returns 0 for invalid code points. * * @param[in] c Code point in question. * @param[in] enc Encoding to convert `c` into a byte sequence. * @retval 0 `c` is invalid. * @return otherwise Number of bytes needed for `enc` to encode `c`. */ static inline int rb_enc_code_to_mbclen(int c, rb_encoding *enc) { OnigCodePoint uc = RBIMPL_CAST((OnigCodePoint)c); return ONIGENC_CODE_TO_MBCLEN(enc, uc); } /** * Identical to rb_enc_uint_chr(), except it writes back to the passed buffer * instead of allocating one. * * @param[in] c Code point. * @param[out] buf Return buffer. * @param[in] enc Target encoding scheme. * @retval <= 0 `c` is invalid in `enc`. * @return otherwise Number of bytes written to `buf`. * @post `c` is encoded according to `enc`, then written to `buf`. * * @internal * * The second argument must be typed. But its current usages prevent us from * being any stricter than this. :FIXME: */ static inline int rb_enc_mbcput(unsigned int c, void *buf, rb_encoding *enc) { OnigCodePoint uc = RBIMPL_CAST((OnigCodePoint)c); OnigUChar *ubuf = RBIMPL_CAST((OnigUChar *)buf); return ONIGENC_CODE_TO_MBC(enc, uc, ubuf); } /** * Queries the previous (left) character. * * @param[in] s Start of the string. * @param[in] p Pointer to a character. * @param[in] e End of the string. * @param[in] enc Encoding. * @retval NULL No previous character. * @retval otherwise Pointer to the head of the previous character. */ static inline char * rb_enc_prev_char(const char *s, const char *p, const char *e, rb_encoding *enc) { const OnigUChar *us = RBIMPL_CAST((const OnigUChar *)s); const OnigUChar *up = RBIMPL_CAST((const OnigUChar *)p); const OnigUChar *ue = RBIMPL_CAST((const OnigUChar *)e); OnigUChar *ur = onigenc_get_prev_char_head(enc, us, up, ue); return RBIMPL_CAST((char *)ur); } /** * Queries the left boundary of a character. This function takes a pointer * that is not necessarily a head of a character, and searches for its head. * * @param[in] s Start of the string. * @param[in] p Pointer to a possibly-middle of a character. * @param[in] e End of the string. * @param[in] enc Encoding. * @return Pointer to the head of the character that contains `p`. */ static inline char * rb_enc_left_char_head(const char *s, const char *p, const char *e, rb_encoding *enc) { const OnigUChar *us = RBIMPL_CAST((const OnigUChar *)s); const OnigUChar *up = RBIMPL_CAST((const OnigUChar *)p); const OnigUChar *ue = RBIMPL_CAST((const OnigUChar *)e); OnigUChar *ur = onigenc_get_left_adjust_char_head(enc, us, up, ue); return RBIMPL_CAST((char *)ur); } /** * Queries the right boundary of a character. This function takes a pointer * that is not necessarily a head of a character, and searches for its tail. * * @param[in] s Start of the string. * @param[in] p Pointer to a possibly-middle of a character. * @param[in] e End of the string. * @param[in] enc Encoding. * @return Pointer to the end of the character that contains `p`. */ static inline char * rb_enc_right_char_head(const char *s, const char *p, const char *e, rb_encoding *enc) { const OnigUChar *us = RBIMPL_CAST((const OnigUChar *)s); const OnigUChar *up = RBIMPL_CAST((const OnigUChar *)p); const OnigUChar *ue = RBIMPL_CAST((const OnigUChar *)e); OnigUChar *ur = onigenc_get_right_adjust_char_head(enc, us, up, ue); return RBIMPL_CAST((char *)ur); } /** * Scans the string backwards for n characters. * * @param[in] s Start of the string. * @param[in] p Pointer to a character. * @param[in] e End of the string. * @param[in] n Steps. * @param[in] enc Encoding. * @retval NULL There are no `n` characters left. * @retval otherwise Pointer to `n` character before `p`. */ static inline char * rb_enc_step_back(const char *s, const char *p, const char *e, int n, rb_encoding *enc) { const OnigUChar *us = RBIMPL_CAST((const OnigUChar *)s); const OnigUChar *up = RBIMPL_CAST((const OnigUChar *)p); const OnigUChar *ue = RBIMPL_CAST((const OnigUChar *)e); const OnigUChar *ur = onigenc_step_back(enc, us, up, ue, n); return RBIMPL_CAST((char *)ur); } /** * @private * * This is an implementation detail of rb_enc_asciicompat(). People don't use * it directly. Just always use rb_enc_asciicompat(). * * @param[in] enc Encoding in question. * @retval 1 It is ASCII compatible. * @retval 0 It isn't. */ static inline int rb_enc_asciicompat_inline(rb_encoding *enc) { return rb_enc_mbminlen(enc)==1 && !rb_enc_dummy_p(enc); } /** * Queries if the passed encoding is _in some sense_ compatible with ASCII. * The concept of ASCII compatibility is nuanced, and private to our * implementation. For instance SJIS is ASCII compatible to us, despite their * having different characters at code point `0x5C`. This is based on some * practical consideration that Japanese people confuses SJIS to be "upper * compatible" with ASCII (which is in fact a wrong idea, but we just don't go * strict here). An example of ASCII incompatible encoding is UTF-16. UTF-16 * shares code points with ASCII, but employs a completely different encoding * scheme. * * @param[in] enc Encoding in question. * @retval 0 It is incompatible. * @retval 1 It is compatible. */ static inline bool rb_enc_asciicompat(rb_encoding *enc) { if (rb_enc_mbminlen(enc) != 1) { return false; } else if (rb_enc_dummy_p(enc)) { return false; } else { return true; } } /** * Queries if the passed string is in an ASCII-compatible encoding. * * @param[in] str A Ruby's string to query. * @retval 0 `str` is not a String, or an ASCII-incompatible string. * @retval 1 Otherwise. */ static inline bool rb_enc_str_asciicompat_p(VALUE str) { rb_encoding *enc = rb_enc_get(str); return rb_enc_asciicompat(enc); } /** * Queries the Ruby-level counterpart instance of ::rb_cEncoding that * corresponds to the passed encoding. * * @param[in] enc An encoding * @retval RUBY_Qnil `enc` is a null pointer. * @retval otherwise An instance of ::rb_cEncoding. */ VALUE rb_enc_from_encoding(rb_encoding *enc); RBIMPL_ATTR_PURE() /** * Queries if the passed encoding is either one of UTF-8/16/32. * * @note It does not take UTF-7, which we actually support, into account. * * @param[in] enc Encoding in question. * @retval 0 It is not a Unicode variant. * @retval otherwise It is. * * @internal * * In reality it returns 1/0, but the value is abstracted as * `ONIGENC_FLAG_UNICODE`. */ int rb_enc_unicode_p(rb_encoding *enc); RBIMPL_ATTR_RETURNS_NONNULL() /** * Queries the encoding that represents ASCII-8BIT a.k.a. binary. * * @return The encoding that represents ASCII-8BIT. * * @internal * * This can not return NULL once the process properly boots up. */ rb_encoding *rb_ascii8bit_encoding(void); RBIMPL_ATTR_RETURNS_NONNULL() /** * Queries the encoding that represents UTF-8. * * @return The encoding that represents UTF-8. * * @internal * * This can not return NULL once the process properly boots up. */ rb_encoding *rb_utf8_encoding(void); RBIMPL_ATTR_RETURNS_NONNULL() /** * Queries the encoding that represents US-ASCII. * * @return The encoding that represents US-ASCII. * * @internal * * This can not return NULL once the process properly boots up. */ rb_encoding *rb_usascii_encoding(void); /** * Queries the encoding that represents the current locale. * * @return The encoding that represents the process' locale. * * @internal * * This is dynamic. If you change the process' locale by e.g. calling * `setlocale(3)`, that should also change the return value of this function. * * There is no official way for Ruby scripts to manipulate locales, though. */ rb_encoding *rb_locale_encoding(void); /** * Queries the "filesystem" encoding. This is the encoding that ruby expects * info from the OS' file system are in. This affects for instance return * value of rb_dir_getwd(). Most notably on Windows it can be an alias of OS * codepage. Most notably on Linux users can set this via default external * encoding. * * @return The "filesystem" encoding. */ rb_encoding *rb_filesystem_encoding(void); /** * Queries the "default external" encoding. This is used to interact with * outer-process things such as File. Though not recommended, you can set this * using rb_enc_set_default_external(). * * @return The "default external" encoding. */ rb_encoding *rb_default_external_encoding(void); /** * Queries the "default internal" encoding. This could be a null pointer. * Otherwise, outer-process info are transcoded from default external encoding * to this one during reading from an IO. * * @return The "default internal" encoding (if any). */ rb_encoding *rb_default_internal_encoding(void); #ifndef rb_ascii8bit_encindex RBIMPL_ATTR_CONST() /** * Identical to rb_ascii8bit_encoding(), except it returns the encoding's index * instead of the encoding itself. * * @return The index of encoding of ASCII-8BIT. * * @internal * * This happens to be 0. */ int rb_ascii8bit_encindex(void); #endif /** * Queries if the passed object is in ascii 8bit (== binary) encoding. The * object must be capable of having inline encoding. Using this macro needs * deep understanding of bit level object binary layout. * * @param[in] obj An object to check. * @retval 1 It is. * @retval 0 It isn't. */ static inline bool RB_ENCODING_IS_ASCII8BIT(VALUE obj) { return RB_ENCODING_GET_INLINED(obj) == rb_ascii8bit_encindex(); } #ifndef rb_utf8_encindex RBIMPL_ATTR_CONST() /** * Identical to rb_utf8_encoding(), except it returns the encoding's index * instead of the encoding itself. * * @return The index of encoding of UTF-8. */ int rb_utf8_encindex(void); #endif #ifndef rb_usascii_encindex RBIMPL_ATTR_CONST() /** * Identical to rb_usascii_encoding(), except it returns the encoding's index * instead of the encoding itself. * * @return The index of encoding of UTF-8. */ int rb_usascii_encindex(void); #endif /** * Identical to rb_locale_encoding(), except it returns the encoding's index * instead of the encoding itself. * * @return The index of the locale encoding. */ int rb_locale_encindex(void); /** * Identical to rb_filesystem_encoding(), except it returns the encoding's * index instead of the encoding itself. * * @return The index of the filesystem encoding. */ int rb_filesystem_encindex(void); /** * Identical to rb_default_external_encoding(), except it returns the * Ruby-level counterpart instance of ::rb_cEncoding that corresponds to the * default external encoding. * * @return An instance of ::rb_cEncoding of default external. */ VALUE rb_enc_default_external(void); /** * Identical to rb_default_internal_encoding(), except it returns the * Ruby-level counterpart instance of ::rb_cEncoding that corresponds to the * default internal encoding. * * @return An instance of ::rb_cEncoding of default internal. */ VALUE rb_enc_default_internal(void); /** * Destructively assigns the passed encoding as the default external encoding. * You should not use this API. It has process-global side effects. Also it * doesn't change encodings of strings that have already been read. * * @param[in] encoding Ruby level encoding. * @exception rb_eArgError `encoding` is ::RUBY_Qnil. * @post The default external encoding is `encoding`. */ void rb_enc_set_default_external(VALUE encoding); /** * Destructively assigns the passed encoding as the default internal encoding. * You should not use this API. It has process-global side effects. Also it * doesn't change encodings of strings that have already been read. * * @param[in] encoding Ruby level encoding. * @post The default internal encoding is `encoding`. * @note Unlike rb_enc_set_default_external() you can pass ::RUBY_Qnil. */ void rb_enc_set_default_internal(VALUE encoding); /** * Returns a platform-depended "charmap" of the current locale. This * information is called a "Codeset name" in IEEE 1003.1 section 13 * (`<langinfo.h>`). This is a very low-level API. The return value can have * no corresponding encoding when passed to rb_find_encoding(). * * @param[in] klass Ignored for no reason (why...) * @return The low-level locale charmap, in Ruby's String. */ VALUE rb_locale_charmap(VALUE klass); RBIMPL_SYMBOL_EXPORT_END() /** @cond INTERNAL_MACRO */ #define RB_ENCODING_GET RB_ENCODING_GET #define RB_ENCODING_GET_INLINED RB_ENCODING_GET_INLINED #define RB_ENCODING_IS_ASCII8BIT RB_ENCODING_IS_ASCII8BIT #define RB_ENCODING_SET RB_ENCODING_SET #define RB_ENCODING_SET_INLINED RB_ENCODING_SET_INLINED #define rb_enc_asciicompat rb_enc_asciicompat #define rb_enc_code_to_mbclen rb_enc_code_to_mbclen #define rb_enc_codepoint rb_enc_codepoint #define rb_enc_left_char_head rb_enc_left_char_head #define rb_enc_mbc_to_codepoint rb_enc_mbc_to_codepoint #define rb_enc_mbcput rb_enc_mbcput #define rb_enc_mbmaxlen rb_enc_mbmaxlen #define rb_enc_mbminlen rb_enc_mbminlen #define rb_enc_name rb_enc_name #define rb_enc_prev_char rb_enc_prev_char #define rb_enc_right_char_head rb_enc_right_char_head #define rb_enc_step_back rb_enc_step_back #define rb_enc_str_asciicompat_p rb_enc_str_asciicompat_p /** @endcond */ #endif /* RUBY_INTERNAL_ENCODING_ENCODING_H */ include/ruby/internal/encoding/ctype.h 0000644 00000017527 15152150500 0014055 0 ustar 00 #ifndef RUBY_INTERNAL_ENCODING_CTYPE_H /*-*-C++-*-vi:se ft=cpp:*/ #define RUBY_INTERNAL_ENCODING_CTYPE_H /** * @file * @author Ruby developers <ruby-core@ruby-lang.org> * @copyright This file is a part of the programming language Ruby. * Permission is hereby granted, to either redistribute and/or * modify this file, provided that the conditions mentioned in the * file COPYING are met. Consult the file for details. * @warning Symbols prefixed with either `RBIMPL` or `rbimpl` are * implementation details. Don't take them as canon. They could * rapidly appear then vanish. The name (path) of this header file * is also an implementation detail. Do not expect it to persist * at the place it is now. Developers are free to move it anywhere * anytime at will. * @note To ruby-core: remember that this header can be possibly * recursively included from extension libraries written in C++. * Do not expect for instance `__VA_ARGS__` is always available. * We assume C99 for ruby itself but we don't assume languages of * extension libraries. They could be written in C++98. * @brief Routines to query chacater types. */ #include "ruby/onigmo.h" #include "ruby/internal/attr/const.h" #include "ruby/internal/dllexport.h" #include "ruby/internal/encoding/encoding.h" #include "ruby/internal/value.h" RBIMPL_SYMBOL_EXPORT_BEGIN() /** * Queries if the passed pointer points to a newline character. What is a * newline and what is not depends on the passed encoding. * * @param[in] p Pointer to a possibly-middle of a character. * @param[in] end End of the string. * @param[in] enc Encoding. * @retval false It isn't. * @retval true It is. */ static inline bool rb_enc_is_newline(const char *p, const char *e, rb_encoding *enc) { OnigUChar *up = RBIMPL_CAST((OnigUChar *)p); OnigUChar *ue = RBIMPL_CAST((OnigUChar *)e); return ONIGENC_IS_MBC_NEWLINE(enc, up, ue); } /** * Queries if the passed code point is of passed character type in the passed * encoding. The "character type" here is a set of macros defined in onigmo.h, * like `ONIGENC_CTYPE_PUNCT`. * * @param[in] c An `OnigCodePoint` value. * @param[in] t An `OnigCtype` value. * @param[in] enc A `rb_encoding*` value. * @retval true `c` is of `t` in `enc`. * @retval false Otherwise. */ static inline bool rb_enc_isctype(OnigCodePoint c, OnigCtype t, rb_encoding *enc) { return ONIGENC_IS_CODE_CTYPE(enc, c, t); } /** * Identical to rb_isascii(), except it additionally takes an encoding. * * @param[in] c A code point. * @param[in] enc An encoding. * @retval false `c` is out of range of ASCII character set in `enc`. * @retval true Otherwise. * * @internal * * `enc` is ignored. This is at least an intentional implementation detail * (not a bug). But there could be rooms for future extensions. */ static inline bool rb_enc_isascii(OnigCodePoint c, rb_encoding *enc) { return ONIGENC_IS_CODE_ASCII(c); } /** * Identical to rb_isalpha(), except it additionally takes an encoding. * * @param[in] c A code point. * @param[in] enc An encoding. * @retval true `enc` classifies `c` as "ALPHA". * @retval false Otherwise. */ static inline bool rb_enc_isalpha(OnigCodePoint c, rb_encoding *enc) { return ONIGENC_IS_CODE_ALPHA(enc, c); } /** * Identical to rb_islower(), except it additionally takes an encoding. * * @param[in] c A code point. * @param[in] enc An encoding. * @retval true `enc` classifies `c` as "LOWER". * @retval false Otherwise. */ static inline bool rb_enc_islower(OnigCodePoint c, rb_encoding *enc) { return ONIGENC_IS_CODE_LOWER(enc, c); } /** * Identical to rb_isupper(), except it additionally takes an encoding. * * @param[in] c A code point. * @param[in] enc An encoding. * @retval true `enc` classifies `c` as "UPPER". * @retval false Otherwise. */ static inline bool rb_enc_isupper(OnigCodePoint c, rb_encoding *enc) { return ONIGENC_IS_CODE_UPPER(enc, c); } /** * Identical to rb_iscntrl(), except it additionally takes an encoding. * * @param[in] c A code point. * @param[in] enc An encoding. * @retval true `enc` classifies `c` as "CNTRL". * @retval false Otherwise. */ static inline bool rb_enc_iscntrl(OnigCodePoint c, rb_encoding *enc) { return ONIGENC_IS_CODE_CNTRL(enc, c); } /** * Identical to rb_ispunct(), except it additionally takes an encoding. * * @param[in] c A code point. * @param[in] enc An encoding. * @retval true `enc` classifies `c` as "PUNCT". * @retval false Otherwise. */ static inline bool rb_enc_ispunct(OnigCodePoint c, rb_encoding *enc) { return ONIGENC_IS_CODE_PUNCT(enc, c); } /** * Identical to rb_isalnum(), except it additionally takes an encoding. * * @param[in] c A code point. * @param[in] enc An encoding. * @retval true `enc` classifies `c` as "ANUM". * @retval false Otherwise. */ static inline bool rb_enc_isalnum(OnigCodePoint c, rb_encoding *enc) { return ONIGENC_IS_CODE_ALNUM(enc, c); } /** * Identical to rb_isprint(), except it additionally takes an encoding. * * @param[in] c A code point. * @param[in] enc An encoding. * @retval true `enc` classifies `c` as "PRINT". * @retval false Otherwise. */ static inline bool rb_enc_isprint(OnigCodePoint c, rb_encoding *enc) { return ONIGENC_IS_CODE_PRINT(enc, c); } /** * Identical to rb_isspace(), except it additionally takes an encoding. * * @param[in] c A code point. * @param[in] enc An encoding. * @retval true `enc` classifies `c` as "PRINT". * @retval false Otherwise. */ static inline bool rb_enc_isspace(OnigCodePoint c, rb_encoding *enc) { return ONIGENC_IS_CODE_SPACE(enc, c); } /** * Identical to rb_isdigit(), except it additionally takes an encoding. * * @param[in] c A code point. * @param[in] enc An encoding. * @retval true `enc` classifies `c` as "DIGIT". * @retval false Otherwise. */ static inline bool rb_enc_isdigit(OnigCodePoint c, rb_encoding *enc) { return ONIGENC_IS_CODE_DIGIT(enc, c); } RBIMPL_ATTR_CONST() /** * Identical to rb_toupper(), except it additionally takes an encoding. * * @param[in] c A code point. * @param[in] enc An encoding. * @return `c`'s (Ruby's definition of) upper case counterpart. * * @internal * * As `RBIMPL_ATTR_CONST` implies this function ignores `enc`. */ int rb_enc_toupper(int c, rb_encoding *enc); RBIMPL_ATTR_CONST() /** * Identical to rb_tolower(), except it additionally takes an encoding. * * @param[in] c A code point. * @param[in] enc An encoding. * @return `c`'s (Ruby's definition of) lower case counterpart. * * @internal * * As `RBIMPL_ATTR_CONST` implies this function ignores `enc`. */ int rb_enc_tolower(int c, rb_encoding *enc); RBIMPL_SYMBOL_EXPORT_END() /** @cond INTERNAL_MACRO */ #define rb_enc_is_newline rb_enc_is_newline #define rb_enc_isalnum rb_enc_isalnum #define rb_enc_isalpha rb_enc_isalpha #define rb_enc_isascii rb_enc_isascii #define rb_enc_isctype rb_enc_isctype #define rb_enc_isdigit rb_enc_isdigit #define rb_enc_islower rb_enc_islower #define rb_enc_isprint rb_enc_isprint #define rb_enc_iscntrl rb_enc_iscntrl #define rb_enc_ispunct rb_enc_ispunct #define rb_enc_isspace rb_enc_isspace #define rb_enc_isupper rb_enc_isupper /** @endcond */ #endif /* RUBY_INTERNAL_ENCODING_CTYPE_H */ include/ruby/internal/encoding/string.h 0000644 00000036371 15152150500 0014235 0 ustar 00 #ifndef RUBY_INTERNAL_ENCODING_STRING_H /*-*-C++-*-vi:se ft=cpp:*/ #define RUBY_INTERNAL_ENCODING_STRING_H /** * @file * @author Ruby developers <ruby-core@ruby-lang.org> * @copyright This file is a part of the programming language Ruby. * Permission is hereby granted, to either redistribute and/or * modify this file, provided that the conditions mentioned in the * file COPYING are met. Consult the file for details. * @warning Symbols prefixed with either `RBIMPL` or `rbimpl` are * implementation details. Don't take them as canon. They could * rapidly appear then vanish. The name (path) of this header file * is also an implementation detail. Do not expect it to persist * at the place it is now. Developers are free to move it anywhere * anytime at will. * @note To ruby-core: remember that this header can be possibly * recursively included from extension libraries written in C++. * Do not expect for instance `__VA_ARGS__` is always available. * We assume C99 for ruby itself but we don't assume languages of * extension libraries. They could be written in C++98. * @brief Routines to manipulate encodings of strings. */ #include "ruby/internal/dllexport.h" #include "ruby/internal/value.h" #include "ruby/internal/encoding/encoding.h" #include "ruby/internal/attr/nonnull.h" #include "ruby/internal/intern/string.h" /* rbimpl_strlen */ RBIMPL_SYMBOL_EXPORT_BEGIN() /** * Identical to rb_str_new(), except it additionally takes an encoding. * * @param[in] ptr A memory region of `len` bytes length. * @param[in] len Length of `ptr`, in bytes, not including the * terminating NUL character. * @param[in] enc Encoding of `ptr`. * @exception rb_eNoMemError Failed to allocate `len+1` bytes. * @exception rb_eArgError `len` is negative. * @return An instance of ::rb_cString, of `len` bytes length, of `enc` * encoding, whose contents are verbatim copy of `ptr`. * @pre At least `len` bytes of continuous memory region shall be * accessible via `ptr`. * @note `enc` can be a null pointer. It can also be seen as a routine * identical to rb_usascii_str_new() then. */ VALUE rb_enc_str_new(const char *ptr, long len, rb_encoding *enc); RBIMPL_ATTR_NONNULL((1)) /** * Identical to rb_enc_str_new(), except it assumes the passed pointer is a * pointer to a C string. It can also be seen as a routine identical to * rb_str_new_cstr(), except it additionally takes an encoding. * * @param[in] ptr A C string. * @param[in] enc Encoding of `ptr`. * @exception rb_eNoMemError Failed to allocate memory. * @return An instance of ::rb_cString, of `enc` encoding, whose contents * are verbatim copy of `ptr`. * @pre `ptr` must not be a null pointer. * @pre Because `ptr` is a C string it makes no sense for `enc` to be * something like UTF-32. * @note `enc` can be a null pointer. It can also be seen as a routine * identical to rb_usascii_str_new_cstr() then. */ VALUE rb_enc_str_new_cstr(const char *ptr, rb_encoding *enc); /** * Identical to rb_enc_str_new(), except it takes a C string literal. It can * also be seen as a routine identical to rb_str_new_static(), except it * additionally takes an encoding. * * @param[in] ptr A C string literal. * @param[in] len `strlen(ptr)`. * @param[in] enc Encoding of `ptr`. * @exception rb_eArgError `len` out of range of `size_t`. * @pre `ptr` must be a C string constant. * @return An instance of ::rb_cString, of `enc` encoding, whose backend * storage is the passed C string literal. * @warning It is a very bad idea to write to a C string literal (often * immediate SEGV shall occur). Consider return values of this * function be read-only. * @note `enc` can be a null pointer. It can also be seen as a routine * identical to rb_usascii_str_new_static() then. */ VALUE rb_enc_str_new_static(const char *ptr, long len, rb_encoding *enc); /** * Identical to rb_enc_str_new(), except it returns a "f"string. It can also * be seen as a routine identical to rb_interned_str(), except it additionally * takes an encoding. * * @param[in] ptr A memory region of `len` bytes length. * @param[in] len Length of `ptr`, in bytes, not including the * terminating NUL character. * @param[in] enc Encoding of `ptr`. * @exception rb_eArgError `len` is negative. * @return A found or created instance of ::rb_cString, of `len` bytes * length, of `enc` encoding, whose contents are identical to that * of `ptr`. * @pre At least `len` bytes of continuous memory region shall be * accessible via `ptr`. * @note `enc` can be a null pointer. */ VALUE rb_enc_interned_str(const char *ptr, long len, rb_encoding *enc); RBIMPL_ATTR_NONNULL((1)) /** * Identical to rb_enc_str_new_cstr(), except it returns a "f"string. It can * also be seen as a routine identical to rb_interned_str_cstr(), except it * additionally takes an encoding. * * @param[in] ptr A memory region of `len` bytes length. * @param[in] enc Encoding of `ptr`. * @return A found or created instance of ::rb_cString of `enc` encoding, * whose contents are identical to that of `ptr`. * @pre At least `len` bytes of continuous memory region shall be * accessible via `ptr`. * @note `enc` can be a null pointer. */ VALUE rb_enc_interned_str_cstr(const char *ptr, rb_encoding *enc); /** * Counts the number of characters of the passed string, according to the * passed encoding. This has to be complicated. The passed string could be * invalid and/or broken. This routine would scan from the beginning til the * end, byte by byte, to seek out character boundaries. Could be super slow. * * @param[in] head Leftmost pointer to the string. * @param[in] tail Rightmost pointer to the string. * @param[in] enc Encoding of the string. * @return Number of characters exist in `head` .. `tail`. The definition * of "character" depends on the passed `enc`. */ long rb_enc_strlen(const char *head, const char *tail, rb_encoding *enc); /** * Queries the n-th character. Like rb_enc_strlen() this function can be fast * or slow depending on the contents. Don't expect characters to be uniformly * distributed across the entire string. * * @param[in] head Leftmost pointer to the string. * @param[in] tail Rightmost pointer to the string. * @param[in] nth Requested index of characters. * @param[in] enc Encoding of the string. * @return Pointer to the first byte of the character that is `nth` * character ahead of `head`, or `tail` if there is no such * character (OOB etc). The definition of "character" depends on * the passed `enc`. */ char *rb_enc_nth(const char *head, const char *tail, long nth, rb_encoding *enc); /** * Identical to rb_enc_get_index(), except the return type. * * @param[in] obj Object in question. * @exception rb_eTypeError `obj` is incapable of having an encoding. * @return `obj`'s encoding. */ VALUE rb_obj_encoding(VALUE obj); /** * Identical to rb_str_cat(), except it additionally takes an encoding. * * @param[out] str Destination object. * @param[in] ptr Contents to append. * @param[in] len Length of `src`, in bytes. * @param[in] enc Encoding of `ptr`. * @exception rb_eArgError `len` is negative. * @exception rb_eEncCompatError `enc` is not compatible with `str`. * @return The passed `dst`. * @post The contents of `ptr` is copied, transcoded into `dst`'s * encoding, then pasted into `dst`'s end. */ VALUE rb_enc_str_buf_cat(VALUE str, const char *ptr, long len, rb_encoding *enc); /** * Encodes the passed code point into a series of bytes. * * @param[in] code Code point. * @param[in] enc Target encoding scheme. * @exception rb_eRangeError `enc` does not glean `code`. * @return An instance of ::rb_cString, of `enc` encoding, whose sole * contents is `code` represented in `enc`. * @note No way to encode code points bigger than UINT_MAX. * * @internal * * In other languages, APIs like this one could be seen as the primitive * routines where encodings' "encode" feature are implemented. However in case * of Ruby this is not the primitive one. We directly manipulate encoded * strings. Encoding conversion routines transcode an encoded string directly * to another one; not via a code point array. */ VALUE rb_enc_uint_chr(unsigned int code, rb_encoding *enc); /** * Identical to rb_external_str_new(), except it additionally takes an * encoding. However the whole point of rb_external_str_new() is to encode a * string into default external encoding. Being able to specify arbitrary * encoding just ruins the designed purpose the function meseems. * * @param[in] ptr A memory region of `len` bytes length. * @param[in] len Length of `ptr`, in bytes, not including the * terminating NUL character. * @param[in] enc Target encoding scheme. * @exception rb_eArgError `len` is negative. * @return An instance of ::rb_cString. In case encoding conversion from * "default internal" to `enc` is fully defined over the given * contents, then the return value is a string of `enc` encoding, * whose contents are the converted ones. Otherwise the string is * a junk. * @warning It doesn't raise on a conversion failure and silently ends up in * a corrupted output. You can know the failure by querying * `valid_encoding?` of the result object. * * @internal * * @shyouhei has no idea why this one does not follow the naming convention * that others obey. It seems to him that this should have been called * `rb_enc_external_str_new`. */ VALUE rb_external_str_new_with_enc(const char *ptr, long len, rb_encoding *enc); /** * Identical to rb_str_export(), except it additionally takes an encoding. * * @param[in] obj Target object. * @param[in] enc Target encoding. * @exception rb_eTypeError No implicit conversion to String. * @return Converted ruby string of `enc` encoding. */ VALUE rb_str_export_to_enc(VALUE obj, rb_encoding *enc); /** * Encoding conversion main routine. * * @param[in] str String to convert. * @param[in] from Source encoding. * @param[in] to Destination encoding. * @return A copy of `str`, with conversion from `from` to `to` applied. * @note `from` can be a null pointer. `str`'s encoding is taken then. * @note `to` can be a null pointer. No-op then. */ VALUE rb_str_conv_enc(VALUE str, rb_encoding *from, rb_encoding *to); /** * Identical to rb_str_conv_enc(), except it additionally takes IO encoder * options. The extra arguments can be constructed using io_extract_modeenc() * etc. * * @param[in] str String to convert. * @param[in] from Source encoding. * @param[in] to Destination encoding. * @param[in] ecflags A set of enum ::ruby_econv_flag_type. * @param[in] ecopts Optional hash. * @return A copy of `str`, with conversion from `from` to `to` applied. * @note `from` can be a null pointer. `str`'s encoding is taken then. * @note `to` can be a null pointer. No-op then. * @note `ecopts` can be ::RUBY_Qnil, which is equivalent to passing an * empty hash. */ VALUE rb_str_conv_enc_opts(VALUE str, rb_encoding *from, rb_encoding *to, int ecflags, VALUE ecopts); /** * Scans the passed string to collect its code range. Because a Ruby's string * is mutable, its contents change from time to time; so does its code range. * A long-lived string tends to fall back to ::RUBY_ENC_CODERANGE_UNKNOWN. * This API scans it and re-assigns a fine-grained code range constant. * * @param[out] str A string. * @return An enum ::ruby_coderange_type. */ int rb_enc_str_coderange(VALUE str); /** * Scans the passed string until it finds something odd. Returns the number of * bytes scanned. As the name implies this is suitable for repeated call. One * of its application is `IO#readlines`. The method reads from its receiver's * read buffer, maybe more than once, looking for newlines. But "newline" can * be different among encodings. This API is used to detect broken contents to * properly mark them as such. * * @param[in] str String to scan. * @param[in] end End of `str`. * @param[in] enc `str`'s encoding. * @param[out] cr Return buffer. * @return Distance between `str` and first such byte where broken. * @post `cr` has the code range type. */ long rb_str_coderange_scan_restartable(const char *str, const char *end, rb_encoding *enc, int *cr); /** * Queries if the passed string is "ASCII only". An ASCII only string is a * string who doesn't have any non-ASCII characters at all. This doesn't * necessarily mean the string is in ASCII encoding. For instance a String of * CP932 encoding can quite much be ASCII only, depending on its contents. * * @param[in] str String in question. * @retval 1 It doesn't have non-ASCII characters. * @retval 0 It has characters that are out of ASCII. */ int rb_enc_str_asciionly_p(VALUE str); RBIMPL_ATTR_NONNULL(()) /** * Looks for the passed string in the passed buffer. * * @param[in] x Buffer that potentially includes `y`. * @param[in] m Number of bytes of `x`. * @param[in] y Query string. * @param[in] n Number of bytes of `y`. * @param[in] enc Encoding of both `x` and `y`. * @retval -1 Not found. * @retval otherwise Found index in `x`. * @note This API can match at a non-character-boundary. */ long rb_memsearch(const void *x, long m, const void *y, long n, rb_encoding *enc); /** @cond INTERNAL_MACRO */ RBIMPL_ATTR_NONNULL(()) static inline VALUE rbimpl_enc_str_new_cstr(const char *str, rb_encoding *enc) { long len = rbimpl_strlen(str); return rb_enc_str_new_static(str, len, enc); } #define rb_enc_str_new(str, len, enc) \ ((RBIMPL_CONSTANT_P(str) && \ RBIMPL_CONSTANT_P(len) ? \ rb_enc_str_new_static: \ rb_enc_str_new) ((str), (len), (enc))) #define rb_enc_str_new_cstr(str, enc) \ ((RBIMPL_CONSTANT_P(str) ? \ rbimpl_enc_str_new_cstr : \ rb_enc_str_new_cstr) ((str), (enc))) /** @endcond */ RBIMPL_SYMBOL_EXPORT_END() #endif /* RUBY_INTERNAL_ENCODING_STRING_H */ include/ruby/internal/encoding/symbol.h 0000644 00000010650 15152150500 0014224 0 ustar 00 #ifndef RUBY_INTERNAL_ENCODING_SYMBOL_H /*-*-C++-*-vi:se ft=cpp:*/ #define RUBY_INTERNAL_ENCODING_SYMBOL_H /** * @file * @author Ruby developers <ruby-core@ruby-lang.org> * @copyright This file is a part of the programming language Ruby. * Permission is hereby granted, to either redistribute and/or * modify this file, provided that the conditions mentioned in the * file COPYING are met. Consult the file for details. * @warning Symbols prefixed with either `RBIMPL` or `rbimpl` are * implementation details. Don't take them as canon. They could * rapidly appear then vanish. The name (path) of this header file * is also an implementation detail. Do not expect it to persist * at the place it is now. Developers are free to move it anywhere * anytime at will. * @note To ruby-core: remember that this header can be possibly * recursively included from extension libraries written in C++. * Do not expect for instance `__VA_ARGS__` is always available. * We assume C99 for ruby itself but we don't assume languages of * extension libraries. They could be written in C++98. * @brief Routines to manipulate encodings of symbols. */ #include "ruby/internal/attr/nonnull.h" #include "ruby/internal/dllexport.h" #include "ruby/internal/encoding/encoding.h" #include "ruby/internal/value.h" RBIMPL_SYMBOL_EXPORT_BEGIN() /** * Identical to rb_intern2(), except it additionally takes an encoding. * * @param[in] name The name of the id. * @param[in] len Length of `name`. * @param[in] enc `name`'s encoding. * @exception rb_eRuntimeError Too many symbols. * @return A (possibly new) id whose value is the given name. * @note These days Ruby internally has two kinds of symbols * (static/dynamic). Symbols created using this function would * become static ones; i.e. would never be garbage collected. It * is up to you to avoid memory leaks. Think twice before using * it. */ ID rb_intern3(const char *name, long len, rb_encoding *enc); RBIMPL_ATTR_NONNULL(()) /** * Identical to rb_symname_p(), except it additionally takes an encoding. * * @param[in] str A C string to check. * @param[in] enc `str`'s encoding. * @retval 1 It is a valid symbol name. * @retval 0 It is invalid as a symbol name. */ int rb_enc_symname_p(const char *str, rb_encoding *enc); /** * Identical to rb_enc_symname_p(), except it additionally takes the passed * string's length. This is needed for strings containing NUL bytes, like in * case of UTF-32. * * @param[in] name A C string to check. * @param[in] len Number of bytes of `str`. * @param[in] enc `str`'s encoding. * @retval 1 It is a valid symbol name. * @retval 0 It is invalid as a symbol name. */ int rb_enc_symname2_p(const char *name, long len, rb_encoding *enc); /** * Identical to rb_check_id(), except it takes a pointer to a memory region * instead of Ruby's string. * * @param[in] ptr A pointer to a memory region. * @param[in] len Number of bytes of `ptr`. * @param[in] enc Encoding of `ptr`. * @exception rb_eEncodingError `ptr` contains non-ASCII according to `enc`. * @retval 0 No such id ever existed in the history. * @retval otherwise The id that represents the given name. */ ID rb_check_id_cstr(const char *ptr, long len, rb_encoding *enc); /** * Identical to rb_check_id_cstr(), except for the return type. It can also be * seen as a routine identical to rb_check_symbol(), except it takes a pointer * to a memory region instead of Ruby's string. * * @param[in] ptr A pointer to a memory region. * @param[in] len Number of bytes of `ptr`. * @param[in] enc Encoding of `ptr`. * @exception rb_eEncodingError `ptr` contains non-ASCII according to `enc`. * @retval RUBY_Qnil No such id ever existed in the history. * @retval otherwise The id that represents the given name. */ VALUE rb_check_symbol_cstr(const char *ptr, long len, rb_encoding *enc); RBIMPL_SYMBOL_EXPORT_END() #endif /* RUBY_INTERNAL_ENCODING_SYMBOL_H */ include/ruby/internal/encoding/transcode.h 0000644 00000062175 15152150500 0014712 0 ustar 00 #ifndef RUBY_INTERNAL_ENCODING_TRANSCODE_H /*-*-C++-*-vi:se ft=cpp:*/ #define RUBY_INTERNAL_ENCODING_TRANSCODE_H /** * @file * @author Ruby developers <ruby-core@ruby-lang.org> * @copyright This file is a part of the programming language Ruby. * Permission is hereby granted, to either redistribute and/or * modify this file, provided that the conditions mentioned in the * file COPYING are met. Consult the file for details. * @warning Symbols prefixed with either `RBIMPL` or `rbimpl` are * implementation details. Don't take them as canon. They could * rapidly appear then vanish. The name (path) of this header file * is also an implementation detail. Do not expect it to persist * at the place it is now. Developers are free to move it anywhere * anytime at will. * @note To ruby-core: remember that this header can be possibly * recursively included from extension libraries written in C++. * Do not expect for instance `__VA_ARGS__` is always available. * We assume C99 for ruby itself but we don't assume languages of * extension libraries. They could be written in C++98. * @brief econv stuff */ #include "ruby/internal/dllexport.h" #include "ruby/internal/value.h" RBIMPL_SYMBOL_EXPORT_BEGIN() /** return value of rb_econv_convert() */ typedef enum { /** * The conversion stopped when it found an invalid sequence. */ econv_invalid_byte_sequence, /** * The conversion stopped when it found a character in the input which * cannot be representable in the output. */ econv_undefined_conversion, /** * The conversion stopped because there is no destination. */ econv_destination_buffer_full, /** * The conversion stopped because there is no input. */ econv_source_buffer_empty, /** * The conversion stopped after converting everything. This is arguably * the expected normal end of conversion. */ econv_finished, /** * The conversion stopped after writing something to somewhere, before * reading everything. */ econv_after_output, /** * The conversion stopped in middle of reading a character, possibly due to * a partial read of a socket etc. */ econv_incomplete_input } rb_econv_result_t; /** An opaque struct that represents a lowest level of encoding conversion. */ typedef struct rb_econv_t rb_econv_t; /** * Converts the contents of the passed string from its encoding to the passed * one. * * @param[in] str Target string. * @param[in] to Destination encoding. * @param[in] ecflags A set of enum * ::ruby_econv_flag_type. * @param[in] ecopts A keyword hash, like * ::rb_io_t::rb_io_enc_t::ecopts. * @exception rb_eArgError Not fully converted. * @exception rb_eInvalidByteSequenceError `str` is malformed. * @exception rb_eUndefinedConversionError `str` has a character not * representable using `to`. * @exception rb_eConversionNotFoundError There is no known conversion from * `str`'s encoding to `to`. * @return A string whose encoding is `to`, and whose contents is converted * contents of `str`. * @note Use rb_econv_prepare_options() to generate `ecopts`. */ VALUE rb_str_encode(VALUE str, VALUE to, int ecflags, VALUE ecopts); /** * Queries if there is more than one way to convert between the passed two * encodings. Encoding conversion are has_and_belongs_to_many relationships. * There could be no direct conversion defined for the passed pair. Ruby tries * to find an indirect way to do so then. For instance ISO-8859-1 has no * direct conversion to ISO-2022-JP. But there is ISO-8859-1 to UTF-8 * conversion; then there is UTF-8 to EUC-JP conversion; finally there also is * EUC-JP to ISO-2022-JP conversion. So in short ISO-8859-1 can be converted * to ISO-2022-JP using that path. This function returns true. Obviously not * everything that can be represented using UTF-8 can also be represented using * EUC-JP. Conversions in practice can fail depending on the actual input, and * that renders exceptions in case of rb_str_encode(). * * @param[in] from_encoding One encoding. * @param[in] to_encoding Another encoding. * @retval 0 No way to convert the two. * @retval 1 At least one way to convert the two. * * @internal * * Practically @shyouhei knows no way for this function to return 0. It seems * everything can eventually be converted to/from UTF-8, which connects * everything. */ int rb_econv_has_convpath_p(const char* from_encoding, const char* to_encoding); /** * Identical to rb_econv_prepare_opts(), except it additionally takes the * initial value of flags. The extra bits are bitwise-ORed to the return * value. * * @param[in] opthash Keyword arguments. * @param[out] ecopts Return buffer. * @param[in] ecflags Default set of enum ::ruby_econv_flag_type. * @exception rb_eArgError Unknown/Broken values passed. * @return Calculated set of enum ::ruby_econv_flag_type. * @post `ecopts` holds a hash object suitable for * ::rb_io_t::rb_io_enc_t::ecopts. */ int rb_econv_prepare_options(VALUE opthash, VALUE *ecopts, int ecflags); /** * Splits a keyword arguments hash (that for instance `String#encode` took) * into a set of enum ::ruby_econv_flag_type and a hash storing replacement * characters etc. * * @param[in] opthash Keyword arguments. * @param[out] ecopts Return buffer. * @exception rb_eArgError Unknown/Broken values passed. * @return Calculated set of enum ::ruby_econv_flag_type. * @post `ecopts` holds a hash object suitable for * ::rb_io_t::rb_io_enc_t::ecopts. */ int rb_econv_prepare_opts(VALUE opthash, VALUE *ecopts); /** * Creates a new instance of struct ::rb_econv_t. * * @param[in] source_encoding Name of an encoding. * @param[in] destination_encoding Name of another encoding. * @param[in] ecflags A set of enum ::ruby_econv_flag_type. * @exception rb_eArgError No such encoding. * @retval NULL Failed to create a struct ::rb_econv_t. * @retval otherwise Allocated struct ::rb_econv_t. * @warning Return value must be passed to rb_econv_close() exactly once. */ rb_econv_t *rb_econv_open(const char *source_encoding, const char *destination_encoding, int ecflags); /** * Identical to rb_econv_open(), except it additionally takes a hash of * optional strings. * * * @param[in] source_encoding Name of an encoding. * @param[in] destination_encoding Name of another encoding. * @param[in] ecflags A set of enum ::ruby_econv_flag_type. * @param[in] ecopts Optional set of strings. * @exception rb_eArgError No such encoding. * @retval NULL Failed to create a struct ::rb_econv_t. * @retval otherwise Allocated struct ::rb_econv_t. * @warning Return value must be passed to rb_econv_close() exactly once. */ rb_econv_t *rb_econv_open_opts(const char *source_encoding, const char *destination_encoding, int ecflags, VALUE ecopts); /** * Converts a string from an encoding to another. * * Possible flags are either ::RUBY_ECONV_PARTIAL_INPUT (means the source * buffer is a part of much larger one), ::RUBY_ECONV_AFTER_OUTPUT (instructs * the converter to stop after output before input), or both of them. * * @param[in,out] ec Conversion specification/state etc. * @param[in] source_buffer_ptr Target string. * @param[in] source_buffer_end End of target string. * @param[out] destination_buffer_ptr Return buffer. * @param[out] destination_buffer_end End of return buffer. * @param[in] flags Flags (see above). * @return The status of the conversion. * @post `destination_buffer_ptr` holds conversion results. */ rb_econv_result_t rb_econv_convert(rb_econv_t *ec, const unsigned char **source_buffer_ptr, const unsigned char *source_buffer_end, unsigned char **destination_buffer_ptr, unsigned char *destination_buffer_end, int flags); /** * Destructs a converter. Note that a converter can have a buffer, and can be * non-empty. Calling this would lose your data then. * * @param[out] ec The converter to destroy. * @post `ec` is no longer a valid pointer. */ void rb_econv_close(rb_econv_t *ec); /** * Assigns the replacement string. The string passed here would appear in * converted string when it cannot represent its source counterpart. This can * happen for instance you convert an emoji to ISO-8859-1. * * @param[out] ec Target converter. * @param[in] str Replacement string. * @param[in] len Number of bytes of `str`. * @param[in] encname Name of encoding of `str`. * @retval 0 Success. * @retval -1 Failure (ENOMEM etc.). * @post `ec`'s replacement string is set to `str`. */ int rb_econv_set_replacement(rb_econv_t *ec, const unsigned char *str, size_t len, const char *encname); /** * "Decorate"s a converter. There are special kind of converters that * transforms the contents, like replacing CR into CRLF. You can add such * decorators to a converter using this API. By using this function a * decorator is prepended at the beginning of a conversion sequence: in case of * CRLF conversion, newlines are converted before encodings are converted. * * @param[out] ec Target converter to decorate. * @param[in] decorator_name Name of decorator to prepend. * @retval 0 Success. * @retval -1 Failure (no such decorator etc.). * @post Decorator works before encoding conversion happens. * * @internal * * What is the possible value of the `decorator_name` is not public. You have * to read through `transcode.c` carefully. */ int rb_econv_decorate_at_first(rb_econv_t *ec, const char *decorator_name); /** * Identical to rb_econv_decorate_at_first(), except it adds to the opposite * direction. For instance CRLF conversion would run _after_ encodings are * converted. * * @param[out] ec Target converter to decorate. * @param[in] decorator_name Name of decorator to prepend. * @retval 0 Success. * @retval -1 Failure (no such decorator etc.). * @post Decorator works after encoding conversion happens. */ int rb_econv_decorate_at_last(rb_econv_t *ec, const char *decorator_name); /** * Creates a `rb_eConverterNotFoundError` exception object (but does not * raise). * * @param[in] senc Name of source encoding. * @param[in] denc Name of destination encoding. * @param[in] ecflags A set of enum ::ruby_econv_flag_type. * @return An instance of `rb_eConverterNotFoundError`. */ VALUE rb_econv_open_exc(const char *senc, const char *denc, int ecflags); /** * Appends the passed string to the passed converter's output buffer. This can * be handy when an encoding needs bytes out of thin air; for instance * ISO-2022-JP has "shift function" which does not correspond to any * characters. * * @param[out] ec Target converter. * @param[in] str String to insert. * @param[in] len Number of bytes of `str`. * @param[in] str_encoding Encoding of `str`. * @retval 0 Success. * @retval -1 Failure (conversion error etc.). * @note `str_encoding` can be anything, and `str` itself is converted * when necessary. */ int rb_econv_insert_output(rb_econv_t *ec, const unsigned char *str, size_t len, const char *str_encoding); /** * Queries an encoding name which best suits for rb_econv_insert_output()'s * last parameter. Strings in this encoding need no conversion when inserted; * can be both time/space efficient. * * @param[in] ec Target converter. * @return Its encoding for insertion. */ const char *rb_econv_encoding_to_insert_output(rb_econv_t *ec); /** * This is a rb_econv_make_exception() + rb_exc_raise() combo. * * @param[in] ec (Possibly failed) conversion. * @exception rb_eInvalidByteSequenceError Invalid byte sequence. * @exception rb_eUndefinedConversionError Conversion undefined. * @note This function can return when no error. */ void rb_econv_check_error(rb_econv_t *ec); /** * This function makes sense right after rb_econv_convert() returns. As listed * in ::rb_econv_result_t, rb_econv_convert() can bail out for various reasons. * This function checks the passed converter's internal state and convert it to * an appropriate exception object. * * @param[in] ec Target converter. * @retval RUBY_Qnil The converter has no error. * @retval otherwise Conversion error turned into an exception. */ VALUE rb_econv_make_exception(rb_econv_t *ec); /** * Queries if rb_econv_putback() makes sense, i.e. there are invalid byte * sequences remain in the buffer. * * @param[in] ec Target converter. * @return Number of bytes that can be pushed back. */ int rb_econv_putbackable(rb_econv_t *ec); /** * Puts back the bytes. In case of ::econv_invalid_byte_sequence, some of * those invalid bytes are discarded and the others are buffered to be * converted later. The latter bytes can be put back using this API. * * @param[out] ec Target converter (invalid byte sequence). * @param[out] p Return buffer. * @param[in] n Max number of bytes to put back. * @post At most `n` bytes of what was put back is written to `p`. */ void rb_econv_putback(rb_econv_t *ec, unsigned char *p, int n); /** * Queries the passed encoding's corresponding ASCII compatible encoding. "The * corresponding ASCII compatible encoding" in this context is an ASCII * compatible encoding which can represent exactly the same character sets as * the given ASCII incompatible encoding. For instance that of UTF-16LE is * UTF-8. * * @param[in] encname Name of an ASCII incompatible encoding. * @retval NULL `encname` is already ASCII compatible. * @retval otherwise The corresponding ASCII compatible encoding. */ const char *rb_econv_asciicompat_encoding(const char *encname); /** * Identical to rb_econv_convert(), except it takes Ruby's string instead of * C's pointer. * * @param[in,out] ec Target converter. * @param[in] src Source string. * @param[in] flags Flags (see rb_econv_convert). * @exception rb_eArgError Converted string is too long. * @exception rb_eInvalidByteSequenceError Invalid byte sequence. * @exception rb_eUndefinedConversionError Conversion undefined. * @return The conversion result. */ VALUE rb_econv_str_convert(rb_econv_t *ec, VALUE src, int flags); /** * Identical to rb_econv_str_convert(), except it converts only a part of the * passed string. Can be handy when you for instance want to do line-buffered * conversion. * * @param[in,out] ec Target converter. * @param[in] src Source string. * @param[in] byteoff Number of bytes to seek. * @param[in] bytesize Number of bytes to read. * @param[in] flags Flags (see rb_econv_convert). * @exception rb_eArgError Converted string is too long. * @exception rb_eInvalidByteSequenceError Invalid byte sequence. * @exception rb_eUndefinedConversionError Conversion undefined. * @return The conversion result. */ VALUE rb_econv_substr_convert(rb_econv_t *ec, VALUE src, long byteoff, long bytesize, int flags); /** * Identical to rb_econv_str_convert(), except it appends the conversion result * to the additionally passed string instead of creating a new string. It can * also be seen as a routine identical to rb_econv_append(), except it takes a * Ruby's string instead of C's pointer. * * @param[in,out] ec Target converter. * @param[in] src Source string. * @param[in] dst Return buffer. * @param[in] flags Flags (see rb_econv_convert). * @exception rb_eArgError Converted string is too long. * @exception rb_eInvalidByteSequenceError Invalid byte sequence. * @exception rb_eUndefinedConversionError Conversion undefined. * @return The conversion result. */ VALUE rb_econv_str_append(rb_econv_t *ec, VALUE src, VALUE dst, int flags); /** * Identical to rb_econv_str_append(), except it appends only a part of the * passed string with conversion. It can also be seen as a routine identical * to rb_econv_substr_convert(), except it appends the conversion result to the * additionally passed string instead of creating a new string. * * @param[in,out] ec Target converter. * @param[in] src Source string. * @param[in] byteoff Number of bytes to seek. * @param[in] bytesize Number of bytes to read. * @param[in] dst Return buffer. * @param[in] flags Flags (see rb_econv_convert). * @exception rb_eArgError Converted string is too long. * @exception rb_eInvalidByteSequenceError Invalid byte sequence. * @exception rb_eUndefinedConversionError Conversion undefined. * @return The conversion result. */ VALUE rb_econv_substr_append(rb_econv_t *ec, VALUE src, long byteoff, long bytesize, VALUE dst, int flags); /** * Converts the passed C's pointer according to the passed converter, then * append the conversion result to the passed Ruby's string. This way buffer * overflow is properly avoided to resize the destination properly. * * @param[in,out] ec Target converter. * @param[in] bytesrc Target string. * @param[in] bytesize Number of bytes of `bytesrc`. * @param[in] dst Return buffer. * @param[in] flags Flags (see rb_econv_convert). * @exception rb_eArgError Converted string is too long. * @exception rb_eInvalidByteSequenceError Invalid byte sequence. * @exception rb_eUndefinedConversionError Conversion undefined. * @return The conversion result. */ VALUE rb_econv_append(rb_econv_t *ec, const char *bytesrc, long bytesize, VALUE dst, int flags); /** * This badly named function does not set the destination encoding to binary, * but instead just nullifies newline conversion decorators if any. Other * ordinal character conversions still happen after this; something non-binary * would still be generated. * * @param[out] ec Target converter to modify. * @post Any newline conversions, if any, would be killed. */ void rb_econv_binmode(rb_econv_t *ec); /** * This enum is kind of omnibus. Gathers various constants. */ enum ruby_econv_flag_type { /** * @name Flags for rb_econv_open() * * @{ */ /** Mask for error handling related bits. */ RUBY_ECONV_ERROR_HANDLER_MASK = 0x000000ff, /** Special handling of invalid sequences are there. */ RUBY_ECONV_INVALID_MASK = 0x0000000f, /** Invalid sequences shall be replaced. */ RUBY_ECONV_INVALID_REPLACE = 0x00000002, /** Special handling of undefined conversion are there. */ RUBY_ECONV_UNDEF_MASK = 0x000000f0, /** Undefined characters shall be replaced. */ RUBY_ECONV_UNDEF_REPLACE = 0x00000020, /** Undefined characters shall be escaped. */ RUBY_ECONV_UNDEF_HEX_CHARREF = 0x00000030, /** Decorators are there. */ RUBY_ECONV_DECORATOR_MASK = 0x0001ff00, /** Newline converters are there. */ RUBY_ECONV_NEWLINE_DECORATOR_MASK = 0x00007f00, /** (Unclear; seems unused). */ RUBY_ECONV_NEWLINE_DECORATOR_READ_MASK = 0x00000f00, /** (Unclear; seems unused). */ RUBY_ECONV_NEWLINE_DECORATOR_WRITE_MASK = 0x00007000, /** Universal newline mode. */ RUBY_ECONV_UNIVERSAL_NEWLINE_DECORATOR = 0x00000100, /** CR to CRLF conversion shall happen. */ RUBY_ECONV_CRLF_NEWLINE_DECORATOR = 0x00001000, /** CRLF to CR conversion shall happen. */ RUBY_ECONV_CR_NEWLINE_DECORATOR = 0x00002000, /** CRLF to LF conversion shall happen. */ RUBY_ECONV_LF_NEWLINE_DECORATOR = 0x00004000, /** Texts shall be XML-escaped. */ RUBY_ECONV_XML_TEXT_DECORATOR = 0x00008000, /** Texts shall be AttrValue escaped */ RUBY_ECONV_XML_ATTR_CONTENT_DECORATOR = 0x00010000, /** (Unclear; seems unused). */ RUBY_ECONV_STATEFUL_DECORATOR_MASK = 0x00f00000, /** Texts shall be AttrValue escaped. */ RUBY_ECONV_XML_ATTR_QUOTE_DECORATOR = 0x00100000, /** Newline decorator's default. */ RUBY_ECONV_DEFAULT_NEWLINE_DECORATOR = #if defined(RUBY_TEST_CRLF_ENVIRONMENT) || defined(_WIN32) RUBY_ECONV_CRLF_NEWLINE_DECORATOR, #else 0, #endif #define ECONV_ERROR_HANDLER_MASK RUBY_ECONV_ERROR_HANDLER_MASK /**< @old{RUBY_ECONV_ERROR_HANDLER_MASK} */ #define ECONV_INVALID_MASK RUBY_ECONV_INVALID_MASK /**< @old{RUBY_ECONV_INVALID_MASK} */ #define ECONV_INVALID_REPLACE RUBY_ECONV_INVALID_REPLACE /**< @old{RUBY_ECONV_INVALID_REPLACE} */ #define ECONV_UNDEF_MASK RUBY_ECONV_UNDEF_MASK /**< @old{RUBY_ECONV_UNDEF_MASK} */ #define ECONV_UNDEF_REPLACE RUBY_ECONV_UNDEF_REPLACE /**< @old{RUBY_ECONV_UNDEF_REPLACE} */ #define ECONV_UNDEF_HEX_CHARREF RUBY_ECONV_UNDEF_HEX_CHARREF /**< @old{RUBY_ECONV_UNDEF_HEX_CHARREF} */ #define ECONV_DECORATOR_MASK RUBY_ECONV_DECORATOR_MASK /**< @old{RUBY_ECONV_DECORATOR_MASK} */ #define ECONV_NEWLINE_DECORATOR_MASK RUBY_ECONV_NEWLINE_DECORATOR_MASK /**< @old{RUBY_ECONV_NEWLINE_DECORATOR_MASK} */ #define ECONV_NEWLINE_DECORATOR_READ_MASK RUBY_ECONV_NEWLINE_DECORATOR_READ_MASK /**< @old{RUBY_ECONV_NEWLINE_DECORATOR_READ_MASK} */ #define ECONV_NEWLINE_DECORATOR_WRITE_MASK RUBY_ECONV_NEWLINE_DECORATOR_WRITE_MASK /**< @old{RUBY_ECONV_NEWLINE_DECORATOR_WRITE_MASK} */ #define ECONV_UNIVERSAL_NEWLINE_DECORATOR RUBY_ECONV_UNIVERSAL_NEWLINE_DECORATOR /**< @old{RUBY_ECONV_UNIVERSAL_NEWLINE_DECORATOR} */ #define ECONV_CRLF_NEWLINE_DECORATOR RUBY_ECONV_CRLF_NEWLINE_DECORATOR /**< @old{RUBY_ECONV_CRLF_NEWLINE_DECORATOR} */ #define ECONV_CR_NEWLINE_DECORATOR RUBY_ECONV_CR_NEWLINE_DECORATOR /**< @old{RUBY_ECONV_CR_NEWLINE_DECORATOR} */ #define ECONV_LF_NEWLINE_DECORATOR RUBY_ECONV_LF_NEWLINE_DECORATOR /**< @old{RUBY_ECONV_LF_NEWLINE_DECORATOR} */ #define ECONV_XML_TEXT_DECORATOR RUBY_ECONV_XML_TEXT_DECORATOR /**< @old{RUBY_ECONV_XML_TEXT_DECORATOR} */ #define ECONV_XML_ATTR_CONTENT_DECORATOR RUBY_ECONV_XML_ATTR_CONTENT_DECORATOR /**< @old{RUBY_ECONV_XML_ATTR_CONTENT_DECORATOR} */ #define ECONV_STATEFUL_DECORATOR_MASK RUBY_ECONV_STATEFUL_DECORATOR_MASK /**< @old{RUBY_ECONV_STATEFUL_DECORATOR_MASK} */ #define ECONV_XML_ATTR_QUOTE_DECORATOR RUBY_ECONV_XML_ATTR_QUOTE_DECORATOR /**< @old{RUBY_ECONV_XML_ATTR_QUOTE_DECORATOR} */ #define ECONV_DEFAULT_NEWLINE_DECORATOR RUBY_ECONV_DEFAULT_NEWLINE_DECORATOR /**< @old{RUBY_ECONV_DEFAULT_NEWLINE_DECORATOR} */ /** @} */ /** * @name Flags for rb_econv_convert() * * @{ */ /** Indicates the input is a part of much larger one. */ RUBY_ECONV_PARTIAL_INPUT = 0x00020000, /** Instructs the converter to stop after output. */ RUBY_ECONV_AFTER_OUTPUT = 0x00040000, #define ECONV_PARTIAL_INPUT RUBY_ECONV_PARTIAL_INPUT /**< @old{RUBY_ECONV_PARTIAL_INPUT} */ #define ECONV_AFTER_OUTPUT RUBY_ECONV_AFTER_OUTPUT /**< @old{RUBY_ECONV_AFTER_OUTPUT} */ RUBY_ECONV_FLAGS_PLACEHOLDER /**< Placeholder (not used) */ }; RBIMPL_SYMBOL_EXPORT_END() #endif /* RUBY_INTERNAL_ENCODING_TRANSCODE_H */ include/ruby/internal/encoding/sprintf.h 0000644 00000006600 15152150500 0014404 0 ustar 00 #ifndef RUBY_INTERNAL_ENCODING_SPRINTF_H /*-*-C++-*-vi:se ft=cpp:*/ #define RUBY_INTERNAL_ENCODING_SPRINTF_H /** * @file * @author Ruby developers <ruby-core@ruby-lang.org> * @copyright This file is a part of the programming language Ruby. * Permission is hereby granted, to either redistribute and/or * modify this file, provided that the conditions mentioned in the * file COPYING are met. Consult the file for details. * @warning Symbols prefixed with either `RBIMPL` or `rbimpl` are * implementation details. Don't take them as canon. They could * rapidly appear then vanish. The name (path) of this header file * is also an implementation detail. Do not expect it to persist * at the place it is now. Developers are free to move it anywhere * anytime at will. * @note To ruby-core: remember that this header can be possibly * recursively included from extension libraries written in C++. * Do not expect for instance `__VA_ARGS__` is always available. * We assume C99 for ruby itself but we don't assume languages of * extension libraries. They could be written in C++98. * @brief Routines to manipulate encodings of symbols. */ #include "ruby/internal/config.h" #include <stdarg.h> #include "ruby/internal/attr/format.h" #include "ruby/internal/attr/nonnull.h" #include "ruby/internal/attr/noreturn.h" #include "ruby/internal/dllexport.h" #include "ruby/internal/encoding/encoding.h" #include "ruby/internal/value.h" RBIMPL_SYMBOL_EXPORT_BEGIN() RBIMPL_ATTR_NONNULL((2)) RBIMPL_ATTR_FORMAT(RBIMPL_PRINTF_FORMAT, 2, 3) /** * Identical to rb_sprintf(), except it additionally takes an encoding. The * passed encoding rules both the incoming format specifier and the resulting * string. * * @param[in] enc Encoding of `fmt`. * @param[in] fmt A `printf`-like format specifier. * @param[in] ... Variadic number of contents to format. * @return A rendered new instance of ::rb_cString, of `enc` encoding. */ VALUE rb_enc_sprintf(rb_encoding *enc, const char *fmt, ...); RBIMPL_ATTR_NONNULL((2)) RBIMPL_ATTR_FORMAT(RBIMPL_PRINTF_FORMAT, 2, 0) /** * Identical to rb_enc_sprintf(), except it takes a `va_list` instead of * variadic arguments. It can also be seen as a routine identical to * rb_vsprintf(), except it additionally takes an encoding. * * @param[in] enc Encoding of `fmt`. * @param[in] fmt A `printf`-like format specifier. * @param[in] ap Contents to format. * @return A rendered new instance of ::rb_cString, of `enc` encoding. */ VALUE rb_enc_vsprintf(rb_encoding *enc, const char *fmt, va_list ap); RBIMPL_ATTR_NORETURN() RBIMPL_ATTR_NONNULL((3)) RBIMPL_ATTR_FORMAT(RBIMPL_PRINTF_FORMAT, 3, 4) /** * Identical to rb_raise(), except it additionally takes an encoding. * * @param[in] enc Encoding of the generating exception. * @param[in] exc A subclass of ::rb_eException. * @param[in] fmt Format specifier string compatible with rb_sprintf(). * @param[in] ... Contents of the message. * @exception exc The specified exception. * @note It never returns. */ void rb_enc_raise(rb_encoding *enc, VALUE exc, const char *fmt, ...); RBIMPL_SYMBOL_EXPORT_END() #endif /* RUBY_INTERNAL_ENCODING_SPRINTF_H */ include/ruby/internal/encoding/coderange.h 0000644 00000017616 15152150500 0014657 0 ustar 00 #ifndef RUBY_INTERNAL_ENCODING_CODERANGE_H /*-*-C++-*-vi:se ft=cpp:*/ #define RUBY_INTERNAL_ENCODING_CODERANGE_H /** * @file * @author Ruby developers <ruby-core@ruby-lang.org> * @copyright This file is a part of the programming language Ruby. * Permission is hereby granted, to either redistribute and/or * modify this file, provided that the conditions mentioned in the * file COPYING are met. Consult the file for details. * @warning Symbols prefixed with either `RBIMPL` or `rbimpl` are * implementation details. Don't take them as canon. They could * rapidly appear then vanish. The name (path) of this header file * is also an implementation detail. Do not expect it to persist * at the place it is now. Developers are free to move it anywhere * anytime at will. * @note To ruby-core: remember that this header can be possibly * recursively included from extension libraries written in C++. * Do not expect for instance `__VA_ARGS__` is always available. * We assume C99 for ruby itself but we don't assume languages of * extension libraries. They could be written in C++98. * @brief Routines for code ranges. */ #include "ruby/internal/attr/const.h" #include "ruby/internal/attr/pure.h" #include "ruby/internal/dllexport.h" #include "ruby/internal/fl_type.h" #include "ruby/internal/value.h" RBIMPL_SYMBOL_EXPORT_BEGIN() /** What rb_enc_str_coderange() returns. */ enum ruby_coderange_type { /** The object's coderange is unclear yet. */ RUBY_ENC_CODERANGE_UNKNOWN = 0, /** The object holds 0 to 127 inclusive and nothing else. */ RUBY_ENC_CODERANGE_7BIT = ((int)RUBY_FL_USER8), /** The object's encoding and contents are consistent each other */ RUBY_ENC_CODERANGE_VALID = ((int)RUBY_FL_USER9), /** The object holds invalid/malformed/broken character(s). */ RUBY_ENC_CODERANGE_BROKEN = ((int)(RUBY_FL_USER8|RUBY_FL_USER9)), /** Where the coderange resides. */ RUBY_ENC_CODERANGE_MASK = (RUBY_ENC_CODERANGE_7BIT| RUBY_ENC_CODERANGE_VALID| RUBY_ENC_CODERANGE_BROKEN) }; RBIMPL_ATTR_CONST() /** * @private * * This is an implementation detail of #RB_ENC_CODERANGE_CLEAN_P. People don't * use it directly. * * @param[in] cr An enum ::ruby_coderange_type. * @retval 1 It is. * @retval 0 It isn't. */ static inline int rb_enc_coderange_clean_p(int cr) { return (cr ^ (cr >> 1)) & RUBY_ENC_CODERANGE_7BIT; } RBIMPL_ATTR_CONST() /** * Queries if a code range is "clean". "Clean" in this context means it is * known and valid. * * @param[in] cr An enum ::ruby_coderange_type. * @retval 1 It is. * @retval 0 It isn't. */ static inline bool RB_ENC_CODERANGE_CLEAN_P(enum ruby_coderange_type cr) { return rb_enc_coderange_clean_p(cr); } RBIMPL_ATTR_PURE_UNLESS_DEBUG() /** * Queries the (inline) code range of the passed object. The object must be * capable of having inline encoding. Using this macro needs deep * understanding of bit level object binary layout. * * @param[in] obj Target object. * @return An enum ::ruby_coderange_type. */ static inline enum ruby_coderange_type RB_ENC_CODERANGE(VALUE obj) { VALUE ret = RB_FL_TEST_RAW(obj, RUBY_ENC_CODERANGE_MASK); return RBIMPL_CAST((enum ruby_coderange_type)ret); } RBIMPL_ATTR_PURE_UNLESS_DEBUG() /** * Queries the (inline) code range of the passed object is * ::RUBY_ENC_CODERANGE_7BIT. The object must be capable of having inline * encoding. Using this macro needs deep understanding of bit level object * binary layout. * * @param[in] obj Target object. * @retval 1 It is ascii only. * @retval 0 Otherwise (including cases when the range is not known). */ static inline bool RB_ENC_CODERANGE_ASCIIONLY(VALUE obj) { return RB_ENC_CODERANGE(obj) == RUBY_ENC_CODERANGE_7BIT; } /** * Destructively modifies the passed object so that its (inline) code range is * the passed one. The object must be capable of having inline encoding. * Using this macro needs deep understanding of bit level object binary layout. * * @param[out] obj Target object. * @param[out] cr An enum ::ruby_coderange_type. * @post `obj`'s code range is `cr`. */ static inline void RB_ENC_CODERANGE_SET(VALUE obj, enum ruby_coderange_type cr) { RB_FL_UNSET_RAW(obj, RUBY_ENC_CODERANGE_MASK); RB_FL_SET_RAW(obj, cr); } /** * Destructively clears the passed object's (inline) code range. The object * must be capable of having inline encoding. Using this macro needs deep * understanding of bit level object binary layout. * * @param[out] obj Target object. * @post `obj`'s code range is ::RUBY_ENC_CODERANGE_UNKNOWN. */ static inline void RB_ENC_CODERANGE_CLEAR(VALUE obj) { RB_FL_UNSET_RAW(obj, RUBY_ENC_CODERANGE_MASK); } RBIMPL_ATTR_CONST() /* assumed ASCII compatibility */ /** * "Mix" two code ranges into one. This is handy for instance when you * concatenate two strings into one. Consider one of then is valid but the * other isn't. The result must be invalid. This macro computes that kind of * mixture. * * @param[in] a An enum ::ruby_coderange_type. * @param[in] b Another enum ::ruby_coderange_type. * @return The `a` "and" `b`. */ static inline enum ruby_coderange_type RB_ENC_CODERANGE_AND(enum ruby_coderange_type a, enum ruby_coderange_type b) { if (a == RUBY_ENC_CODERANGE_7BIT) { return b; } else if (a != RUBY_ENC_CODERANGE_VALID) { return RUBY_ENC_CODERANGE_UNKNOWN; } else if (b == RUBY_ENC_CODERANGE_7BIT) { return RUBY_ENC_CODERANGE_VALID; } else { return b; } } #define ENC_CODERANGE_MASK RUBY_ENC_CODERANGE_MASK /**< @old{RUBY_ENC_CODERANGE_MASK} */ #define ENC_CODERANGE_UNKNOWN RUBY_ENC_CODERANGE_UNKNOWN /**< @old{RUBY_ENC_CODERANGE_UNKNOWN} */ #define ENC_CODERANGE_7BIT RUBY_ENC_CODERANGE_7BIT /**< @old{RUBY_ENC_CODERANGE_7BIT} */ #define ENC_CODERANGE_VALID RUBY_ENC_CODERANGE_VALID /**< @old{RUBY_ENC_CODERANGE_VALID} */ #define ENC_CODERANGE_BROKEN RUBY_ENC_CODERANGE_BROKEN /**< @old{RUBY_ENC_CODERANGE_BROKEN} */ #define ENC_CODERANGE_CLEAN_P(cr) RB_ENC_CODERANGE_CLEAN_P(cr) /**< @old{RB_ENC_CODERANGE_CLEAN_P} */ #define ENC_CODERANGE(obj) RB_ENC_CODERANGE(obj) /**< @old{RB_ENC_CODERANGE} */ #define ENC_CODERANGE_ASCIIONLY(obj) RB_ENC_CODERANGE_ASCIIONLY(obj) /**< @old{RB_ENC_CODERANGE_ASCIIONLY} */ #define ENC_CODERANGE_SET(obj,cr) RB_ENC_CODERANGE_SET(obj,cr) /**< @old{RB_ENC_CODERANGE_SET} */ #define ENC_CODERANGE_CLEAR(obj) RB_ENC_CODERANGE_CLEAR(obj) /**< @old{RB_ENC_CODERANGE_CLEAR} */ #define ENC_CODERANGE_AND(a, b) RB_ENC_CODERANGE_AND(a, b) /**< @old{RB_ENC_CODERANGE_AND} */ #define ENCODING_CODERANGE_SET(obj, encindex, cr) RB_ENCODING_CODERANGE_SET(obj, encindex, cr) /**< @old{RB_ENCODING_CODERANGE_SET} */ /** @cond INTERNAL_MACRO */ #define RB_ENC_CODERANGE RB_ENC_CODERANGE #define RB_ENC_CODERANGE_AND RB_ENC_CODERANGE_AND #define RB_ENC_CODERANGE_ASCIIONLY RB_ENC_CODERANGE_ASCIIONLY #define RB_ENC_CODERANGE_CLEAN_P RB_ENC_CODERANGE_CLEAN_P #define RB_ENC_CODERANGE_CLEAR RB_ENC_CODERANGE_CLEAR #define RB_ENC_CODERANGE_SET RB_ENC_CODERANGE_SET /** @endcond */ RBIMPL_SYMBOL_EXPORT_END() #endif /* RUBY_INTERNAL_ENCODING_CODERANGE_H */ include/ruby/internal/has/cpp_attribute.h 0000644 00000010701 15152150500 0014546 0 ustar 00 #ifndef RBIMPL_HAS_CPP_ATTRIBUTE_H /*-*-C++-*-vi:se ft=cpp:*/ #define RBIMPL_HAS_CPP_ATTRIBUTE_H /** * @file * @author Ruby developers <ruby-core@ruby-lang.org> * @copyright This file is a part of the programming language Ruby. * Permission is hereby granted, to either redistribute and/or * modify this file, provided that the conditions mentioned in the * file COPYING are met. Consult the file for details. * @warning Symbols prefixed with either `RBIMPL` or `rbimpl` are * implementation details. Don't take them as canon. They could * rapidly appear then vanish. The name (path) of this header file * is also an implementation detail. Do not expect it to persist * at the place it is now. Developers are free to move it anywhere * anytime at will. * @note To ruby-core: remember that this header can be possibly * recursively included from extension libraries written in C++. * Do not expect for instance `__VA_ARGS__` is always available. * We assume C99 for ruby itself but we don't assume languages of * extension libraries. They could be written in C++98. * @brief Defines #RBIMPL_HAS_CPP_ATTRIBUTE. */ #include "ruby/internal/compiler_is.h" #include "ruby/internal/compiler_since.h" /** @cond INTERNAL_MACRO */ #if RBIMPL_COMPILER_IS(SunPro) # /* Oracle Developer Studio 12.5's C++ preprocessor is reportedly broken. We # * could simulate __has_cpp_attribute like below, but don't know the exact # * list of which version supported which attribute. Just kill everything for # * now. If you can please :FIXME: */ # /* https://unicode-org.atlassian.net/browse/ICU-12893 */ # /* https://github.com/boostorg/config/pull/95 */ # define RBIMPL_HAS_CPP_ATTRIBUTE0(_) 0 #elif defined(__has_cpp_attribute) # define RBIMPL_HAS_CPP_ATTRIBUTE0(_) __has_cpp_attribute(_) #elif RBIMPL_COMPILER_IS(MSVC) # /* MSVC has never updated its __cplusplus since forever (unless specified # * explicitly by a compiler flag). They also lack __has_cpp_attribute until # * 2019. However, they do have attributes since 2015 or so. */ # /* https://docs.microsoft.com/en-us/cpp/overview/visual-cpp-language-conformance */ # define RBIMPL_HAS_CPP_ATTRIBUTE0(_) (RBIMPL_HAS_CPP_ATTRIBUTE_ ## _) # define RBIMPL_HAS_CPP_ATTRIBUTE_noreturn 200809 * RBIMPL_COMPILER_SINCE(MSVC, 19, 00, 0) # define RBIMPL_HAS_CPP_ATTRIBUTE_carries_dependency 200809 * RBIMPL_COMPILER_SINCE(MSVC, 19, 00, 0) # define RBIMPL_HAS_CPP_ATTRIBUTE_deprecated 201309 * RBIMPL_COMPILER_SINCE(MSVC, 19, 10, 0) # define RBIMPL_HAS_CPP_ATTRIBUTE_fallthrough 201603 * RBIMPL_COMPILER_SINCE(MSVC, 19, 10, 0) # define RBIMPL_HAS_CPP_ATTRIBUTE_maybe_unused 201603 * RBIMPL_COMPILER_SINCE(MSVC, 19, 11, 0) # define RBIMPL_HAS_CPP_ATTRIBUTE_nodiscard 201603 * RBIMPL_COMPILER_SINCE(MSVC, 19, 11, 0) #elif RBIMPL_COMPILER_BEFORE(Clang, 3, 6, 0) # /* Clang 3.6.0 introduced __has_cpp_attribute. Prior to that following # * attributes were already there. */ # /* https://clang.llvm.org/cxx_status.html */ # define RBIMPL_HAS_CPP_ATTRIBUTE0(_) (RBIMPL_HAS_CPP_ATTRIBUTE_ ## _) # define RBIMPL_HAS_CPP_ATTRIBUTE_noreturn 200809 * RBIMPL_COMPILER_SINCE(Clang, 3, 3, 0) # define RBIMPL_HAS_CPP_ATTRIBUTE_deprecated 201309 * RBIMPL_COMPILER_SINCE(Clang, 3, 4, 0) #elif RBIMPL_COMPILER_BEFORE(GCC, 5, 0, 0) # /* GCC 5+ have __has_cpp_attribute, while 4.x had following attributes. */ # /* https://gcc.gnu.org/projects/cxx-status.html */ # define RBIMPL_HAS_CPP_ATTRIBUTE0(_) (RBIMPL_HAS_CPP_ATTRIBUTE_ ## _) # define RBIMPL_HAS_CPP_ATTRIBUTE_noreturn 200809 * RBIMPL_COMPILER_SINCE(GCC, 4, 8, 0) # define RBIMPL_HAS_CPP_ATTRIBUTE_deprecated 201309 * RBIMPL_COMPILER_SINCE(GCC, 4, 9, 0) #else # /* :FIXME: # * Candidate compilers to list here: # * - icpc: They have __INTEL_CXX11_MODE__. # */ # define RBIMPL_HAS_CPP_ATTRIBUTE0(_) 0 #endif /** @endcond */ /** Wraps (or simulates) `__has_cpp_attribute`. */ #if ! defined(__cplusplus) # /* Makes no sense. */ # define RBIMPL_HAS_CPP_ATTRIBUTE(_) 0 #else # /* GCC needs workarounds. See https://gcc.godbolt.org/z/jdz3pa */ # define RBIMPL_HAS_CPP_ATTRIBUTE(_) \ ((RBIMPL_HAS_CPP_ATTRIBUTE0(_) <= __cplusplus) ? RBIMPL_HAS_CPP_ATTRIBUTE0(_) : 0) #endif #endif /* RBIMPL_HAS_CPP_ATTRIBUTE_H */ include/ruby/internal/has/extension.h 0000644 00000003242 15152150500 0013717 0 ustar 00 #ifndef RBIMPL_HAS_EXTENSION_H /*-*-C++-*-vi:se ft=cpp:*/ #define RBIMPL_HAS_EXTENSION_H /** * @file * @author Ruby developers <ruby-core@ruby-lang.org> * @copyright This file is a part of the programming language Ruby. * Permission is hereby granted, to either redistribute and/or * modify this file, provided that the conditions mentioned in the * file COPYING are met. Consult the file for details. * @warning Symbols prefixed with either `RBIMPL` or `rbimpl` are * implementation details. Don't take them as canon. They could * rapidly appear then vanish. The name (path) of this header file * is also an implementation detail. Do not expect it to persist * at the place it is now. Developers are free to move it anywhere * anytime at will. * @note To ruby-core: remember that this header can be possibly * recursively included from extension libraries written in C++. * Do not expect for instance `__VA_ARGS__` is always available. * We assume C99 for ruby itself but we don't assume languages of * extension libraries. They could be written in C++98. * @brief Defines #RBIMPL_HAS_EXTENSION. */ #include "ruby/internal/has/feature.h" /** Wraps (or simulates) `__has_extension`. */ #if defined(__has_extension) # define RBIMPL_HAS_EXTENSION(_) __has_extension(_) #else # /* Pre-3.0 clang had __has_feature but not __has_extension. */ # define RBIMPL_HAS_EXTENSION(_) RBIMPL_HAS_FEATURE(_) #endif #endif /* RBIMPL_HAS_EXTENSION_H */ include/ruby/internal/has/feature.h 0000644 00000003026 15152150501 0013337 0 ustar 00 #ifndef RBIMPL_HAS_FEATURE_H /*-*-C++-*-vi:se ft=cpp:*/ #define RBIMPL_HAS_FEATURE_H /** * @file * @author Ruby developers <ruby-core@ruby-lang.org> * @copyright This file is a part of the programming language Ruby. * Permission is hereby granted, to either redistribute and/or * modify this file, provided that the conditions mentioned in the * file COPYING are met. Consult the file for details. * @warning Symbols prefixed with either `RBIMPL` or `rbimpl` are * implementation details. Don't take them as canon. They could * rapidly appear then vanish. The name (path) of this header file * is also an implementation detail. Do not expect it to persist * at the place it is now. Developers are free to move it anywhere * anytime at will. * @note To ruby-core: remember that this header can be possibly * recursively included from extension libraries written in C++. * Do not expect for instance `__VA_ARGS__` is always available. * We assume C99 for ruby itself but we don't assume languages of * extension libraries. They could be written in C++98. * @brief Defines #RBIMPL_HAS_FEATURE. */ /** Wraps (or simulates) `__has_feature`. */ #if defined(__has_feature) # define RBIMPL_HAS_FEATURE(_) __has_feature(_) #else # define RBIMPL_HAS_FEATURE(_) 0 #endif #endif /* RBIMPL_HAS_FEATURE_H */ include/ruby/internal/has/builtin.h 0000644 00000016162 15152150501 0013357 0 ustar 00 #ifndef RBIMPL_HAS_BUILTIN_H /*-*-C++-*-vi:se ft=cpp:*/ #define RBIMPL_HAS_BUILTIN_H /** * @file * @author Ruby developers <ruby-core@ruby-lang.org> * @copyright This file is a part of the programming language Ruby. * Permission is hereby granted, to either redistribute and/or * modify this file, provided that the conditions mentioned in the * file COPYING are met. Consult the file for details. * @warning Symbols prefixed with either `RBIMPL` or `rbimpl` are * implementation details. Don't take them as canon. They could * rapidly appear then vanish. The name (path) of this header file * is also an implementation detail. Do not expect it to persist * at the place it is now. Developers are free to move it anywhere * anytime at will. * @note To ruby-core: remember that this header can be possibly * recursively included from extension libraries written in C++. * Do not expect for instance `__VA_ARGS__` is always available. * We assume C99 for ruby itself but we don't assume languages of * extension libraries. They could be written in C++98. * @brief Defines #RBIMPL_HAS_BUILTIN. */ #include "ruby/internal/config.h" #include "ruby/internal/compiler_since.h" #if defined(__has_builtin) # if RBIMPL_COMPILER_IS(Intel) # /* :TODO: Intel C Compiler has __has_builtin (since 19.1 maybe?), and is # * reportedly broken. We have to skip them. However the situation can # * change. They might improve someday. We need to revisit here later. */ # elif RBIMPL_COMPILER_IS(GCC) && ! __has_builtin(__builtin_alloca) # /* FreeBSD's <sys/cdefs.h> defines its own *broken* version of # * __has_builtin. Cygwin copied that content to be a victim of the # * broken-ness. We don't take them into account. */ # else # define RBIMPL_HAVE___HAS_BUILTIN 1 # endif #endif /** Wraps (or simulates) `__has_builtin`. */ #if defined(RBIMPL_HAVE___HAS_BUILTIN) # define RBIMPL_HAS_BUILTIN(_) __has_builtin(_) #elif RBIMPL_COMPILER_IS(GCC) # /* :FIXME: Historically GCC has had tons of builtins, but it implemented # * __has_builtin only since GCC 10. This section can be made more # * granular. */ # /* https://gcc.gnu.org/bugzilla/show_bug.cgi?id=66970 */ # define RBIMPL_HAS_BUILTIN(_) (RBIMPL_HAS_BUILTIN_ ## _) # define RBIMPL_HAS_BUILTIN___builtin_add_overflow RBIMPL_COMPILER_SINCE(GCC, 5, 1, 0) # define RBIMPL_HAS_BUILTIN___builtin_alloca RBIMPL_COMPILER_SINCE(GCC, 0, 0, 0) # define RBIMPL_HAS_BUILTIN___builtin_alloca_with_align RBIMPL_COMPILER_SINCE(GCC, 6, 1, 0) # define RBIMPL_HAS_BUILTIN___builtin_assume 0 # /* See http://gcc.gnu.org/bugzilla/show_bug.cgi?id=52624 for bswap16. */ # define RBIMPL_HAS_BUILTIN___builtin_bswap16 RBIMPL_COMPILER_SINCE(GCC, 4, 8, 0) #ifndef __OpenBSD__ # define RBIMPL_HAS_BUILTIN___builtin_bswap32 RBIMPL_COMPILER_SINCE(GCC, 3, 6, 0) # define RBIMPL_HAS_BUILTIN___builtin_bswap64 RBIMPL_COMPILER_SINCE(GCC, 3, 6, 0) #endif # define RBIMPL_HAS_BUILTIN___builtin_clz RBIMPL_COMPILER_SINCE(GCC, 3, 6, 0) # define RBIMPL_HAS_BUILTIN___builtin_clzl RBIMPL_COMPILER_SINCE(GCC, 3, 6, 0) # define RBIMPL_HAS_BUILTIN___builtin_clzll RBIMPL_COMPILER_SINCE(GCC, 3, 6, 0) # define RBIMPL_HAS_BUILTIN___builtin_constant_p RBIMPL_COMPILER_SINCE(GCC, 2,95, 3) # define RBIMPL_HAS_BUILTIN___builtin_ctz RBIMPL_COMPILER_SINCE(GCC, 3, 6, 0) # define RBIMPL_HAS_BUILTIN___builtin_ctzl RBIMPL_COMPILER_SINCE(GCC, 3, 6, 0) # define RBIMPL_HAS_BUILTIN___builtin_ctzll RBIMPL_COMPILER_SINCE(GCC, 3, 6, 0) # define RBIMPL_HAS_BUILTIN___builtin_expect RBIMPL_COMPILER_SINCE(GCC, 3, 0, 0) # define RBIMPL_HAS_BUILTIN___builtin_mul_overflow RBIMPL_COMPILER_SINCE(GCC, 5, 1, 0) # define RBIMPL_HAS_BUILTIN___builtin_mul_overflow_p RBIMPL_COMPILER_SINCE(GCC, 7, 0, 0) # define RBIMPL_HAS_BUILTIN___builtin_popcount RBIMPL_COMPILER_SINCE(GCC, 3, 6, 0) # define RBIMPL_HAS_BUILTIN___builtin_popcountl RBIMPL_COMPILER_SINCE(GCC, 3, 6, 0) # define RBIMPL_HAS_BUILTIN___builtin_popcountll RBIMPL_COMPILER_SINCE(GCC, 3, 6, 0) # define RBIMPL_HAS_BUILTIN___builtin_rotateleft32 0 # define RBIMPL_HAS_BUILTIN___builtin_rotateleft64 0 # define RBIMPL_HAS_BUILTIN___builtin_rotateright32 0 # define RBIMPL_HAS_BUILTIN___builtin_rotateright64 0 # define RBIMPL_HAS_BUILTIN___builtin_sub_overflow RBIMPL_COMPILER_SINCE(GCC, 5, 1, 0) # define RBIMPL_HAS_BUILTIN___builtin_unreachable RBIMPL_COMPILER_SINCE(GCC, 4, 5, 0) # /* Note that "0, 0, 0" might be inaccurate. */ #else # /* Take config.h definition when available */ # define RBIMPL_HAS_BUILTIN(_) ((RBIMPL_HAS_BUILTIN_ ## _)+0) # define RBIMPL_HAS_BUILTIN___builtin_add_overflow HAVE_BUILTIN___BUILTIN_ADD_OVERFLOW # define RBIMPL_HAS_BUILTIN___builtin_alloca 0 # define RBIMPL_HAS_BUILTIN___builtin_alloca_with_align HAVE_BUILTIN___BUILTIN_ALLOCA_WITH_ALIGN # define RBIMPL_HAS_BUILTIN___builtin_assume 0 # define RBIMPL_HAS_BUILTIN___builtin_assume_aligned HAVE_BUILTIN___BUILTIN_ASSUME_ALIGNED # define RBIMPL_HAS_BUILTIN___builtin_bswap16 HAVE_BUILTIN___BUILTIN_BSWAP16 # define RBIMPL_HAS_BUILTIN___builtin_bswap32 HAVE_BUILTIN___BUILTIN_BSWAP32 # define RBIMPL_HAS_BUILTIN___builtin_bswap64 HAVE_BUILTIN___BUILTIN_BSWAP64 # define RBIMPL_HAS_BUILTIN___builtin_clz HAVE_BUILTIN___BUILTIN_CLZ # define RBIMPL_HAS_BUILTIN___builtin_clzl HAVE_BUILTIN___BUILTIN_CLZL # define RBIMPL_HAS_BUILTIN___builtin_clzll HAVE_BUILTIN___BUILTIN_CLZLL # define RBIMPL_HAS_BUILTIN___builtin_constant_p HAVE_BUILTIN___BUILTIN_CONSTANT_P # define RBIMPL_HAS_BUILTIN___builtin_ctz HAVE_BUILTIN___BUILTIN_CTZ # define RBIMPL_HAS_BUILTIN___builtin_ctzl 0 # define RBIMPL_HAS_BUILTIN___builtin_ctzll HAVE_BUILTIN___BUILTIN_CTZLL # define RBIMPL_HAS_BUILTIN___builtin_expect HAVE_BUILTIN___BUILTIN_EXPECT # define RBIMPL_HAS_BUILTIN___builtin_mul_overflow HAVE_BUILTIN___BUILTIN_MUL_OVERFLOW # define RBIMPL_HAS_BUILTIN___builtin_mul_overflow_p HAVE_BUILTIN___BUILTIN_MUL_OVERFLOW_P # define RBIMPL_HAS_BUILTIN___builtin_popcount HAVE_BUILTIN___BUILTIN_POPCOUNT # define RBIMPL_HAS_BUILTIN___builtin_popcountl 0 # define RBIMPL_HAS_BUILTIN___builtin_rotateleft32 0 # define RBIMPL_HAS_BUILTIN___builtin_rotateleft64 0 # define RBIMPL_HAS_BUILTIN___builtin_rotateright32 0 # define RBIMPL_HAS_BUILTIN___builtin_rotateright64 0 # define RBIMPL_HAS_BUILTIN___builtin_popcountll HAVE_BUILTIN___BUILTIN_POPCOUNTLL # define RBIMPL_HAS_BUILTIN___builtin_sub_overflow HAVE_BUILTIN___BUILTIN_SUB_OVERFLOW # if defined(HAVE___BUILTIN_UNREACHABLE) # define RBIMPL_HAS_BUILTIN___builtin_unreachable 1 # else # define RBIMPL_HAS_BUILTIN___builtin_unreachable 0 # endif #endif #endif /* RBIMPL_HAS_BUILTIN_H */ include/ruby/internal/has/declspec_attribute.h 0000644 00000005371 15152150501 0015556 0 ustar 00 #ifndef RBIMPL_HAS_DECLSPEC_ATTRIBUTE_H /*-*-C++-*-vi:se ft=cpp:*/ #define RBIMPL_HAS_DECLSPEC_ATTRIBUTE_H /** * @file * @author Ruby developers <ruby-core@ruby-lang.org> * @copyright This file is a part of the programming language Ruby. * Permission is hereby granted, to either redistribute and/or * modify this file, provided that the conditions mentioned in the * file COPYING are met. Consult the file for details. * @warning Symbols prefixed with either `RBIMPL` or `rbimpl` are * implementation details. Don't take them as canon. They could * rapidly appear then vanish. The name (path) of this header file * is also an implementation detail. Do not expect it to persist * at the place it is now. Developers are free to move it anywhere * anytime at will. * @note To ruby-core: remember that this header can be possibly * recursively included from extension libraries written in C++. * Do not expect for instance `__VA_ARGS__` is always available. * We assume C99 for ruby itself but we don't assume languages of * extension libraries. They could be written in C++98. * @brief Defines #RBIMPL_HAS_DECLSPEC_ATTRIBUTE. */ #include "ruby/internal/compiler_since.h" /** Wraps (or simulates) `__has_declspec_attribute`. */ #if defined(__has_declspec_attribute) # define RBIMPL_HAS_DECLSPEC_ATTRIBUTE(_) __has_declspec_attribute(_) #else # define RBIMPL_HAS_DECLSPEC_ATTRIBUTE(_) (RBIMPL_HAS_DECLSPEC_ATTRIBUTE_ ## _) # define RBIMPL_HAS_DECLSPEC_ATTRIBUTE_align RBIMPL_COMPILER_SINCE(MSVC, 8, 0, 0) # define RBIMPL_HAS_DECLSPEC_ATTRIBUTE_deprecated RBIMPL_COMPILER_SINCE(MSVC,13, 0, 0) # define RBIMPL_HAS_DECLSPEC_ATTRIBUTE_dllexport RBIMPL_COMPILER_SINCE(MSVC, 8, 0, 0) # define RBIMPL_HAS_DECLSPEC_ATTRIBUTE_dllimport RBIMPL_COMPILER_SINCE(MSVC, 8, 0, 0) # define RBIMPL_HAS_DECLSPEC_ATTRIBUTE_empty_bases RBIMPL_COMPILER_SINCE(MSVC,19, 0, 23918) # define RBIMPL_HAS_DECLSPEC_ATTRIBUTE_noalias RBIMPL_COMPILER_SINCE(MSVC, 8, 0, 0) # define RBIMPL_HAS_DECLSPEC_ATTRIBUTE_noinline RBIMPL_COMPILER_SINCE(MSVC,13, 0, 0) # define RBIMPL_HAS_DECLSPEC_ATTRIBUTE_noreturn RBIMPL_COMPILER_SINCE(MSVC,11, 0, 0) # define RBIMPL_HAS_DECLSPEC_ATTRIBUTE_nothrow RBIMPL_COMPILER_SINCE(MSVC, 8, 0, 0) # define RBIMPL_HAS_DECLSPEC_ATTRIBUTE_restrict RBIMPL_COMPILER_SINCE(MSVC,14, 0, 0) # /* Note that "8, 0, 0" might be inaccurate. */ # if ! defined(__cplusplus) # /* Clang has this in both C/C++, but MSVC has this in C++ only.*/ # undef RBIMPL_HAS_DECLSPEC_ATTRIBUTE_nothrow # endif #endif #endif /* RBIMPL_HAS_DECLSPEC_ATTRIBUTE_H */ include/ruby/internal/has/c_attribute.h 0000644 00000004360 15152150501 0014213 0 ustar 00 #ifndef RBIMPL_HAS_C_ATTRIBUTE_H /*-*-C++-*-vi:se ft=cpp:*/ #define RBIMPL_HAS_C_ATTRIBUTE_H /** * @file * @author Ruby developers <ruby-core@ruby-lang.org> * @copyright This file is a part of the programming language Ruby. * Permission is hereby granted, to either redistribute and/or * modify this file, provided that the conditions mentioned in the * file COPYING are met. Consult the file for details. * @warning Symbols prefixed with either `RBIMPL` or `rbimpl` are * implementation details. Don't take them as canon. They could * rapidly appear then vanish. The name (path) of this header file * is also an implementation detail. Do not expect it to persist * at the place it is now. Developers are free to move it anywhere * anytime at will. * @note To ruby-core: remember that this header can be possibly * recursively included from extension libraries written in C++. * Do not expect for instance `__VA_ARGS__` is always available. * We assume C99 for ruby itself but we don't assume languages of * extension libraries. They could be written in C++98. * @brief Defines #RBIMPL_HAS_C_ATTRIBUTE. */ #include "ruby/internal/has/extension.h" #include "ruby/internal/has/warning.h" /** Wraps (or simulates) `__has_c_attribute`. */ #if defined(__cplusplus) # /* Makes no sense. */ # define RBIMPL_HAS_C_ATTRIBUTE(_) 0 #elif RBIMPL_HAS_EXTENSION(c_attributes) # /* Hmm. It seems Clang 17 has this macro defined even when -std=c99 mode, # * _and_ fails to compile complaining that attributes are C2X feature. We # * need to work around this nonsense. */ # define RBIMPL_HAS_C_ATTRIBUTE(_) __has_c_attribute(_) #elif RBIMPL_HAS_WARNING("-Wc2x-extensions") # define RBIMPL_HAS_C_ATTRIBUTE(_) 0 #elif defined(__has_c_attribute) # define RBIMPL_HAS_C_ATTRIBUTE(_) __has_c_attribute(_) #else # /* As of writing everything that lacks __has_c_attribute also completely # * lacks C2x attributes as well. Might change in future? */ # define RBIMPL_HAS_C_ATTRIBUTE(_) 0 #endif #endif /* RBIMPL_HAS_C_ATTRIBUTE_H */ include/ruby/internal/has/attribute.h 0000644 00000020510 15152150501 0013704 0 ustar 00 #ifndef RBIMPL_HAS_ATTRIBUTE_H /*-*-C++-*-vi:se ft=cpp:*/ #define RBIMPL_HAS_ATTRIBUTE_H /** * @file * @author Ruby developers <ruby-core@ruby-lang.org> * @copyright This file is a part of the programming language Ruby. * Permission is hereby granted, to either redistribute and/or * modify this file, provided that the conditions mentioned in the * file COPYING are met. Consult the file for details. * @warning Symbols prefixed with either `RBIMPL` or `rbimpl` are * implementation details. Don't take them as canon. They could * rapidly appear then vanish. The name (path) of this header file * is also an implementation detail. Do not expect it to persist * at the place it is now. Developers are free to move it anywhere * anytime at will. * @note To ruby-core: remember that this header can be possibly * recursively included from extension libraries written in C++. * Do not expect for instance `__VA_ARGS__` is always available. * We assume C99 for ruby itself but we don't assume languages of * extension libraries. They could be written in C++98. * @brief Defines #RBIMPL_HAS_ATTRIBUTE. */ #include "ruby/internal/config.h" #include "ruby/internal/compiler_since.h" #if defined(__has_attribute) # if __has_attribute(pure) || RBIMPL_COMPILER_IS(GCC) # /* FreeBSD's <sys/cdefs.h> defines its own *broken* version of # * __has_attribute. Cygwin copied that content to be a victim of the # * broken-ness. We don't take them into account. */ # define RBIMPL_HAVE___HAS_ATTRIBUTE 1 # endif #endif /** Wraps (or simulates) `__has_attribute`. */ #if defined(RBIMPL_HAVE___HAS_ATTRIBUTE) # define RBIMPL_HAS_ATTRIBUTE(_) __has_attribute(_) #elif RBIMPL_COMPILER_IS(GCC) # /* GCC <= 4 lack __has_attribute predefined macro, while have attributes # * themselves. We can simulate the macro like the following: */ # define RBIMPL_HAS_ATTRIBUTE(_) (RBIMPL_HAS_ATTRIBUTE_ ## _) # define RBIMPL_HAS_ATTRIBUTE_aligned RBIMPL_COMPILER_SINCE(GCC, 0, 0, 0) # define RBIMPL_HAS_ATTRIBUTE_alloc_size RBIMPL_COMPILER_SINCE(GCC, 4, 3, 0) # define RBIMPL_HAS_ATTRIBUTE_artificial RBIMPL_COMPILER_SINCE(GCC, 4, 3, 0) # define RBIMPL_HAS_ATTRIBUTE_always_inline RBIMPL_COMPILER_SINCE(GCC, 3, 1, 0) # define RBIMPL_HAS_ATTRIBUTE_cdecl RBIMPL_COMPILER_SINCE(GCC, 0, 0, 0) # define RBIMPL_HAS_ATTRIBUTE_cold RBIMPL_COMPILER_SINCE(GCC, 4, 3, 0) # define RBIMPL_HAS_ATTRIBUTE_const RBIMPL_COMPILER_SINCE(GCC, 2, 6, 0) # define RBIMPL_HAS_ATTRIBUTE_deprecated RBIMPL_COMPILER_SINCE(GCC, 3, 1, 0) # define RBIMPL_HAS_ATTRIBUTE_dllexport RBIMPL_COMPILER_SINCE(GCC, 0, 0, 0) # define RBIMPL_HAS_ATTRIBUTE_dllimport RBIMPL_COMPILER_SINCE(GCC, 0, 0, 0) # define RBIMPL_HAS_ATTRIBUTE_error RBIMPL_COMPILER_SINCE(GCC, 4, 3, 0) # define RBIMPL_HAS_ATTRIBUTE_format RBIMPL_COMPILER_SINCE(GCC, 0, 0, 0) # define RBIMPL_HAS_ATTRIBUTE_hot RBIMPL_COMPILER_SINCE(GCC, 4, 3, 0) # define RBIMPL_HAS_ATTRIBUTE_leaf RBIMPL_COMPILER_SINCE(GCC, 4, 6, 0) # define RBIMPL_HAS_ATTRIBUTE_malloc RBIMPL_COMPILER_SINCE(GCC, 3, 0, 0) # define RBIMPL_HAS_ATTRIBUTE_no_address_safety_analysis RBIMPL_COMPILER_SINCE(GCC, 4, 8, 0) # define RBIMPL_HAS_ATTRIBUTE_no_sanitize_address RBIMPL_COMPILER_SINCE(GCC, 4, 8, 0) # define RBIMPL_HAS_ATTRIBUTE_no_sanitize_undefined RBIMPL_COMPILER_SINCE(GCC, 4, 9, 0) # define RBIMPL_HAS_ATTRIBUTE_noinline RBIMPL_COMPILER_SINCE(GCC, 3, 1, 0) # define RBIMPL_HAS_ATTRIBUTE_nonnull RBIMPL_COMPILER_SINCE(GCC, 3, 3, 0) # define RBIMPL_HAS_ATTRIBUTE_noreturn RBIMPL_COMPILER_SINCE(GCC, 2, 5, 0) # define RBIMPL_HAS_ATTRIBUTE_nothrow RBIMPL_COMPILER_SINCE(GCC, 3, 3, 0) # define RBIMPL_HAS_ATTRIBUTE_pure RBIMPL_COMPILER_SINCE(GCC, 2,96, 0) # define RBIMPL_HAS_ATTRIBUTE_returns_nonnull RBIMPL_COMPILER_SINCE(GCC, 4, 9, 0) # define RBIMPL_HAS_ATTRIBUTE_returns_twice RBIMPL_COMPILER_SINCE(GCC, 4, 1, 0) # define RBIMPL_HAS_ATTRIBUTE_stdcall RBIMPL_COMPILER_SINCE(GCC, 0, 0, 0) # define RBIMPL_HAS_ATTRIBUTE_unused RBIMPL_COMPILER_SINCE(GCC, 0, 0, 0) # define RBIMPL_HAS_ATTRIBUTE_visibility RBIMPL_COMPILER_SINCE(GCC, 3, 3, 0) # define RBIMPL_HAS_ATTRIBUTE_warn_unused_result RBIMPL_COMPILER_SINCE(GCC, 3, 4, 0) # define RBIMPL_HAS_ATTRIBUTE_warning RBIMPL_COMPILER_SINCE(GCC, 4, 3, 0) # define RBIMPL_HAS_ATTRIBUTE_weak RBIMPL_COMPILER_SINCE(GCC, 0, 0, 0) # /* Note that "0, 0, 0" might be inaccurate. */ #elif RBIMPL_COMPILER_IS(SunPro) # /* Oracle Solaris Studio 12.4 (cc version 5.11) introduced __has_attribute. # * Before that, following attributes were available. */ # /* See https://docs.oracle.com/cd/F24633_01/index.html */ # define RBIMPL_HAS_ATTRIBUTE(_) (RBIMPL_HAS_ATTRIBUTE_ ## _) # define RBIMPL_HAS_ATTRIBUTE_alias RBIMPL_COMPILER_SINCE(SunPro, 5, 9, 0) # define RBIMPL_HAS_ATTRIBUTE_aligned RBIMPL_COMPILER_SINCE(SunPro, 5, 9, 0) # define RBIMPL_HAS_ATTRIBUTE_always_inline RBIMPL_COMPILER_SINCE(SunPro, 5, 10, 0) # define RBIMPL_HAS_ATTRIBUTE_const RBIMPL_COMPILER_SINCE(SunPro, 5, 9, 0) # define RBIMPL_HAS_ATTRIBUTE_constructor RBIMPL_COMPILER_SINCE(SunPro, 5, 9, 0) # define RBIMPL_HAS_ATTRIBUTE_destructor RBIMPL_COMPILER_SINCE(SunPro, 5, 9, 0) # define RBIMPL_HAS_ATTRIBUTE_malloc RBIMPL_COMPILER_SINCE(SunPro, 5, 9, 0) # define RBIMPL_HAS_ATTRIBUTE_noinline RBIMPL_COMPILER_SINCE(SunPro, 5, 9, 0) # define RBIMPL_HAS_ATTRIBUTE_noreturn RBIMPL_COMPILER_SINCE(SunPro, 5, 9, 0) # define RBIMPL_HAS_ATTRIBUTE_packed RBIMPL_COMPILER_SINCE(SunPro, 5, 9, 0) # define RBIMPL_HAS_ATTRIBUTE_pure RBIMPL_COMPILER_SINCE(SunPro, 5, 9, 0) # define RBIMPL_HAS_ATTRIBUTE_returns_twice RBIMPL_COMPILER_SINCE(SunPro, 5, 10, 0) # define RBIMPL_HAS_ATTRIBUTE_vector_size RBIMPL_COMPILER_SINCE(SunPro, 5, 10, 0) # define RBIMPL_HAS_ATTRIBUTE_visibility RBIMPL_COMPILER_SINCE(SunPro, 5, 9, 0) # define RBIMPL_HAS_ATTRIBUTE_weak RBIMPL_COMPILER_SINCE(SunPro, 5, 9, 0) #elif defined (_MSC_VER) # define RBIMPL_HAS_ATTRIBUTE(_) 0 # /* Fallback below doesn't work: see win32/Makefile.sub */ #else # /* Take config.h definition when available. */ # define RBIMPL_HAS_ATTRIBUTE(_) ((RBIMPL_HAS_ATTRIBUTE_ ## _)+0) # ifdef ALWAYS_INLINE # define RBIMPL_HAS_ATTRIBUTE_always_inline 1 # endif # ifdef FUNC_CDECL # define RBIMPL_HAS_ATTRIBUTE_cdecl 1 # endif # ifdef CONSTFUNC # define RBIMPL_HAS_ATTRIBUTE_const 1 # endif # ifdef DEPRECATED # define RBIMPL_HAS_ATTRIBUTE_deprecated 1 # endif # ifdef ERRORFUNC # define RBIMPL_HAS_ATTRIBUTE_error 1 # endif # ifdef FUNC_FASTCALL # define RBIMPL_HAS_ATTRIBUTE_fastcall 1 # endif # ifdef PUREFUNC # define RBIMPL_HAS_ATTRIBUTE_pure 1 # endif # ifdef NO_ADDRESS_SAFETY_ANALYSIS # define RBIMPL_HAS_ATTRIBUTE_no_address_safety_analysis 1 # endif # ifdef NO_SANITIZE # define RBIMPL_HAS_ATTRIBUTE_no_sanitize 1 # endif # ifdef NO_SANITIZE_ADDRESS # define RBIMPL_HAS_ATTRIBUTE_no_sanitize_address 1 # endif # ifdef NOINLINE # define RBIMPL_HAS_ATTRIBUTE_noinline 1 # endif # ifdef RBIMPL_FUNC_NONNULL # define RBIMPL_HAS_ATTRIBUTE_nonnull 1 # endif # ifdef NORETURN # define RBIMPL_HAS_ATTRIBUTE_noreturn 1 # endif # ifdef FUNC_OPTIMIZED # define RBIMPL_HAS_ATTRIBUTE_optimize 1 # endif # ifdef FUNC_STDCALL # define RBIMPL_HAS_ATTRIBUTE_stdcall 1 # endif # ifdef MAYBE_UNUSED # define RBIMPL_HAS_ATTRIBUTE_unused 1 # endif # ifdef WARN_UNUSED_RESULT # define RBIMPL_HAS_ATTRIBUTE_warn_unused_result 1 # endif # ifdef WARNINGFUNC # define RBIMPL_HAS_ATTRIBUTE_warning 1 # endif # ifdef WEAK # define RBIMPL_HAS_ATTRIBUTE_weak 1 # endif #endif #endif /* RBIMPL_HAS_ATTRIBUTE_H */ include/ruby/internal/has/warning.h 0000644 00000003026 15152150501 0013351 0 ustar 00 #ifndef RBIMPL_HAS_WARNING_H /*-*-C++-*-vi:se ft=cpp:*/ #define RBIMPL_HAS_WARNING_H /** * @file * @author Ruby developers <ruby-core@ruby-lang.org> * @copyright This file is a part of the programming language Ruby. * Permission is hereby granted, to either redistribute and/or * modify this file, provided that the conditions mentioned in the * file COPYING are met. Consult the file for details. * @warning Symbols prefixed with either `RBIMPL` or `rbimpl` are * implementation details. Don't take them as canon. They could * rapidly appear then vanish. The name (path) of this header file * is also an implementation detail. Do not expect it to persist * at the place it is now. Developers are free to move it anywhere * anytime at will. * @note To ruby-core: remember that this header can be possibly * recursively included from extension libraries written in C++. * Do not expect for instance `__VA_ARGS__` is always available. * We assume C99 for ruby itself but we don't assume languages of * extension libraries. They could be written in C++98. * @brief Defines #RBIMPL_HAS_WARNING. */ /** Wraps (or simulates) `__has_warning`. */ #if defined(__has_warning) # define RBIMPL_HAS_WARNING(_) __has_warning(_) #else # define RBIMPL_HAS_WARNING(_) 0 #endif #endif /* RBIMPL_HAS_WARNING_H */ include/ruby/internal/config.h 0000644 00000011431 15152150501 0012375 0 ustar 00 #ifndef RBIMPL_CONFIG_H /*-*-C++-*-vi:se ft=cpp:*/ #define RBIMPL_CONFIG_H /** * @author Ruby developers <ruby-core@ruby-lang.org> * @copyright This file is a part of the programming language Ruby. * Permission is hereby granted, to either redistribute and/or * modify this file, provided that the conditions mentioned in the * file COPYING are met. Consult the file for details. * @warning Symbols prefixed with either `RBIMPL` or `rbimpl` are * implementation details. Don't take them as canon. They could * rapidly appear then vanish. The name (path) of this header file * is also an implementation detail. Do not expect it to persist * at the place it is now. Developers are free to move it anywhere * anytime at will. * @note To ruby-core: remember that this header can be possibly * recursively included from extension libraries written in C++. * Do not expect for instance `__VA_ARGS__` is always available. * We assume C99 for ruby itself but we don't assume languages of * extension libraries. They could be written in C++98. * @brief Thin wrapper to ruby/config.h */ #include "ruby/config.h" #ifdef RUBY_EXTCONF_H # include RUBY_EXTCONF_H #endif #include "ruby/internal/compiler_since.h" #undef HAVE_PROTOTYPES #define HAVE_PROTOTYPES 1 #undef HAVE_STDARG_PROTOTYPES #define HAVE_STDARG_PROTOTYPES 1 #undef TOKEN_PASTE #define TOKEN_PASTE(x,y) x##y #if defined(__cplusplus) #/* __builtin_choose_expr and __builtin_types_compatible aren't available # * on C++. See https://gcc.gnu.org/onlinedocs/gcc/Other-Builtins.html */ # undef HAVE_BUILTIN___BUILTIN_CHOOSE_EXPR_CONSTANT_P # undef HAVE_BUILTIN___BUILTIN_TYPES_COMPATIBLE_P /* HAVE_VA_ARGS_MACRO is for C. C++ situations might be different. */ # undef HAVE_VA_ARGS_MACRO # if __cplusplus >= 201103L # define HAVE_VA_ARGS_MACRO # elif defined(__GXX_EXPERIMENTAL_CXX0X__) && __GXX_EXPERIMENTAL_CXX0X__ # define HAVE_VA_ARGS_MACRO # elif defined(__INTEL_CXX11_MODE__) # define HAVE_VA_ARGS_MACRO # elif RBIMPL_COMPILER_SINCE(MSVC, 16, 0, 0) # define HAVE_VA_ARGS_MACRO # else # /* NG, not known. */ # endif #endif #if RBIMPL_COMPILER_BEFORE(GCC, 4, 9, 0) # /* See https://bugs.ruby-lang.org/issues/14221 */ # undef HAVE_BUILTIN___BUILTIN_CHOOSE_EXPR_CONSTANT_P #endif #if RBIMPL_COMPILER_BEFORE(GCC, 5, 0, 0) # /* GCC 4.9.2 reportedly has this feature and is broken. The function is not # * officially documented below. Seems we should not use it. # * https://gcc.gnu.org/onlinedocs/gcc-4.9.4/gcc/Other-Builtins.html */ # undef HAVE_BUILTIN___BUILTIN_ALLOCA_WITH_ALIGN #endif #if defined(__SUNPRO_CC) # /* Oracle Developer Studio 12.5: GCC compatibility guide says it supports # * statement expressions. But to our knowledge they support the extension # * only for C and not for C++. Prove me wrong. Am happy to support them if # * there is a way. */ # undef HAVE_STMT_AND_DECL_IN_EXPR #endif #ifndef STRINGIZE0 # define STRINGIZE(expr) STRINGIZE0(expr) # define STRINGIZE0(expr) #expr #endif #ifdef AC_APPLE_UNIVERSAL_BUILD # undef WORDS_BIGENDIAN # ifdef __BIG_ENDIAN__ # define WORDS_BIGENDIAN # endif #endif #ifndef DLEXT_MAXLEN # define DLEXT_MAXLEN 4 #endif #ifndef RUBY_PLATFORM # define RUBY_PLATFORM "unknown-unknown" #endif #ifdef UNALIGNED_WORD_ACCESS # /* Take that. */ #elif defined(__i386) # define UNALIGNED_WORD_ACCESS 1 #elif defined(__i386__) # define UNALIGNED_WORD_ACCESS 1 #elif defined(_M_IX86) # define UNALIGNED_WORD_ACCESS 1 #elif defined(__x86_64) # define UNALIGNED_WORD_ACCESS 1 #elif defined(__x86_64__) # define UNALIGNED_WORD_ACCESS 1 #elif defined(_M_AMD64) # define UNALIGNED_WORD_ACCESS 1 #elif defined(__powerpc64__) # define UNALIGNED_WORD_ACCESS 1 #elif defined(__POWERPC__) // __POWERPC__ is defined for ppc and ppc64 on Darwin # define UNALIGNED_WORD_ACCESS 1 #elif defined(__aarch64__) # define UNALIGNED_WORD_ACCESS 1 #elif defined(__mc68020__) # define UNALIGNED_WORD_ACCESS 1 #else # define UNALIGNED_WORD_ACCESS 0 #endif /* Detection of __VA_OPT__ */ #if ! defined(HAVE_VA_ARGS_MACRO) # undef HAVE___VA_OPT__ #elif defined(__cplusplus) # if __cplusplus > 201703L # define HAVE___VA_OPT__ # else # undef HAVE___VA_OPT__ # endif #else # /* Idea taken from: https://stackoverflow.com/a/48045656 */ # define RBIMPL_TEST3(q, w, e, ...) e # define RBIMPL_TEST2(...) RBIMPL_TEST3(__VA_OPT__(,),1,0,0) # define RBIMPL_TEST1() RBIMPL_TEST2("ruby") # if RBIMPL_TEST1() # define HAVE___VA_OPT__ # else # undef HAVE___VA_OPT__ # endif # undef RBIMPL_TEST1 # undef RBIMPL_TEST2 # undef RBIMPL_TEST3 #endif /* HAVE_VA_ARGS_MACRO */ #endif /* RBIMPL_CONFIG_H */ include/ruby/internal/core/rdata.h 0000644 00000033571 15152150501 0013164 0 ustar 00 #ifndef RBIMPL_RDATA_H /*-*-C++-*-vi:se ft=cpp:*/ #define RBIMPL_RDATA_H /** * @file * @author Ruby developers <ruby-core@ruby-lang.org> * @copyright This file is a part of the programming language Ruby. * Permission is hereby granted, to either redistribute and/or * modify this file, provided that the conditions mentioned in the * file COPYING are met. Consult the file for details. * @warning Symbols prefixed with either `RBIMPL` or `rbimpl` are * implementation details. Don't take them as canon. They could * rapidly appear then vanish. The name (path) of this header file * is also an implementation detail. Do not expect it to persist * at the place it is now. Developers are free to move it anywhere * anytime at will. * @note To ruby-core: remember that this header can be possibly * recursively included from extension libraries written in C++. * Do not expect for instance `__VA_ARGS__` is always available. * We assume C99 for ruby itself but we don't assume languages of * extension libraries. They could be written in C++98. * @brief Defines struct ::RData. */ #include "ruby/internal/config.h" #ifdef STDC_HEADERS # include <stddef.h> #endif #include "ruby/internal/attr/deprecated.h" #include "ruby/internal/attr/warning.h" #include "ruby/internal/cast.h" #include "ruby/internal/core/rbasic.h" #include "ruby/internal/dllexport.h" #include "ruby/internal/fl_type.h" #include "ruby/internal/value.h" #include "ruby/internal/value_type.h" #include "ruby/defines.h" /** @cond INTERNAL_MACRO */ #ifdef RUBY_UNTYPED_DATA_WARNING # /* Take that. */ #elif defined(RUBY_EXPORT) # define RUBY_UNTYPED_DATA_WARNING 1 #else # define RUBY_UNTYPED_DATA_WARNING 0 #endif #define RBIMPL_DATA_FUNC(f) RBIMPL_CAST((void (*)(void *))(f)) #define RBIMPL_ATTRSET_UNTYPED_DATA_FUNC() \ RBIMPL_ATTR_WARNING(("untyped Data is unsafe; use TypedData instead")) \ RBIMPL_ATTR_DEPRECATED(("by TypedData")) #define RBIMPL_MACRO_SELECT(x, y) x ## y #define RUBY_MACRO_SELECT(x, y) RBIMPL_MACRO_SELECT(x, y) /** @endcond */ /** * Convenient casting macro. * * @param obj An object, which is in fact an ::RData. * @return The passed object casted to ::RData. */ #define RDATA(obj) RBIMPL_CAST((struct RData *)(obj)) /** * Convenient getter macro. * * @param obj An object, which is in fact an ::RData. * @return The passed object's ::RData::data field. */ #define DATA_PTR(obj) RDATA(obj)->data /** * This is a value you can set to ::RData::dfree. Setting this means the data * was allocated using ::ruby_xmalloc() (or variants), and shall be freed using * ::ruby_xfree(). * * @warning Do not use this if you want to use system malloc, because the * system and Ruby might or might not share the same malloc * implementation. */ #define RUBY_DEFAULT_FREE RBIMPL_DATA_FUNC(-1) /** * This is a value you can set to ::RData::dfree. Setting this means the data * is managed by someone else, like, statically allocated. Of course you are * on your own then. */ #define RUBY_NEVER_FREE RBIMPL_DATA_FUNC(0) /** * @private * * @deprecated This macro once was a thing in the old days, but makes no sense * any longer today. Exists here for backwards compatibility * only. You can safely forget about it. */ #define RUBY_UNTYPED_DATA_FUNC(f) f RBIMPL_ATTRSET_UNTYPED_DATA_FUNC() /* #define RUBY_DATA_FUNC(func) ((void (*)(void*))(func)) */ /** * This is the type of callbacks registered to ::RData. The argument is the * `data` field. */ typedef void (*RUBY_DATA_FUNC)(void*); /** * @deprecated * * Old "untyped" user data. It has roughly the same usage as struct * ::RTypedData, but lacked several features such as support for compaction GC. * Use of this struct is not recommended any longer. If it is dead necessary, * please inform the core devs about your usage. * * @internal * * @shyouhei tried to add RBIMPL_ATTR_DEPRECATED for this type but that yielded * too many warnings in the core. Maybe we want to retry later... Just add * deprecated document for now. */ struct RData { /** Basic part, including flags and class. */ struct RBasic basic; /** * This function is called when the object is experiencing GC marks. If it * contains references to other Ruby objects, you need to mark them also. * Otherwise GC will smash your data. * * @see rb_gc_mark() * @warning This is called during GC runs. Object allocations are * impossible at that moment (that is why GC runs). */ RUBY_DATA_FUNC dmark; /** * This function is called when the object is no longer used. You need to * do whatever necessary to avoid memory leaks. * * @warning This is called during GC runs. Object allocations are * impossible at that moment (that is why GC runs). */ RUBY_DATA_FUNC dfree; /** Pointer to the actual C level struct that you want to wrap. */ void *data; }; RBIMPL_SYMBOL_EXPORT_BEGIN() /** * This is the primitive way to wrap an existing C struct into ::RData. * * @param[in] klass Ruby level class of the returning object. * @param[in] datap Pointer to the target C struct. * @param[in] dmark Mark function. * @param[in] dfree Free function. * @exception rb_eTypeError `klass` is not a class. * @exception rb_eNoMemError Out of memory. * @return An allocated object that wraps `datap`. */ VALUE rb_data_object_wrap(VALUE klass, void *datap, RUBY_DATA_FUNC dmark, RUBY_DATA_FUNC dfree); /** * Identical to rb_data_object_wrap(), except it allocates a new data region * internally instead of taking an existing one. The allocation is done using * ruby_calloc(). Hence it makes no sense to pass anything other than * ::RUBY_DEFAULT_FREE to the last argument. * * @param[in] klass Ruby level class of the returning object. * @param[in] size Requested size of memory to allocate. * @param[in] dmark Mark function. * @param[in] dfree Free function. * @exception rb_eTypeError `klass` is not a class. * @exception rb_eNoMemError Out of memory. * @return An allocated object that wraps a new `size` byte region. */ VALUE rb_data_object_zalloc(VALUE klass, size_t size, RUBY_DATA_FUNC dmark, RUBY_DATA_FUNC dfree); /** * @private * Documented in include/ruby/internal/globals.h */ RUBY_EXTERN VALUE rb_cObject; RBIMPL_SYMBOL_EXPORT_END() /** * Converts sval, a pointer to your struct, into a Ruby object. * * @param klass A ruby level class. * @param mark Mark function. * @param free Free function. * @param sval A pointer to your struct. * @exception rb_eTypeError `klass` is not a class. * @exception rb_eNoMemError Out of memory. * @return A created Ruby object. */ #define Data_Wrap_Struct(klass, mark, free, sval) \ rb_data_object_wrap( \ (klass), \ (sval), \ RBIMPL_DATA_FUNC(mark), \ RBIMPL_DATA_FUNC(free)) /** * @private * * This is an implementation detail of #Data_Make_Struct. People don't use it * directly. * * @param result Variable name of created Ruby object. * @param klass Ruby level class of the object. * @param type Type name of the C struct. * @param size Size of the C struct. * @param mark Mark function. * @param free Free function. * @param sval Variable name of created C struct. */ #define Data_Make_Struct0(result, klass, type, size, mark, free, sval) \ VALUE result = rb_data_object_zalloc( \ (klass), \ (size), \ RBIMPL_DATA_FUNC(mark), \ RBIMPL_DATA_FUNC(free)); \ (sval) = RBIMPL_CAST((type *)DATA_PTR(result)); \ RBIMPL_CAST(/*suppress unused variable warnings*/(void)(sval)) /** * Identical to #Data_Wrap_Struct, except it allocates a new data region * internally instead of taking an existing one. The allocation is done using * ruby_calloc(). Hence it makes no sense to pass anything other than * ::RUBY_DEFAULT_FREE to the `free` argument. * * @param klass Ruby level class of the returning object. * @param type Type name of the C struct. * @param mark Mark function. * @param free Free function. * @param sval Variable name of created C struct. * @exception rb_eTypeError `klass` is not a class. * @exception rb_eNoMemError Out of memory. * @return A created Ruby object. */ #ifdef HAVE_STMT_AND_DECL_IN_EXPR #define Data_Make_Struct(klass, type, mark, free, sval) \ RB_GNUC_EXTENSION({ \ Data_Make_Struct0( \ data_struct_obj, \ klass, \ type, \ sizeof(type), \ mark, \ free, \ sval); \ data_struct_obj; \ }) #else #define Data_Make_Struct(klass, type, mark, free, sval) \ rb_data_object_make( \ (klass), \ RBIMPL_DATA_FUNC(mark), \ RBIMPL_DATA_FUNC(free), \ RBIMPL_CAST((void **)&(sval)), \ sizeof(type)) #endif /** * Obtains a C struct from inside of a wrapper Ruby object. * * @param obj An instance of ::RData. * @param type Type name of the C struct. * @param sval Variable name of obtained C struct. * @return Unwrapped C struct that `obj` holds. */ #define Data_Get_Struct(obj, type, sval) \ ((sval) = RBIMPL_CAST((type*)rb_data_object_get(obj))) RBIMPL_ATTRSET_UNTYPED_DATA_FUNC() /** * @private * * This is an implementation detail of rb_data_object_wrap(). People don't use * it directly. * * @param[in] klass Ruby level class of the returning object. * @param[in] ptr Pointer to the target C struct. * @param[in] mark Mark function. * @param[in] free Free function. * @exception rb_eTypeError `klass` is not a class. * @exception rb_eNoMemError Out of memory. * @return An allocated object that wraps `datap`. */ static inline VALUE rb_data_object_wrap_warning(VALUE klass, void *ptr, RUBY_DATA_FUNC mark, RUBY_DATA_FUNC free) { return rb_data_object_wrap(klass, ptr, mark, free); } /** * @private * * This is an implementation detail of #Data_Get_Struct. People don't use it * directly. * * @param[in] obj An instance of ::RData. * @return Unwrapped C struct that `obj` holds. */ static inline void * rb_data_object_get(VALUE obj) { Check_Type(obj, RUBY_T_DATA); return DATA_PTR(obj); } RBIMPL_ATTRSET_UNTYPED_DATA_FUNC() /** * @private * * This is an implementation detail of #Data_Get_Struct. People don't use it * directly. * * @param[in] obj An instance of ::RData. * @return Unwrapped C struct that `obj` holds. */ static inline void * rb_data_object_get_warning(VALUE obj) { return rb_data_object_get(obj); } #if defined(HAVE_BUILTIN___BUILTIN_CHOOSE_EXPR_CONSTANT_P) # define rb_data_object_wrap_warning(klass, ptr, mark, free) \ RB_GNUC_EXTENSION( \ __builtin_choose_expr( \ __builtin_constant_p(klass) && !(klass), \ rb_data_object_wrap(klass, ptr, mark, free), \ (rb_data_object_wrap_warning)(klass, ptr, mark, free))) #endif /** * This is an implementation detail of #Data_Make_Struct. People don't use it * directly. * * @param[in] klass Ruby level class of the returning object. * @param[in] mark_func Mark function. * @param[in] free_func Free function. * @param[in] datap Variable of created C struct. * @param[in] size Requested size of allocation. * @exception rb_eTypeError `klass` is not a class. * @exception rb_eNoMemError Out of memory. * @return A created Ruby object. * @post `*datap` holds the created C struct. */ static inline VALUE rb_data_object_make(VALUE klass, RUBY_DATA_FUNC mark_func, RUBY_DATA_FUNC free_func, void **datap, size_t size) { Data_Make_Struct0(result, klass, void, size, mark_func, free_func, *datap); return result; } RBIMPL_ATTR_DEPRECATED(("by: rb_data_object_wrap")) /** @deprecated This function was renamed to rb_data_object_wrap(). */ static inline VALUE rb_data_object_alloc(VALUE klass, void *data, RUBY_DATA_FUNC dmark, RUBY_DATA_FUNC dfree) { return rb_data_object_wrap(klass, data, dmark, dfree); } /** @cond INTERNAL_MACRO */ #define rb_data_object_wrap_0 rb_data_object_wrap #define rb_data_object_wrap_1 rb_data_object_wrap_warning #define rb_data_object_wrap_2 rb_data_object_wrap_ /* Used here vvvv */ #define rb_data_object_wrap RUBY_MACRO_SELECT(rb_data_object_wrap_2, RUBY_UNTYPED_DATA_WARNING) #define rb_data_object_get_0 rb_data_object_get #define rb_data_object_get_1 rb_data_object_get_warning #define rb_data_object_get_2 rb_data_object_get_ /* Used here vvvv */ #define rb_data_object_get RUBY_MACRO_SELECT(rb_data_object_get_2, RUBY_UNTYPED_DATA_WARNING) #define rb_data_object_make_0 rb_data_object_make #define rb_data_object_make_1 rb_data_object_make_warning #define rb_data_object_make_2 rb_data_object_make_ /* Used here vvvv */ #define rb_data_object_make RUBY_MACRO_SELECT(rb_data_object_make_2, RUBY_UNTYPED_DATA_WARNING) /** @endcond */ #endif /* RBIMPL_RDATA_H */ include/ruby/internal/core/robject.h 0000644 00000012044 15152150501 0013511 0 ustar 00 #ifndef RBIMPL_ROBJECT_H /*-*-C++-*-vi:se ft=cpp:*/ #define RBIMPL_ROBJECT_H /** * @file * @author Ruby developers <ruby-core@ruby-lang.org> * @copyright This file is a part of the programming language Ruby. * Permission is hereby granted, to either redistribute and/or * modify this file, provided that the conditions mentioned in the * file COPYING are met. Consult the file for details. * @warning Symbols prefixed with either `RBIMPL` or `rbimpl` are * implementation details. Don't take them as canon. They could * rapidly appear then vanish. The name (path) of this header file * is also an implementation detail. Do not expect it to persist * at the place it is now. Developers are free to move it anywhere * anytime at will. * @note To ruby-core: remember that this header can be possibly * recursively included from extension libraries written in C++. * Do not expect for instance `__VA_ARGS__` is always available. * We assume C99 for ruby itself but we don't assume languages of * extension libraries. They could be written in C++98. * @brief Defines struct ::RObject. */ #include "ruby/internal/config.h" #ifdef HAVE_STDINT_H # include <stdint.h> #endif #include "ruby/internal/attr/artificial.h" #include "ruby/internal/attr/deprecated.h" #include "ruby/internal/attr/pure.h" #include "ruby/internal/cast.h" #include "ruby/internal/fl_type.h" #include "ruby/internal/value.h" #include "ruby/internal/value_type.h" /** * Convenient casting macro. * * @param obj An object, which is in fact an ::RObject. * @return The passed object casted to ::RObject. */ #define ROBJECT(obj) RBIMPL_CAST((struct RObject *)(obj)) /** @cond INTERNAL_MACRO */ #define ROBJECT_EMBED_LEN_MAX ROBJECT_EMBED_LEN_MAX #define ROBJECT_EMBED ROBJECT_EMBED #define ROBJECT_IV_CAPACITY ROBJECT_IV_CAPACITY #define ROBJECT_IVPTR ROBJECT_IVPTR /** @endcond */ /** * @private * * Bits that you can set to ::RBasic::flags. */ enum ruby_robject_flags { /** * This flag has something to do with memory footprint. If the object is * "small" enough, ruby tries to be creative to abuse padding bits of * struct ::RObject for storing instance variables. This flag denotes that * situation. * * @warning This bit has to be considered read-only. Setting/clearing * this bit without corresponding fix up must cause immediate * SEGV. Also, internal structures of an object change * dynamically and transparently throughout of its lifetime. * Don't assume it being persistent. * * @internal * * 3rd parties must not be aware that there even is more than one way to * store instance variables. Might better be hidden. */ ROBJECT_EMBED = RUBY_FL_USER1 }; struct st_table; /** * Ruby's ordinal objects. Unless otherwise special cased, all predefined and * user-defined classes share this struct to hold their instances. */ struct RObject { /** Basic part, including flags and class. */ struct RBasic basic; /** Object's specific fields. */ union { /** * Object that use separated memory region for instance variables use * this pattern. */ struct { /** Pointer to a C array that holds instance variables. */ VALUE *ivptr; /** * This is a table that holds instance variable name to index * mapping. Used when accessing instance variables using names. * * @internal * * This is a shortcut for `RCLASS_IV_INDEX_TBL(rb_obj_class(obj))`. */ struct rb_id_table *iv_index_tbl; } heap; /* Embedded instance variables. When an object is small enough, it * uses this area to store the instance variables. * * This is a length 1 array because: * 1. GCC has a bug that does not optimize C flexible array members * (https://gcc.gnu.org/bugzilla/show_bug.cgi?id=102452) * 2. Zero length arrays are not supported by all compilers */ VALUE ary[1]; } as; }; RBIMPL_ATTR_PURE_UNLESS_DEBUG() RBIMPL_ATTR_ARTIFICIAL() /** * Queries the instance variables. * * @param[in] obj Object in question. * @return Its instance variables, in C array. * @pre `obj` must be an instance of ::RObject. * * @internal * * @shyouhei finds no reason for this to be visible from extension libraries. */ static inline VALUE * ROBJECT_IVPTR(VALUE obj) { RBIMPL_ASSERT_TYPE(obj, RUBY_T_OBJECT); struct RObject *const ptr = ROBJECT(obj); if (RB_FL_ANY_RAW(obj, ROBJECT_EMBED)) { return ptr->as.ary; } else { return ptr->as.heap.ivptr; } } #endif /* RBIMPL_ROBJECT_H */ include/ruby/internal/core/rbasic.h 0000644 00000012467 15152150501 0013335 0 ustar 00 #ifndef RBIMPL_RBASIC_H /*-*-C++-*-vi:se ft=cpp:*/ #define RBIMPL_RBASIC_H /** * @file * @author Ruby developers <ruby-core@ruby-lang.org> * @copyright This file is a part of the programming language Ruby. * Permission is hereby granted, to either redistribute and/or * modify this file, provided that the conditions mentioned in the * file COPYING are met. Consult the file for details. * @warning Symbols prefixed with either `RBIMPL` or `rbimpl` are * implementation details. Don't take them as canon. They could * rapidly appear then vanish. The name (path) of this header file * is also an implementation detail. Do not expect it to persist * at the place it is now. Developers are free to move it anywhere * anytime at will. * @note To ruby-core: remember that this header can be possibly * recursively included from extension libraries written in C++. * Do not expect for instance `__VA_ARGS__` is always available. * We assume C99 for ruby itself but we don't assume languages of * extension libraries. They could be written in C++98. * @brief Defines struct ::RBasic. */ #include "ruby/internal/attr/artificial.h" #include "ruby/internal/attr/constexpr.h" #include "ruby/internal/attr/forceinline.h" #include "ruby/internal/attr/noalias.h" #include "ruby/internal/attr/pure.h" #include "ruby/internal/cast.h" #include "ruby/internal/dllexport.h" #include "ruby/internal/special_consts.h" #include "ruby/internal/value.h" #include "ruby/assert.h" /** * Convenient casting macro. * * @param obj Arbitrary Ruby object. * @return The passed object casted to ::RBasic. */ #define RBASIC(obj) RBIMPL_CAST((struct RBasic *)(obj)) /** @cond INTERNAL_MACRO */ #define RBASIC_CLASS RBASIC_CLASS #define RBIMPL_RVALUE_EMBED_LEN_MAX 3 #define RVALUE_EMBED_LEN_MAX RVALUE_EMBED_LEN_MAX #define RBIMPL_EMBED_LEN_MAX_OF(T) \ RBIMPL_CAST((int)(sizeof(VALUE[RBIMPL_RVALUE_EMBED_LEN_MAX]) / (sizeof(T)))) /** @endcond */ /** * This is an enum because GDB wants it (rather than a macro). People need not * bother. */ enum ruby_rvalue_flags { /** Max possible number of objects that can be embedded. */ RVALUE_EMBED_LEN_MAX = RBIMPL_RVALUE_EMBED_LEN_MAX }; /** * Ruby's object's, base components. Every single ruby objects have them in * common. */ struct RUBY_ALIGNAS(SIZEOF_VALUE) RBasic { /** * Per-object flags. Each ruby objects have their own characteristics * apart from their classes. For instance whether an object is frozen or * not is not controlled by its class. This is where such properties are * stored. * * @see enum ::ruby_fl_type * * @note This is ::VALUE rather than an enum for alignment purpose. Back * in the 1990s there were no such thing like `_Alignas` in C. */ VALUE flags; /** * Class of an object. Every object has its class. Also, everything is an * object in Ruby. This means classes are also objects. Classes have * their own classes, classes of classes have their classes, too ... and * it recursively continues forever. * * Also note the `const` qualifier. In ruby an object cannot "change" its * class. */ const VALUE klass; #ifdef __cplusplus public: RBIMPL_ATTR_CONSTEXPR(CXX11) RBIMPL_ATTR_ARTIFICIAL() RBIMPL_ATTR_FORCEINLINE() RBIMPL_ATTR_NOALIAS() /** * We need to define this explicit constructor because the field `klass` is * const-qualified above, which effectively defines the implicit default * constructor as "deleted" (as of C++11) -- No way but to define one by * ourselves. */ RBasic() : flags(RBIMPL_VALUE_NULL), klass(RBIMPL_VALUE_NULL) { } #endif }; RBIMPL_SYMBOL_EXPORT_BEGIN() /** * Make the object invisible from Ruby code. * * It is useful to let Ruby's GC manage your internal data structure -- The * object keeps being managed by GC, but `ObjectSpace.each_object` never yields * the object. * * Note that the object also lose a way to call a method on it. * * @param[out] obj A Ruby object. * @return The passed object. * @post The object is destructively modified to be invisible. * @see rb_obj_reveal */ VALUE rb_obj_hide(VALUE obj); /** * Make a hidden object visible again. * * It is the caller's responsibility to pass the right `klass` which `obj` * originally used to belong to. * * @param[out] obj A Ruby object. * @param[in] klass Class of `obj`. * @return Passed `obj`. * @pre `obj` was previously hidden. * @post `obj`'s class is `klass`. * @see rb_obj_hide */ VALUE rb_obj_reveal(VALUE obj, VALUE klass); /* do not use this API to change klass information */ RBIMPL_SYMBOL_EXPORT_END() RBIMPL_ATTR_PURE_UNLESS_DEBUG() RBIMPL_ATTR_ARTIFICIAL() /** * Queries the class of an object. * * @param[in] obj An object. * @return Its class. */ static inline VALUE RBASIC_CLASS(VALUE obj) { RBIMPL_ASSERT_OR_ASSUME(! RB_SPECIAL_CONST_P(obj)); return RBASIC(obj)->klass; } #endif /* RBIMPL_RBASIC_H */ include/ruby/internal/core/rclass.h 0000644 00000006716 15152150501 0013361 0 ustar 00 #ifndef RBIMPL_RCLASS_H /*-*-C++-*-vi:se ft=cpp:*/ #define RBIMPL_RCLASS_H /** * @file * @author Ruby developers <ruby-core@ruby-lang.org> * @copyright This file is a part of the programming language Ruby. * Permission is hereby granted, to either redistribute and/or * modify this file, provided that the conditions mentioned in the * file COPYING are met. Consult the file for details. * @warning Symbols prefixed with either `RBIMPL` or `rbimpl` are * implementation details. Don't take them as canon. They could * rapidly appear then vanish. The name (path) of this header file * is also an implementation detail. Do not expect it to persist * at the place it is now. Developers are free to move it anywhere * anytime at will. * @note To ruby-core: remember that this header can be possibly * recursively included from extension libraries written in C++. * Do not expect for instance `__VA_ARGS__` is always available. * We assume C99 for ruby itself but we don't assume languages of * extension libraries. They could be written in C++98. * @brief Routines to manipulate struct RClass. * @note The struct RClass itself is opaque. */ #include "ruby/internal/dllexport.h" #include "ruby/internal/value.h" #include "ruby/internal/cast.h" /** @cond INTERNAL_MACRO */ #define RMODULE_IS_REFINEMENT RMODULE_IS_REFINEMENT /** @endcond */ /** * Convenient casting macro. * * @param obj An object, which is in fact an RClass. * @return The passed object casted to RClass. */ #define RCLASS(obj) RBIMPL_CAST((struct RClass *)(obj)) /** @alias{RCLASS} */ #define RMODULE RCLASS /** @alias{rb_class_get_superclass} */ #define RCLASS_SUPER rb_class_get_superclass /** * @private * * Bits that you can set to ::RBasic::flags. * * @internal * * Why is it here, given RClass itself is not? */ enum ruby_rmodule_flags { /** * This flag has something to do with refinements. A module created using * rb_mod_refine() has this flag set. This is the bit which controls * difference between normal inclusion versus refinements. */ RMODULE_IS_REFINEMENT = RUBY_FL_USER3 }; struct RClass; /* Opaque, declared here for RCLASS() macro. */ RBIMPL_SYMBOL_EXPORT_BEGIN() /** * Returns the superclass of a class. * @param[in] klass An object of RClass. * @retval RUBY_Qfalse `klass` has no super class. * @retval otherwise Raw superclass of `klass` * @see rb_class_superclass * * ### Q&A ### * * - Q: How can a class have no super class? * * - A: `klass` could be a module. Or it could be ::rb_cBasicObject. * * - Q: What do you mean by "raw" superclass? * * - A: This is a really good question. The answer is that this function * returns something different from what you would normally expect. On * occasions ruby inserts hidden classes in a hierarchy of class * inheritance behind-the-scene. Such classes are called "iclass"es and * distinguished using ::RUBY_T_ICLASS in C level. They are truly * transparent from Ruby level but can be accessed from C, by using this * API. */ VALUE rb_class_get_superclass(VALUE klass); RBIMPL_SYMBOL_EXPORT_END() #endif /* RBIMPL_RCLASS_H */ include/ruby/internal/core/rmatch.h 0000644 00000012502 15152150501 0013336 0 ustar 00 #ifndef RBIMPL_RMATCH_H /*-*-C++-*-vi:se ft=cpp:*/ #define RBIMPL_RMATCH_H /** * @file * @author Ruby developers <ruby-core@ruby-lang.org> * @copyright This file is a part of the programming language Ruby. * Permission is hereby granted, to either redistribute and/or * modify this file, provided that the conditions mentioned in the * file COPYING are met. Consult the file for details. * @warning Symbols prefixed with either `RBIMPL` or `rbimpl` are * implementation details. Don't take them as canon. They could * rapidly appear then vanish. The name (path) of this header file * is also an implementation detail. Do not expect it to persist * at the place it is now. Developers are free to move it anywhere * anytime at will. * @note To ruby-core: remember that this header can be possibly * recursively included from extension libraries written in C++. * Do not expect for instance `__VA_ARGS__` is always available. * We assume C99 for ruby itself but we don't assume languages of * extension libraries. They could be written in C++98. * @brief Defines struct ::RMatch. */ #include "ruby/internal/attr/artificial.h" #include "ruby/internal/attr/pure.h" #include "ruby/internal/cast.h" #include "ruby/internal/core/rbasic.h" #include "ruby/internal/value.h" #include "ruby/internal/value_type.h" #include "ruby/assert.h" /** * Convenient casting macro. * * @param obj An object, which is in fact an ::RMatch. * @return The passed object casted to ::RMatch. */ #define RMATCH(obj) RBIMPL_CAST((struct RMatch *)(obj)) /** @cond INTERNAL_MACRO */ #define RMATCH_REGS RMATCH_REGS /** @endcond */ struct re_patter_buffer; /* a.k.a. OnigRegexType, defined in onigmo.h */ struct re_registers; /* Also in onigmo.h */ /** * @old{re_pattern_buffer} * * @internal * * @shyouhei wonders: is anyone actively using this typedef ...? */ typedef struct re_pattern_buffer Regexp; /** * Represents the region of a capture group. This is basically for caching * purpose. re_registers have similar concepts (`beg` and `end`) but they are * in `ptrdiff_t*`. In order for us to implement `MatchData#offset` that info * has to be converted to offset integers. This is the struct to hold such * things. * * @internal * * But why on earth it has to be visible from extension libraries? */ struct rmatch_offset { long beg; /**< Beginning of a group. */ long end; /**< End of a group. */ }; /** Represents a match. */ struct rb_matchext_struct { /** * "Registers" of a match. This is a quasi-opaque struct that holds * execution result of a match. Roughly resembles `&~`. */ struct re_registers regs; /** Capture group offsets, in C array. */ struct rmatch_offset *char_offset; /** Number of ::rmatch_offset that ::rmatch::char_offset holds. */ int char_offset_num_allocated; }; typedef struct rb_matchext_struct rb_matchext_t; /** * Regular expression execution context. When a regular expression "matches" * to a string, it generates capture groups etc. This struct holds that info. * Visible from Ruby as an instance of `MatchData`. * * @note There is no way for extension libraries to manually generate this * struct except by actually exercising the match operation of a regular * expression. */ struct RMatch { /** Basic part, including flags and class. */ struct RBasic basic; /** * The target string that the match was made against. */ VALUE str; /** * The expression of this match. */ VALUE regexp; /* RRegexp */ }; #define RMATCH_EXT(m) ((rb_matchext_t *)((char *)(m) + sizeof(struct RMatch))) RBIMPL_ATTR_PURE_UNLESS_DEBUG() RBIMPL_ATTR_ARTIFICIAL() /** * Queries the raw ::re_registers. * * @param[in] match A match object * @pre `match` must be of ::RMatch. * @return Its execution result. * @note Good. So you are aware of the fact that it could return NULL. * Yes. It actually does. This is a really bizarre thing. The * situation is about `String#gsub` and its family. They take * strings as arguments, like `"foo".sub("bar", "baz")`. On such * situations, in order to optimise memory allocations, these * methods do not involve regular expressions at all. They just * sequentially scan the receiver. Okay. The story begins here. * Even when they do not kick our regexp engine, there must be * backref objects e.g. `$&`. But how? You know what? Ruby fakes * them. It allocates an empty ::RMatch and behaves as if there * were execution contexts. In reality there weren't. No * ::re_registers are allocated then. There is no way for this * function but to return NULL for those fake ::RMatch. This is * the reason for the nullability of this function. */ static inline struct re_registers * RMATCH_REGS(VALUE match) { RBIMPL_ASSERT_TYPE(match, RUBY_T_MATCH); return &RMATCH_EXT(match)->regs; } #endif /* RBIMPL_RMATCH_H */ include/ruby/internal/core/rstring.h 0000644 00000041177 15152150501 0013562 0 ustar 00 #ifndef RBIMPL_RSTRING_H /*-*-C++-*-vi:se ft=cpp:*/ #define RBIMPL_RSTRING_H /** * @file * @author Ruby developers <ruby-core@ruby-lang.org> * @copyright This file is a part of the programming language Ruby. * Permission is hereby granted, to either redistribute and/or * modify this file, provided that the conditions mentioned in the * file COPYING are met. Consult the file for details. * @warning Symbols prefixed with either `RBIMPL` or `rbimpl` are * implementation details. Don't take them as canon. They could * rapidly appear then vanish. The name (path) of this header file * is also an implementation detail. Do not expect it to persist * at the place it is now. Developers are free to move it anywhere * anytime at will. * @note To ruby-core: remember that this header can be possibly * recursively included from extension libraries written in C++. * Do not expect for instance `__VA_ARGS__` is always available. * We assume C99 for ruby itself but we don't assume languages of * extension libraries. They could be written in C++98. * @brief Defines struct ::RString. */ #include "ruby/internal/config.h" #include "ruby/internal/arithmetic/long.h" #include "ruby/internal/attr/artificial.h" #include "ruby/internal/attr/pure.h" #include "ruby/internal/cast.h" #include "ruby/internal/core/rbasic.h" #include "ruby/internal/dllexport.h" #include "ruby/internal/fl_type.h" #include "ruby/internal/value_type.h" #include "ruby/internal/warning_push.h" #include "ruby/assert.h" /** * Convenient casting macro. * * @param obj An object, which is in fact an ::RString. * @return The passed object casted to ::RString. */ #define RSTRING(obj) RBIMPL_CAST((struct RString *)(obj)) /** @cond INTERNAL_MACRO */ #define RSTRING_NOEMBED RSTRING_NOEMBED #define RSTRING_FSTR RSTRING_FSTR #define RSTRING_LEN RSTRING_LEN #define RSTRING_LENINT RSTRING_LENINT #define RSTRING_PTR RSTRING_PTR #define RSTRING_END RSTRING_END /** @endcond */ /** * @name Conversion of Ruby strings into C's * * @{ */ /** * Ensures that the parameter object is a String. This is done by calling its * `to_str` method. * * @param[in,out] v Arbitrary Ruby object. * @exception rb_eTypeError No implicit conversion defined. * @post `v` is a String. */ #define StringValue(v) rb_string_value(&(v)) /** * Identical to #StringValue, except it returns a `char*`. * * @param[in,out] v Arbitrary Ruby object. * @exception rb_eTypeError No implicit conversion defined. * @return Converted Ruby string's backend C string. * @post `v` is a String. */ #define StringValuePtr(v) rb_string_value_ptr(&(v)) /** * Identical to #StringValuePtr, except it additionally checks for the contents * for viability as a C string. Ruby can accept wider range of contents as * strings, compared to C. This function is to check that. * * @param[in,out] v Arbitrary Ruby object. * @exception rb_eTypeError No implicit conversion defined. * @exception rb_eArgError String is not C-compatible. * @return Converted Ruby string's backend C string. * @post `v` is a String. */ #define StringValueCStr(v) rb_string_value_cstr(&(v)) /** * @private * * @deprecated This macro once was a thing in the old days, but makes no sense * any longer today. Exists here for backwards compatibility * only. You can safely forget about it. */ #define SafeStringValue(v) StringValue(v) /** * Identical to #StringValue, except it additionally converts the string's * encoding to default external encoding. Ruby has a concept called encodings. * A string can have different encoding than the environment expects. Someone * has to make sure its contents be converted to something suitable. This is * that routine. Call it when necessary. * * @param[in,out] v Arbitrary Ruby object. * @exception rb_eTypeError No implicit conversion defined. * @return Converted Ruby string's backend C string. * @post `v` is a String. * * @internal * * Not sure but it seems this macro does not raise on encoding * incompatibilities? Doesn't sound right to @shyouhei. */ #define ExportStringValue(v) do { \ StringValue(v); \ (v) = rb_str_export(v); \ } while (0) /** @} */ /** * @private * * Bits that you can set to ::RBasic::flags. * * @warning These enums are not the only bits we use for strings. * * @internal * * Actually all bits through FL_USER1 to FL_USER19 are used for strings. Why * only this tiny part of them are made public here? @shyouhei can find no * reason. */ enum ruby_rstring_flags { /** * This flag has something to do with memory footprint. If the string is * short enough, ruby tries to be creative to abuse padding bits of struct * ::RString for storing contents. If this flag is set that string does * _not_ do that, to resort to good old fashioned external allocation * strategy instead. * * @warning This bit has to be considered read-only. Setting/clearing * this bit without corresponding fix up must cause immediate * SEGV. Also, internal structures of a string change * dynamically and transparently throughout of its lifetime. * Don't assume it being persistent. * * @internal * * 3rd parties must not be aware that there even is more than one way to * store a string. Might better be hidden. */ RSTRING_NOEMBED = RUBY_FL_USER1, /* Actually, string encodings are also encoded into the flags, using * remaining bits.*/ /** * This flag has something to do with infamous "f"string. What is a * fstring? Well it is a special subkind of strings that is immutable, * deduped globally, and managed by our GC. It is much like a Symbol (in * fact Symbols are dynamic these days and are backended using fstrings). * This concept has been silently introduced at some point in 2.x era. * Since then it gained wider acceptance in the core. But extension * libraries could not know that until very recently. Strings of this flag * live in a special Limbo deep inside of the interpreter. Never try to * manipulate it by hand. * * @internal * * Fstrings are not the only variant strings that we implement today. * Other things are behind-the-scene. This is the only one that is visible * from extension library. There is no clear reason why it has to be. * Given there are more "polite" ways to create fstrings, it seems this bit * need not be exposed to extension libraries. Might better be hidden. */ RSTRING_FSTR = RUBY_FL_USER17 }; /** * Ruby's String. A string in ruby conceptually has these information: * * - Encoding of the string. * - Length of the string. * - Contents of the string. * * It is worth noting that a string is _not_ an array of characters in ruby. * It has never been. In 1.x a string was an array of integers. Since 2.x a * string is no longer an array of anything. A string is a string -- just like * a Time is not an integer. */ struct RString { /** Basic part, including flags and class. */ struct RBasic basic; /** * Length of the string, not including terminating NUL character. * * @note This is in bytes. */ long len; /** String's specific fields. */ union { /** * Strings that use separated memory region for contents use this * pattern. */ struct { /** * Pointer to the contents of the string. In the old days each * string had dedicated memory regions. That is no longer true * today, but there still are strings of such properties. This * field could be used to point such things. */ char *ptr; /** Auxiliary info. */ union { /** * Capacity of `*ptr`. A continuous memory region of at least * `capa` bytes is expected to exist at `*ptr`. This can be * bigger than `len`. */ long capa; /** * Parent of the string. Nowadays strings can share their * contents each other, constructing gigantic nest of objects. * This situation is called "shared", and this is the field to * control such properties. */ VALUE shared; } aux; } heap; /** Embedded contents. */ struct { /* This is a length 1 array because: * 1. GCC has a bug that does not optimize C flexible array members * (https://gcc.gnu.org/bugzilla/show_bug.cgi?id=102452) * 2. Zero length arrays are not supported by all compilers */ char ary[1]; } embed; } as; }; RBIMPL_SYMBOL_EXPORT_BEGIN() /** * Identical to rb_check_string_type(), except it raises exceptions in case of * conversion failures. * * @param[in] obj Target object. * @exception rb_eTypeError No implicit conversion to String. * @return Return value of `obj.to_str`. * @see rb_io_get_io * @see rb_ary_to_ary */ VALUE rb_str_to_str(VALUE obj); /** * Identical to rb_str_to_str(), except it fills the passed pointer with the * converted object. * * @param[in,out] ptr Pointer to a variable of target object. * @exception rb_eTypeError No implicit conversion to String. * @return Return value of `obj.to_str`. * @post `*ptr` is the return value. */ VALUE rb_string_value(volatile VALUE *ptr); /** * Identical to rb_str_to_str(), except it returns the converted string's * backend memory region. * * @param[in,out] ptr Pointer to a variable of target object. * @exception rb_eTypeError No implicit conversion to String. * @post `*ptr` is the return value of `obj.to_str`. * @return Pointer to the contents of the return value. */ char *rb_string_value_ptr(volatile VALUE *ptr); /** * Identical to rb_string_value_ptr(), except it additionally checks for the * contents for viability as a C string. Ruby can accept wider range of * contents as strings, compared to C. This function is to check that. * * @param[in,out] ptr Pointer to a variable of target object. * @exception rb_eTypeError No implicit conversion to String. * @exception rb_eArgError String is not C-compatible. * @post `*ptr` is the return value of `obj.to_str`. * @return Pointer to the contents of the return value. */ char *rb_string_value_cstr(volatile VALUE *ptr); /** * Identical to rb_str_to_str(), except it additionally converts the string * into default external encoding. Ruby has a concept called encodings. A * string can have different encoding than the environment expects. Someone * has to make sure its contents be converted to something suitable. This is * that routine. Call it when necessary. * * @param[in] obj Target object. * @exception rb_eTypeError No implicit conversion to String. * @return Converted ruby string of default external encoding. */ VALUE rb_str_export(VALUE obj); /** * Identical to rb_str_export(), except it converts into the locale encoding * instead. * * @param[in] obj Target object. * @exception rb_eTypeError No implicit conversion to String. * @return Converted ruby string of locale encoding. */ VALUE rb_str_export_locale(VALUE obj); RBIMPL_ATTR_ERROR(("rb_check_safe_str() and Check_SafeStr() are obsolete; use StringValue() instead")) /** * @private * * @deprecated This function once was a thing in the old days, but makes no * sense any longer today. Exists here for backwards * compatibility only. You can safely forget about it. */ void rb_check_safe_str(VALUE); /** * @private * * @deprecated This macro once was a thing in the old days, but makes no sense * any longer today. Exists here for backwards compatibility * only. You can safely forget about it. */ #define Check_SafeStr(v) rb_check_safe_str(RBIMPL_CAST((VALUE)(v))) /** * @private * * Prints diagnostic message to stderr when RSTRING_PTR or RSTRING_END * is NULL. * * @param[in] func The function name where encountered NULL pointer. */ void rb_debug_rstring_null_ptr(const char *func); RBIMPL_SYMBOL_EXPORT_END() RBIMPL_ATTR_PURE_UNLESS_DEBUG() RBIMPL_ATTR_ARTIFICIAL() /** * Queries the length of the string. * * @param[in] str String in question. * @return Its length, in bytes. * @pre `str` must be an instance of ::RString. */ static inline long RSTRING_LEN(VALUE str) { return RSTRING(str)->len; } RBIMPL_WARNING_PUSH() #if RBIMPL_COMPILER_IS(Intel) RBIMPL_WARNING_IGNORED(413) #endif RBIMPL_ATTR_PURE_UNLESS_DEBUG() RBIMPL_ATTR_ARTIFICIAL() /** * @private * * "Expands" an embedded string into an ordinal one. This is a function that * returns aggregated type. The returned struct always has its `as.heap.len` * an `as.heap.ptr` fields set appropriately. * * This is an implementation detail that 3rd parties should never bother. */ static inline struct RString rbimpl_rstring_getmem(VALUE str) { RBIMPL_ASSERT_TYPE(str, RUBY_T_STRING); if (RB_FL_ANY_RAW(str, RSTRING_NOEMBED)) { return *RSTRING(str); } else { /* Expecting compilers to optimize this on-stack struct away. */ struct RString retval; retval.len = RSTRING_LEN(str); retval.as.heap.ptr = RSTRING(str)->as.embed.ary; return retval; } } RBIMPL_WARNING_POP() RBIMPL_ATTR_ARTIFICIAL() /** * Queries the contents pointer of the string. * * @param[in] str String in question. * @return Pointer to its contents. * @pre `str` must be an instance of ::RString. */ static inline char * RSTRING_PTR(VALUE str) { char *ptr = rbimpl_rstring_getmem(str).as.heap.ptr; if (RUBY_DEBUG && RB_UNLIKELY(! ptr)) { /* :BEWARE: @shyouhei thinks that currently, there are rooms for this * function to return NULL. Better check here for maximum safety. * * Also, this is not rb_warn() because RSTRING_PTR() can be called * during GC (see what obj_info() does). rb_warn() needs to allocate * Ruby objects. That is not possible at this moment. */ rb_debug_rstring_null_ptr("RSTRING_PTR"); } return ptr; } RBIMPL_ATTR_ARTIFICIAL() /** * Queries the end of the contents pointer of the string. * * @param[in] str String in question. * @return Pointer to its end of contents. * @pre `str` must be an instance of ::RString. */ static inline char * RSTRING_END(VALUE str) { struct RString buf = rbimpl_rstring_getmem(str); if (RUBY_DEBUG && RB_UNLIKELY(! buf.as.heap.ptr)) { /* Ditto. */ rb_debug_rstring_null_ptr("RSTRING_END"); } return &buf.as.heap.ptr[buf.len]; } RBIMPL_ATTR_ARTIFICIAL() /** * Identical to RSTRING_LEN(), except it differs for the return type. * * @param[in] str String in question. * @exception rb_eRangeError Too long. * @return Its length, in bytes. * @pre `str` must be an instance of ::RString. * * @internal * * This API seems redundant but has actual usages. */ static inline int RSTRING_LENINT(VALUE str) { return rb_long2int(RSTRING_LEN(str)); } /** * Convenient macro to obtain the contents and length at once. * * @param str String in question. * @param ptrvar Variable where its contents is stored. * @param lenvar Variable where its length is stored. */ #ifdef HAVE_STMT_AND_DECL_IN_EXPR # define RSTRING_GETMEM(str, ptrvar, lenvar) \ __extension__ ({ \ struct RString rbimpl_str = rbimpl_rstring_getmem(str); \ (ptrvar) = rbimpl_str.as.heap.ptr; \ (lenvar) = rbimpl_str.len; \ }) #else # define RSTRING_GETMEM(str, ptrvar, lenvar) \ ((ptrvar) = RSTRING_PTR(str), \ (lenvar) = RSTRING_LEN(str)) #endif /* HAVE_STMT_AND_DECL_IN_EXPR */ #endif /* RBIMPL_RSTRING_H */ include/ruby/internal/core/rhash.h 0000644 00000010670 15152150502 0013172 0 ustar 00 #ifndef RBIMPL_RHASH_H /*-*-C++-*-vi:se ft=cpp:*/ #define RBIMPL_RHASH_H /** * @file * @author Ruby developers <ruby-core@ruby-lang.org> * @copyright This file is a part of the programming language Ruby. * Permission is hereby granted, to either redistribute and/or * modify this file, provided that the conditions mentioned in the * file COPYING are met. Consult the file for details. * @warning Symbols prefixed with either `RBIMPL` or `rbimpl` are * implementation details. Don't take them as canon. They could * rapidly appear then vanish. The name (path) of this header file * is also an implementation detail. Do not expect it to persist * at the place it is now. Developers are free to move it anywhere * anytime at will. * @note To ruby-core: remember that this header can be possibly * recursively included from extension libraries written in C++. * Do not expect for instance `__VA_ARGS__` is always available. * We assume C99 for ruby itself but we don't assume languages of * extension libraries. They could be written in C++98. * @brief Routines to manipulate struct RHash. * @note The struct RHash itself is opaque. */ #include "ruby/internal/config.h" #ifdef STDC_HEADERS # include <stddef.h> #endif #include "ruby/internal/dllexport.h" #include "ruby/internal/value.h" #if !defined RUBY_EXPORT && !defined RUBY_NO_OLD_COMPATIBILITY # include "ruby/backward.h" #endif /** * Retrieves the internal table. * * @param[in] h An instance of RHash. * @pre `h` must be of ::RUBY_T_HASH. * @return A struct st_table which has the contents of this hash. * @note Nowadays as Ruby evolved over ages, RHash has multiple backend * storage engines. `h`'s backend is not guaranteed to be a * st_table. This function creates one when necessary. */ #define RHASH_TBL(h) rb_hash_tbl(h, __FILE__, __LINE__) /** * @private * * @deprecated This macro once was a thing in the old days, but makes no sense * any longer today. Exists here for backwards compatibility * only. You can safely forget about it. * * @internal * * Declaration of rb_hash_ifnone() is at include/ruby/backward.h. */ #define RHASH_IFNONE(h) rb_hash_ifnone(h) /** * Queries the size of the hash. Size here means the number of keys that the * hash stores. * * @param[in] h An instance of RHash. * @pre `h` must be of ::RUBY_T_HASH. * @return The size of the hash. */ #define RHASH_SIZE(h) rb_hash_size_num(h) /** * Checks if the hash is empty. * * @param[in] h An instance of RHash. * @pre `h` must be of ::RUBY_T_HASH. * @retval true It is. * @retval false It isn't. */ #define RHASH_EMPTY_P(h) (RHASH_SIZE(h) == 0) /** * Destructively updates the default value of the hash. * * @param[out] h An instance of RHash. * @param[in] ifnone Arbitrary default value. * @pre `h` must be of ::RUBY_T_HASH. * * @internal * * But why you can set this, given rb_hash_ifnone() doesn't exist? */ #define RHASH_SET_IFNONE(h, ifnone) rb_hash_set_ifnone((VALUE)h, ifnone) struct st_table; /* in ruby/st.h */ RBIMPL_SYMBOL_EXPORT_BEGIN() /** * This is the implementation detail of #RHASH_SIZE. People don't call this * directly. * * @param[in] hash An instance of RHash. * @pre `hash` must be of ::RUBY_T_HASH. * @return The size of the hash. */ size_t rb_hash_size_num(VALUE hash); /** * This is the implementation detail of #RHASH_TBL. People don't call this * directly. * * @param[in] hash An instance of RHash. * @param[in] file The `__FILE__`. * @param[in] line The `__LINE__`. * @pre `hash` must be of ::RUBY_T_HASH. * @return Table that has the contents of the hash. */ struct st_table *rb_hash_tbl(VALUE hash, const char *file, int line); /** * This is the implementation detail of #RHASH_SET_IFNONE. People don't call * this directly. * * @param[out] hash An instance of RHash. * @param[in] ifnone Arbitrary default value. * @pre `hash` must be of ::RUBY_T_HASH. */ VALUE rb_hash_set_ifnone(VALUE hash, VALUE ifnone); RBIMPL_SYMBOL_EXPORT_END() #endif /* RBIMPL_RHASH_H */ include/ruby/internal/core/rbignum.h 0000644 00000005605 15152150502 0013532 0 ustar 00 #ifndef RBIMPL_RBIGNUM_H /*-*-C++-*-vi:se ft=cpp:*/ #define RBIMPL_RBIGNUM_H /** * @file * @author Ruby developers <ruby-core@ruby-lang.org> * @copyright This file is a part of the programming language Ruby. * Permission is hereby granted, to either redistribute and/or * modify this file, provided that the conditions mentioned in the * file COPYING are met. Consult the file for details. * @warning Symbols prefixed with either `RBIMPL` or `rbimpl` are * implementation details. Don't take them as canon. They could * rapidly appear then vanish. The name (path) of this header file * is also an implementation detail. Do not expect it to persist * at the place it is now. Developers are free to move it anywhere * anytime at will. * @note To ruby-core: remember that this header can be possibly * recursively included from extension libraries written in C++. * Do not expect for instance `__VA_ARGS__` is always available. * We assume C99 for ruby itself but we don't assume languages of * extension libraries. They could be written in C++98. * @brief Routines to manipulate struct RBignum. * @note The struct RBignum itself is opaque. */ #include "ruby/internal/dllexport.h" #include "ruby/internal/value.h" #include "ruby/internal/value_type.h" #include "ruby/internal/stdbool.h" #define RBIGNUM_SIGN rb_big_sign /**< @alias{rb_big_sign} */ /** @cond INTERNAL_MACRO */ #define RBIGNUM_POSITIVE_P RBIGNUM_POSITIVE_P #define RBIGNUM_NEGATIVE_P RBIGNUM_NEGATIVE_P /** @endcond */ RBIMPL_SYMBOL_EXPORT_BEGIN() /** * The "sign" of a bignum. * * @param[in] num An object of RBignum. * @retval 1 It is greater than or equal to zero. * @retval 0 It is less than zero. * * @internal * * Implementation wise, unlike fixnums (which are 2's complement), bignums are * signed magnitude system. Theoretically it could be possible to have * negative zero instances. But in reality there is no way to create such * thing. Nobody ever needed that kind of insanity. */ int rb_big_sign(VALUE num); RBIMPL_SYMBOL_EXPORT_END() /** * Checks if the bignum is positive. * @param[in] b An object of RBignum. * @retval false `b` is less than zero. * @retval true Otherwise. */ static inline bool RBIGNUM_POSITIVE_P(VALUE b) { RBIMPL_ASSERT_TYPE(b, RUBY_T_BIGNUM); return RBIGNUM_SIGN(b); } /** * Checks if the bignum is negative. * @param[in] b An object of RBignum. * @retval true `b` is less than zero. * @retval false Otherwise. */ static inline bool RBIGNUM_NEGATIVE_P(VALUE b) { RBIMPL_ASSERT_TYPE(b, RUBY_T_BIGNUM); return ! RBIGNUM_POSITIVE_P(b); } #endif /* RBIMPL_RBIGNUM_H */ include/ruby/internal/core/rstruct.h 0000644 00000010153 15152150502 0013567 0 ustar 00 #ifndef RBIMPL_RSTRUCT_H /*-*-C++-*-vi:se ft=cpp:*/ #define RBIMPL_RSTRUCT_H /** * @file * @author Ruby developers <ruby-core@ruby-lang.org> * @copyright This file is a part of the programming language Ruby. * Permission is hereby granted, to either redistribute and/or * modify this file, provided that the conditions mentioned in the * file COPYING are met. Consult the file for details. * @warning Symbols prefixed with either `RBIMPL` or `rbimpl` are * implementation details. Don't take them as canon. They could * rapidly appear then vanish. The name (path) of this header file * is also an implementation detail. Do not expect it to persist * at the place it is now. Developers are free to move it anywhere * anytime at will. * @note To ruby-core: remember that this header can be possibly * recursively included from extension libraries written in C++. * Do not expect for instance `__VA_ARGS__` is always available. * We assume C99 for ruby itself but we don't assume languages of * extension libraries. They could be written in C++98. * @brief Routines to manipulate struct RStruct. * @note The struct RStruct itself is opaque. */ #include "ruby/internal/attr/artificial.h" #include "ruby/internal/dllexport.h" #include "ruby/internal/value.h" #include "ruby/internal/value_type.h" #include "ruby/internal/arithmetic/long.h" #include "ruby/internal/arithmetic/int.h" #if !defined RUBY_EXPORT && !defined RUBY_NO_OLD_COMPATIBILITY # include "ruby/backward.h" #endif /** * @private * * @deprecated This macro once was a thing in the old days, but makes no sense * any longer today. Exists here for backwards compatibility * only. You can safely forget about it. * * @internal * * Declaration of rb_struct_ptr() is at include/ruby/backward.h. */ #define RSTRUCT_PTR(st) rb_struct_ptr(st) /** @cond INTERNAL_MACRO */ #define RSTRUCT_LEN RSTRUCT_LEN #define RSTRUCT_SET RSTRUCT_SET #define RSTRUCT_GET RSTRUCT_GET /** @endcond */ RBIMPL_SYMBOL_EXPORT_BEGIN() /** * Returns the number of struct members. * * @param[in] st An instance of RStruct. * @return The number of members of `st`. * @pre `st` must be of ::RUBY_T_STRUCT. */ VALUE rb_struct_size(VALUE st); /** * Resembles `Struct#[]`. * * @param[in] st An instance of RStruct. * @param[in] k Index a.k.a. key of the struct. * @exception rb_eTypeError `k` is neither Numeric, Symbol, nor String. * @exception rb_eIndexError Numerical index out of range. * @exception rb_eNameError No such key. * @return The member stored at `k` in `st`. * @pre `st` must be of ::RUBY_T_STRUCT. */ VALUE rb_struct_aref(VALUE st, VALUE k); /** * Resembles `Struct#[]=`. * * @param[out] st An instance of RStruct. * @param[in] k Index a.k.a. key of the struct. * @param[in] v Value to store. * @exception rb_eTypeError `k` is neither Numeric, Symbol, nor String. * @exception rb_eIndexError Numerical index out of range. * @exception rb_eNameError No such key. * @return Passed `v`. * @pre `st` must be of ::RUBY_T_STRUCT. * @post `v` is stored at `k` in `st`. */ VALUE rb_struct_aset(VALUE st, VALUE k, VALUE v); RBIMPL_SYMBOL_EXPORT_END() RBIMPL_ATTR_ARTIFICIAL() /** @copydoc rb_struct_size() */ static inline long RSTRUCT_LEN(VALUE st) { RBIMPL_ASSERT_TYPE(st, RUBY_T_STRUCT); return RB_NUM2LONG(rb_struct_size(st)); } RBIMPL_ATTR_ARTIFICIAL() /** @copydoc rb_struct_aset() */ static inline VALUE RSTRUCT_SET(VALUE st, int k, VALUE v) { RBIMPL_ASSERT_TYPE(st, RUBY_T_STRUCT); return rb_struct_aset(st, INT2NUM(k), (v)); } RBIMPL_ATTR_ARTIFICIAL() /** @copydoc rb_struct_aref() */ static inline VALUE RSTRUCT_GET(VALUE st, int k) { RBIMPL_ASSERT_TYPE(st, RUBY_T_STRUCT); return rb_struct_aref(st, INT2NUM(k)); } #endif /* RBIMPL_RSTRUCT_H */ include/ruby/internal/core/rregexp.h 0000644 00000013002 15152150502 0013531 0 ustar 00 #ifndef RBIMPL_RREGEXP_H /*-*-C++-*-vi:se ft=cpp:*/ #define RBIMPL_RREGEXP_H /** * @file * @author Ruby developers <ruby-core@ruby-lang.org> * @copyright This file is a part of the programming language Ruby. * Permission is hereby granted, to either redistribute and/or * modify this file, provided that the conditions mentioned in the * file COPYING are met. Consult the file for details. * @warning Symbols prefixed with either `RBIMPL` or `rbimpl` are * implementation details. Don't take them as canon. They could * rapidly appear then vanish. The name (path) of this header file * is also an implementation detail. Do not expect it to persist * at the place it is now. Developers are free to move it anywhere * anytime at will. * @note To ruby-core: remember that this header can be possibly * recursively included from extension libraries written in C++. * Do not expect for instance `__VA_ARGS__` is always available. * We assume C99 for ruby itself but we don't assume languages of * extension libraries. They could be written in C++98. * @brief Defines struct ::RRegexp. */ #include "ruby/internal/attr/artificial.h" #include "ruby/internal/attr/pure.h" #include "ruby/internal/cast.h" #include "ruby/internal/core/rbasic.h" #include "ruby/internal/core/rstring.h" #include "ruby/internal/value.h" #include "ruby/internal/value_type.h" /** * Convenient casting macro. * * @param obj An object, which is in fact an ::RRegexp. * @return The passed object casted to ::RRegexp. */ #define RREGEXP(obj) RBIMPL_CAST((struct RRegexp *)(obj)) /** * Convenient accessor macro. * * @param obj An object, which is in fact an ::RRegexp. * @return The passed object's pattern buffer. */ #define RREGEXP_PTR(obj) (RREGEXP(obj)->ptr) /** @cond INTERNAL_MACRO */ #define RREGEXP_SRC RREGEXP_SRC #define RREGEXP_SRC_PTR RREGEXP_SRC_PTR #define RREGEXP_SRC_LEN RREGEXP_SRC_LEN #define RREGEXP_SRC_END RREGEXP_SRC_END /** @endcond */ struct re_patter_buffer; /* a.k.a. OnigRegexType, defined in onigmo.h */ /** * Ruby's regular expression. A regexp is compiled into its own intermediate * representation. This one holds that info. Regexp "match" operation then * executes that IR. */ struct RRegexp { /** Basic part, including flags and class. */ struct RBasic basic; /** * The pattern buffer. This is a quasi-opaque struct that holds compiled * intermediate representation of the regular expression. * * @note Compilation of a regexp could be delayed until actual match. */ struct re_pattern_buffer *ptr; /** Source code of this expression. */ const VALUE src; /** * Reference count. A regexp match can take extraordinarily long time to * run. Ruby's regular expression is heavily extended and not a regular * language any longer; runs in NP-time in practice. Now, Ruby also has * threads and GVL. In order to prevent long GVL lockup, our regexp engine * can release it on occasions. This means that multiple threads can touch * a regular expressions at once. That itself is okay. But their cleanup * phase shall wait for all the concurrent runs, to prevent use-after-free * situation. This field is used to count such threads that are executing * this particular pattern buffer. * * @warning Of course, touching this field from extension libraries causes * catastrophic effects. Just leave it. */ unsigned long usecnt; }; RBIMPL_ATTR_PURE_UNLESS_DEBUG() RBIMPL_ATTR_ARTIFICIAL() /** * Convenient getter function. * * @param[in] rexp The regular expression in question. * @return The source code of the regular expression. * @pre `rexp` must be of ::RRegexp. */ static inline VALUE RREGEXP_SRC(VALUE rexp) { RBIMPL_ASSERT_TYPE(rexp, RUBY_T_REGEXP); VALUE ret = RREGEXP(rexp)->src; RBIMPL_ASSERT_TYPE(ret, RUBY_T_STRING); return ret; } RBIMPL_ATTR_PURE_UNLESS_DEBUG() RBIMPL_ATTR_ARTIFICIAL() /** * Convenient getter function. * * @param[in] rexp The regular expression in question. * @return The source code of the regular expression, in C's string. * @pre `rexp` must be of ::RRegexp. * * @internal * * It seems nobody uses this function in the wild. Subject to hide? */ static inline char * RREGEXP_SRC_PTR(VALUE rexp) { return RSTRING_PTR(RREGEXP_SRC(rexp)); } RBIMPL_ATTR_PURE_UNLESS_DEBUG() RBIMPL_ATTR_ARTIFICIAL() /** * Convenient getter function. * * @param[in] rexp The regular expression in question. * @return The length of the source code of the regular expression. * @pre `rexp` must be of ::RRegexp. * * @internal * * It seems nobody uses this function in the wild. Subject to hide? */ static inline long RREGEXP_SRC_LEN(VALUE rexp) { return RSTRING_LEN(RREGEXP_SRC(rexp)); } RBIMPL_ATTR_PURE_UNLESS_DEBUG() RBIMPL_ATTR_ARTIFICIAL() /** * Convenient getter function. * * @param[in] rexp The regular expression in question. * @return The end of the source code of the regular expression. * @pre `rexp` must be of ::RRegexp. * * @internal * * It seems nobody uses this function in the wild. Subject to hide? */ static inline char * RREGEXP_SRC_END(VALUE rexp) { return RSTRING_END(RREGEXP_SRC(rexp)); } #endif /* RBIMPL_RREGEXP_H */ include/ruby/internal/core/rarray.h 0000644 00000032344 15152150502 0013367 0 ustar 00 #ifndef RBIMPL_RARRAY_H /*-*-C++-*-vi:se ft=cpp:*/ #define RBIMPL_RARRAY_H /** * @file * @author Ruby developers <ruby-core@ruby-lang.org> * @copyright This file is a part of the programming language Ruby. * Permission is hereby granted, to either redistribute and/or * modify this file, provided that the conditions mentioned in the * file COPYING are met. Consult the file for details. * @warning Symbols prefixed with either `RBIMPL` or `rbimpl` are * implementation details. Don't take them as canon. They could * rapidly appear then vanish. The name (path) of this header file * is also an implementation detail. Do not expect it to persist * at the place it is now. Developers are free to move it anywhere * anytime at will. * @note To ruby-core: remember that this header can be possibly * recursively included from extension libraries written in C++. * Do not expect for instance `__VA_ARGS__` is always available. * We assume C99 for ruby itself but we don't assume languages of * extension libraries. They could be written in C++98. * @brief Defines struct ::RArray. */ #include "ruby/internal/arithmetic/long.h" #include "ruby/internal/attr/artificial.h" #include "ruby/internal/attr/constexpr.h" #include "ruby/internal/attr/maybe_unused.h" #include "ruby/internal/attr/pure.h" #include "ruby/internal/cast.h" #include "ruby/internal/core/rbasic.h" #include "ruby/internal/dllexport.h" #include "ruby/internal/fl_type.h" #include "ruby/internal/gc.h" #include "ruby/internal/stdbool.h" #include "ruby/internal/value.h" #include "ruby/internal/value_type.h" #include "ruby/assert.h" /** * Convenient casting macro. * * @param obj An object, which is in fact an ::RArray. * @return The passed object casted to ::RArray. */ #define RARRAY(obj) RBIMPL_CAST((struct RArray *)(obj)) /** @cond INTERNAL_MACRO */ #define RARRAY_EMBED_FLAG RARRAY_EMBED_FLAG #define RARRAY_EMBED_LEN_MASK RARRAY_EMBED_LEN_MASK #define RARRAY_EMBED_LEN_MAX RARRAY_EMBED_LEN_MAX #define RARRAY_EMBED_LEN_SHIFT RARRAY_EMBED_LEN_SHIFT /** @endcond */ #define RARRAY_LEN rb_array_len /**< @alias{rb_array_len} */ #define RARRAY_CONST_PTR rb_array_const_ptr /**< @alias{rb_array_const_ptr} */ /** @cond INTERNAL_MACRO */ #if defined(__fcc__) || defined(__fcc_version) || \ defined(__FCC__) || defined(__FCC_VERSION) /* workaround for old version of Fujitsu C Compiler (fcc) */ # define FIX_CONST_VALUE_PTR(x) ((const VALUE *)(x)) #else # define FIX_CONST_VALUE_PTR(x) (x) #endif #define RARRAY_EMBED_LEN RARRAY_EMBED_LEN #define RARRAY_LENINT RARRAY_LENINT #define RARRAY_ASET RARRAY_ASET #define RARRAY_PTR RARRAY_PTR /** @endcond */ /** * @private * * Bits that you can set to ::RBasic::flags. * * @warning These enums are not the only bits we use for arrays. * * @internal * * Unlike strings, flag usages for arrays are scattered across the entire * source codes. @shyouhei doesn't know the complete list. But what is listed * here is at least incomplete. */ enum ruby_rarray_flags { /** * This flag has something to do with memory footprint. If the array is * "small" enough, ruby tries to be creative to abuse padding bits of * struct ::RArray for storing its contents. This flag denotes that * situation. * * @warning This bit has to be considered read-only. Setting/clearing * this bit without corresponding fix up must cause immediate * SEGV. Also, internal structures of an array change * dynamically and transparently throughout of its lifetime. * Don't assume it being persistent. * * @internal * * 3rd parties must not be aware that there even is more than one way to * store array elements. It was a bad idea to expose this to them. */ RARRAY_EMBED_FLAG = RUBY_FL_USER1, /* RUBY_FL_USER2 is for ELTS_SHARED */ /** * When an array employs embedded strategy (see ::RARRAY_EMBED_FLAG), these * bits are used to store the number of elements actually filled into * ::RArray::ary. * * @internal * * 3rd parties must not be aware that there even is more than one way to * store array elements. It was a bad idea to expose this to them. */ RARRAY_EMBED_LEN_MASK = RUBY_FL_USER9 | RUBY_FL_USER8 | RUBY_FL_USER7 | RUBY_FL_USER6 | RUBY_FL_USER5 | RUBY_FL_USER4 | RUBY_FL_USER3 }; /** * This is an enum because GDB wants it (rather than a macro). People need not * bother. */ enum ruby_rarray_consts { /** Where ::RARRAY_EMBED_LEN_MASK resides. */ RARRAY_EMBED_LEN_SHIFT = RUBY_FL_USHIFT + 3 }; /** Ruby's array. */ struct RArray { /** Basic part, including flags and class. */ struct RBasic basic; /** Array's specific fields. */ union { /** * Arrays that use separated memory region for elements use this * pattern. */ struct { /** Number of elements of the array. */ long len; /** Auxiliary info. */ union { /** * Capacity of `*ptr`. A continuous memory region of at least * `capa` elements is expected to exist at `*ptr`. This can be * bigger than `len`. */ long capa; /** * Parent of the array. Nowadays arrays can share their * backend memory regions each other, constructing gigantic * nest of objects. This situation is called "shared", and * this is the field to control such properties. */ #if defined(__clang__) /* <- clang++ is sane */ || \ !defined(__cplusplus) /* <- C99 is sane */ || \ (__cplusplus > 199711L) /* <- C++11 is sane */ const #endif VALUE shared_root; } aux; /** * Pointer to the C array that holds the elements of the array. In * the old days each array had dedicated memory regions. That is * no longer true today, but there still are arrays of such * properties. This field could be used to point such things. */ const VALUE *ptr; } heap; /** * Embedded elements. When an array is short enough, it uses this area * to store its elements. In this case the length is encoded into the * flags. */ /* This is a length 1 array because: * 1. GCC has a bug that does not optimize C flexible array members * (https://gcc.gnu.org/bugzilla/show_bug.cgi?id=102452) * 2. Zero length arrays are not supported by all compilers */ const VALUE ary[1]; } as; }; RBIMPL_SYMBOL_EXPORT_BEGIN() /** * @private * * Declares a section of code where raw pointers are used. This is an * implementation detail of #RARRAY_PTR_USE. People don't use it directly. * * @param[in] ary An object of ::RArray. * @return `ary`'s backend C array. */ VALUE *rb_ary_ptr_use_start(VALUE ary); /** * @private * * Declares an end of a section formerly started by rb_ary_ptr_use_start(). * This is an implementation detail of #RARRAY_PTR_USE. People don't use it * directly. * * @param[in] a An object of ::RArray. */ void rb_ary_ptr_use_end(VALUE a); RBIMPL_SYMBOL_EXPORT_END() RBIMPL_ATTR_PURE_UNLESS_DEBUG() RBIMPL_ATTR_ARTIFICIAL() /** * Queries the length of the array. * * @param[in] ary Array in question. * @return Its number of elements. * @pre `ary` must be an instance of ::RArray, and must has its * ::RARRAY_EMBED_FLAG flag set. * * @internal * * This was a macro before. It was inevitable to be public, since macros are * global constructs. But should it be forever? Now that it is a function, * @shyouhei thinks it could just be eliminated, hidden into implementation * details. */ static inline long RARRAY_EMBED_LEN(VALUE ary) { RBIMPL_ASSERT_TYPE(ary, RUBY_T_ARRAY); RBIMPL_ASSERT_OR_ASSUME(RB_FL_ANY_RAW(ary, RARRAY_EMBED_FLAG)); VALUE f = RBASIC(ary)->flags; f &= RARRAY_EMBED_LEN_MASK; f >>= RARRAY_EMBED_LEN_SHIFT; return RBIMPL_CAST((long)f); } RBIMPL_ATTR_PURE_UNLESS_DEBUG() /** * Queries the length of the array. * * @param[in] a Array in question. * @return Its number of elements. * @pre `a` must be an instance of ::RArray. */ static inline long rb_array_len(VALUE a) { RBIMPL_ASSERT_TYPE(a, RUBY_T_ARRAY); if (RB_FL_ANY_RAW(a, RARRAY_EMBED_FLAG)) { return RARRAY_EMBED_LEN(a); } else { return RARRAY(a)->as.heap.len; } } RBIMPL_ATTR_ARTIFICIAL() /** * Identical to rb_array_len(), except it differs for the return type. * * @param[in] ary Array in question. * @exception rb_eRangeError Too long. * @return Its number of elements. * @pre `ary` must be an instance of ::RArray. * * @internal * * This API seems redundant but has actual usages. */ static inline int RARRAY_LENINT(VALUE ary) { return rb_long2int(RARRAY_LEN(ary)); } RBIMPL_ATTR_PURE_UNLESS_DEBUG() /** * @private * * This is an implementation detail of RARRAY_PTR(). People do not use it * directly. * * @param[in] a An object of ::RArray. * @return Its backend storage. */ static inline const VALUE * rb_array_const_ptr(VALUE a) { RBIMPL_ASSERT_TYPE(a, RUBY_T_ARRAY); if (RB_FL_ANY_RAW(a, RARRAY_EMBED_FLAG)) { return FIX_CONST_VALUE_PTR(RARRAY(a)->as.ary); } else { return FIX_CONST_VALUE_PTR(RARRAY(a)->as.heap.ptr); } } /** * @private * * This is an implementation detail of #RARRAY_PTR_USE. People do not use it * directly. */ #define RBIMPL_RARRAY_STMT(ary, var, expr) do { \ RBIMPL_ASSERT_TYPE((ary), RUBY_T_ARRAY); \ const VALUE rbimpl_ary = (ary); \ VALUE *var = rb_ary_ptr_use_start(rbimpl_ary); \ expr; \ rb_ary_ptr_use_end(rbimpl_ary); \ } while (0) /** * Declares a section of code where raw pointers are used. In case you need to * touch the raw C array instead of polite CAPIs, then that operation shall be * wrapped using this macro. * * ```CXX * const auto ary = rb_eval_string("[...]"); * const auto len = RARRAY_LENINT(ary); * const auto symwrite = rb_intern("write"); * * RARRAY_PTR_USE(ary, ptr, { * rb_funcallv(rb_stdout, symwrite, len, ptr); * }); * ``` * * @param ary An object of ::RArray. * @param ptr_name A variable name which points the C array in `expr`. * @param expr The expression that touches `ptr_name`. * * @internal * * For historical reasons use of this macro is not enforced. There are * extension libraries in the wild which call RARRAY_PTR() without it. We want * them use it... Maybe some transition path can be implemented later. */ #define RARRAY_PTR_USE(ary, ptr_name, expr) \ RBIMPL_RARRAY_STMT(ary, ptr_name, expr) /** * Wild use of a C pointer. This function accesses the backend storage * directly. This is slower than #RARRAY_PTR_USE. It exercises * extra manoeuvres to protect our generational GC. Use of this function is * considered archaic. Use a modern way instead. * * @param[in] ary An object of ::RArray. * @return The backend C array. * * @internal * * That said... there are extension libraries in the wild who uses it. We * cannot but continue supporting. */ static inline VALUE * RARRAY_PTR(VALUE ary) { RBIMPL_ASSERT_TYPE(ary, RUBY_T_ARRAY); VALUE tmp = RB_OBJ_WB_UNPROTECT_FOR(ARRAY, ary); return RBIMPL_CAST((VALUE *)RARRAY_CONST_PTR(tmp)); } /** * Assigns an object in an array. * * @param[out] ary Destination array object. * @param[in] i Index of `ary`. * @param[in] v Arbitrary ruby object. * @pre `ary` must be an instance of ::RArray. * @pre `ary`'s length must be longer than or equal to `i`. * @pre `i` must be greater than or equal to zero. * @post `ary`'s `i`th element is set to `v`. */ static inline void RARRAY_ASET(VALUE ary, long i, VALUE v) { RARRAY_PTR_USE(ary, ptr, RB_OBJ_WRITE(ary, &ptr[i], v)); } /** * @deprecated * * :FIXME: we want to convert RARRAY_AREF into an inline function (to add rooms * for more sanity checks). However there were situations where the address of * this macro is taken i.e. &RARRAY_AREF(...). They cannot be possible if this * is not a macro. Such usages are abuse, and we eliminated them internally. * However we are afraid of similar things to remain in the wild. This macro * remains as it is due to that. If we could warn such usages we can set a * transition path, but currently no way is found to do so. */ #define RARRAY_AREF(a, i) RARRAY_CONST_PTR(a)[i] #endif /* RBIMPL_RARRAY_H */ include/ruby/internal/core/rtypeddata.h 0000644 00000055451 15152150502 0014234 0 ustar 00 #ifndef RBIMPL_RTYPEDDATA_H /*-*-C++-*-vi:se ft=cpp:*/ #define RBIMPL_RTYPEDDATA_H /** * @file * @author Ruby developers <ruby-core@ruby-lang.org> * @copyright This file is a part of the programming language Ruby. * Permission is hereby granted, to either redistribute and/or * modify this file, provided that the conditions mentioned in the * file COPYING are met. Consult the file for details. * @warning Symbols prefixed with either `RBIMPL` or `rbimpl` are * implementation details. Don't take them as canon. They could * rapidly appear then vanish. The name (path) of this header file * is also an implementation detail. Do not expect it to persist * at the place it is now. Developers are free to move it anywhere * anytime at will. * @note To ruby-core: remember that this header can be possibly * recursively included from extension libraries written in C++. * Do not expect for instance `__VA_ARGS__` is always available. * We assume C99 for ruby itself but we don't assume languages of * extension libraries. They could be written in C++98. * @brief Defines struct ::RTypedData. */ #include "ruby/internal/config.h" #ifdef STDC_HEADERS # include <stddef.h> #endif #include "ruby/internal/assume.h" #include "ruby/internal/attr/artificial.h" #include "ruby/internal/attr/flag_enum.h" #include "ruby/internal/attr/nonnull.h" #include "ruby/internal/attr/pure.h" #include "ruby/internal/cast.h" #include "ruby/internal/core/rbasic.h" #include "ruby/internal/core/rdata.h" #include "ruby/internal/dllexport.h" #include "ruby/internal/error.h" #include "ruby/internal/fl_type.h" #include "ruby/internal/stdbool.h" #include "ruby/internal/value_type.h" /** * @private * * @deprecated This macro once was a thing in the old days, but makes no sense * any longer today. Exists here for backwards compatibility * only. You can safely forget about it. */ #define HAVE_TYPE_RB_DATA_TYPE_T 1 /** * @private * * @deprecated This macro once was a thing in the old days, but makes no sense * any longer today. Exists here for backwards compatibility * only. You can safely forget about it. */ #define HAVE_RB_DATA_TYPE_T_FUNCTION 1 /** * @private * * @deprecated This macro once was a thing in the old days, but makes no sense * any longer today. Exists here for backwards compatibility * only. You can safely forget about it. */ #define HAVE_RB_DATA_TYPE_T_PARENT 1 /** * This is a value you can set to ::rb_data_type_struct::dfree. Setting this * means the data was allocated using ::ruby_xmalloc() (or variants), and shall * be freed using ::ruby_xfree(). * * @warning Do not use this if you want to use system malloc, because the * system and Ruby might or might not share the same malloc * implementation. */ #define RUBY_TYPED_DEFAULT_FREE RUBY_DEFAULT_FREE /** * This is a value you can set to ::rb_data_type_struct::dfree. Setting this * means the data is managed by someone else, like, statically allocated. Of * course you are on your own then. */ #define RUBY_TYPED_NEVER_FREE RUBY_NEVER_FREE /** * Convenient casting macro. * * @param obj An object, which is in fact an ::RTypedData. * @return The passed object casted to ::RTypedData. */ #define RTYPEDDATA(obj) RBIMPL_CAST((struct RTypedData *)(obj)) /** * Convenient getter macro. * * @param v An object, which is in fact an ::RTypedData. * @return The passed object's ::RTypedData::data field. */ #define RTYPEDDATA_DATA(v) (RTYPEDDATA(v)->data) /** @old{rb_check_typeddata} */ #define Check_TypedStruct(v, t) \ rb_check_typeddata(RBIMPL_CAST((VALUE)(v)), (t)) /** @cond INTERNAL_MACRO */ #define RTYPEDDATA_P RTYPEDDATA_P #define RTYPEDDATA_TYPE RTYPEDDATA_TYPE #define RUBY_TYPED_FREE_IMMEDIATELY RUBY_TYPED_FREE_IMMEDIATELY #define RUBY_TYPED_FROZEN_SHAREABLE RUBY_TYPED_FROZEN_SHAREABLE #define RUBY_TYPED_WB_PROTECTED RUBY_TYPED_WB_PROTECTED #define RUBY_TYPED_PROMOTED1 RUBY_TYPED_PROMOTED1 /** @endcond */ #define TYPED_DATA_EMBEDDED 2 /** * @private * * Bits for rb_data_type_struct::flags. */ enum RBIMPL_ATTR_FLAG_ENUM() rbimpl_typeddata_flags { /** * This flag has something to do with Ruby's global interpreter lock. For * maximum safety, Ruby locks the entire VM during GC. However your * callback functions could unintentionally unlock it, for instance when * they try to flush an IO buffer. Such operations are dangerous (threads * then run alongside of GC). By default, to prevent those scenario, * callbacks are deferred until the GC engine is 100% sure threads can run. * This flag skips that; structs with it are deallocated during the sweep * phase. * * Using this flag needs deep understanding of both GC and threads. You * would better leave it unspecified. */ RUBY_TYPED_FREE_IMMEDIATELY = 1, RUBY_TYPED_EMBEDDABLE = 2, /** * This flag has something to do with Ractor. Multiple Ractors run without * protecting each other. Sharing an object among Ractors is basically * dangerous, disabled by default. This flag is used to bypass that * restriction. but setting it is not enough. In addition to do so, an * object also has to be frozen, and be passed to * rb_ractor_make_shareable() before being actually shareable. Of course, * you have to manually prevent race conditions then. * * Using this flag needs deep understanding of multithreaded programming. * You would better leave it unspecified. */ RUBY_TYPED_FROZEN_SHAREABLE = RUBY_FL_SHAREABLE, /** * This flag has something to do with our garbage collector. These days * ruby objects are "generational". There are those who are young and * those who are old. Young objects are prone to die; monitored relatively * extensively by the garbage collector. OTOH old objects tend to live * longer. They are relatively rarely considered. This basically works. * But there is one tweak that has to be exercised. When an elder object * has reference(s) to younger one(s), that referenced objects must not * die. In order to detect additions of such references, old generations * are protected by write barriers. It is a very difficult hack to * appropriately insert write barriers everywhere. This mechanism is * disabled by default for 3rd party extensions (they never get aged). By * specifying this flag you can enable the generational feature to your * data structure. Of course, you have to manually insert write barriers * then. * * Using this flag needs deep understanding of GC internals, often at the * level of source code. You would better leave it unspecified. */ RUBY_TYPED_WB_PROTECTED = RUBY_FL_WB_PROTECTED, /* THIS FLAG DEPENDS ON Ruby version */ /** * This flag no longer in use */ RUBY_TYPED_UNUSED = RUBY_FL_UNUSED6, /** * This flag determines whether marking and compaction should be carried out * using the dmark/dcompact callback functions or whether we should mark * declaratively using a list of references defined inside the data struct we're wrapping */ RUBY_TYPED_DECL_MARKING = RUBY_FL_USER2 }; /** * This is the struct that holds necessary info for a struct. It roughly * resembles a Ruby level class; multiple objects can share a ::rb_data_type_t * instance. */ typedef struct rb_data_type_struct rb_data_type_t; /** @copydoc rb_data_type_t */ struct rb_data_type_struct { /** * Name of structs of this kind. This is used for diagnostic purposes. * This has to be unique in the process, but doesn't has to be a valid * C/Ruby identifier. */ const char *wrap_struct_name; /** Function pointers. Resembles C++ `vtbl`.*/ struct { /** * This function is called when the object is experiencing GC marks. * If it contains references to other Ruby objects, you need to mark * them also. Otherwise GC will smash your data. * * @see rb_gc_mark() * @warning This is called during GC runs. Object allocations are * impossible at that moment (that is why GC runs). */ RUBY_DATA_FUNC dmark; /** * This function is called when the object is no longer used. You need * to do whatever necessary to avoid memory leaks. * * @warning This is called during GC runs. Object allocations are * impossible at that moment (that is why GC runs). */ RUBY_DATA_FUNC dfree; /** * This function is to query the size of the underlying memory regions. * * @internal * * This function has only one usage, which is form inside of * `ext/objspace`. */ size_t (*dsize)(const void *); /** * This function is called when the object is relocated. Like * ::rb_data_type_struct::dmark, you need to update references to Ruby * objects inside of your structs. * * @see rb_gc_location() * @warning This is called during GC runs. Object allocations are * impossible at that moment (that is why GC runs). */ RUBY_DATA_FUNC dcompact; /** * This field is reserved for future extension. For now, it must be * filled with zeros. */ void *reserved[1]; /* For future extension. This array *must* be filled with ZERO. */ } function; /** * Parent of this class. Sometimes C structs have inheritance-like * relationships. An example is `struct sockaddr` and its family. If you * design such things, make ::rb_data_type_t for each of them and connect * using this field. Ruby can then transparently cast your data back and * forth when you call #TypedData_Get_Struct(). * * ```CXX * struct parent { }; * static inline const rb_data_type_t parent_type = { * .wrap_struct_name = "parent", * }; * * struct child: public parent { }; * static inline const rb_data_type_t child_type = { * .wrap_struct_name = "child", * .parent = &parent_type, * }; * * // This function can take both parent_class and child_class. * static inline struct parent * * get_parent(VALUE v) * { * struct parent *p; * TypedData_Get_Struct(v, parent_type, struct parent, p); * return p; * } * ``` */ const rb_data_type_t *parent; /** * Type-specific static data. This area can be used for any purpose by a * programmer who define the type. Ruby does not manage this at all. */ void *data; /* This area can be used for any purpose by a programmer who define the type. */ /** * Type-specific behavioural characteristics. This is a bitfield. It is * an EXTREMELY WISE IDEA to leave this field blank. It is designed so * that setting zero is the safest thing to do. If you risk to set any * bits on, you have to know exactly what you are doing. * * @internal * * Why it has to be a ::VALUE? @shyouhei doesn't understand the design. */ VALUE flags; /* RUBY_FL_WB_PROTECTED */ }; /** * "Typed" user data. By using this, extension libraries can wrap a C struct * to make it visible from Ruby. For instance if you have a `struct timeval`, * and you want users to use it, * * ```CXX * static inline const rb_data_type_t timeval_type = { * // Note that unspecified fields are 0-filled by default. * .wrap_struct_name = "timeval", * .function = { * .dmark = nullptr, // no need to mark * .dfree = RUBY_TYPED_DEFAULT_FREE, // use ruby_xfree() * .dsize = [](auto) { * return sizeof(struct timeval); * }, * }, * }; * * extern "C" void * Init_timeval(void) * { * auto klass = rb_define_class("YourName", rb_cObject); * * rb_define_alloc_func(klass, [](auto klass) { * struct timeval *t; * auto ret = TypedData_Make_Struct( * klass, struct timeval, &timeval_type, t); * * if (auto i = gettimeofday(t, nullptr); i == -1) { * rb_sys_fail("gettimeofday(3)"); * } * else { * return ret; * } * }); * } * ``` */ struct RTypedData { /** The part that all ruby objects have in common. */ struct RBasic basic; /** * This field stores various information about how Ruby should handle a * data. This roughly resembles a Ruby level class (apart from method * definition etc.) */ const rb_data_type_t *const type; /** * This has to be always 1. * * @internal */ const VALUE typed_flag; /** Pointer to the actual C level struct that you want to wrap. */ void *data; }; RBIMPL_SYMBOL_EXPORT_BEGIN() RBIMPL_ATTR_NONNULL((3)) /** * This is the primitive way to wrap an existing C struct into ::RTypedData. * * @param[in] klass Ruby level class of the returning object. * @param[in] datap Pointer to the target C struct. * @param[in] type The characteristics of the passed data. * @exception rb_eTypeError `klass` is not a class. * @exception rb_eNoMemError Out of memory. * @return An allocated object that wraps `datap`. */ VALUE rb_data_typed_object_wrap(VALUE klass, void *datap, const rb_data_type_t *type); /** * Identical to rb_data_typed_object_wrap(), except it allocates a new data * region internally instead of taking an existing one. The allocation is done * using ruby_calloc(). Hence it makes no sense for `type->function.dfree` to * be anything other than ::RUBY_TYPED_DEFAULT_FREE. * * @param[in] klass Ruby level class of the returning object. * @param[in] size Requested size of memory to allocate. * @param[in] type The characteristics of the passed data. * @exception rb_eTypeError `klass` is not a class. * @exception rb_eNoMemError Out of memory. * @return An allocated object that wraps a new `size` byte region. */ VALUE rb_data_typed_object_zalloc(VALUE klass, size_t size, const rb_data_type_t *type); /** * Checks for the domestic relationship between the two. * * @param[in] child A data type supposed to be a child of `parent`. * @param[in] parent A data type supposed to be a parent of `child`. * @retval true `child` is a descendent of `parent`. * @retval false Otherwise. * * @internal * * You can path NULL to both arguments, don't know what that means though. */ int rb_typeddata_inherited_p(const rb_data_type_t *child, const rb_data_type_t *parent); /** * Checks if the given object is of given kind. * * @param[in] obj An instance of ::RTypedData. * @param[in] data_type Expected data type of `obj`. * @retval true `obj` is of `data_type`. * @retval false Otherwise. */ int rb_typeddata_is_kind_of(VALUE obj, const rb_data_type_t *data_type); /** * Identical to rb_typeddata_is_kind_of(), except it raises exceptions instead * of returning false. * * @param[in] obj An instance of ::RTypedData. * @param[in] data_type Expected data type of `obj`. * @exception rb_eTypeError obj is not of `data_type`. * @return Unwrapped C struct that `obj` holds. * @post Upon successful return `obj`'s type is guaranteed `data_type`. */ void *rb_check_typeddata(VALUE obj, const rb_data_type_t *data_type); RBIMPL_SYMBOL_EXPORT_END() /** * Converts sval, a pointer to your struct, into a Ruby object. * * @param klass A ruby level class. * @param data_type The type of `sval`. * @param sval A pointer to your struct. * @exception rb_eTypeError `klass` is not a class. * @exception rb_eNoMemError Out of memory. * @return A created Ruby object. */ #define TypedData_Wrap_Struct(klass,data_type,sval)\ rb_data_typed_object_wrap((klass),(sval),(data_type)) /** * @private * * This is an implementation detail of #TypedData_Make_Struct. People don't * use it directly. * * @param result Variable name of created Ruby object. * @param klass Ruby level class of the object. * @param type Type name of the C struct. * @param size Size of the C struct. * @param data_type The data type describing `type`. * @param sval Variable name of created C struct. */ #define TypedData_Make_Struct0(result, klass, type, size, data_type, sval) \ VALUE result = rb_data_typed_object_zalloc(klass, size, data_type); \ (sval) = (type *)RTYPEDDATA_GET_DATA(result); \ RBIMPL_CAST(/*suppress unused variable warnings*/(void)(sval)) /** * Identical to #TypedData_Wrap_Struct, except it allocates a new data region * internally instead of taking an existing one. The allocation is done using * ruby_calloc(). Hence it makes no sense for `data_type->function.dfree` to * be anything other than ::RUBY_TYPED_DEFAULT_FREE. * * @param klass Ruby level class of the object. * @param type Type name of the C struct. * @param data_type The data type describing `type`. * @param sval Variable name of created C struct. * @exception rb_eTypeError `klass` is not a class. * @exception rb_eNoMemError Out of memory. * @return A created Ruby object. */ #ifdef HAVE_STMT_AND_DECL_IN_EXPR #define TypedData_Make_Struct(klass, type, data_type, sval) \ RB_GNUC_EXTENSION({ \ TypedData_Make_Struct0( \ data_struct_obj, \ klass, \ type, \ sizeof(type), \ data_type, \ sval); \ data_struct_obj; \ }) #else #define TypedData_Make_Struct(klass, type, data_type, sval) \ rb_data_typed_object_make( \ (klass), \ (data_type), \ RBIMPL_CAST((void **)&(sval)), \ sizeof(type)) #endif /** * Obtains a C struct from inside of a wrapper Ruby object. * * @param obj An instance of ::RTypedData. * @param type Type name of the C struct. * @param data_type The data type describing `type`. * @param sval Variable name of obtained C struct. * @exception rb_eTypeError `obj` is not a kind of `data_type`. * @return Unwrapped C struct that `obj` holds. */ #define TypedData_Get_Struct(obj,type,data_type,sval) \ ((sval) = RBIMPL_CAST((type *)rb_check_typeddata((obj), (data_type)))) static inline bool RTYPEDDATA_EMBEDDED_P(VALUE obj) { #if RUBY_DEBUG if (RB_UNLIKELY(!RB_TYPE_P(obj, RUBY_T_DATA))) { Check_Type(obj, RUBY_T_DATA); RBIMPL_UNREACHABLE_RETURN(false); } #endif return RTYPEDDATA(obj)->typed_flag & TYPED_DATA_EMBEDDED; } static inline void * RTYPEDDATA_GET_DATA(VALUE obj) { #if RUBY_DEBUG if (RB_UNLIKELY(!RB_TYPE_P(obj, RUBY_T_DATA))) { Check_Type(obj, RUBY_T_DATA); RBIMPL_UNREACHABLE_RETURN(false); } #endif /* We reuse the data pointer in embedded TypedData. We can't use offsetof * since RTypedData a non-POD type in C++. */ const size_t embedded_typed_data_size = sizeof(struct RTypedData) - sizeof(void *); return RTYPEDDATA_EMBEDDED_P(obj) ? (char *)obj + embedded_typed_data_size : RTYPEDDATA(obj)->data; } RBIMPL_ATTR_PURE() RBIMPL_ATTR_ARTIFICIAL() /** * @private * * This is an implementation detail of Check_Type(). People don't use it * directly. * * @param[in] obj Object in question * @retval true `obj` is an instance of ::RTypedData. * @retval false `obj` is an instance of ::RData. * @pre `obj` must be a Ruby object of ::RUBY_T_DATA. */ static inline bool rbimpl_rtypeddata_p(VALUE obj) { VALUE typed_flag = RTYPEDDATA(obj)->typed_flag; return typed_flag != 0 && typed_flag <= 3; } RBIMPL_ATTR_PURE_UNLESS_DEBUG() RBIMPL_ATTR_ARTIFICIAL() /** * Checks whether the passed object is ::RTypedData or ::RData. * * @param[in] obj Object in question * @retval true `obj` is an instance of ::RTypedData. * @retval false `obj` is an instance of ::RData. * @pre `obj` must be a Ruby object of ::RUBY_T_DATA. */ static inline bool RTYPEDDATA_P(VALUE obj) { #if RUBY_DEBUG if (RB_UNLIKELY(! RB_TYPE_P(obj, RUBY_T_DATA))) { Check_Type(obj, RUBY_T_DATA); RBIMPL_UNREACHABLE_RETURN(false); } #endif return rbimpl_rtypeddata_p(obj); } RBIMPL_ATTR_PURE_UNLESS_DEBUG() RBIMPL_ATTR_ARTIFICIAL() /* :TODO: can this function be __attribute__((returns_nonnull)) or not? */ /** * Queries for the type of given object. * * @param[in] obj Object in question * @return Data type struct that corresponds to `obj`. * @pre `obj` must be an instance of ::RTypedData. */ static inline const struct rb_data_type_struct * RTYPEDDATA_TYPE(VALUE obj) { #if RUBY_DEBUG if (RB_UNLIKELY(! RTYPEDDATA_P(obj))) { rb_unexpected_type(obj, RUBY_T_DATA); RBIMPL_UNREACHABLE_RETURN(NULL); } #endif return RTYPEDDATA(obj)->type; } /** * While we don't stop you from using this function, it seems to be an * implementation detail of #TypedData_Make_Struct, which is preferred over * this one. * * @param[in] klass Ruby level class of the returning object. * @param[in] type The data type * @param[out] datap Return pointer. * @param[in] size Size of the C struct. * @exception rb_eTypeError `klass` is not a class. * @exception rb_eNoMemError Out of memory. * @return A created Ruby object. * @post `*datap` points to the C struct wrapped by the returned object. */ static inline VALUE rb_data_typed_object_make(VALUE klass, const rb_data_type_t *type, void **datap, size_t size) { TypedData_Make_Struct0(result, klass, void, size, type, *datap); return result; } RBIMPL_ATTR_DEPRECATED(("by: rb_data_typed_object_wrap")) /** @deprecated This function was renamed to rb_data_typed_object_wrap(). */ static inline VALUE rb_data_typed_object_alloc(VALUE klass, void *datap, const rb_data_type_t *type) { return rb_data_typed_object_wrap(klass, datap, type); } #endif /* RBIMPL_RTYPEDDATA_H */ include/ruby/internal/core/rfile.h 0000644 00000004126 15152150502 0013165 0 ustar 00 #ifndef RBIMPL_RFILE_H /*-*-C++-*-vi:se ft=cpp:*/ #define RBIMPL_RFILE_H /** * @file * @author Ruby developers <ruby-core@ruby-lang.org> * @copyright This file is a part of the programming language Ruby. * Permission is hereby granted, to either redistribute and/or * modify this file, provided that the conditions mentioned in the * file COPYING are met. Consult the file for details. * @warning Symbols prefixed with either `RBIMPL` or `rbimpl` are * implementation details. Don't take them as canon. They could * rapidly appear then vanish. The name (path) of this header file * is also an implementation detail. Do not expect it to persist * at the place it is now. Developers are free to move it anywhere * anytime at will. * @note To ruby-core: remember that this header can be possibly * recursively included from extension libraries written in C++. * Do not expect for instance `__VA_ARGS__` is always available. * We assume C99 for ruby itself but we don't assume languages of * extension libraries. They could be written in C++98. * @brief Defines struct ::RFile. */ #include "ruby/internal/core/rbasic.h" #include "ruby/internal/cast.h" /* rb_io_t is in ruby/io.h. The header file has historically not been included * into ruby/ruby.h. We follow that tradition. */ struct rb_io; /** * Ruby's File and IO. Ruby's IO are not just file descriptors. They have * buffers. They also have encodings. Various information are controlled * using this struct. */ struct RFile { /** Basic part, including flags and class. */ struct RBasic basic; /** IO's specific fields. */ struct rb_io *fptr; }; /** * Convenient casting macro. * * @param obj An object, which is in fact an ::RFile. * @return The passed object casted to ::RFile. */ #define RFILE(obj) RBIMPL_CAST((struct RFile *)(obj)) #endif /* RBIMPL_RFILE_H */ include/ruby/internal/symbol.h 0000644 00000031432 15152150502 0012441 0 ustar 00 #ifndef RBIMPL_SYMBOL_H /*-*-C++-*-vi:se ft=cpp:*/ #define RBIMPL_SYMBOL_H /** * @file * @author Ruby developers <ruby-core@ruby-lang.org> * @copyright This file is a part of the programming language Ruby. * Permission is hereby granted, to either redistribute and/or * modify this file, provided that the conditions mentioned in the * file COPYING are met. Consult the file for details. * @warning Symbols prefixed with either `RBIMPL` or `rbimpl` are * implementation details. Don't take them as canon. They could * rapidly appear then vanish. The name (path) of this header file * is also an implementation detail. Do not expect it to persist * at the place it is now. Developers are free to move it anywhere * anytime at will. * @note To ruby-core: remember that this header can be possibly * recursively included from extension libraries written in C++. * Do not expect for instance `__VA_ARGS__` is always available. * We assume C99 for ruby itself but we don't assume languages of * extension libraries. They could be written in C++98. * @brief Defines #rb_intern */ #include "ruby/internal/config.h" #ifdef STDC_HEADERS # include <stddef.h> #endif #ifdef HAVE_STRING_H # include <string.h> #endif #include "ruby/internal/attr/noalias.h" #include "ruby/internal/attr/nonnull.h" #include "ruby/internal/attr/pure.h" #include "ruby/internal/cast.h" #include "ruby/internal/constant_p.h" #include "ruby/internal/dllexport.h" #include "ruby/internal/has/builtin.h" #include "ruby/internal/value.h" #define RB_ID2SYM rb_id2sym /**< @alias{rb_id2sym} */ #define RB_SYM2ID rb_sym2id /**< @alias{rb_sym2id} */ #define ID2SYM RB_ID2SYM /**< @old{RB_ID2SYM} */ #define SYM2ID RB_SYM2ID /**< @old{RB_SYM2ID} */ #define CONST_ID_CACHE RUBY_CONST_ID_CACHE /**< @old{RUBY_CONST_ID_CACHE} */ #define CONST_ID RUBY_CONST_ID /**< @old{RUBY_CONST_ID} */ /** @cond INTERNAL_MACRO */ #define rb_intern_const rb_intern_const /** @endcond */ RBIMPL_SYMBOL_EXPORT_BEGIN() /** * Converts an instance of ::rb_cSymbol into an ::ID. * * @param[in] obj An instance of ::rb_cSymbol. * @exception rb_eTypeError `obj` is not an instance of ::rb_cSymbol. * @return An ::ID of the identical symbol. */ ID rb_sym2id(VALUE obj); /** * Allocates an instance of ::rb_cSymbol that has the given id. * * @param[in] id An id. * @retval RUBY_Qfalse No such id ever existed in the history. * @retval Otherwise An allocated ::rb_cSymbol instance. */ VALUE rb_id2sym(ID id); RBIMPL_ATTR_NONNULL(()) /** * Finds or creates a symbol of the given name. * * @param[in] name The name of the id. * @exception rb_eRuntimeError Too many symbols. * @return A (possibly new) id whose value is the given name. * @note These days Ruby internally has two kinds of symbols (static / * dynamic). Symbols created using this function would become a * static one; i.e. would never be garbage collected. It is up to * you to avoid memory leaks. Think twice before using it. */ ID rb_intern(const char *name); /** * Identical to rb_intern(), except it additionally takes the length of the * string. This way you can have a symbol that contains NUL characters. * * @param[in] name The name of the id. * @param[in] len Length of `name`. * @exception rb_eRuntimeError Too many symbols. * @return A (possibly new) id whose value is the given name. * @note These days Ruby internally has two kinds of symbols * (static/dynamic). Symbols created using this function would * become static ones; i.e. would never be garbage collected. It * is up to you to avoid memory leaks. Think twice before using * it. */ ID rb_intern2(const char *name, long len); /** * Identical to rb_intern(), except it takes an instance of ::rb_cString. * * @param[in] str The name of the id. * @pre `str` must either be an instance of ::rb_cSymbol, or an instance * of ::rb_cString, or responds to `#to_str` method. * @exception rb_eTypeError Can't convert `str` into ::rb_cString. * @exception rb_eRuntimeError Too many symbols. * @return A (possibly new) id whose value is the given str. * @note These days Ruby internally has two kinds of symbols * (static/dynamic). Symbols created using this function would * become static ones; i.e. would never be garbage collected. It * is up to you to avoid memory leaks. Think twice before using * it. */ ID rb_intern_str(VALUE str); /** * Retrieves the name mapped to the given id. * * @param[in] id An id to query. * @retval NULL No such id ever existed in the history. * @retval otherwise A name that the id represents. * @note The return value is managed by the interpreter. Don't pass it * to free(). */ const char *rb_id2name(ID id); RBIMPL_ATTR_NONNULL(()) /** * Detects if the given name is already interned or not. It first tries to * convert the argument to an instance of ::rb_cString if it is neither an * instance of ::rb_cString nor ::rb_cSymbol. The conversion result is written * back to the variable. Then queries if that name was already interned * before. If found it returns such id, otherwise zero. * * We eventually introduced this API to avoid inadvertent symbol pin-down. * Before, there was no way to know if an ID was already interned or not * without actually creating one (== leaking memory). By using this API you * can avoid such situations: * * ```CXX * bool does_interning_this_leak_memory(VALUE obj) * { * auto tmp = obj; * if (auto id = rb_check_id(&tmp); id) { * return false; * } * else { * return true; // Let GC sweep tmp if necessary. * } * } * ``` * * @param[in,out] namep A pointer to a name to query. * @pre The object referred by `*namep` must either be an instance * of ::rb_cSymbol, or an instance of ::rb_cString, or responds * to `#to_str` method. * @exception rb_eTypeError Can't convert `*namep` into ::rb_cString. * @exception rb_eEncodingError Given string is non-ASCII. * @retval 0 No such id ever existed in the history. * @retval otherwise The id that represents the given name. * @post The object that `*namep` points to is a converted result * object, which is always an instance of either ::rb_cSymbol * or ::rb_cString. * @see https://bugs.ruby-lang.org/issues/5072 * * @internal * * @shyouhei doesn't know why this has to raise rb_eEncodingError. */ ID rb_check_id(volatile VALUE *namep); /** * @copydoc rb_intern_str() * * @internal * * :FIXME: Can anyone tell us what is the difference between this one and * rb_intern_str()? As far as @shyouhei reads the implementation it seems what * rb_to_id() does is is just waste some CPU time, then call rb_intern_str(). * He hopes he is wrong. */ ID rb_to_id(VALUE str); /** * Identical to rb_id2name(), except it returns a Ruby's String instead of C's. * * @param[in] id An id to query. * @retval RUBY_Qfalse No such id ever existed in the history. * @retval otherwise An instance of ::rb_cString with the name of id. * * @internal * * In reality "rb_id2str() is identical to rb_id2name() except it returns Ruby * string" is just describing things upside down; truth is `rb_id2name(foo)` is * a shorthand of `RSTRING_PTR(rb_id2str(foo))`. */ VALUE rb_id2str(ID id); /** * Identical to rb_id2str(), except it takes an instance of ::rb_cSymbol rather * than an ::ID. * * @param[in] id An id to query. * @retval RUBY_Qfalse No such id ever existed in the history. * @retval otherwise An instance of ::rb_cString with the name of id. */ VALUE rb_sym2str(VALUE id); /** * Identical to rb_intern_str(), except it generates a dynamic symbol if * necessary. * * @param[in] name The name of the id. * @pre `name` must either be an instance of ::rb_cSymbol, or an * instance of ::rb_cString, or responds to `#to_str` method. * @exception rb_eTypeError Can't convert `name` into ::rb_cString. * @exception rb_eRuntimeError Too many symbols. * @return A (possibly new) id whose value is the given name. * @note These days Ruby internally has two kinds of symbols * (static/dynamic). Symbols created using this function would * become dynamic ones; i.e. would be garbage collected. It could * be safer for you to use it than alternatives, when applicable. */ VALUE rb_to_symbol(VALUE name); RBIMPL_ATTR_NONNULL(()) /** * Identical to rb_check_id(), except it returns an instance of ::rb_cSymbol * instead. * * @param[in,out] namep A pointer to a name to query. * @pre The object referred by `*namep` must either be an instance * of ::rb_cSymbol, or an instance of ::rb_cString, or responds * to `#to_str` method. * @exception rb_eTypeError Can't convert `*namep` into ::rb_cString. * @exception rb_eEncodingError Given string is non-ASCII. * @retval RUBY_Qnil No such id ever existed in the history. * @retval otherwise The id that represents the given name. * @post The object that `*namep` points to is a converted result * object, which is always an instance of either ::rb_cSymbol * or ::rb_cString. * @see https://bugs.ruby-lang.org/issues/5072 * * @internal * * @shyouhei doesn't know why this has to raise rb_eEncodingError. */ VALUE rb_check_symbol(volatile VALUE *namep); RBIMPL_SYMBOL_EXPORT_END() RBIMPL_ATTR_PURE() RBIMPL_ATTR_NONNULL(()) /** * This is a "tiny optimisation" over rb_intern(). If you pass a string * _literal_, and if your C compiler can special-case strlen of such literal to * strength-reduce into an integer constant expression, then this inline * function can precalc a part of conversion. * * @note This function also works happily for non-constant strings. Why * bother then? Just apply liberally to everything. * @note But #rb_intern() could be faster on compilers with statement * expressions, because they can cache the created ::ID. * @param[in] str The name of the id. * @exception rb_eRuntimeError Too many symbols. * @return A (possibly new) id whose value is the given str. * @note These days Ruby internally has two kinds of symbols (static / * dynamic). Symbols created using this function would become a * static one; i.e. would never be garbage collected. It is up to * you to avoid memory leaks. Think twice before using it. */ static inline ID rb_intern_const(const char *str) { size_t len = strlen(str); return rb_intern2(str, RBIMPL_CAST((long)len)); } RBIMPL_ATTR_NOALIAS() RBIMPL_ATTR_NONNULL(()) /** * @private * * This is an implementation detail of #rb_intern(). Just don't use it. */ static inline ID rbimpl_intern_const(ID *ptr, const char *str) { while (! *ptr) { *ptr = rb_intern_const(str); } return *ptr; } /** * Old implementation detail of rb_intern(). * @deprecated Does anyone use it? Preserved for backward compat. */ #define RUBY_CONST_ID_CACHE(result, str) \ { \ static ID rb_intern_id_cache; \ rbimpl_intern_const(&rb_intern_id_cache, (str)); \ result rb_intern_id_cache; \ } /** * Old implementation detail of rb_intern(). * @deprecated Does anyone use it? Preserved for backward compat. */ #define RUBY_CONST_ID(var, str) \ do { \ static ID rbimpl_id; \ (var) = rbimpl_intern_const(&rbimpl_id, (str)); \ } while (0) #if defined(HAVE_STMT_AND_DECL_IN_EXPR) /* __builtin_constant_p and statement expression is available * since gcc-2.7.2.3 at least. */ #define rb_intern(str) \ (RBIMPL_CONSTANT_P(str) ? \ __extension__ ({ \ static ID rbimpl_id; \ rbimpl_intern_const(&rbimpl_id, (str)); \ }) : \ (rb_intern)(str)) #endif #endif /* RBIMPL_SYMBOL_H */ include/ruby/internal/assume.h 0000644 00000006255 15152150502 0012436 0 ustar 00 #ifndef RBIMPL_ASSUME_H /*-*-C++-*-vi:se ft=cpp:*/ #define RBIMPL_ASSUME_H /** * @file * @author Ruby developers <ruby-core@ruby-lang.org> * @copyright This file is a part of the programming language Ruby. * Permission is hereby granted, to either redistribute and/or * modify this file, provided that the conditions mentioned in the * file COPYING are met. Consult the file for details. * @warning Symbols prefixed with either `RBIMPL` or `rbimpl` are * implementation details. Don't take them as canon. They could * rapidly appear then vanish. The name (path) of this header file * is also an implementation detail. Do not expect it to persist * at the place it is now. Developers are free to move it anywhere * anytime at will. * @note To ruby-core: remember that this header can be possibly * recursively included from extension libraries written in C++. * Do not expect for instance `__VA_ARGS__` is always available. * We assume C99 for ruby itself but we don't assume languages of * extension libraries. They could be written in C++98. * @brief Defines #RBIMPL_ASSUME / #RBIMPL_UNREACHABLE. * * These macros must be defined at once because: * * - #RBIMPL_ASSUME could fallback to #RBIMPL_UNREACHABLE. * - #RBIMPL_UNREACHABLE could fallback to #RBIMPL_ASSUME. */ #include "ruby/internal/config.h" #include "ruby/internal/cast.h" #include "ruby/internal/compiler_since.h" #include "ruby/internal/has/builtin.h" #include "ruby/internal/warning_push.h" /** @cond INTERNAL_MACRO */ #if defined(HAVE___ASSUME) # define RBIMPL_HAVE___ASSUME #endif /** @endcond */ /** Wraps (or simulates) `__builtin_unreachable`. */ #if RBIMPL_HAS_BUILTIN(__builtin_unreachable) # define RBIMPL_UNREACHABLE_RETURN(_) __builtin_unreachable() #elif defined(RBIMPL_HAVE___ASSUME) # define RBIMPL_UNREACHABLE_RETURN(_) return (__assume(0), (_)) #else # define RBIMPL_UNREACHABLE_RETURN(_) return (_) #endif /** Wraps (or simulates) `__builtin_unreachable`. */ #if RBIMPL_HAS_BUILTIN(__builtin_unreachable) # define RBIMPL_UNREACHABLE __builtin_unreachable #elif defined(RBIMPL_HAVE___ASSUME) # define RBIMPL_UNREACHABLE() __assume(0) #endif /** Wraps (or simulates) `__assume`. */ #if RBIMPL_COMPILER_SINCE(Intel, 13, 0, 0) # /* icc warnings are false positives. Ignore them. */ # /* "warning #2261: __assume expression with side effects discarded" */ # define RBIMPL_ASSUME(expr) \ RBIMPL_WARNING_PUSH() \ RBIMPL_WARNING_IGNORED(2261) \ __assume(expr) \ RBIMPL_WARNING_POP() #elif defined(RBIMPL_HAVE___ASSUME) # define RBIMPL_ASSUME __assume #elif RBIMPL_HAS_BUILTIN(__builtin_assume) # define RBIMPL_ASSUME __builtin_assume #elif ! defined(RBIMPL_UNREACHABLE) # define RBIMPL_ASSUME(_) RBIMPL_CAST((void)(_)) #else # define RBIMPL_ASSUME(_) \ (RB_LIKELY(!!(_)) ? RBIMPL_CAST((void)0) : RBIMPL_UNREACHABLE()) #endif #if ! defined(RBIMPL_UNREACHABLE) # define RBIMPL_UNREACHABLE() RBIMPL_ASSUME(0) #endif #endif /* RBIMPL_ASSUME_H */ include/ruby/internal/interpreter.h 0000644 00000022723 15152150502 0013502 0 ustar 00 #ifndef RBIMPL_INTERPRETER_H /*-*-C++-*-vi:se ft=cpp:*/ #define RBIMPL_INTERPRETER_H /** * @file * @author Ruby developers <ruby-core@ruby-lang.org> * @copyright This file is a part of the programming language Ruby. * Permission is hereby granted, to either redistribute and/or * modify this file, provided that the conditions mentioned in the * file COPYING are met. Consult the file for details. * @warning Symbols prefixed with either `RBIMPL` or `rbimpl` are * implementation details. Don't take them as canon. They could * rapidly appear then vanish. The name (path) of this header file * is also an implementation detail. Do not expect it to persist * at the place it is now. Developers are free to move it anywhere * anytime at will. * @note To ruby-core: remember that this header can be possibly * recursively included from extension libraries written in C++. * Do not expect for instance `__VA_ARGS__` is always available. * We assume C99 for ruby itself but we don't assume languages of * extension libraries. They could be written in C++98. * @brief Interpreter embedding APIs. */ #include "ruby/internal/attr/noreturn.h" #include "ruby/internal/attr/nonnull.h" #include "ruby/internal/dllexport.h" #include "ruby/internal/value.h" RBIMPL_SYMBOL_EXPORT_BEGIN() /** * @defgroup embed CRuby Embedding APIs * * CRuby interpreter APIs. These are APIs to embed MRI interpreter into your * program. * These functions are not a part of Ruby extension library API. * Extension libraries of Ruby should not depend on these functions. * * @{ */ /** * @defgroup ruby1 ruby(1) implementation * * A part of the implementation of ruby(1) command. * Other programs that embed Ruby interpreter do not always need to use these * functions. * * @{ */ RBIMPL_ATTR_NONNULL(()) /** * Initializes the process for libruby. * * This function assumes this process is `ruby(1)` and it has just started. * Usually programs that embed CRuby interpreter may not call this function, * and may do their own initialization. * * @param[in] argc Pointer to process main's `argc`. * @param[in] argv Pointer to process main's `argv`. * @warning `argc` and `argv` cannot be `NULL`. * * @internal * * AFAIK Ruby does write to argv, especially `argv[0][0]`, via setproctitle(3). * It is intentional that the argument is not const-qualified. */ void ruby_sysinit(int *argc, char ***argv); /** * Calls ruby_setup() and check error. * * Prints errors and calls exit(3) if an error occurred. */ void ruby_init(void); /** * Processes command line arguments and compiles the Ruby source to execute. * * This function does: * - Processes the given command line flags and arguments for `ruby(1)` * - Compiles the source code from the given argument, `-e` or `stdin`, and * - Returns the compiled source as an opaque pointer to an internal data * structure * * @param[in] argc Process main's `argc`. * @param[in] argv Process main's `argv`. * @return An opaque pointer to the compiled source or an internal special * value. Pass it to ruby_executable_node() to detect which. * @see ruby_executable_node */ void* ruby_options(int argc, char** argv); /** * Checks the return value of ruby_options(). * * ruby_options() sometimes returns a special value to indicate this process * should immediately exit. This function checks if the case. Also stores the * exit status that the caller have to pass to exit(3) into `*status`. * * @param[in] n A return value of ruby_options(). * @param[out] status Pointer to the exit status of this process. * @retval 0 The given value is such a special value. * @retval otherwise The given opaque pointer is actually a compiled * source. */ int ruby_executable_node(void *n, int *status); /** * Runs the given compiled source and exits this process. * * @param[in] n Opaque "node" pointer. * @retval EXIT_SUCCESS Successfully run the source. * @retval EXIT_FAILURE An error occurred. */ int ruby_run_node(void *n); /* version.c */ /** Prints the version information of the CRuby interpreter to stdout. */ void ruby_show_version(void); #ifndef ruby_show_copyright /** Prints the copyright notice of the CRuby interpreter to stdout. */ void ruby_show_copyright(void); #endif /** * A convenience macro to call ruby_init_stack(). * Must be placed just after variable declarations. */ #define RUBY_INIT_STACK \ VALUE variable_in_this_stack_frame; \ ruby_init_stack(&variable_in_this_stack_frame); /** @} */ /** * Set stack bottom of Ruby implementation. * * You must call this function before any heap allocation by Ruby * implementation. Or GC will break living objects. * * @param[in] addr A pointer somewhere on the stack, near its bottom. */ void ruby_init_stack(volatile VALUE *addr); /** * Initializes the VM and builtin libraries. * * @retval 0 Initialization succeeded. * @retval otherwise An error occurred. * * @internal * * Though not a part of our public API, the return value is in fact an enum * ruby_tag_type. You can see the potential "otherwise" values by looking at * vm_core.h. */ int ruby_setup(void); /** * Destructs the VM. * * Runs the VM finalization processes as well as ruby_finalize(), and frees * resources used by the VM. * * @param[in] ex Default value to the return value. * @retval EXIT_FAILURE An error occurred. * @retval ex Successful cleanup. * @note This function does not raise any exception. */ int ruby_cleanup(int ex); /** * Runs the VM finalization processes. * * `END{}` and procs registered by `Kernel.#at_exit` are executed here. See the * Ruby language spec for more details. * * @note This function is allowed to raise an exception if an error occurred. */ void ruby_finalize(void); RBIMPL_ATTR_NORETURN() /** Calls ruby_cleanup() and exits the process. */ void ruby_stop(int); /** * Checks for stack overflow. * * @retval true NG machine stack is about to overflow. * @retval false OK there still is a room in the stack. * * @internal * * Does anybody use it? So far @shyouhei have never seen any actual use-case. */ int ruby_stack_check(void); /** * Queries what Ruby thinks is the machine stack. Ruby manages a region of * memory. It calls that area the "machine stack". By calling this function, * in spite of its name, you can obtain both one end of the stack and its * length at once. Which means you can know the entire region. * * @param[out] topnotch On return the pointer points to the upmost address of * the macihne stack that Ruby knows. * @return Length of the machine stack that Ruby knows. * * @internal * * Does anybody use it? @shyouhei is quite skeptical if this is useful outside * of the VM. Maybe it was a wrong idea to expose this API to 3rd parties. */ size_t ruby_stack_length(VALUE **topnotch); /** * Identical to ruby_run_node(), except it returns an opaque execution status. * You can pass it to rb_cleanup(). * * @param[in] n Opaque "node" pointer. * @retval 0 Successful end-of-execution. * @retval otherwise An error occurred. * * @internal * * Though not a part of our public API, the return value is in fact an enum * ruby_tag_type. You can see the potential "otherwise" values by looking at * vm_core.h. */ int ruby_exec_node(void *n); /** * Sets the current script name to this value. * * This is similar to `$0 = name` in Ruby level but also affects * `Method#location` and others. * * @param[in] name File name to set. */ void ruby_script(const char* name); /** * Identical to ruby_script(), except it takes the name as a Ruby String * instance. * * @param[in] name File name to set. */ void ruby_set_script_name(VALUE name); /** Defines built-in variables */ void ruby_prog_init(void); /** * Sets argv that ruby understands. Your program might have its own command * line parameters etc. Handle them as you wish, and pass remaining parts of * argv here. * * @param[in] argc Number of elements of `argv`. * @param[in] argv Command line arguments. */ void ruby_set_argv(int argc, char **argv); /** * Identical to ruby_options(), except it raises ruby-level exceptions on * failure. * * @param[in] argc Process main's `argc`. * @param[in] argv Process main's `argv`. * @return An opaque "node" pointer. */ void *ruby_process_options(int argc, char **argv); /** * Sets up `$LOAD_PATH`. * * @internal * * @shyouhei guesses this has to be called at very later stage, at least after * the birth of object system. But is not exactly sure when. */ void ruby_init_loadpath(void); /** * Appends the given path to the end of the load path. * * @pre ruby_init_loadpath() must be done beforehand. * @param[in] path The path you want to push to the load path. */ void ruby_incpush(const char *path); /** * Clear signal handlers. * * Ruby installs its own signal handler (apart from those which user scripts * set). This is to clear that. Must be called when the ruby part terminates, * before switching to your program's own logic. */ void ruby_sig_finalize(void); /** @} */ RBIMPL_SYMBOL_EXPORT_END() #endif /* RBIMPL_INTERPRETER_H */ include/ruby/internal/memory.h 0000644 00000056053 15152150502 0012452 0 ustar 00 #ifndef RBIMPL_MEMORY_H /*-*-C++-*-vi:se ft=cpp:*/ #define RBIMPL_MEMORY_H /** * @file * @author Ruby developers <ruby-core@ruby-lang.org> * @copyright This file is a part of the programming language Ruby. * Permission is hereby granted, to either redistribute and/or * modify this file, provided that the conditions mentioned in the * file COPYING are met. Consult the file for details. * @warning Symbols prefixed with either `RBIMPL` or `rbimpl` are * implementation details. Don't take them as canon. They could * rapidly appear then vanish. The name (path) of this header file * is also an implementation detail. Do not expect it to persist * at the place it is now. Developers are free to move it anywhere * anytime at will. * @note To ruby-core: remember that this header can be possibly * recursively included from extension libraries written in C++. * Do not expect for instance `__VA_ARGS__` is always available. * We assume C99 for ruby itself but we don't assume languages of * extension libraries. They could be written in C++98. * @brief Memory management stuff. */ #include "ruby/internal/config.h" #ifdef STDC_HEADERS # include <stddef.h> #endif #ifdef HAVE_STRING_H # include <string.h> #endif #ifdef HAVE_STDINT_H # include <stdint.h> #endif #ifdef HAVE_ALLOCA_H # include <alloca.h> #endif #if defined(_MSC_VER) && defined(_WIN64) # include <intrin.h> # pragma intrinsic(_umul128) #endif #include "ruby/internal/attr/alloc_size.h" #include "ruby/internal/attr/const.h" #include "ruby/internal/attr/constexpr.h" #include "ruby/internal/attr/noalias.h" #include "ruby/internal/attr/nonnull.h" #include "ruby/internal/attr/noreturn.h" #include "ruby/internal/attr/restrict.h" #include "ruby/internal/attr/returns_nonnull.h" #include "ruby/internal/cast.h" #include "ruby/internal/dllexport.h" #include "ruby/internal/has/builtin.h" #include "ruby/internal/stdalign.h" #include "ruby/internal/stdbool.h" #include "ruby/internal/xmalloc.h" #include "ruby/backward/2/limits.h" #include "ruby/backward/2/long_long.h" #include "ruby/backward/2/assume.h" #include "ruby/defines.h" /** @cond INTERNAL_MACRO */ /* Make alloca work the best possible way. */ #if defined(alloca) # /* Take that. */ #elif RBIMPL_HAS_BUILTIN(__builtin_alloca) # define alloca __builtin_alloca #elif defined(_AIX) # pragma alloca #elif defined(__cplusplus) extern "C" void *alloca(size_t); #else extern void *alloca(); #endif /** @endcond */ #if defined(__DOXYGEN__) /** * @private * * Type that is as twice wider as size_t. This is an implementation detail of * rb_mul_size_overflow(). People should not use it. This is not a good name * either. */ typedef uint128_t DSIZE_T; #elif defined(HAVE_INT128_T) && SIZEOF_SIZE_T <= 8 # define DSIZE_T uint128_t #elif SIZEOF_SIZE_T * 2 <= SIZEOF_LONG_LONG # define DSIZE_T unsigned LONG_LONG #endif /** * @private * * Maximum possible number of bytes that #RB_ALLOCV can allocate using * `alloca`. Anything beyond this is allocated using rb_alloc_tmp_buffer(). * This selection is transparent to users. People don't have to bother. */ #ifdef C_ALLOCA # define RUBY_ALLOCV_LIMIT 0 #else # define RUBY_ALLOCV_LIMIT 1024 #endif /** * Prevents premature destruction of local objects. Ruby's garbage collector * is conservative; it scans the C level machine stack as well. Possible in- * use Ruby objects must remain visible on stack, to be properly marked as * such. However contemporary C compilers do not interface well with this. * Consider the following example: * * ```CXX * auto s = rb_str_new_cstr(" world"); * auto sptr = RSTRING_PTR(s); * auto t = rb_str_new_cstr("hello,"); // Possible GC invocation * auto u = rb_str_cat_cstr(t, sptr); * * RB_GC_GUARD(s); // ensure `s` (and thus `sptr`) do not get GC-ed * ``` * * Here, without the #RB_GC_GUARD, the last use of `s` is _before_ the last use * of `sptr`. Compilers could thus think `s` and `t` are allowed to overlap. * That would eliminate `s` from the stack, while `sptr` is still in use. If * our GC ran at that very moment, `s` gets swept out, which also destroys * `sptr`. Boom! You got a SEGV. * * In order to prevent this scenario #RB_GC_GUARD must be placed _after_ the * last use of `sptr`. Placing #RB_GC_GUARD before dereferencing `sptr` would * be of no use. * * #RB_GC_GUARD would not be necessary at all in the above example if non- * inlined function calls are made on the `s` variable after `sptr` is * dereferenced. Thus, in the above example, calling any un-inlined function * on `s` such as `rb_str_modify(s);` will ensure `s` stays on the stack or * register to prevent a GC invocation from prematurely freeing it. * * Using the #RB_GC_GUARD macro is preferable to using the `volatile` keyword * in C. #RB_GC_GUARD has the following advantages: * * - the intent of the macro use is clear. * * - #RB_GC_GUARD only affects its call site. OTOH `volatile` generates some * extra code every time the variable is used, hurting optimisation. * * - `volatile` implementations may be buggy/inconsistent in some compilers * and architectures. #RB_GC_GUARD is customisable for broken * systems/compilers without negatively affecting other systems. * * - C++ since C++20 deprecates `volatile`. If you write your extension * library in that language there is no escape but to use this macro. * * @param v A variable of ::VALUE type. * @post `v` is still alive. */ #ifdef __GNUC__ #define RB_GC_GUARD(v) \ (*__extension__ ({ \ volatile VALUE *rb_gc_guarded_ptr = &(v); \ __asm__("" : : "m"(rb_gc_guarded_ptr)); \ rb_gc_guarded_ptr; \ })) #elif defined _MSC_VER #define RB_GC_GUARD(v) (*rb_gc_guarded_ptr(&(v))) #else #define HAVE_RB_GC_GUARDED_PTR_VAL 1 #define RB_GC_GUARD(v) (*rb_gc_guarded_ptr_val(&(v),(v))) #endif /* Casts needed because void* is NOT compatible with others in C++. */ /** * Convenient macro that allocates an array of n elements. * * @param type Type of array elements. * @param n Length of the array. * @exception rb_eNoMemError No space left for allocation. * @exception rb_eArgError Integer overflow trying to calculate the length * of continuous memory region of `n` elements of * `type`. * @return Storage instance that is capable of storing at least `n` * elements of type `type`. * @note It doesn't return NULL, even when `n` is zero. * @warning The return value shall be invalidated exactly once by either * ruby_xfree(), ruby_xrealloc(), or ruby_xrealloc2(). It is a * failure to pass it to system free(), because the system and Ruby * might or might not share the same malloc() implementation. */ #define RB_ALLOC_N(type,n) RBIMPL_CAST((type *)ruby_xmalloc2((n), sizeof(type))) /** * Shorthand of #RB_ALLOC_N with `n=1`. * * @param type Type of allocation. * @exception rb_eNoMemError No space left for allocation. * @return Storage instance that can hold an `type` object. * @note It doesn't return NULL. * @warning The return value shall be invalidated exactly once by either * ruby_xfree(), ruby_xrealloc(), or ruby_xrealloc2(). It is a * failure to pass it to system free(), because the system and Ruby * might or might not share the same malloc() implementation. */ #define RB_ALLOC(type) RBIMPL_CAST((type *)ruby_xmalloc(sizeof(type))) /** * Identical to #RB_ALLOC_N() but also nullifies the allocated region before * returning. * * @param type Type of array elements. * @param n Length of the array. * @exception rb_eNoMemError No space left for allocation. * @exception rb_eArgError Integer overflow trying to calculate the length * of continuous memory region of `n` elements of * `type`. * @return Storage instance that is capable of storing at least `n` * elements of type `type`. * @post Returned array is filled with zeros. * @note It doesn't return NULL, even when `n` is zero. * @warning The return value shall be invalidated exactly once by either * ruby_xfree(), ruby_xrealloc(), or ruby_xrealloc2(). It is a * failure to pass it to system free(), because the system and Ruby * might or might not share the same malloc() implementation. */ #define RB_ZALLOC_N(type,n) RBIMPL_CAST((type *)ruby_xcalloc((n), sizeof(type))) /** * Shorthand of #RB_ZALLOC_N with `n=1`. * * @param type Type of allocation. * @exception rb_eNoMemError No space left for allocation. * @return Storage instance that can hold an `type` object. * @post Returned object is filled with zeros. * @note It doesn't return NULL. * @warning The return value shall be invalidated exactly once by either * ruby_xfree(), ruby_xrealloc(), or ruby_xrealloc2(). It is a * failure to pass it to system free(), because the system and Ruby * might or might not share the same malloc() implementation. */ #define RB_ZALLOC(type) (RB_ZALLOC_N(type, 1)) /** * Convenient macro that reallocates an array with a new size. * * @param var A variable of `type`, which points to a storage * instance that was previously returned from * either * - ruby_xmalloc(), * - ruby_xmalloc2(), * - ruby_xcalloc(), * - ruby_xrealloc(), or * - ruby_xrealloc2(). * @param type Type of allocation. * @param n Requested new size of each element. * @exception rb_eNoMemError No space left for allocation. * @exception rb_eArgError Integer overflow trying to calculate the length * of continuous memory region of `n` elements of * `type`. * @return Storage instance that is capable of storing at least `n` * elements of type `type`. * @pre The passed variable must point to a valid live storage instance. * It is a failure to pass a variable that holds an already-freed * pointer. * @note It doesn't return NULL, even when `n` is zero. * @warning Do not assume anything on the alignment of the return value. * There is no guarantee that it inherits the passed argument's * one. * @warning The return value shall be invalidated exactly once by either * ruby_xfree(), ruby_xrealloc(), or ruby_xrealloc2(). It is a * failure to pass it to system free(), because the system and Ruby * might or might not share the same malloc() implementation. */ #define RB_REALLOC_N(var,type,n) \ ((var) = RBIMPL_CAST((type *)ruby_xrealloc2((void *)(var), (n), sizeof(type)))) /** * @deprecated This macro is dangerous (does not bother stack overflow at * all). #RB_ALLOCV is the modern way to do the same thing. * @param type Type of array elements. * @param n Length of the array. * @return A pointer on stack. */ #define ALLOCA_N(type,n) \ RBIMPL_CAST((type *)alloca(rbimpl_size_mul_or_raise(sizeof(type), (n)))) /** * Identical to #RB_ALLOCV_N(), except that it allocates a number of bytes and * returns a void* . * * @param v A variable to hold the just-in-case opaque Ruby object. * @param n Size of allocation, in bytes. * @return A void pointer to `n` bytes storage. * @note `n` may be evaluated twice. */ #define RB_ALLOCV(v, n) \ ((n) < RUBY_ALLOCV_LIMIT ? \ ((v) = 0, alloca(n)) : \ rb_alloc_tmp_buffer(&(v), (n))) /** * Allocates a memory region, possibly on stack. If the given size exceeds * #RUBY_ALLOCV_LIMIT, it allocates a dedicated opaque ruby object instead and * let our GC sweep that region after use. Either way you can fire-and-forget. * * ```CXX * #include <sys/types.h> * * VALUE * foo(int n) * { * VALUE v; * auto ptr = RB_ALLOCV(struct tms, v, n); * ... * // no need to free `ptr`. * } * ``` * * If you want to be super-duper polite you can also explicitly state the end * of use of such memory region by calling #RB_ALLOCV_END(). * * @param type The type of array elements. * @param v A variable to hold the just-in-case opaque Ruby object. * @param n Number of elements requested to allocate. * @return An array of `n` elements of `type`. * @note `n` may be evaluated twice. */ #define RB_ALLOCV_N(type, v, n) \ RBIMPL_CAST((type *) \ (((size_t)(n) < RUBY_ALLOCV_LIMIT / sizeof(type)) ? \ ((v) = 0, alloca((n) * sizeof(type))) : \ rb_alloc_tmp_buffer2(&(v), (n), sizeof(type)))) /** * Polite way to declare that the given array is not used any longer. Calling * this not mandatory. Our GC can baby-sit you. However it is not a very bad * idea to use it when possible. Doing so could reduce memory footprint. * * @param v A variable previously passed to either #RB_ALLOCV/#RB_ALLOCV_N. */ #define RB_ALLOCV_END(v) rb_free_tmp_buffer(&(v)) /** * Handy macro to erase a region of memory. * * @param p Target pointer. * @param type Type of `p[0]` * @param n Length of `p`. * @return `p`. * @post First `n` elements of `p` are squashed. */ #define MEMZERO(p,type,n) memset((p), 0, rbimpl_size_mul_or_raise(sizeof(type), (n))) /** * Handy macro to call memcpy. * * @param p1 Destination pointer. * @param p2 Source pointer. * @param type Type of `p2[0]` * @param n Length of `p2`. * @return `p1`. * @post First `n` elements of `p2` are copied into `p1`. */ #define MEMCPY(p1,p2,type,n) ruby_nonempty_memcpy((p1), (p2), rbimpl_size_mul_or_raise(sizeof(type), (n))) /** * Handy macro to call memmove. * * @param p1 Destination pointer. * @param p2 Source pointer. * @param type Type of `p2[0]` * @param n Length of `p2`. * @return `p1`. * @post First `n` elements of `p2` are copied into `p1`. */ #define MEMMOVE(p1,p2,type,n) memmove((p1), (p2), rbimpl_size_mul_or_raise(sizeof(type), (n))) /** * Handy macro to call memcmp * * @param p1 Target LHS. * @param p2 Target RHS. * @param type Type of `p1[0]` * @param n Length of `p1`. * @retval <0 `p1` is "less" than `p2`. * @retval 0 `p1` is equal to `p2`. * @retval >0 `p1` is "greater" than `p2`. */ #define MEMCMP(p1,p2,type,n) memcmp((p1), (p2), rbimpl_size_mul_or_raise(sizeof(type), (n))) #define ALLOC_N RB_ALLOC_N /**< @old{RB_ALLOC_N} */ #define ALLOC RB_ALLOC /**< @old{RB_ALLOC} */ #define ZALLOC_N RB_ZALLOC_N /**< @old{RB_ZALLOC_N} */ #define ZALLOC RB_ZALLOC /**< @old{RB_ZALLOC} */ #define REALLOC_N RB_REALLOC_N /**< @old{RB_REALLOC_N} */ #define ALLOCV RB_ALLOCV /**< @old{RB_ALLOCV} */ #define ALLOCV_N RB_ALLOCV_N /**< @old{RB_ALLOCV_N} */ #define ALLOCV_END RB_ALLOCV_END /**< @old{RB_ALLOCV_END} */ /** * @private * * This is an implementation detail of rbimpl_size_mul_overflow(). * * @internal * * Expecting this struct to be eliminated by function inlinings. This is * nothing more than std::variant<std::size_t> if we could use recent C++, but * reality is we cannot. */ struct rbimpl_size_mul_overflow_tag { bool left; /**< Whether overflow happened or not. */ size_t right; /**< Multiplication result. */ }; RBIMPL_SYMBOL_EXPORT_BEGIN() RBIMPL_ATTR_RESTRICT() RBIMPL_ATTR_RETURNS_NONNULL() RBIMPL_ATTR_ALLOC_SIZE((2)) RBIMPL_ATTR_NONNULL(()) /** * @private * * This is an implementation detail of #RB_ALLOCV(). People don't use this * directly. * * @param[out] store Pointer to a variable. * @param[in] len Requested number of bytes to allocate. * @return Allocated `len` bytes array. * @post `store` holds the corresponding tmp buffer object. */ void *rb_alloc_tmp_buffer(volatile VALUE *store, long len); RBIMPL_ATTR_RESTRICT() RBIMPL_ATTR_RETURNS_NONNULL() RBIMPL_ATTR_ALLOC_SIZE((2,3)) RBIMPL_ATTR_NONNULL(()) /** * @private * * This is an implementation detail of #RB_ALLOCV_N(). People don't use this * directly. * * @param[out] store Pointer to a variable. * @param[in] len Requested number of bytes to allocate. * @param[in] count Number of elements in an array. * @return Allocated `len` bytes array. * @post `store` holds the corresponding tmp buffer object. * * @internal * * Although the meaning of `count` variable is clear, @shyouhei doesn't * understand its needs. */ void *rb_alloc_tmp_buffer_with_count(volatile VALUE *store, size_t len,size_t count); /** * @private * * This is an implementation detail of #RB_ALLOCV_END(). People don't use this * directly. * * @param[out] store Pointer to a variable. * @pre `store` is a NULL, or a pointer to a tmp buffer object. * @post `*store` is ::RUBY_Qfalse. * @post The object formerly stored in `store` is destroyed. */ void rb_free_tmp_buffer(volatile VALUE *store); RBIMPL_ATTR_NORETURN() /** * @private * * This is an implementation detail of #RB_ALLOCV_N(). People don't use this * directly. * * @param[in] x Arbitrary value. * @param[in] y Arbitrary value. * @exception rb_eArgError `x` * `y` would integer overflow. */ void ruby_malloc_size_overflow(size_t x, size_t y); #ifdef HAVE_RB_GC_GUARDED_PTR_VAL volatile VALUE *rb_gc_guarded_ptr_val(volatile VALUE *ptr, VALUE val); #endif RBIMPL_SYMBOL_EXPORT_END() #ifdef _MSC_VER # pragma optimize("", off) /** * @private * * This is an implementation detail of #RB_GC_GUARD(). People don't use this * directly. * * @param[in] ptr A pointer to an on-stack C variable. * @return `ptr` as-is. */ static inline volatile VALUE * rb_gc_guarded_ptr(volatile VALUE *ptr) { return ptr; } # pragma optimize("", on) #endif /** * @deprecated This function was an implementation detail of old * #RB_ALLOCV_N(). We no longer use it. @shyouhei suspects that * there are no actual usage now. However it was not marked as * private before. We cannot delete it any longer. * @param[in] a Arbitrary value. * @param[in] b Arbitrary value. * @param[in] max Possible maximum value. * @param[out] c A pointer to return the computation result. * @retval 1 `c` is insane. * @retval 0 `c` is sane. * @post `c` holds `a` * `b`, but could be overflowed. */ static inline int rb_mul_size_overflow(size_t a, size_t b, size_t max, size_t *c) { #ifdef DSIZE_T RB_GNUC_EXTENSION DSIZE_T da, db, c2; da = a; db = b; c2 = da * db; if (c2 > max) return 1; *c = RBIMPL_CAST((size_t)c2); #else if (b != 0 && a > max / b) return 1; *c = a * b; #endif return 0; } #if defined(__DOXYGEN__) RBIMPL_ATTR_CONSTEXPR(CXX14) #elif RBIMPL_COMPILER_SINCE(GCC, 7, 0, 0) RBIMPL_ATTR_CONSTEXPR(CXX14) /* https://gcc.gnu.org/bugzilla/show_bug.cgi?id=70507 */ #elif RBIMPL_COMPILER_SINCE(Clang, 7, 0, 0) RBIMPL_ATTR_CONSTEXPR(CXX14) /* https://bugs.llvm.org/show_bug.cgi?id=37633 */ #endif RBIMPL_ATTR_CONST() /** * @private * * This is an implementation detail of #RB_ALLOCV_N(). People don't use this * directly. * * @param[in] x Arbitrary value. * @param[in] y Arbitrary value. * @return `{ left, right }`, where `left` is whether there is an integer * overflow or not, and `right` is a (possibly overflowed) result * of `x` * `y`. * * @internal * * This is in fact also an implementation detail of ruby_xmalloc2() etc. */ static inline struct rbimpl_size_mul_overflow_tag rbimpl_size_mul_overflow(size_t x, size_t y) { struct rbimpl_size_mul_overflow_tag ret = { false, 0, }; #if RBIMPL_HAS_BUILTIN(__builtin_mul_overflow) ret.left = __builtin_mul_overflow(x, y, &ret.right); #elif defined(DSIZE_T) RB_GNUC_EXTENSION DSIZE_T dx = x; RB_GNUC_EXTENSION DSIZE_T dy = y; RB_GNUC_EXTENSION DSIZE_T dz = dx * dy; ret.left = dz > SIZE_MAX; ret.right = RBIMPL_CAST((size_t)dz); #elif defined(_MSC_VER) && defined(_WIN64) unsigned __int64 dp = 0; unsigned __int64 dz = _umul128(x, y, &dp); ret.left = RBIMPL_CAST((bool)dp); ret.right = RBIMPL_CAST((size_t)dz); #else /* https://wiki.sei.cmu.edu/confluence/display/c/INT30-C.+Ensure+that+unsigned+integer+operations+do+not+wrap */ ret.left = (y != 0) && (x > SIZE_MAX / y); ret.right = x * y; #endif return ret; } /** * @private * * This is an implementation detail of #RB_ALLOCV_N(). People don't use this * directly. * * @param[in] x Arbitrary value. * @param[in] y Arbitrary value. * @exception rb_eArgError Multiplication could integer overflow. * @return `x` * `y`. * * @internal * * This is in fact also an implementation detail of ruby_xmalloc2() etc. */ static inline size_t rbimpl_size_mul_or_raise(size_t x, size_t y) { struct rbimpl_size_mul_overflow_tag size = rbimpl_size_mul_overflow(x, y); if (RB_LIKELY(! size.left)) { return size.right; } else { ruby_malloc_size_overflow(x, y); RBIMPL_UNREACHABLE_RETURN(0); } } /** * This is an implementation detail of #RB_ALLOCV_N(). People don't use this * directly. * * @param[out] store Pointer to a variable. * @param[in] count Number of elements in an array. * @param[in] elsize Size of each elements. * @return Region of `count` * `elsize` bytes. * @post `store` holds the corresponding tmp buffer object. * * @internal * * We might want to deprecate this function and make a `rbimpl_` counterpart. */ static inline void * rb_alloc_tmp_buffer2(volatile VALUE *store, long count, size_t elsize) { const size_t total_size = rbimpl_size_mul_or_raise(count, elsize); const size_t cnt = (total_size + sizeof(VALUE) - 1) / sizeof(VALUE); return rb_alloc_tmp_buffer_with_count(store, total_size, cnt); } RBIMPL_SYMBOL_EXPORT_BEGIN() RBIMPL_ATTR_NOALIAS() RBIMPL_ATTR_NONNULL((1)) RBIMPL_ATTR_RETURNS_NONNULL() /* At least since 2004, glibc's <string.h> annotates memcpy to be * __attribute__((__nonnull__(1, 2))). However it is safe to pass NULL to the * source pointer, if n is 0. Let's wrap memcpy. */ static inline void * ruby_nonempty_memcpy(void *dest, const void *src, size_t n) { if (n) { return memcpy(dest, src, n); } else { return dest; } } RBIMPL_SYMBOL_EXPORT_END() #endif /* RBIMPL_MEMORY_H */ include/ruby/internal/cast.h 0000644 00000004432 15152150502 0012066 0 ustar 00 #ifndef RBIMPL_CAST_H /*-*-C++-*-vi:se ft=cpp:*/ #define RBIMPL_CAST_H /** * @author Ruby developers <ruby-core@ruby-lang.org> * @copyright This file is a part of the programming language Ruby. * Permission is hereby granted, to either redistribute and/or * modify this file, provided that the conditions mentioned in the * file COPYING are met. Consult the file for details. * @warning Symbols prefixed with either `RBIMPL` or `rbimpl` are * implementation details. Don't take them as canon. They could * rapidly appear then vanish. The name (path) of this header file * is also an implementation detail. Do not expect it to persist * at the place it is now. Developers are free to move it anywhere * anytime at will. * @note To ruby-core: remember that this header can be possibly * recursively included from extension libraries written in C++. * Do not expect for instance `__VA_ARGS__` is always available. * We assume C99 for ruby itself but we don't assume languages of * extension libraries. They could be written in C++98. * @brief Defines RBIMPL_CAST. * * This casting macro makes sense only inside of other macros that are part of * public headers. They could be used from C++, and C-style casts could issue * warnings. Ruby internals are pure C so they should not bother. */ #include "ruby/internal/compiler_since.h" #include "ruby/internal/has/warning.h" #include "ruby/internal/warning_push.h" #if ! defined(__cplusplus) # define RBIMPL_CAST(expr) (expr) #elif RBIMPL_COMPILER_SINCE(GCC, 4, 6, 0) # /* g++ has -Wold-style-cast since 1997 or so, but its _Pragma is broken. */ # /* See https://gcc.godbolt.org/z/XWhU6J */ # define RBIMPL_CAST(expr) (expr) # pragma GCC diagnostic ignored "-Wold-style-cast" #elif RBIMPL_HAS_WARNING("-Wold-style-cast") # define RBIMPL_CAST(expr) \ RBIMPL_WARNING_PUSH() \ RBIMPL_WARNING_IGNORED(-Wold-style-cast) \ (expr) \ RBIMPL_WARNING_POP() #else # define RBIMPL_CAST(expr) (expr) #endif #endif /* RBIMPL_CAST_H */ include/ruby/internal/fl_type.h 0000644 00000101104 15152150502 0012570 0 ustar 00 #ifndef RBIMPL_FL_TYPE_H /*-*-C++-*-vi:se ft=cpp:*/ #define RBIMPL_FL_TYPE_H /** * @file * @author Ruby developers <ruby-core@ruby-lang.org> * @copyright This file is a part of the programming language Ruby. * Permission is hereby granted, to either redistribute and/or * modify this file, provided that the conditions mentioned in the * file COPYING are met. Consult the file for details. * @warning Symbols prefixed with either `RBIMPL` or `rbimpl` are * implementation details. Don't take them as canon. They could * rapidly appear then vanish. The name (path) of this header file * is also an implementation detail. Do not expect it to persist * at the place it is now. Developers are free to move it anywhere * anytime at will. * @note To ruby-core: remember that this header can be possibly * recursively included from extension libraries written in C++. * Do not expect for instance `__VA_ARGS__` is always available. * We assume C99 for ruby itself but we don't assume languages of * extension libraries. They could be written in C++98. * @brief Defines enum ::ruby_fl_type. */ #include "ruby/internal/config.h" /* for ENUM_OVER_INT */ #include "ruby/internal/attr/artificial.h" #include "ruby/internal/attr/deprecated.h" #include "ruby/internal/attr/flag_enum.h" #include "ruby/internal/attr/forceinline.h" #include "ruby/internal/attr/noalias.h" #include "ruby/internal/attr/pure.h" #include "ruby/internal/cast.h" #include "ruby/internal/compiler_since.h" #include "ruby/internal/core/rbasic.h" #include "ruby/internal/dllexport.h" #include "ruby/internal/has/extension.h" #include "ruby/internal/special_consts.h" #include "ruby/internal/stdbool.h" #include "ruby/internal/value.h" #include "ruby/internal/value_type.h" #include "ruby/assert.h" #include "ruby/defines.h" /** @cond INTERNAL_MACRO */ #if RBIMPL_HAS_EXTENSION(enumerator_attributes) # define RBIMPL_HAVE_ENUM_ATTRIBUTE 1 #elif RBIMPL_COMPILER_SINCE(GCC, 6, 0, 0) # define RBIMPL_HAVE_ENUM_ATTRIBUTE 1 #endif #ifdef ENUM_OVER_INT # define RBIMPL_WIDER_ENUM 1 #elif SIZEOF_INT * CHAR_BIT > 12+19+1 # define RBIMPL_WIDER_ENUM 1 #else # define RBIMPL_WIDER_ENUM 0 #endif /** @endcond */ #define FL_SINGLETON RBIMPL_CAST((VALUE)RUBY_FL_SINGLETON) /**< @old{RUBY_FL_SINGLETON} */ #define FL_WB_PROTECTED RBIMPL_CAST((VALUE)RUBY_FL_WB_PROTECTED) /**< @old{RUBY_FL_WB_PROTECTED} */ #define FL_PROMOTED RBIMPL_CAST((VALUE)RUBY_FL_PROMOTED) /**< @old{RUBY_FL_PROMOTED} */ #define FL_FINALIZE RBIMPL_CAST((VALUE)RUBY_FL_FINALIZE) /**< @old{RUBY_FL_FINALIZE} */ #define FL_TAINT RBIMPL_CAST((VALUE)RUBY_FL_TAINT) /**< @old{RUBY_FL_TAINT} */ #define FL_SHAREABLE RBIMPL_CAST((VALUE)RUBY_FL_SHAREABLE) /**< @old{RUBY_FL_SHAREABLE} */ #define FL_UNTRUSTED RBIMPL_CAST((VALUE)RUBY_FL_UNTRUSTED) /**< @old{RUBY_FL_UNTRUSTED} */ #define FL_SEEN_OBJ_ID RBIMPL_CAST((VALUE)RUBY_FL_SEEN_OBJ_ID) /**< @old{RUBY_FL_SEEN_OBJ_ID} */ #define FL_EXIVAR RBIMPL_CAST((VALUE)RUBY_FL_EXIVAR) /**< @old{RUBY_FL_EXIVAR} */ #define FL_FREEZE RBIMPL_CAST((VALUE)RUBY_FL_FREEZE) /**< @old{RUBY_FL_FREEZE} */ #define FL_USHIFT RBIMPL_CAST((VALUE)RUBY_FL_USHIFT) /**< @old{RUBY_FL_USHIFT} */ #define FL_USER0 RBIMPL_CAST((VALUE)RUBY_FL_USER0) /**< @old{RUBY_FL_USER0} */ #define FL_USER1 RBIMPL_CAST((VALUE)RUBY_FL_USER1) /**< @old{RUBY_FL_USER1} */ #define FL_USER2 RBIMPL_CAST((VALUE)RUBY_FL_USER2) /**< @old{RUBY_FL_USER2} */ #define FL_USER3 RBIMPL_CAST((VALUE)RUBY_FL_USER3) /**< @old{RUBY_FL_USER3} */ #define FL_USER4 RBIMPL_CAST((VALUE)RUBY_FL_USER4) /**< @old{RUBY_FL_USER4} */ #define FL_USER5 RBIMPL_CAST((VALUE)RUBY_FL_USER5) /**< @old{RUBY_FL_USER5} */ #define FL_USER6 RBIMPL_CAST((VALUE)RUBY_FL_USER6) /**< @old{RUBY_FL_USER6} */ #define FL_USER7 RBIMPL_CAST((VALUE)RUBY_FL_USER7) /**< @old{RUBY_FL_USER7} */ #define FL_USER8 RBIMPL_CAST((VALUE)RUBY_FL_USER8) /**< @old{RUBY_FL_USER8} */ #define FL_USER9 RBIMPL_CAST((VALUE)RUBY_FL_USER9) /**< @old{RUBY_FL_USER9} */ #define FL_USER10 RBIMPL_CAST((VALUE)RUBY_FL_USER10) /**< @old{RUBY_FL_USER10} */ #define FL_USER11 RBIMPL_CAST((VALUE)RUBY_FL_USER11) /**< @old{RUBY_FL_USER11} */ #define FL_USER12 RBIMPL_CAST((VALUE)RUBY_FL_USER12) /**< @old{RUBY_FL_USER12} */ #define FL_USER13 RBIMPL_CAST((VALUE)RUBY_FL_USER13) /**< @old{RUBY_FL_USER13} */ #define FL_USER14 RBIMPL_CAST((VALUE)RUBY_FL_USER14) /**< @old{RUBY_FL_USER14} */ #define FL_USER15 RBIMPL_CAST((VALUE)RUBY_FL_USER15) /**< @old{RUBY_FL_USER15} */ #define FL_USER16 RBIMPL_CAST((VALUE)RUBY_FL_USER16) /**< @old{RUBY_FL_USER16} */ #define FL_USER17 RBIMPL_CAST((VALUE)RUBY_FL_USER17) /**< @old{RUBY_FL_USER17} */ #define FL_USER18 RBIMPL_CAST((VALUE)RUBY_FL_USER18) /**< @old{RUBY_FL_USER18} */ #define FL_USER19 RBIMPL_CAST((VALUE)(unsigned int)RUBY_FL_USER19) /**< @old{RUBY_FL_USER19} */ #define ELTS_SHARED RUBY_ELTS_SHARED /**< @old{RUBY_ELTS_SHARED} */ #define RB_OBJ_FREEZE rb_obj_freeze_inline /**< @alias{rb_obj_freeze_inline} */ /** @cond INTERNAL_MACRO */ #define RUBY_ELTS_SHARED RUBY_ELTS_SHARED #define RB_FL_ABLE RB_FL_ABLE #define RB_FL_ALL RB_FL_ALL #define RB_FL_ALL_RAW RB_FL_ALL_RAW #define RB_FL_ANY RB_FL_ANY #define RB_FL_ANY_RAW RB_FL_ANY_RAW #define RB_FL_REVERSE RB_FL_REVERSE #define RB_FL_REVERSE_RAW RB_FL_REVERSE_RAW #define RB_FL_SET RB_FL_SET #define RB_FL_SET_RAW RB_FL_SET_RAW #define RB_FL_TEST RB_FL_TEST #define RB_FL_TEST_RAW RB_FL_TEST_RAW #define RB_FL_UNSET RB_FL_UNSET #define RB_FL_UNSET_RAW RB_FL_UNSET_RAW #define RB_OBJ_FREEZE_RAW RB_OBJ_FREEZE_RAW #define RB_OBJ_FROZEN RB_OBJ_FROZEN #define RB_OBJ_FROZEN_RAW RB_OBJ_FROZEN_RAW #define RB_OBJ_UNTRUST RB_OBJ_TAINT #define RB_OBJ_UNTRUSTED RB_OBJ_TAINTED /** @endcond */ /** * @defgroup deprecated_macros Deprecated macro APIs * @{ * These macros are deprecated. Prefer their `RB_`-prefixed versions. */ #define FL_ABLE RB_FL_ABLE /**< @old{RB_FL_ABLE} */ #define FL_ALL RB_FL_ALL /**< @old{RB_FL_ALL} */ #define FL_ALL_RAW RB_FL_ALL_RAW /**< @old{RB_FL_ALL_RAW} */ #define FL_ANY RB_FL_ANY /**< @old{RB_FL_ANY} */ #define FL_ANY_RAW RB_FL_ANY_RAW /**< @old{RB_FL_ANY_RAW} */ #define FL_REVERSE RB_FL_REVERSE /**< @old{RB_FL_REVERSE} */ #define FL_REVERSE_RAW RB_FL_REVERSE_RAW /**< @old{RB_FL_REVERSE_RAW} */ #define FL_SET RB_FL_SET /**< @old{RB_FL_SET} */ #define FL_SET_RAW RB_FL_SET_RAW /**< @old{RB_FL_SET_RAW} */ #define FL_TEST RB_FL_TEST /**< @old{RB_FL_TEST} */ #define FL_TEST_RAW RB_FL_TEST_RAW /**< @old{RB_FL_TEST_RAW} */ #define FL_UNSET RB_FL_UNSET /**< @old{RB_FL_UNSET} */ #define FL_UNSET_RAW RB_FL_UNSET_RAW /**< @old{RB_FL_UNSET_RAW} */ #define OBJ_FREEZE RB_OBJ_FREEZE /**< @old{RB_OBJ_FREEZE} */ #define OBJ_FREEZE_RAW RB_OBJ_FREEZE_RAW /**< @old{RB_OBJ_FREEZE_RAW} */ #define OBJ_FROZEN RB_OBJ_FROZEN /**< @old{RB_OBJ_FROZEN} */ #define OBJ_FROZEN_RAW RB_OBJ_FROZEN_RAW /**< @old{RB_OBJ_FROZEN_RAW} */ #define OBJ_INFECT RB_OBJ_INFECT /**< @old{RB_OBJ_INFECT} */ #define OBJ_INFECT_RAW RB_OBJ_INFECT_RAW /**< @old{RB_OBJ_INFECT_RAW} */ #define OBJ_TAINT RB_OBJ_TAINT /**< @old{RB_OBJ_TAINT} */ #define OBJ_TAINTABLE RB_OBJ_TAINTABLE /**< @old{RB_OBJ_TAINT_RAW} */ #define OBJ_TAINTED RB_OBJ_TAINTED /**< @old{RB_OBJ_TAINTED} */ #define OBJ_TAINTED_RAW RB_OBJ_TAINTED_RAW /**< @old{RB_OBJ_TAINTED_RAW} */ #define OBJ_TAINT_RAW RB_OBJ_TAINT_RAW /**< @old{RB_OBJ_TAINT_RAW} */ #define OBJ_UNTRUST RB_OBJ_UNTRUST /**< @old{RB_OBJ_TAINT} */ #define OBJ_UNTRUSTED RB_OBJ_UNTRUSTED /**< @old{RB_OBJ_TAINTED} */ /** @} */ /** * This is an enum because GDB wants it (rather than a macro). People need not * bother. */ enum ruby_fl_ushift { /** * Number of bits in ::ruby_fl_type that are _not_ open to users. This is * an implementation detail. Please ignore. */ RUBY_FL_USHIFT = 12 }; /* > The expression that defines the value of an enumeration constant shall be * > an integer constant expression that has a value representable as an `int`. * * -- ISO/IEC 9899:2018 section 6.7.2.2 * * So ENUM_OVER_INT situation is an extension to the standard. Note however * that we do not support 16 bit `int` environment. */ RB_GNUC_EXTENSION /** * The flags. Each ruby objects have their own characteristics apart from * their classes. For instance whether an object is frozen or not is not * controlled by its class. This is the type that represents such properties. * * @note About the `FL_USER` terminology: the "user" here does not necessarily * mean only you. For instance struct ::RString instances use these * bits to cache their encodings etc. Devs discussed about this topic, * reached their consensus that ::RUBY_T_DATA is the only valid data * structure that can use these bits; other data structures including * ::RUBY_T_OBJECT use these bits for their own purpose. See also * https://bugs.ruby-lang.org/issues/18059 */ enum RBIMPL_ATTR_FLAG_ENUM() ruby_fl_type { /** * @deprecated This flag once was a thing back in the old days, but makes * no sense any longer today. Exists here for backwards * compatibility only. You can safely forget about it. * * @internal * * The reality is our GC no longer remembers write barriers inside of each * objects, to use dedicated bitmap instead. But this flag is still used * internally. The current usages of this flag should be something * different, which is unclear to @shyouhei. */ RUBY_FL_WB_PROTECTED = (1<<5), /** * Ruby objects are "generational". There are young objects & old objects. * Young objects are prone to die & monitored relatively extensively by the * garbage collector. Old objects tend to live longer & are monitored less * frequently. When an object survives a GC, its age is incremented. When * age is equal to RVALUE_OLD_AGE, the object becomes Old. This flag is set * when an object becomes old, and is used by the write barrier to check if * an old object should be considered for marking more frequently - as old * objects that have references added between major GCs need to be remarked * to prevent the referred object being mistakenly swept. * * @internal * * But honestly, @shyouhei doesn't think this flag should be visible from * 3rd parties. It must be an implementation detail that they should never * know. Might better be hidden. */ RUBY_FL_PROMOTED = (1<<5), /** * This flag is no longer in use * * @internal */ RUBY_FL_UNUSED6 = (1<<6), /** * This flag has something to do with finalisers. A ruby object can have * its finaliser, which is another object that evaluates when the target * object is about to die. This flag is used to denote that there is an * attached finaliser. * * @internal * * But honestly, @shyouhei doesn't think this flag should be visible from * 3rd parties. It must be an implementation detail that they should never * know. Might better be hidden. */ RUBY_FL_FINALIZE = (1<<7), /** * @deprecated This flag once was a thing back in the old days, but makes * no sense any longer today. Exists here for backwards * compatibility only. You can safely forget about it. */ RUBY_FL_TAINT #if defined(RBIMPL_HAVE_ENUM_ATTRIBUTE) RBIMPL_ATTR_DEPRECATED(("taintedness turned out to be a wrong idea.")) #elif defined(_MSC_VER) # pragma deprecated(RUBY_FL_TAINT) #endif = 0, /** * This flag has something to do with Ractor. Multiple Ractors run without * protecting each other. Sharing an object among Ractors are basically * dangerous, disabled by default. This flag is used to bypass that * restriction. Of course, you have to manually prevent race conditions * then. * * This flag needs deep understanding of multithreaded programming. You * would better not use it. */ RUBY_FL_SHAREABLE = (1<<8), /** * @deprecated This flag once was a thing back in the old days, but makes * no sense any longer today. Exists here for backwards * compatibility only. You can safely forget about it. */ RUBY_FL_UNTRUSTED #if defined(RBIMPL_HAVE_ENUM_ATTRIBUTE) RBIMPL_ATTR_DEPRECATED(("trustedness turned out to be a wrong idea.")) #elif defined(_MSC_VER) # pragma deprecated(RUBY_FL_UNTRUSTED) #endif = 0, /** * This flag has something to do with object IDs. Unlike in the old days, * an object's object ID (that a user can query using `Object#object_id`) * is no longer its physical address represented using Ruby level integers. * It is now a monotonic-increasing integer unrelated to the underlying * memory arrangement. Object IDs are assigned when necessary; objects are * born without one, and will eventually have such property when queried. * The interpreter has to manage which one is which. This is the flag that * helps the management. Objects with this flag set are the ones with * object IDs assigned. * * @internal * * But honestly, @shyouhei doesn't think this flag should be visible from * 3rd parties. It must be an implementation detail that they should never * know. Might better be hidden. */ RUBY_FL_SEEN_OBJ_ID = (1<<9), /** * This flag has something to do with instance variables. 3rd parties need * not know, but there are several ways to store an object's instance * variables. Objects with this flag use so-called "generic" backend * storage. This distinction is purely an implementation detail. People * need not be aware of this working behind-the-scene. * * @internal * * As of writing everything except ::RObject and RModule use this scheme. */ RUBY_FL_EXIVAR = (1<<10), /** * This flag has something to do with data immutability. When this flag is * set an object is considered "frozen". No modification are expected to * happen beyond that point for the particular object. Immutability is * basically considered to be a good property these days. Library authors * are expected to obey. Test this bit before you touch a data structure. * * @see rb_check_frozen() */ RUBY_FL_FREEZE = (1<<11), /** (@shyouhei doesn't know how to excude this macro from doxygen). */ #define RBIMPL_FL_USER_N(n) RUBY_FL_USER##n = (1<<(RUBY_FL_USHIFT+n)) RBIMPL_FL_USER_N(0), /**< User-defined flag. */ RBIMPL_FL_USER_N(1), /**< User-defined flag. */ RBIMPL_FL_USER_N(2), /**< User-defined flag. */ RBIMPL_FL_USER_N(3), /**< User-defined flag. */ RBIMPL_FL_USER_N(4), /**< User-defined flag. */ RBIMPL_FL_USER_N(5), /**< User-defined flag. */ RBIMPL_FL_USER_N(6), /**< User-defined flag. */ RBIMPL_FL_USER_N(7), /**< User-defined flag. */ RBIMPL_FL_USER_N(8), /**< User-defined flag. */ RBIMPL_FL_USER_N(9), /**< User-defined flag. */ RBIMPL_FL_USER_N(10), /**< User-defined flag. */ RBIMPL_FL_USER_N(11), /**< User-defined flag. */ RBIMPL_FL_USER_N(12), /**< User-defined flag. */ RBIMPL_FL_USER_N(13), /**< User-defined flag. */ RBIMPL_FL_USER_N(14), /**< User-defined flag. */ RBIMPL_FL_USER_N(15), /**< User-defined flag. */ RBIMPL_FL_USER_N(16), /**< User-defined flag. */ RBIMPL_FL_USER_N(17), /**< User-defined flag. */ RBIMPL_FL_USER_N(18), /**< User-defined flag. */ #ifdef ENUM_OVER_INT RBIMPL_FL_USER_N(19), /**< User-defined flag. */ #else # define RUBY_FL_USER19 (RBIMPL_VALUE_ONE<<(RUBY_FL_USHIFT+19)) #endif #undef RBIMPL_FL_USER_N #undef RBIMPL_WIDER_ENUM /** * This flag has something to do with data structures. Over time, ruby * evolved to reduce memory footprints. One of such attempt is so-called * copy-on-write, which delays duplication of resources until ultimately * necessary. Some data structures share this scheme. For example * multiple instances of struct ::RArray could point identical memory * region in common, as long as they don't differ. As people favour * immutable style of programming than before, this situation is getting * more and more common. Because such "shared" memory regions have nuanced * ownership by nature, each structures need special care for them. This * flag is used to distinguish such shared constructs. * * @internal * * But honestly, @shyouhei doesn't think this flag should be visible from * 3rd parties. It must be an implementation detail that they should never * know. Might better be hidden. */ RUBY_ELTS_SHARED = RUBY_FL_USER2, /** * This flag has something to do with an object's class. There are kind of * classes called "singleton class", each of which have exactly one * instance. What is interesting about singleton classes is that they are * created _after_ their instance were instantiated, like this: * * ```ruby * foo = Object.new # foo is an instance of Object... * bar = foo.singleton_class # foo is now an instance of bar. * ``` * * Here as you see `bar` is a singleton class of `foo`, which is injected * into `foo`'s inheritance tree in a different statement (== distinct * sequence point). In order to achieve this property singleton classes * are special-cased in the interpreter. There is one bit flag that * distinguishes if a class is a singleton class or not, and this is it. * * @internal * * But honestly, @shyouhei doesn't think this flag should be visible from * 3rd parties. It must be an implementation detail that they should never * know. Might better be hidden. */ RUBY_FL_SINGLETON = RUBY_FL_USER0, }; enum { /** * @deprecated This flag once was a thing back in the old days, but makes * no sense any longer today. Exists here for backwards * compatibility only. You can safely forget about it. */ RUBY_FL_DUPPED #if defined(RBIMPL_HAVE_ENUM_ATTRIBUTE) RBIMPL_ATTR_DEPRECATED(("It seems there is no actual usage of this enum.")) #elif defined(_MSC_VER) # pragma deprecated(RUBY_FL_DUPPED) #endif = (int)RUBY_T_MASK | (int)RUBY_FL_EXIVAR }; #undef RBIMPL_HAVE_ENUM_ATTRIBUTE RBIMPL_SYMBOL_EXPORT_BEGIN() /** * This is an implementation detail of #RB_OBJ_FREEZE(). People don't use it * directly. * * @param[out] klass A singleton class. * @post `klass` gets frozen. */ void rb_freeze_singleton_class(VALUE klass); RBIMPL_SYMBOL_EXPORT_END() RBIMPL_ATTR_PURE_UNLESS_DEBUG() RBIMPL_ATTR_ARTIFICIAL() RBIMPL_ATTR_FORCEINLINE() /** * Checks if the object is flaggable. There are some special cases (most * notably ::RUBY_Qfalse) where appending a flag to an object is not possible. * This function can detect that. * * @param[in] obj Object in question * @retval true It is flaggable. * @retval false No it isn't. */ static bool RB_FL_ABLE(VALUE obj) { if (RB_SPECIAL_CONST_P(obj)) { return false; } else if (RB_TYPE_P(obj, RUBY_T_NODE)) { return false; } else { return true; } } RBIMPL_ATTR_PURE_UNLESS_DEBUG() RBIMPL_ATTR_ARTIFICIAL() /** * This is an implementation detail of RB_FL_TEST(). 3rd parties need not use * this. Just always use RB_FL_TEST(). * * @param[in] obj Object in question. * @param[in] flags A set of enum ::ruby_fl_type. * @pre The object must not be an enum ::ruby_special_consts. * @return `obj`'s flags, masked by `flags`. */ static inline VALUE RB_FL_TEST_RAW(VALUE obj, VALUE flags) { RBIMPL_ASSERT_OR_ASSUME(RB_FL_ABLE(obj)); return RBASIC(obj)->flags & flags; } RBIMPL_ATTR_PURE_UNLESS_DEBUG() RBIMPL_ATTR_ARTIFICIAL() /** * Tests if the given flag(s) are set or not. You can pass multiple flags at * once: * * ```CXX * auto obj = rb_eval_string("..."); * if (RB_FL_TEST(obj, RUBY_FL_FREEZE | RUBY_FL_SHAREABLE)) { * printf("Ractor ready!\n"); * } * ``` * * @param[in] obj Object in question. * @param[in] flags A set of enum ::ruby_fl_type. * @return `obj`'s flags, masked by `flags`. * @note It is intentional for this function to return ::VALUE. The * return value could be passed to RB_FL_STE() etc. */ static inline VALUE RB_FL_TEST(VALUE obj, VALUE flags) { if (RB_FL_ABLE(obj)) { return RB_FL_TEST_RAW(obj, flags); } else { return RBIMPL_VALUE_NULL; } } RBIMPL_ATTR_PURE_UNLESS_DEBUG() RBIMPL_ATTR_ARTIFICIAL() /** * This is an implementation detail of RB_FL_ANY(). 3rd parties need not use * this. Just always use RB_FL_ANY(). * * @param[in] obj Object in question. * @param[in] flags A set of enum ::ruby_fl_type. * @retval true The object has any of the flags set. * @retval false No it doesn't at all. * @pre The object must not be an enum ::ruby_special_consts. */ static inline bool RB_FL_ANY_RAW(VALUE obj, VALUE flags) { return RB_FL_TEST_RAW(obj, flags); } RBIMPL_ATTR_PURE_UNLESS_DEBUG() RBIMPL_ATTR_ARTIFICIAL() /** * Identical to RB_FL_TEST(), except it returns bool. * * @param[in] obj Object in question. * @param[in] flags A set of enum ::ruby_fl_type. * @retval true The object has any of the flags set. * @retval false No it doesn't at all. */ static inline bool RB_FL_ANY(VALUE obj, VALUE flags) { return RB_FL_TEST(obj, flags); } RBIMPL_ATTR_PURE_UNLESS_DEBUG() RBIMPL_ATTR_ARTIFICIAL() /** * This is an implementation detail of RB_FL_ALL(). 3rd parties need not use * this. Just always use RB_FL_ALL(). * * @param[in] obj Object in question. * @param[in] flags A set of enum ::ruby_fl_type. * @retval true The object has all of the flags set. * @retval false The object lacks any of the flags. * @pre The object must not be an enum ::ruby_special_consts. */ static inline bool RB_FL_ALL_RAW(VALUE obj, VALUE flags) { return RB_FL_TEST_RAW(obj, flags) == flags; } RBIMPL_ATTR_PURE_UNLESS_DEBUG() RBIMPL_ATTR_ARTIFICIAL() /** * Identical to RB_FL_ANY(), except it mandates all passed flags be set. * * @param[in] obj Object in question. * @param[in] flags A set of enum ::ruby_fl_type. * @retval true The object has all of the flags set. * @retval false The object lacks any of the flags. */ static inline bool RB_FL_ALL(VALUE obj, VALUE flags) { return RB_FL_TEST(obj, flags) == flags; } RBIMPL_ATTR_NOALIAS() RBIMPL_ATTR_ARTIFICIAL() /** * @private * * This is an implementation detail of RB_FL_SET(). 3rd parties need not use * this. Just always use RB_FL_SET(). * * @param[out] obj Object in question. * @param[in] flags A set of enum ::ruby_fl_type. * @post `obj` has `flags` set. * * @internal * * This is function is here to annotate a part of RB_FL_SET_RAW() as * `__declspec(noalias)`. */ static inline void rbimpl_fl_set_raw_raw(struct RBasic *obj, VALUE flags) { obj->flags |= flags; } RBIMPL_ATTR_ARTIFICIAL() /** * This is an implementation detail of RB_FL_SET(). 3rd parties need not use * this. Just always use RB_FL_SET(). * * @param[out] obj Object in question. * @param[in] flags A set of enum ::ruby_fl_type. * @post `obj` has `flags` set. */ static inline void RB_FL_SET_RAW(VALUE obj, VALUE flags) { RBIMPL_ASSERT_OR_ASSUME(RB_FL_ABLE(obj)); rbimpl_fl_set_raw_raw(RBASIC(obj), flags); } RBIMPL_ATTR_ARTIFICIAL() /** * Sets the given flag(s). * * ```CXX * auto v = rb_eval_string("..."); * RB_FL_SET(v, RUBY_FL_FREEZE); * ``` * * @param[out] obj Object in question. * @param[in] flags A set of enum ::ruby_fl_type. * @post `obj` has `flags` set. */ static inline void RB_FL_SET(VALUE obj, VALUE flags) { if (RB_FL_ABLE(obj)) { RB_FL_SET_RAW(obj, flags); } } RBIMPL_ATTR_NOALIAS() RBIMPL_ATTR_ARTIFICIAL() /** * @private * * This is an implementation detail of RB_FL_UNSET(). 3rd parties need not use * this. Just always use RB_FL_UNSET(). * * @param[out] obj Object in question. * @param[in] flags A set of enum ::ruby_fl_type. * @post `obj` has `flags` cleared. * * @internal * * This is function is here to annotate a part of RB_FL_UNSET_RAW() as * `__declspec(noalias)`. */ static inline void rbimpl_fl_unset_raw_raw(struct RBasic *obj, VALUE flags) { obj->flags &= ~flags; } RBIMPL_ATTR_ARTIFICIAL() /** * This is an implementation detail of RB_FL_UNSET(). 3rd parties need not use * this. Just always use RB_FL_UNSET(). * * @param[out] obj Object in question. * @param[in] flags A set of enum ::ruby_fl_type. * @post `obj` has `flags` cleared. */ static inline void RB_FL_UNSET_RAW(VALUE obj, VALUE flags) { RBIMPL_ASSERT_OR_ASSUME(RB_FL_ABLE(obj)); rbimpl_fl_unset_raw_raw(RBASIC(obj), flags); } RBIMPL_ATTR_ARTIFICIAL() /** * Clears the given flag(s). * * @param[out] obj Object in question. * @param[in] flags A set of enum ::ruby_fl_type. * @post `obj` has `flags` cleard. */ static inline void RB_FL_UNSET(VALUE obj, VALUE flags) { if (RB_FL_ABLE(obj)) { RB_FL_UNSET_RAW(obj, flags); } } RBIMPL_ATTR_NOALIAS() RBIMPL_ATTR_ARTIFICIAL() /** * @private * * This is an implementation detail of RB_FL_REVERSE(). 3rd parties need not * use this. Just always use RB_FL_REVERSE(). * * @param[out] obj Object in question. * @param[in] flags A set of enum ::ruby_fl_type. * @post `obj` has `flags` reversed. * * @internal * * This is function is here to annotate a part of RB_FL_REVERSE_RAW() as * `__declspec(noalias)`. */ static inline void rbimpl_fl_reverse_raw_raw(struct RBasic *obj, VALUE flags) { obj->flags ^= flags; } RBIMPL_ATTR_ARTIFICIAL() /** * This is an implementation detail of RB_FL_REVERSE(). 3rd parties need not * use this. Just always use RB_FL_REVERSE(). * * @param[out] obj Object in question. * @param[in] flags A set of enum ::ruby_fl_type. * @post `obj` has `flags` cleared. */ static inline void RB_FL_REVERSE_RAW(VALUE obj, VALUE flags) { RBIMPL_ASSERT_OR_ASSUME(RB_FL_ABLE(obj)); rbimpl_fl_reverse_raw_raw(RBASIC(obj), flags); } RBIMPL_ATTR_ARTIFICIAL() /** * Reverses the flags. This function is here mainly for symmetry on set/unset. * Rarely used in practice. * * @param[out] obj Object in question. * @param[in] flags A set of enum ::ruby_fl_type. * @post `obj` has `flags` reversed. */ static inline void RB_FL_REVERSE(VALUE obj, VALUE flags) { if (RB_FL_ABLE(obj)) { RB_FL_REVERSE_RAW(obj, flags); } } RBIMPL_ATTR_PURE_UNLESS_DEBUG() RBIMPL_ATTR_ARTIFICIAL() RBIMPL_ATTR_DEPRECATED(("taintedness turned out to be a wrong idea.")) /** * @deprecated This function once was a thing in the old days, but makes no * sense any longer today. Exists here for backwards * compatibility only. You can safely forget about it. * * @param[in] obj Object in question. * @return false always. */ static inline bool RB_OBJ_TAINTABLE(VALUE obj) { (void)obj; return false; } RBIMPL_ATTR_PURE_UNLESS_DEBUG() RBIMPL_ATTR_ARTIFICIAL() RBIMPL_ATTR_DEPRECATED(("taintedness turned out to be a wrong idea.")) /** * @deprecated This function once was a thing in the old days, but makes no * sense any longer today. Exists here for backwards * compatibility only. You can safely forget about it. * * @param[in] obj Object in question. * @return false always. */ static inline VALUE RB_OBJ_TAINTED_RAW(VALUE obj) { (void)obj; return false; } RBIMPL_ATTR_PURE_UNLESS_DEBUG() RBIMPL_ATTR_ARTIFICIAL() RBIMPL_ATTR_DEPRECATED(("taintedness turned out to be a wrong idea.")) /** * @deprecated This function once was a thing in the old days, but makes no * sense any longer today. Exists here for backwards * compatibility only. You can safely forget about it. * * @param[in] obj Object in question. * @return false always. */ static inline bool RB_OBJ_TAINTED(VALUE obj) { (void)obj; return false; } RBIMPL_ATTR_ARTIFICIAL() RBIMPL_ATTR_DEPRECATED(("taintedness turned out to be a wrong idea.")) /** * @deprecated This function once was a thing in the old days, but makes no * sense any longer today. Exists here for backwards * compatibility only. You can safely forget about it. * * @param[in] obj Object in question. */ static inline void RB_OBJ_TAINT_RAW(VALUE obj) { (void)obj; return; } RBIMPL_ATTR_ARTIFICIAL() RBIMPL_ATTR_DEPRECATED(("taintedness turned out to be a wrong idea.")) /** * @deprecated This function once was a thing in the old days, but makes no * sense any longer today. Exists here for backwards * compatibility only. You can safely forget about it. * * @param[in] obj Object in question. */ static inline void RB_OBJ_TAINT(VALUE obj) { (void)obj; return; } RBIMPL_ATTR_ARTIFICIAL() RBIMPL_ATTR_DEPRECATED(("taintedness turned out to be a wrong idea.")) /** * @deprecated This function once was a thing in the old days, but makes no * sense any longer today. Exists here for backwards * compatibility only. You can safely forget about it. * * @param[in] dst Victim object. * @param[in] src Infectant object. */ static inline void RB_OBJ_INFECT_RAW(VALUE dst, VALUE src) { (void)dst; (void)src; return; } RBIMPL_ATTR_ARTIFICIAL() RBIMPL_ATTR_DEPRECATED(("taintedness turned out to be a wrong idea.")) /** * @deprecated This function once was a thing in the old days, but makes no * sense any longer today. Exists here for backwards * compatibility only. You can safely forget about it. * * @param[in] dst Victim object. * @param[in] src Infectant object. */ static inline void RB_OBJ_INFECT(VALUE dst, VALUE src) { (void)dst; (void)src; return; } RBIMPL_ATTR_PURE_UNLESS_DEBUG() RBIMPL_ATTR_ARTIFICIAL() /** * This is an implementation detail of RB_OBJ_FROZEN(). 3rd parties need not * use this. Just always use RB_OBJ_FROZEN(). * * @param[in] obj Object in question. * @retval RUBY_FL_FREEZE Yes it is. * @retval 0 No it isn't. * * @internal * * It is intentional not to return bool here. There is a place in ruby core * (namely `class.c:singleton_class_of()`) where return value of this function * is passed to RB_FL_SET_RAW(). */ static inline VALUE RB_OBJ_FROZEN_RAW(VALUE obj) { return RB_FL_TEST_RAW(obj, RUBY_FL_FREEZE); } RBIMPL_ATTR_PURE_UNLESS_DEBUG() RBIMPL_ATTR_ARTIFICIAL() /** * Checks if an object is frozen. * * @param[in] obj Object in question. * @retval true Yes it is. * @retval false No it isn't. */ static inline bool RB_OBJ_FROZEN(VALUE obj) { if (! RB_FL_ABLE(obj)) { return true; } else { return RB_OBJ_FROZEN_RAW(obj); } } RBIMPL_ATTR_ARTIFICIAL() /** * This is an implementation detail of RB_OBJ_FREEZE(). 3rd parties need not * use this. Just always use RB_OBJ_FREEZE(). * * @param[out] obj Object in question. */ static inline void RB_OBJ_FREEZE_RAW(VALUE obj) { RB_FL_SET_RAW(obj, RUBY_FL_FREEZE); } RUBY_SYMBOL_EXPORT_BEGIN void rb_obj_freeze_inline(VALUE obj); RUBY_SYMBOL_EXPORT_END #endif /* RBIMPL_FL_TYPE_H */ include/ruby/internal/method.h 0000644 00000016121 15152150502 0012412 0 ustar 00 #ifndef RBIMPL_METHOD_H /*-*-C++-*-vi:se ft=cpp:*/ #define RBIMPL_METHOD_H /** * @file * @author Ruby developers <ruby-core@ruby-lang.org> * @copyright This file is a part of the programming language Ruby. * Permission is hereby granted, to either redistribute and/or * modify this file, provided that the conditions mentioned in the * file COPYING are met. Consult the file for details. * @warning Symbols prefixed with either `RBIMPL` or `rbimpl` are * implementation details. Don't take them as canon. They could * rapidly appear then vanish. The name (path) of this header file * is also an implementation detail. Do not expect it to persist * at the place it is now. Developers are free to move it anywhere * anytime at will. * @note To ruby-core: remember that this header can be possibly * recursively included from extension libraries written in C++. * Do not expect for instance `__VA_ARGS__` is always available. * We assume C99 for ruby itself but we don't assume languages of * extension libraries. They could be written in C++98. * @brief Creation and modification of Ruby methods. */ #include "ruby/internal/attr/nonnull.h" #include "ruby/internal/dllexport.h" #include "ruby/internal/value.h" #include "ruby/backward/2/stdarg.h" /** * @defgroup defmethod Defining methods * * There are some APIs to define a method from C. * These API takes a C function as a method body. * * ### Method body functions * * Method body functions must return a VALUE and * can be one of the following form: * * #### Fixed number of parameters * * This form is a normal C function, excepting it takes * a receiver object as the first argument. * * ```CXX * static VALUE my_method(VALUE self, VALUE x, VALUE y); * ``` * * #### argc and argv style * * This form takes three parameters: argc, argv and self. * self is the receiver. argc is the number of arguments. * argv is a pointer to an array of the arguments. * * ```CXX * static VALUE my_method(int argc, VALUE *argv, VALUE self); * ``` * * #### Ruby array style * * This form takes two parameters: self and args. * self is the receiver. args is an Array object which * contains the arguments. * * ```CXX * static VALUE my_method(VALUE self, VALUE args); * ``` * * ### Number of parameters * * Method defining APIs takes the number of parameters which the * method will takes. This number is called argc. * argc can be: * * - Zero or positive number. * This means the method body function takes a fixed number of parameters. * * - `-1`. * This means the method body function is "argc and argv" style. * * - `-2`. * This means the method body function is "self and args" style. * * @{ */ RBIMPL_SYMBOL_EXPORT_BEGIN() RBIMPL_ATTR_NONNULL(()) /** * Defines a method. * * @param[out] klass A module or a class. * @param[in] mid Name of the function. * @param[in] func The method body. * @param[in] arity The number of parameters. See @ref defmethod. * @note There are in fact 18 different prototypes for func. * @see ::ruby::backward::cxxanyargs::define_method::rb_define_method */ void rb_define_method(VALUE klass, const char *mid, VALUE (*func)(ANYARGS), int arity); RBIMPL_ATTR_NONNULL(()) /** * Defines a module function for a module. * * @param[out] klass A module or a class. * @param[in] mid Name of the function. * @param[in] func The method body. * @param[in] arity The number of parameters. See @ref defmethod. * @note There are in fact 18 different prototypes for func. * @see ::ruby::backward::cxxanyargs::define_method::rb_define_module_function */ void rb_define_module_function(VALUE klass, const char *mid, VALUE (*func)(ANYARGS), int arity); RBIMPL_ATTR_NONNULL(()) /** * Defines a global function. * * @param[in] mid Name of the function. * @param[in] func The method body. * @param[in] arity The number of parameters. See @ref defmethod. * @note There are in fact 18 different prototypes for func. * @see ::ruby::backward::cxxanyargs::define_method::rb_define_global_function */ void rb_define_global_function(const char *mid, VALUE (*func)(ANYARGS), int arity); RBIMPL_ATTR_NONNULL(()) /** * Defines an undef of a method. -- What? * * In ruby, there are two separate concepts called "undef" and "remove_method". * The thing you imagine when you "un-define" a method is remove_method. This * one on the other hand is masking of a previous method definition. Suppose * for instance: * * ```ruby * class Foo * def foo * end * end * * class Bar < Foo * def bar * foo * end * end * * class Baz < Foo * undef foo # <--- (*1) * end * ``` * * This `undef foo` at `(*1)` must not eliminate `Foo#foo`, because that method * is also used from `Bar#bar`. So instead of physically executing the target * method, `undef` inserts a special filtering entry to the class (`Baz` this * case). That entry, when called, acts as if there were no methods at all. * But the original can still be accessible, via ways like `Bar#bar` above. * * @param[out] klass The class to insert an undef. * @param[in] name Name of the undef. * @exception rb_eTypeError `klass` is a non-module. * @exception rb_eFrozenError `klass` is frozen. * @see rb_remove_method */ void rb_undef_method(VALUE klass, const char *name); RBIMPL_ATTR_NONNULL(()) /** * Defines an alias of a method. * * @param[in,out] klass The class which the original method belongs * to; this is also where the new method will * belong to. * @param[in] dst A new name for the method. * @param[in] src The original name of the method. * @exception rb_eTypeError `klass` is a non-module. * @exception rb_eFrozenError `klass` is frozen. * @exception rb_eNameError There is no such method named as `src` in * `klass`. * * @internal * * Above description is in fact a bit inaccurate because it ignores * Refinements. */ void rb_define_alias(VALUE klass, const char *dst, const char *src); RBIMPL_ATTR_NONNULL(()) /** * Defines public accessor method(s) for an attribute. * * @param[out] klass The class which the attribute will belong to. * @param[in] name Name of the attribute. * @param[in] read Whether to define a getter method. * @param[in] write Whether to define a setter method. * @exception rb_eTypeError `klass` is a non-module. * @exception rb_eFrozenError `klass` is frozen. * @exception rb_eNameError `name` invalid as an attr e.g. an operator. */ void rb_define_attr(VALUE klass, const char *name, int read, int write); /** @} */ RBIMPL_SYMBOL_EXPORT_END() #endif /* RBIMPL_METHOD_H */ include/ruby/internal/compiler_is.h 0000644 00000004071 15152150502 0013440 0 ustar 00 #ifndef RBIMPL_COMPILER_IS_H /*-*-C++-*-vi:se ft=cpp:*/ #define RBIMPL_COMPILER_IS_H /** * @file * @author Ruby developers <ruby-core@ruby-lang.org> * @copyright This file is a part of the programming language Ruby. * Permission is hereby granted, to either redistribute and/or * modify this file, provided that the conditions mentioned in the * file COPYING are met. Consult the file for details. * @warning Symbols prefixed with either `RBIMPL` or `rbimpl` are * implementation details. Don't take them as canon. They could * rapidly appear then vanish. The name (path) of this header file * is also an implementation detail. Do not expect it to persist * at the place it is now. Developers are free to move it anywhere * anytime at will. * @note To ruby-core: remember that this header can be possibly * recursively included from extension libraries written in C++. * Do not expect for instance `__VA_ARGS__` is always available. * We assume C99 for ruby itself but we don't assume languages of * extension libraries. They could be written in C++98. * @brief Defines #RBIMPL_COMPILER_IS. */ /** * @brief Checks if the compiler is of given brand. * @param cc Compiler brand, like `MSVC`. * @retval true It is. * @retval false It isn't. */ #define RBIMPL_COMPILER_IS(cc) RBIMPL_COMPILER_IS_ ## cc #include "ruby/internal/compiler_is/apple.h" #include "ruby/internal/compiler_is/clang.h" #include "ruby/internal/compiler_is/gcc.h" #include "ruby/internal/compiler_is/intel.h" #include "ruby/internal/compiler_is/msvc.h" #include "ruby/internal/compiler_is/sunpro.h" /* :TODO: Other possible compilers to support: * * - IBM XL: recent XL are clang-backended so some tweaks like we do for * Apple's might be needed. * * - ARM's armclang: ditto, it can be clang-backended. */ #endif /* RBIMPL_COMPILER_IS_H */ include/ruby/internal/xmalloc.h 0000644 00000042115 15152150502 0012573 0 ustar 00 #ifndef RBIMPL_XMALLOC_H /*-*-C++-*-vi:se ft=cpp:*/ #define RBIMPL_XMALLOC_H /** * @file * @author Ruby developers <ruby-core@ruby-lang.org> * @copyright This file is a part of the programming language Ruby. * Permission is hereby granted, to either redistribute and/or * modify this file, provided that the conditions mentioned in the * file COPYING are met. Consult the file for details. * @warning Symbols prefixed with either `RBIMPL` or `rbimpl` are * implementation details. Don't take them as canon. They could * rapidly appear then vanish. The name (path) of this header file * is also an implementation detail. Do not expect it to persist * at the place it is now. Developers are free to move it anywhere * anytime at will. * @note To ruby-core: remember that this header can be possibly * recursively included from extension libraries written in C++. * Do not expect for instance `__VA_ARGS__` is always available. * We assume C99 for ruby itself but we don't assume languages of * extension libraries. They could be written in C++98. * @brief Declares ::ruby_xmalloc(). */ #include "ruby/internal/config.h" #ifdef STDC_HEADERS # include <stddef.h> #endif #ifdef HAVE_STDLIB_H # include <stdlib.h> #endif #include "ruby/internal/attr/alloc_size.h" #include "ruby/internal/attr/nodiscard.h" #include "ruby/internal/attr/noexcept.h" #include "ruby/internal/attr/restrict.h" #include "ruby/internal/attr/returns_nonnull.h" #include "ruby/internal/dllexport.h" /** * @private * @warning Do not touch this macro. * @warning It is an implementation detail. * @warning It was a failure at the first place to let you know about it. * @warning The value of this macro must match for ruby itself and all * extension libraries, otherwise serious memory corruption shall * occur. */ #ifndef USE_GC_MALLOC_OBJ_INFO_DETAILS # define USE_GC_MALLOC_OBJ_INFO_DETAILS 0 #endif #define xmalloc ruby_xmalloc /**< @old{ruby_xmalloc} */ #define xmalloc2 ruby_xmalloc2 /**< @old{ruby_xmalloc2} */ #define xcalloc ruby_xcalloc /**< @old{ruby_xcalloc} */ #define xrealloc ruby_xrealloc /**< @old{ruby_xrealloc} */ #define xrealloc2 ruby_xrealloc2 /**< @old{ruby_xrealloc2} */ #define xfree ruby_xfree /**< @old{ruby_xfree} */ RBIMPL_SYMBOL_EXPORT_BEGIN() RBIMPL_ATTR_NODISCARD() RBIMPL_ATTR_RESTRICT() RBIMPL_ATTR_RETURNS_NONNULL() RBIMPL_ATTR_ALLOC_SIZE((1)) /** * Allocates a storage instance. It is largely the same as system malloc(), * except: * * - It raises Ruby exceptions instead of returning NULL, and * - In case of `ENOMEM` it tries to GC to make some room. * * @param[in] size Requested amount of memory. * @exception rb_eNoMemError No space left for `size` bytes allocation. * @return A valid pointer to an allocated storage instance; which has at * least `size` bytes width, with appropriate alignment detected by * the underlying malloc() routine. * @note It doesn't return NULL. * @note Unlike some malloc() implementations, it allocates something and * returns a meaningful value even when `size` is equal to zero. * @warning The return value shall be invalidated exactly once by either * ruby_xfree(), ruby_xrealloc(), or ruby_xrealloc2(). It is a * failure to pass it to system free(), because the system and Ruby * might or might not share the same malloc() implementation. */ void *ruby_xmalloc(size_t size) RBIMPL_ATTR_NOEXCEPT(malloc(size)) ; RBIMPL_ATTR_NODISCARD() RBIMPL_ATTR_RESTRICT() RBIMPL_ATTR_RETURNS_NONNULL() RBIMPL_ATTR_ALLOC_SIZE((1,2)) /** * Identical to ruby_xmalloc(), except it allocates `nelems` * `elemsiz` bytes. * This is needed because the multiplication could integer overflow. On such * situations Ruby does not try to allocate at all but raises Ruby level * exceptions instead. If there is no integer overflow the behaviour is * exactly the same as `ruby_xmalloc(nelems*elemsiz)`. * * @param[in] nelems Number of elements. * @param[in] elemsiz Size of an element. * @exception rb_eNoMemError No space left for allocation. * @exception rb_eArgError `nelems` * `elemsiz` would overflow. * @return A valid pointer to an allocated storage instance; which has at * least `nelems` * `elemsiz` bytes width, with appropriate * alignment detected by the underlying malloc() routine. * @note It doesn't return NULL. * @note Unlike some malloc() implementations, it allocates something and * returns a meaningful value even when `nelems` or `elemsiz` or * both are zero. * @warning The return value shall be invalidated exactly once by either * ruby_xfree(), ruby_xrealloc(), or ruby_xrealloc2(). It is a * failure to pass it to system free(), because the system and Ruby * might or might not share the same malloc() implementation. */ void *ruby_xmalloc2(size_t nelems, size_t elemsiz) RBIMPL_ATTR_NOEXCEPT(malloc(nelems * elemsiz)) ; RBIMPL_ATTR_NODISCARD() RBIMPL_ATTR_RESTRICT() RBIMPL_ATTR_RETURNS_NONNULL() RBIMPL_ATTR_ALLOC_SIZE((1,2)) /** * Identical to ruby_xmalloc2(), except it returns a zero-filled storage * instance. It can also be seen as a routine identical to ruby_xmalloc(), * except it calls calloc() instead of malloc(). * * @param[in] nelems Number of elements. * @param[in] elemsiz Size of an element. * @exception rb_eNoMemError No space left for allocation. * @exception rb_eArgError `nelems` * `elemsiz` would overflow. * @return A valid pointer to an allocated storage instance; which has at * least `nelems` * `elemsiz` bytes width, with appropriate * alignment detected by the underlying calloc() routine. * @post The returned storage instance is filled with zeros. * @note It doesn't return NULL. * @note Unlike some calloc() implementations, it allocates something and * returns a meaningful value even when `nelems` or `elemsiz` or * both are zero. * @warning The return value shall be invalidated exactly once by either * ruby_xfree(), ruby_xrealloc(), or ruby_xrealloc2(). It is a * failure to pass it to system free(), because the system and Ruby * might or might not share the same malloc() implementation. */ void *ruby_xcalloc(size_t nelems, size_t elemsiz) RBIMPL_ATTR_NOEXCEPT(calloc(nelems, elemsiz)) ; RBIMPL_ATTR_NODISCARD() RBIMPL_ATTR_RETURNS_NONNULL() RBIMPL_ATTR_ALLOC_SIZE((2)) /** * Resize the storage instance. * * @param[in] ptr A valid pointer to a storage instance that was * previously returned from either: * - ruby_xmalloc(), * - ruby_xmalloc2(), * - ruby_xcalloc(), * - ruby_xrealloc(), or * - ruby_xrealloc2(). * @param[in] newsiz Requested new amount of memory. * @exception rb_eNoMemError No space left for `newsiz` bytes allocation. * @return A valid pointer to a (possibly newly allocated) storage * instance; which has at least `newsiz` bytes width, with * appropriate alignment detected by the underlying realloc() * routine. * @pre The passed pointer must point to a valid live storage instance. * It is a failure to pass an already freed pointer. * @post In case the function returns the passed pointer as-is, the * storage instance that the pointer holds is either grown or * shrunken to have at least `newsiz` bytes. Otherwise a valid * pointer to a newly allocated storage instance is returned. In * this case `ptr` is invalidated as if it was passed to * ruby_xfree(). * @note It doesn't return NULL. * @warning Unlike some realloc() implementations, passing zero to `newsiz` * is not the same as calling ruby_xfree(), because this function * never returns NULL. Something meaningful still returns then. * @warning It is a failure not to check the return value. Do not assume * anything on it. It could be either identical to, or distinct * form the passed argument. * @warning Do not assume anything on the alignment of the return value. * There is no guarantee that it inherits the passed argument's * one. * @warning The return value shall be invalidated exactly once by either * ruby_xfree(), ruby_xrealloc(), or ruby_xrealloc2(). It is a * failure to pass it to system free(), because the system and Ruby * might or might not share the same malloc() implementation. */ void *ruby_xrealloc(void *ptr, size_t newsiz) RBIMPL_ATTR_NOEXCEPT(realloc(ptr, newsiz)) ; RBIMPL_ATTR_NODISCARD() RBIMPL_ATTR_RETURNS_NONNULL() RBIMPL_ATTR_ALLOC_SIZE((2,3)) /** * Identical to ruby_xrealloc(), except it resizes the given storage instance * to `newelems` * `newsiz` bytes. This is needed because the multiplication * could integer overflow. On such situations Ruby does not try to touch the * contents of argument pointer at all but raises Ruby level exceptions * instead. If there is no integer overflow the behaviour is exactly the same * as `ruby_xrealloc(ptr,nelems*elemsiz)`. * * This is roughly the same as reallocarray() function that OpenBSD * etc. provides, but also interacts with our GC. * * @param[in] ptr A valid pointer to a storage instance that was * previously returned from either: * - ruby_xmalloc(), * - ruby_xmalloc2(), * - ruby_xcalloc(), * - ruby_xrealloc(), or * - ruby_xrealloc2(). * @param[in] newelems Requested new number of elements. * @param[in] newsiz Requested new size of each element. * @exception rb_eNoMemError No space left for allocation. * @exception rb_eArgError `newelems` * `newsiz` would overflow. * @return A valid pointer to a (possibly newly allocated) storage * instance; which has at least `newelems` * `newsiz` bytes width, * with appropriate alignment detected by the underlying realloc() * routine. * @pre The passed pointer must point to a valid live storage instance. * It is a failure to pass an already freed pointer. * @post In case the function returns the passed pointer as-is, the * storage instance that the pointer holds is either grown or * shrunken to have at least `newelems` * `newsiz` bytes. * Otherwise a valid pointer to a newly allocated storage instance * is returned. In this case `ptr` is invalidated as if it was * passed to ruby_xfree(). * @note It doesn't return NULL. * @warning Unlike some realloc() implementations, passing zero to either * `newelems` or `elemsiz` are not the same as calling * ruby_xfree(), because this function never returns NULL. * Something meaningful still returns then. * @warning It is a failure not to check the return value. Do not assume * anything on it. It could be either identical to, or distinct * form the passed argument. * @warning Do not assume anything on the alignment of the return value. * There is no guarantee that it inherits the passed argument's * one. * @warning The return value shall be invalidated exactly once by either * ruby_xfree(), ruby_xrealloc(), or ruby_xrealloc2(). It is a * failure to pass it to system free(), because the system and Ruby * might or might not share the same malloc() implementation. */ void *ruby_xrealloc2(void *ptr, size_t newelems, size_t newsiz) RBIMPL_ATTR_NOEXCEPT(realloc(ptr, newelems * newsiz)) ; /** * Deallocates a storage instance. * * @param[out] ptr Either * - NULL, or * - a valid pointer previously returned from one of: * - ruby_xmalloc(), * - ruby_xmalloc2(), * - ruby_xcalloc(), * - ruby_xrealloc(), or * - ruby_xrealloc2(). * @pre The passed pointer must point to a valid live storage instance. * It is a failure to pass an already freed pointer. * @post The storage instance pointed by the passed pointer gets * invalidated; it is no longer addressable. * @warning Every single storage instance that was previously allocated by * either ruby_xmalloc(), ruby_xmalloc2(), ruby_xcalloc(), * ruby_xrealloc(), or ruby_xrealloc2() shall be invalidated * exactly once by either passing it to ruby_xfree(), or passing * it to either ruby_xrealloc(), ruby_xrealloc2() then check the * return value for invalidation. * @warning Do not pass anything other than pointers described above. For * instance pointers returned from malloc() or mmap() shall not be * passed to this function, because the underlying memory * management mechanism could differ. * @warning Do not pass any invalid pointers to this function e.g. by * calling it twice with a same argument. */ void ruby_xfree(void *ptr) RBIMPL_ATTR_NOEXCEPT(free(ptr)) ; #if USE_GC_MALLOC_OBJ_INFO_DETAILS # define ruby_xmalloc(s1) ruby_xmalloc_with_location(s1, __FILE__, __LINE__) # define ruby_xmalloc2(s1, s2) ruby_xmalloc2_with_location(s1, s2, __FILE__, __LINE__) # define ruby_xcalloc(s1, s2) ruby_xcalloc_with_location(s1, s2, __FILE__, __LINE__) # define ruby_xrealloc(ptr, s1) ruby_xrealloc_with_location(ptr, s1, __FILE__, __LINE__) # define ruby_xrealloc2(ptr, s1, s2) ruby_xrealloc2_with_location(ptr, s1, s2, __FILE__, __LINE__) RBIMPL_ATTR_NODISCARD() RBIMPL_ATTR_RESTRICT() RBIMPL_ATTR_RETURNS_NONNULL() RBIMPL_ATTR_ALLOC_SIZE((1)) void *ruby_xmalloc_body(size_t size) RBIMPL_ATTR_NOEXCEPT(malloc(size)) ; RBIMPL_ATTR_NODISCARD() RBIMPL_ATTR_RESTRICT() RBIMPL_ATTR_RETURNS_NONNULL() RBIMPL_ATTR_ALLOC_SIZE((1,2)) void *ruby_xmalloc2_body(size_t nelems, size_t elemsiz) RBIMPL_ATTR_NOEXCEPT(malloc(nelems * elemsiz)) ; RBIMPL_ATTR_NODISCARD() RBIMPL_ATTR_RESTRICT() RBIMPL_ATTR_RETURNS_NONNULL() RBIMPL_ATTR_ALLOC_SIZE((1,2)) void *ruby_xcalloc_body(size_t nelems, size_t elemsiz) RBIMPL_ATTR_NOEXCEPT(calloc(nelems, elemsiz)) ; RBIMPL_ATTR_NODISCARD() RBIMPL_ATTR_RETURNS_NONNULL() RBIMPL_ATTR_ALLOC_SIZE((2)) void *ruby_xrealloc_body(void *ptr, size_t newsiz) RBIMPL_ATTR_NOEXCEPT(realloc(ptr, newsiz)) ; RBIMPL_ATTR_NODISCARD() RBIMPL_ATTR_RETURNS_NONNULL() RBIMPL_ATTR_ALLOC_SIZE((2,3)) void *ruby_xrealloc2_body(void *ptr, size_t newelems, size_t newsiz) RBIMPL_ATTR_NOEXCEPT(realloc(ptr, newelems * newsiz)) ; RUBY_EXTERN const char *ruby_malloc_info_file; RUBY_EXTERN int ruby_malloc_info_line; static inline void * ruby_xmalloc_with_location(size_t s, const char *file, int line) { void *ptr; ruby_malloc_info_file = file; ruby_malloc_info_line = line; ptr = ruby_xmalloc_body(s); ruby_malloc_info_file = NULL; return ptr; } static inline void * ruby_xmalloc2_with_location(size_t s1, size_t s2, const char *file, int line) { void *ptr; ruby_malloc_info_file = file; ruby_malloc_info_line = line; ptr = ruby_xmalloc2_body(s1, s2); ruby_malloc_info_file = NULL; return ptr; } static inline void * ruby_xcalloc_with_location(size_t s1, size_t s2, const char *file, int line) { void *ptr; ruby_malloc_info_file = file; ruby_malloc_info_line = line; ptr = ruby_xcalloc_body(s1, s2); ruby_malloc_info_file = NULL; return ptr; } static inline void * ruby_xrealloc_with_location(void *ptr, size_t s, const char *file, int line) { void *rptr; ruby_malloc_info_file = file; ruby_malloc_info_line = line; rptr = ruby_xrealloc_body(ptr, s); ruby_malloc_info_file = NULL; return rptr; } static inline void * ruby_xrealloc2_with_location(void *ptr, size_t s1, size_t s2, const char *file, int line) { void *rptr; ruby_malloc_info_file = file; ruby_malloc_info_line = line; rptr = ruby_xrealloc2_body(ptr, s1, s2); ruby_malloc_info_file = NULL; return rptr; } #endif RBIMPL_SYMBOL_EXPORT_END() #endif /* RBIMPL_XMALLOC_H */ include/ruby/internal/arithmetic.h 0000644 00000004105 15152150502 0013262 0 ustar 00 #ifndef RBIMPL_ARITHMETIC_H /*-*-C++-*-vi:se ft=cpp:*/ #define RBIMPL_ARITHMETIC_H /** * @file * @author Ruby developers <ruby-core@ruby-lang.org> * @copyright This file is a part of the programming language Ruby. * Permission is hereby granted, to either redistribute and/or * modify this file, provided that the conditions mentioned in the * file COPYING are met. Consult the file for details. * @warning Symbols prefixed with either `RBIMPL` or `rbimpl` are * implementation details. Don't take them as canon. They could * rapidly appear then vanish. The name (path) of this header file * is also an implementation detail. Do not expect it to persist * at the place it is now. Developers are free to move it anywhere * anytime at will. * @note To ruby-core: remember that this header can be possibly * recursively included from extension libraries written in C++. * Do not expect for instance `__VA_ARGS__` is always available. * We assume C99 for ruby itself but we don't assume languages of * extension libraries. They could be written in C++98. * @brief Conversion between C's arithmetic types and Ruby's numeric * types. */ #include "ruby/internal/arithmetic/char.h" #include "ruby/internal/arithmetic/double.h" #include "ruby/internal/arithmetic/fixnum.h" #include "ruby/internal/arithmetic/gid_t.h" #include "ruby/internal/arithmetic/int.h" #include "ruby/internal/arithmetic/intptr_t.h" #include "ruby/internal/arithmetic/long.h" #include "ruby/internal/arithmetic/long_long.h" #include "ruby/internal/arithmetic/mode_t.h" #include "ruby/internal/arithmetic/off_t.h" #include "ruby/internal/arithmetic/pid_t.h" #include "ruby/internal/arithmetic/short.h" #include "ruby/internal/arithmetic/size_t.h" #include "ruby/internal/arithmetic/st_data_t.h" #include "ruby/internal/arithmetic/uid_t.h" #endif /* RBIMPL_ARITHMETIC_H */ include/ruby/internal/newobj.h 0000644 00000017326 15152150503 0012427 0 ustar 00 #ifndef RBIMPL_NEWOBJ_H /*-*-C++-*-vi:se ft=cpp:*/ #define RBIMPL_NEWOBJ_H /** * @file * @author Ruby developers <ruby-core@ruby-lang.org> * @copyright This file is a part of the programming language Ruby. * Permission is hereby granted, to either redistribute and/or * modify this file, provided that the conditions mentioned in the * file COPYING are met. Consult the file for details. * @warning Symbols prefixed with either `RBIMPL` or `rbimpl` are * implementation details. Don't take them as canon. They could * rapidly appear then vanish. The name (path) of this header file * is also an implementation detail. Do not expect it to persist * at the place it is now. Developers are free to move it anywhere * anytime at will. * @note To ruby-core: remember that this header can be possibly * recursively included from extension libraries written in C++. * Do not expect for instance `__VA_ARGS__` is always available. * We assume C99 for ruby itself but we don't assume languages of * extension libraries. They could be written in C++98. * @brief Defines #NEWOBJ. */ #include "ruby/internal/attr/deprecated.h" #include "ruby/internal/cast.h" #include "ruby/internal/core/rbasic.h" #include "ruby/internal/dllexport.h" #include "ruby/internal/fl_type.h" #include "ruby/internal/special_consts.h" #include "ruby/internal/value.h" #include "ruby/assert.h" /** * Declares, allocates, then assigns a new object to the given variable. * * @param obj Variable name. * @param type Variable type. * @exception rb_eNoMemError No space left. * @return An allocated object, not initialised. * @note Modern programs tend to use #NEWOBJ_OF instead. * * @internal * * :FIXME: Should we deprecate it? */ #define RB_NEWOBJ(obj,type) type *(obj) = RBIMPL_CAST((type *)rb_newobj()) /** * Identical to #RB_NEWOBJ, except it also accepts the allocating object's * class and flags. * * @param obj Variable name. * @param type Variable type. * @param klass Object's class. * @param flags Object's flags. * @exception rb_eNoMemError No space left. * @return An allocated object, filled with the arguments. */ #define RB_NEWOBJ_OF(obj,type,klass,flags) type *(obj) = RBIMPL_CAST((type *)rb_newobj_of(klass, flags)) #define NEWOBJ RB_NEWOBJ /**< @old{RB_NEWOBJ} */ #define NEWOBJ_OF RB_NEWOBJ_OF /**< @old{RB_NEWOBJ_OF} */ #define OBJSETUP rb_obj_setup /**< @old{rb_obj_setup} */ #define CLONESETUP rb_clone_setup /**< @old{rb_clone_setup} */ #define DUPSETUP rb_dup_setup /**< @old{rb_dup_setup} */ RBIMPL_SYMBOL_EXPORT_BEGIN() /** * This is the implementation detail of #RB_NEWOBJ. * * @exception rb_eNoMemError No space left. * @return An allocated object, not initialised. */ VALUE rb_newobj(void); /** * This is the implementation detail of #RB_NEWOBJ_OF. * * @param klass Object's class. * @param flags Object's flags. * @exception rb_eNoMemError No space left. * @return An allocated object, filled with the arguments. */ VALUE rb_newobj_of(VALUE klass, VALUE flags); /** * Fills common fields in the object. * * @note Prefer rb_newobj_of() to this function. * @param[in,out] obj A Ruby object to be set up. * @param[in] klass `obj` will belong to this class. * @param[in] type One of ::ruby_value_type. * @return The passed object. * * @internal * * Historically, authors of Ruby has described the `type` argument as "one of * ::ruby_value_type". In reality it accepts either ::ruby_value_type, * ::ruby_fl_type, or any combinations of the two. For instance * `RUBY_T_STRING | RUBY_FL_FREEZE` is a valid value that this function takes, * and means this is a frozen string. * * 3rd party extension libraries rarely need to allocate Strings this way. * They normally only concern ::RUBY_T_DATA. This argument is mainly used for * specifying flags, @shyouhei suspects. */ VALUE rb_obj_setup(VALUE obj, VALUE klass, VALUE type); /** * Queries the class of an object. This is not always identical to * `RBASIC_CLASS(obj)`. It searches for the nearest ancestor skipping * singleton classes or included modules. * * @param[in] obj Object in question. * @return The object's class, in a normal sense. */ VALUE rb_obj_class(VALUE obj); /** * Clones a singleton class. An object can have its own singleton class. OK. * Then what happens when a program clones such object? The singleton class * that is attached to the source object must also be cloned. Otherwise a * singleton object gets shared with two objects, which breaks "singleton"-ness * of such class. * * This is basically an implementation detail of rb_clone_setup(). People * need not be aware of this working behind-the-scene. * * @param[in] obj The object that has its own singleton class. * @return Cloned singleton class. */ VALUE rb_singleton_class_clone(VALUE obj); /** * Attaches a singleton class to its corresponding object. * * This is basically an implementation detail of rb_clone_setup(). People * need not be aware of this working behind-the-scene. * * @param[in] klass The singleton class. * @param[out] obj The object to attach a class. * @pre The passed two objects must agree with each other that `klass` * becomes a singleton class of `obj`. * @post `klass` becomes the singleton class of `obj`. */ void rb_singleton_class_attached(VALUE klass, VALUE obj); /** * Copies the list of instance variables. 3rd parties need not know, but there * are several ways to store an object's instance variables, depending on its * internal structure. This function makes sense when either of the passed * objects are using so-called "generic" backend storage. This distinction is * purely an implementation detail of rb_clone_setup(). People need not be * aware of this working behind-the-scenes. * * @param[out] clone The destination object. * @param[in] obj The source object. */ void rb_copy_generic_ivar(VALUE clone, VALUE obj); RBIMPL_SYMBOL_EXPORT_END() RBIMPL_ATTR_DEPRECATED(("This is no longer how Object#clone works.")) /** * @deprecated Not sure exactly when but at some time, the implementation of * `Object#clone` stopped using this function. It remained * untouched for a while, and then @shyouhei realised that they * are no longer doing the same thing. It seems nobody seriously * uses this function any longer. Let's just abandon it. * * @param[out] clone The destination object. * @param[in] obj The source object. */ static inline void rb_clone_setup(VALUE clone, VALUE obj) { (void)clone; (void)obj; return; } RBIMPL_ATTR_DEPRECATED(("This is no longer how Object#dup works.")) /** * @deprecated Not sure exactly when but at some time, the implementation of * `Object#dup` stopped using this function. It remained * untouched for a while, and then @shyouhei realised that they * are no longer the same thing. It seems nobody seriously uses * this function any longer. Let's just abandon it. * * @param[out] dup The destination object. * @param[in] obj The source object. */ static inline void rb_dup_setup(VALUE dup, VALUE obj) { (void)dup; (void)obj; return; } #endif /* RBIMPL_NEWOBJ_H */ include/ruby/internal/variable.h 0000644 00000027473 15152150503 0012734 0 ustar 00 #ifndef RBIMPL_VARIABLE_H /*-*-C++-*-vi:se ft=cpp:*/ #define RBIMPL_VARIABLE_H /** * @file * @author Ruby developers <ruby-core@ruby-lang.org> * @copyright This file is a part of the programming language Ruby. * Permission is hereby granted, to either redistribute and/or * modify this file, provided that the conditions mentioned in the * file COPYING are met. Consult the file for details. * @warning Symbols prefixed with either `RBIMPL` or `rbimpl` are * implementation details. Don't take them as canon. They could * rapidly appear then vanish. The name (path) of this header file * is also an implementation detail. Do not expect it to persist * at the place it is now. Developers are free to move it anywhere * anytime at will. * @note To ruby-core: remember that this header can be possibly * recursively included from extension libraries written in C++. * Do not expect for instance `__VA_ARGS__` is always available. * We assume C99 for ruby itself but we don't assume languages of * extension libraries. They could be written in C++98. * @brief Declares rb_define_variable(). */ #include "ruby/internal/dllexport.h" #include "ruby/internal/value.h" #include "ruby/internal/attr/nonnull.h" #include "ruby/internal/attr/noreturn.h" RBIMPL_SYMBOL_EXPORT_BEGIN() /** * Type that represents a global variable getter function. * * @param[in] id The variable name. * @param[in,out] data Where the value is stored. * @return The value that shall be visible from Ruby. */ typedef VALUE rb_gvar_getter_t(ID id, VALUE *data); /** * Type that represents a global variable setter function. * * @param[in] val The value to set. * @param[in] id The variable name. * @param[in,out] data Where the value is to be stored. */ typedef void rb_gvar_setter_t(VALUE val, ID id, VALUE *data); /** * Type that represents a global variable marker function. * * @param[in] var Where the value is to be stored. */ typedef void rb_gvar_marker_t(VALUE *var); /** * @deprecated * * This function has no actual usage (than in ruby itself). Please ignore. It * was a bad idea to expose this function to 3rd parties, but we can no longer * delete it. */ rb_gvar_getter_t rb_gvar_undef_getter; /** * @deprecated * * This function has no actual usage (than in ruby itself). Please ignore. It * was a bad idea to expose this function to 3rd parties, but we can no longer * delete it. */ rb_gvar_setter_t rb_gvar_undef_setter; /** * @deprecated * * This function has no actual usage (than in ruby itself). Please ignore. It * was a bad idea to expose this function to 3rd parties, but we can no longer * delete it. */ rb_gvar_marker_t rb_gvar_undef_marker; /** * This is the getter function that backs global variables defined from a ruby * script. Extension libraries can use this if its global variable needs no * custom logic. */ rb_gvar_getter_t rb_gvar_val_getter; /** * This is the setter function that backs global variables defined from a ruby * script. Extension libraries can use this if its global variable needs no * custom logic. */ rb_gvar_setter_t rb_gvar_val_setter; /** * This is the setter function that backs global variables defined from a ruby * script. Extension libraries can use this if its global variable needs no * custom logic. */ rb_gvar_marker_t rb_gvar_val_marker; /** * @deprecated * * This function has no actual usage (than in ruby itself). Please ignore. It * was a bad idea to expose this function to 3rd parties, but we can no longer * delete it. */ rb_gvar_getter_t rb_gvar_var_getter; /** * @deprecated * * This function has no actual usage (than in ruby itself). Please ignore. It * was a bad idea to expose this function to 3rd parties, but we can no longer * delete it. */ rb_gvar_setter_t rb_gvar_var_setter; /** * @deprecated * * This function has no actual usage (than in ruby itself). Please ignore. It * was a bad idea to expose this function to 3rd parties, but we can no longer * delete it. */ rb_gvar_marker_t rb_gvar_var_marker; RBIMPL_ATTR_NORETURN() /** * This function just raises ::rb_eNameError. Handy when you want to prohibit * a global variable from being squashed by someone. */ rb_gvar_setter_t rb_gvar_readonly_setter; RBIMPL_ATTR_NONNULL(()) /** * "Shares" a global variable between Ruby and C. Normally a Ruby-level global * variable is stored somewhere deep inside of the interpreter's execution * context, but this way you can explicitly specify its storage. * * ```CXX * static VALUE foo; * * extern "C" void * init_Foo(void) * { * foo = rb_eval_string("..."); * rb_define_variable("$foo", &foo); * } * ``` * * In the above example a Ruby global variable named `$foo` is stored in a C * global variable named `foo`. * * @param[in] name Variable (Ruby side). * @param[in] var Variable (C side). * @post Ruby level global variable named `name` is defined if absent, * and its storage is set to `var`. */ void rb_define_variable(const char *name, VALUE *var); RBIMPL_ATTR_NONNULL((1)) /** * Defines a global variable that is purely function-backended. By using this * API a programmer can define a global variable that dynamically changes from * time to time. * * @param[in] name Variable name, in C's string. * @param[in] getter A getter function. * @param[in] setter A setter function. * @post Ruby level global variable named `name` is defined if absent. * * @internal * * @shyouhei doesn't know if this is an Easter egg or an official feature, but * you can pass 0 to the third argument (setter). That effectively nullifies * any efforts to write to the defining global variable. */ void rb_define_virtual_variable(const char *name, rb_gvar_getter_t *getter, rb_gvar_setter_t *setter); RBIMPL_ATTR_NONNULL((1)) /** * Identical to rb_define_virtual_variable(), but can also specify a storage. * A programmer can use the storage for e.g. memoisation, storing intermediate * computation result, etc. * * Also you can pass 0 to this function, unlike other variants: * * - When getter is 0 ::rb_gvar_var_getter is used instead. * - When setter is 0 ::rb_gvar_var_setter is used instead. * - When data is 0, you must specify a non-zero setter function. Otherwise * ::rb_gvar_var_setter tries to write to `*NULL`, and just causes SEGV. * * @param[in] name Variable name, in C's string. * @param[in] var Variable storage. * @param[in] getter A getter function. * @param[in] setter A setter function. * @post Ruby level global variable named `name` is defined if absent. */ void rb_define_hooked_variable(const char *name, VALUE *var, rb_gvar_getter_t *getter, rb_gvar_setter_t *setter); RBIMPL_ATTR_NONNULL(()) /** * Identical to rb_define_variable(), except it does not allow Ruby programs to * assign values to such global variable. C codes can still set values at * will. This could be handy for you when implementing an `errno`-like * experience, where a method updates a read-only global variable as a side- * effect. * * @param[in] name Variable (Ruby side). * @param[in] var Variable (C side). * @post Ruby level global variable named `name` is defined if absent, * and its storage is set to `var`. */ void rb_define_readonly_variable(const char *name, const VALUE *var); RBIMPL_ATTR_NONNULL(()) /** * Defines a Ruby level constant under a namespace. * * @param[out] klass Namespace for the constant to reside. * @param[in] name Name of the constant. * @param[in] val Value of the constant. * @exception rb_eTypeError `klass` is not a kind of ::rb_cModule. * @exception rb_eFrozenError `klass` is frozen. * @post Ruby level constant `klass::name` is defined to be `val`. * @note This API does not stop you from defining a constant that is * unable to reach from ruby (like for instance passing * non-capital letter to `name`). * @note This API does not stop you from overwriting a constant that * already exist. * * @internal * * Above description is in fact inaccurate. This API interfaces with Ractors. */ void rb_define_const(VALUE klass, const char *name, VALUE val); RBIMPL_ATTR_NONNULL(()) /** * Identical to rb_define_const(), except it defines that of "global", * i.e. toplevel constant. * * @param[in] name Name of the constant. * @param[in] val Value of the constant. * @exception rb_eFrozenError ::rb_cObject is frozen. * @post Ruby level constant \::name is defined to be `val`. * @note This API does not stop you from defining a constant that is * unable to reach from ruby (like for instance passing * non-capital letter to `name`). * @note This API does not stop you from overwriting a constant that * already exist. */ void rb_define_global_const(const char *name, VALUE val); RBIMPL_ATTR_NONNULL(()) /** * Asserts that the given constant is deprecated. Attempt to refer such * constant will produce a warning. * * @param[in] mod Namespace of the target constant. * @param[in] name Name of the constant. * @exception rb_eNameError No such constant. * @exception rb_eFrozenError `mod` is frozen. * @post `name` under `mod` is deprecated. */ void rb_deprecate_constant(VALUE mod, const char *name); RBIMPL_ATTR_NONNULL(()) /** * Assigns to a global variable. * * @param[in] name Target global variable. * @param[in] val Value to assign. * @return Passed value. * @post Ruby level global variable named `name` is defined if absent, * whose value is set to `val`. * * @internal * * Above description is in fact inaccurate. This API interfaces with * `set_trace_func`. */ VALUE rb_gv_set(const char *name, VALUE val); RBIMPL_ATTR_NONNULL(()) /** * Obtains a global variable. * * @param[in] name Global variable to query. * @retval RUBY_Qnil The global variable does not exist. * @retval otherwise The value assigned to the global variable. * * @internal * * Unlike rb_gv_set(), there is no way to trace this function. */ VALUE rb_gv_get(const char *name); RBIMPL_ATTR_NONNULL(()) /** * Obtains an instance variable. * * @param[in] obj Target object. * @param[in] name Target instance variable to query. * @exception rb_eEncodingError `name` is corrupt (contains Hanzi etc.). * @retval RUBY_nil No such instance variable. * @retval otherwise The value assigned to the instance variable. */ VALUE rb_iv_get(VALUE obj, const char *name); RBIMPL_ATTR_NONNULL(()) /** * Assigns to an instance variable. * * @param[out] obj Target object. * @param[in] name Target instance variable. * @param[in] val Value to assign. * @exception rb_eFrozenError Can't modify `obj`. * @exception rb_eArgError `obj` has too many instance variables. * @return Passed value. * @post An instance variable named `name` is defined if absent on * `obj`, whose value is set to `val`. * * @internal * * This function does not stop you form creating an ASCII-incompatible instance * variable, but there is no way to get one because rb_iv_get raises exceptions * for such things. This design seems broken... But no idea why. */ VALUE rb_iv_set(VALUE obj, const char *name, VALUE val); RBIMPL_SYMBOL_EXPORT_END() #endif /* RBIMPL_VARIABLE_H */ include/ruby/internal/dllexport.h 0000644 00000006056 15152150503 0013156 0 ustar 00 #ifndef RBIMPL_DLLEXPORT_H /*-*-C++-*-vi:se ft=cpp:*/ #define RBIMPL_DLLEXPORT_H /** * @file * @author Ruby developers <ruby-core@ruby-lang.org> * @copyright This file is a part of the programming language Ruby. * Permission is hereby granted, to either redistribute and/or * modify this file, provided that the conditions mentioned in the * file COPYING are met. Consult the file for details. * @warning Symbols prefixed with either `RBIMPL` or `rbimpl` are * implementation details. Don't take them as canon. They could * rapidly appear then vanish. The name (path) of this header file * is also an implementation detail. Do not expect it to persist * at the place it is now. Developers are free to move it anywhere * anytime at will. * @note To ruby-core: remember that this header can be possibly * recursively included from extension libraries written in C++. * Do not expect for instance `__VA_ARGS__` is always available. * We assume C99 for ruby itself but we don't assume languages of * extension libraries. They could be written in C++98. * @brief Tweaking visibility of C variables/functions. */ #include "ruby/internal/config.h" #include "ruby/internal/compiler_is.h" /** * Declaration of externally visible global variables. Here "externally" means * they should be visible from extension libraries. Depending on operating * systems (dynamic linkers, to be precise), global variables inside of a DLL * may or may not be visible form outside of that DLL by default. This * declaration manually tweaks that default and ensures the declared variable * be truly globally visible. * * ```CXX * extern VALUE foo; // hidden on some OS * RUBY_EXTERN VALUE foo; // ensure visible * ``` */ #undef RUBY_EXTERN #if defined(RUBY_EXPORT) # define RUBY_EXTERN extern #elif defined(_WIN32) # define RUBY_EXTERN extern __declspec(dllimport) #else # define RUBY_EXTERN extern #endif #ifndef RUBY_SYMBOL_EXPORT_BEGIN # define RUBY_SYMBOL_EXPORT_BEGIN /* begin */ #endif #ifndef RUBY_SYMBOL_EXPORT_END # define RUBY_SYMBOL_EXPORT_END /* end */ #endif #ifndef RUBY_FUNC_EXPORTED # define RUBY_FUNC_EXPORTED /* void */ #endif /** @endcond */ /** Shortcut macro equivalent to `RUBY_SYMBOL_EXPORT_BEGIN extern "C" {`. * \@shyouhei finds it handy. */ #if defined(__DOXYGEN__) # define RBIMPL_SYMBOL_EXPORT_BEGIN() /* void */ #elif defined(__cplusplus) # define RBIMPL_SYMBOL_EXPORT_BEGIN() RUBY_SYMBOL_EXPORT_BEGIN extern "C" { #else # define RBIMPL_SYMBOL_EXPORT_BEGIN() RUBY_SYMBOL_EXPORT_BEGIN #endif /** Counterpart of #RBIMPL_SYMBOL_EXPORT_BEGIN */ #if defined(__DOXYGEN__) # define RBIMPL_SYMBOL_EXPORT_END() /* void */ #elif defined(__cplusplus) # define RBIMPL_SYMBOL_EXPORT_END() } RUBY_SYMBOL_EXPORT_END #else # define RBIMPL_SYMBOL_EXPORT_END() RUBY_SYMBOL_EXPORT_END #endif #endif /* RBIMPL_DLLEXPORT_H */ include/ruby/internal/abi.h 0000644 00000003023 15152150503 0011663 0 ustar 00 #ifndef RUBY_ABI_H #define RUBY_ABI_H #ifdef RUBY_ABI_VERSION /* should match the definition in config.h */ /* This number represents Ruby's ABI version. * * In development Ruby, it should be bumped every time an ABI incompatible * change is introduced. This will force other developers to rebuild extension * gems. * * The following cases are considered as ABI incompatible changes: * - Changing any data structures. * - Changing macros or inline functions causing a change in behavior. * - Deprecating or removing function declarations. * * The following cases are NOT considered as ABI incompatible changes: * - Any changes that does not involve the header files in the `include` * directory. * - Adding macros, inline functions, or function declarations. * - Backwards compatible refactors. * - Editing comments. * * In released versions of Ruby, this number is not defined since teeny * versions of Ruby should guarantee ABI compatibility. */ #define RUBY_ABI_VERSION 0 /* Windows does not support weak symbols so ruby_abi_version will not exist * in the shared library. */ #if defined(HAVE_FUNC_WEAK) && !defined(_WIN32) && !defined(__MINGW32__) && !defined(__CYGWIN__) # define RUBY_DLN_CHECK_ABI #endif #endif /* RUBY_ABI_VERSION */ #ifdef RUBY_DLN_CHECK_ABI # ifdef __cplusplus extern "C" { # endif RUBY_FUNC_EXPORTED unsigned long long __attribute__((weak)) ruby_abi_version(void) { # ifdef RUBY_ABI_VERSION return RUBY_ABI_VERSION; # else return 0; # endif } # ifdef __cplusplus } # endif #endif #endif include/ruby/internal/attr/deprecated.h 0000644 00000006474 15152150503 0014217 0 ustar 00 #ifndef RBIMPL_ATTR_DEPRECATED_H /*-*-C++-*-vi:se ft=cpp:*/ #define RBIMPL_ATTR_DEPRECATED_H /** * @file * @author Ruby developers <ruby-core@ruby-lang.org> * @copyright This file is a part of the programming language Ruby. * Permission is hereby granted, to either redistribute and/or * modify this file, provided that the conditions mentioned in the * file COPYING are met. Consult the file for details. * @warning Symbols prefixed with either `RBIMPL` or `rbimpl` are * implementation details. Don't take them as canon. They could * rapidly appear then vanish. The name (path) of this header file * is also an implementation detail. Do not expect it to persist * at the place it is now. Developers are free to move it anywhere * anytime at will. * @note To ruby-core: remember that this header can be possibly * recursively included from extension libraries written in C++. * Do not expect for instance `__VA_ARGS__` is always available. * We assume C99 for ruby itself but we don't assume languages of * extension libraries. They could be written in C++98. * @brief Defines #RBIMPL_ATTR_DEPRECATED. */ #include "ruby/internal/compiler_since.h" #include "ruby/internal/has/attribute.h" #include "ruby/internal/has/c_attribute.h" #include "ruby/internal/has/cpp_attribute.h" #include "ruby/internal/has/declspec_attribute.h" #include "ruby/internal/has/extension.h" /** Wraps (or simulates) `[[deprecated]]` */ #if defined(__COVERITY__) /* Coverity Scan emulates gcc but seems not to support this attribute correctly */ # define RBIMPL_ATTR_DEPRECATED(msg) #elif RBIMPL_HAS_EXTENSION(attribute_deprecated_with_message) # define RBIMPL_ATTR_DEPRECATED(msg) __attribute__((__deprecated__ msg)) #elif defined(__cplusplus) && RBIMPL_COMPILER_SINCE(GCC, 10, 1, 0) && RBIMPL_COMPILER_BEFORE(GCC, 10, 3, 0) # /* https://gcc.gnu.org/bugzilla/show_bug.cgi?id=95302 */ # define RBIMPL_ATTR_DEPRECATED(msg) /* disable until they fix this bug */ #elif RBIMPL_COMPILER_SINCE(GCC, 4, 5, 0) # define RBIMPL_ATTR_DEPRECATED(msg) __attribute__((__deprecated__ msg)) #elif RBIMPL_COMPILER_SINCE(Intel, 13, 0, 0) # define RBIMPL_ATTR_DEPRECATED(msg) __attribute__((__deprecated__ msg)) #elif RBIMPL_HAS_ATTRIBUTE(deprecated) /* but not with message. */ # define RBIMPL_ATTR_DEPRECATED(msg) __attribute__((__deprecated__)) #elif RBIMPL_COMPILER_SINCE(MSVC, 14, 0, 0) # define RBIMPL_ATTR_DEPRECATED(msg) __declspec(deprecated msg) #elif RBIMPL_HAS_DECLSPEC_ATTRIBUTE(deprecated) # define RBIMPL_ATTR_DEPRECATED(msg) __declspec(deprecated) #elif RBIMPL_HAS_CPP_ATTRIBUTE(deprecated) # define RBIMPL_ATTR_DEPRECATED(msg) [[deprecated msg]] #elif RBIMPL_HAS_C_ATTRIBUTE(deprecated) # define RBIMPL_ATTR_DEPRECATED(msg) [[deprecated msg]] #else # define RBIMPL_ATTR_DEPRECATED(msg) /* void */ #endif /** This is when a function is used internally (for backwards compatibility * etc.), but extension libraries must consider it deprecated. */ #if defined(RUBY_EXPORT) # define RBIMPL_ATTR_DEPRECATED_EXT(msg) /* void */ #else # define RBIMPL_ATTR_DEPRECATED_EXT(msg) RBIMPL_ATTR_DEPRECATED(msg) #endif #endif /* RBIMPL_ATTR_DEPRECATED_H */ include/ruby/internal/attr/noreturn.h 0000644 00000004131 15152150503 0013757 0 ustar 00 #ifndef RBIMPL_ATTR_NORETURN_H /*-*-C++-*-vi:se ft=cpp:*/ #define RBIMPL_ATTR_NORETURN_H /** * @file * @author Ruby developers <ruby-core@ruby-lang.org> * @copyright This file is a part of the programming language Ruby. * Permission is hereby granted, to either redistribute and/or * modify this file, provided that the conditions mentioned in the * file COPYING are met. Consult the file for details. * @warning Symbols prefixed with either `RBIMPL` or `rbimpl` are * implementation details. Don't take them as canon. They could * rapidly appear then vanish. The name (path) of this header file * is also an implementation detail. Do not expect it to persist * at the place it is now. Developers are free to move it anywhere * anytime at will. * @note To ruby-core: remember that this header can be possibly * recursively included from extension libraries written in C++. * Do not expect for instance `__VA_ARGS__` is always available. * We assume C99 for ruby itself but we don't assume languages of * extension libraries. They could be written in C++98. * @brief Defines #RBIMPL_ATTR_NORETURN. */ #include "ruby/internal/has/attribute.h" #include "ruby/internal/has/cpp_attribute.h" #include "ruby/internal/has/declspec_attribute.h" /** Wraps (or simulates) `[[noreturn]]` */ #if RBIMPL_HAS_DECLSPEC_ATTRIBUTE(noreturn) # define RBIMPL_ATTR_NORETURN() __declspec(noreturn) #elif RBIMPL_HAS_ATTRIBUTE(noreturn) # define RBIMPL_ATTR_NORETURN() __attribute__((__noreturn__)) #elif RBIMPL_HAS_CPP_ATTRIBUTE(noreturn) # define RBIMPL_ATTR_NORETURN() [[noreturn]] #elif defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 201112) # define RBIMPL_ATTR_NORETURN() _Noreturn #elif defined(_Noreturn) # /* glibc <sys/cdefs.h> has this macro. */ # define RBIMPL_ATTR_NORETURN() _Noreturn #else # define RBIMPL_ATTR_NORETURN() /* void */ #endif #endif /* RBIMPL_ATTR_NORETURN_H */ include/ruby/internal/attr/diagnose_if.h 0000644 00000003723 15152150503 0014360 0 ustar 00 #ifndef RBIMPL_ATTR_DIAGNOSE_IF_H /*-*-C++-*-vi:se ft=cpp:*/ #define RBIMPL_ATTR_DIAGNOSE_IF_H /** * @file * @author Ruby developers <ruby-core@ruby-lang.org> * @copyright This file is a part of the programming language Ruby. * Permission is hereby granted, to either redistribute and/or * modify this file, provided that the conditions mentioned in the * file COPYING are met. Consult the file for details. * @warning Symbols prefixed with either `RBIMPL` or `rbimpl` are * implementation details. Don't take them as canon. They could * rapidly appear then vanish. The name (path) of this header file * is also an implementation detail. Do not expect it to persist * at the place it is now. Developers are free to move it anywhere * anytime at will. * @note To ruby-core: remember that this header can be possibly * recursively included from extension libraries written in C++. * Do not expect for instance `__VA_ARGS__` is always available. * We assume C99 for ruby itself but we don't assume languages of * extension libraries. They could be written in C++98. * @brief Defines #RBIMPL_ATTR_DIAGNOSE_IF. */ #include "ruby/internal/has/attribute.h" #include "ruby/internal/warning_push.h" /** Wraps (or simulates) `__attribute__((diagnose_if))` */ #if RBIMPL_COMPILER_BEFORE(Clang, 5, 0, 0) # /* https://bugs.llvm.org/show_bug.cgi?id=34319 */ # define RBIMPL_ATTR_DIAGNOSE_IF(_, __, ___) /* void */ #elif RBIMPL_HAS_ATTRIBUTE(diagnose_if) # define RBIMPL_ATTR_DIAGNOSE_IF(_, __, ___) \ RBIMPL_WARNING_PUSH() \ RBIMPL_WARNING_IGNORED(-Wgcc-compat) \ __attribute__((__diagnose_if__(_, __, ___))) \ RBIMPL_WARNING_POP() #else # define RBIMPL_ATTR_DIAGNOSE_IF(_, __, ___) /* void */ #endif #endif /* RBIMPL_ATTR_DIAGNOSE_IF_H */ include/ruby/internal/attr/error.h 0000644 00000003142 15152150503 0013235 0 ustar 00 #ifndef RBIMPL_ATTR_ERROR_H /*-*-C++-*-vi:se ft=cpp:*/ #define RBIMPL_ATTR_ERROR_H /** * @file * @author Ruby developers <ruby-core@ruby-lang.org> * @copyright This file is a part of the programming language Ruby. * Permission is hereby granted, to either redistribute and/or * modify this file, provided that the conditions mentioned in the * file COPYING are met. Consult the file for details. * @warning Symbols prefixed with either `RBIMPL` or `rbimpl` are * implementation details. Don't take them as canon. They could * rapidly appear then vanish. The name (path) of this header file * is also an implementation detail. Do not expect it to persist * at the place it is now. Developers are free to move it anywhere * anytime at will. * @note To ruby-core: remember that this header can be possibly * recursively included from extension libraries written in C++. * Do not expect for instance `__VA_ARGS__` is always available. * We assume C99 for ruby itself but we don't assume languages of * extension libraries. They could be written in C++98. * @brief Defines #RBIMPL_ATTR_ERROR. */ #include "ruby/internal/has/attribute.h" /** Wraps (or simulates) `__attribute__((error))` */ #if RBIMPL_HAS_ATTRIBUTE(error) # define RBIMPL_ATTR_ERROR(msg) __attribute__((__error__ msg)) #else # define RBIMPL_ATTR_ERROR(msg) /* void */ #endif #endif /* RBIMPL_ATTR_ERROR_H */ include/ruby/internal/attr/nodiscard.h 0000644 00000004252 15152150503 0014055 0 ustar 00 #ifndef RBIMPL_ATTR_NODISCARD_H /*-*-C++-*-vi:se ft=cpp:*/ #define RBIMPL_ATTR_NODISCARD_H /** * @file * @author Ruby developers <ruby-core@ruby-lang.org> * @copyright This file is a part of the programming language Ruby. * Permission is hereby granted, to either redistribute and/or * modify this file, provided that the conditions mentioned in the * file COPYING are met. Consult the file for details. * @warning Symbols prefixed with either `RBIMPL` or `rbimpl` are * implementation details. Don't take them as canon. They could * rapidly appear then vanish. The name (path) of this header file * is also an implementation detail. Do not expect it to persist * at the place it is now. Developers are free to move it anywhere * anytime at will. * @note To ruby-core: remember that this header can be possibly * recursively included from extension libraries written in C++. * Do not expect for instance `__VA_ARGS__` is always available. * We assume C99 for ruby itself but we don't assume languages of * extension libraries. They could be written in C++98. * @brief Defines #RBIMPL_ATTR_NODISCARD. */ #include "ruby/internal/has/attribute.h" #include "ruby/internal/has/c_attribute.h" #include "ruby/internal/has/cpp_attribute.h" /** * Wraps (or simulates) `[[nodiscard]]`. In C++ (at least since C++20) a * nodiscard attribute can have a message why the result shall not be ignored. * However GCC attribute and SAL annotation cannot take them. */ #if RBIMPL_HAS_CPP_ATTRIBUTE(nodiscard) # define RBIMPL_ATTR_NODISCARD() [[nodiscard]] #elif RBIMPL_HAS_C_ATTRIBUTE(nodiscard) # define RBIMPL_ATTR_NODISCARD() [[nodiscard]] #elif RBIMPL_HAS_ATTRIBUTE(warn_unused_result) # define RBIMPL_ATTR_NODISCARD() __attribute__((__warn_unused_result__)) #elif defined(_Check_return_) # /* Take SAL definition. */ # define RBIMPL_ATTR_NODISCARD() _Check_return_ #else # define RBIMPL_ATTR_NODISCARD() /* void */ #endif #endif /* RBIMPL_ATTR_NODISCARD_H */ include/ruby/internal/attr/maybe_unused.h 0000644 00000003621 15152150503 0014566 0 ustar 00 #ifndef RBIMPL_ATTR_MAYBE_UNUSED_H /*-*-C++-*-vi:se ft=cpp:*/ #define RBIMPL_ATTR_MAYBE_UNUSED_H /** * @file * @author Ruby developers <ruby-core@ruby-lang.org> * @copyright This file is a part of the programming language Ruby. * Permission is hereby granted, to either redistribute and/or * modify this file, provided that the conditions mentioned in the * file COPYING are met. Consult the file for details. * @warning Symbols prefixed with either `RBIMPL` or `rbimpl` are * implementation details. Don't take them as canon. They could * rapidly appear then vanish. The name (path) of this header file * is also an implementation detail. Do not expect it to persist * at the place it is now. Developers are free to move it anywhere * anytime at will. * @note To ruby-core: remember that this header can be possibly * recursively included from extension libraries written in C++. * Do not expect for instance `__VA_ARGS__` is always available. * We assume C99 for ruby itself but we don't assume languages of * extension libraries. They could be written in C++98. * @brief Defines #RBIMPL_ATTR_MAYBE_UNUSED. */ #include "ruby/internal/has/attribute.h" #include "ruby/internal/has/c_attribute.h" #include "ruby/internal/has/cpp_attribute.h" /** Wraps (or simulates) `[[maybe_unused]]` */ #if RBIMPL_HAS_CPP_ATTRIBUTE(maybe_unused) # define RBIMPL_ATTR_MAYBE_UNUSED() [[maybe_unused]] #elif RBIMPL_HAS_C_ATTRIBUTE(maybe_unused) # define RBIMPL_ATTR_MAYBE_UNUSED() [[maybe_unused]] #elif RBIMPL_HAS_ATTRIBUTE(unused) # define RBIMPL_ATTR_MAYBE_UNUSED() __attribute__((__unused__)) #else # define RBIMPL_ATTR_MAYBE_UNUSED() /* void */ #endif #endif /* RBIMPL_ATTR_MAYBE_UNUSED */ include/ruby/internal/attr/const.h 0000644 00000004237 15152150503 0013240 0 ustar 00 #ifndef RBIMPL_ATTR_CONST_H /*-*-C++-*-vi:se ft=cpp:*/ #define RBIMPL_ATTR_CONST_H /** * @file * @author Ruby developers <ruby-core@ruby-lang.org> * @copyright This file is a part of the programming language Ruby. * Permission is hereby granted, to either redistribute and/or * modify this file, provided that the conditions mentioned in the * file COPYING are met. Consult the file for details. * @warning Symbols prefixed with either `RBIMPL` or `rbimpl` are * implementation details. Don't take them as canon. They could * rapidly appear then vanish. The name (path) of this header file * is also an implementation detail. Do not expect it to persist * at the place it is now. Developers are free to move it anywhere * anytime at will. * @note To ruby-core: remember that this header can be possibly * recursively included from extension libraries written in C++. * Do not expect for instance `__VA_ARGS__` is always available. * We assume C99 for ruby itself but we don't assume languages of * extension libraries. They could be written in C++98. * @brief Defines #RBIMPL_ATTR_CONST. */ #include "ruby/internal/compiler_since.h" #include "ruby/internal/has/attribute.h" #include "ruby/internal/has/declspec_attribute.h" /** Wraps (or simulates) `__attribute__((const))` */ #if RBIMPL_HAS_ATTRIBUTE(const) # define RBIMPL_ATTR_CONST() __attribute__((__const__)) #elif RBIMPL_HAS_DECLSPEC_ATTRIBUTE(noalias) # /* If a function can be a const, that is also a noalias. */ # define RBIMPL_ATTR_CONST() __declspec(noalias) #elif RBIMPL_COMPILER_SINCE(SunPro, 5, 10, 0) # define RBIMPL_ATTR_CONST() _Pragma("no_side_effect") #else # define RBIMPL_ATTR_CONST() /* void */ #endif /** Enables #RBIMPL_ATTR_CONST if and only if. ! #RUBY_DEBUG. */ #if !defined(RUBY_DEBUG) || !RUBY_DEBUG # define RBIMPL_ATTR_CONST_UNLESS_DEBUG() RBIMPL_ATTR_CONST() #else # define RBIMPL_ATTR_CONST_UNLESS_DEBUG() /* void */ #endif #endif /* RBIMPL_ATTR_CONST_H */ include/ruby/internal/attr/cold.h 0000644 00000003504 15152150503 0013027 0 ustar 00 #ifndef RBIMPL_ATTR_COLD_H /*-*-C++-*-vi:se ft=cpp:*/ #define RBIMPL_ATTR_COLD_H /** * @file * @author Ruby developers <ruby-core@ruby-lang.org> * @copyright This file is a part of the programming language Ruby. * Permission is hereby granted, to either redistribute and/or * modify this file, provided that the conditions mentioned in the * file COPYING are met. Consult the file for details. * @warning Symbols prefixed with either `RBIMPL` or `rbimpl` are * implementation details. Don't take them as canon. They could * rapidly appear then vanish. The name (path) of this header file * is also an implementation detail. Do not expect it to persist * at the place it is now. Developers are free to move it anywhere * anytime at will. * @note To ruby-core: remember that this header can be possibly * recursively included from extension libraries written in C++. * Do not expect for instance `__VA_ARGS__` is always available. * We assume C99 for ruby itself but we don't assume languages of * extension libraries. They could be written in C++98. * @brief Defines #RBIMPL_ATTR_COLD. */ #include "ruby/internal/compiler_is.h" #include "ruby/internal/has/attribute.h" /** Wraps (or simulates) `__attribute__((cold))` */ #if RBIMPL_COMPILER_IS(SunPro) # /* Recent SunPro has __has_attribute, and is broken. */ # /* It reports it has attribute cold, reality isn't (warnings issued). */ # define RBIMPL_ATTR_COLD() /* void */ #elif RBIMPL_HAS_ATTRIBUTE(cold) # define RBIMPL_ATTR_COLD() __attribute__((__cold__)) #else # define RBIMPL_ATTR_COLD() /* void */ #endif #endif /* RBIMPL_ATTR_COLD_H */ include/ruby/internal/attr/noalias.h 0000644 00000006734 15152150503 0013544 0 ustar 00 #ifndef RBIMPL_ATTR_NOALIAS_H /*-*-C++-*-vi:se ft=cpp:*/ #define RBIMPL_ATTR_NOALIAS_H /** * @file * @author Ruby developers <ruby-core@ruby-lang.org> * @copyright This file is a part of the programming language Ruby. * Permission is hereby granted, to either redistribute and/or * modify this file, provided that the conditions mentioned in the * file COPYING are met. Consult the file for details. * @warning Symbols prefixed with either `RBIMPL` or `rbimpl` are * implementation details. Don't take them as canon. They could * rapidly appear then vanish. The name (path) of this header file * is also an implementation detail. Do not expect it to persist * at the place it is now. Developers are free to move it anywhere * anytime at will. * @note To ruby-core: remember that this header can be possibly * recursively included from extension libraries written in C++. * Do not expect for instance `__VA_ARGS__` is always available. * We assume C99 for ruby itself but we don't assume languages of * extension libraries. They could be written in C++98. * @brief Defines #RBIMPL_ATTR_NOALIAS. * * ### Q&A ### * * - Q: There are seemingly similar attributes named #RBIMPL_ATTR_CONST, * #RBIMPL_ATTR_PURE, and #RBIMPL_ATTR_NOALIAS. What are the difference? * * - A: Allowed operations are different. * * - #RBIMPL_ATTR_CONST ... Functions attributed by this are not allowed to * read/write _any_ pointers at all (there are exceptional situations * when reading a pointer is possible but forget that; they are too * exceptional to be useful). Just remember that everything pointer- * related are NG. * * - #RBIMPL_ATTR_PURE ... Functions attributed by this can read any * nonvolatile pointers, but no writes are allowed at all. The ability * to read _any_ nonvolatile pointers makes it possible to mark ::VALUE- * taking functions as being pure, as long as they are read-only. * * - #RBIMPL_ATTR_NOALIAS ... Can both read/write, but only through * pointers passed to the function as parameters. This is a typical * situation when you create a C++ non-static member function which only * concerns `this`. No global variables are allowed to read/write. So * this is not a super-set of being pure. If you want to read something, * that has to be passed to the function as a pointer. ::VALUE -taking * functions thus cannot be attributed as such. */ #include "ruby/internal/compiler_since.h" #include "ruby/internal/has/declspec_attribute.h" /** Wraps (or simulates) `__declspec((noalias))` */ #if RBIMPL_COMPILER_BEFORE(Clang, 12, 0, 0) # /* # * `::llvm::Attribute::ArgMemOnly` was buggy before. Maybe because nobody # * actually seriously used it. It seems they somehow mitigated the situation # * in LLVM 12. Still not found the exact changeset which fiexed the # * attribute, though. # * # * :FIXME: others (armclang, xlclang, ...) can also be affected? # */ # define RBIMPL_ATTR_NOALIAS() /* void */ #elif RBIMPL_HAS_DECLSPEC_ATTRIBUTE(noalias) # define RBIMPL_ATTR_NOALIAS() __declspec(noalias) #else # define RBIMPL_ATTR_NOALIAS() /* void */ #endif #endif /* RBIMPL_ATTR_NOALIAS_H */ include/ruby/internal/attr/returns_nonnull.h 0000644 00000003431 15152150503 0015354 0 ustar 00 #ifndef RBIMPL_ATTR_RETURNS_NONNULL_H /*-*-C++-*-vi:se ft=cpp:*/ #define RBIMPL_ATTR_RETURNS_NONNULL_H /** * @file * @author Ruby developers <ruby-core@ruby-lang.org> * @copyright This file is a part of the programming language Ruby. * Permission is hereby granted, to either redistribute and/or * modify this file, provided that the conditions mentioned in the * file COPYING are met. Consult the file for details. * @warning Symbols prefixed with either `RBIMPL` or `rbimpl` are * implementation details. Don't take them as canon. They could * rapidly appear then vanish. The name (path) of this header file * is also an implementation detail. Do not expect it to persist * at the place it is now. Developers are free to move it anywhere * anytime at will. * @note To ruby-core: remember that this header can be possibly * recursively included from extension libraries written in C++. * Do not expect for instance `__VA_ARGS__` is always available. * We assume C99 for ruby itself but we don't assume languages of * extension libraries. They could be written in C++98. * @brief Defines #RBIMPL_ATTR_RETURNS_NONNULL. */ #include "ruby/internal/has/attribute.h" /** Wraps (or simulates) `__attribute__((returns_nonnull))` */ #if defined(_Ret_nonnull_) # /* Take SAL definition. */ # define RBIMPL_ATTR_RETURNS_NONNULL() _Ret_nonnull_ #elif RBIMPL_HAS_ATTRIBUTE(returns_nonnull) # define RBIMPL_ATTR_RETURNS_NONNULL() __attribute__((__returns_nonnull__)) #else # define RBIMPL_ATTR_RETURNS_NONNULL() /* void */ #endif #endif /* RBIMPL_ATTR_RETURNS_NONNULL_H */ include/ruby/internal/attr/nonnull.h 0000644 00000003336 15152150503 0013576 0 ustar 00 #ifndef RBIMPL_ATTR_NONNULL_H /*-*-C++-*-vi:se ft=cpp:*/ #define RBIMPL_ATTR_NONNULL_H /** * @file * @author Ruby developers <ruby-core@ruby-lang.org> * @copyright This file is a part of the programming language Ruby. * Permission is hereby granted, to either redistribute and/or * modify this file, provided that the conditions mentioned in the * file COPYING are met. Consult the file for details. * @warning Symbols prefixed with either `RBIMPL` or `rbimpl` are * implementation details. Don't take them as canon. They could * rapidly appear then vanish. The name (path) of this header file * is also an implementation detail. Do not expect it to persist * at the place it is now. Developers are free to move it anywhere * anytime at will. * @note To ruby-core: remember that this header can be possibly * recursively included from extension libraries written in C++. * Do not expect for instance `__VA_ARGS__` is always available. * We assume C99 for ruby itself but we don't assume languages of * extension libraries. They could be written in C++98. * @brief Defines #RBIMPL_ATTR_NONNULL. */ #include "ruby/internal/has/attribute.h" /** Wraps (or simulates) `__attribute__((nonnull))` */ #if RBIMPL_HAS_ATTRIBUTE(nonnull) # define RBIMPL_ATTR_NONNULL(list) __attribute__((__nonnull__ list)) # define RBIMPL_NONNULL_ARG(arg) RBIMPL_ASSERT_NOTHING #else # define RBIMPL_ATTR_NONNULL(list) /* void */ # define RBIMPL_NONNULL_ARG(arg) RUBY_ASSERT(arg) #endif #endif /* RBIMPL_ATTR_NONNULL_H */ include/ruby/internal/attr/alloc_size.h 0000644 00000003220 15152150503 0014225 0 ustar 00 #ifndef RBIMPL_ATTR_ALLOC_SIZE_H /*-*-C++-*-vi:se ft=cpp:*/ #define RBIMPL_ATTR_ALLOC_SIZE_H /** * @file * @author Ruby developers <ruby-core@ruby-lang.org> * @copyright This file is a part of the programming language Ruby. * Permission is hereby granted, to either redistribute and/or * modify this file, provided that the conditions mentioned in the * file COPYING are met. Consult the file for details. * @warning Symbols prefixed with either `RBIMPL` or `rbimpl` are * implementation details. Don't take them as canon. They could * rapidly appear then vanish. The name (path) of this header file * is also an implementation detail. Do not expect it to persist * at the place it is now. Developers are free to move it anywhere * anytime at will. * @note To ruby-core: remember that this header can be possibly * recursively included from extension libraries written in C++. * Do not expect for instance `__VA_ARGS__` is always available. * We assume C99 for ruby itself but we don't assume languages of * extension libraries. They could be written in C++98. * @brief Defines #RBIMPL_ATTR_ALLOC_SIZE. */ #include "ruby/internal/has/attribute.h" /** Wraps (or simulates) `__attribute__((alloc_size))` */ #if RBIMPL_HAS_ATTRIBUTE(alloc_size) # define RBIMPL_ATTR_ALLOC_SIZE(tuple) __attribute__((__alloc_size__ tuple)) #else # define RBIMPL_ATTR_ALLOC_SIZE(tuple) /* void */ #endif #endif /* RBIMPL_ATTR_ALLOC_SIZE_H */ include/ruby/internal/attr/pure.h 0000644 00000003721 15152150503 0013062 0 ustar 00 #ifndef RBIMPL_ATTR_PURE_H /*-*-C++-*-vi:se ft=cpp:*/ #define RBIMPL_ATTR_PURE_H /** * @file * @author Ruby developers <ruby-core@ruby-lang.org> * @copyright This file is a part of the programming language Ruby. * Permission is hereby granted, to either redistribute and/or * modify this file, provided that the conditions mentioned in the * file COPYING are met. Consult the file for details. * @warning Symbols prefixed with either `RBIMPL` or `rbimpl` are * implementation details. Don't take them as canon. They could * rapidly appear then vanish. The name (path) of this header file * is also an implementation detail. Do not expect it to persist * at the place it is now. Developers are free to move it anywhere * anytime at will. * @note To ruby-core: remember that this header can be possibly * recursively included from extension libraries written in C++. * Do not expect for instance `__VA_ARGS__` is always available. * We assume C99 for ruby itself but we don't assume languages of * extension libraries. They could be written in C++98. * @brief Defines #RBIMPL_ATTR_PURE. */ #include "ruby/internal/compiler_since.h" #include "ruby/internal/has/attribute.h" #include "ruby/assert.h" /** Wraps (or simulates) `__attribute__((pure))` */ #if RBIMPL_HAS_ATTRIBUTE(pure) # define RBIMPL_ATTR_PURE() __attribute__((__pure__)) #elif RBIMPL_COMPILER_SINCE(SunPro, 5, 10, 0) # define RBIMPL_ATTR_PURE() _Pragma("does_not_write_global_data") #else # define RBIMPL_ATTR_PURE() /* void */ #endif /** Enables #RBIMPL_ATTR_PURE if and only if. ! #RUBY_DEBUG. */ #if !RUBY_DEBUG # define RBIMPL_ATTR_PURE_UNLESS_DEBUG() RBIMPL_ATTR_PURE() #else # define RBIMPL_ATTR_PURE_UNLESS_DEBUG() /* void */ #endif #endif /* RBIMPL_ATTR_PURE_H */ include/ruby/internal/attr/enum_extensibility.h 0000644 00000003275 15152150503 0016033 0 ustar 00 #ifndef RBIMPL_ATTR_ENUM_EXTENSIBILITY_H /*-*-C++-*-vi:se ft=cpp:*/ #define RBIMPL_ATTR_ENUM_EXTENSIBILITY_H /** * @file * @author Ruby developers <ruby-core@ruby-lang.org> * @copyright This file is a part of the programming language Ruby. * Permission is hereby granted, to either redistribute and/or * modify this file, provided that the conditions mentioned in the * file COPYING are met. Consult the file for details. * @warning Symbols prefixed with either `RBIMPL` or `rbimpl` are * implementation details. Don't take them as canon. They could * rapidly appear then vanish. The name (path) of this header file * is also an implementation detail. Do not expect it to persist * at the place it is now. Developers are free to move it anywhere * anytime at will. * @note To ruby-core: remember that this header can be possibly * recursively included from extension libraries written in C++. * Do not expect for instance `__VA_ARGS__` is always available. * We assume C99 for ruby itself but we don't assume languages of * extension libraries. They could be written in C++98. * @brief #RBIMPL_ATTR_ENUM_EXTENSIBILITY. */ #include "ruby/internal/has/attribute.h" /** Wraps (or simulates) `__attribute__((enum_extensibility))` */ #if RBIMPL_HAS_ATTRIBUTE(enum_extensibility) # define RBIMPL_ATTR_ENUM_EXTENSIBILITY(_) __attribute__((__enum_extensibility__(_))) #else # define RBIMPL_ATTR_ENUM_EXTENSIBILITY(_) /* void */ #endif #endif /* RBIMPL_ATTR_ENUM_EXTENSIBILITY_H */ include/ruby/internal/attr/format.h 0000644 00000003405 15152150503 0013376 0 ustar 00 #ifndef RBIMPL_ATTR_FORMAT_H /*-*-C++-*-vi:se ft=cpp:*/ #define RBIMPL_ATTR_FORMAT_H /** * @file * @author Ruby developers <ruby-core@ruby-lang.org> * @copyright This file is a part of the programming language Ruby. * Permission is hereby granted, to either redistribute and/or * modify this file, provided that the conditions mentioned in the * file COPYING are met. Consult the file for details. * @warning Symbols prefixed with either `RBIMPL` or `rbimpl` are * implementation details. Don't take them as canon. They could * rapidly appear then vanish. The name (path) of this header file * is also an implementation detail. Do not expect it to persist * at the place it is now. Developers are free to move it anywhere * anytime at will. * @note To ruby-core: remember that this header can be possibly * recursively included from extension libraries written in C++. * Do not expect for instance `__VA_ARGS__` is always available. * We assume C99 for ruby itself but we don't assume languages of * extension libraries. They could be written in C++98. * @brief Defines #RBIMPL_ATTR_FORMAT. */ #include "ruby/internal/has/attribute.h" /** Wraps (or simulates) `__attribute__((format))` */ #if RBIMPL_HAS_ATTRIBUTE(format) # define RBIMPL_ATTR_FORMAT(x, y, z) __attribute__((__format__(x, y, z))) #else # define RBIMPL_ATTR_FORMAT(x, y, z) /* void */ #endif #if defined(__MINGW_PRINTF_FORMAT) # define RBIMPL_PRINTF_FORMAT __MINGW_PRINTF_FORMAT #else # define RBIMPL_PRINTF_FORMAT __printf__ #endif #endif /* RBIMPL_ATTR_FORMAT_H */ include/ruby/internal/attr/packed_struct.h 0000644 00000004107 15152150503 0014741 0 ustar 00 #ifndef RBIMPL_ATTR_PACKED_STRUCT_H /*-*-C++-*-vi:se ft=cpp:*/ #define RBIMPL_ATTR_PACKED_STRUCT_H /** * @file * @author Ruby developers <ruby-core@ruby-lang.org> * @copyright This file is a part of the programming language Ruby. * Permission is hereby granted, to either redistribute and/or * modify this file, provided that the conditions mentioned in the * file COPYING are met. Consult the file for details. * @warning Symbols prefixed with either `RBIMPL` or `rbimpl` are * implementation details. Don't take them as canon. They could * rapidly appear then vanish. The name (path) of this header file * is also an implementation detail. Do not expect it to persist * at the place it is now. Developers are free to move it anywhere * anytime at will. * @note To ruby-core: remember that this header can be possibly * recursively included from extension libraries written in C++. * Do not expect for instance `__VA_ARGS__` is always available. * We assume C99 for ruby itself but we don't assume languages of * extension libraries. They could be written in C++98. * @brief Defines #RBIMPL_ATTR_PACKED_STRUCT_BEGIN, * #RBIMPL_ATTR_PACKED_STRUCT_END, * #RBIMPL_ATTR_PACKED_STRUCT_UNALIGNED_BEGIN, and * #RBIMPL_ATTR_PACKED_STRUCT_UNALIGNED_END. */ #include "ruby/internal/config.h" #ifndef RBIMPL_ATTR_PACKED_STRUCT_BEGIN # define RBIMPL_ATTR_PACKED_STRUCT_BEGIN() /* void */ #endif #ifndef RBIMPL_ATTR_PACKED_STRUCT_END # define RBIMPL_ATTR_PACKED_STRUCT_END() /* void */ #endif #if UNALIGNED_WORD_ACCESS # define RBIMPL_ATTR_PACKED_STRUCT_UNALIGNED_BEGIN() RBIMPL_ATTR_PACKED_STRUCT_BEGIN() # define RBIMPL_ATTR_PACKED_STRUCT_UNALIGNED_END() RBIMPL_ATTR_PACKED_STRUCT_END() #else # define RBIMPL_ATTR_PACKED_STRUCT_UNALIGNED_BEGIN() /* void */ # define RBIMPL_ATTR_PACKED_STRUCT_UNALIGNED_END() /* void */ #endif #endif include/ruby/internal/attr/noinline.h 0000644 00000003400 15152150503 0013714 0 ustar 00 #ifndef RBIMPL_ATTR_NOINLINE_H /*-*-C++-*-vi:se ft=cpp:*/ #define RBIMPL_ATTR_NOINLINE_H /** * @file * @author Ruby developers <ruby-core@ruby-lang.org> * @copyright This file is a part of the programming language Ruby. * Permission is hereby granted, to either redistribute and/or * modify this file, provided that the conditions mentioned in the * file COPYING are met. Consult the file for details. * @warning Symbols prefixed with either `RBIMPL` or `rbimpl` are * implementation details. Don't take them as canon. They could * rapidly appear then vanish. The name (path) of this header file * is also an implementation detail. Do not expect it to persist * at the place it is now. Developers are free to move it anywhere * anytime at will. * @note To ruby-core: remember that this header can be possibly * recursively included from extension libraries written in C++. * Do not expect for instance `__VA_ARGS__` is always available. * We assume C99 for ruby itself but we don't assume languages of * extension libraries. They could be written in C++98. * @brief Defines #RBIMPL_ATTR_NOINLINE. */ #include "ruby/internal/has/attribute.h" #include "ruby/internal/has/declspec_attribute.h" /** Wraps (or simulates) `__declspec(noinline)` */ #if RBIMPL_HAS_DECLSPEC_ATTRIBUTE(noinline) # define RBIMPL_ATTR_NOINLINE() __declspec(noinline) #elif RBIMPL_HAS_ATTRIBUTE(noinline) # define RBIMPL_ATTR_NOINLINE() __attribute__((__noinline__)) #else # define RBIMPL_ATTR_NOINLINE() /* void */ #endif #endif /* RBIMPL_ATTR_NOINLINE_H */ include/ruby/internal/attr/noexcept.h 0000644 00000010256 15152150503 0013735 0 ustar 00 #ifndef RBIMPL_ATTR_NOEXCEPT_H /*-*-C++-*-vi:se ft=cpp:*/ #define RBIMPL_ATTR_NOEXCEPT_H /** * @file * @author Ruby developers <ruby-core@ruby-lang.org> * @copyright This file is a part of the programming language Ruby. * Permission is hereby granted, to either redistribute and/or * modify this file, provided that the conditions mentioned in the * file COPYING are met. Consult the file for details. * @warning Symbols prefixed with either `RBIMPL` or `rbimpl` are * implementation details. Don't take them as canon. They could * rapidly appear then vanish. The name (path) of this header file * is also an implementation detail. Do not expect it to persist * at the place it is now. Developers are free to move it anywhere * anytime at will. * @note To ruby-core: remember that this header can be possibly * recursively included from extension libraries written in C++. * Do not expect for instance `__VA_ARGS__` is always available. * We assume C99 for ruby itself but we don't assume languages of * extension libraries. They could be written in C++98. * @brief Defines #RBIMPL_ATTR_NOEXCEPT. * * This isn't actually an attribute in C++ but who cares... * * Mainly due to aesthetic reasons, this one is rarely used in the project. * But can be handy on occasions, especially when a function's noexcept-ness * depends on its calling functions. * * ### Q&A ### * * - Q: Can a function that raises Ruby exceptions be attributed `noexcept`? * * - A: Yes. `noexcept` is about C++ exceptions, not Ruby's. They don't * interface each other. You can safely attribute a function that raises * Ruby exceptions as `noexcept`. * * - Q: How, then, can I assert that a function I wrote doesn't raise any Ruby * exceptions? * * - A: `__attribute__((__leaf__))` is for that purpose. A function attributed * as leaf can still throw C++ exceptions, but not Ruby's. Note however, * that it's extremely difficult -- if not impossible -- to assert that a * function doesn't raise any Ruby exceptions at all. Use of that * attribute is not recommended; mere mortals can't properly use that by * hand. * * - Q: Does it make sense to attribute an inline function `noexcept`? * * - A: I thought so before. But no, I don't think they are useful any longer. * * - When an inline function attributed `noexcept` actually doesn't throw * any exceptions at all: these days I don't see any difference in * generated assembly by adding/removing this attribute. C++ compilers * get smarter and smarter. Today they can infer if it actually throws * or not without any annotations by humans (correct me if I'm wrong). * * - When an inline function attributed `noexcept` actually _does_ throw an * exception: they have to call `std::terminate` then (C++ standard * mandates so). This means exception handling routines are actually * enforced, not omitted. This doesn't impact runtime performance (The * Itanium C++ ABI has zero-cost exception handling), but does impact on * generated binary size. This is bad. */ #include "ruby/internal/compiler_since.h" #include "ruby/internal/has/feature.h" /** Wraps (or simulates) C++11 `noexcept` */ #if ! defined(__cplusplus) # /* Doesn't make sense. */ # define RBIMPL_ATTR_NOEXCEPT(_) /* void */ #elif RBIMPL_HAS_FEATURE(cxx_noexcept) # define RBIMPL_ATTR_NOEXCEPT(_) noexcept(noexcept(_)) #elif defined(__GXX_EXPERIMENTAL_CXX0X__) && __GXX_EXPERIMENTAL_CXX0X__ # define RBIMPL_ATTR_NOEXCEPT(_) noexcept(noexcept(_)) #elif defined(__INTEL_CXX11_MODE__) # define RBIMPL_ATTR_NOEXCEPT(_) noexcept(noexcept(_)) #elif RBIMPL_COMPILER_SINCE(MSVC, 19, 0, 0) # define RBIMPL_ATTR_NOEXCEPT(_) noexcept(noexcept(_)) #elif __cplusplus >= 201103L # define RBIMPL_ATTR_NOEXCEPT(_) noexcept(noexcept(_)) #else # define RBIMPL_ATTR_NOEXCEPT(_) /* void */ #endif #endif /* RBIMPL_ATTR_NOEXCEPT_H */ include/ruby/internal/attr/restrict.h 0000644 00000004114 15152150503 0013743 0 ustar 00 #ifndef RBIMPL_ATTR_RESTRICT_H /*-*-C++-*-vi:se ft=cpp:*/ #define RBIMPL_ATTR_RESTRICT_H /** * @file * @author Ruby developers <ruby-core@ruby-lang.org> * @copyright This file is a part of the programming language Ruby. * Permission is hereby granted, to either redistribute and/or * modify this file, provided that the conditions mentioned in the * file COPYING are met. Consult the file for details. * @warning Symbols prefixed with either `RBIMPL` or `rbimpl` are * implementation details. Don't take them as canon. They could * rapidly appear then vanish. The name (path) of this header file * is also an implementation detail. Do not expect it to persist * at the place it is now. Developers are free to move it anywhere * anytime at will. * @note To ruby-core: remember that this header can be possibly * recursively included from extension libraries written in C++. * Do not expect for instance `__VA_ARGS__` is always available. * We assume C99 for ruby itself but we don't assume languages of * extension libraries. They could be written in C++98. * @brief Defines #RBIMPL_ATTR_RESTRICT. */ #include "ruby/internal/compiler_since.h" #include "ruby/internal/has/attribute.h" /* :FIXME: config.h includes conflicting `#define restrict`. MSVC can be * detected using `RBIMPL_COMPILER_SINCE()`, but Clang & family cannot use * `__has_declspec_attribute()` which involves macro substitution. */ /** Wraps (or simulates) `__declspec(restrict)` */ #if RBIMPL_COMPILER_SINCE(MSVC, 14, 0, 0) # define RBIMPL_ATTR_RESTRICT() __declspec(re ## strict) #elif RBIMPL_HAS_ATTRIBUTE(malloc) # define RBIMPL_ATTR_RESTRICT() __attribute__((__malloc__)) #elif RBIMPL_COMPILER_SINCE(SunPro, 5, 10, 0) # define RBIMPL_ATTR_RESTRICT() _Pragma("returns_new_memory") #else # define RBIMPL_ATTR_RESTRICT() /* void */ #endif #endif /* RBIMPL_ATTR_RESTRICT_H */ include/ruby/internal/attr/forceinline.h 0000644 00000003752 15152150503 0014410 0 ustar 00 #ifndef RBIMPL_ATTR_FORCEINLINE_H /*-*-C++-*-vi:se ft=cpp:*/ #define RBIMPL_ATTR_FORCEINLINE_H /** * @file * @author Ruby developers <ruby-core@ruby-lang.org> * @copyright This file is a part of the programming language Ruby. * Permission is hereby granted, to either redistribute and/or * modify this file, provided that the conditions mentioned in the * file COPYING are met. Consult the file for details. * @warning Symbols prefixed with either `RBIMPL` or `rbimpl` are * implementation details. Don't take them as canon. They could * rapidly appear then vanish. The name (path) of this header file * is also an implementation detail. Do not expect it to persist * at the place it is now. Developers are free to move it anywhere * anytime at will. * @note To ruby-core: remember that this header can be possibly * recursively included from extension libraries written in C++. * Do not expect for instance `__VA_ARGS__` is always available. * We assume C99 for ruby itself but we don't assume languages of * extension libraries. They could be written in C++98. * @brief Defines #RBIMPL_ATTR_FORCEINLINE. */ #include "ruby/internal/compiler_since.h" #include "ruby/internal/has/attribute.h" /** * Wraps (or simulates) `__forceinline`. MSVC complains on declarations like * `static inline __forceinline void foo()`. It seems MSVC's `inline` and * `__forceinline` are mutually exclusive. We have to mimic that behaviour for * non-MSVC compilers. */ #if RBIMPL_COMPILER_SINCE(MSVC, 12, 0, 0) # define RBIMPL_ATTR_FORCEINLINE() __forceinline #elif RBIMPL_HAS_ATTRIBUTE(always_inline) # define RBIMPL_ATTR_FORCEINLINE() __attribute__((__always_inline__)) inline #else # define RBIMPL_ATTR_FORCEINLINE() inline #endif #endif /* RBIMPL_ATTR_FORCEINLINE_H */ include/ruby/internal/attr/constexpr.h 0000644 00000006700 15152150503 0014134 0 ustar 00 #ifndef RBIMPL_ATTR_CONSTEXPR_H /*-*-C++-*-vi:se ft=cpp:*/ #define RBIMPL_ATTR_CONSTEXPR_H /** * @file * @author Ruby developers <ruby-core@ruby-lang.org> * @copyright This file is a part of the programming language Ruby. * Permission is hereby granted, to either redistribute and/or * modify this file, provided that the conditions mentioned in the * file COPYING are met. Consult the file for details. * @warning Symbols prefixed with either `RBIMPL` or `rbimpl` are * implementation details. Don't take them as canon. They could * rapidly appear then vanish. The name (path) of this header file * is also an implementation detail. Do not expect it to persist * at the place it is now. Developers are free to move it anywhere * anytime at will. * @note To ruby-core: remember that this header can be possibly * recursively included from extension libraries written in C++. * Do not expect for instance `__VA_ARGS__` is always available. * We assume C99 for ruby itself but we don't assume languages of * extension libraries. They could be written in C++98. * @brief #RBIMPL_ATTR_CONSTEXPR. */ #include "ruby/internal/has/feature.h" #include "ruby/internal/compiler_is.h" /** @cond INTERNAL_MACRO */ #if ! defined(__cplusplus) # /* Makes no sense. */ # define RBIMPL_HAS_ATTR_CONSTEXPR_CXX11 0 # define RBIMPL_HAS_ATTR_CONSTEXPR_CXX14 0 #elif defined(__cpp_constexpr) # /* https://isocpp.org/std/standing-documents/sd-6-sg10-feature-test-recommendations */ # define RBIMPL_HAS_ATTR_CONSTEXPR_CXX11 (__cpp_constexpr >= 200704L) # define RBIMPL_HAS_ATTR_CONSTEXPR_CXX14 (__cpp_constexpr >= 201304L) #elif RBIMPL_COMPILER_SINCE(MSVC, 19, 0, 0) # define RBIMPL_HAS_ATTR_CONSTEXPR_CXX11 RBIMPL_COMPILER_SINCE(MSVC, 19, 00, 00) # define RBIMPL_HAS_ATTR_CONSTEXPR_CXX14 RBIMPL_COMPILER_SINCE(MSVC, 19, 11, 00) #elif RBIMPL_COMPILER_SINCE(SunPro, 5, 13, 0) # define RBIMPL_HAS_ATTR_CONSTEXPR_CXX11 (__cplusplus >= 201103L) # define RBIMPL_HAS_ATTR_CONSTEXPR_CXX14 (__cplusplus >= 201402L) #elif RBIMPL_COMPILER_SINCE(GCC, 4, 9, 0) # define RBIMPL_HAS_ATTR_CONSTEXPR_CXX11 (__cplusplus >= 201103L) # define RBIMPL_HAS_ATTR_CONSTEXPR_CXX14 (__cplusplus >= 201402L) #elif RBIMPL_HAS_FEATURE(cxx_relaxed_constexpr) # define RBIMPL_HAS_ATTR_CONSTEXPR_CXX11 1 # define RBIMPL_HAS_ATTR_CONSTEXPR_CXX14 1 #elif RBIMPL_HAS_FEATURE(cxx_constexpr) # define RBIMPL_HAS_ATTR_CONSTEXPR_CXX11 1 # define RBIMPL_HAS_ATTR_CONSTEXPR_CXX14 0 #else # /* :FIXME: icpc must have constexpr but don't know how to detect. */ # define RBIMPL_HAS_ATTR_CONSTEXPR_CXX11 0 # define RBIMPL_HAS_ATTR_CONSTEXPR_CXX14 0 #endif /** @endcond */ /** Wraps (or simulates) C++11 `constexpr`. */ #if RBIMPL_HAS_ATTR_CONSTEXPR_CXX14 # define RBIMPL_ATTR_CONSTEXPR(_) constexpr #elif RBIMPL_HAS_ATTR_CONSTEXPR_CXX11 # define RBIMPL_ATTR_CONSTEXPR(_) RBIMPL_ATTR_CONSTEXPR_ ## _ # define RBIMPL_ATTR_CONSTEXPR_CXX11 constexpr # define RBIMPL_ATTR_CONSTEXPR_CXX14 /* void */ #else # define RBIMPL_ATTR_CONSTEXPR(_) /* void */ #endif /** Enables #RBIMPL_ATTR_CONSTEXPR if and only if. ! #RUBY_DEBUG. */ #if !RUBY_DEBUG # define RBIMPL_ATTR_CONSTEXPR_UNLESS_DEBUG(_) RBIMPL_ATTR_CONSTEXPR(_) #else # define RBIMPL_ATTR_CONSTEXPR_UNLESS_DEBUG(_) /* void */ #endif #endif /* RBIMPL_ATTR_CONSTEXPR_H */ include/ruby/internal/attr/weakref.h 0000644 00000003165 15152150504 0013536 0 ustar 00 #ifndef RBIMPL_ATTR_WEAKREF_H /*-*-C++-*-vi:se ft=cpp:*/ #define RBIMPL_ATTR_WEAKREF_H /** * @file * @author Ruby developers <ruby-core@ruby-lang.org> * @copyright This file is a part of the programming language Ruby. * Permission is hereby granted, to either redistribute and/or * modify this file, provided that the conditions mentioned in the * file COPYING are met. Consult the file for details. * @warning Symbols prefixed with either `RBIMPL` or `rbimpl` are * implementation details. Don't take them as canon. They could * rapidly appear then vanish. The name (path) of this header file * is also an implementation detail. Do not expect it to persist * at the place it is now. Developers are free to move it anywhere * anytime at will. * @note To ruby-core: remember that this header can be possibly * recursively included from extension libraries written in C++. * Do not expect for instance `__VA_ARGS__` is always available. * We assume C99 for ruby itself but we don't assume languages of * extension libraries. They could be written in C++98. * @brief Defines #RBIMPL_ATTR_WEAKREF. */ #include "ruby/internal/has/attribute.h" /** Wraps (or simulates) `__attribute__((weakref))` */ #if RBIMPL_HAS_ATTRIBUTE(weakref) # define RBIMPL_ATTR_WEAKREF(sym) __attribute__((__weakref__(# sym))) #else # define RBIMPL_ATTR_WEAKREF(sym) /* void */ #endif #endif /* RBIMPL_ATTR_WEAKREF_H */ include/ruby/internal/attr/flag_enum.h 0000644 00000003303 15152150504 0014041 0 ustar 00 #ifndef RBIMPL_ATTR_FLAG_ENUM_H /*-*-C++-*-vi:se ft=cpp:*/ #define RBIMPL_ATTR_FLAG_ENUM_H /** * @file * @author Ruby developers <ruby-core@ruby-lang.org> * @copyright This file is a part of the programming language Ruby. * Permission is hereby granted, to either redistribute and/or * modify this file, provided that the conditions mentioned in the * file COPYING are met. Consult the file for details. * @warning Symbols prefixed with either `RBIMPL` or `rbimpl` are * implementation details. Don't take them as canon. They could * rapidly appear then vanish. The name (path) of this header file * is also an implementation detail. Do not expect it to persist * at the place it is now. Developers are free to move it anywhere * anytime at will. * @note To ruby-core: remember that this header can be possibly * recursively included from extension libraries written in C++. * Do not expect for instance `__VA_ARGS__` is always available. * We assume C99 for ruby itself but we don't assume languages of * extension libraries. They could be written in C++98. * @brief Defines #RBIMPL_ATTR_FLAG_ENUM. * @see https://clang.llvm.org/docs/AttributeReference.html#flag_enum */ #include "ruby/internal/has/attribute.h" /** Wraps (or simulates) `__attribute__((flag_enum)` */ #if RBIMPL_HAS_ATTRIBUTE(flag_enum) # define RBIMPL_ATTR_FLAG_ENUM() __attribute__((__flag_enum__)) #else # define RBIMPL_ATTR_FLAG_ENUM() /* void */ #endif #endif /* RBIMPLATTR_FLAG_ENUM_H */ include/ruby/internal/attr/artificial.h 0000644 00000004635 15152150504 0014224 0 ustar 00 #ifndef RBIMPL_ATTR_ARTIFICIAL_H /*-*-C++-*-vi:se ft=cpp:*/ #define RBIMPL_ATTR_ARTIFICIAL_H /** * @file * @author Ruby developers <ruby-core@ruby-lang.org> * @copyright This file is a part of the programming language Ruby. * Permission is hereby granted, to either redistribute and/or * modify this file, provided that the conditions mentioned in the * file COPYING are met. Consult the file for details. * @warning Symbols prefixed with either `RBIMPL` or `rbimpl` are * implementation details. Don't take them as canon. They could * rapidly appear then vanish. The name (path) of this header file * is also an implementation detail. Do not expect it to persist * at the place it is now. Developers are free to move it anywhere * anytime at will. * @note To ruby-core: remember that this header can be possibly * recursively included from extension libraries written in C++. * Do not expect for instance `__VA_ARGS__` is always available. * We assume C99 for ruby itself but we don't assume languages of * extension libraries. They could be written in C++98. * @brief Defines #RBIMPL_ATTR_ARTIFICIAL. * * ### Q&A ### * * - Q: What is this attribute? I don't get what GCC manual is talking about. * * - A: In short it is an attribute to manipulate GDB backtraces. The * attribute makes the best sense when it comes with * __attribute__((always_inline)). When a function annotated with this * attribute gets inlined, and when you somehow look at a backtrace which * includes such inlined call site, then the backtrace shows the caller * and not the callee. This is handy for instance when an identical * function is inlined more than once in a single big function. On such * case it gets vital to know where the inlining happened in the callee. * See also https://stackoverflow.com/a/21936099 */ #include "ruby/internal/has/attribute.h" /** Wraps (or simulates) `__attribute__((artificial))` */ #if RBIMPL_HAS_ATTRIBUTE(artificial) # define RBIMPL_ATTR_ARTIFICIAL() __attribute__((__artificial__)) #else # define RBIMPL_ATTR_ARTIFICIAL() /* void */ #endif #endif /* RBIMPL_ATTR_ARTIFICIAL_H */ include/ruby/internal/attr/warning.h 0000644 00000003162 15152150504 0013554 0 ustar 00 #ifndef RBIMPL_ATTR_WARNING_H /*-*-C++-*-vi:se ft=cpp:*/ #define RBIMPL_ATTR_WARNING_H /** * @file * @author Ruby developers <ruby-core@ruby-lang.org> * @copyright This file is a part of the programming language Ruby. * Permission is hereby granted, to either redistribute and/or * modify this file, provided that the conditions mentioned in the * file COPYING are met. Consult the file for details. * @warning Symbols prefixed with either `RBIMPL` or `rbimpl` are * implementation details. Don't take them as canon. They could * rapidly appear then vanish. The name (path) of this header file * is also an implementation detail. Do not expect it to persist * at the place it is now. Developers are free to move it anywhere * anytime at will. * @note To ruby-core: remember that this header can be possibly * recursively included from extension libraries written in C++. * Do not expect for instance `__VA_ARGS__` is always available. * We assume C99 for ruby itself but we don't assume languages of * extension libraries. They could be written in C++98. * @brief Defines #RBIMPL_ATTR_WARNING. */ #include "ruby/internal/has/attribute.h" /** Wraps (or simulates) `__attribute__((warning))` */ #if RBIMPL_HAS_ATTRIBUTE(warning) # define RBIMPL_ATTR_WARNING(msg) __attribute__((__warning__ msg)) #else # define RBIMPL_ATTR_WARNING(msg) /* void */ #endif #endif /* RBIMPL_ATTR_WARNING_H */ include/ruby/internal/iterator.h 0000644 00000044303 15152150504 0012770 0 ustar 00 #ifndef RBIMPL_ITERATOR_H /*-*-C++-*-vi:se ft=cpp:*/ #define RBIMPL_ITERATOR_H /** * @file * @author Ruby developers <ruby-core@ruby-lang.org> * @copyright This file is a part of the programming language Ruby. * Permission is hereby granted, to either redistribute and/or * modify this file, provided that the conditions mentioned in the * file COPYING are met. Consult the file for details. * @warning Symbols prefixed with either `RBIMPL` or `rbimpl` are * implementation details. Don't take them as canon. They could * rapidly appear then vanish. The name (path) of this header file * is also an implementation detail. Do not expect it to persist * at the place it is now. Developers are free to move it anywhere * anytime at will. * @note To ruby-core: remember that this header can be possibly * recursively included from extension libraries written in C++. * Do not expect for instance `__VA_ARGS__` is always available. * We assume C99 for ruby itself but we don't assume languages of * extension libraries. They could be written in C++98. * @brief Block related APIs. */ #include "ruby/internal/attr/deprecated.h" #include "ruby/internal/attr/noreturn.h" #include "ruby/internal/dllexport.h" #include "ruby/internal/value.h" RBIMPL_SYMBOL_EXPORT_BEGIN() /** * @private * * @deprecated This macro once was a thing in the old days, but makes no sense * any longer today. Exists here for backwards compatibility * only. You can safely forget about it. */ #define RB_BLOCK_CALL_FUNC_STRICT 1 /** * @private * * @deprecated This macro once was a thing in the old days, but makes no sense * any longer today. Exists here for backwards compatibility * only. You can safely forget about it. */ #define RUBY_BLOCK_CALL_FUNC_TAKES_BLOCKARG 1 /** * Shim for block function parameters. Historically ::rb_block_call_func_t had * only two parameters. Over time it evolved to have much more than that. By * using this macro you can absorb such API differences. * * ```CXX * // This works since 2.1.0 * VALUE my_own_iterator(RB_BLOCK_CALL_FUNC_ARGLIST(y, c)); * ``` */ #define RB_BLOCK_CALL_FUNC_ARGLIST(yielded_arg, callback_arg) \ VALUE yielded_arg, VALUE callback_arg, int argc, const VALUE *argv, VALUE blockarg /** * This is the type of a function that the interpreter expect for C-backended * blocks. Blocks are often written in Ruby. But C extensions might want to * have their own blocks. In order to do so authors have to create a separate * C function of this type, and pass its pointer to rb_block_call(). * * ```CXX * VALUE * my_own_iterator(RB_BLOCK_CALL_FUNC_ARGLIST(y, c)) * { * const auto plus = rb_intern("+"); * return rb_funcall(c, plus, 1, y); * } * * VALUE * my_own_method(VALUE self) * { * const auto each = rb_intern("each"); * return rb_block_call(self, each, 0, 0, my_own_iterator, self); * } * ``` */ typedef VALUE rb_block_call_func(RB_BLOCK_CALL_FUNC_ARGLIST(yielded_arg, callback_arg)); /** * Shorthand type that represents an iterator-written-in-C function pointer. */ typedef rb_block_call_func *rb_block_call_func_t; /** * This is a shorthand of calling `obj.each`. * * @param[in] obj The receiver. * @return What `obj.each` returns. * * @internal * * Does anyone still need it? This API was to use with rb_iterate(), which is * marked deprecated (see below). Old idiom to call an iterator was: * * ```CXX * VALUE recv; * VALUE iter_func(ANYARGS); * VALUE iter_data; * rb_iterate(rb_each, recv, iter_func, iter_data); * ``` */ VALUE rb_each(VALUE obj); /** * Yields the block. In Ruby there is a concept called a block. You can pass * one to a method. In a method, when called with a block, you can yield it * using this function. * * ```CXX * VALUE * iterate(VALUE self) * { * extern int get_n(VALUE); * extern VALUE get_v(VALUE, VALUE); * const auto n = get_n(self); * * for (int i=0; i<n; i++) { * auto v = get_v(self, i); * * rb_yield(v); * } * return self; * } * ``` * * @param[in] val Passed to the block. * @exception rb_eLocalJumpError There is no block given. * @return Evaluated value of the given block. */ VALUE rb_yield(VALUE val); /** * Identical to rb_yield(), except it takes variadic number of parameters and * pass them to the block. * * @param[in] n Number of parameters. * @param[in] ... List of arguments passed to the block. * @exception rb_eLocalJumpError There is no block given. * @return Evaluated value of the given block. */ VALUE rb_yield_values(int n, ...); /** * Identical to rb_yield_values(), except it takes the parameters as a C array * instead of variadic arguments. * * @param[in] n Number of parameters. * @param[in] argv List of arguments passed to the block. * @exception rb_eLocalJumpError There is no block given. * @return Evaluated value of the given block. */ VALUE rb_yield_values2(int n, const VALUE *argv); /** * Identical to rb_yield_values2(), except you can specify how to handle the * last element of the given array. * * @param[in] n Number of parameters. * @param[in] argv List of arguments passed to the block. * @param[in] kw_splat Handling of keyword parameters: * - RB_NO_KEYWORDS `ary`'s last is not a keyword argument. * - RB_PASS_KEYWORDS `ary`'s last is a keyword argument. * - RB_PASS_CALLED_KEYWORDS makes no sense here. * @exception rb_eLocalJumpError There is no block given. * @return Evaluated value of the given block. */ VALUE rb_yield_values_kw(int n, const VALUE *argv, int kw_splat); /** * Identical to rb_yield_values(), except it splats an array to generate the * list of parameters. * * @param[in] ary Array to splat. * @exception rb_eLocalJumpError There is no block given. * @return Evaluated value of the given block. */ VALUE rb_yield_splat(VALUE ary); /** * Identical to rb_yield_splat(), except you can specify how to handle the last * element of the given array. * * @param[in] ary Array to splat. * @param[in] kw_splat Handling of keyword parameters: * - RB_NO_KEYWORDS `ary`'s last is not a keyword argument. * - RB_PASS_KEYWORDS `ary`'s last is a keyword argument. * - RB_PASS_CALLED_KEYWORDS makes no sense here. * @exception rb_eLocalJumpError There is no block given. * @return Evaluated value of the given block. */ VALUE rb_yield_splat_kw(VALUE ary, int kw_splat); /** * Pass a passed block. * * Sometimes you want to "pass" a block form one method to another. Suppose * you have this Ruby method `foo`: * * ```ruby * def foo(x, y) * x.open(y) do |*z| * yield(*z) * end * end * ``` * * And suppose you want to translate this into C. Then rb_yield_block() * function is usable in this situation. * * ```CXX * VALUE * foo_translated_into_C(VALUE self, VALUE x, VALUE y) * { * const auto open = rb_intern("open"); * * return rb_block_call(x, open, 1, &y, rb_yield_block, Qfalse); * // ^^^^^^^^^^^^^^ Here. * } * ``` * * @see rb_funcall_passing_block * * @internal * * @shyouhei honestly doesn't understand why this is needed, given there * already was rb_funcall_passing_block() at the time it was implemented. If * somebody knows its raison d'etre, please improve the document :FIXME: */ VALUE rb_yield_block(RB_BLOCK_CALL_FUNC_ARGLIST(yielded_arg, callback_arg)); /* rb_block_call_func */ /** * Determines if the current method is given a keyword argument. * * @retval false No keyword argument is given. * @retval true Keyword argument(s) are given. * @ingroup defmethod */ int rb_keyword_given_p(void); /** * Determines if the current method is given a block. * * @retval false No block is given. * @retval true A block is given. * @ingroup defmethod * * @internal * * This function should have returned a bool. But at the time it was designed * the project was entirely written in K&R C. */ int rb_block_given_p(void); /** * Declares that the current method needs a block. * * @exception rb_eLocalJumpError No block given. * @ingroup defmethod */ void rb_need_block(void); #ifndef __cplusplus RBIMPL_ATTR_DEPRECATED(("by: rb_block_call since 1.9")) #endif /** * Old way to iterate a block. * * @deprecated This is an old API. Use rb_block_call() instead. * @warning The passed function must at least once call a ruby method * (to handle interrupts etc.) * @param[in] func1 A function that could yield a value. * @param[in,out] data1 Passed to `func1` * @param[in] proc A function acts as a block. * @param[in,out] data2 Passed to `proc` as the data2 parameter. * @return What `func1` returns. */ VALUE rb_iterate(VALUE (*func1)(VALUE), VALUE data1, rb_block_call_func_t proc, VALUE data2); #ifdef __cplusplus namespace ruby { namespace backward { /** * Old way to iterate a block. * * @deprecated This is an old API. Use rb_block_call() instead. * @warning The passed function must at least once call a ruby method * (to handle interrupts etc.) * @param[in] iter A function that could yield a value. * @param[in,out] data1 Passed to `func1` * @param[in] bl A function acts as a block. * @param[in,out] data2 Passed to `proc` as the data2 parameter. * @return What `func1` returns. */ static inline VALUE rb_iterate_deprecated(VALUE (*iter)(VALUE), VALUE data1, rb_block_call_func_t bl, VALUE data2) { return ::rb_iterate(iter, data1, bl, data2); }}} RBIMPL_ATTR_DEPRECATED(("by: rb_block_call since 1.9")) VALUE rb_iterate(VALUE (*func1)(VALUE), VALUE data1, rb_block_call_func_t proc, VALUE data2); #endif /** * Identical to rb_funcallv(), except it additionally passes a function as a * block. When the method yields, `proc` is called with the yielded value as * its first argument, and `data2` as the second. Yielded values would be * packed into an array if multiple values are yielded at once. * * @param[in,out] obj Receiver. * @param[in] mid Method signature. * @param[in] argc Number of arguments. * @param[in] argv Arguments passed to `obj.mid`. * @param[in] proc A function acts as a block. * @param[in,out] data2 Passed to `proc` as the data2 parameter. * @return What `obj.mid` returns. */ VALUE rb_block_call(VALUE obj, ID mid, int argc, const VALUE *argv, rb_block_call_func_t proc, VALUE data2); /** * Identical to rb_funcallv_kw(), except it additionally passes a function as a * block. It can also be seen as a routine identical to rb_block_call(), * except it handles keyword-ness of `argv[argc-1]`. * * @param[in,out] obj Receiver. * @param[in] mid Method signature. * @param[in] argc Number of arguments including the keywords. * @param[in] argv Arguments passed to `obj.mid`. * @param[in] proc A function acts as a block. * @param[in,out] data2 Passed to `proc` as the data2 parameter. * @param[in] kw_splat Handling of keyword parameters: * - RB_NO_KEYWORDS `argv`'s last is not a keyword argument. * - RB_PASS_KEYWORDS `argv`'s last is a keyword argument. * - RB_PASS_CALLED_KEYWORDS it depends if there is a passed block. * @return What `obj.mid` returns. */ VALUE rb_block_call_kw(VALUE obj, ID mid, int argc, const VALUE *argv, rb_block_call_func_t proc, VALUE data2, int kw_splat); /** * Identical to rb_rescue2(), except it does not take a list of exception * classes. This is a shorthand of: * * ```CXX * rb_rescue2(b_proc, data1, r_proc, data2, rb_eStandardError, (VALUE)0); * ``` * * @param[in] b_proc A function which potentially raises an exception. * @param[in,out] data1 Passed to `b_proc`. * @param[in] r_proc A function which rescues an exception in `b_proc`. * @param[in,out] data2 The first argument of `r_proc`. * @return The return value of `b_proc` if no exception occurs, or the * return value of `r_proc` otherwise. * @see rb_rescue * @see rb_ensure * @see rb_protect * @ingroup exception */ VALUE rb_rescue(VALUE (*b_proc)(VALUE), VALUE data1, VALUE (*r_proc)(VALUE, VALUE), VALUE data2); /** * An equivalent of `rescue` clause. * * First it calls the function `b_proc` with `data1` as the argument. If * nothing is thrown the function happily returns the return value of `b_proc`. * When `b_proc` raises an exception, and the exception is a kind of one of the * given exception classes, it then calls `r_proc` with `data2` and that * exception. If the exception does not match any of them, it propagates. * * @param[in] b_proc A function which potentially raises an exception. * @param[in,out] data1 Passed to `b_proc`. * @param[in] r_proc A function which rescues an exception in `b_proc`. * @param[in,out] data2 The first argument of `r_proc`. * @param[in] ... 1 or more exception classes. Must be terminated by * `(VALUE)0` * @return The return value of `b_proc` if no exception occurs, or the * return value of `r_proc` otherwise. * @see rb_rescue * @see rb_ensure * @see rb_protect * @ingroup exception */ VALUE rb_rescue2(VALUE (*b_proc)(VALUE), VALUE data1, VALUE (*r_proc)(VALUE, VALUE), VALUE data2, ...); /** * Identical to rb_rescue2(), except it takes `va_list` instead of variadic * number of arguments. This is exposed to 3rd parties because inline * functions use it. Basically you don't have to bother. * * @param[in] b_proc A function which potentially raises an exception. * @param[in,out] data1 Passed to `b_proc`. * @param[in] r_proc A function which rescues an exception in `b_proc`. * @param[in,out] data2 The first argument of `r_proc`. * @param[in] ap 1 or more exception classes. Must be terminated by * `(VALUE)0` * @return The return value of `b_proc` if no exception occurs, or the * return value of `r_proc` otherwise. * @see rb_rescue * @see rb_ensure * @see rb_protect * @ingroup exception */ VALUE rb_vrescue2(VALUE (*b_proc)(VALUE), VALUE data1, VALUE (*r_proc)(VALUE, VALUE), VALUE data2, va_list ap); /** * An equivalent to `ensure` clause. Calls the function `b_proc` with `data1` * as the argument, then calls `e_proc` with `data2` when execution terminated. * * @param[in] b_proc A function representing begin clause. * @param[in,out] data1 Passed to `b_proc`. * @param[in] e_proc A function representing ensure clause. * @param[in,out] data2 Passed to `e_proc`. * @retval RUBY_Qnil exception occurred inside of `b_proc`. * @retval otherwise The return value of `b_proc`. * @see rb_rescue * @see rb_rescue2 * @see rb_protect * @ingroup exception */ VALUE rb_ensure(VALUE (*b_proc)(VALUE), VALUE data1, VALUE (*e_proc)(VALUE), VALUE data2); /** * Executes the passed block and catches values thrown from inside of it. * * In case the block does not contain any throw`, this function returns the * value of the last expression evaluated. * * ```CXX * VALUE * iter(RB_BLOCK_CALL_FUNC_ARGLIST(yielded, callback)) * { * return INT2FIX(123); * } * * VALUE * method(VALUE self) * { * return rb_catch("tag", iter, Qnil); // returns 123 * } * ``` * * In case there do exist `throw`, Ruby searches up its execution context for a * `catch` block. When a matching catch is found, the block stops executing * and returns that thrown value instead. * * ```CXX * VALUE * iter(RB_BLOCK_CALL_FUNC_ARGLIST(yielded, callback)) * { * rb_throw("tag", 456); * return INT2FIX(123); * } * * VALUE * method(VALUE self) * { * return rb_catch("tag", iter, Qnil); // returns 456 * } * ``` * * @param[in] tag Arbitrary tag string. * @param[in] func Function pointer that acts as a block. * @param[in,out] data Extra parameter passed to `func`. * @return Either caught value for `tag`, or the return value of `func` * if nothing is thrown. */ VALUE rb_catch(const char *tag, rb_block_call_func_t func, VALUE data); /** * Identical to rb_catch(), except it catches arbitrary Ruby objects. * * @param[in] tag Arbitrary tag object. * @param[in] func Function pointer that acts as a block. * @param[in,out] data Extra parameter passed to `func`. * @return Either caught value for `tag`, or the return value of `func` * if nothing is thrown. */ VALUE rb_catch_obj(VALUE tag, rb_block_call_func_t func, VALUE data); RBIMPL_ATTR_NORETURN() /** * Transfers control to the end of the active `catch` block waiting for `tag`. * Raises rb_eUncughtThrow if there is no `catch` block for the tag. The * second parameter supplies a return value for the `catch` block, which * otherwise defaults to ::RUBY_Qnil. For examples, see rb_catch(). * * @param[in] tag Tag string. * @param[in] val Value to throw. * @exception rb_eUncughtThrow There is no corresponding `catch` clause. * @note It never returns. */ void rb_throw(const char *tag, VALUE val); RBIMPL_ATTR_NORETURN() /** * Identical to rb_throw(), except it allows arbitrary Ruby object to become a * tag. * * @param[in] tag Arbitrary object. * @param[in] val Value to throw. * @exception rb_eUncughtThrow There is no corresponding `catch` clause. * @note It never returns. */ void rb_throw_obj(VALUE tag, VALUE val); RBIMPL_SYMBOL_EXPORT_END() #endif /* RBIMPL_ITERATOR_H */ include/ruby/internal/globals.h 0000644 00000023430 15152150504 0012560 0 ustar 00 #ifndef RBIMPL_GLOBALS_H /*-*-C++-*-vi:se ft=cpp:*/ #define RBIMPL_GLOBALS_H /** * @file * @author Ruby developers <ruby-core@ruby-lang.org> * @copyright This file is a part of the programming language Ruby. * Permission is hereby granted, to either redistribute and/or * modify this file, provided that the conditions mentioned in the * file COPYING are met. Consult the file for details. * @warning Symbols prefixed with either `RBIMPL` or `rbimpl` are * implementation details. Don't take them as canon. They could * rapidly appear then vanish. The name (path) of this header file * is also an implementation detail. Do not expect it to persist * at the place it is now. Developers are free to move it anywhere * anytime at will. * @note To ruby-core: remember that this header can be possibly * recursively included from extension libraries written in C++. * Do not expect for instance `__VA_ARGS__` is always available. * We assume C99 for ruby itself but we don't assume languages of * extension libraries. They could be written in C++98. * @brief Ruby-level global variables / constants, visible from C. */ #include "ruby/internal/attr/pure.h" #include "ruby/internal/dllexport.h" #include "ruby/internal/fl_type.h" #include "ruby/internal/special_consts.h" #include "ruby/internal/value.h" #include "ruby/internal/value_type.h" /** * @defgroup object Core objects and their operations * * @internal * * There are several questionable constants listed in this header file. They * are intentionally left untouched for purely academic backwards compatibility * concerns. But for instance do any one of 3rd party extension libraries even * need to know that there is NameError::Message? * * @endinternal * * @{ */ RBIMPL_SYMBOL_EXPORT_BEGIN() /** * @private * * @deprecated This macro once was a thing in the old days, but makes no sense * any longer today. Exists here for backwards compatibility * only. You can safely forget about it. */ #define RUBY_INTEGER_UNIFICATION 1 RUBY_EXTERN VALUE rb_mKernel; /**< `Kernel` module. */ RUBY_EXTERN VALUE rb_mComparable; /**< `Comparable` module. */ RUBY_EXTERN VALUE rb_mEnumerable; /**< `Enumerable` module. */ RUBY_EXTERN VALUE rb_mErrno; /**< `Errno` module. */ RUBY_EXTERN VALUE rb_mFileTest; /**< `FileTest` module. */ RUBY_EXTERN VALUE rb_mGC; /**< `GC` module. */ RUBY_EXTERN VALUE rb_mMath; /**< `Math` module. */ RUBY_EXTERN VALUE rb_mProcess; /**< `Process` module. */ RUBY_EXTERN VALUE rb_mWaitReadable; /**< `IO::WaitReadable` module. */ RUBY_EXTERN VALUE rb_mWaitWritable; /**< `IO::WaitReadable` module. */ RUBY_EXTERN VALUE rb_cBasicObject; /**< `BasicObject` class. */ RUBY_EXTERN VALUE rb_cObject; /**< `Object` class. */ RUBY_EXTERN VALUE rb_cArray; /**< `Array` class. */ RUBY_EXTERN VALUE rb_cBinding; /**< `Binding` class. */ RUBY_EXTERN VALUE rb_cClass; /**< `Class` class. */ RUBY_EXTERN VALUE rb_cDir; /**< `Dir` class. */ RUBY_EXTERN VALUE rb_cEncoding; /**< `Encoding` class. */ RUBY_EXTERN VALUE rb_cEnumerator; /**< `Enumerator` class. */ RUBY_EXTERN VALUE rb_cFalseClass; /**< `FalseClass` class. */ RUBY_EXTERN VALUE rb_cFile; /**< `File` class. */ RUBY_EXTERN VALUE rb_cComplex; /**< `Complex` class. */ RUBY_EXTERN VALUE rb_cFloat; /**< `Float` class. */ RUBY_EXTERN VALUE rb_cHash; /**< `Hash` class. */ RUBY_EXTERN VALUE rb_cIO; /**< `IO` class. */ RUBY_EXTERN VALUE rb_cInteger; /**< `Module` class. */ RUBY_EXTERN VALUE rb_cMatch; /**< `MatchData` class. */ RUBY_EXTERN VALUE rb_cMethod; /**< `Method` class. */ RUBY_EXTERN VALUE rb_cModule; /**< `Module` class. */ RUBY_EXTERN VALUE rb_cRefinement; /**< `Refinement` class. */ RUBY_EXTERN VALUE rb_cNameErrorMesg; /**< `NameError::Message` class. */ RUBY_EXTERN VALUE rb_cNilClass; /**< `NilClass` class. */ RUBY_EXTERN VALUE rb_cNumeric; /**< `Numeric` class. */ RUBY_EXTERN VALUE rb_cProc; /**< `Proc` class. */ RUBY_EXTERN VALUE rb_cRandom; /**< `Random` class. */ RUBY_EXTERN VALUE rb_cRange; /**< `Range` class. */ RUBY_EXTERN VALUE rb_cRational; /**< `Rational` class. */ RUBY_EXTERN VALUE rb_cRegexp; /**< `Regexp` class. */ RUBY_EXTERN VALUE rb_cStat; /**< `File::Stat` class. */ RUBY_EXTERN VALUE rb_cString; /**< `String` class. */ RUBY_EXTERN VALUE rb_cStruct; /**< `Struct` class. */ RUBY_EXTERN VALUE rb_cSymbol; /**< `Symbol` class. */ RUBY_EXTERN VALUE rb_cThread; /**< `Thread` class. */ RUBY_EXTERN VALUE rb_cTime; /**< `Time` class. */ RUBY_EXTERN VALUE rb_cTrueClass; /**< `TrueClass` class. */ RUBY_EXTERN VALUE rb_cUnboundMethod; /**< `UnboundMethod` class. */ /** * @} * @addtogroup exception * @{ */ RUBY_EXTERN VALUE rb_eException; /**< Mother of all exceptions. */ RUBY_EXTERN VALUE rb_eStandardError; /**< `StandardError` exception. */ RUBY_EXTERN VALUE rb_eSystemExit; /**< `SystemExit` exception. */ RUBY_EXTERN VALUE rb_eInterrupt; /**< `Interrupt` exception. */ RUBY_EXTERN VALUE rb_eSignal; /**< `SignalException` exception. */ RUBY_EXTERN VALUE rb_eFatal; /**< `fatal` exception. */ RUBY_EXTERN VALUE rb_eArgError; /**< `ArgumentError` exception. */ RUBY_EXTERN VALUE rb_eEOFError; /**< `EOFError` exception. */ RUBY_EXTERN VALUE rb_eIndexError; /**< `IndexError` exception. */ RUBY_EXTERN VALUE rb_eStopIteration; /**< `StopIteration` exception. */ RUBY_EXTERN VALUE rb_eKeyError; /**< `KeyError` exception. */ RUBY_EXTERN VALUE rb_eRangeError; /**< `RangeError` exception. */ RUBY_EXTERN VALUE rb_eIOError; /**< `IOError` exception. */ RUBY_EXTERN VALUE rb_eRuntimeError; /**< `RuntimeError` exception. */ RUBY_EXTERN VALUE rb_eFrozenError; /**< `FrozenError` exception. */ RUBY_EXTERN VALUE rb_eSecurityError; /**< `SecurityError` exception. */ RUBY_EXTERN VALUE rb_eSystemCallError; /**< `SystemCallError` exception. */ RUBY_EXTERN VALUE rb_eThreadError; /**< `ThreadError` exception. */ RUBY_EXTERN VALUE rb_eTypeError; /**< `TypeError` exception. */ RUBY_EXTERN VALUE rb_eZeroDivError; /**< `ZeroDivisionError` exception. */ RUBY_EXTERN VALUE rb_eNotImpError; /**< `NotImplementedError` exception. */ RUBY_EXTERN VALUE rb_eNoMemError; /**< `NoMemoryError` exception. */ RUBY_EXTERN VALUE rb_eNoMethodError; /**< `NoMethodError` exception. */ RUBY_EXTERN VALUE rb_eFloatDomainError; /**< `FloatDomainError` exception. */ RUBY_EXTERN VALUE rb_eLocalJumpError; /**< `LocalJumpError` exception. */ RUBY_EXTERN VALUE rb_eSysStackError; /**< `SystemStackError` exception. */ RUBY_EXTERN VALUE rb_eRegexpError; /**< `RegexpError` exception. */ RUBY_EXTERN VALUE rb_eEncodingError; /**< `EncodingError` exception. */ RUBY_EXTERN VALUE rb_eEncCompatError; /**< `Encoding::CompatibilityError` exception. */ RUBY_EXTERN VALUE rb_eNoMatchingPatternError; /**< `NoMatchingPatternError` exception. */ RUBY_EXTERN VALUE rb_eNoMatchingPatternKeyError; /**< `NoMatchingPatternKeyError` exception. */ RUBY_EXTERN VALUE rb_eScriptError; /**< `ScriptError` exception. */ RUBY_EXTERN VALUE rb_eNameError; /**< `NameError` exception. */ RUBY_EXTERN VALUE rb_eSyntaxError; /**< `SyntaxError` exception. */ RUBY_EXTERN VALUE rb_eLoadError; /**< `LoadError` exception. */ RUBY_EXTERN VALUE rb_eMathDomainError; /**< `Math::DomainError` exception. */ /** * @} * @addtogroup object * @{ */ RUBY_EXTERN VALUE rb_stdin; /**< `STDIN` constant. */ RUBY_EXTERN VALUE rb_stdout; /**< `STDOUT` constant. */ RUBY_EXTERN VALUE rb_stderr; /**< `STDERR` constant. */ RBIMPL_ATTR_PURE() /** * Object to class mapping function. Every object have its class. This * function obtains that. * * @param[in] obj Target object to query. * @return The class of the given object. * * @internal * * This function is a super-duper hot path. Optimised targeting modern C * compilers and x86_64 architecture. */ static inline VALUE rb_class_of(VALUE obj) { if (! RB_SPECIAL_CONST_P(obj)) { return RBASIC_CLASS(obj); } else if (obj == RUBY_Qfalse) { return rb_cFalseClass; } else if (obj == RUBY_Qnil) { return rb_cNilClass; } else if (obj == RUBY_Qtrue) { return rb_cTrueClass; } else if (RB_FIXNUM_P(obj)) { return rb_cInteger; } else if (RB_STATIC_SYM_P(obj)) { return rb_cSymbol; } else if (RB_FLONUM_P(obj)) { return rb_cFloat; } #if !RUBY_DEBUG RBIMPL_UNREACHABLE_RETURN(Qfalse); #else RUBY_ASSERT_FAIL("unexpected type"); #endif } #define CLASS_OF rb_class_of /**< @old{rb_class_of} */ RBIMPL_SYMBOL_EXPORT_END() /** @} */ #endif /* RBIMPL_GLOBALS_H */ include/ruby/internal/value_type.h 0000644 00000034171 15152150504 0013316 0 ustar 00 #ifndef RBIMPL_VALUE_TYPE_H /*-*-C++-*-vi:se ft=cpp:*/ #define RBIMPL_VALUE_TYPE_H /** * @file * @author Ruby developers <ruby-core@ruby-lang.org> * @copyright This file is a part of the programming language Ruby. * Permission is hereby granted, to either redistribute and/or * modify this file, provided that the conditions mentioned in the * file COPYING are met. Consult the file for details. * @warning Symbols prefixed with either `RBIMPL` or `rbimpl` are * implementation details. Don't take them as canon. They could * rapidly appear then vanish. The name (path) of this header file * is also an implementation detail. Do not expect it to persist * at the place it is now. Developers are free to move it anywhere * anytime at will. * @note To ruby-core: remember that this header can be possibly * recursively included from extension libraries written in C++. * Do not expect for instance `__VA_ARGS__` is always available. * We assume C99 for ruby itself but we don't assume languages of * extension libraries. They could be written in C++98. * @brief Defines enum ::ruby_value_type. */ #include "ruby/internal/assume.h" #include "ruby/internal/attr/artificial.h" #include "ruby/internal/attr/cold.h" #include "ruby/internal/attr/enum_extensibility.h" #include "ruby/internal/attr/forceinline.h" #include "ruby/internal/attr/pure.h" #include "ruby/internal/cast.h" #include "ruby/internal/constant_p.h" #include "ruby/internal/core/rbasic.h" #include "ruby/internal/dllexport.h" #include "ruby/internal/error.h" #include "ruby/internal/has/builtin.h" #include "ruby/internal/special_consts.h" #include "ruby/internal/stdbool.h" #include "ruby/internal/value.h" #include "ruby/assert.h" #if defined(T_DATA) /* * :!BEWARE!: (Recent?) Solaris' <nfs/nfs.h> have conflicting definition of * T_DATA. Let us stop here. Please have a workaround like this: * * ```C * #include <ruby/ruby.h> // <- Include this one first. * #undef T_DATA // <- ... and stick to RUBY_T_DATA forever. * #include <nfs/nfs.h> // <- OS-provided T_DATA introduced. * ``` * * See also [ruby-core:4261] */ # error Bail out due to conflicting definition of T_DATA. #endif #define T_ARRAY RUBY_T_ARRAY /**< @old{RUBY_T_ARRAY} */ #define T_BIGNUM RUBY_T_BIGNUM /**< @old{RUBY_T_BIGNUM} */ #define T_CLASS RUBY_T_CLASS /**< @old{RUBY_T_CLASS} */ #define T_COMPLEX RUBY_T_COMPLEX /**< @old{RUBY_T_COMPLEX} */ #define T_DATA RUBY_T_DATA /**< @old{RUBY_T_DATA} */ #define T_FALSE RUBY_T_FALSE /**< @old{RUBY_T_FALSE} */ #define T_FILE RUBY_T_FILE /**< @old{RUBY_T_FILE} */ #define T_FIXNUM RUBY_T_FIXNUM /**< @old{RUBY_T_FIXNUM} */ #define T_FLOAT RUBY_T_FLOAT /**< @old{RUBY_T_FLOAT} */ #define T_HASH RUBY_T_HASH /**< @old{RUBY_T_HASH} */ #define T_ICLASS RUBY_T_ICLASS /**< @old{RUBY_T_ICLASS} */ #define T_IMEMO RUBY_T_IMEMO /**< @old{RUBY_T_IMEMO} */ #define T_MASK RUBY_T_MASK /**< @old{RUBY_T_MASK} */ #define T_MATCH RUBY_T_MATCH /**< @old{RUBY_T_MATCH} */ #define T_MODULE RUBY_T_MODULE /**< @old{RUBY_T_MODULE} */ #define T_MOVED RUBY_T_MOVED /**< @old{RUBY_T_MOVED} */ #define T_NIL RUBY_T_NIL /**< @old{RUBY_T_NIL} */ #define T_NODE RUBY_T_NODE /**< @old{RUBY_T_NODE} */ #define T_NONE RUBY_T_NONE /**< @old{RUBY_T_NONE} */ #define T_OBJECT RUBY_T_OBJECT /**< @old{RUBY_T_OBJECT} */ #define T_RATIONAL RUBY_T_RATIONAL /**< @old{RUBY_T_RATIONAL} */ #define T_REGEXP RUBY_T_REGEXP /**< @old{RUBY_T_REGEXP} */ #define T_STRING RUBY_T_STRING /**< @old{RUBY_T_STRING} */ #define T_STRUCT RUBY_T_STRUCT /**< @old{RUBY_T_STRUCT} */ #define T_SYMBOL RUBY_T_SYMBOL /**< @old{RUBY_T_SYMBOL} */ #define T_TRUE RUBY_T_TRUE /**< @old{RUBY_T_TRUE} */ #define T_UNDEF RUBY_T_UNDEF /**< @old{RUBY_T_UNDEF} */ #define T_ZOMBIE RUBY_T_ZOMBIE /**< @old{RUBY_T_ZOMBIE} */ #define BUILTIN_TYPE RB_BUILTIN_TYPE /**< @old{RB_BUILTIN_TYPE} */ #define DYNAMIC_SYM_P RB_DYNAMIC_SYM_P /**< @old{RB_DYNAMIC_SYM_P} */ #define RB_INTEGER_TYPE_P rb_integer_type_p /**< @old{rb_integer_type_p} */ #define SYMBOL_P RB_SYMBOL_P /**< @old{RB_SYMBOL_P} */ #define rb_type_p RB_TYPE_P /**< @alias{RB_TYPE_P} */ /** @cond INTERNAL_MACRO */ #define RB_BUILTIN_TYPE RB_BUILTIN_TYPE #define RB_DYNAMIC_SYM_P RB_DYNAMIC_SYM_P #define RB_FLOAT_TYPE_P RB_FLOAT_TYPE_P #define RB_SYMBOL_P RB_SYMBOL_P #define RB_TYPE_P RB_TYPE_P #define Check_Type Check_Type #if !RUBY_DEBUG # define RBIMPL_ASSERT_TYPE(v, t) RBIMPL_ASSERT_OR_ASSUME(RB_TYPE_P((v), (t))) #else # define RBIMPL_ASSERT_TYPE Check_Type #endif /** @endcond */ /** @old{rb_type} */ #define TYPE(_) RBIMPL_CAST((int)rb_type(_)) /** C-level type of an object. */ enum RBIMPL_ATTR_ENUM_EXTENSIBILITY(closed) ruby_value_type { RUBY_T_NONE = 0x00, /**< Non-object (swept etc.) */ RUBY_T_OBJECT = 0x01, /**< @see struct ::RObject */ RUBY_T_CLASS = 0x02, /**< @see struct ::RClass and ::rb_cClass */ RUBY_T_MODULE = 0x03, /**< @see struct ::RClass and ::rb_cModule */ RUBY_T_FLOAT = 0x04, /**< @see struct ::RFloat */ RUBY_T_STRING = 0x05, /**< @see struct ::RString */ RUBY_T_REGEXP = 0x06, /**< @see struct ::RRegexp */ RUBY_T_ARRAY = 0x07, /**< @see struct ::RArray */ RUBY_T_HASH = 0x08, /**< @see struct ::RHash */ RUBY_T_STRUCT = 0x09, /**< @see struct ::RStruct */ RUBY_T_BIGNUM = 0x0a, /**< @see struct ::RBignum */ RUBY_T_FILE = 0x0b, /**< @see struct ::RFile */ RUBY_T_DATA = 0x0c, /**< @see struct ::RTypedData */ RUBY_T_MATCH = 0x0d, /**< @see struct ::RMatch */ RUBY_T_COMPLEX = 0x0e, /**< @see struct ::RComplex */ RUBY_T_RATIONAL = 0x0f, /**< @see struct ::RRational */ RUBY_T_NIL = 0x11, /**< @see ::RUBY_Qnil */ RUBY_T_TRUE = 0x12, /**< @see ::RUBY_Qfalse */ RUBY_T_FALSE = 0x13, /**< @see ::RUBY_Qtrue */ RUBY_T_SYMBOL = 0x14, /**< @see struct ::RSymbol */ RUBY_T_FIXNUM = 0x15, /**< Integers formerly known as Fixnums. */ RUBY_T_UNDEF = 0x16, /**< @see ::RUBY_Qundef */ RUBY_T_IMEMO = 0x1a, /**< @see struct ::RIMemo */ RUBY_T_NODE = 0x1b, /**< @see struct ::RNode */ RUBY_T_ICLASS = 0x1c, /**< Hidden classes known as IClasses. */ RUBY_T_ZOMBIE = 0x1d, /**< @see struct ::RZombie */ RUBY_T_MOVED = 0x1e, /**< @see struct ::RMoved */ RUBY_T_MASK = 0x1f /**< Bitmask of ::ruby_value_type. */ }; RBIMPL_SYMBOL_EXPORT_BEGIN() RBIMPL_ATTR_COLD() /** * @private * * This was the old implementation of Check_Type(), but they diverged. This * one remains for theoretical backwards compatibility. People normally need * not use it. * * @param[in] obj An object. * @param[in] t A type. * @exception rb_eTypeError `obj` is not of type `t`. * @exception rb_eFatal `obj` is corrupt. * @post Upon successful return `obj` is guaranteed to have type `t`. * * @internal * * The second argument shall have been enum ::ruby_value_type. But at the time * matz designed this function he still used K&R C. There was no such thing * like a function prototype. We can no longer change this API. */ void rb_check_type(VALUE obj, int t); RBIMPL_SYMBOL_EXPORT_END() RBIMPL_ATTR_PURE_UNLESS_DEBUG() RBIMPL_ATTR_ARTIFICIAL() /** * Queries the type of the object. * * @param[in] obj Object in question. * @pre `obj` must not be a special constant. * @return The type of `obj`. */ static inline enum ruby_value_type RB_BUILTIN_TYPE(VALUE obj) { RBIMPL_ASSERT_OR_ASSUME(! RB_SPECIAL_CONST_P(obj)); #if 0 && defined __GNUC__ && !defined __clang__ /* Don't move the access to `flags` before the preceding * RB_SPECIAL_CONST_P check. */ __asm volatile("": : :"memory"); #endif VALUE ret = RBASIC(obj)->flags & RUBY_T_MASK; return RBIMPL_CAST((enum ruby_value_type)ret); } RBIMPL_ATTR_PURE_UNLESS_DEBUG() /** * Queries if the object is an instance of ::rb_cInteger. * * @param[in] obj Object in question. * @retval true It is. * @retval false It isn't. */ static inline bool rb_integer_type_p(VALUE obj) { if (RB_FIXNUM_P(obj)) { return true; } else if (RB_SPECIAL_CONST_P(obj)) { return false; } else { return RB_BUILTIN_TYPE(obj) == RUBY_T_BIGNUM; } } RBIMPL_ATTR_PURE_UNLESS_DEBUG() /** * Identical to RB_BUILTIN_TYPE(), except it can also accept special constants. * * @param[in] obj Object in question. * @return The type of `obj`. */ static inline enum ruby_value_type rb_type(VALUE obj) { if (! RB_SPECIAL_CONST_P(obj)) { return RB_BUILTIN_TYPE(obj); } else if (obj == RUBY_Qfalse) { return RUBY_T_FALSE; } else if (obj == RUBY_Qnil) { return RUBY_T_NIL; } else if (obj == RUBY_Qtrue) { return RUBY_T_TRUE; } else if (obj == RUBY_Qundef) { return RUBY_T_UNDEF; } else if (RB_FIXNUM_P(obj)) { return RUBY_T_FIXNUM; } else if (RB_STATIC_SYM_P(obj)) { return RUBY_T_SYMBOL; } else { RBIMPL_ASSUME(RB_FLONUM_P(obj)); return RUBY_T_FLOAT; } } RBIMPL_ATTR_PURE_UNLESS_DEBUG() RBIMPL_ATTR_ARTIFICIAL() /** * Queries if the object is an instance of ::rb_cFloat. * * @param[in] obj Object in question. * @retval true It is. * @retval false It isn't. */ static inline bool RB_FLOAT_TYPE_P(VALUE obj) { if (RB_FLONUM_P(obj)) { return true; } else if (RB_SPECIAL_CONST_P(obj)) { return false; } else { return RB_BUILTIN_TYPE(obj) == RUBY_T_FLOAT; } } RBIMPL_ATTR_PURE_UNLESS_DEBUG() RBIMPL_ATTR_ARTIFICIAL() /** * Queries if the object is a dynamic symbol. * * @param[in] obj Object in question. * @retval true It is. * @retval false It isn't. */ static inline bool RB_DYNAMIC_SYM_P(VALUE obj) { if (RB_SPECIAL_CONST_P(obj)) { return false; } else { return RB_BUILTIN_TYPE(obj) == RUBY_T_SYMBOL; } } RBIMPL_ATTR_PURE_UNLESS_DEBUG() RBIMPL_ATTR_ARTIFICIAL() /** * Queries if the object is an instance of ::rb_cSymbol. * * @param[in] obj Object in question. * @retval true It is. * @retval false It isn't. */ static inline bool RB_SYMBOL_P(VALUE obj) { return RB_STATIC_SYM_P(obj) || RB_DYNAMIC_SYM_P(obj); } RBIMPL_ATTR_PURE_UNLESS_DEBUG() RBIMPL_ATTR_ARTIFICIAL() RBIMPL_ATTR_FORCEINLINE() /** * @private * * This is an implementation detail of RB_TYPE_P(). Just don't use it. * * @param[in] obj An object. * @param[in] t A type. * @retval true `obj` is of type `t`. * @retval false Otherwise. */ static bool rbimpl_RB_TYPE_P_fastpath(VALUE obj, enum ruby_value_type t) { if (t == RUBY_T_TRUE) { return obj == RUBY_Qtrue; } else if (t == RUBY_T_FALSE) { return obj == RUBY_Qfalse; } else if (t == RUBY_T_NIL) { return obj == RUBY_Qnil; } else if (t == RUBY_T_UNDEF) { return obj == RUBY_Qundef; } else if (t == RUBY_T_FIXNUM) { return RB_FIXNUM_P(obj); } else if (t == RUBY_T_SYMBOL) { return RB_SYMBOL_P(obj); } else if (t == RUBY_T_FLOAT) { return RB_FLOAT_TYPE_P(obj); } else if (RB_SPECIAL_CONST_P(obj)) { return false; } else if (t == RB_BUILTIN_TYPE(obj)) { return true; } else { return false; } } RBIMPL_ATTR_PURE_UNLESS_DEBUG() RBIMPL_ATTR_ARTIFICIAL() /** * Queries if the given object is of given type. * * @param[in] obj An object. * @param[in] t A type. * @retval true `obj` is of type `t`. * @retval false Otherwise. * * @internal * * This function is a super-duper hot path. Optimised targeting modern C * compilers and x86_64 architecture. */ static inline bool RB_TYPE_P(VALUE obj, enum ruby_value_type t) { if (RBIMPL_CONSTANT_P(t)) { return rbimpl_RB_TYPE_P_fastpath(obj, t); } else { return t == rb_type(obj); } } /** @cond INTERNAL_MACRO */ /* Clang, unlike GCC, cannot propagate __builtin_constant_p beyond function * boundary. */ #if defined(__clang__) # undef RB_TYPE_P # define RB_TYPE_P(obj, t) \ (RBIMPL_CONSTANT_P(t) ? \ rbimpl_RB_TYPE_P_fastpath((obj), (t)) : \ (RB_TYPE_P)((obj), (t))) #endif /* clang 3.x (4.2 compatible) can't eliminate CSE of RB_BUILTIN_TYPE * in inline function and caller function * See also 8998c06461ea0bef11b3aeb30b6d2ab71c8762ba */ #if RBIMPL_COMPILER_BEFORE(Clang, 4, 0, 0) # undef rb_integer_type_p # define rb_integer_type_p(obj) \ __extension__ ({ \ const VALUE integer_type_obj = (obj); \ (RB_FIXNUM_P(integer_type_obj) || \ (!RB_SPECIAL_CONST_P(integer_type_obj) && \ RB_BUILTIN_TYPE(integer_type_obj) == RUBY_T_BIGNUM)); \ }) #endif /** @endcond */ RBIMPL_ATTR_PURE() RBIMPL_ATTR_ARTIFICIAL() /** * @private * Defined in ruby/internal/core/rtypeddata.h */ static inline bool rbimpl_rtypeddata_p(VALUE obj); RBIMPL_ATTR_ARTIFICIAL() /** * Identical to RB_TYPE_P(), except it raises exceptions on predication * failure. * * @param[in] v An object. * @param[in] t A type. * @exception rb_eTypeError `obj` is not of type `t`. * @exception rb_eFatal `obj` is corrupt. * @post Upon successful return `obj` is guaranteed to have type `t`. */ static inline void Check_Type(VALUE v, enum ruby_value_type t) { if (RB_UNLIKELY(! RB_TYPE_P(v, t))) { goto unexpected_type; } else if (t == RUBY_T_DATA && rbimpl_rtypeddata_p(v)) { /* Typed data is not simple `T_DATA`, see `rb_check_type` */ goto unexpected_type; } else { return; } unexpected_type: rb_unexpected_type(v, t); } #endif /* RBIMPL_VALUE_TYPE_H */ include/ruby/internal/constant_p.h 0000644 00000003547 15152150504 0013314 0 ustar 00 #ifndef RBIMPL_CONSTANT_P_H /*-*-C++-*-vi:se ft=cpp:*/ #define RBIMPL_CONSTANT_P_H /** * @file * @author Ruby developers <ruby-core@ruby-lang.org> * @copyright This file is a part of the programming language Ruby. * Permission is hereby granted, to either redistribute and/or * modify this file, provided that the conditions mentioned in the * file COPYING are met. Consult the file for details. * @warning Symbols prefixed with either `RBIMPL` or `rbimpl` are * implementation details. Don't take them as canon. They could * rapidly appear then vanish. The name (path) of this header file * is also an implementation detail. Do not expect it to persist * at the place it is now. Developers are free to move it anywhere * anytime at will. * @note To ruby-core: remember that this header can be possibly * recursively included from extension libraries written in C++. * Do not expect for instance `__VA_ARGS__` is always available. * We assume C99 for ruby itself but we don't assume languages of * extension libraries. They could be written in C++98. * @brief Defines #RBIMPL_CONSTANT_P. * * Note that __builtin_constant_p can be applicable inside of inline functions, * according to GCC manual. Clang lacks that feature, though. * * @see https://bugs.llvm.org/show_bug.cgi?id=4898 * @see https://gcc.gnu.org/onlinedocs/gcc/Other-Builtins.html */ #include "ruby/internal/has/builtin.h" /** Wraps (or simulates) `__builtin_constant_p` */ #if RBIMPL_HAS_BUILTIN(__builtin_constant_p) # define RBIMPL_CONSTANT_P(expr) __builtin_constant_p(expr) #else # define RBIMPL_CONSTANT_P(expr) 0 #endif #endif /* RBIMPL_CONSTANT_P_H */ include/ruby/digest.h 0000644 00000003437 15152150504 0010605 0 ustar 00 /************************************************ digest.h - header file for ruby digest modules $Author$ created at: Fri May 25 08:54:56 JST 2001 Copyright (C) 2001-2006 Akinori MUSHA $RoughId: digest.h,v 1.3 2001/07/13 15:38:27 knu Exp $ $Id$ ************************************************/ #include "ruby.h" #define RUBY_DIGEST_API_VERSION 3 typedef int (*rb_digest_hash_init_func_t)(void *); typedef void (*rb_digest_hash_update_func_t)(void *, unsigned char *, size_t); typedef int (*rb_digest_hash_finish_func_t)(void *, unsigned char *); typedef struct { int api_version; size_t digest_len; size_t block_len; size_t ctx_size; rb_digest_hash_init_func_t init_func; rb_digest_hash_update_func_t update_func; rb_digest_hash_finish_func_t finish_func; } rb_digest_metadata_t; #define DEFINE_UPDATE_FUNC_FOR_UINT(name) \ void \ rb_digest_##name##_update(void *ctx, unsigned char *ptr, size_t size) \ { \ const unsigned int stride = 16384; \ \ for (; size > stride; size -= stride, ptr += stride) { \ name##_Update(ctx, ptr, stride); \ } \ /* Since size <= stride, size should fit into an unsigned int */ \ if (size > 0) name##_Update(ctx, ptr, (unsigned int)size); \ } #define DEFINE_FINISH_FUNC_FROM_FINAL(name) \ int \ rb_digest_##name##_finish(void *ctx, unsigned char *ptr) \ { \ return name##_Final(ptr, ctx); \ } static inline VALUE rb_digest_namespace(void) { rb_require("digest"); return rb_path2class("Digest"); } static inline ID rb_id_metadata(void) { return rb_intern_const("metadata"); } static inline VALUE rb_digest_make_metadata(const rb_digest_metadata_t *meta) { #undef RUBY_UNTYPED_DATA_WARNING #define RUBY_UNTYPED_DATA_WARNING 0 return rb_obj_freeze(Data_Wrap_Struct(0, 0, 0, (void *)meta)); } include/ruby/assert.h 0000644 00000017064 15152150504 0010630 0 ustar 00 #ifndef RUBY_ASSERT_H /*-*-C++-*-vi:se ft=cpp:*/ #define RUBY_ASSERT_H /** * @file * @author Ruby developers <ruby-core@ruby-lang.org> * @date Wed May 18 00:21:44 JST 1994 * @copyright This file is a part of the programming language Ruby. * Permission is hereby granted, to either redistribute and/or * modify this file, provided that the conditions mentioned in the * file COPYING are met. Consult the file for details. * @warning Symbols prefixed with either `RBIMPL` or `rbimpl` are * implementation details. Don't take them as canon. They could * rapidly appear then vanish. The name (path) of this header file * is also an implementation detail. Do not expect it to persist * at the place it is now. Developers are free to move it anywhere * anytime at will. * @note To ruby-core: remember that this header can be possibly * recursively included from extension libraries written in C++. * Do not expect for instance `__VA_ARGS__` is always available. * We assume C99 for ruby itself but we don't assume languages of * extension libraries. They could be written in C++98. */ #include "ruby/internal/assume.h" #include "ruby/internal/attr/cold.h" #include "ruby/internal/attr/noreturn.h" #include "ruby/internal/cast.h" #include "ruby/internal/dllexport.h" #include "ruby/backward/2/assume.h" /* RUBY_NDEBUG is very simple: after everything described below are done, * define it with either NDEBUG is undefined (=0) or defined (=1). It is truly * subordinate. * * RUBY_DEBUG versus NDEBUG is complicated. Assertions shall be: * * | -UNDEBUG | -DNDEBUG * ---------------+----------+--------- * -URUBY_DEBUG | (*1) | disabled * -DRUBY_DEBUG=0 | disabled | disabled * -DRUBY_DEBUG=1 | enabled | (*2) * -DRUBY_DEBUG | enabled | (*2) * * where: * * - (*1): Assertions shall be silently disabled, no warnings, in favour of * commit 21991e6ca59274e41a472b5256bd3245f6596c90. * * - (*2): Compile-time warnings shall be issued. */ /** @cond INTERNAL_MACRO */ /* * Pro tip: `!!RUBY_DEBUG-1` expands to... * * - `!!(-1)` (== `!0` == `1`) when RUBY_DEBUG is defined to be empty, * - `(!!0)-1` (== `0-1` == `-1`) when RUBY_DEBUG is defined as 0, and * - `(!!n)-1` (== `1-1` == `0`) when RUBY_DEBUG is defined as something else. */ #if ! defined(RUBY_DEBUG) # define RBIMPL_RUBY_DEBUG 0 #elif !!RUBY_DEBUG-1 < 0 # define RBIMPL_RUBY_DEBUG 0 #else # define RBIMPL_RUBY_DEBUG 1 #endif /* * ISO/IEC 9899 (all past versions) says that "If NDEBUG is defined as a macro * name at the point in the source file where <assert.h> is included, ..." * which means we must not take its defined value into account. */ #if defined(NDEBUG) # define RBIMPL_NDEBUG 1 #else # define RBIMPL_NDEBUG 0 #endif /** @endcond */ /* Here we go... */ #undef RUBY_DEBUG #undef RUBY_NDEBUG #undef NDEBUG #if defined(__DOXYGEN__) # /** Define this macro when you want assertions. */ # define RUBY_DEBUG 0 # /** Define this macro when you don't want assertions. */ # define NDEBUG # /** This macro is basically the same as #NDEBUG */ # define RUBY_NDEBUG 1 #elif (RBIMPL_NDEBUG == 1) && (RBIMPL_RUBY_DEBUG == 0) # /* Assertions disabled as per request, no conflicts. */ # define RUBY_DEBUG 0 # define RUBY_NDEBUG 1 # define NDEBUG #elif (RBIMPL_NDEBUG == 0) && (RBIMPL_RUBY_DEBUG == 1) # /* Assertions enabled as per request, no conflicts. */ # define RUBY_DEBUG 1 # define RUBY_NDEBUG 0 # /* keep NDEBUG undefined */ #elif (RBIMPL_NDEBUG == 0) && (RBIMPL_RUBY_DEBUG == 0) # /* The (*1) situation in above diagram. */ # define RUBY_DEBUG 0 # define RUBY_NDEBUG 1 # define NDEBUG #elif (RBIMPL_NDEBUG == 1) && (RBIMPL_RUBY_DEBUG == 1) # /* The (*2) situation in above diagram. */ # define RUBY_DEBUG 1 # define RUBY_NDEBUG 0 # /* keep NDEBUG undefined */ # if defined(_MSC_VER) # pragma message("NDEBUG is ignored because RUBY_DEBUG>0.") # elif defined(__GNUC__) # pragma GCC warning "NDEBUG is ignored because RUBY_DEBUG>0." # else # error NDEBUG is ignored because RUBY_DEBUG>0. # endif #endif #undef RBIMPL_NDEBUG #undef RBIMPL_RUBY_DEBUG /** @cond INTERNAL_MACRO */ #define RBIMPL_ASSERT_NOTHING RBIMPL_CAST((void)0) RBIMPL_SYMBOL_EXPORT_BEGIN() RBIMPL_ATTR_NORETURN() RBIMPL_ATTR_COLD() void rb_assert_failure(const char *file, int line, const char *name, const char *expr); RBIMPL_SYMBOL_EXPORT_END() #ifdef RUBY_FUNCTION_NAME_STRING # define RBIMPL_ASSERT_FUNC RUBY_FUNCTION_NAME_STRING #else # define RBIMPL_ASSERT_FUNC RBIMPL_CAST((const char *)0) #endif /** @endcond */ /** * Prints the given message, and terminates the entire process abnormally. * * @param mesg The message to display. */ #define RUBY_ASSERT_FAIL(mesg) \ rb_assert_failure(__FILE__, __LINE__, RBIMPL_ASSERT_FUNC, mesg) /** * Asserts that the expression is truthy. If not aborts with the message. * * @param expr What supposedly evaluates to true. * @param mesg The message to display on failure. */ #define RUBY_ASSERT_MESG(expr, mesg) \ (RB_LIKELY(expr) ? RBIMPL_ASSERT_NOTHING : RUBY_ASSERT_FAIL(mesg)) /** * A variant of #RUBY_ASSERT that does not interface with #RUBY_DEBUG. * * @copydetails #RUBY_ASSERT */ #define RUBY_ASSERT_ALWAYS(expr) RUBY_ASSERT_MESG((expr), #expr) /** * Asserts that the given expression is truthy if and only if #RUBY_DEBUG is truthy. * * @param expr What supposedly evaluates to true. */ #if RUBY_DEBUG # define RUBY_ASSERT(expr) RUBY_ASSERT_MESG((expr), #expr) #else # define RUBY_ASSERT(expr) RBIMPL_ASSERT_NOTHING #endif /** * A variant of #RUBY_ASSERT that interfaces with #NDEBUG instead of * #RUBY_DEBUG. This almost resembles `assert` C standard macro, except minor * implementation details. * * @copydetails #RUBY_ASSERT */ /* Currently `RUBY_DEBUG == ! defined(NDEBUG)` is always true. There is no * difference any longer between this one and `RUBY_ASSERT`. */ #if defined(NDEBUG) # define RUBY_ASSERT_NDEBUG(expr) RBIMPL_ASSERT_NOTHING #else # define RUBY_ASSERT_NDEBUG(expr) RUBY_ASSERT_MESG((expr), #expr) #endif /** * @copydoc #RUBY_ASSERT_WHEN * @param mesg The message to display on failure. */ #if RUBY_DEBUG # define RUBY_ASSERT_MESG_WHEN(cond, expr, mesg) RUBY_ASSERT_MESG((expr), (mesg)) #else # define RUBY_ASSERT_MESG_WHEN(cond, expr, mesg) \ ((cond) ? RUBY_ASSERT_MESG((expr), (mesg)) : RBIMPL_ASSERT_NOTHING) #endif /** * A variant of #RUBY_ASSERT that asserts when either #RUBY_DEBUG or `cond` * parameter is truthy. * * @param cond Extra condition that shall hold for assertion to take effect. * @param expr What supposedly evaluates to true. */ #define RUBY_ASSERT_WHEN(cond, expr) RUBY_ASSERT_MESG_WHEN((cond), (expr), #expr) /** * This is either #RUBY_ASSERT or #RBIMPL_ASSUME, depending on #RUBY_DEBUG. * * @copydetails #RUBY_ASSERT */ #if RUBY_DEBUG # define RBIMPL_ASSERT_OR_ASSUME(expr) RUBY_ASSERT_ALWAYS(expr) #elif RBIMPL_COMPILER_BEFORE(Clang, 7, 0, 0) # /* See commit 67d259c5dccd31fe49d417fec169977712ffdf10 */ # define RBIMPL_ASSERT_OR_ASSUME(expr) RBIMPL_ASSERT_NOTHING #elif defined(RUBY_ASSERT_NOASSUME) # /* See commit d300a734414ef6de7e8eb563b7cc4389c455ed08 */ # define RBIMPL_ASSERT_OR_ASSUME(expr) RBIMPL_ASSERT_NOTHING #elif ! defined(RBIMPL_HAVE___ASSUME) # define RBIMPL_ASSERT_OR_ASSUME(expr) RBIMPL_ASSERT_NOTHING #else # define RBIMPL_ASSERT_OR_ASSUME(expr) RBIMPL_ASSUME(expr) #endif #endif /* RUBY_ASSERT_H */ include/ruby/ruby.h 0000644 00000035370 15152150504 0010310 0 ustar 00 #ifndef RUBY_RUBY_H /*-*-C++-*-vi:se ft=cpp:*/ #define RUBY_RUBY_H 1 /** * @file * @author $Author$ * @date Thu Jun 10 14:26:32 JST 1993 * @copyright Copyright (C) 1993-2008 Yukihiro Matsumoto * @copyright Copyright (C) 2000 Network Applied Communication Laboratory, Inc. * @copyright Copyright (C) 2000 Information-technology Promotion Agency, Japan * @copyright This file is a part of the programming language Ruby. * Permission is hereby granted, to either redistribute and/or * modify this file, provided that the conditions mentioned in the * file COPYING are met. Consult the file for details. */ #include "ruby/internal/config.h" /* @shyouhei doesn't understand why we need <intrinsics.h> at this very * beginning of the entire <ruby.h> circus. */ #ifdef HAVE_INTRINSICS_H # include <intrinsics.h> #endif #include <stdarg.h> #include "defines.h" #include "ruby/internal/abi.h" #include "ruby/internal/anyargs.h" #include "ruby/internal/arithmetic.h" #include "ruby/internal/core.h" #include "ruby/internal/ctype.h" #include "ruby/internal/dllexport.h" #include "ruby/internal/error.h" #include "ruby/internal/eval.h" #include "ruby/internal/event.h" #include "ruby/internal/fl_type.h" #include "ruby/internal/gc.h" #include "ruby/internal/glob.h" #include "ruby/internal/globals.h" #include "ruby/internal/has/warning.h" #include "ruby/internal/interpreter.h" #include "ruby/internal/iterator.h" #include "ruby/internal/memory.h" #include "ruby/internal/method.h" #include "ruby/internal/module.h" #include "ruby/internal/newobj.h" #include "ruby/internal/scan_args.h" #include "ruby/internal/special_consts.h" #include "ruby/internal/symbol.h" #include "ruby/internal/value.h" #include "ruby/internal/value_type.h" #include "ruby/internal/variable.h" #include "ruby/assert.h" #include "ruby/backward/2/assume.h" #include "ruby/backward/2/inttypes.h" #include "ruby/backward/2/limits.h" RBIMPL_SYMBOL_EXPORT_BEGIN() /* Module#methods, #singleton_methods and so on return Symbols */ /** * @private * * @deprecated This macro once was a thing in the old days, but makes no sense * any longer today. Exists here for backwards compatibility * only. You can safely forget about it. */ #define USE_SYMBOL_AS_METHOD_NAME 1 /** * Converts an object to a path. It first tries `#to_path` method if any, then * falls back to `#to_str` method. * * @param[in] obj Arbitrary ruby object. * @exception rb_eArgError `obj` contains a NUL byte. * @exception rb_eTypeError `obj` is not path-ish. * @exception rb_eEncCompatError No encoding conversion from `obj` to path. * @return Converted path object. */ VALUE rb_get_path(VALUE obj); /** * Ensures that the parameter object is a path. * * @param[in,out] v Arbitrary ruby object. * @exception rb_eArgError `v` contains a NUL byte. * @exception rb_eTypeError `v` is not path-ish. * @exception rb_eEncCompatError `v` is not path-compatible. * @post `v` is a path. */ #define FilePathValue(v) (RB_GC_GUARD(v) = rb_get_path(v)) /** * @deprecated This function is an alias of rb_get_path() now. The part that * did "no_checksafe" was deleted. It remains here because of no * harm. */ VALUE rb_get_path_no_checksafe(VALUE); /** * This macro actually does the same thing as #FilePathValue now. The "String" * part indicates that this is for when a string is treated like a pathname, * rather than the actual pathname on the file systems. For examples: * `Dir.fnmatch?`, `File.join`, `File.basename`, etc. */ #define FilePathStringValue(v) ((v) = rb_get_path(v)) /** @cond INTERNAL_MACRO */ #if defined(HAVE_BUILTIN___BUILTIN_CONSTANT_P) && defined(HAVE_STMT_AND_DECL_IN_EXPR) # define rb_varargs_argc_check_runtime(argc, vargc) \ (((argc) <= (vargc)) ? (argc) : \ (rb_fatal("argc(%d) exceeds actual arguments(%d)", \ argc, vargc), 0)) # define rb_varargs_argc_valid_p(argc, vargc) \ ((argc) == 0 ? (vargc) <= 1 : /* [ruby-core:85266] [Bug #14425] */ \ (argc) == (vargc)) # if defined(HAVE_BUILTIN___BUILTIN_CHOOSE_EXPR_CONSTANT_P) # ifdef HAVE_ATTRIBUTE_ERRORFUNC ERRORFUNC((" argument length doesn't match"), int rb_varargs_bad_length(int,int)); # else # define rb_varargs_bad_length(argc, vargc) \ ((argc)/rb_varargs_argc_valid_p(argc, vargc)) # endif # define rb_varargs_argc_check(argc, vargc) \ __builtin_choose_expr(__builtin_constant_p(argc), \ (rb_varargs_argc_valid_p(argc, vargc) ? (argc) : \ rb_varargs_bad_length(argc, vargc)), \ rb_varargs_argc_check_runtime(argc, vargc)) # else # define rb_varargs_argc_check(argc, vargc) \ rb_varargs_argc_check_runtime(argc, vargc) # endif #endif /** @endcond */ /** * Queries the name of the passed class. * * @param[in] klass An instance of a class. * @return The name of `klass`. * @note Return value is managed by our GC. Don't free. */ const char *rb_class2name(VALUE klass); /** * Queries the name of the class of the passed object. * * @param[in] obj Arbitrary ruby object. * @return The name of the class of `obj`. * @note Return value is managed by our GC. Don't free. */ const char *rb_obj_classname(VALUE obj); /** * Inspects an object. It first calls the argument's `#inspect` method, then * feeds its result string into ::rb_stdout. * * This is identical to Ruby level `Kernel#p`, except it takes only one object. * * @internal * * Above description is in fact inaccurate. This API interfaces with Ractors. */ void rb_p(VALUE obj); /** * This function is an optimised version of calling `#==`. It checks equality * between two objects by first doing a fast identity check using using C's * `==` (same as `BasicObject#equal?`). If that check fails, it calls `#==` * dynamically. This optimisation actually affects semantics, because when * `#==` returns false for the same object obj, `rb_equal(obj, obj)` would * still return true. This happens for `Float::NAN`, where `Float::NAN == * Float::NAN` is `false`, but `rb_equal(Float::NAN, Float::NAN)` is `true`. * * @param[in] lhs Comparison LHS. * @param[in] rhs Comparison RHS. * @retval RUBY_Qtrue They are the same. * @retval RUBY_Qfalse They are different. */ VALUE rb_equal(VALUE lhs, VALUE rhs); /** * Identical to rb_require_string(), except it takes C's string instead of * Ruby's. * * @param[in] feature Name of a feature, e.g. `"json"`. * @exception rb_eLoadError No such feature. * @exception rb_eRuntimeError `$"` is frozen; unable to push. * @retval RUBY_Qtrue The feature is loaded for the first time. * @retval RUBY_Qfalse The feature has already been loaded. * @post `$"` is updated. */ VALUE rb_require(const char *feature); #include "ruby/intern.h" /** * @private * * @deprecated This macro once was a thing in the old days, but makes no sense * any longer today. Exists here for backwards compatibility * only. You can safely forget about it. */ #define RUBY_VM 1 /* YARV */ /** * @private * * @deprecated This macro once was a thing in the old days, but makes no sense * any longer today. Exists here for backwards compatibility * only. You can safely forget about it. */ #define HAVE_NATIVETHREAD /** * Queries if the thread which calls this function is a ruby's thread. * "Ruby's" in this context is a thread created using one of our APIs like * rb_thread_create(). There are distinctions between ruby's and other * threads. For instance calling ruby methods are allowed only from inside of * a ruby's thread. * * @retval 1 The current thread is a Ruby's thread. * @retval 0 The current thread is a random thread from outside of Ruby. */ int ruby_native_thread_p(void); /** * @private * * This macro is for internal use. Must be a mistake to place here. */ #define InitVM(ext) {void InitVM_##ext(void);InitVM_##ext();} RBIMPL_ATTR_NONNULL((3)) RBIMPL_ATTR_FORMAT(RBIMPL_PRINTF_FORMAT, 3, 4) /** * Our own locale-insensitive version of `snprintf(3)`. It can also be seen as * a routine identical to rb_sprintf(), except it writes back to the passed * buffer instead of allocating a new Ruby object. * * @param[out] str Return buffer * @param[in] n Number of bytes of `str`. * @param[in] fmt A `printf`-like format specifier. * @param[in] ... Variadic number of contents to format. * @return Number of bytes that would have been written to `str`, if `n` * was large enough. Comparing this to `n` can give you insights * that the buffer is too small or too big. Especially passing 0 * to `n` gives you the exact number of bytes necessary to hold * the result string without writing anything to anywhere. * @post `str` holds up to `n-1` bytes of formatted contents (and the * terminating NUL character.) */ int ruby_snprintf(char *str, size_t n, char const *fmt, ...); RBIMPL_ATTR_NONNULL((3)) RBIMPL_ATTR_FORMAT(RBIMPL_PRINTF_FORMAT, 3, 0) /** * Identical to ruby_snprintf(), except it takes a `va_list`. It can also be * seen as a routine identical to rb_vsprintf(), except it writes back to the * passed buffer instead of allocating a new Ruby object. * * @param[out] str Return buffer * @param[in] n Number of bytes of `str`. * @param[in] fmt A `printf`-like format specifier. * @param[in] ap Contents to format. * @return Number of bytes that would have been written to `str`, if `n` * was large enough. Comparing this to `n` can give you insights * that the buffer is too small or too big. Especially passing 0 * to `n` gives you the exact number of bytes necessary to hold * the result string without writing anything to anywhere. * @post `str` holds up to `n-1` bytes of formatted contents (and the * terminating NUL character.) */ int ruby_vsnprintf(char *str, size_t n, char const *fmt, va_list ap); #include <errno.h> /** * @name Errno handling routines for userland threads * @note POSIX chapter 2 section 3 states that for each thread of a process, * the value of `errno` shall not be affected by function calls or * assignments to `errno` by other threads. * * Soooo this `#define errno` below seems like a noob mistake at first sight. * If you look at its actual implementation, the functions are just adding one * level of indirection. It doesn't make any sense sorry? But yes! @ko1 told * @shyouhei that this is inevitable. * * The ultimate reason is because Ruby now has N:M threads implemented. * Threads of that sort change their context in user land. A function can be * "transferred" between threads in middle of their executions. Let us for * instance consider: * * ```cxx * void foo() * { * auto i = errno; * close(0); * errno = i; * } * ``` * * This function (if ran under our Ractor) could change its running thread at * the `close` function. But the two `errno` invocations are different! Look * how the source code above is compiled by clang 17 with `-O3` flag @ Linux: * * ``` * foo(int): # @foo(int) * push rbp * push r14 * push rbx * mov ebx, edi * call __errno_location@PLT * mov r14, rax * mov ebp, dword ptr [rax] * mov edi, ebx * call close@PLT * mov dword ptr [r14], ebp * pop rbx * pop r14 * pop rbp * ret * ``` * * Notice how `__errno_location@PLT` is `call`-ed only once. The compiler * assumes that the location of `errno` does not change during a function call. * Sadly this is no longer true for us. The `close@PLT` now changes threads, * which should also change where `errno` is stored. * * With the `#define errno` below the compilation result changes to this: * * ``` * foo(int): # @foo(int) * push rbp * push rbx * push rax * mov ebx, edi * call rb_errno_ptr()@PLT * mov ebp, dword ptr [rax] * mov edi, ebx * call close@PLT * call rb_errno_ptr()@PLT * mov dword ptr [rax], ebp * add rsp, 8 * pop rbx * pop rbp * ret * ``` * * Which fixes the problem. */ /** * Identical to system `errno`. * * @return The last set `errno` number. */ int rb_errno(void); /** * Set the errno. * * @param err New `errno`. * @post `errno` is now set to `err`. */ void rb_errno_set(int err); /** * The location of `errno` * * @return The (thread-specific) location of `errno`. */ int *rb_errno_ptr(void); /** * Not sure if it is necessary for extension libraries but this is where the * "bare" errno is located. * * @return The location of `errno`. */ static inline int * rb_orig_errno_ptr(void) { return &errno; } #define rb_orig_errno errno /**< System-provided original `errno`. */ #undef errno #define errno (*rb_errno_ptr()) /**< Ractor-aware version of `errno`. */ /** @} */ /** @cond INTERNAL_MACRO */ #if RBIMPL_HAS_WARNING("-Wgnu-zero-variadic-macro-arguments") # /* Skip it; clang -pedantic doesn't like the following */ #elif defined(__GNUC__) && defined(HAVE_VA_ARGS_MACRO) && defined(__OPTIMIZE__) # define rb_yield_values(argc, ...) \ __extension__({ \ const int rb_yield_values_argc = (argc); \ const VALUE rb_yield_values_args[] = {__VA_ARGS__}; \ const int rb_yield_values_nargs = \ (int)(sizeof(rb_yield_values_args) / sizeof(VALUE)); \ rb_yield_values2( \ rb_varargs_argc_check(rb_yield_values_argc, rb_yield_values_nargs), \ rb_yield_values_nargs ? rb_yield_values_args : NULL); \ }) # define rb_funcall(recv, mid, argc, ...) \ __extension__({ \ const int rb_funcall_argc = (argc); \ const VALUE rb_funcall_args[] = {__VA_ARGS__}; \ const int rb_funcall_nargs = \ (int)(sizeof(rb_funcall_args) / sizeof(VALUE)); \ rb_funcallv(recv, mid, \ rb_varargs_argc_check(rb_funcall_argc, rb_funcall_nargs), \ rb_funcall_nargs ? rb_funcall_args : NULL); \ }) #endif /** @endcond */ #ifndef RUBY_DONT_SUBST #include "ruby/subst.h" #endif #if !defined RUBY_EXPORT && !defined RUBY_NO_OLD_COMPATIBILITY # include "ruby/backward.h" #endif RBIMPL_SYMBOL_EXPORT_END() #endif /* RUBY_RUBY_H */ include/ruby/random.h 0000644 00000027006 15152150504 0010604 0 ustar 00 #ifndef RUBY_RANDOM_H /*-*-C++-*-vi:se ft=cpp:*/ #define RUBY_RANDOM_H 1 /** * @file * @date Sat May 7 11:51:14 JST 2016 * @copyright 2007-2020 Yukihiro Matsumoto * @copyright This file is a part of the programming language Ruby. * Permission is hereby granted, to either redistribute and/or * modify this file, provided that the conditions mentioned in the * file COPYING are met. Consult the file for details. * * This is a set of APIs to roll your own subclass of ::rb_cRandom. An * illustrative example of such PRNG can be found at * `ext/-test-/random/loop.c`. */ #include "ruby/ruby.h" /* * version * 0: before versioning; deprecated * 1: added version, flags and init_32bit function */ #define RUBY_RANDOM_INTERFACE_VERSION_MAJOR 1 #define RUBY_RANDOM_INTERFACE_VERSION_MINOR 0 #define RUBY_RANDOM_PASTE_VERSION_SUFFIX(x, y, z) x##_##y##_##z #define RUBY_RANDOM_WITH_VERSION_SUFFIX(name, major, minor) \ RUBY_RANDOM_PASTE_VERSION_SUFFIX(name, major, minor) #define rb_random_data_type \ RUBY_RANDOM_WITH_VERSION_SUFFIX(rb_random_data_type, \ RUBY_RANDOM_INTERFACE_VERSION_MAJOR, \ RUBY_RANDOM_INTERFACE_VERSION_MINOR) #define RUBY_RANDOM_INTERFACE_VERSION_INITIALIZER \ {RUBY_RANDOM_INTERFACE_VERSION_MAJOR, RUBY_RANDOM_INTERFACE_VERSION_MINOR} #define RUBY_RANDOM_INTERFACE_VERSION_MAJOR_MAX 0xff #define RUBY_RANDOM_INTERFACE_VERSION_MINOR_MAX 0xff RBIMPL_SYMBOL_EXPORT_BEGIN() /** * Base components of the random interface. * * @internal * * Ideally this could be an empty class if we could assume C++, but in C a * struct must have at least one field. */ struct rb_random_struct { /** Seed, passed through e.g. `Random.new` */ VALUE seed; }; typedef struct rb_random_struct rb_random_t; /**< @see ::rb_random_struct */ RBIMPL_ATTR_NONNULL(()) /** * This is the type of functions called when your random object is initialised. * Passed buffer is the seed object basically. But in Ruby a number can be * really big. This type of functions accept such big integers as a series of * machine words. * * @param[out] rng Your random struct to fill in. * @param[in] buf Seed, maybe converted from a bignum. * @param[in] len Number of words of `buf`. * @post `rng` is initialised using the passed seeds. */ typedef void rb_random_init_func(rb_random_t *rng, const uint32_t *buf, size_t len); RBIMPL_ATTR_NONNULL(()) /** * This is the type of functions called when your random object is initialised. * Passed data is the seed integer. * * @param[out] rng Your random struct to fill in. * @param[in] data Seed, single word. * @post `rng` is initialised using the passed seeds. */ typedef void rb_random_init_int32_func(rb_random_t *rng, uint32_t data); RBIMPL_ATTR_NONNULL(()) /** * This is the type of functions called from your object's `#rand` method. * * @param[out] rng Your random struct to extract an integer from. * @return A random number. * @post `rng` is consumed somehow. */ typedef unsigned int rb_random_get_int32_func(rb_random_t *rng); RBIMPL_ATTR_NONNULL(()) /** * This is the type of functions called from your object's `#bytes` method. * * @param[out] rng Your random struct to extract an integer from. * @param[out] buf Return buffer of at least `len` bytes length. * @param[in] len Number of bytes of `buf`. * @post `rng` is consumed somehow. * @post `buf` is filled with random bytes. */ typedef void rb_random_get_bytes_func(rb_random_t *rng, void *buf, size_t len); RBIMPL_ATTR_NONNULL(()) /** * This is the type of functions called from your object's `#rand` method. * * @param[out] rng Your random struct to extract an integer from. * @param[in] excl Pass nonzero value here to indicate you don't want 1.0. * @return A random number of range 0.0 to 1.0. * @post `rng` is consumed somehow. */ typedef double rb_random_get_real_func(rb_random_t *rng, int excl); /** PRNG algorithmic interface, analogous to Ruby level classes. */ typedef struct { /** Number of bits of seed numbers. */ size_t default_seed_bits; /** * Major/minor versions of this interface */ struct { uint8_t major, minor; } version; /** * Reserved flags */ uint16_t flags; /** Function to initialize from uint32_t array. */ rb_random_init_func *init; /** Function to initialize from single uint32_t. */ rb_random_init_int32_func *init_int32; /** Function to obtain a random integer. */ rb_random_get_int32_func *get_int32; /** * Function to obtain a series of random bytes. If your PRNG have a native * method to yield arbitrary number of bytes use that to implement this. * But in case you lack such things, you can do so by using * rb_rand_bytes_int32() * * ```CXX * extern rb_random_get_int32_func your_get_int32_func; * * void * your_get_byes_func(rb_random_t *rng, void *buf, size_t len) * { * rb_rand_bytes_int32(your_get_int32_func, rng, buf, len); * } * ``` */ rb_random_get_bytes_func *get_bytes; /** * Function to obtain a random double. If your PRNG have a native method * to yield a floating point random number use that to implement this. But * in case you lack such things, you can do so by using * rb_int_pair_to_real(). * * ```CXX * extern rb_random_get_int32_func your_get_int32_func; * * void * your_get_real_func(rb_random_t *rng, int excl) * { * auto a = your_get_int32_func(rng); * auto b = your_get_int32_func(rng); * return rb_int_pair_to_real(a, b, excl); * } * ``` */ rb_random_get_real_func *get_real; } rb_random_interface_t; /** * This utility macro defines 4 functions named prefix_init, prefix_init_int32, * prefix_get_int32, prefix_get_bytes. */ #define RB_RANDOM_INTERFACE_DECLARE(prefix) \ static void prefix##_init(rb_random_t *, const uint32_t *, size_t); \ static void prefix##_init_int32(rb_random_t *, uint32_t); \ static unsigned int prefix##_get_int32(rb_random_t *); \ static void prefix##_get_bytes(rb_random_t *, void *, size_t) /** * Identical to #RB_RANDOM_INTERFACE_DECLARE except it also declares * prefix_get_real. */ #define RB_RANDOM_INTERFACE_DECLARE_WITH_REAL(prefix) \ RB_RANDOM_INTERFACE_DECLARE(prefix); \ static double prefix##_get_real(rb_random_t *, int) /** * This utility macro expands to the names declared using * #RB_RANDOM_INTERFACE_DECLARE. Expected to be used inside of a * ::rb_random_interface_t initialiser: * * ```CXX * RB_RANDOM_INTERFACE_DECLARE(foo); * * static inline constexpr rb_random_interface_t foo_interface = { * 32768, // bits * RB_RANDOM_INTERFACE_DEFINE(foo), * }; * ``` */ #define RB_RANDOM_INTERFACE_DEFINE(prefix) \ RUBY_RANDOM_INTERFACE_VERSION_INITIALIZER, 0, \ prefix##_init, \ prefix##_init_int32, \ prefix##_get_int32, \ prefix##_get_bytes /** * Identical to #RB_RANDOM_INTERFACE_DEFINE except it also defines * prefix_get_real. */ #define RB_RANDOM_INTERFACE_DEFINE_WITH_REAL(prefix) \ RB_RANDOM_INTERFACE_DEFINE(prefix), \ prefix##_get_real #define RB_RANDOM_DEFINE_INIT_INT32_FUNC(prefix) \ static void prefix##_init_int32(rb_random_t *rnd, uint32_t data) \ { \ prefix##_init(rnd, &data, 1); \ } #if defined _WIN32 && !defined __CYGWIN__ typedef rb_data_type_t rb_random_data_type_t; # define RB_RANDOM_PARENT 0 #else /** This is the type of ::rb_random_data_type. */ typedef const rb_data_type_t rb_random_data_type_t; /** * This utility macro can be used when you define your own PRNG type: * * ```CXX * static inline constexpr rb_random_interface_t your_if = { * 0, RB_RANDOM_INTERFACE_DEFINE(your), * }; * * static inline constexpr rb_random_data_type_t your_prng_type = { * "your PRNG", * { rb_random_mark, }, * RB_RANDOM_PARENT, // <<-- HERE * &your_if, * 0, * } * ``` */ # define RB_RANDOM_PARENT &rb_random_data_type #endif /** * This macro is expected to be called exactly once at the beginning of a * program, possibly from inside of your `Init_Foo()` function. Depending on * platforms #RB_RANDOM_PARENT can require a fixup. This routine does that * when necessary. */ #define RB_RANDOM_DATA_INIT_PARENT(random_data) \ rbimpl_random_data_init_parent(&random_data) /** * This is the implementation of ::rb_data_type_struct::dmark for * ::rb_random_data_type. In case your PRNG does not involve Ruby objects at * all (which is quite likely), you can simply reuse it. * * @param[out] ptr Target to mark, which is a ::rb_random_t this case. */ void rb_random_mark(void *ptr); /** * Initialises an allocated ::rb_random_t instance. Call it from your own * initialiser appropriately. * * @param[out] rnd Your PRNG's base part. * @post `rnd` is filled with an initial state. */ void rb_random_base_init(rb_random_t *rnd); /** * Generates a 64 bit floating point number by concatenating two 32bit unsigned * integers. * * @param[in] a Most significant 32 bits of the result. * @param[in] b Least significant 32 bits of the result. * @param[in] excl Whether the result should exclude 1.0 or not. * @return A double, whose range is either `[0, 1)` or `[0, 1]`. * @see ::rb_random_interface_t::get_real() * * @internal * * This in fact has nothing to do with PRNGs. */ double rb_int_pair_to_real(uint32_t a, uint32_t b, int excl); /** * Repeatedly calls the passed function over and over again until the passed * buffer is filled with random bytes. * * @param[in] func Generator function. * @param[out] prng Passed as-is to `func`. * @param[out] buff Return buffer. * @param[in] size Number of words of `buff`. * @post `buff` is filled with random bytes. * @post `prng` is updated by `func`. * @see ::rb_random_interface_t::get_bytes() */ void rb_rand_bytes_int32(rb_random_get_int32_func *func, rb_random_t *prng, void *buff, size_t size); /** * The data that holds the backend type of ::rb_cRandom. Used as your PRNG's * ::rb_data_type_struct::parent. */ RUBY_EXTERN const rb_data_type_t rb_random_data_type; RBIMPL_SYMBOL_EXPORT_END() RBIMPL_ATTR_PURE_UNLESS_DEBUG() /* :TODO: can this function be __attribute__((returns_nonnull)) or not? */ /** * Queries the interface of the passed random object. * * @param[in] obj An instance (of a subclass) of ::rb_cRandom. * @return Its corresponding ::rb_random_interface_t interface. */ static inline const rb_random_interface_t * rb_rand_if(VALUE obj) { RBIMPL_ASSERT_OR_ASSUME(RTYPEDDATA_P(obj)); const struct rb_data_type_struct *t = RTYPEDDATA_TYPE(obj); const void *ret = t->data; return RBIMPL_CAST((const rb_random_interface_t *)ret); } RBIMPL_ATTR_NOALIAS() /** * @private * * This is an implementation detail of #RB_RANDOM_DATA_INIT_PARENT. People * don't use it directly. * * @param[out] random_data Region to fill. * @post ::rb_random_data_type is filled appropriately. */ static inline void rbimpl_random_data_init_parent(rb_random_data_type_t *random_data) { #if defined _WIN32 && !defined __CYGWIN__ random_data->parent = &rb_random_data_type; #endif } #endif /* RUBY_RANDOM_H */ include/ruby/atomic.h 0000644 00000066710 15152150504 0010605 0 ustar 00 #ifndef RUBY_ATOMIC_H /*-*-C++-*-vi:se ft=cpp:*/ #define RUBY_ATOMIC_H /** * @file * @author Ruby developers <ruby-core@ruby-lang.org> * @copyright This file is a part of the programming language Ruby. * Permission is hereby granted, to either redistribute and/or * modify this file, provided that the conditions mentioned in the * file COPYING are met. Consult the file for details. * @warning Symbols prefixed with either `RBIMPL` or `rbimpl` are * implementation details. Don't take them as canon. They could * rapidly appear then vanish. The name (path) of this header file * is also an implementation detail. Do not expect it to persist * at the place it is now. Developers are free to move it anywhere * anytime at will. * @note To ruby-core: remember that this header can be possibly * recursively included from extension libraries written in C++. * Do not expect for instance `__VA_ARGS__` is always available. * We assume C99 for ruby itself but we don't assume languages of * extension libraries. They could be written in C++98. * @brief Atomic operations * * Basically, if we could assume either C11 or C++11, these macros are just * redundant. Sadly we cannot. We have to do them ourselves. */ #include "ruby/internal/config.h" #ifdef STDC_HEADERS # include <stddef.h> /* size_t */ #endif #ifdef HAVE_SYS_TYPES_H # include <sys/types.h> /* ssize_t */ #endif #if RBIMPL_COMPILER_SINCE(MSVC, 13, 0, 0) # pragma intrinsic(_InterlockedOr) #elif defined(__sun) && defined(HAVE_ATOMIC_H) # include <atomic.h> #endif #include "ruby/assert.h" #include "ruby/backward/2/limits.h" #include "ruby/internal/attr/artificial.h" #include "ruby/internal/attr/noalias.h" #include "ruby/internal/attr/nonnull.h" #include "ruby/internal/compiler_since.h" #include "ruby/internal/cast.h" #include "ruby/internal/value.h" #include "ruby/internal/static_assert.h" #include "ruby/internal/stdbool.h" /* * Asserts that your environment supports more than one atomic types. These * days systems tend to have such property (C11 was a standard of decades ago, * right?) but we still support older ones. */ #if defined(__DOXYGEN__) || defined(HAVE_GCC_ATOMIC_BUILTINS) || defined(HAVE_GCC_SYNC_BUILTINS) # define RUBY_ATOMIC_GENERIC_MACRO 1 #endif /** * Type that is eligible for atomic operations. Depending on your host * platform you might have more than one such type, but we choose one of them * anyways. */ #if defined(__DOXYGEN__) using rb_atomic_t = std::atomic<unsigned>; #elif defined(HAVE_GCC_ATOMIC_BUILTINS) typedef unsigned int rb_atomic_t; #elif defined(HAVE_GCC_SYNC_BUILTINS) typedef unsigned int rb_atomic_t; #elif defined(_WIN32) typedef LONG rb_atomic_t; #elif defined(__sun) && defined(HAVE_ATOMIC_H) typedef unsigned int rb_atomic_t; #else # error No atomic operation found #endif /** * Atomically replaces the value pointed by `var` with the result of addition * of `val` to the old value of `var`. * * @param var A variable of ::rb_atomic_t. * @param val Value to add. * @return What was stored in `var` before the addition. * @post `var` holds `var + val`. */ #define RUBY_ATOMIC_FETCH_ADD(var, val) rbimpl_atomic_fetch_add(&(var), (val)) /** * Atomically replaces the value pointed by `var` with the result of * subtraction of `val` to the old value of `var`. * * @param var A variable of ::rb_atomic_t. * @param val Value to subtract. * @return What was stored in `var` before the subtraction. * @post `var` holds `var - val`. */ #define RUBY_ATOMIC_FETCH_SUB(var, val) rbimpl_atomic_fetch_sub(&(var), (val)) /** * Atomically replaces the value pointed by `var` with the result of * bitwise OR between `val` and the old value of `var`. * * @param var A variable of ::rb_atomic_t. * @param val Value to mix. * @return void * @post `var` holds `var | val`. * @note For portability, this macro can return void. */ #define RUBY_ATOMIC_OR(var, val) rbimpl_atomic_or(&(var), (val)) /** * Atomically replaces the value pointed by `var` with `val`. This is just an * assignment, but you can additionally know the previous value. * * @param var A variable of ::rb_atomic_t. * @param val Value to set. * @return What was stored in `var` before the assignment. * @post `var` holds `val`. */ #define RUBY_ATOMIC_EXCHANGE(var, val) rbimpl_atomic_exchange(&(var), (val)) /** * Atomic compare-and-swap. This stores `val` to `var` if and only if the * assignment changes the value of `var` from `oldval` to `newval`. You can * detect whether the assignment happened or not using the return value. * * @param var A variable of ::rb_atomic_t. * @param oldval Expected value of `var` before the assignment. * @param newval What you want to store at `var`. * @retval oldval Successful assignment (`var` is now `newval`). * @retval otherwise Something else is at `var`; not updated. */ #define RUBY_ATOMIC_CAS(var, oldval, newval) \ rbimpl_atomic_cas(&(var), (oldval), (newval)) /** * Atomic load. This loads `var` with an atomic intrinsic and returns * its value. * * @param var A variable of ::rb_atomic_t * @return What was stored in `var`j */ #define RUBY_ATOMIC_LOAD(var) rbimpl_atomic_load(&(var)) /** * Identical to #RUBY_ATOMIC_EXCHANGE, except for the return type. * * @param var A variable of ::rb_atomic_t. * @param val Value to set. * @return void * @post `var` holds `val`. */ #define RUBY_ATOMIC_SET(var, val) rbimpl_atomic_set(&(var), (val)) /** * Identical to #RUBY_ATOMIC_FETCH_ADD, except for the return type. * * @param var A variable of ::rb_atomic_t. * @param val Value to add. * @return void * @post `var` holds `var + val`. */ #define RUBY_ATOMIC_ADD(var, val) rbimpl_atomic_add(&(var), (val)) /** * Identical to #RUBY_ATOMIC_FETCH_SUB, except for the return type. * * @param var A variable of ::rb_atomic_t. * @param val Value to subtract. * @return void * @post `var` holds `var - val`. */ #define RUBY_ATOMIC_SUB(var, val) rbimpl_atomic_sub(&(var), (val)) /** * Atomically increments the value pointed by `var`. * * @param var A variable of ::rb_atomic_t. * @return void * @post `var` holds `var + 1`. */ #define RUBY_ATOMIC_INC(var) rbimpl_atomic_inc(&(var)) /** * Atomically decrements the value pointed by `var`. * * @param var A variable of ::rb_atomic_t. * @return void * @post `var` holds `var - 1`. */ #define RUBY_ATOMIC_DEC(var) rbimpl_atomic_dec(&(var)) /** * Identical to #RUBY_ATOMIC_INC, except it expects its argument is `size_t`. * There are cases where ::rb_atomic_t is 32bit while `size_t` is 64bit. This * should be used for size related operations to support such platforms. * * @param var A variable of `size_t`. * @return void * @post `var` holds `var + 1`. */ #define RUBY_ATOMIC_SIZE_INC(var) rbimpl_atomic_size_inc(&(var)) /** * Identical to #RUBY_ATOMIC_DEC, except it expects its argument is `size_t`. * There are cases where ::rb_atomic_t is 32bit while `size_t` is 64bit. This * should be used for size related operations to support such platforms. * * @param var A variable of `size_t`. * @return void * @post `var` holds `var - 1`. */ #define RUBY_ATOMIC_SIZE_DEC(var) rbimpl_atomic_size_dec(&(var)) /** * Identical to #RUBY_ATOMIC_EXCHANGE, except it expects its arguments are * `size_t`. There are cases where ::rb_atomic_t is 32bit while `size_t` is * 64bit. This should be used for size related operations to support such * platforms. * * @param var A variable of `size_t`. * @param val Value to set. * @return What was stored in `var` before the assignment. * @post `var` holds `val`. */ #define RUBY_ATOMIC_SIZE_EXCHANGE(var, val) \ rbimpl_atomic_size_exchange(&(var), (val)) /** * Identical to #RUBY_ATOMIC_CAS, except it expects its arguments are `size_t`. * There are cases where ::rb_atomic_t is 32bit while `size_t` is 64bit. This * should be used for size related operations to support such platforms. * * @param var A variable of `size_t`. * @param oldval Expected value of `var` before the assignment. * @param newval What you want to store at `var`. * @retval oldval Successful assignment (`var` is now `newval`). * @retval otherwise Something else is at `var`; not updated. */ #define RUBY_ATOMIC_SIZE_CAS(var, oldval, newval) \ rbimpl_atomic_size_cas(&(var), (oldval), (newval)) /** * Identical to #RUBY_ATOMIC_ADD, except it expects its arguments are `size_t`. * There are cases where ::rb_atomic_t is 32bit while `size_t` is 64bit. This * should be used for size related operations to support such platforms. * * @param var A variable of `size_t`. * @param val Value to add. * @return void * @post `var` holds `var + val`. */ #define RUBY_ATOMIC_SIZE_ADD(var, val) rbimpl_atomic_size_add(&(var), (val)) /** * Identical to #RUBY_ATOMIC_SUB, except it expects its arguments are `size_t`. * There are cases where ::rb_atomic_t is 32bit while `size_t` is 64bit. This * should be used for size related operations to support such platforms. * * @param var A variable of `size_t`. * @param val Value to subtract. * @return void * @post `var` holds `var - val`. */ #define RUBY_ATOMIC_SIZE_SUB(var, val) rbimpl_atomic_size_sub(&(var), (val)) /** * Identical to #RUBY_ATOMIC_EXCHANGE, except it expects its arguments are * `void*`. There are cases where ::rb_atomic_t is 32bit while `void*` is * 64bit. This should be used for pointer related operations to support such * platforms. * * @param var A variable of `void *`. * @param val Value to set. * @return What was stored in `var` before the assignment. * @post `var` holds `val`. * * @internal * * :FIXME: this `(void*)` cast is evil! However `void*` is incompatible with * some pointers, most notably function pointers. */ #define RUBY_ATOMIC_PTR_EXCHANGE(var, val) \ RBIMPL_CAST(rbimpl_atomic_ptr_exchange((void **)&(var), (void *)val)) /** * Identical to #RUBY_ATOMIC_LOAD, except it expects its arguments are `void*`. * There are cases where ::rb_atomic_t is 32bit while `void*` is 64bit. This * should be used for size related operations to support such platforms. * * @param var A variable of `void*` * @return The value of `var` (without tearing) */ #define RUBY_ATOMIC_PTR_LOAD(var) \ RBIMPL_CAST(rbimpl_atomic_ptr_load((void **)&var)) /** * Identical to #RUBY_ATOMIC_CAS, except it expects its arguments are `void*`. * There are cases where ::rb_atomic_t is 32bit while `void*` is 64bit. This * should be used for size related operations to support such platforms. * * @param var A variable of `void*`. * @param oldval Expected value of `var` before the assignment. * @param newval What you want to store at `var`. * @retval oldval Successful assignment (`var` is now `newval`). * @retval otherwise Something else is at `var`; not updated. */ #define RUBY_ATOMIC_PTR_CAS(var, oldval, newval) \ RBIMPL_CAST(rbimpl_atomic_ptr_cas((void **)&(var), (oldval), (newval))) /** * Identical to #RUBY_ATOMIC_EXCHANGE, except it expects its arguments are * ::VALUE. There are cases where ::rb_atomic_t is 32bit while ::VALUE is * 64bit. This should be used for pointer related operations to support such * platforms. * * @param var A variable of ::VALUE. * @param val Value to set. * @return What was stored in `var` before the assignment. * @post `var` holds `val`. */ #define RUBY_ATOMIC_VALUE_EXCHANGE(var, val) \ rbimpl_atomic_value_exchange(&(var), (val)) /** * Identical to #RUBY_ATOMIC_CAS, except it expects its arguments are ::VALUE. * There are cases where ::rb_atomic_t is 32bit while ::VALUE is 64bit. This * should be used for size related operations to support such platforms. * * @param var A variable of `void*`. * @param oldval Expected value of `var` before the assignment. * @param newval What you want to store at `var`. * @retval oldval Successful assignment (`var` is now `newval`). * @retval otherwise Something else is at `var`; not updated. */ #define RUBY_ATOMIC_VALUE_CAS(var, oldval, newval) \ rbimpl_atomic_value_cas(&(var), (oldval), (newval)) /** @cond INTERNAL_MACRO */ RBIMPL_ATTR_ARTIFICIAL() RBIMPL_ATTR_NOALIAS() RBIMPL_ATTR_NONNULL((1)) static inline rb_atomic_t rbimpl_atomic_fetch_add(volatile rb_atomic_t *ptr, rb_atomic_t val) { #if 0 #elif defined(HAVE_GCC_ATOMIC_BUILTINS) return __atomic_fetch_add(ptr, val, __ATOMIC_SEQ_CST); #elif defined(HAVE_GCC_SYNC_BUILTINS) return __sync_fetch_and_add(ptr, val); #elif defined(_WIN32) return InterlockedExchangeAdd(ptr, val); #elif defined(__sun) && defined(HAVE_ATOMIC_H) /* * `atomic_add_int_nv` takes its second argument as `int`! Meanwhile our * `rb_atomic_t` is unsigned. We cannot pass `val` as-is. We have to * manually check integer overflow. */ RBIMPL_ASSERT_OR_ASSUME(val <= INT_MAX); return atomic_add_int_nv(ptr, val) - val; #else # error Unsupported platform. #endif } RBIMPL_ATTR_ARTIFICIAL() RBIMPL_ATTR_NOALIAS() RBIMPL_ATTR_NONNULL((1)) static inline void rbimpl_atomic_add(volatile rb_atomic_t *ptr, rb_atomic_t val) { #if 0 #elif defined(HAVE_GCC_ATOMIC_BUILTINS) /* * GCC on amd64 is smart enough to detect this `__atomic_add_fetch`'s * return value is not used, then compiles it into single `LOCK ADD` * instruction. */ __atomic_add_fetch(ptr, val, __ATOMIC_SEQ_CST); #elif defined(HAVE_GCC_SYNC_BUILTINS) __sync_add_and_fetch(ptr, val); #elif defined(_WIN32) /* * `InterlockedExchangeAdd` is `LOCK XADD`. It seems there also is * `_InterlockedAdd` intrinsic in ARM Windows but not for x86? Sticking to * `InterlockedExchangeAdd` for better portability. */ InterlockedExchangeAdd(ptr, val); #elif defined(__sun) && defined(HAVE_ATOMIC_H) /* Ditto for `atomic_add_int_nv`. */ RBIMPL_ASSERT_OR_ASSUME(val <= INT_MAX); atomic_add_int(ptr, val); #else # error Unsupported platform. #endif } RBIMPL_ATTR_ARTIFICIAL() RBIMPL_ATTR_NOALIAS() RBIMPL_ATTR_NONNULL((1)) static inline void rbimpl_atomic_size_add(volatile size_t *ptr, size_t val) { #if 0 #elif defined(HAVE_GCC_ATOMIC_BUILTINS) __atomic_add_fetch(ptr, val, __ATOMIC_SEQ_CST); #elif defined(HAVE_GCC_SYNC_BUILTINS) __sync_add_and_fetch(ptr, val); #elif defined(_WIN32) && defined(_M_AMD64) /* Ditto for `InterlockeExchangedAdd`. */ InterlockedExchangeAdd64(ptr, val); #elif defined(__sun) && defined(HAVE_ATOMIC_H) && (defined(_LP64) || defined(_I32LPx)) /* Ditto for `atomic_add_int_nv`. */ RBIMPL_ASSERT_OR_ASSUME(val <= LONG_MAX); atomic_add_long(ptr, val); #else RBIMPL_STATIC_ASSERT(size_of_rb_atomic_t, sizeof *ptr == sizeof(rb_atomic_t)); volatile rb_atomic_t *const tmp = RBIMPL_CAST((volatile rb_atomic_t *)ptr); rbimpl_atomic_add(tmp, val); #endif } RBIMPL_ATTR_ARTIFICIAL() RBIMPL_ATTR_NOALIAS() RBIMPL_ATTR_NONNULL((1)) static inline void rbimpl_atomic_inc(volatile rb_atomic_t *ptr) { #if 0 #elif defined(HAVE_GCC_ATOMIC_BUILTINS) || defined(HAVE_GCC_SYNC_BUILTINS) rbimpl_atomic_add(ptr, 1); #elif defined(_WIN32) InterlockedIncrement(ptr); #elif defined(__sun) && defined(HAVE_ATOMIC_H) atomic_inc_uint(ptr); #else rbimpl_atomic_add(ptr, 1); #endif } RBIMPL_ATTR_ARTIFICIAL() RBIMPL_ATTR_NOALIAS() RBIMPL_ATTR_NONNULL((1)) static inline void rbimpl_atomic_size_inc(volatile size_t *ptr) { #if 0 #elif defined(HAVE_GCC_ATOMIC_BUILTINS) || defined(HAVE_GCC_SYNC_BUILTINS) rbimpl_atomic_size_add(ptr, 1); #elif defined(_WIN32) && defined(_M_AMD64) InterlockedIncrement64(ptr); #elif defined(__sun) && defined(HAVE_ATOMIC_H) && (defined(_LP64) || defined(_I32LPx)) atomic_inc_ulong(ptr); #else rbimpl_atomic_size_add(ptr, 1); #endif } RBIMPL_ATTR_ARTIFICIAL() RBIMPL_ATTR_NOALIAS() RBIMPL_ATTR_NONNULL((1)) static inline rb_atomic_t rbimpl_atomic_fetch_sub(volatile rb_atomic_t *ptr, rb_atomic_t val) { #if 0 #elif defined(HAVE_GCC_ATOMIC_BUILTINS) return __atomic_fetch_sub(ptr, val, __ATOMIC_SEQ_CST); #elif defined(HAVE_GCC_SYNC_BUILTINS) return __sync_fetch_and_sub(ptr, val); #elif defined(_WIN32) /* rb_atomic_t is signed here! Safe to do `-val`. */ return InterlockedExchangeAdd(ptr, -val); #elif defined(__sun) && defined(HAVE_ATOMIC_H) /* Ditto for `rbimpl_atomic_fetch_add`. */ const signed neg = -1; RBIMPL_ASSERT_OR_ASSUME(val <= INT_MAX); return atomic_add_int_nv(ptr, neg * val) + val; #else # error Unsupported platform. #endif } RBIMPL_ATTR_ARTIFICIAL() RBIMPL_ATTR_NOALIAS() RBIMPL_ATTR_NONNULL((1)) static inline void rbimpl_atomic_sub(volatile rb_atomic_t *ptr, rb_atomic_t val) { #if 0 #elif defined(HAVE_GCC_ATOMIC_BUILTINS) __atomic_sub_fetch(ptr, val, __ATOMIC_SEQ_CST); #elif defined(HAVE_GCC_SYNC_BUILTINS) __sync_sub_and_fetch(ptr, val); #elif defined(_WIN32) InterlockedExchangeAdd(ptr, -val); #elif defined(__sun) && defined(HAVE_ATOMIC_H) const signed neg = -1; RBIMPL_ASSERT_OR_ASSUME(val <= INT_MAX); atomic_add_int(ptr, neg * val); #else # error Unsupported platform. #endif } RBIMPL_ATTR_ARTIFICIAL() RBIMPL_ATTR_NOALIAS() RBIMPL_ATTR_NONNULL((1)) static inline void rbimpl_atomic_size_sub(volatile size_t *ptr, size_t val) { #if 0 #elif defined(HAVE_GCC_ATOMIC_BUILTINS) __atomic_sub_fetch(ptr, val, __ATOMIC_SEQ_CST); #elif defined(HAVE_GCC_SYNC_BUILTINS) __sync_sub_and_fetch(ptr, val); #elif defined(_WIN32) && defined(_M_AMD64) const ssize_t neg = -1; InterlockedExchangeAdd64(ptr, neg * val); #elif defined(__sun) && defined(HAVE_ATOMIC_H) && (defined(_LP64) || defined(_I32LPx)) const signed neg = -1; RBIMPL_ASSERT_OR_ASSUME(val <= LONG_MAX); atomic_add_long(ptr, neg * val); #else RBIMPL_STATIC_ASSERT(size_of_rb_atomic_t, sizeof *ptr == sizeof(rb_atomic_t)); volatile rb_atomic_t *const tmp = RBIMPL_CAST((volatile rb_atomic_t *)ptr); rbimpl_atomic_sub(tmp, val); #endif } RBIMPL_ATTR_ARTIFICIAL() RBIMPL_ATTR_NOALIAS() RBIMPL_ATTR_NONNULL((1)) static inline void rbimpl_atomic_dec(volatile rb_atomic_t *ptr) { #if 0 #elif defined(HAVE_GCC_ATOMIC_BUILTINS) || defined(HAVE_GCC_SYNC_BUILTINS) rbimpl_atomic_sub(ptr, 1); #elif defined(_WIN32) InterlockedDecrement(ptr); #elif defined(__sun) && defined(HAVE_ATOMIC_H) atomic_dec_uint(ptr); #else rbimpl_atomic_sub(ptr, 1); #endif } RBIMPL_ATTR_ARTIFICIAL() RBIMPL_ATTR_NOALIAS() RBIMPL_ATTR_NONNULL((1)) static inline void rbimpl_atomic_size_dec(volatile size_t *ptr) { #if 0 #elif defined(HAVE_GCC_ATOMIC_BUILTINS) || defined(HAVE_GCC_SYNC_BUILTINS) rbimpl_atomic_size_sub(ptr, 1); #elif defined(_WIN32) && defined(_M_AMD64) InterlockedDecrement64(ptr); #elif defined(__sun) && defined(HAVE_ATOMIC_H) && (defined(_LP64) || defined(_I32LPx)) atomic_dec_ulong(ptr); #else rbimpl_atomic_size_sub(ptr, 1); #endif } RBIMPL_ATTR_ARTIFICIAL() RBIMPL_ATTR_NOALIAS() RBIMPL_ATTR_NONNULL((1)) static inline void rbimpl_atomic_or(volatile rb_atomic_t *ptr, rb_atomic_t val) { #if 0 #elif defined(HAVE_GCC_ATOMIC_BUILTINS) __atomic_or_fetch(ptr, val, __ATOMIC_SEQ_CST); #elif defined(HAVE_GCC_SYNC_BUILTINS) __sync_or_and_fetch(ptr, val); #elif RBIMPL_COMPILER_SINCE(MSVC, 13, 0, 0) _InterlockedOr(ptr, val); #elif defined(_WIN32) && defined(__GNUC__) /* This was for old MinGW. Maybe not needed any longer? */ __asm__( "lock\n\t" "orl\t%1, %0" : "=m"(ptr) : "Ir"(val)); #elif defined(_WIN32) && defined(_M_IX86) __asm mov eax, ptr; __asm mov ecx, val; __asm lock or [eax], ecx; #elif defined(__sun) && defined(HAVE_ATOMIC_H) atomic_or_uint(ptr, val); #else # error Unsupported platform. #endif } /* Nobody uses this but for theoretical backwards compatibility... */ #if RBIMPL_COMPILER_BEFORE(MSVC, 13, 0, 0) static inline rb_atomic_t rb_w32_atomic_or(volatile rb_atomic_t *var, rb_atomic_t val) { return rbimpl_atomic_or(var, val); } #endif RBIMPL_ATTR_ARTIFICIAL() RBIMPL_ATTR_NOALIAS() RBIMPL_ATTR_NONNULL((1)) static inline rb_atomic_t rbimpl_atomic_exchange(volatile rb_atomic_t *ptr, rb_atomic_t val) { #if 0 #elif defined(HAVE_GCC_ATOMIC_BUILTINS) return __atomic_exchange_n(ptr, val, __ATOMIC_SEQ_CST); #elif defined(HAVE_GCC_SYNC_BUILTINS) return __sync_lock_test_and_set(ptr, val); #elif defined(_WIN32) return InterlockedExchange(ptr, val); #elif defined(__sun) && defined(HAVE_ATOMIC_H) return atomic_swap_uint(ptr, val); #else # error Unsupported platform. #endif } RBIMPL_ATTR_ARTIFICIAL() RBIMPL_ATTR_NOALIAS() RBIMPL_ATTR_NONNULL((1)) static inline size_t rbimpl_atomic_size_exchange(volatile size_t *ptr, size_t val) { #if 0 #elif defined(HAVE_GCC_ATOMIC_BUILTINS) return __atomic_exchange_n(ptr, val, __ATOMIC_SEQ_CST); #elif defined(HAVE_GCC_SYNC_BUILTINS) return __sync_lock_test_and_set(ptr, val); #elif defined(_WIN32) && defined(_M_AMD64) return InterlockedExchange64(ptr, val); #elif defined(__sun) && defined(HAVE_ATOMIC_H) && (defined(_LP64) || defined(_I32LPx)) return atomic_swap_ulong(ptr, val); #else RBIMPL_STATIC_ASSERT(size_of_size_t, sizeof *ptr == sizeof(rb_atomic_t)); volatile rb_atomic_t *const tmp = RBIMPL_CAST((volatile rb_atomic_t *)ptr); const rb_atomic_t ret = rbimpl_atomic_exchange(tmp, val); return RBIMPL_CAST((size_t)ret); #endif } RBIMPL_ATTR_ARTIFICIAL() RBIMPL_ATTR_NOALIAS() RBIMPL_ATTR_NONNULL((1)) static inline void * rbimpl_atomic_ptr_exchange(void *volatile *ptr, const void *val) { #if 0 #elif defined(InterlockedExchangePointer) /* const_cast */ PVOID *pptr = RBIMPL_CAST((PVOID *)ptr); PVOID pval = RBIMPL_CAST((PVOID)val); return InterlockedExchangePointer(pptr, pval); #elif defined(__sun) && defined(HAVE_ATOMIC_H) return atomic_swap_ptr(ptr, RBIMPL_CAST((void *)val)); #else RBIMPL_STATIC_ASSERT(sizeof_voidp, sizeof *ptr == sizeof(size_t)); const size_t sval = RBIMPL_CAST((size_t)val); volatile size_t *const sptr = RBIMPL_CAST((volatile size_t *)ptr); const size_t sret = rbimpl_atomic_size_exchange(sptr, sval); return RBIMPL_CAST((void *)sret); #endif } RBIMPL_ATTR_ARTIFICIAL() RBIMPL_ATTR_NOALIAS() RBIMPL_ATTR_NONNULL((1)) static inline VALUE rbimpl_atomic_value_exchange(volatile VALUE *ptr, VALUE val) { RBIMPL_STATIC_ASSERT(sizeof_value, sizeof *ptr == sizeof(size_t)); const size_t sval = RBIMPL_CAST((size_t)val); volatile size_t *const sptr = RBIMPL_CAST((volatile size_t *)ptr); const size_t sret = rbimpl_atomic_size_exchange(sptr, sval); return RBIMPL_CAST((VALUE)sret); } RBIMPL_ATTR_ARTIFICIAL() RBIMPL_ATTR_NOALIAS() RBIMPL_ATTR_NONNULL((1)) static inline rb_atomic_t rbimpl_atomic_load(volatile rb_atomic_t *ptr) { #if 0 #elif defined(HAVE_GCC_ATOMIC_BUILTINS) return __atomic_load_n(ptr, __ATOMIC_SEQ_CST); #else return rbimpl_atomic_fetch_add(ptr, 0); #endif } RBIMPL_ATTR_ARTIFICIAL() RBIMPL_ATTR_NOALIAS() RBIMPL_ATTR_NONNULL((1)) static inline void rbimpl_atomic_set(volatile rb_atomic_t *ptr, rb_atomic_t val) { #if 0 #elif defined(HAVE_GCC_ATOMIC_BUILTINS) __atomic_store_n(ptr, val, __ATOMIC_SEQ_CST); #else /* Maybe std::atomic<rb_atomic_t>::store can be faster? */ rbimpl_atomic_exchange(ptr, val); #endif } RBIMPL_ATTR_ARTIFICIAL() RBIMPL_ATTR_NOALIAS() RBIMPL_ATTR_NONNULL((1)) static inline rb_atomic_t rbimpl_atomic_cas(volatile rb_atomic_t *ptr, rb_atomic_t oldval, rb_atomic_t newval) { #if 0 #elif defined(HAVE_GCC_ATOMIC_BUILTINS) __atomic_compare_exchange_n( ptr, &oldval, newval, 0, __ATOMIC_SEQ_CST, __ATOMIC_SEQ_CST); return oldval; #elif defined(HAVE_GCC_SYNC_BUILTINS) return __sync_val_compare_and_swap(ptr, oldval, newval); #elif RBIMPL_COMPILER_SINCE(MSVC, 13, 0, 0) return InterlockedCompareExchange(ptr, newval, oldval); #elif defined(_WIN32) PVOID *pptr = RBIMPL_CAST((PVOID *)ptr); PVOID pold = RBIMPL_CAST((PVOID)oldval); PVOID pnew = RBIMPL_CAST((PVOID)newval); PVOID pret = InterlockedCompareExchange(pptr, pnew, pold); return RBIMPL_CAST((rb_atomic_t)pret); #elif defined(__sun) && defined(HAVE_ATOMIC_H) return atomic_cas_uint(ptr, oldval, newval); #else # error Unsupported platform. #endif } /* Nobody uses this but for theoretical backwards compatibility... */ #if RBIMPL_COMPILER_BEFORE(MSVC, 13, 0, 0) static inline rb_atomic_t rb_w32_atomic_cas(volatile rb_atomic_t *var, rb_atomic_t oldval, rb_atomic_t newval) { return rbimpl_atomic_cas(var, oldval, newval); } #endif RBIMPL_ATTR_ARTIFICIAL() RBIMPL_ATTR_NOALIAS() RBIMPL_ATTR_NONNULL((1)) static inline size_t rbimpl_atomic_size_cas(volatile size_t *ptr, size_t oldval, size_t newval) { #if 0 #elif defined(HAVE_GCC_ATOMIC_BUILTINS) __atomic_compare_exchange_n( ptr, &oldval, newval, 0, __ATOMIC_SEQ_CST, __ATOMIC_SEQ_CST); return oldval; #elif defined(HAVE_GCC_SYNC_BUILTINS) return __sync_val_compare_and_swap(ptr, oldval, newval); #elif defined(_WIN32) && defined(_M_AMD64) return InterlockedCompareExchange64(ptr, newval, oldval); #elif defined(__sun) && defined(HAVE_ATOMIC_H) && (defined(_LP64) || defined(_I32LPx)) return atomic_cas_ulong(ptr, oldval, newval); #else RBIMPL_STATIC_ASSERT(size_of_size_t, sizeof *ptr == sizeof(rb_atomic_t)); volatile rb_atomic_t *tmp = RBIMPL_CAST((volatile rb_atomic_t *)ptr); return rbimpl_atomic_cas(tmp, oldval, newval); #endif } RBIMPL_ATTR_ARTIFICIAL() RBIMPL_ATTR_NOALIAS() RBIMPL_ATTR_NONNULL((1)) static inline void * rbimpl_atomic_ptr_cas(void **ptr, const void *oldval, const void *newval) { #if 0 #elif defined(InterlockedExchangePointer) /* ... Can we say that InterlockedCompareExchangePtr surly exists when * InterlockedExchangePointer is defined? Seems so but...?*/ PVOID *pptr = RBIMPL_CAST((PVOID *)ptr); PVOID pold = RBIMPL_CAST((PVOID)oldval); PVOID pnew = RBIMPL_CAST((PVOID)newval); return InterlockedCompareExchangePointer(pptr, pnew, pold); #elif defined(__sun) && defined(HAVE_ATOMIC_H) void *pold = RBIMPL_CAST((void *)oldval); void *pnew = RBIMPL_CAST((void *)newval); return atomic_cas_ptr(ptr, pold, pnew); #else RBIMPL_STATIC_ASSERT(sizeof_voidp, sizeof *ptr == sizeof(size_t)); const size_t snew = RBIMPL_CAST((size_t)newval); const size_t sold = RBIMPL_CAST((size_t)oldval); volatile size_t *const sptr = RBIMPL_CAST((volatile size_t *)ptr); const size_t sret = rbimpl_atomic_size_cas(sptr, sold, snew); return RBIMPL_CAST((void *)sret); #endif } RBIMPL_ATTR_ARTIFICIAL() RBIMPL_ATTR_NOALIAS() RBIMPL_ATTR_NONNULL((1)) static inline void * rbimpl_atomic_ptr_load(void **ptr) { #if 0 #elif defined(HAVE_GCC_ATOMIC_BUILTINS) return __atomic_load_n(ptr, __ATOMIC_SEQ_CST); #else void *val = *ptr; return rbimpl_atomic_ptr_cas(ptr, val, val); #endif } RBIMPL_ATTR_ARTIFICIAL() RBIMPL_ATTR_NOALIAS() RBIMPL_ATTR_NONNULL((1)) static inline VALUE rbimpl_atomic_value_cas(volatile VALUE *ptr, VALUE oldval, VALUE newval) { RBIMPL_STATIC_ASSERT(sizeof_value, sizeof *ptr == sizeof(size_t)); const size_t snew = RBIMPL_CAST((size_t)newval); const size_t sold = RBIMPL_CAST((size_t)oldval); volatile size_t *const sptr = RBIMPL_CAST((volatile size_t *)ptr); const size_t sret = rbimpl_atomic_size_cas(sptr, sold, snew); return RBIMPL_CAST((VALUE)sret); } /** @endcond */ #endif /* RUBY_ATOMIC_H */ include/ruby/regex.h 0000644 00000001763 15152150505 0010441 0 ustar 00 #ifndef ONIGURUMA_REGEX_H /*-*-C++-*-vi:se ft=cpp:*/ #define ONIGURUMA_REGEX_H 1 /** * @author $Author$ * @copyright Copyright (C) 1993-2007 Yukihiro Matsumoto * @copyright This file is a part of the programming language Ruby. * Permission is hereby granted, to either redistribute and/or * modify this file, provided that the conditions mentioned in the * file COPYING are met. Consult the file for details. */ #if defined(__cplusplus) extern "C" { #if 0 } /* satisfy cc-mode */ #endif #endif #ifdef RUBY #include "ruby/oniguruma.h" #else #include "oniguruma.h" #endif RUBY_SYMBOL_EXPORT_BEGIN #ifndef ONIG_RUBY_M17N ONIG_EXTERN OnigEncoding OnigEncDefaultCharEncoding; #define mbclen(p,e,enc) rb_enc_mbclen((p),(e),(enc)) #endif /* ifndef ONIG_RUBY_M17N */ RUBY_SYMBOL_EXPORT_END #if defined(__cplusplus) #if 0 { /* satisfy cc-mode */ #endif } /* extern "C" { */ #endif #endif /* ONIGURUMA_REGEX_H */ include/ruby/fiber/scheduler.h 0000644 00000036735 15152150505 0012403 0 ustar 00 #ifndef RUBY_FIBER_SCHEDULER_H /*-*-C++-*-vi:se ft=cpp:*/ #define RUBY_FIBER_SCHEDULER_H /** * @file * @author Ruby developers <ruby-core@ruby-lang.org> * @copyright This file is a part of the programming language Ruby. * Permission is hereby granted, to either redistribute and/or * modify this file, provided that the conditions mentioned in the * file COPYING are met. Consult the file for details. * @brief Scheduler APIs. */ #include "ruby/internal/config.h" #include <errno.h> #ifdef STDC_HEADERS #include <stddef.h> /* size_t */ #endif #include "ruby/ruby.h" #include "ruby/internal/dllexport.h" #include "ruby/internal/arithmetic.h" RBIMPL_SYMBOL_EXPORT_BEGIN() #define RUBY_FIBER_SCHEDULER_VERSION 2 struct timeval; /** * Wrap a `ssize_t` and `int errno` into a single `VALUE`. This interface should * be used to safely capture results from system calls like `read` and `write`. * * You should use `rb_fiber_scheduler_io_result_apply` to unpack the result of * this value and update `int errno`. * * You should not directly try to interpret the result value as it is considered * an opaque representation. However, the general representation is an integer * in the range of `[-int errno, size_t size]`. Linux generally restricts the * result of system calls like `read` and `write` to `<= 2^31` which means this * will typically fit within a single FIXNUM. * * @param[in] result The result of the system call. * @param[in] error The value of `errno`. * @return A `VALUE` which contains the result and/or errno. */ static inline VALUE rb_fiber_scheduler_io_result(ssize_t result, int error) { if (result == -1) { return RB_INT2NUM(-error); } else { return RB_SIZE2NUM(result); } } /** * Apply an io result to the local thread, returning the value of the original * system call that created it and updating `int errno`. * * You should not directly try to interpret the result value as it is considered * an opaque representation. * * @param[in] result The `VALUE` which contains an errno and/or result size. * @post Updates `int errno` with the value if negative. * @return The original result of the system call. */ static inline ssize_t rb_fiber_scheduler_io_result_apply(VALUE result) { if (RB_FIXNUM_P(result) && RB_NUM2INT(result) < 0) { errno = -RB_NUM2INT(result); return -1; } else { return RB_NUM2SIZE(result); } } /** * Queries the current scheduler of the current thread that is calling this * function. * * @retval RUBY_Qnil No scheduler has been set so far to this thread (which * is the default). * @retval otherwise The scheduler that was last set for the current thread * with rb_fiber_scheduler_set(). */ VALUE rb_fiber_scheduler_get(void); /** * Destructively assigns the passed scheduler to that of the current thread * that is calling this function. If the scheduler is set, non-blocking fibers * (created by `Fiber.new` with `blocking: false`, or by `Fiber.schedule`) call * that scheduler's hook methods on potentially blocking operations, and the * current thread will call scheduler's `#close` method on finalisation * (allowing the scheduler to properly manage all non-finished fibers). * `scheduler` can be an object of any class corresponding to * `Fiber::Scheduler` interface. Its implementation is up to the user. * * @param[in] scheduler The scheduler to set. * @exception rb_eArgError `scheduler` does not conform the interface. * @post Current thread's scheduler is `scheduler`. */ VALUE rb_fiber_scheduler_set(VALUE scheduler); /** * Identical to rb_fiber_scheduler_get(), except it also returns ::RUBY_Qnil in * case of a blocking fiber. As blocking fibers do not participate schedulers' * scheduling this function can be handy. * * @retval RUBY_Qnil No scheduler is in effect. * @retval otherwise The scheduler that is in effect, if any. */ VALUE rb_fiber_scheduler_current(void); /** * Identical to rb_fiber_scheduler_current(), except it queries for that of the * passed thread instead of the implicit current one. * * @param[in] thread Target thread. * @exception rb_eTypeError `thread` is not a thread. * @retval RUBY_Qnil No scheduler is in effect in `thread`. * @retval otherwise The scheduler that is in effect in `thread`. */ VALUE rb_fiber_scheduler_current_for_thread(VALUE thread); /** * Converts the passed timeout to an expression that rb_fiber_scheduler_block() * etc. expects. * * @param[in] timeout A duration (can be `NULL`). * @retval RUBY_Qnil No timeout (blocks indefinitely). * @retval otherwise A timeout object. */ VALUE rb_fiber_scheduler_make_timeout(struct timeval *timeout); /** * Closes the passed scheduler object. This expects the scheduler to wait for * all fibers. Thus the scheduler's main loop tends to start here. * * @param[in] scheduler Target scheduler. * @return What `scheduler.close` returns. */ VALUE rb_fiber_scheduler_close(VALUE scheduler); /** * Non-blocking `sleep`. Depending on scheduler implementation, this for * instance switches to another fiber etc. * * @param[in] scheduler Target scheduler. * @param[in] duration Passed as-is to `scheduler.kernel_sleep`. * @return What `scheduler.kernel_sleep` returns. */ VALUE rb_fiber_scheduler_kernel_sleep(VALUE scheduler, VALUE duration); /** * Identical to rb_fiber_scheduler_kernel_sleep(), except it can pass multiple * arguments. * * @param[in] scheduler Target scheduler. * @param[in] argc Number of objects of `argv`. * @param[in] argv Passed as-is to `scheduler.kernel_sleep` * @return What `scheduler.kernel_sleep` returns. */ VALUE rb_fiber_scheduler_kernel_sleepv(VALUE scheduler, int argc, VALUE * argv); /* Description TBW */ #if 0 VALUE rb_fiber_scheduler_timeout_after(VALUE scheduler, VALUE timeout, VALUE exception, VALUE message); VALUE rb_fiber_scheduler_timeout_afterv(VALUE scheduler, int argc, VALUE * argv); int rb_fiber_scheduler_supports_process_wait(VALUE scheduler); #endif /** * Non-blocking `waitpid`. Depending on scheduler implementation, this for * instance switches to another fiber etc. * * @param[in] scheduler Target scheduler. * @param[in] pid Process ID to wait. * @param[in] flags Wait flags, e.g. `WUNTRACED`. * @return What `scheduler.process_wait` returns. */ VALUE rb_fiber_scheduler_process_wait(VALUE scheduler, rb_pid_t pid, int flags); /** * Non-blocking wait for the passed "blocker", which is for instance * `Thread.join` or `Mutex.lock`. Depending on scheduler implementation, this * for instance switches to another fiber etc. * * @param[in] scheduler Target scheduler. * @param[in] blocker What blocks the current fiber. * @param[in] timeout Numeric timeout. * @return What `scheduler.block` returns. */ VALUE rb_fiber_scheduler_block(VALUE scheduler, VALUE blocker, VALUE timeout); /** * Wakes up a fiber previously blocked using rb_fiber_scheduler_block(). * * @param[in] scheduler Target scheduler. * @param[in] blocker What was awaited for. * @param[in] fiber What to unblock. * @return What `scheduler.unblock` returns. */ VALUE rb_fiber_scheduler_unblock(VALUE scheduler, VALUE blocker, VALUE fiber); /** * Non-blocking version of rb_io_wait(). Depending on scheduler * implementation, this for instance switches to another fiber etc. * * The "events" here is a Ruby level integer, which is an OR-ed value of * `IO::READABLE`, `IO::WRITABLE`, and `IO::PRIORITY`. * * @param[in] scheduler Target scheduler. * @param[in] io An io object to wait. * @param[in] events An integer set of interests. * @param[in] timeout Numeric timeout. * @return What `scheduler.io_wait` returns. */ VALUE rb_fiber_scheduler_io_wait(VALUE scheduler, VALUE io, VALUE events, VALUE timeout); /** * Non-blocking wait until the passed IO is ready for reading. This is a * special case of rb_fiber_scheduler_io_wait(), where the interest is * `IO::READABLE` and timeout is never. * * @param[in] scheduler Target scheduler. * @param[in] io An io object to wait. * @return What `scheduler.io_wait` returns. */ VALUE rb_fiber_scheduler_io_wait_readable(VALUE scheduler, VALUE io); /** * Non-blocking wait until the passed IO is ready for writing. This is a * special case of rb_fiber_scheduler_io_wait(), where the interest is * `IO::WRITABLE` and timeout is never. * * @param[in] scheduler Target scheduler. * @param[in] io An io object to wait. * @return What `scheduler.io_wait` returns. */ VALUE rb_fiber_scheduler_io_wait_writable(VALUE scheduler, VALUE io); /** * Non-blocking version of `IO.select`. * * It's possible that this will be emulated using a thread, so you should not * rely on it for high performance. * * @param[in] scheduler Target scheduler. * @param[in] readables An array of readable objects. * @param[in] writables An array of writable objects. * @param[in] exceptables An array of objects that might encounter exceptional conditions. * @param[in] timeout Numeric timeout or nil. * @return What `scheduler.io_select` returns, normally a 3-tuple of arrays of ready objects. */ VALUE rb_fiber_scheduler_io_select(VALUE scheduler, VALUE readables, VALUE writables, VALUE exceptables, VALUE timeout); /** * Non-blocking version of `IO.select`, `argv` variant. */ VALUE rb_fiber_scheduler_io_selectv(VALUE scheduler, int argc, VALUE *argv); /** * Non-blocking read from the passed IO. * * @param[in] scheduler Target scheduler. * @param[in] io An io object to read from. * @param[in] buffer The buffer to read to. * @param[in] length The minimum number of bytes to read. * @param[in] offset The offset in the buffer to read from. * @retval RUBY_Qundef `scheduler` doesn't have `#io_read`. * @return otherwise What `scheduler.io_read` returns `[-errno, size]`. */ VALUE rb_fiber_scheduler_io_read(VALUE scheduler, VALUE io, VALUE buffer, size_t length, size_t offset); /** * Non-blocking write to the passed IO. * * @param[in] scheduler Target scheduler. * @param[in] io An io object to write to. * @param[in] buffer The buffer to write from. * @param[in] length The minimum number of bytes to write. * @param[in] offset The offset in the buffer to write from. * @retval RUBY_Qundef `scheduler` doesn't have `#io_write`. * @return otherwise What `scheduler.io_write` returns `[-errno, size]`. */ VALUE rb_fiber_scheduler_io_write(VALUE scheduler, VALUE io, VALUE buffer, size_t length, size_t offset); /** * Non-blocking read from the passed IO at the specified offset. * * @param[in] scheduler Target scheduler. * @param[in] io An io object to read from. * @param[in] from The offset to read from. * @param[in] buffer The buffer to read to. * @param[in] length The minimum number of bytes to read. * @param[in] offset The offset in the buffer to read to. * @retval RUBY_Qundef `scheduler` doesn't have `#io_read`. * @return otherwise What `scheduler.io_read` returns. */ VALUE rb_fiber_scheduler_io_pread(VALUE scheduler, VALUE io, rb_off_t from, VALUE buffer, size_t length, size_t offset); /** * Non-blocking write to the passed IO at the specified offset. * * @param[in] scheduler Target scheduler. * @param[in] io An io object to write to. * @param[in] from The offset to write to. * @param[in] buffer The buffer to write from. * @param[in] length The minimum number of bytes to write. * @param[in] offset The offset in the buffer to write from. * @retval RUBY_Qundef `scheduler` doesn't have `#io_write`. * @return otherwise What `scheduler.io_write` returns. */ VALUE rb_fiber_scheduler_io_pwrite(VALUE scheduler, VALUE io, rb_off_t from, VALUE buffer, size_t length, size_t offset); /** * Non-blocking read from the passed IO using a native buffer. * * @param[in] scheduler Target scheduler. * @param[in] io An io object to read from. * @param[in] base The memory to read to. * @param[in] size Size of the memory. * @param[in] length The minimum number of bytes to read. * @retval RUBY_Qundef `scheduler` doesn't have `#io_read`. * @return otherwise What `scheduler.io_read` returns. */ VALUE rb_fiber_scheduler_io_read_memory(VALUE scheduler, VALUE io, void *base, size_t size, size_t length); /** * Non-blocking write to the passed IO using a native buffer. * * @param[in] scheduler Target scheduler. * @param[in] io An io object to write to. * @param[in] base The memory to write from. * @param[in] size Size of the memory. * @param[in] length The minimum number of bytes to write. * @retval RUBY_Qundef `scheduler` doesn't have `#io_write`. * @return otherwise What `scheduler.io_write` returns. */ VALUE rb_fiber_scheduler_io_write_memory(VALUE scheduler, VALUE io, const void *base, size_t size, size_t length); /** * Non-blocking pread from the passed IO using a native buffer. * * @param[in] scheduler Target scheduler. * @param[in] io An io object to read from. * @param[in] from The offset to read from. * @param[in] base The memory to read to. * @param[in] size Size of the memory. * @param[in] length The minimum number of bytes to read. * @retval RUBY_Qundef `scheduler` doesn't have `#io_read`. * @return otherwise What `scheduler.io_read` returns. */ VALUE rb_fiber_scheduler_io_pread_memory(VALUE scheduler, VALUE io, rb_off_t from, void *base, size_t size, size_t length); /** * Non-blocking pwrite to the passed IO using a native buffer. * * @param[in] scheduler Target scheduler. * @param[in] io An io object to write to. * @param[in] from The offset to write from. * @param[in] base The memory to write from. * @param[in] size Size of the memory. * @param[in] length The minimum number of bytes to write. * @retval RUBY_Qundef `scheduler` doesn't have `#io_write`. * @return otherwise What `scheduler.io_write` returns. */ VALUE rb_fiber_scheduler_io_pwrite_memory(VALUE scheduler, VALUE io, rb_off_t from, const void *base, size_t size, size_t length); /** * Non-blocking close the given IO. * * @param[in] scheduler Target scheduler. * @param[in] io An io object to close. * @retval RUBY_Qundef `scheduler` doesn't have `#io_close`. * @return otherwise What `scheduler.io_close` returns. */ VALUE rb_fiber_scheduler_io_close(VALUE scheduler, VALUE io); /** * Non-blocking DNS lookup. * * @param[in] scheduler Target scheduler. * @param[in] hostname A host name to query. * @retval RUBY_Qundef `scheduler` doesn't have `#address_resolve`. * @return otherwise What `scheduler.address_resolve` returns. */ VALUE rb_fiber_scheduler_address_resolve(VALUE scheduler, VALUE hostname); /** * Create and schedule a non-blocking fiber. * */ VALUE rb_fiber_scheduler_fiber(VALUE scheduler, int argc, VALUE *argv, int kw_splat); RBIMPL_SYMBOL_EXPORT_END() #endif /* RUBY_FIBER_SCHEDULER_H */ include/ruby/io/buffer.h 0000644 00000007744 15152150505 0011214 0 ustar 00 #ifndef RUBY_IO_BUFFER_H #define RUBY_IO_BUFFER_H /** * @file * @author Samuel Williams * @date Fri 2 Jul 2021 16:29:01 NZST * @copyright Copyright (C) 2021 Samuel Williams * @copyright This file is a part of the programming language Ruby. * Permission is hereby granted, to either redistribute and/or * modify this file, provided that the conditions mentioned in the * file COPYING are met. Consult the file for details. */ #pragma once #include "ruby/ruby.h" #include "ruby/internal/config.h" RBIMPL_SYMBOL_EXPORT_BEGIN() // WARNING: This entire interface is experimental and may change in the future! #define RB_IO_BUFFER_EXPERIMENTAL 1 #define RUBY_IO_BUFFER_VERSION 2 // The `IO::Buffer` class. RUBY_EXTERN VALUE rb_cIOBuffer; // The operating system page size. RUBY_EXTERN size_t RUBY_IO_BUFFER_PAGE_SIZE; // The default buffer size, usually a (small) multiple of the page size. // Can be overridden by the RUBY_IO_BUFFER_DEFAULT_SIZE environment variable. RUBY_EXTERN size_t RUBY_IO_BUFFER_DEFAULT_SIZE; // Represents the internal state of the buffer. // More than one flag can be set at a time. enum rb_io_buffer_flags { // The memory in the buffer is owned by someone else. // More specifically, it means that someone else owns the buffer and we shouldn't try to resize it. RB_IO_BUFFER_EXTERNAL = 1, // The memory in the buffer is allocated internally. RB_IO_BUFFER_INTERNAL = 2, // The memory in the buffer is mapped. // A non-private mapping is marked as external. RB_IO_BUFFER_MAPPED = 4, // A mapped buffer that is also shared. RB_IO_BUFFER_SHARED = 8, // The buffer is locked and cannot be resized. // More specifically, it means we can't change the base address or size. // A buffer is typically locked before a system call that uses the data. RB_IO_BUFFER_LOCKED = 32, // The buffer mapping is private and will not impact other processes or the underlying file. RB_IO_BUFFER_PRIVATE = 64, // The buffer is read-only and cannot be modified. RB_IO_BUFFER_READONLY = 128, // The buffer is backed by a file. RB_IO_BUFFER_FILE = 256, }; // Represents the endian of the data types. enum rb_io_buffer_endian { // The least significant units are put first. RB_IO_BUFFER_LITTLE_ENDIAN = 4, RB_IO_BUFFER_BIG_ENDIAN = 8, #if defined(WORDS_BIGENDIAN) RB_IO_BUFFER_HOST_ENDIAN = RB_IO_BUFFER_BIG_ENDIAN, #else RB_IO_BUFFER_HOST_ENDIAN = RB_IO_BUFFER_LITTLE_ENDIAN, #endif RB_IO_BUFFER_NETWORK_ENDIAN = RB_IO_BUFFER_BIG_ENDIAN }; VALUE rb_io_buffer_new(void *base, size_t size, enum rb_io_buffer_flags flags); VALUE rb_io_buffer_map(VALUE io, size_t size, rb_off_t offset, enum rb_io_buffer_flags flags); VALUE rb_io_buffer_lock(VALUE self); VALUE rb_io_buffer_unlock(VALUE self); int rb_io_buffer_try_unlock(VALUE self); VALUE rb_io_buffer_free(VALUE self); VALUE rb_io_buffer_free_locked(VALUE self); // Access the internal buffer and flags. Validates the pointers. // The points may not remain valid if the source buffer is manipulated. // Consider using rb_io_buffer_lock if needed. enum rb_io_buffer_flags rb_io_buffer_get_bytes(VALUE self, void **base, size_t *size); void rb_io_buffer_get_bytes_for_reading(VALUE self, const void **base, size_t *size); void rb_io_buffer_get_bytes_for_writing(VALUE self, void **base, size_t *size); VALUE rb_io_buffer_transfer(VALUE self); void rb_io_buffer_resize(VALUE self, size_t size); void rb_io_buffer_clear(VALUE self, uint8_t value, size_t offset, size_t length); // The length is the minimum required length. VALUE rb_io_buffer_read(VALUE self, VALUE io, size_t length, size_t offset); VALUE rb_io_buffer_pread(VALUE self, VALUE io, rb_off_t from, size_t length, size_t offset); VALUE rb_io_buffer_write(VALUE self, VALUE io, size_t length, size_t offset); VALUE rb_io_buffer_pwrite(VALUE self, VALUE io, rb_off_t from, size_t length, size_t offset); RBIMPL_SYMBOL_EXPORT_END() #endif /* RUBY_IO_BUFFER_H */ include/ruby/missing.h 0000644 00000015261 15152150505 0010776 0 ustar 00 #ifndef RUBY_MISSING_H /*-*-C++-*-vi:se ft=cpp:*/ #define RUBY_MISSING_H 1 /** * @author $Author$ * @date Sat May 11 23:46:03 JST 2002 * @copyright This file is a part of the programming language Ruby. * Permission is hereby granted, to either redistribute and/or * modify this file, provided that the conditions mentioned in the * file COPYING are met. Consult the file for details. * @brief Prototype for *.c in ./missing, and for missing timeval struct. */ #include "ruby/internal/config.h" #ifdef STDC_HEADERS # include <stddef.h> #endif #if defined(__cplusplus) # include <cmath> #else # include <math.h> /* for INFINITY and NAN */ #endif #ifdef RUBY_ALTERNATIVE_MALLOC_HEADER # include RUBY_ALTERNATIVE_MALLOC_HEADER #endif #if defined(HAVE_TIME_H) # include <time.h> #endif #if defined(HAVE_SYS_TIME_H) # include <sys/time.h> #endif #ifdef HAVE_SYS_STAT_H # include <sys/stat.h> #endif #ifdef HAVE_UNISTD_H # include <unistd.h> #endif #ifdef HAVE_STDIO_H # include <stdio.h> #endif #ifdef HAVE_IEEEFP_H # include <ieeefp.h> #endif #include "ruby/internal/dllexport.h" #include "ruby/internal/attr/format.h" #ifndef M_PI # define M_PI 3.14159265358979323846 #endif #ifndef M_PI_2 # define M_PI_2 (M_PI/2) #endif #if !defined(HAVE_STRUCT_TIMEVAL) struct timeval { time_t tv_sec; /* seconds */ long tv_usec; /* microseconds */ }; #endif /* HAVE_STRUCT_TIMEVAL */ #if !defined(HAVE_STRUCT_TIMESPEC) /* :BEWARE: @shyouhei warns that IT IS A WRONG IDEA to define our own version * of struct timespec here. `clock_gettime` is a system call, and your kernel * could expect something other than just `long` (results stack smashing if * that happens). See also https://ewontfix.com/19/ */ struct timespec { time_t tv_sec; /* seconds */ long tv_nsec; /* nanoseconds */ }; #endif #if !defined(HAVE_STRUCT_TIMEZONE) struct timezone { int tz_minuteswest; int tz_dsttime; }; #endif RBIMPL_SYMBOL_EXPORT_BEGIN() #ifndef HAVE_ACOSH RUBY_EXTERN double acosh(double); RUBY_EXTERN double asinh(double); RUBY_EXTERN double atanh(double); #endif #ifndef HAVE_CRYPT RUBY_EXTERN char *crypt(const char *, const char *); #endif #ifndef HAVE_EACCESS RUBY_EXTERN int eaccess(const char*, int); #endif #ifndef HAVE_ROUND RUBY_EXTERN double round(double); /* numeric.c */ #endif #ifndef HAVE_FLOCK RUBY_EXTERN int flock(int, int); #endif /* #ifndef HAVE_FREXP RUBY_EXTERN double frexp(double, int *); #endif */ #ifndef HAVE_HYPOT RUBY_EXTERN double hypot(double, double); #endif #ifndef HAVE_ERF RUBY_EXTERN double erf(double); RUBY_EXTERN double erfc(double); #endif #ifndef HAVE_TGAMMA RUBY_EXTERN double tgamma(double); #endif #ifndef HAVE_LGAMMA_R RUBY_EXTERN double lgamma_r(double, int *); #endif #ifndef HAVE_CBRT RUBY_EXTERN double cbrt(double); #endif #if !defined(INFINITY) || !defined(NAN) union bytesequence4_or_float { unsigned char bytesequence[4]; float float_value; }; #endif #ifndef INFINITY /** @internal */ RUBY_EXTERN const union bytesequence4_or_float rb_infinity; # define INFINITY (rb_infinity.float_value) # define USE_RB_INFINITY 1 #endif #ifndef NAN /** @internal */ RUBY_EXTERN const union bytesequence4_or_float rb_nan; # define NAN (rb_nan.float_value) # define USE_RB_NAN 1 #endif #ifndef HUGE_VAL # define HUGE_VAL ((double)INFINITY) #endif #ifndef HAVE_FINITE # define HAVE_FINITE 1 # define finite(x) isfinite(x) #endif #ifndef HAVE_NAN RUBY_EXTERN double nan(const char *); #endif #ifndef HAVE_NEXTAFTER RUBY_EXTERN double nextafter(double x, double y); #endif /* #ifndef HAVE_MEMCMP RUBY_EXTERN int memcmp(const void *, const void *, size_t); #endif */ #ifndef HAVE_MEMMOVE RUBY_EXTERN void *memmove(void *, const void *, size_t); #endif /* #ifndef HAVE_MODF RUBY_EXTERN double modf(double, double *); #endif */ #ifndef HAVE_STRCHR RUBY_EXTERN char *strchr(const char *, int); RUBY_EXTERN char *strrchr(const char *, int); #endif #ifndef HAVE_STRERROR RUBY_EXTERN char *strerror(int); #endif #ifndef HAVE_STRSTR RUBY_EXTERN char *strstr(const char *, const char *); #endif #ifndef HAVE_STRLCPY RUBY_EXTERN size_t strlcpy(char *, const char*, size_t); #endif #ifndef HAVE_STRLCAT RUBY_EXTERN size_t strlcat(char *, const char*, size_t); #endif #ifndef HAVE_FFS RUBY_EXTERN int ffs(int); #endif #ifdef BROKEN_CLOSE # include <sys/types.h> # include <sys/socket.h> RUBY_EXTERN int ruby_getpeername(int, struct sockaddr *, socklen_t *); RUBY_EXTERN int ruby_getsockname(int, struct sockaddr *, socklen_t *); RUBY_EXTERN int ruby_shutdown(int, int); RUBY_EXTERN int ruby_close(int); #endif #ifndef HAVE_SETPROCTITLE RBIMPL_ATTR_FORMAT(RBIMPL_PRINTF_FORMAT, 1, 2) RUBY_EXTERN void setproctitle(const char *fmt, ...); #endif #ifdef HAVE_EXPLICIT_BZERO # /* Take that. */ #elif defined(SecureZeroMemory) # define explicit_bzero(b, len) SecureZeroMemory(b, len) #else RUBY_EXTERN void explicit_bzero(void *b, size_t len); #endif #ifndef HAVE_TZSET RUBY_EXTERN void tzset(void); #endif #ifndef HAVE_POSIX_MADVISE RUBY_EXTERN int posix_madvise(void *, size_t, int); #endif #ifndef HAVE_GETEUID RUBY_EXTERN rb_uid_t geteuid(void); #endif #ifndef HAVE_GETUID RUBY_EXTERN rb_uid_t getuid(void); #endif #ifndef HAVE_GETEGID RUBY_EXTERN rb_gid_t getegid(void); #endif #ifndef HAVE_GETGID RUBY_EXTERN rb_gid_t getgid(void); #endif #ifndef HAVE_GETLOGIN RUBY_EXTERN char *getlogin(void); #endif #ifndef HAVE_GETPPID RUBY_EXTERN rb_pid_t getppid(void); #endif #ifndef HAVE_UMASK RUBY_EXTERN rb_mode_t umask(rb_mode_t); #endif #ifndef HAVE_CHMOD RUBY_EXTERN int chmod(const char *, rb_mode_t); #endif #ifndef HAVE_CHOWN RUBY_EXTERN int chown(const char *, rb_uid_t, rb_gid_t); #endif #ifndef HAVE_PCLOSE RUBY_EXTERN int pclose(FILE *); #endif #ifndef HAVE_POPEN RUBY_EXTERN FILE *popen(const char *, const char *); #endif #ifndef HAVE_PIPE RUBY_EXTERN int pipe(int [2]); #endif #ifndef HAVE_DUP RUBY_EXTERN int dup(int); #endif #ifndef HAVE_DUP2 RUBY_EXTERN int dup2(int, int); #endif #ifndef HAVE_KILL RUBY_EXTERN int kill(rb_pid_t, int); #endif #ifndef HAVE_EXECL RUBY_EXTERN int execl(const char *, const char *, ...); #endif #ifndef HAVE_EXECLE RUBY_EXTERN int execle(const char *, const char *, ...); #endif #ifndef HAVE_EXECV RUBY_EXTERN int execv(const char *, char *const []); #endif #ifndef HAVE_EXECVE RUBY_EXTERN int execve(const char *, char *const [], char *const []); #endif #ifndef HAVE_SHUTDOWN RUBY_EXTERN int shutdown(int, int); #endif #ifndef HAVE_SYSTEM RUBY_EXTERN int system(const char *); #endif #ifndef WNOHANG # define WNOHANG 0 #endif #ifndef HAVE_WAITPID # define HAVE_WAITPID 1 RUBY_EXTERN rb_pid_t waitpid(rb_pid_t, int *, int); #endif RBIMPL_SYMBOL_EXPORT_END() #endif /* RUBY_MISSING_H */ include/ruby/thread_native.h 0000644 00000015262 15152150505 0012143 0 ustar 00 #ifndef RUBY_THREAD_NATIVE_H /*-*-C++-*-vi:se ft=cpp:*/ #define RUBY_THREAD_NATIVE_H 1 /** * @file * @author $Author: ko1 $ * @date Wed May 14 19:37:31 2014 * @copyright Copyright (C) 2014 Yukihiro Matsumoto * @copyright This file is a part of the programming language Ruby. * Permission is hereby granted, to either redistribute and/or * modify this file, provided that the conditions mentioned in the * file COPYING are met. Consult the file for details. * * This file contains wrapper APIs for native thread primitives * which Ruby interpreter uses. * * Now, we only support pthread and Windows threads. * * If you want to use Ruby's Mutex and so on to synchronize Ruby Threads, * please use Mutex directly. */ #if defined(_WIN32) #include <windows.h> typedef HANDLE rb_nativethread_id_t; typedef union rb_thread_lock_union { HANDLE mutex; CRITICAL_SECTION crit; } rb_nativethread_lock_t; struct rb_thread_cond_struct { struct cond_event_entry *next; struct cond_event_entry *prev; }; typedef struct rb_thread_cond_struct rb_nativethread_cond_t; #elif defined(HAVE_PTHREAD_H) #include <pthread.h> typedef pthread_t rb_nativethread_id_t; typedef pthread_mutex_t rb_nativethread_lock_t; typedef pthread_cond_t rb_nativethread_cond_t; #elif defined(__wasi__) // no-thread platforms typedef struct rb_nativethread_id_t *rb_nativethread_id_t; typedef struct rb_nativethread_lock_t *rb_nativethread_lock_t; typedef struct rb_nativethread_cond_t *rb_nativethread_cond_t; #elif defined(__DOXYGEN__) /** Opaque type that holds an ID of a native thread. */ struct rb_nativethread_id_t; /** Opaque type that holds a lock. */ struct rb_nativethread_lock_t; /** Opaque type that holds a condition variable. */ struct rb_nativethread_cond_t; #else #error "unsupported thread type" #endif RBIMPL_SYMBOL_EXPORT_BEGIN() /** * Queries the ID of the native thread that is calling this function. * * @return The caller thread's native ID. */ rb_nativethread_id_t rb_nativethread_self(void); /** * Fills the passed lock with an initial value. * * @param[out] lock A mutex to initialise. * @post `lock` is updated to its initial state. * * @internal * * There is no data structure that analogous to pthread_once_t in ruby. It is * pretty much tricky (if not impossible) to properly initialise a mutex * exactly once. */ void rb_nativethread_lock_initialize(rb_nativethread_lock_t *lock); /** * Destroys the passed mutex. * * @param[out] lock A mutex to kill. * @post `lock` is no longer eligible for other functions. * * @internal * * It is an undefined behaviour (see `pthread_mutex_destroy(3posix)`) to * destroy a locked mutex. So it has to be unlocked. But an unlocked mutex * can of course be locked by another thread. That's the ultimate reason why * we do mutex. There is an inevitable race condition here. 2017 edition of * IEEE 1003.1 issue 7 says in its rationale that "care must be taken". Care? * How? * * @shyouhei thinks that POSIX is broken by design. */ void rb_nativethread_lock_destroy(rb_nativethread_lock_t *lock); /** * Blocks until the current thread obtains a lock. * * @param[out] lock A mutex to lock. * @post `lock` is owned by the current native thread. */ void rb_nativethread_lock_lock(rb_nativethread_lock_t *lock); /** * Releases a lock. * * @param[out] lock A mutex to unlock. * @pre `lock` is owned by the current native thread. * @post `lock` is not owned by the current native thread. */ void rb_nativethread_lock_unlock(rb_nativethread_lock_t *lock); /** @alias{rb_nativethread_lock_lock} */ void rb_native_mutex_lock(rb_nativethread_lock_t *lock); /** * Identical to rb_native_mutex_lock(), except it doesn't block in case * rb_native_mutex_lock() would. * * @param[out] lock A mutex to lock. * @retval 0 `lock` is successfully owned by the current thread. * @retval EBUSY `lock` is owned by someone else. */ int rb_native_mutex_trylock(rb_nativethread_lock_t *lock); /** @alias{rb_nativethread_lock_unlock} */ void rb_native_mutex_unlock(rb_nativethread_lock_t *lock); /** @alias{rb_nativethread_lock_initialize} */ void rb_native_mutex_initialize(rb_nativethread_lock_t *lock); /** @alias{rb_nativethread_lock_destroy} */ void rb_native_mutex_destroy(rb_nativethread_lock_t *lock); /** * Signals a condition variable. * * @param[out] cond A condition variable to ping. * @post More than one threads waiting for `cond` gets signalled. * @note This function can spuriously wake multiple threads up. * `pthread_cond_signal(3posix)` says it can even be "impossible * to avoid the unblocking of more than one thread blocked on a * condition variable". Just brace spurious wakeups. */ void rb_native_cond_signal(rb_nativethread_cond_t *cond); /** * Signals a condition variable. * * @param[out] cond A condition variable to ping. * @post All threads waiting for `cond` gets signalled. */ void rb_native_cond_broadcast(rb_nativethread_cond_t *cond); /** * Waits for the passed condition variable to be signalled. * * @param[out] cond A condition variable to wait. * @param[out] mutex A mutex. * @pre `mutex` is owned by the current thread. * @post `mutex` is owned by the current thread. * @note This can wake up spuriously. */ void rb_native_cond_wait(rb_nativethread_cond_t *cond, rb_nativethread_lock_t *mutex); /** * Identical to rb_native_cond_wait(), except it additionally takes timeout in * msec resolution. Timeouts can be detected by catching exceptions. * * @param[out] cond A condition variable to wait. * @param[out] mutex A mutex. * @param[in] msec Timeout. * @exception rb_eSystemCallError `Errno::ETIMEDOUT` for timeout. * @pre `mutex` is owned by the current thread. * @post `mutex` is owned by the current thread. * @note This can wake up spuriously. */ void rb_native_cond_timedwait(rb_nativethread_cond_t *cond, rb_nativethread_lock_t *mutex, unsigned long msec); /** * Fills the passed condition variable with an initial value. * * @param[out] cond A condition variable to initialise. * @post `cond` is updated to its initial state. */ void rb_native_cond_initialize(rb_nativethread_cond_t *cond); /** * Destroys the passed condition variable. * * @param[out] cond A condition variable to kill. * @post `cond` is no longer eligible for other functions. */ void rb_native_cond_destroy(rb_nativethread_cond_t *cond); RBIMPL_SYMBOL_EXPORT_END() #endif include/ruby/version.h 0000644 00000011413 15152150505 0011005 0 ustar 00 #ifndef RUBY_VERSION_H /*-*-C++-*-vi:se ft=cpp:*/ #define RUBY_VERSION_H 1 /** * @file * @author $Author$ * @date Wed May 13 12:56:56 JST 2009 * @copyright Copyright (C) 1993-2009 Yukihiro Matsumoto * @copyright Copyright (C) 2000 Network Applied Communication Laboratory, Inc. * @copyright Copyright (C) 2000 Information-technology Promotion Agency, Japan * @copyright This file is a part of the programming language Ruby. * Permission is hereby granted, to either redistribute and/or * modify this file, provided that the conditions mentioned in the * file COPYING are met. Consult the file for details. * * This file contains only * - never-changeable information, and * - interfaces accessible from extension libraries. * * Never try to check RUBY_VERSION_CODE etc in extension libraries, * check the features with mkmf.rb instead. */ /** * @name The origin. * * These information never change. Just written here to remember. * * @{ */ /** Author of this project. */ #define RUBY_AUTHOR "Yukihiro Matsumoto" /** Ruby's birth year. */ #define RUBY_BIRTH_YEAR 1993 /** Ruby's birth month. */ #define RUBY_BIRTH_MONTH 2 /** Ruby's birth day. */ #define RUBY_BIRTH_DAY 24 /** @} */ /** * @name The API version. * * API version is different from binary version. These numbers are for API * stability. When you have distinct API versions x and y, you cannot expect * codes targeted to x also works for y. * * However let us repeat here that it's a BAD idea to check * #RUBY_API_VERSION_CODE form extension libraries. Different API versions are * just different. There is no such thing like upper compatibility. * * @{ */ /** * Major version. This digit changes sometimes for various reasons, but that * doesn't mean a total rewrite. Practically when it comes to API versioning, * major and minor version changes are equally catastrophic. */ #define RUBY_API_VERSION_MAJOR 3 /** * Minor version. As of writing this version changes annually. Greater * version doesn't mean "better"; they just mean years passed. */ #define RUBY_API_VERSION_MINOR 3 /** * Teeny version. This digit is kind of reserved these days. Kept 0 for the * entire 2.x era. Waiting for future uses. */ #define RUBY_API_VERSION_TEENY 0 /** * This macro is API versions encoded into a C integer. * * @note Use mkmf. * @note Don't rely on it. */ #define RUBY_API_VERSION_CODE (RUBY_API_VERSION_MAJOR*10000+RUBY_API_VERSION_MINOR*100+RUBY_API_VERSION_TEENY) /** @} */ #ifdef RUBY_EXTERN /* Internal note: this file could be included from verconf.mk _before_ * generating config.h, on Windows. The #ifdef above is to trick such * situation. */ RBIMPL_SYMBOL_EXPORT_BEGIN() /** * @name Interfaces from extension libraries. * * Before using these infos, think thrice whether they are really * necessary or not, and if the answer was yes, think twice a week * later again. * * @{ */ /** API versions, in { major, minor, teeny } order. */ RUBY_EXTERN const int ruby_api_version[3]; /** * Stringised version. * * @note This is the runtime version, not the API version. For instance it * was `"2.5.9"` when ::ruby_api_version was `{ 2, 5, 0 }`. */ RUBY_EXTERN const char ruby_version[]; /** Date of release, in a C string. */ RUBY_EXTERN const char ruby_release_date[]; /** * Target platform identifier, in a C string. * * @note Seasoned UNIX programmers should beware that this "platform * identifier" is our invention; not always identical to so-called * target triplets that GNU systems use. For instance on @shyouhei's * machine, ::ruby_platform is `"x64_64-linux"` while its target triplet * is `x86_64-pc-linux-gnu`. * @note Note also that we support Windows. */ RUBY_EXTERN const char ruby_platform[]; /** * This is a monotonic increasing integer that describes specific "patch" * level. You can know the exact changeset your binary is running by this info * (and ::ruby_version), unless this is -1. -1 means there is no release yet * for the version; ruby is actively developed. 0 means the initial GA version. */ RUBY_EXTERN const int ruby_patchlevel; /** * This is what `ruby -v` prints to the standard error. Something like: * `"ruby 2.5.9p229 (2021-04-05 revision 67829) [x86_64-linux]"`. This doesn't * include runtime options like a JIT being enabled. */ RUBY_EXTERN const char ruby_description[]; /** Copyright notice. */ RUBY_EXTERN const char ruby_copyright[]; /** * This is just `"ruby"` for us. But different implementations can have * different strings here. */ RUBY_EXTERN const char ruby_engine[]; /** @} */ RBIMPL_SYMBOL_EXPORT_END() #endif #endif bin/bundler 0000755 00000001075 15152150505 0006677 0 ustar 00 #!/opt/alt/ruby33/bin/ruby # # This file was generated by RubyGems. # # The application 'bundler' is installed as part of a gem, and # this file is here to facilitate running it. # require 'rubygems' version = ">= 0.a" str = ARGV.first if str str = str.b[/\A_(.*)_\z/, 1] if str and Gem::Version.correct?(str) version = str ENV['BUNDLER_VERSION'] = str ARGV.shift end end if Gem.respond_to?(:activate_bin_path) load Gem.activate_bin_path('bundler', 'bundler', version) else gem "bundler", version load Gem.bin_path("bundler", "bundler", version) end bin/gem 0000755 00000000404 15152150505 0006007 0 ustar 00 #!/opt/alt/ruby33/bin/ruby # frozen_string_literal: true #-- # Copyright 2006 by Chad Fowler, Rich Kilmer, Jim Weirich and others. # All rights reserved. # See LICENSE.txt for permissions. #++ require "rubygems/gem_runner" Gem::GemRunner.new.run ARGV.clone bin/syntax_suggest 0000755 00000001126 15152150505 0010330 0 ustar 00 #!/opt/alt/ruby33/bin/ruby # # This file was generated by RubyGems. # # The application 'syntax_suggest' is installed as part of a gem, and # this file is here to facilitate running it. # require 'rubygems' Gem.use_gemdeps version = ">= 0.a" str = ARGV.first if str str = str.b[/\A_(.*)_\z/, 1] if str and Gem::Version.correct?(str) version = str ARGV.shift end end if Gem.respond_to?(:activate_bin_path) load Gem.activate_bin_path('syntax_suggest', 'syntax_suggest', version) else gem "syntax_suggest", version load Gem.bin_path("syntax_suggest", "syntax_suggest", version) end bin/rdoc 0000755 00000001032 15152150505 0006164 0 ustar 00 #!/opt/alt/ruby33/bin/ruby # # This file was generated by RubyGems. # # The application 'rdoc' is installed as part of a gem, and # this file is here to facilitate running it. # require 'rubygems' Gem.use_gemdeps version = ">= 0.a" str = ARGV.first if str str = str.b[/\A_(.*)_\z/, 1] if str and Gem::Version.correct?(str) version = str ARGV.shift end end if Gem.respond_to?(:activate_bin_path) load Gem.activate_bin_path('rdoc', 'rdoc', version) else gem "rdoc", version load Gem.bin_path("rdoc", "rdoc", version) end bin/rackup 0000755 00000001046 15152150505 0006527 0 ustar 00 #!/opt/alt/ruby33/bin/ruby # # This file was generated by RubyGems. # # The application 'rackup' is installed as part of a gem, and # this file is here to facilitate running it. # require 'rubygems' Gem.use_gemdeps version = ">= 0.a" str = ARGV.first if str str = str.b[/\A_(.*)_\z/, 1] if str and Gem::Version.correct?(str) version = str ARGV.shift end end if Gem.respond_to?(:activate_bin_path) load Gem.activate_bin_path('rackup', 'rackup', version) else gem "rackup", version load Gem.bin_path("rackup", "rackup", version) end bin/rake 0000755 00000001032 15152150505 0006157 0 ustar 00 #!/opt/alt/ruby33/bin/ruby # # This file was generated by RubyGems. # # The application 'rake' is installed as part of a gem, and # this file is here to facilitate running it. # require 'rubygems' Gem.use_gemdeps version = ">= 0.a" str = ARGV.first if str str = str.b[/\A_(.*)_\z/, 1] if str and Gem::Version.correct?(str) version = str ARGV.shift end end if Gem.respond_to?(:activate_bin_path) load Gem.activate_bin_path('rake', 'rake', version) else gem "rake", version load Gem.bin_path("rake", "rake", version) end bin/erb 0000755 00000001024 15152150505 0006006 0 ustar 00 #!/opt/alt/ruby33/bin/ruby # # This file was generated by RubyGems. # # The application 'erb' is installed as part of a gem, and # this file is here to facilitate running it. # require 'rubygems' Gem.use_gemdeps version = ">= 0.a" str = ARGV.first if str str = str.b[/\A_(.*)_\z/, 1] if str and Gem::Version.correct?(str) version = str ARGV.shift end end if Gem.respond_to?(:activate_bin_path) load Gem.activate_bin_path('erb', 'erb', version) else gem "erb", version load Gem.bin_path("erb", "erb", version) end bin/ruby 0000755 00000027510 15152150505 0006227 0 ustar 00 ELF >