OSDN Git Service

* config/locale/c_locale_generic.cc: Check errno for ERANGE
[pf3gnuchains/gcc-fork.git] / libchill / rts.c
1 /* GNU CHILL compiler regression test file
2  Copyright (C) 1992, 1993 Free Software Foundation, Inc.
3  
4 This file is part of GNU CC.
5
6 GNU CC is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2, or (at your option)
9 any later version.
10
11 GNU CC 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
14 GNU General Public License for more details.
15
16 You should have received a copy of the GNU General Public License
17 along with GNU CC; see the file COPYING.  If not, write to
18 the Free Software Foundation, 59 Temple Place - Suite 330,
19 Boston, MA 02111-1307, USA.  */
20
21 /* As a special exception, if you link this library with other files,
22    some of which are compiled with GCC, to produce an executable,
23    this library does not by itself cause the resulting executable
24    to be covered by the GNU General Public License.
25    This exception does not however invalidate any other reasons why
26    the executable file might be covered by the GNU General Public License.  */
27
28 #include <stdio.h>
29 #include <string.h>
30 #include <stdlib.h>
31 #include <setjmp.h>
32 #include <signal.h>
33
34 #include "rts.h"
35
36
37 /* some allocation/reallocation functions */
38
39 static void *
40 xmalloc (size)
41      int size;
42 {
43   void *tmp = malloc (size);
44
45   if (!tmp)
46     {
47       fprintf (stderr, "Out of heap space.\n");
48       exit (1);
49     }
50   return (tmp);
51 }
52
53 static void *
54 xrealloc (ptr, size)
55      void *ptr;
56      int size;
57 {
58   void *tmp = realloc (ptr, size);
59
60   if (!tmp)
61     {
62       fprintf (stderr, "Out of heap space.\n");
63       exit (1);
64     }
65   return (tmp);
66 }
67
68 /* the necessary data */
69 #define MAX_NUMBER 100
70 typedef char UsedValues[MAX_NUMBER];
71
72 #define MAX_COPIES 100
73
74 #define MAX_PER_ITEM 20
75 typedef struct TASKINGSTRUCTLIST
76 {
77   struct TASKINGSTRUCTLIST *forward;
78   int    num;
79   TaskingStruct *data[MAX_PER_ITEM];
80   char copies[MAX_COPIES];
81   jmp_buf where;
82 } TaskingStructList;
83
84 static TaskingStructList *task_array[LAST_AND_UNUSED];
85 static UsedValues used_values[LAST_AND_UNUSED];
86
87 static short
88 get_next_free_number (vals)
89      UsedValues vals;
90 {
91   short  i;
92   for (i = 1; i < MAX_NUMBER; i++)
93     {
94       if (!vals[i])
95         {
96           vals[i] = 1;
97           return (i);
98         }
99     }
100   fprintf (stderr, "There are no more free numbers.\n");
101   exit (1);
102 }
103
104 /* function search for the next available copy number */
105 static short
106 get_next_copy_number (p)
107      TaskingStructList *p;
108 {
109   short i;
110
111   for (i = 0; i < MAX_COPIES; i++)
112     {
113       if (!p->copies[i])
114         {
115           p->copies[i] = 1;
116           return (i);
117         }
118     }
119   fprintf (stderr, "No more copies available for \"%s\".\n",
120            p->data[0]->name);
121   exit (1);
122 }
123
124 /* function registers a tasking entry from a module and assign
125    a value to the type */
126
127 void
128 __register_tasking (t)
129      TaskingStruct *t;
130 {
131   TaskingStructList *p;
132
133   /* check first if a value was provided and if it is in range */
134   if (t->value_defined && *t->value >= MAX_NUMBER)
135     {
136       fprintf (stderr, "Value %d out of range.\n", *t->value);
137       exit (1);
138     }
139
140   /* look for item defined */
141   p = task_array[t->type];
142   while (p)
143     {
144       if (!strcmp (p->data[0]->name, t->name))
145         /* have found it */
146         break;
147       p = p->forward;
148     }
149
150   if (!p)
151     {
152       TaskingStructList *wrk = (TaskingStructList *)&task_array[t->type];
153
154       /* this is a new one -- allocate space */
155       p = xmalloc (sizeof (TaskingStructList));
156       memset (p->copies, 0, sizeof (p->copies));
157       p->forward = 0;
158       p->num = 1;
159       p->data[0] = t;
160
161       /* queue it in */
162       while (wrk->forward)
163         wrk = wrk->forward;
164       wrk->forward = p;
165     }
166   else
167     {
168       if (p->num >= MAX_PER_ITEM)
169         {
170           fprintf (stderr, "Too many registrations of \"%s\".\n", t->name);
171           exit (1);
172         }
173       p->data[p->num++] = t;
174     }
175 }
176 \f
177 /* define all the entries for the runtime system. They will be
178    needed by chillrt0.o */
179
180 typedef char *(*fetch_names) ();
181 typedef int (*fetch_numbers) ();
182
183 static char tmp_for_fetch_name[100];
184
185 char *
186 __fetch_name (number)
187      int number;
188 {
189   TaskingStructList *p = task_array[Process];
190
191   while (p)
192     {
193       if (*(p->data[0]->value) == number)
194         return (p->data[0]->name);
195       p = p->forward;
196     }
197   sprintf (tmp_for_fetch_name, "%d", number);
198   return (tmp_for_fetch_name);
199 }
200 fetch_names     __RTS_FETCH_NAMES__ = __fetch_name;
201
202 static int 
203 __fetch_number (name)
204      char *name;
205 {
206   TaskingStructList *p = task_array[Process];
207
208   while (p)
209     {
210       if (!strcmp (p->data[0]->name, name))
211         return (*(p->data[0]->value));
212       p = p->forward;
213     }
214   return (-1);
215 }
216 fetch_numbers   __RTS_FETCH_NUMBERS__ = __fetch_number;
217
218
219 /* here we go to check all registered items */
220 static void
221  __rts_init ()
222 {
223   int i;
224   TaskingStructList *p;
225
226   for (i = Process; i <= Event; i++)
227     {
228       p = task_array[i];
229       while (p)
230         {
231           TaskingStruct *t = 0;
232           int j;
233           short val;
234
235           for (j = 0; j < p->num; j++)
236             {
237               if (p->data[j]->value_defined)
238                 {
239                   if (t)
240                     {
241                       if (*(t->value) != *(p->data[j]->value))
242                         {
243                           fprintf (stderr, "Different values (%d & %d) for \"%s\".",
244                                    *(t->value), *(p->data[j]->value), t->name);
245                           exit (1);
246                         }
247                     }
248                   else
249                     t = p->data[j];
250                 }
251             }
252
253           if (t)
254             {
255
256               val = *(t->value);
257
258               if (used_values[t->type][val])
259                 {
260                   fprintf (stderr, "Value %d for \"%s\" is already used.\n",
261                            val, t->name);
262                   exit (1);
263                 }
264               used_values[t->type][val] = 1;
265             }
266           else
267             {
268               /* we have to create a new value */
269               val = get_next_free_number (used_values[p->data[0]->type]);
270             }
271               
272           for (j = 0; j < p->num; j++)
273             {
274               p->data[j]->value_defined = 1;
275               *(p->data[j]->value) = val;
276             }
277
278           p = p->forward;
279         }
280     }
281 }
282 EntryPoint      __RTS_INIT__ = __rts_init;
283 \f
284 /* define the start process queue */
285 typedef struct STARTENTRY
286 {
287   struct STARTENTRY *forward;
288   INSTANCE whoami;
289   EntryPoint entry;
290   void *data;
291   int datalen;
292 } StartEntry;
293
294 static StartEntry *start_queue = 0;
295 static StartEntry *current_process = 0;
296
297 /* the jump buffer for the main loop */
298 static jmp_buf jump_buffer;
299 static int jump_buffer_initialized = 0;
300
301 /* look for entries in start_queue and start the process */
302 static void
303 __rts_main_loop ()
304 {
305   StartEntry *s;
306
307   while (1)
308     {
309       if (setjmp (jump_buffer) == 0)
310         {
311           jump_buffer_initialized = 1;
312           s = start_queue;
313           while (s)
314             {
315               current_process = s;
316               start_queue = s->forward;
317               
318               /* call the process */
319               (*s->entry) (s->data);
320               s = start_queue;
321             }
322           /* when queue empty we have finished */
323           return;
324         }
325       else
326         {
327           /* stop executed */
328           if (current_process->data)
329             free (current_process->data);
330           free (current_process);
331           current_process = 0;
332         }
333     }
334 }
335 EntryPoint      __RTS_MAIN_LOOP__ = __rts_main_loop;
336
337
338 void
339 __start_process (ptype, pcopy, arg_size, args, ins)
340      short ptype;
341      short pcopy;
342      int arg_size;
343      void *args;
344      INSTANCE *ins;
345 {
346   TaskingStructList *p = task_array[Process];
347   EntryPoint pc = 0;
348   int i;
349   short this_copy = pcopy;
350   StartEntry *s, *wrk;
351
352   /* search for the process */
353   while (p)
354     {
355       if (*(p->data[0]->value) == ptype)
356         break;
357       p = p->forward;
358     }
359   if (!p)
360     {
361       fprintf (stderr, "Cannot find a process with type %d.\n", ptype);
362       exit (1);
363     }
364   
365   /* search for the entry point */
366   for (i = 0; i < p->num; i++)
367     {
368       if (p->data[i]->entry)
369         {
370           pc = p->data[i]->entry;
371           break;
372         }
373     }
374   if (!pc)
375     {
376       fprintf (stderr, "Process \"%s\" doesn't have an entry point.\n",
377                p->data[0]->name);
378       exit (1);
379     }
380
381   /* check the copy */
382   if (pcopy >= MAX_COPIES)
383     {
384       fprintf (stderr, "Copy number (%d) out of range.\n", pcopy);
385       exit (1);
386     }
387   if (pcopy == -1)
388     {
389       /* search for a copy number */
390       this_copy = get_next_copy_number (p);
391     }
392   else
393     {
394       if (p->copies[pcopy])
395         {
396           /* FIXME: should be exception 'startfail' */
397           fprintf (stderr, "Copy number %d already in use for \"%s\".\n",
398                    pcopy, p->data[0]->name);
399           exit (1);
400         }
401       p->copies[this_copy = pcopy] = 1;
402     }
403
404   /* ready to build start_queue entry */
405   s = xmalloc (sizeof (StartEntry));
406   s->forward = 0;
407   s->whoami.pcopy = this_copy;
408   s->whoami.ptype = ptype;
409   s->entry = pc;
410   s->datalen = arg_size;
411   if (args)
412     {
413       s->data = xmalloc (arg_size);
414       memcpy (s->data, args, arg_size);
415     }
416   else
417     s->data = 0;
418
419   /* queue that stuff in */
420   wrk = (StartEntry *)&start_queue;
421   while (wrk->forward)
422     wrk = wrk->forward;
423   wrk->forward = s;
424
425   /* if we have a pointer to ins -- set it */
426   if (ins)
427     {
428       ins->ptype = ptype;
429       ins->pcopy = this_copy;
430     }
431 }
432 \f
433 void
434 __stop_process ()
435 {
436   if (!jump_buffer_initialized)
437     {
438       fprintf (stderr, "STOP called before START.\n");
439       exit (1);
440     }
441   longjmp (jump_buffer, 1);
442 }
443
444
445 /* function returns INSTANCE of current process */
446 INSTANCE
447 __whoami ()
448 {
449   INSTANCE whoami;
450   if (current_process)
451     whoami = current_process->whoami;
452   else
453     {
454       whoami.ptype = 0;
455       whoami.pcopy = 0;
456     }
457   return (whoami);
458 }
459
460 typedef struct
461 {
462   short *sc;
463   int    data_len;
464   void  *data;
465 } SignalDescr;
466
467 typedef struct SIGNALQUEUE
468 {
469   struct SIGNALQUEUE *forward;
470   short    sc;
471   int      data_len;
472   void    *data;
473   INSTANCE to;
474   INSTANCE from;
475 } SignalQueue;
476
477 /* define the signal queue */
478 static SignalQueue *msg_queue = 0;
479 \f
480 /* send a signal */
481 void
482 __send_signal (s, to, prio, with_len, with)
483      SignalDescr *s;
484      INSTANCE     to;
485      int          prio;
486      int          with_len;
487      void        *with;
488 {
489   SignalQueue *wrk = (SignalQueue *)&msg_queue;
490   SignalQueue *p;
491   TaskingStructList *t = task_array[Process];
492
493   /* search for process is defined and running */
494   while (t)
495     {
496       if (*(t->data[0]->value) == to.ptype)
497         break;
498       t = t->forward;
499     }
500   if (!t || !t->copies[to.pcopy])
501     {
502       fprintf (stderr, "Can't find instance [%d,%d].\n",
503                to.ptype, to.pcopy);
504       exit (1);
505     }
506
507   /* go to the end of the msg_queue */
508   while (wrk->forward)
509     wrk = wrk->forward;
510
511   p = xmalloc (sizeof (SignalQueue));
512   p->sc = *(s->sc);
513   if (p->data_len = s->data_len)
514     {
515       p->data = xmalloc (s->data_len);
516       memcpy (p->data, s->data, s->data_len);
517     }
518   else
519     p->data = 0;
520   p->to = to;
521   p->from = __whoami ();
522   p->forward = 0;
523   wrk->forward = p;
524 }
525 \f
526 void
527 start_signal_timeout (i, s, j)
528      int i;
529      SignalDescr *s;
530      int j;
531 {
532   __send_signal (s, __whoami (), 0, 0, 0);
533 }
534
535
536 /* receive a signal */
537 int
538 __wait_signal_timed (sig_got, nsigs, sigptr, datap,
539                      datalen, ins, else_branche,
540                      to, filename, lineno)
541      short    *sig_got;
542      int       nsigs;
543      short    *sigptr[];
544      void     *datap;
545      int       datalen;
546      INSTANCE *ins;
547      int       else_branche;
548      void     *to; 
549      char     *filename;
550      int       lineno; 
551 {
552   INSTANCE me = __whoami ();
553   SignalQueue *wrk, *p = msg_queue;
554   int i;
555   short sc;
556
557   /* search for a signal to `me' */
558   wrk = (SignalQueue *)&msg_queue;
559
560   while (p)
561     {
562       if (p->to.ptype == me.ptype
563           && p->to.pcopy == me.pcopy)
564         break;
565       wrk = p;
566       p = p->forward;
567     }
568
569   if (!p)
570     {
571       fprintf (stderr, "No signal for [%d,%d].\n",
572                me.ptype, me.pcopy);
573       exit (1);
574     }
575
576   /* queue the message out */
577   wrk->forward = p->forward;
578
579   /* now look for signal in list */
580   for (i = 0; i < nsigs; i++)
581     if (*(sigptr[i]) == p->sc)
582       break;
583
584   if (i >= nsigs && ! else_branche)
585     /* signal not in list and no ELSE in code */
586     __cause_exception ("signalfail", __FILE__, __LINE__);
587
588   if (i >= nsigs)
589     {
590       /* signal not in list */
591       sc = p->sc;
592       if (ins)
593         *ins = p->from;
594       if (p->data)
595         free (p->data);
596       free (p);
597       *sig_got = sc;
598       return (0);
599     }
600
601   /* we have found a signal in the list */
602   if (p->data_len)
603     {
604       if (datalen >= p->data_len
605           && datap)
606         memcpy (datap, p->data, p->data_len);
607       else
608         __cause_exception ("spacefail", __FILE__, __LINE__);
609     }
610
611   sc = p->sc;
612   if (ins)
613     *ins = p->from;
614   if (p->data)
615     free (p->data);
616   free (p);
617   *sig_got = sc;
618   return (0);
619 }
620 \f
621 /* wait a certain amount of seconds */
622 int
623 __sleep_till (abstime, reltime, fname, lineno)
624      time_t abstime;
625      int    reltime;
626      char  *fname;
627      int    lineno;
628 {
629   sleep (reltime);
630   return 0;
631 }
632 \f
633 /* set up an alarm */
634 static int timeout_flag = 0;
635
636 static void alarm_handler ()
637 {
638   timeout_flag = 1;
639 }
640
641 int *
642 __define_timeout (howlong, filename, lineno)
643      unsigned long howlong;  /* comes in millisecs */
644      char         *filename;
645      int           lineno;
646 {
647   unsigned int  prev_alarm_value;
648
649   signal (SIGALRM, alarm_handler);
650   prev_alarm_value = alarm ((unsigned int)(howlong / 1000));
651   return &timeout_flag;
652 }
653 \f
654 /* wait till timeout expires */
655 void
656 __wait_timeout (toid, filename, lineno)
657      volatile int    *toid;
658      char   *filename;
659      int     lineno;
660 {
661   while (! *toid) ;
662   *toid = 0;
663 }