/*
*
* parsefile.c
*
* (C) 2002 by Folke Ashberg <folke@ashberg.de>
*
* $Id: parsefile.c,v 1.8 2002/06/11 23:09:16 folke Exp $
*
* parsefile.c provides functions for parsing text with replacing keywords.
* it uses my getline.c for string handling
*
* This stuff provides functions for linehandlin on file descriptors,
* especially using netork sockets, because the getline function is
* non blocking (the write stuff not!)
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
*/
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <stdlib.h>
#include <string.h>
#include <sys/stat.h>
#include "parsefile.h"
#include "getline.h"
#define NONULL(x) ( x==NULL ? "" : x) /* this is nice, found in the mutt code */
struct paramlist * paramlist_init(void){
struct paramlist *pl;
pl=malloc(sizeof(struct paramlist));
pl->name=NULL;
pl->value=NULL;
pl->next=NULL;
return pl;
}
void paramlist_uninit(struct paramlist ** p){
struct paramlist * next;
while (*p){
next=(*p)->next;
if ((*p)->name) free((*p)->name);
if ((*p)->value) free((*p)->value);
free(*p);
*p=next;
}
}
int paramlist_set(struct paramlist * p, char * name, char * value){
/* TODO: deleteting (value==NULL) makes at the moment nothing */
struct paramlist *last=NULL;
if (!name) return 1;
while (p && (p->name) && (strcasecmp(p->name, name))){
last=p;
p=p->next;
}
if (!p){
if (!value) return 0;
p=paramlist_init();
if (last) last->next=p;
}
if (p->name) free(p->name);
if (p->value) free(p->value);
p->name=strdup(name);
p->value= value ? strdup(value) : NULL;
return 0;
};
char * paramlist_get(struct paramlist * params, char * name){
if (!name) return NULL;
while (params){
if (params->name && !strcasecmp(params->name, name)) return params->value;
params=params->next;
}
return NULL;
}
int paramlist_strreplace(char ** dst, char * in, struct paramlist * params){
typedef struct replacelist {
int pos; /* position in in where to replace */
int newlen; /* length of new text (params->value) */
int oldlen; /* length of old text (params->name) */
char * new; /* char to replace with */
struct replacelist * next;
} replacelist;
int len, pos, l;
int replacecount=0;
char * occ;
char * in_inc;
int lastreplacepos;
int incremented;
struct replacelist * rl_first = NULL, * rl = NULL, * rl_last, *rl_next;
struct paramlist * p;
if (!in) return -1;
if (!params){ /* nothing to replace */
*dst=in;
return 0;
}
*dst=NULL;
len=strlen(in);
p=params;
/* look for replacements and save them, count size of new string */
while (p){
if (p->name){
in_inc=in;
incremented=0;
while ((occ=strstr(in_inc, p->name))!=NULL){
pos=occ - in;
/* add entry to replacelist, which has to be sorted by pos,
* we have to look up our entry point */
rl=rl_first;
rl_last=NULL;
while (rl){
if (rl->pos > pos) break;
rl_last=rl;
rl=rl->next;
}
rl_next=rl;
rl=malloc(sizeof(struct replacelist));
if (rl_last) rl_last->next=rl;
else rl_first=rl;
rl->next=rl_next;
rl->pos=pos;
rl->newlen=strlen(NONULL(p->value));
rl->new=p->value;
rl->oldlen=strlen(p->name);
len+=rl->newlen - rl->oldlen;
replacecount++;
/* override old string to ensure no further shorter
* string will match */
memset(occ, 1, strlen(p->name));
/* we loop strstr until we cannot find this p->name */
in_inc+=rl->oldlen;
incremented+=pos;
}
}
p=p->next;
}
if (replacecount>0){
*dst=malloc(len+1);
(*dst)[len]='\0';
rl=rl_first;
pos=0;
lastreplacepos=0;
while (rl){
/* copy unreplaced text into buf */
l=rl->pos - lastreplacepos;
memcpy(&(*dst)[pos], &in[lastreplacepos], l);
lastreplacepos=rl->pos + rl->oldlen;
pos+=l;
if (rl->newlen > 0){
/* copy replaced text */
memcpy(&(*dst)[pos], rl->new, rl->newlen);
pos+=rl->newlen;
}
rl=rl->next;
}
/* copy the rest of the line */
if ((l=len-pos)>0)
memcpy(&(*dst)[pos], &in[lastreplacepos], len-pos);
} else *dst=in;
rl=rl_first;
while (rl){
rl_last=rl;
rl=rl->next;
free(rl_last);
}
return replacecount;
}
int parsefile(char * infile, char * outfile , struct paramlist * params, int leading){
int in, out, ret;
if ( (in=open(infile, O_RDONLY))<0)
return 1;
if ( (out=open(outfile, O_WRONLY | O_CREAT | O_TRUNC, S_IRUSR | S_IWUSR ))<0)
return 1;
ret=parsefds(in, out, params, leading);
close(in);
close(out);
return ret;
}
int parsefds(int in, int out , struct paramlist * params, int leading){
int res, replacements;
char * replaced;
struct linebuf *l;
if ((l=linebuf_init(4096))==NULL)
return 1;
while ( (res=getline(in, l))>=0){
if (l->linelen >=0 ){
replacements=paramlist_strreplace(&replaced, l->line, params);
if (writeline(out, leading, replaced)){
//error
}
if (replacements>0) free(replaced);
}
}
linebuf_uninit(l);
if (res!=GETLINE_EOF) return 1;
return 0;
}
#if 0
int main (int argc, char **argv)
{
struct paramlist *p;
p=paramlist_init();
paramlist_set(p, "test1" , "|1111111111111111111|");
paramlist_set(p, "test2" , "|2222222222222|");
parsefile("/tmp/parse_in", "/tmp/parse_out", p, WRITELINE_LEADING_N);
paramlist_uninit(&p);
return 0;
}
#endif
syntax highlighted by Code2HTML, v. 0.9.1