...and the base gfx value *sigh*
[AROS.git] / compiler / alib / getdatastreamfromformat.c
blob4ca0dda7898b1abe856aa2a70d86ec0a559165d4
1 /*
2 Copyright © 1995-2013, The AROS Development Team. All rights reserved.
3 $Id$
5 Internal utility functions.
6 */
8 #include <aros/debug.h>
9 #include <aros/system.h>
10 #include "alib_intern.h"
12 /******************************************************************************
14 NAME */
15 VOID GetDataStreamFromFormat (
17 /* SYNOPSIS */
18 CONST_STRPTR format,
19 va_list args,
20 RAWARG dataStream, ULONG *dataSize,
21 ULONG *indexStream, ULONG *indexSize)
23 /* FUNCTION
24 Builds an array of parameters which are passed on the stack.
25 This function is used on machines which have compilers which
26 don't pass the arguments to a varargs function unlike the
27 Amiga ones.
29 INPUTS
30 format - Exec/RawDoFmt or Locale/FormatString format string
31 args - This has to be initialized by va_start()
32 (not used if dataStream is NULL)
33 dataStream - data buffer to write to
34 (can be NULL for sizing)
35 dataSize - size of the buffer
36 (can be NULL, or pointer to 0 for sizing)
37 updated to the actual size required at exit.
38 indexStream- array of offsets to the Nth element in the dataStream
39 (can be NULL for sizing)
40 indexSize - size of the index, in bytes
41 (can be NULL, or pointer to 0 for sizing)
42 updated to the actual size required at exit.
44 RESULT
45 An array which can be passed to any function which expects the
46 structure or NULL if something failed. This call may fail for
47 different reasons on different systems. On some systems, NULL
48 indicates that there was not enough memory.
50 NOTES
51 This structure converts from format types to the following
52 dataStream values in the returned structure. The dataStream
53 is suitable for use by Exec/RawDoFmt or Locale/FormatString,
54 and is packed on WORD alignment. The indexStream is used
55 internally by Locale/FormatString for format repositioning.
57 Format code GET_ARG() type Datastream type
58 ----------- ------------- ---------------
59 %c char (really int) WORD
60 %d/%D int WORD
61 %u/%U unsigned int UWORD
62 %x/%X unsigned int UWORD
63 %b BPTR IPTR
64 %s const char * IPTR
65 %p/%P void * IPTR
66 %l<cdDuUxX> LONG LONG
67 %ll<cdDuUxX> QUAD QUAD
68 %i<cdDuUxX> IPTR IPTR
69 %% - -
71 EXAMPLE
73 BUGS
75 SEE ALSO
76 exec.library/RawDoFmt(), locale.library/FormatString()
78 INTERNALS
80 ******************************************************************************/
82 size_t len = dataSize ? *dataSize : 0;
83 int ilen = (indexSize ? *indexSize : 0) / sizeof(indexStream[0]);
84 int imax = 0;
85 size_t size = 0;
86 size_t isize = 0;
87 size_t size_force = 0;
88 BOOL in_format = FALSE;
89 ULONG iflags = 0;
90 size_t vsize = 0, dsize = 0;
91 unsigned int argpos = 0;
93 #define IFLAG_SIGNED (1UL << 31)
94 #define IFLAG_VSIZE(x) ((x) << 16)
95 #define IFLAG_VSIZE_of(x) (((x) >> 16) & 0xf)
96 #define IFLAG_DSIZE(x) ((x) << 0)
97 #define IFLAG_DSIZE_of(x) (((x) >> 0) & 0xf)
98 #define GET_ARG(args, type) (dataStream ? va_arg(args, type) : 0)
100 for (size = 0; format && *format; format++) {
101 if (!in_format) {
102 if (*format == '%') {
103 in_format = TRUE;
104 vsize = dsize = 0;
105 size_force = 0;
106 argpos = 0;
107 iflags = 0;
109 } else {
110 /* Ignore '%%' */
111 if (*format == '%') {
112 in_format = FALSE;
113 continue;
116 /* Ignore non-argument characters */
117 if ((*format >= '0' && *format <= '9')) {
118 argpos = (argpos * 10) + (*format - '0');
119 continue;
122 switch (*format) {
123 case '.':
124 break;
125 case '-':
126 break;
127 case '$':
128 isize = argpos - 1;
129 argpos = 0;
130 break;
131 case 'i':
132 size_force = sizeof(IPTR);
133 break;
134 case 'l':
135 if (size_force >= sizeof(LONG))
136 size_force = sizeof(QUAD);
137 else
138 size_force = sizeof(LONG);
139 break;
140 case 'd':
141 case 'D':
142 vsize = sizeof(int);
143 dsize = sizeof(WORD);
144 iflags |= IFLAG_SIGNED;
145 in_format = FALSE;
146 break;
147 case 'c': /* char is promoted to int through (fmt, ...) */
148 case 'u':
149 case 'U':
150 case 'x':
151 case 'X':
152 vsize = sizeof(unsigned int);
153 dsize = sizeof(WORD);
154 in_format = FALSE;
155 break;
156 case 'p':
157 case 'P':
158 case 's':
159 vsize = sizeof(void *);
160 dsize = sizeof(IPTR);
161 in_format = FALSE;
162 break;
163 case 'b':
164 case 'B':
165 vsize = sizeof(BPTR);
166 dsize = sizeof(BPTR);
167 in_format = FALSE;
168 break;
169 default:
170 vsize = sizeof(int);
171 dsize = sizeof(WORD);
172 in_format = FALSE;
173 break;
176 if (in_format == FALSE) {
177 D(bug("%s: '%c' l=%d (v=%d, d=%d)\n", __func__, *format, size_force, vsize, dsize));
178 if (size_force) {
179 vsize = size_force;
180 dsize = size_force;
183 iflags |= IFLAG_VSIZE(vsize);
184 iflags |= IFLAG_DSIZE(dsize);
186 if (ilen > isize)
187 indexStream[isize] = iflags;
189 isize++;
190 if (isize > imax)
191 imax = isize;
196 /* Convert indexStream flags into offsets
197 * into the datastream. If the datastream
198 * is present, assume we have to pull its
199 * data from the va_list.
201 if (indexStream) {
202 int i;
204 for (i = 0; i < imax && i < ilen; i++) {
205 IPTR arg_val;
206 CONST_APTR buff = (CONST_APTR)((IPTR)dataStream + size);
207 ULONG iflags = indexStream[i];
209 D(bug("%s: indexStream[%d] = %d\n", __func__, i, (int)size));
210 indexStream[i] = size;
211 size += IFLAG_DSIZE_of(iflags);
213 if (!dataStream)
214 continue;
216 /* dataStream present - pull its data from the va_list.
218 switch (IFLAG_VSIZE_of(iflags)) {
219 case sizeof(LONG):
220 if (iflags & IFLAG_SIGNED)
221 arg_val = (SIPTR)va_arg(args, LONG);
222 else
223 arg_val = (IPTR)va_arg(args, ULONG);
224 break;
225 case sizeof(QUAD):
226 if (iflags & IFLAG_SIGNED)
227 arg_val = (SIPTR)va_arg(args, QUAD);
228 else
229 arg_val = (IPTR)va_arg(args, UQUAD);
230 break;
231 default:
232 if (iflags & IFLAG_SIGNED)
233 arg_val = (SIPTR)va_arg(args, int);
234 else
235 arg_val = (IPTR)va_arg(args, int);
236 break;
239 D(bug("%s: dataStream len = 0x%x (%d)\n", __func__, (unsigned int)len, dataSize ? (int)*dataSize : -1));
240 D(bug("%s: dataStream + 0x%x (%d) = 0x%p\n", __func__, (int)((IPTR)buff - (IPTR)dataStream), IFLAG_DSIZE_of(iflags), (void *)arg_val));
241 if (len >= size) {
242 switch (IFLAG_DSIZE_of(iflags)) {
243 case sizeof(UWORD):
244 *((UWORD *)buff) = (UWORD)arg_val;
245 break;
246 case sizeof(ULONG):
247 *((ULONG *)buff) = (ULONG)arg_val;
248 break;
249 case sizeof(UQUAD):
250 *((UQUAD *)buff) = (UQUAD)arg_val;
251 break;
257 if (dataSize)
258 *dataSize = size;
260 if (indexSize)
261 *indexSize = imax * sizeof(indexStream[0]);
262 } /* GetDataStreamFromFormat */