diff options
Diffstat (limited to 'libraries/irrlicht-1.8/source/Irrlicht/libpng/contrib/gregbook/readpng2.c')
-rw-r--r-- | libraries/irrlicht-1.8/source/Irrlicht/libpng/contrib/gregbook/readpng2.c | 511 |
1 files changed, 511 insertions, 0 deletions
diff --git a/libraries/irrlicht-1.8/source/Irrlicht/libpng/contrib/gregbook/readpng2.c b/libraries/irrlicht-1.8/source/Irrlicht/libpng/contrib/gregbook/readpng2.c new file mode 100644 index 0000000..3bbd2ec --- /dev/null +++ b/libraries/irrlicht-1.8/source/Irrlicht/libpng/contrib/gregbook/readpng2.c | |||
@@ -0,0 +1,511 @@ | |||
1 | /*--------------------------------------------------------------------------- | ||
2 | |||
3 | rpng2 - progressive-model PNG display program readpng2.c | ||
4 | |||
5 | --------------------------------------------------------------------------- | ||
6 | |||
7 | Copyright (c) 1998-2007 Greg Roelofs. All rights reserved. | ||
8 | |||
9 | This software is provided "as is," without warranty of any kind, | ||
10 | express or implied. In no event shall the author or contributors | ||
11 | be held liable for any damages arising in any way from the use of | ||
12 | this software. | ||
13 | |||
14 | The contents of this file are DUAL-LICENSED. You may modify and/or | ||
15 | redistribute this software according to the terms of one of the | ||
16 | following two licenses (at your option): | ||
17 | |||
18 | |||
19 | LICENSE 1 ("BSD-like with advertising clause"): | ||
20 | |||
21 | Permission is granted to anyone to use this software for any purpose, | ||
22 | including commercial applications, and to alter it and redistribute | ||
23 | it freely, subject to the following restrictions: | ||
24 | |||
25 | 1. Redistributions of source code must retain the above copyright | ||
26 | notice, disclaimer, and this list of conditions. | ||
27 | 2. Redistributions in binary form must reproduce the above copyright | ||
28 | notice, disclaimer, and this list of conditions in the documenta- | ||
29 | tion and/or other materials provided with the distribution. | ||
30 | 3. All advertising materials mentioning features or use of this | ||
31 | software must display the following acknowledgment: | ||
32 | |||
33 | This product includes software developed by Greg Roelofs | ||
34 | and contributors for the book, "PNG: The Definitive Guide," | ||
35 | published by O'Reilly and Associates. | ||
36 | |||
37 | |||
38 | LICENSE 2 (GNU GPL v2 or later): | ||
39 | |||
40 | This program is free software; you can redistribute it and/or modify | ||
41 | it under the terms of the GNU General Public License as published by | ||
42 | the Free Software Foundation; either version 2 of the License, or | ||
43 | (at your option) any later version. | ||
44 | |||
45 | This program is distributed in the hope that it will be useful, | ||
46 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
47 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
48 | GNU General Public License for more details. | ||
49 | |||
50 | You should have received a copy of the GNU General Public License | ||
51 | along with this program; if not, write to the Free Software Foundation, | ||
52 | Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
53 | |||
54 | ---------------------------------------------------------------------------*/ | ||
55 | |||
56 | |||
57 | #include <stdlib.h> /* for exit() prototype */ | ||
58 | #include <setjmp.h> | ||
59 | |||
60 | #include <zlib.h> | ||
61 | #include "png.h" /* libpng header from the local directory */ | ||
62 | #include "readpng2.h" /* typedefs, common macros, public prototypes */ | ||
63 | |||
64 | |||
65 | /* local prototypes */ | ||
66 | |||
67 | static void readpng2_info_callback(png_structp png_ptr, png_infop info_ptr); | ||
68 | static void readpng2_row_callback(png_structp png_ptr, png_bytep new_row, | ||
69 | png_uint_32 row_num, int pass); | ||
70 | static void readpng2_end_callback(png_structp png_ptr, png_infop info_ptr); | ||
71 | static void readpng2_error_handler(png_structp png_ptr, png_const_charp msg); | ||
72 | |||
73 | |||
74 | |||
75 | |||
76 | void readpng2_version_info(void) | ||
77 | { | ||
78 | fprintf(stderr, " Compiled with libpng %s; using libpng %s\n", | ||
79 | PNG_LIBPNG_VER_STRING, png_libpng_ver); | ||
80 | |||
81 | fprintf(stderr, " and with zlib %s; using zlib %s.\n", | ||
82 | ZLIB_VERSION, zlib_version); | ||
83 | } | ||
84 | |||
85 | |||
86 | |||
87 | |||
88 | int readpng2_check_sig(uch *sig, int num) | ||
89 | { | ||
90 | return !png_sig_cmp(sig, 0, num); | ||
91 | } | ||
92 | |||
93 | |||
94 | |||
95 | |||
96 | /* returns 0 for success, 2 for libpng problem, 4 for out of memory */ | ||
97 | |||
98 | int readpng2_init(mainprog_info *mainprog_ptr) | ||
99 | { | ||
100 | png_structp png_ptr; /* note: temporary variables! */ | ||
101 | png_infop info_ptr; | ||
102 | |||
103 | |||
104 | /* could also replace libpng warning-handler (final NULL), but no need: */ | ||
105 | |||
106 | png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, mainprog_ptr, | ||
107 | readpng2_error_handler, NULL); | ||
108 | if (!png_ptr) | ||
109 | return 4; /* out of memory */ | ||
110 | |||
111 | info_ptr = png_create_info_struct(png_ptr); | ||
112 | if (!info_ptr) { | ||
113 | png_destroy_read_struct(&png_ptr, NULL, NULL); | ||
114 | return 4; /* out of memory */ | ||
115 | } | ||
116 | |||
117 | |||
118 | /* we could create a second info struct here (end_info), but it's only | ||
119 | * useful if we want to keep pre- and post-IDAT chunk info separated | ||
120 | * (mainly for PNG-aware image editors and converters) */ | ||
121 | |||
122 | |||
123 | /* setjmp() must be called in every function that calls a PNG-reading | ||
124 | * libpng function, unless an alternate error handler was installed-- | ||
125 | * but compatible error handlers must either use longjmp() themselves | ||
126 | * (as in this program) or exit immediately, so here we are: */ | ||
127 | |||
128 | if (setjmp(mainprog_ptr->jmpbuf)) { | ||
129 | png_destroy_read_struct(&png_ptr, &info_ptr, NULL); | ||
130 | return 2; | ||
131 | } | ||
132 | |||
133 | |||
134 | #ifdef PNG_HANDLE_AS_UNKNOWN_SUPPORTED | ||
135 | /* prepare the reader to ignore all recognized chunks whose data won't be | ||
136 | * used, i.e., all chunks recognized by libpng except for IHDR, PLTE, IDAT, | ||
137 | * IEND, tRNS, bKGD, gAMA, and sRGB (small performance improvement) */ | ||
138 | { | ||
139 | /* These byte strings were copied from png.h. If a future libpng | ||
140 | * version recognizes more chunks, add them to this list. If a | ||
141 | * future version of readpng2.c recognizes more chunks, delete them | ||
142 | * from this list. */ | ||
143 | static /* const */ png_byte chunks_to_ignore[] = { | ||
144 | 99, 72, 82, 77, '\0', /* cHRM */ | ||
145 | 104, 73, 83, 84, '\0', /* hIST */ | ||
146 | 105, 67, 67, 80, '\0', /* iCCP */ | ||
147 | 105, 84, 88, 116, '\0', /* iTXt */ | ||
148 | 111, 70, 70, 115, '\0', /* oFFs */ | ||
149 | 112, 67, 65, 76, '\0', /* pCAL */ | ||
150 | 112, 72, 89, 115, '\0', /* pHYs */ | ||
151 | 115, 66, 73, 84, '\0', /* sBIT */ | ||
152 | 115, 67, 65, 76, '\0', /* sCAL */ | ||
153 | 115, 80, 76, 84, '\0', /* sPLT */ | ||
154 | 115, 84, 69, 82, '\0', /* sTER */ | ||
155 | 116, 69, 88, 116, '\0', /* tEXt */ | ||
156 | 116, 73, 77, 69, '\0', /* tIME */ | ||
157 | 122, 84, 88, 116, '\0' /* zTXt */ | ||
158 | }; | ||
159 | |||
160 | png_set_keep_unknown_chunks(png_ptr, 1 /* PNG_HANDLE_CHUNK_NEVER */, | ||
161 | chunks_to_ignore, sizeof(chunks_to_ignore)/5); | ||
162 | } | ||
163 | #endif /* PNG_HANDLE_AS_UNKNOWN_SUPPORTED */ | ||
164 | |||
165 | |||
166 | /* instead of doing png_init_io() here, now we set up our callback | ||
167 | * functions for progressive decoding */ | ||
168 | |||
169 | png_set_progressive_read_fn(png_ptr, mainprog_ptr, | ||
170 | readpng2_info_callback, readpng2_row_callback, readpng2_end_callback); | ||
171 | |||
172 | |||
173 | /* make sure we save our pointers for use in readpng2_decode_data() */ | ||
174 | |||
175 | mainprog_ptr->png_ptr = png_ptr; | ||
176 | mainprog_ptr->info_ptr = info_ptr; | ||
177 | |||
178 | |||
179 | /* and that's all there is to initialization */ | ||
180 | |||
181 | return 0; | ||
182 | } | ||
183 | |||
184 | |||
185 | |||
186 | |||
187 | /* returns 0 for success, 2 for libpng (longjmp) problem */ | ||
188 | |||
189 | int readpng2_decode_data(mainprog_info *mainprog_ptr, uch *rawbuf, ulg length) | ||
190 | { | ||
191 | png_structp png_ptr = (png_structp)mainprog_ptr->png_ptr; | ||
192 | png_infop info_ptr = (png_infop)mainprog_ptr->info_ptr; | ||
193 | |||
194 | |||
195 | /* setjmp() must be called in every function that calls a PNG-reading | ||
196 | * libpng function */ | ||
197 | |||
198 | if (setjmp(mainprog_ptr->jmpbuf)) { | ||
199 | png_destroy_read_struct(&png_ptr, &info_ptr, NULL); | ||
200 | mainprog_ptr->png_ptr = NULL; | ||
201 | mainprog_ptr->info_ptr = NULL; | ||
202 | return 2; | ||
203 | } | ||
204 | |||
205 | |||
206 | /* hand off the next chunk of input data to libpng for decoding */ | ||
207 | |||
208 | png_process_data(png_ptr, info_ptr, rawbuf, length); | ||
209 | |||
210 | return 0; | ||
211 | } | ||
212 | |||
213 | |||
214 | |||
215 | |||
216 | static void readpng2_info_callback(png_structp png_ptr, png_infop info_ptr) | ||
217 | { | ||
218 | mainprog_info *mainprog_ptr; | ||
219 | int color_type, bit_depth; | ||
220 | png_uint_32 width, height; | ||
221 | #ifdef PNG_FLOATING_POINT_SUPPORTED | ||
222 | double gamma; | ||
223 | #else | ||
224 | png_fixed_point gamma; | ||
225 | #endif | ||
226 | |||
227 | |||
228 | /* setjmp() doesn't make sense here, because we'd either have to exit(), | ||
229 | * longjmp() ourselves, or return control to libpng, which doesn't want | ||
230 | * to see us again. By not doing anything here, libpng will instead jump | ||
231 | * to readpng2_decode_data(), which can return an error value to the main | ||
232 | * program. */ | ||
233 | |||
234 | |||
235 | /* retrieve the pointer to our special-purpose struct, using the png_ptr | ||
236 | * that libpng passed back to us (i.e., not a global this time--there's | ||
237 | * no real difference for a single image, but for a multithreaded browser | ||
238 | * decoding several PNG images at the same time, one needs to avoid mixing | ||
239 | * up different images' structs) */ | ||
240 | |||
241 | mainprog_ptr = png_get_progressive_ptr(png_ptr); | ||
242 | |||
243 | if (mainprog_ptr == NULL) { /* we be hosed */ | ||
244 | fprintf(stderr, | ||
245 | "readpng2 error: main struct not recoverable in info_callback.\n"); | ||
246 | fflush(stderr); | ||
247 | return; | ||
248 | /* | ||
249 | * Alternatively, we could call our error-handler just like libpng | ||
250 | * does, which would effectively terminate the program. Since this | ||
251 | * can only happen if png_ptr gets redirected somewhere odd or the | ||
252 | * main PNG struct gets wiped, we're probably toast anyway. (If | ||
253 | * png_ptr itself is NULL, we would not have been called.) | ||
254 | */ | ||
255 | } | ||
256 | |||
257 | |||
258 | /* this is just like in the non-progressive case */ | ||
259 | |||
260 | png_get_IHDR(png_ptr, info_ptr, &width, &height, &bit_depth, &color_type, | ||
261 | NULL, NULL, NULL); | ||
262 | mainprog_ptr->width = (ulg)width; | ||
263 | mainprog_ptr->height = (ulg)height; | ||
264 | |||
265 | |||
266 | /* since we know we've read all of the PNG file's "header" (i.e., up | ||
267 | * to IDAT), we can check for a background color here */ | ||
268 | |||
269 | if (mainprog_ptr->need_bgcolor && | ||
270 | png_get_valid(png_ptr, info_ptr, PNG_INFO_bKGD)) | ||
271 | { | ||
272 | png_color_16p pBackground; | ||
273 | |||
274 | /* it is not obvious from the libpng documentation, but this function | ||
275 | * takes a pointer to a pointer, and it always returns valid red, | ||
276 | * green and blue values, regardless of color_type: */ | ||
277 | png_get_bKGD(png_ptr, info_ptr, &pBackground); | ||
278 | |||
279 | /* however, it always returns the raw bKGD data, regardless of any | ||
280 | * bit-depth transformations, so check depth and adjust if necessary */ | ||
281 | if (bit_depth == 16) { | ||
282 | mainprog_ptr->bg_red = pBackground->red >> 8; | ||
283 | mainprog_ptr->bg_green = pBackground->green >> 8; | ||
284 | mainprog_ptr->bg_blue = pBackground->blue >> 8; | ||
285 | } else if (color_type == PNG_COLOR_TYPE_GRAY && bit_depth < 8) { | ||
286 | if (bit_depth == 1) | ||
287 | mainprog_ptr->bg_red = mainprog_ptr->bg_green = | ||
288 | mainprog_ptr->bg_blue = pBackground->gray? 255 : 0; | ||
289 | else if (bit_depth == 2) | ||
290 | mainprog_ptr->bg_red = mainprog_ptr->bg_green = | ||
291 | mainprog_ptr->bg_blue = (255/3) * pBackground->gray; | ||
292 | else /* bit_depth == 4 */ | ||
293 | mainprog_ptr->bg_red = mainprog_ptr->bg_green = | ||
294 | mainprog_ptr->bg_blue = (255/15) * pBackground->gray; | ||
295 | } else { | ||
296 | mainprog_ptr->bg_red = (uch)pBackground->red; | ||
297 | mainprog_ptr->bg_green = (uch)pBackground->green; | ||
298 | mainprog_ptr->bg_blue = (uch)pBackground->blue; | ||
299 | } | ||
300 | } | ||
301 | |||
302 | |||
303 | /* as before, let libpng expand palette images to RGB, low-bit-depth | ||
304 | * grayscale images to 8 bits, transparency chunks to full alpha channel; | ||
305 | * strip 16-bit-per-sample images to 8 bits per sample; and convert | ||
306 | * grayscale to RGB[A] */ | ||
307 | |||
308 | if (color_type == PNG_COLOR_TYPE_PALETTE) | ||
309 | png_set_expand(png_ptr); | ||
310 | if (color_type == PNG_COLOR_TYPE_GRAY && bit_depth < 8) | ||
311 | png_set_expand(png_ptr); | ||
312 | if (png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS)) | ||
313 | png_set_expand(png_ptr); | ||
314 | #ifdef PNG_READ_16_TO_8_SUPPORTED | ||
315 | if (bit_depth == 16) | ||
316 | # ifdef PNG_READ_SCALE_16_TO_8_SUPPORTED | ||
317 | png_set_scale_16(png_ptr); | ||
318 | # else | ||
319 | png_set_strip_16(png_ptr); | ||
320 | # endif | ||
321 | #endif | ||
322 | if (color_type == PNG_COLOR_TYPE_GRAY || | ||
323 | color_type == PNG_COLOR_TYPE_GRAY_ALPHA) | ||
324 | png_set_gray_to_rgb(png_ptr); | ||
325 | |||
326 | |||
327 | /* Unlike the basic viewer, which was designed to operate on local files, | ||
328 | * this program is intended to simulate a web browser--even though we | ||
329 | * actually read from a local file, too. But because we are pretending | ||
330 | * that most of the images originate on the Internet, we follow the recom- | ||
331 | * mendation of the sRGB proposal and treat unlabelled images (no gAMA | ||
332 | * chunk) as existing in the sRGB color space. That is, we assume that | ||
333 | * such images have a file gamma of 0.45455, which corresponds to a PC-like | ||
334 | * display system. This change in assumptions will have no effect on a | ||
335 | * PC-like system, but on a Mac, SGI, NeXT or other system with a non- | ||
336 | * identity lookup table, it will darken unlabelled images, which effec- | ||
337 | * tively favors images from PC-like systems over those originating on | ||
338 | * the local platform. Note that mainprog_ptr->display_exponent is the | ||
339 | * "gamma" value for the entire display system, i.e., the product of | ||
340 | * LUT_exponent and CRT_exponent. */ | ||
341 | |||
342 | #ifdef PNG_FLOATING_POINT_SUPPORTED | ||
343 | if (png_get_gAMA(png_ptr, info_ptr, &gamma)) | ||
344 | png_set_gamma(png_ptr, mainprog_ptr->display_exponent, gamma); | ||
345 | else | ||
346 | png_set_gamma(png_ptr, mainprog_ptr->display_exponent, 0.45455); | ||
347 | #else | ||
348 | if (png_get_gAMA_fixed(png_ptr, info_ptr, &gamma)) | ||
349 | png_set_gamma_fixed(png_ptr, | ||
350 | (png_fixed_point)(100000*mainprog_ptr->display_exponent+.5), gamma); | ||
351 | else | ||
352 | png_set_gamma_fixed(png_ptr, | ||
353 | (png_fixed_point)(100000*mainprog_ptr->display_exponent+.5), 45455); | ||
354 | #endif | ||
355 | |||
356 | /* we'll let libpng expand interlaced images, too */ | ||
357 | |||
358 | mainprog_ptr->passes = png_set_interlace_handling(png_ptr); | ||
359 | |||
360 | |||
361 | /* all transformations have been registered; now update info_ptr data and | ||
362 | * then get rowbytes and channels */ | ||
363 | |||
364 | png_read_update_info(png_ptr, info_ptr); | ||
365 | |||
366 | mainprog_ptr->rowbytes = (int)png_get_rowbytes(png_ptr, info_ptr); | ||
367 | mainprog_ptr->channels = png_get_channels(png_ptr, info_ptr); | ||
368 | |||
369 | |||
370 | /* Call the main program to allocate memory for the image buffer and | ||
371 | * initialize windows and whatnot. (The old-style function-pointer | ||
372 | * invocation is used for compatibility with a few supposedly ANSI | ||
373 | * compilers that nevertheless barf on "fn_ptr()"-style syntax.) */ | ||
374 | |||
375 | (*mainprog_ptr->mainprog_init)(); | ||
376 | |||
377 | |||
378 | /* and that takes care of initialization */ | ||
379 | |||
380 | return; | ||
381 | } | ||
382 | |||
383 | |||
384 | |||
385 | |||
386 | |||
387 | static void readpng2_row_callback(png_structp png_ptr, png_bytep new_row, | ||
388 | png_uint_32 row_num, int pass) | ||
389 | { | ||
390 | mainprog_info *mainprog_ptr; | ||
391 | |||
392 | |||
393 | /* first check whether the row differs from the previous pass; if not, | ||
394 | * nothing to combine or display */ | ||
395 | |||
396 | if (!new_row) | ||
397 | return; | ||
398 | |||
399 | |||
400 | /* retrieve the pointer to our special-purpose struct so we can access | ||
401 | * the old rows and image-display callback function */ | ||
402 | |||
403 | mainprog_ptr = png_get_progressive_ptr(png_ptr); | ||
404 | |||
405 | |||
406 | /* save the pass number for optional use by the front end */ | ||
407 | |||
408 | mainprog_ptr->pass = pass; | ||
409 | |||
410 | |||
411 | /* have libpng either combine the new row data with the existing row data | ||
412 | * from previous passes (if interlaced) or else just copy the new row | ||
413 | * into the main program's image buffer */ | ||
414 | |||
415 | png_progressive_combine_row(png_ptr, mainprog_ptr->row_pointers[row_num], | ||
416 | new_row); | ||
417 | |||
418 | |||
419 | /* finally, call the display routine in the main program with the number | ||
420 | * of the row we just updated */ | ||
421 | |||
422 | (*mainprog_ptr->mainprog_display_row)(row_num); | ||
423 | |||
424 | |||
425 | /* and we're ready for more */ | ||
426 | |||
427 | return; | ||
428 | } | ||
429 | |||
430 | |||
431 | |||
432 | |||
433 | |||
434 | static void readpng2_end_callback(png_structp png_ptr, png_infop info_ptr) | ||
435 | { | ||
436 | mainprog_info *mainprog_ptr; | ||
437 | |||
438 | |||
439 | /* retrieve the pointer to our special-purpose struct */ | ||
440 | |||
441 | mainprog_ptr = png_get_progressive_ptr(png_ptr); | ||
442 | |||
443 | |||
444 | /* let the main program know that it should flush any buffered image | ||
445 | * data to the display now and set a "done" flag or whatever, but note | ||
446 | * that it SHOULD NOT DESTROY THE PNG STRUCTS YET--in other words, do | ||
447 | * NOT call readpng2_cleanup() either here or in the finish_display() | ||
448 | * routine; wait until control returns to the main program via | ||
449 | * readpng2_decode_data() */ | ||
450 | |||
451 | (*mainprog_ptr->mainprog_finish_display)(); | ||
452 | |||
453 | |||
454 | /* all done */ | ||
455 | |||
456 | return; | ||
457 | } | ||
458 | |||
459 | |||
460 | |||
461 | |||
462 | |||
463 | void readpng2_cleanup(mainprog_info *mainprog_ptr) | ||
464 | { | ||
465 | png_structp png_ptr = (png_structp)mainprog_ptr->png_ptr; | ||
466 | png_infop info_ptr = (png_infop)mainprog_ptr->info_ptr; | ||
467 | |||
468 | if (png_ptr && info_ptr) | ||
469 | png_destroy_read_struct(&png_ptr, &info_ptr, NULL); | ||
470 | |||
471 | mainprog_ptr->png_ptr = NULL; | ||
472 | mainprog_ptr->info_ptr = NULL; | ||
473 | } | ||
474 | |||
475 | |||
476 | |||
477 | |||
478 | |||
479 | static void readpng2_error_handler(png_structp png_ptr, png_const_charp msg) | ||
480 | { | ||
481 | mainprog_info *mainprog_ptr; | ||
482 | |||
483 | /* This function, aside from the extra step of retrieving the "error | ||
484 | * pointer" (below) and the fact that it exists within the application | ||
485 | * rather than within libpng, is essentially identical to libpng's | ||
486 | * default error handler. The second point is critical: since both | ||
487 | * setjmp() and longjmp() are called from the same code, they are | ||
488 | * guaranteed to have compatible notions of how big a jmp_buf is, | ||
489 | * regardless of whether _BSD_SOURCE or anything else has (or has not) | ||
490 | * been defined. */ | ||
491 | |||
492 | fprintf(stderr, "readpng2 libpng error: %s\n", msg); | ||
493 | fflush(stderr); | ||
494 | |||
495 | mainprog_ptr = png_get_error_ptr(png_ptr); | ||
496 | if (mainprog_ptr == NULL) { /* we are completely hosed now */ | ||
497 | fprintf(stderr, | ||
498 | "readpng2 severe error: jmpbuf not recoverable; terminating.\n"); | ||
499 | fflush(stderr); | ||
500 | exit(99); | ||
501 | } | ||
502 | |||
503 | /* Now we have our data structure we can use the information in it | ||
504 | * to return control to our own higher level code (all the points | ||
505 | * where 'setjmp' is called in this file.) This will work with other | ||
506 | * error handling mechanisms as well - libpng always calls png_error | ||
507 | * when it can proceed no further, thus, so long as the error handler | ||
508 | * is intercepted, application code can do its own error recovery. | ||
509 | */ | ||
510 | longjmp(mainprog_ptr->jmpbuf, 1); | ||
511 | } | ||