diff --git a/ase/doc/ase-en.man b/ase/doc/ase-en.man index 7190801d..3c595762 100644 --- a/ase/doc/ase-en.man +++ b/ase/doc/ase-en.man @@ -20,7 +20,7 @@ ase-0.1.0.tgz [[[ * {Quickstart,quickstart-en.html} -* {Embedder's guide,awk-en.html} +* {Embedder guide,awk-en.html} * {Frequently Asked Questions,faq-en.html} ]]] diff --git a/ase/doc/awk-mini-en.man b/ase/doc/awk-mini-en.man new file mode 100644 index 00000000..f63b08d7 --- /dev/null +++ b/ase/doc/awk-mini-en.man @@ -0,0 +1,509 @@ +.title Annotated ASEAWK Embedding Sample + +== Annotate ASEAWK Embedding Sample == + +This document annotates a simple embedding sample. Locate the ase_main function to begin exploring the sample. The non-annotated source is available from ##ase/test/awk/mini.c## as well. + +== mini.c == + +{{{ + +/* most of the data types and functions are defined ase/awk/awk.h */ +#include + +/* ase_strXXX and ase_str_XXX functions are defined in ase/str/str.h */ +#include + +/* ase_memXXX functions are defined in ase/cmn/mem.h */ +#include + +/* the following three headers files export +#include +#include +#include + +#include +#include +#include + +struct awk_src_io +{ + const ase_char_t* file; + FILE* handle; +}; + +static const ase_char_t* data_file = ASE_NULL; + +#if defined(vms) || defined(__vms) +/* it seems that the main function should be placed in the main object file + * in OpenVMS. otherwise, the first function in the main object file seems + * to become the main function resulting in program start-up failure. */ +#include +#endif + +#ifndef NDEBUG +void ase_assert_abort (void) +{ + abort (); +} + +void ase_assert_printf (const ase_char_t* fmt, ...) +{ + va_list ap; + va_start (ap, fmt); + ase_vprintf (fmt, ap); + va_end (ap); +} +#endif + + +/* custom memory management function */ +static void* custom_awk_malloc (void* custom, ase_size_t n) +{ + return malloc (n); +} + +static void* custom_awk_realloc (void* custom, void* ptr, ase_size_t n) +{ + return realloc (ptr, n); +} + +static void custom_awk_free (void* custom, void* ptr) +{ + free (ptr); +} + +/* custom character class functions */ +static ase_bool_t custom_awk_isupper (void* custom, ase_cint_t c) +{ + return ase_isupper (c); +} + +static ase_bool_t custom_awk_islower (void* custom, ase_cint_t c) +{ + return ase_islower (c); +} + +static ase_bool_t custom_awk_isalpha (void* custom, ase_cint_t c) +{ + return ase_isalpha (c); +} + +static ase_bool_t custom_awk_isdigit (void* custom, ase_cint_t c) +{ + return ase_isdigit (c); +} + +static ase_bool_t custom_awk_isxdigit (void* custom, ase_cint_t c) +{ + return ase_isxdigit (c); +} + +static ase_bool_t custom_awk_isalnum (void* custom, ase_cint_t c) +{ + return ase_isalnum (c); +} + +static ase_bool_t custom_awk_isspace (void* custom, ase_cint_t c) +{ + return ase_isspace (c); +} + +static ase_bool_t custom_awk_isprint (void* custom, ase_cint_t c) +{ + return ase_isprint (c); +} + +static ase_bool_t custom_awk_isgraph (void* custom, ase_cint_t c) +{ + return ase_isgraph (c); +} + +static ase_bool_t custom_awk_iscntrl (void* custom, ase_cint_t c) +{ + return ase_iscntrl (c); +} + +static ase_bool_t custom_awk_ispunct (void* custom, ase_cint_t c) +{ + return ase_ispunct (c); +} + +static ase_cint_t custom_awk_toupper (void* custom, ase_cint_t c) +{ + return ase_toupper (c); +} + +static ase_cint_t custom_awk_tolower (void* custom, ase_cint_t c) +{ + return ase_tolower (c); +} + +/* custom miscellaneous functions */ +static ase_real_t custom_awk_pow (void* custom, ase_real_t x, ase_real_t y) +{ + return pow (x, y); +} + +static int custom_awk_sprintf ( + void* custom, ase_char_t* buf, ase_size_t size, + const ase_char_t* fmt, ...) +{ + int n; + + va_list ap; + va_start (ap, fmt); + n = ase_vsprintf (buf, size, fmt, ap); + va_end (ap); + + return n; +} + +static void custom_awk_dprintf (void* custom, const ase_char_t* fmt, ...) +{ + va_list ap; + va_start (ap, fmt); + ase_vfprintf (stderr, fmt, ap); + va_end (ap); +} + +/* source input handler */ +static ase_ssize_t awk_srcio_in ( + int cmd, void* arg, ase_char_t* data, ase_size_t size) +{ + struct awk_src_io* src_io = (struct awk_src_io*)arg; + ase_cint_t c; + + if (cmd == ASE_AWK_IO_OPEN) + { + if (src_io->file == ASE_NULL) return 0; + src_io->handle = ase_fopen (src_io->file, ASE_T("r")); + if (src_io->handle == NULL) return -1; + return 1; + } + else if (cmd == ASE_AWK_IO_CLOSE) + { + if (src_io->file == ASE_NULL) return 0; + fclose ((FILE*)src_io->handle); + return 0; + } + else if (cmd == ASE_AWK_IO_READ) + { + if (size <= 0) return -1; + c = ase_fgetc ((FILE*)src_io->handle); + if (c == ASE_CHAR_EOF) return 0; + *data = (ase_char_t)c; + return 1; + } + + return -1; +} + +/* external i/o handler for pipe */ +static ase_ssize_t awk_extio_pipe ( + int cmd, void* arg, ase_char_t* data, ase_size_t size) +{ + ase_awk_extio_t* epa = (ase_awk_extio_t*)arg; + + switch (cmd) + { + case ASE_AWK_IO_OPEN: + { + FILE* handle; + const ase_char_t* mode; + + if (epa->mode == ASE_AWK_EXTIO_PIPE_READ) + mode = ASE_T("r"); + else if (epa->mode == ASE_AWK_EXTIO_PIPE_WRITE) + mode = ASE_T("w"); + else return -1; + + handle = ase_popen (epa->name, mode); + if (handle == NULL) return -1; + epa->handle = (void*)handle; + return 1; + } + + case ASE_AWK_IO_CLOSE: + { + fclose ((FILE*)epa->handle); + epa->handle = NULL; + return 0; + } + + case ASE_AWK_IO_READ: + { + if (ase_fgets (data, size, (FILE*)epa->handle) == ASE_NULL) + { + if (ferror((FILE*)epa->handle)) return -1; + return 0; + } + return ase_strlen(data); + } + + case ASE_AWK_IO_WRITE: + { + #if defined(ASE_CHAR_IS_WCHAR) && defined(__linux) + /* fwprintf seems to return an error with the file + * pointer opened by popen, as of this writing. + * anyway, hopefully the following replacement + * will work all the way. */ + int n = fprintf ( + (FILE*)epa->handle, "%.*ls", size, data); + #else + int n = ase_fprintf ( + (FILE*)epa->handle, ASE_T("%.*s"), size, data); + #endif + if (n < 0) return -1; + + return size; + } + + case ASE_AWK_IO_FLUSH: + { + if (epa->mode == ASE_AWK_EXTIO_PIPE_READ) return -1; + else return 0; + } + + case ASE_AWK_IO_NEXT: + { + return -1; + } + } + + return -1; +} + +/* external i/o handler for file */ +static ase_ssize_t awk_extio_file ( + int cmd, void* arg, ase_char_t* data, ase_size_t size) +{ + ase_awk_extio_t* epa = (ase_awk_extio_t*)arg; + + switch (cmd) + { + case ASE_AWK_IO_OPEN: + { + FILE* handle; + const ase_char_t* mode; + + if (epa->mode == ASE_AWK_EXTIO_FILE_READ) + mode = ASE_T("r"); + else if (epa->mode == ASE_AWK_EXTIO_FILE_WRITE) + mode = ASE_T("w"); + else if (epa->mode == ASE_AWK_EXTIO_FILE_APPEND) + mode = ASE_T("a"); + else return -1; + + handle = ase_fopen (epa->name, mode); + if (handle == NULL) return -1; + + epa->handle = (void*)handle; + return 1; + } + + case ASE_AWK_IO_CLOSE: + { + fclose ((FILE*)epa->handle); + epa->handle = NULL; + return 0; + } + + case ASE_AWK_IO_READ: + { + if (ase_fgets (data, size, (FILE*)epa->handle) == ASE_NULL) + { + if (ferror((FILE*)epa->handle)) return -1; + return 0; + } + return ase_strlen(data); + } + + case ASE_AWK_IO_WRITE: + { + int n = ase_fprintf ( + (FILE*)epa->handle, ASE_T("%.*s"), size, data); + if (n < 0) return -1; + + return size; + } + + case ASE_AWK_IO_FLUSH: + { + if (fflush ((FILE*)epa->handle) == EOF) return -1; + return 0; + } + + case ASE_AWK_IO_NEXT: + { + return -1; + } + + } + + return -1; +} + +/* external i/o handler for console */ +static ase_ssize_t awk_extio_console ( + int cmd, void* arg, ase_char_t* data, ase_size_t size) +{ + ase_awk_extio_t* epa = (ase_awk_extio_t*)arg; + + if (cmd == ASE_AWK_IO_OPEN) + { + if (epa->mode == ASE_AWK_EXTIO_CONSOLE_READ) + { + FILE* fp = ase_fopen (data_file, ASE_T("r")); + if (fp == ASE_NULL) return -1; + + if (ase_awk_setfilename ( + epa->run, data_file, ase_strlen(data_file)) == -1) + { + fclose (fp); + return -1; + } + + epa->handle = fp; + + return 1; + } + else if (epa->mode == ASE_AWK_EXTIO_CONSOLE_WRITE) + { + epa->handle = stdout; + return 1; + } + + return -1; + } + else if (cmd == ASE_AWK_IO_CLOSE) + { + fclose ((FILE*)epa->handle); + epa->handle = NULL; + return 0; + } + else if (cmd == ASE_AWK_IO_READ) + { + while (ase_fgets (data, size, (FILE*)epa->handle) == ASE_NULL) + { + if (ferror((FILE*)epa->handle)) return -1; + return 0; + } + + return ase_strlen(data); + } + else if (cmd == ASE_AWK_IO_WRITE) + { + int n = ase_fprintf ((FILE*)epa->handle, ASE_T("%.*s"), size, data); + if (n < 0) return -1; + + return size; + } + else if (cmd == ASE_AWK_IO_FLUSH) + { + if (fflush ((FILE*)epa->handle) == EOF) return -1; + return 0; + } + else if (cmd == ASE_AWK_IO_NEXT) + { + return -1; + } + + return -1; +} + +int ase_main (int argc, ase_char_t* argv[]) +{ + ase_awk_t* awk; + + ase_awk_prmfns_t prmfns; + ase_awk_srcios_t srcios; + ase_awk_runios_t runios; + + struct awk_src_io src_io = { NULL, NULL }; + + if (argc != 3) + { + ase_printf (ASE_T("Usage: %s source-file data-file\n"), argv[0]); + return -1; + } + + src_io.file = argv[1]; + data_file = argv[2]; + + ase_memset (&prmfns, 0, ASE_SIZEOF(prmfns)); + + prmfns.mmgr.malloc = custom_awk_malloc; + prmfns.mmgr.realloc = custom_awk_realloc; + prmfns.mmgr.free = custom_awk_free; + prmfns.mmgr.custom_data = ASE_NULL; + + prmfns.ccls.is_upper = custom_awk_isupper; + prmfns.ccls.is_lower = custom_awk_islower; + prmfns.ccls.is_alpha = custom_awk_isalpha; + prmfns.ccls.is_digit = custom_awk_isdigit; + prmfns.ccls.is_xdigit = custom_awk_isxdigit; + prmfns.ccls.is_alnum = custom_awk_isalnum; + prmfns.ccls.is_space = custom_awk_isspace; + prmfns.ccls.is_print = custom_awk_isprint; + prmfns.ccls.is_graph = custom_awk_isgraph; + prmfns.ccls.is_cntrl = custom_awk_iscntrl; + prmfns.ccls.is_punct = custom_awk_ispunct; + prmfns.ccls.to_upper = custom_awk_toupper; + prmfns.ccls.to_lower = custom_awk_tolower; + prmfns.ccls.custom_data = ASE_NULL; + + prmfns.misc.pow = custom_awk_pow; + prmfns.misc.sprintf = custom_awk_sprintf; + prmfns.misc.dprintf = custom_awk_dprintf; + prmfns.misc.custom_data = ASE_NULL; + + if ((awk = ase_awk_open(&prmfns, ASE_NULL)) == ASE_NULL) + { + ase_printf (ASE_T("ERROR: cannot open awk\n")); + return -1; + } + + ase_awk_setoption (awk, + ASE_AWK_IMPLICIT | ASE_AWK_EXPLICIT | ASE_AWK_UNIQUEFN | + ASE_AWK_IDIV | ASE_AWK_SHADING | ASE_AWK_SHIFT | + ASE_AWK_EXTIO | ASE_AWK_BLOCKLESS | ASE_AWK_STRBASEONE | + ASE_AWK_STRIPSPACES | ASE_AWK_NEXTOFILE); + + srcios.in = awk_srcio_in; + srcios.out = ASE_NULL; + srcios.custom_data = &src_io; + + if (ase_awk_parse (awk, &srcios) == -1) + { + ase_printf ( + ASE_T("PARSE ERROR: CODE [%d] LINE [%u] %s\n"), + ase_awk_geterrnum(awk), + (unsigned int)ase_awk_geterrlin(awk), + ase_awk_geterrmsg(awk)); + ase_awk_close (awk); + return -1; + } + + runios.pipe = awk_extio_pipe; + runios.file = awk_extio_file; + runios.console = awk_extio_console; + runios.custom_data = ASE_NULL; + + if (ase_awk_run (awk, ASE_NULL, &runios, ASE_NULL, ASE_NULL, ASE_NULL) == -1) + { + ase_printf ( + ASE_T("RUN ERROR: CODE [%d] LINE [%u] %s\n"), + ase_awk_geterrnum(awk), + (unsigned int)ase_awk_geterrlin(awk), + ase_awk_geterrmsg(awk)); + + ase_awk_close (awk); + return -1; + } + + ase_awk_close (awk); + return 0; +} + +}}} diff --git a/ase/doc/doc.css b/ase/doc/doc.css index 672ae374..fe7f3705 100644 --- a/ase/doc/doc.css +++ b/ase/doc/doc.css @@ -1,6 +1,6 @@ body { - font-family: "times new roman", verdana, tahoma, lucida, sans-serif; + font-family: verdana, "times new roman", tahoma, lucida, sans-serif; background-color: white; color: black; #padding: 10px 10px 10px 10px; @@ -18,7 +18,7 @@ body h1,h2,h3,h4,h5 { - font-family: verdana, tahoma; + font-family: tahoma, "times new roman", verdana; border-bottom: 1px solid #779098; } h1 { font-size: 120%; } @@ -71,7 +71,10 @@ pre.code padding: 6px 6px 6px 6px; xbackground-color: #000000; xcolor: #FFD700; - border: 1px dashed #779098; + #border: 1px dashed #779098; + #border: 1px solid #779098; + border: none; + background-color: yellow; } .linenum