1 /* utility.c Utility functions for Wine
5 * This unit contains the implementations of
6 * various Windows API functions that perform
7 * utility tasks; i.e., that do not fit into
8 * any major category but perform useful tasks.
16 static char Copyright[] = "Copyright Andrew C. Bulhak, 1993";
18 /*#define debug_utility*/
20 /* MulDiv is a simple function that may as well have been
21 * implemented as a macro; however Microsoft, in their infinite
22 * wisdom, have implemented it as a DLL function and therefore
24 * Basically, it takes two 16-bit integers, multiplies them
25 * and divides by a third integer.
28 int MulDiv(int foo, int bar, int baz)
30 return (long)(((int)foo*bar)/baz);
33 /* UTILITY_strip015() removes \015 (^M, CR) from a string;
34 * this is done to convert a MS-DOS-style string to a more
35 * UNIX-friendly format. Replacement is done in-place.
38 void UTILITY_strip015(char *dest) {
42 while(*src == '\015') src++; /* Skip \015s */
43 while((*src) && (*src != '\015')) *(dest++) = *(src++);
45 *dest = '\0'; /* Add null terminator */
49 * OutputDebugString strips CRs from its (string) parameter and
50 * calls DebugPrintString(), which was written by someone else.
51 * Since this is part of the standard Windows API, it needs no
52 * references to nonstandard DLLs.
55 void OutputDebugString(LPSTR foo)
57 UTILITY_strip015(foo);
58 DebugPrintString(foo);
61 /* UTILITY_qualify(source, dest) takes the format string source and
62 * changes all the parameters to correspond to Linux integer sizes
63 * rather than Windows sizes. For example, it converts %i to %hi
64 * and %lx to %x. No array size checking is done at present.
67 static void UTILITY_qualify(const char *source, char *dest)
70 printf("UTILITY_qualify(\"%s\", \"%s\");\n", source, dest);
72 if(!source) return; /* Dumbass attack! */
74 /* Find next format code. */
75 while((*source != '%') && (*source)) {
76 *(dest++) = *(source++);
78 /* Yeah, I know I shouldn't use gotos.... */
79 if (!(*source)) goto loop_end;
81 *(dest++) = *(source++);
82 /* Now insert a size qualifier, if needed. */
90 /* We have a 16-bit value here. */
94 /* Here we go 'round the mulberry bush... */
100 /* UTILITY_argsize() evaluates the size of the argument list that
101 * accompanies a vsprintf() or wvsprintf() call.
103 * char *format; printf-style format string.
104 * BOOL windows; if this is TRUE, we assume that ints are
105 * 16 bits in size; otherwise we deal with
108 * size (in bytes) of the arguments that follow the call.
111 size_t UTILITY_argsize(const char *format, BOOL windows)
115 #define INT_SIZE (windows ? 2 : 4)
118 while((*format) && (*format != '%')) format++; /* skip ahead */
122 printf("found:\t\"%%");
124 format++; /* skip past '%' */
125 /* First skip the flags, field width, etc. */
126 /* First the flags */
127 if ((*format == '#') || (*format == '-') || (*format == '+')
128 || (*format == ' ')) {
130 printf("%c", *format);
134 /* Now the field width, etc. */
135 while(isdigit(*format)) {
137 printf("%c", *format);
143 printf("%c", *format);
147 while(isdigit(*format)) {
149 printf("%c", *format);
153 /* Now we handle the rest */
154 if((*format == 'h') || (*format == 'l') || (*format == 'L')) {
156 printf("%c", modifier);
158 modifier = *(format++);
160 /* Handle the actual type. */
162 printf("%c\"\n", *format);
172 size += ((modifier == 'l') ? 4 : INT_SIZE);
174 case 's': size += sizeof(char *); break;
180 /* It doesn't look as if Windows' wvsprintf()
181 supports floating-point arguments. However,
182 I'll leave this code here just in case. */
183 size += (modifier == 'L') ? sizeof(long double) : sizeof(double);
185 case 'p': size += sizeof(void *); break;
186 case 'n': size += sizeof(int *); break;
192 printf("UTILITY_argsize: returning %i\n", size);
197 /* UTILITY_convertArgs() creates a 32-bit argument list from a 16-bit list.
198 * This is used to allow wvsprintf() arguments to be fed through
202 * char *fmt; format string
203 * char *winarg; Windows-style arguments
206 * malloc()ed pointer to new argument list. This should
207 * be free()d as soon as it is finished with.
210 char *UTILITY_convertArgs(char *format, char *winarg)
212 char *result = (char *)malloc(UTILITY_argsize(format, 0));
216 while((*format) && (*format != '%')) format++; /* skip ahead */
220 printf("found:\t\"%%");
222 format++; /* skip past '%' */
223 /* First skip the flags, field width, etc. */
224 /* First the flags */
225 if ((*format == '#') || (*format == '-') || (*format == '+')
226 || (*format == ' ')) format++;
227 /* Now the field width, etc. */
228 while(isdigit(*format)) format++;
229 if(*format == '.') format++;
230 while(isdigit(*format)) format++;
231 /* Now we handle the rest */
232 if((*format == 'h') || (*format == 'l') || (*format == 'L'))
233 modifier = *(format++);
234 /* Handle the actual type. */
236 printf("%c\"\n", *format);
241 *(((int *)rptr)++) = (modifier=='l') ? *(((int *)winarg)++) : *(((short *)winarg)++);
248 *(((unsigned int *)rptr)++) = (modifier=='l') ? *(((unsigned int *)winarg)++)
249 : *(((unsigned short *)winarg)++);
253 case 'n': /* A pointer, is a pointer, is a pointer... */
254 *(((char **)rptr)++) = *(((char **)winarg)++);
261 /* It doesn't look as if Windows' wvsprintf()
262 supports floating-point arguments. However,
263 I'll leave this code here just in case. */
265 *(((long double *)rptr)++) = *(((long double *)winarg)++);
266 else *(((double *)rptr)++) = *(((double *)winarg)++);
275 /**************************************************************************
276 * wsprintf [USER.420]
278 int wsprintf(LPSTR lpOutput, LPSTR lpFormat, ...)
282 va_start(valist, lpFormat);
283 ArgCnt = vsprintf(lpOutput, lpFormat, valist);
289 /* wvsprintf() is an implementation of vsprintf(). This
290 * implementation converts the arguments to 32-bit integers and
291 * calls the standard library function vsprintf().
293 * Known shortcomings:
294 * wvsprintf() doesn't yet convert the arguments back after
295 * calling vsprintf(), so if Windows implements %n and a
296 * program depends on it, we're in trouble.
299 int wvsprintf(LPSTR buf, LPSTR format, LPSTR args)
301 char qualified_fmt[1536];
305 /* 1.5K is a safe value as wvsprintf can only handle buffers up to
306 1K and in a worst case such a buffer would look like "%i%i%i..." */
308 if(!buf || !format) return 0;
310 /* Change the format string so that ints are handled as short by
312 UTILITY_qualify(format, qualified_fmt);
314 /* Convert agruments to 32-bit values */
315 newargs = UTILITY_convertArgs(format, args);
317 result = vsprintf(buf, qualified_fmt, newargs);