mirror of
https://git.postgresql.org/git/postgresql.git
synced 2024-08-17 16:03:23 +02:00
152 lines
3.0 KiB
C
152 lines
3.0 KiB
C
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
#include <ctype.h>
|
|
|
|
#include "regis.h"
|
|
#include "common.h"
|
|
|
|
int
|
|
RS_isRegis(const char *str) {
|
|
unsigned char *ptr=(unsigned char *)str;
|
|
|
|
while(ptr && *ptr)
|
|
if ( isalpha(*ptr) || *ptr=='[' || *ptr==']' || *ptr=='^')
|
|
ptr++;
|
|
else
|
|
return 0;
|
|
return 1;
|
|
}
|
|
|
|
#define RS_IN_ONEOF 1
|
|
#define RS_IN_ONEOF_IN 2
|
|
#define RS_IN_NONEOF 3
|
|
#define RS_IN_WAIT 4
|
|
|
|
static RegisNode*
|
|
newRegisNode(RegisNode *prev, int len) {
|
|
RegisNode *ptr;
|
|
ptr = (RegisNode*)malloc(RNHDRSZ+len+1);
|
|
if (!ptr)
|
|
ts_error(ERROR, "No memory");
|
|
memset(ptr,0,RNHDRSZ+len+1);
|
|
if (prev)
|
|
prev->next=ptr;
|
|
return ptr;
|
|
}
|
|
|
|
int
|
|
RS_compile(Regis *r, int issuffix, const char *str) {
|
|
int i,len = strlen(str);
|
|
int state = RS_IN_WAIT;
|
|
RegisNode *ptr=NULL;
|
|
|
|
memset(r,0,sizeof(Regis));
|
|
r->issuffix = (issuffix) ? 1 : 0;
|
|
|
|
for(i=0;i<len;i++) {
|
|
unsigned char c = *( ( (unsigned char*)str ) + i );
|
|
if ( state == RS_IN_WAIT ) {
|
|
if ( isalpha(c) ) {
|
|
if ( ptr )
|
|
ptr = newRegisNode(ptr,len);
|
|
else
|
|
ptr = r->node = newRegisNode(NULL,len);
|
|
ptr->data[ 0 ] = c;
|
|
ptr->type = RSF_ONEOF;
|
|
ptr->len=1;
|
|
} else if ( c=='[' ) {
|
|
if ( ptr )
|
|
ptr = newRegisNode(ptr,len);
|
|
else
|
|
ptr = r->node = newRegisNode(NULL,len);
|
|
ptr->type = RSF_ONEOF;
|
|
state=RS_IN_ONEOF;
|
|
} else
|
|
ts_error(ERROR,"Error in regis: %s at pos %d\n", str, i+1);
|
|
} else if ( state == RS_IN_ONEOF ) {
|
|
if ( c=='^' ) {
|
|
ptr->type = RSF_NONEOF;
|
|
state=RS_IN_NONEOF;
|
|
} else if ( isalpha(c) ) {
|
|
ptr->data[ 0 ] = c;
|
|
ptr->len=1;
|
|
state=RS_IN_ONEOF_IN;
|
|
} else
|
|
ts_error(ERROR,"Error in regis: %s at pos %d\n", str, i+1);
|
|
} else if ( state == RS_IN_ONEOF_IN || state == RS_IN_NONEOF ) {
|
|
if ( isalpha(c) ) {
|
|
ptr->data[ ptr->len ] = c;
|
|
ptr->len++;
|
|
} else if ( c==']' ) {
|
|
state=RS_IN_WAIT;
|
|
} else
|
|
ts_error(ERROR,"Error in regis: %s at pos %d\n", str, i+1);
|
|
} else
|
|
ts_error(ERROR,"Internal error in RS_compile: %d\n", state);
|
|
}
|
|
|
|
ptr = r->node;
|
|
while(ptr) {
|
|
r->nchar++;
|
|
ptr=ptr->next;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
void
|
|
RS_free(Regis *r) {
|
|
RegisNode *ptr=r->node,*tmp;
|
|
|
|
while(ptr) {
|
|
tmp=ptr->next;
|
|
free(ptr);
|
|
ptr = tmp;
|
|
}
|
|
|
|
r->node = NULL;
|
|
}
|
|
|
|
int
|
|
RS_execute(Regis *r, const char *str, int len) {
|
|
RegisNode *ptr=r->node;
|
|
unsigned char *c;
|
|
|
|
if (len<0)
|
|
len=strlen(str);
|
|
|
|
if (len<r->nchar)
|
|
return 0;
|
|
|
|
if ( r->issuffix )
|
|
c = ((unsigned char*)str) + len - r->nchar;
|
|
else
|
|
c = (unsigned char*)str;
|
|
|
|
while(ptr) {
|
|
switch(ptr->type) {
|
|
case RSF_ONEOF:
|
|
if ( ptr->len==0 ) {
|
|
if ( *c != *(ptr->data) )
|
|
return 0;
|
|
} else if ( strchr((char*)ptr->data, *c) == NULL )
|
|
return 0;
|
|
break;
|
|
case RSF_NONEOF:
|
|
if ( ptr->len==0 ) {
|
|
if ( *c == *(ptr->data) )
|
|
return 0;
|
|
} else if ( strchr((char*)ptr->data, *c) != NULL )
|
|
return 0;
|
|
break;
|
|
default:
|
|
ts_error(ERROR,"RS_execute: Unknown type node: %d\n", ptr->type);
|
|
}
|
|
ptr=ptr->next;
|
|
c++;
|
|
}
|
|
|
|
return 1;
|
|
}
|