diff --git a/ase/awk/Awk.java b/ase/awk/Awk.java index a358e04e..a85428a2 100644 --- a/ase/awk/Awk.java +++ b/ase/awk/Awk.java @@ -1,5 +1,5 @@ /* - * $Id: Awk.java,v 1.11 2006-11-26 16:16:34 bacon Exp $ + * $Id: Awk.java,v 1.12 2006-11-27 04:33:21 bacon Exp $ */ package ase.awk; @@ -20,7 +20,7 @@ public abstract class Awk { public Object run () { - //System.load ("c://projects//ase/awk/aseawk.dll"); + System.load ("c://projects//ase/awk/aseawk.dll"); return null; } }); diff --git a/ase/awk/awk.h b/ase/awk/awk.h index 660b4016..80690ba6 100644 --- a/ase/awk/awk.h +++ b/ase/awk/awk.h @@ -1,5 +1,5 @@ /* - * $Id: awk.h,v 1.152 2006-11-25 15:51:30 bacon Exp $ + * $Id: awk.h,v 1.153 2006-11-27 04:33:22 bacon Exp $ */ #ifndef _ASE_AWK_AWK_H_ @@ -141,7 +141,7 @@ enum ASE_AWK_EXPLICIT = (1 << 1), /* a function name should not coincide to be a variable name */ - ASE_AWK_UNIQUE = (1 << 2), + ASE_AWK_UNIQUEAFN = (1 << 2), /* allow variable shading */ ASE_AWK_SHADING = (1 << 3), @@ -250,7 +250,10 @@ enum ASE_AWK_EENDBLOCK, /* END requires an action block */ ASE_AWK_EDUPBEGIN, /* duplicate BEGIN */ ASE_AWK_EDUPEND, /* duplicate END */ - ASE_AWK_EDUPFUNC, /* duplicate function name */ + ASE_AWK_EFNREDEFBFN, /* function redefines a builtin function */ + ASE_AWK_EFNREDEFAFN, /* function redefines an existing function */ + ASE_AWK_EFNREDEFGLOBAL, /* function redefines a global variable */ + ASE_AWK_EPARREDEFAFN, /* parameter redefines the function name */ ASE_AWK_EDUPPARAM, /* duplicate parameter name */ ASE_AWK_EDUPVAR, /* duplicate variable name */ ASE_AWK_EDUPNAME, /* duplicate name - function, variable, etc */ diff --git a/ase/awk/err.c b/ase/awk/err.c index 74151aac..51e691be 100644 --- a/ase/awk/err.c +++ b/ase/awk/err.c @@ -1,5 +1,5 @@ /* - * $Id: err.c,v 1.51 2006-11-19 10:12:07 bacon Exp $ + * $Id: err.c,v 1.52 2006-11-27 04:33:22 bacon Exp $ */ #include @@ -64,7 +64,10 @@ const ase_char_t* ase_awk_geterrstr (int errnum) ASE_T("END requires an action block"), ASE_T("duplicate BEGIN"), ASE_T("duplicate END"), - ASE_T("duplicate function name"), + ASE_T("the function name redefines a built-in function"), + ASE_T("a function cannot be redefined with the same name"), + ASE_T("the function name redefines a global variable"), + ASE_T("a parameter name cannot be the same as the name of the owning function"), ASE_T("duplicate parameter name"), ASE_T("duplicate variable name"), ASE_T("duplicate name"), diff --git a/ase/awk/jni.c b/ase/awk/jni.c index 56e3fe58..1b69078b 100644 --- a/ase/awk/jni.c +++ b/ase/awk/jni.c @@ -1,5 +1,5 @@ /* - * $Id: jni.c,v 1.26 2006-11-26 15:55:43 bacon Exp $ + * $Id: jni.c,v 1.27 2006-11-27 04:33:22 bacon Exp $ */ #include @@ -21,8 +21,9 @@ #error this module supports ASE_CHAR_IS_WCHAR only #endif -#define EXCEPTION_AWK "ase/awk/Exception" -#define FIELD_HANDLE "handle" +#define CLASS_EXCEPTION "ase/awk/Exception" +#define CLASS_EXTIO "ase/awk/Extio" +#define FIELD_HANDLE "handle" enum { @@ -143,7 +144,7 @@ static void __awk_dprintf (const ase_char_t* fmt, ...) JNIEXPORT void JNICALL Java_ase_awk_Awk_open (JNIEnv* env, jobject obj) { jclass class; - jfieldID fid; + jfieldID fid_handle; jthrowable except; ase_awk_t* awk; ase_awk_syscas_t syscas; @@ -181,39 +182,55 @@ JNIEXPORT void JNICALL Java_ase_awk_Awk_open (JNIEnv* env, jobject obj) awk = ase_awk_open (&syscas); if (awk == NULL) { - except = (*env)->FindClass (env, EXCEPTION_AWK); - if (except == 0) return; + (*env)->DeleteLocalRef (env, class); + + except = (*env)->FindClass (env, CLASS_EXCEPTION); + if (except == NULL) return; + (*env)->ThrowNew (env, except, "cannot create awk"); + (*env)->DeleteLocalRef (env, except); return; } - fid = (*env)->GetFieldID (env, class, FIELD_HANDLE, "J"); - if (fid == 0) return; + fid_handle = (*env)->GetFieldID (env, class, FIELD_HANDLE, "J"); + if (fid_handle == 0) + { + /* something wrong. should not happen */ + (*env)->DeleteLocalRef (env, class); + return; + } - (*env)->SetLongField (env, obj, fid, (jlong)awk); + (*env)->SetLongField (env, obj, fid_handle, (jlong)awk); - opt = ASE_AWK_EXPLICIT | ASE_AWK_UNIQUE | ASE_AWK_DBLSLASHES | + opt = ASE_AWK_EXPLICIT | ASE_AWK_UNIQUEAFN | ASE_AWK_DBLSLASHES | ASE_AWK_SHADING | ASE_AWK_IMPLICIT | ASE_AWK_SHIFT | ASE_AWK_EXTIO | ASE_AWK_BLOCKLESS | ASE_AWK_HASHSIGN | ASE_AWK_NEXTOFILE; ase_awk_setopt (awk, opt); + (*env)->DeleteLocalRef (env, class); printf ("__awk(native) done => %u, 0x%X\n", awk, awk); } JNIEXPORT void JNICALL Java_ase_awk_Awk_close (JNIEnv* env, jobject obj) { jclass class; - jfieldID fid; + jfieldID fid_handle; class = (*env)->GetObjectClass(env, obj); - fid = (*env)->GetFieldID (env, class, FIELD_HANDLE, "J"); - if (fid == 0) return; + fid_handle = (*env)->GetFieldID (env, class, FIELD_HANDLE, "J"); + if (fid_handle == NULL) + { + /* something wrong. should not happen */ + (*env)->DeleteLocalRef (env, class); + return; + } - ase_awk_close ((ase_awk_t*) (*env)->GetLongField (env, obj, fid)); - (*env)->SetLongField (env, obj, fid, (jlong)0); + ase_awk_close ((ase_awk_t*)(*env)->GetLongField (env, obj, fid_handle)); + (*env)->SetLongField (env, obj, fid_handle, (jlong)0); + (*env)->DeleteLocalRef (env, class); printf ("close (native) done\n"); } @@ -280,8 +297,8 @@ JNIEXPORT void JNICALL Java_ase_awk_Awk_parse (JNIEnv* env, jobject obj) char msg[256]; int n; - except = (*env)->FindClass (env, EXCEPTION_AWK); - if (except == 0) return; + except = (*env)->FindClass (env, CLASS_EXCEPTION); + if (except == NULL) return; snprintf (msg, sizeof(msg), "parse error at line %d: %S", ase_awk_getsrcline(awk), @@ -289,6 +306,7 @@ JNIEXPORT void JNICALL Java_ase_awk_Awk_parse (JNIEnv* env, jobject obj) if (n < 0 || n >= sizeof(msg)) msg[sizeof(msg)-1] = '\0'; (*env)->ThrowNew (env, except, msg); + (*env)->DeleteLocalRef (env, except); return; } } @@ -296,7 +314,7 @@ JNIEXPORT void JNICALL Java_ase_awk_Awk_parse (JNIEnv* env, jobject obj) JNIEXPORT void JNICALL Java_ase_awk_Awk_run (JNIEnv* env, jobject obj) { jclass class; - jfieldID fid; + jfieldID fid_handle; jthrowable except; ase_awk_t* awk; @@ -305,10 +323,14 @@ JNIEXPORT void JNICALL Java_ase_awk_Awk_run (JNIEnv* env, jobject obj) class = (*env)->GetObjectClass (env, obj); - fid = (*env)->GetFieldID (env, class, FIELD_HANDLE, "J"); - if (fid == 0) return; + fid_handle = (*env)->GetFieldID (env, class, FIELD_HANDLE, "J"); + if (fid_handle == 0) + { + (*env)->DeleteLocalRef (env, class); + return; + } - awk = (ase_awk_t*) (*env)->GetLongField (env, obj, fid); + awk = (ase_awk_t*) (*env)->GetLongField (env, obj, fid_handle); runio_data.env = env; runio_data.obj = obj; @@ -326,15 +348,20 @@ JNIEXPORT void JNICALL Java_ase_awk_Awk_run (JNIEnv* env, jobject obj) char msg[256]; int n; - except = (*env)->FindClass (env, EXCEPTION_AWK); - if (except == 0) return; + (*env)->DeleteLocalRef (env, class); + + except = (*env)->FindClass (env, CLASS_EXCEPTION); + if (except == NULL) return; /* exception thrown */ snprintf (msg, sizeof(msg), "%S", ase_awk_geterrstr(ase_awk_geterrnum(awk))); if (n < 0 || n >= sizeof(msg)) msg[sizeof(msg)-1] = '\0'; (*env)->ThrowNew (env, except, msg); + (*env)->DeleteLocalRef (env, except); return; } + + (*env)->DeleteLocalRef (env, class); } static ase_ssize_t __java_open_source (JNIEnv* env, jobject obj, int mode) @@ -494,7 +521,7 @@ static ase_ssize_t __java_open_extio ( class = (*env)->GetObjectClass(env, obj); - extio_class = (*env)->FindClass (env, "ase/awk/Extio"); + extio_class = (*env)->FindClass (env, CLASS_EXTIO); if (extio_class == NULL) { (*env)->DeleteLocalRef (env, class); @@ -855,11 +882,11 @@ static ase_ssize_t __process_extio ( return -1; } -JNIEXPORT int JNICALL Java_ase_awk_Awk_setfilename (JNIEnv* env, jobject obj, jlong run_id, jstring name) +JNIEXPORT jint JNICALL Java_ase_awk_Awk_setfilename (JNIEnv* env, jobject obj, jlong run_id, jstring name) { ase_awk_run_t* run = (ase_awk_run_t*)run_id; const jchar* str; - int len, n; + jint len, n; str = (*env)->GetStringChars (env, name, JNI_FALSE); len = (*env)->GetStringLength (env, name); @@ -868,11 +895,11 @@ JNIEXPORT int JNICALL Java_ase_awk_Awk_setfilename (JNIEnv* env, jobject obj, jl return n; } -JNIEXPORT int JNICALL Java_ase_awk_Awk_setofilename (JNIEnv* env, jobject obj, jlong run_id, jstring name) +JNIEXPORT jint JNICALL Java_ase_awk_Awk_setofilename (JNIEnv* env, jobject obj, jlong run_id, jstring name) { ase_awk_run_t* run = (ase_awk_run_t*)run_id; const jchar* str; - int len, n; + jint len, n; str = (*env)->GetStringChars (env, name, JNI_FALSE); len = (*env)->GetStringLength (env, name); @@ -881,3 +908,73 @@ JNIEXPORT int JNICALL Java_ase_awk_Awk_setofilename (JNIEnv* env, jobject obj, j return n; } +static int __handle_bfn (ase_awk_run_t* run) +{ + jclass class; + jmethodID mid; + + /* + class = (*env)->GetObjectClass(env, obj); + + mid = (*env)->GetMethodID (env, class, funtion_name...., "(I)I"); + if (mid == NULL) + { + (*env)->DeleteLocalRef (env, class); + return -1; + } + */ + +/* +CreateObjectArray... +Call the method with this array. +Delete the array... +*/ + + /* + (*env)->DeleteLocalRef (env, class); + */ + return 0; +} + +JNIEXPORT void JNICALL Java_ase_awk_Awk_addbfn ( + JNIEnv* env, jobject obj, jstring name, jint min_args, jint max_args) +{ + jclass class; + jfieldID fid_handle; + jthrowable except; + + ase_awk_t* awk; + const jchar* str; + jint len; + + class = (*env)->GetObjectClass(env, obj); + + fid_handle = (*env)->GetFieldID (env, class, FIELD_HANDLE, "J"); + if (fid_handle == NULL) + { + (*env)->DeleteLocalRef (env, class); + return; + } + + awk = (ase_awk_t*) (*env)->GetLongField (env, obj, fid_handle); + + str = (*env)->GetStringChars (env, name, JNI_FALSE); + len = (*env)->GetStringLength (env, name); + + if (ase_awk_addbfn (awk, str, len, 0, + min_args, max_args, ASE_NULL, __handle_bfn) == ASE_NULL) + { + (*env)->ReleaseStringChars (env, name, str); + (*env)->DeleteLocalRef (env, class); + + except = (*env)->FindClass (env, CLASS_EXCEPTION); + if (except == NULL) return; + + (*env)->ThrowNew (env, except, "cannot add the function"); + (*env)->DeleteLocalRef (env, except); + return; + } + + (*env)->ReleaseStringChars (env, name, str); + (*env)->DeleteLocalRef (env, class); +} diff --git a/ase/awk/jni.h b/ase/awk/jni.h index 2d69bc05..a09cdba6 100644 --- a/ase/awk/jni.h +++ b/ase/awk/jni.h @@ -1,5 +1,5 @@ /* - * $Id: jni.h,v 1.9 2006-11-24 13:20:49 bacon Exp $ + * $Id: jni.h,v 1.10 2006-11-27 04:33:22 bacon Exp $ */ #ifndef _ASE_AWK_JNI_H_ @@ -15,8 +15,8 @@ JNIEXPORT void JNICALL Java_ase_awk_Awk_open (JNIEnv*, jobject); JNIEXPORT void JNICALL Java_ase_awk_Awk_close (JNIEnv*, jobject); JNIEXPORT void JNICALL Java_ase_awk_Awk_parse (JNIEnv*, jobject); JNIEXPORT void JNICALL Java_ase_awk_Awk_run (JNIEnv*, jobject); -JNIEXPORT int JNICALL Java_ase_awk_Awk_setfilename (JNIEnv*, jobject, jlong, jstring); -JNIEXPORT int JNICALL Java_ase_awk_Awk_setofilename (JNIEnv*, jobject, jlong, jstring); +JNIEXPORT jint JNICALL Java_ase_awk_Awk_setfilename (JNIEnv*, jobject, jlong, jstring); +JNIEXPORT jint JNICALL Java_ase_awk_Awk_setofilename (JNIEnv*, jobject, jlong, jstring); #ifdef __cplusplus } diff --git a/ase/awk/misc.c b/ase/awk/misc.c index 74b8422f..fc76eadb 100644 --- a/ase/awk/misc.c +++ b/ase/awk/misc.c @@ -1,5 +1,5 @@ /* - * $Id: misc.c,v 1.39 2006-11-20 11:08:08 bacon Exp $ + * $Id: misc.c,v 1.40 2006-11-27 04:33:22 bacon Exp $ */ #include @@ -541,7 +541,12 @@ ase_size_t ase_awk_longtostr ( if (t == 0) { /* zero */ - if (buf == ASE_NULL) return prefix_len + 1; + if (buf == ASE_NULL) + { + /* if buf is not given, + * return the number of bytes required */ + return prefix_len + 1; + } if (size < prefix_len+1) { @@ -552,7 +557,7 @@ ase_size_t ase_awk_longtostr ( for (i = 0; i < prefix_len; i++) buf[i] = prefix[i]; buf[prefix_len] = ASE_T('0'); if (size > prefix_len+1) buf[prefix_len+1] = ASE_T('\0'); - return 1; + return prefix_len+1; } /* non-zero values */ diff --git a/ase/awk/parse.c b/ase/awk/parse.c index edc4a8c2..b42c092a 100644 --- a/ase/awk/parse.c +++ b/ase/awk/parse.c @@ -1,5 +1,5 @@ /* - * $Id: parse.c,v 1.210 2006-11-26 15:55:44 bacon Exp $ + * $Id: parse.c,v 1.211 2006-11-27 04:33:22 bacon Exp $ */ #include @@ -620,19 +620,28 @@ static ase_awk_nde_t* __parse_function (ase_awk_t* awk) name = ASE_AWK_STR_BUF(&awk->token.name); name_len = ASE_AWK_STR_LEN(&awk->token.name); + + /* check if it is a builtin function */ + if (ase_awk_getbfn (awk, name, name_len) != ASE_NULL) + { + PANIC (awk, ASE_AWK_EFNREDEFBFN); + } + if (ase_awk_map_get(&awk->tree.afns, name, name_len) != ASE_NULL) { /* the function is defined previously */ - PANIC (awk, ASE_AWK_EDUPFUNC); + PANIC (awk, ASE_AWK_EFNREDEFAFN); } - if (awk->option & ASE_AWK_UNIQUE) + if (awk->option & ASE_AWK_UNIQUEAFN) { /* check if it coincides to be a global variable name */ - if (ase_awk_tab_find ( - &awk->parse.globals, 0, name, name_len) != (ase_size_t)-1) + ase_size_t g; + + g = ase_awk_tab_find (&awk->parse.globals, 0, name, name_len); + if (g != (ase_size_t)-1) { - PANIC (awk, ASE_AWK_EDUPNAME); + PANIC (awk, ASE_AWK_EFNREDEFGLOBAL); } } @@ -692,7 +701,7 @@ static ase_awk_nde_t* __parse_function (ase_awk_t* awk) param = ASE_AWK_STR_BUF(&awk->token.name); param_len = ASE_AWK_STR_LEN(&awk->token.name); - if (awk->option & ASE_AWK_UNIQUE) + if (awk->option & ASE_AWK_UNIQUEAFN) { /* check if a parameter conflicts with a function */ if (ase_awk_strxncmp (name_dup, name_len, param, param_len) == 0 || @@ -700,7 +709,7 @@ static ase_awk_nde_t* __parse_function (ase_awk_t* awk) { ASE_AWK_FREE (awk, name_dup); ase_awk_tab_clear (&awk->parse.params); - PANIC (awk, ASE_AWK_EDUPNAME); + PANIC (awk, ASE_AWK_EPARREDEFAFN); } /* NOTE: the following is not a conflict @@ -1078,7 +1087,7 @@ static ase_awk_t* __add_global ( { if (!force) { - if (awk->option & ASE_AWK_UNIQUE) + if (awk->option & ASE_AWK_UNIQUEAFN) { /* check if it conflict with a function name */ if (ase_awk_map_get ( @@ -1159,7 +1168,7 @@ static ase_awk_t* __collect_locals (ase_awk_t* awk, ase_size_t nlocals) /* NOTE: it is not checked againt globals names */ - if (awk->option & ASE_AWK_UNIQUE) + if (awk->option & ASE_AWK_UNIQUEAFN) { /* check if it conflict with a function name */ if (ase_awk_map_get ( diff --git a/ase/test/awk/Awk.java b/ase/test/awk/Awk.java index 7f61b3f2..555318a8 100644 --- a/ase/test/awk/Awk.java +++ b/ase/test/awk/Awk.java @@ -1,5 +1,5 @@ /* - * $Id: Awk.java,v 1.11 2006-11-26 16:17:51 bacon Exp $ + * $Id: Awk.java,v 1.12 2006-11-27 04:33:22 bacon Exp $ */ package ase.test.awk; @@ -15,6 +15,12 @@ public class Awk extends ase.awk.StdAwk public Awk () throws ase.awk.Exception { super (); + + addbfn (bfn_sin, 1, 3); + } + + public void bfn_sin () + { } protected String[] getInputConsoleNames () diff --git a/ase/test/awk/awk.c b/ase/test/awk/awk.c index 07c3e6f1..8beb5f97 100644 --- a/ase/test/awk/awk.c +++ b/ase/test/awk/awk.c @@ -1,5 +1,5 @@ /* - * $Id: awk.c,v 1.126 2006-11-26 14:41:22 bacon Exp $ + * $Id: awk.c,v 1.127 2006-11-27 04:33:22 bacon Exp $ */ #include @@ -749,11 +749,18 @@ static int __main (int argc, ase_char_t* argv[]) #endif const ase_char_t* mfn = ASE_NULL; - opt = ASE_AWK_IMPLICIT | ASE_AWK_EXPLICIT | ASE_AWK_UNIQUE | ASE_AWK_HASHSIGN | - /*ASE_AWK_DBLSLASHES |*/ - ASE_AWK_SHADING | ASE_AWK_SHIFT | - ASE_AWK_EXTIO | ASE_AWK_BLOCKLESS | ASE_AWK_STRINDEXONE | - ASE_AWK_STRIPSPACES | ASE_AWK_NEXTOFILE /*| ASE_AWK_NEWLINE*/; + opt = ASE_AWK_IMPLICIT | + ASE_AWK_EXPLICIT | + ASE_AWK_UNIQUEAFN | + ASE_AWK_HASHSIGN | + /*ASE_AWK_DBLSLASHES |*/ + ASE_AWK_SHADING | + ASE_AWK_SHIFT | + ASE_AWK_EXTIO | + ASE_AWK_BLOCKLESS | + ASE_AWK_STRINDEXONE | + ASE_AWK_STRIPSPACES | + ASE_AWK_NEXTOFILE; if (argc <= 1) {