Commits

Ruslan Osmanov committed cbad717

Fix: non-static zend_always_inline function failed to compile with some (non-zts) php setups
Change: static EventBuffer::addBuffer made non-static with one argument
Add: EventBuffer expand, prepend, prependBuffer, drain, copyout, readLine, search methods

  • Participants
  • Parent commits d64bc28

Comments (0)

Files changed (9)

File classes/buffer.c

 #include "src/util.h"
 #include "src/priv.h"
 
+extern int le_event_buffer_pos;
+
 /* {{{ proto resource EventBuffer::__construct(void); */
 PHP_METHOD(EventBuffer, __construct)
 {
 }
 /* }}} */
 
-/* {{{ proto bool EventBuffer::addBuffer(EventBuffer outbuf, EventBuffer inbuf); 
- * Move all data from one evbuffer into another evbuffer.
+/* {{{ proto int EventBuffer::remove(string &data, long max_bytes);
+ *
+ * Read data from an evbuffer and drain the bytes read.  If more bytes are
+ * requested than are available in the evbuffer, we only extract as many bytes
+ * as were available.
+ *
+ * Returns the number of bytes read, or -1 if we can't drain the buffer.
+ */
+PHP_METHOD(EventBuffer, remove)
+{
+	php_event_buffer_t *b;
+	zval               *zbuf      = getThis();
+	zval               *zdata;
+	long                max_bytes;
+	long                ret;
+	char               *data;
+
+	if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "zl",
+				&zdata, &max_bytes) == FAILURE) {
+		return;
+	}
+
+	if (!Z_ISREF_P(zdata)) {
+		/* Was not passed by reference */
+		return;
+	}
+
+	PHP_EVENT_FETCH_BUFFER(b, zbuf);
+
+	data = emalloc(sizeof(char) * max_bytes + 1);
+
+	ret = evbuffer_remove(b->buf, data, max_bytes);
+
+	if (ret > 0) {
+		convert_to_string(zdata);
+		zval_dtor(zdata);
+		Z_STRVAL_P(zdata) = estrndup(data, ret);
+		Z_STRLEN_P(zdata) = ret;
+	}
+
+	efree(data);
+
+	RETVAL_LONG(ret);
+}
+/* }}} */
+
+/* {{{ proto bool EventBuffer::addBuffer(EventBuffer buf); 
+ * Move all data from the buffer provided in buf parameter to the current instance of EventBuffer.
  * This is a destructive add. The data from one buffer moves into the other buffer. However, no unnecessary memory copies occur.
  */
 PHP_METHOD(EventBuffer, addBuffer)
 {
-	php_event_buffer_t *b_out     , *b_in;
-	zval               *zbuf_out  , *zbuf_in;
+	php_event_buffer_t *b_dst;
+	php_event_buffer_t *b_src;
+	zval               *zbuf_dst = getThis();
+	zval               *zbuf_src;
 
-	if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "OO",
-				&zbuf_out, php_event_buffer_ce,
-				&zbuf_in, php_event_buffer_ce) == FAILURE) {
+	if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "O",
+				&zbuf_src, php_event_buffer_ce) == FAILURE) {
 		return;
 	}
 
-	PHP_EVENT_FETCH_BUFFER(b_out, zbuf_out);
-	PHP_EVENT_FETCH_BUFFER(b_in, zbuf_in);
+	PHP_EVENT_FETCH_BUFFER(b_dst, zbuf_dst);
+	PHP_EVENT_FETCH_BUFFER(b_src, zbuf_src);
 
-	if (evbuffer_add_buffer(b_out->buf, b_in->buf)) {
+	if (evbuffer_add_buffer(b_dst->buf, b_src->buf)) {
 		RETURN_FALSE;
 	}
 
 }
 /* }}} */
 
-/* {{{ proto int EventBuffer::remove(string &data, long max_bytes);
+/* {{{ proto bool EventBuffer::removeBuffer(EventBuffer buf, int len); 
+ * Moves exactly len bytes from buf to the end of current instance of EventBuffer
+ */
+PHP_METHOD(EventBuffer, removeBuffer)
+{
+	php_event_buffer_t *b_dst;
+	php_event_buffer_t *b_src;
+	zval               *zbuf_dst = getThis();
+	zval               *zbuf_src;
+	long                len;
+
+	if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "Ol",
+				&zbuf_src, php_event_buffer_ce, &len) == FAILURE) {
+		return;
+	}
+
+	PHP_EVENT_FETCH_BUFFER(b_dst, zbuf_dst);
+	PHP_EVENT_FETCH_BUFFER(b_src, zbuf_src);
+
+	if (evbuffer_remove_buffer(b_src->buf, b_dst->buf, (size_t) len)) {
+		RETURN_FALSE;
+	}
+
+	RETVAL_TRUE;
+}
+/* }}} */
+
+/* {{{ proto bool EventBuffer::expand(int len); 
+ * Alters the last chunk of memory in the buffer, or adds a new chunk, such that the buffer is now large enough to contain datlen bytes without any further allocations.
+ */
+PHP_METHOD(EventBuffer, expand)
+{
+	php_event_buffer_t *b;
+	zval               *zbuf = getThis();
+	long                len;
+
+	if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l",
+				&len) == FAILURE) {
+		return;
+	}
+
+	PHP_EVENT_FETCH_BUFFER(b, zbuf);
+
+	if (evbuffer_expand(b->buf, (size_t) len)) {
+		RETURN_FALSE;
+	}
+
+	RETVAL_TRUE;
+}
+/* }}} */
+
+/* {{{ proto bool EventBuffer::prepend(string data); 
  *
- * Read data from an evbuffer and drain the bytes read.  If more bytes are
- * requested than are available in the evbuffer, we only extract as many bytes
- * as were available.
+ * Prepend data to the front of the event buffer.
+ */
+PHP_METHOD(EventBuffer, prepend)
+{
+	php_event_buffer_t  *b;
+	zval                *zbuf    = getThis();
+	zval               **ppzdata;
+
+	if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "Z",
+				&ppzdata) == FAILURE) {
+		return;
+	}
+
+	PHP_EVENT_FETCH_BUFFER(b, zbuf);
+
+	convert_to_string_ex(ppzdata);
+
+	if (evbuffer_prepend(b->buf, (void *) Z_STRVAL_PP(ppzdata), Z_STRLEN_PP(ppzdata))) {
+		RETURN_FALSE;
+	}
+
+	RETVAL_TRUE;
+}
+/* }}} */
+
+/* {{{ proto bool EventBuffer::prependBuffer(EventBuffer buf); 
+ * Behaves as EventBuffer::addBuffer, except that it moves data to the front of the buffer.
+ */
+PHP_METHOD(EventBuffer, prependBuffer)
+{
+	php_event_buffer_t *b_dst;
+	php_event_buffer_t *b_src;
+	zval               *zbuf_dst = getThis();
+	zval               *zbuf_src;
+
+	if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "O",
+				&zbuf_src, php_event_buffer_ce) == FAILURE) {
+		return;
+	}
+
+	PHP_EVENT_FETCH_BUFFER(b_dst, zbuf_dst);
+	PHP_EVENT_FETCH_BUFFER(b_src, zbuf_src);
+
+	if (evbuffer_prepend_buffer(b_dst->buf, b_src->buf)) {
+		RETURN_FALSE;
+	}
+
+	RETVAL_TRUE;
+}
+/* }}} */
+
+/* {{{ proto bool EventBuffer::drain(long len);
  *
- * Returns the number of bytes read, or -1 if we can't drain the buffer.
+ * Behaves as EventBuffer::remove(), except that it does not copy the data: it
+ * just removes it from the front of the buffer.
  */
-PHP_METHOD(EventBuffer, remove)
+PHP_METHOD(EventBuffer, drain)
+{
+	zval               *zbuf = getThis();
+	php_event_buffer_t *b;
+	long                len;
+
+	if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l",
+				&len) == FAILURE) {
+		return;
+	}
+
+	PHP_EVENT_FETCH_BUFFER(b, zbuf);
+
+	if (evbuffer_drain(b->buf, len)) {
+		RETURN_FALSE;
+	}
+
+	RETVAL_TRUE;
+}
+/* }}} */
+
+/* {{{ proto int EventBuffer::copyout(string &data, long max_bytes);
+ *
+ * Behaves just like EventBuffer::remove(), but does not drain any data from the buffer.
+ * I.e. it copies the first max_bytes bytes from the front of the buffer into data.
+ * If there are fewer than datlen bytes available, the function copies all the bytes there are.
+ *
+ * Returns the number of bytes copied, or -1 on failure.
+ */
+PHP_METHOD(EventBuffer, copyout)
 {
 	php_event_buffer_t *b;
 	zval               *zbuf      = getThis();
 
 	data = emalloc(sizeof(char) * max_bytes + 1);
 
-	ret = evbuffer_remove(b->buf, data, max_bytes);
+	ret = evbuffer_copyout(b->buf, data, max_bytes);
 
 	if (ret > 0) {
 		convert_to_string(zdata);
 }
 /* }}} */
 
+/* {{{ proto mixed EventBuffer::readLine(int len, int eol_style);
+ *
+ * Extracts a line from the front of the buffer and returns it in a newly
+ * allocated NUL-terminated string. If there is not a whole
+ * line to read, the function returns NULL. The line terminator is not included
+ * in the copied string.
+ *
+ * eol_style is one of EventBuffer:EOL_* constants.
+ *
+ * On success returns the line read from the buffer, otherwise NULL.
+ */
+PHP_METHOD(EventBuffer, readLine)
+{
+	zval               *zbuf      = getThis();
+	php_event_buffer_t *b;
+	long                len;
+	long                eol_style;
+	char               *res;
+
+	if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ll",
+				&len, &eol_style) == FAILURE) {
+		return;
+	}
+
+	PHP_EVENT_FETCH_BUFFER(b, zbuf);
+
+	res = evbuffer_readln(b->buf, (size_t *) &len, eol_style);
+
+	if (!res) {
+		RETURN_NULL();
+	}
+
+	RETVAL_STRINGL(res, len, 0);
+}
+/* }}} */
+
+/* {{{ proto resource EventBuffer::search(string what[, resource start = NULL[, resource end = NULL]]);
+ *
+ * Scans the buffer for an occurrence of the len-character string what. It
+ * returns resource representing the position of the string, or NULL if the
+ * string was not found. If the start argument is provided, it's the position
+ * at which the search should begin; otherwise, the search is from the start
+ * of the string. If end argument provided, the search is performed between
+ * start and end buffer positions.
+ *
+ * Returns resource representing position of the first occurance of the string
+ * in the buffer, or NULL if string is not found
+ */
+PHP_METHOD(EventBuffer, search)
+{
+	zval                *zbuf       = getThis();
+	zval                *zstart_pos = NULL;
+	zval                *zend_pos   = NULL;
+	zval                *zwhat;
+	php_event_buffer_t  *b;
+	struct evbuffer_ptr *start_pos  = NULL;
+	struct evbuffer_ptr *end_pos    = NULL;
+	struct evbuffer_ptr *res_pos;
+
+	if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|r!r!",
+				&zwhat, &zstart_pos, &zend_pos) == FAILURE) {
+		return;
+	}
+
+	PHP_EVENT_FETCH_BUFFER(b, zbuf);
+
+	if (zstart_pos) {
+		PHP_EVENT_FETCH_BUFFER_POS(start_pos, zstart_pos);
+	}
+
+	res_pos = emalloc(sizeof(struct evbuffer_ptr));
+
+	if (zend_pos) {
+		PHP_EVENT_FETCH_BUFFER_POS(end_pos, zend_pos);
+
+		*res_pos = evbuffer_search(b->buf, Z_STRVAL_P(zwhat), (size_t) Z_STRLEN_P(zwhat), start_pos);
+	} else {
+		*res_pos = evbuffer_search_range(b->buf, Z_STRVAL_P(zwhat), (size_t) Z_STRLEN_P(zwhat),
+				start_pos, end_pos);
+	}
+
+	if (res_pos->pos == -1) {
+		efree(res_pos);
+		RETURN_NULL();
+	}
+
+	ZEND_REGISTER_RESOURCE(return_value, res_pos, le_event_buffer_pos);
+}
+/* }}} */
+
 /*
  * Local variables:
  * tab-width: 4

File examples/listener.php

 	$output = $bev->getOutput();
 
 	/* Copy all the data from the input buffer to the output buffer. */
-	EventBuffer::addBuffer($output, $input);
+	$output->addBuffer($input);
 }
 
 function echo_event_cb($bev, $events, $ctx) {
     <email>osmanov@php.net</email>
     <active>yes</active>
   </lead>
-  <date>2013-02-05</date>
+  <date>2013-02-06</date>
   <!--{{{ Current version -->
   <version>
     <release>1.1.1</release>
   <license uri="http://www.php.net/license">PHP</license>
   <notes><![CDATA[
   Fix: non-static zend_always_inline function failed to compile with some (non-zts) php setups
+  Change: static EventBuffer::addBuffer made non-static with one argument
+  Add: EventBuffer expand, prepend, prependBuffer, drain, copyout, readLine, search methods
   ]]></notes>
   <!--}}}-->
   <!--{{{ Contents -->
   </stability>
   <license uri="http://www.php.net/license">PHP</license>
   <notes><![CDATA[
+  Fix: non-static zend_always_inline function failed to compile with some (non-zts) php setups
+  Change: static EventBuffer::addBuffer made non-static with one argument
+  Add: EventBuffer expand, prepend, prependBuffer, drain, copyout, readLine, search methods
   ]]></notes>
   </release>
   <!--}}}-->
 static HashTable event_bevent_properties;
 static HashTable event_buffer_properties;
 
-#if 0
-static HashTable event_util_properties;
-
-#if HAVE_EVENT_EXTRA_LIB
-static HashTable event_dns_base_properties;
-static HashTable event_listener_properties;
-static HashTable event_http_conn_properties;
-static HashTable event_http_properties;
-#endif
-#endif
-
 static zend_object_handlers object_handlers;
 
+int le_event_buffer_pos;
+
 static const zend_module_dep event_deps[] = {
 	ZEND_MOD_OPTIONAL("sockets")
 	{NULL, NULL, NULL}
 }
 /* }}} */
 
+/* {{{ php_event_buffer_pos_dtor */
+static void php_event_buffer_pos_dtor(zend_rsrc_list_entry *rsrc TSRMLS_DC)
+{
+	struct evbuffer_ptr *p = (struct evbuffer_ptr *) rsrc->ptr;
+
+	efree(p);
+}
+/* }}} */
+
 /* Private functions }}} */
 
 
 /* {{{ PHP_MINIT_FUNCTION */
 PHP_MINIT_FUNCTION(event)
 {
+	le_event_buffer_pos = zend_register_list_destructors_ex(php_event_buffer_pos_dtor, NULL, PHP_EVENT_BUFFER_POS_RES_NAME, module_number);
+
 	zend_object_handlers *std_hnd = zend_get_std_object_handlers();
 
 	memcpy(&object_handlers, std_hnd, sizeof(zend_object_handlers));
 
 	REGISTER_EVENT_CLASS_CONST_LONG(php_event_util_ce, LIBEVENT_VERSION_NUMBER, LIBEVENT_VERSION_NUMBER);
 
+	REGISTER_EVENT_CLASS_CONST_LONG(php_event_buffer_ce, EOL_ANY,         EVBUFFER_EOL_ANY);
+	REGISTER_EVENT_CLASS_CONST_LONG(php_event_buffer_ce, EOL_CRLF,        EVBUFFER_EOL_CRLF);
+	REGISTER_EVENT_CLASS_CONST_LONG(php_event_buffer_ce, EOL_CRLF_STRICT, EVBUFFER_EOL_CRLF_STRICT);
+	REGISTER_EVENT_CLASS_CONST_LONG(php_event_buffer_ce, EOL_LF,          EVBUFFER_EOL_LF);
+#if LIBEVENT_VERSION_NUMBER >= 0x02010100
+	REGISTER_EVENT_CLASS_CONST_LONG(php_event_buffer_ce, EOL_NUL,         EVBUFFER_EOL_NUL);
+#endif
+
 	/* Handle libevent's error logging more gracefully than it's default
 	 * logging to stderr, or calling abort()/exit() */
 	event_set_fatal_callback(fatal_error_cb);
 
 #include "src/common.h"
 
-#define PHP_EVENT_RES_NAME "Event"
-#define PHP_EVENT_BASE_RES_NAME "Event Base"
-#define PHP_EVENT_CONFIG_RES_NAME "Event Config"
-#define PHP_EVENT_BEVENT_RES_NAME "Buffer Event"
-#define PHP_EVENT_BUFFER_RES_NAME "Event Buffer"
-
-#if HAVE_EVENT_EXTRA_LIB
-# define PHP_EVENT_DNS_BASE_RES_NAME "Event DNS Base"
-# define PHP_EVENT_LISTENER_RES_NAME "Event Connection Listener"
-# define PHP_EVENT_HTTP_CONN_RES_NAME "Event HTTP Connection"
-# define PHP_EVENT_HTTP_RES_NAME "Event HTTP Server"
-#endif
+#define PHP_EVENT_BUFFER_POS_RES_NAME "EventBuffer Position"
 
 PHP_MINIT_FUNCTION(event);
 PHP_MSHUTDOWN_FUNCTION(event);
 	ZEND_ARG_INFO(0, data) 
 ZEND_END_ARG_INFO();
 
-ZEND_BEGIN_ARG_INFO_EX(arginfo_evbuffer_add_buffer, 0, 0, 2)
-	ZEND_ARG_INFO(0, outbuf)
-	ZEND_ARG_INFO(0, inbuf) 
+ZEND_BEGIN_ARG_INFO_EX(arginfo_evbuffer_add_buffer, 0, 0, 1)
+	ZEND_ARG_INFO(0, buf)
+ZEND_END_ARG_INFO();
+
+ZEND_BEGIN_ARG_INFO_EX(arginfo_evbuffer_remove_buffer, 0, 0, 2)
+	ZEND_ARG_INFO(0, buf)
+	ZEND_ARG_INFO(0, len)
+ZEND_END_ARG_INFO();
+
+ZEND_BEGIN_ARG_INFO_EX(arginfo_evbuffer_len, 0, 0, 1)
+	ZEND_ARG_INFO(0, len)
 ZEND_END_ARG_INFO();
 
 ZEND_BEGIN_ARG_INFO_EX(arginfo_evbuffer_remove, 0, 0, 2)
 	ZEND_ARG_INFO(0, max_bytes)
 ZEND_END_ARG_INFO();
 
+ZEND_BEGIN_ARG_INFO_EX(arginfo_evbuffer_read_line, 0, 0, 2)
+	ZEND_ARG_INFO(0, len)
+	ZEND_ARG_INFO(0, eol_style)
+ZEND_END_ARG_INFO();
+
+ZEND_BEGIN_ARG_INFO_EX(arginfo_evbuffer_search, 0, 0, 1)
+	ZEND_ARG_INFO(0, what)
+	ZEND_ARG_INFO(0, start)
+	ZEND_ARG_INFO(0, end)
+ZEND_END_ARG_INFO();
+
 
 ZEND_BEGIN_ARG_INFO_EX(arginfo_event_socket_1, 0, 0, 0)
 	ZEND_ARG_INFO(0, socket)
 /* }}} */
 
 const zend_function_entry php_event_buffer_ce_functions[] = {/* {{{ */
-	PHP_ME(EventBuffer, __construct,   arginfo_event__void,         ZEND_ACC_PUBLIC  | ZEND_ACC_CTOR)
-	PHP_ME(EventBuffer, freeze,        arginfo_evbuffer_freeze,     ZEND_ACC_PUBLIC)
-	PHP_ME(EventBuffer, unfreeze,      arginfo_evbuffer_freeze,     ZEND_ACC_PUBLIC)
-	PHP_ME(EventBuffer, lock,          arginfo_event__void,         ZEND_ACC_PUBLIC)
-	PHP_ME(EventBuffer, unlock,        arginfo_event__void,         ZEND_ACC_PUBLIC)
-	PHP_ME(EventBuffer, enableLocking, arginfo_event__void,         ZEND_ACC_PUBLIC)
-	PHP_ME(EventBuffer, add,           arginfo_evbuffer_add,        ZEND_ACC_PUBLIC)
-	PHP_ME(EventBuffer, addBuffer,     arginfo_evbuffer_add_buffer, ZEND_ACC_PUBLIC | ZEND_ACC_STATIC)
-	PHP_ME(EventBuffer, remove,        arginfo_evbuffer_remove,     ZEND_ACC_PUBLIC)
+	PHP_ME(EventBuffer, __construct,   arginfo_event__void,            ZEND_ACC_PUBLIC  | ZEND_ACC_CTOR)
+	PHP_ME(EventBuffer, freeze,        arginfo_evbuffer_freeze,        ZEND_ACC_PUBLIC)
+	PHP_ME(EventBuffer, unfreeze,      arginfo_evbuffer_freeze,        ZEND_ACC_PUBLIC)
+	PHP_ME(EventBuffer, lock,          arginfo_event__void,            ZEND_ACC_PUBLIC)
+	PHP_ME(EventBuffer, unlock,        arginfo_event__void,            ZEND_ACC_PUBLIC)
+	PHP_ME(EventBuffer, enableLocking, arginfo_event__void,            ZEND_ACC_PUBLIC)
+	PHP_ME(EventBuffer, add,           arginfo_evbuffer_add,           ZEND_ACC_PUBLIC)
+	PHP_ME(EventBuffer, addBuffer,     arginfo_evbuffer_add_buffer,    ZEND_ACC_PUBLIC)
+	PHP_ME(EventBuffer, removeBuffer,  arginfo_evbuffer_remove_buffer, ZEND_ACC_PUBLIC)
+	PHP_ME(EventBuffer, remove,        arginfo_evbuffer_remove,        ZEND_ACC_PUBLIC)
+	PHP_ME(EventBuffer, expand,        arginfo_evbuffer_len,           ZEND_ACC_PUBLIC)
+	PHP_ME(EventBuffer, prepend,       arginfo_evbuffer_add,           ZEND_ACC_PUBLIC)
+	PHP_ME(EventBuffer, prependBuffer, arginfo_evbuffer_add_buffer,    ZEND_ACC_PUBLIC)
+	PHP_ME(EventBuffer, drain,         arginfo_evbuffer_len,           ZEND_ACC_PUBLIC)
+	PHP_ME(EventBuffer, copyout,       arginfo_evbuffer_remove,        ZEND_ACC_PUBLIC)
+	PHP_ME(EventBuffer, readLine,      arginfo_evbuffer_read_line,     ZEND_ACC_PUBLIC)
+	PHP_ME(EventBuffer, search,        arginfo_evbuffer_search,        ZEND_ACC_PUBLIC)
 
 	PHP_FE_END
 };
 PHP_METHOD(EventBuffer, add);
 PHP_METHOD(EventBuffer, remove);
 PHP_METHOD(EventBuffer, addBuffer);
+PHP_METHOD(EventBuffer, removeBuffer);
+PHP_METHOD(EventBuffer, expand);
+PHP_METHOD(EventBuffer, prepend);
+PHP_METHOD(EventBuffer, prependBuffer);
+PHP_METHOD(EventBuffer, drain);
+PHP_METHOD(EventBuffer, copyout);
+PHP_METHOD(EventBuffer, readLine);
+PHP_METHOD(EventBuffer, search);
 
 PHP_METHOD(EventUtil, getLastSocketErrno);
 PHP_METHOD(EventUtil, getLastSocketError);
 
 #endif
 
+
 #endif /* PHP_EVENT_PRIV_H */
 
 /* 
 #define PHP_EVENT_FETCH_HTTP(b, zb) \
 	b = (php_event_http_t *) zend_object_store_get_object(zb TSRMLS_CC);
 
+#define PHP_EVENT_FETCH_BUFFER_POS(p, zp) \
+	ZEND_FETCH_RESOURCE((p), struct evbuffer_ptr *, &(zp), -1, PHP_EVENT_BUFFER_POS_RES_NAME, le_event_buffer_pos)
+
 #define PHP_EVENT_TIMEVAL_SET(tv, t)                     \
         do {                                             \
             tv.tv_sec  = (long) t;                       \