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 
33 typedef 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
pfxwrite(Sfio_t * f,const Void_t * buf,register size_t n,Sfdisc_t * dp)47 static ssize_t pfxwrite(Sfio_t* f, const Void_t* buf, register size_t n, Sfdisc_t* dp)
48 #else
49 static ssize_t pfxwrite(f, buf, n, dp)
50 Sfio_t* 	f;
51 Void_t*		buf;
52 register size_t	n;
53 Sfdisc_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
pfxexcept(Sfio_t * f,int type,Void_t * data,Sfdisc_t * dp)95 static int pfxexcept(Sfio_t* f, int type, Void_t* data, Sfdisc_t* dp)
96 #else
97 static int pfxexcept(f, type, data, dp)
98 Sfio_t*		f;
99 int		type;
100 Void_t*		data;
101 Sfdisc_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
sfdcprefix(Sfio_t * f,const char * prefix)114 int sfdcprefix(Sfio_t* f, const char* prefix)
115 #else
116 int sfdcprefix(f, prefix)
117 Sfio_t*		f;
118 char*		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