source: rtems/cpukit/libmisc/shell/dd-conv.c @ c499856

4.115
Last change on this file since c499856 was 9a77af8, checked in by Ralf Corsepius <ralf.corsepius@…>, on 03/26/10 at 17:18:43

Add HAVE_CONFIG_H support to let files receive configure defines.

  • Property mode set to 100644
File size: 7.2 KB
Line 
1/*-
2 * Copyright (c) 1991, 1993, 1994
3 *      The Regents of the University of California.  All rights reserved.
4 *
5 * This code is derived from software contributed to Berkeley by
6 * Keith Muller of the University of California, San Diego and Lance
7 * Visser of Convex Computer Corporation.
8 *
9 * Redistribution and use in source and binary forms, with or without
10 * modification, are permitted provided that the following conditions
11 * are met:
12 * 1. Redistributions of source code must retain the above copyright
13 *    notice, this list of conditions and the following disclaimer.
14 * 2. Redistributions in binary form must reproduce the above copyright
15 *    notice, this list of conditions and the following disclaimer in the
16 *    documentation and/or other materials provided with the distribution.
17 * 4. Neither the name of the University nor the names of its contributors
18 *    may be used to endorse or promote products derived from this software
19 *    without specific prior written permission.
20 *
21 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24 * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
25 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31 * SUCH DAMAGE.
32 */
33
34#ifdef HAVE_CONFIG_H
35#include "config.h"
36#endif
37
38#ifndef lint
39#if 0
40static char sccsid[] = "@(#)conv.c      8.3 (Berkeley) 4/2/94";
41#endif
42#endif /* not lint */
43#include <sys/cdefs.h>
44__FBSDID("$FreeBSD: src/bin/dd/conv.c,v 1.19 2004/04/06 20:06:45 markm Exp $");
45
46#include <sys/param.h>
47
48#include <err.h>
49#include <inttypes.h>
50#include <string.h>
51
52#include "dd.h"
53#include "extern-dd.h"
54
55/*
56 * def --
57 * Copy input to output.  Input is buffered until reaches obs, and then
58 * output until less than obs remains.  Only a single buffer is used.
59 * Worst case buffer calculation is (ibs + obs - 1).
60 */
61void
62def(rtems_shell_dd_globals* globals)
63{
64        u_char *inp;
65        const u_char *t;
66        size_t cnt;
67
68        if ((t = ctab) != NULL)
69                for (inp = in.dbp - (cnt = in.dbrcnt); cnt--; ++inp)
70                        *inp = t[*inp];
71
72        /* Make the output buffer look right. */
73        out.dbp = in.dbp;
74        out.dbcnt = in.dbcnt;
75
76        if (in.dbcnt >= out.dbsz) {
77                /* If the output buffer is full, write it. */
78                dd_out(globals, 0);
79
80                /*
81                 * Ddout copies the leftover output to the beginning of
82                 * the buffer and resets the output buffer.  Reset the
83                 * input buffer to match it.
84                 */
85                in.dbp = out.dbp;
86                in.dbcnt = out.dbcnt;
87        }
88}
89
90void
91def_close(rtems_shell_dd_globals* globals)
92{
93        /* Just update the count, everything is already in the buffer. */
94        if (in.dbcnt)
95                out.dbcnt = in.dbcnt;
96}
97
98/*
99 * Copy variable length newline terminated records with a max size cbsz
100 * bytes to output.  Records less than cbs are padded with spaces.
101 *
102 * max in buffer:  MAX(ibs, cbsz)
103 * max out buffer: obs + cbsz
104 */
105void
106block(rtems_shell_dd_globals* globals)
107{
108        u_char *inp, *outp;
109        const u_char *t;
110        size_t cnt, maxlen;
111        static int intrunc;
112        int ch;
113
114        /*
115         * Record truncation can cross block boundaries.  If currently in a
116         * truncation state, keep tossing characters until reach a newline.
117         * Start at the beginning of the buffer, as the input buffer is always
118         * left empty.
119         */
120        if (intrunc) {
121                for (inp = in.db, cnt = in.dbrcnt; cnt && *inp++ != '\n'; --cnt)
122                        ;
123                if (!cnt) {
124                        in.dbcnt = 0;
125                        in.dbp = in.db;
126                        return;
127                }
128                intrunc = 0;
129                /* Adjust the input buffer numbers. */
130                in.dbcnt = cnt - 1;
131                in.dbp = inp + cnt - 1;
132        }
133
134        /*
135         * Copy records (max cbsz size chunks) into the output buffer.  The
136         * translation is done as we copy into the output buffer.
137         */
138        ch = 0;
139        for (inp = in.dbp - in.dbcnt, outp = out.dbp; in.dbcnt;) {
140                maxlen = MIN(cbsz, in.dbcnt);
141                if ((t = ctab) != NULL)
142                        for (cnt = 0; cnt < maxlen && (ch = *inp++) != '\n';
143                            ++cnt)
144                                *outp++ = t[ch];
145                else
146                        for (cnt = 0; cnt < maxlen && (ch = *inp++) != '\n';
147                            ++cnt)
148                                *outp++ = ch;
149                /*
150                 * Check for short record without a newline.  Reassemble the
151                 * input block.
152                 */
153                if (ch != '\n' && in.dbcnt < cbsz) {
154                        (void)memmove(in.db, in.dbp - in.dbcnt, in.dbcnt);
155                        break;
156                }
157
158                /* Adjust the input buffer numbers. */
159                in.dbcnt -= cnt;
160                if (ch == '\n')
161                        --in.dbcnt;
162
163                /* Pad short records with spaces. */
164                if (cnt < cbsz)
165                        (void)memset(outp, ctab ? ctab[' '] : ' ', cbsz - cnt);
166                else {
167                        /*
168                         * If the next character wouldn't have ended the
169                         * block, it's a truncation.
170                         */
171                        if (!in.dbcnt || *inp != '\n')
172                                ++st.trunc;
173
174                        /* Toss characters to a newline. */
175                        for (; in.dbcnt && *inp++ != '\n'; --in.dbcnt)
176                                ;
177                        if (!in.dbcnt)
178                                intrunc = 1;
179                        else
180                                --in.dbcnt;
181                }
182
183                /* Adjust output buffer numbers. */
184                out.dbp += cbsz;
185                if ((out.dbcnt += cbsz) >= out.dbsz)
186                        dd_out(globals, 0);
187                outp = out.dbp;
188        }
189        in.dbp = in.db + in.dbcnt;
190}
191
192void
193block_close(rtems_shell_dd_globals* globals)
194{
195        /*
196         * Copy any remaining data into the output buffer and pad to a record.
197         * Don't worry about truncation or translation, the input buffer is
198         * always empty when truncating, and no characters have been added for
199         * translation.  The bottom line is that anything left in the input
200         * buffer is a truncated record.  Anything left in the output buffer
201         * just wasn't big enough.
202         */
203        if (in.dbcnt) {
204                ++st.trunc;
205                (void)memmove(out.dbp, in.dbp - in.dbcnt, in.dbcnt);
206                (void)memset(out.dbp + in.dbcnt, ctab ? ctab[' '] : ' ',
207                    cbsz - in.dbcnt);
208                out.dbcnt += cbsz;
209        }
210}
211
212/*
213 * Convert fixed length (cbsz) records to variable length.  Deletes any
214 * trailing blanks and appends a newline.
215 *
216 * max in buffer:  MAX(ibs, cbsz) + cbsz
217 * max out buffer: obs + cbsz
218 */
219void
220unblock(rtems_shell_dd_globals* globals)
221{
222        u_char *inp;
223        const u_char *t;
224        size_t cnt;
225
226        /* Translation and case conversion. */
227        if ((t = ctab) != NULL)
228                for (inp = in.dbp - (cnt = in.dbrcnt); cnt--; ++inp)
229                        *inp = t[*inp];
230        /*
231         * Copy records (max cbsz size chunks) into the output buffer.  The
232         * translation has to already be done or we might not recognize the
233         * spaces.
234         */
235        for (inp = in.db; in.dbcnt >= cbsz; inp += cbsz, in.dbcnt -= cbsz) {
236                for (t = inp + cbsz - 1; t >= inp && *t == ' '; --t)
237                        ;
238                if (t >= inp) {
239                        cnt = t - inp + 1;
240                        (void)memmove(out.dbp, inp, cnt);
241                        out.dbp += cnt;
242                        out.dbcnt += cnt;
243                }
244                *out.dbp++ = '\n';
245                if (++out.dbcnt >= out.dbsz)
246                        dd_out(globals, 0);
247        }
248        if (in.dbcnt)
249                (void)memmove(in.db, in.dbp - in.dbcnt, in.dbcnt);
250        in.dbp = in.db + in.dbcnt;
251}
252
253void
254unblock_close(rtems_shell_dd_globals* globals)
255{
256        u_char *t;
257        size_t cnt;
258
259        if (in.dbcnt) {
260                warnx("%s: short input record", in.name);
261                for (t = in.db + in.dbcnt - 1; t >= in.db && *t == ' '; --t)
262                        ;
263                if (t >= in.db) {
264                        cnt = t - in.db + 1;
265                        (void)memmove(out.dbp, in.db, cnt);
266                        out.dbp += cnt;
267                        out.dbcnt += cnt;
268                }
269                ++out.dbcnt;
270                *out.dbp++ = '\n';
271        }
272}
Note: See TracBrowser for help on using the repository browser.