1/*
2Copyright (C) 1993 Free Software Foundation
3
4This file is part of the GNU IO Library.  This library is free
5software; you can redistribute it and/or modify it under the
6terms of the GNU General Public License as published by the
7Free Software Foundation; either version 2, or (at your option)
8any later version.
9
10This library is distributed in the hope that it will be useful,
11but WITHOUT ANY WARRANTY; without even the implied warranty of
12MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13GNU General Public License for more details.
14
15You should have received a copy of the GNU General Public License
16along with this library; see the file COPYING.  If not, write to the Free
17Software Foundation, 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
18
19As a special exception, if you link this library with files
20compiled with a GNU compiler to produce an executable, this does not cause
21the resulting executable to be covered by the GNU General Public License.
22This exception does not however invalidate any other reasons why
23the executable file might be covered by the GNU General Public License. */
24
25#include <stdarg.h>
26#include <string.h>
27#include "libioP.h"
28#include "stream.h"
29#include "strstream.h"
30
31static char Buffer[_IO_BUFSIZ];
32#define EndBuffer (Buffer+_IO_BUFSIZ)
33static char* next_chunk = Buffer; // Start of available part of Buffer.
34
35char* form(const char* format, ...)
36{
37    int space_left = EndBuffer - next_chunk;
38    // If less that 25% of the space is available start over.
39    if (space_left < (_IO_BUFSIZ>>2))
40	next_chunk = Buffer;
41    char* buf = next_chunk;
42
43    strstreambuf stream(buf, EndBuffer-buf-1, buf);
44    va_list ap;
45    va_start(ap, format);
46    stream.vform(format, ap);
47    va_end(ap);
48    stream.sputc(0);
49    next_chunk = buf + stream.pcount();
50    return buf;
51}
52
53#define u_long unsigned long
54
55static char* itoa(unsigned long i, int size, int neg, int base)
56{
57    // Conservative estimate: If base==2, might need 8 characters
58    // for each input byte, but normally 3 is plenty.
59    int needed = size ? size
60	: (base >= 8 ? 3 : 8) * sizeof(unsigned long) + 2;
61    int space_left = EndBuffer - next_chunk;
62    if (space_left <= needed)
63	next_chunk = Buffer; // start over.
64
65    char* buf = next_chunk;
66
67    register char* ptr = buf+needed+1;
68    next_chunk = ptr;
69
70    if (needed < (2+neg) || ptr > EndBuffer)
71	return NULL;
72    *--ptr = 0;
73
74    if (i == 0)
75	*--ptr = '0';
76    while (i != 0 && ptr > buf) {
77	int ch = i % base;
78	i = i / base;
79	if (ch >= 10)
80	    ch += 'a' - 10;
81	else
82	    ch += '0';
83	*--ptr = ch;
84    }
85    if (neg)
86	*--ptr = '-';
87    if (size == 0)
88	return ptr;
89    while (ptr > buf)
90	*--ptr = ' ';
91    return buf;
92}
93
94char* dec(long i, int len /* = 0 */)
95{
96    if (i >= 0) return itoa((unsigned long)i, len, 0, 10);
97    else return itoa((unsigned long)(-i), len, 1, 10);
98}
99char* dec(int i, int len /* = 0 */)
100{
101    if (i >= 0) return itoa((unsigned long)i, len, 0, 10);
102    else return itoa((unsigned long)(-i), len, 1, 10);
103}
104char* dec(unsigned long i, int len /* = 0 */)
105{
106    return itoa(i, len, 0, 10);
107}
108char* dec(unsigned int i, int len /* = 0 */)
109{
110    return itoa(i, len, 0, 10);
111}
112
113char* hex(long i, int len /* = 0 */)
114{
115    return itoa((unsigned long)i, len, 0, 16);
116}
117char* hex(int i, int len /* = 0 */)
118{
119    return itoa((unsigned long)i, len, 0, 16);
120}
121char* hex(unsigned long i, int len /* = 0 */)
122{
123    return itoa(i, len, 0, 16);
124}
125char* hex(unsigned int i, int len /* = 0 */)
126{
127    return itoa(i, len, 0, 16);
128}
129
130char* oct(long i, int len /* = 0 */)
131{
132    return itoa((unsigned long)i, len, 0, 8);
133}
134char* oct(int i, int len /* = 0 */)
135{
136    return itoa((unsigned long)i, len, 0, 8);
137}
138char* oct(unsigned long i, int len /* = 0 */)
139{
140    return itoa(i, len, 0, 8);
141}
142char* oct(unsigned int i, int len /* = 0 */)
143{
144    return itoa(i, len, 0, 8);
145}
146
147static char *str(const char* s, int len, int width)
148{
149  if (width < len)
150    width = len;
151  int space_left = EndBuffer - next_chunk;
152  if (space_left <= width + 1)
153    next_chunk = Buffer; // start over.
154  char* buf = next_chunk;
155  memset (buf, ' ', width - len);
156  memcpy (buf + width - len, s, len);
157  buf[width] = 0;
158  return buf;
159}
160
161char* str(const char* s, int width)
162{
163  return str (s, strlen (s), width);
164}
165
166char* chr(char ch, int width)
167{
168  char c = ch;
169  return str (&c, 1, width);
170}
171