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:
Dustin Mitchell 2000-01-18 23:13:56 +00:00
commit e24104982b

View file

@ -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