No empty .Rs/.Re
[netbsd-mini2440.git] / external / bsd / atf / dist / atf-c / ui.c
blobe00ca737e607147ca8599c54b47fa5f764e22c1e
1 /*
2 * Automated Testing Framework (atf)
4 * Copyright (c) 2008 The NetBSD Foundation, Inc.
5 * All rights reserved.
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
16 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND
17 * CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
18 * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
19 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20 * IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS BE LIABLE FOR ANY
21 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
23 * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
24 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
25 * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
26 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
27 * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30 #include <sys/ioctl.h>
32 #include <stdarg.h>
33 #include <stdio.h>
34 #include <stdlib.h>
35 #include <string.h>
36 #include <termios.h>
37 #include <unistd.h>
39 #include "atf-c/dynstr.h"
40 #include "atf-c/env.h"
41 #include "atf-c/error.h"
42 #include "atf-c/sanity.h"
43 #include "atf-c/text.h"
44 #include "atf-c/ui.h"
46 /* ---------------------------------------------------------------------
47 * Auxiliary functions.
48 * --------------------------------------------------------------------- */
50 static
51 size_t
52 terminal_width(void)
54 static bool done = false;
55 static size_t width = 0;
57 if (!done) {
58 if (atf_env_has("COLUMNS")) {
59 const char *cols = atf_env_get("COLUMNS");
60 if (strlen(cols) > 0) {
61 width = atoi(cols); /* XXX No error checking */
63 } else {
64 struct winsize ws;
65 if (ioctl(STDOUT_FILENO, TIOCGWINSZ, &ws) != -1)
66 width = ws.ws_col;
69 if (width >= 80)
70 width -= 5;
72 done = true;
75 return width;
78 static
79 atf_error_t
80 format_paragraph(atf_dynstr_t *dest,
81 const char *tag, bool repeat, size_t col, bool firstp,
82 char *str)
84 const size_t maxcol = terminal_width();
85 size_t curcol;
86 char *last, *str2;
87 atf_dynstr_t pad, fullpad;
88 atf_error_t err;
90 err = atf_dynstr_init_rep(&pad, col - strlen(tag), ' ');
91 if (atf_is_error(err))
92 goto out;
94 err = atf_dynstr_init_rep(&fullpad, col, ' ');
95 if (atf_is_error(err))
96 goto out_pad;
98 if (firstp || repeat)
99 err = atf_dynstr_append_fmt(dest, "%s%s", tag,
100 atf_dynstr_cstring(&pad));
101 else
102 err = atf_dynstr_append_fmt(dest, atf_dynstr_cstring(&fullpad));
103 if (atf_is_error(err))
104 goto out_pads;
106 last = NULL; /* Silence GCC warning. */
107 str2 = strtok_r(str, " ", &last);
108 curcol = col;
109 do {
110 const bool firstw = (str == str2);
112 if (!firstw) {
113 if (maxcol > 0 && curcol + strlen(str2) + 1 > maxcol) {
114 if (repeat)
115 err = atf_dynstr_append_fmt
116 (dest, "\n%s%s", tag, atf_dynstr_cstring(&pad));
117 else
118 err = atf_dynstr_append_fmt
119 (dest, "\n%s", atf_dynstr_cstring(&fullpad));
120 curcol = col;
121 } else {
122 err = atf_dynstr_append_fmt(dest, " ");
123 curcol++;
127 if (!atf_is_error(err)) {
128 err = atf_dynstr_append_fmt(dest, str2);
129 curcol += strlen(str2);
131 str2 = strtok_r(NULL, " ", &last);
133 } while (!atf_is_error(err) && str2 != NULL);
135 out_pads:
136 atf_dynstr_fini(&fullpad);
137 out_pad:
138 atf_dynstr_fini(&pad);
139 out:
140 return err;
143 static
144 atf_error_t
145 format_aux(atf_dynstr_t *dest,
146 const char *tag, bool repeat, size_t col, char *str)
148 char *last, *str2;
149 atf_error_t err;
151 PRE(col == 0 || col >= strlen(tag));
152 if (col == 0)
153 col = strlen(tag);
155 str2 = str + strlen(str);
156 while (str2 != str && *--str2 == '\n')
157 *str2 = '\0';
159 last = NULL; /* Silence GCC warning. */
160 str2 = strtok_r(str, "\n", &last);
161 do {
162 const bool first = (str2 == str);
163 err = format_paragraph(dest, tag, repeat, col, first, str2);
164 str2 = strtok_r(NULL, "\n", &last);
165 if (!atf_is_error(err) && str2 != NULL) {
166 if (repeat)
167 err = atf_dynstr_append_fmt(dest, "\n%s\n", tag);
168 else
169 err = atf_dynstr_append_fmt(dest, "\n\n");
171 } while (str2 != NULL && !atf_is_error(err));
173 return 0;
176 /* ---------------------------------------------------------------------
177 * Free functions.
178 * --------------------------------------------------------------------- */
180 atf_error_t
181 atf_ui_format_ap(atf_dynstr_t *dest,
182 const char *tag, bool repeat, size_t col,
183 const char *fmt, va_list ap)
185 char *src;
186 atf_error_t err;
187 va_list ap2;
189 va_copy(ap2, ap);
190 err = atf_text_format_ap(&src, fmt, ap2);
191 va_end(ap2);
192 if (!atf_is_error(err)) {
193 err = format_aux(dest, tag, repeat, col, src);
194 free(src);
197 return err;
200 atf_error_t
201 atf_ui_format_fmt(atf_dynstr_t *dest,
202 const char *tag, bool repeat, size_t col,
203 const char *fmt, ...)
205 va_list ap;
206 atf_error_t err;
208 va_start(ap, fmt);
209 err = atf_ui_format_ap(dest, tag, repeat, col, fmt, ap);
210 va_end(ap);
212 return err;