From c3fe59cd3195e3f12a1e114bd8d2e13de25c487e Mon Sep 17 00:00:00 2001
From: hyung-hwan <hyunghwan.chung@gmail.com>
Date: Wed, 28 Jun 2006 14:19:01 +0000
Subject: [PATCH] *** empty log message ***

---
 ase/awk/awk.h        | 13 ++++++++-
 ase/awk/extio.c      | 61 +++++++++++++++++++++++++++++++++------
 ase/awk/extio.h      | 10 +++++--
 ase/awk/run.c        | 68 ++++++++++++++++++++++++++++++++++++++------
 ase/awk/tree.h       |  3 +-
 ase/test/awk/t12.awk |  2 ++
 6 files changed, 134 insertions(+), 23 deletions(-)

diff --git a/ase/awk/awk.h b/ase/awk/awk.h
index 365c4c59..6d1bf9c2 100644
--- a/ase/awk/awk.h
+++ b/ase/awk/awk.h
@@ -1,5 +1,5 @@
 /* 
- * $Id: awk.h,v 1.73 2006-06-26 15:09:28 bacon Exp $
+ * $Id: awk.h,v 1.74 2006-06-28 14:19:01 bacon Exp $
  */
 
 #ifndef _XP_AWK_AWK_H_
@@ -18,8 +18,19 @@ typedef xp_ssize_t (*xp_awk_io_t) (
 struct xp_awk_extio_t 
 {
 	int type;
+
 	xp_char_t* name;
 	void* handle;
+
+	/* input buffer */
+	struct
+	{
+		xp_char_t buf[2048];
+		xp_size_t pos;
+		xp_size_t len;
+		xp_bool_t eof;
+	} in;
+
 	xp_awk_extio_t* next;
 };
 
diff --git a/ase/awk/extio.c b/ase/awk/extio.c
index 29998f8b..cd2ec74a 100644
--- a/ase/awk/extio.c
+++ b/ase/awk/extio.c
@@ -1,5 +1,5 @@
 /*
- * $Id: extio.c,v 1.14 2006-06-28 10:40:24 bacon Exp $
+ * $Id: extio.c,v 1.15 2006-06-28 14:19:01 bacon Exp $
  */
 
 #include <xp/awk/awk_i.h>
@@ -11,7 +11,8 @@
 #endif
 
 int xp_awk_readextio (
-	xp_awk_run_t* run, int in_type, const xp_char_t* name, int* errnum)
+	xp_awk_run_t* run, int in_type,
+	const xp_char_t* name, xp_str_t* buf, int* errnum)
 {
 	xp_awk_extio_t* p = run->extio;
 	xp_awk_io_t handler;
@@ -76,6 +77,12 @@ int xp_awk_readextio (
 
 		p->type = in_type;
 		p->handle = XP_NULL;
+
+		p->in.buf[0] = XP_C('\0');
+		p->in.pos = 0;
+		p->in.len = 0;
+		p->in.eof = xp_false;
+
 		p->next = XP_NULL;
 
 		if (handler (XP_AWK_IO_OPEN, extio_opt, p, XP_NULL, 0) == -1)
@@ -105,16 +112,52 @@ int xp_awk_readextio (
 		run->extio = p;
 	}
 
-	{
-xp_char_t buf[1024];
+	/* read a line */
+	xp_str_clear (buf);
 
-	if (handler (XP_AWK_IO_READ, 0, p, buf, xp_countof(buf)) == 0)
+	while (1)
 	{
-		/* no more data. end of data stream */
-		return 0;
-	}
+		xp_char_t c;
 
-xp_printf(XP_TEXT("%s"), buf);
+		if (p->in.pos >= p->in.len)
+		{
+			xp_ssize_t n;
+
+			if (p->in.eof)
+			{
+				if (XP_STR_LEN(buf) == 0) return 0;
+				break;
+			}
+
+			n = handler (XP_AWK_IO_READ, 0, 
+				p, p->in.buf, xp_countof(p->in.buf));
+			if (n == -1) 
+			{
+				/* handler error. getline should return -1 */
+				/* TODO: set ERRNO */
+				*errnum = XP_AWK_ENOERR;
+				return -1;
+			}
+
+			if (n == 0) 
+			{
+				p->in.eof = xp_true;
+				if (XP_STR_LEN(buf) == 0) return 0;
+				break;
+			}
+
+			p->in.len = n;
+			p->in.pos = 0;
+		}
+
+		c = p->in.buf[p->in.pos++];
+		if (c == XP_C('\n')) break; 
+
+		if (xp_str_ccat (buf, c) == (xp_size_t)-1)
+		{
+			*errnum = XP_AWK_ENOMEM;
+			return -1;
+		}
 	}
 
 	return 1;
diff --git a/ase/awk/extio.h b/ase/awk/extio.h
index 2cf08ae2..acd61f84 100644
--- a/ase/awk/extio.h
+++ b/ase/awk/extio.h
@@ -1,3 +1,7 @@
+/*
+ * $Id: extio.h,v 1.5 2006-06-28 14:19:01 bacon Exp $
+ */
+
 #ifndef _XP_AWK_EXTIO_H_
 #define _XP_AWK_EXTIO_H_
 
@@ -5,16 +9,16 @@
 #error Never include this file directly. Include <xp/awk/awk.h> instead
 #endif
 
-
 #ifdef __cplusplus
 extern "C"
 #endif
 
 int xp_awk_readextio (
-	xp_awk_run_t* run, int type, const xp_char_t* name, int* errnum);
+	xp_awk_run_t* run, int in_type, 
+	const xp_char_t* name, xp_str_t* buf, int* errnum);
 
 int xp_awk_writeextio (
-	xp_awk_run_t* run, int type, 
+	xp_awk_run_t* run, int out_type, 
 	const xp_char_t* name, xp_awk_val_t* v, int* errnum);
 
 int xp_awk_closeextio (
diff --git a/ase/awk/run.c b/ase/awk/run.c
index ee09568b..bd87e443 100644
--- a/ase/awk/run.c
+++ b/ase/awk/run.c
@@ -1,5 +1,5 @@
 /*
- * $Id: run.c,v 1.112 2006-06-28 10:40:24 bacon Exp $
+ * $Id: run.c,v 1.113 2006-06-28 14:19:01 bacon Exp $
  */
 
 #include <xp/awk/awk_i.h>
@@ -1608,6 +1608,8 @@ static xp_awk_val_t* __eval_binop_lor (
 	}
 
 	xp_awk_refdownval (run, lv);
+
+	if (res == XP_NULL) PANIC (run, XP_AWK_ENOMEM);
 	return res;
 }
 
@@ -1652,6 +1654,8 @@ static xp_awk_val_t* __eval_binop_land (
 	}
 
 	xp_awk_refdownval (run, lv);
+
+	if (res == XP_NULL) PANIC (run, XP_AWK_ENOMEM);
 	return res;
 }
 
@@ -1844,6 +1848,7 @@ static xp_awk_val_t* __eval_binop_eq (
 
 	res = xp_awk_makeintval (run, r);
 	if (res == XP_NULL) PANIC (run, XP_AWK_ENOMEM);
+
 	return res;
 }
 
@@ -3060,11 +3065,14 @@ static xp_awk_val_t* __eval_pos (xp_awk_run_t* run, xp_awk_nde_t* nde)
 
 static xp_awk_val_t* __eval_getline (xp_awk_run_t* run, xp_awk_nde_t* nde)
 {
-	xp_awk_nde_getline_t* p = (xp_awk_nde_getline_t*)nde;
-	xp_awk_val_t* in;
+	xp_awk_nde_getline_t* p;
+	xp_awk_val_t* in, * res;
 	xp_char_t* str;
+	xp_str_t buf;
 	int errnum, n;
 
+	p = (xp_awk_nde_getline_t*)nde;
+
 	xp_assert (p->in_type == XP_AWK_IN_PIPE ||
 	           p->in_type == XP_AWK_IN_COPROC ||
 		   p->in_type == XP_AWK_IN_FILE);
@@ -3082,14 +3090,56 @@ static xp_awk_val_t* __eval_getline (xp_awk_run_t* run, xp_awk_nde_t* nde)
 	}
 	xp_awk_refdownval (run, in);
 
-	n = xp_awk_readextio (run, p->in_type, str, &errnum);
+	/* TODO: optimization in line buffer management */
+	if (xp_str_open (&buf, 256) == XP_NULL)
+	{
+		xp_free (str);
+		PANIC (run, XP_AWK_ENOMEM);
+	}
+
+	n = xp_awk_readextio (run, p->in_type, str, &buf, &errnum);
 	xp_free (str);
 
-	/* TODO: set the value to var if it is not null */
-	/* TODO: set $0 if var is null */
+	if (n < 0 && errnum != XP_AWK_ENOERR) 
+	{
+		xp_str_close (&buf);
+		PANIC (run, errnum);
+	}
 
-	if (n < 0 && errnum != XP_AWK_ENOERR) PANIC (run, errnum);
-	return xp_awk_makeintval (run, n);
+	if (n > 0)
+	{
+		if (p->var == XP_NULL)
+		{
+		/* TODO: set $0 if var is null */
+			xp_printf (XP_T("set %s to $0\n"), XP_STR_BUF(&buf));
+			xp_str_close (&buf);
+		}
+		else
+		{
+			xp_awk_val_t* v;
+
+			v = xp_awk_makestrval (
+				XP_STR_BUF(&buf), XP_STR_LEN(&buf));
+
+			xp_str_close (&buf);
+
+			if (v == XP_NULL) PANIC (run, XP_AWK_ENOMEM);
+			xp_awk_refupval (v);
+	
+			if (__do_assignment(run, 
+				(xp_awk_nde_var_t*)p->var, v) == XP_NULL)
+			{
+				xp_awk_refdownval (run, v);
+				return XP_NULL;
+			}
+			xp_awk_refdownval (run, v);
+		}
+	}
+	
+	res =  xp_awk_makeintval (run, n);
+	if (res == XP_NULL) PANIC (run, XP_AWK_ENOMEM);
+
+	return res;
 }
 
 static int __raw_push (xp_awk_run_t* run, void* val)
@@ -3100,7 +3150,7 @@ static int __raw_push (xp_awk_run_t* run, void* val)
 		xp_size_t n;
 	       
 		n = run->stack_limit + STACK_INCREMENT;
-		tmp = (void**)xp_realloc (run->stack, n * xp_sizeof(void*));
+		tmp = (void**) xp_realloc (run->stack, n * xp_sizeof(void*));
 		if (tmp == XP_NULL) return -1;
 
 		run->stack = tmp;
diff --git a/ase/awk/tree.h b/ase/awk/tree.h
index c11a54c9..26aa43c0 100644
--- a/ase/awk/tree.h
+++ b/ase/awk/tree.h
@@ -1,5 +1,5 @@
 /*
- * $Id: tree.h,v 1.53 2006-06-28 10:40:24 bacon Exp $
+ * $Id: tree.h,v 1.54 2006-06-28 14:19:01 bacon Exp $
  */
 
 #ifndef _XP_AWK_TREE_H_
@@ -208,6 +208,7 @@ struct xp_awk_nde_rex_t
 	xp_size_t  len;
 };
 
+/* XP_AWK_NDE_ARG, XP_AWK_NDE_VAR, ... */
 struct xp_awk_nde_var_t
 {
 	XP_AWK_NDE_HDR;
diff --git a/ase/test/awk/t12.awk b/ase/test/awk/t12.awk
index 9559b66a..239218a9 100644
--- a/ase/test/awk/t12.awk
+++ b/ase/test/awk/t12.awk
@@ -7,4 +7,6 @@ BEGIN
 	print "line 4" >> "2";
 	print "line 4" >> "3";
 	print "line 4" >> "4";
+
+	while ((getline x < "abc") > 0) print x;
 }