G:/ScriptBasic/source/extensions/re/interface.c

Go to the documentation of this file.
00001 /* reinterf.c
00002 
00003 Interface file for the regular expression functions to be used as a
00004 ScriptBasic application.
00005 
00006 NTLIBS:
00007 UXLIBS:
00008 DWLIBS:
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;        /* error returned by regcomp */
00033   int iErrorRegex;          /* error returned by regex   */
00034   unsigned long lMatches;   /* the number of () matches during the last match */
00035   unsigned long *lMatchLen; /* the length of the matches */ 
00036   char **pszMatch;          /* string array if the () matches */
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   /* if there was any () match before release those */
00183   reset_pmatches(p);
00184 
00185   /* get the regular expression */
00186   vRegexp = besARGUMENT(2);
00187   besDEREFERENCE(vRegexp);
00188   /* undef as regular expression matches nothing */
00189   if( vRegexp == NULL ){
00190     besALLOC_RETURN_LONG;
00191     LONGVALUE(besRETURNVALUE) = 0;
00192     }
00193   /* we need this as string */
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   /* if regexp is erroneous return false */
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   /* we need this as string */
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   /* STORE THE PARENTHESED MATCH RESULTS */
00230   if( ! p->iErrorRegex && nmatch ){
00231 
00232     /* allocate space for the strings */
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     /* copy the substring into the dollar buffer */
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);/* allocate a dummy byte to store a null length string */
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] )/* copy all non-zero-length strings */
00269         memcpy(p->pszMatch[i],STRINGVALUE(vString)+pmatch[i].rm_so,p->lMatchLen[i]);
00270       }
00271     }
00272 
00273   /* if there is a replace argument we return the result string. */
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; /* as a default we get the total match */
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   /* if there was any () match before release those */
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   /* if there is a replace argument we return the result string. */
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; /* where the substring to match starts */
00504   int iTerm;  /* where the last substring finished */
00505   struct list *root,**last,*item;
00506  
00507   root = NULL;
00508   last = &root;
00509 
00510   p = (pModuleObject)besMODULEPOINTER;
00511 
00512   /* get the regular expression */
00513   vRegexp = besARGUMENT(2);
00514   besDEREFERENCE(vRegexp);
00515   /* undef as regular expression matches nothing */
00516   if( vRegexp == NULL ){
00517     besALLOC_RETURN_LONG;
00518     LONGVALUE(besRETURNVALUE) = 0;
00519     }
00520   /* we need this as string */
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   /* if regexp is erroneous return false */
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   /* we need this as string */
00547   vString = besCONVERT2STRING(vString);
00548 
00549   /* there should be a replace argument. */
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;          /* from the start of the substring */
00558     pmatch->rm_eo = STRLEN(vString); /* to the end                      */
00559     p->iErrorRegex = regexec(preg, STRINGVALUE(vString),nmatch,pmatch,REG_STARTEND);
00560 
00561     /* if there is no more match then exit from the match loop */
00562     if( p->iErrorRegex == REG_NOMATCH  )break;
00563 
00564     /* if there was any () match before release those */
00565     reset_pmatches(p);
00566 
00567     /* STORE THE PARENTHESED MATCH RESULTS */
00568     if( ! p->iErrorRegex && nmatch ){
00569 
00570       /* allocate space for the strings */
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       /* copy the substring into the dollar buffer */
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);/* allocate a dummy byte to store a null length string */
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] )/* copy all non-zero-length strings */
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     /* copy the string that preceedes the current match into the list */
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     /* copy the replace into the list */
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

Generated on Sun Mar 12 23:56:29 2006 for ScriptBasic by  doxygen 1.4.6-NO