Preserve 16-byte stack alignment in the various assembly
[wine] / dlls / msvcrt / misc.c
1 /*
2  * msvcrt.dll misc functions
3  *
4  * Copyright 2000 Jon Griffiths
5  *
6  * This library is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Lesser General Public
8  * License as published by the Free Software Foundation; either
9  * version 2.1 of the License, or (at your option) any later version.
10  *
11  * This library is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14  * Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public
17  * License along with this library; if not, write to the Free Software
18  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
19  */
20
21 #include "config.h"
22 #include "wine/port.h"
23
24 #include <stdlib.h>
25
26 #include "msvcrt.h"
27 #include "wine/debug.h"
28
29 WINE_DEFAULT_DEBUG_CHANNEL(msvcrt);
30
31
32 /*********************************************************************
33  *              _beep (MSVCRT.@)
34  */
35 void _beep( unsigned int freq, unsigned int duration)
36 {
37     TRACE(":Freq %d, Duration %d\n",freq,duration);
38     Beep(freq, duration);
39 }
40
41 /*********************************************************************
42  *              rand (MSVCRT.@)
43  */
44 int MSVCRT_rand(void)
45 {
46   return (rand() & 0x7fff);
47 }
48
49 /*********************************************************************
50  *              _sleep (MSVCRT.@)
51  */
52 void _sleep(unsigned long timeout)
53 {
54   TRACE("_sleep for %ld milliseconds\n",timeout);
55   Sleep((timeout)?timeout:1);
56 }
57
58 /*********************************************************************
59  *              _lfind (MSVCRT.@)
60  */
61 void* _lfind(const void* match, const void* start,
62              unsigned int* array_size, unsigned int elem_size,
63              int (*cf)(const void*,const void*) )
64 {
65   unsigned int size = *array_size;
66   if (size)
67     do
68     {
69       if (cf(match, start) == 0)
70         return (void *)start; /* found */
71       start = (char*)start + elem_size;
72     } while (--size);
73   return NULL;
74 }
75
76 /*********************************************************************
77  *              _lsearch (MSVCRT.@)
78  */
79 void* _lsearch(const void* match, void* start,
80                unsigned int* array_size, unsigned int elem_size,
81                int (*cf)(const void*,const void*) )
82 {
83   unsigned int size = *array_size;
84   if (size)
85     do
86     {
87       if (cf(match, start) == 0)
88         return start; /* found */
89       start = (char*)start + elem_size;
90     } while (--size);
91
92   /* not found, add to end */
93   memcpy(start, match, elem_size);
94   array_size[0]++;
95   return start;
96 }
97
98 /*********************************************************************
99  *              _chkesp (MSVCRT.@)
100  *
101  * Trap to a debugger if the value of the stack pointer has changed.
102  *
103  * PARAMS
104  *  None.
105  *
106  * RETURNS
107  *  Does not return.
108  *
109  * NOTES
110  *  This function is available for iX86 only.
111  *
112  *  When VC++ generates debug code, it stores the value of the stack pointer
113  *  before calling any external function, and checks the value following
114  *  the call. It then calls this function, which will trap if the values are
115  *  not the same. Usually this means that the prototype used to call
116  *  the function is incorrect.  It can also mean that the .spec entry has
117  *  the wrong calling convention or parameters.
118  */
119 #ifdef __i386__
120
121 # ifdef __GNUC__
122
123 __ASM_GLOBAL_FUNC(_chkesp,
124                   "jnz 1f\n\t"
125                   "ret\n"
126                   "1:\tpushl %ebp\n\t"
127                   "movl %esp,%ebp\n\t"
128                   "subl $12,%esp\n\t"
129                   "pushl %eax\n\t"
130                   "pushl %ecx\n\t"
131                   "pushl %edx\n\t"
132                   "call " __ASM_NAME("MSVCRT_chkesp_fail") "\n\t"
133                   "popl %edx\n\t"
134                   "popl %ecx\n\t"
135                   "popl %eax\n\t"
136                   "leave\n\t"
137                   "ret");
138
139 void MSVCRT_chkesp_fail(void)
140 {
141   ERR("Stack pointer incorrect after last function call - Bad prototype/spec entry?\n");
142   DebugBreak();
143 }
144
145 # else  /* __GNUC__ */
146
147 /**********************************************************************/
148
149 void _chkesp(void)
150 {
151 }
152
153 # endif  /* __GNUC__ */
154
155 #endif  /* __i386__ */