void skit_pfile_stream_flush(skit_pfile_stream *stream)
{
	SKIT_USE_FEATURE_EMULATION;
	sASSERT(stream != NULL);
	skit_pfile_stream_internal *pstreami = &(stream->as_internal);
	if( pstreami->file_handle == NULL )
		sTRACE(skit_stream_throw_exc(SKIT_FILE_IO_EXCEPTION, &(stream->as_stream), "Attempt to flush an unopened stream."));
	
	#ifdef __VMS
	/* 
	On OpenVMS, fflush does not force writes onto disk, but fsync does. 
	Thus, the behavior the caller will probably expect is that of fsync.
	Unittests will fail on OpenVMS if fflush is used.  Using fflush makes
	it impossible to have one pfile_stream read the writes created by
	another concurrent pfile_stream open to the same file.
	Source: http://h71000.www7.hp.com/commercial/c/docs/5763p029.html
	*/
	int errval = fsync(fileno(pstreami->file_handle));
	#else
	/*
	Linux, on the other hand, seems to prefer fflush as a way to make
	writes immediately available to other open streams.  This was found
	by expermintation after the VMS path made unittests fail.
	*/
	int errval = fflush(pstreami->file_handle);
	#endif
	
	if ( errval != 0 )
	{
		char errbuf[1024];
		/* TODO: throw exception for invalid streams when (errval == EBADF) */
		sTRACE(skit_stream_throw_exc(SKIT_FILE_IO_EXCEPTION, &(stream->as_stream), skit_errno_to_cstr(errbuf, sizeof(errbuf))));
	}
}
Exemple #2
0
END_RULE

static void skit_peg_lookup_test()
{
	SKIT_USE_FEATURE_EMULATION;
	skit_peg_parser *parser = skit_peg_parser_mock_new(skit_slice_null());
	SKIT_PEG_PARSING_INITIAL_VARS(parser);
	
	int result;
	
	// --------- Normal, non-SUFFIX test. ---------
	skit_peg_lookup_index *index = sETRACE(skit_peg_lookup_index_new());
	
	result = 0;
	sASSERT_PARSE_PASS(parser, "x", lookup_test, index, &result);
	sASSERT_EQ(result, 1);

	result = 0;
	sASSERT_PARSE_PASS(parser, "foobar", lookup_test, index, &result);
	sASSERT_EQ(result, 2);

	result = 0;
	sASSERT_PARSE_PASS(parser, "foo", lookup_test, index, &result);
	sASSERT_EQ(result, 3);

	result = 0;
	sASSERT_PARSE_PASS(parser, "FOO", lookup_test, index, &result);
	sASSERT_EQ(result, 4);
	
	sTRACE(skit_peg_lookup_index_free(index));
	
	// --------- SUFFIX test. ---------
	index = sETRACE(skit_peg_lookup_index_new());
	
	result = 0;
	sASSERT_PARSE_PASS(parser, "x bar", suffix_test, index, &result);
	sASSERT_EQ(result, 1);

	result = 0;
	sASSERT_PARSE_PASS(parser, "foobar bar", suffix_test, index, &result);
	sASSERT_EQ(result, 2);

	result = 0;
	sASSERT_PARSE_PASS(parser, "foo baz", suffix_test, index, &result);
	sASSERT_EQ(result, 3);

	result = 0;
	sASSERT_PARSE_PASS(parser, "FOO baz", suffix_test, index, &result);
	sASSERT_EQ(result, 4);
	
	sTRACE(skit_peg_lookup_index_free(index));
	
	sTRACE(skit_peg_parser_mock_free(parser));
	
	printf("  skit_peg_lookup_test passed.\n");
}
skit_slice skit_pfile_stream_read(skit_pfile_stream *stream, skit_loaf *buffer, size_t nbytes)
{
	SKIT_USE_FEATURE_EMULATION;
	sASSERT(stream != NULL);
	skit_pfile_stream_internal *pstreami = &(stream->as_internal);
	skit_loaf *read_buf;
	
	/* Return NULL slices when attempting to read from an already-exhausted stream. */
	if ( feof(pstreami->file_handle) )
		return skit_slice_null();
	
	/* Figure out which buffer to use. */
	read_buf = skit_pfile_get_read_buffer(pstreami, buffer);
	
	/* The provided buffer might not be large enough. */
	/* Thankfully, the necessary size is easy to calculate in this case. */
	if ( sLLENGTH(*read_buf) < nbytes )
		skit_loaf_resize(read_buf, nbytes);
	
	/* Do the read. */
	size_t nbytes_read = fread( sLPTR(*read_buf), 1, nbytes, pstreami->file_handle );
	if ( ferror(pstreami->file_handle) )
	{
		char errbuf[1024];
		sTRACE(skit_stream_throw_exc(SKIT_FILE_IO_EXCEPTION, &(stream->as_stream), skit_errno_to_cstr(errbuf, sizeof(errbuf))));
	}
	
	return skit_slice_of(read_buf->as_slice, 0, nbytes_read);
}
  static ngx_int_t
ngx_http_time_get_handler(ngx_http_request_t *r, ngx_http_variable_value_t *v, uintptr_t data)
{
  fSTEP;

  ngx_http_time_vctx_t *ctx = (ngx_http_time_vctx_t *)data;
  u_char               *buf;

  time_t timestamp;

  buf = ngx_palloc(r->pool, MAX_TIME_LEN);
  if (NULL == buf){
    v->not_found = 1;
    v->data = NULL;
    v->len = 0;
    v->valid = 0;
    return NGX_OK;
  }
  
  TRACE("to output");
  timestamp = time(NULL);
  v->len = strftime((char*)buf,  MAX_TIME_LEN,  (char*)ctx->format.data,  localtime(&timestamp));
  v->data = buf;
  v->valid = 1;


  sTRACE(ctx->format.data);

  return NGX_OK;
}
void skit_unittest_signal_handling()
{
	SKIT_USE_FEATURE_EMULATION;
	printf("\n");
	printf("The unittester will now trigger a segfault by dereferencing NULL.\n");
	printf("This signal should get handled and print a stacktrace.\n");
	skit_push_tracing_sig_handler();
	sTRACE(skit_unittest_signal_subfunc());
	printf("This should never get printed.\n");
}
Exemple #6
0
void skit_peg_unittests()
{
	SKIT_USE_FEATURE_EMULATION;
	printf("skit_peg_parser_unittests()\n");
	sTRACE(skit_peg_macros_test());
	sTRACE(skit_peg_parse_one_newline_test());
	sTRACE(skit_peg_whitespace_test());
	sTRACE(skit_peg_word_boundary_test());
	sTRACE(skit_peg_end_of_text_test());
	// TODO: token, keyword tests.
	sTRACE(skit_peg_any_word_test());
	sTRACE(skit_peg_lookup_test());
	sTRACE(skit_peg_branch_discard_test());
	sTRACE(skit_peg_line_bounds_test());
	printf("  skit_peg_parser_unittests all passed!\n");
	printf("\n");
}
void skit_pfile_stream_fcloser( skit_pfile_stream *pstream, void *arg, FILE *file_handle )
{
	SKIT_USE_FEATURE_EMULATION;
	skit_pfile_stream_internal *pstreami = &(pstream->as_internal);

	int errval = fclose(pstreami->file_handle);
	if ( errval != 0 )
	{
		char errbuf[1024];
		/* TODO: throw exception for invalid file handles when (errval == EBADF) */
		sTRACE(skit_stream_throw_exc(SKIT_FILE_IO_EXCEPTION, &(pstream->as_stream), skit_errno_to_cstr(errbuf, sizeof(errbuf))));
	}
}
// append_int -> append_internal.
static void skit_pfile_stream_append_int(skit_pfile_stream *stream, skit_slice slice)
{
	SKIT_USE_FEATURE_EMULATION;
	skit_pfile_stream_internal *pstreami = &(stream->as_internal);
	if( pstreami->file_handle == NULL )
		sTRACE(skit_stream_throw_exc(SKIT_FILE_IO_EXCEPTION, &(stream->as_stream), "Attempt to write to an unopened stream."));

	ssize_t length = sSLENGTH(slice);

	/* Optimize this case. */
	if ( length == 0 )
		return;
		/*sRETURN();*/

	/* Do the write. */
	size_t n_bytes_written = fwrite( sSPTR(slice), 1, length, pstreami->file_handle );
	if ( n_bytes_written != length && ferror(pstreami->file_handle) )
	{
		char errbuf[1024];
		sTRACE(skit_stream_throw_exc(SKIT_FILE_IO_EXCEPTION, &(stream->as_stream), skit_errno_to_cstr(errbuf, sizeof(errbuf))));
	}
}
void skit_pfile_stream_close(skit_pfile_stream *stream)
{
	SKIT_USE_FEATURE_EMULATION;
	sASSERT(stream != NULL);
	skit_pfile_stream_internal *pstreami = &(stream->as_internal);
	if( pstreami->file_handle == NULL )
		sTRACE(skit_stream_throw_exc(SKIT_FILE_IO_EXCEPTION, &(stream->as_stream), "Attempt to close an unopened stream."));

	sASSERT(pstreami->closer_func != NULL);
	sTRACE1(pstreami->closer_func(stream, pstreami->closer_func_arg, pstreami->file_handle));

	pstreami->file_handle = NULL;
}
void skit_pfile_stream_appendf_va(skit_pfile_stream *stream, const char *fmtstr, va_list vl )
{
	SKIT_USE_FEATURE_EMULATION;
	sASSERT(stream != NULL);
	sASSERT(fmtstr != NULL);
	skit_pfile_stream_internal *pstreami = &(stream->as_internal);
	if( pstreami->file_handle == NULL )
		sTRACE(skit_stream_throw_exc(SKIT_FILE_IO_EXCEPTION, &(stream->as_stream), "Attempt to write to an unopened stream."));
	
	vfprintf( pstreami->file_handle, fmtstr, vl ); /* TODO: error handling? */
	if ( skit_pfile_stream_check_flush(pstreami, skit_slice_of_cstr(fmtstr)) )
		skit_pfile_stream_flush(stream);
}
const char *skit__pfile_stream_populate(skit_pfile_stream *stream, skit_slice fname, const char *access_mode)
{
	SKIT_USE_FEATURE_EMULATION;
	sASSERT(stream != NULL);
	skit_pfile_stream_internal *pstreami = &(stream->as_internal);
	
	if ( pstreami->file_handle != NULL )
		sTRACE(skit_stream_throw_exc(SKIT_FILE_IO_EXCEPTION, &(stream->as_stream), "Already open to another file."));
	
	pstreami->name = skit_loaf_dup(fname);
	pstreami->access_mode = skit_loaf_copy_cstr(access_mode);
	
	return skit_loaf_as_cstr(pstreami->name);
}
void skit__pfile_stream_assign_fp(skit_pfile_stream *stream, FILE *fp)
{
	SKIT_USE_FEATURE_EMULATION;
	char errbuf[1024];
	skit_pfile_stream_internal *pstreami = &(stream->as_internal);
	pstreami->file_handle = fp;
	if ( pstreami->file_handle == NULL )
	{
		/* TODO: generate different kinds of exceptions depending on what went wrong. */
		sTRACE(skit_stream_throw_exc(SKIT_FILE_IO_EXCEPTION, &(stream->as_stream), skit_errno_to_cstr(errbuf, sizeof(errbuf))));
	}

	pstreami->closer_func = &skit_pfile_stream_own_closer;
	pstreami->closer_func_arg = NULL;
}
void skit_pfile_stream_appendln(skit_pfile_stream *stream, skit_slice line)
{
	SKIT_USE_FEATURE_EMULATION;
	sASSERT(stream != NULL);
	/* The error handling is handled by subsequent calls. */
	skit_pfile_stream_internal *pstreami = &(stream->as_internal);
	int do_flush = 0;
	skit_pfile_stream_append_int(stream, line);
	do_flush |= skit_pfile_stream_check_flush(pstreami, line);
	sTRACE(skit_pfile_stream_newline(pstreami));
	do_flush |= skit_pfile_stream_check_flush(pstreami, sSLICE("\n"));

	if ( do_flush )
		skit_pfile_stream_flush(stream);
}
static size_t skit_pfile_slurp_source(void *context, void *sink, size_t requested_chunk_size)
{
	SKIT_USE_FEATURE_EMULATION;
	
	skit_pfile_stream *stream = context;
	skit_pfile_stream_internal *pstreami = &(stream->as_internal);

	/* Read the next chunk of bytes from the file. */
	size_t nbytes_read = fread( sink, 1, requested_chunk_size, pstreami->file_handle );
	if ( ferror(pstreami->file_handle) )
	{
		char errbuf[1024];
		sTRACE(skit_stream_throw_exc(SKIT_FILE_IO_EXCEPTION, &(stream->as_stream), skit_errno_to_cstr(errbuf, sizeof(errbuf))));
	}
	
	return nbytes_read;
}
Exemple #15
0
END_RULE

static void skit_peg_branch_discard_test()
{
	SKIT_USE_FEATURE_EMULATION;
	skit_peg_parser *parser = skit_peg_parser_mock_new(skit_slice_null());
	SKIT_PEG_PARSING_INITIAL_VARS(parser);
	int which_discard = 0;
	parser->caller_context = &which_discard;
	parser->branch_discard = &skit_peg_bd_test_callback;
	
	sASSERT_PARSE_PASS(parser, "abcd",      branch_discard_1);
	sASSERT_PARSE_PASS(parser, "aaaabaaaa", branch_discard_2);
	sASSERT_PARSE_PASS(parser, "abc",       branch_discard_3);
	
	sTRACE(skit_peg_parser_mock_free(parser));
	
	printf("  skit_peg_branch_discard_test passed.\n");
}
void skit_unittest_signal_subfunc()
{
	SKIT_USE_FEATURE_EMULATION;
	sTRACE(skit_unittest_signal_subfunc2());
}
skit_slice skit_pfile_stream_read_fn(skit_pfile_stream *stream, skit_loaf *buffer, void *context, int (*accept_char)( skit_custom_read_context *ctx ))
{
	SKIT_USE_FEATURE_EMULATION;
	sASSERT(stream != NULL);
	skit_pfile_stream_internal *pstreami = &(stream->as_internal);
	skit_custom_read_context ctx;
	skit_loaf *read_buf;
	
	/* Return NULL slices when attempting to read from an already-exhausted stream. */
	if ( feof(pstreami->file_handle) )
		return skit_slice_null();
	
	/* Figure out which buffer to use. */
	read_buf = skit_pfile_get_read_buffer(pstreami, buffer);
	ssize_t length = sLLENGTH(*read_buf);
	skit_utf8c *buf_ptr = sLPTR(*read_buf);
	ctx.caller_context = context; /* Pass the caller's context along. */
	
	/* Iterate and feed the caller 1 character at a time. */
	FILE *fhandle = pstreami->file_handle;
	ssize_t nbytes = 0;
	int done = 0;
	while ( !done )
	{
		/* Get the next character. */
		int c = fgetc(fhandle);
		
		/* EOF check. */
		if ( c == EOF )
			break;
		
		/* Upsize buffer as needed. */
		nbytes++;
		if ( length < nbytes )
		{
			/* Slow, but w/e. */
			skit_loaf_resize(read_buf, nbytes+64);
			length = sLLENGTH(*read_buf);
			buf_ptr = sLPTR(*read_buf);
		}
		
		/* Place the new character into the read buffer. */
		buf_ptr[nbytes-1] = c;
		
		/* Push the character to the caller. */
		ctx.current_char = c;
		ctx.current_slice = skit_slice_of(read_buf->as_slice, 0, nbytes);
		if ( !accept_char(&ctx) )
			break;
	}
	
	/* fgetc returns EOF to signal errors as well. */
	/* To distinguish that from legit EOFs, we need to check the ferror function. */
	if ( ferror(fhandle) )
	{
		char errbuf[1024];
		sTRACE(skit_stream_throw_exc(SKIT_FILE_IO_EXCEPTION, &(stream->as_stream), skit_errno_to_cstr(errbuf, sizeof(errbuf))));
	}
	
	return ctx.current_slice;
}
void skit_array_unittest()
{
	SKIT_USE_FEATURE_EMULATION;
	printf("skit_array_unittest()\n");
	
	sTRACE(skit_slice_sanity_check());
	
	skit_utest_int_loaf loaf = skit_utest_int_loaf_alloc(4);
	int *ptr = skit_utest_int_loaf_ptr(loaf);
	ptr[0] = 1;
	ptr[1] = 3;
	ptr[2] = 3;
	ptr[3] = 7;
	skit_utest_int_loaf_resize(&loaf, 5);
	ptr = skit_utest_int_loaf_ptr(loaf);
	ptr[4] = 3;
	sASSERT_EQ(ptr[0], 1);
	sASSERT_EQ(ptr[1], 3);
	sASSERT_EQ(ptr[2], 3);
	sASSERT_EQ(ptr[3], 7);
	sASSERT_EQ(ptr[4], 3);
	
	skit_utest_int_slice slice = skit_utest_int_slice_of(loaf.as_slice, 2, SKIT_EOT);
	ptr = skit_utest_int_slice_ptr(slice);
	sASSERT_EQ(ptr[0], 3);
	sASSERT_EQ(ptr[1], 7);
	sASSERT_EQ(ptr[2], 3);
	
	slice = skit_utest_int_slice_of(loaf.as_slice, 2, 4);
	ptr = skit_utest_int_slice_ptr(slice);
	sASSERT_EQ(skit_utest_int_slice_len(slice), 2);
	sASSERT_EQ(ptr[0], 3);
	sASSERT_EQ(ptr[1], 7);
	
	skit_utest_int_slice_bfd_put( &loaf, &slice, 7 );
	ptr = skit_utest_int_slice_ptr(slice);
	sASSERT_EQ(ptr[0], 3);
	sASSERT_EQ(ptr[1], 7);
	sASSERT_EQ(ptr[2], 7);
	
	ptr = skit_utest_int_loaf_ptr(loaf);
	sASSERT_EQ(ptr[0], 1);
	sASSERT_EQ(ptr[1], 3);
	sASSERT_EQ(ptr[2], 3);
	sASSERT_EQ(ptr[3], 7);
	sASSERT_EQ(ptr[4], 7);
	
	skit_utest_int_loaf_put(&loaf, 0);
	ptr = skit_utest_int_loaf_ptr(loaf);
	sASSERT_EQ(ptr[0], 1);
	sASSERT_EQ(ptr[1], 3);
	sASSERT_EQ(ptr[2], 3);
	sASSERT_EQ(ptr[3], 7);
	sASSERT_EQ(ptr[4], 7);
	sASSERT_EQ(ptr[5], 0);
	
	skit_utest_int_loaf_put(&loaf, 8);
	ptr = skit_utest_int_loaf_ptr(loaf);
	sASSERT_EQ(ptr[0], 1);
	sASSERT_EQ(ptr[1], 3);
	sASSERT_EQ(ptr[2], 3);
	sASSERT_EQ(ptr[3], 7);
	sASSERT_EQ(ptr[4], 7);
	sASSERT_EQ(ptr[5], 0);
	sASSERT_EQ(ptr[6], 8);
	
	int *elem = skit_utest_int_loaf_index(loaf, 6);
	sASSERT_EQ(*elem, 8);
	
	skit_utest_int_loaf_free(&loaf);
	
	sTRACE(skit_array_bfd_new_el_test());
	sTRACE(skit_array_filter_test());
	
	printf("  skit_array_unittest passed!\n");
	printf("\n");
}
/* This readln implementation uses the advice posted by "R.." in the following
article:
http://stackoverflow.com/questions/4411345/c-reading-a-text-file-with-variable-length-lines-line-by-line-using-fread-f
It should be able to handle lines with '\0' characters embedded in them, 
read no more characters from the file than exactly one line, and also
terminate correctly at the end-of-file.
*/
static void skit_try_fgets(
	skit_pfile_stream_internal *pstreami,
	skit_slice next_chunk,
	size_t *nbytes_read,
	int    *done )
{
	SKIT_USE_FEATURE_EMULATION;
	char *buf = (char*)sSPTR(next_chunk);
	size_t buf_len = sSLENGTH(next_chunk);
	*done = 0;
	
	/* Check for potentially dumb cases. */
	if ( buf_len < 1 )
	{
		*nbytes_read = 0;
		return; /* Force the caller to allocate more. */
	}
	
	/* Fill the chunk with newline characters. */
	memset(buf, '\n', buf_len); 
	
	/* Read data over it. */
	char *ret = fgets(buf, buf_len, pstreami->file_handle);
	
	/* Catch errors. */
	if ( ferror(pstreami->file_handle) )
	{
		char errbuf[1024];
		sTRACE(skit_stream_throw_exc(SKIT_FILE_IO_EXCEPTION, (skit_stream*)pstreami, skit_errno_to_cstr(errbuf, sizeof(errbuf))));
	}
	
	/* fgets returns NULL when there is an error or when EOF occurs. */
	/* We already dealt with errors, so it must be an EOF. */
	/* This also indicates that "no characters have been read". */
	/* In this case the buffer is left untouched, so we can't differentiate */
	/*   what happens based on it's contents like the later code does, so */
	/*   it needs to be special-cased right here. */
	if ( ret == NULL )
	{
		*done = 1; /* This means we're done, one way or another. */
		*nbytes_read = 0;
		return;
	}
	
	/* Find the first newline. */
	char *ptr = memchr(buf, '\n', buf_len);
	
	if ( !ptr ) 
	{
		/* No newlines found: our buffer was completely overwritten, and is thus not large enough. */
		/* We will have filled the buffer /except/ for the '\0' character that fgets puts at the end. */
		*nbytes_read = buf_len - 1;
		return;
	}
	
	/* The remaining cases are: */
	/* end-of-line */
	/* end-of-file */
	/* Having placed a bunch of newlines in our buffer will help in */
	/*   in distinguishing between these possibilities, because fgets */
	/*   doesn't do anything helpful like returning a "number of bytes */
	/*   read" value. */
	if ( *(ptr+1) == '\0' )
	{
		/* Termination due to end-of-line. */
		sASSERT_EQ_HEX( *ptr, '\n' );
		*done = 1;
		
		/* Don't return the last '\n'. */
		/* The '\n' is supposed to be absent per the stream interface. */
		*nbytes_read = ptr - buf;
		
		/* Be nice and nul-terminate things, just in case. */
		*ptr = '\0';
	}
	else
	{
		/* The newline was from our memset. */
		/* This means that end-of-file was reached. */
		
		*done = 1;
		
		/* There should be a '\0' placed before the '\n' by fgets. */
		/* This is the end-of-line for the last line in the file. */
		/* The '\0' isn't from the file, so we don't return it.  */
		/* Because we aren't return the '\n' from the memset or the '\0' from fgets, */
		/*   we'll subtract 1 from our final pointer. */
		sASSERT_EQ_HEX( *(ptr-1), '\0' );
		*nbytes_read = ptr - buf - 1;
	}
	
	return;
}