home *** CD-ROM | disk | FTP | other *** search
/ Amiga Elysian Archive / AmigaElysianArchive.iso / newc_dev / du10.lha / du / du.c < prev    next >
C/C++ Source or Header  |  1992-11-01  |  17KB  |  761 lines

  1.  
  2. /*
  3.  *  du.c
  4.  *
  5.  *  Author: Georg Hessmann (hessmann@fmi.uni-passau-de)
  6.  *
  7.  *  Copyright: source is public domain, no copyright
  8.  *
  9.  *  Version history:
  10.  *
  11.  *  1.0  01.Nov.92  First release.
  12.  *
  13.  */
  14.  
  15.  
  16. #define VERSION "1.0"
  17.  
  18. static const char version[] = "\0$VER: du " VERSION " (11/01/92)";
  19.  
  20.  
  21.  
  22.  
  23. #define SysBase        pb->pb_SysBase
  24. #define DOSBase        pb->pb_DOSBase
  25. #define UtilityBase    pb->pb_UtilityBase
  26.  
  27. #undef __USE_SYSBASE
  28. #define NOINFO
  29.  
  30.  
  31. /*
  32.  * Amiga-Includes
  33.  */
  34.  
  35. #include <exec/types.h>
  36. #include <exec/lists.h>
  37. #include <exec/memory.h>
  38. #include <dos/dos.h>
  39. #include <dos/dosasl.h>
  40. #include <dos/exall.h>
  41.  
  42. #include <clib/exec_protos.h>
  43. #include <clib/dos_protos.h>
  44. #include <clib/utility_protos.h>
  45. #if defined(__SASC_60) && defined(__USE_SYSBASE)
  46. # include <pragmas/exec_sysbase_pragmas.h>
  47. #else
  48. # include <pragmas/exec_pragmas.h>
  49. #endif
  50. #include <pragmas/dos_pragmas.h>
  51. #include <pragmas/utility_pragmas.h>
  52.  
  53.  
  54. #pragma libcall DOSBase ParsePatternNoCase 3C6 32103
  55. #pragma libcall DOSBase ExAllEnd 3DE 5432105
  56.  
  57.  
  58.  
  59. /*
  60.  * Define SAS/C builtin function
  61.  */
  62.  
  63. #define strlen __builtin_strlen
  64. #define memset __builtin_memset
  65. #define memcpy __builtin_memcpy
  66.  
  67. extern int strlen(char *);
  68. extern void *memset(void *, int, unsigned);
  69. extern void *memcpy(void *, void *, unsigned);
  70.  
  71.  
  72.  
  73. /*
  74.  * Define amiga.lib function.
  75.  */
  76.  
  77. void __stdargs NewList(struct List * list);
  78.  
  79.  
  80. /*
  81.  * Template for ReadArgs()
  82.  */
  83.  
  84. #if defined(NOINFO)
  85. # define TEMPLATE    "DIR/M,BYTE/S,KBYTE/S,ALL/S,SHORT/S,NOINFO/S"
  86. #else
  87. # define TEMPLATE    "DIR/M,BYTE/S,KBYTE/S,ALL/S,SHORT/S"
  88. #endif
  89.  
  90.  
  91.  
  92. /*
  93.  * Used error strings
  94.  */
  95.  
  96. #define MSG_NOT_FOUND    "%s not found\n"
  97. #define MSG_PAT_ERROR   "Error in pattern %s\n"
  98. #define MSG_NO_MEM      "Not enough memory\n"
  99. #define MSG_NO_EXAMINE  "Can't examine %s\n"
  100. #define MSG_NO_LOCK    "Can't lock %s\n"
  101. #define MSG_NO_NAMELOCK "Can't get name from lock\n"
  102.  
  103.  
  104. /*
  105.  * Usefull macro to check Ctrl-C
  106.  */
  107.  
  108. #define IsCtrlC        (SetSignal(0L,SIGBREAKF_CTRL_C) & SIGBREAKF_CTRL_C)
  109.  
  110.  
  111. /*
  112.  * Stack of the 'to processed' directories
  113.  */
  114.  
  115. struct DirStack {
  116.   struct Node   ds_Node;
  117.   short         ds_Pad;
  118.   BPTR          ds_Lock;
  119.   long          ds_Size;        /* bytes */
  120.   long          ds_Blocks;
  121.   struct List   ds_Childs;        /* Unterdirectories (falls vorhanden) */
  122. };
  123.  
  124.  
  125. /*
  126.  * Defines the current path
  127.  */
  128.  
  129. struct CurPath {
  130.   struct Node   cp_Node;
  131.   char        * cp_Path;
  132. };
  133.  
  134.  
  135. /*
  136.  * List of all allocated memory
  137.  */
  138.  
  139. struct MemLst {
  140.   void          * ml_Data;
  141.   long            ml_Size;
  142.   struct MemLst * ml_Next;
  143. };
  144.  
  145.  
  146. /*
  147.  * Structure of all pseudo global variables
  148.  */
  149.  
  150. enum pval   { blocks, bytes, kbytes };
  151.  
  152. struct ParamBlock {
  153.   struct Library       * pb_DOSBase;
  154.   struct Library       * pb_SysBase;
  155.   struct Library       * pb_UtilityBase;
  156.   int                    pb_BlockSize;
  157.   struct ExAllControl  * pb_EAC;
  158.   struct FileInfoBlock * pb_Fib;
  159.   enum pval              pb_PrtVal;
  160.   int                    pb_All;
  161.   int                    pb_Short;
  162.   int                    pb_PrintIt;    // fuer SHORT
  163. #if defined(NOINFO)
  164.   int                    pb_NoInfo;
  165. #endif
  166.   int                    pb_NeedSlash;
  167.   struct List            pb_Path;
  168.   int                    pb_EASize;
  169.   char                 * pb_EAData;
  170.   char                 * pb_MemHandle;
  171.   char                 * pb_MemEnd;    // zeigt auf das letzte Byte
  172.   char                 * pb_CurMem;
  173.   struct MemLst        * pb_MemList;
  174. };
  175.  
  176.  
  177.  
  178. /*
  179.  * Prototypes of the help functions
  180.  */
  181.  
  182. static int  DoDir        (struct ParamBlock * pb, char * name);
  183. static int  ListOneTree  (struct ParamBlock * pb, struct DirStack * ds, BPTR lock);
  184. static int  ListOneDir   (struct ParamBlock * pb, struct DirStack * ds, BPTR lock);
  185. static int  InsertNewDir (struct ParamBlock * pb, struct DirStack * ds, char * name);
  186. static int  AppendPath   (struct ParamBlock * pb, struct DirStack * ds);
  187. static void PrintPath    (struct ParamBlock * pb);
  188. static int  PrintIt      (struct ParamBlock * pb, long blk, long bte, char * name);
  189. static char * MyStrDup   (struct ParamBlock * pb, char * str);
  190. static void * MyAlloc    (struct ParamBlock * pb, long size);
  191. static void MyFree       (struct ParamBlock * pb);
  192.  
  193.  
  194.  
  195.  
  196. /*
  197.  * Main function. Must be the first in the module.
  198.  */
  199.  
  200. int __saveds du(void)
  201. {
  202.   long rc = RETURN_OK;
  203.   long options[6];
  204.   struct RDArgs * args;
  205.   char * PatBuf = NULL;
  206.   struct FileInfoBlock __aligned fib;  // wird nur an pb weiter gereicht
  207.   struct ParamBlock Params;
  208.   struct ParamBlock * pb = &Params;
  209.  
  210. #if defined(__USE_SYSBASE) || !defined(__SASC_60)
  211.   Params.pb_SysBase  = *(struct Library **)(4);
  212. #endif
  213.   Params.pb_DOSBase     = OpenLibrary("dos.library", 37);
  214.   Params.pb_UtilityBase = OpenLibrary("utility.library", 37);
  215.   if (!Params.pb_DOSBase || !Params.pb_UtilityBase) return RETURN_FAIL;
  216.  
  217.   Params.pb_MemHandle = NULL;
  218.   Params.pb_MemEnd    = NULL;
  219.   Params.pb_CurMem    = NULL;
  220.   Params.pb_MemList   = NULL;
  221.   Params.pb_EAData    = MyAlloc(pb, 2000);
  222.   Params.pb_EASize    = 2000;
  223.   Params.pb_Fib       = &fib;
  224.   Params.pb_PrtVal    = blocks;
  225.   Params.pb_PrintIt   = TRUE;
  226.  
  227.   memset(options, 0, sizeof(options));
  228.  
  229.   args = ReadArgs(TEMPLATE, options, NULL);
  230.   if (args) {
  231.     char ** dirs = (char **)options[0];
  232.     char * NoArg[2];            
  233.  
  234.     Params.pb_EAC = AllocDosObject(DOS_EXALLCONTROL, NULL);
  235.     if (Params.pb_EAC) {
  236.  
  237.       if (options[1]) Params.pb_PrtVal = bytes;
  238.       if (options[2]) Params.pb_PrtVal = kbytes;
  239.       Params.pb_All       = options[3];
  240.       Params.pb_Short     = options[4];
  241. #if defined(NOINFO)
  242.       Params.pb_NoInfo    = options[5];
  243. #endif
  244.       
  245.       if (Params.pb_EAData) {
  246.       
  247.         if (!dirs) {
  248.           // wenn keine Argumente angegeben, dann Name des akt. Dirs. verwenden
  249.           char * namebuf = MyAlloc(pb, 500);
  250.           if (!namebuf) {
  251.               PutStr(MSG_NO_MEM);
  252.               rc = RETURN_ERROR;
  253.           }
  254.           else {
  255.             BPTR lock = Lock("", ACCESS_READ);
  256.             if (!lock) {
  257.               char * temp = "\"\"";
  258.               VPrintf(MSG_NO_LOCK, (long *)&temp);
  259.               rc = RETURN_ERROR;
  260.             }
  261.             else {
  262.               if (!NameFromLock(lock, namebuf, 499)) {
  263.                 PutStr(MSG_NO_NAMELOCK);
  264.                 rc = RETURN_ERROR;
  265.               }
  266.               else {
  267.                 NoArg[0] = namebuf;        // Name des aktuellen Directories
  268.                 NoArg[1] = NULL;
  269.                 dirs = NoArg;
  270.               }
  271.               UnLock(lock);
  272.             }
  273.           }
  274.         }
  275.  
  276.         if (rc == RETURN_OK) {
  277.           char * ptr;
  278.   
  279.           for (; ptr = *dirs; dirs++) {
  280.             int isWild;
  281.  
  282.             if (PatBuf == NULL) PatBuf = MyAlloc(pb, 1024);
  283.             if (PatBuf == NULL) {
  284.               PutStr(MSG_NO_MEM);
  285.               rc = RETURN_ERROR;
  286.               break;
  287.             }
  288.             isWild = ParsePatternNoCase(ptr, PatBuf, 1023);
  289.             
  290.             if (isWild < 0) {
  291.               VPrintf(MSG_PAT_ERROR, (long*)&ptr);
  292.               rc = RETURN_ERROR;
  293.               break;
  294.             }
  295.             else {
  296.               if (isWild == 0) {
  297.                 // Kein Pattern
  298.                 rc = DoDir(pb, ptr);
  299.                 if (rc != RETURN_OK) break;
  300.               }
  301.               else {
  302.                 // Pattern
  303.                 char __aligned buf[sizeof(struct AnchorPath)+200];
  304.                 struct AnchorPath * ap = (struct AnchorPath *)buf;
  305.  
  306.                 memset(ap, 0, sizeof(struct AnchorPath));
  307.                 ap->ap_Strlen = 200;
  308.  
  309.                 if (MatchFirst(PatBuf, ap) == 0) {
  310.                   rc = DoDir(pb, ap->ap_Buf);
  311.                   while (rc == RETURN_OK && MatchNext(ap) == 0) {
  312.                     rc = DoDir(pb, ap->ap_Buf);
  313.                     if (rc != RETURN_OK) MatchEnd(ap);
  314.                   }
  315.                   if (rc != RETURN_OK) break;
  316.                 }
  317.               }
  318.             }
  319.  
  320.           }
  321.           FreeArgs(args);
  322.         }
  323.       }
  324.       else {
  325.         PutStr(MSG_NO_MEM);
  326.         rc = RETURN_ERROR;
  327.       }
  328.  
  329.       FreeDosObject(DOS_EXALLCONTROL, Params.pb_EAC);
  330.     }
  331.     else {
  332.       PutStr(MSG_NO_MEM);
  333.       rc = RETURN_ERROR;
  334.     }
  335.  
  336.     MyFree(pb);
  337.  
  338.   }
  339.   else {
  340.     PrintFault(IoErr(), NULL);
  341.     rc = RETURN_ERROR;
  342.   }
  343.   
  344.   CloseLibrary(DOSBase);
  345.  
  346.   return rc;
  347. }
  348.  
  349.  
  350.  
  351. /*
  352.  * DoDir()
  353.  *
  354.  * Main function to 'du' one directory or file.
  355.  *
  356.  */
  357.  
  358. static int DoDir(struct ParamBlock * pb, char * name)
  359. {
  360.   long ret = RETURN_OK;
  361.   BPTR lock;
  362.   struct DirStack   ds;
  363.   struct InfoData __aligned idata;
  364.  
  365.   memset(&ds, 0, sizeof(struct DirStack));
  366.   NewList(&ds.ds_Childs);
  367.  
  368.   pb->pb_PrintIt   = TRUE;
  369.   pb->pb_BlockSize = 512;
  370.   NewList(&pb->pb_Path);
  371.   
  372.   ds.ds_Node.ln_Name = name;
  373.   lock = Lock(name, ACCESS_READ);
  374.   
  375.   if (lock) {
  376.     if (Info(lock, &idata)) {
  377.       pb->pb_BlockSize = idata.id_BytesPerBlock;
  378.       //VPrintf("BS: %ld\n", (long*)&pb->pb_BlockSize);
  379.     }
  380.  
  381.     if (ListOneTree(pb, &ds, lock)) {
  382.       ret = RETURN_ERROR;
  383.     }
  384.     UnLock(lock);
  385.   }
  386.   else {
  387.     VPrintf(MSG_NOT_FOUND, (long*)&name);
  388.     ret = RETURN_ERROR;
  389.   }
  390.  
  391.   return ret;    
  392. }
  393.  
  394.  
  395.  
  396. /*
  397.  * ListOneTree()
  398.  *
  399.  * List one file or one directory.
  400.  * If the directory has sub-directory, ListOneTree()
  401.  * calls itself recursively.
  402.  *
  403.  */
  404.  
  405. static int ListOneTree(struct ParamBlock * pb, struct DirStack * ds, BPTR lock)
  406. {
  407.   register struct List * dl;
  408.   BPTR olock, nlock;
  409.   int ret;
  410.   int oPrintIt = pb->pb_PrintIt;
  411. #define child(x)    ((struct DirStack *)(x)->lh_Head)
  412.   
  413.   if (!Examine(lock, pb->pb_Fib)) {
  414.     VPrintf(MSG_NO_EXAMINE, (long *)&ds->ds_Node.ln_Name);
  415.     return -1;
  416.   }
  417.   
  418.   if (pb->pb_Fib->fib_DirEntryType > 0) {
  419.     // es ist ein Directory
  420.   
  421.     olock = CurrentDir(lock);
  422.     AppendPath(pb, ds);
  423.  
  424.     ret = ListOneDir(pb, ds, lock);
  425.     
  426.     dl = &ds->ds_Childs;
  427.     while (!ret && !IsListEmpty(dl)) {
  428.  
  429.       nlock = Lock(child(dl)->ds_Node.ln_Name, ACCESS_READ);
  430.       if (!nlock) {
  431.         VPrintf(MSG_NO_LOCK, (long *)&child(dl)->ds_Node.ln_Name);
  432.         ret = -1;
  433.       }
  434.       else {
  435.         if (pb->pb_Short) pb->pb_PrintIt = FALSE;
  436.         ret = ListOneTree(pb, child(dl), nlock);
  437.         UnLock(nlock);
  438.       }
  439.       
  440.       ds->ds_Size += child(dl)->ds_Size;
  441.       ds->ds_Blocks += child(dl)->ds_Blocks + 1 +1 ;
  442.  
  443.       RemHead(dl);
  444.     }
  445.     
  446.     pb->pb_PrintIt = oPrintIt;
  447.  
  448.     if (!ret) ret = PrintIt(pb, ds->ds_Blocks, ds->ds_Size, NULL);
  449.     CurrentDir(olock);
  450.     RemTail(&pb->pb_Path);
  451.  
  452.   }
  453.   else {
  454.     // es ist ein normales File
  455.     ds->ds_Blocks = UDivMod32(pb->pb_Fib->fib_Size, pb->pb_BlockSize) + 1 + 1;
  456.     ds->ds_Size = pb->pb_Fib->fib_Size;
  457.  
  458.     ret = PrintIt(pb, ds->ds_Blocks, ds->ds_Size, ds->ds_Node.ln_Name);
  459.   }
  460.  
  461.   return ret;
  462. }
  463.  
  464.  
  465. /*
  466.  * ListOneDir()
  467.  *
  468.  * List all files/directories of one directory and builds the
  469.  * list of the child directories.
  470.  *
  471.  */
  472.  
  473. static int ListOneDir(struct ParamBlock * pb, struct DirStack * ds, BPTR lock)
  474. {
  475.    struct ExAllControl * eac = pb->pb_EAC;
  476.    struct ExAllData * ead;
  477.    long size = 0;
  478.    long blocks = 0;
  479.    int more;
  480.    
  481.    eac->eac_LastKey = 0;
  482.    do {
  483.        more = ExAll(lock, (struct ExAllData *)pb->pb_EAData, pb->pb_EASize, ED_SIZE, eac);
  484.        if ((!more) && (IoErr() != ERROR_NO_MORE_ENTRIES)) {
  485.            /* ExAll failed abnormally */
  486.            break;
  487.        }
  488.        if (eac->eac_Entries == 0) {
  489.            /* ExAll failed normally with no entries */ 
  490.            continue;                   /* ("more" is *usually* zero) */
  491.        }
  492.        ead = (struct ExAllData *)pb->pb_EAData;
  493.  
  494.        do {
  495.        
  496.            if (ead->ed_Type > 0) {
  497.              /* ist ein Directory */
  498.              if (InsertNewDir(pb, ds, ead->ed_Name)) {
  499.                /* Fehler beim Eintragen */
  500.                // ExAllEnd bring GURU
  501.                //if (pb->pb_DOSBase->lib_Version >= 39) {
  502.                //  ExAllEnd(lock, (struct ExAllData *)pb->pb_EAData, pb->pb_EASize, ED_SIZE, eac);
  503.                //}
  504.                return -1;
  505.              }
  506.            }
  507.            else {
  508.              long blk = UDivMod32(ead->ed_Size, pb->pb_BlockSize) + 1 + 1;
  509.              if (pb->pb_All) {
  510.                if (PrintIt(pb, blk, ead->ed_Size, ead->ed_Name)) {
  511.                  // CTRL-C wurde gedrueckt
  512.                  // ExAllEnd bring GURU
  513.                  //if (pb->pb_DOSBase->lib_Version >= 39) {
  514.                  //  ExAllEnd(lock, (struct ExAllData *)pb->pb_EAData, pb->pb_EASize, ED_SIZE, eac);
  515.                  //}
  516.                  return -1;
  517.                }
  518.              }
  519.              size += ead->ed_Size; 
  520.              blocks += blk;
  521.  
  522.              // das mit den File-Ext. Bloecken funkt. noch nicht so ganz
  523.              //if (ead->ed_Size > 72 * pb->pb_BlockSize) blocks += ead->ed_Size / (72 * pb->pb_BlockSize) ;
  524.            }
  525.            /* get next ead */
  526.            ead = ead->ed_Next;
  527.  
  528.        } while (ead);
  529.  
  530.    } while (more);
  531.  
  532.    
  533.    ds->ds_Size = size;
  534.    ds->ds_Blocks = blocks;
  535.    
  536.    return 0;
  537. }
  538.  
  539.  
  540.  
  541. /*
  542.  * InsertNewDir()
  543.  *
  544.  * Add one sub-directory into the child-list of the current directory.
  545.  *
  546.  */
  547.  
  548. static int InsertNewDir(struct ParamBlock * pb, struct DirStack * ds, char * name)
  549. {
  550.   struct DirStack * nds = MyAlloc(pb, sizeof(struct DirStack));
  551.   
  552.   if (!nds) {
  553.     PutStr(MSG_NO_MEM);
  554.     return -1;
  555.   }
  556.   NewList(&nds->ds_Childs);
  557.   
  558.   nds->ds_Node.ln_Name  = MyStrDup(pb, name);
  559.   if (!nds->ds_Node.ln_Name) {
  560.     PutStr(MSG_NO_MEM);
  561.     return -1;
  562.   }
  563.  
  564.   AddTail(&ds->ds_Childs, &nds->ds_Node);
  565.   
  566.   return 0;
  567. }
  568.  
  569.  
  570. /*
  571.  * AppendPath()
  572.  *
  573.  * Add a new directory to the current path.
  574.  *
  575.  */
  576.  
  577. static int AppendPath(struct ParamBlock * pb, struct DirStack * ds)
  578. {
  579.   struct CurPath * cp = MyAlloc(pb, sizeof(struct CurPath));
  580.   
  581.   if (!cp) {
  582.     PutStr(MSG_NO_MEM);
  583.     return -1;
  584.   }
  585.  
  586.   cp->cp_Path = ds->ds_Node.ln_Name;
  587.   cp->cp_Node.ln_Name = ds->ds_Node.ln_Name;
  588.   AddTail(&pb->pb_Path, &cp->cp_Node);
  589. }
  590.  
  591.  
  592. /*
  593.  * PrintPath()
  594.  *
  595.  * Print the current path to stdout.
  596.  *
  597.  */
  598.  
  599. static void PrintPath(struct ParamBlock * pb)
  600. {
  601.   struct CurPath * cp;
  602.   char * s;
  603.   char c;
  604.   
  605.   pb->pb_NeedSlash = FALSE;
  606.  
  607.   if (IsListEmpty(&pb->pb_Path)) return;
  608.  
  609.   for (cp = (struct CurPath *)pb->pb_Path.lh_Head;
  610.        cp != (struct CurPath *)pb->pb_Path.lh_TailPred;
  611.        cp = (struct CurPath *)cp->cp_Node.ln_Succ) {
  612.  
  613.     s = cp->cp_Path;
  614.     if (s) {
  615.       if (s[strlen(s)-1] == ':' || s[strlen(s)-1] == '/') {
  616.         PutStr(s);
  617.       }
  618.       else {
  619.         PutStr(s);
  620.         PutStr("/");
  621.       }
  622.     }
  623.   }
  624.   PutStr(cp->cp_Path);
  625.   c = cp->cp_Path[strlen(cp->cp_Path)-1];
  626.   pb->pb_NeedSlash = c != ':' && c != '/';
  627. }
  628.  
  629.  
  630.  
  631. /*
  632.  * PrintIt()
  633.  *
  634.  * Print the data of a directory (name==NULL) or a file (name!=NULL)
  635.  * Check for Ctrl-C.
  636.  *
  637.  */
  638.  
  639. static int PrintIt(struct ParamBlock * pb, long blk, long bte, char * name)
  640.   long t;
  641.  
  642.   if (IsCtrlC) {
  643.     PrintFault(ERROR_BREAK, NULL);
  644.     return -1;
  645.   }
  646.  
  647.   if (!pb->pb_PrintIt) return 0;
  648.   
  649. #if defined(NOINFO)
  650.   if (name) {
  651.     long len = strlen(name);
  652.     if (pb->pb_NoInfo &&
  653.         name[len-5] == '.' &&
  654.         name[len-4] == 'i' &&
  655.         name[len-3] == 'n' &&
  656.         name[len-2] == 'f' &&
  657.         name[len-1] == 'o') return 0;
  658.   }
  659. #endif
  660.  
  661.   switch (pb->pb_PrtVal) {
  662.     case blocks:
  663.       t = blk;
  664.       break;
  665.     case bytes:
  666.       t = bte;
  667.       break;
  668.     case kbytes:
  669.       t = UDivMod32((bte+512), 1024);
  670.       break;
  671.   }
  672.   VPrintf("%ld\t", &t);
  673.   PrintPath(pb);
  674.   if (name) {
  675.     if (pb->pb_NeedSlash) PutStr("/");
  676.     PutStr(name);
  677.   }
  678.   PutStr("\n");
  679.   
  680.   return 0;
  681. }
  682.  
  683.  
  684. /*
  685.  * MyStrDup()
  686.  *
  687.  * Make a copy of a string.
  688.  *
  689.  */
  690.  
  691. static char * MyStrDup(struct ParamBlock * pb, char * str)
  692. {
  693.   int len = strlen(str);
  694.   char * new = MyAlloc(pb, len+1);
  695.   CopyMem(str, new, len+1);
  696.   
  697.   return new;
  698. }
  699.  
  700.  
  701. /*
  702.  * MyAlloc()
  703.  *
  704.  * Alloc a pice of memory.
  705.  *
  706.  */
  707.  
  708. static void * MyAlloc(struct ParamBlock * pb, long size)
  709. {
  710. # define MEMBLCK  (5*1024)
  711.  
  712.   size = (size+3) & 0xFFFFFFFC;        // damit der naechste wieder aligned ist
  713.                       // struct MemList sollte aligned-Groesse haben
  714.  
  715.   if (size > MEMBLCK-sizeof(struct MemList)) return NULL; // geht nicht, brauch ich nicht
  716.  
  717.   if (pb->pb_MemHandle == NULL || pb->pb_CurMem+size > pb->pb_MemEnd) {
  718.     if ((pb->pb_MemHandle = AllocMem(MEMBLCK, MEMF_PUBLIC | MEMF_CLEAR)) == NULL) {
  719.       return NULL;
  720.     }
  721.     else {
  722.       struct MemLst * ml = (struct MemLst *)pb->pb_MemHandle;
  723.       pb->pb_CurMem = pb->pb_MemHandle + sizeof(struct MemLst);
  724.       pb->pb_MemEnd = pb->pb_MemHandle + MEMBLCK - 1;
  725.       ml->ml_Data = (void *)pb->pb_MemHandle;
  726.       ml->ml_Size = MEMBLCK;
  727.       ml->ml_Next = pb->pb_MemList;
  728.       pb->pb_MemList = ml;
  729.       return MyAlloc(pb, size);
  730.     }
  731.   }
  732.   else {
  733.     void * t = pb->pb_CurMem;
  734.     pb->pb_CurMem += size;
  735.     return t;        // immer long aligned
  736.   }
  737. }
  738.  
  739.  
  740. /*
  741.  * MyFree()
  742.  *
  743.  * Frees _all_ allocated memory (MyStrDup/MyAlloc).
  744.  *
  745.  */
  746.  
  747. static void MyFree(struct ParamBlock * pb)
  748. {
  749.   struct MemLst * ml1, * ml2;
  750.  
  751.   for (ml1 = pb->pb_MemList; ml1 != NULL; ml1 = ml2) {
  752.     //if ((char *)ml1 == (char *)ml1->ml_Data) PutStr("ok\n");
  753.     //else PutStr("NOOO!\n");
  754.     ml2 = ml1->ml_Next;
  755.     FreeMem(ml1->ml_Data, ml1->ml_Size);
  756.   }
  757. }
  758.  
  759.  
  760.