chiark / gitweb /
utils/macros.h: Add <ctype.h> and `foocmp' helper macros.
authorMark Wooding <mdw@distorted.org.uk>
Tue, 1 Oct 2019 17:41:17 +0000 (18:41 +0100)
committerMark Wooding <mdw@distorted.org.uk>
Fri, 8 May 2020 12:44:29 +0000 (13:44 +0100)
Both of these have been a nuisance for years.  Do something about it.

The command

git grep -En '\<(is|to)[a-z]+\(|\<(str|mem)[a-z]*cmp\(' -- '*.[ch]'

finds code which it might be good to change.

The hairy Emacs command

(query-replace-regexp
 "\\<\\(\\(str\\|mem\\)\\sw*cmp\\)(\\([^,]*\\), \\([^)]*\\)) \\(==\\|!=\\|<\\|<=\\|>\\|>=\\) 0"
 '(replace-eval-replacement
   . (concat (replace-quote (upcase (match-string 1)))
     "(\\3, \\5, \\4)"))
 nil
 (if (and transient-mark-mode mark-active) (region-beginning))
 (if (and transient-mark-mode mark-active) (region-end))
 nil)

will convert easy cases of `foocmp' calls, but hard ones have to be done
by hand.

22 files changed:
codec/baseconv.c
codec/bincode.c
codec/url.c
hash/crc-mktab.c
hash/unihash-mkstatic.c
sel/bres-adns.c
sel/ident.c
struct/dstr-putf.c
struct/sym.c
struct/t/assoc-test.c
struct/t/da-test.c
struct/t/dstr-putf-test.c
struct/t/sym-test.c
sys/t/fdpass-test.c
sys/t/mdup-test.c
test/testrig.c
trace/trace.c
trace/traceopt.c
utils/macros.3
utils/macros.h
utils/str.c
utils/versioncmp.c

index bdb850f7d19ca53b2cbf4c9092e8fd7b6758852e..b7cb0a0618ebe0a893c2721c336429a9eb8cdb88 100644 (file)
@@ -35,6 +35,7 @@
 #include "alloc.h"
 #include "codec.h"
 #include "dstr.h"
+#include "macros.h"
 #include "sub.h"
 
 #include "base64.h"
@@ -279,7 +280,7 @@ enum {
 
 #define PUTWRAP(x) WRAP({                                              \
   char ch = encodemap[x];                                              \
-  if (f & CDCF_LOWERC) ch = tolower((unsigned char)ch);                        \
+  if (f & CDCF_LOWERC) ch = TOLOWER(ch);                               \
   DPUTC(d, ch);                                                                \
 })
 
@@ -350,9 +351,9 @@ static int ctxn##_dodecode(ctxn##_ctx *ctx,                         \
        case 0:                                                         \
          break;                                                        \
        case CDCF_LOWERC:                                               \
-         if (isupper(ch)) goto badch;                                  \
+         if (ISUPPER(ch)) goto badch;                                  \
        default:                                                        \
-         ch = toupper(ch);                                             \
+         ch = TOUPPER(ch);                                             \
       }                                                                        \
       x = decodemap[ch];                                               \
       switch (x) {                                                     \
index af1e677242fc955c452486993dc88370d3df4247..77d24570e51db875e95052b17a8fd2c2884ed324 100644 (file)
@@ -36,6 +36,7 @@
 
 #include "codec.h"
 #include "dstr.h"
+#include "macros.h"
 #include "mdwopt.h"
 #include "quis.h"
 #include "report.h"
@@ -195,7 +196,7 @@ int main(int argc, char *argv[])
          n = strcspn(p, ",");
          for (i = 0; flagtab[i].name; i++) {
            if (strlen(flagtab[i].name) == n &&
-               strncmp(flagtab[i].name, p, n) == 0)
+               STRNCMP(flagtab[i].name, ==, p, n))
              goto found;
          }
          die(EXIT_FAILURE, "unknown flag `%.*s'", (int)n, p);
@@ -215,7 +216,7 @@ int main(int argc, char *argv[])
 
   for (cc = cctab;; cc++) {
     if (!*cc) die(EXIT_FAILURE, "unknown codec `%s'", *argv);
-    else if (strcmp(*argv, (*cc)->name) == 0) break;
+    else if (STRCMP(*argv, ==, (*cc)->name)) break;
   }
   argv++; argc--;
 
@@ -267,7 +268,7 @@ int main(int argc, char *argv[])
   if (!argc)
     code(c, "<stdin>", stdin, ofp);
   else for (i = 0; i < argc; i++) {
-    if (strcmp(argv[i], "-") == 0)
+    if (STRCMP(argv[i], ==, "-"))
       code(c, "<stdin>", stdin, ofp);
     else if ((ifp = fopen(argv[i], imode)) == 0) {
       die(EXIT_FAILURE, "couldn't open `%s' for reading: %s",
index 0de87ae1fff337ab5244ed8a348908d694de71f7..eecfe820dd0180ac8cb31b68e19ad7a3d1b2b095 100644 (file)
@@ -33,6 +33,7 @@
 #include <string.h>
 
 #include "dstr.h"
+#include "macros.h"
 #include "url.h"
 
 /*----- Main code ---------------------------------------------------------*/
@@ -66,8 +67,8 @@ static void encode(url_ectx *ctx, dstr *d, const char *p)
       case ' ': DPUTC(d, '+');
        break;
       default:
-       if (isspace((unsigned char)*p)) goto unsafe;
-       else if (isalnum((unsigned char)*p)) goto safe;
+       if (ISSPACE(*p)) goto unsafe;
+       else if (ISALNUM(*p)) goto safe;
        else if (ctx->f&URLF_LAX) goto safe;
        else goto unsafe;
       case '/': case '~':
index 4453cf36d87c42468ccb0256fd9003383daac26a..a176d161192493597633ff18f9ddebe2f1a6efd8 100644 (file)
@@ -37,6 +37,7 @@
 #include <stdlib.h>
 #include <string.h>
 
+#include "macros.h"
 #include "mdwopt.h"
 #include "quis.h"
 #include "report.h"
@@ -266,8 +267,8 @@ int main(int argc, char *argv[])
        die(EXIT_FAILURE, "not enough memory");
       guard = p;
       for (q = file; *q; p++, q++) {
-       if (isalnum((unsigned char)*q))
-         *p = toupper((unsigned char)*q);
+       if (ISALNUM(*q))
+         *p = TOUPPER(*q);
        else
          *p = '_';
       }
index 0505fcff3e45fdf28ca162ce526f65846ff27a96..958b3d7fe28e9b04e3b6e035652141e90e9f3f90 100644 (file)
@@ -187,8 +187,8 @@ int main(int argc, char *argv[])
        die(EXIT_FAILURE, "not enough memory");
       guard = p;
       for (q = file; *q; p++, q++) {
-       if (isalnum((unsigned char)*q))
-         *p = toupper((unsigned char)*q);
+       if (ISALNUM(*q))
+         *p = TOUPPER(*q);
        else
          *p = '_';
       }
index 03fafa4f12a9935a717b9940431101e280227633..491a9a8659aeb926bafb05b84ab6525638567ff0 100644 (file)
@@ -215,7 +215,7 @@ static void report(bres_client *rc, adns_answer *a,
   if (a->cname) n[j++] = a->cname;
   else { n[j++] = *nv; nv++; nn--; }
   for (i = 0; i < nn && j < N(n) - 1; i++)
-    if (strcmp(n[0], nv[i]) != 0) n[j++] = nv[i];
+    if (STRCMP(n[0], !=, nv[i])) n[j++] = nv[i];
   n[j++] = 0;
   for (i = j = 0; i < an && j < N(aa) - 1; i++) {
     if (av[i].addr.sa.sa_family == AF_INET)
index 0017f0a3877faef70c4d36d975245caa47b22f07..a59cd229fa7148375e3d0029c289e8089317c56d 100644 (file)
@@ -44,6 +44,7 @@
 #include "dstr.h"
 #include "exc.h"
 #include "ident.h"
+#include "macros.h"
 #include "selbuf.h"
 
 /*----- Main code ---------------------------------------------------------*/
@@ -77,13 +78,13 @@ static char *next(char **pp)
 
   /* --- Skip past any leading whitespace --- */
 
-  while (isspace((unsigned char)*p))
+  while (ISSPACE(*p))
     p++;
 
   /* --- Now start work on the string itself --- */
 
   for (;;) {
-    if (*p == 0 || *p == ':' || *p == ',' || isspace((unsigned char)*p))
+    if (*p == 0 || *p == ':' || *p == ',' || ISSPACE(*p))
       break;
     else if (*p == '\\') {
       p++;
@@ -97,7 +98,7 @@ static char *next(char **pp)
 
   /* --- Tidy up afterwards --- */
 
-  while (isspace((unsigned char)*p))
+  while (ISSPACE(*p))
     p++;
   if (*p == 0)
     *pp = 0;
@@ -132,11 +133,11 @@ static void parse(char *p, ident_reply *i)
   /* --- Find out what sort of a reply this is --- */
 
   q = next(&p);
-  if (strcmp(q, "USERID") == 0) {
+  if (STRCMP(q, ==, "USERID")) {
     i->type = IDENT_USERID;
     i->u.userid.os = next(&p);
     i->u.userid.user = next(&p);
-  } else if (strcmp(q, "ERROR") == 0) {
+  } else if (STRCMP(q, ==, "ERROR")) {
     i->type = IDENT_ERROR;
     i->u.error = next(&p);
   } else
index e097968a875d7e9ceaa2ed8268b8e03f3a91c8e1..270f9a3f84bdd96e4cdf83c772c6da86daaf6ee7 100644 (file)
@@ -47,6 +47,7 @@
 
 #include "darray.h"
 #include "dstr.h"
+#include "macros.h"
 
 /*----- Tunable constants -------------------------------------------------*/
 
@@ -247,7 +248,7 @@ int dstr_vputf(dstr *d, const char *p, va_list *ap)
 
   done_flags:
     i = 0;
-    while (isdigit((unsigned char)*p)) i = 10*i + *p++ - '0';
+    while (ISDIGIT(*p)) i = 10*i + *p++ - '0';
 
     /* --- Snag: this might have been an argument position indicator --- */
 
@@ -269,11 +270,11 @@ int dstr_vputf(dstr *d, const char *p, va_list *ap)
       fs->wd = i;
     } else if (*p == '*') {
       p++;
-      if (!isdigit((unsigned char)*p))
+      if (!ISDIGIT(*p))
        i = anext++;
       else {
        i = *p++ - '0';
-       while (isdigit((unsigned char)*p)) i = 10*i + *p++ - '0';
+       while (ISDIGIT(*p)) i = 10*i + *p++ - '0';
        assert(*p == '$'); p++;
        assert(i > 0); i--;
       }
@@ -286,19 +287,19 @@ int dstr_vputf(dstr *d, const char *p, va_list *ap)
     if (*p == '.') {
       p++;
       f |= f_prec;
-      if (isdigit((unsigned char)*p)) {
+      if (ISDIGIT(*p)) {
        i = *p++ - '0';
-       while (isdigit((unsigned char)*p)) i = 10*i + *p++ - '0';
+       while (ISDIGIT(*p)) i = 10*i + *p++ - '0';
        fs->prec = i;
       } else if (*p != '*')
        fs->prec = 0;
       else {
        p++;
-       if (!isdigit((unsigned char)*p))
+       if (!ISDIGIT(*p))
          i = anext++;
        else {
          i = *p++ - '0';
-         while (isdigit((unsigned char)*p)) i = 10*i + *p++ - '0';
+         while (ISDIGIT(*p)) i = 10*i + *p++ - '0';
          assert(*p == '$'); p++;
          assert(i > 0); i--;
        }
index 4543811676af87d303f88dbe0f3fd0e0a1fedf6c..2eb309c175ec20de8f87343ee0361bf13c236283 100644 (file)
@@ -40,6 +40,7 @@
 #include "bits.h"
 #include "exc.h"
 #include "hash.h"
+#include "macros.h"
 #include "sub.h"
 #include "sym.h"
 #include "unihash.h"
@@ -136,7 +137,8 @@ void *sym_find(sym_table *t, const char *n, long l, size_t sz, unsigned *f)
 
   for (p = bin; *p; p = &(*p)->next) {
     q = (sym_base *)*p;
-    if (hash == q->b.hash && len == q->len && !memcmp(n, SYM_NAME(q), len)) {
+    if (hash == q->b.hash && len == q->len &&
+       MEMCMP(n, ==, SYM_NAME(q), len)) {
 
       /* --- Found a match --- *
        *
index bd1bab4e45564595d31a445c99bc15f8b985ff92..a727bbf38de65e0eea5b342382d73c8ad4a04712 100644 (file)
@@ -5,6 +5,7 @@
 
 #include "assoc.h"
 #include "atom.h"
+#include "macros.h"
 
 typedef struct word {
   assoc_base _b;
@@ -34,7 +35,7 @@ int main(void)
     buf[strlen(buf) - 1] = 0;
     p = strtok(buf, " ");
 
-    if (strcmp(p, "set") == 0) {
+    if (STRCMP(p, ==, "set")) {
       char *k = strtok(0, " ");
       int i = atoi(strtok(0, " "));
       unsigned f;
@@ -42,14 +43,14 @@ int main(void)
       w->i = i;
       if (!f)
        n++;
-    } else if (strcmp(p, "get") == 0) {
+    } else if (STRCMP(p, ==, "get")) {
       char *k = strtok(0, " ");
       word *w = assoc_find(&t, atom_intern(&at, k), 0, 0);
       if (w)
        printf("%i\n", w->i);
       else
        puts("*MISSING*");
-    } else if (strcmp(p, "del") == 0) {
+    } else if (STRCMP(p, ==, "del")) {
       char *k = strtok(0, " ");
       word *w = assoc_find(&t, atom_intern(&at, k), 0, 0);
       if (w) {
@@ -57,9 +58,9 @@ int main(void)
        n--;
       } else
        puts("*MISSING*");
-    } else if (strcmp(p, "count") == 0) {
+    } else if (STRCMP(p, ==, "count")) {
       printf("%lu\n", (unsigned long)n);
-    } else if (strcmp(p, "show") == 0) {
+    } else if (STRCMP(p, ==, "show")) {
       assoc_iter i;
       word *w;
       word **v, **vv;
index 0f3e6253c071d823397de7516da3265916eef334..ba86a8d936f495a4433c847581d60aad1c41e528 100644 (file)
@@ -10,6 +10,7 @@
 
 #include "darray.h"
 #include "exc.h"
+#include "macros.h"
 
 DA_DECL(vec, int);
 
@@ -49,18 +50,18 @@ int main(void)
     p = strtok(buf, " ");
 
     TRY {
-      if (strcmp(p, "push") == 0) {
+      if (STRCMP(p, ==, "push")) {
        int n = atoi(strtok(0, " "));
        DA_PUSH(&v, n);
-      } else if (strcmp(p, "unshift") == 0) {
+      } else if (STRCMP(p, ==, "unshift")) {
        int n = atoi(strtok(0, " "));
        DA_UNSHIFT(&v, n);
-      } else if (strcmp(p, "pop") == 0) {
+      } else if (STRCMP(p, ==, "pop")) {
        printf("%i\n", DA_POP(&v));
-      } else if (strcmp(p, "shift") == 0) {
+      } else if (STRCMP(p, ==, "shift")) {
        printf("%i\n", DA_SHIFT(&v));
-      } else if (strcmp(p, "insert") == 0 ||
-                strcmp(p, "append") == 0) {
+      } else if (STRCMP(p, ==, "insert") ||
+                STRCMP(p, ==, "append")) {
        vec vv;
        char *q = p;
        DA_CREATE(&vv);
@@ -69,7 +70,7 @@ int main(void)
          int n = atoi(p);
          DA_PUSH(&vv, n);
        }
-       if (strcmp(q, "insert") == 0) {
+       if (STRCMP(q, ==, "insert")) {
          DA_SHUNT(&v, DA_LEN(&vv));
          DA_SLIDE(&v, DA_LEN(&vv));
          memcpy(DA(&v), DA(&vv), DA_LEN(&vv) * sizeof(int));
@@ -80,13 +81,13 @@ int main(void)
          memcpy(DA(&v) + l, DA(&vv), DA_LEN(&vv) * sizeof(int));
        }
        DA_DESTROY(&vv);
-      } else if (strcmp(p, "delete") == 0) {
+      } else if (STRCMP(p, ==, "delete")) {
        int n = atoi(strtok(0, " "));
        DA_UNSLIDE(&v, n);
-      } else if (strcmp(p, "reduce") == 0) {
+      } else if (STRCMP(p, ==, "reduce")) {
        int n = atoi(strtok(0, " "));
        DA_SHRINK(&v, n);
-      } else if (strcmp(p, "set") == 0) {
+      } else if (STRCMP(p, ==, "set")) {
        size_t i = atoi(strtok(0, " "));
        int n = atoi(strtok(0, " "));
        size_t l = DA_LEN(&v);
@@ -97,23 +98,23 @@ int main(void)
            DA(&v)[j] = -1;
        }
        DA(&v)[i] = n;
-      } else if (strcmp(p, "get") == 0) {
+      } else if (STRCMP(p, ==, "get")) {
        size_t i = atoi(strtok(0, " "));
        if (i >= DA_LEN(&v))
          puts("*RANGE*");
        else
          printf("%i\n", DA(&v)[i]);
-      } else if (strcmp(p, "first") == 0) {
+      } else if (STRCMP(p, ==, "first")) {
        if (DA_LEN(&v))
          printf("%i\n", DA_FIRST(&v));
        else
          puts("*RANGE*");
-      } else if (strcmp(p, "last") == 0) {
+      } else if (STRCMP(p, ==, "last")) {
        if (DA_LEN(&v))
          printf("%i\n", DA_LAST(&v));
        else
          puts("*RANGE*");
-      } else if (strcmp(p, "show") == 0) {
+      } else if (STRCMP(p, ==, "show")) {
        if (DA_LEN(&v) == 0)
          puts("*EMPTY*");
        else {
index 5de787075b8f74a4bbcefae3a0476d8ce915d08f..462371d5e8d37b92908da475246093d3b499500e 100644 (file)
@@ -8,6 +8,7 @@
 #include <string.h>
 
 #include "dstr.h"
+#include "macros.h"
 
 static int win = 0, lose = 0;
 static dstr d = DSTR_INIT;
@@ -15,7 +16,7 @@ static char buf[1024];
 
 static void check(const char *what, const char *want)
 {
-  if (strcmp(want, d.buf) == 0)
+  if (STRCMP(want, ==, d.buf))
     win++;
   else {
     lose++;
index 8a9435f563ff2b1144cb0e8f16082e4121b28d95..dfc2391220e1562bfb79fbf2311cc58d96e99159 100644 (file)
@@ -3,6 +3,7 @@
 #include <stdlib.h>
 #include <string.h>
 
+#include "macros.h"
 #include "sym.h"
 
 typedef struct word {
@@ -31,7 +32,7 @@ int main(void)
     buf[strlen(buf) - 1] = 0;
     p = strtok(buf, " ");
 
-    if (strcmp(p, "set") == 0) {
+    if (STRCMP(p, ==, "set")) {
       char *k = strtok(0, " ");
       int i = atoi(strtok(0, " "));
       unsigned f;
@@ -39,14 +40,14 @@ int main(void)
       w->i = i;
       if (!f)
        n++;
-    } else if (strcmp(p, "get") == 0) {
+    } else if (STRCMP(p, ==, "get")) {
       char *k = strtok(0, " ");
       word *w = sym_find(&t, k, -1, 0, 0);
       if (w)
        printf("%i\n", w->i);
       else
        puts("*MISSING*");
-    } else if (strcmp(p, "del") == 0) {
+    } else if (STRCMP(p, ==, "del")) {
       char *k = strtok(0, " ");
       word *w = sym_find(&t, k, -1, 0, 0);
       if (w) {
@@ -54,9 +55,9 @@ int main(void)
        n--;
       } else
        puts("*MISSING*");
-    } else if (strcmp(p, "count") == 0) {
+    } else if (STRCMP(p, ==, "count")) {
       printf("%lu\n", (unsigned long)n);
-    } else if (strcmp(p, "show") == 0) {
+    } else if (STRCMP(p, ==, "show")) {
       sym_iter i;
       word *w;
       word **v, **vv;
index 01966381688fdb35a5405da23bcecd404f0c88e9..54fc8dc707b1608623460f49ba70bfeeb9baa997 100644 (file)
@@ -63,7 +63,7 @@ int main(int argc, char *argv[])
 
   ego(argv[0]);
 
-  if (argc == 3 && strcmp(argv[1], "server") == 0) {
+  if (argc == 3 && STRCMP(argv[1], ==, "server")) {
     set_unix_addr(&sun, argv[2]);
     lsk = socket(PF_UNIX, SOCK_STREAM, 0);
     if (lsk < 0) die(2, "socket: %s", strerror(errno));
@@ -77,14 +77,14 @@ int main(int argc, char *argv[])
     if (n < 0) die(2, "fdrecv: %s", strerror(errno));
     close(sk);
     if (fd == -1) die(2, "no fd found");
-    if (n != sizeof(sockmsg) || strcmp(buf, sockmsg) != 0)
+    if (n != sizeof(sockmsg) || STRCMP(buf, !=, sockmsg))
       die(2, "socket message mismatch (found `%.*s')", (int)n, buf);
     n = read(fd, buf, sizeof(buf));
     if (n < 0) die(2, "read: %s", strerror(errno));
-    if (n != sizeof(pipemsg) || strcmp(buf, pipemsg) != 0)
+    if (n != sizeof(pipemsg) || STRCMP(buf, !=, pipemsg))
       die(2, "pipe message mismatch (found `%.*s')", (int)n, buf);
     close(fd);
-  } else if (argc == 3 && strcmp(argv[1], "client") == 0) {
+  } else if (argc == 3 && STRCMP(argv[1], ==, "client")) {
     set_unix_addr(&sun, argv[2]);
     if (pipe(pfd)) die(2, "pipe: %s", strerror(errno));
     sk = socket(PF_UNIX, SOCK_STREAM, 0);
index 43aa45d8d05584f8cba09283b4bf08aa437b3788..6597b3323fa7e6ad4a0bfebb96c71c629ebf5194 100644 (file)
@@ -6,6 +6,7 @@
 #include <sys/types.h>
 #include <sys/stat.h>
 #include <fcntl.h>
+#include "macros.h"
 #include "mdup.h"
 
 #define MAXFD 256
@@ -33,7 +34,7 @@ int main(int argc, char *argv[])
   int verbose = 0;
 
   for (i = 1, j = 0; i < argc; i++) {
-    if (strcmp(argv[i], "-v") == 0) { verbose++; continue; }
+    if (STRCMP(argv[i], ==, "-v")) { verbose++; continue; }
     if (j >= MAXFD) { fprintf(stderr, "too many\n"); exit(1); }
     if (sscanf(argv[i], "%d:%d", &fds[j].cur, &fds[j].want) < 2 ||
        fds[j].cur >= MAXFD)
index c85276f330dd7210f91512de8327b69df04475ad..c7dea673490ceee746afdaf4a45352b1cd403dff 100644 (file)
@@ -34,6 +34,7 @@
 #include <string.h>
 
 #include "dstr.h"
+#include "macros.h"
 #include "report.h"
 #include "quis.h"
 #include "testrig.h"
@@ -99,7 +100,7 @@ again:
 
   /* --- Skip leading whitespace --- */
 
-  while (isspace((unsigned char)ch))
+  while (ISSPACE(ch))
     ch = getc(fp);
 
   /* --- Trap some special characters --- */
@@ -163,7 +164,7 @@ again:
          case '`':
            goto done;
          default:
-           if (isspace((unsigned char)ch))
+           if (ISSPACE(ch))
              goto done;
        }
        if (ch == '\\') {
@@ -328,7 +329,7 @@ int test_do(const test_suite suites[], FILE *fp, test_results *results)
       goto done;
     }
 
-    if (strcmp(tok.buf, "SUITE") == 0) {
+    if (STRCMP(tok.buf, ==, "SUITE")) {
       t = gettok(fp);
       if (t != TOK_WORD) {
        moan("expected <word>; found `%s'", decode(t));
@@ -339,7 +340,7 @@ int test_do(const test_suite suites[], FILE *fp, test_results *results)
          chunks = 0;
          break;
        }
-       if (strcmp(tok.buf, ss->name) == 0) {
+       if (STRCMP(tok.buf, ==, ss->name)) {
          chunks = ss->chunks;
          break;
        }
@@ -354,7 +355,7 @@ int test_do(const test_suite suites[], FILE *fp, test_results *results)
     for (cch = chunks; ; cch++) {
       if (!cch->name)
        goto skip_chunk;
-      if (strcmp(tok.buf, cch->name) == 0)
+      if (STRCMP(tok.buf, ==, cch->name))
        break;
     }
 
@@ -479,7 +480,7 @@ void test_run(int argc, char *argv[],
        if (i >= argc - 1)
          break;
        p = argv[++i];
-       if (strcmp(p, "--") == 0) {
+       if (STRCMP(p, ==, "--")) {
          i++;
          break;
        }
index 2681cd32e456c6f621f96862ea1fac993f21d324..e06bf7bd2ce09fecbe7e3447184f831f15334ef2 100644 (file)
@@ -38,6 +38,7 @@
 /* --- Local headers --- */
 
 #include "dstr.h"
+#include "macros.h"
 #include "quis.h"
 #include "trace.h"
 
@@ -132,7 +133,7 @@ void trace_block(unsigned l, const char *s, const void *b, size_t sz)
     dstr_puts(&d, ": ");
     for (i = 0; i < 8; i++) {
       if (i < sz)
-       dstr_putc(&d, isprint(p[i]) ? p[i] : '.');
+       dstr_putc(&d, ISPRINT(p[i]) ? p[i] : '.');
       else
        dstr_putc(&d, '*');
     }
index 78d82bdbe04f80808967ac142ad51a15dcd90623..bbb8b02361bb91d7ea889c26db7af5a778826dca 100644 (file)
@@ -31,6 +31,7 @@
 #include <string.h>
 #include <stdlib.h>
 
+#include "macros.h"
 #include "report.h"
 #include "trace.h"
 
@@ -57,7 +58,7 @@ unsigned traceopt(const trace_opt *t, const char *p,
 
   /* --- Dump out help text --- */
 
-  if (!p || !strcmp(p, "?")) {
+  if (!p || STRCMP(p, ==, "?")) {
     const trace_opt *tt;
     puts("Trace options:");
     for (tt = t; tt->ch; tt++) {
index 98ab23861629d91f2e4025e194bf29a942d46839..2d17fa6ab9d2094191c6f40df9150da0338cfd39 100644 (file)
@@ -6,6 +6,25 @@ macros \- useful macros
 .\" @STR
 .\" @GLUE
 .\" @STATIC_ASSERT
+.\" @ISALNUM
+.\" @ISALPHA
+.\" @ISASCII
+.\" @ISBLANK
+.\" @ISCNTRL
+.\" @ISDIGIT
+.\" @ISGRAPH
+.\" @ISLOWER
+.\" @ISPRINT
+.\" @ISPUNCT
+.\" @ISSPACE
+.\" @ISUPPER
+.\" @ISXDIGIT
+.\" @TOASCII
+.\" @TOLOWER
+.\" @TOUPPER
+.\" @MEMCMP
+.\" @STRCMP
+.\" @STRNCMP
 .\" @DISCARD
 .\" @IGNORE
 .\" @DEPRECATED
@@ -27,6 +46,27 @@ macros \- useful macros
 .BI "GLUE(" tokens\fR... ", " tokens\fR... ")"
 .BI "STATIC_ASSERT(" cond ", " msg ");"
 
+.BI "ISALNUM(int " ch ");"
+.BI "ISALPHA(int " ch ");"
+.BI "ISASCII(int " ch ");"
+.BI "ISBLANK(int " ch ");"
+.BI "ISCNTRL(int " ch ");"
+.BI "ISDIGIT(int " ch ");"
+.BI "ISGRAPH(int " ch ");"
+.BI "ISLOWER(int " ch ");"
+.BI "ISPRINT(int " ch ");"
+.BI "ISPUNCT(int " ch ");"
+.BI "ISSPACE(int " ch ");"
+.BI "ISUPPER(int " ch ");"
+.BI "ISXDIGIT(int " ch ");"
+.BI "TOASCII(int " ch ");"
+.BI "TOLOWER(int " ch ");"
+.BI "TOUPPER(int " ch ");"
+
+.BI "MEMCMP(const void *" x ", " op ", const void *" y ", size_t " n ");"
+.BI "STRCMP(const char *" x ", " op ", const char *" y ");"
+.BI "STRNCMP(const char *" x ", " op ", const char *" y ", size_t " n ");"
+
 .BI "void DISCARD(" scalar ");"
 .BI "void IGNORE(" variable ");"
 
@@ -78,6 +118,40 @@ falls back to a somewhat ugly hack which currently ignores the
 .IR msg .
 .PP
 The
+.BR IS ...\&
+and
+.BR TO ...\&
+macros are wrappers around the corresponding standard
+.B <ctype.h>
+macros with the corresponding lowercase names.  They take care of
+forcing the character argument
+.I ch
+to
+.BR "unsigned char" :
+this conversion is necessary on platforms with signed
+.B char
+to avoid passing negative values into the standard macros.
+.PP
+The
+.BR MEMCMP ,
+.BR STRCMP ,
+and
+.B STRNCMP
+macros are wrappers around the standard
+.B <string.h>
+functions with the corresponding lowercase names.  They take an
+additional argument
+.I op
+which is a equality or ordering operator (e.g.,
+.B ==
+or
+.BR > )
+inserted between the two operands.  The standard functions return a
+false value if and only if the operands are equal, which is
+counterintuitive and leads to mistakes; requiring an explicit relational
+operator should reduce the number of such mistakes.
+.PP
+The
 .B DISCARD
 macro discards its argument, which must be of some scalar type.  This
 can be useful in muffling warnings about ignoring return codes in cases
index 9e27a4813a4b3f8997e2ba85784d587023d87778..a5263e19ed319ef09d795284a52370706450e28b 100644 (file)
        IGNORABLE extern char static_assert_failed[2*!!(cond) - 1]
 #endif
 
+/*----- String and character hacks ----------------------------------------*/
+
+#define CTYPE_HACK(func, ch) (func((unsigned char)(ch)))
+
+#define ISALNUM(ch) CTYPE_HACK(isalnum, ch)
+#define ISALPHA(ch) CTYPE_HACK(isalpha, ch)
+#define ISASCII(ch) CTYPE_HACK(isascii, ch)
+#define ISBLANK(ch) CTYPE_HACK(isblank, ch)
+#define ISCNTRL(ch) CTYPE_HACK(iscntrl, ch)
+#define ISDIGIT(ch) CTYPE_HACK(isdigit, ch)
+#define ISGRAPH(ch) CTYPE_HACK(isgraph, ch)
+#define ISLOWER(ch) CTYPE_HACK(islower, ch)
+#define ISPRINT(ch) CTYPE_HACK(isprint, ch)
+#define ISPUNCT(ch) CTYPE_HACK(ispunct, ch)
+#define ISSPACE(ch) CTYPE_HACK(isspace, ch)
+#define ISUPPER(ch) CTYPE_HACK(isupper, ch)
+#define ISXDIGIT(ch) CTYPE_HACK(isxdigit, ch)
+
+#define TOASCII(ch) CTYPE_HACK(toascii, ch)
+#define TOLOWER(ch) CTYPE_HACK(tolower, ch)
+#define TOUPPER(ch) CTYPE_HACK(toupper, ch)
+
+#define MEMCMP(x, op, y, n) (memcmp((x), (y), (n)) op 0)
+#define STRCMP(x, op, y) (strcmp((x), (y)) op 0)
+#define STRNCMP(x, op, y, n) (strncmp((x), (y), (n)) op 0)
+
 /*----- Compiler diagnostics ----------------------------------------------*/
 
 /* --- Compiler-specific definitions --- */
index 51ca3236d5af3a63dee27fac3f8f45d2960d9a6a..e7598284564c9f85382d6915e9a7a1f22d93dbcb 100644 (file)
@@ -32,6 +32,7 @@
 #include <stdlib.h>
 #include <string.h>
 
+#include "macros.h"
 #include "str.h"
 
 /*----- Main code ---------------------------------------------------------*/
@@ -58,7 +59,7 @@ char *str_qword(char **pp, unsigned f)
 
   if (!p)
     return (0);
-  while (isspace((unsigned char)*p))
+  while (ISSPACE(*p))
     p++;
   if (!*p) {
     *pp = 0;
@@ -83,8 +84,8 @@ char *str_qword(char **pp, unsigned f)
          *qq++ = *q;
        break;
       default:
-       if (isspace((unsigned char)*q)) {
-         do q++; while (*q && isspace((unsigned char)*q));
+       if (ISSPACE(*q)) {
+         do q++; while (*q && ISSPACE(*q));
          goto done;
        } else if (!(f & STRF_QUOTE))
          goto stdchar;
@@ -312,7 +313,7 @@ void str_sanitize(char *d, const char *p, size_t sz)
   sz--;
   while (*p && sz) {
     int ch = *p++;
-    if (!isgraph((unsigned char)ch))
+    if (!ISGRAPH(ch))
       ch = '_';
     *d++ = ch;
     sz--;
index 3556916be2f7f8ea4833eaa2e4ac092c40d525bd..e8bf9ae473d56c173f8ff49238ca2213fd012a38 100644 (file)
@@ -30,6 +30,7 @@
 #include <ctype.h>
 #include <string.h>
 
+#include "macros.h"
 #include "versioncmp.h"
 
 /*----- Main code ---------------------------------------------------------*/
@@ -79,7 +80,7 @@ static int vint(const char **vv, const char *vl)
 
   while (v < vl) {
     ch = *v;
-    if (!isdigit((unsigned char)ch))
+    if (!ISDIGIT(ch))
       break;
     v++;
     n = n * 10 + (ch - '0');
@@ -96,7 +97,7 @@ static const char *vchr(const char **vv, const char *vl)
 
   while (v < vl) {
     ch = *v;
-    if (isdigit((unsigned char)ch))
+    if (ISDIGIT(ch))
       break;
     v++;
   }
@@ -124,12 +125,12 @@ static int vcmp(const char *va, const char *val,
     pa = vchr(&va, val); pb = vchr(&vb, vbl);
     for (;;) {
       if (pa == va) ia = 1;
-      else if (isalpha((unsigned char)*pa)) ia = 2;
+      else if (ISALPHA(*pa)) ia = 2;
       else if (*pa == '~') ia = 0;
       else ia = 3;
 
       if (pb == vb) ib = 1;
-      else if (isalpha((unsigned char)*pb)) ib = 2;
+      else if (ISALPHA(*pb)) ib = 2;
       else if (*pb == '~') ib = 0;
       else ib = 3;