Class: Remind::Native
- Inherits:
-
Object
- Object
- Remind::Native
- Defined in:
- lib/remind/native.rb
Overview
The dlopen'd library: the Remind functions the bindings call, the shim functions that reach what Fiddle cannot, and the globals Remind keeps its state in.
Fiddle rather than a C extension, because there is no extension to write. Remind's sources build into a shared library as they are, and everything here is a plain C function over ints and pointers. The one file of C in this gem, ext/shim.c, exists for struct layout and for the six-call sequence that parses a REM line -- not because Fiddle needs help calling anything.
Functions are looked up on first call and kept: Fiddle::Handle#[] is a
dlsym every time.
Constant Summary collapse
- INT =
Fiddle::TYPE_INT
- POINTER =
Fiddle::TYPE_VOIDP
- SIZE =
Fiddle::TYPE_SIZE_T
- VOID =
Fiddle::TYPE_VOID
- FUNCTIONS =
name => [C symbol, argument types, return type]
{ # Dates. Remind counts days from 1990-01-01 and numbers months from # zero; both conversions are called rather than repeated, so the epoch # cannot drift from the library's. dse: ["DSE", [INT, INT, INT], INT], from_dse: ["FromDSE", [INT, POINTER, POINTER, POINTER], VOID], # Expressions, and the messages for when they fail. evaluate: ["EvalExpr", [POINTER, POINTER, POINTER], INT], error_message: ["GetErr", [INT], POINTER], # The startup sequence `Runtime` mirrors. Remind does all of this inside # InitRemind, which also parses argv, opens files and exits on bad # input, and is therefore not something a library can call. init_variables: ["InitVars", [], VOID], init_user_functions: ["InitUserFunctions", [], VOID], init_translation_table: ["InitTranslationTable", [], VOID], init_files: ["InitFiles", [], VOID], init_dedupe_table: ["InitDedupeTable", [], VOID], init_buffer: ["DBufInit", [POINTER], VOID], system_date: ["SystemDate", [POINTER, POINTER, POINTER], INT], system_time: ["SystemTime", [INT], INT], # libc's, through the same handle: Remind writes its diagnostics through # a FILE *, so somewhere to point it is part of the interface. open_stream: ["fopen", [POINTER, POINTER], POINTER], # The shim. sizeof_trigger: ["remrb_sizeof_trigger", [], SIZE], sizeof_timetrig: ["remrb_sizeof_timetrig", [], SIZE], parse_reminder: ["remrb_parse_reminder", [POINTER, POINTER, POINTER, POINTER, POINTER, INT], INT], next_trigger: ["remrb_next_trigger", [POINTER, POINTER, INT, POINTER], INT], free_trigger: ["remrb_free_trigger", [POINTER], VOID], open_file: ["remrb_open_file", [POINTER], INT], read_line: ["remrb_read_line", [POINTER], INT], trigger_tags: ["remrb_trigger_tags", [POINTER], POINTER], trigger_timezone: ["remrb_trigger_timezone", [POINTER], POINTER], }.freeze
- TRIGGER_FIELDS =
The Trigger fields a calendar entry is made out of. Each is an accessor in the shim, compiled against Remind's own headers, so no byte offset is ever written down on this side.
%i[ wd d m y back delta rep localomit skip until typ once scanfrom from priority duration_days eventduration eventstart is_todo addomit need_wkday ].freeze
- TIMETRIG_FIELDS =
%i[time delta repeat duration].freeze
- CONSTANTS =
The values Remind uses for "the reminder did not say", and the constants it tags a body with. Read from the shim rather than copied, for the same reason as the field offsets.
%i[ no_day no_month no_year no_weekday no_until no_time quote_marker normal_mode cal_mode eof msg_type msf_type run_type cal_type sat_type passthru_type ].freeze
- GLOBALS =
Remind keeps its idea of now in globals rather than passing it around, so these are as much a part of the interface as the functions.
DSEToday the date every relative calculation is relative to LocalDSEToday the same, before a --date override moves it RealToday what the system clock said at startup CurYear the year an incomplete date is completed with SysTime seconds since midnight, or -1 to read the clock %w[DSEToday LocalDSEToday RealToday CurYear SysTime LocalSysTime].freeze
- BUFFERS =
The dynamic buffers Remind expects to have been initialised, and the stream it expects to have been pointed somewhere.
%w[Banner LineBuffer ExprBuf].freeze
- ERROR_STREAM =
"ErrFp"
Instance Attribute Summary collapse
-
#path ⇒ Object
readonly
Returns the value of attribute path.
Instance Method Summary collapse
-
#address_of(name) ⇒ Object
The address of a global, for the functions that take one: DBufInit wants the buffer itself, not a copy of it.
-
#initialize(path = Library.path) ⇒ Native
constructor
A new instance of Native.
- #read_global(name) ⇒ Object
-
#standard_error ⇒ Object
stderris a variable in libc, and it holds the FILE * rather than being one. - #write_global(name, value) ⇒ Object
-
#write_pointer(name, address) ⇒ Object
A pointer-sized global, which is what a FILE * is.
Constructor Details
Instance Attribute Details
#path ⇒ Object (readonly)
Returns the value of attribute path.
105 106 107 |
# File 'lib/remind/native.rb', line 105 def path @path end |
Instance Method Details
#address_of(name) ⇒ Object
The address of a global, for the functions that take one: DBufInit wants the buffer itself, not a copy of it.
147 148 149 |
# File 'lib/remind/native.rb', line 147 def address_of(name) Fiddle::Pointer.new(@handle[name]) end |
#read_global(name) ⇒ Object
137 138 139 |
# File 'lib/remind/native.rb', line 137 def read_global(name) global(name)[0, Fiddle::SIZEOF_INT].unpack1("i!") end |
#standard_error ⇒ Object
stderr is a variable in libc, and it holds the FILE * rather than
being one.
159 160 161 162 163 164 |
# File 'lib/remind/native.rb', line 159 def standard_error Fiddle::Pointer.new(Fiddle::Handle::DEFAULT["stderr"], Fiddle::SIZEOF_VOIDP)[ 0, Fiddle::SIZEOF_VOIDP, ].unpack1("J") end |
#write_global(name, value) ⇒ Object
141 142 143 |
# File 'lib/remind/native.rb', line 141 def write_global(name, value) global(name)[0, Fiddle::SIZEOF_INT] = [value].pack("i!") end |
#write_pointer(name, address) ⇒ Object
A pointer-sized global, which is what a FILE * is.
152 153 154 155 |
# File 'lib/remind/native.rb', line 152 def write_pointer(name, address) Fiddle::Pointer.new(@handle[name], Fiddle::SIZEOF_VOIDP)[0, Fiddle::SIZEOF_VOIDP] = [address].pack("J") end |