2 * Utility functions shared between modules, but not exported.
14 #include <mach/clock.h>
15 #include <mach/mach.h>
21 /* initialize a generic dynamic array struct */
22 int dynarray_init(struct dynamic_array
*da
, size_t entry_size
, size_t grow_size
) {
27 if (entry_size
== 0 || grow_size
== 0) {
28 fprintf(stderr
, "%s: internal error: sizes cannot be zero\n", __func__
);
35 da
->entry_size
= entry_size
;
36 da
->grow_size
= grow_size
;
37 da
->a
= malloc(da
->entry_size
* da
->grow_size
);
39 fprintf(stderr
, "%s():%s\n", "malloc", strerror(errno
));
42 da
->allocated
= da
->grow_size
;
46 /* allocate and initialize a new generic dynamic array */
47 struct dynamic_array
*dynarray_new(size_t entry_size
, size_t grow_size
) {
48 struct dynamic_array
*da
;
53 da
= calloc(1, sizeof *da
);
55 fprintf(stderr
, "%s():%s\n", "calloc", strerror(errno
));
59 if (dynarray_init(da
, entry_size
, grow_size
)) {
60 fprintf(stderr
, "%s():%s\n", "dynarray_init", strerror(errno
));
68 void dynarray_empty(struct dynamic_array
*da
, void (*free_element
)(void *)) {
69 while ( da
->entries
-- ) {
70 void *element
= (void *)DYNARRAY_ITEM(*da
, da
->entries
);
72 free_element(element
);
79 /* copy item onto end of array */
80 void *dynarray_add(struct dynamic_array
*da
, void *item
) {
86 /* make room, make room */
87 if (da
->entries
== da
->allocated
) {
88 size_t new_allocated
= da
->allocated
+ da
->grow_size
;
89 void *tmp_ptr
= realloc(da
->a
, new_allocated
* da
->entry_size
);
90 if (tmp_ptr
== NULL
) {
91 fprintf(stderr
, "%s():%s\n", "realloc", strerror(errno
));
95 da
->allocated
= new_allocated
;
99 dst
= DYNARRAY_ITEM(*da
, da
->entries
);
100 memcpy(dst
, item
, da
->entry_size
);
107 /* simplified strtoul with range checking */
108 int str_to_word(char *s
) {
115 l
= strtoul(s
, &ep
, 0);
118 || !(*s
&& *ep
== '\0') ) {
119 /* out of range of conversion, or invalid character encountered */
123 if (l
>= DCPU16_RAM
) {
124 /* out of range for our needs */
132 /* just like strtok_r, but ignores separators within quotes */
133 char *strqtok_r(char *str
, const char *sep
, int esc
, const char *quote
, char **lastq
, char **lasts
) {
146 /* next token starts after any leading seps */
147 while (**lasts
&& strchr(sep
, **lasts
)) {
159 /* the previous character was the escape, do not consider this character any further */
166 /* this character is the escape, do not consider the next character */
167 if (**lasts
== esc
) {
173 /* we have a quote open, only consider matching quote to close */
175 if (**lasts
== **lastq
)
181 /* this character is an opening quote, remember what it is */
182 if (strchr(quote
, **lasts
)) {
188 /* this character is a separator, separate and be done */
189 if (strchr(sep
, **lasts
)) {
197 /* were we left with an unmatched quote?
198 remember where we had trouble
199 try everything following lonely quote again, but pretend quote is there */
208 /* now strip escape characters */
209 for (src
= dst
= tok
; *src
; src
++, dst
++) {
219 /* remember where we had trouble */
226 /* like gettimeofday, except with nanoseconds */
228 int gettimespecofday(struct timespec
*ts
) {
234 host_get_clock_service(mach_host_self(), CALENDAR_CLOCK
, &cclock
);
235 clock_get_time(cclock
, &mts
);
236 mach_port_deallocate(mach_task_self(), cclock
);
237 ts
->tv_sec
= mts
.tv_sec
;
238 ts
->tv_nsec
= mts
.tv_nsec
;
240 retval
= clock_gettime(CLOCK_REALTIME
, ts
);
241 #endif /* __MACH__ */
247 int timespec_add(struct timespec
*result
, const struct timespec
*x
) {
248 result
->tv_sec
+= x
->tv_sec
;
249 result
->tv_nsec
+= x
->tv_nsec
;
251 result
->tv_sec
+= result
->tv_nsec
/ 1000000000;
252 result
->tv_nsec
%= 1000000000;
258 int timespec_subtract(struct timespec
*result
, struct timespec
*x
, struct timespec
*y
) {
259 if (x
->tv_nsec
< y
->tv_nsec
) {
260 int z
= (y
->tv_nsec
- x
->tv_nsec
) / 1000000000 + 1;
261 y
->tv_nsec
-= 1000000000 * z
;
264 if (x
->tv_nsec
- y
->tv_nsec
> 1000000000) {
265 int z
= (x
->tv_nsec
- y
->tv_nsec
) / 1000000000;
266 y
->tv_nsec
+= 1000000000 * z
;
269 result
->tv_sec
= x
->tv_sec
- y
->tv_sec
;
270 result
->tv_nsec
= x
->tv_nsec
- y
->tv_nsec
;
272 return x
->tv_sec
< y
->tv_sec
;
275 int timeval_subtract(struct timeval
*result
, struct timeval
*x
, struct timeval
*y
) {
276 /* Perform the carry for the later subtraction by updating y. */
277 if (x
->tv_usec
< y
->tv_usec
) {
278 int nsec
= (y
->tv_usec
- x
->tv_usec
) / 1000000 + 1;
279 y
->tv_usec
-= 1000000 * nsec
;
282 if (x
->tv_usec
- y
->tv_usec
> 1000000) {
283 int nsec
= (x
->tv_usec
- y
->tv_usec
) / 1000000;
284 y
->tv_usec
+= 1000000 * nsec
;
288 /* Compute the time remaining to wait.
289 tv_usec is certainly positive. */
290 result
->tv_sec
= x
->tv_sec
- y
->tv_sec
;
291 result
->tv_usec
= x
->tv_usec
- y
->tv_usec
;
293 /* Return 1 if result is negative. */
294 return x
->tv_sec
< y
->tv_sec
;