Devel-CCov
view release on metacpan or search on metacpan
#ifdef __cplusplus
}
#endif
static int isword(char ch)
{
return (isalnum(ch) || ch == '#' || ch == '_')?1:0;
}
static int myrelen(char *re, int relen)
{
int len=0;
int tx;
for (tx=0; tx < relen; tx++) {
if (re[tx] == '\\') { tx++; continue; }
++len;
}
return len;
}
static int myrematch(char *base, char *targ, int targlen)
{
int tx;
int bx;
for (tx=0,bx=0; tx < targlen; tx++) {
if (targ[tx] == '\\') {
++tx;
if (targ[tx] == 'b') {
/* fprintf(stderr, "\\b=%c.%c\n", base[bx-1], base[bx]);/**/
if (!(isword(base[bx-1]) ^ isword(base[bx]))) return 0;
} else {
croak("myrematch: unknown metacharacter '%c'", targ[tx]);
}
} else {
/* fprintf(stderr, "%c=%c\n", base[bx], targ[tx]);/**/
if (base[bx] != targ[tx]) return 0;
bx++;
}
}
return 1;
}
MODULE = Devel::CCov PACKAGE = Devel::CCov
PROTOTYPES: ENABLE
void
cc_exprstr(in_str, in_target)
SV *in_str
SV *in_target
PREINIT:
STRLEN length;
STRLEN targlen, relen;
char *base_str;
char *targ_str;
int st_start, st_pos;
int pos = 0;
int state = 'r';
int line = 1;
int plevel = 0;
PPCODE:
base_str = SvPV(in_str, length);
if (length == 0) croak("cc_exprstr: length=0");
targ_str = SvPV(in_target, targlen);
relen = myrelen(targ_str, targlen);
while (pos < length) {
char at = base_str[pos];
char at2 = pos+1 < length? base_str[pos+1] : ' ';
char old_st = state;
if (at == '\n') ++line;
switch (state) {
case 'r':
if (at == '/' && at2 == '*') { state = 'c'; break; }
if (at == '/' && at2 == '/') { state = 'C'; break; }
if (at == '\'') { state = 'q'; break; }
if (at == '"') { state = 'Q'; break; }
if (at == '(') { ++plevel; break; }
if (at == ')') { --plevel; break; }
if (pos <= length - relen && plevel==0 &&
myrematch(base_str+pos, targ_str, targlen)) {
STRLEN tlen;
/*warn("len=%d targlen=%d pos=%d", length, targlen, pos);/**/
tlen = pos;
XPUSHs(sv_2mortal(newSVpv(base_str,tlen>0? tlen:0)));
tlen = length-pos;
XPUSHs(sv_2mortal(newSVpv(base_str+pos,tlen>0? tlen:0)));
PUTBACK;
return;
}
break;
case 'c':
if (at == '*' && at2 == '/') { ++pos; state = 'r'; }
break;
case 'C':
if (at == '\n') state = 'r';
break;
case 'q':
if (at == '\\' && at2 == '\\') { ++pos; break; }
if (at == '\\' && at2 == '\'') { ++pos; break; }
if (at == '\'') { state = 'r'; break; }
break;
case 'Q':
if (at == '\\' && at2 == '\\') { ++pos; break; }
if (at == '\\' && at2 == '"') { ++pos; break; }
if (at == '"') { state = 'r'; break; }
break;
default: croak("cc_exprstr: unknown state '%c' at line %d", state, line);
}
if (state != old_st && state != 'r') {
st_start = line; st_pos = pos;
}
++pos;
}
if (state == 'c') croak("cc_exprstr: unclosed comment starting on line %d: %s",st_start,base_str+st_pos);
if (state == 'q')
croak("cc_exprstr: unmatched single quote starting on line %d", st_start);
if (state == 'Q')
croak("cc_exprstr: unmatched double quote starting on line %d", st_start);
void
cc_strstr(in_str, in_target)
SV *in_str
SV *in_target
PREINIT:
STRLEN length;
STRLEN targlen, relen;
char *base_str;
char *targ_str;
int st_start, st_pos;
int pos = 0;
int state = 'r';
int line = 1;
PPCODE:
base_str = SvPV(in_str, length);
if (length == 0) croak("cc_strstr: length=0");
targ_str = SvPV(in_target, targlen);
relen = myrelen(targ_str, targlen);
while (pos < length) {
char at = base_str[pos];
char at2 = pos+1 < length? base_str[pos+1] : ' ';
char old_st = state;
if (at == '\n') ++line;
switch (state) {
case 'r':
if (at == '/' && at2 == '*') { state = 'c'; break; }
if (at == '/' && at2 == '/') { state = 'C'; break; }
if (at == '\'') { state = 'q'; break; }
if (at == '"') { state = 'Q'; break; }
if (pos <= length - relen &&
myrematch(base_str+pos, targ_str, targlen)) {
STRLEN tlen;
/*warn("len=%d targlen=%d pos=%d", length, targlen, pos);/**/
tlen = pos;
XPUSHs(sv_2mortal(newSVpv(base_str,tlen>0? tlen:0)));
tlen = length-pos;
XPUSHs(sv_2mortal(newSVpv(base_str+pos,tlen>0? tlen:0)));
PUTBACK;
return;
}
break;
case 'c':
if (at == '*' && at2 == '/') { ++pos; state = 'r'; break; }
break;
case 'C':
if (at == '\n') state = 'r';
break;
case 'q':
if (at == '\\' && at2 == '\\') { ++pos; break; }
if (at == '\\' && at2 == '\'') { ++pos; break; }
if (at == '\'') { state = 'r'; break; }
break;
case 'Q':
if (at == '\\' && at2 == '\\') { ++pos; break; }
if (at == '\\' && at2 == '"') { ++pos; break; }
if (at == '"') { state = 'r'; break; }
break;
default: croak("cc_strstr: unknown state '%c' at line %d", state, line);
}
if (0 && state != old_st) {
warn("LINE %d:%d state %c->%c\n", line, pos, old_st, state);
}
if (state != old_st && state != 'r') {
st_start = line; st_pos = pos;
}
if (0 && state != old_st && state == 'r') {
int px;
fprintf(stderr, "LINE %d %c[%d-%d] [", st_start, old_st, st_pos, pos);
for (px=st_pos; px <= pos && px < length; px++) {
fprintf(stderr, "%c", base_str[px]);
}
fprintf(stderr, "]\n");
}
++pos;
}
if (state == 'c') croak("cc_strstr: unclosed comment starting on line %d: %s",st_start,base_str+st_pos);
if (state == 'q')
croak("cc_strstr: unmatched single quote starting on line %d", st_start);
if (state == 'Q')
croak("cc_strstr: unmatched double quote starting on line %d", st_start);
void
extract_balanced(in_str, paren1)
SV *in_str
char paren1
PREINIT:
STRLEN length;
char *base_str;
int line;
int pos;
int opens,closes;
int st_start;
int st_pos;
char state;
char paren2;
PPCODE:
/*warn("---BEGIN codeblock\n");/**/
if (!(paren1 == '(' || paren1 == '{'))
croak("extract_balanced: only works on () and {}");
paren2 = paren1 == '('? ')' : '}';
base_str = SvPV(in_str, length);
line = 1;
pos = 0;
opens = closes = 0;
state = 'r';
if (base_str[0] != paren1)
croak("extract_balanced: string doesn't begin with open quote");
++pos;
++opens;
while (opens - closes > 0 && pos < length) {
char at = base_str[pos];
char at2 = pos+1 < length? base_str[pos+1] : ' ';
char old_st = state;
if (at == '\n') ++line;
switch (state) {
case 'r':
if (at == paren1) { ++opens; break; }
if (at == paren2) { ++closes; break; }
if (at == '/' && at2 == '*') { state = 'c'; break; }
if (at == '/' && at2 == '/') { state = 'C'; break; }
if (at == '\'') { state = 'q'; break; }
if (at == '"') { state = 'Q'; break; }
break;
case 'c':
if (at == '*' && at2 == '/') { ++pos; state = 'r'; break; }
break;
case 'C':
if (at == '\n') state = 'r';
break;
case 'q':
if (at == '\\' && at2 == '\\') { ++pos; break; }
if (at == '\\' && at2 == '\'') { ++pos; break; }
if (at == '\'') { state = 'r'; break; }
break;
case 'Q':
if (at == '\\' && at2 == '\\') { ++pos; break; }
if (at == '\\' && at2 == '"') { ++pos; break; }
if (at == '"') { state = 'r'; break; }
break;
default: croak("extract_balanced: unknown state '%c' at line %d", state, line);
}
if (state != old_st && state != 'r') {
st_start = line; st_pos = pos;
}
if (0 && state != old_st && state == 'r') {
int px;
fprintf(stderr, "LINE %d %c[%d-%d] [", st_start, old_st, st_pos, pos);
for (px=st_pos; px <= pos && px < length; px++) {
fprintf(stderr, "%c", base_str[px]);
}
fprintf(stderr, "]\n");
}
++pos;
}
if (state == 'c') croak("extract_balanced: unclosed comment starting on line %d: %s",st_start,base_str+st_pos);
if (state == 'q')
( run in 0.947 second using v1.01-cache-2.11-cpan-71847e10f99 )