*** empty log message ***

This commit is contained in:
hyung-hwan 2007-03-14 08:07:21 +00:00
parent 10311f1433
commit 974656c4ae
3 changed files with 555 additions and 60 deletions

View File

@ -44,16 +44,16 @@ typedef struct ase_awk_prmfns_t ase_awk_prmfns_t;
struct ase_awk_prmfns_t struct ase_awk_prmfns_t
{ {
ase_mmgr_t mmgr; ase_mmgr_t mmgr;
ase_ccls_t ccls; ase_ccls_t ccls;
struct struct
{ {
ase_awk_pow_t pow; ase_awk_pow_t pow;
ase_awk_sprintf_t sprintf; ase_awk_sprintf_t sprintf;
ase_awk_dprintf_t dprintf; ase_awk_dprintf_t dprintf;
void* custom_data; void* custom_data;
} misc; } misc;
}; };
}}} }}}
@ -64,14 +64,11 @@ A caller of ##ase_awk_open## should fill in most of the fields of a ##ase_awk_pr
typedef ase_real_t (*ase_awk_pow_t) (void* custom, ase_real_t x, ase_real_t y); typedef ase_real_t (*ase_awk_pow_t) (void* custom, ase_real_t x, ase_real_t y);
/* similar to snprintf of the standard C library. */ /* similar to snprintf of the standard C library. */
typedef int (*ase_awk_sprintf_t) ( typedef int (*ase_awk_sprintf_t) (void* custom, ase_char_t* buf, ase_size_t size, const ase_char_t* fmt, ...);
void* custom, ase_char_t* buf, ase_size_t size,
const ase_char_t* fmt, ...);
/* similar to printf of the standard C library. called by a few uncommonly /* similar to printf of the standard C library. called by a few uncommonly
* used output functions usually for debugging purpose */ * used output functions usually for debugging purpose */
typedef void (*ase_awk_dprintf_t) ( typedef void (*ase_awk_dprintf_t) (void* custom, const ase_char_t* fmt, ...);
void* custom, const ase_char_t* fmt, ...);
}}} }}}
The fourth field of the group is passed to its member functions as the first argument on invocation. The function pointed by the ##sprintf## field should ensure that the resuliting string is null-terminated and ##%s## and ##%c## are accepted for the ##ase_char_t*## and ##ase_char_t## type respectively regardless the character mode. The fourth field of the group is passed to its member functions as the first argument on invocation. The function pointed by the ##sprintf## field should ensure that the resuliting string is null-terminated and ##%s## and ##%c## are accepted for the ##ase_char_t*## and ##ase_char_t## type respectively regardless the character mode.
@ -115,7 +112,6 @@ struct ase_ccls_t
The functions in these groups perform the memory operations and character class related operations respectively. They follow the style of the memory allocation functions and character class handling functions of the standard C library except that they accept a pointer to the user-defined data as the first argument, thus providing more flexibility. The pointer to the user-defined data is specified into the ##custom_data## field of each group. The ##realloc## field, however, can be ##ASE_NULL##, in which case the functions pointed by the free and the malloc field replace the role of the function pointed by the ##realloc## field. The functions in these groups perform the memory operations and character class related operations respectively. They follow the style of the memory allocation functions and character class handling functions of the standard C library except that they accept a pointer to the user-defined data as the first argument, thus providing more flexibility. The pointer to the user-defined data is specified into the ##custom_data## field of each group. The ##realloc## field, however, can be ##ASE_NULL##, in which case the functions pointed by the free and the malloc field replace the role of the function pointed by the ##realloc## field.
=== Source IO Handler === === Source IO Handler ===
The source code is handled by a source input handler provided by the user. The optional source code output handler can be provided to have the internal parse tree converted back to the source code. The source code is handled by a source input handler provided by the user. The optional source code output handler can be provided to have the internal parse tree converted back to the source code.
@ -123,16 +119,15 @@ The source code is handled by a source input handler provided by the user. The o
The source code handler is defined as follows: The source code handler is defined as follows:
{{{ {{{
typedef ase_ssize_t (*ase_awk_io_t) ( typedef ase_ssize_t (*ase_awk_io_t) (int cmd, void* custom, ase_char_t* data, ase_size_t count);
int cmd, void* custom, ase_char_t* data, ase_size_t count);
typedef struct ase_awk_srcios_t ase_awk_srcios_t; typedef struct ase_awk_srcios_t ase_awk_srcios_t;
struct ase_awk_srcios_t struct ase_awk_srcios_t
{ {
ase_awk_io_t in; /* source input */ ase_awk_io_t in; /* source input */
ase_awk_io_t out; /* source output */ ase_awk_io_t out; /* source output */
void* custom_data; void* custom_data;
}; };
}}} }}}
@ -146,61 +141,62 @@ The typical source handler will look as follows:
{{{ {{{
ase_ssize_t awk_srcio_in (int cmd, void* arg, ase_char_t* data, ase_size_t size) ase_ssize_t awk_srcio_in (int cmd, void* arg, ase_char_t* data, ase_size_t size)
{ {
if (cmd == ASE_AWK_IO_OPEN) if (cmd == ASE_AWK_IO_OPEN)
{ {
/* open the stream */ /* open the stream */
return 1; return 1;
} }
else if (cmd == ASE_AWK_IO_CLOSE) else if (cmd == ASE_AWK_IO_CLOSE)
{ {
/* close the stream */ /* close the stream */
return 0; return 0;
} }
else if (cmd == ASE_AWK_IO_READ) else if (cmd == ASE_AWK_IO_READ)
{ {
/* read the stream */ /* read the stream */
return the number of characters read; return the number of characters read;
} }
return -1; return -1;
} }
ase_ssize_t awk_srcio_out (int cmd, void* arg, ase_char_t* data, ase_size_t size) ase_ssize_t awk_srcio_out (int cmd, void* arg, ase_char_t* data, ase_size_t size)
{ {
if (cmd == ASE_AWK_IO_OPEN) if (cmd == ASE_AWK_IO_OPEN)
{ {
/* open the stream */ /* open the stream */
return 1; return 1;
} }
else if (cmd == ASE_AWK_IO_CLOSE) else if (cmd == ASE_AWK_IO_CLOSE)
{ {
/* close the stream after flushing it */ /* close the stream after flushing it */
return 0; return 0;
} }
else if (cmd == ASE_AWK_IO_WRITE) else if (cmd == ASE_AWK_IO_WRITE)
{ {
/* write the stream */ /* write the stream */
return the number of characters written; return the number of characters written;
} }
return -1; return -1;
} }
}}} }}}
Once you have the source handler ready, you can fill in the fields of a ##ase_awk_srcios_t## structure and pass it to the call of ##ase_awk_parse##. Once you have the source handler ready, you can fill in the fields of a ##ase_awk_srcios_t## structure and pass it to the call of ##ase_awk_parse##.
{{{ {{{
ase_awk_srcios_t srcios; ase_awk_srcios_t srcios;
srcios.in = awk_srcio_in; srcios.in = awk_srcio_in;
srcios.out = awk_srcio_out; srcios.out = awk_srcio_out;
srcios.custom_data = point to the extra information necessary; srcios.custom_data = point to the extra information necessary;
ase_awk_parse (awk, &srcios); if (ase_awk_parse (awk, &srcios) == -1)
{
/* handle error */
}
}}} }}}
=== External IO Handler === === External IO Handler ===
External IO handlers should be provided to support the AWK's built-in IO facilities. External IO handlers should be provided to support the AWK's built-in IO facilities.

View File

@ -20,6 +20,9 @@ all: aseawk
aseawk: awk.obj aseawk: awk.obj
link /nologo /out:$@.exe $(LDFLAGS) $(LIBS) awk.obj link /nologo /out:$@.exe $(LDFLAGS) $(LIBS) awk.obj
mini: mini.obj
link /nologo /out:$@.exe $(LDFLAGS) $(LIBS) mini.obj
java: java:
javac -classpath ../../.. Awk.java javac -classpath ../../.. Awk.java
@ -27,7 +30,7 @@ jrun:
java -classpath ../../.. ase.test.awk.Awk java -classpath ../../.. ase.test.awk.Awk
clean: clean:
del $(OBJS) *.obj aseawk.exe del $(OBJS) *.obj aseawk.exe mini.exe
.SUFFIXES: .c .obj .SUFFIXES: .c .obj
.c.obj: .c.obj:

496
ase/test/awk/mini.c Normal file
View File

@ -0,0 +1,496 @@
/*
* $Id: mini.c,v 1.1 2007-03-14 08:07:21 bacon Exp $
*/
#include <ase/awk/awk.h>
#include <ase/cmn/str.h>
#include <ase/cmn/mem.h>
#include <ase/utl/ctype.h>
#include <ase/utl/stdio.h>
#include <ase/utl/main.h>
#include <stdarg.h>
#include <math.h>
#include <stdlib.h>
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 <ase/utl/main.c>
#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;
}