require "crystal/at_exit_handlers" {% unless flag?(:win32) %} require "c/unistd" {% end %} # The standard input file descriptor. Contains data piped to the program. # # On Unix systems, if the file descriptor is a TTY, the runtime duplicates it. # So `STDIN.fd` might not be `0`. # The reason for this is to enable non-blocking reads for concurrency. Other fibers # can run while waiting on user input. The original file descriptor is # inherited from the parent process. Setting it to non-blocking mode would # reflect back, which can cause problems. # # On Windows, `STDIN` is always blocking. STDIN = IO::FileDescriptor.from_stdio(0) # The standard output file descriptor. # # Typically used to output data and information. # # At the start of the program STDOUT is configured like this: # - if it's a TTY device (like the console) then `sync` is `true`, # meaning that output will be outputted as soon as it is written # to STDOUT. This is so users can see real time output data. # - if it's not a TTY device (like a file, or because the output # was piped to a file) then `sync` is `false` but `flush_on_newline` # is `true`. This is so that if you pipe the output to a file, and, # for example, you `tail -f`, you can see data on a line-per-line basis. # This is convenient but slower than with `flush_on_newline` set to `false`. # If you need a bit more performance and you don't care about near real-time # output you can do `STDOUT.flush_on_newline = false`. # # On Unix systems, if the file descriptor is a TTY, the runtime duplicates it. # So `STDOUT.fd` might not be `1`. # The reason for this is to enable non-blocking writes for concurrency. Other fibers # can run while waiting on IO. The original file descriptor is # inherited from the parent process. Setting it to non-blocking mode would # reflect back which can cause problems. # # On Windows, `STDOUT` is always blocking. STDOUT = IO::FileDescriptor.from_stdio(1) # The standard error file descriptor. # # Typically used to output error messages and diagnostics. # # At the start of the program STDERR is configured like this: # - if it's a TTY device (like the console) then `sync` is `true`, # meaning that output will be outputted as soon as it is written # to STDERR. This is so users can see real time output data. # - if it's not a TTY device (like a file, or because the output # was piped to a file) then `sync` is `false` but `flush_on_newline` # is `true`. This is so that if you pipe the output to a file, and, # for example, you `tail -f`, you can see data on a line-per-line basis. # This is convenient but slower than with `flush_on_newline` set to `false`. # If you need a bit more performance and you don't care about near real-time # output you can do `STDERR.flush_on_newline = false`. # # On Unix systems, if the file descriptor is a TTY, the runtime duplicates it. # So `STDERR.fd` might not be `2`. # The reason for this is to enable non-blocking writes for concurrency. Other fibers # can run while waiting on IO. The original file descriptor is # inherited from the parent process. Setting it to non-blocking mode would # reflect back which can cause problems. # # On Windows, `STDERR` is always blocking. STDERR = IO::FileDescriptor.from_stdio(2) # The name, the program was called with. # # The result may be a relative or absolute path (including symbolic links), # just the command name or the empty string. # # See `Process.executable_path` for a more convenient alternative that always # returns the absolute real path to the executable file (if it exists). PROGRAM_NAME = String.new(ARGV_UNSAFE.value) # An array of arguments passed to the program. ARGV = Array.new(ARGC_UNSAFE - 1) { |i| String.new(ARGV_UNSAFE[1 + i]) } # An `IO` for reading files from `ARGV`. # # Usage example: # # `program.cr`: # ``` # puts ARGF.gets_to_end # ``` # # A file to read from: (`file`) # ```text # 123 # ``` # # ```text # $ crystal build program.cr # $ ./program file # 123 # $ ./program file file # 123123 # $ # If ARGV is empty, ARGF reads from STDIN instead: # $ echo "hello" | ./program # hello # $ ./program unknown # Unhandled exception: Error opening file with mode 'r': 'unknown': No such file or directory (File::NotFoundError) # ... # ``` # # After a file from `ARGV` has been read, it's removed from `ARGV`. # # You can manipulate `ARGV` yourself to control what `ARGF` operates on. # If you remove a file from `ARGV`, it is ignored by `ARGF`; if you add files to `ARGV`, `ARGF` will read from it. # # ``` # ARGV.replace ["file1"] # ARGF.gets_to_end # => Content of file1 # ARGV # => [] # ARGV << "file2" # ARGF.gets_to_end # => Content of file2 # ``` ARGF = IO::ARGF.new(ARGV, STDIN) # The newline constant EOL = {% if flag?(:windows) %} "\r\n" {% else %} "\n" {% end %} # Repeatedly executes the block. # # ``` # loop do # line = gets # break unless line # # ... # end # ``` def loop(&) while true yield end end # Reads a line from `STDIN`. # # See also: `IO#gets`. def gets(*args, **options) STDIN.gets(*args, **options) end # Reads a line from `STDIN`. # # See also: `IO#read_line`. def read_line(*args, **options) STDIN.read_line(*args, **options) end # Prints objects to `STDOUT` and then invokes `STDOUT.flush`. # # See also: `IO#print`. def print(*objects : _) : Nil STDOUT.print *objects end # Prints a formatted string to `STDOUT`. # # For details on the format string, see `sprintf`. def printf(format_string, *args) : Nil printf format_string, args end # :ditto: def printf(format_string, args : Array | Tuple) : Nil STDOUT.printf format_string, args end # Returns a formatted string. # The string is produced according to the *format_string* with format specifiers # being replaced by values from *args* formatted according to the specifier. # # Within the format string, any characters other than format specifiers # (specifiers beginning with `%`) are copied to the result. The formatter # supports the following kinds of format specifiers: # # * Sequential (`%.1f`). The first `%` consumes the first argument, the second # consumes the second argument, and so on. # * Positional (`%3$.1f`). The one-based argument index is specified as part of # the flags. # * Named substitution (`%.1f`, `%{name}`). The angle bracket form accepts # flags and the curly bracket form doesn't. Exactly one `Hash` or `NamedTuple` # must be passed as the argument. # # Mixing of different kinds of format specifiers is disallowed, except that the # two named forms may be used together. # # A simple format specifier consists of a percent sign, followed by optional flags, # width, and precision indicators, then terminated with a field type # character. # # ```text # %[flags][width][.precision]type # ``` # # A formatted substitution is similar but after the percent sign follows the # mandatory name of the substitution wrapped in angle brackets. # # ```text # %[flags][width][.precision]type # ``` # # The percent sign itself is escaped by `%%`. No format modifiers are allowed, # and no arguments are consumed. # # The field type controls how the corresponding argument value is to be # interpreted, while the flags modify that interpretation. # # The field type characters are: # # ```text # Field | Integer Format # ------+------------------------------------------------------------------ # b | Formats argument as a binary number. # d | Formats argument as a decimal number. # i | Same as d. # o | Formats argument as an octal number. # x | Formats argument as a hexadecimal number using lowercase letters. # X | Same as x, but uses uppercase letters. # # Field | Float Format # ------+--------------------------------------------------------------- # e | Formats floating point argument into exponential notation # | with one digit before the decimal point as [-]d.dddddde[+-]dd. # | The precision specifies the number of digits after the decimal # | point (defaulting to six). # E | Equivalent to e, but uses an uppercase E to indicate # | the exponent. # f | Formats floating point argument as [-]ddd.dddddd, # | where the precision specifies the number of digits after # | the decimal point. # g | Formats a floating point number using exponential form # | if the exponent is less than -4 or greater than or # | equal to the precision, or in dd.dddd form otherwise. # | The precision specifies the number of significant digits. # G | Equivalent to g, but use an uppercase E in exponent form. # a | Formats floating point argument as [-]0xh.hhhhp[+-]dd, # | which consists of an optional sign, "0x", fraction part # | as hexadecimal, "p", and exponential part as decimal. # A | Equivalent to a, but uses uppercase X and P. # # Field | Other Format # ------+------------------------------------------------------------ # c | Argument is a single character itself. # s | Argument is a string to be substituted. If the format # | sequence contains a precision, at most that many characters # | will be copied. # ``` # # Flags modify the behavior of the format specifiers: # # ```text # Flag | Applies to | Meaning # ---------+---------------+---------------------------------------------------- # space | bdiouxX | Add a leading space character to # | aAeEfgG | non-negative numbers. Has no effect if the plus # | (numeric fmt) | flag is also given. # ---------+---------------+---------------------------------------------------- # # | boxX | Use an alternative format. # | aAeEfgG | For x, X, b, prefix any non-zero result with # | | 0x, 0X, or 0b respectively. # | | For o, prefix any non-zero result with 0o. Note # | | that this prefix is different from C and Ruby. # | | For a, A, e, E, f, g, G, # | | force a decimal point to be added, # | | even if no digits follow. # | | For g and G, do not remove trailing zeros. # ---------+---------------+---------------------------------------------------- # + | bdiouxX | Add a leading plus sign to non-negative # | aAeEfgG | numbers. # | (numeric fmt) | # ---------+---------------+---------------------------------------------------- # - | all | Left-justify the result of this conversion. # ---------+---------------+---------------------------------------------------- # 0 (zero) | bdiouxX | Pad with zeros, not spaces. Has no effect if the # | aAeEfgG | number is left-justified, or a precision is given # | (numeric fmt) | to an integer field type. # ---------+---------------+---------------------------------------------------- # * | all | Use the next argument as the field width or # | | precision. If width is negative, set the minus flag # | | and use the argument's absolute value as field # | | width. If precision is negative, it is ignored. # ---------+---------------+---------------------------------------------------- # 1$ 2$ 3$ | all | As a flag, specifies the one-based argument index # ... | | for a positional format specifier. # | | Immediately after *, use the argument at the given # | | one-based index as the width or precision, instead # | | of the next argument. The entire format string must # | | also use positional format specifiers throughout. # ``` # # Examples of flags: # # Decimal number conversion: # ``` # sprintf "%d", 123 # => "123" # sprintf "%+d", 123 # => "+123" # sprintf "% d", 123 # => " 123" # ``` # # Octal number conversion: # ``` # sprintf "%o", 123 # => "173" # sprintf "%+o", 123 # => "+173" # sprintf "%o", -123 # => "-173" # sprintf "%+o", -123 # => "-173" # ``` # # Hexadecimal number conversion: # ``` # sprintf "%x", 123 # => "7b" # sprintf "%+x", 123 # => "+7b" # sprintf "%x", -123 # => "-7b" # sprintf "%+x", -123 # => "-7b" # sprintf "%#x", 0 # => "0" # sprintf "% x", 123 # => " 7b" # sprintf "% x", -123 # => "-7b" # sprintf "%X", 123 # => "7B" # sprintf "%#X", -123 # => "-0X7B" # ``` # # Binary number conversion: # ``` # sprintf "%b", 123 # => "1111011" # sprintf "%+b", 123 # => "+1111011" # sprintf "%+b", -123 # => "-1111011" # sprintf "%b", -123 # => "-1111011" # sprintf "%#b", 0 # => "0" # sprintf "% b", 123 # => " 1111011" # sprintf "%+ b", 123 # => "+1111011" # sprintf "% b", -123 # => "-1111011" # sprintf "%+ b", -123 # => "-1111011" # sprintf "%#b", 123 # => "0b1111011" # ``` # # Floating point conversion: # ``` # sprintf "%a", 123 # => "0x1.ecp+6" # sprintf "%A", 123 # => "0X1.ECP+6" # ``` # # Exponential form conversion: # ``` # sprintf "%g", 123.4 # => "123.4" # sprintf "%g", 123.4567 # => "123.457" # sprintf "%20.8g", 1234.56789 # => " 1234.5679" # sprintf "%20.8g", 123456789 # => " 1.2345679e+08" # sprintf "%20.8G", 123456789 # => " 1.2345679E+08" # sprintf "%20.8g", -123456789 # => " -1.2345679e+08" # sprintf "%20.8G", -123456789 # => " -1.2345679E+08" # ``` # # The field width is an optional integer, followed optionally by a # period and a precision. The width specifies the minimum number of # characters that will be written to the result for this field. # # Examples of width: # ``` # sprintf "%20d", 123 # => " 123" # sprintf "%+20d", 123 # => " +123" # sprintf "%020d", 123 # => "00000000000000000123" # sprintf "%+020d", 123 # => "+0000000000000000123" # sprintf "% 020d", 123 # => " 0000000000000000123" # sprintf "%-20d", 123 # => "123 " # sprintf "%-+20d", 123 # => "+123 " # sprintf "%- 20d", 123 # => " 123 " # sprintf "%020x", -123 # => "-000000000000000007b" # sprintf "%020X", -123 # => "-000000000000000007B" # ``` # # For numeric fields, the precision controls the number of decimal places # displayed. # # For string fields, the precision determines the maximum # number of characters to be copied from the string. # # Examples of precisions: # # Precision for `d`, `o`, `x` and `b` is # minimum number of digits: # ``` # sprintf "%20.8d", 123 # => " 00000123" # sprintf "%020.8d", 123 # => " 00000123" # sprintf "%20.8o", 123 # => " 00000173" # sprintf "%020.8o", 123 # => " 00000173" # sprintf "%20.8x", 123 # => " 0000007b" # sprintf "%020.8x", 123 # => " 0000007b" # sprintf "%20.8b", 123 # => " 01111011" # sprintf "%20.8d", -123 # => " -00000123" # sprintf "%020.8d", -123 # => " -00000123" # sprintf "%20.8o", -123 # => " -00000173" # sprintf "%20.8x", -123 # => " -0000007b" # sprintf "%20.8b", -11 # => " -00001011" # ``` # # Precision for `e` is number of digits after the decimal point: # ``` # sprintf "%20.8e", 1234.56789 # => " 1.23456789e+03" # ``` # # Precision for `f` is number of digits after the decimal point: # ``` # sprintf "%20.8f", 1234.56789 # => " 1234.56789000" # ``` # # Precision for `g` is number of significant digits: # ``` # sprintf "%20.8g", 1234.56789 # => " 1234.5679" # sprintf "%20.8g", 123456789 # => " 1.2345679e+08" # sprintf "%-20.8g", 123456789 # => "1.2345679e+08 " # ``` # # Precision for `s` is maximum number of characters: # ``` # sprintf "%20.8s", "string test" # => " string t" # ``` # # Additional examples: # ``` # sprintf "%d %04x", 123, 123 # => "123 007b" # sprintf "%08b '%4s'", 123, 123 # => "01111011 ' 123'" # sprintf "%+g:% g:%-g", 1.23, 1.23, 1.23 # => "+1.23: 1.23:1.23" # sprintf "%-3$*1$.*2$s", 10, 5, "abcdefghij" # => "abcde " # ``` def sprintf(format_string, *args) : String sprintf format_string, args end # :ditto: def sprintf(format_string, args : Array | Tuple) : String String.build(format_string.bytesize) do |str| String::Formatter(typeof(args)).new(format_string, args, str).format end end # Prints *objects* to `STDOUT`, each followed by a newline character unless # the object is a `String` and already ends with a newline. # # See also: `IO#puts`. def puts(*objects) : Nil STDOUT.puts *objects end # Inspects *object* to `STDOUT` followed # by a newline. Returns *object*. # # See also: `Object#inspect(io)`. def p(object) object.inspect(STDOUT) puts object end # Inspects each object in *objects* to `STDOUT`, followed # by a newline. Returns *objects*. # # See also: `Object#inspect(io)`. def p(*objects) objects.each do |obj| p obj # ameba:disable Lint/DebugCalls end objects end # Inspects *objects* to `STDOUT`, followed # by a newline. Returns *objects*. # # ``` # p foo: 23, bar: 42 # => {foo: 23, bar: 42} # ``` # # See `Object#inspect(io)` def p(**objects) p(objects) unless objects.empty? # ameba:disable Lint/DebugCalls end # Pretty prints *object* to `STDOUT` followed # by a newline. Returns *object*. # # See also: `Object#pretty_print(pp)`. def pp(object) PrettyPrint.format(object, STDOUT, 79) puts object end # Pretty prints each object in *objects* to `STDOUT`, followed # by a newline. Returns *objects*. # # See also: `Object#pretty_print(pp)`. def pp(*objects) objects.each do |obj| pp obj # ameba:disable Lint/DebugCalls end objects end # Pretty prints *objects* to `STDOUT`, followed # by a newline. Returns *objects*. # # ``` # p foo: 23, bar: 42 # => {foo: 23, bar: 42} # ``` # # See `Object#pretty_print(pp)` def pp(**objects) pp(objects) unless objects.empty? # ameba:disable Lint/DebugCalls end # Registers the given `Proc` for execution when the program exits regularly. # # A regular exit happens when either # * the main fiber reaches the end of the program, # * the main fiber rescues an unhandled exception, or # * `::exit` is called. # # `Process.exit` does *not* trigger `at_exit` handlers, nor does external process # termination (see `Process.on_terminate` for handling that). # # If multiple handlers are registered, they are executed in reverse order of registration. # # ``` # def do_at_exit(str1) # at_exit { print str1 } # end # # at_exit { puts "cruel world" } # do_at_exit("goodbye ") # exit # ``` # # Produces: # # ```text # goodbye cruel world # ``` # # The exit status code that will be returned by this program is passed to # the block as its first argument. In case of any unhandled exception, it is # passed as the second argument to the block, if the program terminates # normally or `exit(status)` is called explicitly, then the second argument # will be `nil`. # # NOTE: If `at_exit` is called inside an `at_exit` handler, it will be called # right after the current `at_exit` handler ends, and then other handlers # will be invoked. def at_exit(&handler : Int32, Exception? ->) : Nil Crystal::AtExitHandlers.add(handler) end # Terminates execution immediately, returning the given status code # to the invoking environment. # # Registered `at_exit` procs are executed. def exit(status : Int32 | Process::Status = 0) : NoReturn status = Crystal::AtExitHandlers.run status Crystal.ignore_stdio_errors { STDOUT.flush } Crystal.ignore_stdio_errors { STDERR.flush } Process.exit(status) end # Terminates execution immediately, printing *message* to `STDERR` and # then calling `exit(status)`. def abort(message = nil, status = 1) : NoReturn Crystal.ignore_stdio_errors { STDERR.puts message } if message exit status end {% if !flag?(:preview_mt) && flag?(:unix) %} class Process # :nodoc: # # Hooks are defined here due to load order problems. def self.after_fork_child_callbacks @@after_fork_child_callbacks ||= [ # reinit event loop first: -> { Crystal::EventLoop.current.after_fork }, # reinit signal handling: ->Crystal::System::Signal.after_fork, ->Crystal::System::SignalChildHandler.after_fork, # additional reinitialization ->Random::DEFAULT.new_seed, -> { Random.thread_default.new_seed }, ] of -> Nil end end {% end %} {% unless flag?(:interpreted) || flag?(:wasm32) %} {% if flag?(:execution_context) %} Fiber::ExecutionContext.init_default_context {% else %} Crystal::Scheduler.init {% end %} # load debug info on start up of the program is executed with CRYSTAL_LOAD_DEBUG_INFO=1 # this will make debug info available on print_frame that is used by Crystal's segfault handler # # - CRYSTAL_LOAD_DEBUG_INFO=0 will never use debug info (See Exception::CallStack.load_debug_info) # - CRYSTAL_LOAD_DEBUG_INFO=1 will load debug info on startup # - Other values will load debug info on demand: when the backtrace of the first exception is generated Exception::CallStack.load_debug_info if ENV["CRYSTAL_LOAD_DEBUG_INFO"]? == "1" Exception::CallStack.setup_crash_handler {% if flag?(:win32) %} Crystal::System::Process.start_interrupt_loop {% else %} Crystal::System::Signal.setup_default_handlers {% end %} {% end %} {% if flag?(:interpreted) && flag?(:unix) && Crystal::Interpreter.class.has_method?(:signal_descriptor) %} Crystal::System::Signal.setup_default_handlers {% end %}