1/***********************************************************************
2*                                                                      *
3*               This software is part of the ast package               *
4*          Copyright (c) 1985-2011 AT&T Intellectual Property          *
5*                      and is licensed under the                       *
6*                 Eclipse Public License, Version 1.0                  *
7*                    by AT&T Intellectual Property                     *
8*                                                                      *
9*                A copy of the License is available at                 *
10*          http://www.eclipse.org/org/documents/epl-v10.html           *
11*         (with md5 checksum b35adb5213ca9657e911e9befb180842)         *
12*                                                                      *
13*              Information and Software Systems Research               *
14*                            AT&T Research                             *
15*                           Florham Park NJ                            *
16*                                                                      *
17*                 Glenn Fowler <gsf@research.att.com>                  *
18*                  David Korn <dgk@research.att.com>                   *
19*                   Phong Vo <kpv@research.att.com>                    *
20*                                                                      *
21***********************************************************************/
22#include "sfdchdr.h"
23
24/*
25 * a discipline that prepends a prefix string to each output line
26 *
27 * Glenn Fowler
28 * AT&T Research
29 *
30 * @(#)$Id: sfdcprefix (AT&T Research) 1998-06-25 $
31 */
32
33typedef struct
34{
35	Sfdisc_t	disc;		/* sfio discipline		*/
36	size_t		length;		/* prefix length		*/
37	size_t		empty;		/* empty line prefix length	*/
38	int		skip;		/* this line already prefixed	*/
39	char		prefix[1];	/* prefix string		*/
40} Prefix_t;
41
42/*
43 * prefix write
44 */
45
46#if __STD_C
47static ssize_t pfxwrite(Sfio_t* f, const Void_t* buf, register size_t n, Sfdisc_t* dp)
48#else
49static ssize_t pfxwrite(f, buf, n, dp)
50Sfio_t* 	f;
51Void_t*		buf;
52register size_t	n;
53Sfdisc_t*	dp;
54#endif
55{
56	register Prefix_t*	pfx = (Prefix_t*)dp;
57	register char*		b;
58	register char*		s;
59	register char*		e;
60	register char*		t;
61	register ssize_t	w;
62	int			skip;
63
64	skip = 0;
65	w = 0;
66	b = (char*)buf;
67	s = b;
68	e = s + n;
69	do
70	{
71		if (!(t = memchr(s, '\n', e - s)))
72		{
73			skip = 1;
74			t = e - 1;
75		}
76		n = t - s + 1;
77		if (pfx->skip)
78			pfx->skip = 0;
79		else
80			sfwr(f, pfx->prefix, n > 1 ? pfx->length : pfx->empty, dp);
81		w += sfwr(f, s, n, dp);
82		if ((s = t + 1) >= e)
83			return w;
84	} while ((s = t + 1) < e);
85	pfx->skip = skip;
86	return w;
87
88}
89
90/*
91 * remove the discipline on close
92 */
93
94#if __STD_C
95static int pfxexcept(Sfio_t* f, int type, Void_t* data, Sfdisc_t* dp)
96#else
97static int pfxexcept(f, type, data, dp)
98Sfio_t*		f;
99int		type;
100Void_t*		data;
101Sfdisc_t*	dp;
102#endif
103{
104	if (type == SF_FINAL || type == SF_DPOP)
105		free(dp);
106	return 0;
107}
108
109/*
110 * push the prefix discipline on f
111 */
112
113#if __STD_C
114int sfdcprefix(Sfio_t* f, const char* prefix)
115#else
116int sfdcprefix(f, prefix)
117Sfio_t*		f;
118char*		prefix;
119#endif
120{
121	register Prefix_t*	pfx;
122	register char*		s;
123	size_t			n;
124
125	/*
126	 * this is a writeonly discipline
127	 */
128
129	if (!prefix || !(n = strlen(prefix)) || !(sfset(f, 0, 0) & SF_WRITE))
130		return -1;
131	if (!(pfx = (Prefix_t*)malloc(sizeof(Prefix_t) + n)))
132		return -1;
133	memset(pfx, 0, sizeof(*pfx));
134
135	pfx->disc.writef = pfxwrite;
136	pfx->disc.exceptf = pfxexcept;
137	pfx->length = n;
138	memcpy(pfx->prefix, prefix, n);
139	s = (char*)prefix + n;
140	while (--s > (char*)prefix && (*s == ' ' || *s == '\t'));
141	n = s - (char*)prefix;
142	if (*s != ' ' || *s != '\t')
143		n++;
144	pfx->empty = n;
145
146	if (sfdisc(f, &pfx->disc) != &pfx->disc)
147	{
148		free(pfx);
149		return -1;
150	}
151
152	return 0;
153}
154