head	1.2;
access;
symbols;
locks; strict;
comment	@# @;


1.2
date	2020.08.03.02.09.49;	author agc;	state Exp;
branches;
next	1.1;
commitid	OApujfOqM88wNyiC;

1.1
date	2013.06.01.22.27.32;	author agc;	state Exp;
branches;
next	;
commitid	iN24HBUPLvFJKXRw;


desc
@@


1.2
log
@Fix typo - thanks to Brad Harder (yukonbob)!
@
text
@Extending eawk
==============

To add new functionality to eawk, extensions are used. They can be layered
on top of each other, and provide access to third-party libraries. To write
and use an extensions, we'll look at the base64 encoding extension in eawk:

-- see extend/base64/base64.c

1. include the header to get definitions

#include "eawk.h"

2. write wrapper functions for every function you want to call from eawk:

	/* base64 encode function */
	static awkcell_t *
	eawk_base64_b64encode(void *veawk, char *name, int argc, awkcell_t **a)
	{
		eawk_t		*eawk = (eawk_t *)veawk;
		size_t		 outsize;
		size_t		 insize;
		char		*out;
		char		*in;

		USE_ARG(name);
		if (argc < 1 || argc > 2) {
			eawk_setsval(eawk, eawk->fp->retval, "");
			return eawk->fp->retval;
		}
		/* get data off stack */
		in = eawk_getsval(eawk, a[0]);
		insize = (argc > 1) ? (size_t)eawk_getfval(eawk, a[1]) : strlen(in);
		outsize = ((insize * 4) / 3) + 32;
		out = calloc(1, outsize);
		outsize = b64encode(in, insize, out, outsize, 0);
		/* return code */
		eawk_setsvalN(eawk, eawk->fp->retval, out, outsize);
		free(out);
		return eawk->fp->retval;
	}

argc gives the number of args the awk script used when calling your function

string data is retrieved from the runtime stack with eawk_getsval, args are
numbered from 0 (and the function name and return value are not counted).
Numeric data can be retried with eawk_getfval.

When returning args, eawk_setsval is used for strings (and eawk_setsvalN for
fixed length strings). eawk_setfval is used for numeric data. Arrays can be
used to receive and send back values, see the regexec() wrapper for an example
of this.

3.  Finally, the extension mechanism loads the wrapper functions from
a .so, and the function is accessed using this mechanism.

	int eawk_use_base64(eawk_t */*eawk*/);

	/* register base64 functions */
	int
	eawk_use_base64(eawk_t *eawk)
	{
		if (eawk_find_lib(eawk, "base64") < 0) {
			eawk_register_func(eawk, "base64", "b64decode", eawk_base64_b64decode);
			eawk_register_func(eawk, "base64", "b64encode", eawk_base64_b64encode);
			eawk_register_func(eawk, "base64", "b85decode", eawk_base64_b85decode);
			eawk_register_func(eawk, "base64", "b85encode", eawk_base64_b85encode);
		}
		return 1;
	}

The eawk_register_func is the means by which a wrapper function (see
above) is invoked from an eawk script.  The second arg is the name of
the library, the third arg the name that is recognised in the script
to invoke the function, and the last arg is the name of the function
which we defined earlier.

It's possible for a wrapper function to be called with different
script function names -- see the lstat and stat wrapper function in
extend/c/c.c

We also forward declare the 'use' function to avoid compiler warnings -

	int eawk_use_base64(eawk_t */*eawk*/);

it will be invoked automatically using dlopen(3) functionality.

4. An example of its use:

        echo "Another fine mess you got me into" | \
	env LD_LIBRARY_PATH=lib:extend/base64 bin/eawk '\
		BEGIN { use("base64") }
		{ print $0, b64encode($0), b85encode($0) }'

(which is test 23 in the regression test suite, and prints out base64
and base85 encoding for the input)
@


1.1
log
@add preliminary documentation for both extending, and embedding, eawk.
@
text
@d5 1
a5 1
on top of each other, and provide access to thirs-party libraries. To write
@

