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