ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/deliantra/server/common/utils.C
Revision: 1.78
Committed: Fri May 16 17:09:38 2008 UTC (16 years ago) by root
Content type: text/plain
Branch: MAIN
CVS Tags: rel-2_6, rel-2_55, rel-2_56, rel-2_61
Changes since 1.77: +13 -23 lines
Log Message:
*** empty log message ***

File Contents

# User Rev Content
1 elmex 1.1 /*
2 root 1.68 * This file is part of Deliantra, the Roguelike Realtime MMORPG.
3 pippijn 1.39 *
4 root 1.74 * Copyright (©) 2005,2006,2007,2008 Marc Alexander Lehmann / Robin Redeker / the Deliantra team
5 root 1.57 * Copyright (©) 2002,2007 Mark Wedel & Crossfire Development Team
6     * Copyright (©) 1992,2007 Frank Tore Johansen
7 pippijn 1.39 *
8 root 1.68 * Deliantra is free software: you can redistribute it and/or modify
9 root 1.60 * it under the terms of the GNU General Public License as published by
10     * the Free Software Foundation, either version 3 of the License, or
11     * (at your option) any later version.
12 pippijn 1.39 *
13 root 1.60 * This program is distributed in the hope that it will be useful,
14     * but WITHOUT ANY WARRANTY; without even the implied warranty of
15     * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16     * GNU General Public License for more details.
17 pippijn 1.39 *
18 root 1.60 * You should have received a copy of the GNU General Public License
19     * along with this program. If not, see <http://www.gnu.org/licenses/>.
20 root 1.57 *
21 root 1.68 * The authors can be reached via e-mail to <support@deliantra.net>
22 pippijn 1.39 */
23 elmex 1.1
24     /*
25     * General convenience functions for crossfire.
26     */
27    
28 root 1.37 #include <cstdlib>
29     #include <sys/types.h>
30     #include <unistd.h>
31     #include <sys/time.h>
32     #include <time.h>
33     #include <signal.h>
34    
35 elmex 1.1 #include <global.h>
36     #include <material.h>
37    
38 root 1.4 #include <glib.h>
39    
40 root 1.63 refcnt_base::refcnt_t refcnt_dummy;
41 root 1.74 ssize_t slice_alloc;
42 root 1.77 rand_gen rndm, rmg_rndm;
43 root 1.40
44 root 1.42 void
45     tausworthe_random_generator::seed (uint32_t seed)
46 root 1.40 {
47 root 1.74 state [0] = seed * 69069U; if (state [0] < 2U) state [0] += 2U;
48     state [1] = state [0] * 69069U; if (state [0] < 8U) state [0] += 8U;
49     state [2] = state [1] * 69069U; if (state [0] < 16U) state [0] += 16U;
50     state [3] = state [2] * 69069U; if (state [0] < 128U) state [0] += 128U;
51 root 1.40
52     for (int i = 11; --i; )
53     operator ()();
54     }
55    
56     uint32_t
57     tausworthe_random_generator::next ()
58     {
59     state [0] = ((state [0] & 0xFFFFFFFEU) << 18U) ^ (((state [0] << 6U) ^ state [0]) >> 13U);
60     state [1] = ((state [1] & 0xFFFFFFF8U) << 2U) ^ (((state [1] << 2U) ^ state [1]) >> 27U);
61     state [2] = ((state [2] & 0xFFFFFFF0U) << 7U) ^ (((state [2] << 13U) ^ state [2]) >> 21U);
62     state [3] = ((state [3] & 0xFFFFFF80U) << 13U) ^ (((state [3] << 3U) ^ state [3]) >> 12U);
63    
64     return state [0] ^ state [1] ^ state [2] ^ state [3];
65     }
66    
67 root 1.42 uint32_t
68 root 1.50 tausworthe_random_generator::get_range (uint32_t num)
69 root 1.42 {
70 root 1.50 return (next () * (uint64_t)num) >> 32U;
71 root 1.42 }
72    
73     // return a number within (min .. max)
74     int
75     tausworthe_random_generator::get_range (int r_min, int r_max)
76     {
77 root 1.50 return r_min + get_range (max (r_max - r_min + 1, 0));
78 root 1.42 }
79    
80 elmex 1.1 /*
81     * The random functions here take luck into account when rolling random
82     * dice or numbers. This function has less of an impact the larger the
83     * difference becomes in the random numbers. IE, the effect is lessened
84     * on a 1-1000 roll, vs a 1-6 roll. This can be used by crafty programmers,
85     * to specifically disable luck in certain rolls, simply by making the
86     * numbers larger (ie, 1d1000 > 500 vs 1d6 > 3)
87     */
88    
89     /*
90     * Roll a random number between min and max. Uses op to determine luck,
91     * and if goodbad is non-zero, luck increases the roll, if zero, it decreases.
92     * Generally, op should be the player/caster/hitter requesting the roll,
93     * not the recipient (ie, the poor slob getting hit). [garbled 20010916]
94     */
95 root 1.9 int
96 root 1.41 random_roll (int r_min, int r_max, const object *op, int goodbad)
97 root 1.9 {
98 root 1.78 r_max = max (r_min, r_max);
99    
100 root 1.41 int base = r_max - r_min > 1 ? 20 : 50; /* d2 and d3 are corner cases */
101 elmex 1.1
102 root 1.41 if (op->type == PLAYER)
103 root 1.9 {
104 root 1.41 int luck = op->stats.luck;
105 elmex 1.1
106 root 1.41 if (rndm (base) < min (10, abs (luck)))
107     {
108     //TODO: take luck into account
109     }
110 elmex 1.1 }
111 root 1.41
112     return rndm (r_min, r_max);
113 elmex 1.1 }
114    
115     /*
116     * This is a 64 bit version of random_roll above. This is needed
117     * for exp loss calculations for players changing religions.
118     */
119 root 1.9 sint64
120 root 1.78 random_roll64 (sint64 r_min, sint64 r_max, const object *op, int goodbad)
121 root 1.9 {
122 root 1.78 sint64 omin = r_min;
123     sint64 range = max (0, r_max - r_min + 1);
124     int base = range > 2 ? 20 : 50; /* d2 and d3 are corner cases */
125 elmex 1.1
126 root 1.45 /*
127     * Make a call to get two 32 bit unsigned random numbers, and just to
128     * a little bitshifting.
129 root 1.9 */
130 root 1.55 sint64 ran = (sint64) rndm.next () ^ ((sint64) rndm.next () << 31);
131 root 1.9
132     if (op->type != PLAYER)
133 root 1.78 return ((ran % range) + r_min);
134 root 1.9
135 root 1.55 int luck = op->stats.luck;
136    
137 root 1.78 if (rndm (base) < min (10, abs (luck)))
138 root 1.9 {
139     /* we have a winner */
140     ((luck > 0) ? (luck = 1) : (luck = -1));
141 root 1.78 range -= luck;
142     if (range < 1)
143 root 1.9 return (omin); /*check again */
144 root 1.55
145 root 1.78 ((goodbad) ? (r_min += luck) : (range));
146 elmex 1.1
147 root 1.78 return (max (omin, min (r_max, (ran % range) + r_min)));
148 elmex 1.1 }
149 root 1.45
150 root 1.78 return ran % range + r_min;
151 elmex 1.1 }
152    
153     /*
154     * Roll a number of dice (2d3, 4d6). Uses op to determine luck,
155     * If goodbad is non-zero, luck increases the roll, if zero, it decreases.
156     * Generally, op should be the player/caster/hitter requesting the roll,
157     * not the recipient (ie, the poor slob getting hit).
158     * The args are num D size (ie 4d6) [garbled 20010916]
159     */
160 root 1.9 int
161     die_roll (int num, int size, const object *op, int goodbad)
162     {
163 root 1.55 int min, luck, total, i, gotlucky;
164 root 1.9
165 root 1.55 int diff = size;
166 root 1.9 min = 1;
167     luck = total = gotlucky = 0;
168 root 1.55 int base = diff > 2 ? 20 : 50; /* d2 and d3 are corner cases */
169    
170 root 1.9 if (size < 2 || diff < 1)
171     {
172     LOG (llevError, "Calling die_roll with num=%d size=%d\n", num, size);
173 root 1.55 return num; /* avoids a float exception */
174 root 1.9 }
175 elmex 1.1
176 root 1.9 if (op->type == PLAYER)
177     luck = op->stats.luck;
178    
179     for (i = 0; i < num; i++)
180     {
181 root 1.45 if (rndm (base) < MIN (10, abs (luck)) && !gotlucky)
182 root 1.9 {
183     /* we have a winner */
184     gotlucky++;
185     ((luck > 0) ? (luck = 1) : (luck = -1));
186     diff -= luck;
187     if (diff < 1)
188     return (num); /*check again */
189     ((goodbad) ? (min += luck) : (diff));
190 root 1.45 total += MAX (1, MIN (size, rndm (diff) + min));
191 root 1.9 }
192     else
193 root 1.45 total += rndm (size) + 1;
194 elmex 1.1 }
195 root 1.45
196     return total;
197 elmex 1.1 }
198    
199     /* convert materialname to materialtype_t */
200    
201 root 1.9 materialtype_t *
202 root 1.47 name_to_material (const shstr &name)
203 elmex 1.1 {
204 root 1.47 for (materialtype_t *mt = materialt; mt && mt->next; mt = mt->next)
205     if (name == mt->name)
206     return mt;
207 elmex 1.1
208 root 1.62 return 0;
209 elmex 1.1 }
210    
211     /* when doing transmutation of objects, we have to recheck the resistances,
212     * as some that did not apply previously, may apply now.
213     */
214 root 1.9 void
215     transmute_materialname (object *op, const object *change)
216 elmex 1.1 {
217 root 1.9 materialtype_t *mt;
218     int j;
219 elmex 1.1
220 root 1.9 if (op->materialname == NULL)
221     return;
222 elmex 1.1
223 root 1.9 if (change->materialname != NULL && strcmp (op->materialname, change->materialname))
224     return;
225    
226 root 1.26 if (!op->is_armor ())
227 root 1.9 return;
228    
229     mt = name_to_material (op->materialname);
230     if (!mt)
231     {
232 root 1.58 LOG (llevError, "archetype '%s>%s' uses nonexistent material '%s'\n", &op->arch->archname, &op->name, &op->materialname);
233 root 1.9 return;
234     }
235    
236     for (j = 0; j < NROFATTACKS; j++)
237     if (op->resist[j] == 0 && change->resist[j] != 0)
238     {
239     op->resist[j] += mt->mod[j];
240     if (op->resist[j] > 100)
241     op->resist[j] = 100;
242     if (op->resist[j] < -100)
243     op->resist[j] = -100;
244     }
245 elmex 1.1 }
246    
247     /* set the materialname and type for an item */
248 root 1.9 void
249     set_materialname (object *op, int difficulty, materialtype_t *nmt)
250 elmex 1.1 {
251 root 1.9 materialtype_t *mt, *lmt;
252    
253     if (op->materialname != NULL)
254     return;
255 elmex 1.1
256 root 1.9 if (nmt == NULL)
257     {
258     lmt = NULL;
259 root 1.61
260 root 1.47 for (mt = materialt; mt && mt->next; mt = mt->next)
261 root 1.61 if (op->materials & mt->material && rndm (1, 100) <= mt->chance &&
262     difficulty >= mt->difficulty && (op->magic >= mt->magic || mt->magic == 0))
263     {
264     lmt = mt;
265     if (!(op->is_weapon () || op->is_armor ()))
266 root 1.9 break;
267 root 1.61 }
268 root 1.9 }
269     else
270 root 1.61 lmt = nmt;
271 elmex 1.1
272 root 1.9 if (lmt != NULL)
273     {
274 root 1.26 if (op->stats.dam && op->is_weapon ())
275 root 1.9 {
276     op->stats.dam += lmt->damage;
277     if (op->stats.dam < 1)
278     op->stats.dam = 1;
279     }
280 root 1.46
281 root 1.9 if (op->stats.sp && op->type == BOW)
282     op->stats.sp += lmt->sp;
283 root 1.26 if (op->stats.wc && op->is_weapon ())
284 root 1.9 op->stats.wc += lmt->wc;
285 root 1.26 if (op->is_armor ())
286 root 1.9 {
287     if (op->stats.ac)
288     op->stats.ac += lmt->ac;
289 root 1.61
290     for (int j = 0; j < NROFATTACKS; j++)
291 root 1.9 if (op->resist[j] != 0)
292     {
293     op->resist[j] += lmt->mod[j];
294     if (op->resist[j] > 100)
295     op->resist[j] = 100;
296     if (op->resist[j] < -100)
297     op->resist[j] = -100;
298     }
299     }
300 root 1.61
301 root 1.46 op->materialname = lmt->name;
302 root 1.9 /* dont make it unstackable if it doesn't need to be */
303 root 1.26 if (op->is_weapon () || op->is_armor ())
304 root 1.9 {
305     op->weight = (op->weight * lmt->weight) / 100;
306     op->value = (op->value * lmt->value) / 100;
307 root 1.2 }
308 elmex 1.1 }
309     }
310    
311     /*
312     * Strip out the media tags from a String.
313     * Warning the input string will contain the result string
314     */
315 root 1.9 void
316     strip_media_tag (char *message)
317     {
318     int in_tag = 0;
319     char *dest;
320     char *src;
321    
322     src = dest = message;
323     while (*src != '\0')
324     {
325     if (*src == '[')
326     {
327     in_tag = 1;
328     }
329     else if (in_tag && (*src == ']'))
330     in_tag = 0;
331     else if (!in_tag)
332     {
333     *dest = *src;
334     dest++;
335     }
336     src++;
337     }
338     *dest = '\0';
339     }
340    
341     const char *
342     strrstr (const char *haystack, const char *needle)
343     {
344     const char *lastneedle;
345    
346     lastneedle = NULL;
347     while ((haystack = strstr (haystack, needle)) != NULL)
348     {
349     lastneedle = haystack;
350     haystack++;
351 elmex 1.1 }
352 root 1.9 return lastneedle;
353    
354 elmex 1.1 }
355 root 1.9
356 elmex 1.1 #define EOL_SIZE (sizeof("\n")-1)
357 root 1.9 void
358     strip_endline (char *buf)
359     {
360     if (strlen (buf) < sizeof ("\n"))
361     {
362     return;
363 elmex 1.1 }
364 root 1.9 if (!strcmp (buf + strlen (buf) - EOL_SIZE, "\n"))
365     buf[strlen (buf) - EOL_SIZE] = '\0';
366 elmex 1.1 }
367    
368     /**
369     * Replace in string src all occurrences of key by replacement. The resulting
370     * string is put into result; at most resultsize characters (including the
371     * terminating null character) will be written to result.
372     */
373 root 1.9 void
374     replace (const char *src, const char *key, const char *replacement, char *result, size_t resultsize)
375 elmex 1.1 {
376 root 1.9 size_t resultlen;
377     size_t keylen;
378 elmex 1.1
379 root 1.9 /* special case to prevent infinite loop if key==replacement=="" */
380     if (strcmp (key, replacement) == 0)
381     {
382     snprintf (result, resultsize, "%s", src);
383     return;
384     }
385    
386     keylen = strlen (key);
387    
388     resultlen = 0;
389     while (*src != '\0' && resultlen + 1 < resultsize)
390     {
391     if (strncmp (src, key, keylen) == 0)
392 root 1.2 {
393 root 1.9 snprintf (result + resultlen, resultsize - resultlen, "%s", replacement);
394     resultlen += strlen (result + resultlen);
395     src += keylen;
396 root 1.2 }
397 root 1.9 else
398 root 1.2 {
399 root 1.9 result[resultlen++] = *src++;
400 root 1.2 }
401 root 1.9 }
402     result[resultlen] = '\0';
403 elmex 1.1 }
404    
405     /**
406     * Taking a string as an argument, mutate it into a string that looks like a list.
407     * a 'list' for the purposes here, is a string of items, seperated by commas, except
408     * for the last entry, which has an 'and' before it, and a full stop (period) after it.
409     * This function will also strip all trailing non alphanumeric characters.
410     * It does not insert an oxford comma.
411     */
412 root 1.9 void
413     make_list_like (char *input)
414     {
415     char *p, tmp[MAX_BUF];
416     int i;
417    
418     if (!input || strlen (input) > MAX_BUF - 5)
419 elmex 1.1 return;
420 root 1.9 /* bad stuff would happen if we continued here, the -5 is to make space for ' and ' */
421    
422     strncpy (tmp, input, MAX_BUF - 5);
423     /*trim all trailing commas, spaces etc. */
424     for (i = strlen (tmp); !isalnum (tmp[i]) && i >= 0; i--)
425     tmp[i] = '\0';
426 root 1.11
427 root 1.9 strcat (tmp, ".");
428    
429     p = strrchr (tmp, ',');
430     if (p)
431     {
432     *p = '\0';
433     strcpy (input, tmp);
434     p++;
435     strcat (input, " and");
436     strcat (input, p);
437     }
438     else
439     strcpy (input, tmp);
440 root 1.11
441 root 1.9 return;
442 elmex 1.1 }
443 root 1.3
444 root 1.14 /////////////////////////////////////////////////////////////////////////////
445    
446 root 1.37 void
447     fork_abort (const char *msg)
448     {
449     if (!fork ())
450     {
451     signal (SIGABRT, SIG_DFL);
452 root 1.52 // try to put corefiles into a subdirectory, if existing, to allow
453     // an administrator to reduce the I/O load.
454     chdir ("cores");
455 root 1.37 abort ();
456     }
457    
458 root 1.38 LOG (llevError, "fork abort: %s\n", msg);
459 root 1.37 }
460 root 1.38
461 root 1.25 void *salloc_ (int n) throw (std::bad_alloc)
462 root 1.10 {
463 root 1.25 void *ptr = g_slice_alloc (n);
464 root 1.13
465 root 1.23 if (!ptr)
466 root 1.13 throw std::bad_alloc ();
467 root 1.4
468 root 1.74 slice_alloc += n;
469 root 1.23 return ptr;
470     }
471    
472 root 1.25 void *salloc_ (int n, void *src) throw (std::bad_alloc)
473 root 1.23 {
474 root 1.25 void *ptr = salloc_ (n);
475 root 1.23
476 root 1.24 if (src)
477 root 1.25 memcpy (ptr, src, n);
478 root 1.24 else
479 root 1.25 memset (ptr, 0, n);
480 root 1.23
481     return ptr;
482 root 1.3 }
483 root 1.11
484 root 1.69 /******************************************************************************/
485    
486 root 1.72 #if DEBUG_SALLOC
487 root 1.69
488 root 1.70 #define MAGIC 0xa1b2c35543deadLL
489 root 1.69
490     void *g_slice_alloc (unsigned long size)
491     {
492     unsigned long *p = (unsigned long *) (g_slice_alloc)(size + sizeof (unsigned long));
493     *p++ = size ^ MAGIC;
494     //fprintf (stderr, "g_slice_alloc %ld %p\n", size, p);//D
495     return (void *)p;
496     }
497    
498     void *g_slice_alloc0 (unsigned long size)
499     {
500     return memset (g_slice_alloc (size), 0, size);
501     }
502    
503     void g_slice_free1 (unsigned long size, void *ptr)
504     {
505 root 1.74 //fprintf (stderr, "g_slice_free %ld %p\n", size, ptr);//D
506 root 1.69 if (expect_true (ptr))
507     {
508     unsigned long *p = (unsigned long *)ptr;
509     unsigned long s = *--p ^ MAGIC;
510    
511 root 1.71 if (size != (unsigned long)(*p ^ MAGIC))
512 root 1.74 {
513     LOG (logBacktrace | llevError, "slice free size (%lx) doesn't match alloc size (%lx)\n", size, s);
514     abort ();
515     }
516 root 1.69
517     *p = MAGIC;
518    
519     (g_slice_free1)(s + sizeof (unsigned long), p);
520     }
521     }
522    
523     #endif
524    
525     /******************************************************************************/
526    
527 root 1.11 void assign (char *dst, const char *src, int maxlen)
528     {
529     if (!src)
530     src = "";
531    
532     int len = strlen (src);
533    
534     if (len >= maxlen - 1)
535     {
536     if (maxlen <= 4)
537     {
538     memset (dst, '.', maxlen - 1);
539     dst [maxlen - 1] = 0;
540     }
541     else
542     {
543     memcpy (dst, src, maxlen - 4);
544     memcpy (dst + maxlen - 4, "...", 4);
545     }
546     }
547     else
548     memcpy (dst, src, len + 1);
549     }
550    
551 root 1.65 const char *
552 root 1.51 format (const char *format, ...)
553     {
554 root 1.65 static dynbuf_text buf;
555 root 1.51
556 root 1.65 buf.clear ();
557 root 1.51
558 root 1.65 va_list ap;
559     va_start (ap, format);
560     buf.vprintf (format, ap);
561     va_end (ap);
562    
563     return buf;
564 root 1.51 }
565    
566 root 1.23 tstamp now ()
567     {
568     struct timeval tv;
569    
570     gettimeofday (&tv, 0);
571     return tstamp (tv.tv_sec) + tstamp (tv.tv_usec) * tstamp (1e-6);
572     }
573 root 1.17
574 root 1.32 int
575     similar_direction (int a, int b)
576     {
577     if (!a || !b)
578     return 0;
579    
580     int diff = (b - a) & 7;
581     return diff <= 1 || diff >= 7;
582     }
583    
584 root 1.48 /* crc32 0xdebb20e3 table and supplementary functions. */
585     extern const uint32_t crc_32_tab[256] =
586     {
587     0x00000000UL, 0x77073096UL, 0xee0e612cUL, 0x990951baUL, 0x076dc419UL,
588     0x706af48fUL, 0xe963a535UL, 0x9e6495a3UL, 0x0edb8832UL, 0x79dcb8a4UL,
589     0xe0d5e91eUL, 0x97d2d988UL, 0x09b64c2bUL, 0x7eb17cbdUL, 0xe7b82d07UL,
590     0x90bf1d91UL, 0x1db71064UL, 0x6ab020f2UL, 0xf3b97148UL, 0x84be41deUL,
591     0x1adad47dUL, 0x6ddde4ebUL, 0xf4d4b551UL, 0x83d385c7UL, 0x136c9856UL,
592     0x646ba8c0UL, 0xfd62f97aUL, 0x8a65c9ecUL, 0x14015c4fUL, 0x63066cd9UL,
593     0xfa0f3d63UL, 0x8d080df5UL, 0x3b6e20c8UL, 0x4c69105eUL, 0xd56041e4UL,
594     0xa2677172UL, 0x3c03e4d1UL, 0x4b04d447UL, 0xd20d85fdUL, 0xa50ab56bUL,
595     0x35b5a8faUL, 0x42b2986cUL, 0xdbbbc9d6UL, 0xacbcf940UL, 0x32d86ce3UL,
596     0x45df5c75UL, 0xdcd60dcfUL, 0xabd13d59UL, 0x26d930acUL, 0x51de003aUL,
597     0xc8d75180UL, 0xbfd06116UL, 0x21b4f4b5UL, 0x56b3c423UL, 0xcfba9599UL,
598     0xb8bda50fUL, 0x2802b89eUL, 0x5f058808UL, 0xc60cd9b2UL, 0xb10be924UL,
599     0x2f6f7c87UL, 0x58684c11UL, 0xc1611dabUL, 0xb6662d3dUL, 0x76dc4190UL,
600     0x01db7106UL, 0x98d220bcUL, 0xefd5102aUL, 0x71b18589UL, 0x06b6b51fUL,
601     0x9fbfe4a5UL, 0xe8b8d433UL, 0x7807c9a2UL, 0x0f00f934UL, 0x9609a88eUL,
602     0xe10e9818UL, 0x7f6a0dbbUL, 0x086d3d2dUL, 0x91646c97UL, 0xe6635c01UL,
603     0x6b6b51f4UL, 0x1c6c6162UL, 0x856530d8UL, 0xf262004eUL, 0x6c0695edUL,
604     0x1b01a57bUL, 0x8208f4c1UL, 0xf50fc457UL, 0x65b0d9c6UL, 0x12b7e950UL,
605     0x8bbeb8eaUL, 0xfcb9887cUL, 0x62dd1ddfUL, 0x15da2d49UL, 0x8cd37cf3UL,
606     0xfbd44c65UL, 0x4db26158UL, 0x3ab551ceUL, 0xa3bc0074UL, 0xd4bb30e2UL,
607     0x4adfa541UL, 0x3dd895d7UL, 0xa4d1c46dUL, 0xd3d6f4fbUL, 0x4369e96aUL,
608     0x346ed9fcUL, 0xad678846UL, 0xda60b8d0UL, 0x44042d73UL, 0x33031de5UL,
609     0xaa0a4c5fUL, 0xdd0d7cc9UL, 0x5005713cUL, 0x270241aaUL, 0xbe0b1010UL,
610     0xc90c2086UL, 0x5768b525UL, 0x206f85b3UL, 0xb966d409UL, 0xce61e49fUL,
611     0x5edef90eUL, 0x29d9c998UL, 0xb0d09822UL, 0xc7d7a8b4UL, 0x59b33d17UL,
612     0x2eb40d81UL, 0xb7bd5c3bUL, 0xc0ba6cadUL, 0xedb88320UL, 0x9abfb3b6UL,
613     0x03b6e20cUL, 0x74b1d29aUL, 0xead54739UL, 0x9dd277afUL, 0x04db2615UL,
614     0x73dc1683UL, 0xe3630b12UL, 0x94643b84UL, 0x0d6d6a3eUL, 0x7a6a5aa8UL,
615     0xe40ecf0bUL, 0x9309ff9dUL, 0x0a00ae27UL, 0x7d079eb1UL, 0xf00f9344UL,
616     0x8708a3d2UL, 0x1e01f268UL, 0x6906c2feUL, 0xf762575dUL, 0x806567cbUL,
617     0x196c3671UL, 0x6e6b06e7UL, 0xfed41b76UL, 0x89d32be0UL, 0x10da7a5aUL,
618     0x67dd4accUL, 0xf9b9df6fUL, 0x8ebeeff9UL, 0x17b7be43UL, 0x60b08ed5UL,
619     0xd6d6a3e8UL, 0xa1d1937eUL, 0x38d8c2c4UL, 0x4fdff252UL, 0xd1bb67f1UL,
620     0xa6bc5767UL, 0x3fb506ddUL, 0x48b2364bUL, 0xd80d2bdaUL, 0xaf0a1b4cUL,
621     0x36034af6UL, 0x41047a60UL, 0xdf60efc3UL, 0xa867df55UL, 0x316e8eefUL,
622     0x4669be79UL, 0xcb61b38cUL, 0xbc66831aUL, 0x256fd2a0UL, 0x5268e236UL,
623     0xcc0c7795UL, 0xbb0b4703UL, 0x220216b9UL, 0x5505262fUL, 0xc5ba3bbeUL,
624     0xb2bd0b28UL, 0x2bb45a92UL, 0x5cb36a04UL, 0xc2d7ffa7UL, 0xb5d0cf31UL,
625     0x2cd99e8bUL, 0x5bdeae1dUL, 0x9b64c2b0UL, 0xec63f226UL, 0x756aa39cUL,
626     0x026d930aUL, 0x9c0906a9UL, 0xeb0e363fUL, 0x72076785UL, 0x05005713UL,
627     0x95bf4a82UL, 0xe2b87a14UL, 0x7bb12baeUL, 0x0cb61b38UL, 0x92d28e9bUL,
628     0xe5d5be0dUL, 0x7cdcefb7UL, 0x0bdbdf21UL, 0x86d3d2d4UL, 0xf1d4e242UL,
629     0x68ddb3f8UL, 0x1fda836eUL, 0x81be16cdUL, 0xf6b9265bUL, 0x6fb077e1UL,
630     0x18b74777UL, 0x88085ae6UL, 0xff0f6a70UL, 0x66063bcaUL, 0x11010b5cUL,
631     0x8f659effUL, 0xf862ae69UL, 0x616bffd3UL, 0x166ccf45UL, 0xa00ae278UL,
632     0xd70dd2eeUL, 0x4e048354UL, 0x3903b3c2UL, 0xa7672661UL, 0xd06016f7UL,
633     0x4969474dUL, 0x3e6e77dbUL, 0xaed16a4aUL, 0xd9d65adcUL, 0x40df0b66UL,
634     0x37d83bf0UL, 0xa9bcae53UL, 0xdebb9ec5UL, 0x47b2cf7fUL, 0x30b5ffe9UL,
635     0xbdbdf21cUL, 0xcabac28aUL, 0x53b39330UL, 0x24b4a3a6UL, 0xbad03605UL,
636     0xcdd70693UL, 0x54de5729UL, 0x23d967bfUL, 0xb3667a2eUL, 0xc4614ab8UL,
637     0x5d681b02UL, 0x2a6f2b94UL, 0xb40bbe37UL, 0xc30c8ea1UL, 0x5a05df1bUL,
638     0x2d02ef8dL
639     };
640    
641 root 1.73 void thread::start (void *(*start_routine)(void *), void *arg)
642     {
643 root 1.75 pthread_attr_t attr;
644    
645     pthread_attr_init (&attr);
646     pthread_attr_setdetachstate (&attr, PTHREAD_CREATE_DETACHED);
647     pthread_attr_setstacksize (&attr, PTHREAD_STACK_MIN < sizeof (long) * 4096
648     ? sizeof (long) * 4096 : PTHREAD_STACK_MIN);
649     #ifdef PTHREAD_SCOPE_PROCESS
650     pthread_attr_setscope (&attr, PTHREAD_SCOPE_PROCESS);
651     #endif
652    
653 root 1.73 sigset_t fullsigset, oldsigset;
654     sigfillset (&fullsigset);
655    
656     pthread_sigmask (SIG_SETMASK, &fullsigset, &oldsigset);
657    
658 root 1.75 if (pthread_create (&id, &attr, start_routine, arg))
659 root 1.73 cleanup ("unable to create a new thread");
660    
661     pthread_sigmask (SIG_SETMASK, &oldsigset, 0);
662     }
663 root 1.75