Initial import from FreeBSD RELENG_4:
[dragonfly.git] / contrib / libio / dbz / case.c
1 /*
2  * case-mapping stuff
3  *
4  * We exploit the fact that we are dealing only with headers here, and
5  * headers are limited to the ASCII characters by RFC822.  It is barely
6  * possible that we might be dealing with a translation into another
7  * character set, but in particular it's very unlikely for a header
8  * character to be outside -128..255.
9  *
10  * Life would be a whole lot simpler if tolower() could safely and portably
11  * be applied to any char.
12  */
13 #include <stdio.h>
14 #include "string.h"
15 #include "case.h"
16
17 /* note that case.h knows the value of OFFSET */
18 #define OFFSET  128             /* avoid trouble with negative chars */
19 #define MAPSIZE (256+OFFSET)
20 char casemap[MAPSIZE];          /* relies on init to '\0' */
21 static int primed = 0;          /* has casemap been set up? */
22
23 /*
24  - prime - set up case-mapping stuff
25  */
26 static void
27 prime()
28 {
29         register char *lp;
30         register char *up;
31         register int c;
32         register int i;
33         static char lower[] = "abcdefghijklmnopqrstuvwxyz";
34         static char upper[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
35
36         for (lp = lower, up = upper; *lp != '\0'; lp++, up++) {
37                 c = *lp;
38                 casemap[c+OFFSET] = c;
39                 casemap[*up+OFFSET] = c;
40         }
41         for (i = 0; i < MAPSIZE; i++)
42                 if (casemap[i] == '\0')
43                         casemap[i] = (char)(i-OFFSET);
44         primed = 1;
45 }
46
47 /*
48  - cistrncmp - case-independent strncmp
49  */
50 int                             /* < == > 0 */
51 cistrncmp(s1, s2, len)
52 char *s1;
53 char *s2;
54 int len;
55 {
56         register char *p1;
57         register char *p2;
58         register int n;
59
60         if (!primed)
61                 prime();
62
63         p1 = s1;
64         p2 = s2;
65         n = len;
66         while (--n >= 0 && *p1 != '\0' && TOLOW(*p1) == TOLOW(*p2)) {
67                 p1++;
68                 p2++;
69         }
70         if (n < 0)
71                 return(0);
72
73         /*
74          * The following case analysis is necessary so that characters
75          * which look negative collate low against normal characters but
76          * high against the end-of-string NUL.
77          */
78         if (*p1 == '\0' && *p2 == '\0')
79                 return(0);
80         else if (*p1 == '\0')
81                 return(-1);
82         else if (*p2 == '\0')
83                 return(1);
84         else
85                 return(TOLOW(*p1) - TOLOW(*p2));
86 }
87
88 /*
89  - rfc822ize - do the bizarre case conversion needed for rfc822 message-ids
90  *
91  * Actually, this is not quite complete.  Absolute, total, full RFC822
92  * compliance requires a horrible parsing job, because of the arcane
93  * quoting conventions -- abc"def"ghi is not equivalent to abc"DEF"ghi,
94  * for example.  There are three or four things that might occur in the
95  * domain part of a message-id that are case-sensitive.  They don't seem
96  * to ever occur in real news, thank Cthulhu.  (What?  You were expecting
97  * a merciful and forgiving deity to be invoked in connection with RFC822?
98  * Forget it; none of them would come near it.)
99  */
100 char *                          /* returns the argument */
101 rfc822ize(s)
102 char *s;
103 {
104         register char *p;
105         static char post[] = "postmaster";
106         static int postlen = sizeof(post)-1;
107
108         if (!primed)
109                 prime();
110
111         p = strrchr(s, '@');
112         if (p == NULL)                  /* no local/domain split */
113                 p = "";                 /* assume all local */
114         else if (p - (s+1) == postlen && CISTREQN(s+1, post, postlen)) {
115                 /* crazy special case -- "postmaster" is case-insensitive */
116                 p = s;
117         }
118 #ifdef NONSTANDARD
119 #ifdef RFCVIOLATION
120 #ifdef B_2_11_MISTAKE
121         p = s;                          /* all case-insensitive */
122 #endif
123 #endif
124 #endif
125         for (; *p != '\0'; p++)
126                 *p = TOLOW(*p);
127
128         return(s);
129 }