Finished writing the thing -- I think
git-svn-id: https://swig.svn.sourceforge.net/svnroot/swig/trunk/SWIG@104 626c5289-ae23-0410-ae9c-e8d60b6d4f22
This commit is contained in:
parent
67940725e8
commit
e24104982b
1 changed files with 700 additions and 608 deletions
|
|
@ -16,7 +16,7 @@
|
|||
|
||||
#include "doh.h"
|
||||
#include "swigcore.h"
|
||||
#if 0
|
||||
|
||||
static char cvstag[] = "$Header$";
|
||||
|
||||
/*
|
||||
|
|
@ -25,13 +25,15 @@ static char cvstag[] = "$Header$";
|
|||
* contain.
|
||||
*/
|
||||
|
||||
typedef struct SSTag {
|
||||
typedef struct SSTag
|
||||
{
|
||||
int length; /* distance to the next tag */
|
||||
int line; /* of this character */
|
||||
DOH *filename; /* of this character */
|
||||
} SSTag;
|
||||
|
||||
typedef struct Super {
|
||||
typedef struct Super
|
||||
{
|
||||
DOHCOMMON;
|
||||
|
||||
/* -- from the regular string implementation */
|
||||
|
|
@ -89,11 +91,11 @@ static void Super_delete_tag(Super *s, int index);
|
|||
static void Super_count_newlines(char *s, int len);
|
||||
static void Super_string_insert(Super *s, int pos, char *str,
|
||||
int len, DOH *filename, int line);
|
||||
static void Super_super_insert2(Super *s, int pos, Super *str,
|
||||
static void Super_super_insert2(Super *s, int pos, char *str,
|
||||
int, DOH *, int);
|
||||
static void Super_super_insert(Super *s, int pos, Super *str);
|
||||
|
||||
typedef void (*callback)(Super *, int, DOH *, int, DOH *, int);
|
||||
typedef void (*callback)(Super *, int, char *, int, DOH *, int);
|
||||
static int Super_raw_replace(Super *str, char *token, int flags,
|
||||
callback insert, DOH *rep, int rep_len,
|
||||
DOH *rep_fn, int rep_line);
|
||||
|
|
@ -578,7 +580,12 @@ Super_seek(DOH *so, long offset, int whence)
|
|||
s->pbi = 0;
|
||||
|
||||
if (whence == SEEK_SET) offset = -s->sp;
|
||||
else if (whence == SEEK_END) offset = s->len - offset;
|
||||
else if (whence == SEEK_END) offset = s->len - s->sp - offset;
|
||||
|
||||
if (offset + s->sp < 0)
|
||||
offset = -s->sp;
|
||||
else if (offset + s->sp > s->len)
|
||||
offset = s->len - s->sp;
|
||||
|
||||
Super_move(s, offset);
|
||||
|
||||
|
|
@ -871,7 +878,7 @@ Super_add_space(Super *s, int more_bytes)
|
|||
newsize = (s->len + more_bytes) * 2;
|
||||
s->str = (char *)DohRealloc(s->str, newsize);
|
||||
assert(s->str);
|
||||
s->maxsize = newsize
|
||||
s->maxsize = newsize;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -964,11 +971,11 @@ Super_string_insert(Super *s, int pos, char *str, int len,
|
|||
* ------------------------------------------------------------------------- */
|
||||
|
||||
static void
|
||||
Super_super_insert2(Super *s, int pos, Super *str,
|
||||
Super_super_insert2(Super *s, int pos, char *str,
|
||||
int ignore1, DOH *ignore2, int ignore3)
|
||||
{ /* this function's prototype matches Super_string_insert, so it can
|
||||
be used as a callback */
|
||||
Super_super_insert(s, pos, str);
|
||||
Super_super_insert(s, pos, (Super *)str);
|
||||
}
|
||||
|
||||
static void
|
||||
|
|
@ -1076,12 +1083,78 @@ Super_super_insert(Super *s, int pos, Super *str)
|
|||
*
|
||||
* ------------------------------------------------------------------------- */
|
||||
|
||||
/* static variables for use in Super_raw_replace */
|
||||
|
||||
static Super *rr_dest;
|
||||
static Super *rr_original;
|
||||
|
||||
static void
|
||||
Super_rr_append_chunk(int start, int len)
|
||||
{
|
||||
SSTag initial, final;
|
||||
SSTag new_initial, new_final;
|
||||
int initial_tag, final_tag;
|
||||
int old_numtags, old_len;
|
||||
/* the job of this function: append a chunk to rr_dest from
|
||||
rr_original. */
|
||||
|
||||
/* we use Super_move because it lets us move relatively within the
|
||||
string instead of having to recalculate from the beginning every
|
||||
time with Super_get_tag() */
|
||||
Super_move(rr_original, start - rr_original->sp);
|
||||
initial_tag = rr_original->curtag;
|
||||
initial = rr_original->tags[initial_tag];
|
||||
|
||||
new_initial.line = rr_original->line;
|
||||
new_initial.filename = rr_original->filename;
|
||||
new_initial.length = initial.length - rr_original->curtag_offset;
|
||||
|
||||
Super_move(rr_original, len);
|
||||
final_tag = rr_original->curtag;
|
||||
|
||||
if (rr_original->curtag_offset )
|
||||
{
|
||||
final = rr_original->tags[final_tag];
|
||||
new_final.line = rr_original->line;
|
||||
new_final.filename = rr_original->filename;
|
||||
new_final.length = rr_original->curtag_offset;
|
||||
}
|
||||
else /* avoid zero-length final tag */
|
||||
{
|
||||
final_tag--;
|
||||
final = rr_original->tags[final_tag];
|
||||
new_final = final;
|
||||
}
|
||||
|
||||
/* tuck away some other info */
|
||||
old_numtags = rr_original->numtags;
|
||||
old_len = rr_original->len;
|
||||
|
||||
/* OK, now we swap in our new tags, offset the tags and str fields
|
||||
appropriately, set the lengths correctly, and call insert. */
|
||||
rr_original->tags[initial_tag] = new_initial;
|
||||
rr_original->tags[final_tag] = new_final;
|
||||
rr_original->numtags = final_tag - initial_tag + 1;
|
||||
rr_original->tags += initial_tag;
|
||||
rr_original->len = len;
|
||||
rr_original->str += start;
|
||||
|
||||
Super_super_insert(rr_dest, DOH_END, rr_original); /* easy!? */
|
||||
|
||||
rr_original->str -= start;
|
||||
rr_original->len = old_len;
|
||||
rr_original->tags -= initial_tag;
|
||||
rr_original->numtags = old_numtags;
|
||||
rr_original->tags[final_tag] = final;
|
||||
rr_original->tags[initial_tag] = initial;
|
||||
}
|
||||
|
||||
static int
|
||||
Super_raw_replace(Super *str, char *token, int flags,
|
||||
callback insert, DOH *rep, int rep_len,
|
||||
DOH *rep_fn, int rep_line)
|
||||
{
|
||||
char *s, *t;
|
||||
char *match, *lastmatch_end;
|
||||
int tokenlen, state, i;
|
||||
int repcount = 0;
|
||||
Super fake; /* HACK! :) */
|
||||
|
|
@ -1091,127 +1164,146 @@ Super_raw_replace(Super *str, char *token, int flags,
|
|||
int old_len;
|
||||
|
||||
str->hashkey = -1;
|
||||
|
||||
tokenlen = strlen(token);
|
||||
|
||||
/* first see if there is a match, using the speedy library
|
||||
function */
|
||||
t = strstr(str->str, token);
|
||||
if (!t) return 0;
|
||||
match = strstr(str->str, token);
|
||||
if (!match) return 0;
|
||||
|
||||
/* otherwise, keep the current text of the string and its tags. */
|
||||
old_str = str->str;
|
||||
old_len = str->len;
|
||||
old_tags = str->tags;
|
||||
old_numtags = str->numtags;
|
||||
for (i = 0; i < old_numtags; i++)
|
||||
Incref(old_tags[i].filename); /* we want to keep this! */
|
||||
/* if there is a match, then fill in the global variables. Note
|
||||
that we only copy the necessary fields. */
|
||||
rr_dest = str;
|
||||
rr_original = (Super *)CopySuper((DOH *)str);
|
||||
|
||||
/* and obliterate this super, allocating new space for both tags
|
||||
and data. */
|
||||
Super_clear(str);
|
||||
str->str = (char *) DohMalloc(str->maxsize);
|
||||
assert(str->str);
|
||||
str->tags = (SSTag *) DohMalloc(str->maxtags * sizeof(SSTag));
|
||||
|
||||
/* fill in the fake Super so we can use it for appending */
|
||||
fake.str = old_str;
|
||||
fake.tags = old_tags;
|
||||
/* Now obliterate our "destination". */
|
||||
Super_clear(rr_dest);
|
||||
|
||||
/* if we can do this using library functions, get to work. */
|
||||
if (!(flags & (DOH_REPLACE_ID | DOH_REPLACE_NOQUOTE)))
|
||||
while (1)
|
||||
{
|
||||
int offset;
|
||||
|
||||
if (t > fake.str)
|
||||
lastmatch_end = rr_original->str;
|
||||
while ((match = strstr(lastmatch_end, token)))
|
||||
{
|
||||
/* append a chunk from the old string */
|
||||
fake.len = t - fake.str;
|
||||
fake.numtags = Super_get_tag(&fake, fake.len, &offset) + 1;
|
||||
if (offset == 0) fake.numtags--; /* avoid an empty last tag */
|
||||
Super_super_insert(str, DOH_END, &fake);
|
||||
/* copy the unchanged stuff from the original */
|
||||
Super_rr_append_chunk(lastmatch_end - rr_original->str,
|
||||
match - lastmatch_end);
|
||||
|
||||
/* now move 'fake' over that chunk */
|
||||
fake.str += fake.len;
|
||||
fake.tags += numtags - 1;
|
||||
/* OBIWAN! */ /*
|
||||
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! */
|
||||
}
|
||||
}
|
||||
/* and now insert the replacement */
|
||||
(*insert)(rr_dest, DOH_END, (char *)rep,
|
||||
rep_len, rep_fn, rep_line);
|
||||
|
||||
while (1)
|
||||
/* Depending on flags. We compare in different ways */
|
||||
state = 0;
|
||||
t = c;
|
||||
while ((*c) && (count)) {
|
||||
switch(state) {
|
||||
case 0:
|
||||
if (*c == *token) {
|
||||
if (!(flags & DOH_REPLACE_ID)) {
|
||||
if (strncmp(c,token,tokenlen) == 0) {
|
||||
char temp = *c;
|
||||
*c = 0;
|
||||
Super_add(str,t);
|
||||
*c = temp;
|
||||
Super_add(str,rep);
|
||||
c += (tokenlen-1);
|
||||
t = c+1;
|
||||
count--;
|
||||
/* now move our pointer up.. */
|
||||
lastmatch_end = match + tokenlen;
|
||||
repcount++;
|
||||
}
|
||||
} else if (isalpha(*c) || (*c == '_') || (*c == '$')) {
|
||||
char temp = *c;
|
||||
*c = 0;
|
||||
Super_add(str,t);
|
||||
*c = temp;
|
||||
t = c;
|
||||
state = 10;
|
||||
}
|
||||
} else if (flags & DOH_REPLACE_NOQUOTE) {
|
||||
if (*c == '\"') state = 20;
|
||||
else if (*c == '\'') state = 30;
|
||||
}
|
||||
break;
|
||||
case 10: /* The start of an identifier */
|
||||
if (isalnum(*c) || (*c == '_') || (*c == '$')) state = 10;
|
||||
else {
|
||||
char temp = *c;
|
||||
*c = 0;
|
||||
if (strcmp(token,t) == 0) {
|
||||
Super_add(str,rep);
|
||||
count--;
|
||||
repcount++;
|
||||
} else {
|
||||
Super_add(str,t);
|
||||
}
|
||||
*c = temp;
|
||||
t = c;
|
||||
state = 0;
|
||||
}
|
||||
break;
|
||||
case 20: /* A Super */
|
||||
if (*c == '\"') state = 0;
|
||||
else if (*c == '\\') c++;
|
||||
break;
|
||||
case 30: /* A Single quoted Super */
|
||||
if (*c == '\'') state = 0;
|
||||
else if (*c == '\\') c++;
|
||||
break;
|
||||
}
|
||||
c++;
|
||||
}
|
||||
if ((count) && (state == 10)) {
|
||||
if (strcmp(token,t) == 0) {
|
||||
Super_add(str,rep);
|
||||
} else {
|
||||
Super_add(str,t);
|
||||
}
|
||||
} else {
|
||||
Super_add(str,t);
|
||||
}
|
||||
DohFree(s);
|
||||
}
|
||||
|
||||
/* copy the unchanged stuff from the end */
|
||||
Super_rr_append_chunk(lastmatch_end - rr_original->str,
|
||||
rr_original->str + rr_original->len -
|
||||
lastmatch_end);
|
||||
|
||||
Delete(rr_original);
|
||||
return repcount;
|
||||
}
|
||||
|
||||
/* otherwise we need to do our own kind of search, with Dave's
|
||||
special little state machine to tell us when we're in quotes or
|
||||
not at the beginning of an identifier. */
|
||||
#define RR_BEGIN_MATCH 0
|
||||
#define RR_INSIDE_IDENTIFIER 1
|
||||
#define RR_INSIDE_SINGLE_QUOTE 2
|
||||
#define RR_INSIDE_DOUBLE_QUOTE 3
|
||||
#define RR_DONE -1
|
||||
state = 0;
|
||||
match = lastmatch_end = rr_original->str;
|
||||
|
||||
while (*match && state != RR_DONE)
|
||||
{
|
||||
switch(state)
|
||||
{
|
||||
case RR_BEGIN_MATCH:
|
||||
if (*match == *token &&
|
||||
strncmp(match,token,tokenlen) == 0)
|
||||
{
|
||||
/* skip if not the whole identifier */
|
||||
if (flags & DOH_REPLACE_ID)
|
||||
{
|
||||
char after= *(match + tokenlen);
|
||||
if (after == '_' || after == '$' || isalnum(after))
|
||||
{
|
||||
match += tokenlen;
|
||||
state = RR_INSIDE_IDENTIFIER;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
/* copy the unchanged stuff from the original */
|
||||
Super_rr_append_chunk(lastmatch_end - rr_original->str,
|
||||
match - lastmatch_end);
|
||||
|
||||
/* and now insert the replacement */
|
||||
(*insert)(rr_dest, DOH_END, (char *)rep,
|
||||
rep_len, rep_fn, rep_line);
|
||||
|
||||
/* now move our pointer up.. */
|
||||
match = lastmatch_end = match + tokenlen;
|
||||
repcount++;
|
||||
|
||||
/* bail now if we only want to replace one */
|
||||
if (flags & DOH_REPLACE_FIRST)
|
||||
state = RR_DONE;
|
||||
|
||||
/* we're now not ready to replace another identifier,
|
||||
if anybody cares */
|
||||
else if (flags & DOH_REPLACE_ID)
|
||||
state = RR_INSIDE_IDENTIFIER;
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
if (flags & DOH_REPLACE_ID)
|
||||
{
|
||||
if (*match == '_' || *match == '*' || isalpha(*match))
|
||||
state = RR_INSIDE_IDENTIFIER;
|
||||
}
|
||||
|
||||
if (flags & DOH_REPLACE_NOQUOTE)
|
||||
{
|
||||
if (*match == '\"') state = RR_INSIDE_DOUBLE_QUOTES;
|
||||
else if (*match == '\'') state = RR_INSIDE_SINGLE_QUOTES;
|
||||
else if (*match == '\\' &&
|
||||
(*(match+1) == '\'' || *(match+1) == '\"'))
|
||||
match++;
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case RR_IN_IDENTIFIER:
|
||||
if (!(isalnum(*match) || (*match == '_') || (*match == '$')))
|
||||
state = RR_BEGIN_MATCH;
|
||||
break;
|
||||
|
||||
case RR_IN_DOUBLE_QUOTES:
|
||||
if (*match == '\"') state = RR_BEGIN_MATCH;
|
||||
else if (*match == '\\') match++;
|
||||
break;
|
||||
|
||||
case RR_IN_SINGLE_QUOTES:
|
||||
if (*match == '\'') state = RR_BEGIN_MATCH;
|
||||
else if (*match == '\\') match++;
|
||||
break;
|
||||
}
|
||||
|
||||
match++;
|
||||
}
|
||||
|
||||
/* copy the unchanged stuff from the end */
|
||||
Super_rr_append_chunk(lastmatch_end - rr_original->str,
|
||||
rr_original->str + rr_original->len -
|
||||
lastmatch_end);
|
||||
|
||||
|
||||
Delete(rr_original);
|
||||
return repcount;
|
||||
}
|
||||
#endif
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue