RPA Toolkit
Use external array to write the parse records. Added 'abort' directive to RPA. Added...
authorMartin Stoilov <martin@rpasearch.com>
Tue, 24 May 2011 06:47:19 +0000 (23:47 -0700)
committerMartin Stoilov <martin@rpasearch.com>
Tue, 24 May 2011 06:47:19 +0000 (23:47 -0700)
37 files changed:
rgrep/rpagrep.c
rgrep/rpagrep.h
rgrep/unix/main.c
rjs/ecma262.rpa
rjs/rjs.c
rjs/rjs.h
rjs/rjscompiler.c
rjs/rjscompiler.h
rjs/rjserror.h [new file with mode: 0644]
rjs/rjsexec.c
rjs/rjsparser.c
rjs/rjsparser.h
rpa/rpacache.c
rpa/rpacompiler.c
rpa/rpadbex.c
rpa/rpaerror.h
rpa/rpaparser.c
rpa/rpaparser.h
rpa/rparecord.c
rpa/rparecord.h
rpa/rpastat.c
rpa/rpastat.h
rpa/rpastatpriv.h
rpa/rpavm.c
rpa/rpavm.h
tests/testrpa/rpacompiler-altexp.c
tests/testrpa/rpacompiler-class.c
tests/testrpa/rpacompiler-exp.c
tests/testrpa/rpacompiler-minusexp.c
tests/testrpa/rpacompiler-notexp.c
tests/testrpa/rpacompiler-rule.c
tests/testrpa/rpacompiler-rulealtrec.c
tests/testrpa/rpacompiler-rulerec.c
tests/testrpa/rpavm-matchchr.c
tests/testrpa/rpavm-matchrng.c
tests/testrpa/rpavm-mnode.c
tests/testrpa/rpavm-ref.c

index 621568f..fa2d712 100644 (file)
@@ -212,7 +212,7 @@ int rpa_grep_match(rpa_grep_t *pGrep, const char* buffer, unsigned long size)
        if (!hStat)
                return -1;
        rpa_stat_cachedisable(hStat, pGrep->disablecache);
-       rpa_stat_encodingset(hStat, pGrep->encoding);
+       rpa_stat_setencoding(hStat, pGrep->encoding);
        hStat->debug = pGrep->execdebug;
        ret = rpa_stat_match(hStat, pGrep->hPattern, input, start, end);
        if (ret > 0) {
@@ -221,9 +221,6 @@ int rpa_grep_match(rpa_grep_t *pGrep, const char* buffer, unsigned long size)
                rpa_grep_output_utf8_string(pGrep, "\n");
        }
        pGrep->cachehit = hStat->cache->hit;
-       pGrep->orphrecords = r_array_length(hStat->orphans);
-       pGrep->emitstacksize = r_array_length(hStat->emitstack);
-
        rpa_stat_destroy(hStat);
        return 0;
 }
@@ -231,10 +228,11 @@ int rpa_grep_match(rpa_grep_t *pGrep, const char* buffer, unsigned long size)
 
 int rpa_grep_parse(rpa_grep_t *pGrep, const char* buffer, unsigned long size)
 {
+       rlong ret;
        rlong i;
        rchar location[128];
        rpastat_t *hStat;
-       rarray_t *records = NULL;
+       rarray_t *records = rpa_record_array();
        rparecord_t *prec;
        const char *input = buffer, *start = buffer, *end = buffer + size;
 
@@ -242,10 +240,31 @@ int rpa_grep_parse(rpa_grep_t *pGrep, const char* buffer, unsigned long size)
        if (!hStat)
                return -1;
        rpa_stat_cachedisable(hStat, pGrep->disablecache);
-       rpa_stat_encodingset(hStat, pGrep->encoding);
+       rpa_stat_setencoding(hStat, pGrep->encoding);
        hStat->debug = pGrep->execdebug;
-       rpa_stat_parse(hStat, pGrep->hPattern, input, start, end, &records);
-       if (records) {
+       ret = rpa_stat_parse(hStat, pGrep->hPattern, input, start, end, records);
+       if (ret < 0) {
+               rpa_errinfo_t err;
+               rpa_stat_lasterrorinfo(hStat, &err);
+               if (err.code) {
+                       r_snprintf(location, sizeof(location), "Parse Error: Code: %ld", err.code);
+                       rpa_grep_output_utf8_string(pGrep, location);
+               }
+               if (err.ruleid) {
+                       r_snprintf(location, sizeof(location), ", Rule UID: %ld", err.ruleid);
+                       rpa_grep_output_utf8_string(pGrep, location);
+               }
+               if (*err.name) {
+                       r_snprintf(location, sizeof(location), ", Name: %s", err.name);
+                       rpa_grep_output_utf8_string(pGrep, location);
+               }
+               if (err.offset) {
+                       r_snprintf(location, sizeof(location), " at Offset: %ld", err.offset);
+                       rpa_grep_output_utf8_string(pGrep, location);
+               }
+               rpa_grep_output_utf8_string(pGrep, "\n");
+
+       } else {
                if (pGrep->greptype == RPA_GREPTYPE_PARSE) {
                        for (i = 0; i < r_array_length(records); i++) {
                                prec = (rparecord_t *)r_array_slot(records, i);
@@ -264,12 +283,9 @@ int rpa_grep_parse(rpa_grep_t *pGrep, const char* buffer, unsigned long size)
                        }
 
                }
-               r_array_destroy(records);
        }
+       r_array_destroy(records);
        pGrep->cachehit = hStat->cache->hit;
-       pGrep->orphrecords = r_array_length(hStat->orphans);
-       pGrep->emitstacksize = r_array_length(hStat->emitstack);
-
        rpa_stat_destroy(hStat);
        return 0;
 }
@@ -286,16 +302,14 @@ int rpa_grep_scan(rpa_grep_t *pGrep, const char* buffer, unsigned long size)
        hStat = rpa_stat_create(pGrep->hDbex, 0);
        if (!hStat)
                return -1;
-       rpa_stat_encodingset(hStat, pGrep->encoding);
+       rpa_stat_setencoding(hStat, pGrep->encoding);
        rpa_stat_cachedisable(hStat, pGrep->disablecache);
        hStat->debug = pGrep->execdebug;
        pGrep->cachehit = hStat->cache->hit;
-       pGrep->orphrecords = r_array_length(hStat->orphans);
 
 again:
        ret = rpa_stat_scan(hStat, pGrep->hPattern, input, start, end, &matched);
        pGrep->cachehit += hStat->cache->hit;
-       pGrep->orphrecords += r_array_length(hStat->orphans);
 
        if (ret > 0) {
                if (!displayed) {
@@ -309,8 +323,6 @@ again:
                input = matched + ret;
                goto again;
        }
-
-       pGrep->emitstacksize = r_array_length(hStat->emitstack);
        rpa_stat_destroy(hStat);
        return 0;
 }
@@ -328,7 +340,7 @@ int rpa_grep_scan_lines(rpa_grep_t *pGrep, const char* buffer, unsigned long siz
        hStat = rpa_stat_create(pGrep->hDbex, 0);
        if (!hStat)
                return -1;
-       rpa_stat_encodingset(hStat, pGrep->encoding);
+       rpa_stat_setencoding(hStat, pGrep->encoding);
        hStat->debug = pGrep->execdebug;
        
 again:
index 6ee1f82..e686681 100644 (file)
@@ -50,8 +50,6 @@ typedef struct rpa_grep_s {
        unsigned long scanmilisec;
        unsigned long usedstack;
        unsigned long cachehit;
-       unsigned long orphrecords;
-       unsigned long emitstacksize;            // Must be ZERO, if not something is going wrong
        unsigned int icase;
        unsigned int encoding;
        unsigned int greptype;
index 9409679..5e566dd 100644 (file)
@@ -290,10 +290,9 @@ end:
                        milsec = 1;
                minutes = milsec/60000;
                sec = (milsec%60000)/1000.0;
-               fprintf(stdout, "\ntime: %0ldm%1.3fs, %ld KB (%ld KB/sec), stack: %ld KB, memory: %ld KB (leaked %ld Bytes), cachehit: %ld, "
-                               "orphan records: %ld, emitstacksize: %ld\n",
+               fprintf(stdout, "\ntime: %0ldm%1.3fs, %ld KB (%ld KB/sec), stack: %ld KB, memory: %ld KB (leaked %ld Bytes), cachehit: %ld \n",
                                minutes, sec, sckb, 1000*sckb/milsec, pGrep->usedstack / 1000, (rlong)r_debug_get_maxmem()/1000, (rlong)r_debug_get_allocmem(),
-                               pGrep->cachehit, pGrep->orphrecords, pGrep->emitstacksize);
+                               pGrep->cachehit);
        }
 
        rpa_grep_destroy(pGrep);
index 0c6451c..b427315 100644 (file)
 #!emit sqstring
 
 #!emitid SyntaxError                                   UID_SYNTAXERROR                                         1
-#!emitid FunctionSyntaxError                   UID_FUNCTIONSYNTAXERROR                         1
-#!emitid BlockSyntaxError                              UID_BLOCKSYNTAXERROR                            1
-#!emitid GlobalSyntaxError                             UID_GLOBALSYNTAXERROR                           1
-#!emitid IndexSyntaxError                              UID_INDEXSYNTAXERROR                            1
-#!emitid MultiplicativeSyntaxError             UID_MULTIPLICATIVESYNTAXERROR           1
-#!emitid AdditiveSyntaxError                   UID_ADDITIVESYNTAXERROR                         1
 #!emitid AdditiveOperator                              UID_BINARYOPERATOR                                      2
 #!emitid AdditiveOperator                              UID_ADDITIVEOPERATOR                            2
 #!emitid MultiplicativeOperator                        UID_MULTIPLICATIVEOPERATOR                      2
@@ -95,6 +89,9 @@
 #!emitid DoWhileExpressionCompare              UID_DOWHILEEXPRESSIONCOMPARE            59
 #!emitid Program                                               UID_PROGRAM                                             60
 
+#!abort AbortIfNotSC
+#!abort AbortIfNotMultiplicativeExpression
+
 
 # 6 Source Text
 SourceCharacter                        ::= .
@@ -109,6 +106,7 @@ S                                           ::= ( <WhiteSpace> | <LineTerminator> )+
 SC                                             ::= <S>? ';' <S>?
 COMMA                                  ::= <S>? ',' <S>?
 EQ                                             ::= <S>? '=' <S>?
+AbortIfNotSC                   ::= <SC>
 
 # 7.4 Comments
 Comment                                        ::= <MultiLineComment> | <SingleLineComment>
@@ -208,9 +206,10 @@ Elision                                                    ::= ',' <S>? <Elision> | <S>? ','
 
 
 # 11.2 Left-Hand-Side Expressions
-IndexSyntaxError                               ::= '[' (. - <SC>)*
+LSB                                                            ::= <S>? '[' <S>?
+RSB                                                            ::= <S>? ']' <S>?
 MemberExpressionBase                   ::= <MemberExpression>
-MemberExpressionIndexOp                        ::= <MemberExpressionBase> <S>? (('[' <S>? <Expression> <S>? ']' <S>?) | <IndexSyntaxError>) 
+MemberExpressionIndexOp                        ::= <MemberExpressionBase> <LSB> <Expression> <RSB>
 MemberExpressionDotOp                  ::= <MemberExpressionBase> '.' <IdentifierName>
 
 MemberExpression                               ::= <MemberExpressionIndexOp>  |
@@ -260,16 +259,15 @@ UnaryExpression                           ::=     <UnaryExpressionOp> | <PrefixExpression>
 
 
 # 11.5 Multiplicative Operators
-MultiplicativeSyntaxError              ::= <MultiplicativeOperator>  
 MultiplicativeOperator                         ::= '*' | '/' | '%'
-MultiplicativeExpressionOp             ::= <MultiplicativeExpression> <S>? ((<MultiplicativeOperator> <S>? <UnaryExpression>) | <MultiplicativeSyntaxError>)
+MultiplicativeExpressionOp             ::= <MultiplicativeExpression> <S>? <MultiplicativeOperator> <S>? <UnaryExpression>
 MultiplicativeExpression               ::= <MultiplicativeExpressionOp> | 
                                                                        <UnaryExpression>
 
 # 11.6 Additive Operators
-AdditiveSyntaxError                            ::= <AdditiveOperator>  
 AdditiveOperator                               ::= '+' | '-'
-AdditiveExpressionOp                   ::= <AdditiveExpression> <S>? ((<AdditiveOperator> <S>? <MultiplicativeExpression>) | <AdditiveSyntaxError>)
+AbortIfNotMultiplicativeExpression     ::= <MultiplicativeExpression>
+AdditiveExpressionOp                   ::= <AdditiveExpression> <S>? <AdditiveOperator> <S>? <AbortIfNotMultiplicativeExpression>
 AdditiveExpression                             ::= <AdditiveExpressionOp> | 
                                                                        <MultiplicativeExpression>
 
@@ -350,11 +348,11 @@ Statement                                         ::= <FunctionDeclarationStatement> |
                                                                <SwitchStatementOp>
 
 # 12.1 Block
-Block                                                          ::= <S>? '{' <S>? <StatementList>? <S>? ('}' | <BlockSyntaxError>) <S>?
+Block                                                          ::= <S>? '{' <S>? <StatementList>? <S>? '}' <S>?
 StatementList                                          ::= (<S>? <Statement>)+
 
 # 12.2 Variable Statement
-VariableStatement                                      ::= 'var' <S>? <VariableDeclarationList> <SC>
+VariableStatement                                      ::= 'var' <S>? <VariableDeclarationList> <AbortIfNotSC>
 VariableDeclarationList                        ::= <VariableDeclaration> (<COMMA> <VariableDeclaration> )*
 VariableAllocate                                       ::= <IdentifierNoEmit>
 VariableAllocateAndInit                                ::= <IdentifierNoEmit>
@@ -366,7 +364,7 @@ Initialiser                                                 ::= <EQ> <AssignmentExpression>
 EmptyStatement                                         ::= <SC>
 
 # 12.4 Expression Statement
-ExpressionStatement                            ::= (<Expression> - ('function' | '{')) <SC>
+ExpressionStatement                            ::= (<Expression> - ('function' | '{')) <AbortIfNotSC>
 
 
 # 12.5 The if Statement
@@ -379,7 +377,7 @@ IfStatement                                                 ::= <IfConditionOp> <S>? <IfTrueStatement> <S>? 'else' <S>? <I
 # 12.6 Iteration Statements
 # 12.6a Iteration do ... while() 
 DoWhileExpressionCompare                       ::= <Expression>
-IterationDo                                                    ::= 'do' <S>? <Statement> <S>? 'while' <S>? '(' <S>? <DoWhileExpressionCompare> <S>? ')' (<S>? ';')
+IterationDo                                                    ::= 'do' <S>? <Statement> <S>? 'while' <S>? '(' <S>? <DoWhileExpressionCompare> <S>? ')' <AbortIfNotSC>
 
 # 12.6b Iteration while()
 WhileExpressionCompare                         ::= <Expression>
@@ -399,16 +397,16 @@ IterationStatement                                        ::= <IterationWhile> |
                                                                        <IterationDo>
 
 # 12.9 The return Statement
-ReturnOp                                                       ::= ('return' - 'return' <IdentifierPart>) <WhiteSpace>* <AssignmentExpression>? (<S>? ';')
-ReturnStatement                                                ::= ('return' - 'return' <IdentifierPart>) <WhiteSpace>* <AssignmentExpression>? (<S>? ';')
+ReturnOp                                                       ::= ('return' - 'return' <IdentifierPart>) <WhiteSpace>* <AssignmentExpression>? <AbortIfNotSC>
+ReturnStatement                                                ::= ('return' - 'return' <IdentifierPart>) <WhiteSpace>* <AssignmentExpression>? <AbortIfNotSC>
 
 # The Break Statement
 BreakOp                                                                ::= 'break' - 'break' <IdentifierPart>
-BreakStatement                                         ::= <S>? <BreakOp> <SC>
+BreakStatement                                         ::= <S>? <BreakOp> <AbortIfNotSC>
 
 # The Continue Statement
 ContinueOp                                                     ::= 'continue' - 'continue' <IdentifierPart>
-ContinueStatement                                      ::= <S>? <ContinueOp> <SC>
+ContinueStatement                                      ::= <S>? <ContinueOp> <AbortIfNotSC>
 
 
 
@@ -434,13 +432,12 @@ DefaultClauseOp                                           ::= <DefaultKeywordOp> <S>? ':' <S>? <StatementList>?
 
 # 13 Function Definition
 FunctionName                                           ::= <IdentifierNoEmit>
-FunctionDeclaration                                    ::= ('function'-'function'<IdentifierPart>)<S>?<FunctionName><S>?'('<S>?<FormalParameterList>?<S>?')'<S>?'{'<S>?<FunctionBody>?<S>? ('}' | <FunctionSyntaxError>)
-FunctionExpression                                     ::= ('function'-'function'<IdentifierPart>)<S>?<FunctionName>?<S>?'('<S>?<FormalParameterList>?<S>?')'<S>?'{'<S>?<FunctionBody>?<S>?('}' | <FunctionSyntaxError>)
+FunctionDeclaration                                    ::= ('function'-'function'<IdentifierPart>)<S>?<FunctionName><S>?'('<S>?<FormalParameterList>?<S>?')'<S>?'{'<S>?<FunctionBody>?<S>?'}'
+FunctionExpression                                     ::= ('function'-'function'<IdentifierPart>)<S>?<FunctionName>?<S>?'('<S>?<FormalParameterList>?<S>?')'<S>?'{'<S>?<FunctionBody>?<S>?'}'
 FormalParameterList                            ::= <FunctionParameter> ( <S>? ',' <S>? <FunctionParameter> )*
 FunctionParameter                                      ::= <IdentifierNoEmit>
-# FunctionBody                                         ::= <SourceElements>
-FunctionBody                                           ::= (<S>? (<SourceElement> ))+
-FunctionDeclarationStatement           ::= ('function' - 'function' <IdentifierPart>)<S>?<FunctionName><S>?'('<S>?<FormalParameterList>?<S>?')' <SC>
+FunctionBody                                           ::= <SourceElements>
+FunctionDeclarationStatement           ::= ('function' - 'function' <IdentifierPart>)<S>?<FunctionName><S>?'('<S>?<FormalParameterList>?<S>?')' <AbortIfNotSC>
 
 # FunctionName                                         ::= <IdentifierNoEmit>
 # FunctionNameLookupAlloc                      ::= <IdentifierNoEmit>
@@ -449,19 +446,15 @@ FunctionDeclarationStatement              ::= ('function' - 'function' <IdentifierPart>)<S>?
 # FunctionExpression                           ::= ('function' - 'function'<IdentifierPart>)<S>?<FunctionName>?<S>?'('<S>?<FormalParameterList>?<S>?')'<S>?'{'<S>?<FunctionBody>?<S>?'}'
 # FunctionParameter                            ::= <Identifier>
 # FormalParameterList                          ::= <FunctionParameter> ( <S>? ',' <S>? <FunctionParameter> )*
-# FunctionDefinitionStatement          ::= ('function' - 'function' <IdentifierPart>)<S>?<FunctionNameLookupAlloc><S>?'('<S>?<FormalParameterList>?<S>?')' <SC>
+# FunctionDefinitionStatement          ::= ('function' - 'function' <IdentifierPart>)<S>?<FunctionNameLookupAlloc><S>?'('<S>?<FormalParameterList>?<S>?')' <AbortIfNotSC>
 # FunctionBody                                         ::= <SourceElements>
 
 
 # 14 Program
-BlockSyntaxError                               ::= (. - '}')+ '}'
-FunctionSyntaxError                            ::= (. - '}')+ '}'
-GlobalSyntaxError                              ::= (. - <SC>)+
-
 SourceElements                                         ::= (<S>? <SourceElement>)+
 SourceElement                                  ::= <FunctionDeclaration> |
                                                                <Statement> 
-Program                                                        ::= <SourceElements> | <GlobalSyntaxError>
+Program                                                        ::= <SourceElements>
 # The root rule, it is anonymous
 <Program>
 
index 2230b47..016c027 100644 (file)
--- a/rjs/rjs.c
+++ b/rjs/rjs.c
@@ -31,6 +31,7 @@ rjs_engine_t *rjs_engine_create()
        jse->cpu = rvm_cpu_create_default();
        jse->co = rjs_compiler_create(jse->cpu);
        jse->cgs = r_array_create(sizeof(rvm_codegen_t*));
+       jse->errors = r_array_create(sizeof(rjs_error_t));
        rvm_cpu_addswitable(jse->cpu, "rjsswitable", rjsswitable);
        if (!jse->pa || !jse->cpu || !jse->co || !jse->cgs)
                goto error;
@@ -55,6 +56,7 @@ void rjs_engine_destroy(rjs_engine_t *jse)
                        }
                }
                r_array_destroy(jse->cgs);
+               r_array_destroy(jse->errors);
                rjs_parser_destroy(jse->pa);
                rvm_cpu_destroy(jse->cpu);
                rjs_compiler_destroy(jse->co);
@@ -69,10 +71,15 @@ rint rjs_engine_open(rjs_engine_t *jse)
 }
 
 
-static rint rjs_engine_parse(rjs_engine_t *jse, const rchar *script, rsize_t size, rarray_t **records)
+static rint rjs_engine_parse(rjs_engine_t *jse, const rchar *script, rsize_t size, rarray_t *records)
 {
        rlong res = 0;
-       res = rjs_parser_exec(jse->pa, script, size, records);
+       rjs_error_t error;
+
+       r_memset(&error, 0, sizeof(error));
+       res = rjs_parser_exec(jse->pa, script, size, records, &error);
+       if (res < 0)
+               r_array_add(jse->errors, &error);
        return res;
 }
 
@@ -80,10 +87,10 @@ static rint rjs_engine_parse(rjs_engine_t *jse, const rchar *script, rsize_t siz
 rint rjs_engine_compile(rjs_engine_t *jse, const rchar *script, rsize_t size)
 {
        rvm_codegen_t *topcg = NULL;
-       rarray_t *records = NULL;
+       rarray_t *records = rpa_record_array();
        jse->co->debug = jse->debugcompile;
 
-       if (rjs_engine_parse(jse, script, size, &records) < 0) {
+       if (rjs_engine_parse(jse, script, size, records) < 0) {
 
                goto err;
        }
@@ -112,8 +119,8 @@ err:
 
 rint rjs_engine_dumpast(rjs_engine_t *jse, const rchar *script, rsize_t size)
 {
-       rarray_t *records = NULL;
-       if (rjs_engine_parse(jse, script, size, &records) < 0) {
+       rarray_t *records = rpa_record_array();
+       if (rjs_engine_parse(jse, script, size, records) < 0) {
 
 
                return -1;
index 5070116..3630edc 100644 (file)
--- a/rjs/rjs.h
+++ b/rjs/rjs.h
@@ -10,11 +10,14 @@ extern "C" {
 #include "rvmcpu.h"
 #include "rjsparser.h"
 #include "rjscompiler.h"
+#include "rjserror.h"
+
 
 typedef struct rjs_engine_s {
        rjs_parser_t *pa;
        rjs_compiler_t *co;
        rarray_t *cgs;
+       rarray_t *errors;
        rvmcpu_t *cpu;
        rlong debugcompile:1;
        rlong debugexec:1;
index 0a9ac19..85d48ee 100644 (file)
@@ -24,13 +24,11 @@ void rjs_compiler_debugtail(rjs_compiler_t *co, rarray_t *records, rlong rec)
 }
 
 
-void rjs_compiler_adderror(rjs_compiler_t *co, rlong code, const rchar *script, rlong scriptsize)
+void rjs_compiler_adderror(rjs_compiler_t *co, rlong code, const rchar *script)
 {
-       rjs_coerror_t error;
-       error.code = code;
-       error.script = script;
-       error.scriptsize = scriptsize;
-       r_array_add(co->errors, &error);
+       /*
+        * Not used for now. I should probably get rid of this altogether.
+        */
 }
 
 
@@ -370,7 +368,7 @@ rint rjs_compiler_rh_identifier(rjs_compiler_t *co, rarray_t *records, rlong rec
                        goto end;
                }
 
-               rjs_compiler_adderror(co, RJS_ERROR_UNDEFINED, prec->input, prec->inputsiz);
+               rjs_compiler_adderror(co, RJS_ERROR_UNDEFINED, prec->input);
                return 0;
        }
 
@@ -752,7 +750,7 @@ rint rjs_compiler_rh_functionparameter(rjs_compiler_t *co, rarray_t *records, rl
         */
        ctx = rjs_compiler_getctx(co, RJS_COCTX_FUNCTION);
        if (!ctx) {
-               rjs_compiler_adderror(co, RJS_ERROR_NOTAFUNCTION, prec->input, prec->inputsiz);
+               rjs_compiler_adderror(co, RJS_ERROR_NOTAFUNCTION, prec->input);
                return 0;
        }
        R_ASSERT(ctx);
@@ -833,7 +831,7 @@ rint rjs_compiler_rh_argument(rjs_compiler_t *co, rarray_t *records, rlong rec)
        prec = (rparecord_t *)r_array_slot(records, rec);
        rjs_compiler_debughead(co, records, rec);
        if (!ctx) {
-               rjs_compiler_adderror(co, RJS_ERROR_NOTAFUNCTIONCALL, prec->input, prec->inputsiz);
+               rjs_compiler_adderror(co, RJS_ERROR_NOTAFUNCTIONCALL, prec->input);
                return 0;
        }
        R_ASSERT(ctx);
@@ -860,7 +858,7 @@ rint rjs_compiler_rh_arguments(rjs_compiler_t *co, rarray_t *records, rlong rec)
        prec = (rparecord_t *)r_array_slot(records, rec);
        rjs_compiler_debughead(co, records, rec);
        if (!ctx) {
-               rjs_compiler_adderror(co, RJS_ERROR_NOTAFUNCTIONCALL, prec->input, prec->inputsiz);
+               rjs_compiler_adderror(co, RJS_ERROR_NOTAFUNCTIONCALL, prec->input);
                return 0;
        }
        R_ASSERT(ctx);
@@ -940,7 +938,7 @@ rint rjs_compiler_rh_ifconditionop(rjs_compiler_t *co, rarray_t *records, rlong
        prec = (rparecord_t *)r_array_slot(records, rec);
        rjs_compiler_debughead(co, records, rec);
        if (!ctx) {
-               rjs_compiler_adderror(co, RJS_ERROR_NOTAIFSTATEMENT, prec->input, prec->inputsiz);
+               rjs_compiler_adderror(co, RJS_ERROR_NOTAIFSTATEMENT, prec->input);
                return 0;
        }
        R_ASSERT(ctx);
@@ -964,7 +962,7 @@ rint rjs_compiler_rh_iftruestatement(rjs_compiler_t *co, rarray_t *records, rlon
        prec = (rparecord_t *)r_array_slot(records, rec);
        rjs_compiler_debughead(co, records, rec);
        if (!ctx) {
-               rjs_compiler_adderror(co, RJS_ERROR_NOTAIFSTATEMENT, prec->input, prec->inputsiz);
+               rjs_compiler_adderror(co, RJS_ERROR_NOTAIFSTATEMENT, prec->input);
                return 0;
        }
        R_ASSERT(ctx);
@@ -990,7 +988,7 @@ rint rjs_compiler_rh_iffalsestatement(rjs_compiler_t *co, rarray_t *records, rlo
        prec = (rparecord_t *)r_array_slot(records, rec);
        rjs_compiler_debughead(co, records, rec);
        if (!ctx) {
-               rjs_compiler_adderror(co, RJS_ERROR_NOTAIFSTATEMENT, prec->input, prec->inputsiz);
+               rjs_compiler_adderror(co, RJS_ERROR_NOTAIFSTATEMENT, prec->input);
                return 0;
        }
        R_ASSERT(ctx);
@@ -1171,7 +1169,7 @@ rint rjs_compiler_rh_dowhileexpressioncompare(rjs_compiler_t *co, rarray_t *reco
        prec = (rparecord_t *)r_array_slot(records, rec);
        rjs_compiler_debughead(co, records, rec);
        if (!ctx) {
-               rjs_compiler_adderror(co, RJS_ERROR_NOTALOOP, prec->input, prec->inputsiz);
+               rjs_compiler_adderror(co, RJS_ERROR_NOTALOOP, prec->input);
                return 0;
        }
        R_ASSERT(ctx);
@@ -1198,7 +1196,7 @@ rint rjs_compiler_rh_forexpressioncompare(rjs_compiler_t *co, rarray_t *records,
        prec = (rparecord_t *)r_array_slot(records, rec);
        rjs_compiler_debughead(co, records, rec);
        if (!ctx) {
-               rjs_compiler_adderror(co, RJS_ERROR_NOTALOOP, prec->input, prec->inputsiz);
+               rjs_compiler_adderror(co, RJS_ERROR_NOTALOOP, prec->input);
                return 0;
        }
        R_ASSERT(ctx);
@@ -1224,7 +1222,7 @@ rint rjs_compiler_rh_forexpressionincrement(rjs_compiler_t *co, rarray_t *record
        prec = (rparecord_t *)r_array_slot(records, rec);
        rjs_compiler_debughead(co, records, rec);
        if (!ctx) {
-               rjs_compiler_adderror(co, RJS_ERROR_NOTALOOP, prec->input, prec->inputsiz);
+               rjs_compiler_adderror(co, RJS_ERROR_NOTALOOP, prec->input);
                return 0;
        }
        R_ASSERT(ctx);
@@ -1436,7 +1434,7 @@ rint rjs_compiler_rh_continue(rjs_compiler_t *co, rarray_t *records, rlong rec)
        prec = (rparecord_t *)r_array_slot(records, rec);
        rjs_compiler_debughead(co, records, rec);
        if (!ctx) {
-               rjs_compiler_adderror(co, RJS_ERROR_NOTALOOP, prec->input, prec->inputsiz);
+               rjs_compiler_adderror(co, RJS_ERROR_NOTALOOP, prec->input);
                return 0;
        }
        R_ASSERT(ctx);
@@ -1466,7 +1464,7 @@ rint rjs_compiler_rh_break(rjs_compiler_t *co, rarray_t *records, rlong rec)
        prec = (rparecord_t *)r_array_slot(records, rec);
        rjs_compiler_debughead(co, records, rec);
        if (!ctx) {
-               rjs_compiler_adderror(co, RJS_ERROR_NOTALOOP, prec->input, prec->inputsiz);
+               rjs_compiler_adderror(co, RJS_ERROR_NOTALOOP, prec->input);
                return 0;
        }
        R_ASSERT(ctx);
@@ -1498,7 +1496,7 @@ rint rjs_compiler_rh_syntaxerror(rjs_compiler_t *co, rarray_t *records, rlong re
        rec = rpa_recordtree_get(records, rec, RPA_RECORD_END);
        prec = (rparecord_t *)r_array_slot(records, rec);
        rjs_compiler_debughead(co, records, rec);
-       rjs_compiler_adderror(co, RJS_ERROR_SYNTAX, prec->input, prec->inputsiz);
+       rjs_compiler_adderror(co, RJS_ERROR_SYNTAX, prec->input);
        rjs_compiler_debugtail(co, records, rec);
        return 0;
 }
@@ -1528,7 +1526,6 @@ rjs_compiler_t *rjs_compiler_create(rvmcpu_t *cpu)
 
        co->scope = rvm_scope_create();
        co->coctx = r_array_create(sizeof(rjs_coctx_t *));
-       co->errors = r_array_create(sizeof(rjs_coerror_t));
        co->cpu = cpu;
        r_memset(co->handlers, 0, sizeof(co->handlers));
 
@@ -1597,7 +1594,6 @@ void rjs_compiler_destroy(rjs_compiler_t *co)
        if (co) {
                rvm_scope_destroy(co->scope);
                r_array_destroy(co->coctx);
-               r_array_destroy(co->errors);
                r_free(co->temp);
                co->cpu = NULL;
                r_free(co);
@@ -1675,7 +1671,6 @@ rint rjs_compiler_compile(rjs_compiler_t *co, rarray_t *records, rvm_codegen_t *
        }
        co->cg = cg;
 
-       r_array_setlength(co->errors, 0);
        for (i = 0; i >= 0; i = rpa_recordtree_next(records, i, RPA_RECORD_START)) {
                if (rjs_compiler_playrecord(co, records, i) < 0)
                        /*
@@ -1684,13 +1679,6 @@ rint rjs_compiler_compile(rjs_compiler_t *co, rarray_t *records, rvm_codegen_t *
                        return -1;
        }
 
-       if (r_array_length(co->errors)) {
-               /*
-                * TBD
-                */
-               return -1;
-       }
-
        if (rvm_codegen_relocate(co->cg, &labelerr) < 0) {
                /*
                 * TBD
index 7a654cd..1524d61 100644 (file)
@@ -13,6 +13,7 @@ extern "C" {
 #include "rvmcpu.h"
 #include "rjsuids.h"
 #include "rparecord.h"
+#include "rjserror.h"
 
 #define RJS_COMPILER_NHANDLERS 128
 #define RJS_COMPILER_CODEGENKEEP (1 << 0)
@@ -25,13 +26,6 @@ extern "C" {
 #define RJS_COCTX_ITERATION (1 << 5)
 #define RJS_COCTX_OPERATION (1 << 5)
 
-#define RJS_ERROR_NONE 0
-#define RJS_ERROR_UNDEFINED 1
-#define RJS_ERROR_SYNTAX 2
-#define RJS_ERROR_NOTAFUNCTION 3
-#define RJS_ERROR_NOTAFUNCTIONCALL 4
-#define RJS_ERROR_NOTALOOP 5
-#define RJS_ERROR_NOTAIFSTATEMENT 6
 
 typedef struct rjs_coctx_s {
        rulong type;
@@ -85,12 +79,6 @@ typedef struct rjs_coctx_iteration_s {
 } rjs_coctx_iteration_t;
 
 
-typedef struct rjs_coerror_s {
-       rlong code;
-       const rchar *script;
-       rlong scriptsize;
-} rjs_coerror_t;
-
 
 typedef struct rjs_compiler_s rjs_compiler_t;
 typedef rint (*RJS_COMPILER_RH)(rjs_compiler_t *co, rarray_t *records, rlong rec);
@@ -100,7 +88,6 @@ struct rjs_compiler_s {
        rvm_codegen_t *cg;
        rvm_scope_t *scope;
        rarray_t *coctx;
-       rarray_t *errors;
        rchar *temp;
        rlong headoff;
        rlong opcode;
diff --git a/rjs/rjserror.h b/rjs/rjserror.h
new file mode 100644 (file)
index 0000000..c08db31
--- /dev/null
@@ -0,0 +1,28 @@
+#ifndef _RJSERROR_H_
+#define _RJSERROR_H_
+
+
+#define RJS_ERRORTYPE_NONE 0
+#define RJS_ERRORTYPE_SYNTAX 1
+#define RJS_ERRORTYPE_RUNTIME 2
+
+
+#define RJS_ERROR_NONE 0
+#define RJS_ERROR_UNDEFINED 1
+#define RJS_ERROR_SYNTAX 2
+#define RJS_ERROR_NOTAFUNCTION 3
+#define RJS_ERROR_NOTAFUNCTIONCALL 4
+#define RJS_ERROR_NOTALOOP 5
+#define RJS_ERROR_NOTAIFSTATEMENT 6
+
+
+typedef struct rjs_error_s {
+       rlong type;
+       rlong error;
+       rlong offset;
+       rlong line;
+       rlong lineoffset;
+} rjs_error_t;
+
+
+#endif /* RJSERROR_H_ */
index 8fac5be..faf4c17 100644 (file)
@@ -128,16 +128,14 @@ rlong jrs_offset2line(const rchar *script, rlong offset)
 
 void rjs_display_errors(rjs_engine_t *jse, rstr_t *script)
 {
-       rlong line = 0;
        rlong i;
-       rjs_coerror_t *err;
-
-       for (i = 0; i < r_array_length(jse->co->errors); i++) {
-               err = (rjs_coerror_t *)r_array_slot(jse->co->errors, i);
-               line = jrs_offset2line(script->str, (rlong)(err->script - script->str));
-               fprintf(stdout, "Line: %ld (%ld, %ld), Error Code: %ld, ", (rlong)line, (rlong)(err->script - script->str), (rlong)err->scriptsize, err->code);
-               fprintf(stdout, "%s: ", errormsg[err->code]);
-               fwrite(err->script, sizeof(rchar), err->scriptsize, stdout);
+       rjs_error_t *err;
+
+       for (i = 0; i < r_array_length(jse->errors); i++) {
+               err = (rjs_error_t *)r_array_slot(jse->errors, i);
+               fprintf(stdout, "Line: %ld (%ld, %ld), Error Code: %ld, ", (rlong)err->line, err->offset, err->lineoffset, err->error);
+               fprintf(stdout, "%s: ", errormsg[err->error]);
+               fwrite(script->str + err->lineoffset, sizeof(rchar), err->offset - err->lineoffset, stdout);
                fprintf(stdout, "\n");
        }
 }
@@ -196,7 +194,7 @@ int main(int argc, char *argv[])
        }
 
 end:
-       if (jse->co && r_array_length(jse->co->errors))
+       if (jse && r_array_length(jse->errors))
                rjs_display_errors(jse, script);
        rjs_engine_destroy(jse);
        if (unmapscript)
index 9c259c0..c31f058 100644 (file)
@@ -1,6 +1,7 @@
 #include "rmem.h"
 #include "rjsrules.h"
 #include "rjsparser.h"
+#include "rjserror.h"
 
 
 void rjs_parser_dbex_error(rjs_parser_t *parser)
@@ -62,11 +63,50 @@ void rjs_parser_destroy(rjs_parser_t *parser)
 }
 
 
-rlong rjs_parser_exec(rjs_parser_t *parser, const rchar *script, rsize_t size, rarray_t **ast)
+rlong jrs_parser_offset2line(const rchar *script, rlong offset)
+{
+       rlong line = 1;
+       const rchar *ptr;
+
+       for (line = 1, ptr = script + offset; ptr >= script; --ptr) {
+               if (*ptr == '\n')
+                       line += 1;
+       }
+
+       return line;
+}
+
+
+rlong jrs_parser_offset2lineoffset(const rchar *script, rlong offset)
+{
+       rlong lineoffset = 0;
+       const rchar *ptr;
+
+       for (lineoffset = 0, ptr = script + offset; ptr > script; --ptr) {
+               if (*ptr == '\n')
+                       break;
+               lineoffset += 1;
+       }
+       return offset - lineoffset;
+}
+
+
+rlong rjs_parser_exec(rjs_parser_t *parser, const rchar *script, rsize_t size, rarray_t *ast, rjs_error_t *error)
 {
        rlong res = 0;
        rpastat_t *stat = rpa_stat_create(parser->dbex, 4096);
        res = rpa_stat_parse(stat, rpa_dbex_last(parser->dbex), script, script, script + size, ast);
+       if (res < 0 && error) {
+               rpa_errinfo_t rpaerror;
+               rpa_stat_lasterrorinfo(stat, &rpaerror);
+               if (rpaerror.code == RPA_E_RULEABORT) {
+                       error->type = RJS_ERRORTYPE_SYNTAX;
+                       error->error = RJS_ERROR_SYNTAX;
+                       error->offset = rpaerror.offset;
+                       error->line = jrs_parser_offset2line(script, error->offset);
+                       error->lineoffset = jrs_parser_offset2lineoffset(script, error->offset);
+               }
+       }
        rpa_stat_destroy(stat);
        return res;
 }
index ebfb690..d52bf36 100644 (file)
@@ -10,6 +10,7 @@ extern "C" {
 #include "rarray.h"
 #include "rvmcpu.h"
 #include "rpa.h"
+#include "rjserror.h"
 
 
 typedef struct rjs_parser_s {
@@ -20,7 +21,7 @@ typedef struct rjs_parser_s {
 
 rjs_parser_t *rjs_parser_create();
 void rjs_parser_destroy(rjs_parser_t *parser);
-rlong rjs_parser_exec(rjs_parser_t *parser, const rchar *script, rsize_t size, rarray_t **ast);
+rlong rjs_parser_exec(rjs_parser_t *parser, const rchar *script, rsize_t size, rarray_t *ast, rjs_error_t *error);
 
 
 #ifdef __cplusplus
index 2ea8a6e..3de762d 100644 (file)
@@ -61,10 +61,11 @@ void rpa_cache_set(rpacache_t *cache, rlong top, rlong ruleid, rlong ret, rarray
        cache->entry[bucket].recsize = size;
        cache->entry[bucket].serial = cache->serial;
        r_array_setlength(cacherecords, 0);
-       for (i = 0; i < size; i++) {
-               r_array_add(cacherecords, r_array_slot(records, startrec + i));
+       if (records) {
+               for (i = 0; i < size; i++) {
+                       r_array_add(cacherecords, r_array_slot(records, startrec + i));
+               }
        }
-
 }
 
 
index 65fa969..ca4e4d2 100644 (file)
@@ -341,7 +341,7 @@ rint rpa_compiler_loop_end(rpa_compiler_t *co)
        rvm_codegen_addins(co->cg, rvm_asm(RVM_MOV, R3, R0, XX, 0));                                                //          |
        rvm_codegen_addins(co->cg, rvm_asm(RVM_MOV, R_TOP, R_OTP, XX, 0));                                          //          |
        rvm_codegen_index_addrelocins(co->cg, RVM_RELOC_BRANCH, exp.loopidx, rvm_asm(RVM_B, DA, XX, XX, 0));        //          |
-       rvm_codegen_redefinelabel_default(co->cg, exp.failidx);                                                             //          |
+       rvm_codegen_redefinelabel_default(co->cg, exp.failidx);                                                     //          |
        rvm_codegen_addins(co->cg, rvm_asm(RVM_MOV, R_REC, R1, XX, 0));          //        <-------------------------------------
        rvm_codegen_addins(co->cg, rvm_asm(RVM_MOVS, R0, DA, XX, -1));
        rvm_codegen_addins(co->cg, rvm_asm(RVM_BX, LR, XX, XX, 0));
@@ -356,7 +356,11 @@ rint rpa_compiler_loop_end(rpa_compiler_t *co)
        rvm_codegen_addins(co->cg, rvm_asm(RVM_CMP, R0, DA, XX, 0));
        rvm_codegen_addins(co->cg, rvm_asm(RVM_BGRE, DA, XX, XX, 3));
        rvm_codegen_addins(co->cg, rvm_asm(RVM_MOVS, R0, DA, XX, -1));
-       rvm_codegen_addins(co->cg, rvm_asm(RVM_BX, LR, XX, XX, 0));
+       if (exp.rulepref && (exp.rulepref->flags & RPA_RFLAG_ABORTONFAIL)) {
+               rvm_codegen_index_addrelocins(co->cg, RVM_RELOC_BLOB, exp.dataidx, rvm_asm(RPA_ABORT, DA, R_OTP, R0, 0));
+       } else {
+               rvm_codegen_addins(co->cg, rvm_asm(RVM_BX, LR, XX, XX, 0));
+       }
        rvm_codegen_addins(co->cg, rvm_asm(RVM_ADD, R_TOP, R_TOP, R3, 0));
        rvm_codegen_addins(co->cg, rvm_asm(RVM_BX, LR, XX, XX, 0));
        return 0;
@@ -419,6 +423,9 @@ rint rpa_compiler_rule_end(rpa_compiler_t *co)
        rvm_codegen_addins(co->cg, rvm_asm(RVM_BX, LR, XX, XX, 0));
        rvm_codegen_addins(co->cg, rvm_asm(RVM_MOV, R_REC, R1, XX, 0));
        rvm_codegen_addins(co->cg, rvm_asm(RVM_MOVS, R0, DA, XX, -1));
+       if (exp.rulepref && (exp.rulepref->flags & RPA_RFLAG_ABORTONFAIL)) {
+               rvm_codegen_index_addrelocins(co->cg, RVM_RELOC_BLOB, exp.dataidx, rvm_asm(RPA_ABORT, DA, R_OTP, R0, 0));
+       }
        rvm_codegen_addins(co->cg, rvm_asm(RVM_BX, LR, XX, XX, 0));
        rvm_codegen_redefinelabel_default(co->cg, exp.endidx);
        rvm_codegen_addins(co->cg, rvm_asm(RVM_POP, LR, XX, XX, 0));
@@ -427,6 +434,9 @@ rint rpa_compiler_rule_end(rpa_compiler_t *co)
        rvm_codegen_addins(co->cg, rvm_asm(RVM_MOV, R_OTP, R_TOP, XX, 0));
        rvm_codegen_addins(co->cg, rvm_asm(RVM_MOVS, R0, DA, XX, -1));
        rvm_codegen_addins(co->cg, rvm_asml(RPA_SETCACHE, DA, R_REC, R_REC, exp.start));
+       if (exp.rulepref && (exp.rulepref->flags & RPA_RFLAG_ABORTONFAIL)) {
+               rvm_codegen_index_addrelocins(co->cg, RVM_RELOC_BLOB, exp.dataidx, rvm_asm(RPA_ABORT, DA, R_OTP, R0, 0));
+       }
        rvm_codegen_addins(co->cg, rvm_asm(RVM_BX, LR, XX, XX, 0));
        return 0;
 }
index 60ed607..1d8c5fb 100644 (file)
@@ -39,6 +39,7 @@ struct rpadbex_s {
        rpa_compiler_t *co;
        rpa_parser_t *pa;
        rarray_t *records;
+       rarray_t *temprecords;
        rharray_t *rules;
        rarray_t *recstack;
        rarray_t *inlinestack;
@@ -53,8 +54,6 @@ static rparecord_t *rpa_dbex_rulerecord(rpadbex_t *dbex, rparule_t rid);
 static rparecord_t *rpa_dbex_record(rpadbex_t *dbex, rlong rec);
 static rint rpa_dbex_rulename(rpadbex_t *dbex, rlong rec, const rchar **name, rsize_t *namesize);
 static rint rpa_parseinfo_loopdetect(rpadbex_t *dbex, rlong parent, rlong loopto);
-static rlong rpa_dbex_play_recordhandler(rpadbex_t *dbex, rlong rec);
-static rlong rpa_dbex_play_recordhandlers(rpadbex_t *dbex, rlong rec, rlong nrecs);
 static rlong rpa_dbex_firstinlined(rpadbex_t *dbex);
 static rint rpa_dbex_findinlined(rpadbex_t *dbex, rlong startrec);
 static rint rpa_dbex_playchildrecords(rpadbex_t *dbex, rlong rec);
@@ -284,6 +283,33 @@ static rint rpa_dbex_rh_uid(rpadbex_t *dbex, rlong rec)
 }
 
 
+static rint rpa_dbex_rh_abort(rpadbex_t *dbex, rlong rec)
+{
+       const rchar *name = NULL;
+       rsize_t namesize;
+       rarray_t *records = dbex->records;
+       rparecord_t *prec;
+
+       rec = rpa_recordtree_get(records, rec, RPA_RECORD_START);
+       prec = rpa_dbex_record(dbex, rec);
+       R_ASSERT(prec);
+       rpa_dbex_debug_recordhead(dbex, rec);
+       if (rpa_dbex_rulename(dbex, rec, &name, &namesize) < 0) {
+               return -1;
+       }
+       rpa_compiler_rulepref_set_flag(dbex->co, name, namesize, RPA_RFLAG_ABORTONFAIL);
+       rpa_dbex_debug_recordtail(dbex, rec);
+       if (rpa_dbex_playchildrecords(dbex, rec) < 0)
+               return -1;
+       rec = rpa_recordtree_get(records, rec, RPA_RECORD_END);
+       prec = rpa_dbex_record(dbex, rec);
+       R_ASSERT(prec);
+       rpa_dbex_debug_recordhead(dbex, rec);
+       rpa_dbex_debug_recordtail(dbex, rec);
+       return 0;
+}
+
+
 static rint rpa_dbex_rh_emit(rpadbex_t *dbex, rlong rec)
 {
        const rchar *name = NULL;
@@ -1305,6 +1331,7 @@ rpadbex_t *rpa_dbex_create(void)
        dbex->co = rpa_compiler_create();
        dbex->pa = rpa_parser_create();
        dbex->records = r_array_create(sizeof(rparecord_t));
+       dbex->temprecords = r_array_create(sizeof(rparecord_t));
        dbex->rules = r_harray_create(sizeof(rpa_ruleinfo_t));
        dbex->recstack = r_array_create(sizeof(rulong));
        dbex->inlinestack = r_array_create(sizeof(rulong));
@@ -1334,6 +1361,7 @@ rpadbex_t *rpa_dbex_create(void)
        dbex->handlers[RPA_PRODUCTION_REQOP] = rpa_dbex_rh_exp;
        dbex->handlers[RPA_PRODUCTION_MINOP] = rpa_dbex_rh_minexp;
        dbex->handlers[RPA_PRODUCTION_DIRECTIVEEMIT] = rpa_dbex_rh_emit;
+       dbex->handlers[RPA_PRODUCTION_DIRECTIVEABORT] = rpa_dbex_rh_abort;
        dbex->handlers[RPA_PRODUCTION_DIRECTIVENOEMIT] = rpa_dbex_rh_noemit;
        dbex->handlers[RPA_PRODUCTION_DIRECTIVEEMITALL] = rpa_dbex_rh_emitall;
        dbex->handlers[RPA_PRODUCTION_DIRECTIVEEMITNONE] = rpa_dbex_rh_emitnone;
@@ -1350,6 +1378,7 @@ void rpa_dbex_destroy(rpadbex_t *dbex)
                rpa_parser_destroy(dbex->pa);
                r_harray_destroy(dbex->rules);
                r_array_destroy(dbex->records);
+               r_array_destroy(dbex->temprecords);
                r_array_destroy(dbex->recstack);
                r_array_destroy(dbex->inlinestack);
                r_free(dbex->handlers);
@@ -1589,9 +1618,11 @@ static rlong rpa_dbex_copy_handler(rarray_t *records, rlong rec, rpointer userda
 }
 
 
-static void rpa_dbex_copyrecords(rpadbex_t *dbex, rarray_t *records)
+static void rpa_dbex_copyrecords(rpadbex_t *dbex)
 {
        rint i;
+       rarray_t *records = dbex->temprecords;
+
        for (i = rpa_recordtree_get(records, 0, RPA_RECORD_START); i >= 0; i = rpa_recordtree_next(records, i, RPA_RECORD_START))
                rpa_recordtree_walk(records, i, 0, rpa_dbex_copy_handler, dbex);
 }
@@ -1675,7 +1706,8 @@ rlong rpa_dbex_load(rpadbex_t *dbex, const rchar *rules, rsize_t size)
                RPA_DBEX_SETERRINFO_CODE(dbex, RPA_E_NOTOPEN);
                return -1;
        }
-       if ((ret = rpa_parser_load(dbex->pa, rules, size)) < 0) {
+       r_array_setlength(dbex->temprecords, 0);
+       if ((ret = rpa_parser_load(dbex->pa, rules, size, dbex->temprecords)) < 0) {
 
                return -1;
        }
@@ -1684,7 +1716,7 @@ rlong rpa_dbex_load(rpadbex_t *dbex, const rchar *rules, rsize_t size)
                RPA_DBEX_SETERRINFO_OFFSET(dbex, ret);
                return -1;
        }
-       rpa_dbex_copyrecords(dbex, dbex->pa->stat->records);
+       rpa_dbex_copyrecords(dbex);
        return ret;
 }
 
@@ -2068,51 +2100,6 @@ const rchar *rpa_dbex_version()
 }
 
 
-static rlong rpa_dbex_play_recordhandler(rpadbex_t *dbex, rlong rec)
-{
-       rparecord_t *prec = (rparecord_t *) r_array_slot(dbex->records, rec);
-       rpa_dbex_recordhandler handler = dbex->handlers[prec->ruleuid];
-       if (handler) {
-               if (handler(dbex, rec) < 0)
-                       return -1;
-       }
-       return 0;
-}
-
-
-static rlong rpa_dbex_play_recordhandlers(rpadbex_t *dbex, rlong rec, rlong nrecs)
-{
-       rparecord_t *prec;
-       rlong i, res = 0;
-
-       for (i = rec; i < rec + nrecs; i++) {
-               prec = (rparecord_t *) r_array_slot(dbex->records, i);
-
-               if (prec->ruleuid == RPA_PRODUCTION_MINOP && (prec->type & RPA_RECORD_START)) {
-                       rlong lastchild = rpa_recordtree_lastchild(dbex->records, i, RPA_RECORD_START);
-                       rlong firstchild = rpa_recordtree_firstchild(dbex->records, i, RPA_RECORD_START);
-                       if (firstchild < 0 || lastchild < 0 || firstchild == lastchild)
-                               return -1;
-                       if ((res = rpa_dbex_play_recordhandler(dbex, i)) < 0)
-                               return -1;
-                       if ((res = rpa_dbex_play_recordhandlers(dbex, lastchild, rpa_recordtree_size(dbex->records, lastchild))) < 0)
-                               return -1;
-                       if ((res = rpa_dbex_play_recordhandlers(dbex, firstchild, lastchild - firstchild)) < 0)
-                               return -1;
-                       if ((res = rpa_dbex_play_recordhandler(dbex, rpa_recordtree_get(dbex->records, i, RPA_RECORD_END))) < 0)
-                               return -1;
-                       i += rpa_recordtree_size(dbex->records, i) - 1;
-                       continue;
-               }
-
-               if (rpa_dbex_play_recordhandler(dbex, i) < 0)
-                       return -1;
-       }
-
-       return i;
-}
-
-
 static rint rpa_dbex_compile_rule(rpadbex_t *dbex, rparule_t rid)
 {
        rlong codeoff;
index 98155ce..fc9df73 100644 (file)
@@ -49,7 +49,9 @@
 #define RPA_E_UNRESOLVED_SYMBOL 1007
 #define RPA_E_PARAM 1008
 
+#define RPA_E_EXECUTION 2000
 #define RPA_E_USERABORT 2001
+#define RPA_E_RULEABORT 2002
 
 /**
  * \typedef rpaerror_t
index 81e5b91..07307a2 100644 (file)
@@ -33,16 +33,14 @@ void rpa_parser_destroy(rpa_parser_t *pa)
 }
 
 
-rlong rpa_parser_load(rpa_parser_t *pa, const rchar *prods, rsize_t size)
+rlong rpa_parser_load(rpa_parser_t *pa, const rchar *prods, rsize_t size, rarray_t *records)
 {
        rlong ret = 0;
        rpa_compiler_t *co = pa->co;
        rpastat_t *stat = pa->stat;
 
-       rpa_stat_init(stat, prods, prods, prods + size);
        rpa_stat_cachedisable(stat, 0);
-
-       if (rpa_stat_exec(stat, rvm_codegen_getcode(co->cg, 0), pa->main) < 0)
+       if (rpa_stat_exec(stat, rvm_codegen_getcode(co->cg, 0), pa->main, prods, prods, prods + size, records) < 0)
                return -1;
        ret = (rlong)RVM_CPUREG_GETL(stat->cpu, R0);
        if (ret < 0)
@@ -51,9 +49,9 @@ rlong rpa_parser_load(rpa_parser_t *pa, const rchar *prods, rsize_t size)
 }
 
 
-rlong rpa_parser_load_s(rpa_parser_t *pa, const rchar *prods)
+rlong rpa_parser_load_s(rpa_parser_t *pa, const rchar *prods, rarray_t *records)
 {
-       return rpa_parser_load(pa, prods, r_strlen(prods));
+       return rpa_parser_load(pa, prods, r_strlen(prods), records);
 }
 
 
@@ -86,6 +84,12 @@ static void rpa_production_directives(rpa_parser_t *pa)
        rpa_compiler_branch_end(co);
 
        rpa_compiler_branch_begin(co, RPA_MATCH_NONE);
+       rpa_compiler_reference_nan_s(co, "abort");
+       rvm_codegen_index_addrelocins(co->cg, RVM_RELOC_BRANCH, RPA_COMPILER_CURRENTEXP(co)->endidx, rvm_asm(RVM_BLES, DA, XX, XX, 0));
+       rpa_compiler_branch_end(co);
+
+
+       rpa_compiler_branch_begin(co, RPA_MATCH_NONE);
        rpa_compiler_reference_nan_s(co, "emitid");
        rvm_codegen_index_addrelocins(co->cg, RVM_RELOC_BRANCH, RPA_COMPILER_CURRENTEXP(co)->endidx, rvm_asm(RVM_BLES, DA, XX, XX, 0));
        rpa_compiler_branch_end(co);
@@ -231,6 +235,37 @@ static void rpa_production_directive_emit(rpa_parser_t *pa)
 }
 
 
+static void rpa_production_directive_abort(rpa_parser_t *pa)
+{
+       rpa_compiler_t *co = pa->co;
+
+       rpa_compiler_rulepref_set_ruleuid_flags_s(co, "abort", RPA_PRODUCTION_DIRECTIVEABORT, RPA_RFLAG_EMITRECORD);
+       rpa_compiler_rule_begin_s(co, "abort");
+
+       rvm_codegen_addins(co->cg, rvm_asm(RPA_MATCHCHR_NAN, DA, XX, XX, '#'));
+       rvm_codegen_index_addrelocins(co->cg, RVM_RELOC_BRANCH, RPA_COMPILER_CURRENTEXP(co)->endidx, rvm_asm(RVM_BLES, DA, XX, XX, 0));
+       rpa_compiler_reference_opt_s(co, "space");
+       rvm_codegen_addins(co->cg, rvm_asm(RPA_MATCHCHR_NAN, DA, XX, XX, '!'));
+       rvm_codegen_index_addrelocins(co->cg, RVM_RELOC_BRANCH, RPA_COMPILER_CURRENTEXP(co)->endidx, rvm_asm(RVM_BLES, DA, XX, XX, 0));
+       rpa_compiler_reference_opt_s(co, "space");
+       rvm_codegen_addins(co->cg, rvm_asm(RPA_MATCHCHR_NAN, DA, XX, XX, 'a'));
+       rvm_codegen_index_addrelocins(co->cg, RVM_RELOC_BRANCH, RPA_COMPILER_CURRENTEXP(co)->endidx, rvm_asm(RVM_BLES, DA, XX, XX, 0));
+       rvm_codegen_addins(co->cg, rvm_asm(RPA_MATCHCHR_NAN, DA, XX, XX, 'b'));
+       rvm_codegen_index_addrelocins(co->cg, RVM_RELOC_BRANCH, RPA_COMPILER_CURRENTEXP(co)->endidx, rvm_asm(RVM_BLES, DA, XX, XX, 0));
+       rvm_codegen_addins(co->cg, rvm_asm(RPA_MATCHCHR_NAN, DA, XX, XX, 'o'));
+       rvm_codegen_index_addrelocins(co->cg, RVM_RELOC_BRANCH, RPA_COMPILER_CURRENTEXP(co)->endidx, rvm_asm(RVM_BLES, DA, XX, XX, 0));
+       rvm_codegen_addins(co->cg, rvm_asm(RPA_MATCHCHR_NAN, DA, XX, XX, 'r'));
+       rvm_codegen_index_addrelocins(co->cg, RVM_RELOC_BRANCH, RPA_COMPILER_CURRENTEXP(co)->endidx, rvm_asm(RVM_BLES, DA, XX, XX, 0));
+       rvm_codegen_addins(co->cg, rvm_asm(RPA_MATCHCHR_NAN, DA, XX, XX, 't'));
+       rvm_codegen_index_addrelocins(co->cg, RVM_RELOC_BRANCH, RPA_COMPILER_CURRENTEXP(co)->endidx, rvm_asm(RVM_BLES, DA, XX, XX, 0));
+       rpa_compiler_reference_nan_s(co, "space");
+       rvm_codegen_index_addrelocins(co->cg, RVM_RELOC_BRANCH, RPA_COMPILER_CURRENTEXP(co)->endidx, rvm_asm(RVM_BLES, DA, XX, XX, 0));
+       rpa_compiler_reference_nan_s(co, "rulename");
+
+       rpa_compiler_rule_end(co);
+}
+
+
 static void rpa_production_directive_emitall(rpa_parser_t *pa)
 {
        rpa_compiler_t *co = pa->co;
@@ -425,6 +460,9 @@ static void rpa_production_rulename(rpa_parser_t *pa)
        rvm_codegen_index_addrelocins(co->cg, RVM_RELOC_BRANCH, RPA_COMPILER_CURRENTEXP(co)->endidx, rvm_asm(RVM_BGRE, DA, XX, XX, 0));
        rvm_codegen_addins(co->cg, rvm_asm2(RPA_MATCHRNG_NAN, DA, XX, XX, 'A', 'Z'));
        rvm_codegen_index_addrelocins(co->cg, RVM_RELOC_BRANCH, RPA_COMPILER_CURRENTEXP(co)->endidx, rvm_asm(RVM_BGRE, DA, XX, XX, 0));
+       rvm_codegen_addins(co->cg, rvm_asm(RPA_MATCHCHR_NAN, DA, XX, XX, '_'));
+       rvm_codegen_index_addrelocins(co->cg, RVM_RELOC_BRANCH, RPA_COMPILER_CURRENTEXP(co)->endidx, rvm_asm(RVM_BGRE, DA, XX, XX, 0));
+
        rpa_compiler_class_end(co);
        rvm_codegen_index_addrelocins(co->cg, RVM_RELOC_BRANCH, RPA_COMPILER_CURRENTEXP(co)->endidx, rvm_asm(RVM_BLES, DA, XX, XX, 0));
 
@@ -435,6 +473,8 @@ static void rpa_production_rulename(rpa_parser_t *pa)
        rvm_codegen_index_addrelocins(co->cg, RVM_RELOC_BRANCH, RPA_COMPILER_CURRENTEXP(co)->endidx, rvm_asm(RVM_BGRE, DA, XX, XX, 0));
        rvm_codegen_addins(co->cg, rvm_asm2(RPA_MATCHRNG_NAN, DA, XX, XX, '0', '9'));
        rvm_codegen_index_addrelocins(co->cg, RVM_RELOC_BRANCH, RPA_COMPILER_CURRENTEXP(co)->endidx, rvm_asm(RVM_BGRE, DA, XX, XX, 0));
+       rvm_codegen_addins(co->cg, rvm_asm(RPA_MATCHCHR_NAN, DA, XX, XX, '_'));
+       rvm_codegen_index_addrelocins(co->cg, RVM_RELOC_BRANCH, RPA_COMPILER_CURRENTEXP(co)->endidx, rvm_asm(RVM_BGRE, DA, XX, XX, 0));
        rpa_compiler_class_end(co);
        rvm_codegen_index_addrelocins(co->cg, RVM_RELOC_BRANCH, RPA_COMPILER_CURRENTEXP(co)->endidx, rvm_asm(RVM_BLES, DA, XX, XX, 0));
 
@@ -1415,6 +1455,7 @@ static rint rpa_parser_init(rpa_parser_t *pa)
        rpa_production_directive_emit(pa);
        rpa_production_directive_noemit(pa);
        rpa_production_directive_emitid(pa);
+       rpa_production_directive_abort(pa);
        rpa_production_directives(pa);
        rpa_production_char(pa);
        rpa_production_clsnum(pa);
index 343f3b0..6aefcef 100644 (file)
@@ -47,6 +47,7 @@ enum {
        RPA_PRODUCTION_DIRECTIVENOEMIT,
        RPA_PRODUCTION_DIRECTIVEEMITNONE,
        RPA_PRODUCTION_DIRECTIVEEMITALL,
+       RPA_PRODUCTION_DIRECTIVEABORT,
        RPA_PRODUCTION_DIRECTIVEEMITID,
 
 
@@ -66,8 +67,8 @@ typedef struct rpa_parser_s {
 
 rpa_parser_t *rpa_parser_create();
 void rpa_parser_destroy(rpa_parser_t *pa);
-rlong rpa_parser_load(rpa_parser_t *pa, const rchar *prods, rsize_t size);
-rlong rpa_parser_load_s(rpa_parser_t *pa, const rchar *prods);
+rlong rpa_parser_load(rpa_parser_t *pa, const rchar *prods, rsize_t size, rarray_t *records);
+rlong rpa_parser_load_s(rpa_parser_t *pa, const rchar *prods, rarray_t *records);
 
 #ifdef __cplusplus
 }
index 5664d84..a84355b 100644 (file)
@@ -436,3 +436,12 @@ void rpa_record_dumpindented(rarray_t *records, rlong rec, rint level)
                r_printf(" %s\n", buffer);
        return;
 }
+
+
+rarray_t *rpa_record_array()
+{
+       rarray_t *records;
+
+       records = r_array_create(sizeof(rparecord_t));
+       return records;
+}
index 26f4bd1..8a90d58 100644 (file)
@@ -94,6 +94,7 @@ void rpa_record_setusertype(rarray_t *records, rlong rec, ruint32 usertype, rval
 rlong rpa_record_getusertype(rarray_t *records, rlong rec);
 rint rpa_record_optchar(rparecord_t *prec, rint defc);
 rint rpa_record_loopchar(rparecord_t *prec, rint defc);
+rarray_t *rpa_record_array();
 #ifdef __cplusplus
 }
 #endif
index 52cc1bc..01bc770 100644 (file)
@@ -7,9 +7,6 @@
 #include "rcharconv.h"
 
 
-#define RPA_STAT_SETERROR_CODE(__s__, __e__) do { (__s__)->error = __e__; } while (0)
-
-
 rpastat_t *rpa_stat_create(rpadbex_t *dbex, rulong stacksize)
 {
        rpastat_t *stat = (rpastat_t *) r_zmalloc(sizeof(*stat));
@@ -22,11 +19,7 @@ rpastat_t *rpa_stat_create(rpadbex_t *dbex, rulong stacksize)
                return NULL;
        }
        stat->dbex = dbex;
-       stat->records = r_array_create(sizeof(rparecord_t));
-       stat->emitstack = r_array_create(sizeof(rlong));
-       stat->orphans = r_array_create(sizeof(rlong));
        stat->cpu->userdata1 = stat;
-
        return stat;
 }
 
@@ -36,9 +29,6 @@ void rpa_stat_destroy(rpastat_t *stat)
        if (stat) {
                if (stat->instack)
                        r_free(stat->instackbuffer);
-               r_array_destroy(stat->records);
-               r_array_destroy(stat->emitstack);
-               r_array_destroy(stat->orphans);
                rpavm_cpu_destroy(stat->cpu);
                rpa_cache_destroy(stat->cache);
                r_free(stat);
@@ -52,7 +42,7 @@ void rpa_stat_cachedisable(rpastat_t *stat, ruint disable)
 }
 
 
-rint rpa_stat_init(rpastat_t *stat, const rchar *input, const rchar *start, const rchar *end)
+rint rpa_stat_init(rpastat_t *stat, const rchar *input, const rchar *start, const rchar *end, rarray_t *records)
 {
        rulong size;
 
@@ -65,14 +55,13 @@ rint rpa_stat_init(rpastat_t *stat, const rchar *input, const rchar *start, cons
        if (input < start || input > end) {
                return -1;
        }
+       r_memset(&stat->err, 0, sizeof(stat->err));
        size = end - start;
        stat->start = start;
        stat->end = end;
        stat->input = input;
-       stat->error = 0;
-       r_array_setlength(stat->orphans, 0);
-       r_array_setlength(stat->emitstack, 0);
        stat->cache->hit = 0;
+       stat->records = records;
        if (stat->instacksize < size) {
                stat->instackbuffer = r_realloc(stat->instackbuffer, (size + 2) * sizeof(rpainput_t));
                stat->instacksize = size + 1;
@@ -81,6 +70,14 @@ rint rpa_stat_init(rpastat_t *stat, const rchar *input, const rchar *start, cons
        }
        stat->ip.input = input;
        stat->ip.serial = 0;
+       RVM_CPUREG_SETL(stat->cpu, R_REC, 0);
+       RVM_CPUREG_SETU(stat->cpu, SP, 0);
+       RVM_CPUREG_SETU(stat->cpu, FP, 0);
+       RVM_CPUREG_SETU(stat->cpu, R_LOO, 0);
+       RVM_CPUREG_SETU(stat->cpu, R_TOP, -1);
+       if (stat->records) {
+               RVM_CPUREG_SETL(stat->cpu, R_REC, (rlong)(r_array_length(stat->records) - 1));
+       }
        return 0;
 }
 
@@ -91,7 +88,7 @@ void rpa_stat_cacheinvalidate(rpastat_t *stat)
 }
 
 
-rint rpa_stat_encodingset(rpastat_t *stat, ruint encoding)
+rint rpa_stat_setencoding(rpastat_t *stat, ruint encoding)
 {
        if (!stat) {
                return -1;
@@ -102,49 +99,7 @@ rint rpa_stat_encodingset(rpastat_t *stat, ruint encoding)
 }
 
 
-static rparecord_t *rpa_stat_nextrecord(rpastat_t *stat, rparecord_t *cur)
-{
-       if (r_array_empty(stat->records))
-               return NULL;
-       if (cur == NULL) {
-               return (rparecord_t *)r_array_slot(stat->records, 0);
-       }
-       if (cur >= (rparecord_t *)r_array_lastslot(stat->records) || cur < (rparecord_t *)r_array_slot(stat->records, 0))
-               return NULL;
-       R_ASSERT(cur->next);
-       cur = (rparecord_t *)r_array_slot(stat->records, cur->next);
-       if (cur->type == RPA_RECORD_TAIL)
-               return NULL;
-       return cur;
-}
-
-
-static void rpa_stat_fixrecords(rpastat_t *stat)
-{
-       rarray_t *records;
-       rparecord_t *cur = (rparecord_t *)r_array_slot(stat->records, 0);
-
-       return;
-       cur = rpa_stat_nextrecord(stat, cur);
-       if (!cur) {
-               /*
-                * There are no records
-                */
-               r_array_setlength(stat->records, 0);
-               return;
-       }
-       records = (rarray_t *)r_array_create(sizeof(rparecord_t));
-       while (cur) {
-               r_array_add(records, cur);
-               cur = rpa_stat_nextrecord(stat, cur);
-       }
-       r_array_destroy(stat->records);
-       stat->records = records;
-}
-
-
-
-rlong rpa_stat_exec(rpastat_t *stat, rvm_asmins_t *prog, rword off)
+rlong rpa_stat_exec(rpastat_t *stat, rvm_asmins_t *prog, rword off, const rchar *input, const rchar *start, const rchar *end, rarray_t *records)
 {
        rlong ret;
 
@@ -152,42 +107,40 @@ rlong rpa_stat_exec(rpastat_t *stat, rvm_asmins_t *prog, rword off)
                return -1;
        }
        rpa_stat_cacheinvalidate(stat);
-       r_array_setlength(stat->records, 0);
-       RVM_CPUREG_SETU(stat->cpu, SP, 0);
-       RVM_CPUREG_SETU(stat->cpu, FP, 0);
-       RVM_CPUREG_SETL(stat->cpu, R_REC, -1);
-       RVM_CPUREG_SETU(stat->cpu, R_LOO, 0);
-       RVM_CPUREG_SETU(stat->cpu, R_TOP, -1);
+       rpa_stat_init(stat, input, start, end, records);
        if (stat->debug) {
                ret = rvm_cpu_exec_debug(stat->cpu, prog, off);
        } else {
                ret = rvm_cpu_exec(stat->cpu, prog, off);
        }
        if (ret < 0) {
-               if (stat->cpu->error == RVM_E_USERABORT)
-                       RPA_STAT_SETERROR_CODE(stat, RPA_E_USERABORT);
-               else
-                       RPA_STAT_SETERROR_CODE(stat, stat->cpu->error);
-               r_array_setlength(stat->records, 0);
+               if (!stat->cpu->error) {
+                       if (stat->cpu->error) {
+                               RPA_STAT_SETERROR_CODE(stat, stat->cpu->error);
+                       } else {
+                               /*
+                                * We should never get to here. Error have to be more
+                                * specific and set at the places they are detected.
+                                */
+                               RPA_STAT_SETERROR_CODE(stat, RPA_E_EXECUTION);
+                       }
+               }
                return -1;
        }
-       rpa_stat_fixrecords(stat);
        ret = (rlong)RVM_CPUREG_GETL(stat->cpu, R0);
        if (ret < 0) {
-               r_array_setlength(stat->records, 0);
                return 0;
        }
        return ret;
 }
 
 
-static rlong rpa_stat_exec_noinit(rpastat_t *stat, rparule_t rid, const rchar *input, const rchar *start, const rchar *end)
+static rlong rpa_stat_exec_rid(rpastat_t *stat, rparule_t rid, const rchar *input, const rchar *start, const rchar *end, rarray_t *records)
 {
        rlong topsiz = 0;
        rpainput_t *ptp;
 
-       rpa_stat_init(stat, input, start, end);
-       if ((topsiz = rpa_stat_exec(stat, rpa_dbex_executable(stat->dbex), rpa_dbex_executableoffset(stat->dbex, rid))) < 0) {
+       if ((topsiz = rpa_stat_exec(stat, rpa_dbex_executable(stat->dbex), rpa_dbex_executableoffset(stat->dbex, rid),  input, start, end, records)) < 0) {
                return -1;
        }
        if (topsiz <= 0)
@@ -201,11 +154,8 @@ rlong rpa_stat_scan(rpastat_t *stat, rparule_t rid, const rchar *input, const rc
 {
        rlong ret;
 
-       if (!stat) {
-               return -1;
-       }
        while (input < end) {
-               ret = rpa_stat_exec_noinit(stat, rid, input, start, end);
+               ret = rpa_stat_exec_rid(stat, rid, input, start, end, NULL);
                if (ret < 0)
                        return -1;
                if (ret > 0) {
@@ -220,28 +170,13 @@ rlong rpa_stat_scan(rpastat_t *stat, rparule_t rid, const rchar *input, const rc
 
 rlong rpa_stat_match(rpastat_t *stat, rparule_t rid, const rchar *input, const rchar *start, const rchar *end)
 {
-       if (!stat) {
-               return -1;
-       }
-
-       return rpa_stat_exec_noinit(stat, rid, input, start, end);
+       return rpa_stat_exec_rid(stat, rid, input, start, end, NULL);
 }
 
 
-rlong rpa_stat_parse(rpastat_t *stat, rparule_t rid, const rchar *input, const rchar *start, const rchar *end, rarray_t **records)
+rlong rpa_stat_parse(rpastat_t *stat, rparule_t rid, const rchar *input, const rchar *start, const rchar *end, rarray_t *records)
 {
-       rint res = 0;
-
-       if (!stat) {
-               return -1;
-       }
-
-       res = rpa_stat_exec_noinit(stat, rid, input, start, end);
-       if (res > 0 && !r_array_empty(stat->records) && records) {
-               *records = stat->records;
-               stat->records = r_array_create(sizeof(rparecord_t));
-       }
-       return res;
+       return rpa_stat_exec_rid(stat, rid, input, start, end, records);
 }
 
 
@@ -250,7 +185,7 @@ rint rpa_stat_abort(rpastat_t *stat)
        if (!stat) {
                return -1;
        }
-
+       RPA_STAT_SETERROR_CODE(stat, RPA_E_USERABORT);
        rvm_cpu_abort(stat->cpu);
        return 0;
 }
@@ -378,3 +313,20 @@ rlong rpa_stat_shift(rpastat_t *stat, rssize_t top)
 
        return top;
 }
+
+
+rlong rpa_stat_lasterror(rpastat_t *stat)
+{
+       if (!stat)
+               return -1;
+       return stat->err.code;
+}
+
+
+rlong rpa_stat_lasterrorinfo(rpastat_t *stat, rpa_errinfo_t *errinfo)
+{
+       if (!stat || !errinfo)
+               return -1;
+       r_memcpy(errinfo, &stat->err, sizeof(rpa_errinfo_t));
+       return 0;
+}
index 3001211..55db4d3 100644 (file)
@@ -74,12 +74,33 @@ rpastat_t *rpa_stat_create(rpadbex_t *dbex, rulong stacksize);
 void rpa_stat_destroy(rpastat_t *stat);
 
 
-rint rpa_stat_encodingset(rpastat_t *stat, ruint encoding);
 rlong rpa_stat_scan(rpastat_t *stat, rparule_t rid, const rchar *input, const rchar *start, const rchar *end, const rchar **where);
+rlong rpa_stat_parse(rpastat_t *stat, rparule_t rid, const rchar *input, const rchar *start, const rchar *end, rarray_t *records);
 rlong rpa_stat_match(rpastat_t *stat, rparule_t rid, const rchar *input, const rchar *start, const rchar *end);
-rlong rpa_stat_parse(rpastat_t *stat, rparule_t rid, const rchar *input, const rchar *start, const rchar *end, rarray_t **records);
+rlong rpa_stat_exec(rpastat_t *stat, rvm_asmins_t *prog, rword off, const rchar *input, const rchar *start, const rchar *end, rarray_t *records);
 rint rpa_stat_abort(rpastat_t *stat);
-rlong rpa_stat_exec(rpastat_t *stat, rvm_asmins_t *prog, rword off);
+rint rpa_stat_setencoding(rpastat_t *stat, ruint encoding);
+
+
+/**
+ * \brief Return the error code of the last occurred error.
+ *
+ * \param dbex Pointer to \ref rpadbex_t object.
+ * \return The error code of the last occurred error. If this function fails the
+ * return value is negative.
+ */
+rlong rpa_stat_lasterror(rpastat_t *stat);
+
+/**
+ * \brief Get error information for the last occurred error.
+ *
+ * \param dbex Pointer to \ref rpadbex_t object.
+ * \param errinfo Pointer to \ref rpa_errinfo_t buffer that will be
+ * filled with the error information. This parameter cannot be NULL.
+ * \return Return 0 if the function is successful or negative otherwise. If this function fails the
+ * return value is negative.
+ */
+rlong rpa_stat_lasterrorinfo(rpastat_t *stat, rpa_errinfo_t *errinfo);
 
 
 #ifdef __cplusplus
index 477a08c..8660935 100644 (file)
 extern "C" {
 #endif
 
+#define RPA_STAT_SETERROR_CODE(__d__, __e__) do { (__d__)->err.code = __e__; } while (0)
+#define RPA_STAT_SETERRINFO_OFFSET(__d__, __o__) do { (__d__)->err.offset = __o__; (__d__)->err.mask |= RPA_ERRINFO_OFFSET; } while (0)
+#define RPA_STAT_SETERRINFO_RULEUID(__d__, __r__) do { (__d__)->err.ruleid = __r__; (__d__)->err.mask |= RPA_ERRINFO_RULEID; } while (0)
+#define RPA_STAT_SETERRINFO_NAME(__d__, __n__, __s__) do { \
+       (__d__)->err.mask |= RPA_ERRINFO_NAME; \
+       r_memset((__d__)->err.name, 0, sizeof((__d__)->err.name)); \
+       r_strncpy((__d__)->err.name, __n__, R_MIN(__s__, (sizeof((__d__)->err.name) - 1)));  } while (0)
 
 struct rpastat_s {
        rpadbex_t *dbex;
        const rchar *input;
        const rchar *start;
        const rchar *end;
-       ruint error;
+       rpa_errinfo_t err;
        ruint encoding;
        ruint debug;
        rarray_t *records;
-       rarray_t *emitstack;
-       rarray_t *orphans;
        rpainput_t *instackbuffer;
        rpainput_t *instack;                    /* instack = &instackbuffer[1]; This allows R_TOP = -1, without any additional checks */
        rulong instacksize;
@@ -34,7 +39,7 @@ struct rpastat_s {
        rvmcpu_t *cpu;
 };
 
-rint rpa_stat_init(rpastat_t *stat, const rchar *input, const rchar *start, const rchar *end);
+rint rpa_stat_init(rpastat_t *stat, const rchar *input, const rchar *start, const rchar *end, rarray_t *records);
 void rpa_stat_cachedisable(rpastat_t *stat, ruint disable);
 void rpa_stat_cacheinvalidate(rpastat_t *stat);
 rint rpa_stat_matchchr(rpastat_t *stat, rssize_t top, rulong wc);
index bf852c5..e321e23 100644 (file)
@@ -211,15 +211,34 @@ static void rpavm_swi_matchrng_mop(rvmcpu_t *cpu, rvm_asmins_t *ins)
 
 static void rpavm_swi_emittail(rvmcpu_t *cpu, rvm_asmins_t *ins)
 {
-       rparecord_t *rec;
        rpastat_t *stat = (rpastat_t *)cpu->userdata1;
        rlong index = RVM_CPUREG_GETL(cpu, R_REC);
 
-       index = r_array_replace(stat->records, index + 1, NULL);
-       RVM_CPUREG_SETL(cpu, R_REC, index);
-       rec = (rparecord_t *)r_array_slot(stat->records, index);
-       rec->type = RPA_RECORD_TAIL;
-       r_array_setlength(stat->records, index);
+       if (stat->records)
+               r_array_setlength(stat->records, index + 1);
+}
+
+
+static void rpavm_swi_abort(rvmcpu_t *cpu, rvm_asmins_t *ins)
+{
+       rpa_ruledata_t *ruledata = RVM_CPUREG_GETP(cpu, ins->op1);
+       rstr_t name = {(rchar*)ruledata + ruledata->name, ruledata->namesize};
+       rpastat_t *stat = (rpastat_t *)cpu->userdata1;
+       rlong index = RVM_CPUREG_GETL(cpu, R_REC);
+       rword tp = RVM_CPUREG_GETU(cpu, ins->op2);
+
+
+       if (stat->records)
+               r_array_setlength(stat->records, index + 1);
+       RPA_STAT_SETERROR_CODE(stat, RPA_E_RULEABORT);
+       RPA_STAT_SETERRINFO_RULEUID(stat, ruledata->ruleuid);
+       if (name.str) {
+               RPA_STAT_SETERRINFO_NAME(stat, name.str, name.size);
+       }
+       if (stat->instack[tp].input) {
+               RPA_STAT_SETERRINFO_OFFSET(stat, stat->instack[tp].input - stat->start);
+       }
+       rvm_cpu_abort(cpu);
 }
 
 
@@ -234,7 +253,7 @@ static void rpavm_swi_emitstart(rvmcpu_t *cpu, rvm_asmins_t *ins)
 
        if (stat->debug)
                r_printf("%ld: %s, %s, tp = %ld\n", RVM_CPUREG_GETU(cpu, FP), "START", name.str, tp);
-       if (!(ruledata->flags & RPA_RFLAG_EMITRECORD))
+       if (!stat->records || !(ruledata->flags & RPA_RFLAG_EMITRECORD))
                return;
        index = r_array_replace(stat->records, index + 1, NULL);
 
@@ -268,7 +287,7 @@ static void rpavm_swi_emitend(rvmcpu_t *cpu, rvm_asmins_t *ins)
 
        if (stat->debug)
                r_printf("%ld: %s, %s, tp = %ld, tplen = %ld\n", RVM_CPUREG_GETU(cpu, FP), "END ", name.str, tp, tplen);
-       if (!(ruledata->flags & RPA_RFLAG_EMITRECORD))
+       if (!stat->records || !(ruledata->flags & RPA_RFLAG_EMITRECORD))
                return;
 
        index = r_array_replace(stat->records, index + 1, NULL);
@@ -311,18 +330,6 @@ static void rpavm_swi_prninfo(rvmcpu_t *cpu, rvm_asmins_t *ins)
 }
 
 
-static void rpavm_swi_getnextrec(rvmcpu_t *cpu, rvm_asmins_t *ins)
-{
-       rpastat_t *stat = (rpastat_t *)cpu->userdata1;
-       rlong rec = RVM_CPUREG_GETL(cpu, ins->op2);
-
-       rparecord_t *prec = (rparecord_t *)r_array_slot(stat->records, rec);
-
-//     r_printf("%s, rec = %ld, next = %ld\n", __FUNCTION__, rec, prec->next);
-       RVM_CPUREG_SETL(cpu, ins->op1, prec->next);
-}
-
-
 static void rpavm_swi_setcache(rvmcpu_t *cpu, rvm_asmins_t *ins)
 {
        rpastat_t *stat = (rpastat_t *)cpu->userdata1;
@@ -356,9 +363,11 @@ static void rpavm_swi_checkcache(rvmcpu_t *cpu, rvm_asmins_t *ins)
                if (r0 > 0) {
                        if (entry->recsize) {
                                long i;
-                               r_array_setlength(stat->records, RVM_CPUREG_GETL(cpu, R_REC) + 1);
-                               for (i = 0; i < r_array_length(entry->records); i++) {
-                                       r_array_add(stat->records, r_array_slot(entry->records, i));
+                               if (stat->records) {
+                                       r_array_setlength(stat->records, RVM_CPUREG_GETL(cpu, R_REC) + 1);
+                                       for (i = 0; i < r_array_length(entry->records); i++) {
+                                               r_array_add(stat->records, r_array_slot(entry->records, i));
+                                       }
                                }
                                RVM_CPUREG_SETL(cpu, R_REC, r_array_length(stat->records) - 1);
                        }
@@ -397,7 +406,7 @@ static rvm_switable_t rpavm_swi_table[] = {
                {"RPA_EMITSTART", rpavm_swi_emitstart},
                {"RPA_EMITEND", rpavm_swi_emitend},
                {"RPA_EMITTAIL", rpavm_swi_emittail},
-               {"RPA_GETNEXTREC", rpavm_swi_getnextrec},
+               {"RPA_ABORT", rpavm_swi_abort},
                {"RPA_PRNINFO", rpavm_swi_prninfo},
                {NULL, NULL},
 };
index ea97859..fe18278 100644 (file)
@@ -20,6 +20,7 @@ extern "C" {
 #define RPA_INLINE_REF (1<<5)
 #define RPA_LOOP_INDERECTION 1024
 #define RPA_RFLAG_EMITRECORD (1 << 0)
+#define RPA_RFLAG_ABORTONFAIL (1 << 2)
 
 #define R_REC (TP - 3)
 #define R_LOO (TP - 2)
@@ -50,17 +51,10 @@ extern "C" {
 #define RPA_EMITSTART          RVM_OPSWI(RVM_SWI_ID(RPAVM_SWI_TABLEID, 16))
 #define RPA_EMITEND                    RVM_OPSWI(RVM_SWI_ID(RPAVM_SWI_TABLEID, 17))
 #define RPA_EMITTAIL           RVM_OPSWI(RVM_SWI_ID(RPAVM_SWI_TABLEID, 18))
-#define RPA_GETNEXTREC         RVM_OPSWI(RVM_SWI_ID(RPAVM_SWI_TABLEID, 19))
+#define RPA_ABORT                      RVM_OPSWI(RVM_SWI_ID(RPAVM_SWI_TABLEID, 19))
 #define RPA_PRNINFO                    RVM_OPSWI(RVM_SWI_ID(RPAVM_SWI_TABLEID, 20))
 
 
-
-//#define RPA_GETRECLEN                RVM_OPSWI(RVM_SWI_ID(RPAVM_SWI_TABLEID, 19))
-//#define RPA_SETRECLEN                RVM_OPSWI(RVM_SWI_ID(RPAVM_SWI_TABLEID, 20))
-//#define RPA_GETCURREC                RVM_OPSWI(RVM_SWI_ID(RPAVM_SWI_TABLEID, 21))
-//#define RPA_SETCURREC                RVM_OPSWI(RVM_SWI_ID(RPAVM_SWI_TABLEID, 22))
-
-
 typedef struct rpainput_s {
        const rchar *input;
        ruint32 wc;
index 9398693..984a98f 100644 (file)
@@ -82,7 +82,7 @@ int main(int argc, char *argv[])
        stat = rpa_stat_create(NULL, 4096);
        rvm_cpu_addswitable(stat->cpu, "common_table", common_calltable);
 
-       rpa_stat_init(stat, teststr, teststr, teststr+12);
+       rpa_stat_init(stat, teststr, teststr, teststr+12, NULL);
 
        mainoff = rvm_codegen_addins(co->cg, rvm_asml(RVM_NOP, XX, XX, XX, -1));
        rvm_codegen_addins(co->cg, rvm_asml(RVM_MOV, R_TOP, DA, XX, -1));
index f45bc44..cb6e0fa 100644 (file)
@@ -128,7 +128,7 @@ int main(int argc, char *argv[])
        stat = rpa_stat_create(NULL, 4096);
        rvm_cpu_addswitable(stat->cpu, "common_table", common_calltable);
 
-       rpa_stat_init(stat, teststr, teststr, teststr+12);
+       rpa_stat_init(stat, teststr, teststr, teststr+12, NULL);
 
        mainoff = rvm_codegen_addins(co->cg, rvm_asml(RVM_NOP, XX, XX, XX, -1));
        rvm_codegen_addins(co->cg, rvm_asml(RVM_MOV, R_TOP, DA, XX, -1));
index f3563ca..81c10f5 100644 (file)
@@ -151,7 +151,7 @@ int main(int argc, char *argv[])
        stat = rpa_stat_create(NULL, 4096);
        rvm_cpu_addswitable(stat->cpu, "common_table", common_calltable);
 
-       rpa_stat_init(stat, teststr, teststr, teststr+12);
+       rpa_stat_init(stat, teststr, teststr, teststr+12, NULL);
 
        mainoff = rvm_codegen_addins(co->cg, rvm_asml(RVM_NOP, XX, XX, XX, -1));
        rvm_codegen_addins(co->cg, rvm_asml(RVM_MOV, R_TOP, DA, XX, -1));
index 12c41c7..03810f9 100644 (file)
@@ -91,7 +91,7 @@ int main(int argc, char *argv[])
        stat = rpa_stat_create(NULL, 4096);
        rvm_cpu_addswitable(stat->cpu, "common_table", common_calltable);
 
-       rpa_stat_init(stat, teststr, teststr, teststr+12);
+       rpa_stat_init(stat, teststr, teststr, teststr+12, NULL);
 
        mainoff = rvm_codegen_addins(co->cg, rvm_asml(RVM_NOP, XX, XX, XX, -1));
        rvm_codegen_addins(co->cg, rvm_asml(RVM_MOV, R_TOP, DA, XX, -1));
index 0aa83e0..4c218fc 100644 (file)
@@ -151,7 +151,7 @@ int main(int argc, char *argv[])
        stat = rpa_stat_create(NULL, 4096);
        rvm_cpu_addswitable(stat->cpu, "common_table", common_calltable);
 
-       rpa_stat_init(stat, teststr, teststr, teststr+12);
+       rpa_stat_init(stat, teststr, teststr, teststr+12, NULL);
 
        mainoff = rvm_codegen_addins(co->cg, rvm_asml(RVM_NOP, XX, XX, XX, -1));
        rvm_codegen_addins(co->cg, rvm_asml(RVM_MOV, R_TOP, DA, XX, -1));
index 8ce1f8b..417cae4 100644 (file)
@@ -104,7 +104,7 @@ int main(int argc, char *argv[])
        stat = rpa_stat_create(NULL, 4096);
        rvm_cpu_addswitable(stat->cpu, "common_table", common_calltable);
 
-       rpa_stat_init(stat, teststr, teststr, teststr+12);
+       rpa_stat_init(stat, teststr, teststr, teststr+12, NULL);
 
        mainoff = rvm_codegen_addins(co->cg, rvm_asml(RVM_NOP, XX, XX, XX, -1));
        rvm_codegen_addins(co->cg, rvm_asml(RVM_MOV, R_TOP, DA, XX, -1));
index 1b41293..e72756d 100644 (file)
@@ -138,7 +138,7 @@ int main(int argc, char *argv[])
        stat = rpa_stat_create(NULL, 4096);
        rvm_cpu_addswitable(stat->cpu, "common_table", common_calltable);
 
-       rpa_stat_init(stat, teststr, teststr, teststr+30);
+       rpa_stat_init(stat, teststr, teststr, teststr+30, NULL);
 
        mainoff = rvm_codegen_addins(co->cg, rvm_asml(RVM_NOP, XX, XX, XX, -1));
        rvm_codegen_addins(co->cg, rvm_asml(RVM_MOV, R_TOP, DA, XX, -1));
index 18db205..0bd936d 100644 (file)
@@ -80,7 +80,7 @@ int main(int argc, char *argv[])
        stat = rpa_stat_create(NULL, 4096);
        rvm_cpu_addswitable(stat->cpu, "common_table", common_calltable);
 
-       rpa_stat_init(stat, teststr, teststr, teststr+12);
+       rpa_stat_init(stat, teststr, teststr, teststr+12, NULL);
 
        mainoff = rvm_codegen_addins(co->cg, rvm_asml(RVM_NOP, XX, XX, XX, -1));
        rvm_codegen_addins(co->cg, rvm_asml(RVM_MOV, R_TOP, DA, XX, -1));
index 31b1cab..687eac7 100644 (file)
@@ -69,7 +69,7 @@ int main(int argc, char *argv[])
        stat = rpa_stat_create(NULL, 4096);
        rvm_cpu_addswitable(stat->cpu, "common_table", common_calltable);
 
-       rpa_stat_init(stat, teststr, teststr, teststr+3);
+       rpa_stat_init(stat, teststr, teststr, teststr+3, NULL);
 
        mainoff = rvm_codegen_addins(co->cg, rvm_asml(RVM_NOP, XX, XX, XX, -1));
        rvm_codegen_addins(co->cg, rvm_asml(RVM_MOV, R_TOP, DA, XX, -1));
index 7dbedb9..4cca0cb 100644 (file)
@@ -67,7 +67,7 @@ int main(int argc, char *argv[])
        stat = rpa_stat_create(NULL, 4096);
        rvm_cpu_addswitable(stat->cpu, "common_table", common_calltable);
 
-       rpa_stat_init(stat, teststr, teststr, teststr+3);
+       rpa_stat_init(stat, teststr, teststr, teststr+3, NULL);
 
        mainoff = rvm_codegen_addins(co->cg, rvm_asml(RVM_NOP, XX, XX, XX, -1));
        rvm_codegen_addins(co->cg, rvm_asml(RVM_MOV, R_TOP, DA, XX, -1));
index 8e82159..6320f90 100644 (file)
@@ -128,7 +128,7 @@ int main(int argc, char *argv[])
        stat = rpa_stat_create(NULL, 4096);
        rvm_cpu_addswitable(stat->cpu, "common_table", common_calltable);
 
-       rpa_stat_init(stat, teststr, teststr, teststr+12);
+       rpa_stat_init(stat, teststr, teststr, teststr+12, NULL);
 
        mainoff = rvm_codegen_addins(co->cg, rvm_asml(RVM_NOP, XX, XX, XX, -1));
        rvm_codegen_addins(co->cg, rvm_asml(RVM_MOV, R_TOP, DA, XX, -1));
index 3ec2356..619ffc8 100644 (file)
@@ -128,7 +128,7 @@ int main(int argc, char *argv[])
        stat = rpa_stat_create(NULL, 4096);
        rvm_cpu_addswitable(stat->cpu, "common_table", common_calltable);
 
-       rpa_stat_init(stat, teststr, teststr, teststr+12);
+       rpa_stat_init(stat, teststr, teststr, teststr+12, NULL);
 
        mainoff = rvm_codegen_addins(co->cg, rvm_asml(RVM_NOP, XX, XX, XX, -1));
        rvm_codegen_addins(co->cg, rvm_asml(RVM_MOV, R_TOP, DA, XX, -1));