source: mainline/uspace/lib/posix/stdlib.c@ 102a729

lfn serial ticket/834-toolchain-update topic/msim-upgrade topic/simplify-dev-export
Last change on this file since 102a729 was 102a729, checked in by Petr Koupy <petr.koupy@…>, 14 years ago

Various bugfixes in stdlib.h functions.

  • Property mode set to 100644
File size: 10.2 KB
Line 
1/*
2 * Copyright (c) 2011 Petr Koupy
3 * Copyright (c) 2011 Jiri Zarevucky
4 * All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 *
10 * - Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * - Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * - The name of the author may not be used to endorse or promote products
16 * derived from this software without specific prior written permission.
17 *
18 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
19 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
20 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
21 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
22 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
23 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
24 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
25 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
27 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28 */
29
30/** @addtogroup libposix
31 * @{
32 */
33/** @file Standard library definitions.
34 */
35
36#define LIBPOSIX_INTERNAL
37
38#include "internal/common.h"
39#include "stdlib.h"
40
41#include "errno.h"
42#include "limits.h"
43
44#include "libc/sort.h"
45#include "libc/str.h"
46#include "libc/vfs/vfs.h"
47
48/**
49 *
50 * @param array
51 * @param count
52 * @param size
53 * @param compare
54 */
55int posix_atexit(void (*func)(void))
56{
57 // TODO: low priority, just a compile-time dependency of binutils
58 not_implemented();
59}
60
61/**
62 * Integer absolute value.
63 *
64 * @param i Input value.
65 * @return Absolute value of the parameter.
66 */
67int posix_abs(int i)
68{
69 return i < 0 ? -i : i;
70}
71
72/**
73 * Long integer absolute value.
74 *
75 * @param i Input value.
76 * @return Absolute value of the parameter.
77 */
78long posix_labs(long i)
79{
80 return i < 0 ? -i : i;
81}
82
83/**
84 * Long long integer absolute value.
85 *
86 * @param i Input value.
87 * @return Absolute value of the parameter.
88 */
89long long posix_llabs(long long i)
90{
91 return i < 0 ? -i : i;
92}
93
94/**
95 * Compute the quotient and remainder of an integer division.
96 *
97 * @param numer Numerator.
98 * @param denom Denominator.
99 * @return Quotient and remainder packed into structure.
100 */
101posix_div_t posix_div(int numer, int denom)
102{
103 return (posix_div_t) { .quot = numer / denom, .rem = numer % denom };
104}
105
106/**
107 * Compute the quotient and remainder of a long integer division.
108 *
109 * @param numer Numerator.
110 * @param denom Denominator.
111 * @return Quotient and remainder packed into structure.
112 */
113posix_ldiv_t posix_ldiv(long numer, long denom)
114{
115 return (posix_ldiv_t) { .quot = numer / denom, .rem = numer % denom };
116}
117
118/**
119 * Compute the quotient and remainder of a long long integer division.
120 *
121 * @param numer Numerator.
122 * @param denom Denominator.
123 * @return Quotient and remainder packed into structure.
124 */
125posix_lldiv_t posix_lldiv(long long numer, long long denom)
126{
127 return (posix_lldiv_t) { .quot = numer / denom, .rem = numer % denom };
128}
129
130/**
131 * Private helper function that serves as a compare function for qsort().
132 *
133 * @param elem1 First element to compare.
134 * @param elem2 Second element to compare.
135 * @param compare Comparison function without userdata parameter.
136 * @return Relative ordering of the elements.
137 */
138static int sort_compare_wrapper(void *elem1, void *elem2, void *userdata)
139{
140 int (*compare)(const void *, const void *) = userdata;
141 int ret = compare(elem1, elem2);
142
143 /* Native qsort internals expect this. */
144 if (ret < 0) {
145 return -1;
146 } else if (ret > 0) {
147 return 1;
148 } else {
149 return 0;
150 }
151}
152
153/**
154 * Array sorting utilizing the quicksort algorithm.
155 *
156 * @param array Array of elements to sort.
157 * @param count Number of elements in the array.
158 * @param size Width of each element.
159 * @param compare Decides relative ordering of two elements.
160 */
161void posix_qsort(void *array, size_t count, size_t size,
162 int (*compare)(const void *, const void *))
163{
164 /* Implemented in libc with one extra argument. */
165 qsort(array, count, size, sort_compare_wrapper, compare);
166}
167
168/**
169 * Binary search in a sorted array.
170 *
171 * @param key Object to search for.
172 * @param base Pointer to the first element of the array.
173 * @param nmemb Number of elements in the array.
174 * @param size Size of each array element.
175 * @param compar Comparison function.
176 * @return Pointer to a matching element, or NULL if none can be found.
177 */
178void *posix_bsearch(const void *key, const void *base,
179 size_t nmemb, size_t size, int (*compar)(const void *, const void *))
180{
181 while (nmemb > 0) {
182 const void *middle = base + (nmemb / 2) * size;
183 int cmp = compar(key, middle);
184 if (cmp == 0) {
185 return (void *) middle;
186 }
187 if (middle == base) {
188 /* There is just one member left to check and it
189 * didn't match the key. Avoid infinite loop.
190 */
191 break;
192 }
193 if (cmp < 0) {
194 nmemb = nmemb / 2;
195 } else if (cmp > 0) {
196 nmemb = nmemb - (nmemb / 2);
197 base = middle;
198 }
199 }
200
201 return NULL;
202}
203
204/**
205 * Retrieve a value of the given environment variable.
206 *
207 * Since HelenOS doesn't support env variables at the moment,
208 * this function always returns NULL.
209 *
210 * @param name Name of the variable.
211 * @return Value of the variable or NULL if such variable does not exist.
212 */
213char *posix_getenv(const char *name)
214{
215 return NULL;
216}
217
218/**
219 *
220 * @param name
221 * @param resolved
222 * @return
223 */
224int posix_putenv(char *string)
225{
226 // TODO: low priority, just a compile-time dependency of binutils
227 not_implemented();
228}
229
230/**
231 * Issue a command.
232 *
233 * @param string String to be passed to a command interpreter or NULL.
234 * @return Termination status of the command if the command is not NULL,
235 * otherwise indicate whether there is a command interpreter (non-zero)
236 * or not (zero).
237 */
238int posix_system(const char *string) {
239 // TODO: does nothing at the moment
240 return 0;
241}
242
243/**
244 * Resolve absolute pathname.
245 *
246 * @param name Pathname to be resolved.
247 * @param resolved Either buffer for the resolved absolute pathname or NULL.
248 * @return On success, either resolved (if it was not NULL) or pointer to the
249 * newly allocated buffer containing the absolute pathname (if resolved was
250 * NULL). Otherwise NULL.
251 *
252 */
253char *posix_realpath(const char *restrict name, char *restrict resolved)
254{
255 #ifndef PATH_MAX
256 assert(resolved == NULL);
257 #endif
258
259 if (name == NULL) {
260 errno = EINVAL;
261 return NULL;
262 }
263
264 // TODO: symlink resolution
265
266 /* Function absolutize is implemented in libc and declared in vfs.h.
267 * No more processing is required as HelenOS doesn't have symlinks
268 * so far (as far as I can tell), although this function will need
269 * to be updated when that support is implemented.
270 */
271 char* absolute = absolutize(name, NULL);
272
273 if (absolute == NULL) {
274 /* POSIX requires some specific errnos to be set
275 * for some cases, but there is no way to find out from
276 * absolutize().
277 */
278 errno = EINVAL;
279 return NULL;
280 }
281
282 if (resolved == NULL) {
283 return absolute;
284 } else {
285 #ifdef PATH_MAX
286 str_cpy(resolved, PATH_MAX, absolute);
287 #endif
288 free(absolute);
289 return resolved;
290 }
291}
292
293/**
294 * Converts a string representation of a floating-point number to
295 * its native representation. See posix_strtold().
296 *
297 * @param nptr String representation of a floating-point number.
298 * @return Double-precision number resulting from the string conversion.
299 */
300double posix_atof(const char *nptr)
301{
302 return posix_strtod(nptr, NULL);
303}
304
305/**
306 * Converts a string representation of a floating-point number to
307 * its native representation. See posix_strtold().
308 *
309 * @param nptr String representation of a floating-point number.
310 * @param endptr Pointer to the final part of the string which
311 * was not used for conversion.
312 * @return Single-precision number resulting from the string conversion.
313 */
314float posix_strtof(const char *restrict nptr, char **restrict endptr)
315{
316 return (float) posix_strtold(nptr, endptr);
317}
318
319/**
320 * Converts a string representation of a floating-point number to
321 * its native representation. See posix_strtold().
322 *
323 * @param nptr String representation of a floating-point number.
324 * @param endptr Pointer to the final part of the string which
325 * was not used for conversion.
326 * @return Double-precision number resulting from the string conversion.
327 */
328double posix_strtod(const char *restrict nptr, char **restrict endptr)
329{
330 return (double) posix_strtold(nptr, endptr);
331}
332
333/**
334 * Allocate memory chunk.
335 *
336 * @param size Size of the chunk to allocate.
337 * @return Either pointer to the allocated chunk or NULL if not possible.
338 */
339void *posix_malloc(size_t size)
340{
341 return malloc(size);
342}
343
344/**
345 * Allocate memory for an array of elements.
346 *
347 * @param nelem Number of elements in the array.
348 * @param elsize Size of each element.
349 * @return Either pointer to the allocated array or NULL if not possible.
350 */
351void *posix_calloc(size_t nelem, size_t elsize)
352{
353 return calloc(nelem, elsize);
354}
355
356/**
357 * Reallocate memory chunk to a new size.
358 *
359 * @param ptr Memory chunk to reallocate. Might be NULL.
360 * @param size Size of the reallocated chunk. Might be zero.
361 * @return Either NULL or the pointer to the newly reallocated chunk.
362 */
363void *posix_realloc(void *ptr, size_t size)
364{
365 if (ptr != NULL && size == 0) {
366 /* Native realloc does not handle this special case. */
367 free(ptr);
368 return NULL;
369 } else {
370 return realloc(ptr, size);
371 }
372}
373
374/**
375 * Free allocated memory chunk.
376 *
377 * @param ptr Memory chunk to be freed.
378 */
379void posix_free(void *ptr)
380{
381 if (ptr) {
382 free(ptr);
383 }
384}
385
386/**
387 *
388 * @param tmpl
389 * @return
390 */
391char *posix_mktemp(char *tmpl)
392{
393 // TODO: low priority, just a compile-time dependency of binutils
394 not_implemented();
395}
396
397/**
398 * Get system load average statistics.
399 *
400 * Not supported. Always returns -1.
401 *
402 * @param loadavg Array where the load averages shall be placed.
403 * @param nelem Maximum number of elements to be placed into the array.
404 * @return Number of elements placed into the array on success, -1 otherwise.
405 */
406int bsd_getloadavg(double loadavg[], int nelem)
407{
408 return -1;
409}
410
411/** @}
412 */
Note: See TracBrowser for help on using the repository browser.