Subversion Repositories Kolibri OS

Rev

Go to most recent revision | Blame | Compare with Previous | Last modification | View Log | Download | RSS feed

  1.  
  2. ; pngerror.asm - stub functions for i/o and memory allocation
  3.  
  4. ; Last changed in libpng 1.6.24 [August 4, 2016]
  5. ; Copyright (c) 1998-2002,2004,2006-2016 Glenn Randers-Pehrson
  6. ; (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger)
  7. ; (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.)
  8.  
  9. ; This code is released under the libpng license.
  10. ; For conditions of distribution and use, see the disclaimer
  11. ; and license in png.h
  12.  
  13. ; This file provides a location for all error handling.  Users who
  14. ; need special error handling are expected to write replacement functions
  15. ; and use png_set_error_fn() to use those functions.  See the instructions
  16. ; at each function.
  17.  
  18. ; This function is called whenever there is a fatal error.  This function
  19. ; should not be changed.  If there is a need to handle errors differently,
  20. ; you should supply a replacement error function and use png_set_error_fn()
  21. ; to replace the error function at run-time.
  22.  
  23. ;if PNG_ERROR_TEXT_SUPPORTED
  24. ;void png_error(png_const_structrp png_ptr, charp error_message)
  25. ;{
  26. if PNG_ERROR_NUMBERS_SUPPORTED eq 1
  27. ;   char msg[16];
  28. ;   if (png_ptr != NULL)
  29. ;   {
  30. ;      if ((png_ptr->flags &
  31. ;         (PNG_FLAG_STRIP_ERROR_NUMBERS|PNG_FLAG_STRIP_ERROR_TEXT)) != 0)
  32. ;      {
  33. ;         if (*error_message == PNG_LITERAL_SHARP)
  34. ;         {
  35.                 ;Strip "#nnnn " from beginning of error message.
  36. ;            int offset;
  37. ;            for (offset = 1; offset<15; offset++)
  38. ;               if (error_message[offset] == ' ')
  39. ;                  break;
  40.  
  41. ;            if ((png_ptr->flags & PNG_FLAG_STRIP_ERROR_TEXT) != 0)
  42. ;            {
  43. ;               int i;
  44. ;               for (i = 0; i < offset - 1; i++)
  45. ;                  msg[i] = error_message[i + 1];
  46. ;               msg[i - 1] = '\0';
  47. ;               error_message = msg;
  48. ;            }
  49.  
  50. ;            else
  51. ;               error_message += offset;
  52. ;         }
  53.  
  54. ;         else
  55. ;         {
  56. ;            if ((png_ptr->flags & PNG_FLAG_STRIP_ERROR_TEXT) != 0)
  57. ;            {
  58. ;               msg[0] = '0';
  59. ;               msg[1] = '\0';
  60. ;               error_message = msg;
  61. ;            }
  62. ;         }
  63. ;      }
  64. ;   }
  65. end if
  66. ;   if (png_ptr != NULL && png_ptr->error_fn != NULL)
  67. ;      (*(png_ptr->error_fn))(png_ptr, error_message);
  68.  
  69.         ; If the custom handler doesn't exist, or if it returns,
  70.         ; use the default handler, which will not return.
  71. ;   png_default_error(png_ptr, error_message);
  72. ;}
  73. ;#else
  74. ;void png_err(png_const_structrp png_ptr)
  75. ;{
  76.         ; Prior to 1.5.2 the error_fn received a NULL pointer, expressed
  77.         ; erroneously as '\0', instead of the empty string "".  This was
  78.         ; apparently an error, introduced in libpng-1.2.20, and png_default_error
  79.         ; will crash in this case.
  80.  
  81. ;   if (png_ptr != NULL && png_ptr->error_fn != NULL)
  82. ;      (*(png_ptr->error_fn))(png_ptr, "");
  83.  
  84.         ; If the custom handler doesn't exist, or if it returns,
  85.         ; use the default handler, which will not return.
  86. ;   png_default_error(png_ptr, "");
  87. ;}
  88. ;end if /* ERROR_TEXT */
  89.  
  90. ; Utility to safely appends strings to a buffer.  This never errors out so
  91. ; error checking is not required in the caller.
  92.  
  93. ;size_t (charp buffer, size_t bufsize, size_t pos, charp string)
  94. align 4
  95. proc png_safecat uses ebx ecx edi esi, buffer:dword, bufsize:dword, pos:dword, string:dword
  96.         mov edi,[buffer]
  97.         cmp edi,0
  98.         je .end0
  99.         mov ebx,[pos]
  100.         mov ecx,[bufsize]
  101.         cmp ebx,ecx
  102.         jge .end0 ;if (..!=0 && ..<..)
  103.                 mov esi,[string]
  104.                 cmp esi,0
  105.                 je .end1 ;if (..!=0)
  106.                 dec ecx
  107.                 @@:
  108.                         cmp byte[esi],0
  109.                         je .end1
  110.                         cmp ebx,ecx
  111.                         jge .end1
  112.                         movsb
  113.                         inc ebx
  114.                         jmp @b
  115. align 4
  116.                 .end1:
  117.                 xor al,al
  118.                 stosb
  119.         .end0:
  120.         mov eax,ebx
  121.         ret
  122. endp
  123.  
  124. ;#if defined(PNG_WARNINGS_SUPPORTED) || defined(PNG_TIME_RFC1123_SUPPORTED)
  125. ; Utility to dump an unsigned value into a buffer, given a start pointer and
  126. ; and end pointer (which should point just *beyond* the end of the buffer!)
  127. ; Returns the pointer to the start of the formatted string.
  128.  
  129. ;charp png_format_number(charp start, charp end, int format,
  130. ;    png_alloc_size_t number)
  131. ;{
  132. ;   int count = 0;    /* number of digits output */
  133. ;   int mincount = 1; /* minimum number required */
  134. ;   int output = 0;   /* digit output (for the fixed point format) */
  135.  
  136. ;   *--end = '\0';
  137.  
  138. ;   /* This is written so that the loop always runs at least once, even with
  139. ;    * number zero.
  140.  
  141. ;   while (end > start && (number != 0 || count < mincount))
  142. ;   {
  143.  
  144. ;      char digits[] = "0123456789ABCDEF";
  145.  
  146. ;      switch (format)
  147. ;      {
  148. ;         case PNG_NUMBER_FORMAT_fixed:
  149. ;            /* Needs five digits (the fraction) */
  150. ;            mincount = 5;
  151. ;            if (output != 0 || number % 10 != 0)
  152. ;            {
  153. ;               *--end = digits[number % 10];
  154. ;               output = 1;
  155. ;            }
  156. ;            number /= 10;
  157. ;            break;
  158.  
  159. ;         case PNG_NUMBER_FORMAT_02u:
  160. ;            /* Expects at least 2 digits. */
  161. ;            mincount = 2;
  162. ;            /* FALL THROUGH */
  163.  
  164. ;         case PNG_NUMBER_FORMAT_u:
  165. ;            *--end = digits[number % 10];
  166. ;            number /= 10;
  167. ;            break;
  168.  
  169. ;         case PNG_NUMBER_FORMAT_02x:
  170. ;            /* This format expects at least two digits */
  171. ;            mincount = 2;
  172. ;            /* FALL THROUGH */
  173.  
  174. ;         case PNG_NUMBER_FORMAT_x:
  175. ;            *--end = digits[number & 0xf];
  176. ;            number >>= 4;
  177. ;            break;
  178.  
  179. ;         default: /* an error */
  180. ;            number = 0;
  181. ;            break;
  182. ;      }
  183.  
  184.         ; Keep track of the number of digits added
  185. ;      ++count;
  186.  
  187.         ; Float a fixed number here:
  188. ;      if ((format == PNG_NUMBER_FORMAT_fixed) && (count == 5) && (end > start))
  189. ;      {
  190.         ; End of the fraction, but maybe nothing was output?  In that case
  191.         ; drop the decimal point.  If the number is a true zero handle that
  192.         ; here.
  193.  
  194. ;         if (output != 0)
  195. ;            *--end = '.';
  196. ;         else if (number == 0) /* and !output */
  197. ;            *--end = '0';
  198. ;      }
  199. ;   }
  200.  
  201. ;   return end;
  202. ;}
  203. ;end if
  204.  
  205. ;if PNG_WARNINGS_SUPPORTED
  206. ; This function is called whenever there is a non-fatal error.  This function
  207. ; should not be changed.  If there is a need to handle warnings differently,
  208. ; you should supply a replacement warning function and use
  209. ; png_set_error_fn() to replace the warning function at run-time.
  210.  
  211. ;void png_warning(png_const_structrp png_ptr, charp warning_message)
  212. ;{
  213. ;   int offset = 0;
  214. ;   if (png_ptr != NULL)
  215. ;   {
  216. if PNG_ERROR_NUMBERS_SUPPORTED eq 1
  217. ;   if ((png_ptr->flags &
  218. ;       (PNG_FLAG_STRIP_ERROR_NUMBERS|PNG_FLAG_STRIP_ERROR_TEXT)) != 0)
  219. end if
  220. ;      {
  221. ;         if (*warning_message == PNG_LITERAL_SHARP)
  222. ;         {
  223. ;            for (offset = 1; offset < 15; offset++)
  224. ;               if (warning_message[offset] == ' ')
  225. ;                  break;
  226. ;         }
  227. ;      }
  228. ;   }
  229. ;   if (png_ptr != NULL && png_ptr->warning_fn != NULL)
  230. ;      (*(png_ptr->warning_fn))(png_ptr, warning_message + offset);
  231. ;   else
  232. ;      png_default_warning(png_ptr, warning_message + offset);
  233. ;}
  234.  
  235. ; These functions support 'formatted' warning messages with up to
  236. ; PNG_WARNING_PARAMETER_COUNT parameters.  In the format string the parameter
  237. ; is introduced by @<number>, where 'number' starts at 1.  This follows the
  238. ; standard established by X/Open for internationalizable error messages.
  239.  
  240. ;void
  241. ;png_warning_parameter(png_warning_parameters p, int number,
  242. ;    charp string)
  243. ;{
  244. ;   if (number > 0 && number <= PNG_WARNING_PARAMETER_COUNT)
  245. ;      (void)png_safecat(p[number-1], (sizeof p[number-1]), 0, string);
  246. ;}
  247.  
  248. ;void
  249. ;png_warning_parameter_unsigned(png_warning_parameters p, int number, int format,
  250. ;    png_alloc_size_t value)
  251. ;{
  252. ;   char buffer[PNG_NUMBER_BUFFER_SIZE];
  253. ;   png_warning_parameter(p, number, PNG_FORMAT_NUMBER(buffer, format, value));
  254. ;}
  255.  
  256. ;void (png_warning_parameters p, int number, int format, int_32 value)
  257. align 4
  258. proc png_warning_parameter_signed, p:dword, number:dword, format:dword, value:dword
  259. ;   png_alloc_size_t u;
  260. ;   charp str;
  261. ;   char buffer[PNG_NUMBER_BUFFER_SIZE];
  262.  
  263.         ; Avoid overflow by doing the negate in a png_alloc_size_t:
  264. ;   u = (png_alloc_size_t)value;
  265. ;   if (value < 0)
  266. ;      u = ~u + 1;
  267.  
  268. ;   str = PNG_FORMAT_NUMBER(buffer, format, u);
  269.  
  270. ;   if (value < 0 && str > buffer)
  271. ;      *--str = '-';
  272.  
  273. ;   png_warning_parameter(p, number, str);
  274.         ret
  275. endp
  276.  
  277. ;void (png_const_structrp png_ptr, png_warning_parameters p, charp message)
  278. align 4
  279. proc png_formatted_warning, png_ptr:dword, p:dword, message:dword
  280.         ; The internal buffer is just 192 bytes - enough for all our messages,
  281.         ; overflow doesn't happen because this code checks!  If someone figures
  282.         ; out how to send us a message longer than 192 bytes, all that will
  283.         ; happen is that the message will be truncated appropriately.
  284.  
  285. ;   size_t i = 0; /* Index in the msg[] buffer: */
  286. ;   char msg[192];
  287.  
  288.         ; Each iteration through the following loop writes at most one character
  289.         ; to msg[i++] then returns here to validate that there is still space for
  290.         ; the trailing '\0'.  It may (in the case of a parameter) read more than
  291.         ; one character from message[]; it must check for '\0' and continue to the
  292.         ; test if it finds the end of string.
  293.  
  294. ;   while (i<(sizeof msg)-1 && *message != '\0')
  295. ;   {
  296.         ; '@' at end of string is now just printed (previously it was skipped);
  297.         ; it is an error in the calling code to terminate the string with @.
  298.  
  299. ;      if (p != NULL && *message == '@' && message[1] != '\0')
  300. ;      {
  301. ;         int parameter_char = *++message; /* Consume the '@' */
  302. ;         char valid_parameters[] = "123456789";
  303. ;         int parameter = 0;
  304.  
  305.                 ; Search for the parameter digit, the index in the string is the
  306.                 ; parameter to use.
  307.  
  308. ;         while (valid_parameters[parameter] != parameter_char &&
  309. ;            valid_parameters[parameter] != '\0')
  310. ;            ++parameter;
  311.  
  312.                 ; If the parameter digit is out of range it will just get printed.
  313. ;         if (parameter < PNG_WARNING_PARAMETER_COUNT)
  314. ;         {
  315.                 ; Append this parameter
  316. ;            charp parm = p[parameter];
  317. ;            charp pend = p[parameter] + (sizeof p[parameter]);
  318.  
  319.                 ; No need to copy the trailing '\0' here, but there is no guarantee
  320.                 ; that parm[] has been initialized, so there is no guarantee of a
  321.                 ; trailing '\0':
  322.  
  323. ;            while (i<(sizeof msg)-1 && *parm != '\0' && parm < pend)
  324. ;               msg[i++] = *parm++;
  325.  
  326.         ; Consume the parameter digit too:
  327. ;            ++message;
  328. ;            continue;
  329. ;         }
  330.  
  331.         ; else not a parameter and there is a character after the @ sign; just
  332.         ; copy that.  This is known not to be '\0' because of the test above.
  333.  
  334. ;      }
  335.  
  336.         ; At this point *message can't be '\0', even in the bad parameter case
  337.         ; above where there is a lone '@' at the end of the message string.
  338.  
  339. ;      msg[i++] = *message++;
  340. ;   }
  341.  
  342.         ; i is always less than (sizeof msg), so:
  343. ;   msg[i] = '\0';
  344.  
  345.         ; And this is the formatted message. It may be larger than
  346.         ; PNG_MAX_ERROR_TEXT, but that is only used for 'chunk' errors and these
  347.         ; are not (currently) formatted.
  348.  
  349. ;   png_warning(png_ptr, msg);
  350.         ret
  351. endp
  352. ;end if /* WARNINGS */
  353.  
  354. ;void png_benign_error(png_const_structrp png_ptr, charp error_message)
  355. ;{
  356. ;   if ((png_ptr->flags & PNG_FLAG_BENIGN_ERRORS_WARN) != 0)
  357. ;   {
  358. ;#     ifdef PNG_READ_SUPPORTED
  359. ;         if ((png_ptr->mode & PNG_IS_READ_STRUCT) != 0 &&
  360. ;            png_ptr->chunk_name != 0)
  361. ;            png_chunk_warning(png_ptr, error_message);
  362. ;         else
  363. ;#     endif
  364. ;      png_warning(png_ptr, error_message);
  365. ;   }
  366.  
  367. ;   else
  368. ;   {
  369. ;#     ifdef PNG_READ_SUPPORTED
  370. ;         if ((png_ptr->mode & PNG_IS_READ_STRUCT) != 0 &&
  371. ;            png_ptr->chunk_name != 0)
  372. ;            png_chunk_error(png_ptr, error_message);
  373. ;         else
  374. ;#     endif
  375. ;      png_error(png_ptr, error_message);
  376. ;   }
  377. ;}
  378.  
  379. ;void png_app_warning(png_const_structrp png_ptr, charp error_message)
  380. ;{
  381. ;   if ((png_ptr->flags & PNG_FLAG_APP_WARNINGS_WARN) != 0)
  382. ;      png_warning(png_ptr, error_message);
  383. ;   else
  384. ;      png_error(png_ptr, error_message);
  385. ;}
  386.  
  387. ;void (png_structrp png_ptr, charp error_message)
  388. align 4
  389. proc png_app_error uses eax edi, png_ptr:dword, error_message:dword
  390.         mov edi,[png_ptr]
  391.         mov eax,[edi+png_struct.flags]
  392.         and eax,PNG_FLAG_APP_ERRORS_WARN
  393.         cmp eax,0
  394.         je @f ;if (..!=0)
  395.                 png_warning edi, [error_message]
  396.                 jmp .end0
  397.         @@: ;else
  398.                 png_error edi, [error_message]
  399.         .end0:
  400.         ret
  401. endp
  402.  
  403. PNG_MAX_ERROR_TEXT equ 196 ;Currently limited by profile_error in png.asm
  404. if (PNG_WARNINGS_SUPPORTED eq 1) | \
  405.         ((PNG_READ_SUPPORTED eq 1) & (PNG_ERROR_TEXT_SUPPORTED eq 1))
  406. ; These utilities are used internally to build an error message that relates
  407. ; to the current chunk.  The chunk name comes from png_ptr->chunk_name,
  408. ; which is used to prefix the message.  The message is limited in length
  409. ; to 63 bytes. The name characters are output as hex digits wrapped in []
  410. ; if the character is invalid.
  411.  
  412. ;#define isnonalpha(c) ((c) < 65 || (c) > 122 || ((c) > 90 && (c) < 97))
  413. align 4
  414. png_digit db \ ;char[16]
  415.         '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', \
  416.         'A', 'B', 'C', 'D', 'E', 'F'
  417.  
  418. ;void (png_const_structrp png_ptr, charp buffer, charp error_message)
  419. align 4
  420. proc png_format_buffer, png_ptr:dword, buffer:dword, error_message:dword
  421. ;   uint_32 chunk_name = png_ptr->chunk_name;
  422. ;   int iout = 0, ishift = 24;
  423.  
  424. ;   while (ishift >= 0)
  425. ;   {
  426. ;      int c = (int)(chunk_name >> ishift) & 0xff;
  427.  
  428. ;      ishift -= 8;
  429. ;      if (isnonalpha(c) != 0)
  430. ;      {
  431. ;         buffer[iout++] = PNG_LITERAL_LEFT_SQUARE_BRACKET;
  432. ;         buffer[iout++] = png_digit[(c & 0xf0) >> 4];
  433. ;         buffer[iout++] = png_digit[c & 0x0f];
  434. ;         buffer[iout++] = PNG_LITERAL_RIGHT_SQUARE_BRACKET;
  435. ;      }
  436.  
  437. ;      else
  438. ;      {
  439. ;         buffer[iout++] = (char)c;
  440. ;      }
  441. ;   }
  442.  
  443. ;   if (error_message == NULL)
  444. ;      buffer[iout] = '\0';
  445.  
  446. ;   else
  447. ;   {
  448. ;      int iin = 0;
  449.  
  450. ;      buffer[iout++] = ':';
  451. ;      buffer[iout++] = ' ';
  452.  
  453. ;      while (iin < PNG_MAX_ERROR_TEXT-1 && error_message[iin] != '\0')
  454. ;         buffer[iout++] = error_message[iin++];
  455.  
  456.                 ;iin < PNG_MAX_ERROR_TEXT, so the following is safe:
  457. ;      buffer[iout] = '\0';
  458. ;   }
  459.         ret
  460. endp
  461. end if ;WARNINGS || ERROR_TEXT
  462.  
  463. ;void (png_const_structrp png_ptr, charp error_message)
  464. align 4
  465. proc png_chunk_error, png_ptr:dword, error_message:dword
  466. ;   char msg[18+PNG_MAX_ERROR_TEXT];
  467. ;   if (png_ptr == NULL)
  468. ;      png_error(png_ptr, error_message);
  469.  
  470. ;   else
  471. ;   {
  472. ;      png_format_buffer(png_ptr, msg, error_message);
  473. ;      png_error(png_ptr, msg);
  474. ;   }
  475.         ret
  476. endp
  477.  
  478. ;void (png_const_structrp png_ptr, charp warning_message)
  479. align 4
  480. proc png_chunk_warning, png_ptr:dword, warning_message:dword
  481. ;   char msg[18+PNG_MAX_ERROR_TEXT];
  482. ;   if (png_ptr == NULL)
  483. ;      png_warning(png_ptr, warning_message);
  484.  
  485. ;   else
  486. ;   {
  487. ;      png_format_buffer(png_ptr, msg, warning_message);
  488. ;      png_warning(png_ptr, msg);
  489. ;   }
  490.         ret
  491. endp
  492.  
  493. ;void (png_const_structrp png_ptr, charp error_message)
  494. align 4
  495. proc png_chunk_benign_error, png_ptr:dword, error_message:dword
  496. ;   if ((png_ptr->flags & PNG_FLAG_BENIGN_ERRORS_WARN) != 0)
  497. ;      png_chunk_warning(png_ptr, error_message);
  498.  
  499. ;   else
  500. ;      png_chunk_error(png_ptr, error_message);
  501.         ret
  502. endp
  503.  
  504. ;void (png_const_structrp png_ptr, charp message, int error)
  505. align 4
  506. proc png_chunk_report, png_ptr:dword, message:dword, error:dword
  507.         ; This is always supported, but for just read or just write it
  508.         ; unconditionally does the right thing.
  509.  
  510. ;#  if defined(PNG_READ_SUPPORTED) && defined(PNG_WRITE_SUPPORTED)
  511. ;      if ((png_ptr->mode & PNG_IS_READ_STRUCT) != 0)
  512. ;#  endif
  513.  
  514. if PNG_READ_SUPPORTED eq 1
  515. ;      {
  516. ;         if (error < PNG_CHUNK_ERROR)
  517. ;            png_chunk_warning(png_ptr, message);
  518.  
  519. ;         else
  520. ;            png_chunk_benign_error(png_ptr, message);
  521. ;      }
  522. end if
  523.  
  524. ;#  if defined(PNG_READ_SUPPORTED) && defined(PNG_WRITE_SUPPORTED)
  525. ;      else if ((png_ptr->mode & PNG_IS_READ_STRUCT) == 0)
  526. ;#  endif
  527.  
  528. if PNG_WRITE_SUPPORTED eq 1
  529. ;      {
  530. ;         if (error < PNG_CHUNK_WRITE_ERROR)
  531. ;            png_app_warning(png_ptr, message);
  532. ;
  533. ;         else
  534. ;            png_app_error(png_ptr, message);
  535. ;      }
  536. end if
  537.         ret
  538. endp
  539.  
  540. ;void (png_const_structrp png_ptr, charp name)
  541. align 4
  542. proc png_fixed_error, png_ptr:dword, name:dword
  543. ;#  define fixed_message "fixed point overflow in "
  544. ;#  define fixed_message_ln ((sizeof fixed_message)-1)
  545. ;   int  iin;
  546. ;   char msg[fixed_message_ln+PNG_MAX_ERROR_TEXT];
  547. ;   memcpy(msg, fixed_message, fixed_message_ln);
  548. ;   iin = 0;
  549. ;   if (name != NULL)
  550. ;      while (iin < (PNG_MAX_ERROR_TEXT-1) && name[iin] != 0)
  551. ;      {
  552. ;         msg[fixed_message_ln + iin] = name[iin];
  553. ;         ++iin;
  554. ;      }
  555. ;   msg[fixed_message_ln + iin] = 0;
  556. ;   png_error(png_ptr, msg);
  557.         ret
  558. endp
  559.  
  560. ; This API only exists if ANSI-C style error handling is used,
  561. ; otherwise it is necessary for png_default_error to be overridden.
  562.  
  563. ;jmp_buf* (png_structrp png_ptr, png_longjmp_ptr longjmp_fn,
  564. ;    size_t jmp_buf_size)
  565. align 4
  566. proc png_set_longjmp_fn, png_ptr:dword, longjmp_fn:dword, jmp_buf_size:dword
  567.         ; From libpng 1.6.0 the app gets one chance to set a 'jmpbuf_size' value
  568.         ; and it must not change after that.  Libpng doesn't care how big the
  569.         ; buffer is, just that it doesn't change.
  570.  
  571.         ; If the buffer size is no *larger* than the size of jmp_buf when libpng is
  572.         ; compiled a built in jmp_buf is returned; this preserves the pre-1.6.0
  573.         ; semantics that this call will not fail.  If the size is larger, however,
  574.         ; the buffer is allocated and this may fail, causing the function to return
  575.         ; NULL.
  576.  
  577. ;   if (png_ptr == NULL)
  578. ;      return NULL;
  579.  
  580. ;   if (png_ptr->jmp_buf_ptr == NULL)
  581. ;   {
  582. ;      png_ptr->jmp_buf_size = 0; /* not allocated */
  583.  
  584. ;      if (jmp_buf_size <= (sizeof png_ptr->jmp_buf_local))
  585. ;         png_ptr->jmp_buf_ptr = &png_ptr->jmp_buf_local;
  586.  
  587. ;      else
  588. ;      {
  589. ;         png_ptr->jmp_buf_ptr = png_malloc_warn(png_ptr, jmp_buf_size);
  590.  
  591. ;         if (png_ptr->jmp_buf_ptr == NULL)
  592. ;            return NULL; /* new NULL return on OOM */
  593.  
  594. ;         png_ptr->jmp_buf_size = jmp_buf_size;
  595. ;      }
  596. ;   }
  597.  
  598. ;   else /* Already allocated: check the size */
  599. ;   {
  600. ;      size_t size = png_ptr->jmp_buf_size;
  601.  
  602. ;      if (size == 0)
  603. ;      {
  604. ;         size = (sizeof png_ptr->jmp_buf_local);
  605. ;         if (png_ptr->jmp_buf_ptr != &png_ptr->jmp_buf_local)
  606. ;         {
  607.         ; This is an internal error in libpng: somehow we have been left
  608.         ; with a stack allocated jmp_buf when the application regained
  609.         ; control.  It's always possible to fix this up, but for the moment
  610.         ; this is a png_error because that makes it easy to detect.
  611.  
  612. ;            png_error(png_ptr, "Libpng jmp_buf still allocated");
  613. ;            /* png_ptr->jmp_buf_ptr = &png_ptr->jmp_buf_local; */
  614. ;         }
  615. ;      }
  616.  
  617. ;      if (size != jmp_buf_size)
  618. ;      {
  619. ;         png_warning(png_ptr, "Application jmp_buf size changed");
  620. ;         return NULL; /* caller will probably crash: no choice here */
  621. ;      }
  622. ;   }
  623.  
  624.         ; Finally fill in the function, now we have a satisfactory buffer. It is
  625.         ; valid to change the function on every call.
  626.  
  627. ;   png_ptr->longjmp_fn = longjmp_fn;
  628. ;   return png_ptr->jmp_buf_ptr;
  629. .end_f:
  630.         ret
  631. endp
  632.  
  633. ;void (png_structrp png_ptr)
  634. align 4
  635. proc png_free_jmpbuf, png_ptr:dword
  636. ;   if (png_ptr != NULL)
  637. ;   {
  638. ;      jmp_buf *jb = png_ptr->jmp_buf_ptr;
  639.  
  640.                 ; A size of 0 is used to indicate a local, stack, allocation of the
  641.                 ; pointer; used here and in png.c
  642.  
  643. ;      if (jb != NULL && png_ptr->jmp_buf_size > 0)
  644. ;      {
  645.  
  646.                         ; This stuff is so that a failure to free the error control structure
  647.                         ; does not leave libpng in a state with no valid error handling: the
  648.                         ; free always succeeds, if there is an error it gets ignored.
  649.  
  650. ;         if (jb != &png_ptr->jmp_buf_local)
  651. ;         {
  652. ;            /* Make an internal, libpng, jmp_buf to return here */
  653. ;            jmp_buf free_jmp_buf;
  654.  
  655. ;            if (!setjmp(free_jmp_buf))
  656. ;            {
  657. ;               png_ptr->jmp_buf_ptr = &free_jmp_buf; /* come back here */
  658. ;               png_ptr->jmp_buf_size = 0; /* stack allocation */
  659. ;               png_ptr->longjmp_fn = longjmp;
  660. ;               png_free(png_ptr, jb); /* Return to setjmp on error */
  661. ;            }
  662. ;         }
  663. ;      }
  664.  
  665.         ; *Always* cancel everything out:
  666. ;      png_ptr->jmp_buf_size = 0;
  667. ;      png_ptr->jmp_buf_ptr = NULL;
  668. ;      png_ptr->longjmp_fn = 0;
  669. ;   }
  670.         ret
  671. endp
  672.  
  673. ; This is the default error handling function.  Note that replacements for
  674. ; this function MUST NOT RETURN, or the program will likely crash.  This
  675. ; function is used by default, or if the program supplies NULL for the
  676. ; error function pointer in png_set_error_fn().
  677.  
  678. ;void (png_const_structrp png_ptr, charp error_message)
  679. align 4
  680. proc png_default_error, png_ptr:dword, error_message:dword
  681. if PNG_CONSOLE_IO_SUPPORTED eq 1
  682. if PNG_ERROR_NUMBERS_SUPPORTED eq 1
  683.         ; Check on NULL only added in 1.5.4
  684. ;   if (error_message != NULL && *error_message == PNG_LITERAL_SHARP)
  685. ;   {
  686.                 ; Strip "#nnnn " from beginning of error message.
  687. ;      int offset;
  688. ;      char error_number[16];
  689. ;      for (offset = 0; offset<15; offset++)
  690. ;      {
  691. ;         error_number[offset] = error_message[offset + 1];
  692. ;         if (error_message[offset] == ' ')
  693. ;            break;
  694. ;      }
  695.  
  696. ;      if ((offset > 1) && (offset < 15))
  697. ;      {
  698. ;         error_number[offset - 1] = '\0';
  699. ;         fprintf(stderr, "libpng error no. %s: %s",
  700. ;             error_number, error_message + offset + 1);
  701. ;         fprintf(stderr, PNG_STRING_NEWLINE);
  702. ;      }
  703.  
  704. ;      else
  705. ;      {
  706. ;         fprintf(stderr, "libpng error: %s, offset=%d",
  707. ;             error_message, offset);
  708. ;         fprintf(stderr, PNG_STRING_NEWLINE);
  709. ;      }
  710. ;   }
  711. ;   else
  712. end if
  713. ;   {
  714. ;      fprintf(stderr, "libpng error: %s", error_message ? error_message :
  715. ;         "undefined");
  716. ;      fprintf(stderr, PNG_STRING_NEWLINE);
  717. ;   }
  718. end if
  719. ;   png_longjmp(png_ptr, 1);
  720.         ret
  721. endp
  722.  
  723. ; This function is called when there is a warning, but the library thinks
  724. ; it can continue anyway.  Replacement functions don't have to do anything
  725. ; here if you don't want them to.  In the default configuration, png_ptr is
  726. ; not used, but it is passed in case it may be useful.
  727.  
  728. ;void (png_const_structrp png_ptr, charp warning_message)
  729. align 4
  730. proc png_default_warning, png_ptr:dword, warning_message:dword
  731. if PNG_CONSOLE_IO_SUPPORTED eq 1
  732. if PNG_ERROR_NUMBERS_SUPPORTED eq 1
  733. ;   if (*warning_message == PNG_LITERAL_SHARP)
  734. ;   {
  735. ;      int offset;
  736. ;      char warning_number[16];
  737. ;      for (offset = 0; offset < 15; offset++)
  738. ;      {
  739. ;         warning_number[offset] = warning_message[offset + 1];
  740. ;         if (warning_message[offset] == ' ')
  741. ;            break;
  742. ;      }
  743.  
  744. ;      if ((offset > 1) && (offset < 15))
  745. ;      {
  746. ;         warning_number[offset + 1] = '\0';
  747. ;         fprintf(stderr, "libpng warning no. %s: %s",
  748. ;             warning_number, warning_message + offset);
  749. ;         fprintf(stderr, PNG_STRING_NEWLINE);
  750. ;      }
  751.  
  752. ;      else
  753. ;      {
  754. ;         fprintf(stderr, "libpng warning: %s",
  755. ;             warning_message);
  756. ;         fprintf(stderr, PNG_STRING_NEWLINE);
  757. ;      }
  758. ;   }
  759. ;   else
  760. end if
  761. ;   {
  762. ;      fprintf(stderr, "libpng warning: %s", warning_message);
  763. ;      fprintf(stderr, PNG_STRING_NEWLINE);
  764. ;   }
  765. end if
  766.         ret
  767. endp
  768.  
  769. ; This function is called when the application wants to use another method
  770. ; of handling errors and warnings.  Note that the error function MUST NOT
  771. ; return to the calling routine or serious problems will occur.  The return
  772. ; method used in the default routine calls longjmp(png_ptr->jmp_buf_ptr, 1)
  773.  
  774. ;void (png_structrp png_ptr, voidp error_ptr,
  775. ;    png_error_ptr error_fn, png_error_ptr warning_fn)
  776. align 4
  777. proc png_set_error_fn, png_ptr:dword, error_ptr:dword, error_fn:dword, warning_fn:dword
  778. ;   if (png_ptr == NULL)
  779. ;      return;
  780.  
  781. ;   png_ptr->error_ptr = error_ptr;
  782. ;   png_ptr->error_fn = error_fn;
  783. if PNG_WARNINGS_SUPPORTED eq 1
  784. ;   png_ptr->warning_fn = warning_fn;
  785. end if
  786.         ret
  787. endp
  788.  
  789.  
  790. ; This function returns a pointer to the error_ptr associated with the user
  791. ; functions.  The application should free any memory associated with this
  792. ; pointer before png_write_destroy and png_read_destroy are called.
  793.  
  794. ;voidp (png_const_structrp png_ptr)
  795. align 4
  796. proc png_get_error_ptr, png_ptr:dword
  797. ;   if (png_ptr == NULL)
  798. ;      return NULL;
  799.  
  800. ;   return ((voidp)png_ptr->error_ptr);
  801.         ret
  802. endp
  803.  
  804. ;void (png_structrp png_ptr, uint_32 strip_mode)
  805. align 4
  806. proc png_set_strip_error_numbers, png_ptr:dword, strip_mode:dword
  807. ;   if (png_ptr != NULL)
  808. ;   {
  809. ;      png_ptr->flags &=
  810. ;         ((~(PNG_FLAG_STRIP_ERROR_NUMBERS |
  811. ;         PNG_FLAG_STRIP_ERROR_TEXT))&strip_mode);
  812. ;   }
  813.         ret
  814. endp
  815.  
  816. ; Currently the above both depend on SETJMP_SUPPORTED, however it would be
  817. ; possible to implement without setjmp support just so long as there is some
  818. ; way to handle the error return here:
  819.  
  820. ;void (png_structp png_nonconst_ptr, charp error_message)
  821. align 4
  822. proc png_safe_error uses eax ebx, png_nonconst_ptr:dword, error_message:dword
  823.         mov ebx,[png_nonconst_ptr]
  824.         mov ebx,[ebx+png_struct.error_ptr]
  825.         ; An error is always logged here, overwriting anything (typically a warning)
  826.         ; that is already there:
  827.  
  828.         cmp ebx,0
  829.         je .end0 ;if (..!=0)
  830.                 stdcall png_safecat, dword[ebx+png_image.message], sizeof.png_image.message, 0, [error_message]
  831.                 or dword[ebx+png_image.warning_or_error], PNG_IMAGE_ERROR
  832.  
  833.                 ; Retrieve the jmp_buf from within the png_control, making this work for
  834.                 ; C++ compilation too is pretty tricky: C++ wants a pointer to the first
  835.                 ; element of a jmp_buf, but C doesn't tell us the type of that.
  836.  
  837. ;      if (image->opaque != NULL && image->opaque->error_buf != NULL)
  838. ;         longjmp(png_control_jmp_buf(image->opaque), 1);
  839.  
  840.                 ; Missing longjmp buffer, the following is to help debugging:
  841. ;      {
  842. ;         size_t pos = png_safecat(image->message, (sizeof image->message), 0,
  843. ;             "bad longjmp: ");
  844. ;         png_safecat(image->message, (sizeof image->message), pos,
  845. ;             error_message);
  846. ;      }
  847.         .end0:
  848.  
  849.         ; Here on an internal programming error.
  850. ;   abort();
  851.         ret
  852. endp
  853.  
  854. ;void (png_structp png_nonconst_ptr, charp warning_message)
  855. align 4
  856. proc png_safe_warning uses eax ebx, png_nonconst_ptr:dword, warning_message:dword
  857.         mov ebx,[png_nonconst_ptr]
  858.         mov ebx,[ebx+png_struct.error_ptr]
  859.  
  860.         ; A warning is only logged if there is no prior warning or error.
  861.         cmp dword[ebx+png_image.warning_or_error],0
  862.         jne @f ;if (..==0)
  863.                 stdcall png_safecat, dword[ebx+png_image.message], sizeof.png_image.message, 0, [warning_message]
  864.                 or dword[ebx+png_image.warning_or_error], PNG_IMAGE_WARNING
  865.         @@:
  866.         ret
  867. endp
  868.  
  869. ;int (png_imagep image_in, int (*function)(voidp), voidp arg)
  870. align 4
  871. proc png_safe_execute uses ebx, image_in:dword, function:dword, arg:dword
  872. ;   volatile png_imagep image = image_in;
  873. ;   volatile int result;
  874. ;   volatile voidp saved_error_buf;
  875. ;   jmp_buf safe_jmpbuf;
  876.  
  877.         ; Safely execute function(arg) with png_error returning to this function.
  878.         mov ebx,[image_in]
  879. ;   saved_error_buf = image->opaque->error_buf;
  880. ;   result = setjmp(safe_jmpbuf) == 0;
  881.  
  882. ;   if (result != 0)
  883. ;   {
  884. ;      image->opaque->error_buf = safe_jmpbuf;
  885.                 stdcall [function], [arg]
  886. ;   }
  887.  
  888. ;   image->opaque->error_buf = saved_error_buf;
  889.  
  890.         ; And do the cleanup prior to any failure return.
  891.         cmp eax,0
  892.         jne @f ;if (..==0)
  893.                 stdcall png_image_free, ebx
  894.         @@:
  895.         ret
  896. endp
  897.  
  898.