/***********************************************************************
* *
* This software is part of the ast package *
* Copyright (c) 1985-2010 AT&T Intellectual Property *
* and is licensed under the *
* Common Public License, Version 1.0 *
* by AT&T Intellectual Property *
* *
* A copy of the License is available at *
* http://www.opensource.org/licenses/cpl1.0.txt *
* (with md5 checksum 059e8cd6165cb4c31e351f2b69388fd9) *
* *
* Information and Software Systems Research *
* AT&T Research *
* Florham Park NJ *
* *
* Glenn Fowler <gsf@research.att.com> *
* David Korn <dgk@research.att.com> *
* Phong Vo <kpv@research.att.com> *
* *
***********************************************************************/
#include "sfdchdr.h"
/*
* a discipline that prepends a prefix string to each output line
*
* Glenn Fowler
* AT&T Research
*
* @(#)$Id: sfdcprefix (AT&T Research) 1998-06-25 $
*/
typedef struct
{
Sfdisc_t disc; /* sfio discipline */
size_t length; /* prefix length */
size_t empty; /* empty line prefix length */
int skip; /* this line already prefixed */
char prefix[1]; /* prefix string */
} Prefix_t;
/*
* prefix write
*/
#if __STD_C
static ssize_t pfxwrite(Sfio_t* f, const Void_t* buf, register size_t n, Sfdisc_t* dp)
#else
static ssize_t pfxwrite(f, buf, n, dp)
Sfio_t* f;
Void_t* buf;
register size_t n;
Sfdisc_t* dp;
#endif
{
register Prefix_t* pfx = (Prefix_t*)dp;
register char* b;
register char* s;
register char* e;
register char* t;
register ssize_t w;
int skip;
skip = 0;
w = 0;
b = (char*)buf;
s = b;
e = s + n;
do
{
if (!(t = memchr(s, '\n', e - s)))
{
skip = 1;
t = e - 1;
}
n = t - s + 1;
if (pfx->skip)
pfx->skip = 0;
else
sfwr(f, pfx->prefix, n > 1 ? pfx->length : pfx->empty, dp);
w += sfwr(f, s, n, dp);
if ((s = t + 1) >= e)
return w;
} while ((s = t + 1) < e);
pfx->skip = skip;
return w;
}
/*
* remove the discipline on close
*/
#if __STD_C
static int pfxexcept(Sfio_t* f, int type, Void_t* data, Sfdisc_t* dp)
#else
static int pfxexcept(f, type, data, dp)
Sfio_t* f;
int type;
Void_t* data;
Sfdisc_t* dp;
#endif
{
if (type == SF_FINAL || type == SF_DPOP)
free(dp);
return 0;
}
/*
* push the prefix discipline on f
*/
#if __STD_C
int sfdcprefix(Sfio_t* f, const char* prefix)
#else
int sfdcprefix(f, prefix)
Sfio_t* f;
char* prefix;
#endif
{
register Prefix_t* pfx;
register char* s;
size_t n;
/*
* this is a writeonly discipline
*/
if (!prefix || !(n = strlen(prefix)) || !(sfset(f, 0, 0) & SF_WRITE))
return -1;
if (!(pfx = (Prefix_t*)malloc(sizeof(Prefix_t) + n)))
return -1;
memset(pfx, 0, sizeof(*pfx));
pfx->disc.writef = pfxwrite;
pfx->disc.exceptf = pfxexcept;
pfx->length = n;
memcpy(pfx->prefix, prefix, n);
s = (char*)prefix + n;
while (--s > (char*)prefix && (*s == ' ' || *s == '\t'));
n = s - (char*)prefix;
if (*s != ' ' || *s != '\t')
n++;
pfx->empty = n;
if (sfdisc(f, &pfx->disc) != &pfx->disc)
{
free(pfx);
return -1;
}
return 0;
}