home *** CD-ROM | disk | FTP | other *** search
/ Total Destruction / Total_Destruction.iso / addons / Lccwin32.exe / Lccwin32 / lccpub / src / Seh.c < prev    next >
Encoding:
C/C++ Source or Header  |  1997-11-11  |  6.4 KB  |  255 lines

  1. /* seh.c: Structured exception handling in the compiler */
  2. #include "c.h"
  3. extern int getTvalValue(void);
  4. extern int getLevel(void);
  5.  
  6. int hasExceptions=0;
  7. typedef struct tagExceptionInfo {
  8.     struct tagExceptionInfo *Next;
  9.     struct tagExceptionInfo *Previous;
  10.     int l1;
  11.     int l2;
  12.     int l3;
  13.     int value;
  14.     int Flags;
  15. } ExceptionInfo;
  16.  
  17. #define FINISHED 1
  18.  
  19. static ExceptionInfo *pCurrentException=NULL;
  20. static ExceptionInfo *rootException=NULL;
  21. static int StaticDataEmitted = 0;
  22. /* Add another exception to the exception stack */
  23. ExceptionInfo *PushException(void)
  24. {
  25.     ExceptionInfo *result;
  26.  
  27.     if (rootException == NULL)    {
  28.         rootException =  (ExceptionInfo *)allocate(sizeof(ExceptionInfo),FUNC);
  29.         result = rootException;
  30.         memset(result,0,sizeof(ExceptionInfo));
  31.     }
  32.     else {
  33.         /* search the last element */
  34.         result = rootException;
  35.         while (result->Next) {
  36.             result = result->Next;
  37.         }
  38.         result->Next = (ExceptionInfo *)allocate(sizeof(ExceptionInfo),FUNC);
  39.         memset(result->Next,0,sizeof(ExceptionInfo));
  40.         result->Next->Previous = result;
  41.         result = result->Next;
  42.     }
  43.     return(result);
  44. }
  45.  
  46. /*
  47.     No 'free' is done, since all the data is allocated in the FUNC heap
  48.     that will be freed at the end of the function.
  49. */
  50. void PopException(void)
  51. {
  52.     if (pCurrentException->Previous) {
  53.         pCurrentException = pCurrentException->Previous;
  54.         pCurrentException->Next = NULL;
  55.     }
  56.     else {
  57.         rootException = NULL;
  58.         pCurrentException = NULL;
  59.     }
  60. }
  61.  
  62. /*
  63.     Utility function to add an assembler instruction to the code list.
  64. */
  65. static void AddAsm(char *str)
  66. {
  67.     char *s;
  68.  
  69.     s = stringn(str,strlen(str));
  70.     walk(0, 0, 0);
  71.     code(Start);    /* prevent unreachable code message */
  72.     code(Asm);
  73.     codelist->u.acode.code = s;
  74.     codelist->u.acode.argv = NULL;
  75. }
  76.  
  77. int doTry(void)
  78. {
  79.     char tmpnom[25],tmpbuf[256];
  80.     int l1,l2,l3;
  81.     Symbol sl;
  82.  
  83.     /* 1. Push the exceptions stack by one */
  84.     pCurrentException = PushException();
  85.     /* Announce to the runtime that the static data is active
  86.        within this block. Exceptions are enabled */
  87.     AddAsm("\tmovl\t$0x0,-4(%ebp)");
  88.     /* Update this global variable used in a few parts of lcc */
  89.     hasExceptions++;
  90.     /* Generate 3 labels:
  91.        The first (label 1) marks the beginning of the first part
  92.        of code that will be called to determine if the handler
  93.        handles the exception or not.
  94.        The second label will announce the start of the exception
  95.        handler.
  96.        The third announces the continuation of the normal code
  97.        section
  98.     */
  99.     l1 = genlabel(1);
  100.     sl = findlabel(l1);
  101.     sl->ref = 1.0;
  102.     sl->firstuse = sl->lastuse = StatementCount;
  103.     l2 = genlabel(1);
  104.     sl = findlabel(l2);
  105.     sl->ref = 1.0;
  106.     sl->firstuse = sl->lastuse = StatementCount;
  107.     l3 = genlabel(1);
  108.     sl = findlabel(l3);
  109.     sl->ref = 1.0;
  110.     sl->firstuse = sl->lastuse = StatementCount;
  111.     pCurrentException->l1 = l1;
  112.     pCurrentException->l2 = l2;
  113.     pCurrentException->l3 = l3;
  114.     /* The static data needed here should be emitted only once
  115.        per compiled file
  116.     */
  117.     if (StaticDataEmitted == 0) {
  118.         AddAsm("\t.data");
  119.         sprintf(tmpbuf,"_$ExcepData:",tmpnom);
  120.         AddAsm(tmpbuf);
  121.         AddAsm("\t.long\t0xffffffff");
  122.         sprintf(tmpbuf,"\t.long\t_$%d",l1);
  123.         AddAsm(tmpbuf);
  124.         sprintf(tmpbuf,"\t.long\t_$%d",l2);
  125.         AddAsm(tmpbuf);
  126.         AddAsm("\t.text");
  127.         StaticDataEmitted = 1;
  128.     }
  129.     /* If we are in a nested exception block, the static data
  130.        should point to the two labels that contain the two blocks
  131.        of code to be called by the runtime
  132.     */
  133.     if (pCurrentException != rootException) {
  134.         AddAsm("\tmovl\t$_$ExcepData,%eax");
  135.         sprintf(tmpbuf,"\tmovl\t$_$%d,4(%%eax)",l1);
  136.         AddAsm(tmpbuf);
  137.         sprintf(tmpbuf,"\tmovl\t$_$%d,8(%%eax)",l2);
  138.         AddAsm(tmpbuf);
  139.     }
  140.     return(1);
  141. }
  142.  
  143. static void RestorePreviousException(void)
  144. {
  145.     char tmpbuf[256];
  146.  
  147.     /*
  148.         To avoid traps in the trap handlers, the runtime stores
  149.         a continuation address at -4(%ebp). If we arrive here,
  150.         everything is O.K. We have to restore then the zero at
  151.         -4(%ebp) to go on normally
  152.     */
  153.     AddAsm("\tmovl\t$0x0,-4(%ebp)");
  154.  
  155.     AddAsm("\tmovl\t$_$ExcepData,%eax");
  156.     sprintf(tmpbuf,"\tmovl\t$_$%d,4(%%eax)",pCurrentException->Previous->l1);
  157.     AddAsm(tmpbuf);
  158.     sprintf(tmpbuf,"\tmovl\t$_$%d,8(%%eax)",pCurrentException->Previous->l2);
  159.     AddAsm(tmpbuf);        
  160. }
  161.  
  162. static void EmitFilterCode(void)
  163. {
  164.     char tmpbuf[256];
  165.  
  166.     sprintf(tmpbuf,"_$%d:",pCurrentException->l1);
  167.     AddAsm(tmpbuf);
  168.     sprintf(tmpbuf,"\tmovl\t$%d,%%eax",pCurrentException->value);
  169.     AddAsm(tmpbuf);
  170.     AddAsm("\tret");
  171. }
  172.  
  173. int FinishTryBlock(void)
  174. {
  175.     char tmpbuf[256];
  176.  
  177.     if (pCurrentException->Flags & FINISHED) return(0);
  178.     if (pCurrentException == rootException) {
  179.         /* no exceptions are now active. Announce it to the
  180.            runtime
  181.         */
  182.         AddAsm("\tmovl\t$-1,-4(%ebp)");
  183.     }
  184.     else {
  185.         RestorePreviousException();
  186.     }
  187.     /* emit a jump to the end of the exception stuff */
  188.     sprintf(tmpbuf,"\tjmp\t_$%d",pCurrentException->l3);
  189.     AddAsm(tmpbuf);
  190.     /* Avoid emitting this code again */
  191.     pCurrentException->Flags |= FINISHED;
  192.     return(1);
  193. }
  194.  
  195. int doExcept(void)
  196. {
  197.     char tmpbuf[20];
  198.  
  199.     /* No error treatment yet. Any syntax error leaves the parser
  200.        in a mess...
  201.      */
  202.     t = gettok();
  203.     if (t != '(') {
  204.         error("Incorrect __except syntax\n");
  205.         return(0);
  206.     }
  207.     t = gettok();
  208.     if (t != ICON) {
  209.         error("Incorrect __except expression!");
  210.         return(0);
  211.     }
  212.     /* This should be actually an evaluation of an integer expression */
  213.     pCurrentException->value = getTvalValue();
  214.     t = gettok();
  215.     if (t != ')') {
  216.         error("missing ')' in __except expression");
  217.         return(0);
  218.     }
  219.     FinishTryBlock();
  220.     EmitFilterCode();
  221.     /* Emit the label that marks the beginning of the exception handler
  222.        code
  223.     */
  224.     sprintf(tmpbuf,"_$%d:",pCurrentException->l2);
  225.     AddAsm(tmpbuf);
  226.     /* Emit code to restore the stack  when the exception 
  227.        handler is called
  228.     */
  229.     AddAsm("\tmovl\t-24(%ebp),%esp");
  230.     /* Parse the exception handler code */
  231.     t = gettok(); /* swallow the '{' */
  232.     compound(0,NULL,getLevel());
  233.     if (pCurrentException == rootException) {
  234.         /*
  235.             We are at the end of the top level exception block.
  236.             Announce to the runtime there is no exception handler active
  237.         */
  238.         AddAsm("\tmovl\t$-1,-4(%ebp)");
  239.     }
  240.     else {
  241.         RestorePreviousException();
  242.     }
  243.     /* Continuation of the normal code sequence */
  244.     sprintf(tmpbuf,"_$%d:",pCurrentException->l3);
  245.     AddAsm(tmpbuf);
  246.     /* Clean up the exception stack, popping one level */
  247.     PopException();
  248.     return(1);
  249. }
  250.  
  251. void ResetExceptions(void)
  252. {
  253.     rootException = NULL;
  254. }
  255.