Back to index

lightning-sunbird  0.9+nobinonly
jmemdos.c
Go to the documentation of this file.
00001 /*
00002  * jmemdos.c
00003  *
00004  * Copyright (C) 1992-1997, Thomas G. Lane.
00005  * This file is part of the Independent JPEG Group's software.
00006  * For conditions of distribution and use, see the accompanying README file.
00007  *
00008  * This file provides an MS-DOS-compatible implementation of the system-
00009  * dependent portion of the JPEG memory manager.  Temporary data can be
00010  * stored in extended or expanded memory as well as in regular DOS files.
00011  *
00012  * If you use this file, you must be sure that NEED_FAR_POINTERS is defined
00013  * if you compile in a small-data memory model; it should NOT be defined if
00014  * you use a large-data memory model.  This file is not recommended if you
00015  * are using a flat-memory-space 386 environment such as DJGCC or Watcom C.
00016  * Also, this code will NOT work if struct fields are aligned on greater than
00017  * 2-byte boundaries.
00018  *
00019  * Based on code contributed by Ge' Weijers.
00020  */
00021 
00022 /*
00023  * If you have both extended and expanded memory, you may want to change the
00024  * order in which they are tried in jopen_backing_store.  On a 286 machine
00025  * expanded memory is usually faster, since extended memory access involves
00026  * an expensive protected-mode-and-back switch.  On 386 and better, extended
00027  * memory is usually faster.  As distributed, the code tries extended memory
00028  * first (what? not everyone has a 386? :-).
00029  *
00030  * You can disable use of extended/expanded memory entirely by altering these
00031  * definitions or overriding them from the Makefile (eg, -DEMS_SUPPORTED=0).
00032  */
00033 
00034 #ifndef XMS_SUPPORTED
00035 #define XMS_SUPPORTED  1
00036 #endif
00037 #ifndef EMS_SUPPORTED
00038 #define EMS_SUPPORTED  1
00039 #endif
00040 
00041 
00042 #define JPEG_INTERNALS
00043 #include "jinclude.h"
00044 #include "jpeglib.h"
00045 #include "jmemsys.h"        /* import the system-dependent declarations */
00046 
00047 #ifndef HAVE_STDLIB_H              /* <stdlib.h> should declare these */
00048 extern void * malloc JPP((size_t size));
00049 extern void free JPP((void *ptr));
00050 extern char * getenv JPP((const char * name));
00051 #endif
00052 
00053 #ifdef NEED_FAR_POINTERS
00054 
00055 #ifdef __TURBOC__
00056 /* These definitions work for Borland C (Turbo C) */
00057 #include <alloc.h>          /* need farmalloc(), farfree() */
00058 #define far_malloc(x)       farmalloc(x)
00059 #define far_free(x)  farfree(x)
00060 #else
00061 /* These definitions work for Microsoft C and compatible compilers */
00062 #include <malloc.h>         /* need _fmalloc(), _ffree() */
00063 #define far_malloc(x)       _fmalloc(x)
00064 #define far_free(x)  _ffree(x)
00065 #endif
00066 
00067 #else /* not NEED_FAR_POINTERS */
00068 
00069 #define far_malloc(x)       malloc(x)
00070 #define far_free(x)  free(x)
00071 
00072 #endif /* NEED_FAR_POINTERS */
00073 
00074 #ifdef DONT_USE_B_MODE             /* define mode parameters for fopen() */
00075 #define READ_BINARY  "r"
00076 #else
00077 #define READ_BINARY  "rb"
00078 #endif
00079 
00080 #ifndef USE_MSDOS_MEMMGR    /* make sure user got configuration right */
00081   You forgot to define USE_MSDOS_MEMMGR in jconfig.h. /* deliberate syntax error */
00082 #endif
00083 
00084 #if MAX_ALLOC_CHUNK >= 65535L      /* make sure jconfig.h got this right */
00085   MAX_ALLOC_CHUNK should be less than 64K. /* deliberate syntax error */
00086 #endif
00087 
00088 
00089 /*
00090  * Declarations for assembly-language support routines (see jmemdosa.asm).
00091  *
00092  * The functions are declared "far" as are all their pointer arguments;
00093  * this ensures the assembly source code will work regardless of the
00094  * compiler memory model.  We assume "short" is 16 bits, "long" is 32.
00095  */
00096 
00097 typedef void far * XMSDRIVER;      /* actually a pointer to code */
00098 typedef struct {            /* registers for calling XMS driver */
00099        unsigned short ax, dx, bx;
00100        void far * ds_si;
00101       } XMScontext;
00102 typedef struct {            /* registers for calling EMS driver */
00103        unsigned short ax, dx, bx;
00104        void far * ds_si;
00105       } EMScontext;
00106 
00107 extern short far jdos_open JPP((short far * handle, char far * filename));
00108 extern short far jdos_close JPP((short handle));
00109 extern short far jdos_seek JPP((short handle, long offset));
00110 extern short far jdos_read JPP((short handle, void far * buffer,
00111                             unsigned short count));
00112 extern short far jdos_write JPP((short handle, void far * buffer,
00113                              unsigned short count));
00114 extern void far jxms_getdriver JPP((XMSDRIVER far *));
00115 extern void far jxms_calldriver JPP((XMSDRIVER, XMScontext far *));
00116 extern short far jems_available JPP((void));
00117 extern void far jems_calldriver JPP((EMScontext far *));
00118 
00119 
00120 /*
00121  * Selection of a file name for a temporary file.
00122  * This is highly system-dependent, and you may want to customize it.
00123  */
00124 
00125 static int next_file_num;   /* to distinguish among several temp files */
00126 
00127 LOCAL(void)
00128 select_file_name (char * fname)
00129 {
00130   const char * env;
00131   char * ptr;
00132   FILE * tfile;
00133 
00134   /* Keep generating file names till we find one that's not in use */
00135   for (;;) {
00136     /* Get temp directory name from environment TMP or TEMP variable;
00137      * if none, use "."
00138      */
00139     if ((env = (const char *) getenv("TMP")) == NULL)
00140       if ((env = (const char *) getenv("TEMP")) == NULL)
00141        env = ".";
00142     if (*env == '\0')              /* null string means "." */
00143       env = ".";
00144     ptr = fname;            /* copy name to fname */
00145     while (*env != '\0')
00146       *ptr++ = *env++;
00147     if (ptr[-1] != '\\' && ptr[-1] != '/')
00148       *ptr++ = '\\';        /* append backslash if not in env variable */
00149     /* Append a suitable file name */
00150     next_file_num++;        /* advance counter */
00151     sprintf(ptr, "JPG%03d.TMP", next_file_num);
00152     /* Probe to see if file name is already in use */
00153     if ((tfile = fopen(fname, READ_BINARY)) == NULL)
00154       break;
00155     fclose(tfile);          /* oops, it's there; close tfile & try again */
00156   }
00157 }
00158 
00159 
00160 /*
00161  * Near-memory allocation and freeing are controlled by the regular library
00162  * routines malloc() and free().
00163  */
00164 
00165 GLOBAL(void *)
00166 jpeg_get_small (j_common_ptr cinfo, size_t sizeofobject)
00167 {
00168   return (void *) malloc(sizeofobject);
00169 }
00170 
00171 GLOBAL(void)
00172 jpeg_free_small (j_common_ptr cinfo, void * object, size_t sizeofobject)
00173 {
00174   free(object);
00175 }
00176 
00177 
00178 /*
00179  * "Large" objects are allocated in far memory, if possible
00180  */
00181 
00182 GLOBAL(void FAR *)
00183 jpeg_get_large (j_common_ptr cinfo, size_t sizeofobject)
00184 {
00185   return (void FAR *) far_malloc(sizeofobject);
00186 }
00187 
00188 GLOBAL(void)
00189 jpeg_free_large (j_common_ptr cinfo, void FAR * object, size_t sizeofobject)
00190 {
00191   far_free(object);
00192 }
00193 
00194 
00195 /*
00196  * This routine computes the total memory space available for allocation.
00197  * It's impossible to do this in a portable way; our current solution is
00198  * to make the user tell us (with a default value set at compile time).
00199  * If you can actually get the available space, it's a good idea to subtract
00200  * a slop factor of 5% or so.
00201  */
00202 
00203 #ifndef DEFAULT_MAX_MEM            /* so can override from makefile */
00204 #define DEFAULT_MAX_MEM            300000L /* for total usage about 450K */
00205 #endif
00206 
00207 GLOBAL(long)
00208 jpeg_mem_available (j_common_ptr cinfo, long min_bytes_needed,
00209                   long max_bytes_needed, long already_allocated)
00210 {
00211   return cinfo->mem->max_memory_to_use - already_allocated;
00212 }
00213 
00214 
00215 /*
00216  * Backing store (temporary file) management.
00217  * Backing store objects are only used when the value returned by
00218  * jpeg_mem_available is less than the total space needed.  You can dispense
00219  * with these routines if you have plenty of virtual memory; see jmemnobs.c.
00220  */
00221 
00222 /*
00223  * For MS-DOS we support three types of backing storage:
00224  *   1. Conventional DOS files.  We access these by direct DOS calls rather
00225  *      than via the stdio package.  This provides a bit better performance,
00226  *      but the real reason is that the buffers to be read or written are FAR.
00227  *      The stdio library for small-data memory models can't cope with that.
00228  *   2. Extended memory, accessed per the XMS V2.0 specification.
00229  *   3. Expanded memory, accessed per the LIM/EMS 4.0 specification.
00230  * You'll need copies of those specs to make sense of the related code.
00231  * The specs are available by Internet FTP from the SIMTEL archives 
00232  * (oak.oakland.edu and its various mirror sites).  See files
00233  * pub/msdos/microsoft/xms20.arc and pub/msdos/info/limems41.zip.
00234  */
00235 
00236 
00237 /*
00238  * Access methods for a DOS file.
00239  */
00240 
00241 
00242 METHODDEF(void)
00243 read_file_store (j_common_ptr cinfo, backing_store_ptr info,
00244                void FAR * buffer_address,
00245                long file_offset, long byte_count)
00246 {
00247   if (jdos_seek(info->handle.file_handle, file_offset))
00248     ERREXIT(cinfo, JERR_TFILE_SEEK);
00249   /* Since MAX_ALLOC_CHUNK is less than 64K, byte_count will be too. */
00250   if (byte_count > 65535L)  /* safety check */
00251     ERREXIT(cinfo, JERR_BAD_ALLOC_CHUNK);
00252   if (jdos_read(info->handle.file_handle, buffer_address,
00253               (unsigned short) byte_count))
00254     ERREXIT(cinfo, JERR_TFILE_READ);
00255 }
00256 
00257 
00258 METHODDEF(void)
00259 write_file_store (j_common_ptr cinfo, backing_store_ptr info,
00260                 void FAR * buffer_address,
00261                 long file_offset, long byte_count)
00262 {
00263   if (jdos_seek(info->handle.file_handle, file_offset))
00264     ERREXIT(cinfo, JERR_TFILE_SEEK);
00265   /* Since MAX_ALLOC_CHUNK is less than 64K, byte_count will be too. */
00266   if (byte_count > 65535L)  /* safety check */
00267     ERREXIT(cinfo, JERR_BAD_ALLOC_CHUNK);
00268   if (jdos_write(info->handle.file_handle, buffer_address,
00269                (unsigned short) byte_count))
00270     ERREXIT(cinfo, JERR_TFILE_WRITE);
00271 }
00272 
00273 
00274 METHODDEF(void)
00275 close_file_store (j_common_ptr cinfo, backing_store_ptr info)
00276 {
00277   jdos_close(info->handle.file_handle);   /* close the file */
00278   remove(info->temp_name);  /* delete the file */
00279 /* If your system doesn't have remove(), try unlink() instead.
00280  * remove() is the ANSI-standard name for this function, but
00281  * unlink() was more common in pre-ANSI systems.
00282  */
00283   TRACEMSS(cinfo, 1, JTRC_TFILE_CLOSE, info->temp_name);
00284 }
00285 
00286 
00287 LOCAL(boolean)
00288 open_file_store (j_common_ptr cinfo, backing_store_ptr info,
00289                long total_bytes_needed)
00290 {
00291   short handle;
00292 
00293   select_file_name(info->temp_name);
00294   if (jdos_open((short far *) & handle, (char far *) info->temp_name)) {
00295     /* might as well exit since jpeg_open_backing_store will fail anyway */
00296     ERREXITS(cinfo, JERR_TFILE_CREATE, info->temp_name);
00297     return FALSE;
00298   }
00299   info->handle.file_handle = handle;
00300   info->read_backing_store = read_file_store;
00301   info->write_backing_store = write_file_store;
00302   info->close_backing_store = close_file_store;
00303   TRACEMSS(cinfo, 1, JTRC_TFILE_OPEN, info->temp_name);
00304   return TRUE;                     /* succeeded */
00305 }
00306 
00307 
00308 /*
00309  * Access methods for extended memory.
00310  */
00311 
00312 #if XMS_SUPPORTED
00313 
00314 static XMSDRIVER xms_driver;       /* saved address of XMS driver */
00315 
00316 typedef union {                    /* either long offset or real-mode pointer */
00317        long offset;
00318        void far * ptr;
00319       } XMSPTR;
00320 
00321 typedef struct {            /* XMS move specification structure */
00322        long length;
00323        XMSH src_handle;
00324        XMSPTR src;
00325        XMSH dst_handle;
00326        XMSPTR dst;
00327       } XMSspec;
00328 
00329 #define ODD(X)       (((X) & 1L) != 0)
00330 
00331 
00332 METHODDEF(void)
00333 read_xms_store (j_common_ptr cinfo, backing_store_ptr info,
00334               void FAR * buffer_address,
00335               long file_offset, long byte_count)
00336 {
00337   XMScontext ctx;
00338   XMSspec spec;
00339   char endbuffer[2];
00340 
00341   /* The XMS driver can't cope with an odd length, so handle the last byte
00342    * specially if byte_count is odd.  We don't expect this to be common.
00343    */
00344 
00345   spec.length = byte_count & (~ 1L);
00346   spec.src_handle = info->handle.xms_handle;
00347   spec.src.offset = file_offset;
00348   spec.dst_handle = 0;
00349   spec.dst.ptr = buffer_address;
00350   
00351   ctx.ds_si = (void far *) & spec;
00352   ctx.ax = 0x0b00;          /* EMB move */
00353   jxms_calldriver(xms_driver, (XMScontext far *) & ctx);
00354   if (ctx.ax != 1)
00355     ERREXIT(cinfo, JERR_XMS_READ);
00356 
00357   if (ODD(byte_count)) {
00358     read_xms_store(cinfo, info, (void FAR *) endbuffer,
00359                  file_offset + byte_count - 1L, 2L);
00360     ((char FAR *) buffer_address)[byte_count - 1L] = endbuffer[0];
00361   }
00362 }
00363 
00364 
00365 METHODDEF(void)
00366 write_xms_store (j_common_ptr cinfo, backing_store_ptr info,
00367                void FAR * buffer_address,
00368                long file_offset, long byte_count)
00369 {
00370   XMScontext ctx;
00371   XMSspec spec;
00372   char endbuffer[2];
00373 
00374   /* The XMS driver can't cope with an odd length, so handle the last byte
00375    * specially if byte_count is odd.  We don't expect this to be common.
00376    */
00377 
00378   spec.length = byte_count & (~ 1L);
00379   spec.src_handle = 0;
00380   spec.src.ptr = buffer_address;
00381   spec.dst_handle = info->handle.xms_handle;
00382   spec.dst.offset = file_offset;
00383 
00384   ctx.ds_si = (void far *) & spec;
00385   ctx.ax = 0x0b00;          /* EMB move */
00386   jxms_calldriver(xms_driver, (XMScontext far *) & ctx);
00387   if (ctx.ax != 1)
00388     ERREXIT(cinfo, JERR_XMS_WRITE);
00389 
00390   if (ODD(byte_count)) {
00391     read_xms_store(cinfo, info, (void FAR *) endbuffer,
00392                  file_offset + byte_count - 1L, 2L);
00393     endbuffer[0] = ((char FAR *) buffer_address)[byte_count - 1L];
00394     write_xms_store(cinfo, info, (void FAR *) endbuffer,
00395                   file_offset + byte_count - 1L, 2L);
00396   }
00397 }
00398 
00399 
00400 METHODDEF(void)
00401 close_xms_store (j_common_ptr cinfo, backing_store_ptr info)
00402 {
00403   XMScontext ctx;
00404 
00405   ctx.dx = info->handle.xms_handle;
00406   ctx.ax = 0x0a00;
00407   jxms_calldriver(xms_driver, (XMScontext far *) & ctx);
00408   TRACEMS1(cinfo, 1, JTRC_XMS_CLOSE, info->handle.xms_handle);
00409   /* we ignore any error return from the driver */
00410 }
00411 
00412 
00413 LOCAL(boolean)
00414 open_xms_store (j_common_ptr cinfo, backing_store_ptr info,
00415               long total_bytes_needed)
00416 {
00417   XMScontext ctx;
00418 
00419   /* Get address of XMS driver */
00420   jxms_getdriver((XMSDRIVER far *) & xms_driver);
00421   if (xms_driver == NULL)
00422     return FALSE;           /* no driver to be had */
00423 
00424   /* Get version number, must be >= 2.00 */
00425   ctx.ax = 0x0000;
00426   jxms_calldriver(xms_driver, (XMScontext far *) & ctx);
00427   if (ctx.ax < (unsigned short) 0x0200)
00428     return FALSE;
00429 
00430   /* Try to get space (expressed in kilobytes) */
00431   ctx.dx = (unsigned short) ((total_bytes_needed + 1023L) >> 10);
00432   ctx.ax = 0x0900;
00433   jxms_calldriver(xms_driver, (XMScontext far *) & ctx);
00434   if (ctx.ax != 1)
00435     return FALSE;
00436 
00437   /* Succeeded, save the handle and away we go */
00438   info->handle.xms_handle = ctx.dx;
00439   info->read_backing_store = read_xms_store;
00440   info->write_backing_store = write_xms_store;
00441   info->close_backing_store = close_xms_store;
00442   TRACEMS1(cinfo, 1, JTRC_XMS_OPEN, ctx.dx);
00443   return TRUE;                     /* succeeded */
00444 }
00445 
00446 #endif /* XMS_SUPPORTED */
00447 
00448 
00449 /*
00450  * Access methods for expanded memory.
00451  */
00452 
00453 #if EMS_SUPPORTED
00454 
00455 /* The EMS move specification structure requires word and long fields aligned
00456  * at odd byte boundaries.  Some compilers will align struct fields at even
00457  * byte boundaries.  While it's usually possible to force byte alignment,
00458  * that causes an overall performance penalty and may pose problems in merging
00459  * JPEG into a larger application.  Instead we accept some rather dirty code
00460  * here.  Note this code would fail if the hardware did not allow odd-byte
00461  * word & long accesses, but all 80x86 CPUs do.
00462  */
00463 
00464 typedef void far * EMSPTR;
00465 
00466 typedef union {                    /* EMS move specification structure */
00467        long length;         /* It's easy to access first 4 bytes */
00468        char bytes[18];             /* Misaligned fields in here! */
00469       } EMSspec;
00470 
00471 /* Macros for accessing misaligned fields */
00472 #define FIELD_AT(spec,offset,type)  (*((type *) &(spec.bytes[offset])))
00473 #define SRC_TYPE(spec)             FIELD_AT(spec,4,char)
00474 #define SRC_HANDLE(spec)    FIELD_AT(spec,5,EMSH)
00475 #define SRC_OFFSET(spec)    FIELD_AT(spec,7,unsigned short)
00476 #define SRC_PAGE(spec)             FIELD_AT(spec,9,unsigned short)
00477 #define SRC_PTR(spec)              FIELD_AT(spec,7,EMSPTR)
00478 #define DST_TYPE(spec)             FIELD_AT(spec,11,char)
00479 #define DST_HANDLE(spec)    FIELD_AT(spec,12,EMSH)
00480 #define DST_OFFSET(spec)    FIELD_AT(spec,14,unsigned short)
00481 #define DST_PAGE(spec)             FIELD_AT(spec,16,unsigned short)
00482 #define DST_PTR(spec)              FIELD_AT(spec,14,EMSPTR)
00483 
00484 #define EMSPAGESIZE  16384L /* gospel, see the EMS specs */
00485 
00486 #define HIBYTE(W)  (((W) >> 8) & 0xFF)
00487 #define LOBYTE(W)  ((W) & 0xFF)
00488 
00489 
00490 METHODDEF(void)
00491 read_ems_store (j_common_ptr cinfo, backing_store_ptr info,
00492               void FAR * buffer_address,
00493               long file_offset, long byte_count)
00494 {
00495   EMScontext ctx;
00496   EMSspec spec;
00497 
00498   spec.length = byte_count;
00499   SRC_TYPE(spec) = 1;
00500   SRC_HANDLE(spec) = info->handle.ems_handle;
00501   SRC_PAGE(spec)   = (unsigned short) (file_offset / EMSPAGESIZE);
00502   SRC_OFFSET(spec) = (unsigned short) (file_offset % EMSPAGESIZE);
00503   DST_TYPE(spec) = 0;
00504   DST_HANDLE(spec) = 0;
00505   DST_PTR(spec)    = buffer_address;
00506   
00507   ctx.ds_si = (void far *) & spec;
00508   ctx.ax = 0x5700;          /* move memory region */
00509   jems_calldriver((EMScontext far *) & ctx);
00510   if (HIBYTE(ctx.ax) != 0)
00511     ERREXIT(cinfo, JERR_EMS_READ);
00512 }
00513 
00514 
00515 METHODDEF(void)
00516 write_ems_store (j_common_ptr cinfo, backing_store_ptr info,
00517                void FAR * buffer_address,
00518                long file_offset, long byte_count)
00519 {
00520   EMScontext ctx;
00521   EMSspec spec;
00522 
00523   spec.length = byte_count;
00524   SRC_TYPE(spec) = 0;
00525   SRC_HANDLE(spec) = 0;
00526   SRC_PTR(spec)    = buffer_address;
00527   DST_TYPE(spec) = 1;
00528   DST_HANDLE(spec) = info->handle.ems_handle;
00529   DST_PAGE(spec)   = (unsigned short) (file_offset / EMSPAGESIZE);
00530   DST_OFFSET(spec) = (unsigned short) (file_offset % EMSPAGESIZE);
00531   
00532   ctx.ds_si = (void far *) & spec;
00533   ctx.ax = 0x5700;          /* move memory region */
00534   jems_calldriver((EMScontext far *) & ctx);
00535   if (HIBYTE(ctx.ax) != 0)
00536     ERREXIT(cinfo, JERR_EMS_WRITE);
00537 }
00538 
00539 
00540 METHODDEF(void)
00541 close_ems_store (j_common_ptr cinfo, backing_store_ptr info)
00542 {
00543   EMScontext ctx;
00544 
00545   ctx.ax = 0x4500;
00546   ctx.dx = info->handle.ems_handle;
00547   jems_calldriver((EMScontext far *) & ctx);
00548   TRACEMS1(cinfo, 1, JTRC_EMS_CLOSE, info->handle.ems_handle);
00549   /* we ignore any error return from the driver */
00550 }
00551 
00552 
00553 LOCAL(boolean)
00554 open_ems_store (j_common_ptr cinfo, backing_store_ptr info,
00555               long total_bytes_needed)
00556 {
00557   EMScontext ctx;
00558 
00559   /* Is EMS driver there? */
00560   if (! jems_available())
00561     return FALSE;
00562 
00563   /* Get status, make sure EMS is OK */
00564   ctx.ax = 0x4000;
00565   jems_calldriver((EMScontext far *) & ctx);
00566   if (HIBYTE(ctx.ax) != 0)
00567     return FALSE;
00568 
00569   /* Get version, must be >= 4.0 */
00570   ctx.ax = 0x4600;
00571   jems_calldriver((EMScontext far *) & ctx);
00572   if (HIBYTE(ctx.ax) != 0 || LOBYTE(ctx.ax) < 0x40)
00573     return FALSE;
00574 
00575   /* Try to allocate requested space */
00576   ctx.ax = 0x4300;
00577   ctx.bx = (unsigned short) ((total_bytes_needed + EMSPAGESIZE-1L) / EMSPAGESIZE);
00578   jems_calldriver((EMScontext far *) & ctx);
00579   if (HIBYTE(ctx.ax) != 0)
00580     return FALSE;
00581 
00582   /* Succeeded, save the handle and away we go */
00583   info->handle.ems_handle = ctx.dx;
00584   info->read_backing_store = read_ems_store;
00585   info->write_backing_store = write_ems_store;
00586   info->close_backing_store = close_ems_store;
00587   TRACEMS1(cinfo, 1, JTRC_EMS_OPEN, ctx.dx);
00588   return TRUE;                     /* succeeded */
00589 }
00590 
00591 #endif /* EMS_SUPPORTED */
00592 
00593 
00594 /*
00595  * Initial opening of a backing-store object.
00596  */
00597 
00598 GLOBAL(void)
00599 jpeg_open_backing_store (j_common_ptr cinfo, backing_store_ptr info,
00600                       long total_bytes_needed)
00601 {
00602   /* Try extended memory, then expanded memory, then regular file. */
00603 #if XMS_SUPPORTED
00604   if (open_xms_store(cinfo, info, total_bytes_needed))
00605     return;
00606 #endif
00607 #if EMS_SUPPORTED
00608   if (open_ems_store(cinfo, info, total_bytes_needed))
00609     return;
00610 #endif
00611   if (open_file_store(cinfo, info, total_bytes_needed))
00612     return;
00613   ERREXITS(cinfo, JERR_TFILE_CREATE, "");
00614 }
00615 
00616 
00617 /*
00618  * These routines take care of any system-dependent initialization and
00619  * cleanup required.
00620  */
00621 
00622 GLOBAL(long)
00623 jpeg_mem_init (j_common_ptr cinfo)
00624 {
00625   next_file_num = 0;        /* initialize temp file name generator */
00626   return DEFAULT_MAX_MEM;   /* default for max_memory_to_use */
00627 }
00628 
00629 GLOBAL(void)
00630 jpeg_mem_term (j_common_ptr cinfo)
00631 {
00632   /* Microsoft C, at least in v6.00A, will not successfully reclaim freed
00633    * blocks of size > 32Kbytes unless we give it a kick in the rear, like so:
00634    */
00635 #ifdef NEED_FHEAPMIN
00636   _fheapmin();
00637 #endif
00638 }