(root)/
gcc-13.2.0/
gcc/
testsuite/
gm2/
iso/
run/
pass/
except.c
       1  /*
       2   * Copyright (C) 2008 Free Software Foundation, Inc.
       3   * This file is part of GNU Modula-2.
       4   *  
       5   * GNU Modula-2 is free software; you can redistribute it and/or modify it under
       6   * the terms of the GNU General Public License as published by the Free
       7   * Software Foundation; either version 2, or (at your option) any later
       8   * version.
       9   * 
      10   * GNU Modula-2 is distributed in the hope that it will be useful, but WITHOUT ANY
      11   * WARRANTY; without even the implied warranty of MERCHANTABILITY or
      12   * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
      13   * for more details.
      14   * 
      15   * You should have received a copy of the GNU General Public License along
      16   * with gm2; see the file COPYING.  If not, write to the Free Software
      17   * Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
      18   */
      19  
      20  #include <setjmp.h>
      21  #include <malloc.h>
      22  #include <stdio.h>
      23  
      24  typedef enum jmpstatus {
      25    jmp_normal,
      26    jmp_retry,
      27    jmp_exception,
      28  } jmp_status;
      29  
      30  struct setjmp_stack {
      31    jmp_buf  env;
      32    struct setjmp_stack *next;
      33  } *head = NULL;
      34  
      35  void pushsetjmp (void)
      36  {
      37    struct setjmp_stack *p = (struct setjmp_stack *) malloc (sizeof (struct setjmp_stack));
      38  
      39    p->next = head;
      40    head = p;
      41  }
      42  
      43  void exception (void)
      44  {
      45    printf("invoking exception handler\n");
      46    longjmp (head->env, jmp_exception);
      47  }
      48  
      49  void retry (void)
      50  {
      51    printf("retry\n");
      52    longjmp (head->env, jmp_retry);
      53  }
      54  
      55  void popsetjmp (void)
      56  {
      57    struct setjmp_stack *p = head;
      58  
      59    head = head->next;
      60    free (p);
      61  }
      62  
      63  
      64  static int *ip = NULL;
      65  
      66  void fly (void)
      67  {
      68    printf("fly main body\n");
      69    if (ip == NULL) {
      70      printf("ip == NULL\n");
      71      exception();
      72    }
      73    if ((*ip) == 0) {
      74      printf("*ip == 0\n");
      75      exception();
      76    }
      77    if ((4 / (*ip)) == 4)
      78      printf("yes it worked\n");
      79    else
      80      printf("no it failed\n");
      81  }
      82  
      83  /*
      84   *   a GNU C version of the Modula-2 example given in the ISO standard.
      85   *   This is written to prove that the underlying runtime system
      86   *   will work with the C interpretation.  Thus gm2 will produce
      87   *   trees which follow the "template" setjmp/longjmp schema below
      88   *   when compiling EXCEPT/TRY statements.
      89   */
      90  
      91  void tryFlying (void)
      92  {
      93    void tryFlying_m2_exception () {
      94      printf("inside tryFlying exception routine\n");
      95      if ((ip != NULL) && ((*ip) == 0)) {
      96        (*ip) = 1;
      97        retry();
      98      }
      99    }
     100  
     101    int t;
     102  
     103    pushsetjmp ();
     104    do {
     105      t = setjmp (head->env);
     106    } while (t == jmp_retry);
     107  
     108    if (t == jmp_exception) {
     109      /* exception called */
     110      tryFlying_m2_exception ();
     111      /* exception has not been handled, invoke previous handler */
     112      printf("exception not handled here\n");
     113      popsetjmp();
     114      exception();
     115    }
     116  
     117    printf("tryFlying main body\n");  
     118    fly();
     119    popsetjmp();
     120  }
     121  
     122  
     123  void keepFlying (void)
     124  {
     125    void keepFlying_m2_exception () {
     126      printf("inside keepFlying exception routine\n");
     127      if (ip == NULL) {
     128        ip = (int *)malloc (sizeof (int));
     129        *ip = 0;
     130        retry();
     131      }
     132    }
     133    int t;
     134  
     135    pushsetjmp ();
     136    do {
     137      t = setjmp (head->env);
     138    } while (t == jmp_retry);
     139    
     140    if (t == jmp_exception) {
     141      /* exception called */
     142      keepFlying_m2_exception ();
     143      /* exception has not been handled, invoke previous handler */
     144      popsetjmp();
     145      exception();
     146    }
     147    printf("keepFlying main body\n");
     148    tryFlying();
     149    popsetjmp();
     150  }
     151  
     152  
     153  main ()
     154  {
     155    keepFlying();
     156    printf("all done\n");
     157  }