Replace all POSIX-features to become fully ISO-C99
As it turned out, the only things that needed replacing were
getline(), strdup() and the timing in the benchmarks. Analogously,
we replace -D_DEFAULT_SOURCE with -D_ISOC99_SOURCE.
This way we further extend the number of platforms where libgrapheme can
be compiled and run on, e.g. MSVC still does not include getline().
Signed-off-by: Laslo Hunhold <dev@frign.de>
diff --git a/benchmark/util.c b/benchmark/util.c
index 94531bb..bdad3a5 100644
--- a/benchmark/util.c
+++ b/benchmark/util.c
@@ -71,10 +71,9 @@
}
static double
-time_diff(struct timespec *a, struct timespec *b)
+time_diff(clock_t a, clock_t b)
{
- return (double)(b->tv_sec - a->tv_sec) +
- (double)(b->tv_nsec - a->tv_nsec) * 1E-9;
+ return (double)(b - a) / CLOCKS_PER_SEC;
}
void
@@ -82,14 +81,14 @@
const char *comment, const char *unit, double *baseline,
size_t num_iterations, size_t units_per_iteration)
{
- struct timespec start, end;
+ clock_t start, end;
size_t i;
double diff;
printf("\t%s ", name);
fflush(stdout);
- clock_gettime(CLOCK_MONOTONIC, &start);
+ start = clock();
for (i = 0; i < num_iterations; i++) {
func(payload);
@@ -98,8 +97,8 @@
fflush(stdout);
}
}
- clock_gettime(CLOCK_MONOTONIC, &end);
- diff = time_diff(&start, &end) / (double)num_iterations /
+ end = clock();
+ diff = time_diff(start, end) / (double)num_iterations /
(double)units_per_iteration;
if (isnan(*baseline)) {
diff --git a/config.mk b/config.mk
index 5dcc742..c5284c5 100644
--- a/config.mk
+++ b/config.mk
@@ -14,7 +14,7 @@
BINSUFFIX =
# flags
-CPPFLAGS = -D_DEFAULT_SOURCE
+CPPFLAGS = -D_ISOC99_SOURCE
CFLAGS = -std=c99 -Os -Wall -Wextra -Wpedantic
LDFLAGS = -s
diff --git a/gen/util.c b/gen/util.c
index 9d076b2..332be82 100644
--- a/gen/util.c
+++ b/gen/util.c
@@ -146,6 +146,43 @@
return 0;
}
+static bool
+get_line(char **buf, size_t *bufsize, FILE *fp, size_t *len)
+{
+ int ret = EOF;
+
+ for (*len = 0;; (*len)++) {
+ if (*len > 0 && *buf != NULL && (*buf)[*len - 1] == '\n') {
+ /*
+ * if the previously read character was a newline,
+ * we fake an end-of-file so we NUL-terminate and
+ * are done.
+ */
+ ret = EOF;
+ } else {
+ ret = fgetc(fp);
+ }
+
+ if (*len >= *bufsize) {
+ /* the buffer needs to be expanded */
+ *bufsize += 512;
+ if ((*buf = realloc(*buf, *bufsize)) == NULL) {
+ fprintf(stderr, "get_line: Out of memory.\n");
+ exit(1);
+ }
+ }
+
+ if (ret != EOF) {
+ (*buf)[*len] = (char)ret;
+ } else {
+ (*buf)[*len] = '\0';
+ break;
+ }
+ }
+
+ return *len == 0 && (feof(fp) || ferror(fp));
+}
+
void
parse_file_with_callback(const char *fname,
int (*callback)(const char *, char **, size_t, char *,
@@ -154,8 +191,7 @@
{
FILE *fp;
char *line = NULL, **field = NULL, *comment;
- size_t linebufsize = 0, i, fieldbufsize = 0, j, nfields;
- ssize_t len;
+ size_t linebufsize = 0, i, fieldbufsize = 0, j, nfields, len;
/* open file */
if (!(fp = fopen(fname, "r"))) {
@@ -164,7 +200,7 @@
exit(1);
}
- while ((len = getline(&line, &linebufsize, fp)) >= 0) {
+ while (!get_line(&line, &linebufsize, fp, &len)) {
/* remove trailing newline */
if (len > 0 && line[len - 1] == '\n') {
line[len - 1] = '\0';
@@ -654,7 +690,8 @@
{
struct break_test *t,
**test = ((struct break_test_payload *)payload)->test;
- size_t i, *testlen = ((struct break_test_payload *)payload)->testlen;
+ size_t i, *testlen = ((struct break_test_payload *)payload)->testlen,
+ commentlen;
char *token;
(void)fname;
@@ -733,11 +770,15 @@
}
/* store comment */
- if (comment != NULL &&
- ((*test)[*testlen - 1].descr = strdup(comment)) == NULL) {
- fprintf(stderr, "break_test_callback: strdup: %s.\n",
- strerror(errno));
- return 1;
+ if (comment != NULL) {
+ commentlen = strlen(comment) + 1;
+ if (((*test)[*testlen - 1].descr = malloc(commentlen)) ==
+ NULL) {
+ fprintf(stderr, "break_test_callback: malloc: %s.\n",
+ strerror(errno));
+ return 1;
+ }
+ memcpy((*test)[*testlen - 1].descr, comment, commentlen);
}
return 0;