imjerror.pas 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460
  1. unit imjerror;
  2. { This file contains simple error-reporting and trace-message routines.
  3. These are suitable for Unix-like systems and others where writing to
  4. stderr is the right thing to do. Many applications will want to replace
  5. some or all of these routines.
  6. These routines are used by both the compression and decompression code. }
  7. { Source: jerror.c; Copyright (C) 1991-1996, Thomas G. Lane. }
  8. { note: format_message still contains a hack }
  9. interface
  10. uses
  11. imjmorecfg,
  12. imjdeferr,
  13. imjpeglib;
  14. {
  15. jversion;
  16. }
  17. const
  18. EXIT_FAILURE = 1; { define halt() codes if not provided }
  19. {GLOBAL}
  20. function jpeg_std_error (var err : jpeg_error_mgr) : jpeg_error_mgr_ptr;
  21. procedure ERREXIT(cinfo : j_common_ptr; code : J_MESSAGE_CODE);
  22. procedure ERREXIT1(cinfo : j_common_ptr; code : J_MESSAGE_CODE; p1 : uInt);
  23. procedure ERREXIT2(cinfo : j_common_ptr; code : J_MESSAGE_CODE; p1 : int; p2 : int);
  24. procedure ERREXIT3(cinfo : j_common_ptr; code : J_MESSAGE_CODE;
  25. p1 : int; p2 : int; p3 : int);
  26. procedure ERREXIT4(cinfo : j_common_ptr; code : J_MESSAGE_CODE;
  27. p1 : int; p2 : int; p3 : int; p4 : int);
  28. procedure ERREXITS(cinfo : j_common_ptr;code : J_MESSAGE_CODE;
  29. str : string);
  30. { Nonfatal errors (we can keep going, but the data is probably corrupt) }
  31. procedure WARNMS(cinfo : j_common_ptr; code : J_MESSAGE_CODE);
  32. procedure WARNMS1(cinfo : j_common_ptr;code : J_MESSAGE_CODE; p1 : int);
  33. procedure WARNMS2(cinfo : j_common_ptr; code : J_MESSAGE_CODE;
  34. p1 : int; p2 : int);
  35. { Informational/debugging messages }
  36. procedure TRACEMS(cinfo : j_common_ptr; lvl : int; code : J_MESSAGE_CODE);
  37. procedure TRACEMS1(cinfo : j_common_ptr; lvl : int;
  38. code : J_MESSAGE_CODE; p1 : long);
  39. procedure TRACEMS2(cinfo : j_common_ptr; lvl : int; code : J_MESSAGE_CODE;
  40. p1 : int;
  41. p2 : int);
  42. procedure TRACEMS3(cinfo : j_common_ptr;
  43. lvl : int;
  44. code : J_MESSAGE_CODE;
  45. p1 : int; p2 : int; p3 : int);
  46. procedure TRACEMS4(cinfo : j_common_ptr; lvl : int; code : J_MESSAGE_CODE;
  47. p1 : int; p2 : int; p3 : int; p4 : int);
  48. procedure TRACEMS5(cinfo : j_common_ptr; lvl : int; code : J_MESSAGE_CODE;
  49. p1 : int; p2 : int; p3 : int; p4 : int; p5 : int);
  50. procedure TRACEMS8(cinfo : j_common_ptr; lvl : int; code : J_MESSAGE_CODE;
  51. p1 : int; p2 : int; p3 : int; p4 : int;
  52. p5 : int; p6 : int; p7 : int; p8 : int);
  53. procedure TRACEMSS(cinfo : j_common_ptr; lvl : int;
  54. code : J_MESSAGE_CODE; str : string);
  55. implementation
  56. { How to format a message string, in format_message() ? }
  57. {$IFDEF OS2}
  58. {$DEFINE NO_FORMAT}
  59. {$ENDIF}
  60. {$IFDEF FPC}
  61. {$DEFINE NO_FORMAT}
  62. {$ENDIF}
  63. uses
  64. {$IFNDEF NO_FORMAT}
  65. {$IFDEF VER70}
  66. drivers, { Turbo Vision unit with FormatStr }
  67. {$ELSE}
  68. sysutils, { Delphi Unit with Format() }
  69. {$ENDIF}
  70. {$ENDIF}
  71. imjcomapi;
  72. { Error exit handler: must not return to caller.
  73. Applications may override this if they want to get control back after
  74. an error. Typically one would longjmp somewhere instead of exiting.
  75. The setjmp buffer can be made a private field within an expanded error
  76. handler object. Note that the info needed to generate an error message
  77. is stored in the error object, so you can generate the message now or
  78. later, at your convenience.
  79. You should make sure that the JPEG object is cleaned up (with jpeg_abort
  80. or jpeg_destroy) at some point. }
  81. {METHODDEF}
  82. procedure error_exit (cinfo : j_common_ptr); far;
  83. begin
  84. { Always display the message }
  85. cinfo^.err^.output_message(cinfo);
  86. { Let the memory manager delete any temp files before we die }
  87. jpeg_destroy(cinfo);
  88. halt(EXIT_FAILURE);
  89. end;
  90. { Actual output of an error or trace message.
  91. Applications may override this method to send JPEG messages somewhere
  92. other than stderr. }
  93. { Macros to simplify using the error and trace message stuff }
  94. { The first parameter is either type of cinfo pointer }
  95. { Fatal errors (print message and exit) }
  96. procedure ERREXIT(cinfo : j_common_ptr; code : J_MESSAGE_CODE);
  97. begin
  98. cinfo^.err^.msg_code := ord(code);
  99. cinfo^.err^.error_exit(cinfo);
  100. end;
  101. procedure ERREXIT1(cinfo : j_common_ptr; code : J_MESSAGE_CODE; p1 : uInt);
  102. begin
  103. cinfo^.err^.msg_code := ord(code);
  104. cinfo^.err^.msg_parm.i[0] := p1;
  105. cinfo^.err^.error_exit (cinfo);
  106. end;
  107. procedure ERREXIT2(cinfo : j_common_ptr; code : J_MESSAGE_CODE;
  108. p1 : int; p2 : int);
  109. begin
  110. cinfo^.err^.msg_code := ord(code);
  111. cinfo^.err^.msg_parm.i[0] := p1;
  112. cinfo^.err^.msg_parm.i[1] := p2;
  113. cinfo^.err^.error_exit (cinfo);
  114. end;
  115. procedure ERREXIT3(cinfo : j_common_ptr; code : J_MESSAGE_CODE;
  116. p1 : int; p2 : int; p3 : int);
  117. begin
  118. cinfo^.err^.msg_code := ord(code);
  119. cinfo^.err^.msg_parm.i[0] := p1;
  120. cinfo^.err^.msg_parm.i[1] := p2;
  121. cinfo^.err^.msg_parm.i[2] := p3;
  122. cinfo^.err^.error_exit (cinfo);
  123. end;
  124. procedure ERREXIT4(cinfo : j_common_ptr; code : J_MESSAGE_CODE;
  125. p1 : int; p2 : int; p3 : int; p4 : int);
  126. begin
  127. cinfo^.err^.msg_code := ord(code);
  128. cinfo^.err^.msg_parm.i[0] := p1;
  129. cinfo^.err^.msg_parm.i[1] := p2;
  130. cinfo^.err^.msg_parm.i[2] := p3;
  131. cinfo^.err^.msg_parm.i[3] := p4;
  132. cinfo^.err^.error_exit (cinfo);
  133. end;
  134. procedure ERREXITS(cinfo : j_common_ptr;code : J_MESSAGE_CODE;
  135. str : string);
  136. begin
  137. cinfo^.err^.msg_code := ord(code);
  138. cinfo^.err^.msg_parm.s := str; { string[JMSG_STR_PARM_MAX] }
  139. cinfo^.err^.error_exit (cinfo);
  140. end;
  141. { Nonfatal errors (we can keep going, but the data is probably corrupt) }
  142. procedure WARNMS(cinfo : j_common_ptr; code : J_MESSAGE_CODE);
  143. begin
  144. cinfo^.err^.msg_code := ord(code);
  145. cinfo^.err^.emit_message(cinfo, -1);
  146. end;
  147. procedure WARNMS1(cinfo : j_common_ptr;code : J_MESSAGE_CODE; p1 : int);
  148. begin
  149. cinfo^.err^.msg_code := ord(code);
  150. cinfo^.err^.msg_parm.i[0] := p1;
  151. cinfo^.err^.emit_message (cinfo, -1);
  152. end;
  153. procedure WARNMS2(cinfo : j_common_ptr; code : J_MESSAGE_CODE;
  154. p1 : int; p2 : int);
  155. begin
  156. cinfo^.err^.msg_code := ord(code);
  157. cinfo^.err^.msg_parm.i[0] := p1;
  158. cinfo^.err^.msg_parm.i[1] := p2;
  159. cinfo^.err^.emit_message (cinfo, -1);
  160. end;
  161. { Informational/debugging messages }
  162. procedure TRACEMS(cinfo : j_common_ptr; lvl : int; code : J_MESSAGE_CODE);
  163. begin
  164. cinfo^.err^.msg_code := ord(code);
  165. cinfo^.err^.emit_message(cinfo, lvl);
  166. end;
  167. procedure TRACEMS1(cinfo : j_common_ptr; lvl : int;
  168. code : J_MESSAGE_CODE; p1 : long);
  169. begin
  170. cinfo^.err^.msg_code := ord(code);
  171. cinfo^.err^.msg_parm.i[0] := p1;
  172. cinfo^.err^.emit_message (cinfo, lvl);
  173. end;
  174. procedure TRACEMS2(cinfo : j_common_ptr; lvl : int; code : J_MESSAGE_CODE;
  175. p1 : int;
  176. p2 : int);
  177. begin
  178. cinfo^.err^.msg_code := ord(code);
  179. cinfo^.err^.msg_parm.i[0] := p1;
  180. cinfo^.err^.msg_parm.i[1] := p2;
  181. cinfo^.err^.emit_message (cinfo, lvl);
  182. end;
  183. procedure TRACEMS3(cinfo : j_common_ptr;
  184. lvl : int;
  185. code : J_MESSAGE_CODE;
  186. p1 : int; p2 : int; p3 : int);
  187. var
  188. _mp : int8array;
  189. begin
  190. _mp[0] := p1; _mp[1] := p2; _mp[2] := p3;
  191. cinfo^.err^.msg_parm.i := _mp;
  192. cinfo^.err^.msg_code := ord(code);
  193. cinfo^.err^.emit_message (cinfo, lvl);
  194. end;
  195. procedure TRACEMS4(cinfo : j_common_ptr; lvl : int; code : J_MESSAGE_CODE;
  196. p1 : int; p2 : int; p3 : int; p4 : int);
  197. var
  198. _mp : int8array;
  199. begin
  200. _mp[0] := p1; _mp[1] := p2; _mp[2] := p3; _mp[3] := p4;
  201. cinfo^.err^.msg_parm.i := _mp;
  202. cinfo^.err^.msg_code := ord(code);
  203. cinfo^.err^.emit_message (cinfo, lvl);
  204. end;
  205. procedure TRACEMS5(cinfo : j_common_ptr; lvl : int; code : J_MESSAGE_CODE;
  206. p1 : int; p2 : int; p3 : int; p4 : int; p5 : int);
  207. var
  208. _mp : ^int8array;
  209. begin
  210. _mp := @cinfo^.err^.msg_parm.i;
  211. _mp^[0] := p1; _mp^[1] := p2; _mp^[2] := p3;
  212. _mp^[3] := p4; _mp^[5] := p5;
  213. cinfo^.err^.msg_code := ord(code);
  214. cinfo^.err^.emit_message (cinfo, lvl);
  215. end;
  216. procedure TRACEMS8(cinfo : j_common_ptr; lvl : int; code : J_MESSAGE_CODE;
  217. p1 : int; p2 : int; p3 : int; p4 : int;
  218. p5 : int; p6 : int; p7 : int; p8 : int);
  219. var
  220. _mp : int8array;
  221. begin
  222. _mp[0] := p1; _mp[1] := p2; _mp[2] := p3; _mp[3] := p4;
  223. _mp[4] := p5; _mp[5] := p6; _mp[6] := p7; _mp[7] := p8;
  224. cinfo^.err^.msg_parm.i := _mp;
  225. cinfo^.err^.msg_code := ord(code);
  226. cinfo^.err^.emit_message (cinfo, lvl);
  227. end;
  228. procedure TRACEMSS(cinfo : j_common_ptr; lvl : int;
  229. code : J_MESSAGE_CODE; str : string);
  230. begin
  231. cinfo^.err^.msg_code := ord(code);
  232. cinfo^.err^.msg_parm.s := str; { string JMSG_STR_PARM_MAX }
  233. cinfo^.err^.emit_message (cinfo, lvl);
  234. end;
  235. {METHODDEF}
  236. procedure output_message (cinfo : j_common_ptr); far;
  237. var
  238. buffer : string; {[JMSG_LENGTH_MAX];}
  239. begin
  240. { Create the message }
  241. cinfo^.err^.format_message (cinfo, buffer);
  242. { Send it to stderr, adding a newline }
  243. WriteLn(output, buffer);
  244. end;
  245. { Decide whether to emit a trace or warning message.
  246. msg_level is one of:
  247. -1: recoverable corrupt-data warning, may want to abort.
  248. 0: important advisory messages (always display to user).
  249. 1: first level of tracing detail.
  250. 2,3,...: successively more detailed tracing messages.
  251. An application might override this method if it wanted to abort on warnings
  252. or change the policy about which messages to display. }
  253. {METHODDEF}
  254. procedure emit_message (cinfo : j_common_ptr; msg_level : int); far;
  255. var
  256. err : jpeg_error_mgr_ptr;
  257. begin
  258. err := cinfo^.err;
  259. if (msg_level < 0) then
  260. begin
  261. { It's a warning message. Since corrupt files may generate many warnings,
  262. the policy implemented here is to show only the first warning,
  263. unless trace_level >= 3. }
  264. if (err^.num_warnings = 0) or (err^.trace_level >= 3) then
  265. err^.output_message(cinfo);
  266. { Always count warnings in num_warnings. }
  267. Inc( err^.num_warnings );
  268. end
  269. else
  270. begin
  271. { It's a trace message. Show it if trace_level >= msg_level. }
  272. if (err^.trace_level >= msg_level) then
  273. err^.output_message (cinfo);
  274. end;
  275. end;
  276. { Format a message string for the most recent JPEG error or message.
  277. The message is stored into buffer, which should be at least JMSG_LENGTH_MAX
  278. characters. Note that no '\n' character is added to the string.
  279. Few applications should need to override this method. }
  280. {METHODDEF}
  281. procedure format_message (cinfo : j_common_ptr; var buffer : string); far;
  282. var
  283. err : jpeg_error_mgr_ptr;
  284. msg_code : J_MESSAGE_CODE;
  285. msgtext : string;
  286. isstring : boolean;
  287. begin
  288. err := cinfo^.err;
  289. msg_code := J_MESSAGE_CODE(err^.msg_code);
  290. msgtext := '';
  291. { Look up message string in proper table }
  292. if (msg_code > JMSG_NOMESSAGE)
  293. and (msg_code <= J_MESSAGE_CODE(err^.last_jpeg_message)) then
  294. begin
  295. msgtext := err^.jpeg_message_table^[msg_code];
  296. end
  297. else
  298. if (err^.addon_message_table <> NIL) and
  299. (msg_code >= err^.first_addon_message) and
  300. (msg_code <= err^.last_addon_message) then
  301. begin
  302. msgtext := err^.addon_message_table^[J_MESSAGE_CODE
  303. (ord(msg_code) - ord(err^.first_addon_message))];
  304. end;
  305. { Defend against bogus message number }
  306. if (msgtext = '') then
  307. begin
  308. err^.msg_parm.i[0] := int(msg_code);
  309. msgtext := err^.jpeg_message_table^[JMSG_NOMESSAGE];
  310. end;
  311. { Check for string parameter, as indicated by %s in the message text }
  312. isstring := Pos('%s', msgtext) > 0;
  313. { Format the message into the passed buffer }
  314. if (isstring) then
  315. buffer := Concat(msgtext, err^.msg_parm.s)
  316. else
  317. begin
  318. {$IFDEF VER70}
  319. FormatStr(buffer, msgtext, err^.msg_parm.i);
  320. {$ELSE}
  321. {$IFDEF NO_FORMAT}
  322. buffer := msgtext;
  323. {$ELSE}
  324. buffer := Format(msgtext, [
  325. err^.msg_parm.i[0], err^.msg_parm.i[1],
  326. err^.msg_parm.i[2], err^.msg_parm.i[3],
  327. err^.msg_parm.i[4], err^.msg_parm.i[5],
  328. err^.msg_parm.i[6], err^.msg_parm.i[7] ]);
  329. {$ENDIF}
  330. {$ENDIF}
  331. end;
  332. end;
  333. { Reset error state variables at start of a new image.
  334. This is called during compression startup to reset trace/error
  335. processing to default state, without losing any application-specific
  336. method pointers. An application might possibly want to override
  337. this method if it has additional error processing state. }
  338. {METHODDEF}
  339. procedure reset_error_mgr (cinfo : j_common_ptr); far;
  340. begin
  341. cinfo^.err^.num_warnings := 0;
  342. { trace_level is not reset since it is an application-supplied parameter }
  343. cinfo^.err^.msg_code := 0; { may be useful as a flag for "no error" }
  344. end;
  345. { Fill in the standard error-handling methods in a jpeg_error_mgr object.
  346. Typical call is:
  347. cinfo : jpeg_compress_struct;
  348. err : jpeg_error_mgr;
  349. cinfo.err := jpeg_std_error(@err);
  350. after which the application may override some of the methods. }
  351. {GLOBAL}
  352. function jpeg_std_error (var err : jpeg_error_mgr) : jpeg_error_mgr_ptr;
  353. begin
  354. err.error_exit := error_exit;
  355. err.emit_message := emit_message;
  356. err.output_message := output_message;
  357. err.format_message := format_message;
  358. err.reset_error_mgr := reset_error_mgr;
  359. err.trace_level := 0; { default := no tracing }
  360. err.num_warnings := 0; { no warnings emitted yet }
  361. err.msg_code := 0; { may be useful as a flag for "no error" }
  362. { Initialize message table pointers }
  363. err.jpeg_message_table := @jpeg_std_message_table;
  364. err.last_jpeg_message := pred(JMSG_LASTMSGCODE);
  365. err.addon_message_table := NIL;
  366. err.first_addon_message := JMSG_NOMESSAGE; { for safety }
  367. err.last_addon_message := JMSG_NOMESSAGE;
  368. jpeg_std_error := @err;
  369. end;
  370. end.