1 /****************************************************************************** 2 3 # # #### #### # # ##### # # 4 ## ## # # # # # # # # # 5 # ## # #### # # # ##### ###### 6 # # # # ### # # # # ### # # 7 # # # # # # # # # # ### # # 8 # # #### #### ###### # ##### ### # # 9 10 ******************************************************************************/ 11 /* This file is part of MAPMAKER 3.0b, Copyright 1987-1992, Whitehead Institute 12 for Biomedical Research. All rights reserved. See READ.ME for license. */ 13 14 /*** Predefined Messages for sending. ***/ 15 #define RERUN 1 16 #define PUNT 2 17 #define QUIT 3 18 #define MATHERROR 4 19 #define NOMEMORY 5 20 #define ENDOFILE 6 21 #define ENDOINPUT 7 22 #define IOERROR 8 23 #define CANTOPEN 9 24 #define CRASH 10 25 #define INTERRUPT 11 26 #define SYSERROR 12 27 #define ABORT 13 28 #define SOFTABORT 14 29 #define BADEQN 15 30 #define CANTCLOSE 16 31 32 /* The first message number accessible to the user code is 20. */ 33 #define USER_MESSAGE(n) (20+n) 34 35 /* Message variables for the above */ 36 extern char *MATHERROR_type; /* allocated LINE long */ 37 extern real MATHERROR_arg1; 38 extern real MATHERROR_arg2; 39 extern int NOMEMORY_num_cells; 40 extern int NOMEMORY_cell_size; 41 extern char *CANTOPEN_path; /* allocated PATH_LENGTH long */ 42 extern char CANTOPEN_modechar; 43 extern char *IOERROR_errmsg; /* allocated LINE long */ 44 extern char *IOERROR_linecopy; /* set the ptr, ths is not allocated */ 45 extern char *IOERROR_filename; /* allocated PATH_LENGTH long */ 46 extern char IOERROR_modechar; 47 extern char *SYSERROR_errmsg; /* allocated LINE long */ 48 extern char *SOFTABORT_msgstr; /* a ptr, not allocated */ 49 extern char *BADEQN_errmsg; 50 extern int BADEQN_errpos; 51 52 /* user accessible stuff */ 53 extern int msg; /* the message # */ 54 extern char **mname; /* [msg] => name for this msg # */ 55 extern char *msgstr; /* use for msg vars - is MAXLINE long */ 56 57 void setmsg(); /* sets up a message */ 58 /* args int msg; char *msgname; void (*send_proc)(),(*message_proc)(); 59 message_proc may be NULL */ 60 61 void untrapped_msg(); /* Deal with unhandled messages - in syscode.c */ 62 void trapped_msg(); 63 void verbose_untrapped_msg(); 64 65 /* Possible send_procs - happen when we call send(MSG); args: message msg; */ 66 void sender(); 67 void trapper(); 68 void punter(); 69 void default_action(); /* DON'T USE */ 70 71 /* Possible message_procs in msglib.c. These produce an error message string 72 for untrapped messages. */ 73 void strmsg_default(); 74 void strmsg_NOMEMORY(); 75 void strmsg_MATHERROR(); 76 void strmsg_CANTOPEN(); 77 void strmsg_SYSERROR(); 78 79 /* Stuff for internal use only! - see msglib.c */ 80 extern jmp_buf stk[]; 81 extern int lvl; 82 extern bool exiting1; 83 extern void (*(maction[]))(), (*(mstrmsg[]))(); /* args: int msg; */ 84 #define MSGS 50 85 #define MSGNAMLEN 39 86 #define TRAP_DEPTH 100 87 #define MAX_IO_FAILURES 20 88 #define MAX_BAD_SIGNALS 20 89 void sigcounter(); /* count weird signals & CRASH if too many */ 90 int lvl_plus_plus(); /* return lvl for push onto stk[], chacking overflow */ 91 92 /*****************************************************************************/ 93 /* Trap Syntax: (Braces are USUALLY not required for single statements) 94 95 run { 96 blah; * Signal() statements can be in this 97 blah; * block or in procedures called from 98 blah; * it- break statements will work in here 99 blah; * return is ABSOLUTELY NOT ALLOWED in here! 100 } except { * 101 when FOO: * As this is really a switch statement, 102 blah; * be sure each clause ends with a break, 103 blah; * relay, or return instruction; 104 break; * 105 when BAR: 106 ... 107 relay_others; * This must exist for unhandled 108 } * signals to be passed on! 109 */ 110 111 112 /* These are the basic syntactic elements... 113 The while condition here is never true! (e.g. like while(FALSE)) We use the 114 while so that break statements will work inside run {...} blocks. */ 115 116 #define run if ((msg=setjmp(stk[lvl_plus_plus()]))==0) { do 117 #define except while(--lvl>10000); } else switch(msg) 118 119 #define send(num) (*(maction[num]))(num) 120 #define when case 121 #define relay sender(msg) 122 #define relay_others default: sender(msg) 123 124 125 /* An abbreviation to catch only one signal- all others are relayed. 126 Syntax: 127 128 run { 129 ... 130 } except_when(FOO) { * braces are not required for 1 statement here. 131 ... * break can be used in an except_when clause 132 } * to stop a loop surrounding the run... thing 133 */ 134 135 #define except_when(num) \ 136 while(--lvl>10000); } else if (msg!=num) { sender(msg); } else 137 138 /* Trapping() provides nicer syntax for the trivial do-nothing traps. 139 Syntax: 140 141 run { 142 ... 143 } trapping(FOO); * the same as except_when(FOO) {} 144 */ 145 146 #define trapping(m) except_when(m) 147 148 149 /* Another alternative to the except ... when notation shown above. 150 In this case, one block of code is used to handle all messages, although 151 this block may look at the msg variable to tell what happened. 152 Note that the break statement should work correctly in an 153 when_aborting { ... } block. 154 Syntax: 155 156 run { 157 ... 158 } when_aborting { 159 if (msg==FOO) { 160 ... 161 } else if (msg==BAR) { 162 ... 163 } else relay; * remember to add this if you don't 164 } * just want to fall out. 165 */ 166 167 #define when_aborting while(--lvl>10000); } else 168 #define on_error while(--lvl>10000); } else 169 170 171 /* Yet another way to do traps. On_exit is similar to the 172 when_aborting construct shown above, except that the on_exit clause is 173 always executed, whether there was a message or whether it was just 174 "fallen into". As with when_aborting, the variable msg will be set 175 within this code correctly (msg==0 if no msg). Note that the break 176 statement should also work correctly in an on_exit { ... } block. 177 178 For example, the following code will never leave a chunk of malloced space 179 around. If array() fails, NOMEMORY is sent to the caller, after an error 180 message is printed. This code behaves correctly, freeing all malloced 181 space, even if the first array() call succeeds and the second fails! 182 183 p=q=NULL; * This must be here as the pointers may not be initialized, 184 ... * which might cause us to try to unarray a bad pointer! 185 run { 186 array(p, ... ); 187 array(q, ... ); 188 ... 189 } on_exit { 190 unarray(p,...); 191 unarray(q,...); 192 relay_messages; 193 } 194 */ 195 196 #define on_exit \ 197 while(--lvl>10000); \ 198 } \ 199 for (exiting1=TRUE; exiting1; exiting1=FALSE) 200 201 #define relay_messages sender(msg) /* nicer syntax than relay for this */ 202 203 /* We use stack_check() to check to see if the run stack is where it 204 was last time this was called with the given variable (an int). Use 205 init_stack_check() to set it sometime before calling stack check(). 206 Remember to call stack_check() from some toplevel loop which should 207 not be building up run...except calls. If stack_check() fails, the 208 program should be aborted! */ 209 210 bool stack_check(); /* args: int *var; return TRUE if all is OK */ 211 void init_stack_check(); /* args: int *var; */ 212 213 214 /******************** Support for Unix style signals ********************/ 215 216 /* Signal trap functions for signal_trap_init (which is in syscode.c) */ 217 SIGHANDLE handle_quit(); 218 SIGHANDLE handle_matherror(); 219 SIGHANDLE handle_weird_signal(); 220 SIGHANDLE handle_interrupt(); 221 SIGHANDLE handle_buserror(); 222 223 void signal_trap_init(); /* no args; in syscode.c */ 224 void msg_init(); /* no args; in syscode.c */ 225 226 227 /***** THE FOLLOWING IS AS YET UNUSED, AND MAYBE BEST LEFT THAT WAY *****/ 228 229 /* After any run...except... thing, msg will be set to either 0 or a 230 valid message number. Therefore, we can use it as a state variable to 231 keep track of whether we aborted or fell through to after the except { } 232 clause.. However use this with extreme care (eg: only use it in a 233 function AFTER executing a run...except... thing). */ 234 235 #define relay_trapped_msg sender(msg) 236 237 extern bool in_tty_gets; 238 extern bool hit_interrupt; 239 240 241 242 243 244