New upstream version 1.0.0
Bdale Garbee
4 years ago
0 | Changelog for libmawk | |
1 | ~~~~~~~~~~~~~~~~~~~~~ | |
2 | libmawk 1.0.0 (released: 2018-11-11, r1276) | |
3 | [API] -Change: resume capable function call entries | |
4 | [build] -Fix: make clean should remove custom C test objects and executables | |
5 | [build] -Fix: incomplete install headers list | |
6 | [build] -Add: Makefile variable for selecting zmalloc alternatives | |
7 | [build] -Add: optional DESTDIR for debian | |
8 | [build] -Add: --prefix, --debug, --symbols | |
9 | [build] -Add: help | |
10 | [build] -Chnage: upgrade to tmpasm and latest version of scconfig | |
11 | [build] -Add: optional support for soname | |
12 | [build] -Change: use $(MAKE) instead of make in central Makefiles for parallel build | |
13 | [build] -Add: detect -rdynamic | |
14 | [core] -Change: extend mpow2 for covering new celltypes | |
15 | [core] -Cleanup: rename _STOP and _RANGE to _RANGE_STOP and _RANGE_CHK to make their purpose more clear | |
16 | [core] -Fix: return read error in getline doesn't fall in infinite loop in fill buff anymore | |
17 | [core] -Add: MAWK_MEM_PEDANTIC compile time option; when set, try to free all allocation instead of letting zmalloc catch them all | |
18 | [core] -Fix: don't free the hash before freeing argv and others | |
19 | [core] -Fix: make sure code blocks are free'd only once, but are really free'd | |
20 | [core] -Fix: memory leak when initializing argv | |
21 | [core] -Fix: let mawk_delete() free arrays, don't manually do that on argv | |
22 | [core] -Change: let mawk_delete() free user function | |
23 | [core] -Change: fin is under files - higher level code should do all access through the file infra | |
24 | [core] -Fix: FIN is only about buffering, no open/close should go through that API | |
25 | [core] -Fix: reference count vf structs since one vf might be open multiple times from FILE_NODEs (for input and output) and should be destroyed only once | |
26 | [core] -Fix: closing all files, not only output files, is not a pedantic-mem feature - not doig it could lead to leaking fds and other resources even if zmalloc pools are freed centrally | |
27 | [core] -Fix: there is only one way files are closed, only one code is needed | |
28 | [core] -Fix: mawk_fill_buff returns a signed long for indicating temporary error (fixed for 64 bit) | |
29 | [core] -Fix: rename state field userdata to func_userdata to make the purpose more clear | |
30 | [core] -Add: ctx_userdata intended for the host app for storing whatever data, per context | |
31 | [core] -Add: have a field in the state struct for the C function being called back so that subsequent execute()s may know about that | |
32 | [core] -Fix: memory leak: free data of c function calls compiled into the code at uninit | |
33 | [core] -Fix: C89 fixes (func-data ptr conv through union, don't use strcasemp(), strdup, snprintf, //, vararg macros) | |
34 | [core] -Fix: wrong arg passed to isnan - cell instead fo double value | |
35 | [core] -Fix: vio fclose survives if there's no close function available (double close?) | |
36 | [doc] -Add: short desc about the vm | |
37 | [doc] -Add: explain how execution/resume works | |
38 | [doc] -Add: describe deep recursion | |
39 | [doc] -Add: minimalistic install | |
40 | [example_apps] -Add: blocking fifo test also tests bifunct getline in an user function | |
41 | [example_apps] -Add: make sure to demonstrate how the code is suspended even in user functions | |
42 | [example_apps] -Update: 15_call for the new function call API | |
43 | [example_apps] -Add: example on run limit resume | |
44 | [example_apps] -Add: central Makefile that runs all examples | |
45 | [example_apps] -Add: call a c function from c using awk's func call (demonstrate that awk and c functions should not make any difference) | |
46 | [example_apps] -Fix: hash_re won't init std pipes twice | |
47 | [example_apps] -Fix: custom vio test sets up pipes correctly and closes the hass from the app's end of the deal at the end | |
48 | [example_apps] -Add: better explanation of the c_func_call example and hook it in the all-test-chain | |
49 | [libmawk] -Fix: C function call from execute with new function call conventions | |
50 | [libmawk] -Fix: call_functionp increases sp before push else the stack pointer points to the wrong place | |
51 | [libmawk] -Fix: restore sp on function call failure | |
52 | [libmawk] -Fix: before closing stdio on awk side, close stdin on app side to make sure both ends can be closed | |
53 | [libmawk] -Fix: do not leak function arguments already pushed on stack if an awk function call fails due to bad arguments | |
54 | [libmawk] -Fix: allow c functions to be called using mawk_call_function*() | |
55 | [libmawk] -Fix: don't close stdin if it's not open | |
56 | [libmawk] -Fix: don't use strdup() for c function reg | |
57 | [libmawk] -Fix: don't close non-fifo stdin as fifo | |
58 | [libmawk] -Fix: priting uninitialized cell should work and should result in empty string | |
59 | [libmawk] -Add: wants_to_exit flag so that a libmawk caller knows a script wants to exit | |
60 | [libmawk] -Add: function call API with cell argc/argv | |
61 | [parser] -Fix: really reset the parser stack when it gets freed - used to segfault for two includes on the topmost level | |
62 | [parser] -Fix: allow excess newlines in the main context - this fixes a corner case around multiple includes | |
63 | [regression] -Add: test for bifunct call() | |
64 | [regression] -Add: test for acall() (dynamic call with array as argument) | |
65 | [regression] -Add: test for stack grow on deep recursion | |
66 | [regression] -Add: test program for awk function call corner cases | |
67 | [regression] -Add: libmawk corner case test base | |
68 | [regression] -Fix: libmawk func call test diag messages are more clear on what's wrong or good | |
69 | [rexp] -Fix: infinite loop bug (gawk test noloop1 and noloop2) - contributed by Thomas E. Dickey as a mawk fix | |
70 | [vio] -Fix: set eof flags on fifo creation (fixes a conditional jump on uninited var bug) | |
71 | [vio] -Fix: closing FIN closes the vio layer even if fin buffer had not been initialized | |
72 | [vio] -Fix: close vf throug FIN to make sure buffers are also freed | |
73 | [vio] -Fix: simpler common header with refco and who-knows-what in the future | |
74 | [vio] -Fix: initialize refco to 0 | |
75 | [vm] -Change: avoid recursive calls to execute() on plain hardwired awk function calls | |
76 | [vm] -Change: wants_to_ret is execution state instead - need to remember whether we are running range1 or range2 | |
77 | [vm] -Fix: leak in function return value stack handling | |
78 | [vm] -Add: new convention in bi_funct calling: return stack may be a directive for executing an user functioin (for bi_call and bi_acall) | |
79 | [vm] -Fix: mawk_bi_call() and bifunct acall() follow the new no-recurse calling convention | |
80 | [vm] -Add: new low level c->awk call functions trying to follow the no-recurse execute_() conventions | |
81 | [vm] -Move: execute API into new execute.h | |
82 | [vm] -Add: a separate execution exit status for exit() | |
83 | [vm] -Add: execution run limit and resume | |
84 | [vm] -Fix: bi_funct getline can indicate 'nomore' instead of eof | |
85 | [vm] -Fix: properly save and restore old_stack_base and old_sp on stack danger (stack growth) | |
86 | [vm] -Cleanup: remumber types (continous numbering) | |
87 | [vm] -Add: more stack-related cell types and make room for future non-string additions | |
88 | [vm] -Fix: compare() returns double so that nan-checks can be performed | |
89 | [vm] -Fix: error return with value from execute() | |
90 | [vm] -Fix: make MAWK->pow big enough and make it safe (need to be unsigned long for these values and for the bit ops) | |
91 | ||
92 | ||
93 | libmawk 0.10.1 (released: 2014-07-11, r1056) | |
94 | [compiler] -Fix: zero-offset bug in jmp push (xref test crash) | |
95 | [build] -Add: make test should run the standard regression tests; do not run tests automatically on build | |
96 | [core] -Add: zfifo: generic fifo implemented using zmalloc/zfree | |
97 | [core] -Add: mawk_file_find() has a create flag that can disable creating a new file node - useful for forcing existing/open files | |
98 | [core] -Cleanup: move fin struct to fin.h | |
99 | [core] -Cleanup: rename FIN to mawk_input_t for naming consistency | |
100 | [core] -Fix: rewritten mawk_FINgets - cleaner code that is non-blocking-safe | |
101 | [core] -Fix: zrealloc() should not crash if old ptr is NULL | |
102 | [core] -Fix: safer vf close, close outputs only in uninit, when EXIT has finished for sure | |
103 | [vio] -Fix: input is always fd, output is always FILE *; remove fgets and stdin related API | |
104 | [vio] -Clenaup: cleaner ways recognizing "/dev/std*" | |
105 | [vio] -Add: support for /dev/fd/xxx (fdopen() wrapper) | |
106 | [vio] -Add: an extra layer to dispatch vio calls - multiple vio implementations can coexist | |
107 | [vio] -Add: virtualize vio init (non-per-file vio hooks); use MAWK->vio_init instead of hardwired vio_orig (so that vio_orig can be omitted) | |
108 | [vio] -Del: setbuf from API - this callback was a hack, now all done by the call that sets up stdio | |
109 | [vio] -Change: replace is_stdouts with a more generic mark_no_close hook | |
110 | [vio] -Fix: use zmalloc/zfree for the mawk_vio_t allocations | |
111 | [vio] -Add: a generic fifo implementation that also replaces the artificial FIN buf | |
112 | [regression] -Cleanup: remove test/ and convert all shell script based tests to make-based tests in regression/ | |
113 | [tools] -Fix: find_globals uses the right dir | |
114 | [tools] -Fix: sym prefix validator won't complain for main() | |
115 | [API] -Add: file name validation hook | |
116 | [API] -Add: call to register a file by name:type and vio handle in the high level list of files; also sets up input buffering as needed | |
117 | [API] -Add: call to close the default input fifo (sending eof to the script) | |
118 | [API] -Add: convenient stdio-init call for multi-staged init | |
119 | [example_app] -Add: custom output pipe hack examples and update pipe in buffer fill examples with all possible corner cases | |
120 | [example_app] -Add: file name validation and vio hook examples | |
121 | ||
122 | ||
123 | libmawk 0.10.0 (released: 2014-06-26, r937) | |
124 | Major changes in core, mostly for virtual arrays: | |
125 | [array] -Add: introduce new VM instructions for all array-element-write operations and split the lvalue rule of the grammar; besides being new instructions, they do the same in the execution switch as before | |
126 | [array] -Add: virtualize array operations | |
127 | [array] -Add: virtual, per instance ENVIRON[] that copies environ[] upon the first access and affects exec() | |
128 | [array] -Del: ST_ENV: ENVIRON[] is not a global special case anymore, just a builtin array with a different implementation | |
129 | [core] -Fix: replace "short int type" and a bunch of C_ macros for cell type with a proper enum | |
130 | [core] -Add: macro option for cell operators for speed | |
131 | [core] -Fix: set ERRNO in fin after a read error | |
132 | [core] -Cleanup: mawk_ prefix zmalloc, zfree, ZMALLOC, ZFREE and a lot of other constants and macros | |
133 | [init] -Add: a flag for indicating that it is ok for initialize_argv() to end up without a script | |
134 | [dump] -Fix: print the code of illegal instructions | |
135 | [dump] -Add: da_text: use blank lines to separate blocks: functions, BEGIN, MAIN, END | |
136 | [dump] -Change: da_text: after user functions, dump code in BEGIN-MAIN-END order - it is more intuitive this way | |
137 | [dump] -Add: text dump includes a summary of the global symbol table | |
138 | [dump] -Change: introduce -W dumpsym for dumping symbols independently of dumping code | |
139 | [da_bin] -Fix: properly save/load C_SNULL and C_SPACE (special split argument types) to/from binary dump | |
140 | API CHANGES affecting libmawk: | |
141 | [core] -Clenaup: rename STRING to mawk_string_t | |
142 | [core] -Clenaup: rename CELL to libmawk_cell_t | |
143 | [core] -Change: use an union instead of dval in CELL, to make room for other data types | |
144 | [core] -Add: new cell type C_ARR_REF (should be execute()-internal); an array reference by name and index (instead of pointer to a cell) | |
145 | [API] -move parsing the script from init stage1 to stage2 to give the host app a chance to inject things into the context before any code is parsed | |
146 | [API] -Change: get_var should return a read-only CELL - direct modification of the cell is a bad idea due to possible side effects required at write | |
147 | [API] -Fix: libmawk_print_cell shall be called with the context (mawk_state_t) as any other call in the API | |
148 | [API] -Change: new, easier-to-use c-func calling conventions and helpers | |
149 | [array] -Cleanup: rename ARRAY to mawk_array_t | |
150 | New libmawk API features: | |
151 | [API] -Add: helper functions to return the numeric value of a cell | |
152 | [API] -Add: an easy way to set a cell to empty | |
153 | [API] -Add: high level array set_at calls and scalar set calls | |
154 | ||
155 | libmawk 0.9.7 (released: 2014-05-17, r732) | |
156 | Major code structure changes: | |
157 | [vio] -Split: file/pipe open/close operations to virtual IO (vio) | |
158 | [linux] -Add: initial linux kernel module effort (defunct yet) | |
159 | [array] -Add: virtualized array access (except for write) with callback functions | |
160 | [libmawk] -Split: lmawk-comp and lmawk-exec frames - most code is in common yet | |
161 | [libmawk] -Add: MAWK_NO_FORK for configuring against system() and fork() | |
162 | Code cleanup: | |
163 | [da_bin] -Cleanup: compiler warnings around da_bin (binary script save/load) | |
164 | [da_bin] -Split: da_bin and da_bin_helper: precompiled binary script load doesn't directly call read() but an user provided callback for virtualization | |
165 | [da_bin] -Fix: array creation on binary load | |
166 | [da_bin] -Fix: when resetting code base size for loading binary, use zmalloc for proper allocation size | |
167 | [build] -Fix: Makefile cleanup for portability | |
168 | [libmawk] -Fix: prefix NF, RS and other similar macro names with MAWK_ - they collide in the Linux kernel | |
169 | [test_3rd] -Add: scripts for running optional 3rd party tests from vendor/ (for the gawk set, without much configuration or filtering) | |
170 | [regex] -Change: error handling without setjmp/longjmp (return values and a bunch of checks) | |
171 | [regex] -Fix: regex lib uses zmalloc memory allocation to ensure all memory is free'd after a context is destroyed | |
172 | [regex] -Add: tiny test program to trigger almost all possible error conditions in the regex lib | |
173 | [regex] -Fix: move runtime states of the regex lib in the mawk struct to make it reentrant | |
174 | [regex] -Fix: bi_vars are part of the mawk struct because parallel scripts may have different values for the same variables or even modify them from script | |
175 | More portable doubles (and numeric): | |
176 | [numeric] -Add: use porty's math_wrap for log() to get rid of undeterministic fpe | |
177 | [numeric] -Add: use PM math protection copied from libporty | |
178 | [numeric] -Add: new builtin function isnan() | |
179 | [numeric] -Fix: virtualize strtod int strtonum: on a real int-only platform (e.g. Linux kernel) there won't be strtod at all | |
180 | Fixes of the core functionality: | |
181 | [libmawk] -Fix: make sure runtime error exit code takes over in final_error_code | |
182 | [bi_func] -Fix: substr for start indices less than 1 behave similar to how substr() handles length overruns (silently truncate) - gawk has the same behavior | |
183 | [bi_func] -Fix: gsub() patch for the ^ bug | |
184 | [io] -Fix: redirection conditions messed up in r349 | |
185 | [libmawk] -Fix: disable -v only when MAWK_NO_EXEC is set, and don't even consider MAWK_NO_COMP | |
186 | [libmawk] -Fix: fin_exec should respect a MAWK exit request and not retry reading | |
187 | [libmawk] -Fix: if FIN can not be open (invalid file name, nonexisting file), don't segfault but return error | |
188 | ||
189 | libmawk 0.9.6 (missed) | |
190 | ||
191 | libmawk 0.9.5 (released: 2012-10-13, r527) | |
192 | [libmawk] -Add: memory usage accounting figures; -Wmaxmem=size sets maximum | |
193 | memory allocation in bytes (optional suffixes: k and m) | |
194 | [libmawk] -Add: binary save/load functionality (-Wcompile and -b) | |
195 | works on 32 bit systems only (will be fixed later) | |
196 | [libmawk] -Change: replace hardwired double references with generin numeric | |
197 | (C_NUM, num_t) - libmawk can be configured to use int or | |
198 | double as numeric format (./configure --numeric=) | |
199 | [libmawk] -Cleanup: (portability tweak) const correctness in mawk_reverse_find | |
200 | [libmawk] -Add: (portability tweak) _POSIX_SOURCE | |
201 | [libmawk] -Fix: (portability tweak) explicit rules for rexp/*.o incuding | |
202 | $(CC) command line for old fashioned make having the wrong | |
203 | implicit rule | |
204 | [libmawk] -Cleanup: (portability tweak) k&r style function | |
205 | declarations/definitions removed from rexp lib | |
206 | [libmawk] -Fix: (portability tweak) missing prototypes to avoid implicit | |
207 | declaration warning | |
208 | [libmawk] -Change: disable two zfree() calls that would free main code to | |
209 | avoid double frees | |
210 | [libmawk] -Add: compile with app clfags | |
211 | [libmawk] -Cleanup: move scconfig'd -D options to conf.h from Makefile.conf | |
212 | to make compiler command lines shorter | |
213 | [libmawk] -Cleanup: new vars.[ch] for collecting variable-related code | |
214 | [libmawk] -Fix: mawk_mm (aka free_later) mechanism memory handling erros | |
215 | when realloc()'d | |
216 | [doc] -Add: explain design decisions behind our two gnu-dependencies | |
217 | [doc] -Add: portability table (per system: compiles out of the box, has | |
218 | FPE problems, awklib test ran fine) | |
219 | ||
220 | libmawk 0.9.4 (released: 2010-12-26, r392) | |
221 | [scconfig] -Add: detect pipe(2) and set NO_PIPE, replacing HAVE_REAL_PIPES | |
222 | [scconfig] -Add: detect size_t include file (removes the ifdef mess) | |
223 | [scconfig] -Add: require detection of cc/fpic (fixes compilation on amd64) | |
224 | [libmawk] -Cleanup: del PROTO() macro: libmawk requires at least C89 compiler | |
225 | [libmawk] -Cleanup: remove revision history and file name comments from *.[ch] | |
226 | copyright notice above all mawk copyright notices | |
227 | [libmawk] -Cleanup: version to clearly indicate that this is lmawk | |
228 | [libmawk] -Cleanup: unified indentation in all .c and .h files | |
229 | [libmawk] -Cleanup: remove a lot of compiler warnings, fix const correctness | |
230 | [libmawk] -Cleanup: Makefile.dep generation rule; proper, up-to-date Makefile.dep | |
231 | [libmawk] -Del: remove FAKE_PIPES support (was only for DOS anyway) | |
232 | [libmawk] -Del: void * is a must, PTR should not fall back to char * | |
233 | [libmawk] -Del: cut out MSDOS support with all its "dreaded segment nonsense" | |
234 | [libmawk] -Fix: get bison to generate a reentrant parser | |
235 | [libmawk] -Fix: move static globals to mawk state struct | |
236 | [libmawk] -Fix: memory leaks | |
237 | ||
238 | ||
239 | libmawk 0.9.3 (released: 2010-12-21, r307) | |
240 | [libmawk] -Fix: use -fPIC for compiling (helps on amd64) | |
241 | [libmawk] -Add: new builtin variable ERRNO with a different error code for each corner case in extension calls | |
242 | [libmawk] -Add: new built-in variable LIBPATH for library search path | |
243 | - skip loading a script if name started with '+' and the script was already loaded | |
244 | - if script file name starts with '/', assume it to be an absolute path and skip LIBPATH search | |
245 | [scconfig] -Add: scconfig configures/generates Makefiles of libmawk after autodetecting system features | |
246 | [scconfig] -Del: config-user, v7, atarist: scconfig should take care of all supported systems | |
247 | [scconfig] -Add: central ./configure and Makefile | |
248 | [libmawk] -Fix: order of running BEGINs with "include" | |
249 | [libmawk] -Fix: memory leaks around parser state | |
250 | [awklib] -Add: three awk libraries: | |
251 | - lib_rand for reproducible pseudo random numbers | |
252 | - lib_array for packing/unpacking/printing arrays | |
253 | - lib_ascii for converting characters to ASCII codes | |
254 | ||
255 | ||
256 | libmawk 0.9.2 (released: 2010-12-12, r229) | |
257 | [libmawk] -Fix: invalid memory handling around cells | |
258 | [libmawk] -Fix: manual page dates and author and project/executable name | |
259 | [libmawk] -Add: dynamic awk function calls (call() and acall()) | |
260 | [libmawk] -Add: dynamic awk variable value fetch (valueof()) | |
261 | [libmawk] -Add: include | |
262 | ||
263 | libmawk 0.9.1 (released: 2009-08-14, r198) | |
264 | [API] -Add: remember userdata when registering and calling back c functions | |
265 | [API] -Add: option to suppress undefined function calls | |
266 | [API] -Add: new call allowing awk function calls without varargs | |
267 | [API] -Change: split up libmawk_initialize in 3 stages (optional) | |
268 | [libmawk] -Del: autotools, keep last generated Makefile for hand editing | |
269 | [libmawk] -Del: config.h (merged in Makefile.conf.in) | |
270 | [libmawk] -Rename: mawk -> lmawk (the binary) | |
271 | [libmawk] -Change: print cell prints integers without .000000 | |
272 | [testapp] -Move: testapp out from libmawk (new dir structure) | |
273 | [testapp] -Fix: stack handling bug | |
274 | [doc] -Add: manual pages for libmawk calls | |
275 | ||
276 | libmawk 0.9.0 (released: 2009-07-22, r146) | |
277 | * Initial release, based on mawk 1.3.3 | |
278 | * r3...r8 Separate libmawk_call() from execute(); allow undefined functions | |
279 | * r9...r42 globals to struct (reentrant) | |
280 | * r43...r92 rename non-static functions to have a mawk_ prefix | |
281 | * r92...r145 libmawk | |
282 |
0 | all: src/libmawk/Makefile.conf | |
1 | cd src && $(MAKE) | |
2 | ||
3 | install: src/libmawk/Makefile.conf | |
4 | cd src && $(MAKE) install | |
5 | cd doc && $(MAKE) install | |
6 | ||
7 | uninstall: | |
8 | cd src && $(MAKE) uninstall | |
9 | ||
10 | linstall: src/libmawk/Makefile.conf | |
11 | cd src && $(MAKE) linstall | |
12 | ||
13 | clean: | |
14 | cd src && $(MAKE) clean | |
15 | ||
16 | distclean: | |
17 | cd src && $(MAKE) distclean | |
18 | cd scconfig && $(MAKE) clean | |
19 | ||
20 | test: | |
21 | cd src && $(MAKE) test | |
22 | ||
23 | src/libmawk/Makefile.conf: | |
24 | @echo "Please run ./configure first."; false |
0 | 1. Introduction | |
1 | ||
2 | Libmawk is a fork of mawk 1.3.3, restructured for embedding. This means the | |
3 | user gets libmawk.h and libmawk.so and can embed awk scripting language | |
4 | in any application written in C. For more information, check out the web page | |
5 | at http://repo.hu/projects/libmawk and the documentation in doc/. | |
6 | ||
7 | 2. Requirements and compiling | |
8 | ||
9 | ANSI C compiler, POSIX shell and make are required for compiling libmawk. | |
10 | Bison should be installed for developing libmawk; if it is not installed, | |
11 | local changes to the grammar will be ingored. | |
12 | ||
13 | ./configure; make | |
14 | ||
15 | On top of usual scconfig arguments, ./configure accepts --numeric=TYPE, | |
16 | where TYPE is int or double. Default is double. This switch affects | |
17 | what type libmawk stores numbers in. | |
18 | ||
19 | 3. installation | |
20 | ||
21 | Run "make install" or "make linstall". The linstall version | |
22 | will use symlinks instead of actual copying of files which is useful if | |
23 | you develop libmawk, the library itself. | |
24 | ||
25 | Debian package can be installed from http://repo.hu/debian. | |
26 | ||
27 | 4. Compatibility with mawk | |
28 | ||
29 | Compatibility with mawk is maintained to some degree. Currently libmawk | |
30 | offers a small set of extra features on awk level while providing | |
31 | everything that mawk provides. A valid mawk script will work with | |
32 | libmawk/lmawk without modification. However, the new features will work | |
33 | only with libmawk/lmawk and not mawk, so portable scripts shouldn't | |
34 | depend on them. All extensions are clearly marked in the manual. | |
35 | ||
36 | Conclusion: libmawk will compile and install mawk executable, which is | |
37 | backward compatible with mawk executable but also adds some extension | |
38 | features. | |
39 | ||
40 | Awklib depends on one of the libmawk features (include), thus awklib | |
41 | scripts won't work with other awk implementations without tweaking. |
0 | Release notes for libmawk 1.0.0 | |
1 | ||
2 | This release introduces runlimits, better floating point handling on | |
3 | corner cases (i.e. NaN) and memory leak cleanups. | |
4 |
0 | all: | |
1 | ||
2 | include ../src/libmawk/Makefile.conf | |
3 | ||
4 | install: | |
5 | $(MKDIR) $(DOCDIR) | |
6 | $(CP) $(PWD)/*.html $(DOCDIR) |
0 | 1. update the changelog | |
1 | 2. update the release notes | |
2 | 3. change the version number in src/scconfig/hooks.c | |
3 | 4. test a fresh checkout | |
4 | 5. svn tag |
0 | 000. full doc rewrite | |
1 | ||
2 | Features: | |
3 | - c->awk func call should be able to pass arrays | |
4 | ||
5 | 00. vio rewrite | |
6 | - add all vio in a linked list in MAWK for garbage collection at mawk_uninit | |
7 | - add a force-clenup hook for this; but also replace mawk_close_out_pipes() | |
8 | - hooks? wrapper? | |
9 | - document file_name_rewrite | |
10 | - document vio | |
11 | ||
12 | 0. bugs | |
13 | - string ref crash: | |
14 | for(n = 0; n < 1000000; n++) A[n] = "foo" | |
15 | if refcount of "foo" reaches 65535, it crashes | |
16 | - mpow2 should be static | |
17 | ||
18 | 1. restrictions | |
19 | - detect and use LDFLAGS -dynamic | |
20 | - split compile and run into separate libs: | |
21 | - implement a Single Safe number->string converter; | |
22 | grep for OFMT and CONVFMT and INT_FMT to find all the buggy sprintf based | |
23 | implementations | |
24 | - split da_bin to exec and comp | |
25 | - fix error.c: it shouldn't depend on stdio.h and it shouldn't print | |
26 | to stderr anyway (incompatible with the lib idea) | |
27 | - check whether int-compiled lmawk handles OFMT/CONVFMT properly | |
28 | - floating point: | |
29 | - try to find a platform with FPE for overflow and test | |
30 | - consider a -W nandebug option so that the user knows where the script | |
31 | went wrong; but he could also just check from the script | |
32 | - if isinf() is avaialable, check for inf() result and convert them to nan | |
33 | ||
34 | ||
35 | 1.5. | |
36 | - check all zmalloc() and zrealloc() calls - they may return NULL and callers | |
37 | should return in that case so that runtime error takes over | |
38 | ||
39 | 2. porting | |
40 | - test on UNIX | |
41 | - provide a real alternative to realpath() | |
42 | ||
43 | 3.0 extend arrays | |
44 | - array copy | |
45 | - array in array (for orig implementation only?) | |
46 | - length(array) as in gawk? POSIX: length() works on strings only | |
47 | update test_3rd funlen accordingly! | |
48 | ||
49 | 3.1 features, minor bugs | |
50 | - debugging (gdb scripts); location-file instruction to track src file changes | |
51 | - consider printf with no arg to work like in gawk; also check posix about this | |
52 | test_3rd: printf0 | |
53 | - decide whether regex "^+" (and "^*"?) should be accepted and treated as | |
54 | plain + and * at the beginning of the string; update test_3rd reindops | |
55 | (check posix regex) | |
56 | - decide whether regex should support binary; related tests to update: | |
57 | test_3rd jared, regx8bit | |
58 | - posix FS point 3. requires that ^ work in FS; check test_3rd uparrfs | |
59 | - introduce a new symtab flag for remembering builtin vars and arrays; | |
60 | when -W dumpsym, do not dump these unless verbose | |
61 | - introduce a -W dumpallsym (for verbose symdumps) | |
62 | - write regression test for flush() (it used to pass the wrong pointer) | |
63 | ||
64 | 4. lib fineprint | |
65 | - expose mawk_append_input_file | |
66 | ||
67 | 5. optimization | |
68 | - mawk_find_bi_ptr(): use perfect hash instead of linear search | |
69 | does it really matter? | |
70 | - peephole: | |
71 | - 'print "a", a, "b", b, "c", c' results in push/cat pairs; | |
72 | make the parser emit a lot of pushes and replace cat with catN | |
73 | - 'expr = 1' will add a pop; there should be another type of assignment | |
74 | that doesn't push anything | |
75 | - replace tail recursion (call+ret) | |
76 |
0 | <HTML> | |
1 | <BODY> | |
2 | <H1> Why not using autotools </H1> | |
3 | <P> | |
4 | I believe autotools is the wrong designed and poor implementation, partly | |
5 | trying to solve the wrong problem. The fix for this is a better design. | |
6 | For example scconfig - which is the system that configures libmawk. It | |
7 | can do everything it needs to do (yes, including cross compilation). | |
8 | <P> | |
9 | Mawk generally dosn't require too many special things and should compile | |
10 | fine on POSIX systems. If it doesn't compile for you, you have the following | |
11 | choices: | |
12 | <OL> | |
13 | <LI> you can contact me, report bugs, so I can fix scconfig | |
14 | <LI> you can bypass scconfig and manually create Makefile.conf | |
15 | and conf.h for your system yourself (won't help much in | |
16 | fixing scconfig, tho) | |
17 | <LI> you can create and maintain your own autotools version (but official | |
18 | libmawk will not include support for autotools) | |
19 | </OL> | |
20 | </BODY> | |
21 | </HTML> |
0 | This directory hosts documentation about libmawk internals. | |
1 | ||
2 | These files are useful for developers of libmawk and in some specail | |
3 | case for application developers if they plan to use advanced features | |
4 | of libmawk. | |
5 |
0 | API: Virtual array vs. function | |
1 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | |
2 | ||
3 | 1. Introduction: virtual arrays | |
4 | ||
5 | Libmawk implements support for virtual arrays: arrays that do not simply | |
6 | store data in a hash. This feature is designed for maximal flexibility: | |
7 | awk arrays have a set of hooks (function pointers) and whenever the | |
8 | bytecode interpreter has to read, list or modify an array, it will | |
9 | call the hook functions. The original array implementation is just | |
10 | a set of hooks simply storing data without side effects. The ENVIRON[] | |
11 | array is set up with another set of hooks that syncs the environment | |
12 | with awk array (and calls the original hooks for the actual data storage). | |
13 | ||
14 | ||
15 | 2. API: arrays are function calls at the end of the day | |
16 | ||
17 | This also means that an application developer has two alternative paths | |
18 | to provide bindings to the application code: | |
19 | - explicit function calls | |
20 | - implicit function calls through an awk array | |
21 | ||
22 | For example if the application wants to expose direct I/O port access, | |
23 | it may: | |
24 | - implement functions io_out(port, value) and io_in(port) | |
25 | - implement an array IO[port] | |
26 | ||
27 | However, having side effects is usually not desirable. An awk program that | |
28 | uses functions not declared in the awk code makes it clear that these functions | |
29 | are external, whereas an array may be just a global awk variable, side effects | |
30 | are not obvious. | |
31 | ||
32 | ||
33 | 3. how to chose? | |
34 | ||
35 | While technically the two ways of the API design are equivalent in the sense | |
36 | that both end up in function calls, there are always considerations that | |
37 | may make one better than the other for a specific application. Below are | |
38 | the pros and cons: | |
39 | ||
40 | Function calls, pro: | |
41 | - easy to recognize external calls in the awk code | |
42 | - can implement much more than lookup, set and list | |
43 | - may provide faster listing | |
44 | ||
45 | Function calls, con: | |
46 | - longer awk source | |
47 | - when there are multiple different implementations under different names, | |
48 | an awk function that needs to operate on all may need to get a function | |
49 | name prefix and do dynamic function calls that makes the awk | |
50 | code look more complicated | |
51 | ||
52 | Array, pro: | |
53 | - simple and short awk code, especially for listing ("for in") | |
54 | - when there are multiple different implementation, passing one of them | |
55 | to an awk function (by reference) hides the differences, keeping awk | |
56 | function code simple | |
57 | - the whole set of data can be handled together: output of split, generic | |
58 | array print or load functions | |
59 | ||
60 | Array, con: | |
61 | - hidden side effects (risks awk source readability) | |
62 | - always have to implement lookup, set and list | |
63 | ||
64 | NOTE: a major advantage of arrays is listing (the "for in" construction). | |
65 | In mawk this is implemented by saving a list of all indices that exist at | |
66 | the time of entering the loop. While most of the time this means duplicating | |
67 | string references only, it may still be slow and may take considerable amount | |
68 | of memory if the array is large. What counts as large may vary, but generally | |
69 | a 10^6 indices may cause memory allocations in the megabyte range already. | |
70 | ||
71 | In practice the following considerations could easily decide the question: | |
72 | A. if there are more operations than lookup/set/list, use functions | |
73 | B. if only set/get is required, check if listing looks useful or not; | |
74 | if useful, go for arrays (where listing is done via "for in"); | |
75 | similarly: if there's a function based API for set/get/list, reconsider | |
76 | using an array instead of custom listing. Unless arrays are large! | |
77 | C. are generic array functions useful in common applications? If so, arrays | |
78 | may be better. Generic array functions include: | |
79 | - awk function that prints all indices of an array | |
80 | - awk function doing some complex lookup, e.g. regex search on all indices | |
81 | - loading the array from a string using split(); useful when indices | |
82 | are small integers, typically counting from 0 or 1 | |
83 | D. would there be alternative implementations and generic awk functions | |
84 | operating on them depending on their arguments? If so, arrays may be better | |
85 | as they can be passed as reference | |
86 | ||
87 | 4. examples | |
88 | ||
89 | According to these, the I/O port example is better implemented with functions | |
90 | as arrays offer no benefit in any of the above points: | |
91 | A. has only set and get, at this point arrays are as good as functions | |
92 | B. "for in" listing is not a typical application: array has no benefit | |
93 | C. printing all ports is rarely useful; complex lookups are not common; | |
94 | loading I/O space with split() is not useful; | |
95 | no obvious example of generic array code being useful on an IO array: | |
96 | array has no benefit | |
97 | D. having multiple alternative I/O spaces and passing one of these | |
98 | to an awk function as array is not probable: array has no benefit | |
99 | ||
100 | An example where array is more suitable is an interface for network interfaces | |
101 | (ifconfig): arrays NIC_IP[], NIC_NETMASK[], NIC_MTU[], etc, indexed by | |
102 | the name of the nic: | |
103 | A. has lookup, set and list; array is as good as functions | |
104 | B. it's a reasonable application to list all interfaces: "for in" is useful, | |
105 | array looks better | |
106 | C. printing all interfaces makes sense; complex lookup | |
107 | (e.g. "all alias interfaces") makes sense; loading the array may make | |
108 | sense (e.g. restoring network settings); split wouldn't work, tho; array | |
109 | looks better | |
110 | D. no obvious alternative arrays to be passed in arg; array has no benefit | |
111 | ||
112 | In point A. and D. arrays are not better than functions (but not worse either), | |
113 | but in B. and C. arrays definitely have an advantage for this app. |
0 | <HTML> | |
1 | <BODY> | |
2 | <h1> The Virtual Machine (VM) </h1> | |
3 | ||
4 | The VM lives in execute.c function mawk_execute_(). | |
5 | <p> | |
6 | In principle it takes an array of instructions (INST), executing them | |
7 | one by one, operating on the current <a href="stack.html"> evaluation | |
8 | stack</a> (or stack for short). Most of the execution really goes in | |
9 | order as the compiler prepares up everything to achieve linearity. | |
10 | This makes the execution loop relatively simple and efficient: it is | |
11 | just a large <i>while(dont_need_to_exit) execute_next_instruction;</i>. | |
12 | The actual instruction execution is a real large switch on the instruction | |
13 | opcode. | |
14 | <p> | |
15 | An usual example on how this is implemented in practice can be | |
16 | obtained by <i>lmawk -Wdump -f test.awk</i> on some simple arithmetic | |
17 | script: | |
18 | <table border=1> | |
19 | <tr><th> awk <th> asm (VM instructions) | |
20 | <tr> | |
21 | <td> | |
22 | <pre> | |
23 | BEGIN { a = 3 + 4 * 5 } | |
24 | </pre> | |
25 | <td> | |
26 | <pre> | |
27 | BEGIN | |
28 | 000 pusha a | |
29 | 002 pushd 3 | |
30 | 004 pushd 4 | |
31 | 006 pushd 5 | |
32 | 008 mul | |
33 | 009 add | |
34 | 010 assign | |
35 | 011 pop | |
36 | 012 exit0 | |
37 | </pre> | |
38 | </table> | |
39 | <p> | |
40 | First the lvalue (target variable, left side) of the assignment is pushed, | |
41 | then the expression (right side). The stack is, from top to down: {5, 4, 3, a}. | |
42 | The top of the stack is 5, the second element is 4 by the time <i>mul</i> runs. | |
43 | <i>Mul</i> will replace these two elements by 20, decreasing the stack size by | |
44 | one, leaving the result on the top. Next <i>add</i> does a similar job, | |
45 | replacing the top two items of the stack {20, 3} with their sum, 23. At | |
46 | the end <i>assign</i> runs on the stack {23, a}, removing both items, copying | |
47 | the value 23 to the global variable <i>a</i>. At the end it also puts | |
48 | the result on the top of the stack, leaving the stack as {23} - this is | |
49 | the result (output) of the assignment operation. Since the script doesn't | |
50 | need to use the result, it runs a <i>pop</i> that removes and discards | |
51 | the top item, leaving the stack empty. Since the script didn't have main | |
52 | or END parts, the script can quit at this point, executing the <i>exit0</i> | |
53 | instruction (exiting with value 0 - the implicit exit). | |
54 | <p> | |
55 | NOTE: currently there's absolutely no optimization in the parser: everything | |
56 | is calculated as written in the script and some values are saved just to be | |
57 | discarded by the next instruction. | |
58 | <p> | |
59 | An interesting and important feature of execute_() is that it can save all | |
60 | states and return to the caller <b>at any point</b> of the execution, i.e. | |
61 | between any two instruction in the code. It can also resume execution from | |
62 | the next instruction. This provides the host application full control over | |
63 | scheduling the script, while the script can be built of sequential, blocking | |
64 | instructions. | |
65 | ||
66 | <h2> Jumps and conditions </h2> | |
67 | ||
68 | There are a few instructions that have to break linear execution flow, tho: | |
69 | <ul> | |
70 | <li> <a href="parser_if.html"> if()</a> needs to make a jump depending on some condition | |
71 | <li> conditional code (e.g. <i>/^A/ { ... }</i>) is the same | |
72 | <li> range conditional code (e.g. <i>/^A/,/^B/ { ... }</i>) is still the same with some extra complications (internal state tracking whether the script is within the range) | |
73 | <li> <a href="parser_for.html">loops</a> obviously need to do a similar conditional jump back | |
74 | <li> function calls have to temporarily suspend executing the current code and jump to the function code from which a <i>ret</i> or <i>ret0</i> instruction jumps back | |
75 | </ul> | |
76 | <p> | |
77 | Some of the above are implemented using conditional and unconditional jumps | |
78 | to direct addresses (first column on the asm). For example a simple if | |
79 | is compiled to contain 2 jumps: | |
80 | <table border=1> | |
81 | <tr><th> awk <th> asm (VM instructions) | |
82 | <tr> | |
83 | <td> | |
84 | <pre> | |
85 | BEGIN { | |
86 | if (bool) | |
87 | a = 6 | |
88 | else | |
89 | a = 7 | |
90 | } | |
91 | </pre> | |
92 | <td> | |
93 | <pre> | |
94 | BEGIN | |
95 | 000 pushi bool | |
96 | 002 jz 012 | |
97 | 004 pusha a | |
98 | 006 pushd 6 | |
99 | 008 assign | |
100 | 009 pop | |
101 | 010 jmp 018 | |
102 | 012 pusha a | |
103 | 014 pushd 7 | |
104 | 016 assign | |
105 | 017 pop | |
106 | 018 exit0 | |
107 | </pre> | |
108 | </table> | |
109 | <p> | |
110 | The first one is a conditional jump, "jump if [top of the stack is] zero" | |
111 | (<i>jz</i>) - this makes the VM jump to the <i>else</i> branch at address 10. | |
112 | The <i>then</i> branch ends in an unconditional jump to the next instruction | |
113 | after the if (which is the implicit exit in this example), bypassing | |
114 | the code of the <i>else</i> branch. | |
115 | <p> | |
116 | A jump is carried out by a simple modification of the "next instruction" | |
117 | pointer before running the next iteration of the execution loop. | |
118 | ||
119 | <h2> Recursion: function calls </h2> | |
120 | ||
121 | A slightly more complicated mechanism is used when jumps are of recursive | |
122 | nature: the code has to jump to somewhere to do some work and then | |
123 | return here and continue execution from the next instruction. A typical | |
124 | example on this is executing user functions. | |
125 | <p> | |
126 | The original mawk implementation simply called mawk_execute_() recursively. | |
127 | This meant the C compiler took care of saving all internal states on the | |
128 | C stack for the detour. However, this wouldn't allow the code to be suspended | |
129 | during such detour as it would be problematic to rebuild the C stack on a resume. | |
130 | <p> | |
131 | Thus libmawk's mawk_execute_() does not recurse on C level but on VM level. | |
132 | For example when a function is called (using the <i>call</i> instruction): | |
133 | <ul> | |
134 | <li> 1. prepare the eval stack for the function (as mawk did): push arguments and local variables | |
135 | <li> 2. push execution state on top of the eval stack | |
136 | <li> 3. unconditional jump to the function body | |
137 | </ul> | |
138 | <p> | |
139 | Upon a <i>ret</i> instruction from the function: | |
140 | <ul> | |
141 | <li> 1. save and remove the return value from the top of the stack | |
142 | <li> 2. restore previous execution state from the top of the stack | |
143 | <li> 3. remove all arguments and local variables from the stack (remove the frame) | |
144 | <li> 4. push the return value on top of the stack | |
145 | <li> 5. continue execution normally - because step 2., this will run the instruction right after the <i>call</i> | |
146 | </ul> | |
147 | ||
148 | <h3> additional cases of recursion </h3> | |
149 | A range pattern is recursive as well: it needs to evaluate one or two pattern | |
150 | matching before it decides whether to execute the action and/or update | |
151 | the state. The range check starts with instruction _RANGE_CHK which | |
152 | encodes expression code offsets and state in the next few instruction slots. It | |
153 | recurses to evaluate expressions which are terminated by the _RANGE_STOP command. | |
154 | Entering an expression evaluation is similar to a function call while | |
155 | _RANGE_STOP is very similar to a ret. | |
156 | ||
157 | <h3> deep recursion </h3> | |
158 | At any time the eval stack has to have enough space after sp for | |
159 | evaluation the longest awk expression. Any user function recursion will | |
160 | bump sp leaving less room for expressions and further recursion. Relocating | |
161 | the stack (with a realloc()) is not a good idea as there might be cell | |
162 | pointers pointing to stack elements all around. | |
163 | ||
164 | Instead, mawk limits expression length in compile time to a fixed | |
165 | maximum. If entering a new function would not leave at list this | |
166 | amount of eval stack above sp, "deep recursion" is performed. This | |
167 | starts by allocating an entire new stack for the call. Call stacking | |
168 | saves enough pointers so that the code can switch back to the | |
169 | previous stack easily. The allocation is done using zmalloc(), the overhead | |
170 | is minimal. Since the original stack/stacks is/are kept intact, any | |
171 | pointer stays valid. sp points into the new stack block and will increase | |
172 | there until another deep recursion. | |
173 | ||
174 | This wastes some stack space on the old stack (potentially max expression | |
175 | length minus one slot) but guarantees that: | |
176 | - checks and special things need to be done only at entering/leaving functions | |
177 | - even that happens rarely as a stack block is large enough to host | |
178 | many functions besides the longest expression | |
179 | - the stack can grow as big as it likes to, without having to allocate | |
180 | one large block of memory | |
181 | - all allocation is done from normal instance memory - allocation limit, | |
182 | and auto cleanup at the end are granted | |
183 | ||
184 | <h2> Resuming execute_() </h2> | |
185 | ||
186 | Since the far most common thing in an embedded setup is to resume a | |
187 | code interrupted by execution limit or a blocking getline, mawk_execute_() is | |
188 | doing that by default. The top few slots in the eval stack is always a full | |
189 | state dump, the same thing used in recursion. Entering mawk_execute_() pops this | |
190 | section and initializes all internal states from it. When execution needs | |
191 | to be interrupted, mawk_execute_() saves internal states onto the top | |
192 | of the stack. | |
193 | ||
194 | <h2> Entering execute_() (fresh start) </h2> | |
195 | ||
196 | Entering in run state involves setting up internal states pointing to | |
197 | the beginning of the code in question, pushing these states on top of | |
198 | the stack and calling mawk_execute_() which will "resume" from these states. | |
199 | Similar thing happens when the application calls an awk function. | |
200 | <p> | |
201 | It may be that the execution is interrupted in the middle of running of | |
202 | a large block of code, for example in BEGIN. The top of the stack holds | |
203 | the current execution state so that mawk_execute_() will be able to | |
204 | continue execution. The application may decide to run an awk | |
205 | function before resuming the code: this operation would push a new | |
206 | set of execution state on top of the stack and call mawk_execute_(). | |
207 | When the current state finishes at the _RET instruction, mawk_execute_() | |
208 | would take the next frame from the stack and would automatically resume | |
209 | execution of the interrupted BEGIN block. This would cause the return value | |
210 | of the function to be lost and would attempt to resume BEGIN as a side effect | |
211 | of the function call! | |
212 | <p> | |
213 | To avoid such confusion, any new enter to mawk_execute_() is required to | |
214 | push two sets of states: an EXEST_EXIT and the actual state it wants | |
215 | to "resume" at (start execution at). When mawk_execute_() hits the _RET | |
216 | instruction in the above example, it does pop the next frame, but that | |
217 | frame would be the EXEST_EXIT which would cause it to interrupt immediately. | |
218 | This leaves the stack exactly as it looked like before the function call, | |
219 | and the application later may decide to resume execution. | |
220 | <p> | |
221 | Fresh start entries: | |
222 | <ul> | |
223 | <li> running BEGIN (last stage of initialization) | |
224 | <li> running main on new input, in non-interrupted state | |
225 | <li> running END (first stage of uninitialization) | |
226 | <li> an awk function is called by the application | |
227 | </ul> | |
228 | ||
229 | ||
230 |
0 | <!-- Creator : groff version 1.22.2 --> | |
1 | <!-- CreationDate: Sat Jun 14 14:27:30 2014 --> | |
2 | <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" | |
3 | "http://www.w3.org/TR/html4/loose.dtd"> | |
4 | <html> | |
5 | <head> | |
6 | <meta name="generator" content="groff -Thtml, see www.gnu.org"> | |
7 | <meta http-equiv="Content-Type" content="text/html; charset=US-ASCII"> | |
8 | <meta name="Content-Style" content="text/css"> | |
9 | <style type="text/css"> | |
10 | p { margin-top: 0; margin-bottom: 0; vertical-align: top } | |
11 | pre { margin-top: 0; margin-bottom: 0; vertical-align: top } | |
12 | table { margin-top: 0; margin-bottom: 0; vertical-align: top } | |
13 | h1 { text-align: center } | |
14 | </style> | |
15 | <title>EXAMPLE</title> | |
16 | ||
17 | </head> | |
18 | <body> | |
19 | ||
20 | <h1 align="center">EXAMPLE</h1> | |
21 | ||
22 | <a href="#NAME">NAME</a><br> | |
23 | <a href="#SYNOPSIS">SYNOPSIS</a><br> | |
24 | <a href="#DESCRIPTION">DESCRIPTION</a><br> | |
25 | <a href="#Example application">Example application</a><br> | |
26 | ||
27 | <hr> | |
28 | ||
29 | ||
30 | <h2>NAME | |
31 | <a name="NAME"></a> | |
32 | </h2> | |
33 | ||
34 | ||
35 | <p style="margin-left:11%; margin-top: 1em">libmawk example | |
36 | − how to use the library</p> | |
37 | ||
38 | <h2>SYNOPSIS | |
39 | <a name="SYNOPSIS"></a> | |
40 | </h2> | |
41 | ||
42 | ||
43 | <p style="margin-left:11%; margin-top: 1em"><b>#include | |
44 | <libmawk.h></b></p> | |
45 | ||
46 | <h2>DESCRIPTION | |
47 | <a name="DESCRIPTION"></a> | |
48 | </h2> | |
49 | ||
50 | ||
51 | <p style="margin-left:11%; margin-top: 1em">Libmawk is a | |
52 | library that lets applications to embed awk scripts using | |
53 | the code of the popular implementation <b>mawk.</b> The | |
54 | normal process is to call libmawk_initialize() to set up a | |
55 | new mawk context (with script(s) loaded), then in the main | |
56 | loop feed it using libmawk_append_input(). For "out of | |
57 | band" communication, the program may also call | |
58 | functions implemented in awk and read (or modify) global | |
59 | variables of the awk script. The hos tapplication usally | |
60 | will also bind some of its functions to the context using | |
61 | libmawk_register_function, which allows the awk script to | |
62 | call the host applicaiton’s functions directly as they | |
63 | were awk builtins or user defined functions. After the main | |
64 | loop, the application destroys the context freeing up all | |
65 | memory allocated for the script(s).</p> | |
66 | ||
67 | <p style="margin-left:11%; margin-top: 1em">One context is | |
68 | for one awk program. One awk program may consist of multiple | |
69 | script files (just as with command line awk, with multiple | |
70 | -f filename arguments). Libmawk is instance safe, the host | |
71 | application may create multiple instances of contexts with | |
72 | the same or with different set of awk scripts loaded. These | |
73 | contexts are totally separate, no variables, functions or | |
74 | any sort of states are shared. However, the host application | |
75 | may provide means of communication between those scripts by | |
76 | custom functions or by copying variable contents between | |
77 | them.</p> | |
78 | ||
79 | <h2>Example application | |
80 | <a name="Example application"></a> | |
81 | </h2> | |
82 | ||
83 | ||
84 | <p style="margin-left:11%; margin-top: 1em">The following | |
85 | example application creates a single context to demonstrate | |
86 | all the above mentioned functionality. <br> | |
87 | #include <stdio.h> <br> | |
88 | #include <libmawk.h></p> | |
89 | ||
90 | <p style="margin-left:11%; margin-top: 1em">CELL | |
91 | *blobb(mawk_state_t *context, CELL * sp, int a_args) <br> | |
92 | {</p> | |
93 | ||
94 | <table width="100%" border="0" rules="none" frame="void" | |
95 | cellspacing="0" cellpadding="0"> | |
96 | <tr valign="top" align="left"> | |
97 | <td width="8%"></td> | |
98 | <td width="7%"></td> | |
99 | <td width="8%"> | |
100 | ||
101 | ||
102 | <p>int n;</p></td> | |
103 | <td width="77%"> | |
104 | </td></tr> | |
105 | <tr valign="top" align="left"> | |
106 | <td width="8%"></td> | |
107 | <td width="7%"></td> | |
108 | <td width="8%"> | |
109 | ||
110 | ||
111 | <p>char buff[64];</p></td> | |
112 | <td width="77%"> | |
113 | </td></tr> | |
114 | <tr valign="top" align="left"> | |
115 | <td width="8%"></td> | |
116 | <td width="7%"></td> | |
117 | <td width="8%"> | |
118 | ||
119 | ||
120 | <p>/* do something - print BLOBB and all arguments */</p></td> | |
121 | <td width="77%"> | |
122 | </td></tr> | |
123 | <tr valign="top" align="left"> | |
124 | <td width="8%"></td> | |
125 | <td width="7%"></td> | |
126 | <td width="8%"> | |
127 | ||
128 | ||
129 | <p>printf("BLOBB! ");</p></td> | |
130 | <td width="77%"> | |
131 | </td></tr> | |
132 | <tr valign="top" align="left"> | |
133 | <td width="8%"></td> | |
134 | <td width="7%"></td> | |
135 | <td width="8%"> | |
136 | ||
137 | ||
138 | <p>for(n = a_args-1; n >= 0; n--)</p></td> | |
139 | <td width="77%"> | |
140 | </td></tr> | |
141 | <tr valign="top" align="left"> | |
142 | <td width="8%"></td> | |
143 | <td width="7%"> | |
144 | </td> | |
145 | <td width="8%"> | |
146 | </td> | |
147 | <td width="77%"> | |
148 | ||
149 | ||
150 | <p>printf("%d=’%s’ ", n, | |
151 | libmawk_print_cell((sp-n), buff, sizeof(buff)));</p></td></tr> | |
152 | <tr valign="top" align="left"> | |
153 | <td width="8%"></td> | |
154 | <td width="7%"></td> | |
155 | <td width="8%"> | |
156 | ||
157 | ||
158 | <p>printf("0);</p></td> | |
159 | <td width="77%"> | |
160 | </td></tr> | |
161 | <tr valign="top" align="left"> | |
162 | <td width="8%"></td> | |
163 | <td width="7%"></td> | |
164 | <td width="8%"> | |
165 | ||
166 | ||
167 | <p>/* restore the stack (remove all arguments) */</p></td> | |
168 | <td width="77%"> | |
169 | </td></tr> | |
170 | <tr valign="top" align="left"> | |
171 | <td width="8%"></td> | |
172 | <td width="7%"></td> | |
173 | <td width="8%"> | |
174 | ||
175 | ||
176 | <p>sp = sp - a_args;</p></td> | |
177 | <td width="77%"> | |
178 | </td></tr> | |
179 | <tr valign="top" align="left"> | |
180 | <td width="8%"></td> | |
181 | <td width="7%"></td> | |
182 | <td width="8%"> | |
183 | ||
184 | ||
185 | <p>/* set a return value (find out where the return value | |
186 | is on the stack,</p></td> | |
187 | <td width="77%"> | |
188 | </td></tr> | |
189 | <tr valign="top" align="left"> | |
190 | <td width="8%"></td> | |
191 | <td width="7%"></td> | |
192 | <td width="8%"> | |
193 | ||
194 | ||
195 | <p>using libmawk_stackret()) */</p></td> | |
196 | <td width="77%"> | |
197 | </td></tr> | |
198 | <tr valign="top" align="left"> | |
199 | <td width="8%"></td> | |
200 | <td width="7%"></td> | |
201 | <td width="8%"> | |
202 | ||
203 | ||
204 | <p>libmawk_set_cell(context, libmawk_stackret(sp), | |
205 | ’f’, (double)1234);</p></td> | |
206 | <td width="77%"> | |
207 | </td></tr> | |
208 | <tr valign="top" align="left"> | |
209 | <td width="8%"></td> | |
210 | <td width="7%"></td> | |
211 | <td width="8%"> | |
212 | ||
213 | ||
214 | <p>/* return the new stack pointer - should be the one that | |
215 | it was before</p></td> | |
216 | <td width="77%"> | |
217 | </td></tr> | |
218 | <tr valign="top" align="left"> | |
219 | <td width="8%"></td> | |
220 | <td width="7%"></td> | |
221 | <td width="8%"> | |
222 | ||
223 | ||
224 | <p>arguments had been pushed on the stack */</p></td> | |
225 | <td width="77%"> | |
226 | </td></tr> | |
227 | <tr valign="top" align="left"> | |
228 | <td width="8%"></td> | |
229 | <td width="7%"></td> | |
230 | <td width="8%"> | |
231 | ||
232 | ||
233 | <p>return sp;</p></td> | |
234 | <td width="77%"> | |
235 | </td></tr> | |
236 | </table> | |
237 | ||
238 | <p style="margin-left:11%;">}</p> | |
239 | ||
240 | <p style="margin-left:11%; margin-top: 1em">int main(int | |
241 | argc, char **argv) <br> | |
242 | {</p> | |
243 | ||
244 | <table width="100%" border="0" rules="none" frame="void" | |
245 | cellspacing="0" cellpadding="0"> | |
246 | <tr valign="top" align="left"> | |
247 | <td width="8%"></td> | |
248 | <td width="92%"> | |
249 | ||
250 | ||
251 | <p>mawk_state_t *m;</p></td></tr> | |
252 | <tr valign="top" align="left"> | |
253 | <td width="8%"></td> | |
254 | <td width="92%"> | |
255 | ||
256 | ||
257 | <p>CELL ret, arrv, *vr;</p></td></tr> | |
258 | <tr valign="top" align="left"> | |
259 | <td width="8%"></td> | |
260 | <td width="92%"> | |
261 | ||
262 | ||
263 | <p>char buff[64];</p></td></tr> | |
264 | </table> | |
265 | ||
266 | <p style="margin-left:11%; margin-top: 1em">/* the simpler | |
267 | way is:</p> | |
268 | ||
269 | <table width="100%" border="0" rules="none" frame="void" | |
270 | cellspacing="0" cellpadding="0"> | |
271 | <tr valign="top" align="left"> | |
272 | <td width="8%"></td> | |
273 | <td width="92%"> | |
274 | ||
275 | ||
276 | <p>m = libmawk_initialize(argc, argv);</p></td></tr> | |
277 | <tr valign="top" align="left"> | |
278 | <td width="8%"></td> | |
279 | <td width="92%"> | |
280 | ||
281 | ||
282 | <p>However, if the application wants to change the | |
283 | environment before</p></td></tr> | |
284 | <tr valign="top" align="left"> | |
285 | <td width="8%"></td> | |
286 | <td width="92%"> | |
287 | ||
288 | ||
289 | <p>executing BEGIN, the following, 3 stage initialization | |
290 | should be done:</p></td></tr> | |
291 | </table> | |
292 | ||
293 | <p style="margin-left:11%;">*/</p> | |
294 | ||
295 | <table width="100%" border="0" rules="none" frame="void" | |
296 | cellspacing="0" cellpadding="0"> | |
297 | <tr valign="top" align="left"> | |
298 | <td width="8%"></td> | |
299 | <td width="7%"></td> | |
300 | <td width="8%"> | |
301 | ||
302 | ||
303 | <p>m = libmawk_initialize_stage1(); /* set up m */</p></td> | |
304 | <td width="8%"></td> | |
305 | <td width="7%"></td> | |
306 | <td width="62%"> | |
307 | </td></tr> | |
308 | <tr valign="top" align="left"> | |
309 | <td width="8%"></td> | |
310 | <td width="7%"></td> | |
311 | <td width="8%"> | |
312 | ||
313 | ||
314 | <p>custom_array_init(m); /* set up a new builtin array with | |
315 | side effects, before parsing scripts */</p></td> | |
316 | <td width="8%"></td> | |
317 | <td width="7%"></td> | |
318 | <td width="62%"> | |
319 | </td></tr> | |
320 | <tr valign="top" align="left"> | |
321 | <td width="8%"></td> | |
322 | <td width="7%"></td> | |
323 | <td width="8%"> | |
324 | ||
325 | ||
326 | <p>m = libmawk_initialize_stage2(m, argc, argv); /* parse | |
327 | args loads the script(s) */</p></td> | |
328 | <td width="8%"></td> | |
329 | <td width="7%"></td> | |
330 | <td width="62%"> | |
331 | </td></tr> | |
332 | <tr valign="top" align="left"> | |
333 | <td width="8%"></td> | |
334 | <td width="7%"></td> | |
335 | <td width="8%"> | |
336 | ||
337 | ||
338 | <p>m = libmawk_initialize_stage3(m); /* execute BEGIN {} | |
339 | */</p> </td> | |
340 | <td width="8%"></td> | |
341 | <td width="7%"></td> | |
342 | <td width="62%"> | |
343 | </td></tr> | |
344 | <tr valign="top" align="left"> | |
345 | <td width="8%"></td> | |
346 | <td width="7%"></td> | |
347 | <td width="8%"> | |
348 | ||
349 | ||
350 | <p>ret.type = C_NOINIT;</p></td> | |
351 | <td width="8%"></td> | |
352 | <td width="7%"></td> | |
353 | <td width="62%"> | |
354 | </td></tr> | |
355 | <tr valign="top" align="left"> | |
356 | <td width="8%"></td> | |
357 | <td width="7%"></td> | |
358 | <td width="8%"> | |
359 | ||
360 | ||
361 | <p>if (m != NULL) {</p></td> | |
362 | <td width="8%"></td> | |
363 | <td width="7%"></td> | |
364 | <td width="62%"> | |
365 | </td></tr> | |
366 | <tr valign="top" align="left"> | |
367 | <td width="8%"></td> | |
368 | <td width="7%"> | |
369 | </td> | |
370 | <td width="8%"> | |
371 | </td> | |
372 | <td width="8%"> | |
373 | ||
374 | ||
375 | <p>/* test function call */</p></td> | |
376 | <td width="7%"></td> | |
377 | <td width="62%"> | |
378 | </td></tr> | |
379 | <tr valign="top" align="left"> | |
380 | <td width="8%"></td> | |
381 | <td width="7%"> | |
382 | </td> | |
383 | <td width="8%"> | |
384 | </td> | |
385 | <td width="8%"> | |
386 | ||
387 | ||
388 | <p>if (libmawk_call_function(m, "func", &ret, | |
389 | "dfs", (int)42, (double)1.234, (char *)"test | |
390 | string.") == 0) {</p></td> | |
391 | <td width="7%"></td> | |
392 | <td width="62%"> | |
393 | </td></tr> | |
394 | <tr valign="top" align="left"> | |
395 | <td width="8%"></td> | |
396 | <td width="7%"> | |
397 | </td> | |
398 | <td width="8%"> | |
399 | </td> | |
400 | <td width="8%"> | |
401 | </td> | |
402 | <td width="7%"> | |
403 | ||
404 | ||
405 | <p>printf("Return value of func is ’%s’0, | |
406 | libmawk_print_cell(&ret, buff, sizeof(buff)));</p></td> | |
407 | <td width="62%"> | |
408 | </td></tr> | |
409 | <tr valign="top" align="left"> | |
410 | <td width="8%"></td> | |
411 | <td width="7%"> | |
412 | </td> | |
413 | <td width="8%"> | |
414 | </td> | |
415 | <td width="8%"> | |
416 | </td> | |
417 | <td width="7%"> | |
418 | ||
419 | ||
420 | <p>libmawk_cell_destroy(m, &ret);</p></td> | |
421 | <td width="62%"> | |
422 | </td></tr> | |
423 | <tr valign="top" align="left"> | |
424 | <td width="8%"></td> | |
425 | <td width="7%"> | |
426 | </td> | |
427 | <td width="8%"> | |
428 | </td> | |
429 | <td width="8%"> | |
430 | ||
431 | ||
432 | <p>}</p></td> | |
433 | <td width="7%"></td> | |
434 | <td width="62%"> | |
435 | </td></tr> | |
436 | <tr valign="top" align="left"> | |
437 | <td width="8%"></td> | |
438 | <td width="7%"> | |
439 | </td> | |
440 | <td width="8%"> | |
441 | </td> | |
442 | <td width="8%"> | |
443 | ||
444 | ||
445 | <p>printf("Failed to call func()0);</p></td> | |
446 | <td width="7%"></td> | |
447 | <td width="62%"> | |
448 | </td></tr> | |
449 | <tr valign="top" align="left"> | |
450 | <td width="8%"></td> | |
451 | <td width="7%"> | |
452 | </td> | |
453 | <td width="8%"> | |
454 | </td> | |
455 | <td width="8%"> | |
456 | ||
457 | ||
458 | <p>/* this is the same function call with a different | |
459 | syntax */</p></td> | |
460 | <td width="7%"></td> | |
461 | <td width="62%"> | |
462 | </td></tr> | |
463 | <tr valign="top" align="left"> | |
464 | <td width="8%"></td> | |
465 | <td width="7%"> | |
466 | </td> | |
467 | <td width="8%"> | |
468 | </td> | |
469 | <td width="8%"> | |
470 | ||
471 | ||
472 | <p>{</p></td> | |
473 | <td width="7%"></td> | |
474 | <td width="62%"> | |
475 | </td></tr> | |
476 | <tr valign="top" align="left"> | |
477 | <td width="8%"></td> | |
478 | <td width="7%"> | |
479 | </td> | |
480 | <td width="8%"> | |
481 | </td> | |
482 | <td width="8%"> | |
483 | </td> | |
484 | <td width="7%"> | |
485 | ||
486 | ||
487 | <p>int i = 42;</p></td> | |
488 | <td width="62%"> | |
489 | </td></tr> | |
490 | <tr valign="top" align="left"> | |
491 | <td width="8%"></td> | |
492 | <td width="7%"> | |
493 | </td> | |
494 | <td width="8%"> | |
495 | </td> | |
496 | <td width="8%"> | |
497 | </td> | |
498 | <td width="7%"> | |
499 | ||
500 | ||
501 | <p>double d = 1.234;</p></td> | |
502 | <td width="62%"> | |
503 | </td></tr> | |
504 | <tr valign="top" align="left"> | |
505 | <td width="8%"></td> | |
506 | <td width="7%"> | |
507 | </td> | |
508 | <td width="8%"> | |
509 | </td> | |
510 | <td width="8%"> | |
511 | </td> | |
512 | <td width="7%"> | |
513 | ||
514 | ||
515 | <p>char *s = "test string.";</p></td> | |
516 | <td width="62%"> | |
517 | </td></tr> | |
518 | <tr valign="top" align="left"> | |
519 | <td width="8%"></td> | |
520 | <td width="7%"> | |
521 | </td> | |
522 | <td width="8%"> | |
523 | </td> | |
524 | <td width="8%"> | |
525 | </td> | |
526 | <td width="7%"> | |
527 | ||
528 | ||
529 | <p>void *args[] = {&i, &d, s};</p></td> | |
530 | <td width="62%"> | |
531 | </td></tr> | |
532 | <tr valign="top" align="left"> | |
533 | <td width="8%"></td> | |
534 | <td width="7%"> | |
535 | </td> | |
536 | <td width="8%"> | |
537 | </td> | |
538 | <td width="8%"> | |
539 | </td> | |
540 | <td width="7%"> | |
541 | ||
542 | ||
543 | <p>if (libmawk_call_functionp(m, "func", | |
544 | &ret, "dfs", args) != 0) {</p></td> | |
545 | <td width="62%"> | |
546 | </td></tr> | |
547 | <tr valign="top" align="left"> | |
548 | <td width="8%"></td> | |
549 | <td width="7%"> | |
550 | </td> | |
551 | <td width="8%"> | |
552 | </td> | |
553 | <td width="8%"> | |
554 | </td> | |
555 | <td width="7%"> | |
556 | </td> | |
557 | <td width="62%"> | |
558 | ||
559 | ||
560 | <p>printf("Return value of func is ’%s’0, | |
561 | libmawk_print_cell(&ret, buff, sizeof(buff)));</p></td></tr> | |
562 | <tr valign="top" align="left"> | |
563 | <td width="8%"></td> | |
564 | <td width="7%"> | |
565 | </td> | |
566 | <td width="8%"> | |
567 | </td> | |
568 | <td width="8%"> | |
569 | </td> | |
570 | <td width="7%"> | |
571 | </td> | |
572 | <td width="62%"> | |
573 | ||
574 | ||
575 | <p>libmawk_cell_destroy(m, &ret);</p></td></tr> | |
576 | <tr valign="top" align="left"> | |
577 | <td width="8%"></td> | |
578 | <td width="7%"> | |
579 | </td> | |
580 | <td width="8%"> | |
581 | </td> | |
582 | <td width="8%"> | |
583 | </td> | |
584 | <td width="7%"> | |
585 | ||
586 | ||
587 | <p>}</p></td> | |
588 | <td width="62%"> | |
589 | </td></tr> | |
590 | <tr valign="top" align="left"> | |
591 | <td width="8%"></td> | |
592 | <td width="7%"> | |
593 | </td> | |
594 | <td width="8%"> | |
595 | </td> | |
596 | <td width="8%"> | |
597 | ||
598 | ||
599 | <p>}</p></td> | |
600 | <td width="7%"></td> | |
601 | <td width="62%"> | |
602 | </td></tr> | |
603 | <tr valign="top" align="left"> | |
604 | <td width="8%"></td> | |
605 | <td width="7%"> | |
606 | </td> | |
607 | <td width="8%"> | |
608 | </td> | |
609 | <td width="8%"> | |
610 | ||
611 | ||
612 | <p>/* register a C function (resolved runtime) */</p></td> | |
613 | <td width="7%"></td> | |
614 | <td width="62%"> | |
615 | </td></tr> | |
616 | <tr valign="top" align="left"> | |
617 | <td width="8%"></td> | |
618 | <td width="7%"> | |
619 | </td> | |
620 | <td width="8%"> | |
621 | </td> | |
622 | <td width="8%"> | |
623 | ||
624 | ||
625 | <p>if (libmawk_register_function(m, "blobb", | |
626 | blobb) != 0) {</p></td> | |
627 | <td width="7%"></td> | |
628 | <td width="62%"> | |
629 | </td></tr> | |
630 | <tr valign="top" align="left"> | |
631 | <td width="8%"></td> | |
632 | <td width="7%"> | |
633 | </td> | |
634 | <td width="8%"> | |
635 | </td> | |
636 | <td width="8%"> | |
637 | </td> | |
638 | <td width="7%"> | |
639 | ||
640 | ||
641 | <p>fprintf(stderr, "ERROR: Unable to register function | |
642 | blobb0);</p> </td> | |
643 | <td width="62%"> | |
644 | </td></tr> | |
645 | <tr valign="top" align="left"> | |
646 | <td width="8%"></td> | |
647 | <td width="7%"> | |
648 | </td> | |
649 | <td width="8%"> | |
650 | </td> | |
651 | <td width="8%"> | |
652 | ||
653 | ||
654 | <p>}</p></td> | |
655 | <td width="7%"></td> | |
656 | <td width="62%"> | |
657 | </td></tr> | |
658 | <tr valign="top" align="left"> | |
659 | <td width="8%"></td> | |
660 | <td width="7%"> | |
661 | </td> | |
662 | <td width="8%"> | |
663 | </td> | |
664 | <td width="8%"> | |
665 | ||
666 | ||
667 | <p>/* run some data */</p></td> | |
668 | <td width="7%"></td> | |
669 | <td width="62%"> | |
670 | </td></tr> | |
671 | <tr valign="top" align="left"> | |
672 | <td width="8%"></td> | |
673 | <td width="7%"> | |
674 | </td> | |
675 | <td width="8%"> | |
676 | </td> | |
677 | <td width="8%"> | |
678 | ||
679 | ||
680 | <p>libmawk_append_input(m, "This is a0ultiline test | |
681 | input0ut in the artificial input buffer.0);</p></td> | |
682 | <td width="7%"></td> | |
683 | <td width="62%"> | |
684 | </td></tr> | |
685 | <tr valign="top" align="left"> | |
686 | <td width="8%"></td> | |
687 | <td width="7%"> | |
688 | </td> | |
689 | <td width="8%"> | |
690 | </td> | |
691 | <td width="8%"> | |
692 | ||
693 | ||
694 | <p>libmawk_run_main(m);</p></td> | |
695 | <td width="7%"></td> | |
696 | <td width="62%"> | |
697 | </td></tr> | |
698 | <tr valign="top" align="left"> | |
699 | <td width="8%"></td> | |
700 | <td width="7%"> | |
701 | </td> | |
702 | <td width="8%"> | |
703 | </td> | |
704 | <td width="8%"> | |
705 | ||
706 | ||
707 | <p>/* print var: scalar */</p></td> | |
708 | <td width="7%"></td> | |
709 | <td width="62%"> | |
710 | </td></tr> | |
711 | <tr valign="top" align="left"> | |
712 | <td width="8%"></td> | |
713 | <td width="7%"> | |
714 | </td> | |
715 | <td width="8%"> | |
716 | </td> | |
717 | <td width="8%"> | |
718 | ||
719 | ||
720 | <p>vr = libmawk_get_var(m, "var");</p></td> | |
721 | <td width="7%"></td> | |
722 | <td width="62%"> | |
723 | </td></tr> | |
724 | <tr valign="top" align="left"> | |
725 | <td width="8%"></td> | |
726 | <td width="7%"> | |
727 | </td> | |
728 | <td width="8%"> | |
729 | </td> | |
730 | <td width="8%"> | |
731 | ||
732 | ||
733 | <p>if (vr != NULL)</p></td> | |
734 | <td width="7%"></td> | |
735 | <td width="62%"> | |
736 | </td></tr> | |
737 | <tr valign="top" align="left"> | |
738 | <td width="8%"></td> | |
739 | <td width="7%"> | |
740 | </td> | |
741 | <td width="8%"> | |
742 | </td> | |
743 | <td width="8%"> | |
744 | </td> | |
745 | <td width="7%"> | |
746 | ||
747 | ||
748 | <p>printf("Variable var = ’%s’0, | |
749 | libmawk_print_cell(vr, buff, sizeof(buff)));</p></td> | |
750 | <td width="62%"> | |
751 | </td></tr> | |
752 | <tr valign="top" align="left"> | |
753 | <td width="8%"></td> | |
754 | <td width="7%"> | |
755 | </td> | |
756 | <td width="8%"> | |
757 | </td> | |
758 | <td width="8%"> | |
759 | ||
760 | ||
761 | <p>else</p></td> | |
762 | <td width="7%"></td> | |
763 | <td width="62%"> | |
764 | </td></tr> | |
765 | <tr valign="top" align="left"> | |
766 | <td width="8%"></td> | |
767 | <td width="7%"> | |
768 | </td> | |
769 | <td width="8%"> | |
770 | </td> | |
771 | <td width="8%"> | |
772 | </td> | |
773 | <td width="7%"> | |
774 | ||
775 | ||
776 | <p>printf("No such variable</p></td> | |
777 | <td width="62%"> | |
778 | </td></tr> | |
779 | <tr valign="top" align="left"> | |
780 | <td width="8%"></td> | |
781 | <td width="7%"> | |
782 | </td> | |
783 | <td width="8%"> | |
784 | </td> | |
785 | <td width="8%"> | |
786 | ||
787 | ||
788 | <p>/* print var: array */</p></td> | |
789 | <td width="7%"></td> | |
790 | <td width="62%"> | |
791 | </td></tr> | |
792 | </table> | |
793 | ||
794 | <p style="margin-left:11%;">#warning TODO</p> | |
795 | ||
796 | <table width="100%" border="0" rules="none" frame="void" | |
797 | cellspacing="0" cellpadding="0"> | |
798 | <tr valign="top" align="left"> | |
799 | <td width="8%"></td> | |
800 | <td width="7%"> | |
801 | </td> | |
802 | <td width="8%"> | |
803 | </td> | |
804 | <td width="8%"> | |
805 | ||
806 | ||
807 | <p>arrv.type = C_NOINIT;</p></td> | |
808 | <td width="69%"> | |
809 | </td></tr> | |
810 | <tr valign="top" align="left"> | |
811 | <td width="8%"></td> | |
812 | <td width="7%"> | |
813 | </td> | |
814 | <td width="8%"> | |
815 | </td> | |
816 | <td width="8%"> | |
817 | ||
818 | ||
819 | <p>if (libmawk_get_array_at(m, "arr", | |
820 | "hello", &arrv, 0) > 0)</p></td> | |
821 | <td width="69%"> | |
822 | </td></tr> | |
823 | <tr valign="top" align="left"> | |
824 | <td width="8%"></td> | |
825 | <td width="7%"> | |
826 | </td> | |
827 | <td width="8%"> | |
828 | </td> | |
829 | <td width="8%"> | |
830 | </td> | |
831 | <td width="69%"> | |
832 | ||
833 | ||
834 | <p>printf("Variable arr[</p></td></tr> | |
835 | <tr valign="top" align="left"> | |
836 | <td width="8%"></td> | |
837 | <td width="7%"> | |
838 | </td> | |
839 | <td width="8%"> | |
840 | </td> | |
841 | <td width="8%"> | |
842 | ||
843 | ||
844 | <p>else</p></td> | |
845 | <td width="69%"> | |
846 | </td></tr> | |
847 | <tr valign="top" align="left"> | |
848 | <td width="8%"></td> | |
849 | <td width="7%"> | |
850 | </td> | |
851 | <td width="8%"> | |
852 | </td> | |
853 | <td width="8%"> | |
854 | </td> | |
855 | <td width="69%"> | |
856 | ||
857 | ||
858 | <p>printf("No such variable</p></td></tr> | |
859 | </table> | |
860 | ||
861 | <p style="margin-left:11%; margin-top: 1em">#warning todo: | |
862 | array set</p> | |
863 | ||
864 | <table width="100%" border="0" rules="none" frame="void" | |
865 | cellspacing="0" cellpadding="0"> | |
866 | <tr valign="top" align="left"> | |
867 | <td width="11%"></td> | |
868 | <td width="-3%"></td> | |
869 | <td width="7%"> | |
870 | </td> | |
871 | <td width="8%"> | |
872 | </td> | |
873 | <td width="8%"> | |
874 | ||
875 | ||
876 | <p>/* set var: array; change the existing | |
877 | (arr["hello"]) */</p></td> | |
878 | <td width="69%"> | |
879 | </td></tr> | |
880 | <tr valign="top" align="left"> | |
881 | <td width="11%"></td> | |
882 | <td width="-3%"></td> | |
883 | <td width="7%"> | |
884 | ||
885 | ||
886 | <p>//</p></td> | |
887 | <td width="8%"> | |
888 | </td> | |
889 | <td width="8%"> | |
890 | ||
891 | ||
892 | <p>if (ret != NULL)</p></td> | |
893 | <td width="69%"> | |
894 | </td></tr> | |
895 | <tr valign="top" align="left"> | |
896 | <td width="11%"></td> | |
897 | <td width="-3%"></td> | |
898 | <td width="7%"> | |
899 | ||
900 | ||
901 | <p>//</p></td> | |
902 | <td width="8%"> | |
903 | </td> | |
904 | <td width="8%"> | |
905 | </td> | |
906 | <td width="69%"> | |
907 | ||
908 | ||
909 | <p>libmawk_set_cell(m, ret, ’s’, | |
910 | "WORLD");</p> </td></tr> | |
911 | <tr valign="top" align="left"> | |
912 | <td width="11%"></td> | |
913 | <td width="-3%"></td> | |
914 | <td width="7%"> | |
915 | </td> | |
916 | <td width="8%"> | |
917 | </td> | |
918 | <td width="8%"> | |
919 | ||
920 | ||
921 | <p>/* set var: array; create a new index */</p></td> | |
922 | <td width="69%"> | |
923 | </td></tr> | |
924 | </table> | |
925 | ||
926 | <p style="margin-left:11%;">#warning todo: array set</p> | |
927 | ||
928 | <table width="100%" border="0" rules="none" frame="void" | |
929 | cellspacing="0" cellpadding="0"> | |
930 | <tr valign="top" align="left"> | |
931 | <td width="11%"></td> | |
932 | <td width="-3%"></td> | |
933 | <td width="7%"> | |
934 | ||
935 | ||
936 | <p>//</p></td> | |
937 | <td width="8%"> | |
938 | </td> | |
939 | <td width="77%"> | |
940 | ||
941 | ||
942 | <p>libmawk_get_array_at(m, "arr", | |
943 | "bye", &arrv, 1);</p></td></tr> | |
944 | <tr valign="top" align="left"> | |
945 | <td width="11%"></td> | |
946 | <td width="-3%"></td> | |
947 | <td width="7%"> | |
948 | ||
949 | ||
950 | <p>//</p></td> | |
951 | <td width="8%"> | |
952 | </td> | |
953 | <td width="77%"> | |
954 | ||
955 | ||
956 | <p>libmawk_set_cell(m, ret, ’s’, | |
957 | "universe");</p> </td></tr> | |
958 | <tr valign="top" align="left"> | |
959 | <td width="11%"></td> | |
960 | <td width="-3%"></td> | |
961 | <td width="7%"> | |
962 | </td> | |
963 | <td width="8%"> | |
964 | </td> | |
965 | <td width="77%"> | |
966 | ||
967 | ||
968 | <p>/* run some more data */</p></td></tr> | |
969 | <tr valign="top" align="left"> | |
970 | <td width="11%"></td> | |
971 | <td width="-3%"></td> | |
972 | <td width="7%"> | |
973 | </td> | |
974 | <td width="8%"> | |
975 | </td> | |
976 | <td width="77%"> | |
977 | ||
978 | ||
979 | <p>libmawk_append_input(m, "Second0);</p></td></tr> | |
980 | <tr valign="top" align="left"> | |
981 | <td width="11%"></td> | |
982 | <td width="-3%"></td> | |
983 | <td width="7%"> | |
984 | </td> | |
985 | <td width="8%"> | |
986 | </td> | |
987 | <td width="77%"> | |
988 | ||
989 | ||
990 | <p>libmawk_append_input(m, "run.0);</p></td></tr> | |
991 | <tr valign="top" align="left"> | |
992 | <td width="11%"></td> | |
993 | <td width="-3%"></td> | |
994 | <td width="7%"> | |
995 | </td> | |
996 | <td width="8%"> | |
997 | </td> | |
998 | <td width="77%"> | |
999 | ||
1000 | ||
1001 | <p>libmawk_run_main(m);</p></td></tr> | |
1002 | <tr valign="top" align="left"> | |
1003 | <td width="11%"></td> | |
1004 | <td width="-3%"></td> | |
1005 | <td width="7%"> | |
1006 | </td> | |
1007 | <td width="8%"> | |
1008 | </td> | |
1009 | <td width="77%"> | |
1010 | ||
1011 | ||
1012 | <p>custom_array_print(m);</p></td></tr> | |
1013 | <tr valign="top" align="left"> | |
1014 | <td width="11%"></td> | |
1015 | <td width="-3%"></td> | |
1016 | <td width="7%"> | |
1017 | </td> | |
1018 | <td width="8%"> | |
1019 | </td> | |
1020 | <td width="77%"> | |
1021 | ||
1022 | ||
1023 | <p>/* run end */</p></td></tr> | |
1024 | <tr valign="top" align="left"> | |
1025 | <td width="11%"></td> | |
1026 | <td width="-3%"></td> | |
1027 | <td width="7%"> | |
1028 | </td> | |
1029 | <td width="8%"> | |
1030 | </td> | |
1031 | <td width="77%"> | |
1032 | ||
1033 | ||
1034 | <p>libmawk_uninitialize(m);</p></td></tr> | |
1035 | <tr valign="top" align="left"> | |
1036 | <td width="11%"></td> | |
1037 | <td width="-3%"></td> | |
1038 | <td width="7%"></td> | |
1039 | <td width="8%"> | |
1040 | ||
1041 | ||
1042 | <p>}</p></td> | |
1043 | <td width="77%"> | |
1044 | </td></tr> | |
1045 | <tr valign="top" align="left"> | |
1046 | <td width="11%"></td> | |
1047 | <td width="-3%"></td> | |
1048 | <td width="7%"></td> | |
1049 | <td width="8%"> | |
1050 | ||
1051 | ||
1052 | <p>else {</p></td> | |
1053 | <td width="77%"> | |
1054 | </td></tr> | |
1055 | <tr valign="top" align="left"> | |
1056 | <td width="11%"></td> | |
1057 | <td width="-3%"></td> | |
1058 | <td width="7%"> | |
1059 | </td> | |
1060 | <td width="8%"> | |
1061 | </td> | |
1062 | <td width="77%"> | |
1063 | ||
1064 | ||
1065 | <p>printf("Init failed.0);</p></td></tr> | |
1066 | <tr valign="top" align="left"> | |
1067 | <td width="11%"></td> | |
1068 | <td width="-3%"></td> | |
1069 | <td width="7%"></td> | |
1070 | <td width="8%"> | |
1071 | ||
1072 | ||
1073 | <p>}</p></td> | |
1074 | <td width="77%"> | |
1075 | </td></tr> | |
1076 | <tr valign="top" align="left"> | |
1077 | <td width="11%"></td> | |
1078 | <td width="-3%"></td> | |
1079 | <td width="7%"></td> | |
1080 | <td width="8%"> | |
1081 | ||
1082 | ||
1083 | <p>printf("END0);</p></td> | |
1084 | <td width="77%"> | |
1085 | </td></tr> | |
1086 | <tr valign="top" align="left"> | |
1087 | <td width="11%"></td> | |
1088 | <td width="-3%"></td> | |
1089 | <td width="7%"></td> | |
1090 | <td width="8%"> | |
1091 | ||
1092 | ||
1093 | <p>return 0 ;</p></td> | |
1094 | <td width="77%"> | |
1095 | </td></tr> | |
1096 | </table> | |
1097 | ||
1098 | <p style="margin-left:11%;">}</p> | |
1099 | <hr> | |
1100 | </body> | |
1101 | </html> |
0 | <HTML> | |
1 | <BODY> | |
2 | <H1> awk script execution </H1> | |
3 | Libmawk runs the bytecode of the script in a <a href="developer/vm">virtual machine</a>. | |
4 | The VM takes the bytecode as a series of instructions that operate on data | |
5 | stored on the execution stack and in global states of the script instance | |
6 | (libmawk_state_t). | |
7 | <p> | |
8 | There is only one thing at a time an instance is doing, however that | |
9 | one thing may be interrupted and resumed any time. This one thing is | |
10 | always one of these: | |
11 | <ul> | |
12 | <li> running BEGIN | |
13 | <li> running END | |
14 | <li> running main (the stdin read and pattern match rules) | |
15 | <li> running an awk function called from the application | |
16 | <li> nothing: empty stack; before starting or after finishing any of the above activities | |
17 | </ul> | |
18 | <p> | |
19 | BEGIN, END, main and awk functions are the four entry points of executing | |
20 | the script. Normally BEGIN is run right after setting up the script, then | |
21 | main is run on all input and END is run when the script exits, right | |
22 | before uninitialization of the script instance. This is a 1:1 copy | |
23 | of the standard way awk works. The fourth, calling awk functions directly | |
24 | from the application is an extra entry point. | |
25 | <p> | |
26 | The script is not doing anything unless the application commands it to. Some | |
27 | of the simplified API does this automatically, but the raw API (staged | |
28 | init/uninit) always lets the app decide when to <b>start</b> running the script. | |
29 | This document calls an <i>execution transaction<i> when the application calls | |
30 | the API to start running a script. | |
31 | <p> | |
32 | Any execution related call is non-blocking, thus it will return after a | |
33 | reasonable time spent running the script and will never stuck running | |
34 | an infinite loop. When such an API call returns, the return value | |
35 | is a mawk_exec_result_t that indicates the reason of the return: | |
36 | <ul> | |
37 | <li> 1. if the script attempts to read a file/pipe that would block, it interrupts execution and returns (with <i>MAWK_EXER_INT_READ</i>) instead | |
38 | <li> 2. when reaching the run limit (a given number of instructions has been executed), the script is interrupted (return value is <i>MAWK_EXER_INT_RUNLIMIT</i>) | |
39 | <li> 3. the script may finish executing the current execution transaction (<i>MAWK_EXER_DONE</i> or <i>MAWK_EXER_FUNCRET</i>) | |
40 | <li> 4. the script may decide to exit | |
41 | </ul> | |
42 | <p> | |
43 | <i>Execution transaction<i> are collected on the evaluation stack. If | |
44 | the application requests an execution and the API call returns before | |
45 | finishing, the transaction is still active. The application is | |
46 | free to initiate a new <i>execution transaction<i>, without | |
47 | first finishing the previous one. However, the VM will always resume and | |
48 | progress running the most recent <i>execution transaction<i>. This means | |
49 | <i>execution transactions<i> are sort of nested. When the top, most recent | |
50 | <i>execution transaction<i> finishes (return 3), the next resume request | |
51 | will go on with the previous transaction. | |
52 | <p> | |
53 | Note, however, that the script has global states. The most obvious state | |
54 | is the exit state: if the script runs exit(), it will discard all open | |
55 | transactions. For example consider a script that is running a main part | |
56 | processing the input. When the application is in this phase, the topmost | |
57 | transaction is always a "running main" transaction that returned | |
58 | previously because there was no more input to be processed. If the | |
59 | application calls an awk function that decides to do an exit(), that will | |
60 | affect not only discard the function transaction but the pending "running main" | |
61 | transaction as well. Whenever the application requests a resume on | |
62 | the code, that will start running the END section. | |
63 | ||
64 | ||
65 | <h2> return path 1.: MAWK_EXER_INT_READ </h2> | |
66 | Assume stdin is a FIFO between the application and the script. The | |
67 | first script tries to prefix each line: | |
68 | <pre> | |
69 | { | |
70 | print "prefix:", $0 | |
71 | } | |
72 | </pre> | |
73 | The application fills the FIFO with some data that may contain one or | |
74 | more full records, potentially ending with a partial (unterminated) | |
75 | record. If the application resumes the script, it will try to | |
76 | read all full records and process them. It will interrupt | |
77 | execution and return MAWK_EXER_INT_READ the first time a full | |
78 | record can't be read. This always happens "before the {}". | |
79 | <p> | |
80 | A slightly more complicated script prefixes odd and even lines differently: | |
81 | <pre> | |
82 | { | |
83 | print "odd:", $0 | |
84 | getline | |
85 | print "even:", $0 | |
86 | } | |
87 | </pre> | |
88 | This script may return with MAWK_EXER_INT_READ either before {} | |
89 | or in the getline instruction. This means the application should not | |
90 | assume that when main returns it was not in the middle of such | |
91 | a block. (In the actual VM main starts with an implicit getline so | |
92 | there's no difference between the two cases). | |
93 | <p> | |
94 | A similar situation is when an awk function is executing getline on a FIFO: | |
95 | the application that calls the function shall not expect that the function | |
96 | finishes and produces its return value in the initial execution request. | |
97 | Instead the request will create a new <i>execution transaction<i> and | |
98 | multiple resume calls may be needed until the function actually returns. | |
99 | <p> | |
100 | Obviously the application shall fill the FIFO while executing resumes: | |
101 | if there is no new input and the script is waiting for new input, the | |
102 | resume call will return immediately. | |
103 | ||
104 | ||
105 | <h2> return path 2.: <i>MAWK_EXER_INT_RUNLIMIT</i> </h2> | |
106 | When runlimit is set the VM returns after executing a certain amount of | |
107 | instructions. The application shall decide whether to simply resume or | |
108 | to stop executing the script. | |
109 | <p> | |
110 | This feature is useful when the application is implemented as a single | |
111 | threaded async loop: running a blocking script would block the entire loop. | |
112 | ||
113 | ||
114 | <h2> return path 3.: <i>MAWK_EXER_DONE</i> or <i>MAWK_EXER_FUNCRET</i> </h2> | |
115 | When BEGIN or main or END finishes <i>MAWK_EXER_DONE</i> is returned. When | |
116 | an awk function called by the application returns, <i>MAWK_EXER_FUNCRET</i> | |
117 | is returned and the retc argument is filled with the return value cell | |
118 | (which may be of cell type NOINIT in case there was no return value). | |
119 | <p> | |
120 | The application <b>shall never</b> expect the initial call that | |
121 | created the new <i>execution transaction<i> will end in | |
122 | <i>MAWK_EXER_DONE</i> or <i>MAWK_EXER_FUNCRET</i>; when it does not, | |
123 | a subsequent resume call eventually will. | |
124 | ||
125 | <h2> return path 4.: <i>MAWK_EXER_EXIT</i> </h2> | |
126 | Similar to <i>MAWK_EXER_DONE</i>, but means the script called exit. | |
127 | This is legal from even an awk function call, in which case the | |
128 | function will never have a return value (as the code can not be resumed | |
129 | any more). Normal awk rules apply: calling exit() from BEGIN or main | |
130 | (or subsequent functions, called by the script or the application) puts | |
131 | the script in exit mode and next resume will run END. Calling exit from | |
132 | END will exit immediately leaving the script in non-runnable state. | |
133 | ||
134 | ||
135 | <h2> conclusion: script execution </h2> | |
136 | It is safe to assume calling any script execution will return with | |
137 | a conclusion if, and only if: | |
138 | <ul> | |
139 | <li> the script is not allowed to use getline on FIFOs (which can not be guaranteed!) or there are no FIFOs or otherwise blocking input (i.e. all files are plain files); and | |
140 | <li> there is no run limit configured | |
141 | </ul> | |
142 | <p> | |
143 | Since these are not guaranteed in most common use cases, the code should prepare | |
144 | to: | |
145 | <ul> | |
146 | <li> start executing the code and check if it's already finished | |
147 | <li> resume until it actually does finish | |
148 | <li> if the script returned <i>MAWK_EXER_INT_READ</i>: fill FIFOs or if that's not possible stop resuming as there won't be any progress | |
149 | </ul> | |
150 | <p> | |
151 | Thus following c-pseudo-code should be used: | |
152 | <pre> | |
153 | TODO | |
154 | </pre> |
0 | <HTML> | |
1 | <BODY> | |
2 | <H1> Table Of Contents </H1> | |
3 | <H2> Manual pages </H2> | |
4 | <UL> | |
5 | <LI> <a href="lmawk.1.html"> lmawk(1) </a> - command line implementation | |
6 | <LI> <a href="example.7libmawk.html"> example(7libmawk) </a> - example on using the library | |
7 | <LI> <a href="libmawk_append_input.3libmawk.html"> libmawk_append_input(3) </a> | |
8 | <LI> <a href="libmawk_call_function.3libmawk.html"> libmawk_call_function(3) </a> | |
9 | <LI> <a href="libmawk_cell_destroy.3libmawk.html"> libmawk_cell_destroy(3) </a> | |
10 | <LI> <a href="libmawk_get_var.3libmawk.html"> libmawk_get_var(3) </a> | |
11 | <LI> <a href="libmawk_initialize.3libmawk.html"> libmawk_initialize(3) </a> | |
12 | <LI> <a href="libmawk_initialize_stage.3libmawk.html"> libmawk_initialize_stage(3) </a> | |
13 | <LI> <a href="libmawk_register_function.3libmawk.html"> libmawk_register_function(3) </a> | |
14 | <LI> <a href="libmawk_run_main.3libmawk.html"> libmawk_run_main(3) </a> | |
15 | <LI> <a href="libmawk_set_cell.3libmawk.html"> libmawk_set_cell(3) </a> | |
16 | <LI> <a href="libmawk_uninitialize.3libmawk.html"> libmawk_uninitialize(3) </a> | |
17 | </UL> | |
18 | <H2> Design decisions </H2> | |
19 | <UL> | |
20 | <LI> <a href="autotools.html"> why not using autotools in libmawk </a> | |
21 | <LI> <a href="portability.html"> portability with scconfig </a> | |
22 | <LI> <a href="semi-gnu.html"> semi-dependency on GNU utils </a> | |
23 | <LI> <a href="numeric.html"> different numeric types and FPE/NaN </a> | |
24 | </UL> | |
25 | </BODY> | |
26 | </HTML> | |
27 |
0 | <!-- Creator : groff version 1.22.2 --> | |
1 | <!-- CreationDate: Sat Jun 14 14:27:30 2014 --> | |
2 | <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" | |
3 | "http://www.w3.org/TR/html4/loose.dtd"> | |
4 | <html> | |
5 | <head> | |
6 | <meta name="generator" content="groff -Thtml, see www.gnu.org"> | |
7 | <meta http-equiv="Content-Type" content="text/html; charset=US-ASCII"> | |
8 | <meta name="Content-Style" content="text/css"> | |
9 | <style type="text/css"> | |
10 | p { margin-top: 0; margin-bottom: 0; vertical-align: top } | |
11 | pre { margin-top: 0; margin-bottom: 0; vertical-align: top } | |
12 | table { margin-top: 0; margin-bottom: 0; vertical-align: top } | |
13 | h1 { text-align: center } | |
14 | </style> | |
15 | <title>LIBMAWK_APPEND_INPUT</title> | |
16 | ||
17 | </head> | |
18 | <body> | |
19 | ||
20 | <h1 align="center">LIBMAWK_APPEND_INPUT</h1> | |
21 | ||
22 | <a href="#NAME">NAME</a><br> | |
23 | <a href="#SYNOPSIS">SYNOPSIS</a><br> | |
24 | <a href="#DESCRIPTION">DESCRIPTION</a><br> | |
25 | <a href="#SEE ALSO">SEE ALSO</a><br> | |
26 | ||
27 | <hr> | |
28 | ||
29 | ||
30 | <h2>NAME | |
31 | <a name="NAME"></a> | |
32 | </h2> | |
33 | ||
34 | ||
35 | ||
36 | <p style="margin-left:11%; margin-top: 1em">libmawk_append_input | |
37 | − append a string to an input buffer</p> | |
38 | ||
39 | <h2>SYNOPSIS | |
40 | <a name="SYNOPSIS"></a> | |
41 | </h2> | |
42 | ||
43 | ||
44 | <p style="margin-left:11%; margin-top: 1em"><b>#include | |
45 | <libmawk.h></b></p> | |
46 | ||
47 | <p style="margin-left:11%; margin-top: 1em"><b>void | |
48 | libmawk_append_input(mawk_state_t *</b><i>m</i><b>, const | |
49 | char *</b><i>input_str</i><b>);</b></p> | |
50 | ||
51 | <p style="margin-left:11%; margin-top: 1em"><b>void | |
52 | libmawk_append_ninput(mawk_state_t *</b><i>m</i><b>, const | |
53 | char *</b><i>input</i><b>, int</b><i>len</i><b>);</b></p> | |
54 | ||
55 | <h2>DESCRIPTION | |
56 | <a name="DESCRIPTION"></a> | |
57 | </h2> | |
58 | ||
59 | ||
60 | <p style="margin-left:11%; margin-top: 1em">The | |
61 | <b>libmawk_append_input</b>() and | |
62 | <b>libmawk_append_ninput</b>() functions allow the | |
63 | application to fill the input buffer of a libmawk context. | |
64 | No record separator is appended, only the bytes donated by | |
65 | input_str or input, thus it is possible to append partial | |
66 | records. Appending to the input doesn’t have the side | |
67 | effect of any script being run. There may be multiple | |
68 | libmawk_append_input() calls before a call to | |
69 | libmawk_run_main(). The latter all is used to let the script | |
70 | process the input buffer.</p> | |
71 | ||
72 | <p style="margin-left:11%; margin-top: 1em">The only | |
73 | difference between the two calls are the input format: | |
74 | <b>libmawk_append_input</b>() expects a nul-terminated | |
75 | string, whereas <b>libmawk_append_ninput</b>() takes an | |
76 | arbitrary binary data and its length.</p> | |
77 | ||
78 | <p style="margin-left:11%; margin-top: 1em">Argument m is a | |
79 | libmawk context previously returned by libmawk_initialize() | |
80 | or libmawk_initialize_stage3().</p> | |
81 | ||
82 | <h2>SEE ALSO | |
83 | <a name="SEE ALSO"></a> | |
84 | </h2> | |
85 | ||
86 | ||
87 | ||
88 | <p style="margin-left:11%; margin-top: 1em"><b>libmawk_initialize_stage</b>(3libmawk), | |
89 | <b>libmawk_initialize</b>(3libmawk), | |
90 | <b>libmawk_run_main</b>(3libmawk).</p> | |
91 | <hr> | |
92 | </body> | |
93 | </html> |
0 | <!-- Creator : groff version 1.22.2 --> | |
1 | <!-- CreationDate: Sat Jun 14 14:27:31 2014 --> | |
2 | <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" | |
3 | "http://www.w3.org/TR/html4/loose.dtd"> | |
4 | <html> | |
5 | <head> | |
6 | <meta name="generator" content="groff -Thtml, see www.gnu.org"> | |
7 | <meta http-equiv="Content-Type" content="text/html; charset=US-ASCII"> | |
8 | <meta name="Content-Style" content="text/css"> | |
9 | <style type="text/css"> | |
10 | p { margin-top: 0; margin-bottom: 0; vertical-align: top } | |
11 | pre { margin-top: 0; margin-bottom: 0; vertical-align: top } | |
12 | table { margin-top: 0; margin-bottom: 0; vertical-align: top } | |
13 | h1 { text-align: center } | |
14 | </style> | |
15 | <title>LIBMAWK_CALL_FUNCTION</title> | |
16 | ||
17 | </head> | |
18 | <body> | |
19 | ||
20 | <h1 align="center">LIBMAWK_CALL_FUNCTION</h1> | |
21 | ||
22 | <a href="#NAME">NAME</a><br> | |
23 | <a href="#SYNOPSIS">SYNOPSIS</a><br> | |
24 | <a href="#DESCRIPTION">DESCRIPTION</a><br> | |
25 | <a href="#RETURN VALUE">RETURN VALUE</a><br> | |
26 | <a href="#SEE ALSO">SEE ALSO</a><br> | |
27 | ||
28 | <hr> | |
29 | ||
30 | ||
31 | <h2>NAME | |
32 | <a name="NAME"></a> | |
33 | </h2> | |
34 | ||
35 | ||
36 | ||
37 | <p style="margin-left:11%; margin-top: 1em">libmawk_call_function | |
38 | − call an user defined (script) function</p> | |
39 | ||
40 | <h2>SYNOPSIS | |
41 | <a name="SYNOPSIS"></a> | |
42 | </h2> | |
43 | ||
44 | ||
45 | <p style="margin-left:11%; margin-top: 1em"><b>#include | |
46 | <libmawk.h></b></p> | |
47 | ||
48 | <p style="margin-left:11%; margin-top: 1em"><b>int | |
49 | libmawk_call_function(mawk_state_t *</b><i>MAWK</i><b>, | |
50 | const char *</b><i>fname</i><b>, CELL *</b><i>res</i><b>, | |
51 | const char *</b><i>argtpes</i><b>, ...); <br> | |
52 | int libmawk_call_functionp(mawk_state_t *</b><i>MAWK</i><b>, | |
53 | const char *</b><i>fname</i><b>, CELL *</b><i>res</i><b>, | |
54 | const char *</b><i>argtpes</i><b>, void **args);</b></p> | |
55 | ||
56 | <h2>DESCRIPTION | |
57 | <a name="DESCRIPTION"></a> | |
58 | </h2> | |
59 | ||
60 | ||
61 | <p style="margin-left:11%; margin-top: 1em">The | |
62 | <b>libmawk_call_function</b>() function looks up an user | |
63 | defined awk function called <i>fname</i> , fills the stack | |
64 | with arguments converted from the varargs and calls the | |
65 | function. The <b>libmawk_call_functionp</b>() performs the | |
66 | same action but avoids using vararg by requiring an array of | |
67 | generic pointers to the function arguments.</p> | |
68 | ||
69 | <p style="margin-left:11%; margin-top: 1em">Argtype is a | |
70 | zero terminated string for both functions, each character | |
71 | corresponding to an argument. Type characters are described | |
72 | in libmawk_set_cell() manual page.</p> | |
73 | ||
74 | <p style="margin-left:11%; margin-top: 1em">If res is | |
75 | non-NULL, it is cell_destroyed (regardless of errors) and | |
76 | the return value of the user function is copied into it. The | |
77 | caller shall run libmawk_cell_destroy on it.</p> | |
78 | ||
79 | <p style="margin-left:11%; margin-top: 1em">Argument m is a | |
80 | libmawk context previously returned by libmawk_initialize() | |
81 | or libmawk_initialize_stage3().</p> | |
82 | ||
83 | <h2>RETURN VALUE | |
84 | <a name="RETURN VALUE"></a> | |
85 | </h2> | |
86 | ||
87 | ||
88 | <p style="margin-left:11%; margin-top: 1em">A pointer to | |
89 | the cell returned by the user function. The cell | |
90 | returnedmust be destroyed by the application using | |
91 | libmawk_cell_destroy.</p> | |
92 | ||
93 | <h2>SEE ALSO | |
94 | <a name="SEE ALSO"></a> | |
95 | </h2> | |
96 | ||
97 | ||
98 | ||
99 | <p style="margin-left:11%; margin-top: 1em"><b>libmawk_initialize_stage</b>(3libmawk), | |
100 | <b>libmawk_initialize</b>(3libmawk), | |
101 | <b>libmawk_cell_destroy</b>(3libmawk), | |
102 | <b>libmawk_set_cell</b>(3libmawk),</p> | |
103 | <hr> | |
104 | </body> | |
105 | </html> |
0 | <!-- Creator : groff version 1.22.2 --> | |
1 | <!-- CreationDate: Sat Jun 14 14:27:31 2014 --> | |
2 | <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" | |
3 | "http://www.w3.org/TR/html4/loose.dtd"> | |
4 | <html> | |
5 | <head> | |
6 | <meta name="generator" content="groff -Thtml, see www.gnu.org"> | |
7 | <meta http-equiv="Content-Type" content="text/html; charset=US-ASCII"> | |
8 | <meta name="Content-Style" content="text/css"> | |
9 | <style type="text/css"> | |
10 | p { margin-top: 0; margin-bottom: 0; vertical-align: top } | |
11 | pre { margin-top: 0; margin-bottom: 0; vertical-align: top } | |
12 | table { margin-top: 0; margin-bottom: 0; vertical-align: top } | |
13 | h1 { text-align: center } | |
14 | </style> | |
15 | <title>LIBMAWK_CELL_DESTROY</title> | |
16 | ||
17 | </head> | |
18 | <body> | |
19 | ||
20 | <h1 align="center">LIBMAWK_CELL_DESTROY</h1> | |
21 | ||
22 | <a href="#NAME">NAME</a><br> | |
23 | <a href="#SYNOPSIS">SYNOPSIS</a><br> | |
24 | <a href="#DESCRIPTION">DESCRIPTION</a><br> | |
25 | <a href="#SEE ALSO">SEE ALSO</a><br> | |
26 | ||
27 | <hr> | |
28 | ||
29 | ||
30 | <h2>NAME | |
31 | <a name="NAME"></a> | |
32 | </h2> | |
33 | ||
34 | ||
35 | ||
36 | <p style="margin-left:11%; margin-top: 1em">libmawk_cell_destroy | |
37 | − free all memory associated with a cell</p> | |
38 | ||
39 | <h2>SYNOPSIS | |
40 | <a name="SYNOPSIS"></a> | |
41 | </h2> | |
42 | ||
43 | ||
44 | <p style="margin-left:11%; margin-top: 1em"><b>#include | |
45 | <libmawk.h></b></p> | |
46 | ||
47 | <p style="margin-left:11%; margin-top: 1em"><b>void | |
48 | libmawk_cell_destroy(mawk_state_t *</b><i>m</i><b>, CELL | |
49 | *</b><i>c</i><b>);</b></p> | |
50 | ||
51 | <h2>DESCRIPTION | |
52 | <a name="DESCRIPTION"></a> | |
53 | </h2> | |
54 | ||
55 | ||
56 | <p style="margin-left:11%; margin-top: 1em">The | |
57 | <b>libmawk_cell_destroy</b>() function frees all memory | |
58 | allocated to store a mawk cell. It is useful with some of | |
59 | the libmawk calls that return a newly allocated cell, such | |
60 | as the libmawk_call_function() call.</p> | |
61 | ||
62 | <p style="margin-left:11%; margin-top: 1em">Argument m is a | |
63 | libmawk context previously returned by libmawk_initialize() | |
64 | or libmawk_initialize_stage3().</p> | |
65 | ||
66 | <h2>SEE ALSO | |
67 | <a name="SEE ALSO"></a> | |
68 | </h2> | |
69 | ||
70 | ||
71 | ||
72 | <p style="margin-left:11%; margin-top: 1em"><b>libmawk_initialize_stage</b>(3libmawk), | |
73 | <b>libmawk_initialize</b>(3libmawk), | |
74 | <b>libmawk_call_function</b>(3libmawk).</p> | |
75 | <hr> | |
76 | </body> | |
77 | </html> |
0 | <!-- Creator : groff version 1.22.2 --> | |
1 | <!-- CreationDate: Sat Jun 14 14:27:31 2014 --> | |
2 | <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" | |
3 | "http://www.w3.org/TR/html4/loose.dtd"> | |
4 | <html> | |
5 | <head> | |
6 | <meta name="generator" content="groff -Thtml, see www.gnu.org"> | |
7 | <meta http-equiv="Content-Type" content="text/html; charset=US-ASCII"> | |
8 | <meta name="Content-Style" content="text/css"> | |
9 | <style type="text/css"> | |
10 | p { margin-top: 0; margin-bottom: 0; vertical-align: top } | |
11 | pre { margin-top: 0; margin-bottom: 0; vertical-align: top } | |
12 | table { margin-top: 0; margin-bottom: 0; vertical-align: top } | |
13 | h1 { text-align: center } | |
14 | </style> | |
15 | <title>LIBMAWK_GET_VAR</title> | |
16 | ||
17 | </head> | |
18 | <body> | |
19 | ||
20 | <h1 align="center">LIBMAWK_GET_VAR</h1> | |
21 | ||
22 | <a href="#NAME">NAME</a><br> | |
23 | <a href="#SYNOPSIS">SYNOPSIS</a><br> | |
24 | <a href="#DESCRIPTION">DESCRIPTION</a><br> | |
25 | <a href="#SEE ALSO">SEE ALSO</a><br> | |
26 | ||
27 | <hr> | |
28 | ||
29 | ||
30 | <h2>NAME | |
31 | <a name="NAME"></a> | |
32 | </h2> | |
33 | ||
34 | ||
35 | ||
36 | <p style="margin-left:11%; margin-top: 1em">libmawk_get_var | |
37 | − returns a pointer to a mawk variable</p> | |
38 | ||
39 | <h2>SYNOPSIS | |
40 | <a name="SYNOPSIS"></a> | |
41 | </h2> | |
42 | ||
43 | ||
44 | <p style="margin-left:11%; margin-top: 1em"><b>#include | |
45 | <libmawk.h></b></p> | |
46 | ||
47 | <p style="margin-left:11%; margin-top: 1em"><b>CELL | |
48 | *libmawk_get_var(mawk_state_t *</b><i>m</i><b>, const char | |
49 | *</b><i>vname</i><b>); <br> | |
50 | int libmawk_get_array_at(mawk_state_t *</b><i>m</i><b>, | |
51 | const char *</b><i>arr_name</i><b>, <br> | |
52 | const char *</b><i>idx</i><b>, const char | |
53 | *</b><i>res</i><b>, int</b> <i>alloc</i><b>);</b></p> | |
54 | ||
55 | <h2>DESCRIPTION | |
56 | <a name="DESCRIPTION"></a> | |
57 | </h2> | |
58 | ||
59 | ||
60 | <p style="margin-left:11%; margin-top: 1em">The | |
61 | <b>libmawk_get_var</b>() function returns a pointer to a | |
62 | mawk cell that represents the global variable with name | |
63 | passed in <i>vname</i> in the given context. The returned | |
64 | CELL should never be free’d or destroyed. Function | |
65 | libmawk_print_cell may be used for converting the cell to | |
66 | string. The caller should not change the type of cell but is | |
67 | free to change the value.</p> | |
68 | ||
69 | <p style="margin-left:11%; margin-top: 1em">Function | |
70 | <b>libmawk_get_array_at</b>() performs the same operation | |
71 | for an element of an array. -1 is returned if | |
72 | <i>arr_name</i> is not an array or upon an error. If | |
73 | <i>idx</i> is not an existing index in the array it is | |
74 | allocated if <i>alloc</i> is non-zero. If <i>res</i> is not | |
75 | NULL, it is destroyed (regardless of the return value) and | |
76 | if the index exists (or is created by the call), is loaded | |
77 | with the value. The caller needs to destroy <i>res</i> after | |
78 | use. Since <i>res</i> is destroyed when non-NULL, it must be | |
79 | a valid cell with valid type.</p> | |
80 | ||
81 | <p style="margin-left:11%; margin-top: 1em">Argument m is a | |
82 | libmawk context previously returned by libmawk_initialize() | |
83 | or libmawk_initialize_stage3().</p> | |
84 | ||
85 | <h2>SEE ALSO | |
86 | <a name="SEE ALSO"></a> | |
87 | </h2> | |
88 | ||
89 | ||
90 | ||
91 | <p style="margin-left:11%; margin-top: 1em"><b>libmawk_initialize_stage</b>(3libmawk), | |
92 | <b>libmawk_initialize</b>(3libmawk), | |
93 | <b>libmawk_call_function</b>(3libmawk), | |
94 | <b>libmawk_print_cell</b>(3libmawk).</p> | |
95 | <hr> | |
96 | </body> | |
97 | </html> |
0 | <!-- Creator : groff version 1.22.2 --> | |
1 | <!-- CreationDate: Sat Jun 14 14:27:31 2014 --> | |
2 | <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" | |
3 | "http://www.w3.org/TR/html4/loose.dtd"> | |
4 | <html> | |
5 | <head> | |
6 | <meta name="generator" content="groff -Thtml, see www.gnu.org"> | |
7 | <meta http-equiv="Content-Type" content="text/html; charset=US-ASCII"> | |
8 | <meta name="Content-Style" content="text/css"> | |
9 | <style type="text/css"> | |
10 | p { margin-top: 0; margin-bottom: 0; vertical-align: top } | |
11 | pre { margin-top: 0; margin-bottom: 0; vertical-align: top } | |
12 | table { margin-top: 0; margin-bottom: 0; vertical-align: top } | |
13 | h1 { text-align: center } | |
14 | </style> | |
15 | <title>LIBMAWK_INITIALIZE</title> | |
16 | ||
17 | </head> | |
18 | <body> | |
19 | ||
20 | <h1 align="center">LIBMAWK_INITIALIZE</h1> | |
21 | ||
22 | <a href="#NAME">NAME</a><br> | |
23 | <a href="#SYNOPSIS">SYNOPSIS</a><br> | |
24 | <a href="#DESCRIPTION">DESCRIPTION</a><br> | |
25 | <a href="#RETURN VALUE">RETURN VALUE</a><br> | |
26 | <a href="#SEE ALSO">SEE ALSO</a><br> | |
27 | ||
28 | <hr> | |
29 | ||
30 | ||
31 | <h2>NAME | |
32 | <a name="NAME"></a> | |
33 | </h2> | |
34 | ||
35 | ||
36 | ||
37 | <p style="margin-left:11%; margin-top: 1em">libmawk_initialize | |
38 | − create a new libmawk context</p> | |
39 | ||
40 | <h2>SYNOPSIS | |
41 | <a name="SYNOPSIS"></a> | |
42 | </h2> | |
43 | ||
44 | ||
45 | <p style="margin-left:11%; margin-top: 1em"><b>#include | |
46 | <libmawk.h></b></p> | |
47 | ||
48 | ||
49 | <p style="margin-left:11%; margin-top: 1em"><b>mawk_state_t | |
50 | *libmawk_initialize(int</b> <i>s</i><b>, char | |
51 | *</b><i>argv[]</i><b>);</b></p> | |
52 | ||
53 | <h2>DESCRIPTION | |
54 | <a name="DESCRIPTION"></a> | |
55 | </h2> | |
56 | ||
57 | ||
58 | <p style="margin-left:11%; margin-top: 1em">The | |
59 | <b>libmawk_initialize</b>() function returns a pointer to a | |
60 | newly created libmawk context. Any amount of libmawk | |
61 | contexts can live in parallel in an application. Arguments | |
62 | are the same as for a command line mawk session. Scripts are | |
63 | loaded (either from command line or from files using -f), | |
64 | variables are set (with -v), special options are set (with | |
65 | -W), etc.</p> | |
66 | ||
67 | <h2>RETURN VALUE | |
68 | <a name="RETURN VALUE"></a> | |
69 | </h2> | |
70 | ||
71 | ||
72 | <p style="margin-left:11%; margin-top: 1em">A pointer to a | |
73 | new libmawk context or NULL on error.</p> | |
74 | ||
75 | <h2>SEE ALSO | |
76 | <a name="SEE ALSO"></a> | |
77 | </h2> | |
78 | ||
79 | ||
80 | ||
81 | <p style="margin-left:11%; margin-top: 1em"><b>libmawk_initialize_stage</b>(3libmawk), | |
82 | <b>libmawk_uninitialize</b>(3libmawk),</p> | |
83 | <hr> | |
84 | </body> | |
85 | </html> |
0 | <!-- Creator : groff version 1.22.2 --> | |
1 | <!-- CreationDate: Sat Jun 14 14:27:32 2014 --> | |
2 | <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" | |
3 | "http://www.w3.org/TR/html4/loose.dtd"> | |
4 | <html> | |
5 | <head> | |
6 | <meta name="generator" content="groff -Thtml, see www.gnu.org"> | |
7 | <meta http-equiv="Content-Type" content="text/html; charset=US-ASCII"> | |
8 | <meta name="Content-Style" content="text/css"> | |
9 | <style type="text/css"> | |
10 | p { margin-top: 0; margin-bottom: 0; vertical-align: top } | |
11 | pre { margin-top: 0; margin-bottom: 0; vertical-align: top } | |
12 | table { margin-top: 0; margin-bottom: 0; vertical-align: top } | |
13 | h1 { text-align: center } | |
14 | </style> | |
15 | <title>LIBMAWK_INITIALIZE_STAGE</title> | |
16 | ||
17 | </head> | |
18 | <body> | |
19 | ||
20 | <h1 align="center">LIBMAWK_INITIALIZE_STAGE</h1> | |
21 | ||
22 | <a href="#NAME">NAME</a><br> | |
23 | <a href="#SYNOPSIS">SYNOPSIS</a><br> | |
24 | <a href="#DESCRIPTION">DESCRIPTION</a><br> | |
25 | <a href="#RETURN VALUE">RETURN VALUE</a><br> | |
26 | <a href="#SEE ALSO">SEE ALSO</a><br> | |
27 | ||
28 | <hr> | |
29 | ||
30 | ||
31 | <h2>NAME | |
32 | <a name="NAME"></a> | |
33 | </h2> | |
34 | ||
35 | ||
36 | ||
37 | <p style="margin-left:11%; margin-top: 1em">libmawk_initialize_stage* | |
38 | − create a new libmawk context in 3 stages</p> | |
39 | ||
40 | <h2>SYNOPSIS | |
41 | <a name="SYNOPSIS"></a> | |
42 | </h2> | |
43 | ||
44 | ||
45 | <p style="margin-left:11%; margin-top: 1em"><b>#include | |
46 | <libmawk.h></b></p> | |
47 | ||
48 | ||
49 | <p style="margin-left:11%; margin-top: 1em"><b>mawk_state_t | |
50 | *libmawk_initialize_stage1(void);</b></p> | |
51 | ||
52 | ||
53 | <p style="margin-left:11%; margin-top: 1em"><b>mawk_state_t | |
54 | *libmawk_initialize_stage2(mawk_state_t *</b> | |
55 | <i>m,</i><b>int</b> <i>s</i> | |
56 | <b>,</b><i>char</i><b>*"</b><i>argv[]</i><b>);</b></p> | |
57 | ||
58 | ||
59 | <p style="margin-left:11%; margin-top: 1em"><b>mawk_state_t | |
60 | *libmawk_initialize_stage3(mawk_state_t *</b> | |
61 | <i>m</i><b>);</b></p> | |
62 | ||
63 | <h2>DESCRIPTION | |
64 | <a name="DESCRIPTION"></a> | |
65 | </h2> | |
66 | ||
67 | ||
68 | <p style="margin-left:11%; margin-top: 1em">The | |
69 | <b>libmawk_initialize_stage*</b>() functions together do the | |
70 | same as libmawk_initialize() but allows the application to | |
71 | take actions between different stages. | |
72 | <b>libmawk_initialize_stage1</b>() returns a pointer to a | |
73 | newly created libmawk context. Any amount of libmawk | |
74 | contexts can live in parallel in an application.</p> | |
75 | ||
76 | ||
77 | <p style="margin-left:11%; margin-top: 1em"><b>libmawk_initialize_stage2</b>() | |
78 | can be called after a succesful stage1 call. <br> | |
79 | Stage2 is responsible for processing the command line | |
80 | arguments and loading any script.</p> | |
81 | ||
82 | <p style="margin-left:11%; margin-top: 1em">Arguments are | |
83 | the same as for a command line mawk session. Scripts are | |
84 | loaded (either from command line or from files using -f), | |
85 | variables are set (with -v), special options are set (with | |
86 | -W), etc. Unlike with libmawk_initialize(), the application | |
87 | may decide not to provide any script at this stage. All | |
88 | command line arguments are processed.</p> | |
89 | ||
90 | <p style="margin-left:11%; margin-top: 1em">The most common | |
91 | case is that the application calls stage1 with no script, | |
92 | then already having a context makes some manipulations on it | |
93 | (for example registers some C functions that would be | |
94 | already called in the BEGIN part of the script that will be | |
95 | later loaded). Optionally before calling stage2 the | |
96 | application loads the actual script(s) using | |
97 | mawk_append_input_file().</p> | |
98 | ||
99 | ||
100 | <p style="margin-left:11%; margin-top: 1em"><b>libmawk_initialize_stage3</b>() | |
101 | is called as a final step of the three-stage initialization | |
102 | process. Stage3 is responsible for running all the BEGIN | |
103 | parts of all scripts loaded at stage1 or stage2. It is | |
104 | useful to have stage3 in a separate call to allow | |
105 | applications to manipulate the context right before | |
106 | initializing the scripts.</p> | |
107 | ||
108 | <p style="margin-left:11%; margin-top: 1em">Stage2 gets the | |
109 | pointer returned by stage1 and stage3 gets the pointer | |
110 | returned by stage2. Subsequent calls to libmawk functions | |
111 | should get the pointer returned by stage3.</p> | |
112 | ||
113 | <h2>RETURN VALUE | |
114 | <a name="RETURN VALUE"></a> | |
115 | </h2> | |
116 | ||
117 | ||
118 | <p style="margin-left:11%; margin-top: 1em">At stage 1 a | |
119 | pointer to a new libmawk context or NULL on error. | |
120 | Subsequent stages will return the same pointer or NULL on | |
121 | error.</p> | |
122 | ||
123 | <h2>SEE ALSO | |
124 | <a name="SEE ALSO"></a> | |
125 | </h2> | |
126 | ||
127 | ||
128 | ||
129 | <p style="margin-left:11%; margin-top: 1em"><b>libmawk_initialize_stage</b>(3libmawk), | |
130 | <b>libmawk_uninitialize</b>(3libmawk), | |
131 | <b>mawk_append_input_file(3libmawk).</b></p> | |
132 | <hr> | |
133 | </body> | |
134 | </html> |
0 | <!-- Creator : groff version 1.22.2 --> | |
1 | <!-- CreationDate: Sat Jun 14 14:27:32 2014 --> | |
2 | <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" | |
3 | "http://www.w3.org/TR/html4/loose.dtd"> | |
4 | <html> | |
5 | <head> | |
6 | <meta name="generator" content="groff -Thtml, see www.gnu.org"> | |
7 | <meta http-equiv="Content-Type" content="text/html; charset=US-ASCII"> | |
8 | <meta name="Content-Style" content="text/css"> | |
9 | <style type="text/css"> | |
10 | p { margin-top: 0; margin-bottom: 0; vertical-align: top } | |
11 | pre { margin-top: 0; margin-bottom: 0; vertical-align: top } | |
12 | table { margin-top: 0; margin-bottom: 0; vertical-align: top } | |
13 | h1 { text-align: center } | |
14 | </style> | |
15 | <title>LIBMAWK_REGISTER_FUNCTION</title> | |
16 | ||
17 | </head> | |
18 | <body> | |
19 | ||
20 | <h1 align="center">LIBMAWK_REGISTER_FUNCTION</h1> | |
21 | ||
22 | <a href="#NAME">NAME</a><br> | |
23 | <a href="#SYNOPSIS">SYNOPSIS</a><br> | |
24 | <a href="#DESCRIPTION">DESCRIPTION</a><br> | |
25 | <a href="#RETURN VALUE">RETURN VALUE</a><br> | |
26 | <a href="#SEE ALSO">SEE ALSO</a><br> | |
27 | ||
28 | <hr> | |
29 | ||
30 | ||
31 | <h2>NAME | |
32 | <a name="NAME"></a> | |
33 | </h2> | |
34 | ||
35 | ||
36 | ||
37 | <p style="margin-left:11%; margin-top: 1em">libmawk_register_function | |
38 | − registers a C function with a callback</p> | |
39 | ||
40 | <h2>SYNOPSIS | |
41 | <a name="SYNOPSIS"></a> | |
42 | </h2> | |
43 | ||
44 | ||
45 | <p style="margin-left:11%; margin-top: 1em"><b>#include | |
46 | <libmawk.h></b></p> | |
47 | ||
48 | <p style="margin-left:11%; margin-top: 1em"><b>typedef CELL | |
49 | *libmawk_c_function(mawk_state_t *</b><i>m</i><b>, CELL | |
50 | *</b><i>sp</i><b>, int</b> <i>a_args</i><b>); <br> | |
51 | int libmawk_register_function(mawk_state_t | |
52 | *</b><i>MAWK</i><b>, const char *</b><i>fname</i><b>, | |
53 | libmawk_c_function *</b><i>callback</i><b>); <br> | |
54 | CELL *libmawk_stackret(CELL | |
55 | *</b><i>original_sp</i><b>);</b></p> | |
56 | ||
57 | <h2>DESCRIPTION | |
58 | <a name="DESCRIPTION"></a> | |
59 | </h2> | |
60 | ||
61 | ||
62 | <p style="margin-left:11%; margin-top: 1em">The | |
63 | <b>libmawk_register_function</b>() call registers an user | |
64 | defined function donated by the host application in a mawk | |
65 | context so that it acts exactly like user defined functions | |
66 | in written in awk. The name of the new function is given in | |
67 | <i>fname</i> and should not match any of the user defined | |
68 | function names in the awk script.</p> | |
69 | ||
70 | <p style="margin-left:11%; margin-top: 1em">When the user | |
71 | function is called back, argument <i>sp</i> is the stack | |
72 | pointer and <i>a_args</i> holds the number of arguments. The | |
73 | user function is responsible for managing the stack: it | |
74 | should pop all arguments before returning.</p> | |
75 | ||
76 | <p style="margin-left:11%; margin-top: 1em">The user | |
77 | function should also generate a return value, which is done | |
78 | by calling libmawk_set_cell() on the stack slot returned by | |
79 | libmawk_stackret. Libmawk_stackret should be called with the | |
80 | modified <i>sp</i> after popping all arguments.</p> | |
81 | ||
82 | <p style="margin-left:11%; margin-top: 1em">Argument m is a | |
83 | libmawk context previously returned by libmawk_initialize() | |
84 | or libmawk_initialize_stage3().</p> | |
85 | ||
86 | <p style="margin-left:11%; margin-top: 1em">For more | |
87 | information about user function callbacks, especially on | |
88 | stack handling, see manual page example(3libmawk).</p> | |
89 | ||
90 | <h2>RETURN VALUE | |
91 | <a name="RETURN VALUE"></a> | |
92 | </h2> | |
93 | ||
94 | ||
95 | <p style="margin-left:11%; margin-top: 1em">The user | |
96 | function should return the stack pointer after popping all | |
97 | arguments.</p> | |
98 | ||
99 | <p style="margin-left:11%; margin-top: 1em">The | |
100 | libmawk_register_function call returns 0 on success.</p> | |
101 | ||
102 | <p style="margin-left:11%; margin-top: 1em">Call | |
103 | libmawk_stackret returns a stack pointer to the slot where | |
104 | the user function should store its return value.</p> | |
105 | ||
106 | <h2>SEE ALSO | |
107 | <a name="SEE ALSO"></a> | |
108 | </h2> | |
109 | ||
110 | ||
111 | ||
112 | <p style="margin-left:11%; margin-top: 1em"><b>libmawk_initialize_stage</b>(3libmawk), | |
113 | <b>libmawk_initialize</b>(3libmawk), | |
114 | <b>libmawk_set_cell</b>(3libmawk), | |
115 | <b>libmawk_print_cell</b>(3libmawk).</p> | |
116 | <hr> | |
117 | </body> | |
118 | </html> |
0 | <!-- Creator : groff version 1.22.2 --> | |
1 | <!-- CreationDate: Sat Jun 14 14:27:32 2014 --> | |
2 | <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" | |
3 | "http://www.w3.org/TR/html4/loose.dtd"> | |
4 | <html> | |
5 | <head> | |
6 | <meta name="generator" content="groff -Thtml, see www.gnu.org"> | |
7 | <meta http-equiv="Content-Type" content="text/html; charset=US-ASCII"> | |
8 | <meta name="Content-Style" content="text/css"> | |
9 | <style type="text/css"> | |
10 | p { margin-top: 0; margin-bottom: 0; vertical-align: top } | |
11 | pre { margin-top: 0; margin-bottom: 0; vertical-align: top } | |
12 | table { margin-top: 0; margin-bottom: 0; vertical-align: top } | |
13 | h1 { text-align: center } | |
14 | </style> | |
15 | <title>LIBMAWK_RUN_MAIN</title> | |
16 | ||
17 | </head> | |
18 | <body> | |
19 | ||
20 | <h1 align="center">LIBMAWK_RUN_MAIN</h1> | |
21 | ||
22 | <a href="#NAME">NAME</a><br> | |
23 | <a href="#SYNOPSIS">SYNOPSIS</a><br> | |
24 | <a href="#DESCRIPTION">DESCRIPTION</a><br> | |
25 | <a href="#SEE ALSO">SEE ALSO</a><br> | |
26 | ||
27 | <hr> | |
28 | ||
29 | ||
30 | <h2>NAME | |
31 | <a name="NAME"></a> | |
32 | </h2> | |
33 | ||
34 | ||
35 | ||
36 | <p style="margin-left:11%; margin-top: 1em">libmawk_run_main | |
37 | − run main parts of a script</p> | |
38 | ||
39 | <h2>SYNOPSIS | |
40 | <a name="SYNOPSIS"></a> | |
41 | </h2> | |
42 | ||
43 | ||
44 | <p style="margin-left:11%; margin-top: 1em"><b>#include | |
45 | <libmawk.h></b></p> | |
46 | ||
47 | <p style="margin-left:11%; margin-top: 1em"><b>void | |
48 | libmawk_run_main(mawk_state_t *</b><i>m</i><b>);</b></p> | |
49 | ||
50 | <h2>DESCRIPTION | |
51 | <a name="DESCRIPTION"></a> | |
52 | </h2> | |
53 | ||
54 | ||
55 | <p style="margin-left:11%; margin-top: 1em">The | |
56 | <b>libmawk_run_main</b>() attempts to take and parse the | |
57 | next input record and runs all main parts of the script that | |
58 | matches. If there are multiple full records in the input | |
59 | buffer, the process repeats until the buffer becomes empty | |
60 | or contains a partial record. If there is no full record in | |
61 | the buffer, the call returns with nothing done. The call | |
62 | itself never blocks, but the script may. The input buffer | |
63 | may be filled using the libmawk_append_input() call.</p> | |
64 | ||
65 | <p style="margin-left:11%; margin-top: 1em">Argument m is a | |
66 | libmawk context previously returned by libmawk_initialize() | |
67 | or libmawk_initialize_stage3().</p> | |
68 | ||
69 | <h2>SEE ALSO | |
70 | <a name="SEE ALSO"></a> | |
71 | </h2> | |
72 | ||
73 | ||
74 | ||
75 | <p style="margin-left:11%; margin-top: 1em"><b>libmawk_initialize_stage</b>(3libmawk), | |
76 | <b>libmawk_initialize</b>(3libmawk), | |
77 | <b>libmawk_append_input</b>(3libmawk),</p> | |
78 | <hr> | |
79 | </body> | |
80 | </html> |
0 | <!-- Creator : groff version 1.22.2 --> | |
1 | <!-- CreationDate: Sat Jun 14 14:27:32 2014 --> | |
2 | <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" | |
3 | "http://www.w3.org/TR/html4/loose.dtd"> | |
4 | <html> | |
5 | <head> | |
6 | <meta name="generator" content="groff -Thtml, see www.gnu.org"> | |
7 | <meta http-equiv="Content-Type" content="text/html; charset=US-ASCII"> | |
8 | <meta name="Content-Style" content="text/css"> | |
9 | <style type="text/css"> | |
10 | p { margin-top: 0; margin-bottom: 0; vertical-align: top } | |
11 | pre { margin-top: 0; margin-bottom: 0; vertical-align: top } | |
12 | table { margin-top: 0; margin-bottom: 0; vertical-align: top } | |
13 | h1 { text-align: center } | |
14 | </style> | |
15 | <title>LIBMAWK_SET_CELL</title> | |
16 | ||
17 | </head> | |
18 | <body> | |
19 | ||
20 | <h1 align="center">LIBMAWK_SET_CELL</h1> | |
21 | ||
22 | <a href="#NAME">NAME</a><br> | |
23 | <a href="#SYNOPSIS">SYNOPSIS</a><br> | |
24 | <a href="#DESCRIPTION">DESCRIPTION</a><br> | |
25 | <a href="#RETURN VALUE">RETURN VALUE</a><br> | |
26 | <a href="#SEE ALSO">SEE ALSO</a><br> | |
27 | ||
28 | <hr> | |
29 | ||
30 | ||
31 | <h2>NAME | |
32 | <a name="NAME"></a> | |
33 | </h2> | |
34 | ||
35 | ||
36 | ||
37 | <p style="margin-left:11%; margin-top: 1em">libmawk_set_cell | |
38 | − set the value of a mawk cell.</p> | |
39 | ||
40 | <h2>SYNOPSIS | |
41 | <a name="SYNOPSIS"></a> | |
42 | </h2> | |
43 | ||
44 | ||
45 | <p style="margin-left:11%; margin-top: 1em"><b>#include | |
46 | <libmawk.h></b></p> | |
47 | ||
48 | <p style="margin-left:11%; margin-top: 1em"><b>CELL | |
49 | *libmawk_set_cell(mawk_state_t *</b><i>m</i><b>, CELL | |
50 | *</b><i>cell</i><b>, const | |
51 | char</b><i>argtype</i><b>,</b><i>...</i><b>); <br> | |
52 | CELL *libmawk_set_cellp(mawk_state_t *</b><i>m</i><b>, CELL | |
53 | *</b><i>cell</i><b>, const char</b><i>argtype</i><b>, void | |
54 | *</b><i>argp</i><b>);</b></p> | |
55 | ||
56 | <h2>DESCRIPTION | |
57 | <a name="DESCRIPTION"></a> | |
58 | </h2> | |
59 | ||
60 | ||
61 | <p style="margin-left:11%; margin-top: 1em">The | |
62 | <b>libmawk_set_cell</b>() function modifies the value of a | |
63 | mawk cell (variable). Argumetn argtype is a format character | |
64 | that describes the type of the payload (accessed trough | |
65 | vararg).</p> | |
66 | ||
67 | <p style="margin-left:11%; margin-top: 1em">The | |
68 | <b>libmawk_set_cellp</b>() function performs the same action | |
69 | but accepts a generic pointer to the payload.</p> | |
70 | ||
71 | <p style="margin-left:11%; margin-top: 1em"><b>Format | |
72 | character</b> is one of the followings: <br> | |
73 | ’d’ for int payload <br> | |
74 | ’f’ for double payload <br> | |
75 | ’s’ for (zero terminated) char * payload.</p> | |
76 | ||
77 | <p style="margin-top: 1em">Argument m is a libmawk context | |
78 | previously returned by libmawk_initialize() or | |
79 | libmawk_initialize_stage3().</p> | |
80 | ||
81 | <h2>RETURN VALUE | |
82 | <a name="RETURN VALUE"></a> | |
83 | </h2> | |
84 | ||
85 | ||
86 | <p style="margin-left:11%; margin-top: 1em">A pointer to | |
87 | the cell modified.</p> | |
88 | ||
89 | <h2>SEE ALSO | |
90 | <a name="SEE ALSO"></a> | |
91 | </h2> | |
92 | ||
93 | ||
94 | ||
95 | <p style="margin-left:11%; margin-top: 1em"><b>libmawk_initialize_stage</b>(3libmawk), | |
96 | <b>libmawk_initialize</b>(3libmawk), | |
97 | <b>libmawk_get_var</b>(3libmawk).</p> | |
98 | <hr> | |
99 | </body> | |
100 | </html> |