home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Gold Fish 2
/
goldfish_vol2_cd1.bin
/
files
/
util
/
misc
/
flush
/
flush.c
< prev
next >
Wrap
C/C++ Source or Header
|
1994-01-13
|
16KB
|
820 lines
#define VERSION "1.2"
/*********************************************************************
* Flush Flushes all unused libraries, devices and fonts.
* Note that some libraries and devices refuse to
* flush themselves.
*
*
* Options:
*
* -d ; only flush devices
* -f ; only flush fonts
* -l ; only flush libraries
* -r ; report only; don't flush
* -v ; be verbose; print names of all removed objects
* -oOBJ ; remove OBJ , must have a suffix of
* .library, .device, or .font(x,y)
* -h ; this message
*
*
* Runs under AmigaDOS 2.04+
*
*
***** Written by Gary Duncan
*
* Bug reports etc via e-mail to gduncan@philips.oz.au) , or mail to
*
*Work: Gary Duncan
* Philips PTS
* 23 Lakeside Dr
* Tally-Ho Technology Park
* Burwood East Vic 3151
* Australia
*
*Home: Gary Duncan
* 57 Melbourne Hill Rd
* Warrandyte
* Vic 3113
* Australia
*
*Thanks to these beta-testers for testing early versions:-
*
* Benbuck Nason (bigben@netcom.com)
* Torsten Nielsen (torsten@diku.dk)
* Darren Reid and others (shockwave@jupiter.sun.csd.unb.ca)
*
*
***** Freely distributable for non-commercial purposes.
* Please keep this header intact.
*
* Use this program at your own risk.
*
*
* Compiles under SAS 6.3
*
* Formatted with 'indent -gnu' ; a big time-saving program.
*
*****************************************************************/
#include "flush.h"
extern struct GfxBase *GfxBase;
/*
* string for AmigaDOS Version Command
*/
char A_vers[] = "\0$VER: Flush\t" VERSION " (13.1.94)";
/*
* lib/device array ; one entry per lib/device list containing
* name and open count.
*/
static S_LIB *pre_flush;
static S_LIB *post_flush;
static int pre_cnt = 0;
static int post_cnt = 0;
char *remove_it;
int r_count = 0;
ULONG s_total;
ULONG s_fast;
ULONG s_chipx;
ULONG e_total;
ULONG e_fast;
ULONG e_chipx;
ULONG r_total;
ULONG r_fast;
ULONG r_chipx;
BOOL v_flag = FALSE;
BOOL r_flag = FALSE;
BOOL o_flag = FALSE;
BOOL d_flag = FALSE;
BOOL f_flag = FALSE;
BOOL l_flag = FALSE;
/*
**********************************************************
*/
main (int argc, char **argv)
{
ULONG t, c, f;
/*
* check options
*/
scan_args (argc, argv);
/*
* get buffers to hold List items
*/
GetItemsBuf (&pre_flush, &post_flush);
/*
* kluge to get printf() to get its 16K malloc'd buffer now
* so that it won't confuse memory usage reporting later
*/
printf ("\r");
fflush (stdout);
/*
* get memory at start
*/
memm (&s_fast, &s_chipx);
/*
* check if its just one removal
*/
if (o_flag)
{
rem_obj (remove_it);
}
else
{
/*
* flush fonts before libs, as attempting to flush
* diskfont.library seems to flush them automatically
* and we want font flushing shown.
*/
if (f_flag == TRUE)
{
FlushFonts (r_flag);
}
else if (l_flag == TRUE)
{
FlushLibraries (r_flag);
}
else if (d_flag == TRUE)
{
FlushDevices (r_flag);
}
else
{
FlushFonts (r_flag);
FlushLibraries (r_flag);
FlushDevices (r_flag);
}
}
/*
* get memory at end
*/
memm (&e_fast, &e_chipx);
c = (e_chipx - s_chipx) / 1024;
f = (e_fast - s_fast) / 1024;
t = c + f;
if (r_flag == FALSE)
{
printf ("Memory regained (KB) : total = %ld, [chip = %ld, fast = %ld]\n",
t, c, f);
}
}
/*
**********************************************************
*/
void
FlushLibraries (BOOL flag)
{
LIBRARY *l_ptr;
NODE *node;
int lib_cnt = 0;
int open_cnt = 0;
int j;
int cc = 0;
BOOL flushed_flag;
pre_cnt = 0;
post_cnt = 0;
/*
* iterate through lib list until all flushable libs flushed;
* need to do this because some libs use other libs, i.e do
* a flush themselves
*
* - if "report" option, just pass through once
*
*/
while (TRUE)
{
Forbid ();
for (flushed_flag = FALSE, node = SysBase->LibList.lh_Head;
node->ln_Succ; node = node->ln_Succ)
{
char *l_name;
++cc;
l_ptr = (LIBRARY *) node;
l_name = node->ln_Name;
open_cnt = l_ptr->lib_OpenCnt;
/*
* if flushable, record if not already in table
*/
if (
(open_cnt == 0)
&&
(!check_flushed (pre_cnt, pre_flush, l_name))
)
{
/*
* hold open count, lib name
*/
pre_flush[pre_cnt].o_cnt = open_cnt;
pre_flush[pre_cnt].confeds.vr.ver = l_ptr->lib_Version;
pre_flush[pre_cnt].confeds.vr.rev = l_ptr->lib_Revision;
strncpy (pre_flush[pre_cnt].name, l_name, S_BUFLEN - 1);
/*
* don't flush diskfont.library if fonts shouldn't be
* flushed
*/
if (r_flag == FALSE)
{
if (!(l_flag && (strcmp (l_name, "diskfont.library") == 0)))
RemLibrary (l_ptr);
}
flushed_flag = TRUE;
++pre_cnt;
}
}
Permit ();
if (lib_cnt == 0)
lib_cnt = cc; /* hold first pass lib count */
/*
* if no flushable libs this time, exit loop
*/
if ((flushed_flag == FALSE) || (r_flag == TRUE))
break;
}
/*
* see if report only
*/
if (r_flag == TRUE)
{
for (j = 0; j < pre_cnt; ++j)
{
char *l_name = pre_flush[j].name;
printf ("\tFlushable Library : %-27s(%d.%d)\n", l_name,
pre_flush[j].confeds.vr.ver,
pre_flush[j].confeds.vr.rev);
}
return;
}
/*
* now see what's been flushed
*/
if (pre_cnt)
{
Forbid ();
for (node = SysBase->LibList.lh_Head; node->ln_Succ;
node = node->ln_Succ)
{
l_ptr = (LIBRARY *) node;
if (l_ptr->lib_OpenCnt == 0)
{
/*
* hold open count, lib name
*/
post_flush[post_cnt].o_cnt = l_ptr->lib_OpenCnt;
post_flush[post_cnt].confeds.vr.ver = l_ptr->lib_Version;
post_flush[post_cnt].confeds.vr.rev = l_ptr->lib_Revision;
strncpy (post_flush[post_cnt].name, node->ln_Name, S_BUFLEN - 1);
++post_cnt;
}
}
Permit ();
}
/*
* report on flushed libraries
*/
printf ("Libraries: total = %2d , flushable = %2d, flushed = %2d\n",
lib_cnt, pre_cnt, pre_cnt - post_cnt);
/*
* now see how many libraries flushed themselves
*/
if (pre_cnt && v_flag)
{
for (j = 0; j < pre_cnt; ++j)
{
char *l_name = pre_flush[j].name;
if (!check_flushed (post_cnt, post_flush, l_name))
printf ("\tFlushed : %-27s(%d.%d)\n", l_name,
pre_flush[j].confeds.vr.ver,
pre_flush[j].confeds.vr.rev);
}
/*
* now see how many libraries did not flush themselves
*/
for (j = 0; j < post_cnt; ++j)
{
char *l_name = post_flush[j].name;
printf ("\tNot Flushed : %-27s(%d.%d)\n", l_name,
post_flush[j].confeds.vr.ver,
post_flush[j].confeds.vr.rev);
}
printf ("\n");
}
return;
}
/*
**********************************************************
*/
void
FlushDevices (BOOL flag)
{
LIBRARY *l_ptr;
NODE *node;
int dev_cnt = 0;
int j;
pre_cnt = 0;
post_cnt = 0;
Forbid ();
for (node = SysBase->DeviceList.lh_Head; node->ln_Succ;
node = node->ln_Succ)
{
l_ptr = (LIBRARY *) node;
++dev_cnt;
/*
* record all flushable ( open count = 0 )
*/
if (l_ptr->lib_OpenCnt == 0)
{
/*
* hold open count, lib name
*/
pre_flush[pre_cnt].o_cnt = l_ptr->lib_OpenCnt;
pre_flush[pre_cnt].confeds.vr.ver = l_ptr->lib_Version;
pre_flush[pre_cnt].confeds.vr.rev = l_ptr->lib_Revision;
strncpy (pre_flush[pre_cnt].name, node->ln_Name, S_BUFLEN);
++pre_cnt;
if (r_flag == FALSE)
{
RemDevice ((DEVICE *) l_ptr);
}
}
}
Permit ();
/*
* see if report only
*/
if (r_flag == TRUE)
{
for (j = 0; j < pre_cnt; ++j)
{
char *l_name = pre_flush[j].name;
printf ("\tFlushable Device : %-27s(%d.%d)\n", l_name,
pre_flush[j].confeds.vr.ver,
pre_flush[j].confeds.vr.rev);
}
return;
}
/*
* now see what's been flushed
*/
if (pre_cnt)
{
Forbid ();
for (node = SysBase->DeviceList.lh_Head; node->ln_Succ;
node = node->ln_Succ)
{
l_ptr = (LIBRARY *) node;
if (l_ptr->lib_OpenCnt == 0)
{
/*
* hold open count, lib name
*/
post_flush[post_cnt].o_cnt = l_ptr->lib_OpenCnt;
post_flush[post_cnt].confeds.vr.ver = l_ptr->lib_Version;
post_flush[post_cnt].confeds.vr.rev = l_ptr->lib_Revision;
strncpy (post_flush[post_cnt].name, node->ln_Name, S_BUFLEN);
++post_cnt;
}
}
Permit ();
}
/*
* report
*/
printf ("Devices : total = %2d , flushable = %2d, flushed = %2d\n",
dev_cnt, pre_cnt, pre_cnt - post_cnt);
/*
* now see how many devices flushed themselves
*/
if (pre_cnt && v_flag)
{
for (j = 0; j < pre_cnt; ++j)
{
char *l_name = pre_flush[j].name;
if (!check_flushed (post_cnt, post_flush, l_name))
printf ("\tFlushed : %-27s(%d.%d)\n", l_name,
pre_flush[j].confeds.vr.ver,
pre_flush[j].confeds.vr.rev);
}
/*
* now see how many devices did not flush themselves
*/
for (j = 0; j < post_cnt; ++j)
{
char *l_name = post_flush[j].name;
printf ("\tNot Flushed : %-27s(%d.%d)\n", l_name,
post_flush[j].confeds.vr.ver,
post_flush[j].confeds.vr.rev);
}
printf ("\n");
}
return;
}
/*
**********************************************************
*/
void
FlushFonts (BOOL flag)
{
TEXTFONT *tf;
NODE *node;
int font_cnt = 0;
int o_cnt;
int j;
pre_cnt = 0;
/*
* now record fonts, and flush those flushable
*/
Forbid ();
for (node = GfxBase->TextFonts.lh_Head; node->ln_Succ;
node = node->ln_Succ)
{
tf = (TEXTFONT *) node;
++font_cnt;
o_cnt = tf->tf_Accessors;
if ((o_cnt == 0) && (tf->tf_Flags & FPF_DISKFONT))
{
/*
* flushable ; hold font name
*/
pre_flush[pre_cnt].o_cnt = o_cnt;
pre_flush[pre_cnt].confeds.fonts.font_x = tf->tf_XSize;
pre_flush[pre_cnt].confeds.fonts.font_y = tf->tf_YSize;
strncpy (pre_flush[pre_cnt].name, node->ln_Name, S_BUFLEN - 1);
++pre_cnt;
/*
* then flush it
*/
if (r_flag == FALSE)
{
RemFont (tf);
Remove (node);
}
}
}
Permit ();
/*
* see if report only
*/
if (r_flag == TRUE)
{
for (j = 0; j < pre_cnt; ++j)
{
char *l_name = pre_flush[j].name;
printf ("\tFlushable Font : %-27s(X=%2d,Y=%2d)\n", l_name,
pre_flush[j].confeds.fonts.font_x,
pre_flush[j].confeds.fonts.font_y);
}
return;
}
/*
* see what's been flushed
*/
/*
* force font flushing (lib won't be flushed)
*/
rem_obj ("diskfont.library");
post_cnt = 0;
Forbid ();
for (node = GfxBase->TextFonts.lh_Head; node->ln_Succ;
node = node->ln_Succ)
{
tf = (TEXTFONT *) node;
o_cnt = tf->tf_Accessors;
if ((o_cnt == 0) && (tf->tf_Flags & FPF_DISKFONT))
{
/*
* hold open count, font name
*/
post_flush[post_cnt].o_cnt = o_cnt;
post_flush[post_cnt].confeds.fonts.font_x = tf->tf_XSize;
post_flush[post_cnt].confeds.fonts.font_y = tf->tf_YSize;
strncpy (post_flush[post_cnt].name, node->ln_Name, S_BUFLEN - 1);
++post_cnt;
}
}
Permit ();
printf ("Fonts : total = %2d , flushable = %2d, flushed = %2d\n",
font_cnt, pre_cnt, pre_cnt - post_cnt);
if (pre_cnt && v_flag)
{
/*
* now see how many fonts were flushed
*/
for (j = 0; j < pre_cnt; ++j)
{
char *l_name = pre_flush[j].name;
if (!check_flushed (post_cnt, post_flush, l_name))
{
printf ("\tFlushed : %-27s(X=%2d,Y=%2d)\n", l_name,
pre_flush[j].confeds.fonts.font_x,
pre_flush[j].confeds.fonts.font_y);
}
}
/*
* now see how many fonts were not flushed
*/
for (j = 0; j < post_cnt; ++j)
{
char *l_name = post_flush[j].name;
printf ("\tNot Flushed : %-27s(X=%2d,Y=%2d)\n", l_name,
post_flush[j].confeds.fonts.font_x,
post_flush[j].confeds.fonts.font_y);
}
printf ("\n");
}
return;
}
/*
**********************************************************
*/
int
GetListCount (LIST * list)
{
int count = 0;
NODE *node;
Forbid ();
for (node = list->lh_Head; node->ln_Succ; node = node->ln_Succ)
count++;
Permit ();
return count;
}
/*
**********************************************************
*/
void
memm (ULONG * fast, ULONG * chipx)
{
*fast = AvailMem (MEMF_FAST);
*chipx = AvailMem (MEMF_CHIP);
}
/*
**********************************************************
*/
BOOL
check_flushed (int count, S_LIB * s_ptr, char *n_ptr)
{
int j;
for (j = 0; j < count; ++j)
{
if (strcmp (s_ptr[j].name, n_ptr) == 0)
return TRUE;
}
return FALSE;
}
/*
**********************************************************
*/
void
GetItemsBuf (S_LIB ** pre, S_LIB ** post)
{
ULONG bf, bl, bd;
ULONG v;
bf = GetListCount (&GfxBase->TextFonts);
bl = GetListCount (&SysBase->LibList);
bd = GetListCount (&SysBase->DeviceList);
v = max (bf, bl);
v = max (v, bd);
/*
* increase the entry count a bit for safety
*/
v += 10;
if ((*pre = malloc (v * sizeof (S_LIB))) == NULL)
{
fprintf (stderr, "Can't malloc pre-buffer\n");
exit (1);
}
if ((*post = malloc (v * sizeof (S_LIB))) == NULL)
{
fprintf (stderr, "Can't malloc post-buffer\n");
exit (1);
}
}
/*
**********************************************************
*/
void
usage ()
{
printf (
"Flush: flushes unused libraries, devices, fonts from RAM\n\
Version %s [%s] written by gduncan@philips.oz.au\n\n\
usage: flush [-d] [-f] [-l] [-v] [-r] [-h] [-oOBJ]\n\
-d ; only flush devices\n\
-f ; only flush fonts\n\
-l ; only flush libraries\n\
-r ; report only; don't flush\n\
-v ; be verbose; print names of all removed objects\n\
-oOBJ ; remove OBJ , must have a suffix of .library or .device\n\
-h ; this message\n",
VERSION, __DATE__);
}
/***************************************************************************
Function : scan_args
Purpose: scans and validates command line
Entry :
Returns :
****************************************************************************/
void
scan_args (int argc, char **argv)
{
char *ptr;
char arch;
while (--argc)
{
ptr = *++argv;
arch = *++ptr;
switch (arch)
{
case 'h':
usage ();
exit (1);
case 'd':
d_flag = TRUE;
break;
case 'f':
f_flag = TRUE;
break;
case 'l':
l_flag = TRUE;
break;
case 'v':
v_flag = TRUE;
break;
case 'r':
r_flag = TRUE;
break;
case 'o':
o_flag = TRUE;
remove_it = ++ptr;
break;
default:
fprintf (stderr, "unknown option\n"); /* bad option */
exit (1);
}
}
}
/*
**********************************************************
*/
void
rem_obj (char *ptr)
{
char *z;
NODE *lp;
if ((z = strstr (ptr, ".library")) != NULL)
{
if ((lp = (NODE *) FindName ((LIST *) SysBase->LibList.lh_Head, ptr)))
RemLibrary ((LIBRARY *) lp);
}
else if ((z = strstr (ptr, ".device")) != NULL)
{
if ((lp = (NODE *) FindName ((LIST *) SysBase->DeviceList.lh_Head, ptr)))
RemDevice ((DEVICE *) lp);
}
else
fprintf (stderr, "not a .device or .library\n");
}
/**/