1161200Ssam/*-
2174245Ssam * Copyright (c) 2002-2007 Sam Leffler, Errno Consulting
3161200Ssam * All rights reserved.
4161200Ssam *
5161200Ssam * Redistribution and use in source and binary forms, with or without
6161200Ssam * modification, are permitted provided that the following conditions
7161200Ssam * are met:
8161200Ssam * 1. Redistributions of source code must retain the above copyright
9161200Ssam *    notice, this list of conditions and the following disclaimer,
10161200Ssam *    without modification.
11161200Ssam * 2. Redistributions in binary form must reproduce at minimum a disclaimer
12161200Ssam *    similar to the "NO WARRANTY" disclaimer below ("Disclaimer") and any
13161200Ssam *    redistribution must be conditioned upon including a substantially
14161200Ssam *    similar Disclaimer requirement for further binary redistribution.
15161200Ssam *
16161200Ssam * NO WARRANTY
17161200Ssam * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
18161200Ssam * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
19161200Ssam * LIMITED TO, THE IMPLIED WARRANTIES OF NONINFRINGEMENT, MERCHANTIBILITY
20161200Ssam * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
21161200Ssam * THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY,
22161200Ssam * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
23161200Ssam * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
24161200Ssam * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
25161200Ssam * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
26161200Ssam * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
27161200Ssam * THE POSSIBILITY OF SUCH DAMAGES.
28161200Ssam *
29161200Ssam * $FreeBSD$
30161200Ssam */
31161200Ssam
32161200Ssam#include <stdio.h>
33161200Ssam#include <string.h>
34161200Ssam
35161200Ssam#include "statfoo.h"
36161200Ssam
37161200Ssamstatic void
38161200Ssamstatfoo_setfmt(struct statfoo *sf, const char *fmt0)
39161200Ssam{
40161200Ssam#define	N(a)	(sizeof(a)/sizeof(a[0]))
41161200Ssam	char fmt[4096];
42161200Ssam	char *fp, *tok;
43161200Ssam	int i, j;
44161200Ssam
45161200Ssam	j = 0;
46161200Ssam	strlcpy(fmt, fmt0, sizeof(fmt));
47161200Ssam	for (fp = fmt; (tok = strsep(&fp, ", ")) != NULL;) {
48161200Ssam		for (i = 0; i < sf->nstats; i++)
49161200Ssam			if (strcasecmp(tok, sf->stats[i].name) == 0)
50161200Ssam				break;
51161200Ssam		if (i >= sf->nstats) {
52161200Ssam			fprintf(stderr, "%s: unknown statistic name \"%s\" "
53161200Ssam				"skipped\n", sf->name, tok);
54161200Ssam			continue;
55161200Ssam		}
56161200Ssam		if (j+3 > sizeof(sf->fmts)) {
57161200Ssam			fprintf(stderr, "%s: not enough room for all stats; "
58161200Ssam				"stopped at %s\n", sf->name, tok);
59161200Ssam			break;
60161200Ssam		}
61161200Ssam		if (j != 0)
62161200Ssam			sf->fmts[j++] = ' ';
63231863Sadrian		sf->fmts[j++] = FMTS_IS_STAT;
64231863Sadrian		sf->fmts[j++] = i & 0xff;
65231863Sadrian		sf->fmts[j++] = (i >> 8) & 0xff;
66161200Ssam	}
67161200Ssam	sf->fmts[j] = '\0';
68161200Ssam#undef N
69161200Ssam}
70161200Ssam
71161200Ssamstatic void
72161200Ssamstatfoo_collect(struct statfoo *sf)
73161200Ssam{
74161200Ssam	fprintf(stderr, "%s: don't know how to collect data\n", sf->name);
75161200Ssam}
76161200Ssam
77161200Ssamstatic void
78161200Ssamstatfoo_update_tot(struct statfoo *sf)
79161200Ssam{
80161200Ssam	fprintf(stderr, "%s: don't know how to update total data\n", sf->name);
81161200Ssam}
82161200Ssam
83161200Ssamstatic int
84161200Ssamstatfoo_get(struct statfoo *sf, int s, char b[], size_t bs)
85161200Ssam{
86161200Ssam	fprintf(stderr, "%s: don't know how to get stat #%u\n", sf->name, s);
87161200Ssam	return 0;
88161200Ssam}
89161200Ssam
90161200Ssamstatic void
91161200Ssamstatfoo_print_header(struct statfoo *sf, FILE *fd)
92161200Ssam{
93161200Ssam	const unsigned char *cp;
94231863Sadrian	int i;
95231863Sadrian	const struct fmt *f;
96161200Ssam
97161200Ssam	for (cp = sf->fmts; *cp != '\0'; cp++) {
98231863Sadrian		if (*cp == FMTS_IS_STAT) {
99231863Sadrian			i = *(++cp);
100231863Sadrian			i |= ((int) *(++cp)) << 8;
101231863Sadrian			f = &sf->stats[i];
102161200Ssam			fprintf(fd, "%*s", f->width, f->label);
103161200Ssam		} else
104161200Ssam			putc(*cp, fd);
105161200Ssam	}
106161200Ssam	putc('\n', fd);
107161200Ssam}
108161200Ssam
109161200Ssamstatic void
110161200Ssamstatfoo_print_current(struct statfoo *sf, FILE *fd)
111161200Ssam{
112161200Ssam	char buf[32];
113161200Ssam	const unsigned char *cp;
114231863Sadrian	int i;
115231863Sadrian	const struct fmt *f;
116161200Ssam
117161200Ssam	for (cp = sf->fmts; *cp != '\0'; cp++) {
118231863Sadrian		if (*cp == FMTS_IS_STAT) {
119231863Sadrian			i = *(++cp);
120231863Sadrian			i |= ((int) *(++cp)) << 8;
121231863Sadrian			f = &sf->stats[i];
122231863Sadrian			if (sf->get_curstat(sf, i, buf, sizeof(buf)))
123161200Ssam				fprintf(fd, "%*s", f->width, buf);
124161200Ssam		} else
125161200Ssam			putc(*cp, fd);
126161200Ssam	}
127161200Ssam	putc('\n', fd);
128161200Ssam}
129161200Ssam
130161200Ssamstatic void
131161200Ssamstatfoo_print_total(struct statfoo *sf, FILE *fd)
132161200Ssam{
133161200Ssam	char buf[32];
134161200Ssam	const unsigned char *cp;
135231863Sadrian	const struct fmt *f;
136231863Sadrian	int i;
137161200Ssam
138161200Ssam	for (cp = sf->fmts; *cp != '\0'; cp++) {
139231863Sadrian		if (*cp == FMTS_IS_STAT) {
140231863Sadrian			i = *(++cp);
141231863Sadrian			i |= ((int) *(++cp)) << 8;
142231863Sadrian			f = &sf->stats[i];
143231863Sadrian			if (sf->get_totstat(sf, i, buf, sizeof(buf)))
144161200Ssam				fprintf(fd, "%*s", f->width, buf);
145161200Ssam		} else
146161200Ssam			putc(*cp, fd);
147161200Ssam	}
148161200Ssam	putc('\n', fd);
149161200Ssam}
150161200Ssam
151161200Ssamstatic void
152161200Ssamstatfoo_print_verbose(struct statfoo *sf, FILE *fd)
153161200Ssam{
154174570Ssam	const struct fmt *f;
155161200Ssam	char s[32];
156174570Ssam	int i, width;
157161200Ssam
158174570Ssam	width = 0;
159161200Ssam	for (i = 0; i < sf->nstats; i++) {
160174570Ssam		f = &sf->stats[i];
161174570Ssam		if (f->width > width)
162174570Ssam			width = f->width;
163174570Ssam	}
164174570Ssam	for (i = 0; i < sf->nstats; i++) {
165174570Ssam		f = &sf->stats[i];
166161200Ssam		if (sf->get_totstat(sf, i, s, sizeof(s)) && strcmp(s, "0"))
167174570Ssam			fprintf(fd, "%-*s %s\n", width, s, f->desc);
168161200Ssam	}
169161200Ssam}
170161200Ssam
171161200Ssamstatic void
172161200Ssamstatfoo_print_fields(struct statfoo *sf, FILE *fd)
173161200Ssam{
174161200Ssam	int i, w, width;
175161200Ssam
176161200Ssam	width = 0;
177161200Ssam	for (i = 0; i < sf->nstats; i++) {
178161200Ssam		w = strlen(sf->stats[i].name);
179161200Ssam		if (w > width)
180161200Ssam			width = w;
181161200Ssam	}
182161200Ssam	for (i = 0; i < sf->nstats; i++) {
183161200Ssam		const struct fmt *f = &sf->stats[i];
184161200Ssam		if (f->width != 0)
185161200Ssam			fprintf(fd, "%-*s %s\n", width, f->name, f->desc);
186161200Ssam	}
187161200Ssam}
188161200Ssam
189161200Ssamvoid
190161200Ssamstatfoo_init(struct statfoo *sf, const char *name, const struct fmt *stats, int nstats)
191161200Ssam{
192161200Ssam	sf->name = name;
193161200Ssam	sf->stats = stats;
194161200Ssam	sf->nstats = nstats;
195161200Ssam	sf->setfmt = statfoo_setfmt;
196161200Ssam	sf->collect_cur = statfoo_collect;
197161200Ssam	sf->collect_tot = statfoo_collect;
198161200Ssam	sf->update_tot = statfoo_update_tot;
199161200Ssam	sf->get_curstat = statfoo_get;
200161200Ssam	sf->get_totstat = statfoo_get;
201161200Ssam	sf->print_header = statfoo_print_header;
202161200Ssam	sf->print_current = statfoo_print_current;
203161200Ssam	sf->print_total = statfoo_print_total;
204161200Ssam	sf->print_verbose = statfoo_print_verbose;
205161200Ssam	sf->print_fields = statfoo_print_fields;
206161200Ssam}
207