1 /*
2  * Copyright © 1994-2017 World Wide Web Consortium
3  * See http://www.w3.org/Consortium/Legal/copyright-software
4  *
5  * Author: Bert Bos <bert@w3.org>
6  * Created: 1997
7  **/
8 #include "config.h"
9 #include <stdlib.h>
10 #include <stdarg.h>
11 #ifdef HAVE_STRING_H
12 #  include <string.h>
13 #elif HAVE_STRINGS_H
14 #  include <strings.h>
15 #endif
16 #include <ctype.h>
17 #include <stdbool.h>
18 #include "export.h"
19 #include "heap.e"
20 
21 EXPORT typedef char *string;
22 EXPORT typedef const char *conststring;
23 
24 EXPORT typedef struct _pairlist {
25   string name;
26   string value;
27   struct _pairlist *next;
28 } *pairlist;
29 
30 EXPORT typedef unsigned int MediaSet;
31 EXPORT enum _Media {
32   MediaNone = 0,
33   MediaPrint = (1 << 0),
34   MediaScreen = (1 << 1),
35   MediaTTY = (1 << 2),
36   MediaBraille = (1 << 3),
37   MediaTV = (1 << 4),
38   MediaProjection = (1 << 5),
39   MediaEmbossed = (1 << 6),
40   MediaAll = 0xFF
41 };
42 
43 #define eq(s, t) (*(s) == *(t) && strcmp(s, t) == 0)
44 EXPORTDEF(eq(s, t))
45 
46 #define hexval(c) ((c) <= '9' ? (c)-'0' : (c) <= 'F' ? 10+(c)-'A' : 10+(c)-'a')
EXPORTDEF(hexval (c))47 EXPORTDEF(hexval(c))
48 
49 /* pairlist_delete -- free all memory occupied by a pairlist */
50 EXPORT void pairlist_delete(pairlist p)
51 {
52   if (p) {
53     pairlist_delete(p->next);
54     dispose(p->name);
55     dispose(p->value);
56     dispose(p);
57   }
58 }
59 
60 /* pairlist_copy -- make a deep copy of a pairlist */
pairlist_copy(const pairlist p)61 EXPORT pairlist pairlist_copy(const pairlist p)
62 {
63   pairlist h = NULL;
64 
65   if (p) {
66     new(h);
67     h->name = newstring(p->name);
68     h->value = newstring(p->value);
69     h->next = pairlist_copy(p->next);
70   }
71   return h;
72 }
73 
74 /* pairlist_get -- get value corresponding to name, or NULL */
pairlist_get(pairlist p,const conststring name)75 EXPORT conststring pairlist_get(pairlist p, const conststring name)
76 {
77   for (; p && strcasecmp(p->name, name) != 0; p = p->next);
78   return p ? p->value : NULL;
79 }
80 
81 /* pairlist_set -- add or change a name/value pair */
pairlist_set(pairlist * p,const conststring name,const conststring val)82 EXPORT void pairlist_set(pairlist *p, const conststring name,
83 			 const conststring val)
84 {
85   pairlist h;
86 
87   for (h = *p; h && strcasecmp(h->name, name) != 0; h = h->next);
88   if (h) {
89     free(h->value);
90     h->value = newstring(val);
91   } else {
92     new(h);
93     h->name = newstring(name);
94     h->value = newstring(val);
95     h->next = *p;
96     *p = h;
97   }
98 }
99 
100 /* pairlist_unset -- remove a name/value pair from list, false if not found */
pairlist_unset(pairlist * p,const conststring name)101 EXPORT bool pairlist_unset(pairlist *p, const conststring name)
102 {
103 
104   pairlist h, h1;
105 
106   if (! *p) return false;
107   if (strcasecmp((*p)->name, name) == 0) {
108     /* Remove first pair in list */
109     h = *p;
110     free(h->name);
111     free(h->value);
112     *p = h->next;
113     free(h);
114     return true;
115   }
116   for (h = *p; h->next && strcasecmp(h->next->name, name) != 0; h = h->next);
117   if (! h->next) return false;	/* Not found */
118   free(h->next->name);
119   free(h->next->value);
120   h1 = h->next;
121   h->next = h->next->next;
122   free(h1);
123   return true;
124 }
125 
126 /* strapp -- append to a string, re-allocating memory; last arg must be 0 */
strapp(string * s,...)127 EXPORT string strapp(string *s,...)
128 {
129   va_list ap;
130   int i, j;
131   conststring h;
132 
133   va_start(ap, s);
134   if (!s) {new(s); *s = NULL;}
135   i = *s ? strlen(*s) : 0;
136   while ((h = va_arg(ap, conststring))) {
137     j = strlen(h);
138     renewarray(*s, i + j + 1);
139     strcpy(*s + i, h);
140     i += j;
141   }
142   va_end(ap);
143   return *s;
144 }
145 
146 /* chomp -- remove trailing \n or \r\n (if any) from string */
chomp(string s)147 EXPORT void chomp(string s)
148 {
149   int i;
150 
151   if (s && (i = strlen(s)) != 0 && s[i-1] == '\n') {
152     s[i-1] = '\0';
153     if (i > 1 && s[i-2] == '\r') s[i-2] = '\0';
154   }
155 }
156 
min(int a,int b)157 EXPORT int min(int a, int b) { return a < b ? a : b; }
max(int a,int b)158 EXPORT int max(int a, int b) { return a > b ? a : b; }
159 
160 /* down -- convert a string to lowercase, return pointer to arg */
down(const string s)161 EXPORT string down(const string s)
162 {
163   string t;
164 
165   for (t = s; *t; t++) *t = tolower(*t);
166   return s;
167 }
168 
169 /* hasprefix -- true if s starts with prefix */
hasprefix(conststring s,conststring prefix)170 EXPORT bool hasprefix(conststring s, conststring prefix)
171 {
172   if (!prefix) return true;	/* NULL is prefix of everything */
173   if (!s) return !prefix;	/* Only NULL is prefix of NULL */
174   while (*prefix && *prefix == *s) prefix++, s++;
175   return *prefix == '\0';
176 }
177 
178 /* hasaffix -- true if s ends with affix */
hasaffix(conststring s,conststring affix)179 EXPORT bool hasaffix(conststring s, conststring affix)
180 {
181   size_t i, j;
182 
183   if (!affix) return true;
184   if (!s) return !affix;
185   i = strlen(s);
186   j = strlen(affix);
187   if (i < j) return false;
188   s = s + i - j;
189   while (*affix && *affix == *s) affix++, s++;
190   return *affix == '\0';
191 }
192 
193 /* only_space -- check if s contains only whitespace */
only_space(conststring s)194 EXPORT bool only_space(conststring s)
195 {
196   while (*s == ' ' || *s == '\n' || *s == '\r' || *s == '\t' || *s == '\f')
197     s++;
198   return *s == '\0';
199 }
200 
201