{"thread":{"id":"2204","subject":"daemon.c broken on OpenBSD","startedAt":"2005-10-24T04:06:23Z","lastAt":"2005-10-25T23:40:59Z","messageCount":16,"participants":["Randal L. Schwartz","Junio C Hamano","Matthias Urlichs","Linus Torvalds","H. Peter Anvin","Morten Welinder"],"isPatch":false,"patchVersion":null,"patchTotal":null},"messages":[{"id":"10519","messageId":"867jc336f4.fsf@blue.stonehenge.com","threadId":"2204","inReplyTo":null,"subject":"daemon.c broken on OpenBSD","fromName":"Randal L. Schwartz","fromEmail":"merlyn@stonehenge.com","sentAt":"2005-10-24T04:06:23Z","receivedAt":"2005-10-24T04:06:23Z","isPatch":false,"sender":{"key":"merlyn@stonehenge.com","avatar":"https://gravatar.com/avatar/dc528d210743ff0333e6213f9ee7b33b23f1b7bc1f3c5a8c2d819074ecd7ab19?d=mp&s=160"},"body":"\nWow.\n\n    gcc -o daemon.o -c -g -O2 -Wall -I/usr/local/include -L/usr/local/lib -Dstrcasestr=gitstrcasestr -DNO_STRCASESTR=1 -DSHA1_HEADER='<openssl/sha.h>' daemon.c\n    In file included from /usr/include/sys/poll.h:54,\n                     from daemon.c:7:\n    /usr/include/ctype.h:67: error: syntax error before ']' token\n    /usr/include/ctype.h:68: error: syntax error before ']' token\n    /usr/include/ctype.h:70: error: syntax error before ']' token\n    /usr/include/ctype.h:75: error: syntax error before ']' token\n    /usr/include/ctype.h:78: error: syntax error before '(' token\n    /usr/include/ctype.h:79: error: syntax error before '(' token\n    /usr/include/ctype.h:93: error: syntax error before \"c\"\n    In file included from /usr/include/sys/poll.h:54,\n                     from daemon.c:7:\n    /usr/include/ctype.h:91:1: unterminated #if\n    /usr/include/ctype.h:40:1: unterminated #ifndef\n    In file included from daemon.c:7:\n    /usr/include/sys/poll.h:53:1: unterminated #ifndef\n    /usr/include/sys/poll.h:28:1: unterminated #ifndef\n    gmake: *** [daemon.o] Error 1\n\nApparently something in the early lines of daemon.c (before line 7)\nis defining something that breaks the core /usr/include/ctype.h.\n\nLines 66 to 68 of ctype.h look like:\n\n    #if defined(__GNUC__) || defined(_ANSI_LIBRARY) || defined(lint)\n    int\tisalnum(int);\n    int\tisalpha(int);\n\nIf that rings a bell, help me out here.  I'm guessing \"isalnum\" is getting\ndefined (wrongly).  Yeah, looks like in cache.h.  Why is this getting\ndefined?\n\n-- \nRandal L. Schwartz - Stonehenge Consulting Services, Inc. - +1 503 777 0095\n<merlyn@stonehenge.com> <URL:http://www.stonehenge.com/merlyn/>\nPerl/Unix/security consulting, Technical writing, Comedy, etc. etc.\nSee PerlTraining.Stonehenge.com for onsite and open-enrollment Perl training!\n"},{"id":"10520","messageId":"7v64rnsd83.fsf@assigned-by-dhcp.cox.net","threadId":"2204","inReplyTo":"867jc336f4.fsf@blue.stonehenge.com","subject":"Re: daemon.c broken on OpenBSD","fromName":"Junio C Hamano","fromEmail":"junkio@cox.net","sentAt":"2005-10-24T05:20:12Z","receivedAt":"2005-10-24T05:20:12Z","isPatch":false,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"merlyn@stonehenge.com (Randal L. Schwartz) writes:\n\n> Wow.\n>...\n> If that rings a bell, help me out here.  I'm guessing \"isalnum\" is getting\n> defined (wrongly).  Yeah, looks like in cache.h.  Why is this getting\n> defined?\n\nWow indeed.  It comes from this thread:\n\n\thttp://marc.theaimsgroup.com/?l=git&m=112917422812418&w=2\n\n\nMaybe something like this would help?\n\n ------------\n[PATCH] do not override standard ctype macros, but use our own.\n\n...since it can cause breakage in system supplied header files...\n\nSigned-off-by: Junio C Hamano <junkio@cox.net>\n\n---\n\n   It would be easier for *you* to grok if I say this patch is\n   essentially this ;-):\n\n\t$ git-ls-files |\n\txargs perl -i -p -e '\n\t\ts/\\bis(space|digit|alpha|alnum)\\b/is_$1/g;\n\t\ts/\\bto(lower|upper)\\b/to_$1/g;\n\t'\n\n   except that I did not touch gitk.\n\ndiff --git a/apply.c b/apply.c\nindex e5c0b7d..9608f92 100644\n--- a/apply.c\n+++ b/apply.c\n@@ -113,7 +113,7 @@ static unsigned long linelen(const char \n \n static int is_dev_null(const char *str)\n {\n-\treturn !memcmp(\"/dev/null\", str, 9) && isspace(str[9]);\n+\treturn !memcmp(\"/dev/null\", str, 9) && is_space(str[9]);\n }\n \n #define TERM_SPACE\t1\n@@ -167,7 +167,7 @@ static char * find_name(const char *line\n \tfor (;;) {\n \t\tchar c = *line;\n \n-\t\tif (isspace(c)) {\n+\t\tif (is_space(c)) {\n \t\t\tif (c == '\\n')\n \t\t\t\tbreak;\n \t\t\tif (name_terminate(start, line-start, c, terminate))\n@@ -447,7 +447,7 @@ static char *git_header_name(char *line,\n \t\t/* second points at one past closing dq of name.\n \t\t * find the second name.\n \t\t */\n-\t\twhile ((second < line + llen) && isspace(*second))\n+\t\twhile ((second < line + llen) && is_space(*second))\n \t\t\tsecond++;\n \n \t\tif (line + llen <= second)\n@@ -508,7 +508,7 @@ static char *git_header_name(char *line,\n \t\t\tlen = strlen(np);\n \t\t\tif (len < cp - name &&\n \t\t\t    !strncmp(np, name, len) &&\n-\t\t\t    isspace(name[len])) {\n+\t\t\t    is_space(name[len])) {\n \t\t\t\t/* Good */\n \t\t\t\tmemmove(sp, np, len + 1);\n \t\t\t\treturn sp;\n@@ -615,7 +615,7 @@ static int parse_num(const char *line, u\n {\n \tchar *ptr;\n \n-\tif (!isdigit(*line))\n+\tif (!is_digit(*line))\n \t\treturn 0;\n \t*p = strtoul(line, &ptr, 10);\n \treturn ptr - line;\ndiff --git a/cache.h b/cache.h\nindex d776016..3f6ff0d 100644\n--- a/cache.h\n+++ b/cache.h\n@@ -388,23 +388,17 @@ extern char git_default_email[MAX_GITNAM\n extern char git_default_name[MAX_GITNAME];\n \n /* Sane ctype - no locale, and works with signed chars */\n-#undef isspace\n-#undef isdigit\n-#undef isalpha\n-#undef isalnum\n-#undef tolower\n-#undef toupper\n extern unsigned char sane_ctype[256];\n #define GIT_SPACE 0x01\n #define GIT_DIGIT 0x02\n #define GIT_ALPHA 0x04\n #define sane_istest(x,mask) ((sane_ctype[(unsigned char)(x)] & (mask)) != 0)\n-#define isspace(x) sane_istest(x,GIT_SPACE)\n-#define isdigit(x) sane_istest(x,GIT_DIGIT)\n-#define isalpha(x) sane_istest(x,GIT_ALPHA)\n-#define isalnum(x) sane_istest(x,GIT_ALPHA | GIT_DIGIT)\n-#define tolower(x) sane_case((unsigned char)(x), 0x20)\n-#define toupper(x) sane_case((unsigned char)(x), 0)\n+#define is_space(x) sane_istest(x,GIT_SPACE)\n+#define is_digit(x) sane_istest(x,GIT_DIGIT)\n+#define is_alpha(x) sane_istest(x,GIT_ALPHA)\n+#define is_alnum(x) sane_istest(x,GIT_ALPHA | GIT_DIGIT)\n+#define to_lower(x) sane_case((unsigned char)(x), 0x20)\n+#define to_upper(x) sane_case((unsigned char)(x), 0)\n \n static inline int sane_case(int x, int high)\n {\ndiff --git a/commit.c b/commit.c\nindex 8f40318..4d094b5 100644\n--- a/commit.c\n+++ b/commit.c\n@@ -379,7 +379,7 @@ static int add_user_info(const char *wha\n \n static int is_empty_line(const char *line, int len)\n {\n-\twhile (len && isspace(line[len-1]))\n+\twhile (len && is_space(line[len-1]))\n \t\tlen--;\n \treturn !len;\n }\ndiff --git a/compat/strcasestr.c b/compat/strcasestr.c\nindex b96414d..d1a4253 100644\n--- a/compat/strcasestr.c\n+++ b/compat/strcasestr.c\n@@ -12,7 +12,7 @@ char *gitstrcasestr(const char *haystack\n \t\tfor (j = 0; j < nlen; j++) {\n \t\t\tunsigned char c1 = haystack[i+j];\n \t\t\tunsigned char c2 = needle[j];\n-\t\t\tif (toupper(c1) != toupper(c2))\n+\t\t\tif (to_upper(c1) != to_upper(c2))\n \t\t\t\tgoto next;\n \t\t}\n \t\treturn (char *) haystack + i;\ndiff --git a/config.c b/config.c\nindex 519fecf..24b017f 100644\n--- a/config.c\n+++ b/config.c\n@@ -40,7 +40,7 @@ static char *parse_value(void)\n \t\t}\n \t\tif (comment)\n \t\t\tcontinue;\n-\t\tif (isspace(c) && !quote) {\n+\t\tif (is_space(c) && !quote) {\n \t\t\tspace = 1;\n \t\t\tcontinue;\n \t\t}\n@@ -97,9 +97,9 @@ static int get_value(config_fn_t fn, cha\n \t\tc = get_next_char();\n \t\tif (c == EOF)\n \t\t\tbreak;\n-\t\tif (!isalnum(c))\n+\t\tif (!is_alnum(c))\n \t\t\tbreak;\n-\t\tname[len++] = tolower(c);\n+\t\tname[len++] = to_lower(c);\n \t\tif (len >= MAXNAME)\n \t\t\treturn -1;\n \t}\n@@ -128,11 +128,11 @@ static int get_base_var(char *name)\n \t\t\treturn -1;\n \t\tif (c == ']')\n \t\t\treturn baselen;\n-\t\tif (!isalnum(c))\n+\t\tif (!is_alnum(c))\n \t\t\treturn -1;\n \t\tif (baselen > MAXNAME / 2)\n \t\t\treturn -1;\n-\t\tname[baselen++] = tolower(c);\n+\t\tname[baselen++] = to_lower(c);\n \t}\n }\n \n@@ -151,7 +151,7 @@ static int git_parse_file(config_fn_t fn\n \t\t\tcomment = 0;\n \t\t\tcontinue;\n \t\t}\n-\t\tif (comment || isspace(c))\n+\t\tif (comment || is_space(c))\n \t\t\tcontinue;\n \t\tif (c == '#' || c == ';') {\n \t\t\tcomment = 1;\n@@ -165,9 +165,9 @@ static int git_parse_file(config_fn_t fn\n \t\t\tvar[baselen] = 0;\n \t\t\tcontinue;\n \t\t}\n-\t\tif (!isalpha(c))\n+\t\tif (!is_alpha(c))\n \t\t\tbreak;\n-\t\tvar[baselen] = tolower(c);\n+\t\tvar[baselen] = to_lower(c);\n \t\tif (get_value(fn, var, baselen+1) < 0)\n \t\t\tbreak;\n \t}\ndiff --git a/convert-objects.c b/convert-objects.c\nindex a892013..621c1bb 100644\n--- a/convert-objects.c\n+++ b/convert-objects.c\n@@ -166,7 +166,7 @@ static unsigned long parse_oldstyle_date\n \tconst char **fmt = formats;\n \n \tp = buffer;\n-\twhile (isspace(c = *buf))\n+\twhile (is_space(c = *buf))\n \t\tbuf++;\n \twhile ((c = *buf++) != '\\n')\n \t\t*p++ = c;\n@@ -181,7 +181,7 @@ static unsigned long parse_oldstyle_date\n \t\t\tbuf = next;\n \t\t} else {\n \t\t\tconst char **p = timezones;\n-\t\t\twhile (isspace(*buf))\n+\t\t\twhile (is_space(*buf))\n \t\t\t\tbuf++;\n \t\t\twhile (*p) {\n \t\t\t\tif (!memcmp(buf, *p, strlen(*p))) {\n@@ -217,7 +217,7 @@ static int convert_date_line(char *dst, \n \tdst += len;\n \n \t/* Is it already in new format? */\n-\tif (isdigit(*date)) {\n+\tif (is_digit(*date)) {\n \t\tint datelen = next - date;\n \t\tmemcpy(dst, date, datelen);\n \t\treturn len + datelen;\ndiff --git a/date.c b/date.c\nindex 63f5a09..340052d 100644\n--- a/date.c\n+++ b/date.c\n@@ -131,9 +131,9 @@ static int match_string(const char *date\n \tfor (i = 0; *date; date++, str++, i++) {\n \t\tif (*date == *str)\n \t\t\tcontinue;\n-\t\tif (toupper(*date) == toupper(*str))\n+\t\tif (to_upper(*date) == to_upper(*str))\n \t\t\tcontinue;\n-\t\tif (!isalnum(*date))\n+\t\tif (!is_alnum(*date))\n \t\t\tbreak;\n \t\treturn 0;\n \t}\n@@ -145,7 +145,7 @@ static int skip_alpha(const char *date)\n \tint i = 0;\n \tdo {\n \t\ti++;\n-\t} while (isalpha(date[i]));\n+\t} while (is_alpha(date[i]));\n \treturn i;\n }\n \n@@ -229,7 +229,7 @@ static int match_multi_number(unsigned l\n \n \tnum2 = strtol(end+1, &end, 10);\n \tnum3 = -1;\n-\tif (*end == c && isdigit(end[1]))\n+\tif (*end == c && is_digit(end[1]))\n \t\tnum3 = strtol(end+1, &end, 10);\n \n \t/* Time? Date? */\n@@ -295,7 +295,7 @@ static int match_digit(const char *date,\n \tcase ':':\n \tcase '/':\n \tcase '-':\n-\t\tif (isdigit(end[1])) {\n+\t\tif (is_digit(end[1])) {\n \t\t\tint match = match_multi_number(num, *end, date, end, tm);\n \t\t\tif (match)\n \t\t\t\treturn match;\n@@ -310,7 +310,7 @@ static int match_digit(const char *date,\n \tn = 0;\n \tdo {\n \t\tn++;\n-\t} while (isdigit(date[n]));\n+\t} while (is_digit(date[n]));\n \n \t/* Four-digit year or a timezone? */\n \tif (n == 4) {\n@@ -420,11 +420,11 @@ int parse_date(const char *date, char *r\n \t\tif (!c || c == '\\n')\n \t\t\tbreak;\n \n-\t\tif (isalpha(c))\n+\t\tif (is_alpha(c))\n \t\t\tmatch = match_alpha(date, &tm, &offset);\n-\t\telse if (isdigit(c))\n+\t\telse if (is_digit(c))\n \t\t\tmatch = match_digit(date, &tm, &offset, &tm_gmt);\n-\t\telse if ((c == '-' || c == '+') && isdigit(date[1]))\n+\t\telse if ((c == '-' || c == '+') && is_digit(date[1]))\n \t\t\tmatch = match_tz(date, &offset);\n \n \t\tif (!match) {\ndiff --git a/diff-tree.c b/diff-tree.c\nindex 382011a..f7b16eb 100644\n--- a/diff-tree.c\n+++ b/diff-tree.c\n@@ -137,7 +137,7 @@ static int diff_tree_stdin(char *line)\n \tline[len-1] = 0;\n \tif (get_sha1_hex(line, commit))\n \t\treturn -1;\n-\tif (isspace(line[40]) && !get_sha1_hex(line+41, parent)) {\n+\tif (is_space(line[40]) && !get_sha1_hex(line+41, parent)) {\n \t\tline[40] = 0;\n \t\tline[81] = 0;\n \t\tsprintf(this_header, \"%s (from %s)\\n\", line, line+41);\ndiff --git a/ident.c b/ident.c\nindex bc89e1d..0a3d735 100644\n--- a/ident.c\n+++ b/ident.c\n@@ -34,7 +34,7 @@ static void copy_gecos(struct passwd *w,\n \t\t}\n \t\tif (len + nlen < sz) {\n \t\t\t/* Sorry, Mr. McDonald... */\n-\t\t\t*dst++ = toupper(*w->pw_name);\n+\t\t\t*dst++ = to_upper(*w->pw_name);\n \t\t\tmemcpy(dst, w->pw_name + 1, nlen - 1);\n \t\t\tdst += nlen - 1;\n \t\t}\ndiff --git a/mailinfo.c b/mailinfo.c\nindex cb853df..3a06240 100644\n--- a/mailinfo.c\n+++ b/mailinfo.c\n@@ -6,9 +6,10 @@\n #include <stdio.h>\n #include <stdlib.h>\n #include <string.h>\n-#include <ctype.h>\n #include <iconv.h>\n \n+#include \"cache.h\"\n+\n #ifdef NO_STRCASESTR\n extern char *gitstrcasestr(const char *haystack, const char *needle);\n #endif\n@@ -61,7 +62,7 @@ static int handle_from(char *line)\n \t */\n \twhile (at > line) {\n \t\tchar c = at[-1];\n-\t\tif (isspace(c))\n+\t\tif (is_space(c))\n \t\t\tbreak;\n \t\tif (c == '<') {\n \t\t\tat[-1] = ' ';\n@@ -72,7 +73,7 @@ static int handle_from(char *line)\n \tdst = email;\n \tfor (;;) {\n \t\tunsigned char c = *at;\n-\t\tif (!c || c == '>' || isspace(c)) {\n+\t\tif (!c || c == '>' || is_space(c)) {\n \t\t\tif (c == '>')\n \t\t\t\t*at = ' ';\n \t\t\tbreak;\n@@ -90,7 +91,7 @@ static int handle_from(char *line)\n \tat = line + strlen(line);\n \twhile (at > line) {\n \t\tunsigned char c = *--at;\n-\t\tif (!isspace(c)) {\n+\t\tif (!is_space(c)) {\n \t\t\tat[(c == ')') ? 0 : 1] = 0;\n \t\t\tbreak;\n \t\t}\n@@ -99,7 +100,7 @@ static int handle_from(char *line)\n \tat = line;\n \tfor (;;) {\n \t\tunsigned char c = *at;\n-\t\tif (!c || !isspace(c)) {\n+\t\tif (!c || !is_space(c)) {\n \t\t\tif (c == '(')\n \t\t\t\tat++;\n \t\t\tbreak;\n@@ -164,7 +165,7 @@ static int handle_subcontent_type(char *\n \tif (*charset) {\n \t\tint i, c;\n \t\tfor (i = 0; (c = charset[i]) != 0; i++)\n-\t\t\tcharset[i] = tolower(c);\n+\t\t\tcharset[i] = to_lower(c);\n \t}\n \treturn 0;\n }\n@@ -199,7 +200,7 @@ static int is_multipart_boundary(const c\n static int eatspace(char *line)\n {\n \tint len = strlen(line);\n-\twhile (len > 0 && isspace(line[len-1]))\n+\twhile (len > 0 && is_space(line[len-1]))\n \t\tline[--len] = 0;\n \treturn len;\n }\n@@ -211,27 +212,27 @@ static int eatspace(char *line)\n /* First lines of body can have From:, Date:, and Subject: */\n static int handle_inbody_header(int *seen, char *line)\n {\n-\tif (!memcmp(\"From:\", line, 5) && isspace(line[5])) {\n+\tif (!memcmp(\"From:\", line, 5) && is_space(line[5])) {\n \t\tif (!(*seen & SEEN_FROM) && handle_from(line+6)) {\n \t\t\t*seen |= SEEN_FROM;\n \t\t\treturn 1;\n \t\t}\n \t}\n-\tif (!memcmp(\"Date:\", line, 5) && isspace(line[5])) {\n+\tif (!memcmp(\"Date:\", line, 5) && is_space(line[5])) {\n \t\tif (!(*seen & SEEN_DATE)) {\n \t\t\thandle_date(line+6);\n \t\t\t*seen |= SEEN_DATE;\n \t\t\treturn 1;\n \t\t}\n \t}\n-\tif (!memcmp(\"Subject:\", line, 8) && isspace(line[8])) {\n+\tif (!memcmp(\"Subject:\", line, 8) && is_space(line[8])) {\n \t\tif (!(*seen & SEEN_SUBJECT)) {\n \t\t\thandle_subject(line+9);\n \t\t\t*seen |= SEEN_SUBJECT;\n \t\t\treturn 1;\n \t\t}\n \t}\n-\tif (!memcmp(\"[PATCH]\", line, 7) && isspace(line[7])) {\n+\tif (!memcmp(\"[PATCH]\", line, 7) && is_space(line[7])) {\n \t\tif (!(*seen & SEEN_SUBJECT)) {\n \t\t\thandle_subject(line);\n \t\t\t*seen |= SEEN_SUBJECT;\n@@ -282,10 +283,10 @@ static void cleanup_space(char *buf)\n \tunsigned char c;\n \twhile ((c = *buf) != 0) {\n \t\tbuf++;\n-\t\tif (isspace(c)) {\n+\t\tif (is_space(c)) {\n \t\t\tbuf[-1] = ' ';\n \t\t\tc = *buf;\n-\t\t\twhile (isspace(c)) {\n+\t\t\twhile (is_space(c)) {\n \t\t\t\tint len = strlen(buf);\n \t\t\t\tmemmove(buf, buf+1, len);\n \t\t\t\tc = *buf;\n@@ -312,7 +313,7 @@ static void check_header(char *line, int\n \tfor (i = 0; header[i].name; i++) {\n \t\tint len = header[i].namelen;\n \t\tif (!strncasecmp(line, header[i].name, len) &&\n-\t\t    line[len] == ':' && isspace(line[len + 1])) {\n+\t\t    line[len] == ':' && is_space(line[len + 1])) {\n \t\t\theader[i].func(line + len + 2);\n \t\t\tbreak;\n \t\t}\n@@ -491,7 +492,7 @@ static void decode_header_bq(char *it)\n \t\tif (!cp)\n \t\t\treturn; /* no munging */\n \t\tfor (sp = ep; sp < cp; sp++)\n-\t\t\tcharset_q[sp - ep] = tolower(*sp);\n+\t\t\tcharset_q[sp - ep] = to_lower(*sp);\n \t\tcharset_q[cp - ep] = 0;\n \t\tencoding = cp[1];\n \t\tif (!encoding || cp[2] != '?')\n@@ -499,7 +500,7 @@ static void decode_header_bq(char *it)\n \t\tep = strstr(cp + 3, \"?=\");\n \t\tif (!ep)\n \t\t\treturn; /* no munging */\n-\t\tswitch (tolower(encoding)) {\n+\t\tswitch (to_lower(encoding)) {\n \t\tdefault:\n \t\t\treturn; /* no munging */\n \t\tcase 'b':\n@@ -709,11 +710,6 @@ static void handle_body(void)\n static const char mailinfo_usage[] =\n \t\"git-mailinfo [-k] [-u] msg patch <mail >info\";\n \n-static void usage(void) {\n-\tfprintf(stderr, \"%s\\n\", mailinfo_usage);\n-\texit(1);\n-}\n-\n int main(int argc, char **argv)\n {\n \twhile (1 < argc && argv[1][0] == '-') {\n@@ -722,12 +718,12 @@ int main(int argc, char **argv)\n \t\telse if (!strcmp(argv[1], \"-u\"))\n \t\t\tmetainfo_utf8 = 1;\n \t\telse\n-\t\t\tusage();\n+\t\t\tusage(mailinfo_usage);\n \t\targc--; argv++;\n \t}\n \n \tif (argc != 3)\n-\t\tusage();\n+\t\tusage(mailinfo_usage);\n \tcmitmsg = fopen(argv[1], \"w\");\n \tif (!cmitmsg) {\n \t\tperror(argv[1]);\ndiff --git a/mailsplit.c b/mailsplit.c\nindex 189f4ed..de9fb2b 100644\n--- a/mailsplit.c\n+++ b/mailsplit.c\n@@ -33,11 +33,11 @@ static int is_from_line(const char *line\n \t\t\tbreak;\n \t}\n \n-\tif (!isdigit(colon[-4]) ||\n-\t    !isdigit(colon[-2]) ||\n-\t    !isdigit(colon[-1]) ||\n-\t    !isdigit(colon[ 1]) ||\n-\t    !isdigit(colon[ 2]))\n+\tif (!is_digit(colon[-4]) ||\n+\t    !is_digit(colon[-2]) ||\n+\t    !is_digit(colon[-1]) ||\n+\t    !is_digit(colon[ 1]) ||\n+\t    !is_digit(colon[ 2]))\n \t\treturn 0;\n \n \t/* year */\ndiff --git a/pack-objects.c b/pack-objects.c\nindex b3e6152..314616d 100644\n--- a/pack-objects.c\n+++ b/pack-objects.c\n@@ -464,7 +464,7 @@ int main(int argc, char **argv)\n \t\tp = line+40;\n \t\twhile (*p) {\n \t\t\tunsigned char c = *p++;\n-\t\t\tif (isspace(c))\n+\t\t\tif (is_space(c))\n \t\t\t\tcontinue;\n \t\t\thash = hash * 11 + c;\n \t\t}\ndiff --git a/patch-id.c b/patch-id.c\nindex edbc4aa..ba09d2a 100644\n--- a/patch-id.c\n+++ b/patch-id.c\n@@ -21,7 +21,7 @@ static int remove_space(char *line)\n \tunsigned char c;\n \n \twhile ((c = *src++) != '\\0') {\n-\t\tif (!isspace(c))\n+\t\tif (!is_space(c))\n \t\t\t*dst++ = c;\n \t}\n \treturn dst - line;\ndiff --git a/refs.c b/refs.c\nindex 97506a4..4d202ee 100644\n--- a/refs.c\n+++ b/refs.c\n@@ -43,7 +43,7 @@ int validate_symref(const char *path)\n \t\treturn -1;\n \tbuf = buffer + 4;\n \tlen -= 4;\n-\twhile (len && isspace(*buf))\n+\twhile (len && is_space(*buf))\n \t\tbuf++, len--;\n \tif (len >= 5 && !memcmp(\"refs/\", buf, 5))\n \t\treturn 0;\n@@ -103,9 +103,9 @@ const char *resolve_ref(const char *path\n \t\t\tbreak;\n \t\tbuf = buffer + 4;\n \t\tlen -= 4;\n-\t\twhile (len && isspace(*buf))\n+\t\twhile (len && is_space(*buf))\n \t\t\tbuf++, len--;\n-\t\twhile (len && isspace(buf[len-1]))\n+\t\twhile (len && is_space(buf[len-1]))\n \t\t\tbuf[--len] = 0;\n \t\tpath = git_path(\"%.*s\", len, buf);\n \t}\ndiff --git a/stripspace.c b/stripspace.c\nindex 96cd0a8..a6204b6 100644\n--- a/stripspace.c\n+++ b/stripspace.c\n@@ -1,6 +1,6 @@\n #include <stdio.h>\n #include <string.h>\n-#include <ctype.h>\n+#include \"cache.h\"\n \n /*\n  * Remove empty lines from the beginning and end.\n@@ -15,7 +15,7 @@ static void cleanup(char *line)\n \tif (len > 1 && line[len-1] == '\\n') {\n \t\tdo {\n \t\t\tunsigned char c = line[len-2];\n-\t\t\tif (!isspace(c))\n+\t\t\tif (!is_space(c))\n \t\t\t\tbreak;\n \t\t\tline[len-2] = '\\n';\n \t\t\tlen--;\n"},{"id":"10534","messageId":"pan.2005.10.24.14.03.31.13115@smurf.noris.de","threadId":"2204","inReplyTo":"7v64rnsd83.fsf@assigned-by-dhcp.cox.net","subject":"Re: daemon.c broken on OpenBSD","fromName":"Matthias Urlichs","fromEmail":"smurf@smurf.noris.de","sentAt":"2005-10-24T14:03:32Z","receivedAt":"2005-10-24T14:03:32Z","isPatch":false,"sender":{"key":"matthias@urlichs.de","avatar":"https://gravatar.com/avatar/2708905af227313eba6f2b2ae0f7d0259b5ac5d71baef58fe5a13c699ce0bbf0?d=mp&s=160"},"body":"Hi, Junio C Hamano wrote:\n\n> Maybe something like this would help?\n\nI agree that this change, though intrusive, is a good idea.\n\n-- \nMatthias Urlichs   |   {M:U} IT Design @ m-u-it.de   |  smurf@smurf.noris.de\nDisclaimer: The quote was selected randomly. Really. | http://smurf.noris.de\n - -\nThe thing I like best about Spider-Man is that there's a hyphen in the\ntitle. -- SJM's review of the movie\n"},{"id":"10536","messageId":"Pine.LNX.4.64.0510240901020.10477@g5.osdl.org","threadId":"2204","inReplyTo":"867jc336f4.fsf@blue.stonehenge.com","subject":"Re: daemon.c broken on OpenBSD","fromName":"Linus Torvalds","fromEmail":"torvalds@osdl.org","sentAt":"2005-10-24T16:02:04Z","receivedAt":"2005-10-24T16:02:04Z","isPatch":false,"sender":{"key":"torvalds@linux-foundation.org","avatar":"https://avatars.githubusercontent.com/u/1024025?v=4"},"body":"\n\nOn Sun, 23 Oct 2005, Randal L. Schwartz wrote:\n> \n> If that rings a bell, help me out here.  I'm guessing \"isalnum\" is getting\n> defined (wrongly).  Yeah, looks like in cache.h.  Why is this getting\n> defined?\n\nWe're doing our own ctype.h.\n\nThe fix is to make sure that \"cache.h\" is included _after_ system \nincludes.\n\niow, this should fix it, methinks.\n\n\t\tLinus\n---\ndiff --git a/daemon.c b/daemon.c\nindex 0c6182f..6e5de11 100644\n--- a/daemon.c\n+++ b/daemon.c\n@@ -1,5 +1,3 @@\n-#include \"cache.h\"\n-#include \"pkt-line.h\"\n #include <signal.h>\n #include <sys/wait.h>\n #include <sys/socket.h>\n@@ -10,6 +8,9 @@\n #include <arpa/inet.h>\n #include <syslog.h>\n \n+#include \"cache.h\"\n+#include \"pkt-line.h\"\n+\n static int log_syslog;\n static int verbose;\n \n"},{"id":"10537","messageId":"86irvmzyq9.fsf@blue.stonehenge.com","threadId":"2204","inReplyTo":"Pine.LNX.4.64.0510240901020.10477@g5.osdl.org","subject":"Re: daemon.c broken on OpenBSD","fromName":"Randal L. Schwartz","fromEmail":"merlyn@stonehenge.com","sentAt":"2005-10-24T16:06:06Z","receivedAt":"2005-10-24T16:06:06Z","isPatch":false,"sender":{"key":"merlyn@stonehenge.com","avatar":"https://gravatar.com/avatar/dc528d210743ff0333e6213f9ee7b33b23f1b7bc1f3c5a8c2d819074ecd7ab19?d=mp&s=160"},"body":">>>>> \"Linus\" == Linus Torvalds <torvalds@osdl.org> writes:\n\nLinus> We're doing our own ctype.h.\n\nLinus> The fix is to make sure that \"cache.h\" is included _after_ system \nLinus> includes.\n\nThat probably won't work, because on OpenBSD, it's not a #define, but\nrather a real function call.  You can't just #undef that (unless my C\nis even more rusty).\n\n-- \nRandal L. Schwartz - Stonehenge Consulting Services, Inc. - +1 503 777 0095\n<merlyn@stonehenge.com> <URL:http://www.stonehenge.com/merlyn/>\nPerl/Unix/security consulting, Technical writing, Comedy, etc. etc.\nSee PerlTraining.Stonehenge.com for onsite and open-enrollment Perl training!\n"},{"id":"10539","messageId":"Pine.LNX.4.64.0510240936450.10477@g5.osdl.org","threadId":"2204","inReplyTo":"86irvmzyq9.fsf@blue.stonehenge.com","subject":"Re: daemon.c broken on OpenBSD","fromName":"Linus Torvalds","fromEmail":"torvalds@osdl.org","sentAt":"2005-10-24T16:43:51Z","receivedAt":"2005-10-24T16:43:51Z","isPatch":false,"sender":{"key":"torvalds@linux-foundation.org","avatar":"https://avatars.githubusercontent.com/u/1024025?v=4"},"body":"\n\nOn Mon, 24 Oct 2005, Randal L. Schwartz wrote:\n> \n> That probably won't work, because on OpenBSD, it's not a #define, but\n> rather a real function call.  You can't just #undef that (unless my C\n> is even more rusty).\n\nSure you can. \n\nThe #undef won't necessarily _do_ anything, but it protects against \nsystems where it is a #define. Then, the #define makes sure that if it's \nanything else, the #define will take precedence.\n\nSo yes, it's ugly, but it definitely is safe in practice, as long as the \nlocal headers are included before the system ones.\n\nI think Junio's patch (that renames things) is possibly the \"cleaner\" \nalternative, but on the other hand there's a lot of advantages to just \nusing the standard names. No chance of somebody using the wrong version by \nmistake.\n\n\t\t\tLinus\n"},{"id":"10540","messageId":"435D1402.4050601@zytor.com","threadId":"2204","inReplyTo":"Pine.LNX.4.64.0510240936450.10477@g5.osdl.org","subject":"Re: daemon.c broken on OpenBSD","fromName":"H. Peter Anvin","fromEmail":"hpa@zytor.com","sentAt":"2005-10-24T17:04:02Z","receivedAt":"2005-10-24T17:04:02Z","isPatch":false,"sender":{"key":"hpa@zytor.com","avatar":null},"body":"Linus Torvalds wrote:\n> \n> I think Junio's patch (that renames things) is possibly the \"cleaner\" \n> alternative, but on the other hand there's a lot of advantages to just \n> using the standard names. No chance of somebody using the wrong version by \n> mistake.\n> \n\nBut there is also no risk of other unexpected dependencies.  I would \nvote for using git-specific names.\n\n\t-hpa\n"},{"id":"10541","messageId":"Pine.LNX.4.64.0510241002180.10477@g5.osdl.org","threadId":"2204","inReplyTo":"Pine.LNX.4.64.0510240936450.10477@g5.osdl.org","subject":"Re: daemon.c broken on OpenBSD","fromName":"Linus Torvalds","fromEmail":"torvalds@osdl.org","sentAt":"2005-10-24T17:14:46Z","receivedAt":"2005-10-24T17:14:46Z","isPatch":false,"sender":{"key":"torvalds@linux-foundation.org","avatar":"https://avatars.githubusercontent.com/u/1024025?v=4"},"body":"\n\nOn Mon, 24 Oct 2005, Linus Torvalds wrote:\n> \n> So yes, it's ugly, but it definitely is safe in practice, as long as the \n> local headers are included before the system ones.\n\nSide note: \"safe in practice\" isn't necessarily the same as \"safe in \ntheory\".\n\nI think that strictly speaking, if you include <ctype.h>, the \"isxxxx()\" \nformat is always reserved (where \"x\" is lowercase letters), and in theory \nyou could have a compiler that recognizes them even before the \npre-processor as being something built-in.\n\nIn _practice_, such a compiler would be incredibly broken (it would have \nto do the recognition after preprocessing too), and I doubt you'd ever see \nsuch a thing, but from a pure language-lawyer standpoint it might \ntechnically be possible.\n\nHowever, I'm surprised that you see <ctype.h> at all. The OpenBSD headers \nseem to be including <ctype.h> from <sys/poll.h>, which doesn't make any \nsense. It may not be strictly against POSIX, but it's definitely strange \nand bad form to do unnecessary name pollution that the user didn't ask \nfor.\n\nSo git actually tries to be pretty good about things. Not only does it try \nto handle any existing system <ctype.h> by doing the #undef, it actually \ndoesn't include the system ctype.h at _all_ when it includes \"cache.h\". \nAnd OpenBSD is being a bit strange.\n\n\t\tLinus\n"},{"id":"10542","messageId":"435D1963.8070205@zytor.com","threadId":"2204","inReplyTo":"Pine.LNX.4.64.0510241002180.10477@g5.osdl.org","subject":"Re: daemon.c broken on OpenBSD","fromName":"H. Peter Anvin","fromEmail":"hpa@zytor.com","sentAt":"2005-10-24T17:26:59Z","receivedAt":"2005-10-24T17:26:59Z","isPatch":false,"sender":{"key":"hpa@zytor.com","avatar":null},"body":"Linus Torvalds wrote:\n> \n> Side note: \"safe in practice\" isn't necessarily the same as \"safe in \n> theory\".\n> \n> I think that strictly speaking, if you include <ctype.h>, the \"isxxxx()\" \n> format is always reserved (where \"x\" is lowercase letters), and in theory \n> you could have a compiler that recognizes them even before the \n> pre-processor as being something built-in.\n> \n> In _practice_, such a compiler would be incredibly broken (it would have \n> to do the recognition after preprocessing too), and I doubt you'd ever see \n> such a thing, but from a pure language-lawyer standpoint it might \n> technically be possible.\n> \n\nA much more likely cause for problems would be system headers that use \nthe isxxx() macros as part of other macros.  That would be in violation \nof POSIX, but is reasonably common.\n\n> However, I'm surprised that you see <ctype.h> at all. The OpenBSD headers \n> seem to be including <ctype.h> from <sys/poll.h>, which doesn't make any \n> sense. It may not be strictly against POSIX, but it's definitely strange \n> and bad form to do unnecessary name pollution that the user didn't ask \n> for.\n\nIt is strictly against POSIX, but again, fairly common.\n\n> So git actually tries to be pretty good about things. Not only does it try \n> to handle any existing system <ctype.h> by doing the #undef, it actually \n> doesn't include the system ctype.h at _all_ when it includes \"cache.h\". \n> And OpenBSD is being a bit strange.\n\nI think there is another good reason for doing the renaming bit: we're \ncreating new macros with different semantics; in particular, the git \nmacros handle signed char input and don't guarantee anything w.r.t. EOF.\n\n\t-hpa\n"},{"id":"10543","messageId":"Pine.LNX.4.64.0510241054480.10477@g5.osdl.org","threadId":"2204","inReplyTo":"435D1963.8070205@zytor.com","subject":"Re: daemon.c broken on OpenBSD","fromName":"Linus Torvalds","fromEmail":"torvalds@osdl.org","sentAt":"2005-10-24T17:58:25Z","receivedAt":"2005-10-24T17:58:25Z","isPatch":false,"sender":{"key":"torvalds@linux-foundation.org","avatar":"https://avatars.githubusercontent.com/u/1024025?v=4"},"body":"\n\nOn Mon, 24 Oct 2005, H. Peter Anvin wrote:\n> \n> A much more likely cause for problems would be system headers that use the\n> isxxx() macros as part of other macros.  That would be in violation of POSIX,\n> but is reasonably common.\n\nHmm.. Yes, that's a good point. I don't see what thing could do it that we \ncare about (and since we do actually do a pretty valid ctype \nimplementation, it should all work out right regardless), but yes, it \nmight be safer to rename the things.\n\nEspecially if we then continue to make sure _not_ to include <ctype.h> \nourselves, so that only systems with broken headers (like the ones on \nOpenBSD ;) could ever use the standard names anyway. That way we'd not \nhave to worry whether somebody uses them by mistake..\n\nBtw, nobody ever replied to my question whether we might be using \nsomething else that is locale-specific. I'm not actually locate-aware \nenough to even know what else than <ctype.h> might be dangerous to use..\n\nAnybody?\n\n\t\tLinus\n"},{"id":"10544","messageId":"435D21DE.6080404@zytor.com","threadId":"2204","inReplyTo":"Pine.LNX.4.64.0510241054480.10477@g5.osdl.org","subject":"Re: daemon.c broken on OpenBSD","fromName":"H. Peter Anvin","fromEmail":"hpa@zytor.com","sentAt":"2005-10-24T18:03:10Z","receivedAt":"2005-10-24T18:03:10Z","isPatch":false,"sender":{"key":"hpa@zytor.com","avatar":null},"body":"Linus Torvalds wrote:\n> \n> Btw, nobody ever replied to my question whether we might be using \n> something else that is locale-specific. I'm not actually locate-aware \n> enough to even know what else than <ctype.h> might be dangerous to use..\n> \n\nRegexxen are probably the single most problematic thing.\n\n\t-hpa\n"},{"id":"10545","messageId":"118833cc0510241125y4d97821dxc6ea0ca62f659db4@mail.gmail.com","threadId":"2204","inReplyTo":"435D21DE.6080404@zytor.com","subject":"Re: daemon.c broken on OpenBSD","fromName":"Morten Welinder","fromEmail":"mwelinder@gmail.com","sentAt":"2005-10-24T18:25:01Z","receivedAt":"2005-10-24T18:25:01Z","isPatch":false,"sender":{"key":"mwelinder@gmail.com","avatar":null},"body":"Locale issues:\n\n* Environment strings have unspecified encoding.\n* File names ditto.  (Which matters when they get printed together with other\n  strings.)\n* gecos information ditto.\n\nIf, and if only, you[*] call setlocale:\n\n* ctype stuff.\n* strtod, printf %[efg]\n* Regexps\n\n(Integer parsing and printing seems to be safe in pratice if not in theory.)\n\nIf you call system() you also need to watch out for things like Gnu sort\nbeing locale sensitive.\n\nMorten\n\n\n[*] That would be not just you, but also all the yous behind all the\n     libraries you link.\n"},{"id":"10552","messageId":"7vek6amy0n.fsf@assigned-by-dhcp.cox.net","threadId":"2204","inReplyTo":"435D1963.8070205@zytor.com","subject":"Re: daemon.c broken on OpenBSD","fromName":"Junio C Hamano","fromEmail":"junkio@cox.net","sentAt":"2005-10-24T20:59:52Z","receivedAt":"2005-10-24T20:59:52Z","isPatch":false,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"\"H. Peter Anvin\" <hpa@zytor.com> writes:\n\n> I think there is another good reason for doing the renaming bit: we're \n> creating new macros with different semantics; in particular, the git \n> macros handle signed char input and don't guarantee anything w.r.t. EOF.\n>\n> \t-hpa\n\nThanks.  I'll include the renaming bits to \"master\" branch when\nI hear somebody on OpenBSD confirms that the patch fixes it.\n"},{"id":"10622","messageId":"86vezljhve.fsf@blue.stonehenge.com","threadId":"2204","inReplyTo":"7v64rnsd83.fsf@assigned-by-dhcp.cox.net","subject":"Re: daemon.c broken on OpenBSD","fromName":"Randal L. Schwartz","fromEmail":"merlyn@stonehenge.com","sentAt":"2005-10-25T23:29:09Z","receivedAt":"2005-10-25T23:29:09Z","isPatch":false,"sender":{"key":"merlyn@stonehenge.com","avatar":"https://gravatar.com/avatar/dc528d210743ff0333e6213f9ee7b33b23f1b7bc1f3c5a8c2d819074ecd7ab19?d=mp&s=160"},"body":"\nI can confirm that the following patch lets the current origin\ncompile on OpenBSD.  If you could apply this until you sort out the\nrest of the namespace issue, I would be happy.  Thanks.\n\ndiff --git a/daemon.c b/daemon.c\nindex 0c6182f..c3f8641 100644\n--- a/daemon.c\n+++ b/daemon.c\n@@ -1,5 +1,3 @@\n-#include \"cache.h\"\n-#include \"pkt-line.h\"\n #include <signal.h>\n #include <sys/wait.h>\n #include <sys/socket.h>\n@@ -9,6 +7,8 @@\n #include <netinet/in.h>\n #include <arpa/inet.h>\n #include <syslog.h>\n+#include \"pkt-line.h\"\n+#include \"cache.h\"\n \n static int log_syslog;\n static int verbose;\n\n\n-- \nRandal L. Schwartz - Stonehenge Consulting Services, Inc. - +1 503 777 0095\n<merlyn@stonehenge.com> <URL:http://www.stonehenge.com/merlyn/>\nPerl/Unix/security consulting, Technical writing, Comedy, etc. etc.\nSee PerlTraining.Stonehenge.com for onsite and open-enrollment Perl training!\n"},{"id":"10623","messageId":"86r7a9jhq4.fsf@blue.stonehenge.com","threadId":"2204","inReplyTo":"86vezljhve.fsf@blue.stonehenge.com","subject":"Re: daemon.c broken on OpenBSD","fromName":"Randal L. Schwartz","fromEmail":"merlyn@stonehenge.com","sentAt":"2005-10-25T23:32:19Z","receivedAt":"2005-10-25T23:32:19Z","isPatch":false,"sender":{"key":"merlyn@stonehenge.com","avatar":"https://gravatar.com/avatar/dc528d210743ff0333e6213f9ee7b33b23f1b7bc1f3c5a8c2d819074ecd7ab19?d=mp&s=160"},"body":">>>>> \"Randal\" == Randal L Schwartz <merlyn@stonehenge.com> writes:\n\nRandal> I can confirm that the following patch lets the current origin\nRandal> compile on OpenBSD.  If you could apply this until you sort out the\nRandal> rest of the namespace issue, I would be happy.  Thanks.\n\nActually, you probably want this instead:\n\nSubject: [PATCH] openbsd patch\n\n---\n\n daemon.c |    4 ++--\n 1 files changed, 2 insertions(+), 2 deletions(-)\n\napplies-to: 6234aa4f7095054a137e030030f914dc6633f809\n7666c6f2cf2fcf41fce1d0665b79e5cc2f7b73b5\ndiff --git a/daemon.c b/daemon.c\nindex 0c6182f..c3f8641 100644\n--- a/daemon.c\n+++ b/daemon.c\n@@ -1,5 +1,3 @@\n-#include \"cache.h\"\n-#include \"pkt-line.h\"\n #include <signal.h>\n #include <sys/wait.h>\n #include <sys/socket.h>\n@@ -9,6 +7,8 @@\n #include <netinet/in.h>\n #include <arpa/inet.h>\n #include <syslog.h>\n+#include \"pkt-line.h\"\n+#include \"cache.h\"\n \n static int log_syslog;\n static int verbose;\n---\n0.99.8.GIT\n\n\n-- \nRandal L. Schwartz - Stonehenge Consulting Services, Inc. - +1 503 777 0095\n<merlyn@stonehenge.com> <URL:http://www.stonehenge.com/merlyn/>\nPerl/Unix/security consulting, Technical writing, Comedy, etc. etc.\nSee PerlTraining.Stonehenge.com for onsite and open-enrollment Perl training!\n"},{"id":"10629","messageId":"86k6g1jhbo.fsf@blue.stonehenge.com","threadId":"2204","inReplyTo":"86r7a9jhq4.fsf@blue.stonehenge.com","subject":"Re: daemon.c broken on OpenBSD","fromName":"Randal L. Schwartz","fromEmail":"merlyn@stonehenge.com","sentAt":"2005-10-25T23:40:59Z","receivedAt":"2005-10-25T23:40:59Z","isPatch":false,"sender":{"key":"merlyn@stonehenge.com","avatar":"https://gravatar.com/avatar/dc528d210743ff0333e6213f9ee7b33b23f1b7bc1f3c5a8c2d819074ecd7ab19?d=mp&s=160"},"body":">>>>> \"Randal\" == Randal L Schwartz <merlyn@stonehenge.com> writes:\n\nRandal> Actually, you probably want this instead:\n\nAnd this one too, because .gitignore is missing some files:\n\n>From nobody Mon Sep 17 00:00:00 2001\nSubject: [PATCH] fix .gitignore to add new progs\nFrom: Charlie <root@blue.stonehenge.com>\nDate: 1130283408 -0700\n\n---\n\n .gitignore |    2 ++\n 1 files changed, 2 insertions(+), 0 deletions(-)\n\napplies-to: eba31d473719d9a1f2d00b40b3011460d7af864c\nc0964c0160d7b08c0b5dd28d1b9462fd2b01bd50\ndiff --git a/.gitignore b/.gitignore\nindex 52cb9e2..758aaf6 100644\n--- a/.gitignore\n+++ b/.gitignore\n@@ -54,6 +54,7 @@ git-merge-recursive\n git-merge-resolve\n git-merge-stupid\n git-mktag\n+git-mv\n git-octopus\n git-pack-objects\n git-parse-remote\n@@ -78,6 +79,7 @@ git-revert\n git-send-email\n git-send-pack\n git-sh-setup\n+git-shell\n git-shortlog\n git-show-branch\n git-show-index\n---\n0.99.8.GIT\n\n\n-- \nRandal L. Schwartz - Stonehenge Consulting Services, Inc. - +1 503 777 0095\n<merlyn@stonehenge.com> <URL:http://www.stonehenge.com/merlyn/>\nPerl/Unix/security consulting, Technical writing, Comedy, etc. etc.\nSee PerlTraining.Stonehenge.com for onsite and open-enrollment Perl training!\n"}]}