]> The Tcpdump Group git mirrors - tcpdump/blobdiff - util-print.c
Use more the ND_TTEST_1() macro
[tcpdump] / util-print.c
index 2c3eb6597feef9ab593cb8c492ed04ac0521c2e6..58efc4b4b5a6dcc2c579701601284e69a0bf5198 100644 (file)
@@ -21,7 +21,7 @@
 
 /*
  * txtproto_print() derived from original code by Hannes Gredler
- * (hannes@juniper.net):
+ * (hannes@gredler.at):
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that: (1) source code
 #include "config.h"
 #endif
 
-#include <tcpdump-stdinc.h>
+#include <netdissect-stdinc.h>
 
 #include <sys/stat.h>
 
 #ifdef HAVE_FCNTL_H
 #include <fcntl.h>
 #endif
+#include <ctype.h>
 #include <stdio.h>
 #include <stdarg.h>
 #include <stdlib.h>
 #include <string.h>
 
-#include "interface.h"
+#include "netdissect.h"
+#include "extract.h"
+#include "ascii_strcasecmp.h"
+#include "timeval-operations.h"
 
 int32_t thiszone;              /* seconds offset from gmt to local time */
+/* invalid string to print '(invalid)' for malformed or corrupted packets */
+const char istr[] = " (invalid)";
 
 /*
- * Print out a null-terminated filename (or other ascii string).
+ * timestamp display buffer size, the biggest size of both formats is needed
+ * sizeof("0000000000.000000000") > sizeof("00:00:00.000000000")
+ */
+#define TS_BUF_SIZE sizeof("0000000000.000000000")
+
+#define TOKBUFSIZE 128
+
+/*
+ * Print out a character, filtering out the non-printable ones
+ */
+void
+fn_print_char(netdissect_options *ndo, u_char c)
+{
+       if (!ND_ISASCII(c)) {
+               c = ND_TOASCII(c);
+               ND_PRINT((ndo, "M-"));
+       }
+       if (!ND_ISPRINT(c)) {
+               c ^= 0x40;      /* DEL to ?, others to alpha */
+               ND_PRINT((ndo, "^"));
+       }
+       ND_PRINT((ndo, "%c", c));
+}
+
+/*
+ * Print out a null-terminated filename (or other ASCII string).
  * If ep is NULL, assume no truncation check is needed.
  * Return true if truncated.
+ * Stop at ep (if given) or before the null char, whichever is first.
  */
 int
 fn_print(netdissect_options *ndo,
-         register const u_char *s, register const u_char *ep)
+         const u_char *s, const u_char *ep)
 {
-       register int ret;
-       register u_char c;
+       int ret;
+       u_char c;
 
        ret = 1;                        /* assume truncated */
        while (ep == NULL || s < ep) {
@@ -88,15 +120,66 @@ fn_print(netdissect_options *ndo,
 }
 
 /*
- * Print out a counted filename (or other ascii string).
+ * Print out a null-terminated filename (or other ASCII string) from
+ * a fixed-length buffer.
+ * If ep is NULL, assume no truncation check is needed.
+ * Return the number of bytes of string processed, including the
+ * terminating null, if not truncated.  Return 0 if truncated.
+ */
+u_int
+fn_printztn(netdissect_options *ndo,
+         const u_char *s, u_int n, const u_char *ep)
+{
+       u_int bytes;
+       u_char c;
+
+       bytes = 0;
+       for (;;) {
+               if (n == 0 || (ep != NULL && s >= ep)) {
+                       /*
+                        * Truncated.  This includes "no null before we
+                        * got to the end of the fixed-length buffer".
+                        *
+                        * XXX - BOOTP says "null-terminated", which
+                        * means the maximum length of the string, in
+                        * bytes, is 1 less than the size of the buffer,
+                        * as there must always be a terminating null.
+                        */
+                       bytes = 0;
+                       break;
+               }
+
+               c = *s++;
+               bytes++;
+               n--;
+               if (c == '\0') {
+                       /* End of string */
+                       break;
+               }
+               if (!ND_ISASCII(c)) {
+                       c = ND_TOASCII(c);
+                       ND_PRINT((ndo, "M-"));
+               }
+               if (!ND_ISPRINT(c)) {
+                       c ^= 0x40;      /* DEL to ?, others to alpha */
+                       ND_PRINT((ndo, "^"));
+               }
+               ND_PRINT((ndo, "%c", c));
+       }
+       return(bytes);
+}
+
+/*
+ * Print out a counted filename (or other ASCII string).
  * If ep is NULL, assume no truncation check is needed.
  * Return true if truncated.
+ * Stop at ep (if given) or after n bytes, whichever is first.
  */
 int
 fn_printn(netdissect_options *ndo,
-          register const u_char *s, register u_int n, register const u_char *ep)
+          const u_char *s, u_int n, const u_char *ep)
 {
-       register u_char c;
+       u_char c;
 
        while (n > 0 && (ep == NULL || s < ep)) {
                n--;
@@ -115,17 +198,19 @@ fn_printn(netdissect_options *ndo,
 }
 
 /*
- * Print out a null-padded filename (or other ascii string).
+ * Print out a null-padded filename (or other ASCII string).
  * If ep is NULL, assume no truncation check is needed.
  * Return true if truncated.
+ * Stop at ep (if given) or after n bytes or before the null char,
+ * whichever is first.
  */
 int
 fn_printzp(netdissect_options *ndo,
-           register const u_char *s, register u_int n,
-           register const u_char *ep)
+           const u_char *s, u_int n,
+           const u_char *ep)
 {
-       register int ret;
-       register u_char c;
+       int ret;
+       u_char c;
 
        ret = 1;                        /* assume truncated */
        while (n > 0 && (ep == NULL || s < ep)) {
@@ -156,9 +241,8 @@ ts_format(netdissect_options *ndo
 #ifndef HAVE_PCAP_SET_TSTAMP_PRECISION
 _U_
 #endif
-, int sec, int usec)
+, int sec, int usec, char *buf)
 {
-       static char buf[sizeof("00:00:00.000000000")];
        const char *format;
 
 #ifdef HAVE_PCAP_SET_TSTAMP_PRECISION
@@ -173,75 +257,123 @@ _U_
                break;
 
        default:
-               format = "%02d:%02d:%02d.{unknown precision}";
+               format = "%02d:%02d:%02d.{unknown}";
                break;
        }
 #else
        format = "%02d:%02d:%02d.%06u";
 #endif
 
-       snprintf(buf, sizeof(buf), format,
+       snprintf(buf, TS_BUF_SIZE, format,
                  sec / 3600, (sec % 3600) / 60, sec % 60, usec);
 
         return buf;
 }
 
+/*
+ * Format the timestamp - Unix timeval style
+ */
+static char *
+ts_unix_format(netdissect_options *ndo
+#ifndef HAVE_PCAP_SET_TSTAMP_PRECISION
+_U_
+#endif
+, int sec, int usec, char *buf)
+{
+       const char *format;
+
+#ifdef HAVE_PCAP_SET_TSTAMP_PRECISION
+       switch (ndo->ndo_tstamp_precision) {
+
+       case PCAP_TSTAMP_PRECISION_MICRO:
+               format = "%u.%06u";
+               break;
+
+       case PCAP_TSTAMP_PRECISION_NANO:
+               format = "%u.%09u";
+               break;
+
+       default:
+               format = "%u.{unknown}";
+               break;
+       }
+#else
+       format = "%u.%06u";
+#endif
+
+       snprintf(buf, TS_BUF_SIZE, format,
+                (unsigned)sec, (unsigned)usec);
+
+       return buf;
+}
+
 /*
  * Print the timestamp
  */
 void
 ts_print(netdissect_options *ndo,
-         register const struct timeval *tvp)
+         const struct timeval *tvp)
 {
-       register int s;
+       int s;
        struct tm *tm;
        time_t Time;
-       static unsigned b_sec;
-       static unsigned b_usec;
-       int d_usec;
-       int d_sec;
+       char buf[TS_BUF_SIZE];
+       static struct timeval tv_ref;
+       struct timeval tv_result;
+       int negative_offset;
+       int nano_prec;
 
        switch (ndo->ndo_tflag) {
 
        case 0: /* Default */
                s = (tvp->tv_sec + thiszone) % 86400;
-               ND_PRINT((ndo, "%s ", ts_format(ndo, s, tvp->tv_usec)));
+               ND_PRINT((ndo, "%s ", ts_format(ndo, s, tvp->tv_usec, buf)));
                break;
 
        case 1: /* No time stamp */
                break;
 
        case 2: /* Unix timeval style */
-               ND_PRINT((ndo, "%u.%06u ",
-                            (unsigned)tvp->tv_sec,
-                            (unsigned)tvp->tv_usec));
+               ND_PRINT((ndo, "%s ", ts_unix_format(ndo,
+                         tvp->tv_sec, tvp->tv_usec, buf)));
                break;
 
-       case 3: /* Microseconds since previous packet */
-        case 5: /* Microseconds since first packet */
-               if (b_sec == 0) {
-                        /* init timestamp for first packet */
-                        b_usec = tvp->tv_usec;
-                        b_sec = tvp->tv_sec;
-                }
+       case 3: /* Microseconds/nanoseconds since previous packet */
+        case 5: /* Microseconds/nanoseconds since first packet */
+#ifdef HAVE_PCAP_SET_TSTAMP_PRECISION
+               switch (ndo->ndo_tstamp_precision) {
+               case PCAP_TSTAMP_PRECISION_MICRO:
+                       nano_prec = 0;
+                       break;
+               case PCAP_TSTAMP_PRECISION_NANO:
+                       nano_prec = 1;
+                       break;
+               default:
+                       nano_prec = 0;
+                       break;
+               }
+#else
+               nano_prec = 0;
+#endif
+               if (!(netdissect_timevalisset(&tv_ref)))
+                       tv_ref = *tvp; /* set timestamp for first packet */
 
-                d_usec = tvp->tv_usec - b_usec;
-                d_sec = tvp->tv_sec - b_sec;
+               negative_offset = netdissect_timevalcmp(tvp, &tv_ref, <);
+               if (negative_offset)
+                       netdissect_timevalsub(&tv_ref, tvp, &tv_result, nano_prec);
+               else
+                       netdissect_timevalsub(tvp, &tv_ref, &tv_result, nano_prec);
 
-                while (d_usec < 0) {
-                    d_usec += 1000000;
-                    d_sec--;
-                }
+               ND_PRINT((ndo, (negative_offset ? "-" : " ")));
 
-                ND_PRINT((ndo, "%s ", ts_format(ndo, d_sec, d_usec)));
+               ND_PRINT((ndo, "%s ", ts_format(ndo,
+                         tv_result.tv_sec, tv_result.tv_usec, buf)));
 
-                if (ndo->ndo_tflag == 3) { /* set timestamp for last packet */
-                    b_sec = tvp->tv_sec;
-                    b_usec = tvp->tv_usec;
-                }
+                if (ndo->ndo_tflag == 3)
+                       tv_ref = *tvp; /* set timestamp for previous packet */
                break;
 
-       case 4: /* Default + Date*/
+       case 4: /* Default + Date */
                s = (tvp->tv_sec + thiszone) % 86400;
                Time = (tvp->tv_sec + thiszone) - s;
                tm = gmtime (&Time);
@@ -250,33 +382,29 @@ ts_print(netdissect_options *ndo,
                else
                        ND_PRINT((ndo, "%04d-%02d-%02d %s ",
                                tm->tm_year+1900, tm->tm_mon+1, tm->tm_mday,
-                               ts_format(ndo, s, tvp->tv_usec)));
+                               ts_format(ndo, s, tvp->tv_usec, buf)));
                break;
        }
 }
 
 /*
- * Print a relative number of seconds (e.g. hold time, prune timer)
+ * Print an unsigned relative number of seconds (e.g. hold time, prune timer)
  * in the form 5m1s.  This does no truncation, so 32230861 seconds
  * is represented as 1y1w1d1h1m1s.
  */
 void
-relts_print(netdissect_options *ndo,
-            int secs)
+unsigned_relts_print(netdissect_options *ndo,
+                     uint32_t secs)
 {
        static const char *lengths[] = {"y", "w", "d", "h", "m", "s"};
-       static const int seconds[] = {31536000, 604800, 86400, 3600, 60, 1};
+       static const u_int seconds[] = {31536000, 604800, 86400, 3600, 60, 1};
        const char **l = lengths;
-       const int *s = seconds;
+       const u_int *s = seconds;
 
        if (secs == 0) {
                ND_PRINT((ndo, "0s"));
                return;
        }
-       if (secs < 0) {
-               ND_PRINT((ndo, "-"));
-               secs = -secs;
-       }
        while (secs > 0) {
                if (secs >= *s) {
                        ND_PRINT((ndo, "%d%s", secs / *s, *l));
@@ -287,6 +415,42 @@ relts_print(netdissect_options *ndo,
        }
 }
 
+/*
+ * Print a signed relative number of seconds (e.g. hold time, prune timer)
+ * in the form 5m1s.  This does no truncation, so 32230861 seconds
+ * is represented as 1y1w1d1h1m1s.
+ */
+void
+signed_relts_print(netdissect_options *ndo,
+                   int32_t secs)
+{
+       if (secs < 0) {
+               ND_PRINT((ndo, "-"));
+               if (secs == INT32_MIN) {
+                       /*
+                        * -2^31; you can't fit its absolute value into
+                        * a 32-bit signed integer.
+                        *
+                        * Just directly pass said absolute value to
+                        * unsigned_relts_print() directly.
+                        *
+                        * (XXX - does ISO C guarantee that -(-2^n),
+                        * when calculated and cast to an n-bit unsigned
+                        * integer type, will have the value 2^n?)
+                        */
+                       unsigned_relts_print(ndo, 2147483648U);
+               } else {
+                       /*
+                        * We now know -secs will fit into an int32_t;
+                        * negate it and pass that to unsigned_relts_print().
+                        */
+                       unsigned_relts_print(ndo, -secs);
+               }
+               return;
+       }
+       unsigned_relts_print(ndo, secs);
+}
+
 /*
  *  this is a generic routine for printing unknown data;
  *  we pass on the linefeed plus indentation string to
@@ -316,8 +480,8 @@ print_unknown_data(netdissect_options *ndo, const u_char *cp,const char *ident,i
  * Convert a token value to a string; use "fmt" if not found.
  */
 const char *
-tok2strbuf(register const struct tok *lp, register const char *fmt,
-          register u_int v, char *buf, size_t bufsize)
+tok2strbuf(const struct tok *lp, const char *fmt,
+          u_int v, char *buf, size_t bufsize)
 {
        if (lp != NULL) {
                while (lp->s != NULL) {
@@ -335,12 +499,14 @@ tok2strbuf(register const struct tok *lp, register const char *fmt,
 
 /*
  * Convert a token value to a string; use "fmt" if not found.
+ * Uses tok2strbuf() on one of four local static buffers of size TOKBUFSIZE
+ * in round-robin fashion.
  */
 const char *
-tok2str(register const struct tok *lp, register const char *fmt,
-       register u_int v)
+tok2str(const struct tok *lp, const char *fmt,
+       u_int v)
 {
-       static char buf[4][128];
+       static char buf[4][TOKBUFSIZE];
        static int idx = 0;
        char *ret;
 
@@ -355,13 +521,14 @@ tok2str(register const struct tok *lp, register const char *fmt,
  * if the s field is positive.
  */
 static char *
-bittok2str_internal(register const struct tok *lp, register const char *fmt,
-          register u_int v, const char *sep)
+bittok2str_internal(const struct tok *lp, const char *fmt,
+          u_int v, const char *sep)
 {
-        static char buf[256]; /* our stringbuffer */
-        int buflen=0;
-        register u_int rotbit; /* this is the bit we rotate through all bitpositions */
-        register u_int tokval;
+        static char buf[1024+1]; /* our string buffer */
+        char *bufp = buf;
+        size_t space_left = sizeof(buf), string_size;
+        u_int rotbit; /* this is the bit we rotate through all bitpositions */
+        u_int tokval;
         const char * sepstr = "";
 
        while (lp != NULL && lp->s != NULL) {
@@ -374,8 +541,20 @@ bittok2str_internal(register const struct tok *lp, register const char *fmt,
                  */
                if (tokval == (v&rotbit)) {
                     /* ok we have found something */
-                    buflen+=snprintf(buf+buflen, sizeof(buf)-buflen, "%s%s",
-                                     sepstr, lp->s);
+                    if (space_left <= 1)
+                        return (buf); /* only enough room left for NUL, if that */
+                    string_size = strlcpy(bufp, sepstr, space_left);
+                    if (string_size >= space_left)
+                        return (buf);    /* we ran out of room */
+                    bufp += string_size;
+                    space_left -= string_size;
+                    if (space_left <= 1)
+                        return (buf); /* only enough room left for NUL, if that */
+                    string_size = strlcpy(bufp, lp->s, space_left);
+                    if (string_size >= space_left)
+                        return (buf);    /* we ran out of room */
+                    bufp += string_size;
+                    space_left -= string_size;
                     sepstr = sep;
                     break;
                 }
@@ -384,7 +563,7 @@ bittok2str_internal(register const struct tok *lp, register const char *fmt,
             lp++;
        }
 
-        if (buflen == 0)
+        if (bufp == buf)
             /* bummer - lets print the "unknown" message as advised in the fmt string if we got one */
             (void)snprintf(buf, sizeof(buf), fmt == NULL ? "#%08x" : fmt, v);
         return (buf);
@@ -395,8 +574,8 @@ bittok2str_internal(register const struct tok *lp, register const char *fmt,
  * this is useful for parsing bitfields, the output strings are not seperated.
  */
 char *
-bittok2str_nosep(register const struct tok *lp, register const char *fmt,
-          register u_int v)
+bittok2str_nosep(const struct tok *lp, const char *fmt,
+          u_int v)
 {
     return (bittok2str_internal(lp, fmt, v, ""));
 }
@@ -406,23 +585,23 @@ bittok2str_nosep(register const struct tok *lp, register const char *fmt,
  * this is useful for parsing bitfields, the output strings are comma seperated.
  */
 char *
-bittok2str(register const struct tok *lp, register const char *fmt,
-          register u_int v)
+bittok2str(const struct tok *lp, const char *fmt,
+          u_int v)
 {
     return (bittok2str_internal(lp, fmt, v, ", "));
 }
 
 /*
  * Convert a value to a string using an array; the macro
- * tok2strary() in <interface.h> is the public interface to
+ * tok2strary() in <netdissect.h> is the public interface to
  * this function and ensures that the second argument is
  * correct for bounds-checking.
  */
 const char *
-tok2strary_internal(register const char **lp, int n, register const char *fmt,
-       register int v)
+tok2strary_internal(const char **lp, int n, const char *fmt,
+       int v)
 {
-       static char buf[128];
+       static char buf[TOKBUFSIZE];
 
        if (v >= 0 && v < n && lp[v] != NULL)
                return lp[v];
@@ -463,7 +642,6 @@ mask2plen(uint32_t mask)
        return (prefix_len);
 }
 
-#ifdef INET6
 int
 mask62plen(const u_char *mask)
 {
@@ -490,7 +668,6 @@ mask62plen(const u_char *mask)
        }
        return (cidr_len);
 }
-#endif /* INET6 */
 
 /*
  * Routine to print out information for text-based protocols such as FTP,
@@ -514,7 +691,7 @@ fetch_token(netdissect_options *ndo, const u_char *pptr, u_int idx, u_int len,
        size_t toklen = 0;
 
        for (; idx < len; idx++) {
-               if (!ND_TTEST(*(pptr + idx))) {
+               if (!ND_TTEST_1(pptr + idx)) {
                        /* ran past end of captured data */
                        return (0);
                }
@@ -548,7 +725,7 @@ fetch_token(netdissect_options *ndo, const u_char *pptr, u_int idx, u_int len,
         * an end-of-line (CR or LF).
         */
        for (; idx < len; idx++) {
-               if (!ND_TTEST(*(pptr + idx))) {
+               if (!ND_TTEST_1(pptr + idx)) {
                        /* ran past end of captured data */
                        break;
                }
@@ -583,7 +760,7 @@ print_txt_line(netdissect_options *ndo, const char *protoname,
 
        startidx = idx;
        while (idx < len) {
-               ND_TCHECK(*(pptr+idx));
+               ND_TCHECK_1(pptr + idx);
                if (*(pptr+idx) == '\n') {
                        /*
                         * LF without CR; end of line.
@@ -599,7 +776,7 @@ print_txt_line(netdissect_options *ndo, const char *protoname,
                                /* not in this packet */
                                return (0);
                        }
-                       ND_TCHECK(*(pptr+idx+1));
+                       ND_TCHECK_1(pptr + idx + 1);
                        if (*(pptr+idx+1) == '\n') {
                                /*
                                 * CR-LF; end of line.
@@ -651,22 +828,29 @@ txtproto_print(netdissect_options *ndo, const u_char *pptr, u_int len,
        u_int idx, eol;
        u_char token[MAX_TOKEN+1];
        const char *cmd;
-       int is_reqresp = 0;
+       int print_this = 0;
        const char *pnp;
 
        if (cmds != NULL) {
                /*
                 * This protocol has more than just request and
                 * response lines; see whether this looks like a
-                * request or response.
+                * request or response and, if so, print it and,
+                * in verbose mode, print everything after it.
+                *
+                * This is for HTTP-like protocols, where we
+                * want to print requests and responses, but
+                * don't want to print continuations of request
+                * or response bodies in packets that don't
+                * contain the request or response line.
                 */
                idx = fetch_token(ndo, pptr, 0, len, token, sizeof(token));
                if (idx != 0) {
                        /* Is this a valid request name? */
                        while ((cmd = *cmds++) != NULL) {
-                               if (strcasecmp((const char *)token, cmd) == 0) {
+                               if (ascii_strcasecmp((const char *)token, cmd) == 0) {
                                        /* Yes. */
-                                       is_reqresp = 1;
+                                       print_this = 1;
                                        break;
                                }
                        }
@@ -688,28 +872,36 @@ txtproto_print(netdissect_options *ndo, const u_char *pptr, u_int len,
                                if (isdigit(token[0]) && isdigit(token[1]) &&
                                    isdigit(token[2]) && token[3] == '\0') {
                                        /* Yes. */
-                                       is_reqresp = 1;
+                                       print_this = 1;
                                }
                        }
                }
        } else {
                /*
-                * This protocol has only request and response lines
-                * (e.g., FTP, where all the data goes over a
-                * different connection); assume the payload is
-                * a request or response.
+                * Either:
+                *
+                * 1) This protocol has only request and response lines
+                *    (e.g., FTP, where all the data goes over a different
+                *    connection); assume the payload is a request or
+                *    response.
+                *
+                * or
+                *
+                * 2) This protocol is just text, so that we should
+                *    always, at minimum, print the first line and,
+                *    in verbose mode, print all lines.
                 */
-               is_reqresp = 1;
+               print_this = 1;
        }
 
        /* Capitalize the protocol name */
        for (pnp = protoname; *pnp != '\0'; pnp++)
-               ND_PRINT((ndo, "%c", toupper(*pnp)));
+               ND_PRINT((ndo, "%c", toupper((u_char)*pnp)));
 
-       if (is_reqresp) {
+       if (print_this) {
                /*
                 * In non-verbose mode, just print the protocol, followed
-                * by the first line as the request or response info.
+                * by the first line.
                 *
                 * In verbose mode, print lines as text until we run out
                 * of characters or see something that's not a
@@ -741,7 +933,7 @@ safeputs(netdissect_options *ndo,
 {
        u_int idx = 0;
 
-       while (*s && idx < maxlen) {
+       while (idx < maxlen && *s) {
                safeputchar(ndo, *s);
                idx++;
                s++;
@@ -755,11 +947,38 @@ safeputchar(netdissect_options *ndo,
        ND_PRINT((ndo, (c < 0x80 && ND_ISPRINT(c)) ? "%c" : "\\0x%02x", c));
 }
 
-#ifdef LBL_ALIGN
+#if (defined(__i386__) || defined(_M_IX86) || defined(__X86__) || defined(__x86_64__) || defined(_M_X64)) || \
+    (defined(__arm__) || defined(_M_ARM) || defined(__aarch64__)) || \
+    (defined(__m68k__) && (!defined(__mc68000__) && !defined(__mc68010__))) || \
+    (defined(__ppc__) || defined(__ppc64__) || defined(_M_PPC) || defined(_ARCH_PPC) || defined(_ARCH_PPC64)) || \
+    (defined(__s390__) || defined(__s390x__) || defined(__zarch__)) || \
+    defined(__vax__)
+/*
+ * The procesor natively handles unaligned loads, so just use memcpy()
+ * and memcmp(), to enable those optimizations.
+ *
+ * XXX - are those all the x86 tests we need?
+ * XXX - do we need to worry about ARMv1 through ARMv5, which didn't
+ * support unaligned loads, and, if so, do we need to worry about all
+ * of them, or just some of them, e.g. ARMv5?
+ * XXX - are those the only 68k tests we need not to generated
+ * unaligned accesses if the target is the 68000 or 68010?
+ * XXX - are there any tests we don't need, because some definitions are for
+ * compilers that also predefine the GCC symbols?
+ * XXX - do we need to test for both 32-bit and 64-bit versions of those
+ * architectures in all cases?
+ */
+#else
 /*
- * Some compilers try to optimize memcpy(), using the alignment constraint
- * on the argument pointer type.  by using this function, we try to avoid the
- * optimization.
+ * The processor doesn't natively handle unaligned loads,
+ * and the compiler might "helpfully" optimize memcpy()
+ * and memcmp(), when handed pointers that would normally
+ * be properly aligned, into sequences that assume proper
+ * alignment.
+ *
+ * Do copies and compares of possibly-unaligned data by
+ * calling routines that wrap memcpy() and memcmp(), to
+ * prevent that optimization.
  */
 void
 unaligned_memcpy(void *p, const void *q, size_t l)