r8630: give a much nicer backtrace on assert() failures in ejs
authorAndrew Tridgell <tridge@samba.org>
Wed, 20 Jul 2005 05:13:01 +0000 (05:13 +0000)
committerGerald (Jerry) Carter <jerry@samba.org>
Wed, 10 Oct 2007 18:29:46 +0000 (13:29 -0500)
I will submit this upstream
(This used to be commit a2266f6927d953459bd4b02fbca0a9c95c18494e)

source4/lib/appweb/ejs/ejsInternal.h
source4/lib/appweb/ejs/ejsLex.c
source4/lib/appweb/ejs/ejsLib.c

index 3bf99d88b9ac185e49255553197488e73aa79cad..8b66dafdcaee9397febb1fd5f57f0cf349ad430d 100644 (file)
@@ -192,6 +192,8 @@ typedef struct ejEval {
        char            *tokEndp;                                       /* Pointer past end of token */
        char            *tokServp;                                      /* Pointer to next token char */
        int                     tokSize;                                        /* Size of token buffer */
+       struct ejEval *next;                    /* used for backtraces */
+       const char  *procName;                  /* gives name in backtrace */
 } EjsInput;
 
 /*
index a5f15c297955c114f559f12dc7e1bb110a6e84a0..b4617a638e7ed68853b0a142e74d56a200fb57ba 100644 (file)
@@ -60,11 +60,13 @@ int ejsLexOpenScript(Ejs *ep, char *script)
        mprAssert(ep);
        mprAssert(script);
 
-       if ((ep->input = mprMalloc(sizeof(EjsInput))) == NULL) {
+       if ((ip = mprMalloc(sizeof(EjsInput))) == NULL) {
                return -1;
        }
-       ip = ep->input;
        memset(ip, 0, sizeof(*ip));
+       ip->next = ep->input;
+       ep->input = ip;
+       ip->procName = ep->proc?ep->proc->procName:NULL;
 
 /*
  *     Create the parse token buffer and script buffer
@@ -102,6 +104,7 @@ void ejsLexCloseScript(Ejs *ep)
 
        ip = ep->input;
        mprAssert(ip);
+       ep->input = ip->next;
 
        for (i = 0; i < EJS_TOKEN_STACK; i++) {
                mprFree(ip->putBack[i].token);
index b3e61ec3752212fcbcb4281fb685b2adf4db312e..eed6d67fb42025744e1898b06483466a4d91d34c 100644 (file)
@@ -385,7 +385,6 @@ int ejsEvalBlock(EjsId eid, char *script, MprVar *vp, char **emsg)
 int ejsEvalScript(EjsId eid, char *script, MprVar *vp, char **emsg)
 {
        Ejs                     *ep;
-       EjsInput        *oldBlock;
        int                     state;
        void            *endlessLoopTest;
        int                     loopCounter;
@@ -408,7 +407,6 @@ int ejsEvalScript(EjsId eid, char *script, MprVar *vp, char **emsg)
        /*
         *      Allocate a new evaluation block, and save the old one
         */
-       oldBlock = ep->input;
        ejsLexOpenScript(ep, script);
 
        /*
@@ -447,11 +445,6 @@ int ejsEvalScript(EjsId eid, char *script, MprVar *vp, char **emsg)
                *emsg = mprStrdup(ep->error);
        }
 
-       /*
-        *      Restore the old evaluation block
-        */
-       ep->input = oldBlock;
-
        if (state == EJS_STATE_ERR) {
                return -1;
        }
@@ -475,24 +468,31 @@ static void ejsErrorCore(Ejs* ep, const char *fmt, va_list args)
 {
        EjsInput        *ip;
        char            *errbuf, *msgbuf;
+       int frame = 0;
 
        mprAssert(ep);
 
        msgbuf = NULL;
        mprAllocVsprintf(&msgbuf, MPR_MAX_STRING, fmt, args);
 
-       if (ep) {
-               ip = ep->input;
-               if (ip) {
-                       mprAllocSprintf(&errbuf, MPR_MAX_STRING,
-                               "%s\nError on line %d. Offending line: %s\n\n",
-                               msgbuf, ip->lineNumber, ip->line);
-               } else {
-                       mprAllocSprintf(&errbuf, MPR_MAX_STRING, "%s\n", msgbuf);
-               }
-               mprFree(ep->error);
-               ep->error = errbuf;
+       ip = ep->input;
+       mprAllocSprintf(&errbuf, MPR_MAX_STRING, "%s\nBacktrace:\n", msgbuf);
+
+       /* form a backtrace */
+       while (ip) {
+               char *msg2, *ebuf2;
+               mprAllocSprintf(&msg2, MPR_MAX_STRING,
+                                               "\t[%2d] %20s:%-4d -> %s\n",
+                                               frame++, ip->procName?ip->procName:"", ip->lineNumber, ip->line);
+               ebuf2 = mprRealloc(errbuf, strlen(errbuf) + strlen(msg2) + 1);
+               if (ebuf2 == NULL) break;
+               errbuf = ebuf2;
+               memcpy(errbuf+strlen(errbuf), msg2, strlen(msg2)+1);
+               mprFree(msg2);
+               ip = ip->next;
        }
+       mprFree(ep->error);
+       ep->error = errbuf;
        mprFree(msgbuf);
 }