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/
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.
12 * The Original Code is the Sablotron XSLT Processor.
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.
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
39 #include "domprovider.h"
44 SituaInfo& SituaInfo::operator=(const SituaInfo& other)
46 pending = other.pending;
48 currFile = other.currFile;
49 currMsg = other.currMsg;
50 currLine = other.currLine;
51 SDOMExceptionCode = other.SDOMExceptionCode;
55 void SituaInfo::clear()
62 SDOMExceptionCode = 0;
66 /*****************************************************************
70 *****************************************************************/
72 Situation::Situation()
74 theRecoder = new Recoder;
77 logfile = errwfile = NULL;
81 // define this symbol to disable adding the meta tag
82 #ifdef SABLOT_DISABLE_ADDING_META
83 flags |= SAB_DISABLE_ADDING_META;
86 //define thos symbol to avoid errors in document() when not found
87 #ifdef SABLOT_DISABLE_DOC_ERRORS
88 flags |= SAB_IGNORE_DOC_NOT_FOUND;
92 theProvider = new DOMProviderUniversal();
95 Situation::~Situation()
97 theRecoder -> clear(*this);
99 if (logfile) stdclose(logfile);
100 if (errwfile) stdclose(errwfile);
101 cdelete(theProvider);
104 Recoder& Situation::recoder() const
109 void Situation::setFlag(SablotFlag f)
114 Bool Situation::hasFlag(SablotFlag f)
119 void Situation::resetFlag(SablotFlag f)
124 void Situation::setFlags(int f)
129 int Situation::getFlags()
134 Str Situation::timeStr()
138 return asctime(localtime(&currtime));
141 void Situation::setCurrV(Vertex *v)
146 info.currLine = v -> lineno;
150 void Situation::setCurrVDoc(Vertex *v)
155 info.currFile = v -> getSubtreeInfo() -> getBaseURI();
159 void Situation::setCurrLine(int lno)
164 void Situation::setCurrSAXLine(int lno)
166 info.currSAXLine = lno;
169 int Situation::getCurrSAXLine()
171 return info.currSAXLine;
174 void Situation::setCurrFile(const Str& fname)
176 info.currFile = fname;
179 eFlag Situation::openDefaultFiles()
181 E( msgOutputFile((char *) "stderr", NULL) );
185 eFlag Situation::closeFiles()
196 eFlag Situation::eraseLog(char *newLogFile)
203 if (!(logfile = stdopen(newLogFile,"w")))
204 Err1(this, E_FILE_OPEN, newLogFile);
205 setlinebuf__(logfile);
210 eFlag Situation::msgOutputFile(char *_errwfn, char *_logfn)
215 if (!(logfile = stdopen(_logfn,"a")))
216 Err1(this, E_FILE_OPEN, _logfn);
217 setlinebuf__(logfile);
221 if (!(errwfile = stdopen(_errwfn,"w")))
222 Err1(this, E_FILE_OPEN, _errwfn);
223 setlinebuf__(errwfile);
228 // constructMsgFields
229 // called to transform a List of Str's to a NULL-terminated array
230 // of char*'s. Stores just POINTERS so make sure the strings don't change.
231 // Dispose of the return value using delete[].
233 char** constructMsgFields(PList<DStr*>& strings)
235 int len = strings.number();
236 char **p = new char*[len + 1];
239 for (i = 0; i < len; i++)
240 p[i] = (char*)(*strings[i]);
245 void safeFormat(char* dest, int size, const char* format,
246 const char* arg1, const char* arg2, const char* arg3)
250 const char* a[__numargs];
252 int total = 0, num = 0;
257 memset(l, 0, 3 * sizeof(int));
258 memset(b, 0, 3 * sizeof(char*));
262 for (i = 0; i < __numargs; i++)
263 if (a[i]) { l[i] = strlen(a[i]); num++; total += l[i];}
265 //replace too long buffers
266 for (i = 0; i < __numargs; i++)
268 if (l[i] > size / __numargs)
270 b[i] = new char[size / __numargs + 1];
272 strcpy(b[i] + 3, a[i] + (l[i] - size / __numargs + 3));
276 sprintf(dest, format,
282 for (i = 0; i < __numargs; i++)
283 if (b[i]) delete[] b[i];
286 #define __MSG_BUFSIZE 512
287 void Situation::generateMessage(MsgType type, MsgCode code,
288 const Str& arg1, const Str& arg2,
291 char buf[__MSG_BUFSIZE];
293 void *messengerUD = NULL;
294 MessageHandler *messenger = NULL;
296 messenger = proc -> getMessageHandler(&messengerUD);
299 out.append(new DStr("msgtype:"));
301 case MT_ERROR: *(out[0]) += "error"; break;
302 case MT_WARN: *(out[0]) += "warning"; break;
303 case MT_LOG: *(out[0]) += "log"; break;
308 sprintf(buf,"code:%d",code);
309 out.append(new DStr(buf));
312 out.append(new DStr("module:Sablotron"));
313 if (!info.currFile.isEmpty())
315 //check for buffer overflow
316 //sprintf(buf,"URI:%s",(char*)(info.currFile));
317 safeFormat(buf, __MSG_BUFSIZE - 5,
319 (char*)(info.currFile),
321 out.append(new DStr(buf));
323 if (info.currLine && type != MT_LOG)
325 sprintf(buf,"line:%d",info.currLine);
326 out.append(new DStr(buf));
328 if (info.currV && type != MT_LOG)
330 //may overflow for extremly (~500 bytes) long tag names
332 info.currV -> speak(nameStr, SM_NAME);
333 //sprintf(buf,"node:%s%s'%s'",
334 // vertexTypeNames[info.currV -> vt & VT_BASE],
335 // (info.currV -> vt == VT_VERTEX ? "" : " "),
336 // (char *) nameStr);
337 safeFormat(buf, __MSG_BUFSIZE - 10,
339 vertexTypeNames[info.currV -> vt & VT_BASE],
340 (info.currV -> vt == VT_VERTEX ? "" : " "),
342 out.append(new DStr(buf));
345 SabMsg *p = GetMessage(code);
348 //check buffer overflow
349 DStr msgText = messenger ? (char*)"msg:" : (char*)"";
350 //sprintf(buf,p -> text,(char*)(Str&)arg1,(char*)(Str&)arg2);
351 safeFormat(buf, __MSG_BUFSIZE - strlen(p -> text),
357 out.append(new DStr(msgText));
360 if (messenger && !(flags & SAB_NO_ERROR_REPORTING))
362 // construct the message fields
363 char **msgFields = constructMsgFields(out);
364 MH_ERROR externalCode =
365 messenger -> makeCode(messengerUD, proc,
366 type == MT_ERROR ? 1 : 0,
367 MH_FACILITY_SABLOTRON, (unsigned short)code);
369 // FIXME: casting to MH_LEVEL -- necessary?
373 messenger -> error(messengerUD, proc,
374 externalCode, (MH_LEVEL) MH_LEVEL_ERROR,
379 messenger -> log(messengerUD, proc,
380 externalCode, (MH_LEVEL) MH_LEVEL_WARN,
385 messenger -> log(messengerUD, proc,
386 externalCode, (MH_LEVEL) MH_LEVEL_INFO,
391 // note that the strings pointed at by msgFields members are deleted
392 // upon destruction of 'out'
395 // in any case, construct the message and return it in theMessage
396 // construct the message
400 fullout = GetMessage((MsgCode)(MSG_ERROR + type)) -> text;
402 int outnum = out.number();
403 for (int j = 0; j < outnum; j++)
417 fullout = *(out.last());
420 if (!messenger && !(type == MT_ERROR && (flags & SAB_NO_ERROR_REPORTING)))
422 // display the message yourself
423 FILE *thefile = (type == MT_LOG ? logfile : errwfile);
425 fprintf(thefile,"%s\n",(char*) fullout);
428 theMessage = fullout;
430 // dispose of the temp string array
434 void Situation::message(MsgType type, MsgCode code,
435 const Str& arg1, const Str& arg2)
444 if (type == MT_ERROR)
449 if (type == MT_ERROR)
451 generateMessage(type, code, arg1, arg2, temp);
454 // only log errors and warnings if we are using our own reporter
455 if ((type == MT_ERROR || type == MT_WARN) &&
456 (!proc || !proc -> getMessageHandler(NULL)))
457 generateMessage(MT_LOG, code, arg1, arg2, temp);
459 #ifdef SABLOT_ABORT_ON_ERROR
460 if (type == MT_ERROR) abort();
465 void Situation::report(Situation *sit, MsgType type, MsgCode code, const Str &str1, const Str &str2)
467 message(type, code, str1, str2);
471 Bool Situation::isError()
473 return (Bool) (info.pending != E_OK);
476 int Situation::getError() const
481 void Situation::clearError()
484 info.currMsg.empty();
487 void Situation::clear()
493 void Situation::setSDOMExceptionCode(int code)
495 info.SDOMExceptionCode = code;
498 int Situation::getSDOMExceptionCode() const
500 // the exception code was moved to infoDOM by message()
501 return infoDOM.SDOMExceptionCode;
504 void Situation::getSDOMExceptionExtra(MsgCode& theCode,
505 Str& theMessage, Str& theDocument, int& theLine) const
507 theCode = infoDOM.pending;
508 theMessage = infoDOM.currMsg;
509 theDocument = infoDOM.currFile;
510 theLine = infoDOM.currLine;
513 void Situation::swapProcessor(void *& proc_)
516 proc = (Processor*) proc_;
520 const Str& Situation::findBaseURI(const Str& unmappedBase)
523 return proc -> findBaseURI(*this, unmappedBase);
528 void Situation::setSXPOptions(unsigned long options)
530 theProvider -> setOptions(options);
533 unsigned long Situation::getSXPOptions()
535 return theProvider -> getOptions();
538 void Situation::setSXPMaskBit(int mask)
540 theProvider -> setMaskBit(mask);
543 int Situation::getSXPMaskBit()
545 return theProvider -> getMaskBit();
548 void Situation::setDOMProvider(DOMHandler *domh, void* udata)
550 theProvider -> setExtProvider(domh, udata);