pax_global_header00006660000000000000000000000064127166224460014524gustar00rootroot0000000000000052 comment=d64c914c1ece85f4f85f8b89e2111fb5dafa7372 lua-systemd-master/000077500000000000000000000000001271662244600146305ustar00rootroot00000000000000lua-systemd-master/.gitignore000066400000000000000000000000201271662244600166100ustar00rootroot00000000000000*.o *.so *.rock lua-systemd-master/LICENSE000066400000000000000000000020661271662244600156410ustar00rootroot00000000000000The MIT License (MIT) Copyright (c) 2014 Daurnimator Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. lua-systemd-master/README.md000066400000000000000000000642201271662244600161130ustar00rootroot00000000000000# [Systemd](http://freedesktop.org/wiki/Software/systemd/) for Lua. This library is for working with systemd from scripts and daemons written in Lua. Where necessary, the low level `libsystemd` functions have been bound in C. Higher level functions with more idiomatic lua semantics are written in Lua on top of these C primitives. Compatible with Lua 5.1, 5.2 and 5.3 (thanks [compat-5.3](https://github.com/keplerproject/lua-compat-5.3)). # Status Waiting for API to stabilise before making an initial release. ## Todo - [x] [Notify](http://www.freedesktop.org/software/systemd/man/sd_notify.html) - Notify service manager about start-up completion and other daemon status changes - [x] [ID128](http://www.freedesktop.org/software/systemd/man/sd-id128.html) - APIs for processing 128-bit IDs - [x] [Journal](http://www.freedesktop.org/software/systemd/man/sd-journal.html) - [x] [Journal Writing](http://www.freedesktop.org/software/systemd/man/sd_journal_sendv.html) - [x] [Journal Reading](http://www.freedesktop.org/software/systemd/man/sd_journal_next.html) - [x] [Journal Change Notification](http://www.freedesktop.org/software/systemd/man/sd_journal_get_fd.html) - [x] [Login](http://www.freedesktop.org/software/systemd/man/sd-login.html) - [x] [PID/Peer Information](http://www.freedesktop.org/software/systemd/man/sd_pid_get_session.html) - [x] [User State](http://www.freedesktop.org/software/systemd/man/sd_uid_get_state.html) - [x] [Session Information](http://www.freedesktop.org/software/systemd/man/sd_session_is_active.html) - [x] [Seat Information](http://www.freedesktop.org/software/systemd/man/sd_seat_get_active.html) - [x] [Login Monitoring](http://www.freedesktop.org/software/systemd/man/sd_login_monitor.html) - Monitor login sessions, seats, users and virtual machines/containers - [ ] Unit Control - Requires use of [dbus API](http://www.freedesktop.org/wiki/Software/systemd/dbus/) # Installation lua-systemd is on luarocks: https://luarocks.org/modules/daurnimator/systemd Install via luarocks: `luarocks install --server=http://luarocks.org/manifests/daurnimator systemd` # Usage ## Bound from C All functions return `nil, error_message [, errno]` in case of error. C | Lua | Comments -----------------------------------------------------------------------------------------------------------------------------------------|------------------------------------------|---------------------------------------- [`SD_LISTEN_FDS_START`](http://www.freedesktop.org/software/systemd/man/SD_LISTEN_FDS_START.html) | `systemd.daemon.LISTEN_FDS_START` | [`sd_notify()`](http://www.freedesktop.org/software/systemd/man/sd_notify.html) | `systemd.daemon.notify()` | [`sd_pid_notify()`](http://www.freedesktop.org/software/systemd/man/sd_pid_notify.html) | `systemd.daemon.pid_notify()` | [`sd_pid_notify_with_fds()`](http://www.freedesktop.org/software/systemd/man/sd_pid_notify_with_fds.html) | `systemd.daemon.pid_notify_with_fds()` | [`sd_booted()`](http://www.freedesktop.org/software/systemd/man/sd_booted.html) | `systemd.daemon.booted()` | [`sd_listen_fds()`](http://www.freedesktop.org/software/systemd/man/sd_listen_fds.html) | `systemd.daemon.listen_fds()` | [`sd_journal_sendv()`](http://www.freedesktop.org/software/systemd/man/sd_journal_sendv.html) | `systemd.journal.sendv()` | [`sd_journal_perror()`](http://www.freedesktop.org/software/systemd/man/sd_journal_perror.html) | `systemd.journal.perror()` | [`sd_journal_stream_fd()`](http://www.freedesktop.org/software/systemd/man/sd_journal_stream_fd.html) | `systemd.journal.stream_fd()` | On success, returns a Lua `file` object instead of raw file descriptor [`SD_JOURNAL_LOCAL_ONLY`](http://www.freedesktop.org/software/systemd/man/SD_JOURNAL_LOCAL_ONLY.html) | `systemd.journal.OPEN.LOCAL_ONLY` | [`SD_JOURNAL_RUNTIME_ONLY`](http://www.freedesktop.org/software/systemd/man/SD_JOURNAL_RUNTIME_ONLY.html) | `systemd.journal.OPEN.RUNTIME_ONLY` | [`SD_JOURNAL_SYSTEM`](http://www.freedesktop.org/software/systemd/man/SD_JOURNAL_SYSTEM.html) | `systemd.journal.OPEN.SYSTEM` | [`SD_JOURNAL_CURRENT_USER`](http://www.freedesktop.org/software/systemd/man/SD_JOURNAL_CURRENT_USER.html) | `systemd.journal.OPEN.CURRENT_USER` | [`sd_journal_open()`](http://www.freedesktop.org/software/systemd/man/sd_journal_open.html) | `systemd.journal.open()` | [`sd_journal_open_directory()`](http://www.freedesktop.org/software/systemd/man/sd_journal_open_directory.html) | `systemd.journal.open_directory()` | [`sd_journal_open_files()`](http://www.freedesktop.org/software/systemd/man/sd_journal_open_files.html) | `systemd.journal.open_files()` | [`sd_journal_open_container()`](http://www.freedesktop.org/software/systemd/man/sd_journal_open_container.html) | `systemd.journal.open_container()` | [`sd_journal_close()`](http://www.freedesktop.org/software/systemd/man/sd_journal_close.html) | | Bound as `__gc` metamethod on journal objects [`sd_journal_get_cutoff_realtime_usec()`](http://www.freedesktop.org/software/systemd/man/sd_journal_get_cutoff_realtime_usec.html) | `my_journal:get_cutoff_realtime_usec()` | [`sd_journal_get_cutoff_monotonic_usec()`](http://www.freedesktop.org/software/systemd/man/sd_journal_get_cutoff_monotonic_usec.html) | `my_journal:get_cutoff_monotonic_usec()` | [`sd_journal_get_usage()`](http://www.freedesktop.org/software/systemd/man/sd_journal_get_usage.html) | `my_journal:get_usage()` | [`sd_journal_next()`](http://www.freedesktop.org/software/systemd/man/sd_journal_next.html) | `my_journal:next()` | [`sd_journal_next_skip()`](http://www.freedesktop.org/software/systemd/man/sd_journal_next_skip.html) | `my_journal:next_skip()` | [`sd_journal_previous()`](http://www.freedesktop.org/software/systemd/man/sd_journal_previous.html) | `my_journal:previous()` | [`sd_journal_previous_skip()`](http://www.freedesktop.org/software/systemd/man/sd_journal_previous_skip.html) | `my_journal:previous_skip()` | [`sd_journal_seek_head()`](http://www.freedesktop.org/software/systemd/man/sd_journal_seek_head.html) | `my_journal:seek_head()` | [`sd_journal_seek_tail()`](http://www.freedesktop.org/software/systemd/man/sd_journal_seek_tail.html) | `my_journal:seek_tail()` | [`sd_journal_seek_monotonic_usec()`](http://www.freedesktop.org/software/systemd/man/sd_journal_seek_monotonic_usec.html) | `my_journal:seek_monotonic_usec()` | [`sd_journal_seek_realtime_usec()`](http://www.freedesktop.org/software/systemd/man/sd_journal_seek_realtime_usec.html) | `my_journal:seek_realtime_usec()` | [`sd_journal_seek_cursor()`](http://www.freedesktop.org/software/systemd/man/sd_journal_seek_cursor.html) | `my_journal:seek_cursor()` | [`sd_journal_get_cursor()`](http://www.freedesktop.org/software/systemd/man/sd_journal_get_cursor.html) | `my_journal:get_cursor()` | [`sd_journal_test_cursor()`](http://www.freedesktop.org/software/systemd/man/sd_journal_test_cursor.html) | `my_journal:test_cursor()` | [`sd_journal_get_realtime_usec()`](http://www.freedesktop.org/software/systemd/man/sd_journal_get_realtime_usec.html) | `my_journal:get_realtime_usec()` | [`sd_journal_get_monotonic_usec()`](http://www.freedesktop.org/software/systemd/man/sd_journal_get_monotonic_usec.html) | `my_journal:get_monotonic_usec()` | [`sd_journal_get_data()`](http://www.freedesktop.org/software/systemd/man/sd_journal_get_data.html) | `my_journal:get_data()` | [`sd_journal_enumerate_data()`](http://www.freedesktop.org/software/systemd/man/sd_journal_enumerate_data.html) | `my_journal:enumerate_data()` | [`sd_journal_restart_data()`](http://www.freedesktop.org/software/systemd/man/sd_journal_restart_data.html) | `my_journal:restart_data()` | [`sd_journal_query_unique()`](http://www.freedesktop.org/software/systemd/man/sd_journal_query_unique.html) | `my_journal:query_unique()` | [`sd_journal_enumerate_unique()`](http://www.freedesktop.org/software/systemd/man/sd_journal_enumerate_unique.html) | `my_journal:enumerate_unique()` | [`sd_journal_restart_unique()`](http://www.freedesktop.org/software/systemd/man/sd_journal_restart_unique.html) | `my_journal:restart_unique()` | [`sd_journal_set_data_threshold()`](http://www.freedesktop.org/software/systemd/man/sd_journal_set_data_threshold.html) | `my_journal:set_data_threshold()` | [`sd_journal_get_data_threshold()`](http://www.freedesktop.org/software/systemd/man/sd_journal_get_data_threshold.html) | `my_journal:get_data_threshold()` | [`sd_journal_add_match()`](http://www.freedesktop.org/software/systemd/man/sd_journal_add_match.html) | `my_journal:add_match()` | [`sd_journal_add_disjunction()`](http://www.freedesktop.org/software/systemd/man/sd_journal_add_disjunction.html) | `my_journal:add_disjunction()` | [`sd_journal_add_conjunction()`](http://www.freedesktop.org/software/systemd/man/sd_journal_add_conjunction.html) | `my_journal:add_conjunction()` | [`sd_journal_flush_matches()`](http://www.freedesktop.org/software/systemd/man/sd_journal_flush_matches.html) | `my_journal:flush_matches()` | [`SD_JOURNAL_NOP`](http://www.freedesktop.org/software/systemd/man/SD_JOURNAL_NOP.html) | `systemd.journal.WAKEUP.NOP` | [`SD_JOURNAL_APPEND`](http://www.freedesktop.org/software/systemd/man/SD_JOURNAL_APPEND.html) | `systemd.journal.WAKEUP.APPEND` | [`SD_JOURNAL_INVALIDATE`](http://www.freedesktop.org/software/systemd/man/SD_JOURNAL_INVALIDATE.html) | `systemd.journal.WAKEUP.INVALIDATE` | [`sd_journal_get_fd()`](http://www.freedesktop.org/software/systemd/man/sd_journal_get_fd.html) | `my_journal:get_fd()` | [`sd_journal_get_events()`](http://www.freedesktop.org/software/systemd/man/sd_journal_get_events.html) | `my_journal:get_events()` | [`sd_journal_get_timeout()`](http://www.freedesktop.org/software/systemd/man/sd_journal_get_timeout.html) | `my_journal:get_timeout()` | Returns `false` if timeout isn't available, otherwise returns value in seconds [`sd_journal_process()`](http://www.freedesktop.org/software/systemd/man/sd_journal_process.html) | `my_journal:process()` | [`sd_journal_wait()`](http://www.freedesktop.org/software/systemd/man/sd_journal_wait.html) | `my_journal:wait()` | `timeout` is in seconds instead of microseconds [`sd_journal_reliable_fd()`](http://www.freedesktop.org/software/systemd/man/sd_journal_reliable_fd.html) | `my_journal:reliable_fd()` | [`sd_id128_randomize()`](http://www.freedesktop.org/software/systemd/man/sd_id128_randomize.html) | `systemd.id128.randomize()` | Also available as `randomise` for any non-americans out there [`sd_id128_from_string()`](http://www.freedesktop.org/software/systemd/man/sd_id128_from_string.html) | `systemd.id128.from_string()` | [`sd_id128_get_machine()`](http://www.freedesktop.org/software/systemd/man/sd_id128_get_machine.html) | `systemd.id128.get_machine()` | [`sd_id128_get_boot()`](http://www.freedesktop.org/software/systemd/man/sd_id128_get_boot.html) | `systemd.id128.get_boot()` | [`sd_id128_to_string()`](http://www.freedesktop.org/software/systemd/man/sd_id128_to_string.html) | `my_id128:to_string()` | Also available as `__tostring` metamethod: `tostring(my_id128_t)` [`sd_id128_equal()`](http://www.freedesktop.org/software/systemd/man/sd_id128_equal.html) | `id128_a == id128_b` | Bound as `__eq` metamethod [`sd_journal_get_catalog_for_message_id()`](http://www.freedesktop.org/software/systemd/man/sd_journal_get_catalog_for_message_id.html) | `my_id128:get_catalog()` | [`sd_get_seats()`](http://www.freedesktop.org/software/systemd/man/sd_get_seats.html) | `systemd.login.get_seats()` | [`sd_get_sessions()`](http://www.freedesktop.org/software/systemd/man/sd_get_sessions.html) | `systemd.login.get_sessions()` | [`sd_get_uids()`](http://www.freedesktop.org/software/systemd/man/sd_get_uids.html) | `systemd.login.get_uids()` | [`sd_get_machine_names()`](http://www.freedesktop.org/software/systemd/man/sd_get_machine_names.html) | `systemd.login.get_machine_names()` | [`sd_pid_get_session()`](http://www.freedesktop.org/software/systemd/man/sd_pid_get_session.html) | `systemd.login.pid_get_session()` | [`sd_pid_get_unit()`](http://www.freedesktop.org/software/systemd/man/sd_pid_get_unit.html) | `systemd.login.pid_get_unit()` | [`sd_pid_get_user_unit()`](http://www.freedesktop.org/software/systemd/man/sd_pid_get_user_unit.html) | `systemd.login.pid_get_user_unit()` | [`sd_pid_get_owner_uid()`](http://www.freedesktop.org/software/systemd/man/sd_pid_get_owner_uid.html) | `systemd.login.pid_get_owner_uid()` | [`sd_pid_get_machine_name()`](http://www.freedesktop.org/software/systemd/man/sd_pid_get_machine_name.html) | `systemd.login.pid_get_machine_name()` | [`sd_pid_get_slice()`](http://www.freedesktop.org/software/systemd/man/sd_pid_get_slice.html) | `systemd.login.pid_get_slice()` | [`sd_pid_get_user_slice()`](http://www.freedesktop.org/software/systemd/man/sd_pid_get_user_slice.html) | `systemd.login.pid_get_user_slice()` | [`sd_peer_get_session()`](http://www.freedesktop.org/software/systemd/man/sd_peer_get_session.html) | `systemd.login.peer_get_session()` | [`sd_peer_get_unit()`](http://www.freedesktop.org/software/systemd/man/sd_peer_get_unit.html) | `systemd.login.peer_get_unit()` | [`sd_peer_get_user_unit()`](http://www.freedesktop.org/software/systemd/man/sd_peer_get_user_unit.html) | `systemd.login.peer_get_user_unit()` | [`sd_peer_get_owner_uid()`](http://www.freedesktop.org/software/systemd/man/sd_peer_get_owner_uid.html) | `systemd.login.peer_get_owner_uid()` | [`sd_peer_get_machine_name()`](http://www.freedesktop.org/software/systemd/man/sd_peer_get_machine_name.html) | `systemd.login.peer_get_machine_name()` | [`sd_peer_get_slice()`](http://www.freedesktop.org/software/systemd/man/sd_peer_get_slice.html) | `systemd.login.peer_get_slice()` | [`sd_peer_get_user_slice()`](http://www.freedesktop.org/software/systemd/man/sd_peer_get_user_slice.html) | `systemd.login.peer_get_user_slice()` | [`sd_uid_get_state()`](http://www.freedesktop.org/software/systemd/man/sd_uid_get_state.html) | `systemd.login.uid_get_state()` | [`sd_uid_is_on_seat()`](http://www.freedesktop.org/software/systemd/man/sd_uid_is_on_seat.html) | `systemd.login.uid_is_on_seat()` | [`sd_uid_get_sessions()`](http://www.freedesktop.org/software/systemd/man/sd_uid_get_sessions.html) | `systemd.login.uid_get_sessions()` | [`sd_uid_get_seats()`](http://www.freedesktop.org/software/systemd/man/sd_uid_get_seats.html) | `systemd.login.uid_get_seats()` | [`sd_uid_get_display()`](http://www.freedesktop.org/software/systemd/man/sd_uid_get_display.html) | `systemd.login.uid_get_display()` | [`sd_session_is_active()`](http://www.freedesktop.org/software/systemd/man/sd_session_is_active.html) | `systemd.login.session_is_active()` | [`sd_session_is_remote()`](http://www.freedesktop.org/software/systemd/man/sd_session_is_remote.html) | `systemd.login.session_is_remote()` | [`sd_session_get_state()`](http://www.freedesktop.org/software/systemd/man/sd_session_get_state.html) | `systemd.login.session_get_state()` | [`sd_session_get_uid()`](http://www.freedesktop.org/software/systemd/man/sd_session_get_uid.html) | `systemd.login.session_get_uid()` | [`sd_session_get_seat()`](http://www.freedesktop.org/software/systemd/man/sd_session_get_seat.html) | `systemd.login.session_get_seat()` | [`sd_session_get_service()`](http://www.freedesktop.org/software/systemd/man/sd_session_get_service.html) | `systemd.login.session_get_service()` | [`sd_session_get_type()`](http://www.freedesktop.org/software/systemd/man/sd_session_get_type.html) | `systemd.login.session_get_type()` | [`sd_session_get_class()`](http://www.freedesktop.org/software/systemd/man/sd_session_get_class.html) | `systemd.login.session_get_class()` | [`sd_session_get_desktop()`](http://www.freedesktop.org/software/systemd/man/sd_session_get_desktop.html) | `systemd.login.session_get_desktop()` | [`sd_session_get_display()`](http://www.freedesktop.org/software/systemd/man/sd_session_get_display.html) | `systemd.login.session_get_display()` | [`sd_session_get_remote_host()`](http://www.freedesktop.org/software/systemd/man/sd_session_get_remote_host.html) | `systemd.login.session_get_remote_host()`| [`sd_session_get_remote_user()`](http://www.freedesktop.org/software/systemd/man/sd_session_get_remote_user.html) | `systemd.login.session_get_remote_user()`| [`sd_session_get_tty()`](http://www.freedesktop.org/software/systemd/man/sd_session_get_tty.html) | `systemd.login.session_get_tty()` | [`sd_session_get_vt()`](http://www.freedesktop.org/software/systemd/man/sd_session_get_vt.html) | `systemd.login.session_get_vt()` | [`sd_seat_get_active()`](http://www.freedesktop.org/software/systemd/man/sd_seat_get_active.html) | `systemd.login.seat_get_active()` | On success, returns `session, uid` [`sd_seat_get_sessions()`](http://www.freedesktop.org/software/systemd/man/sd_seat_get_sessions.html) | `systemd.login.seat_get_sessions()` | On success, returns `sessions, uids` [`sd_seat_can_multi_session()`](http://www.freedesktop.org/software/systemd/man/sd_seat_can_multi_session.html) | `systemd.login.seat_can_multi_session()` | [`sd_seat_can_tty()`](http://www.freedesktop.org/software/systemd/man/sd_seat_can_tty.html) | `systemd.login.seat_can_tty()` | [`sd_seat_can_graphical()`](http://www.freedesktop.org/software/systemd/man/sd_seat_can_graphical.html) | `systemd.login.seat_can_graphical()` | [`sd_machine_get_class()`](http://www.freedesktop.org/software/systemd/man/sd_machine_get_class.html) | `systemd.login.machine_get_class()` | [`sd_machine_get_ifindices()`](http://www.freedesktop.org/software/systemd/man/sd_machine_get_ifindices.html) | `systemd.login.machine_get_ifindices()` | [`sd_login_monitor_new()`](http://www.freedesktop.org/software/systemd/man/sd_login_monitor_new.html) | `systemd.login.monitor()` | [`sd_login_monitor_unref()`](http://www.freedesktop.org/software/systemd/man/sd_login_monitor_unref.html) | | Bound as `__gc` metamethod on monitor objects [`sd_login_monitor_flush()`](http://www.freedesktop.org/software/systemd/man/sd_login_monitor_flush.html) | `my_login_monitor:flush()` | [`sd_login_monitor_get_fd()`](http://www.freedesktop.org/software/systemd/man/sd_login_monitor_get_fd.html) | `my_login_monitor:get_fd()` | [`sd_login_monitor_get_events()`](http://www.freedesktop.org/software/systemd/man/sd_login_monitor_get_events.html) | `my_login_monitor:get_events()` | [`sd_login_monitor_get_timeout()`](http://www.freedesktop.org/software/systemd/man/sd_login_monitor_get_timeout.html) | `my_login_monitor:get_timeout()` | Returns `false` if timeout isn't available, otherwise returns value in seconds ## Misc extras ### `systemd.daemon.notifyt(tbl)` and `systemd.daemon.pid_notifyt(tbl)` Like `notify`, but takes a lua table instead of a newline delimited list. Numbers will be coerced to strings. ```lua notifyt { READY = 1, STATUS = "Server now accepting connections", WATCHDOG = 1 } ``` ### `interval = systemd.daemon.watchdog_enabled()` Returns the watchdog interval (in seconds) if there is one set otherwise returns `false`. You should call `kick_dog` or `notify("WATCHDOG=1")` every half of this interval. Similar functionality to [`sd_watchdog_enabled()`](http://www.freedesktop.org/software/systemd/man/sd_watchdog_enabled.html) ### `systemd.daemon.kick_dog()` Tells systemd to update the watchdog timestamp. This should be called on an interval. ### `systemd.journal.LOG` Table containing the `syslog(3)` priority constants: `EMERG`, `ALERT`, `CRIT`, `ERR`, `WARNING`, `NOTICE`, `INFO`, `DEBUG` Useful as the second argument to `systemd.journal.streamfd()` ### `systemd.journal.print(priority, fmt_string, ...)` Same argument signature as C, but written in lua on top of `sendv()` and `string.format()` ### `systemd.journal.sendt(tbl)` Log a message to the journal with the key/value pairs from `tbl` ```lua systemd.journal.sendt { SYSLOG_IDENTIFIER = "identifier" ; SYSLOG_FACILITY = "facility" ; PRIORITY = systemd.journal.LOG.ERR ; MESSAGE = "something happended!" ; MY_CUSTOM_FIELD = "extra detail."; } ``` ### `value = my_journal:get(field)` Returns the given field from the current journal entry (which may be `nil`) Throws a lua error on failure. ### `my_journal:each_data()` A valid lua iterator that enumerates through field, value pairs. ```lua for field, value in my_journal:each_data() do print(field, value) end ``` Throws a lua error on failure. ### `my_journal:each_unique(field_name)` A valid lua iterator that enumerates through unique field values. ```lua -- Print each different `_SYSTEMD_UNIT` for value in my_journal:each_unique("_SYSTEMD_UNIT") do print(value) end ``` Throws a lua error on failure. ### `t = my_journal:to_table()` Converts the current journal entry to a lua table. Includes [Address Fields](http://www.freedesktop.org/software/systemd/man/systemd.journal-fields.html#Address%20Fields): - `__CURSOR` - `__REALTIME_TIMESTAMP` - `__MONOTONIC_TIMESTAMP` ### `text = my_journal:get_catalog()` Looks up the current journal entry's `MESSAGE_ID` in the [message catalog](http://www.freedesktop.org/wiki/Software/systemd/catalog/). Substitutes the templated fields (between `@` symbols) with values from this journal entry. Returns: - the filled out catalogue entry as a string - `false` if `MESSAGE_ID` is not set, or does not exist in the catalogue - `nil, err_msg, errno` in case of failure. Same functionality as [`sd_journal_get_catalog()`](http://www.freedesktop.org/software/systemd/man/sd_journal_get_catalog.html). ### `systemd.messages` A table of well-known message ids as `id128` objects. Taken from [`sd-messages.h`](http://cgit.freedesktop.org/systemd/systemd/tree/src/systemd/sd-messages.h?id=HEAD) lua-systemd-master/examples/000077500000000000000000000000001271662244600164465ustar00rootroot00000000000000lua-systemd-master/examples/list-boots.lua000077500000000000000000000016251271662244600212570ustar00rootroot00000000000000#!/usr/bin/env lua --[[ This program acts like journalctl --list-boots ]] local sj = require "systemd.journal" local j = assert(sj.open()) local t = {} local n = 0 for boot_id in j:each_unique("_BOOT_ID") do local boot_info = { id = boot_id; } n = n + 1 t[n] = boot_info -- We need to find the first and last entries for each boot assert(j:add_match("_BOOT_ID="..boot_id)) assert(j:seek_head()) assert(j:next()) boot_info.head = j:get_realtime_usec() assert(j:seek_tail()) assert(j:previous()) boot_info.tail = j:get_realtime_usec() j:flush_matches() end table.sort(t, function(a,b) return a.head < b.head end) local d_width = math.floor(math.log(n, 10))+2 for i=1, n do local boot_info = t[i] io.write(string.format("%"..d_width.."d %s %s—%s\n", i-n, boot_info.id, os.date("%a %Y-%m-%d %H:%M:%S %Z", boot_info.head/1e6), os.date("%a %Y-%m-%d %H:%M:%S %Z", boot_info.tail/1e6) )) end lua-systemd-master/examples/logger.lua000066400000000000000000000005761271662244600204400ustar00rootroot00000000000000local journal = require "systemd.journal" function log(severity, msg, level) local info = debug.getinfo((level or 1)+1, "nlS") if info.currentline == -1 then info.currentline = nil end return assert(journal.sendt{ CODE_FILE = info.short_src; CODE_FUNC = info.name; CODE_LINE = info.currentline; PRIORITY = journal.LOG[severity:upper()] or 5; MESSAGE = msg; }) end lua-systemd-master/examples/new_id.lua000077500000000000000000000010171271662244600204200ustar00rootroot00000000000000#!/usr/bin/env lua --[[ This program acts like `journalctl --new-id128` ]] local id128 = require "systemd.id128" local myuuid = tostring(assert(id128.randomise())) io.write(table.concat({ "As string:", myuuid, "", "As UUID:", myuuid:gsub("(........)(....)(....)(....)(........)", "%1-%2-%3-%4-%5"), "", "As macro:", "#define MESSAGE_XYZ SD_ID128_MAKE(" .. myuuid:gsub("(..)", "%1,"):sub(1,-2) .. ")", "", "As Python constant:", ">>> import uuid", ">>> MESSAGE_XYZ = uuid.UUID('" .. myuuid .. "')", "" },"\n")) lua-systemd-master/examples/tail_logs.lua000066400000000000000000000032201271662244600211230ustar00rootroot00000000000000#!/usr/bin/env lua --[[ This script will tail your journal. Output will be in json format. Uses the cqueues library (see http://25thandclement.com/~william/projects/cqueues.html) ]] local cqueues = require "cqueues" local bit = require "bit32" local json = require "dkjson" local sj = require "systemd.journal" local j = assert(sj.open()) assert(j:seek_tail()) assert(j:previous()) -- Wrap the journal object with an object that implements the cqueues.poll interface local wrap_journal do local methods = {} function methods:pollfd() return self.j:get_fd() end function methods:events() local mask = self.j:get_events() local events = "" if bit.band(mask, 1) ~= 0 then events = events .. "r" end if bit.band(mask, 4) ~= 0 then events = events .. "w" end return events end function methods:timeout() local m = self.j:get_timeout() if type(m) == "number" then local now = cqueues.monotime() return m - now; end end local mt = { __index = function(t,k) local f = methods[k] if f ~= nil then return f end -- Delegate to original journal methods local f = t.j[k] if type(f) == "function" then -- Need to make sure the correct 'self' is passed through return function(o, ...) if o == t then o = t.j end return f(o, ...) end end end; } function wrap_journal(j) return setmetatable({j = j}, mt) end end local w = wrap_journal(j) local q = cqueues.new() q:wrap(function() while true do local a = cqueues.poll(w) if a and a:process() ~= sj.WAKEUP.NOP then while a:next() do local t = assert(a:to_table()) print(json.encode(t)) end end end end) assert(q:loop()) lua-systemd-master/src/000077500000000000000000000000001271662244600154175ustar00rootroot00000000000000lua-systemd-master/src/daemon.c000066400000000000000000000060701271662244600170310ustar00rootroot00000000000000#include "lua.h" #include "lauxlib.h" #include "compat-5.3.h" #include /* ENOTSUP */ #include /* pid_t */ #include #include "util.c" shim_weak_stub_declare(int, sd_booted, (), -ENOTSUP) shim_weak_stub_declare(int, sd_notify, (int unset_environment, const char *state), -ENOTSUP) shim_weak_stub_declare(int, sd_pid_notify, (pid_t pid, int unset_environment, const char *state), -ENOTSUP) shim_weak_stub_declare(int, sd_pid_notify_with_fds, (pid_t pid, int unset_environment, const char *state, const int *fds, unsigned n_fds), -ENOTSUP) shim_weak_stub_declare(int, sd_listen_fds, (int unset_environment), -ENOTSUP) static int handle_notify_result (lua_State *L, int err) { if (err > 0) { lua_pushboolean(L, 1); return 1; } else if (err == 0) { lua_pushnil(L); lua_pushliteral(L, "NOTIFY_SOCKET not set"); return 2; } else { return handle_error(L, -err); } } static int notify (lua_State *L) { int unset_environment = lua_toboolean(L, 1); const char *state = luaL_checkstring(L, 2); return handle_notify_result(L, shim_weak_stub(sd_notify)(unset_environment, state)); } static int pid_notify (lua_State *L) { pid_t pid = luaL_checkinteger(L, 1); int unset_environment = lua_toboolean(L, 2); const char *state = luaL_checkstring(L, 3); return handle_notify_result(L, shim_weak_stub(sd_pid_notify)(pid, unset_environment, state)); } static int pid_notify_with_fds (lua_State *L) { pid_t pid = luaL_checkinteger(L, 1); int unset_environment = lua_toboolean(L, 2); const char *state = luaL_checkstring(L, 3); int *fds; unsigned n_fds; unsigned i; luaL_checktype(L, 4, LUA_TTABLE); n_fds = lua_rawlen(L, 4); fds = lua_newuserdata(L, n_fds*sizeof(int)); for (i=0; i < n_fds; i++) { lua_rawgeti(L, 4, i+1); luaL_argcheck(L, lua_type(L, -1) == LUA_TNUMBER && lua_isinteger(L, -1), 4, "expected array of file descritors (integers)"); fds[i] = lua_tointeger(L, -1); lua_settop(L, 5); } return handle_notify_result(L, shim_weak_stub(sd_pid_notify_with_fds)(pid, unset_environment, state, fds, n_fds)); } static int booted (lua_State *L) { int booted = shim_weak_stub(sd_booted)(); if (booted >= 0) { lua_pushboolean(L, booted); return 1; } else { return handle_error(L, -booted); } } static int listen_fds (lua_State *L) { int unset_environment = lua_toboolean(L, 1); int n_descriptors = shim_weak_stub(sd_listen_fds)(unset_environment); if (n_descriptors < 0) { return handle_error(L, -n_descriptors); } lua_pushinteger(L, n_descriptors); return 1; } int luaopen_systemd_daemon_core (lua_State *L) { lua_newtable(L); /* 209 */ set_func_if_symbol_exists("sd_notify", L, notify, "notify"); set_func_if_symbol_exists("sd_booted", L, booted, "booted"); set_func_if_symbol_exists("sd_listen_fds", L, listen_fds, "listen_fds"); /* 214 */ set_func_if_symbol_exists("sd_pid_notify", L, pid_notify, "pid_notify"); /* 219 */ set_func_if_symbol_exists("sd_pid_notify_with_fds", L, pid_notify_with_fds, "pid_notify_with_fds"); lua_pushnumber(L, SD_LISTEN_FDS_START); lua_setfield(L, -2, "LISTEN_FDS_START"); return 1; } lua-systemd-master/src/daemon.lua000066400000000000000000000022371271662244600173710ustar00rootroot00000000000000local c = require "systemd.daemon.core" -- Wrap notify functions with versions that take tables -- this lets you write `notifyt { READY=1, STATE="awesome!" }` local function pack_state(t) local state = { } for k, v in pairs(t) do state[#state+1] = k.."="..v end return table.concat(state, "\n") end function c.notifyt(t) return c.notify(false, pack_state(t)) end function c.pid_notifyt(pid, t) return c.pid_notify(pid, false, pack_state(t)) end -- Get our own pid in pure lua. local function get_pid() local fd, err, n = io.open "/proc/self/stat" if fd == nil then return nil, err, n end local pid = fd:read "*n" fd:close() return pid end -- sd_watchdog_enabled in pure lua. -- returns watchdog interval function c.watchdog_enabled(unset_environment) if unset_environment then error("unset not supported", 2) end local pid = os.getenv "WATCHDOG_PID" if not pid then return false end pid = tonumber(pid) if pid ~= get_pid() then return false end local usec = os.getenv "WATCHDOG_USEC" usec = tonumber(usec) if usec == nil then return nil, "invalid interval" end return usec/1e6 end function c.kick_dog() return c.notify(false, "WATCHDOG=1") end return c lua-systemd-master/src/id128.c000066400000000000000000000045511271662244600164170ustar00rootroot00000000000000#include "lua.h" #include "lauxlib.h" #include "compat-5.3.h" #include #include "util.c" #include "id128.h" #include "messages.h" static int randomize (lua_State *L) { sd_id128_t *ret = lua_newuserdata(L, sizeof(sd_id128_t)); int err = sd_id128_randomize(ret); if (err < 0) return handle_error(L, -err); luaL_setmetatable(L, ID128_METATABLE); return 1; } static int from_string (lua_State *L) { size_t l; const char *s = luaL_checklstring(L, 1, &l); if (l != 32 && l != 37) return luaL_argerror(L, 1, "string must be 32 hex characters or a 37 character formatted RFC UUID"); sd_id128_t *ret = lua_newuserdata(L, sizeof(sd_id128_t)); int err = sd_id128_from_string(s, ret); if (err < 0) return handle_error(L, -err); luaL_setmetatable(L, ID128_METATABLE); return 1; } static int get_machine (lua_State *L) { sd_id128_t *ret = lua_newuserdata(L, sizeof(sd_id128_t)); int err = sd_id128_get_machine(ret); if (err < 0) return handle_error(L, -err); luaL_setmetatable(L, ID128_METATABLE); return 1; } static int get_boot (lua_State *L) { sd_id128_t *ret = lua_newuserdata(L, sizeof(sd_id128_t)); int err = sd_id128_get_boot(ret); if (err < 0) return handle_error(L, -err); luaL_setmetatable(L, ID128_METATABLE); return 1; } static int equal (lua_State *L) { sd_id128_t *a = luaL_checkudata(L, 1, ID128_METATABLE); sd_id128_t *b = luaL_checkudata(L, 2, ID128_METATABLE); lua_pushboolean(L, sd_id128_equal(*a, *b)); return 1; } static int to_string (lua_State *L) { sd_id128_t *a = luaL_checkudata(L, 1, ID128_METATABLE); char s[33]; sd_id128_to_string(*a, s); lua_pushlstring(L, s, 32); return 1; } int luaopen_systemd_id128_core (lua_State *L) { static const luaL_Reg lib[] = { {"randomize", randomize}, {"from_string", from_string}, {"get_machine", get_machine}, {"get_boot", get_boot}, {NULL, NULL} }; luaL_newlib(L, lib); static const luaL_Reg meta[] = { {"__eq", equal}, {"__tostring", to_string}, {NULL, NULL} }; static const luaL_Reg methods[] = { {"to_string", to_string}, {"get_catalog", journal_get_catalog_for_message_id}, {NULL, NULL} }; if (luaL_newmetatable(L, ID128_METATABLE)) { luaL_newlib(L, methods); lua_setfield(L, -2, "__index"); luaL_setfuncs(L, meta, 0); } /* Expose id128 methods */ lua_getfield(L, -1, "__index"); lua_setfield(L, -3, "ID128_METHODS"); lua_pop(L, 1); return 1; } lua-systemd-master/src/id128.h000066400000000000000000000011721271662244600164200ustar00rootroot00000000000000#include "lua.h" #include "lauxlib.h" #include #define ID128_METATABLE "ID128" static sd_id128_t check_id128_t (lua_State *L, int arg) { sd_id128_t boot_id; switch(lua_type(L, arg)) { case LUA_TUSERDATA: return *(sd_id128_t*)luaL_checkudata(L, arg, ID128_METATABLE); case LUA_TSTRING: luaL_argcheck(L, sd_id128_from_string(lua_tostring(L, arg), &boot_id) == 0, arg, "string is not a valid id128"); return boot_id; default: luaL_argerror(L, arg, lua_pushfstring(L, "id128 expected, got %s", luaL_typename(L, arg))); /* unreachable */ } } int luaopen_systemd_id128_core (lua_State *L); lua-systemd-master/src/id128.lua000066400000000000000000000001541271662244600167510ustar00rootroot00000000000000local c = require "systemd.id128.core" local methods = c.ID128_METHODS c.randomise = c.randomize return c lua-systemd-master/src/init.lua000066400000000000000000000003061271662244600170640ustar00rootroot00000000000000return { daemon = require "systemd.daemon" ; id128 = require "systemd.id128" ; journal = require "systemd.journal" ; login = require "systemd.login" ; messages = require "systemd.messages" ; } lua-systemd-master/src/journal.c000066400000000000000000000406461271662244600172470ustar00rootroot00000000000000#include "lua.h" #include "lauxlib.h" #include "compat-5.3.h" #include /* free */ #include /* FILE, fdopen, fclose */ #include /* uint64_t */ #include /* struct iovec */ #include #define SD_JOURNAL_SUPPRESS_LOCATION #include #include "util.c" #include "journal.h" #include "id128.h" static int handle_log_result (lua_State *L, int err) { if (err == 0) { lua_pushboolean(L, 1); return 1; } else { return handle_error(L, -err); } } static int sendv (lua_State *L) { int res; size_t i, n; struct iovec *iov; luaL_checktype(L, 1, LUA_TTABLE); n = lua_rawlen(L, 1); iov = lua_newuserdata(L, n*sizeof(struct iovec)); /* allocate via lua so we get free cleanup */ for (i=0; if; int res = fclose(pf); return luaL_fileresult(L, (res == 0), NULL); } static int stream_fd (lua_State *L) { int fd; const char *identifier = luaL_checkstring(L, 1); int priority = luaL_checkinteger(L, 2); int level_prefix = lua_toboolean(L, 3); /* Optional arg, defaults to false */ luaL_Stream *p = (luaL_Stream *)lua_newuserdata(L, sizeof(luaL_Stream)); p->closef = NULL; /* create a `closed' file handle before opening file, in case of errors */ luaL_setmetatable(L, LUA_FILEHANDLE); fd = sd_journal_stream_fd(identifier, priority, level_prefix); if (fd < 0) return handle_error(L, -fd); p->f = fdopen(fd, "w"); if (!p->f) return handle_error(L, errno); p->closef = &io_fclose; return 1; } static int journal_open (lua_State *L) { int err; int flags = luaL_optinteger(L, 1, 0); sd_journal **j = lua_newuserdata(L, sizeof(sd_journal*)); err = sd_journal_open(j, flags); if (err != 0) return handle_error(L, -err); luaL_setmetatable(L, JOURNAL_METATABLE); return 1; } static int journal_open_directory (lua_State *L) { int err; const char *path = luaL_checkstring(L, 1); int flags = luaL_optinteger(L, 2, 0); sd_journal **j = lua_newuserdata(L, sizeof(sd_journal*)); err = sd_journal_open_directory(j, path, flags); if (err != 0) return handle_error(L, -err); luaL_setmetatable(L, JOURNAL_METATABLE); return 1; } static int journal_open_files (lua_State *L) { int err; sd_journal **j; const char **paths; size_t len; int flags; luaL_checktype(L, 1, LUA_TTABLE); lua_settop(L, 2); len = lua_rawlen(L, 1); paths = lua_newuserdata(L, sizeof(const char*)*(len+1)); paths[len] = NULL; for (; len>0; len--) { lua_rawgeti(L, 1, len); paths[len-1] = luaL_checkstring(L, -1); lua_pop(L, 1); } flags = luaL_optinteger(L, 2, 0); j = lua_newuserdata(L, sizeof(sd_journal*)); err = sd_journal_open_files(j, paths, flags); if (err != 0) return handle_error(L, -err); luaL_setmetatable(L, JOURNAL_METATABLE); return 1; } static int journal_open_container (lua_State *L) { int err; const char *machine = luaL_checkstring(L, 1); int flags = luaL_optinteger(L, 2, 0); sd_journal **j = lua_newuserdata(L, sizeof(sd_journal*)); err = sd_journal_open_container(j, machine, flags); if (err != 0) return handle_error(L, -err); luaL_setmetatable(L, JOURNAL_METATABLE); return 1; } static int journal_close (lua_State *L) { sd_journal **jp = luaL_checkudata(L, 1, JOURNAL_METATABLE); if (*jp != NULL) { sd_journal_close(*jp); *jp = NULL; } return 0; } static sd_journal* check_journal(lua_State *L, int index) { sd_journal **jp = luaL_checkudata(L, index, JOURNAL_METATABLE); if (*jp == NULL) luaL_error(L, "Invalid journal handle"); return *jp; } static int journal_tostring (lua_State *L) { sd_journal *j = check_journal(L, 1); lua_pushfstring(L, "%s: %p", JOURNAL_METATABLE, j); return 1; } static int journal_get_cutoff_realtime_usec (lua_State *L) { sd_journal *j = check_journal(L, 1); uint64_t from; uint64_t to; int err = sd_journal_get_cutoff_realtime_usec(j, &from, &to); if (err < 0) return handle_error(L, -err); else if (err == 0) { lua_pushboolean(L, 0); return 1; } else { lua_pushuint64(L, from); lua_pushuint64(L, to); return 2; } } static int journal_get_cutoff_monotonic_usec (lua_State *L) { sd_journal *j = check_journal(L, 1); sd_id128_t boot_id = check_id128_t(L, 2); uint64_t from; uint64_t to; int err = sd_journal_get_cutoff_monotonic_usec(j, boot_id, &from, &to); if (err < 0) return handle_error(L, -err); else if (err == 0) { lua_pushboolean(L, 0); return 1; } else { lua_pushuint64(L, from); lua_pushuint64(L, to); return 2; } } static int journal_get_usage (lua_State *L) { sd_journal *j = check_journal(L, 1); uint64_t bytes; int err = sd_journal_get_usage(j, &bytes); if (err != 0) return handle_error(L, -err); lua_pushuint64(L, bytes); return 1; } static int journal_next (lua_State *L) { sd_journal *j = check_journal(L, 1); int err = sd_journal_next(j); if (err < 0) return handle_error(L, -err); lua_pushboolean(L, err); return 1; } static int journal_next_skip (lua_State *L) { sd_journal *j = check_journal(L, 1); uint64_t skip = luaL_checkuint64(L, 2); int err = sd_journal_next_skip(j, skip); if (err < 0) return handle_error(L, -err); lua_pushinteger(L, err); return 1; } static int journal_previous (lua_State *L) { sd_journal *j = check_journal(L, 1); int err = sd_journal_previous(j); if (err < 0) return handle_error(L, -err); lua_pushboolean(L, err); return 1; } static int journal_previous_skip (lua_State *L) { sd_journal *j = check_journal(L, 1); uint64_t skip = luaL_checkuint64(L, 2); int err = sd_journal_previous_skip(j, skip); if (err < 0) return handle_error(L, -err); lua_pushinteger(L, err); return 1; } static int journal_seek_head (lua_State *L) { sd_journal *j = check_journal(L, 1); int err = sd_journal_seek_head(j); if (err != 0) return handle_error(L, -err); lua_pushboolean(L, 1); return 1; } static int journal_seek_tail (lua_State *L) { sd_journal *j = check_journal(L, 1); int err = sd_journal_seek_tail(j); if (err != 0) return handle_error(L, -err); lua_pushboolean(L, 1); return 1; } static int journal_seek_monotonic_usec (lua_State *L) { sd_journal *j = check_journal(L, 1); sd_id128_t boot_id = check_id128_t(L, 2); uint64_t usec = luaL_checkuint64(L, 3); int err = sd_journal_seek_monotonic_usec(j, boot_id, usec); if (err != 0) return handle_error(L, -err); lua_pushboolean(L, 1); return 1; } static int journal_seek_realtime_usec (lua_State *L) { sd_journal *j = check_journal(L, 1); uint64_t usec = luaL_checkuint64(L, 2); int err = sd_journal_seek_realtime_usec(j, usec); if (err != 0) return handle_error(L, -err); lua_pushboolean(L, 1); return 1; } static int journal_seek_cursor (lua_State *L) { sd_journal *j = check_journal(L, 1); const char *cursor = luaL_checkstring(L, 2); int err = sd_journal_seek_cursor(j, cursor); if (err != 0) return handle_error(L, -err); lua_pushboolean(L, 1); return 1; } static int journal_get_cursor (lua_State *L) { sd_journal *j = check_journal(L, 1); char *cursor; int err = sd_journal_get_cursor(j, &cursor); if (err != 0) return handle_error(L, -err); lua_pushstring(L, cursor); free(cursor); return 1; } static int journal_test_cursor (lua_State *L) { sd_journal *j = check_journal(L, 1); const char *cursor = luaL_checkstring(L, 2); int err = sd_journal_test_cursor(j, cursor); if (err < 0) return handle_error(L, -err); lua_pushboolean(L, err); return 1; } static int journal_get_realtime_usec (lua_State *L) { sd_journal *j = check_journal(L, 1); uint64_t usec; int err = sd_journal_get_realtime_usec(j, &usec); if (err != 0) return handle_error(L, -err); lua_pushuint64(L, usec); return 1; } static int journal_get_monotonic_usec (lua_State *L) { sd_journal *j = check_journal(L, 1); uint64_t usec; sd_id128_t *boot_id = lua_newuserdata(L, sizeof(sd_id128_t)); int err = sd_journal_get_monotonic_usec(j, &usec, boot_id); if (err != 0) return handle_error(L, -err); lua_pushuint64(L, usec); lua_insert(L, 2); /* put below boot_id */ luaL_setmetatable(L, ID128_METATABLE); return 2; } static int journal_get_data (lua_State *L) { sd_journal *j = check_journal(L, 1); const char *field = luaL_checkstring(L, 2); const void *data; size_t length; int err = sd_journal_get_data(j, field, &data, &length); if (err == -ENOENT) { lua_pushboolean(L, 0); lua_pushnil(L); return 2; } else if (err != 0) { return handle_error(L, -err); } else { lua_pushboolean(L, 1); lua_pushlstring(L, data, length); return 2; } } static int journal_enumerate_data (lua_State *L) { sd_journal *j = check_journal(L, 1); const void *data; size_t length; int err = sd_journal_enumerate_data(j, &data, &length); if (err < 0) return handle_error(L, -err); else if (err == 0) { lua_pushboolean(L, 0); lua_pushnil(L); } else { lua_pushboolean(L, 1); lua_pushlstring(L, data, length); } return 2; } static int journal_restart_data (lua_State *L) { sd_journal *j = check_journal(L, 1); sd_journal_restart_data(j); return 0; } static int journal_query_unique (lua_State *L) { sd_journal *j = check_journal(L, 1); const char *field = luaL_checkstring(L, 2); int err = sd_journal_query_unique(j, field); if (err != 0) return handle_error(L, -err); lua_pushboolean(L, 1); return 1; } static int journal_enumerate_unique (lua_State *L) { sd_journal *j = check_journal(L, 1); const void *data; size_t length; int err = sd_journal_enumerate_unique(j, &data, &length); if (err < 0) return handle_error(L, -err); else if (err == 0) { lua_pushboolean(L, 0); lua_pushnil(L); } else { lua_pushboolean(L, 1); lua_pushlstring(L, data, length); } return 2; } static int journal_restart_unique (lua_State *L) { sd_journal *j = check_journal(L, 1); sd_journal_restart_unique(j); return 0; } static int journal_set_data_threshold (lua_State *L) { sd_journal *j = check_journal(L, 1); size_t sz = luaL_optinteger(L, 2, 0); int err = sd_journal_set_data_threshold(j, sz); if (err != 0) return handle_error(L, -err); lua_pushboolean(L, 1); return 1; } static int journal_get_data_threshold (lua_State *L) { sd_journal *j = check_journal(L, 1); size_t sz; int err = sd_journal_get_data_threshold(j, &sz); if (err != 0) return handle_error(L, -err); lua_pushinteger(L, sz); return 1; } static int journal_add_match (lua_State *L) { sd_journal *j = check_journal(L, 1); size_t size; const char *data = luaL_checklstring(L, 2, &size); int err = sd_journal_add_match(j, data, size); if (err != 0) return handle_error(L, -err); lua_pushboolean(L, 1); return 1; } static int journal_add_disjunction (lua_State *L) { sd_journal *j = check_journal(L, 1); int err = sd_journal_add_disjunction(j); if (err != 0) return handle_error(L, -err); lua_pushboolean(L, 1); return 1; } static int journal_add_conjunction (lua_State *L) { sd_journal *j = check_journal(L, 1); int err = sd_journal_add_conjunction(j); if (err != 0) return handle_error(L, -err); lua_pushboolean(L, 1); return 1; } static int journal_flush_matches (lua_State *L) { sd_journal *j = check_journal(L, 1); sd_journal_flush_matches(j); lua_pushboolean(L, 1); return 1; } static int journal_get_fd (lua_State *L) { sd_journal *j = check_journal(L, 1); int err = sd_journal_get_fd(j); if (err < 0) return handle_error(L, -err); lua_pushinteger(L, err); return 1; } static int journal_get_events (lua_State *L) { sd_journal *j = check_journal(L, 1); int err = sd_journal_get_events(j); if (err < 0) return handle_error(L, -err); lua_pushinteger(L, err); return 1; } static int journal_get_timeout (lua_State *L) { sd_journal *j = check_journal(L, 1); uint64_t timeout_usec; int err = sd_journal_get_timeout(j, &timeout_usec); if (err < 0) return handle_error(L, -err); if ((err == 0) || (timeout_usec == (uint64_t) -1)) { /* local file; no timeout needed */ lua_pushboolean(L, 0); } else { lua_pushnumber(L, ((double)timeout_usec)/1000000); } return 1; } static int journal_process (lua_State *L) { sd_journal *j = check_journal(L, 1); int err = sd_journal_process(j); if (err < 0) return handle_error(L, -err); lua_pushinteger(L, err); return 1; } static int journal_wait (lua_State *L) { sd_journal *j = check_journal(L, 1); uint64_t timeout_usec; int err; if (lua_isnoneornil(L, 2)) { /* default to infinite wait */ timeout_usec = -1; } else { timeout_usec = luaL_checknumber(L, 2) * 1000000; } err = sd_journal_wait(j, timeout_usec); if (err < 0) return handle_error(L, -err); lua_pushinteger(L, err); return 1; } static int journal_reliable_fd (lua_State *L) { sd_journal *j = check_journal(L, 1); int err = sd_journal_reliable_fd(j); if (err < 0) return handle_error(L, -err); lua_pushboolean(L, err); return 1; } static const luaL_Reg journal_methods[] = { {"get_cutoff_realtime_usec", journal_get_cutoff_realtime_usec}, {"get_cutoff_monotonic_usec", journal_get_cutoff_monotonic_usec}, {"get_usage", journal_get_usage}, {"next", journal_next}, {"next_skip", journal_next_skip}, {"previous", journal_previous}, {"previous_skip", journal_previous_skip}, {"seek_head", journal_seek_head}, {"seek_tail", journal_seek_tail}, {"seek_monotonic_usec", journal_seek_monotonic_usec}, {"seek_realtime_usec", journal_seek_realtime_usec}, {"seek_cursor", journal_seek_cursor}, {"get_cursor", journal_get_cursor}, {"test_cursor", journal_test_cursor}, {"get_realtime_usec", journal_get_realtime_usec}, {"get_monotonic_usec", journal_get_monotonic_usec}, {"get_data", journal_get_data}, {"enumerate_data", journal_enumerate_data}, {"restart_data", journal_restart_data}, {"query_unique", journal_query_unique}, {"enumerate_unique", journal_enumerate_unique}, {"restart_unique", journal_restart_unique}, {"set_data_threshold", journal_set_data_threshold}, {"get_data_threshold", journal_get_data_threshold}, {"add_match", journal_add_match}, {"add_disjunction", journal_add_disjunction}, {"add_conjunction", journal_add_conjunction}, {"flush_matches", journal_flush_matches}, {"get_fd", journal_get_fd}, {"get_events", journal_get_events}, {"get_timeout", journal_get_timeout}, {"process", journal_process}, {"wait", journal_wait}, {"reliable_fd", journal_reliable_fd}, {NULL, NULL} }; int luaopen_systemd_journal_core (lua_State *L) { static const luaL_Reg lib[] = { {"sendv", sendv}, {"perror", _perror}, {"stream_fd", stream_fd}, {"open", journal_open}, {"open_directory", journal_open_directory}, {"open_files", journal_open_files}, {"open_container", journal_open_container}, {NULL, NULL} }; /* ensure ID128_METATABLE is loaded */ luaL_requiref(L, "systemd.id128.core", luaopen_systemd_id128_core, 0); luaL_newlib(L, lib); /* Even with compat-5.2, Lua 5.1 doesn't have an easy way to make your own file objects */ /* Set up function environment for stream_fd for 5.1 so handle gets closed correctly */ #if !defined(LUA_VERSION_NUM) || LUA_VERSION_NUM == 501 lua_getfield(L, -1, "stream_fd"); lua_createtable(L, 0, 1); lua_pushcfunction(L, &io_fclose); lua_setfield(L, -2, "__close"); lua_setfenv(L, -2); lua_pop(L, 1); #endif lua_createtable(L, 0, 3); lua_pushnumber(L, SD_JOURNAL_NOP); lua_setfield(L, -2, "NOP"); lua_pushnumber(L, SD_JOURNAL_APPEND); lua_setfield(L, -2, "APPEND"); lua_pushnumber(L, SD_JOURNAL_INVALIDATE); lua_setfield(L, -2, "INVALIDATE"); lua_setfield(L, -2, "WAKEUP"); if (luaL_newmetatable(L, JOURNAL_METATABLE) != 0) { lua_pushcfunction(L, journal_close); lua_setfield(L, -2, "__gc"); lua_pushcfunction(L, journal_tostring); lua_setfield(L, -2, "__tostring"); luaL_newlib(L, journal_methods); lua_setfield(L, -2, "__index"); } /* Expose journal methods */ lua_getfield(L, -1, "__index"); lua_setfield(L, -3, "JOURNAL_METHODS"); lua_pop(L, 1); lua_createtable(L, 0, 4); lua_pushnumber(L, SD_JOURNAL_LOCAL_ONLY); lua_setfield(L, -2, "LOCAL_ONLY"); lua_pushnumber(L, SD_JOURNAL_RUNTIME_ONLY); lua_setfield(L, -2, "RUNTIME_ONLY"); lua_pushnumber(L, SD_JOURNAL_SYSTEM); lua_setfield(L, -2, "SYSTEM"); lua_pushnumber(L, SD_JOURNAL_CURRENT_USER); lua_setfield(L, -2, "CURRENT_USER"); lua_setfield(L, -2, "OPEN"); return 1; } lua-systemd-master/src/journal.h000066400000000000000000000001531271662244600172410ustar00rootroot00000000000000#include "lua.h" #define JOURNAL_METATABLE "sd_journal" int luaopen_systemd_journal_core (lua_State *L); lua-systemd-master/src/journal.lua000066400000000000000000000042171271662244600176000ustar00rootroot00000000000000local id128 = require "systemd.id128" local c = require "systemd.journal.core" local methods = c.JOURNAL_METHODS local function strip_field_name(str) return str:match("=(.*)$") end local function split_field(str) return str:match("^([^=]*)=(.*)$") end c.LOG = { EMERG = 0; ALERT = 1; CRIT = 2; ERR = 3; WARNING = 4; NOTICE = 5; INFO = 6; DEBUG = 7; } function c.print(priority, ...) return c.sendv { "PRIORITY=" .. priority; "MESSAGE=" .. string.format(...); } end function c.sendt(m) local t = { } for k, v in pairs(m) do t[#t+1] = k .. "=" .. v end return c.sendv(t) end function methods:get(field) local ok, res, code = self:get_data(field) if ok then return strip_field_name(res) elseif ok == false then return nil else error(res, 2); end end local function next_field(self) local ok, res = self:enumerate_data() if ok then return split_field(res) elseif ok == false then return nil else error(res, 2) end end function methods:each_data() self:restart_data() return next_field, self end local function next_unique(self) local ok, res = self:enumerate_unique() if ok then return strip_field_name(res) elseif ok == false then return nil else error(res, 2) end end function methods:each_unique(field) self:restart_unique() assert(self:query_unique(field)) return next_unique, self end -- Converts the current journal entry to a lua table -- Includes __ prefixed "Address Fields" function methods:to_table() local t = { __CURSOR = self:get_cursor(); __REALTIME_TIMESTAMP = self:get_realtime_usec(); __MONOTONIC_TIMESTAMP = self:get_monotonic_usec(); } for field, value in self:each_data() do t[field] = value end return t end function methods:get_catalog() local ok, err, errno = self:get_data "MESSAGE_ID" if ok == nil then return nil, err, errno elseif ok == false then return false else local message_id = err:match("=(.*)$") if message_id == nil then return false end local message_id = id128.from_string(message_id) local text = message_id:get_catalog() if not text then return false end local t = self:to_table() text = text:gsub("@([^@]-)@", t) return text end end return c lua-systemd-master/src/login.c000066400000000000000000000610041271662244600166740ustar00rootroot00000000000000#include "lua.h" #include "lauxlib.h" #include "compat-5.3.h" #include /* free */ #include /* uint64_t */ #include /* pid_t */ #include /* ENOTSUP */ #include #include "util.c" #include "login.h" shim_weak_stub_declare(int, sd_pid_get_session, (pid_t pid, char **session), -ENOTSUP); shim_weak_stub_declare(int, sd_pid_get_owner_uid, (pid_t pid, uid_t *uid), -ENOTSUP); shim_weak_stub_declare(int, sd_pid_get_unit, (pid_t pid, char **unit), -ENOTSUP); shim_weak_stub_declare(int, sd_pid_get_user_unit, (pid_t pid, char **unit), -ENOTSUP); shim_weak_stub_declare(int, sd_pid_get_machine_name, (pid_t pid, char **machine), -ENOTSUP); shim_weak_stub_declare(int, sd_pid_get_slice, (pid_t pid, char **slice), -ENOTSUP); shim_weak_stub_declare(int, sd_pid_get_user_slice, (pid_t pid, char **slice), -ENOTSUP); shim_weak_stub_declare(int, sd_pid_get_cgroup, (pid_t pid, char **cgroup), -ENOTSUP); shim_weak_stub_declare(int, sd_peer_get_session, (int fd, char **session), -ENOTSUP); shim_weak_stub_declare(int, sd_peer_get_owner_uid, (int fd, uid_t *uid), -ENOTSUP); shim_weak_stub_declare(int, sd_peer_get_unit, (int fd, char **unit), -ENOTSUP); shim_weak_stub_declare(int, sd_peer_get_user_unit, (int fd, char **unit), -ENOTSUP); shim_weak_stub_declare(int, sd_peer_get_machine_name, (int fd, char **machine), -ENOTSUP); shim_weak_stub_declare(int, sd_peer_get_slice, (int fd, char **slice), -ENOTSUP); shim_weak_stub_declare(int, sd_peer_get_user_slice, (int fd, char **slice), -ENOTSUP); shim_weak_stub_declare(int, sd_peer_get_cgroup, (int fd, char **cgroup), -ENOTSUP); shim_weak_stub_declare(int, sd_uid_get_state, (uid_t uid, char **state), -ENOTSUP); shim_weak_stub_declare(int, sd_uid_get_display, (uid_t uid, char **session), -ENOTSUP); shim_weak_stub_declare(int, sd_uid_is_on_seat, (uid_t uid, int require_active, const char *seat), -ENOTSUP); shim_weak_stub_declare(int, sd_uid_get_sessions, (uid_t uid, int require_active, char ***sessions), -ENOTSUP); shim_weak_stub_declare(int, sd_uid_get_seats, (uid_t uid, int require_active, char ***seats), -ENOTSUP); shim_weak_stub_declare(int, sd_session_is_active, (const char *session), -ENOTSUP); shim_weak_stub_declare(int, sd_session_is_remote, (const char *session), -ENOTSUP); shim_weak_stub_declare(int, sd_session_get_state, (const char *session, char **state), -ENOTSUP); shim_weak_stub_declare(int, sd_session_get_uid, (const char *session, uid_t *uid), -ENOTSUP); shim_weak_stub_declare(int, sd_session_get_seat, (const char *session, char **seat), -ENOTSUP); shim_weak_stub_declare(int, sd_session_get_service, (const char *session, char **service), -ENOTSUP); shim_weak_stub_declare(int, sd_session_get_type, (const char *session, char **type), -ENOTSUP); shim_weak_stub_declare(int, sd_session_get_class, (const char *session, char **clazz), -ENOTSUP); shim_weak_stub_declare(int, sd_session_get_desktop, (const char *session, char **desktop), -ENOTSUP); shim_weak_stub_declare(int, sd_session_get_display, (const char *session, char **display), -ENOTSUP); shim_weak_stub_declare(int, sd_session_get_remote_host, (const char *session, char **remote_host), -ENOTSUP); shim_weak_stub_declare(int, sd_session_get_remote_user, (const char *session, char **remote_user), -ENOTSUP); shim_weak_stub_declare(int, sd_session_get_tty, (const char *session, char **display), -ENOTSUP); shim_weak_stub_declare(int, sd_session_get_vt, (const char *session, unsigned *vtnr), -ENOTSUP); shim_weak_stub_declare(int, sd_seat_get_active, (const char *seat, char **session, uid_t *uid), -ENOTSUP); shim_weak_stub_declare(int, sd_seat_get_sessions, (const char *seat, char ***sessions, uid_t **uid, unsigned *n_uids), -ENOTSUP); shim_weak_stub_declare(int, sd_seat_can_multi_session, (const char *seat), -ENOTSUP); shim_weak_stub_declare(int, sd_seat_can_tty, (const char *seat), -ENOTSUP); shim_weak_stub_declare(int, sd_seat_can_graphical, (const char *seat), -ENOTSUP); shim_weak_stub_declare(int, sd_machine_get_class, (const char *machine, char **clazz), -ENOTSUP); shim_weak_stub_declare(int, sd_machine_get_ifindices, (const char *machine, int **ifindices), -ENOTSUP); shim_weak_stub_declare(int, sd_get_seats, (char ***seats), -ENOTSUP); shim_weak_stub_declare(int, sd_get_sessions, (char ***sessions), -ENOTSUP); shim_weak_stub_declare(int, sd_get_uids, (uid_t **users), -ENOTSUP); shim_weak_stub_declare(int, sd_get_machine_names, (char ***machines), -ENOTSUP); shim_weak_stub_declare(int, sd_login_monitor_new, (const char *category, sd_login_monitor** ret), -ENOTSUP); shim_weak_stub_declare(sd_login_monitor*, sd_login_monitor_unref, (sd_login_monitor *m), NULL); shim_weak_stub_declare(int, sd_login_monitor_flush, (sd_login_monitor *m), -ENOTSUP); shim_weak_stub_declare(int, sd_login_monitor_get_fd, (sd_login_monitor *m), -ENOTSUP); shim_weak_stub_declare(int, sd_login_monitor_get_events, (sd_login_monitor *m), -ENOTSUP); shim_weak_stub_declare(int, sd_login_monitor_get_timeout, (sd_login_monitor *m, uint64_t *timeout_usec), -ENOTSUP); static void push_array_of_strings (lua_State *L, char **strings, int n) { int i; lua_createtable(L, n, 0); if (strings != NULL) { for (i=0; i /* free */ #include /* ENOENT */ #include #include "util.c" #include "messages.h" #include "id128.h" int journal_get_catalog_for_message_id (lua_State *L) { sd_id128_t id = check_id128_t(L, 1); char *ret; int err = sd_journal_get_catalog_for_message_id(id, &ret); if (err == -ENOENT) { lua_pushboolean(L, 0); return 1; } else if (err != 0) { return handle_error(L, -err); } else { lua_pushstring(L, ret); free(ret); return 1; } } lua-systemd-master/src/messages.h000066400000000000000000000001571271662244600174020ustar00rootroot00000000000000#include "lua.h" __attribute__((visibility("hidden"))) int journal_get_catalog_for_message_id (lua_State *L); lua-systemd-master/src/messages.lua000066400000000000000000000066441271662244600177430ustar00rootroot00000000000000--[[ This module gives aliases for some common well known message ids. The aliases are taken from `sd_messages.h`. Information about these message ids can be found in the system catalog in /usr/lib/systemd/catalog/ ]] local id128 = require "systemd.id128" local messages = {} messages.JOURNAL_START = id128.from_string "f77379a8490b408bbe5f6940505a777b" messages.JOURNAL_STOP = id128.from_string "d93fb3c9c24d451a97cea615ce59c00b" messages.JOURNAL_DROPPED = id128.from_string "a596d6fe7bfa4994828e72309e95d61e" messages.JOURNAL_MISSED = id128.from_string "e9bf28e6e834481bb6f48f548ad13606" messages.JOURNAL_USAGE = id128.from_string "ec387f577b844b8fa948f33cad9a75e6" messages.COREDUMP = id128.from_string "fc2e22bc6ee647b6b90729ab34a250b1" messages.SESSION_START = id128.from_string "8d45620c1a4348dbb17410da57c60c66" messages.SESSION_STOP = id128.from_string "3354939424b4456d9802ca8333ed424a" messages.SEAT_START = id128.from_string "fcbefc5da23d428093f97c82a9290f7b" messages.SEAT_STOP = id128.from_string "e7852bfe46784ed0accde04bc864c2d5" messages.MACHINE_START = id128.from_string "24d8d4452573402496068381a6312df2" messages.MACHINE_STOP = id128.from_string "58432bd3bace477cb514b56381b8a758" messages.TIME_CHANGE = id128.from_string "c7a787079b354eaaa9e77b371893cd27" messages.TIMEZONE_CHANGE = id128.from_string "45f82f4aef7a4bbf942ce861d1f20990" messages.STARTUP_FINISHED = id128.from_string "b07a249cd024414a82dd00cd181378ff" messages.SLEEP_START = id128.from_string "6bbd95ee977941e497c48be27c254128" messages.SLEEP_STOP = id128.from_string "8811e6df2a8e40f58a94cea26f8ebf14" messages.SHUTDOWN = id128.from_string "98268866d1d54a499c4e98921d93bc40" messages.UNIT_STARTING = id128.from_string "7d4958e842da4a758f6c1cdc7b36dcc5" messages.UNIT_STARTED = id128.from_string "39f53479d3a045ac8e11786248231fbf" messages.UNIT_STOPPING = id128.from_string "de5b426a63be47a7b6ac3eaac82e2f6f" messages.UNIT_STOPPED = id128.from_string "9d1aaa27d60140bd96365438aad20286" messages.UNIT_FAILED = id128.from_string "be02cf6855d2428ba40df7e9d022f03d" messages.UNIT_RELOADING = id128.from_string "d34d037fff1847e6ae669a370e694725" messages.UNIT_RELOADED = id128.from_string "7b05ebc668384222baa8881179cfda54" messages.SPAWN_FAILED = id128.from_string "641257651c1b4ec9a8624d7a40a9e1e7" messages.FORWARD_SYSLOG_MISSED = id128.from_string "0027229ca0644181a76c4e92458afa2e" messages.OVERMOUNTING = id128.from_string "1dee0369c7fc4736b7099b38ecb46ee7" messages.LID_OPENED = id128.from_string "b72ea4a2881545a0b50e200e55b9b06f" messages.LID_CLOSED = id128.from_string "b72ea4a2881545a0b50e200e55b9b070" messages.SYSTEM_DOCKED = id128.from_string "f5f416b862074b28927a48c3ba7d51ff" messages.SYSTEM_UNDOCKED = id128.from_string "51e171bd585248568110144c517cca53" messages.POWER_KEY = id128.from_string "b72ea4a2881545a0b50e200e55b9b071" messages.SUSPEND_KEY = id128.from_string "b72ea4a2881545a0b50e200e55b9b072" messages.HIBERNATE_KEY = id128.from_string "b72ea4a2881545a0b50e200e55b9b073" messages.CONFIG_ERROR = id128.from_string "c772d24e9a884cbeb9ea12625c306c01" messages.BOOTCHART = id128.from_string "9f26aa562cf440c2b16c773d0479b518" return messages lua-systemd-master/src/util.c000066400000000000000000000027611271662244600165460ustar00rootroot00000000000000#include "lua.h" #include "lauxlib.h" /* luaL_checknumber */ #include /* strerror */ #include /* dlsym, dlerror */ static int handle_error(lua_State *L, int err) { lua_pushnil(L); lua_pushstring(L, strerror(err)); lua_pushinteger(L, err); return 3; } #ifndef lua_pushuint64 #define lua_pushuint64 lua_pushnumber #endif #ifndef luaL_checkuint64 #define luaL_checkuint64 luaL_checknumber #endif /* This hack is required as lua always passes RTLD_NOW to dlopen * Without this loading lua-systemd would fail with an error about undefined symbols * e.g. sd_machine_get_ifindices missing on a system running systemd 213 * * To ensure graceful fallback we have to have some indirection via a function pointer. */ #define shim_weak_stub_name(symbol) symbol ## _stub #define shim_weak_stub(symbol) symbol ## _pointer #define shim_weak_stub_declare(ret_type, symbol, args, val) \ static ret_type (*shim_weak_stub(symbol)) args; \ static ret_type shim_weak_stub_name(symbol) args { return val; } \ __attribute__((constructor)) static void initialize_ ## symbol() { \ if ((shim_weak_stub(symbol) = dlsym(RTLD_DEFAULT, #symbol)) == NULL) { \ shim_weak_stub(symbol) = shim_weak_stub_name(symbol); \ } \ } #define symbol_exists(name) (dlsym(RTLD_DEFAULT, name) != NULL || dlerror() == NULL) #define set_func(L, func, name) (lua_pushcclosure(L, func, 0), lua_setfield(L, -2, name)) #define set_func_if_symbol_exists(symbol, L, func, name) if (symbol_exists(symbol)) set_func(L, func, name) lua-systemd-master/systemd-scm-0.rockspec000066400000000000000000000015611271662244600207730ustar00rootroot00000000000000package = "systemd" version = "scm-0" source = { url = "git://github.com/daurnimator/lua-systemd" } description = { summary = "Lua bindings to systemd", homepage = "https://github.com/daurnimator/lua-systemd", license = "MIT/X11" } dependencies = { "lua >= 5.0, < 5.4" } build = { type = "builtin", modules = { ["systemd.init"] = "src/init.lua", ["systemd.daemon"] = "src/daemon.lua", ["systemd"] = { sources = { "src/daemon.c", "src/id128.c", "src/messages.c", "src/journal.c", "src/login.c", "vendor/compat-5.3/c-api/compat-5.3.c", }, defines = { "_GNU_SOURCE" }, -- for RTLD_DEFAULT libraries = { "systemd" }, incdirs = { "vendor/compat-5.3/c-api/" } }, ["systemd.id128"] = "src/id128.lua", ["systemd.journal"] = "src/journal.lua", ["systemd.login"] = "src/login.lua", ["systemd.messages"] = "src/messages.lua" } } lua-systemd-master/vendor/000077500000000000000000000000001271662244600161255ustar00rootroot00000000000000lua-systemd-master/vendor/compat-5.3/000077500000000000000000000000001271662244600177135ustar00rootroot00000000000000lua-systemd-master/vendor/compat-5.3/.gitignore000066400000000000000000000001101271662244600216730ustar00rootroot00000000000000# generated files *.so *.dll *.o *.obj HISTO # vim temporaries .*.swp lua-systemd-master/vendor/compat-5.3/LICENSE000066400000000000000000000020721271662244600207210ustar00rootroot00000000000000The MIT License (MIT) Copyright (c) 2015 Kepler Project. Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. lua-systemd-master/vendor/compat-5.3/README.md000066400000000000000000000161601271662244600211760ustar00rootroot00000000000000# lua-compat-5.3 Lua-5.3-style APIs for Lua 5.2 and 5.1. ## What is it This is a small module that aims to make it easier to write code in a Lua-5.3-style that is compatible with Lua 5.1, Lua 5.2, and Lua 5.3. This does *not* make Lua 5.2 (or even Lua 5.1) entirely compatible with Lua 5.3, but it brings the API closer to that of Lua 5.3. It includes: * _For writing Lua_: The Lua module `compat53`, which can be require'd from Lua scripts and run in Lua 5.1, 5.2, and 5.3, including a backport of the `utf8` module, the 5.3 `table` module, and the string packing functions straight from the Lua 5.3 sources. * _For writing C_: A C header and file which can be linked to your Lua module written in C, providing some functions from the C API of Lua 5.3 that do not exist in Lua 5.2 or 5.1, making it easier to write C code that compiles with all three versions of liblua. ## How to use it ### Lua module ```lua require("compat53") ``` `compat53` makes changes to your global environment and does not return a meaningful return value, so the usual idiom of storing the return of `require` in a local variable makes no sense. When run under Lua 5.3, this module does nothing. When run under Lua 5.2 or 5.1, it replaces some of your standard functions and adds new ones to bring your environment closer to that of Lua 5.3. It also tries to load the backported `utf8`, `table`, and string packing modules automatically. If unsuccessful, pure Lua versions of the new `table` functions are used as a fallback, and [Roberto's struct library][1] is tried for string packing. ### C code There are two ways of adding the C API compatibility functions/macros to your project: * If `COMPAT53_PREFIX` is *not* `#define`d, `compat-5.3.h` `#include`s `compat-5.3.c`, and all functions are made `static`. You don't have to compile/link/add `compat-5.3.c` yourself. This is useful for one-file projects. * If `COMPAT53_PREFIX` is `#define`d, all exported functions are renamed behind the scenes using this prefix to avoid linker conflicts with other code using this package. This doesn't change the way you call the compatibility functions in your code. You have to compile and link `compat-5.3.c` to your project yourself. You can change the way the functions are exported using the `COMPAT53_API` macro (e.g. if you need some `__declspec` magic). ## What's implemented ### Lua * the `utf8` module backported from the Lua 5.3 sources * `string.pack`, `string.packsize`, and `string.unpack` from the Lua 5.3 sources or from the `struct` module. (`struct` is not 100% compatible to Lua 5.3's string packing!) * `math.maxinteger` and `math.mininteger`, `math.tointeger`, `math.type`, and `math.ult` * `ipairs` respects `__index` metamethod * `table.move` * `table` library respects metamethods For Lua 5.1 additionally: * `load` and `loadfile` accept `mode` and `env` parameters * `table.pack` and `table.unpack` * string patterns may contain embedded zeros * `string.rep` accepts `sep` argument * `string.format` calls `tostring` on arguments for `%s` * `math.log` accepts base argument * `xpcall` takes additional arguments * `pcall` and `xpcall` can execute functions that yield * `pairs` respects `__pairs` metamethod * `rawlen` (but `#` still doesn't respect `__len` for tables) * `package.searchers` as alias for `package.loaders` * `package.searchpath` * `coroutine` functions dealing with the main coroutine * `coroutine.create` accepts functions written in C * return code of `os.execute` * `io.write` and `file:write` return file handle * `io.lines` and `file:lines` accept format arguments (like `io.read`) * `debug.setmetatable` returns object * `debug.getuservalue` and `debug.setuservalue` ### C * `lua_KContext` * `lua_KFunction` * `lua_dump` (extra `strip` parameter, ignored) * `lua_getfield` (return value) * `lua_geti` and `lua_seti` * `lua_getglobal` (return value) * `lua_getmetafield` (return value) * `lua_gettable` (return value) * `lua_getuservalue` and `lua_setuservalue` (limited compatibility) * `lua_isinteger` * `lua_numbertointeger` * `lua_callk` and `lua_pcallk` (limited compatibility) * `lua_rawget` and `lua_rawgeti` (return values) * `lua_rawgetp` and `lua_rawsetp` * `luaL_requiref` (now checks `package.loaded` first) * `lua_rotate` * `lua_stringtonumber` For Lua 5.1 additionally: * `LUA_OK` * `LUA_OP*` macros for `lua_arith` and `lua_compare` * `lua_Unsigned` * `luaL_Stream` * `LUA_FILEHANDLE` * `lua_absindex` * `lua_arith` * `lua_compare` * `lua_len`, `lua_rawlen`, and `luaL_len` * `lua_copy` * `lua_pushglobaltable` * `luaL_testudata` * `luaL_setfuncs`, `luaL_newlibtable`, and `luaL_newlib` * `luaL_setmetatable` * `luaL_getsubtable` * `luaL_traceback` * `luaL_fileresult` * `luaL_checkversion` (with empty body, only to avoid compile errors) * `luaL_tolstring` * `luaL_buffinitsize`, `luaL_prepbuffsize`, and `luaL_pushresultsize` * `lua_pushunsigned`, `lua_tounsignedx`, `lua_tounsigned`, `luaL_checkunsigned`, `luaL_optunsigned`, if `LUA_COMPAT_APIINTCASTS` is defined. ## What's not implemented * bit operators * integer division operator * utf8 escape sequences * 64 bit integers * `coroutine.isyieldable` * Lua 5.1: `_ENV`, `goto`, labels, ephemeron tables, etc. See [`lua-compat-5.2`][2] for a detailed list. * the following C API functions/macros: * `lua_isyieldable` * `lua_getextraspace` * `lua_arith` (new operators missing) * `lua_push(v)fstring` (new formats missing) * `lua_upvalueid` (5.1) * `lua_upvaluejoin` (5.1) * `lua_version` (5.1) * `lua_yieldk` (5.1) * `luaL_execresult` (5.1) * `luaL_loadbufferx` (5.1) * `luaL_loadfilex` (5.1) ### Yieldable C functions The emulation of `lua_(p)callk` for previous Lua versions is not 100% perfect, because the continuation functions in Lua 5.2 have different signatures than the ones in Lua 5.3 (and Lua 5.1 doesn't have continuation functions at all). But with the help of a small macro the same code can be used for all three Lua versions (the 5.1 version won't support yielding though). Original Lua 5.3 code (example adapted from the Lua 5.3 manual): ```C static int k (lua_State *L, int status, lua_KContext ctx) { ... /* code 2 */ } int original_function (lua_State *L) { ... /* code 1 */ return k(L, lua_pcallk(L, n, m, h, ctx2, k), ctx1); } ``` Portable version: ```C LUA_KFUNCTION( k ) { ... /* code 2; parameters L, status, and ctx available here */ } int original_function (lua_State *L) { ... /* code 1 */ return k(L, lua_pcallk(L, n, m, h, ctx2, k), ctx1); } ``` ## See also * For Lua-5.2-style APIs under Lua 5.1, see [lua-compat-5.2][2], which also is the basis for most of the code in this project. * For Lua-5.1-style APIs under Lua 5.0, see [Compat-5.1][3] ## Credits This package contains code written by: * [The Lua Team](http://www.lua.org) * Philipp Janda ([@siffiejoe](http://github.com/siffiejoe)) * Tomás Guisasola Gorham ([@tomasguisasola](http://github.com/tomasguisasola)) * Hisham Muhammad ([@hishamhm](http://github.com/hishamhm)) * Renato Maia ([@renatomaia](http://github.com/renatomaia)) [1]: http://www.inf.puc-rio.br/~roberto/struct/ [2]: http://github.com/keplerproject/lua-compat-5.2/ [3]: http://keplerproject.org/compat/ lua-systemd-master/vendor/compat-5.3/c-api/000077500000000000000000000000001271662244600207045ustar00rootroot00000000000000lua-systemd-master/vendor/compat-5.3/c-api/compat-5.3.c000066400000000000000000000366311271662244600226470ustar00rootroot00000000000000#include #include #include #include #include #include #include #include "compat-5.3.h" /* don't compile it again if it already is included via compat53.h */ #ifndef COMPAT53_C_ #define COMPAT53_C_ /* definitions for Lua 5.1 only */ #if defined( LUA_VERSION_NUM ) && LUA_VERSION_NUM == 501 COMPAT53_API int lua_absindex (lua_State *L, int i) { if (i < 0 && i > LUA_REGISTRYINDEX) i += lua_gettop(L) + 1; return i; } static void compat53_call_lua (lua_State *L, char const code[], size_t len, int nargs, int nret) { lua_rawgetp(L, LUA_REGISTRYINDEX, (void*)code); if (lua_type(L, -1) != LUA_TFUNCTION) { lua_pop(L, 1); if (luaL_loadbuffer(L, code, len, "=none")) lua_error(L); lua_pushvalue(L, -1); lua_rawsetp(L, LUA_REGISTRYINDEX, (void*)code); } lua_insert(L, -nargs-1); lua_call(L, nargs, nret); } static const char compat53_arith_code[] = "local op,a,b=...\n" "if op==0 then return a+b\n" "elseif op==1 then return a-b\n" "elseif op==2 then return a*b\n" "elseif op==3 then return a/b\n" "elseif op==4 then return a%b\n" "elseif op==5 then return a^b\n" "elseif op==6 then return -a\n" "end\n"; COMPAT53_API void lua_arith (lua_State *L, int op) { if (op < LUA_OPADD || op > LUA_OPUNM) luaL_error(L, "invalid 'op' argument for lua_arith"); luaL_checkstack(L, 5, "not enough stack slots"); if (op == LUA_OPUNM) lua_pushvalue(L, -1); lua_pushnumber(L, op); lua_insert(L, -3); compat53_call_lua(L, compat53_arith_code, sizeof(compat53_arith_code)-1, 3, 1); } static const char compat53_compare_code[] = "local a,b=...\n" "return a<=b\n"; COMPAT53_API int lua_compare (lua_State *L, int idx1, int idx2, int op) { int result = 0; switch (op) { case LUA_OPEQ: return lua_equal(L, idx1, idx2); case LUA_OPLT: return lua_lessthan(L, idx1, idx2); case LUA_OPLE: luaL_checkstack(L, 5, "not enough stack slots"); idx1 = lua_absindex(L, idx1); idx2 = lua_absindex(L, idx2); lua_pushvalue(L, idx1); lua_pushvalue(L, idx2); compat53_call_lua(L, compat53_compare_code, sizeof(compat53_compare_code)-1, 2, 1); result = lua_toboolean(L, -1); lua_pop(L, 1); return result; default: luaL_error(L, "invalid 'op' argument for lua_compare"); } return 0; } COMPAT53_API void lua_copy (lua_State *L, int from, int to) { int abs_to = lua_absindex(L, to); luaL_checkstack(L, 1, "not enough stack slots"); lua_pushvalue(L, from); lua_replace(L, abs_to); } COMPAT53_API void lua_len (lua_State *L, int i) { switch (lua_type(L, i)) { case LUA_TSTRING: /* fall through */ case LUA_TTABLE: if (!luaL_callmeta(L, i, "__len")) lua_pushnumber(L, (int)lua_objlen(L, i)); break; case LUA_TUSERDATA: if (luaL_callmeta(L, i, "__len")) break; /* maybe fall through */ default: luaL_error(L, "attempt to get length of a %s value", lua_typename(L, lua_type(L, i))); } } COMPAT53_API int lua_rawgetp (lua_State *L, int i, const void *p) { int abs_i = lua_absindex(L, i); lua_pushlightuserdata(L, (void*)p); lua_rawget(L, abs_i); return lua_type(L, -1); } COMPAT53_API void lua_rawsetp (lua_State *L, int i, const void *p) { int abs_i = lua_absindex(L, i); luaL_checkstack(L, 1, "not enough stack slots"); lua_pushlightuserdata(L, (void*)p); lua_insert(L, -2); lua_rawset(L, abs_i); } COMPAT53_API lua_Integer lua_tointegerx (lua_State *L, int i, int *isnum) { lua_Integer n = lua_tointeger(L, i); if (isnum != NULL) { *isnum = (n != 0 || lua_isnumber(L, i)); } return n; } COMPAT53_API lua_Number lua_tonumberx (lua_State *L, int i, int *isnum) { lua_Number n = lua_tonumber(L, i); if (isnum != NULL) { *isnum = (n != 0 || lua_isnumber(L, i)); } return n; } COMPAT53_API void luaL_checkversion (lua_State *L) { (void)L; } COMPAT53_API int luaL_getsubtable (lua_State *L, int i, const char *name) { int abs_i = lua_absindex(L, i); luaL_checkstack(L, 3, "not enough stack slots"); lua_pushstring(L, name); lua_gettable(L, abs_i); if (lua_istable(L, -1)) return 1; lua_pop(L, 1); lua_newtable(L); lua_pushstring(L, name); lua_pushvalue(L, -2); lua_settable(L, abs_i); return 0; } COMPAT53_API int luaL_len (lua_State *L, int i) { int res = 0, isnum = 0; luaL_checkstack(L, 1, "not enough stack slots"); lua_len(L, i); res = (int)lua_tointegerx(L, -1, &isnum); lua_pop(L, 1); if (!isnum) luaL_error(L, "object length is not a number"); return res; } COMPAT53_API void luaL_setfuncs (lua_State *L, const luaL_Reg *l, int nup) { luaL_checkstack(L, nup+1, "too many upvalues"); for (; l->name != NULL; l++) { /* fill the table with given functions */ int i; lua_pushstring(L, l->name); for (i = 0; i < nup; i++) /* copy upvalues to the top */ lua_pushvalue(L, -(nup + 1)); lua_pushcclosure(L, l->func, nup); /* closure with those upvalues */ lua_settable(L, -(nup + 3)); /* table must be below the upvalues, the name and the closure */ } lua_pop(L, nup); /* remove upvalues */ } COMPAT53_API void luaL_setmetatable (lua_State *L, const char *tname) { luaL_checkstack(L, 1, "not enough stack slots"); luaL_getmetatable(L, tname); lua_setmetatable(L, -2); } COMPAT53_API void *luaL_testudata (lua_State *L, int i, const char *tname) { void *p = lua_touserdata(L, i); luaL_checkstack(L, 2, "not enough stack slots"); if (p == NULL || !lua_getmetatable(L, i)) return NULL; else { int res = 0; luaL_getmetatable(L, tname); res = lua_rawequal(L, -1, -2); lua_pop(L, 2); if (!res) p = NULL; } return p; } COMPAT53_API const char *luaL_tolstring (lua_State *L, int idx, size_t *len) { if (!luaL_callmeta(L, idx, "__tostring")) { int t = lua_type(L, idx); switch (t) { case LUA_TNIL: lua_pushliteral(L, "nil"); break; case LUA_TSTRING: case LUA_TNUMBER: lua_pushvalue(L, idx); break; case LUA_TBOOLEAN: if (lua_toboolean(L, idx)) lua_pushliteral(L, "true"); else lua_pushliteral(L, "false"); break; default: lua_pushfstring(L, "%s: %p", lua_typename(L, t), lua_topointer(L, idx)); break; } } return lua_tolstring(L, -1, len); } #if !defined(COMPAT53_IS_LUAJIT) static int compat53_countlevels (lua_State *L) { lua_Debug ar; int li = 1, le = 1; /* find an upper bound */ while (lua_getstack(L, le, &ar)) { li = le; le *= 2; } /* do a binary search */ while (li < le) { int m = (li + le)/2; if (lua_getstack(L, m, &ar)) li = m + 1; else le = m; } return le - 1; } static int compat53_findfield (lua_State *L, int objidx, int level) { if (level == 0 || !lua_istable(L, -1)) return 0; /* not found */ lua_pushnil(L); /* start 'next' loop */ while (lua_next(L, -2)) { /* for each pair in table */ if (lua_type(L, -2) == LUA_TSTRING) { /* ignore non-string keys */ if (lua_rawequal(L, objidx, -1)) { /* found object? */ lua_pop(L, 1); /* remove value (but keep name) */ return 1; } else if (compat53_findfield(L, objidx, level - 1)) { /* try recursively */ lua_remove(L, -2); /* remove table (but keep name) */ lua_pushliteral(L, "."); lua_insert(L, -2); /* place '.' between the two names */ lua_concat(L, 3); return 1; } } lua_pop(L, 1); /* remove value */ } return 0; /* not found */ } static int compat53_pushglobalfuncname (lua_State *L, lua_Debug *ar) { int top = lua_gettop(L); lua_getinfo(L, "f", ar); /* push function */ lua_pushvalue(L, LUA_GLOBALSINDEX); if (compat53_findfield(L, top + 1, 2)) { lua_copy(L, -1, top + 1); /* move name to proper place */ lua_pop(L, 2); /* remove pushed values */ return 1; } else { lua_settop(L, top); /* remove function and global table */ return 0; } } static void compat53_pushfuncname (lua_State *L, lua_Debug *ar) { if (*ar->namewhat != '\0') /* is there a name? */ lua_pushfstring(L, "function " LUA_QS, ar->name); else if (*ar->what == 'm') /* main? */ lua_pushliteral(L, "main chunk"); else if (*ar->what == 'C') { if (compat53_pushglobalfuncname(L, ar)) { lua_pushfstring(L, "function " LUA_QS, lua_tostring(L, -1)); lua_remove(L, -2); /* remove name */ } else lua_pushliteral(L, "?"); } else lua_pushfstring(L, "function <%s:%d>", ar->short_src, ar->linedefined); } #define COMPAT53_LEVELS1 12 /* size of the first part of the stack */ #define COMPAT53_LEVELS2 10 /* size of the second part of the stack */ COMPAT53_API void luaL_traceback (lua_State *L, lua_State *L1, const char *msg, int level) { lua_Debug ar; int top = lua_gettop(L); int numlevels = compat53_countlevels(L1); int mark = (numlevels > COMPAT53_LEVELS1 + COMPAT53_LEVELS2) ? COMPAT53_LEVELS1 : 0; if (msg) lua_pushfstring(L, "%s\n", msg); lua_pushliteral(L, "stack traceback:"); while (lua_getstack(L1, level++, &ar)) { if (level == mark) { /* too many levels? */ lua_pushliteral(L, "\n\t..."); /* add a '...' */ level = numlevels - COMPAT53_LEVELS2; /* and skip to last ones */ } else { lua_getinfo(L1, "Slnt", &ar); lua_pushfstring(L, "\n\t%s:", ar.short_src); if (ar.currentline > 0) lua_pushfstring(L, "%d:", ar.currentline); lua_pushliteral(L, " in "); compat53_pushfuncname(L, &ar); lua_concat(L, lua_gettop(L) - top); } } lua_concat(L, lua_gettop(L) - top); } COMPAT53_API int luaL_fileresult (lua_State *L, int stat, const char *fname) { int en = errno; /* calls to Lua API may change this value */ if (stat) { lua_pushboolean(L, 1); return 1; } else { lua_pushnil(L); if (fname) lua_pushfstring(L, "%s: %s", fname, strerror(en)); else lua_pushstring(L, strerror(en)); lua_pushnumber(L, (lua_Number)en); return 3; } } #endif /* not COMPAT53_IS_LUAJIT */ COMPAT53_API void luaL_buffinit (lua_State *L, luaL_Buffer_53 *B) { /* make it crash if used via pointer to a 5.1-style luaL_Buffer */ B->b.p = NULL; B->b.L = NULL; B->b.lvl = 0; /* reuse the buffer from the 5.1-style luaL_Buffer though! */ B->ptr = B->b.buffer; B->capacity = LUAL_BUFFERSIZE; B->nelems = 0; B->L2 = L; } COMPAT53_API char *luaL_prepbuffsize (luaL_Buffer_53 *B, size_t s) { if (B->capacity - B->nelems < s) { /* needs to grow */ char* newptr = NULL; size_t newcap = B->capacity * 2; if (newcap - B->nelems < s) newcap = B->nelems + s; if (newcap < B->capacity) /* overflow */ luaL_error(B->L2, "buffer too large"); newptr = lua_newuserdata(B->L2, newcap); memcpy(newptr, B->ptr, B->nelems); if (B->ptr != B->b.buffer) lua_replace(B->L2, -2); /* remove old buffer */ B->ptr = newptr; B->capacity = newcap; } return B->ptr+B->nelems; } COMPAT53_API void luaL_addlstring (luaL_Buffer_53 *B, const char *s, size_t l) { memcpy(luaL_prepbuffsize(B, l), s, l); luaL_addsize(B, l); } COMPAT53_API void luaL_addvalue (luaL_Buffer_53 *B) { size_t len = 0; const char *s = lua_tolstring(B->L2, -1, &len); if (!s) luaL_error(B->L2, "cannot convert value to string"); if (B->ptr != B->b.buffer) lua_insert(B->L2, -2); /* userdata buffer must be at stack top */ luaL_addlstring(B, s, len); lua_remove(B->L2, B->ptr != B->b.buffer ? -2 : -1); } void luaL_pushresult (luaL_Buffer_53 *B) { lua_pushlstring(B->L2, B->ptr, B->nelems); if (B->ptr != B->b.buffer) lua_replace(B->L2, -2); /* remove userdata buffer */ } #endif /* Lua 5.1 */ /* definitions for Lua 5.1 and Lua 5.2 */ #if defined( LUA_VERSION_NUM ) && LUA_VERSION_NUM <= 502 COMPAT53_API int lua_geti (lua_State *L, int index, lua_Integer i) { index = lua_absindex(L, index); lua_pushinteger(L, i); lua_gettable(L, index); return lua_type(L, -1); } COMPAT53_API int lua_isinteger (lua_State *L, int index) { if (lua_type(L, index) == LUA_TNUMBER) { lua_Number n = lua_tonumber(L, index); lua_Integer i = lua_tointeger(L, index); if (i == n) return 1; } return 0; } static void compat53_reverse (lua_State *L, int a, int b) { for (; a < b; ++a, --b) { lua_pushvalue(L, a); lua_pushvalue(L, b); lua_replace(L, a); lua_replace(L, b); } } COMPAT53_API void lua_rotate (lua_State *L, int idx, int n) { int n_elems = 0; idx = lua_absindex(L, idx); n_elems = lua_gettop(L)-idx+1; if (n < 0) n += n_elems; if ( n > 0 && n < n_elems) { luaL_checkstack(L, 2, "not enough stack slots available"); n = n_elems - n; compat53_reverse(L, idx, idx+n-1); compat53_reverse(L, idx+n, idx+n_elems-1); compat53_reverse(L, idx, idx+n_elems-1); } } COMPAT53_API void lua_seti (lua_State *L, int index, lua_Integer i) { luaL_checkstack(L, 1, "not enough stack slots available"); index = lua_absindex(L, index); lua_pushinteger(L, i); lua_insert(L, -2); lua_settable(L, index); } #if !defined(lua_str2number) # define lua_str2number(s, p) strtod(s, p) #endif COMPAT53_API size_t lua_stringtonumber (lua_State *L, const char *s) { char* endptr; lua_Number n = lua_str2number(s, &endptr); if (endptr != s) { while (*endptr != '\0' && isspace((unsigned char)*endptr)) ++endptr; if (*endptr == '\0') { lua_pushnumber(L, n); return endptr - s + 1; } } return 0; } COMPAT53_API void luaL_requiref (lua_State *L, const char *modname, lua_CFunction openf, int glb) { luaL_checkstack(L, 3, "not enough stack slots available"); lua_getfield(L, LUA_REGISTRYINDEX, "_LOADED"); if (lua_getfield(L, -1, modname) == LUA_TNIL) { lua_pop(L, 1); lua_pushcfunction(L, openf); lua_pushstring(L, modname); lua_call(L, 1, 1); lua_pushvalue(L, -1); lua_setfield(L, -3, modname); } if (glb) { lua_pushvalue(L, -1); lua_setglobal(L, modname); } lua_replace(L, -2); } #endif /* Lua 5.1 and 5.2 */ #endif /* COMPAT53_C_ */ /********************************************************************* * This file contains parts of Lua 5.2's and Lua 5.3's source code: * * Copyright (C) 1994-2014 Lua.org, PUC-Rio. * * Permission is hereby granted, free of charge, to any person obtaining * a copy of this software and associated documentation files (the * "Software"), to deal in the Software without restriction, including * without limitation the rights to use, copy, modify, merge, publish, * distribute, sublicense, and/or sell copies of the Software, and to * permit persons to whom the Software is furnished to do so, subject to * the following conditions: * * The above copyright notice and this permission notice shall be * included in all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. *********************************************************************/ lua-systemd-master/vendor/compat-5.3/c-api/compat-5.3.h000066400000000000000000000247471271662244600226610ustar00rootroot00000000000000#ifndef COMPAT53_H_ #define COMPAT53_H_ #include #include #include #include #include #include #if defined(COMPAT53_PREFIX) /* - change the symbol names of functions to avoid linker conflicts * - compat-5.3.c needs to be compiled (and linked) separately */ # if !defined(COMPAT53_API) # define COMPAT53_API extern # endif # undef COMPAT53_INCLUDE_SOURCE #else /* COMPAT53_PREFIX */ /* - make all functions static and include the source. * - don't mess with the symbol names of functions * - compat-5.3.c doesn't need to be compiled (and linked) separately */ # define COMPAT53_PREFIX lua # undef COMPAT53_API # if defined(__GNUC__) || defined(__clang__) # define COMPAT53_API __attribute__((__unused__)) static # else # define COMPAT53_API static # endif # define COMPAT53_INCLUDE_SOURCE #endif /* COMPAT53_PREFIX */ #define COMPAT53_CONCAT_HELPER(a, b) a##b #define COMPAT53_CONCAT(a, b) COMPAT53_CONCAT_HELPER(a, b) /* declarations for Lua 5.1 */ #if defined(LUA_VERSION_NUM) && LUA_VERSION_NUM == 501 /* XXX not implemented: * lua_arith (new operators) * lua_upvalueid * lua_upvaluejoin * lua_version * lua_yieldk * luaL_execresult * luaL_loadbufferx * luaL_loadfilex */ /* PUC-Rio Lua uses lconfig_h as include guard for luaconf.h, * LuaJIT uses luaconf_h. If you use PUC-Rio's include files * but LuaJIT's library, you will need to define the macro * COMPAT53_IS_LUAJIT yourself! */ #if !defined(COMPAT53_IS_LUAJIT) && defined(luaconf_h) # define COMPAT53_IS_LUAJIT #endif #define LUA_OK 0 #define LUA_OPADD 0 #define LUA_OPSUB 1 #define LUA_OPMUL 2 #define LUA_OPDIV 3 #define LUA_OPMOD 4 #define LUA_OPPOW 5 #define LUA_OPUNM 6 #define LUA_OPEQ 0 #define LUA_OPLT 1 #define LUA_OPLE 2 typedef struct luaL_Stream { FILE *f; /* The following field is for LuaJIT which adds a uint32_t field * to file handles. */ #if INT_MAX > 2147483640L unsigned int type; #else unsigned long type; #endif lua_CFunction closef; } luaL_Stream; typedef size_t lua_Unsigned; typedef struct luaL_Buffer_53 { luaL_Buffer b; /* make incorrect code crash! */ char *ptr; size_t nelems; size_t capacity; lua_State *L2; } luaL_Buffer_53; #define luaL_Buffer luaL_Buffer_53 #define lua_absindex COMPAT53_CONCAT(COMPAT53_PREFIX, _absindex) COMPAT53_API int lua_absindex (lua_State *L, int i); #define lua_arith COMPAT53_CONCAT(COMPAT53_PREFIX, _arith) COMPAT53_API void lua_arith (lua_State *L, int op); #define lua_compare COMPAT53_CONCAT(COMPAT53_PREFIX, _compare) COMPAT53_API int lua_compare (lua_State *L, int idx1, int idx2, int op); #define lua_copy COMPAT53_CONCAT(COMPAT53_PREFIX, _copy) COMPAT53_API void lua_copy (lua_State *L, int from, int to); #define lua_getuservalue(L, i) \ (lua_getfenv(L, i), lua_type(L, -1)) #define lua_setuservalue(L, i) \ (luaL_checktype(L, -1, LUA_TTABLE), lua_setfenv(L, i)) #define lua_len COMPAT53_CONCAT(COMPAT53_PREFIX, _len) COMPAT53_API void lua_len (lua_State *L, int i); #define luaL_newlibtable(L, l) \ (lua_createtable(L, 0, sizeof(l)/sizeof(*(l))-1)) #define luaL_newlib(L, l) \ (luaL_newlibtable(L, l), luaL_register(L, NULL, l)) #define lua_pushglobaltable(L) \ lua_pushvalue(L, LUA_GLOBALSINDEX) #define lua_rawgetp COMPAT53_CONCAT(COMPAT53_PREFIX, _rawgetp) COMPAT53_API int lua_rawgetp (lua_State *L, int i, const void *p); #define lua_rawsetp COMPAT53_CONCAT(COMPAT53_PREFIX, _rawsetp) COMPAT53_API void lua_rawsetp(lua_State *L, int i, const void *p); #define lua_rawlen(L, i) lua_objlen(L, i) #define lua_tointegerx COMPAT53_CONCAT(COMPAT53_PREFIX, _tointegerx) COMPAT53_API lua_Integer lua_tointegerx (lua_State *L, int i, int *isnum); #define lua_tonumberx COMPAT53_CONCAT(COMPAT53_PREFIX, _tonumberx) COMPAT53_API lua_Number lua_tonumberx (lua_State *L, int i, int *isnum); #define luaL_checkversion COMPAT53_CONCAT(COMPAT53_PREFIX, L_checkversion) COMPAT53_API void luaL_checkversion (lua_State *L); #define luaL_getsubtable COMPAT53_CONCAT(COMPAT53_PREFIX, L_getsubtable) COMPAT53_API int luaL_getsubtable (lua_State* L, int i, const char *name); #define luaL_len COMPAT53_CONCAT(COMPAT53_PREFIX, L_len) COMPAT53_API int luaL_len (lua_State *L, int i); #define luaL_setfuncs COMPAT53_CONCAT(COMPAT53_PREFIX, L_setfuncs) COMPAT53_API void luaL_setfuncs (lua_State *L, const luaL_Reg *l, int nup); #define luaL_setmetatable COMPAT53_CONCAT(COMPAT53_PREFIX, L_setmetatable) COMPAT53_API void luaL_setmetatable (lua_State *L, const char *tname); #define luaL_testudata COMPAT53_CONCAT(COMPAT53_PREFIX, L_testudata) COMPAT53_API void *luaL_testudata (lua_State *L, int i, const char *tname); #define luaL_tolstring COMPAT53_CONCAT(COMPAT53_PREFIX, L_tolstring) COMPAT53_API const char *luaL_tolstring (lua_State *L, int idx, size_t *len); #if !defined(COMPAT53_IS_LUAJIT) #define luaL_traceback COMPAT53_CONCAT(COMPAT53_PREFIX, L_traceback) COMPAT53_API void luaL_traceback (lua_State *L, lua_State *L1, const char *msg, int level); #define luaL_fileresult COMPAT53_CONCAT(COMPAT53_PREFIX, L_fileresult) COMPAT53_API int luaL_fileresult (lua_State *L, int stat, const char *fname); #endif /* COMPAT53_IS_LUAJIT */ #define lua_callk(L, na, nr, ctx, cont) \ ((void)(ctx), (void)(cont), lua_call(L, na, nr)) #define lua_pcallk(L, na, nr, err, ctx, cont) \ ((void)(ctx), (void)(cont), lua_pcall(L, na, nr, err)) #define luaL_buffinit COMPAT53_CONCAT(COMPAT53_PREFIX, _buffinit_53) COMPAT53_API void luaL_buffinit (lua_State *L, luaL_Buffer_53 *B); #define luaL_prepbuffsize COMPAT53_CONCAT(COMPAT53_PREFIX, _prepbufsize_53) COMPAT53_API char *luaL_prepbuffsize (luaL_Buffer_53 *B, size_t s); #define luaL_addlstring COMPAT53_CONCAT(COMPAT53_PREFIX, _addlstring_53) COMPAT53_API void luaL_addlstring (luaL_Buffer_53 *B, const char *s, size_t l); #define luaL_addvalue COMPAT53_CONCAT(COMPAT53_PREFIX, _addvalue_53) COMPAT53_API void luaL_addvalue (luaL_Buffer_53 *B); #define luaL_pushresult COMPAT53_CONCAT(COMPAT53_PREFIX, _pushresult_53) COMPAT53_API void luaL_pushresult (luaL_Buffer_53 *B); #undef luaL_buffinitsize #define luaL_buffinitsize(L, B, s) \ (luaL_buffinit(L, B), luaL_prepbuffsize(B, s)) #undef luaL_prepbuffer #define luaL_prepbuffer(B) \ luaL_prepbuffsize(B, LUAL_BUFFERSIZE) #undef luaL_addchar #define luaL_addchar(B, c) \ ((void)((B)->nelems < (B)->capacity || luaL_prepbuffsize(B, 1)), \ ((B)->ptr[(B)->nelems++] = (c))) #undef luaL_addsize #define luaL_addsize(B, s) \ ((B)->nelems += (s)) #undef luaL_addstring #define luaL_addstring(B, s) \ luaL_addlstring(B, s, strlen(s)) #undef luaL_pushresultsize #define luaL_pushresultsize(B, s) \ (luaL_addsize(B, s), luaL_pushresult(B)) #if defined(LUA_COMPAT_APIINTCASTS) #define lua_pushunsigned(L, n) \ lua_pushinteger(L, (lua_Integer)(n)) #define lua_tounsignedx(L, i, is) \ ((lua_Unsigned)lua_tointegerx(L, i, is)) #define lua_tounsigned(L, i) \ lua_tounsignedx(L, i, NULL) #define luaL_checkunsigned(L, a) \ ((lua_Unsigned)luaL_checkinteger(L, a)) #define luaL_optunsigned(L, a, d) \ ((lua_Unsigned)luaL_optinteger(L, a, (lua_Integer)(d))) #endif #endif /* Lua 5.1 only */ /* declarations for Lua 5.1 and 5.2 */ #if defined(LUA_VERSION_NUM) && LUA_VERSION_NUM <= 502 typedef int lua_KContext; typedef int (*lua_KFunction)(lua_State *L, int status, lua_KContext ctx); #define lua_dump(L, w, d, s) \ ((void)(s), lua_dump(L, w, d)) #define lua_getfield(L, i, k) \ (lua_getfield(L, i, k), lua_type(L, -1)) #define lua_gettable(L, i) \ (lua_gettable(L, i), lua_type(L, -1)) #define lua_geti COMPAT53_CONCAT(COMPAT53_PREFIX, _geti) COMPAT53_API int lua_geti (lua_State *L, int index, lua_Integer i); #define lua_isinteger COMPAT53_CONCAT(COMPAT53_PREFIX, _isinteger) COMPAT53_API int lua_isinteger (lua_State *L, int index); #define lua_numbertointeger(n, p) \ ((*(p) = (lua_Integer)(n)), 1) #define lua_rawget(L, i) \ (lua_rawget(L, i), lua_type(L, -1)) #define lua_rawgeti(L, i, n) \ (lua_rawgeti(L, i, n), lua_type(L, -1)) #define lua_rotate COMPAT53_CONCAT(COMPAT53_PREFIX, _rotate) COMPAT53_API void lua_rotate (lua_State *L, int idx, int n); #define lua_seti COMPAT53_CONCAT(COMPAT53_PREFIX, _seti) COMPAT53_API void lua_seti (lua_State *L, int index, lua_Integer i); #define lua_strtonum COMPAT53_CONCAT(COMPAT53_PREFIX, _stringtonumber) COMPAT53_API size_t lua_stringtonumber (lua_State *L, const char *s); #define luaL_getmetafield(L, o, e) \ (luaL_getmetafield(L, o, e) ? lua_type(L, -1) : LUA_TNIL) #define luaL_requiref COMPAT53_CONCAT(COMPAT53_PREFIX, L_requiref_53) COMPAT53_API void luaL_requiref (lua_State *L, const char *modname, lua_CFunction openf, int glb ); #endif /* Lua 5.1 and Lua 5.2 */ /* declarations for Lua 5.2 */ #if defined(LUA_VERSION_NUM) && LUA_VERSION_NUM == 502 /* XXX not implemented: * lua_isyieldable * lua_getextraspace * lua_arith (new operators) * lua_pushfstring (new formats) */ #define lua_getglobal(L, n) \ (lua_getglobal(L, n), lua_type(L, -1)) #define lua_getuservalue(L, i) \ (lua_getuservalue(L, i), lua_type(L, -1)) #define lua_rawgetp(L, i, p) \ (lua_rawgetp(L, i, p), lua_type(L, -1)) #define LUA_KFUNCTION(_name) \ static int (_name)(lua_State *L, int status, lua_KContext ctx); \ static int (_name ## _52)(lua_State *L) { \ lua_KContext ctx; \ int status = lua_getctx(L, &ctx); \ return (_name)(L, status, ctx); \ } \ static int (_name)(lua_State *L, int status, lua_KContext ctx) #define lua_pcallk(L, na, nr, err, ctx, cont) \ lua_pcallk(L, na, nr, err, ctx, cont ## _52) #define lua_callk(L, na, nr, ctx, cont) \ lua_callk(L, na, nr, ctx, cont ## _52) #define lua_yieldk(L, nr, ctx, cont) \ lua_yieldk(L, nr, ctx, cont ## _52) #ifdef lua_call # undef lua_call # define lua_call(L, na, nr) \ (lua_callk)(L, na, nr, 0, NULL) #endif #ifdef lua_pcall # undef lua_pcall # define lua_pcall(L, na, nr, err) \ (lua_pcallk)(L, na, nr, err, 0, NULL) #endif #ifdef lua_yield # undef lua_yield # define lua_yield(L, nr) \ (lua_yieldk)(L, nr, 0, NULL) #endif #endif /* Lua 5.2 only */ /* other Lua versions */ #if !defined(LUA_VERSION_NUM) || LUA_VERSION_NUM < 501 || LUA_VERSION_NUM > 503 # error "unsupported Lua version (i.e. not Lua 5.1, 5.2, or 5.3)" #endif /* other Lua versions except 5.1, 5.2, and 5.3 */ /* helper macro for defining continuation functions (for every version * *except* Lua 5.2) */ #ifndef LUA_KFUNCTION #define LUA_KFUNCTION(_name) \ static int (_name)(lua_State *L, int status, lua_KContext ctx) #endif #if defined(COMPAT53_INCLUDE_SOURCE) # include "compat-5.3.c" #endif #endif /* COMPAT53_H_ */ lua-systemd-master/vendor/compat-5.3/compat53.lua000066400000000000000000000734471271662244600220700ustar00rootroot00000000000000local lua_version = _VERSION:sub(-3) if lua_version < "5.3" then -- local aliases for commonly used functions local type, select, error = type, select, error -- select the most powerful getmetatable function available local gmt = type(debug) == "table" and debug.getmetatable or getmetatable or function() return false end -- type checking functions local checkinteger -- forward declararation local function argcheck(cond, i, f, extra) if not cond then error("bad argument #"..i.." to '"..f.."' ("..extra..")", 0) end end local function checktype(x, t, i, f) local xt = type(x) if xt ~= t then error("bad argument #"..i.." to '"..f.."' ("..t.. " expected, got "..xt..")", 0) end end -- load utf8 library local utf8_ok, utf8lib = pcall(require, "compat53.utf8") if utf8_ok then utf8 = utf8lib package.loaded["utf8"] = utf8lib if lua_version == "5.1" then utf8lib.charpattern = "[%z\1-\127\194-\244][\128-\191]*" end end -- load table library local table_ok, tablib = pcall(require, "compat53.table") if table_ok then for k,v in pairs(tablib) do table[k] = v end end -- load string packing functions local str_ok, strlib = pcall(require, "compat53.string") if str_ok then for k,v in pairs(strlib) do string[k] = v end end -- try Roberto's struct module for string packing/unpacking if -- compat53.string is unavailable if not str_ok then local struct_ok, struct = pcall(require, "struct") if struct_ok then string.pack = struct.pack string.packsize = struct.size string.unpack = struct.unpack end end -- update math library do local maxint, minint = 1, 0 while maxint+1 > maxint and 2*maxint > maxint do maxint = maxint * 2 end if 2*maxint <= maxint then maxint = 2*maxint-1 minint = -maxint-1 else maxint = maxint minint = -maxint end math.maxinteger = maxint math.mininteger = minint function math.tointeger(n) if type(n) == "number" and n <= maxint and n >= minint and n % 1 == 0 then return n end return nil end function math.type(n) if type(n) == "number" then if n <= maxint and n >= minint and n % 1 == 0 then return "integer" else return "float" end else return nil end end function checkinteger(x, i, f) local t = type(x) if t ~= "number" then error("bad argument #"..i.." to '"..f.. "' (number expected, got "..t..")", 0) elseif x > maxint or x < minint or x % 1 ~= 0 then error("bad argument #"..i.." to '"..f.. "' (number has no integer representation)", 0) else return x end end function math.ult(m, n) m = checkinteger(m, "1", "math.ult") n = checkinteger(n, "2", "math.ult") if m >= 0 and n < 0 then return true elseif m < 0 and n >= 0 then return false else return m < n end end end -- ipairs should respect __index metamethod do local _ipairs = ipairs local function ipairs_iterator(st, var) var = var + 1 local val = st[var] if val ~= nil then return var, st[var] end end function ipairs(t) if gmt(t) ~= nil then -- t has metatable return ipairs_iterator, t, 0 else return _ipairs(t) end end end -- update table library (if C module not available) if not table_ok then local table_concat = table.concat function table.concat(list, sep, i, j) local mt = gmt(list) if type(mt) == "table" and type(mt.__len) == "function" then local src = list list, i, j = {}, i or 1, j or mt.__len(src) for k = i, j do list[k] = src[k] end end return table_concat(list, sep, i, j) end local table_insert = table.insert function table.insert(list, ...) local mt = gmt(list) local has_mt = type(mt) == "table" local has_len = has_mt and type(mt.__len) == "function" if has_mt and (has_len or mt.__index or mt.__newindex) then local e = (has_len and mt.__len(list) or #list)+1 local nargs, pos, value = select('#', ...), ... if nargs == 1 then pos, value = e, pos elseif nargs == 2 then pos = checkinteger(pos, "2", "table.insert") argcheck(1 <= pos and pos <= e, "2", "table.insert", "position out of bounds" ) else error("wrong number of arguments to 'insert'", 0) end for i = e-1, pos, -1 do list[i+1] = list[i] end list[pos] = value else return table_insert(list, ...) end end function table.move(a1, f, e, t, a2) a2 = a2 or a1 f = checkinteger(f, "2", "table.move") argcheck(f > 0, "2", "table.move", "initial position must be positive") e = checkinteger(e, "3", "table.move") t = checkinteger(t, "4", "table.move") if e >= f then local m, n, d = 0, e-f, 1 if t > f then m, n, d = n, m, -1 end for i = m, n, d do a2[t+i] = a1[f+i] end end return a2 end local table_remove = table.remove function table.remove(list, pos) local mt = gmt(list) local has_mt = type(mt) == "table" local has_len = has_mt and type(mt.__len) == "function" if has_mt and (has_len or mt.__index or mt.__newindex) then local e = (has_len and mt.__len(list) or #list) pos = pos ~= nil and checkinteger(pos, "2", "table.remove") or e if pos ~= e then argcheck(1 <= pos and pos <= e+1, "2", "table.remove", "position out of bounds" ) end local result = list[pos] while pos < e do list[pos] = list[pos+1] pos = pos + 1 end list[pos] = nil return result else return table_remove(list, pos) end end do local function pivot(list, cmp, a, b) local m = b - a if m > 2 then local c = a + (m-m%2)/2 local x, y, z = list[a], list[b], list[c] if not cmp(x, y) then x, y, a, b = y, x, b, a end if not cmp(y, z) then y, z, b, c = z, y, c, b end if not cmp(x, y) then x, y, a, b = y, x, b, a end return b, y else return b, list[b] end end local function lt_cmp(a, b) return a < b end local function qsort(list, cmp, b, e) if b < e then local i, j, k, val = b, e, pivot(list, cmp, b, e) while i < j do while i < j and cmp(list[i], val) do i = i + 1 end while i < j and not cmp(list[j], val) do j = j - 1 end if i < j then list[i], list[j] = list[j], list[i] if i == k then k = j end -- update pivot position i, j = i+1, j-1 end end if i ~= k and not cmp(list[i], val) then list[i], list[k] = val, list[i] k = i -- update pivot position end qsort(list, cmp, b, i == k and i-1 or i) return qsort(list, cmp, i+1, e) end end local table_sort = table.sort function table.sort(list, cmp) local mt = gmt(list) local has_mt = type(mt) == "table" local has_len = has_mt and type(mt.__len) == "function" if has_len then cmp = cmp or lt_cmp local len = mt.__len(list) return qsort(list, cmp, 1, len) else return table_sort(list, cmp) end end end local table_unpack = lua_version == "5.1" and unpack or table.unpack local function unpack_helper(list, i, j, ...) if j < i then return ... else return unpack_helper(list, i, j-1, list[j], ...) end end function table.unpack(list, i, j) local mt = gmt(list) local has_mt = type(mt) == "table" local has_len = has_mt and type(mt.__len) == "function" if has_mt and (has_len or mt.__index) then i, j = i or 1, j or (has_len and mt.__len(list)) or #list return unpack_helper(list, i, j) else return table_unpack(list, i, j) end end end -- update table library -- bring Lua 5.1 (and LuaJIT) up to speed with Lua 5.2 if lua_version == "5.1" then -- detect LuaJIT (including LUAJIT_ENABLE_LUA52COMPAT compilation flag) local is_luajit = (string.dump(function() end) or ""):sub(1, 3) == "\027LJ" local is_luajit52 = is_luajit and #setmetatable({}, { __len = function() return 1 end }) == 1 -- table that maps each running coroutine to the coroutine that resumed it -- this is used to build complete tracebacks when "coroutine-friendly" pcall -- is used. local pcall_previous = {} local pcall_callOf = {} local xpcall_running = {} local coroutine_running = coroutine.running -- handle debug functions if type(debug) == "table" then if not is_luajit52 then local _G, package = _G, package local debug_setfenv = debug.setfenv function debug.setuservalue(obj, value) if type(obj) ~= "userdata" then error("bad argument #1 to 'setuservalue' (userdata expected, got ".. type(obj)..")", 2) end if value == nil then value = _G end if type(value) ~= "table" then error("bad argument #2 to 'setuservalue' (table expected, got ".. type(value)..")", 2) end return debug_setfenv(obj, value) end local debug_getfenv = debug.getfenv function debug.getuservalue(obj) if type(obj) ~= "userdata" then return nil else local v = debug_getfenv(obj) if v == _G or v == package then return nil end return v end end local debug_setmetatable = debug.setmetatable function debug.setmetatable(value, tab) debug_setmetatable(value, tab) return value end end -- not luajit with compat52 enabled if not is_luajit then local debug_getinfo = debug.getinfo local function calculate_trace_level(co, level) if level ~= nil then for out = 1, 1/0 do local info = (co==nil) and debug_getinfo(out, "") or debug_getinfo(co, out, "") if info == nil then local max = out-1 if level <= max then return level end return nil, level-max end end end return 1 end local stack_pattern = "\nstack traceback:" local stack_replace = "" local debug_traceback = debug.traceback function debug.traceback(co, msg, level) local lvl local nilmsg if type(co) ~= "thread" then co, msg, level = coroutine_running(), co, msg end if msg == nil then msg = "" nilmsg = true elseif type(msg) ~= "string" then return msg end if co == nil then msg = debug_traceback(msg, level or 1) else local xpco = xpcall_running[co] if xpco ~= nil then lvl, level = calculate_trace_level(xpco, level) if lvl then msg = debug_traceback(xpco, msg, lvl) else msg = msg..stack_pattern end lvl, level = calculate_trace_level(co, level) if lvl then local trace = debug_traceback(co, "", lvl) msg = msg..trace:gsub(stack_pattern, stack_replace) end else co = pcall_callOf[co] or co lvl, level = calculate_trace_level(co, level) if lvl then msg = debug_traceback(co, msg, lvl) else msg = msg..stack_pattern end end co = pcall_previous[co] while co ~= nil do lvl, level = calculate_trace_level(co, level) if lvl then local trace = debug_traceback(co, "", lvl) msg = msg..trace:gsub(stack_pattern, stack_replace) end co = pcall_previous[co] end end if nilmsg then msg = msg:gsub("^\n", "") end msg = msg:gsub("\n\t%(tail call%): %?", "\000") msg = msg:gsub("\n\t%.%.%.\n", "\001\n") msg = msg:gsub("\n\t%.%.%.$", "\001") msg = msg:gsub("(%z+)\001(%z+)", function(some, other) return "\n\t(..."..#some+#other.."+ tail call(s)...)" end) msg = msg:gsub("\001(%z+)", function(zeros) return "\n\t(..."..#zeros.."+ tail call(s)...)" end) msg = msg:gsub("(%z+)\001", function(zeros) return "\n\t(..."..#zeros.."+ tail call(s)...)" end) msg = msg:gsub("%z+", function(zeros) return "\n\t(..."..#zeros.." tail call(s)...)" end) msg = msg:gsub("\001", function(zeros) return "\n\t..." end) return msg end end -- is not luajit end -- debug table available if not is_luajit52 then local _pairs = pairs function pairs(t) local mt = gmt(t) if type(mt) == "table" and type(mt.__pairs) == "function" then return mt.__pairs(t) else return _pairs(t) end end end if not is_luajit then local function check_mode(mode, prefix) local has = { text = false, binary = false } for i = 1,#mode do local c = mode:sub(i, i) if c == "t" then has.text = true end if c == "b" then has.binary = true end end local t = prefix:sub(1, 1) == "\27" and "binary" or "text" if not has[t] then return "attempt to load a "..t.." chunk (mode is '"..mode.."')" end end local setfenv = setfenv local _load, _loadstring = load, loadstring function load(ld, source, mode, env) mode = mode or "bt" local chunk, msg if type( ld ) == "string" then if mode ~= "bt" then local merr = check_mode(mode, ld) if merr then return nil, merr end end chunk, msg = _loadstring(ld, source) else local ld_type = type(ld) if ld_type ~= "function" then error("bad argument #1 to 'load' (function expected, got ".. ld_type..")", 2) end if mode ~= "bt" then local checked, merr = false, nil local function checked_ld() if checked then return ld() else checked = true local v = ld() merr = check_mode(mode, v or "") if merr then return nil end return v end end chunk, msg = _load(checked_ld, source) if merr then return nil, merr end else chunk, msg = _load(ld, source) end end if not chunk then return chunk, msg end if env ~= nil then setfenv(chunk, env) end return chunk end loadstring = load local _loadfile = loadfile local io_open = io.open function loadfile(file, mode, env) mode = mode or "bt" if mode ~= "bt" then local f = io_open(file, "rb") if f then local prefix = f:read(1) f:close() if prefix then local merr = check_mode(mode, prefix) if merr then return nil, merr end end end end local chunk, msg = _loadfile(file) if not chunk then return chunk, msg end if env ~= nil then setfenv(chunk, env) end return chunk end end -- not luajit if not is_luajit52 then function rawlen(v) local t = type(v) if t ~= "string" and t ~= "table" then error("bad argument #1 to 'rawlen' (table or string expected)", 2) end return #v end end if not is_luajit52 then local os_execute = os.execute function os.execute(cmd) local code = os_execute(cmd) -- Lua 5.1 does not report exit by signal. if code == 0 then return true, "exit", code else return nil, "exit", code/256 -- only correct on POSIX! end end end if not table_ok and not is_luajit52 then table.pack = function(...) return { n = select('#', ...), ... } end end local main_coroutine = coroutine.create(function() end) local _pcall = pcall local coroutine_create = coroutine.create function coroutine.create(func) local success, result = _pcall(coroutine_create, func) if not success then if type(func) ~= "function" then error("bad argument #1 (function expected)", 0) end result = coroutine_create(function(...) return func(...) end) end return result end local pcall_mainOf = {} if not is_luajit52 then function coroutine.running() local co = coroutine_running() if co then return pcall_mainOf[co] or co, false else return main_coroutine, true end end end local coroutine_yield = coroutine.yield function coroutine.yield(...) local co, flag = coroutine_running() if co and not flag then return coroutine_yield(...) else error("attempt to yield from outside a coroutine", 0) end end if not is_luajit then local coroutine_resume = coroutine.resume function coroutine.resume(co, ...) if co == main_coroutine then return false, "cannot resume non-suspended coroutine" else return coroutine_resume(co, ...) end end local coroutine_status = coroutine.status function coroutine.status(co) local notmain = coroutine_running() if co == main_coroutine then return notmain and "normal" or "running" else return coroutine_status(co) end end local function pcall_results(current, call, success, ...) if coroutine_status(call) == "suspended" then return pcall_results(current, call, coroutine_resume(call, coroutine_yield(...))) end if pcall_previous then pcall_previous[call] = nil local main = pcall_mainOf[call] if main == current then current = nil end pcall_callOf[main] = current end pcall_mainOf[call] = nil return success, ... end local function pcall_exec(current, call, ...) local main = pcall_mainOf[current] or current pcall_mainOf[call] = main if pcall_previous then pcall_previous[call] = current pcall_callOf[main] = call end return pcall_results(current, call, coroutine_resume(call, ...)) end local coroutine_create52 = coroutine.create local function pcall_coroutine(func) if type(func) ~= "function" then local callable = func func = function (...) return callable(...) end end return coroutine_create52(func) end function pcall(func, ...) local current = coroutine_running() if not current then return _pcall(func, ...) end return pcall_exec(current, pcall_coroutine(func), ...) end local _tostring = tostring local function xpcall_catch(current, call, msgh, success, ...) if not success then xpcall_running[current] = call local ok, result = _pcall(msgh, ...) xpcall_running[current] = nil if not ok then return false, "error in error handling (".._tostring(result)..")" end return false, result end return true, ... end local _xpcall = xpcall local _unpack = unpack function xpcall(f, msgh, ...) local current = coroutine_running() if not current then local args, n = { ... }, select('#', ...) return _xpcall(function() return f(_unpack(args, 1, n)) end, msgh) end local call = pcall_coroutine(f) return xpcall_catch(current, call, msgh, pcall_exec(current, call, ...)) end end -- not luajit if not is_luajit then local math_log = math.log math.log = function(x, base) if base ~= nil then return math_log(x)/math_log(base) else return math_log(x) end end end local package = package if not is_luajit then local io_open = io.open local table_concat = table.concat function package.searchpath(name, path, sep, rep) sep = (sep or "."):gsub("(%p)", "%%%1") rep = (rep or package.config:sub(1, 1)):gsub("(%%)", "%%%1") local pname = name:gsub(sep, rep):gsub("(%%)", "%%%1") local msg = {} for subpath in path:gmatch("[^;]+") do local fpath = subpath:gsub("%?", pname) local f = io_open(fpath, "r") if f then f:close() return fpath end msg[#msg+1] = "\n\tno file '" .. fpath .. "'" end return nil, table_concat(msg) end end local p_index = { searchers = package.loaders } local rawset = rawset setmetatable(package, { __index = p_index, __newindex = function(p, k, v) if k == "searchers" then rawset(p, "loaders", v) p_index.searchers = v else rawset(p, k, v) end end }) local string_gsub = string.gsub local function fix_pattern(pattern) return (string_gsub(pattern, "%z", "%%z")) end local string_find = string.find function string.find(s, pattern, ...) return string_find(s, fix_pattern(pattern), ...) end local string_gmatch = string.gmatch function string.gmatch(s, pattern) return string_gmatch(s, fix_pattern(pattern)) end function string.gsub(s, pattern, ...) return string_gsub(s, fix_pattern(pattern), ...) end local string_match = string.match function string.match(s, pattern, ...) return string_match(s, fix_pattern(pattern), ...) end if not is_luajit then local string_rep = string.rep function string.rep(s, n, sep) if sep ~= nil and sep ~= "" and n >= 2 then return s .. string_rep(sep..s, n-1) else return string_rep(s, n) end end end if not is_luajit then local string_format = string.format do local addqt = { ["\n"] = "\\\n", ["\\"] = "\\\\", ["\""] = "\\\"" } local function addquoted(c) return addqt[c] or string_format("\\%03d", c:byte()) end local _unpack = unpack function string.format(fmt, ...) local args, n = { ... }, select('#', ...) local i = 0 local function adjust_fmt(lead, mods, kind) if #lead % 2 == 0 then i = i + 1 if kind == "s" then args[i] = tostring(args[i]) elseif kind == "q" then args[i] = '"'..string_gsub(args[i], "[%z%c\\\"\n]", addquoted)..'"' return lead.."%"..mods.."s" end end end fmt = string_gsub(fmt, "(%%*)%%([%d%.%-%+%# ]*)(%a)", adjust_fmt) return string_format(fmt, _unpack(args, 1, n)) end end end local io_open = io.open local io_write = io.write local io_output = io.output function io.write(...) local res, msg, errno = io_write(...) if res then return io_output() else return nil, msg, errno end end if not is_luajit then local lines_iterator do local function helper( st, var_1, ... ) if var_1 == nil then if st.doclose then st.f:close() end if (...) ~= nil then error((...), 2) end end return var_1, ... end local _unpack = unpack function lines_iterator(st) return helper(st, st.f:read(_unpack(st, 1, st.n))) end end local valid_format = { ["*l"] = true, ["*n"] = true, ["*a"] = true } local io_input = io.input function io.lines(fname, ...) local doclose, file, msg if fname ~= nil then doclose, file, msg = true, io_open(fname, "r") if not file then error(msg, 2) end else doclose, file = false, io_input() end local st = { f=file, doclose=doclose, n=select('#', ...), ... } for i = 1, st.n do if type(st[i]) ~= "number" and not valid_format[st[i]] then error("bad argument #"..(i+1).." to 'for iterator' (invalid format)", 2) end end return lines_iterator, st end do local io_stdout = io.stdout local io_type = io.type local file_meta = gmt(io_stdout) if type(file_meta) == "table" and type(file_meta.__index) == "table" then local file_write = file_meta.__index.write file_meta.__index.write = function(self, ...) local res, msg, errno = file_write(self, ...) if res then return self else return nil, msg, errno end end file_meta.__index.lines = function(self, ...) if io_type(self) == "closed file" then error("attempt to use a closed file", 2) end local st = { f=self, doclose=false, n=select('#', ...), ... } for i = 1, st.n do if type(st[i]) ~= "number" and not valid_format[st[i]] then error("bad argument #"..(i+1).." to 'for iterator' (invalid format)", 2) end end return lines_iterator, st end end end end -- not luajit end -- lua 5.1 end -- lua < 5.3 -- vi: set expandtab softtabstop=3 shiftwidth=3 : lua-systemd-master/vendor/compat-5.3/lprefix.h000066400000000000000000000065631271662244600215470ustar00rootroot00000000000000/* ** $Id: lprefix.h,v 1.2 2014/12/29 16:54:13 roberto Exp $ ** Definitions for Lua code that must come before any other header file ** See Copyright Notice in lua.h */ #ifndef lprefix_h #define lprefix_h /* ** Allows POSIX/XSI stuff */ #if !defined(LUA_USE_C89) /* { */ #if !defined(_XOPEN_SOURCE) #define _XOPEN_SOURCE 600 #elif _XOPEN_SOURCE == 0 #undef _XOPEN_SOURCE /* use -D_XOPEN_SOURCE=0 to undefine it */ #endif /* ** Allows manipulation of large files in gcc and some other compilers */ #if !defined(LUA_32BITS) && !defined(_FILE_OFFSET_BITS) #define _LARGEFILE_SOURCE 1 #define _FILE_OFFSET_BITS 64 #endif #endif /* } */ /* ** Windows stuff */ #if defined(_WIN32) /* { */ #if !defined(_CRT_SECURE_NO_WARNINGS) #define _CRT_SECURE_NO_WARNINGS /* avoid warnings about ISO C functions */ #endif #endif /* } */ /* COMPAT53 adaptation */ #include "c-api/compat-5.3.h" #undef LUAMOD_API #define LUAMOD_API extern #ifdef lutf8lib_c # define luaopen_utf8 luaopen_compat53_utf8 # include /* we don't support the %U format string of lua_pushfstring! * code below adapted from the Lua 5.3 sources: */ static const char *compat53_utf8_escape (lua_State* L, ...) { long x = 0; va_list argp; va_start(argp, L); x = (long)va_arg(argp, long); va_end(argp); if (x < 0x80) { /* ASCII */ char c = (char)x; lua_pushlstring(L, &c, 1); } else { char buff[8] = { 0 }; unsigned int mfb = 0x3f; int n = 1; do { buff[8 - (n++)] = (char)(0x80|(x & 0x3f)); x >>= 6; mfb >>= 1; } while (x > mfb); buff[8-n] = (char)((~mfb << 1) | x); lua_pushlstring(L, buff+8-n, n); } return lua_tostring(L, -1); } # define lua_pushfstring(L, fmt, l) \ compat53_utf8_escape(L, l) #endif #ifdef ltablib_c # define luaopen_table luaopen_compat53_table /* lua_rawgeti in compat53.h is implemented as a macro, so the * function signature doesn't match when you use a function pointer */ static int compat53_rawgeti (lua_State *L, int i, lua_Integer n) { return lua_rawgeti(L, i, n); } # undef lua_rawgeti # define lua_rawgeti compat53_rawgeti static void compat53_rawseti (lua_State *L, int i, lua_Integer n) { lua_rawseti(L, i, (int)n); } # undef lua_rawseti # define lua_rawseti compat53_rawseti #endif /* ltablib_c */ #ifdef lstrlib_c /* move the string library open function out of the way (we only take * the string packing functions)! */ # define luaopen_string luaopen_string_XXX /* used in string.format implementation, which we don't use: */ # ifndef LUA_INTEGER_FRMLEN # define LUA_INTEGER_FRMLEN "" # define LUA_NUMBER_FRMLEN "" # endif # if LUA_VERSION_NUM < 503 /* lstrlib assumes that lua_Integer and lua_Unsigned have the same * size, so we use the unsigned equivalent of ptrdiff_t! */ # define lua_Unsigned size_t # endif static int str_pack (lua_State *L); static int str_packsize (lua_State *L); static int str_unpack (lua_State *L); LUAMOD_API int luaopen_compat53_string (lua_State *L) { luaL_Reg const funcs[] = { { "pack", str_pack }, { "packsize", str_packsize }, { "unpack", str_unpack }, { NULL, NULL } }; luaL_newlib(L, funcs); return 1; } /* make luaopen_string(_XXX) static, so it (and all other referenced * string functions) won't be included in the resulting dll * (hopefully). */ # undef LUAMOD_API # define LUAMOD_API static #endif /* lstrlib.c */ #endif lua-systemd-master/vendor/compat-5.3/lstrlib.c000066400000000000000000001212401271662244600215320ustar00rootroot00000000000000/* ** $Id: lstrlib.c,v 1.221 2014/12/11 14:03:07 roberto Exp $ ** Standard library for string operations and pattern-matching ** See Copyright Notice in lua.h */ #define lstrlib_c #define LUA_LIB #include "lprefix.h" #include #include #include #include #include #include #include "lua.h" #include "lauxlib.h" #include "lualib.h" /* ** maximum number of captures that a pattern can do during ** pattern-matching. This limit is arbitrary. */ #if !defined(LUA_MAXCAPTURES) #define LUA_MAXCAPTURES 32 #endif /* macro to 'unsign' a character */ #define uchar(c) ((unsigned char)(c)) /* ** Some sizes are better limited to fit in 'int', but must also fit in ** 'size_t'. (We assume that 'lua_Integer' cannot be smaller than 'int'.) */ #define MAXSIZE \ (sizeof(size_t) < sizeof(int) ? (~(size_t)0) : (size_t)(INT_MAX)) static int str_len (lua_State *L) { size_t l; luaL_checklstring(L, 1, &l); lua_pushinteger(L, (lua_Integer)l); return 1; } /* translate a relative string position: negative means back from end */ static lua_Integer posrelat (lua_Integer pos, size_t len) { if (pos >= 0) return pos; else if (0u - (size_t)pos > len) return 0; else return (lua_Integer)len + pos + 1; } static int str_sub (lua_State *L) { size_t l; const char *s = luaL_checklstring(L, 1, &l); lua_Integer start = posrelat(luaL_checkinteger(L, 2), l); lua_Integer end = posrelat(luaL_optinteger(L, 3, -1), l); if (start < 1) start = 1; if (end > (lua_Integer)l) end = l; if (start <= end) lua_pushlstring(L, s + start - 1, (size_t)(end - start + 1)); else lua_pushliteral(L, ""); return 1; } static int str_reverse (lua_State *L) { size_t l, i; luaL_Buffer b; const char *s = luaL_checklstring(L, 1, &l); char *p = luaL_buffinitsize(L, &b, l); for (i = 0; i < l; i++) p[i] = s[l - i - 1]; luaL_pushresultsize(&b, l); return 1; } static int str_lower (lua_State *L) { size_t l; size_t i; luaL_Buffer b; const char *s = luaL_checklstring(L, 1, &l); char *p = luaL_buffinitsize(L, &b, l); for (i=0; i MAXSIZE / n) /* may overflow? */ return luaL_error(L, "resulting string too large"); else { size_t totallen = (size_t)n * l + (size_t)(n - 1) * lsep; luaL_Buffer b; char *p = luaL_buffinitsize(L, &b, totallen); while (n-- > 1) { /* first n-1 copies (followed by separator) */ memcpy(p, s, l * sizeof(char)); p += l; if (lsep > 0) { /* empty 'memcpy' is not that cheap */ memcpy(p, sep, lsep * sizeof(char)); p += lsep; } } memcpy(p, s, l * sizeof(char)); /* last copy (not followed by separator) */ luaL_pushresultsize(&b, totallen); } return 1; } static int str_byte (lua_State *L) { size_t l; const char *s = luaL_checklstring(L, 1, &l); lua_Integer posi = posrelat(luaL_optinteger(L, 2, 1), l); lua_Integer pose = posrelat(luaL_optinteger(L, 3, posi), l); int n, i; if (posi < 1) posi = 1; if (pose > (lua_Integer)l) pose = l; if (posi > pose) return 0; /* empty interval; return no values */ n = (int)(pose - posi + 1); if (posi + n <= pose) /* arithmetic overflow? */ return luaL_error(L, "string slice too long"); luaL_checkstack(L, n, "string slice too long"); for (i=0; i= ms->level || ms->capture[l].len == CAP_UNFINISHED) return luaL_error(ms->L, "invalid capture index %%%d", l + 1); return l; } static int capture_to_close (MatchState *ms) { int level = ms->level; for (level--; level>=0; level--) if (ms->capture[level].len == CAP_UNFINISHED) return level; return luaL_error(ms->L, "invalid pattern capture"); } static const char *classend (MatchState *ms, const char *p) { switch (*p++) { case L_ESC: { if (p == ms->p_end) luaL_error(ms->L, "malformed pattern (ends with '%%')"); return p+1; } case '[': { if (*p == '^') p++; do { /* look for a ']' */ if (p == ms->p_end) luaL_error(ms->L, "malformed pattern (missing ']')"); if (*(p++) == L_ESC && p < ms->p_end) p++; /* skip escapes (e.g. '%]') */ } while (*p != ']'); return p+1; } default: { return p; } } } static int match_class (int c, int cl) { int res; switch (tolower(cl)) { case 'a' : res = isalpha(c); break; case 'c' : res = iscntrl(c); break; case 'd' : res = isdigit(c); break; case 'g' : res = isgraph(c); break; case 'l' : res = islower(c); break; case 'p' : res = ispunct(c); break; case 's' : res = isspace(c); break; case 'u' : res = isupper(c); break; case 'w' : res = isalnum(c); break; case 'x' : res = isxdigit(c); break; case 'z' : res = (c == 0); break; /* deprecated option */ default: return (cl == c); } return (islower(cl) ? res : !res); } static int matchbracketclass (int c, const char *p, const char *ec) { int sig = 1; if (*(p+1) == '^') { sig = 0; p++; /* skip the '^' */ } while (++p < ec) { if (*p == L_ESC) { p++; if (match_class(c, uchar(*p))) return sig; } else if ((*(p+1) == '-') && (p+2 < ec)) { p+=2; if (uchar(*(p-2)) <= c && c <= uchar(*p)) return sig; } else if (uchar(*p) == c) return sig; } return !sig; } static int singlematch (MatchState *ms, const char *s, const char *p, const char *ep) { if (s >= ms->src_end) return 0; else { int c = uchar(*s); switch (*p) { case '.': return 1; /* matches any char */ case L_ESC: return match_class(c, uchar(*(p+1))); case '[': return matchbracketclass(c, p, ep-1); default: return (uchar(*p) == c); } } } static const char *matchbalance (MatchState *ms, const char *s, const char *p) { if (p >= ms->p_end - 1) luaL_error(ms->L, "malformed pattern (missing arguments to '%%b')"); if (*s != *p) return NULL; else { int b = *p; int e = *(p+1); int cont = 1; while (++s < ms->src_end) { if (*s == e) { if (--cont == 0) return s+1; } else if (*s == b) cont++; } } return NULL; /* string ends out of balance */ } static const char *max_expand (MatchState *ms, const char *s, const char *p, const char *ep) { ptrdiff_t i = 0; /* counts maximum expand for item */ while (singlematch(ms, s + i, p, ep)) i++; /* keeps trying to match with the maximum repetitions */ while (i>=0) { const char *res = match(ms, (s+i), ep+1); if (res) return res; i--; /* else didn't match; reduce 1 repetition to try again */ } return NULL; } static const char *min_expand (MatchState *ms, const char *s, const char *p, const char *ep) { for (;;) { const char *res = match(ms, s, ep+1); if (res != NULL) return res; else if (singlematch(ms, s, p, ep)) s++; /* try with one more repetition */ else return NULL; } } static const char *start_capture (MatchState *ms, const char *s, const char *p, int what) { const char *res; int level = ms->level; if (level >= LUA_MAXCAPTURES) luaL_error(ms->L, "too many captures"); ms->capture[level].init = s; ms->capture[level].len = what; ms->level = level+1; if ((res=match(ms, s, p)) == NULL) /* match failed? */ ms->level--; /* undo capture */ return res; } static const char *end_capture (MatchState *ms, const char *s, const char *p) { int l = capture_to_close(ms); const char *res; ms->capture[l].len = s - ms->capture[l].init; /* close capture */ if ((res = match(ms, s, p)) == NULL) /* match failed? */ ms->capture[l].len = CAP_UNFINISHED; /* undo capture */ return res; } static const char *match_capture (MatchState *ms, const char *s, int l) { size_t len; l = check_capture(ms, l); len = ms->capture[l].len; if ((size_t)(ms->src_end-s) >= len && memcmp(ms->capture[l].init, s, len) == 0) return s+len; else return NULL; } static const char *match (MatchState *ms, const char *s, const char *p) { if (ms->matchdepth-- == 0) luaL_error(ms->L, "pattern too complex"); init: /* using goto's to optimize tail recursion */ if (p != ms->p_end) { /* end of pattern? */ switch (*p) { case '(': { /* start capture */ if (*(p + 1) == ')') /* position capture? */ s = start_capture(ms, s, p + 2, CAP_POSITION); else s = start_capture(ms, s, p + 1, CAP_UNFINISHED); break; } case ')': { /* end capture */ s = end_capture(ms, s, p + 1); break; } case '$': { if ((p + 1) != ms->p_end) /* is the '$' the last char in pattern? */ goto dflt; /* no; go to default */ s = (s == ms->src_end) ? s : NULL; /* check end of string */ break; } case L_ESC: { /* escaped sequences not in the format class[*+?-]? */ switch (*(p + 1)) { case 'b': { /* balanced string? */ s = matchbalance(ms, s, p + 2); if (s != NULL) { p += 4; goto init; /* return match(ms, s, p + 4); */ } /* else fail (s == NULL) */ break; } case 'f': { /* frontier? */ const char *ep; char previous; p += 2; if (*p != '[') luaL_error(ms->L, "missing '[' after '%%f' in pattern"); ep = classend(ms, p); /* points to what is next */ previous = (s == ms->src_init) ? '\0' : *(s - 1); if (!matchbracketclass(uchar(previous), p, ep - 1) && matchbracketclass(uchar(*s), p, ep - 1)) { p = ep; goto init; /* return match(ms, s, ep); */ } s = NULL; /* match failed */ break; } case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': { /* capture results (%0-%9)? */ s = match_capture(ms, s, uchar(*(p + 1))); if (s != NULL) { p += 2; goto init; /* return match(ms, s, p + 2) */ } break; } default: goto dflt; } break; } default: dflt: { /* pattern class plus optional suffix */ const char *ep = classend(ms, p); /* points to optional suffix */ /* does not match at least once? */ if (!singlematch(ms, s, p, ep)) { if (*ep == '*' || *ep == '?' || *ep == '-') { /* accept empty? */ p = ep + 1; goto init; /* return match(ms, s, ep + 1); */ } else /* '+' or no suffix */ s = NULL; /* fail */ } else { /* matched once */ switch (*ep) { /* handle optional suffix */ case '?': { /* optional */ const char *res; if ((res = match(ms, s + 1, ep + 1)) != NULL) s = res; else { p = ep + 1; goto init; /* else return match(ms, s, ep + 1); */ } break; } case '+': /* 1 or more repetitions */ s++; /* 1 match already done */ /* go through */ case '*': /* 0 or more repetitions */ s = max_expand(ms, s, p, ep); break; case '-': /* 0 or more repetitions (minimum) */ s = min_expand(ms, s, p, ep); break; default: /* no suffix */ s++; p = ep; goto init; /* return match(ms, s + 1, ep); */ } } break; } } } ms->matchdepth++; return s; } static const char *lmemfind (const char *s1, size_t l1, const char *s2, size_t l2) { if (l2 == 0) return s1; /* empty strings are everywhere */ else if (l2 > l1) return NULL; /* avoids a negative 'l1' */ else { const char *init; /* to search for a '*s2' inside 's1' */ l2--; /* 1st char will be checked by 'memchr' */ l1 = l1-l2; /* 's2' cannot be found after that */ while (l1 > 0 && (init = (const char *)memchr(s1, *s2, l1)) != NULL) { init++; /* 1st char is already checked */ if (memcmp(init, s2+1, l2) == 0) return init-1; else { /* correct 'l1' and 's1' to try again */ l1 -= init-s1; s1 = init; } } return NULL; /* not found */ } } static void push_onecapture (MatchState *ms, int i, const char *s, const char *e) { if (i >= ms->level) { if (i == 0) /* ms->level == 0, too */ lua_pushlstring(ms->L, s, e - s); /* add whole match */ else luaL_error(ms->L, "invalid capture index %%%d", i + 1); } else { ptrdiff_t l = ms->capture[i].len; if (l == CAP_UNFINISHED) luaL_error(ms->L, "unfinished capture"); if (l == CAP_POSITION) lua_pushinteger(ms->L, ms->capture[i].init - ms->src_init + 1); else lua_pushlstring(ms->L, ms->capture[i].init, l); } } static int push_captures (MatchState *ms, const char *s, const char *e) { int i; int nlevels = (ms->level == 0 && s) ? 1 : ms->level; luaL_checkstack(ms->L, nlevels, "too many captures"); for (i = 0; i < nlevels; i++) push_onecapture(ms, i, s, e); return nlevels; /* number of strings pushed */ } /* check whether pattern has no special characters */ static int nospecials (const char *p, size_t l) { size_t upto = 0; do { if (strpbrk(p + upto, SPECIALS)) return 0; /* pattern has a special character */ upto += strlen(p + upto) + 1; /* may have more after \0 */ } while (upto <= l); return 1; /* no special chars found */ } static int str_find_aux (lua_State *L, int find) { size_t ls, lp; const char *s = luaL_checklstring(L, 1, &ls); const char *p = luaL_checklstring(L, 2, &lp); lua_Integer init = posrelat(luaL_optinteger(L, 3, 1), ls); if (init < 1) init = 1; else if (init > (lua_Integer)ls + 1) { /* start after string's end? */ lua_pushnil(L); /* cannot find anything */ return 1; } /* explicit request or no special characters? */ if (find && (lua_toboolean(L, 4) || nospecials(p, lp))) { /* do a plain search */ const char *s2 = lmemfind(s + init - 1, ls - (size_t)init + 1, p, lp); if (s2) { lua_pushinteger(L, s2 - s + 1); lua_pushinteger(L, s2 - s + lp); return 2; } } else { MatchState ms; const char *s1 = s + init - 1; int anchor = (*p == '^'); if (anchor) { p++; lp--; /* skip anchor character */ } ms.L = L; ms.matchdepth = MAXCCALLS; ms.src_init = s; ms.src_end = s + ls; ms.p_end = p + lp; do { const char *res; ms.level = 0; lua_assert(ms.matchdepth == MAXCCALLS); if ((res=match(&ms, s1, p)) != NULL) { if (find) { lua_pushinteger(L, s1 - s + 1); /* start */ lua_pushinteger(L, res - s); /* end */ return push_captures(&ms, NULL, 0) + 2; } else return push_captures(&ms, s1, res); } } while (s1++ < ms.src_end && !anchor); } lua_pushnil(L); /* not found */ return 1; } static int str_find (lua_State *L) { return str_find_aux(L, 1); } static int str_match (lua_State *L) { return str_find_aux(L, 0); } static int gmatch_aux (lua_State *L) { MatchState ms; size_t ls, lp; const char *s = lua_tolstring(L, lua_upvalueindex(1), &ls); const char *p = lua_tolstring(L, lua_upvalueindex(2), &lp); const char *src; ms.L = L; ms.matchdepth = MAXCCALLS; ms.src_init = s; ms.src_end = s+ls; ms.p_end = p + lp; for (src = s + (size_t)lua_tointeger(L, lua_upvalueindex(3)); src <= ms.src_end; src++) { const char *e; ms.level = 0; lua_assert(ms.matchdepth == MAXCCALLS); if ((e = match(&ms, src, p)) != NULL) { lua_Integer newstart = e-s; if (e == src) newstart++; /* empty match? go at least one position */ lua_pushinteger(L, newstart); lua_replace(L, lua_upvalueindex(3)); return push_captures(&ms, src, e); } } return 0; /* not found */ } static int gmatch (lua_State *L) { luaL_checkstring(L, 1); luaL_checkstring(L, 2); lua_settop(L, 2); lua_pushinteger(L, 0); lua_pushcclosure(L, gmatch_aux, 3); return 1; } static void add_s (MatchState *ms, luaL_Buffer *b, const char *s, const char *e) { size_t l, i; lua_State *L = ms->L; const char *news = lua_tolstring(L, 3, &l); for (i = 0; i < l; i++) { if (news[i] != L_ESC) luaL_addchar(b, news[i]); else { i++; /* skip ESC */ if (!isdigit(uchar(news[i]))) { if (news[i] != L_ESC) luaL_error(L, "invalid use of '%c' in replacement string", L_ESC); luaL_addchar(b, news[i]); } else if (news[i] == '0') luaL_addlstring(b, s, e - s); else { push_onecapture(ms, news[i] - '1', s, e); luaL_tolstring(L, -1, NULL); /* if number, convert it to string */ lua_remove(L, -2); /* remove original value */ luaL_addvalue(b); /* add capture to accumulated result */ } } } } static void add_value (MatchState *ms, luaL_Buffer *b, const char *s, const char *e, int tr) { lua_State *L = ms->L; switch (tr) { case LUA_TFUNCTION: { int n; lua_pushvalue(L, 3); n = push_captures(ms, s, e); lua_call(L, n, 1); break; } case LUA_TTABLE: { push_onecapture(ms, 0, s, e); lua_gettable(L, 3); break; } default: { /* LUA_TNUMBER or LUA_TSTRING */ add_s(ms, b, s, e); return; } } if (!lua_toboolean(L, -1)) { /* nil or false? */ lua_pop(L, 1); lua_pushlstring(L, s, e - s); /* keep original text */ } else if (!lua_isstring(L, -1)) luaL_error(L, "invalid replacement value (a %s)", luaL_typename(L, -1)); luaL_addvalue(b); /* add result to accumulator */ } static int str_gsub (lua_State *L) { size_t srcl, lp; const char *src = luaL_checklstring(L, 1, &srcl); const char *p = luaL_checklstring(L, 2, &lp); int tr = lua_type(L, 3); lua_Integer max_s = luaL_optinteger(L, 4, srcl + 1); int anchor = (*p == '^'); lua_Integer n = 0; MatchState ms; luaL_Buffer b; luaL_argcheck(L, tr == LUA_TNUMBER || tr == LUA_TSTRING || tr == LUA_TFUNCTION || tr == LUA_TTABLE, 3, "string/function/table expected"); luaL_buffinit(L, &b); if (anchor) { p++; lp--; /* skip anchor character */ } ms.L = L; ms.matchdepth = MAXCCALLS; ms.src_init = src; ms.src_end = src+srcl; ms.p_end = p + lp; while (n < max_s) { const char *e; ms.level = 0; lua_assert(ms.matchdepth == MAXCCALLS); e = match(&ms, src, p); if (e) { n++; add_value(&ms, &b, src, e, tr); } if (e && e>src) /* non empty match? */ src = e; /* skip it */ else if (src < ms.src_end) luaL_addchar(&b, *src++); else break; if (anchor) break; } luaL_addlstring(&b, src, ms.src_end-src); luaL_pushresult(&b); lua_pushinteger(L, n); /* number of substitutions */ return 2; } /* }====================================================== */ /* ** {====================================================== ** STRING FORMAT ** ======================================================= */ /* maximum size of each formatted item (> len(format('%99.99f', -1e308))) */ #define MAX_ITEM 512 /* valid flags in a format specification */ #define FLAGS "-+ #0" /* ** maximum size of each format specification (such as "%-099.99d") ** (+2 for length modifiers; +10 accounts for %99.99x plus margin of error) */ #define MAX_FORMAT (sizeof(FLAGS) + 2 + 10) static void addquoted (lua_State *L, luaL_Buffer *b, int arg) { size_t l; const char *s = luaL_checklstring(L, arg, &l); luaL_addchar(b, '"'); while (l--) { if (*s == '"' || *s == '\\' || *s == '\n') { luaL_addchar(b, '\\'); luaL_addchar(b, *s); } else if (*s == '\0' || iscntrl(uchar(*s))) { char buff[10]; if (!isdigit(uchar(*(s+1)))) sprintf(buff, "\\%d", (int)uchar(*s)); else sprintf(buff, "\\%03d", (int)uchar(*s)); luaL_addstring(b, buff); } else luaL_addchar(b, *s); s++; } luaL_addchar(b, '"'); } static const char *scanformat (lua_State *L, const char *strfrmt, char *form) { const char *p = strfrmt; while (*p != '\0' && strchr(FLAGS, *p) != NULL) p++; /* skip flags */ if ((size_t)(p - strfrmt) >= sizeof(FLAGS)/sizeof(char)) luaL_error(L, "invalid format (repeated flags)"); if (isdigit(uchar(*p))) p++; /* skip width */ if (isdigit(uchar(*p))) p++; /* (2 digits at most) */ if (*p == '.') { p++; if (isdigit(uchar(*p))) p++; /* skip precision */ if (isdigit(uchar(*p))) p++; /* (2 digits at most) */ } if (isdigit(uchar(*p))) luaL_error(L, "invalid format (width or precision too long)"); *(form++) = '%'; memcpy(form, strfrmt, (p - strfrmt + 1) * sizeof(char)); form += p - strfrmt + 1; *form = '\0'; return p; } /* ** add length modifier into formats */ static void addlenmod (char *form, const char *lenmod) { size_t l = strlen(form); size_t lm = strlen(lenmod); char spec = form[l - 1]; strcpy(form + l - 1, lenmod); form[l + lm - 1] = spec; form[l + lm] = '\0'; } static int str_format (lua_State *L) { int top = lua_gettop(L); int arg = 1; size_t sfl; const char *strfrmt = luaL_checklstring(L, arg, &sfl); const char *strfrmt_end = strfrmt+sfl; luaL_Buffer b; luaL_buffinit(L, &b); while (strfrmt < strfrmt_end) { if (*strfrmt != L_ESC) luaL_addchar(&b, *strfrmt++); else if (*++strfrmt == L_ESC) luaL_addchar(&b, *strfrmt++); /* %% */ else { /* format item */ char form[MAX_FORMAT]; /* to store the format ('%...') */ char *buff = luaL_prepbuffsize(&b, MAX_ITEM); /* to put formatted item */ int nb = 0; /* number of bytes in added item */ if (++arg > top) luaL_argerror(L, arg, "no value"); strfrmt = scanformat(L, strfrmt, form); switch (*strfrmt++) { case 'c': { nb = sprintf(buff, form, (int)luaL_checkinteger(L, arg)); break; } case 'd': case 'i': case 'o': case 'u': case 'x': case 'X': { lua_Integer n = luaL_checkinteger(L, arg); addlenmod(form, LUA_INTEGER_FRMLEN); nb = sprintf(buff, form, n); break; } #if defined(LUA_USE_AFORMAT) case 'a': case 'A': #endif case 'e': case 'E': case 'f': case 'g': case 'G': { addlenmod(form, LUA_NUMBER_FRMLEN); nb = sprintf(buff, form, luaL_checknumber(L, arg)); break; } case 'q': { addquoted(L, &b, arg); break; } case 's': { size_t l; const char *s = luaL_tolstring(L, arg, &l); if (!strchr(form, '.') && l >= 100) { /* no precision and string is too long to be formatted; keep original string */ luaL_addvalue(&b); break; } else { nb = sprintf(buff, form, s); lua_pop(L, 1); /* remove result from 'luaL_tolstring' */ break; } } default: { /* also treat cases 'pnLlh' */ return luaL_error(L, "invalid option '%%%c' to 'format'", *(strfrmt - 1)); } } luaL_addsize(&b, nb); } } luaL_pushresult(&b); return 1; } /* }====================================================== */ /* ** {====================================================== ** PACK/UNPACK ** ======================================================= */ /* value used for padding */ #if !defined(LUA_PACKPADBYTE) #define LUA_PACKPADBYTE 0x00 #endif /* maximum size for the binary representation of an integer */ #define MAXINTSIZE 16 /* number of bits in a character */ #define NB CHAR_BIT /* mask for one character (NB 1's) */ #define MC ((1 << NB) - 1) /* size of a lua_Integer */ #define SZINT ((int)sizeof(lua_Integer)) /* dummy union to get native endianness */ static const union { int dummy; char little; /* true iff machine is little endian */ } nativeendian = {1}; /* dummy structure to get native alignment requirements */ struct cD { char c; union { double d; void *p; lua_Integer i; lua_Number n; } u; }; #define MAXALIGN (offsetof(struct cD, u)) /* ** Union for serializing floats */ typedef union Ftypes { float f; double d; lua_Number n; char buff[5 * sizeof(lua_Number)]; /* enough for any float type */ } Ftypes; /* ** information to pack/unpack stuff */ typedef struct Header { lua_State *L; int islittle; int maxalign; } Header; /* ** options for pack/unpack */ typedef enum KOption { Kint, /* signed integers */ Kuint, /* unsigned integers */ Kfloat, /* floating-point numbers */ Kchar, /* fixed-length strings */ Kstring, /* strings with prefixed length */ Kzstr, /* zero-terminated strings */ Kpadding, /* padding */ Kpaddalign, /* padding for alignment */ Knop /* no-op (configuration or spaces) */ } KOption; /* ** Read an integer numeral from string 'fmt' or return 'df' if ** there is no numeral */ static int digit (int c) { return '0' <= c && c <= '9'; } static int getnum (const char **fmt, int df) { if (!digit(**fmt)) /* no number? */ return df; /* return default value */ else { int a = 0; do { a = a*10 + (*((*fmt)++) - '0'); } while (digit(**fmt) && a <= ((int)MAXSIZE - 9)/10); return a; } } /* ** Read an integer numeral and raises an error if it is larger ** than the maximum size for integers. */ static int getnumlimit (Header *h, const char **fmt, int df) { int sz = getnum(fmt, df); if (sz > MAXINTSIZE || sz <= 0) luaL_error(h->L, "integral size (%d) out of limits [1,%d]", sz, MAXINTSIZE); return sz; } /* ** Initialize Header */ static void initheader (lua_State *L, Header *h) { h->L = L; h->islittle = nativeendian.little; h->maxalign = 1; } /* ** Read and classify next option. 'size' is filled with option's size. */ static KOption getoption (Header *h, const char **fmt, int *size) { int opt = *((*fmt)++); *size = 0; /* default */ switch (opt) { case 'b': *size = sizeof(char); return Kint; case 'B': *size = sizeof(char); return Kuint; case 'h': *size = sizeof(short); return Kint; case 'H': *size = sizeof(short); return Kuint; case 'l': *size = sizeof(long); return Kint; case 'L': *size = sizeof(long); return Kuint; case 'j': *size = sizeof(lua_Integer); return Kint; case 'J': *size = sizeof(lua_Integer); return Kuint; case 'T': *size = sizeof(size_t); return Kuint; case 'f': *size = sizeof(float); return Kfloat; case 'd': *size = sizeof(double); return Kfloat; case 'n': *size = sizeof(lua_Number); return Kfloat; case 'i': *size = getnumlimit(h, fmt, sizeof(int)); return Kint; case 'I': *size = getnumlimit(h, fmt, sizeof(int)); return Kuint; case 's': *size = getnumlimit(h, fmt, sizeof(size_t)); return Kstring; case 'c': *size = getnum(fmt, -1); if (*size == -1) luaL_error(h->L, "missing size for format option 'c'"); return Kchar; case 'z': return Kzstr; case 'x': *size = 1; return Kpadding; case 'X': return Kpaddalign; case ' ': break; case '<': h->islittle = 1; break; case '>': h->islittle = 0; break; case '=': h->islittle = nativeendian.little; break; case '!': h->maxalign = getnumlimit(h, fmt, MAXALIGN); break; default: luaL_error(h->L, "invalid format option '%c'", opt); } return Knop; } /* ** Read, classify, and fill other details about the next option. ** 'psize' is filled with option's size, 'notoalign' with its ** alignment requirements. ** Local variable 'size' gets the size to be aligned. (Kpadal option ** always gets its full alignment, other options are limited by ** the maximum alignment ('maxalign'). Kchar option needs no alignment ** despite its size. */ static KOption getdetails (Header *h, size_t totalsize, const char **fmt, int *psize, int *ntoalign) { KOption opt = getoption(h, fmt, psize); int align = *psize; /* usually, alignment follows size */ if (opt == Kpaddalign) { /* 'X' gets alignment from following option */ if (**fmt == '\0' || getoption(h, fmt, &align) == Kchar || align == 0) luaL_argerror(h->L, 1, "invalid next option for option 'X'"); } if (align <= 1 || opt == Kchar) /* need no alignment? */ *ntoalign = 0; else { if (align > h->maxalign) /* enforce maximum alignment */ align = h->maxalign; if ((align & (align - 1)) != 0) /* is 'align' not a power of 2? */ luaL_argerror(h->L, 1, "format asks for alignment not power of 2"); *ntoalign = (align - (int)(totalsize & (align - 1))) & (align - 1); } return opt; } /* ** Pack integer 'n' with 'size' bytes and 'islittle' endianness. ** The final 'if' handles the case when 'size' is larger than ** the size of a Lua integer, correcting the extra sign-extension ** bytes if necessary (by default they would be zeros). */ static void packint (luaL_Buffer *b, lua_Unsigned n, int islittle, int size, int neg) { char *buff = luaL_prepbuffsize(b, size); int i; buff[islittle ? 0 : size - 1] = (char)(n & MC); /* first byte */ for (i = 1; i < size; i++) { n >>= NB; buff[islittle ? i : size - 1 - i] = (char)(n & MC); } if (neg && size > SZINT) { /* negative number need sign extension? */ for (i = SZINT; i < size; i++) /* correct extra bytes */ buff[islittle ? i : size - 1 - i] = (char)MC; } luaL_addsize(b, size); /* add result to buffer */ } /* ** Copy 'size' bytes from 'src' to 'dest', correcting endianness if ** given 'islittle' is different from native endianness. */ static void copywithendian (volatile char *dest, volatile const char *src, int size, int islittle) { if (islittle == nativeendian.little) { while (size-- != 0) *(dest++) = *(src++); } else { dest += size - 1; while (size-- != 0) *(dest--) = *(src++); } } static int str_pack (lua_State *L) { luaL_Buffer b; Header h; const char *fmt = luaL_checkstring(L, 1); /* format string */ int arg = 1; /* current argument to pack */ size_t totalsize = 0; /* accumulate total size of result */ initheader(L, &h); lua_pushnil(L); /* mark to separate arguments from string buffer */ luaL_buffinit(L, &b); while (*fmt != '\0') { int size, ntoalign; KOption opt = getdetails(&h, totalsize, &fmt, &size, &ntoalign); totalsize += ntoalign + size; while (ntoalign-- > 0) luaL_addchar(&b, LUA_PACKPADBYTE); /* fill alignment */ arg++; switch (opt) { case Kint: { /* signed integers */ lua_Integer n = luaL_checkinteger(L, arg); if (size < SZINT) { /* need overflow check? */ lua_Integer lim = (lua_Integer)1 << ((size * NB) - 1); luaL_argcheck(L, -lim <= n && n < lim, arg, "integer overflow"); } packint(&b, (lua_Unsigned)n, h.islittle, size, (n < 0)); break; } case Kuint: { /* unsigned integers */ lua_Integer n = luaL_checkinteger(L, arg); if (size < SZINT) /* need overflow check? */ luaL_argcheck(L, (lua_Unsigned)n < ((lua_Unsigned)1 << (size * NB)), arg, "unsigned overflow"); packint(&b, (lua_Unsigned)n, h.islittle, size, 0); break; } case Kfloat: { /* floating-point options */ volatile Ftypes u; char *buff = luaL_prepbuffsize(&b, size); lua_Number n = luaL_checknumber(L, arg); /* get argument */ if (size == sizeof(u.f)) u.f = (float)n; /* copy it into 'u' */ else if (size == sizeof(u.d)) u.d = (double)n; else u.n = n; /* move 'u' to final result, correcting endianness if needed */ copywithendian(buff, u.buff, size, h.islittle); luaL_addsize(&b, size); break; } case Kchar: { /* fixed-size string */ size_t len; const char *s = luaL_checklstring(L, arg, &len); luaL_argcheck(L, len == (size_t)size, arg, "wrong length"); luaL_addlstring(&b, s, size); break; } case Kstring: { /* strings with length count */ size_t len; const char *s = luaL_checklstring(L, arg, &len); luaL_argcheck(L, size >= (int)sizeof(size_t) || len < ((size_t)1 << (size * NB)), arg, "string length does not fit in given size"); packint(&b, (lua_Unsigned)len, h.islittle, size, 0); /* pack length */ luaL_addlstring(&b, s, len); totalsize += len; break; } case Kzstr: { /* zero-terminated string */ size_t len; const char *s = luaL_checklstring(L, arg, &len); luaL_argcheck(L, strlen(s) == len, arg, "string contains zeros"); luaL_addlstring(&b, s, len); luaL_addchar(&b, '\0'); /* add zero at the end */ totalsize += len + 1; break; } case Kpadding: luaL_addchar(&b, LUA_PACKPADBYTE); /* go through */ case Kpaddalign: case Knop: arg--; /* undo increment */ break; } } luaL_pushresult(&b); return 1; } static int str_packsize (lua_State *L) { Header h; const char *fmt = luaL_checkstring(L, 1); /* format string */ size_t totalsize = 0; /* accumulate total size of result */ initheader(L, &h); while (*fmt != '\0') { int size, ntoalign; KOption opt = getdetails(&h, totalsize, &fmt, &size, &ntoalign); size += ntoalign; /* total space used by option */ luaL_argcheck(L, totalsize <= MAXSIZE - size, 1, "format result too large"); totalsize += size; switch (opt) { case Kstring: /* strings with length count */ case Kzstr: /* zero-terminated string */ luaL_argerror(L, 1, "variable-length format"); break; default: break; } } lua_pushinteger(L, (lua_Integer)totalsize); return 1; } /* ** Unpack an integer with 'size' bytes and 'islittle' endianness. ** If size is smaller than the size of a Lua integer and integer ** is signed, must do sign extension (propagating the sign to the ** higher bits); if size is larger than the size of a Lua integer, ** it must check the unread bytes to see whether they do not cause an ** overflow. */ static lua_Integer unpackint (lua_State *L, const char *str, int islittle, int size, int issigned) { lua_Unsigned res = 0; int i; int limit = (size <= SZINT) ? size : SZINT; for (i = limit - 1; i >= 0; i--) { res <<= NB; res |= (lua_Unsigned)(unsigned char)str[islittle ? i : size - 1 - i]; } if (size < SZINT) { /* real size smaller than lua_Integer? */ if (issigned) { /* needs sign extension? */ lua_Unsigned mask = (lua_Unsigned)1 << (size*NB - 1); res = ((res ^ mask) - mask); /* do sign extension */ } } else if (size > SZINT) { /* must check unread bytes */ int mask = (!issigned || (lua_Integer)res >= 0) ? 0 : MC; for (i = limit; i < size; i++) { if ((unsigned char)str[islittle ? i : size - 1 - i] != mask) luaL_error(L, "%d-byte integer does not fit into Lua Integer", size); } } return (lua_Integer)res; } static int str_unpack (lua_State *L) { Header h; const char *fmt = luaL_checkstring(L, 1); size_t ld; const char *data = luaL_checklstring(L, 2, &ld); size_t pos = (size_t)posrelat(luaL_optinteger(L, 3, 1), ld) - 1; int n = 0; /* number of results */ luaL_argcheck(L, pos <= ld, 3, "initial position out of string"); initheader(L, &h); while (*fmt != '\0') { int size, ntoalign; KOption opt = getdetails(&h, pos, &fmt, &size, &ntoalign); if ((size_t)ntoalign + size > ~pos || pos + ntoalign + size > ld) luaL_argerror(L, 2, "data string too short"); pos += ntoalign; /* skip alignment */ /* stack space for item + next position */ luaL_checkstack(L, 2, "too many results"); n++; switch (opt) { case Kint: case Kuint: { lua_Integer res = unpackint(L, data + pos, h.islittle, size, (opt == Kint)); lua_pushinteger(L, res); break; } case Kfloat: { volatile Ftypes u; lua_Number num; copywithendian(u.buff, data + pos, size, h.islittle); if (size == sizeof(u.f)) num = (lua_Number)u.f; else if (size == sizeof(u.d)) num = (lua_Number)u.d; else num = u.n; lua_pushnumber(L, num); break; } case Kchar: { lua_pushlstring(L, data + pos, size); break; } case Kstring: { size_t len = (size_t)unpackint(L, data + pos, h.islittle, size, 0); luaL_argcheck(L, pos + len + size <= ld, 2, "data string too short"); lua_pushlstring(L, data + pos + size, len); pos += len; /* skip string */ break; } case Kzstr: { size_t len = (int)strlen(data + pos); lua_pushlstring(L, data + pos, len); pos += len + 1; /* skip string plus final '\0' */ break; } case Kpaddalign: case Kpadding: case Knop: n--; /* undo increment */ break; } pos += size; } lua_pushinteger(L, pos + 1); /* next position */ return n + 1; } /* }====================================================== */ static const luaL_Reg strlib[] = { {"byte", str_byte}, {"char", str_char}, {"dump", str_dump}, {"find", str_find}, {"format", str_format}, {"gmatch", gmatch}, {"gsub", str_gsub}, {"len", str_len}, {"lower", str_lower}, {"match", str_match}, {"rep", str_rep}, {"reverse", str_reverse}, {"sub", str_sub}, {"upper", str_upper}, {"pack", str_pack}, {"packsize", str_packsize}, {"unpack", str_unpack}, {NULL, NULL} }; static void createmetatable (lua_State *L) { lua_createtable(L, 0, 1); /* table to be metatable for strings */ lua_pushliteral(L, ""); /* dummy string */ lua_pushvalue(L, -2); /* copy table */ lua_setmetatable(L, -2); /* set table as metatable for strings */ lua_pop(L, 1); /* pop dummy string */ lua_pushvalue(L, -2); /* get string library */ lua_setfield(L, -2, "__index"); /* metatable.__index = string */ lua_pop(L, 1); /* pop metatable */ } /* ** Open string library */ LUAMOD_API int luaopen_string (lua_State *L) { luaL_newlib(L, strlib); createmetatable(L); return 1; } lua-systemd-master/vendor/compat-5.3/ltablib.c000066400000000000000000000232761271662244600215020ustar00rootroot00000000000000/* ** $Id: ltablib.c,v 1.79 2014/11/02 19:19:04 roberto Exp $ ** Library for Table Manipulation ** See Copyright Notice in lua.h */ #define ltablib_c #define LUA_LIB #include "lprefix.h" #include #include #include "lua.h" #include "lauxlib.h" #include "lualib.h" /* ** Structure with table-access functions */ typedef struct { int (*geti) (lua_State *L, int idx, lua_Integer n); void (*seti) (lua_State *L, int idx, lua_Integer n); } TabA; /* ** Check that 'arg' has a table and set access functions in 'ta' to raw ** or non-raw according to the presence of corresponding metamethods. */ static void checktab (lua_State *L, int arg, TabA *ta) { ta->geti = NULL; ta->seti = NULL; if (lua_getmetatable(L, arg)) { lua_pushliteral(L, "__index"); /* 'index' metamethod */ if (lua_rawget(L, -2) != LUA_TNIL) ta->geti = lua_geti; lua_pushliteral(L, "__newindex"); /* 'newindex' metamethod */ if (lua_rawget(L, -3) != LUA_TNIL) ta->seti = lua_seti; lua_pop(L, 3); /* pop metatable plus both metamethods */ } if (ta->geti == NULL || ta->seti == NULL) { luaL_checktype(L, arg, LUA_TTABLE); /* must be table for raw methods */ if (ta->geti == NULL) ta->geti = lua_rawgeti; if (ta->seti == NULL) ta->seti = lua_rawseti; } } #define aux_getn(L,n,ta) (checktab(L, n, ta), luaL_len(L, n)) #if defined(LUA_COMPAT_MAXN) static int maxn (lua_State *L) { lua_Number max = 0; luaL_checktype(L, 1, LUA_TTABLE); lua_pushnil(L); /* first key */ while (lua_next(L, 1)) { lua_pop(L, 1); /* remove value */ if (lua_type(L, -1) == LUA_TNUMBER) { lua_Number v = lua_tonumber(L, -1); if (v > max) max = v; } } lua_pushnumber(L, max); return 1; } #endif static int tinsert (lua_State *L) { TabA ta; lua_Integer e = aux_getn(L, 1, &ta) + 1; /* first empty element */ lua_Integer pos; /* where to insert new element */ switch (lua_gettop(L)) { case 2: { /* called with only 2 arguments */ pos = e; /* insert new element at the end */ break; } case 3: { lua_Integer i; pos = luaL_checkinteger(L, 2); /* 2nd argument is the position */ luaL_argcheck(L, 1 <= pos && pos <= e, 2, "position out of bounds"); for (i = e; i > pos; i--) { /* move up elements */ (*ta.geti)(L, 1, i - 1); (*ta.seti)(L, 1, i); /* t[i] = t[i - 1] */ } break; } default: { return luaL_error(L, "wrong number of arguments to 'insert'"); } } (*ta.seti)(L, 1, pos); /* t[pos] = v */ return 0; } static int tremove (lua_State *L) { TabA ta; lua_Integer size = aux_getn(L, 1, &ta); lua_Integer pos = luaL_optinteger(L, 2, size); if (pos != size) /* validate 'pos' if given */ luaL_argcheck(L, 1 <= pos && pos <= size + 1, 1, "position out of bounds"); (*ta.geti)(L, 1, pos); /* result = t[pos] */ for ( ; pos < size; pos++) { (*ta.geti)(L, 1, pos + 1); (*ta.seti)(L, 1, pos); /* t[pos] = t[pos + 1] */ } lua_pushnil(L); (*ta.seti)(L, 1, pos); /* t[pos] = nil */ return 1; } static int tmove (lua_State *L) { TabA ta; lua_Integer f = luaL_checkinteger(L, 2); lua_Integer e = luaL_checkinteger(L, 3); lua_Integer t = luaL_checkinteger(L, 4); int tt = !lua_isnoneornil(L, 5) ? 5 : 1; /* destination table */ /* the following restriction avoids several problems with overflows */ luaL_argcheck(L, f > 0, 2, "initial position must be positive"); if (e >= f) { /* otherwise, nothing to move */ lua_Integer n, i; ta.geti = (luaL_getmetafield(L, 1, "__index") == LUA_TNIL) ? (luaL_checktype(L, 1, LUA_TTABLE), lua_rawgeti) : lua_geti; ta.seti = (luaL_getmetafield(L, tt, "__newindex") == LUA_TNIL) ? (luaL_checktype(L, tt, LUA_TTABLE), lua_rawseti) : lua_seti; n = e - f + 1; /* number of elements to move */ if (t > f) { for (i = n - 1; i >= 0; i--) { (*ta.geti)(L, 1, f + i); (*ta.seti)(L, tt, t + i); } } else { for (i = 0; i < n; i++) { (*ta.geti)(L, 1, f + i); (*ta.seti)(L, tt, t + i); } } } lua_pushvalue(L, tt); /* return "to table" */ return 1; } static void addfield (lua_State *L, luaL_Buffer *b, TabA *ta, lua_Integer i) { (*ta->geti)(L, 1, i); if (!lua_isstring(L, -1)) luaL_error(L, "invalid value (%s) at index %d in table for 'concat'", luaL_typename(L, -1), i); luaL_addvalue(b); } static int tconcat (lua_State *L) { TabA ta; luaL_Buffer b; size_t lsep; lua_Integer i, last; const char *sep = luaL_optlstring(L, 2, "", &lsep); checktab(L, 1, &ta); i = luaL_optinteger(L, 3, 1); last = luaL_opt(L, luaL_checkinteger, 4, luaL_len(L, 1)); luaL_buffinit(L, &b); for (; i < last; i++) { addfield(L, &b, &ta, i); luaL_addlstring(&b, sep, lsep); } if (i == last) /* add last value (if interval was not empty) */ addfield(L, &b, &ta, i); luaL_pushresult(&b); return 1; } /* ** {====================================================== ** Pack/unpack ** ======================================================= */ static int pack (lua_State *L) { int i; int n = lua_gettop(L); /* number of elements to pack */ lua_createtable(L, n, 1); /* create result table */ lua_insert(L, 1); /* put it at index 1 */ for (i = n; i >= 1; i--) /* assign elements */ lua_rawseti(L, 1, i); lua_pushinteger(L, n); lua_setfield(L, 1, "n"); /* t.n = number of elements */ return 1; /* return table */ } static int unpack (lua_State *L) { TabA ta; lua_Integer i, e; lua_Unsigned n; checktab(L, 1, &ta); i = luaL_optinteger(L, 2, 1); e = luaL_opt(L, luaL_checkinteger, 3, luaL_len(L, 1)); if (i > e) return 0; /* empty range */ n = (lua_Unsigned)e - i; /* number of elements minus 1 (avoid overflows) */ if (n >= (unsigned int)INT_MAX || !lua_checkstack(L, (int)(++n))) return luaL_error(L, "too many results to unpack"); do { /* must have at least one element */ (*ta.geti)(L, 1, i); /* push arg[i..e] */ } while (i++ < e); return (int)n; } /* }====================================================== */ /* ** {====================================================== ** Quicksort ** (based on 'Algorithms in MODULA-3', Robert Sedgewick; ** Addison-Wesley, 1993.) ** ======================================================= */ static void set2 (lua_State *L, TabA *ta, int i, int j) { (*ta->seti)(L, 1, i); (*ta->seti)(L, 1, j); } static int sort_comp (lua_State *L, int a, int b) { if (!lua_isnil(L, 2)) { /* function? */ int res; lua_pushvalue(L, 2); lua_pushvalue(L, a-1); /* -1 to compensate function */ lua_pushvalue(L, b-2); /* -2 to compensate function and 'a' */ lua_call(L, 2, 1); res = lua_toboolean(L, -1); lua_pop(L, 1); return res; } else /* a < b? */ return lua_compare(L, a, b, LUA_OPLT); } static void auxsort (lua_State *L, TabA *ta, int l, int u) { while (l < u) { /* for tail recursion */ int i, j; /* sort elements a[l], a[(l+u)/2] and a[u] */ (*ta->geti)(L, 1, l); (*ta->geti)(L, 1, u); if (sort_comp(L, -1, -2)) /* a[u] < a[l]? */ set2(L, ta, l, u); /* swap a[l] - a[u] */ else lua_pop(L, 2); if (u-l == 1) break; /* only 2 elements */ i = (l+u)/2; (*ta->geti)(L, 1, i); (*ta->geti)(L, 1, l); if (sort_comp(L, -2, -1)) /* a[i]geti)(L, 1, u); if (sort_comp(L, -1, -2)) /* a[u]geti)(L, 1, i); /* Pivot */ lua_pushvalue(L, -1); (*ta->geti)(L, 1, u-1); set2(L, ta, i, u-1); /* a[l] <= P == a[u-1] <= a[u], only need to sort from l+1 to u-2 */ i = l; j = u-1; for (;;) { /* invariant: a[l..i] <= P <= a[j..u] */ /* repeat ++i until a[i] >= P */ while ((*ta->geti)(L, 1, ++i), sort_comp(L, -1, -2)) { if (i>=u) luaL_error(L, "invalid order function for sorting"); lua_pop(L, 1); /* remove a[i] */ } /* repeat --j until a[j] <= P */ while ((*ta->geti)(L, 1, --j), sort_comp(L, -3, -1)) { if (j<=l) luaL_error(L, "invalid order function for sorting"); lua_pop(L, 1); /* remove a[j] */ } if (jgeti)(L, 1, u-1); (*ta->geti)(L, 1, i); set2(L, ta, u-1, i); /* swap pivot (a[u-1]) with a[i] */ /* a[l..i-1] <= a[i] == P <= a[i+1..u] */ /* adjust so that smaller half is in [j..i] and larger one in [l..u] */ if (i-l < u-i) { j=l; i=i-1; l=i+2; } else { j=i+1; i=u; u=j-2; } auxsort(L, ta, j, i); /* call recursively the smaller one */ } /* repeat the routine for the larger one */ } static int sort (lua_State *L) { TabA ta; int n = (int)aux_getn(L, 1, &ta); luaL_checkstack(L, 50, ""); /* assume array is smaller than 2^50 */ if (!lua_isnoneornil(L, 2)) /* is there a 2nd argument? */ luaL_checktype(L, 2, LUA_TFUNCTION); lua_settop(L, 2); /* make sure there are two arguments */ auxsort(L, &ta, 1, n); return 0; } /* }====================================================== */ static const luaL_Reg tab_funcs[] = { {"concat", tconcat}, #if defined(LUA_COMPAT_MAXN) {"maxn", maxn}, #endif {"insert", tinsert}, {"pack", pack}, {"unpack", unpack}, {"remove", tremove}, {"move", tmove}, {"sort", sort}, {NULL, NULL} }; LUAMOD_API int luaopen_table (lua_State *L) { luaL_newlib(L, tab_funcs); #if defined(LUA_COMPAT_UNPACK) /* _G.unpack = table.unpack */ lua_getfield(L, -1, "unpack"); lua_setglobal(L, "unpack"); #endif return 1; } lua-systemd-master/vendor/compat-5.3/lutf8lib.c000066400000000000000000000155301271662244600216140ustar00rootroot00000000000000/* ** $Id: lutf8lib.c,v 1.13 2014/11/02 19:19:04 roberto Exp $ ** Standard library for UTF-8 manipulation ** See Copyright Notice in lua.h */ #define lutf8lib_c #define LUA_LIB #include "lprefix.h" #include #include #include #include "lua.h" #include "lauxlib.h" #include "lualib.h" #define MAXUNICODE 0x10FFFF #define iscont(p) ((*(p) & 0xC0) == 0x80) /* from strlib */ /* translate a relative string position: negative means back from end */ static lua_Integer u_posrelat (lua_Integer pos, size_t len) { if (pos >= 0) return pos; else if (0u - (size_t)pos > len) return 0; else return (lua_Integer)len + pos + 1; } /* ** Decode one UTF-8 sequence, returning NULL if byte sequence is invalid. */ static const char *utf8_decode (const char *o, int *val) { static unsigned int limits[] = {0xFF, 0x7F, 0x7FF, 0xFFFF}; const unsigned char *s = (const unsigned char *)o; unsigned int c = s[0]; unsigned int res = 0; /* final result */ if (c < 0x80) /* ascii? */ res = c; else { int count = 0; /* to count number of continuation bytes */ while (c & 0x40) { /* still have continuation bytes? */ int cc = s[++count]; /* read next byte */ if ((cc & 0xC0) != 0x80) /* not a continuation byte? */ return NULL; /* invalid byte sequence */ res = (res << 6) | (cc & 0x3F); /* add lower 6 bits from cont. byte */ c <<= 1; /* to test next bit */ } res |= ((c & 0x7F) << (count * 5)); /* add first byte */ if (count > 3 || res > MAXUNICODE || res <= limits[count]) return NULL; /* invalid byte sequence */ s += count; /* skip continuation bytes read */ } if (val) *val = res; return (const char *)s + 1; /* +1 to include first byte */ } /* ** utf8len(s [, i [, j]]) --> number of characters that start in the ** range [i,j], or nil + current position if 's' is not well formed in ** that interval */ static int utflen (lua_State *L) { int n = 0; size_t len; const char *s = luaL_checklstring(L, 1, &len); lua_Integer posi = u_posrelat(luaL_optinteger(L, 2, 1), len); lua_Integer posj = u_posrelat(luaL_optinteger(L, 3, -1), len); luaL_argcheck(L, 1 <= posi && --posi <= (lua_Integer)len, 2, "initial position out of string"); luaL_argcheck(L, --posj < (lua_Integer)len, 3, "final position out of string"); while (posi <= posj) { const char *s1 = utf8_decode(s + posi, NULL); if (s1 == NULL) { /* conversion error? */ lua_pushnil(L); /* return nil ... */ lua_pushinteger(L, posi + 1); /* ... and current position */ return 2; } posi = s1 - s; n++; } lua_pushinteger(L, n); return 1; } /* ** codepoint(s, [i, [j]]) -> returns codepoints for all characters ** that start in the range [i,j] */ static int codepoint (lua_State *L) { size_t len; const char *s = luaL_checklstring(L, 1, &len); lua_Integer posi = u_posrelat(luaL_optinteger(L, 2, 1), len); lua_Integer pose = u_posrelat(luaL_optinteger(L, 3, posi), len); int n; const char *se; luaL_argcheck(L, posi >= 1, 2, "out of range"); luaL_argcheck(L, pose <= (lua_Integer)len, 3, "out of range"); if (posi > pose) return 0; /* empty interval; return no values */ n = (int)(pose - posi + 1); if (posi + n <= pose) /* (lua_Integer -> int) overflow? */ return luaL_error(L, "string slice too long"); luaL_checkstack(L, n, "string slice too long"); n = 0; se = s + pose; for (s += posi - 1; s < se;) { int code; s = utf8_decode(s, &code); if (s == NULL) return luaL_error(L, "invalid UTF-8 code"); lua_pushinteger(L, code); n++; } return n; } static void pushutfchar (lua_State *L, int arg) { lua_Integer code = luaL_checkinteger(L, arg); luaL_argcheck(L, 0 <= code && code <= MAXUNICODE, arg, "value out of range"); lua_pushfstring(L, "%U", (long)code); } /* ** utfchar(n1, n2, ...) -> char(n1)..char(n2)... */ static int utfchar (lua_State *L) { int n = lua_gettop(L); /* number of arguments */ if (n == 1) /* optimize common case of single char */ pushutfchar(L, 1); else { int i; luaL_Buffer b; luaL_buffinit(L, &b); for (i = 1; i <= n; i++) { pushutfchar(L, i); luaL_addvalue(&b); } luaL_pushresult(&b); } return 1; } /* ** offset(s, n, [i]) -> index where n-th character counting from ** position 'i' starts; 0 means character at 'i'. */ static int byteoffset (lua_State *L) { size_t len; const char *s = luaL_checklstring(L, 1, &len); lua_Integer n = luaL_checkinteger(L, 2); lua_Integer posi = (n >= 0) ? 1 : len + 1; posi = u_posrelat(luaL_optinteger(L, 3, posi), len); luaL_argcheck(L, 1 <= posi && --posi <= (lua_Integer)len, 3, "position out of range"); if (n == 0) { /* find beginning of current byte sequence */ while (posi > 0 && iscont(s + posi)) posi--; } else { if (iscont(s + posi)) luaL_error(L, "initial position is a continuation byte"); if (n < 0) { while (n < 0 && posi > 0) { /* move back */ do { /* find beginning of previous character */ posi--; } while (posi > 0 && iscont(s + posi)); n++; } } else { n--; /* do not move for 1st character */ while (n > 0 && posi < (lua_Integer)len) { do { /* find beginning of next character */ posi++; } while (iscont(s + posi)); /* (cannot pass final '\0') */ n--; } } } if (n == 0) /* did it find given character? */ lua_pushinteger(L, posi + 1); else /* no such character */ lua_pushnil(L); return 1; } static int iter_aux (lua_State *L) { size_t len; const char *s = luaL_checklstring(L, 1, &len); lua_Integer n = lua_tointeger(L, 2) - 1; if (n < 0) /* first iteration? */ n = 0; /* start from here */ else if (n < (lua_Integer)len) { n++; /* skip current byte */ while (iscont(s + n)) n++; /* and its continuations */ } if (n >= (lua_Integer)len) return 0; /* no more codepoints */ else { int code; const char *next = utf8_decode(s + n, &code); if (next == NULL || iscont(next)) return luaL_error(L, "invalid UTF-8 code"); lua_pushinteger(L, n + 1); lua_pushinteger(L, code); return 2; } } static int iter_codes (lua_State *L) { luaL_checkstring(L, 1); lua_pushcfunction(L, iter_aux); lua_pushvalue(L, 1); lua_pushinteger(L, 0); return 3; } /* pattern to match a single UTF-8 character */ #define UTF8PATT "[\0-\x7F\xC2-\xF4][\x80-\xBF]*" static struct luaL_Reg funcs[] = { {"offset", byteoffset}, {"codepoint", codepoint}, {"char", utfchar}, {"len", utflen}, {"codes", iter_codes}, /* placeholders */ {"charpattern", NULL}, {NULL, NULL} }; LUAMOD_API int luaopen_utf8 (lua_State *L) { luaL_newlib(L, funcs); lua_pushliteral(L, UTF8PATT); lua_setfield(L, -2, "charpattern"); return 1; } lua-systemd-master/vendor/compat-5.3/rockspecs/000077500000000000000000000000001271662244600217075ustar00rootroot00000000000000lua-systemd-master/vendor/compat-5.3/rockspecs/compat53-0.1-1.rockspec000066400000000000000000000016721271662244600255350ustar00rootroot00000000000000package = "compat53" version = "0.1-1" source = { url = "https://github.com/keplerproject/lua-compat-5.3/archive/v0.1.zip", dir = "lua-compat-5.3-0.1", } description = { summary = "Compatibility module providing Lua-5.3-style APIs for Lua 5.2 and 5.1", detailed = [[ This is a small module that aims to make it easier to write Lua code in a Lua-5.3-style that runs on Lua 5.3, 5.2, and 5.1. It does *not* make Lua 5.2 (or even 5.1) entirely compatible with Lua 5.3, but it brings the API closer to that of Lua 5.3. ]], homepage = "https://github.com/keplerproject/lua-compat-5.3", license = "MIT" } dependencies = { "lua >= 5.1, < 5.4", --"struct" -- make Roberto's struct module optional } build = { type = "builtin", modules = { ["compat53"] = "compat53.lua", ["compat53.utf8"] = "lutf8lib.c", ["compat53.table"] = "ltablib.c", ["compat53.string"] = "lstrlib.c", } } lua-systemd-master/vendor/compat-5.3/rockspecs/compat53-scm-0.rockspec000066400000000000000000000016771271662244600260250ustar00rootroot00000000000000package = "compat53" version = "scm-0" source = { url = "https://github.com/keplerproject/lua-compat-5.3/archive/master.zip", dir = "lua-compat-5.3-master", } description = { summary = "Compatibility module providing Lua-5.3-style APIs for Lua 5.2 and 5.1", detailed = [[ This is a small module that aims to make it easier to write Lua code in a Lua-5.3-style that runs on Lua 5.3, 5.2, and 5.1. It does *not* make Lua 5.2 (or even 5.1) entirely compatible with Lua 5.3, but it brings the API closer to that of Lua 5.3. ]], homepage = "https://github.com/keplerproject/lua-compat-5.3", license = "MIT" } dependencies = { "lua >= 5.1, < 5.4", --"struct" -- make Roberto's struct module optional } build = { type = "builtin", modules = { ["compat53"] = "compat53.lua", ["compat53.utf8"] = "lutf8lib.c", ["compat53.table"] = "ltablib.c", ["compat53.string"] = "lstrlib.c", } } lua-systemd-master/vendor/compat-5.3/tests/000077500000000000000000000000001271662244600210555ustar00rootroot00000000000000lua-systemd-master/vendor/compat-5.3/tests/test.lua000077500000000000000000000453161271662244600225530ustar00rootroot00000000000000#!/usr/bin/env lua local F, tproxy, writefile, noprint, ___ do local type, unpack = type, table.unpack or unpack local assert, io = assert, io function F(...) local args, n = { ... }, select('#', ...) for i = 1, n do local t = type(args[i]) if t ~= "string" and t ~= "number" and t ~= "boolean" then args[i] = t end end return unpack(args, 1, n) end function tproxy(t) return setmetatable({}, { __index = t, __newindex = t, __len = function() return #t end, }), t end function writefile(name, contents, bin) local f = assert(io.open(name, bin and "wb" or "w")) f:write(contents) f:close() end function noprint() end local sep = ("="):rep(70) function ___() print(sep) end end local V = _VERSION:gsub("^.*(%d+)%.(%d+)$", "%1%2") if jit then V = "jit" end print( "testing Lua API ..." ) package.path = "../?.lua;"..package.path package.cpath = "./?-"..V..".so;./?-"..V..".dll;./?.so;./?.dll" require("compat53") ___'' do local t = setmetatable( {}, { __index = { 1, false, "three" } } ) for i,v in ipairs(t) do print("ipairs", i, v) end end ___'' do local p, t = tproxy{ "a", "b", "c" } print("table.concat", table.concat(p)) print("table.concat", table.concat(p, ",", 2)) print("table.concat", table.concat(p, ".", 1, 2)) print("table.concat", table.concat(t)) print("table.concat", table.concat(t, ",", 2)) print("table.concat", table.concat(t, ".", 1, 2)) end ___'' do local p, t = tproxy{ "a", "b", "c" } table.insert(p, "d") print("table.insert", next(p), t[4]) table.insert(p, 1, "z") print("table.insert", next(p), t[1], t[2]) table.insert(p, 2, "y") print("table.insert", next(p), t[1], t[2], p[3]) t = { "a", "b", "c" } table.insert(t, "d") print("table.insert", t[1], t[2], t[3], t[4]) table.insert(t, 1, "z") print("table.insert", t[1], t[2], t[3], t[4], t[5]) table.insert(t, 2, "y") print("table.insert", t[1], t[2], t[3], t[4], t[5]) end ___'' do local ps, s = tproxy{ "a", "b", "c", "d" } local pd, d = tproxy{ "A", "B", "C", "D" } table.move(ps, 1, 4, 1, pd) print("table.move", next(pd), d[1], d[2], d[3], d[4]) pd, d = tproxy{ "A", "B", "C", "D" } table.move(ps, 2, 4, 1, pd) print("table.move", next(pd), d[1], d[2], d[3], d[4]) pd, d = tproxy{ "A", "B", "C", "D" } table.move(ps, 2, 3, 4, pd) print("table.move", next(pd), d[1], d[2], d[3], d[4], d[5]) table.move(ps, 2, 4, 1) print("table.move", next(ps), s[1], s[2], s[3], s[4]) ps, s = tproxy{ "a", "b", "c", "d" } table.move(ps, 2, 3, 4) print("table.move", next(ps), s[1], s[2], s[3], s[4], s[5]) s = { "a", "b", "c", "d" } d = { "A", "B", "C", "D" } table.move(s, 1, 4, 1, d) print("table.move", d[1], d[2], d[3], d[4]) d = { "A", "B", "C", "D" } table.move(s, 2, 4, 1, d) print("table.move", d[1], d[2], d[3], d[4]) d = { "A", "B", "C", "D" } table.move(s, 2, 3, 4, d) print("table.move", d[1], d[2], d[3], d[4], d[5]) table.move(s, 2, 4, 1) print("table.move", s[1], s[2], s[3], s[4]) s = { "a", "b", "c", "d" } table.move(s, 2, 3, 4) print("table.move", s[1], s[2], s[3], s[4], s[5]) end ___'' do local p, t = tproxy{ "a", "b", "c", "d", "e" } print("table.remove", table.remove(p)) print("table.remove", next(p), t[1], t[2], t[3], t[4], t[5]) print("table.remove", table.remove(p, 1)) print("table.remove", next(p), t[1], t[2], t[3], t[4]) print("table.remove", table.remove(p, 2)) print("table.remove", next(p), t[1], t[2], t[3]) print("table.remove", table.remove(p, 3)) print("table.remove", next(p), t[1], t[2], t[3]) p, t = tproxy{} print("table.remove", table.remove(p)) print("table.remove", next(p), next(t)) t = { "a", "b", "c", "d", "e" } print("table.remove", table.remove(t)) print("table.remove", t[1], t[2], t[3], t[4], t[5]) print("table.remove", table.remove(t, 1)) print("table.remove", t[1], t[2], t[3], t[4]) print("table.remove", table.remove(t, 2)) print("table.remove", t[1], t[2], t[3]) print("table.remove", table.remove(t, 3)) print("table.remove", t[1], t[2], t[3]) t = {} print("table.remove", table.remove(t)) print("table.remove", next(t)) end ___'' do local p, t = tproxy{ 3, 1, 5, 2, 8, 5, 2, 9, 7, 4 } table.sort(p) print("table.sort", next(p)) for i,v in ipairs(t) do print("table.sort", i, v) end table.sort(p) print("table.sort", next(p)) for i,v in ipairs(t) do print("table.sort", i, v) end p, t = tproxy{ 9, 8, 7, 6, 5, 4, 3, 2, 1 } table.sort(p) print("table.sort", next(p)) for i,v in ipairs(t) do print("table.sort", i, v) end table.sort(p, function(a, b) return a > b end) print("table.sort", next(p)) for i,v in ipairs(t) do print("table.sort", i, v) end p, t = tproxy{ 1, 1, 1, 1, 1 } print("table.sort", next(p)) for i,v in ipairs(t) do print("table.sort", i, v) end t = { 3, 1, 5, 2, 8, 5, 2, 9, 7, 4 } table.sort(t) for i,v in ipairs(t) do print("table.sort", i, v) end table.sort(t, function(a, b) return a > b end) for i,v in ipairs(t) do print("table.sort", i, v) end end ___'' do local p, t = tproxy{ "a", "b", "c" } print("table.unpack", table.unpack(p)) print("table.unpack", table.unpack(p, 2)) print("table.unpack", table.unpack(p, 1, 2)) print("table.unpack", table.unpack(t)) print("table.unpack", table.unpack(t, 2)) print("table.unpack", table.unpack(t, 1, 2)) end ___'' print("math.maxinteger", math.maxinteger+1 > math.maxinteger) print("math.mininteger", math.mininteger-1 < math.mininteger) ___'' print("math.tointeger", math.tointeger(0)) print("math.tointeger", math.tointeger(math.pi)) print("math.tointeger", math.tointeger("hello")) print("math.tointeger", math.tointeger(math.maxinteger+2.0)) print("math.tointeger", math.tointeger(math.mininteger*2.0)) ___'' print("math.type", math.type(0)) print("math.type", math.type(math.pi)) print("math.type", math.type("hello")) ___'' print("math.ult", math.ult(1, 2), math.ult(2, 1)) print("math.ult", math.ult(-1, 2), math.ult(2, -1)) print("math.ult", math.ult(-1, -2), math.ult(-2, -1)) print("math.ult", pcall(math.ult, "x", 2)) print("math.ult", pcall(math.ult, 1, 2.1)) ___'' print("testing Lua API for Lua 5.1 ...") ___'' print("debug.getuservalue()", F(debug.getuservalue(false))) print("debug.setuservalue()", pcall(function() debug.setuservalue(false, {}) end)) print("debug.setmetatable()", F(debug.setmetatable({}, {}))) ___'' do local t = setmetatable({}, { __pairs = function() return pairs({ a = "a" }) end, }) for k,v in pairs(t) do print("pairs()", k, v) end end ___'' do local code = "print('hello world')\n" local badcode = "print('blub\n" print("load()", pcall(function() load(true) end)) print("load()", F(load(badcode))) print("load()", F(load(code))) print("load()", F(load(code, "[L]"))) print("load()", F(load(code, "[L]", "b"))) print("load()", F(load(code, "[L]", "t"))) print("load()", F(load(code, "[L]", "bt"))) local f = load(code, "[L]", "bt", {}) print("load()", pcall(f)) f = load(code, "[L]", "bt", { print = noprint }) print("load()", pcall(f)) local bytecode = string.dump(f) print("load()", F(load(bytecode))) print("load()", F(load(bytecode, "[L]"))) print("load()", F(load(bytecode, "[L]", "b"))) print("load()", F(load(bytecode, "[L]", "t"))) print("load()", F(load(bytecode, "[L]", "bt"))) f = load(bytecode, "[L]", "bt", {}) print("load()", pcall(f)) f = load(bytecode, "[L]", "bt", { print = noprint }) print("load()", pcall(f)) local function make_loader(code) local mid = math.floor( #code/2 ) local array = { code:sub(1, mid), code:sub(mid+1) } local i = 0 return function() i = i + 1 return array[i] end end print("load()", F(load(make_loader(badcode)))) print("load()", F(load(make_loader(code)))) print("load()", F(load(make_loader(code), "[L]"))) print("load()", F(load(make_loader(code), "[L]", "b"))) print("load()", F(load(make_loader(code), "[L]", "t"))) print("load()", F(load(make_loader(code), "[L]", "bt"))) f = load(make_loader(code), "[L]", "bt", {}) print("load()", pcall(f)) f = load(make_loader(code), "[L]", "bt", { print = noprint }) print("load()", pcall(f)) print("load()", F(load(make_loader(bytecode)))) print("load()", F(load(make_loader(bytecode), "[L]"))) print("load()", F(load(make_loader(bytecode), "[L]", "b"))) print("load()", F(load(make_loader(bytecode), "[L]", "t"))) print("load()", F(load(make_loader(bytecode), "[L]", "bt"))) f = load(make_loader(bytecode), "[L]", "bt", {}) print("load()", pcall(f)) f = load(make_loader(bytecode), "[L]", "bt", { print = noprint }) print("load()", pcall(f)) writefile("good.lua", code) writefile("bad.lua", badcode) writefile("good.luac", bytecode, true) print("loadfile()", F(loadfile("bad.lua"))) print("loadfile()", F(loadfile("good.lua"))) print("loadfile()", F(loadfile("good.lua", "b"))) print("loadfile()", F(loadfile("good.lua", "t"))) print("loadfile()", F(loadfile("good.lua", "bt"))) f = loadfile("good.lua", "bt", {}) print("loadfile()", pcall(f)) f = loadfile("good.lua", "bt", { print = noprint }) print("loadfile()", pcall(f)) print("loadfile()", F(loadfile("good.luac"))) print("loadfile()", F(loadfile("good.luac", "b"))) print("loadfile()", F(loadfile("good.luac", "t"))) print("loadfile()", F(loadfile("good.luac", "bt"))) f = loadfile("good.luac", "bt", {}) print("loadfile()", pcall(f)) f = loadfile("good.luac", "bt", { print = noprint }) print("loadfile()", pcall(f)) os.remove("good.lua") os.remove("bad.lua") os.remove("good.luac") end ___'' do local function func(throw) if throw then error("argh") else return 1, 2, 3 end end local function tb(err) return "|"..err.."|" end print("xpcall()", xpcall(func, debug.traceback, false)) print("xpcall()", xpcall(func, debug.traceback, true)) print("xpcall()", xpcall(func, tb, true)) local function func2(cb) print("xpcall()", xpcall(cb, debug.traceback, "str")) end local function func3(cb) print("pcall()", pcall(cb, "str")) end local function cb(arg) coroutine.yield(2) return arg end local c = coroutine.wrap(func2) print("xpcall()", c(cb)) print("xpcall()", c()) local c = coroutine.wrap(func3) print("pcall()", c(cb)) print("pcall()", c()) end ___'' do local t = setmetatable({ 1 }, { __len = function() return 5 end }) print("rawlen()", rawlen(t), rawlen("123")) end ___'' print("os.execute()", os.execute("exit 1")) io.flush() print("os.execute()", os.execute("echo 'hello world!'")) io.flush() print("os.execute()", os.execute("no_such_file")) ___'' do local t = table.pack("a", nil, "b", nil) print("table.(un)pack()", t.n, table.unpack(t, 1, t.n)) end ___'' do print("coroutine.running()", F(coroutine.wrap(function() return coroutine.running() end)())) print("coroutine.running()", F(coroutine.running())) local main_co, co1, co2 = coroutine.running() -- coroutine.yield print("coroutine.yield()", pcall(function() coroutine.yield(1, 2, 3) end)) print("coroutine.yield()", coroutine.wrap(function() coroutine.yield(1, 2, 3) end)()) print("coroutine.resume()", coroutine.resume(main_co, 1, 2, 3)) co1 = coroutine.create(function(a, b, c) print("coroutine.resume()", a, b, c) return a, b, c end) print("coroutine.resume()", coroutine.resume(co1, 1, 2, 3)) co1 = coroutine.create(function() print("coroutine.status()", "[co1] main is", coroutine.status(main_co)) print("coroutine.status()", "[co1] co2 is", coroutine.status(co2)) end) co2 = coroutine.create(function() print("coroutine.status()", "[co2] main is", coroutine.status(main_co)) print("coroutine.status()", "[co2] co2 is", coroutine.status(co2)) coroutine.yield() coroutine.resume(co1) end) print("coroutine.status()", coroutine.status(main_co)) print("coroutine.status()", coroutine.status(co2)) coroutine.resume(co2) print("coroutine.status()", F(coroutine.status(co2))) coroutine.resume(co2) print("coroutine.status()", F(coroutine.status(co2))) end ___'' print("math.log()", math.log(1000)) print("math.log()", math.log(1000, 10)) ___'' do local path, prefix = "./?.lua;?/init.lua;../?.lua", "package.searchpath()" print(prefix, package.searchpath("no.such.module", path)) print(prefix, package.searchpath("no.such.module", "")) print(prefix, package.searchpath("compat52", path)) print(prefix, package.searchpath("no:such:module", path, ":", "|")) end ___'' do local function mod_func() return {} end local function my_searcher(name) if name == "my.module" then print("package.searchers", "my.module found") return mod_func end end local function my_searcher2(name) if name == "my.module" then print("package.searchers", "my.module found 2") return mod_func end end table.insert(package.searchers, my_searcher) require("my.module") package.loaded["my.module"] = nil local new_s = { my_searcher2 } for i,f in ipairs(package.searchers) do new_s[i+1] = f end package.searchers = new_s require("my.module") end ___'' do print("string.find()", ("abc\0abc\0abc"):find("[^a\0]+")) print("string.find()", ("abc\0abc\0abc"):find("%w+\0", 5)) for x in ("abc\0def\0ghi"):gmatch("[^\0]+") do print("string.gmatch()", x) end for x in ("abc\0def\0ghi"):gmatch("%w*\0") do print("string.gmatch()", #x) end print("string.gsub()", ("abc\0def\0ghi"):gsub("[\0]", "X")) print("string.gsub()", ("abc\0def\0ghi"):gsub("%w*\0", "X")) print("string.gsub()", ("abc\0def\0ghi"):gsub("%A", "X")) print("string.match()", ("abc\0abc\0abc"):match("([^\0a]+)")) print("string.match()", #("abc\0abc\0abc"):match(".*\0")) print("string.rep()", string.rep("a", 0)) print("string.rep()", string.rep("b", 1)) print("string.rep()", string.rep("c", 4)) print("string.rep()", string.rep("a", 0, "|")) print("string.rep()", string.rep("b", 1, "|")) print("string.rep()", string.rep("c", 4, "|")) local _tostring = tostring function tostring(v) if type(v) == "number" then return "(".._tostring(v)..")" else return _tostring(v) end end print("string.format()", string.format("%q", "\"\\\0000\0010\r0\n0\t0\"")) print("string.format()", string.format("%12.3fx%%sxx%.6s", 3.1, {})) print("string.format()", string.format("%-3f %%%s %%s", 3.1, true)) print("string.format()", string.format("% 3.2g %%d %%%s", 3.1, nil)) print("string.format()", string.format("%+3d %%d %%%%%10.6s", 3, io.stdout)) print("string.format()", pcall(function() print("string.format()", string.format("%d %%s", {})) end)) tostring = _tostring end ___'' do print("io.write()", io.type(io.write("hello world\n"))) local f = assert(io.tmpfile()) print("file:write()", io.type(f:write("hello world\n"))) f:close() end ___'' do writefile("data.txt", "123 18.8 hello world\ni'm here\n") for a,b in io.lines("test.lua", 2, "*l") do print("io.lines()", a, b) break end for l in io.lines("test.lua") do print("io.lines()", l) break end for n1,n2,rest in io.lines("data.txt", "*n", "*n", "*a") do print("io.lines()", n1, n2, rest) end for l in io.lines("data.txt") do print("io.lines()", l) end print("io.lines()", pcall(function() for l in io.lines("data.txt", "*x") do print(l) end end)) print("io.lines()", pcall(function() for l in io.lines("no_such_file.txt") do print(l) end end)) local f = assert(io.open("test.lua", "r")) for a,b in f:lines(2, "*l") do print("file:lines()", a, b) break end f:close() f = assert(io.open("data.txt", "r")) for n1,n2,rest in f:lines("*n", "*n", "*a") do print("file:lines()", n1, n2, rest) end f:close() f = assert(io.open("data.txt", "r")) for l in f:lines() do print("file:lines()", l) end f:close() print("file:lines()", pcall(function() for l in f:lines() do print(l) end end)) print("file:lines()", pcall(function() local f = assert(io.open("data.txt", "r")) for l in f:lines("*l", "*x") do print(l) end f:close() end)) os.remove("data.txt") end ___'' print("testing C API ...") local mod = require("testmod") ___'' print(mod.isinteger(1)) print(mod.isinteger(0)) print(mod.isinteger(1234567)) print(mod.isinteger(12.3)) print(mod.isinteger(math.huge)) print(mod.isinteger(math.sqrt(-1))) ___'' print(mod.rotate(1, 1, 2, 3, 4, 5, 6)) print(mod.rotate(-1, 1, 2, 3, 4, 5, 6)) print(mod.rotate(4, 1, 2, 3, 4, 5, 6)) print(mod.rotate(-4, 1, 2, 3, 4, 5, 6)) ___'' print(mod.strtonum("+123")) print(mod.strtonum(" 123 ")) print(mod.strtonum("-1.23")) print(mod.strtonum(" 123 abc")) print(mod.strtonum("jkl")) ___'' local a, b, c = mod.requiref() print( type(a), type(b), type(c), a.boolean, b.boolean, c.boolean, type(requiref1), type(requiref2), type(requiref3)) ___'' local proxy, backend = {}, {} setmetatable(proxy, { __index = backend, __newindex = backend }) print(rawget(proxy, 1), rawget(backend, 1)) print(mod.getseti(proxy, 1)) print(rawget(proxy, 1), rawget(backend, 1)) print(mod.getseti(proxy, 1)) print(rawget(proxy, 1), rawget(backend, 1)) -- tests for Lua 5.1 ___'' print(mod.tonumber(12)) print(mod.tonumber("12")) print(mod.tonumber("0")) print(mod.tonumber(false)) print(mod.tonumber("error")) ___'' print(mod.tointeger(12)) print(mod.tointeger("12")) print(mod.tointeger("0")) print( "aaa" ) print(mod.tointeger(math.pi)) print( "bbb" ) print(mod.tointeger(false)) print(mod.tointeger("error")) ___'' print(mod.len("123")) print(mod.len({ 1, 2, 3})) print(pcall(mod.len, true)) local ud, meta = mod.newproxy() meta.__len = function() return 5 end print(mod.len(ud)) meta.__len = function() return true end print(pcall(mod.len, ud)) ___'' print(mod.copy(true, "string", {}, 1)) ___'' print(mod.rawxetp()) print(mod.rawxetp("I'm back")) ___'' print(F(mod.globals()), mod.globals() == _G) ___'' local t = {} print(F(mod.subtable(t))) local x, msg = mod.subtable(t) print(F(x, msg, x == t.xxx)) ___'' print(F(mod.udata())) print(mod.udata("nosuchtype")) ___'' print(F(mod.uservalue())) ___'' print(mod.getupvalues()) ___'' print(mod.absindex("hi", true)) ___'' print(mod.arith(2, 1)) print(mod.arith(3, 5)) ___'' print(mod.compare(1, 1)) print(mod.compare(2, 1)) print(mod.compare(1, 2)) ___'' print(mod.tolstring("string")) local t = setmetatable({}, { __tostring = function(v) return "mytable" end }) print(mod.tolstring(t)) local t = setmetatable({}, { __tostring = function(v) return nil end }) print(pcall(mod.tolstring, t)) ___'' print(mod.buffer()) ___'' lua-systemd-master/vendor/compat-5.3/tests/testmod.c000066400000000000000000000152251271662244600227050ustar00rootroot00000000000000#include #include #include #include "compat-5.3.h" static int test_isinteger (lua_State *L) { lua_pushboolean(L, lua_isinteger(L, 1)); return 1; } static int test_rotate (lua_State *L) { int r = luaL_checkint(L, 1); int n = lua_gettop(L)-1; luaL_argcheck(L, (r < 0 ? -r : r) <= n, 1, "not enough arguments"); lua_rotate(L, 2, r); return n; } static int test_str2num (lua_State *L) { const char *s = luaL_checkstring(L, 1); size_t len = lua_stringtonumber(L, s); if (len == 0) lua_pushnumber(L, 0); lua_pushinteger(L, (lua_Integer)len); return 2; } static int my_mod (lua_State *L ) { lua_newtable(L); lua_pushboolean(L, 1); lua_setfield(L, -2, "boolean"); return 1; } static int test_requiref (lua_State *L) { lua_getfield(L, LUA_REGISTRYINDEX, "_LOADED"); lua_newtable(L); lua_pushboolean(L, 0); lua_setfield(L, -2, "boolean"); lua_setfield(L, -2, "requiref3"); lua_pop(L, 1); luaL_requiref(L, "requiref1", my_mod, 0); luaL_requiref(L, "requiref2", my_mod, 1); luaL_requiref(L, "requiref3", my_mod, 1); return 3; } static int test_getseti (lua_State *L) { lua_Integer k = luaL_checkinteger(L, 2); lua_Integer n = 0; if (lua_geti(L, 1, k) == LUA_TNUMBER) { n = lua_tointeger(L, -1); } else { lua_pop(L, 1); lua_pushinteger(L, n); } lua_pushinteger(L, n+1); lua_seti(L, 1, k); return 1; } /* additional tests for Lua5.1 */ #define NUP 3 static int test_newproxy (lua_State *L) { lua_settop(L, 0); lua_newuserdata(L, 0); lua_newtable(L); lua_pushvalue(L, -1); lua_pushboolean(L, 1); lua_setfield(L, -2, "__gc"); lua_setmetatable(L, -3); return 2; } static int test_absindex (lua_State *L) { int i = 1; for (i = 1; i <= NUP; ++i) lua_pushvalue(L, lua_absindex(L, lua_upvalueindex(i))); lua_pushvalue(L, lua_absindex(L, LUA_REGISTRYINDEX)); lua_pushstring(L, lua_typename(L, lua_type(L, lua_absindex(L, -1)))); lua_replace(L, lua_absindex(L, -2)); lua_pushvalue(L, lua_absindex(L, -2)); lua_pushvalue(L, lua_absindex(L, -4)); lua_pushvalue(L, lua_absindex(L, -6)); i += 3; lua_pushvalue(L, lua_absindex(L, 1)); lua_pushvalue(L, lua_absindex(L, 2)); lua_pushvalue(L, lua_absindex(L, 3)); i += 3; return i; } static int test_arith (lua_State *L) { lua_settop(L, 2); lua_pushvalue(L, 1); lua_pushvalue(L, 2); lua_arith(L, LUA_OPADD); lua_pushvalue(L, 1); lua_pushvalue(L, 2); lua_arith(L, LUA_OPSUB); lua_pushvalue(L, 1); lua_pushvalue(L, 2); lua_arith(L, LUA_OPMUL); lua_pushvalue(L, 1); lua_pushvalue(L, 2); lua_arith(L, LUA_OPDIV); lua_pushvalue(L, 1); lua_pushvalue(L, 2); lua_arith(L, LUA_OPMOD); lua_pushvalue(L, 1); lua_pushvalue(L, 2); lua_arith(L, LUA_OPPOW); lua_pushvalue(L, 1); lua_arith(L, LUA_OPUNM); return lua_gettop(L)-2; } static int test_compare (lua_State *L) { luaL_checknumber(L, 1); luaL_checknumber(L, 2); lua_settop(L, 2); lua_pushboolean(L, lua_compare(L, 1, 2, LUA_OPEQ)); lua_pushboolean(L, lua_compare(L, 1, 2, LUA_OPLT)); lua_pushboolean(L, lua_compare(L, 1, 2, LUA_OPLE)); return 3; } static int test_globals (lua_State *L) { lua_pushglobaltable(L); return 1; } static int test_tonumber (lua_State *L) { int isnum = 0; lua_Number n = lua_tonumberx(L, 1, &isnum); if (!isnum) lua_pushnil(L); else lua_pushnumber(L, n); return 1; } static int test_tointeger (lua_State *L) { int isnum = 0; lua_Integer n = lua_tointegerx(L, 1, &isnum); if (!isnum) lua_pushnil(L); else lua_pushinteger(L, n); return 1; } static int test_len (lua_State *L) { luaL_checkany(L, 1); lua_len(L, 1); lua_pushinteger(L, luaL_len(L, 1)); return 2; } static int test_copy (lua_State *L) { int args = lua_gettop(L); if (args >= 2) { int i = 0; for (i = args-1; i > 0; --i) lua_copy(L, args, i); } return args; } /* need an address */ static char const dummy = 0; static int test_rawxetp (lua_State *L) { if (lua_gettop(L) > 0) lua_pushvalue(L, 1); else lua_pushliteral(L, "hello again"); lua_rawsetp(L, LUA_REGISTRYINDEX, &dummy); lua_settop(L, 0); lua_rawgetp(L, LUA_REGISTRYINDEX, &dummy); return 1; } static int test_udata (lua_State *L) { const char *tname = luaL_optstring(L, 1, "utype1"); void *u1 = lua_newuserdata(L, 1); int u1pos = lua_gettop(L); void *u2 = lua_newuserdata(L, 1); int u2pos = lua_gettop(L); luaL_newmetatable(L, "utype1"); luaL_newmetatable(L, "utype2"); lua_pop(L, 2); luaL_setmetatable(L, "utype2"); lua_pushvalue(L, u1pos); luaL_setmetatable(L, "utype1"); lua_pop(L, 1); (void)u1; (void)u2; lua_pushlightuserdata(L, luaL_testudata(L, u1pos, tname)); lua_pushlightuserdata(L, luaL_testudata(L, u2pos, tname)); return 2; } static int test_subtable (lua_State *L) { luaL_checktype(L, 1, LUA_TTABLE); lua_settop(L, 1); if (luaL_getsubtable(L, 1, "xxx")) { lua_pushliteral(L, "oldtable"); } else { lua_pushliteral(L, "newtable"); } return 2; } static int test_uservalue (lua_State *L) { void *udata = lua_newuserdata(L, 1); int ui = lua_gettop(L); lua_newtable(L); lua_setuservalue(L, ui); lua_getuservalue(L, ui); (void)udata; return 1; } static int test_upvalues (lua_State *L) { int i = 1; for (i = 1; i <= NUP; ++i) lua_pushvalue(L, lua_upvalueindex(i)); return NUP; } static int test_tolstring (lua_State *L) { size_t len = 0; luaL_tolstring(L, 1, &len); lua_pushinteger(L, (int)len); return 2; } static int test_buffer (lua_State *L) { luaL_Buffer b; char *p = luaL_buffinitsize(L, &b, LUAL_BUFFERSIZE+1); p[0] = 'a'; p[1] = 'b'; luaL_addsize(&b, 2); luaL_addstring(&b, "c"); lua_pushliteral(L, "d"); luaL_addvalue(&b); luaL_addchar(&b, 'e'); luaL_pushresult(&b); return 1; } static const luaL_Reg funcs[] = { { "isinteger", test_isinteger }, { "rotate", test_rotate }, { "strtonum", test_str2num }, { "requiref", test_requiref }, { "getseti", test_getseti }, { "newproxy", test_newproxy }, { "arith", test_arith }, { "compare", test_compare }, { "tonumber", test_tonumber }, { "tointeger", test_tointeger }, { "len", test_len }, { "copy", test_copy }, { "rawxetp", test_rawxetp }, { "subtable", test_subtable }, { "udata", test_udata }, { "uservalue", test_uservalue }, { "globals", test_globals }, { "tolstring", test_tolstring }, { "buffer", test_buffer }, { NULL, NULL } }; static const luaL_Reg more_funcs[] = { { "getupvalues", test_upvalues }, { "absindex", test_absindex }, { NULL, NULL } }; int luaopen_testmod (lua_State *L) { int i = 1; luaL_newlib(L, funcs); for (i = 1; i <= NUP; ++i) lua_pushnumber(L, i); luaL_setfuncs(L, more_funcs, NUP); return 1; }