00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011 #include <stdio.h>
00012 #include <string.h>
00013
00014 #include "../../basext.h"
00015
00016 #include <sys/types.h>
00017 #include "regex.h"
00018
00031 typedef struct _ModuleObject {
00032 int iErrorRegcomp;
00033 int iErrorRegex;
00034 unsigned long lMatches;
00035 unsigned long *lMatchLen;
00036 char **pszMatch;
00037 } ModuleObject, *pModuleObject;
00038
00039
00040 #define RE_REG_NOMATCH 0x00080001
00041 #define RE_REG_BADPAT 0x00080002
00042 #define RE_REG_ECOLLATE 0x00080003
00043 #define RE_REG_ECTYPE 0x00080004
00044 #define RE_REG_EESCAPE 0x00080005
00045 #define RE_REG_ESUBREG 0x00080006
00046 #define RE_REG_EBRACK 0x00080007
00047 #define RE_REG_EPAREN 0x00080008
00048 #define RE_REG_EBRACE 0x00080009
00049 #define RE_REG_BADBR 0x0008000A
00050 #define RE_REG_ERANGE 0x0008000B
00051 #define RE_REG_ESPACE 0x0008000C
00052 #define RE_REG_BADRPT 0x0008000D
00053 #define RE_REG_EMPTY 0x0008000E
00054 #define RE_REG_ASSERT 0x0008000F
00055 #define RE_REG_INVARG 0x00080010
00056
00057 static int ConvertError(int Error){
00058 switch( Error ){
00059 case REG_NOMATCH : return RE_REG_NOMATCH;
00060 case REG_BADPAT : return RE_REG_BADPAT;
00061 case REG_ECOLLATE : return RE_REG_ECOLLATE;
00062 case REG_ECTYPE : return RE_REG_ECTYPE;
00063 case REG_EESCAPE : return RE_REG_EESCAPE;
00064 case REG_ESUBREG : return RE_REG_ESUBREG;
00065 case REG_EBRACK : return RE_REG_EBRACK;
00066 case REG_EPAREN : return RE_REG_EPAREN;
00067 case REG_EBRACE : return RE_REG_EBRACE;
00068 case REG_BADBR : return RE_REG_BADBR;
00069 case REG_ERANGE : return RE_REG_ERANGE;
00070 case REG_ESPACE : return RE_REG_ESPACE;
00071 case REG_BADRPT : return RE_REG_BADRPT;
00072 case REG_EMPTY : return RE_REG_EMPTY;
00073 case REG_ASSERT : return RE_REG_ASSERT;
00074 case REG_INVARG : return RE_REG_INVARG;
00075 default: return 0x00080011;
00076 }
00077 }
00078
00079
00080 besVERSION_NEGOTIATE
00081
00082 return (int)INTERFACE_VERSION;
00083
00084 besEND
00085
00086 besSUB_START
00087 pModuleObject p;
00088
00089 besMODULEPOINTER = besALLOC(sizeof(ModuleObject));
00090 if( besMODULEPOINTER == NULL )return 0;
00091 p = (pModuleObject)besMODULEPOINTER;
00092
00093 p->lMatches = 0;
00094
00095 besEND
00096
00097 #define reset_pmatches(p) \
00098 if( p->lMatches ){\
00099 besFREE(p->lMatchLen);\
00100 p->lMatchLen = NULL;\
00101 besFREE(p->pszMatch);\
00102 p->pszMatch = NULL;\
00103 p->lMatches = 0;\
00104 }
00105
00106 besSUB_FINISH
00107 pModuleObject p;
00108
00109 p = (pModuleObject)besMODULEPOINTER;
00110 reset_pmatches(p);
00111
00112 return 0;
00113 besEND
00114
00115
00116
00170 besFUNCTION(match)
00171 regex_t *preg;
00172 regmatch_t *pmatch;
00173 VARIABLE vString,vRegexp,vReplace;
00174 size_t nmatch;
00175 pModuleObject p;
00176 int iError;
00177 int eflags,eopt;
00178 int i;
00179
00180 p = (pModuleObject)besMODULEPOINTER;
00181
00182
00183 reset_pmatches(p);
00184
00185
00186 vRegexp = besARGUMENT(2);
00187 besDEREFERENCE(vRegexp);
00188
00189 if( vRegexp == NULL ){
00190 besALLOC_RETURN_LONG;
00191 LONGVALUE(besRETURNVALUE) = 0;
00192 }
00193
00194 vRegexp = besCONVERT2STRING(vRegexp);
00195 preg = (regex_t *)besALLOC(sizeof(regex_t));
00196 if( preg == NULL )return COMMAND_ERROR_MEMORY_LOW;
00197 preg->re_endp = STRINGVALUE(vRegexp)+STRLEN(vRegexp);
00198
00199 eflags = REG_PEND|REG_EXTENDED;
00200 eopt = besOPTION("re$flag");
00201 if( eopt )eopt = ~ eopt;
00202
00203 #define SBCASE 0x0001
00204 #define SBNEWLINE 0x0002
00205
00206 if( eopt & SBCASE )eflags |= REG_ICASE;
00207 if( eopt & SBNEWLINE )eflags |= REG_NEWLINE;
00208
00209
00210 if( p->iErrorRegcomp = regcomp(preg, STRINGVALUE(vRegexp), eflags) ){
00211 besALLOC_RETURN_LONG;
00212 LONGVALUE(besRETURNVALUE) = 0;
00213 return ConvertError(p->iErrorRegcomp);
00214 }
00215
00216 nmatch = preg->re_nsub + 1;
00217
00218 vString = besARGUMENT(1);
00219 besDEREFERENCE(vString);
00220
00221 vString = besCONVERT2STRING(vString);
00222
00223 pmatch = (regmatch_t *)besALLOC(sizeof(regmatch_t) * nmatch );
00224 if( pmatch == NULL )return COMMAND_ERROR_MEMORY_LOW;
00225 pmatch->rm_so = 0;
00226 pmatch->rm_eo = STRLEN(vString);
00227 p->iErrorRegex = regexec(preg, STRINGVALUE(vString),nmatch,pmatch,REG_STARTEND);
00228
00229
00230 if( ! p->iErrorRegex && nmatch ){
00231
00232
00233
00234 p->lMatches = nmatch;
00235 p->lMatchLen = besALLOC(nmatch*sizeof(long));
00236 if( p->lMatchLen == NULL ){
00237 p->lMatches = 0;
00238 regfree(preg);
00239 besFREE(pmatch);
00240 besFREE(preg);
00241 return COMMAND_ERROR_MEMORY_LOW;
00242 }
00243
00244 p->pszMatch = besALLOC(nmatch*sizeof(char *));
00245 if( p->pszMatch == NULL ){
00246 besFREE(p->lMatchLen);
00247 p->lMatches = 0;
00248 regfree(preg);
00249 besFREE(pmatch);
00250 besFREE(preg);
00251 return COMMAND_ERROR_MEMORY_LOW;
00252 }
00253
00254
00255 for( i=0 ; ((size_t)i) < nmatch ; i++ ){
00256 p->lMatchLen[i] = pmatch[i].rm_eo - pmatch[i].rm_so;
00257 if( p->lMatchLen[i] )
00258 p->pszMatch[i] = besALLOC(p->lMatchLen[i]);
00259 else
00260 p->pszMatch[i] = besALLOC(1);
00261 if( p->pszMatch[i] == NULL ){
00262 do{ besFREE(p->pszMatch[--i]); }while(i);
00263 regfree(preg);
00264 besFREE(pmatch);
00265 besFREE(preg);
00266 return COMMAND_ERROR_MEMORY_LOW;
00267 }
00268 if( p->lMatchLen[i] )
00269 memcpy(p->pszMatch[i],STRINGVALUE(vString)+pmatch[i].rm_so,p->lMatchLen[i]);
00270 }
00271 }
00272
00273
00274 vReplace = besARGUMENT(3);
00275 besDEREFERENCE(vReplace);
00276 if( vReplace ){
00277 vReplace = besCONVERT2STRING(vReplace);
00278 i = 0;
00279 iError =
00280 besMatchSize(STRINGVALUE(vReplace),
00281 STRLEN(vReplace),
00282 p->lMatchLen,
00283 p->lMatches,&i);
00284 if( iError ){
00285 besRETURNVALUE = NULL;
00286 regfree(preg);
00287 besFREE(pmatch);
00288 besFREE(preg);
00289 return COMMAND_ERROR_SUCCESS;
00290 }
00291 besALLOC_RETURN_STRING(i);
00292 iError =
00293 besMatchParameter(STRINGVALUE(vReplace),
00294 STRLEN(vReplace),
00295 p->pszMatch,
00296 p->lMatchLen,
00297 STRINGVALUE(besRETURNVALUE),
00298 p->lMatches,
00299 &(STRLEN(besRETURNVALUE)));
00300 if( iError ){
00301 besRETURNVALUE = NULL;
00302 regfree(preg);
00303 besFREE(pmatch);
00304 besFREE(preg);
00305 return COMMAND_ERROR_SUCCESS;
00306 }
00307 }else{
00308 besALLOC_RETURN_LONG;
00309 LONGVALUE(besRETURNVALUE) = p->iErrorRegex ? 0 : -1;
00310 }
00311
00312 regfree(preg);
00313 besFREE(pmatch);
00314 besFREE(preg);
00315
00316 besEND
00317
00327 besFUNCTION(nmatch)
00328 pModuleObject p;
00329
00330 p = (pModuleObject)besMODULEPOINTER;
00331
00332 besALLOC_RETURN_LONG;
00333 LONGVALUE(besRETURNVALUE) = p->lMatches -1;
00334
00335 besEND
00336
00348 besFUNCTION(dollar)
00349 pModuleObject p;
00350 VARIABLE Argument;
00351 long n;
00352
00353 p = (pModuleObject)besMODULEPOINTER;
00354 n = 0;
00355 besRETURNVALUE = NULL;
00356 if( p->pszMatch == NULL )return COMMAND_ERROR_SUCCESS;
00357 Argument = besARGUMENT(1);
00358 besDEREFERENCE(Argument);
00359 if( Argument != NULL ){
00360 Argument = besCONVERT2LONG(Argument);
00361 n = LONGVALUE(Argument);
00362 }
00363 if( ((unsigned)n) > p->lMatches || n < 0 )return COMMAND_ERROR_SUCCESS;
00364 besALLOC_RETURN_STRING(p->lMatchLen[n]);
00365 STRLEN(besRETURNVALUE) = p->lMatchLen[n];
00366 memcpy(STRINGVALUE(besRETURNVALUE),p->pszMatch[n],STRLEN(besRETURNVALUE));
00367
00368 besEND
00369
00381 besFUNCTION(reset)
00382 pModuleObject p;
00383
00384 p = (pModuleObject)besMODULEPOINTER;
00385
00386 reset_pmatches(p);
00387 besEND
00388
00399 besFUNCTION(format)
00400 VARIABLE vReplace;
00401 pModuleObject p;
00402 int iError;
00403 int i;
00404
00405 p = (pModuleObject)besMODULEPOINTER;
00406 if( p->lMatches == 0 ){
00407 besRETURNVALUE = NULL;
00408 return COMMAND_ERROR_SUCCESS;
00409 }
00410
00411
00412 vReplace = besARGUMENT(1);
00413 if( vReplace == NULL ){
00414 besRETURNVALUE = NULL;
00415 return COMMAND_ERROR_SUCCESS;
00416 }
00417 vReplace = besCONVERT2STRING(vReplace);
00418 i = 0;
00419 iError =
00420 besMatchSize(STRINGVALUE(vReplace),
00421 STRLEN(vReplace),
00422 p->lMatchLen,
00423 p->lMatches,&i);
00424 if( iError ){
00425 besRETURNVALUE = NULL;
00426 return COMMAND_ERROR_SUCCESS;
00427 }
00428 besALLOC_RETURN_STRING(i);
00429 iError =
00430 besMatchParameter(STRINGVALUE(vReplace),
00431 STRLEN(vReplace),
00432 p->pszMatch,
00433 p->lMatchLen,
00434 STRINGVALUE(besRETURNVALUE),
00435 p->lMatches,
00436 &(STRLEN(besRETURNVALUE)));
00437 if( iError ){
00438 besRETURNVALUE = NULL;
00439 return COMMAND_ERROR_SUCCESS;
00440 }
00441
00442 besEND
00443
00444 struct list{
00445 unsigned long len;
00446 char *string;
00447 struct list *next;
00448 };
00449
00450 static void release_list(pSupportTable pSt, struct list *p){
00451 struct list *q;
00452
00453 while( p ){
00454 q = p;
00455 p = p->next;
00456 if( q->string )besFREE(q->string);
00457 besFREE(q);
00458 }
00459 }
00460 #define ReleaseList(X) release_list(pSt,(X))
00461
00494 besFUNCTION(replace)
00495 regex_t *preg;
00496 regmatch_t *pmatch;
00497 VARIABLE vString,vRegexp,vReplace;
00498 size_t nmatch;
00499 pModuleObject p;
00500 int iError;
00501 int eflags,eopt;
00502 int i;
00503 int iStart;
00504 int iTerm;
00505 struct list *root,**last,*item;
00506
00507 root = NULL;
00508 last = &root;
00509
00510 p = (pModuleObject)besMODULEPOINTER;
00511
00512
00513 vRegexp = besARGUMENT(2);
00514 besDEREFERENCE(vRegexp);
00515
00516 if( vRegexp == NULL ){
00517 besALLOC_RETURN_LONG;
00518 LONGVALUE(besRETURNVALUE) = 0;
00519 }
00520
00521 vRegexp = besCONVERT2STRING(vRegexp);
00522 preg = (regex_t *)besALLOC(sizeof(regex_t));
00523 if( preg == NULL )return COMMAND_ERROR_MEMORY_LOW;
00524 preg->re_endp = STRINGVALUE(vRegexp)+STRLEN(vRegexp);
00525
00526 eflags = REG_PEND|REG_EXTENDED;
00527 eopt = besOPTION("re$flag");
00528 if( eopt )eopt = ~ eopt;
00529
00530 if( eopt & SBCASE )eflags |= REG_ICASE;
00531 if( eopt & SBNEWLINE )eflags |= REG_NEWLINE;
00532
00533 eopt = besOPTION("re$replaceone");
00534
00535
00536 if( p->iErrorRegcomp = regcomp(preg, STRINGVALUE(vRegexp), eflags) ){
00537 besALLOC_RETURN_LONG;
00538 LONGVALUE(besRETURNVALUE) = 0;
00539 return ConvertError(p->iErrorRegcomp);
00540 }
00541
00542 nmatch = preg->re_nsub + 1;
00543
00544 vString = besARGUMENT(1);
00545 besDEREFERENCE(vString);
00546
00547 vString = besCONVERT2STRING(vString);
00548
00549
00550 vReplace = besARGUMENT(3);
00551 besDEREFERENCE(vReplace);
00552 vReplace = besCONVERT2STRING(vReplace);
00553
00554 for( iStart = 0 ; ((unsigned)iStart) < STRLEN(vString) ; ){
00555 pmatch = (regmatch_t *)besALLOC(sizeof(regmatch_t) * nmatch );
00556 if( pmatch == NULL )return COMMAND_ERROR_MEMORY_LOW;
00557 pmatch->rm_so = iStart;
00558 pmatch->rm_eo = STRLEN(vString);
00559 p->iErrorRegex = regexec(preg, STRINGVALUE(vString),nmatch,pmatch,REG_STARTEND);
00560
00561
00562 if( p->iErrorRegex == REG_NOMATCH )break;
00563
00564
00565 reset_pmatches(p);
00566
00567
00568 if( ! p->iErrorRegex && nmatch ){
00569
00570
00571
00572 p->lMatches = nmatch;
00573 p->lMatchLen = besALLOC(nmatch*sizeof(long));
00574 if( p->lMatchLen == NULL ){
00575 p->lMatches = 0;
00576 regfree(preg);
00577 besFREE(pmatch);
00578 besFREE(preg);
00579 return COMMAND_ERROR_MEMORY_LOW;
00580 }
00581
00582 p->pszMatch = besALLOC(nmatch*sizeof(char *));
00583 if( p->pszMatch == NULL ){
00584 besFREE(p->lMatchLen);
00585 p->lMatches = 0;
00586 regfree(preg);
00587 besFREE(pmatch);
00588 besFREE(preg);
00589 return COMMAND_ERROR_MEMORY_LOW;
00590 }
00591
00592
00593 for( i=0 ; ((size_t)i) < nmatch ; i++ ){
00594 p->lMatchLen[i] = pmatch[i].rm_eo - pmatch[i].rm_so;
00595 if( p->lMatchLen[i] )
00596 p->pszMatch[i] = besALLOC(p->lMatchLen[i]);
00597 else
00598 p->pszMatch[i] = besALLOC(1);
00599 if( p->pszMatch[i] == NULL ){
00600 do{ besFREE(p->pszMatch[--i]); }while(i);
00601 regfree(preg);
00602 besFREE(pmatch);
00603 besFREE(preg);
00604 return COMMAND_ERROR_MEMORY_LOW;
00605 }
00606 if( p->lMatchLen[i] )
00607 memcpy(p->pszMatch[i],STRINGVALUE(vString)+pmatch[i].rm_so,p->lMatchLen[i]);
00608 }
00609 }
00610
00611 i = 0;
00612 iError =
00613 besMatchSize(STRINGVALUE(vReplace),
00614 STRLEN(vReplace),
00615 p->lMatchLen,
00616 p->lMatches,&i);
00617 if( iError ){
00618 besRETURNVALUE = NULL;
00619 regfree(preg);
00620 besFREE(pmatch);
00621 besFREE(preg);
00622 return COMMAND_ERROR_SUCCESS;
00623 }
00624
00625
00626 if( pmatch->rm_so > iStart ){
00627 *last = besALLOC(sizeof(struct list));
00628 if( *last == NULL ){
00629 ReleaseList(root);
00630 besRETURNVALUE = NULL;
00631 regfree(preg);
00632 besFREE(pmatch);
00633 besFREE(preg);
00634 return COMMAND_ERROR_SUCCESS;
00635 }
00636 (*last)->next = NULL;
00637 (*last)->len = pmatch->rm_so-iStart;
00638 (*last)->string = besALLOC( (*last)->len );
00639 if( (*last)->string == NULL ){
00640 ReleaseList(root);
00641 besRETURNVALUE = NULL;
00642 regfree(preg);
00643 besFREE(pmatch);
00644 besFREE(preg);
00645 return COMMAND_ERROR_SUCCESS;
00646 }
00647 memcpy((*last)->string,STRINGVALUE(vString)+iStart,(*last)->len);
00648 last = &( (*last)->next );
00649 }
00650
00651
00652 if( i ){
00653 *last = besALLOC(sizeof(struct list));
00654 if( *last == NULL ){
00655 ReleaseList(root);
00656 besRETURNVALUE = NULL;
00657 regfree(preg);
00658 besFREE(pmatch);
00659 besFREE(preg);
00660 return COMMAND_ERROR_SUCCESS;
00661 }
00662 (*last)->next = NULL;
00663 (*last)->len = i;
00664 (*last)->string = besALLOC( (*last)->len );
00665 if( (*last)->string == NULL ){
00666 ReleaseList(root);
00667 besRETURNVALUE = NULL;
00668 regfree(preg);
00669 besFREE(pmatch);
00670 besFREE(preg);
00671 return COMMAND_ERROR_SUCCESS;
00672 }
00673 iError =
00674 besMatchParameter(STRINGVALUE(vReplace),
00675 STRLEN(vReplace),
00676 p->pszMatch,
00677 p->lMatchLen,
00678 (*last)->string,
00679 p->lMatches,
00680 &((*last)->len));
00681 last = &( (*last)->next );
00682 if( iError ){
00683 ReleaseList(root);
00684 besRETURNVALUE = NULL;
00685 regfree(preg);
00686 besFREE(pmatch);
00687 besFREE(preg);
00688 return COMMAND_ERROR_SUCCESS;
00689 }
00690 }
00691 iStart = pmatch->rm_eo;
00692 iTerm = iStart;
00693 if( eopt )break;
00694 }
00695
00696 if( ((unsigned)iTerm) < STRLEN(vString) ){
00697 *last = besALLOC(sizeof(struct list));
00698 if( *last == NULL ){
00699 ReleaseList(root);
00700 besRETURNVALUE = NULL;
00701 regfree(preg);
00702 besFREE(pmatch);
00703 besFREE(preg);
00704 return COMMAND_ERROR_SUCCESS;
00705 }
00706 (*last)->next = NULL;
00707 (*last)->len = STRLEN(vString)-iTerm;
00708 (*last)->string = besALLOC( (*last)->len );
00709 if( (*last)->string == NULL ){
00710 ReleaseList(root);
00711 besRETURNVALUE = NULL;
00712 regfree(preg);
00713 besFREE(pmatch);
00714 besFREE(preg);
00715 return COMMAND_ERROR_SUCCESS;
00716 }
00717 memcpy((*last)->string,STRINGVALUE(vString)+iTerm,(*last)->len);
00718 last = &( (*last)->next );
00719 }
00720
00721 regfree(preg);
00722 besFREE(pmatch);
00723 besFREE(preg);
00724
00725 i = 0;
00726 for( item = root ; item ; item = item->next ){
00727 i += item->len;
00728 }
00729 besALLOC_RETURN_STRING(i);
00730 i = 0;
00731 for( item = root ; item ; item = item->next ){
00732 memcpy(STRINGVALUE(besRETURNVALUE)+i,item->string,item->len);
00733 i += item->len;
00734 }
00735 ReleaseList(root);
00736
00737 besEND