Replace all POSIX-features to become fully ISO-C99 - libgrapheme - unicode string library
 (HTM) git clone git://git.suckless.org/libgrapheme
 (DIR) Log
 (DIR) Files
 (DIR) Refs
 (DIR) README
 (DIR) LICENSE
       ---
 (DIR) commit c0d28c3cad5c9e02dfa93b3ff3e6953ad0f22d75
 (DIR) parent 0e95e5c797b1dc41117e1ea5455f2a7f2932868d
 (HTM) Author: Laslo Hunhold <dev@frign.de>
       Date:   Fri, 24 Feb 2023 18:21:02 +0100
       
       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>
       
       Diffstat:
         M benchmark/util.c                    |      13 ++++++-------
         M config.mk                           |       2 +-
         M gen/util.c                          |      59 ++++++++++++++++++++++++++-----
       
       3 files changed, 57 insertions(+), 17 deletions(-)
       ---
 (DIR) diff --git a/benchmark/util.c b/benchmark/util.c
       @@ -71,10 +71,9 @@ generate_utf8_test_buffer(const struct break_test *test, size_t testlen,
        }
        
        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 @@ run_benchmark(void (*func)(const void *), const void *payload, const char *name,
                      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 @@ run_benchmark(void (*func)(const void *), const void *payload, const char *name,
                                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)) {
 (DIR) diff --git a/config.mk b/config.mk
       @@ -14,7 +14,7 @@ SONAME    = libgrapheme.so.$(VERSION_MAJOR).$(VERSION_MINOR).$(VERSION_PATCH)
        BINSUFFIX = 
        
        # flags
       -CPPFLAGS = -D_DEFAULT_SOURCE
       +CPPFLAGS = -D_ISOC99_SOURCE
        CFLAGS   = -std=c99 -Os -Wall -Wextra -Wpedantic
        LDFLAGS  = -s
        
 (DIR) diff --git a/gen/util.c b/gen/util.c
       @@ -146,6 +146,43 @@ range_parse(const char *str, struct range *range)
                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 @@ parse_file_with_callback(const char *fname,
        {
                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 @@ parse_file_with_callback(const char *fname,
                        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 @@ break_test_callback(const char *fname, char **field, size_t nfields,
        {
                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 @@ break_test_callback(const char *fname, char **field, size_t nfields,
                }
        
                /* 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;