#define PC_MALLOC 256/* Bytes for pointers */ #define PS_MALLOC 512/* Bytes for data */
typedefstruct st_pointer_array { /* when using array-strings */
TYPELIB typelib; /* Pointer to strings */
uchar *str; /* Strings is here */
uint8 *flag; /* Flag about each var. */
uint array_allocs,max_count,length,max_length;
} POINTER_ARRAY;
int main(int argc, char *argv[])
{ int i,error; char word_end_chars[256],*pos;
POINTER_ARRAY from,to;
REPLACE *replace;
MY_INIT(argv[0]);
if (static_get_options(&argc,&argv)) exit(1); if (get_replace_strings(&argc,&argv,&from,&to)) exit(1);
for (i=1,pos=word_end_chars ; i < 256 ; i++) if (my_isspace(&my_charset_latin1,i))
*pos++= (char) i;
*pos=0; if (!(replace=init_replace((char**) from.typelib.type_names,
(char**) to.typelib.type_names,
(uint) from.typelib.count,word_end_chars))) exit(1);
free_pointer_array(&from);
free_pointer_array(&to); if (initialize_buffer()) return1;
error=0; if (argc == 0)
error=convert_pipe(replace,stdin,stdout); else
{ while (argc--)
{
error=convert_file(replace,*(argv++));
}
}
free_buffer();
my_free(replace);
my_end(verbose ? MY_CHECK_ERROR | MY_GIVE_INFO : MY_CHECK_ERROR); exit(error ? 2 : 0); return0; /* No compiler warning */
} /* main */
/* reads options */ /* Initiates DEBUG - but no debugging here ! */
staticint static_get_options(int *argc, char***argv)
{ int help,version; char *pos;
silent=verbose=help=0;
while (--*argc > 0 && *(pos = *(++*argv)) == '-' && pos[1] != '-') { while (*++pos)
{
version=0; switch((*pos)) { case's':
silent=1; break; case'v':
verbose=1; break; case'#':
DBUG_PUSH (++pos);
pos= (char*) " "; /* Skip rest of arguments */ break; case'V':
version=1; /* fall through */ case'I': case'?':
help=1; /* Help text written */
print_version(); if (version) break;
puts("This software comes with ABSOLUTELY NO WARRANTY. This is free software,\nand you are welcome to modify and redistribute it under the GPL license\n");
puts("This program replaces strings in files or from stdin to stdout.\n" "It accepts a list of from-string/to-string pairs and replaces\n" "each occurrence of a from-string with the corresponding to-string.\n" "The first occurrence of a found string is matched. If there is\n" "more than one possibility for the string to replace, longer\n" "matches are preferred before shorter matches.\n\n" "A from-string can contain these special characters:\n" " \\^ Match start of line.\n" " \\$ Match end of line.\n" " \\b Match space-character, start of line or end of line.\n" " For a end \\b the next replace starts locking at the end\n" " space-character. A \\b alone in a string matches only a\n" " space-character.\n");
printf("Usage: %s [-?svIV] from to from to ... -- [files]\n", my_progname);
puts("or");
printf("Usage: %s [-?svIV] from to from to ... < fromfile > tofile\n", my_progname);
puts("");
puts("Options: -? or -I \"Info\" -s \"silent\" -v \"verbose\""); break; default:
fprintf(stderr,"illegal option: -%c\n",*pos); break;
}
}
} if (*argc == 0)
{ if (!help)
my_message(0,"No replace options given",MYF(ME_BELL)); exit(0); /* Don't use as pipe */
} return(0);
} /* static_get_options */
typedefstruct st_rep_set {
uint *bits; /* Pointer to used sets */ short next[LAST_CHAR_CODE]; /* Pointer to next sets */
uint found_len; /* Best match to date */ int found_offset;
uint table_offset;
uint size_of_bits; /* For convenience */
} REP_SET;
typedefstruct st_rep_sets {
uint count; /* Number of sets */
uint extra; /* Extra sets in buffer */
uint invisible; /* Sets not chown */
uint size_of_bits;
REP_SET *set,*set_buffer;
uint *bit_buffer;
} REP_SETS;
typedefstruct st_found_set {
uint table_offset; int found_offset;
} FOUND_SET;
/* Count number of states */ for (i=result_len=max_length=0 , states=2 ; i < count ; i++)
{
len=replace_len(from[i]); if (!len)
{
errno=EINVAL;
my_message(0,"No to-string for last from-string",MYF(ME_BELL));
DBUG_RETURN(0);
}
states+=len+1;
result_len+=(uint) strlen(to[i])+1; if (len > max_length)
max_length=len;
}
bzero((char*) is_word_end,sizeof(is_word_end)); for (i=0 ; word_end_chars[i] ; i++)
is_word_end[(uchar) word_end_chars[i]]=1;
if (init_sets(&sets,states))
DBUG_RETURN(0);
found_sets=0; if (!(found_set= (FOUND_SET*) my_malloc(PSI_NOT_INSTRUMENTED, sizeof(FOUND_SET)*max_length*count,
MYF(MY_WME))))
{
free_sets(&sets);
DBUG_RETURN(0);
}
(void) make_new_set(&sets); /* Set starting set */
make_sets_invisible(&sets); /* Hide previus sets */
used_sets=-1;
word_states=make_new_set(&sets); /* Start of new word */
start_states=make_new_set(&sets); /* This is first state */ if (!(follow=(FOLLOWS*) my_malloc(PSI_NOT_INSTRUMENTED,
(states+2)*sizeof(FOLLOWS), MYF(MY_WME))))
{
free_sets(&sets);
my_free(found_set);
DBUG_RETURN(0);
}
for (set_nr=0,pos=0 ; set_nr < sets.count ; set_nr++)
{
set=sets.set+set_nr;
default_state= 0; /* Start from beginning */
/* If end of found-string not found or start-set with current set */
for (i= (uint) ~0; (i=get_next_bit(set,i)) ;)
{ if (!follow[i].chr)
{ if (! default_state)
default_state= find_found(found_set,set->table_offset,
set->found_offset+1);
}
}
copy_bits(sets.set+used_sets,set); /* Save set for changes */ if (!default_state)
or_bits(sets.set+used_sets,sets.set); /* Can restart from start */
/* Find all chars that follows current sets */
bzero((char*) used_chars,sizeof(used_chars)); for (i= (uint) ~0; (i=get_next_bit(sets.set+used_sets,i)) ;)
{
used_chars[follow[i].chr]=1; if ((follow[i].chr == SPACE_CHAR && !follow[i+1].chr &&
follow[i].len > 1) || follow[i].chr == END_OF_LINE)
used_chars[0]=1;
}
/* Mark word_chars used if \b is in state */ if (used_chars[SPACE_CHAR]) for (pos= word_end_chars ; *pos ; pos++)
used_chars[(int) (uchar) *pos] = 1;
/* Handle other used characters */ for (chr= 0 ; chr < 256 ; chr++)
{ if (! used_chars[chr])
set->next[chr]= (short) (chr ? default_state : -1); else
{
new_set=make_new_set(&sets);
set=sets.set+set_nr; /* if realloc */
new_set->table_offset=set->table_offset;
new_set->found_len=set->found_len;
new_set->found_offset=set->found_offset+1;
found_end=0;
for (i= (uint) ~0 ; (i=get_next_bit(sets.set+used_sets,i)) ; )
{ if (!follow[i].chr || follow[i].chr == chr ||
(follow[i].chr == SPACE_CHAR &&
(is_word_end[chr] ||
(!chr && follow[i].len > 1 && ! follow[i+1].chr))) ||
(follow[i].chr == END_OF_LINE && ! chr))
{ if ((! chr || (follow[i].chr && !follow[i+1].chr)) &&
follow[i].len > found_end)
found_end=follow[i].len; if (chr && follow[i].chr)
internal_set_bit(new_set,i+1); /* To next set */ else
internal_set_bit(new_set,i);
}
} if (found_end)
{
new_set->found_len=0; /* Set for testing if first */
bits_set=0; for (i= (uint) ~0; (i=get_next_bit(new_set,i)) ;)
{ if ((follow[i].chr == SPACE_CHAR ||
follow[i].chr == END_OF_LINE) && ! chr)
bit_nr=i+1; else
bit_nr=i; if (follow[bit_nr-1].len < found_end ||
(new_set->found_len &&
(chr == 0 || !follow[bit_nr].chr)))
internal_clear_bit(new_set,i); else
{ if (chr == 0 || !follow[bit_nr].chr)
{ /* best match */
new_set->table_offset=follow[bit_nr].table_offset; if (chr || (follow[i].chr == SPACE_CHAR ||
follow[i].chr == END_OF_LINE))
new_set->found_offset=found_end; /* New match */
new_set->found_len=found_end;
}
bits_set++;
}
} if (bits_set == 1)
{
set->next[chr] = find_found(found_set,
new_set->table_offset,
new_set->found_offset);
free_last_set(&sets);
} else
set->next[chr] = find_set(&sets,new_set);
} else
set->next[chr] = find_set(&sets,new_set);
}
}
}
/* Alloc replace structure for the replace-state-machine */
end=(to= *start) + *max_length-1;
rep_pos=rep+1; for(;;)
{ while (!rep_pos->found)
{
rep_pos= rep_pos->next[(uchar) *from]; if (to == end)
{
(*max_length)+=8192; if (!(new=my_realloc(PSI_NOT_INSTRUMENTED, *start,*max_length,MYF(MY_WME)))) return (uint) -1;
to=new+(to - *start);
end=(*start=new)+ *max_length-1;
}
*to++= *from++;
} if (!(rep_str = ((REPLACE_STRING*) rep_pos))->replace_string) return (uint) (to - *start)-1;
updated=1; /* Some char * is replaced */
to-=rep_str->to_offset; for (pos=rep_str->replace_string; *pos ; pos++)
{ if (to == end)
{
(*max_length)*=2; if (!(new=my_realloc(PSI_NOT_INSTRUMENTED, *start,*max_length,MYF(MY_WME)))) return (uint) -1;
to=new+(to - *start);
end=(*start=new)+ *max_length-1;
}
*to++= *pos;
} if (!*(from-=rep_str->from_offset) && rep_pos->found != 2) return (uint) (to - *start);
rep_pos=rep;
}
}
staticchar *buffer; /* The buffer itself, grown as needed. */ staticint bufbytes; /* Number of bytes in the buffer. */ staticint bufread,my_eof; /* Number of bytes to get with each read(). */ static uint bufalloc; staticchar *out_buff; static uint out_length;
staticint fill_buffer_retaining(File fd, int n)
{ int i;
/* See if we need to grow the buffer. */ if ((int) bufalloc - n <= bufread)
{ while ((int) bufalloc - n <= bufread)
{
bufalloc *= 2;
bufread *= 2;
}
buffer = my_realloc(PSI_NOT_INSTRUMENTED, buffer, bufalloc+1, MYF(MY_WME)); if (! buffer) return(-1);
}
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.