home *** CD-ROM | disk | FTP | other *** search
/ Turbo Toolbox / Turbo_Toolbox.iso / 1989 / 07 / hitech / coproc.c next >
Encoding:
C/C++ Source or Header  |  1989-04-24  |  6.0 KB  |  201 lines

  1. /*********************************************************/
  2. /*                       COPROC.C                        */
  3. /*              Coroutinenmodul für Turbo C              */
  4. /*          (C) 1989  Guido Goldstein & TOOLBOX          */
  5. /*********************************************************/
  6.  
  7. #include <setjmp.h> /* Prototypen für nicht lokales goto */
  8. #include <alloc.h>   /* Speicherverwaltung */
  9. #include <pointer.h> /* Makros für Arbeit mit Zeigern */
  10.  
  11. /* Struktur für die Coprozess-Verwaltung */
  12. typedef struct {
  13.   int       from ;    /* Caller der Routine */
  14.   jmp_buf   buffer ;  /* Buffer für longjmp aus setjmp.h */
  15.   char      init   ;  /* Flag ob schon  aktiv gewesen */
  16.   void far  (*fnc)(); /* Adresse der Funktion    */
  17.   char far  *stack ;  /* Zeiger auf den Stack */
  18.   unsigned  st_size ; /* Größe des Stacks (max. 64K) */
  19.                } COPROCESS ;
  20.  
  21. #define MAXCOPROC 62       /* Max. Anzahl an Coroutinen */
  22. #define MAINP (MAXCOPROC+1)  /* Handle für das
  23.                               Hauptprogramm (main) */
  24.  
  25. COPROCESS _coproc[MAXCOPROC+2] ;
  26.  
  27. int       HERE ; /* Aktueller Coprocess */
  28.  
  29. /* Sprung zur angegebenen Coroutine */
  30. #define transfer(to) if (!setjmp(_coproc[HERE].buffer)) \
  31.                          callcoproc(to);
  32.  
  33. /* Vereinfachter Rücksprung zum Caller */
  34. #define coreturn()   if (!setjmp(_coproc[HERE].buffer)) \
  35.                          callcoproc(_coproc[HERE].from);
  36.  
  37. /* Coprocess mit Nummer n aufrufen */
  38. /* Evtl. den Stack bereitstellen und initialisieren */
  39. void far callcoproc (int n)
  40. {
  41.   if (n < MAINP && ((long)_coproc[n].fnc != 0L)) {
  42.     /* Wenn gültige Prozess-Nr., den Process aufrufen */
  43.     _coproc[n].from = HERE ;
  44.     HERE = n ;
  45.     if (_coproc[n].init)
  46.       /* Process lief schon, weitermachen */
  47.       longjmp (_coproc[n].buffer,1);
  48.     else {
  49.       /* Neustart, Prozess erst initialisieren */
  50.       COPROCESS *cp ;  /* Zeiger statt Index */
  51.       cp = &_coproc[n] ;
  52.       if ((long)cp->stack == 0L) {
  53.         /* Wenn nötig, neuen Stack bereitstellen */
  54.         cp->stack = farmalloc(cp->st_size);
  55.         if ((long)cp->stack == 0L) /* Speicherfehler */
  56.           return ;
  57.         } /* end if */
  58.       /* Initialisierungsflag setzen */
  59.       cp->init = 1 ;
  60.       /* Sprungpuffer einstellen */
  61.       /* Zuerst die Adresse der Funktion
  62.          (Coprozess) in den Puffer */
  63.       cp->buffer->j_cs = FP_SEG(cp->fnc);
  64.       cp->buffer->j_ip = FP_OFF(cp->fnc);
  65.       /* Stackbereich in den Puffer */
  66.       cp->buffer->j_ss = FP_SEG(cp->stack);
  67.       /* Stackpointer auf Ende des Stackbereichs setzen */
  68.       cp->buffer->j_sp = FP_OFF(cp->stack)+cp->st_size;
  69.       /* Datensegment festlegen  - siehe Text -  */
  70.       cp->buffer->j_ds = _DS ;
  71.       /* Coprocess starten */
  72.       longjmp (cp->buffer,1);
  73.       } /* end else */
  74.     } /* end if */
  75.   else {
  76.     if (n == MAINP) {
  77.     /* Zurück in die aurufende Routine */
  78.       _coproc[MAINP].from = HERE ;
  79.       n = HERE = MAINP ;
  80.       longjmp (_coproc[n].buffer,1);
  81.       } /* end if */
  82.     } /* end else */
  83. } /* end of callcoproc */
  84.  
  85. /* Neue Coroutine aufnehmen, Handle zurückgeben */
  86. int far newcoproc (void far (*f)(), unsigned int st_size)
  87. {
  88.   int i ;
  89.  
  90.   /* Freien Puffer suchen */
  91.   for (i = 0;
  92.       (i < MAXCOPROC) && ((long)_coproc[i].fnc != 0L) ;
  93.        i++) ;
  94.   if (i < MAXCOPROC) {
  95.     /* Wenn gefunden, initialisieren */
  96.     _coproc[i].fnc = f ;
  97.     if ((long)_coproc[i].stack != 0L) {
  98.       /* Falls Stack noch belegt, freigeben */
  99.       farfree (_coproc[i].stack);
  100.       _coproc[i].st_size = 0 ;
  101.       _coproc[i].buffer->j_ss = _SS ;
  102.       _coproc[i].buffer->j_sp = _SP ;
  103.       } /* end if */
  104.     _coproc[i].stack = 0L ;
  105.     _coproc[i].st_size = st_size ;
  106.     } /* end if */
  107.   else  /* Kein freier Puffer */
  108.     return (-1); /* Fehler */
  109.   return (i);
  110. } /* end of newcoproc */
  111.  
  112. /* Freien Stackspeicher der Coroutine zurückgeben */
  113. unsigned far costackfree (void)
  114. {
  115.   char huge *s1 ;
  116.   char huge *s2 ;
  117.  
  118.   s1 = (char huge *) _coproc[HERE].stack ;
  119.   s2 = (char huge *) MK_FP (_SS,_SP);
  120.   return ((unsigned)((long)s2-(long)s1));
  121. } /* end of costackfree */
  122.  
  123. /* Coroutine mit Nummer proc aus Puffer löschen */
  124. int far remcoproc (int proc)
  125. {
  126.   if (proc < MAINP) {
  127.     /* Wenn gültiger Processhandle, Process löschen */
  128.     COPROCESS *cp ;
  129.     cp = &_coproc[proc] ;
  130.     cp->fnc = 0L ;
  131.     cp->init = 0 ;
  132.     if ((long)cp->stack != 0L) {
  133.       /* Wenn nötig, Stack freigeben */
  134.       farfree (cp->stack);
  135.       cp->stack = 0L ;
  136.       cp->st_size = 0 ;
  137.       cp->buffer->j_ss = _SS ;
  138.       cp->buffer->j_sp = _SP ;
  139.       } /* end if */
  140.     return (proc);
  141.     } /* end if */
  142.   return (-1);
  143. } /* end of remcoproc */
  144.  
  145. /* Bestehenden Handle mit neuer Routine belegen */
  146. /* !!!   Stack bleibt gleich !!! */
  147. int far changecoproc (int p, void far (*f)())
  148. {
  149.   if (p < MAINP) {
  150.     _coproc[p].init = 0 ;
  151.     _coproc[p].fnc = f ;
  152.     return (p);
  153.     }
  154.   return (-1);
  155. } /* end of changecoproc */
  156.  
  157. /* Coprocess-Puffer initialisieren */
  158. void far initcoproc (void)
  159. {
  160.   int i ;
  161.  
  162.   for (i = 0; i < (MAXCOPROC+1); i++) {
  163.     _coproc[i].init = 0 ;
  164.     _coproc[i].fnc  = 0L ;
  165.     _coproc[i].stack = 0L ;
  166.     _coproc[i].st_size = 0 ;
  167.     }
  168.   _coproc[MAINP].init = 1 ;
  169.   _coproc[MAINP].from = -1 ;
  170.   HERE = MAINP ;
  171. } /* end of initcoproc */
  172.  
  173. /* Coprocess richtig beenden */
  174. void far exitcoproc (void)
  175. {
  176.   COPROCESS *cp ;
  177.  
  178.   cp = &_coproc[HERE] ;
  179.   if (cp->from >= 0 && cp->from < MAINP) {
  180.     /* Wenn möglich, zurück zum Caller */
  181.     HERE = cp->from ;
  182.     /* Routine löschen */
  183.     cp->fnc = 0L ;
  184.     cp->init = 0 ;
  185.     cp = &_coproc[HERE] ;
  186.     /* Sprung zum Caller */
  187.     if ((long)cp->fnc != 0L)
  188.       longjmp (cp->buffer,1);
  189.     else
  190.       /* Oder in das Hauptprogramm */
  191.       longjmp (_coproc[MAINP].buffer,1);
  192.     } /* end if */
  193.   else
  194.     /* Zurück ins Hauptprogramm */
  195.     if (cp->from < 0 || cp->from >= MAINP) {
  196.       cp->fnc = 0L ;
  197.       HERE = MAINP ;
  198.       longjmp (_coproc[MAINP].buffer,1);
  199.       } /* end if */
  200. } /* end of exitcoproc */
  201.