관리-도구
편집 파일: ruby.h
#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 */