1 /*
2 * The contents of this file are subject to the Mozilla Public
3 * License Version 1.1 (the "License"); you may not use this file
4 * except in compliance with the License. You may obtain a copy of
5 * the License at http://www.mozilla.org/MPL/
6 *
7 * Software distributed under the License is distributed on an "AS
8 * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
9 * implied. See the License for the specific language governing
10 * rights and limitations under the License.
11 *
12 * The Original Code is the Sablotron XSLT Processor.
13 *
14 * The Initial Developer of the Original Code is Ginger Alliance Ltd.
15 * Portions created by Ginger Alliance are Copyright (C) 2000-2002
16 * Ginger Alliance Ltd. All Rights Reserved.
17 *
18 * Contributor(s):
19 *
20 * Alternatively, the contents of this file may be used under the
21 * terms of the GNU General Public License Version 2 or later (the
22 * "GPL"), in which case the provisions of the GPL are applicable
23 * instead of those above. If you wish to allow use of your
24 * version of this file only under the terms of the GPL and not to
25 * allow others to use your version of this file under the MPL,
26 * indicate your decision by deleting the provisions above and
27 * replace them with the notice and other provisions required by
28 * the GPL. If you do not delete the provisions above, a recipient
29 * may use your version of this file under either the MPL or the
30 * GPL.
31 */
32
33 #include "base.h"
34 #include "platform.h"
35 #include "proc.h"
36 #include "utf8.h"
37 // #include <new.h>
38 #include <ctype.h>
39 // #include <strings.h>
40
41 // GP: clean
42
43 #if defined(CHECK_LEAKS)
44 #pragma Msg("Building with leak checking")
45 #endif
46
47 // includes for time measurement moved to platform.cpp
48
49 /****************************************
50 X S L c o n s t a n t s
51 ****************************************/
52
53 // !!!!!!!!!!!!!!!!!!!!!
54 // the order of items in the following tables must agree with
55 // that in the corresponding enums as defined in base.h
56
57 const char* xslOpNames[]=
58 {
59 "apply-imports","apply-templates",
60 "attribute","attribute-set",
61 "call-template","choose",
62 "comment", "copy","copy-of",
63 "decimal-format","element",
64 "fallback","for-each",
65 "if","import",
66 "include","key",
67 "message","namespace-alias",
68 "number","otherwise",
69 "output","param",
70 "preserve-space","processing-instruction",
71 "sort","strip-space",
72 "stylesheet","template",
73 "text","transform",
74 "value-of","variable",
75 "when","with-param",
76 NULL
77 };
78
79 const char* xslAttNames[]=
80 {
81 "case-order", "cdata-section-elements", "count",
82 "data-type", "decimal-separator", "digit", "disable-output-escaping", "doctype-public", "doctype-system",
83 "elements", "encoding", "exclude-result-prefixes", "extension-element-prefixes",
84 "format", "from",
85 "grouping-separator", "grouping-size",
86 "href",
87 "id", "indent", "infinity",
88 "lang", "letter-value", "level",
89 "match", "media-type", "method", "minus-sign", "mode",
90 "name", "namespace", "NaN",
91 "omit-xml-declaration", "order",
92 "pattern-separator", "percent", "per-mille", "priority",
93 "result-prefix",
94 "select", "standalone", "stylesheet-prefix",
95 "terminate", "test",
96 "use", "use-attribute-sets",
97 "value", "version",
98 "zero-digit",
99 NULL
100 };
101
102 const char* axisNames[]=
103 {
104 "ancestor","ancestor-or-self",
105 "attribute","child",
106 "descendant","descendant-or-self",
107 "following","following-sibling",
108 "namespace","parent",
109 "preceding","preceding-sibling",
110 "self",
111 NULL,
112 "root"
113 };
114
115 const char* vertexTypeNames[] =
116 {
117 "","root","element","attribute",
118 "text","processing instruction","comment","namespace"
119 };
120
121 const char* exNodeTypeNames[] =
122 {
123 "node", "text",
124 "processing-instruction", "comment",
125 NULL
126 };
127
128 const char* theXSLTNamespace = "http://www.w3.org/1999/XSL/Transform";
129 const char* oldXSLTNamespace = "http://www.w3.org/XSL/Transform/1.0";
130 const char* theXMLNamespace = "http://www.w3.org/XML/1998/namespace";
131 const char* theXHTMLNamespace = "http://www.w3.org/1999/xhtml";
132 const char* theXMLNSNamespace = "http://www.w3.org/2000/xmlns/";
133 const char* theSabExtNamespace = "http://www.gingerall.org/sablotron/extension";
134 const char* theEXSLTDynNamespace = "http://exslt.org/dynamic";
135
136 const char* theWhitespace = " \t\x0a\x0d";
137
138 //
139 // escape strings
140 //
141
142 const char
143 * escNewline = " ",
144 * escTab = "	",
145 * escLess = "<",
146 * escGreater = ">",
147 * escQuote = """,
148 * escApos = "'";
149
150 //
151 // handler types
152 // to match HandlerType in shandler.h
153 //
154
155 const char* hlrTypeNames[] = {"message", "scheme", "streaming",
156 "miscellaneous", "encoding"};
157
158 /*****************************************************************
159 Global handlers that can be set via Sablot functions
160 *****************************************************************/
161
162 // URI scheme handler
163 SchemeHandler* theSchemeHandler = NULL;
164 // message handler (errors, warnings, log messages...)
165 MessageHandler* theMessageHandler = NULL;
166 // SAX call handler (streamed access to the result document)
167 SAXHandler* theSAXHandler = NULL;
168 void* theSAXUserData = NULL;
169
170 /****************************************
171 l o o k u p
172 ****************************************/
173
174 // Finds a string in a NULL-terminated table of pointers.
175
lookup(const char * str,const char ** table)176 int lookup(const char* str, const char** table)
177 {
178 const char **p = table;
179 int i = 0;
180 while (*p)
181 {
182 if (!strcmp(str,*p)) return i;
183 p++; i++;
184 };
185 return i;
186 }
187
lookupNoCase(const char * str,const char ** table)188 int lookupNoCase(const char* str, const char** table)
189 {
190 const char **p = table;
191 int i = 0;
192 while (*p)
193 {
194 if (strEqNoCase(str,*p)) return i;
195 p++; i++;
196 };
197 return i;
198 }
199
200
201
202 /*****************************************************************
203 stdopen(), stdclose()
204 *****************************************************************/
205
isstd(const char * fname)206 Bool isstd(const char *fname)
207 {
208 if (!strcmp(fname,"/__stdin") || !strcmp(fname,"/__stderr")
209 || !strcmp(fname,"/__stdout"))
210 return TRUE;
211 return FALSE;
212 }
213
stdclose(FILE * f)214 int stdclose(FILE *f)
215 {
216 if ((!f) || (f == stdin) || (f == stdout) || (f == stderr))
217 return 0;
218 else return fclose(f);
219 }
220
stdopen(const char * fn,const char * mode)221 FILE* stdopen(const char *fn, const char *mode)
222 {
223 if (!strcmp(fn,"/__stderr"))
224 return stderr;
225 else if (!strcmp(fn,"/__stdout"))
226 return stdout;
227 else if (!strcmp(fn,"/__stdin"))
228 return stdin;
229 else
230 {
231 //we suppose we are working with uri PATH part
232 //on windows platforms it has form "/c:/bla/blah"
233 //so we need to remove the leading slash
234 #ifdef __WIN_TOOLS
235 const char * _fn;
236 if (fn[0] == '/' && fn[2] == ':')
237 _fn = fn + 1;
238 else
239 _fn = fn;
240 #else
241 const char * _fn = fn;
242 #endif
243 FILE* x = fopen(_fn,mode);
244 if (x) return x;
245 return NULL;
246 };
247 };
248
249 /*****************************************************************
250 strEqNoCase
251 *****************************************************************/
252
strEqNoCase(const char * s1,const char * s2)253 Bool strEqNoCase(const char* s1, const char* s2)
254 {
255 int i;
256 for (i = 0; s1[i]; i++)
257 {
258 if (tolower(s1[i]) != tolower(s2[i]))
259 return FALSE;
260 }
261 return s2[i] ? FALSE : TRUE;
262 }
263
264 /*****************************************************************
265 Memory leaks
266 *****************************************************************/
267
checkLeak()268 void checkLeak()
269 {
270 #if (defined(WIN32) && defined(CHECK_LEAKS))
271 _CrtSetReportMode( _CRT_WARN, _CRTDBG_MODE_FILE );
272 _CrtSetReportFile( _CRT_WARN, _CRTDBG_FILE_STDERR );
273 _CrtMemDumpAllObjectsSince(NULL);
274 #endif
275 }
276
memStats()277 void memStats()
278 {
279 #if (defined(WIN32) && defined(CHECK_LEAKS))
280 _CrtSetReportMode( _CRT_WARN, _CRTDBG_MODE_FILE );
281 _CrtSetReportFile( _CRT_WARN, _CRTDBG_FILE_STDERR );
282 _CrtMemState memsnap;
283 _CrtMemCheckpoint(&memsnap);
284 _CrtMemDumpStatistics(&memsnap);
285 #endif
286 }
287
288 /*****************************************************************
289 new handler
290 *****************************************************************/
291
292 //#ifdef _DEBUG
293 //#pragma Msg("'new' handler in linux?")
294 //#endif
295 /*
296 #ifdef WIN32
297 static _PNH oldNewHandler = NULL;
298 #endif
299
300 int sablotNewHandler(size_t size)
301 {
302 #if defined(WIN32) || defined(__linux__) || defined(__unix)
303 throw(E_MEMORY);
304 #else
305 //situation.error(E_MEMORY, *theEmptyString, theEmptyString);
306 #endif
307 return 0;
308 }
309
310 void pushNewHandler()
311 {
312 #ifdef WIN32
313 sabassert(!oldNewHandler);
314 oldNewHandler = _set_new_handler(sablotNewHandler);
315 #endif
316 }
317
318 void popNewHandler()
319 {
320 #ifdef WIN32
321 _set_new_handler( oldNewHandler );
322 oldNewHandler = NULL;
323 #endif
324 }
325 */
326 /*****************************************************************
327 fcomp
328
329 float comparison: returns 0 / 1 / -1 if p1 == / > / < p2.
330 *****************************************************************/
331
fcomp(double p1,double p2)332 int fcomp(double p1, double p2)
333 {
334 double d = p1 - p2;
335 if ((d < EPS) && (d > -EPS)) return 0;
336 else return (d > 0 ? 1 : -1);
337 }
338
339 // time
340
getMillisecsDiff(double originalTime)341 Str getMillisecsDiff(double originalTime)
342 {
343 char buf[20];
344 // getMillisecs() is in platform.cpp
345 sprintf(buf, "%.3f", getMillisecs() - originalTime);
346 return Str(buf);
347 }
348
349
350 /**************** XML name checks ********************/
351
isValidNCName(const char * name)352 Bool isValidNCName(const char* name)
353 {
354 int len = utf8StrLength(name);
355 if (len == 0) return FALSE;
356
357 wchar_t *buff = new wchar_t[len + 1];
358
359 utf8ToUtf16(buff, name);
360
361 Bool result = utf8IsLetter(buff[0]) || buff[0] == 0x005F; //underscore
362 for (int i = 1; i < len && result; i++)
363 {
364 result =
365 utf8IsLetter(buff[i]) ||
366 utf8IsDigit(buff[i]) ||
367 utf8IsCombiningChar(buff[i]) ||
368 utf8IsExtender(buff[i]) ||
369 buff[i] == 0x002E || //dot
370 buff[i] == 0x002D || //hyphen
371 buff[i] == 0x005F; //underscore
372 }
373
374 delete[] buff;
375 return result;
376 }
377
isValidQName(const char * name)378 Bool isValidQName(const char* name)
379 {
380 char *local = NULL;
381 char *start = NULL;
382 Bool copy = false;
383 Bool result = TRUE;
384
385 char *colon = (char *)strchr(name, ':');
386 if (colon)
387 {
388 //*colon = '\0';
389 local = colon + 1;
390 copy = true;
391 start = new char[colon - name + 1];
392 strncpy(start, name, colon - name);
393 start[colon - name] = '\0';
394 } else {
395 start = (char*)name;
396 }
397
398 result = isValidNCName(start) && (local == NULL || isValidNCName(local));
399
400 //if (colon) *colon = ':';
401 if (copy) delete start;
402 return result;
403 }
404
405
406 //string parsing
getWhDelimString(char * & list,Str & firstPart)407 Bool getWhDelimString(char *&list, Str& firstPart)
408 {
409 skipWhite(list);
410 if (!*list) return FALSE;
411 char *list_was = list;
412 for(; *list && !isWhite(*list); list++);
413 firstPart.nset(list_was, (int)(list - list_was));
414 return TRUE;
415 }
416