revert between 56095 -> 55830 in arch
[AROS.git] / workbench / c / Avail.c
blobe6c8f793385db12c1c34bbe06f570970cd56839a
1 /*
2 Copyright © 1995-2016, The AROS Development Team. All rights reserved.
3 $Id$
5 Desc: Avail CLI command
6 Lang: English
7 */
9 /******************************************************************************
12 NAME
14 Avail [CHIP | FAST | TOTAL | FLUSH] [H | HUMAN]
16 SYNOPSIS
18 CHIP/S, FAST/S, TOTAL/S, FLUSH/S, H=HUMAN/S
20 LOCATION
24 FUNCTION
26 Give a summary of the memory usage and availability in the system.
27 To free up unused memory that still may be allocated (libraries,
28 devices, fonts and such present in memory but whcih are currently
29 not in use), use the FLUSH option.
31 INPUTS
33 CHIP -- show only "chip" memory
34 FAST -- show only "fast" memory
35 TOTAL -- show information on memory regardless of type
36 FLUSH -- remove unnecessary things residing in memory
37 HUMAN -- display more human-readable values (gigabytes as "G",
38 megabytes as "M", kilobytes as "K")
40 RESULT
42 NOTES
44 "Chip" and "fast" memory are associated with the Amiga computer
45 and may not be applicable on your hardware platform.
47 EXAMPLE
49 BUGS
51 SEE ALSO
53 INTERNALS
55 HISTORY
57 ******************************************************************************/
59 #include <aros/cpu.h> // for __WORDSIZE
60 #include <exec/execbase.h>
61 #include <exec/memory.h>
62 #include <proto/exec.h>
63 #include <dos/dos.h>
64 #include <proto/dos.h>
65 #include <utility/tagitem.h>
66 #include <string.h>
68 const TEXT version[] = "$VER: Avail 42.2 (24.2.2016)\n";
70 #if (__WORDSIZE == 64)
71 #define AVAIL_ARCHSTR "%13s"
72 #define AVAIL_ARCHVAL "%13iu"
73 #else
74 #define AVAIL_ARCHSTR "%9s"
75 #define AVAIL_ARCHVAL "%9iu"
76 #endif
78 #define ARG_TEMPLATE "CHIP/S,FAST/S,TOTAL/S,FLUSH/S,H=HUMAN/S"
80 enum
82 ARG_CHIP = 0,
83 ARG_FAST,
84 ARG_TOTAL,
85 ARG_FLUSH,
86 ARG_HUMAN,
87 NOOFARGS
90 LONG printm(CONST_STRPTR head, IPTR *array, LONG num);
92 int __nocommandline = 1;
94 BOOL aHuman;
96 /* Allocate all memory (even for >2G systems), then free it.
97 * This will force all expungable items out of memory
99 static void FlushMem(struct ExecBase *SysBase)
101 APTR Mem;
103 Mem = AllocMem(0x7ffffff0, MEMF_PUBLIC);
104 if (Mem) {
105 FlushMem(SysBase);
106 FreeMem(Mem, 0x7ffffff0);
110 int main(void)
112 IPTR args[NOOFARGS] = { (IPTR)FALSE,
113 (IPTR)FALSE,
114 (IPTR)FALSE,
115 (IPTR)FALSE,
116 (IPTR)FALSE };
117 struct RDArgs *rda;
118 LONG error = 0;
119 BOOL bPrintErr = TRUE;
120 rda = ReadArgs(ARG_TEMPLATE, args, NULL);
122 if (rda != NULL)
124 UWORD typeCount = 0;
125 BOOL aChip = (BOOL)args[ARG_CHIP];
126 BOOL aFast = (BOOL)args[ARG_FAST];
127 BOOL aTotal = (BOOL)args[ARG_TOTAL];
128 BOOL aFlush = (BOOL)args[ARG_FLUSH];
129 aHuman = (BOOL)args[ARG_HUMAN];
131 if (aChip)
133 typeCount++;
135 if (aFast)
137 typeCount++;
139 if (aTotal)
141 typeCount++;
144 IPTR chip[4], fast[4], total[4];
146 if (typeCount > 1)
148 FPuts(Output(), "Only one of CHIP, FAST or TOTAL allowed\n");
149 bPrintErr = FALSE;
150 FreeArgs(rda);
152 return RETURN_FAIL;
154 else
156 if (aFlush)
158 FlushMem(SysBase);
161 if(aChip)
164 chip[0] = AvailMem(MEMF_CHIP);
166 if (printm(NULL, chip, 1) < 0)
168 error = RETURN_ERROR;
171 else if(aFast)
173 fast[0] = AvailMem(MEMF_FAST);
175 if (printm(NULL, fast, 1) < 0)
177 error = RETURN_ERROR;
180 else if (aTotal)
182 total[0] = AvailMem(MEMF_ANY);
184 if (printm(NULL, total, 1) < 0)
186 error = RETURN_ERROR;
189 else
191 Forbid();
193 chip[0] = AvailMem(MEMF_CHIP);
194 chip[2] = AvailMem(MEMF_CHIP | MEMF_TOTAL);
195 chip[3] = AvailMem(MEMF_CHIP | MEMF_LARGEST);
196 chip[1] = chip[2] - chip[0];
197 fast[0] = AvailMem(MEMF_FAST);
198 fast[2] = AvailMem(MEMF_FAST | MEMF_TOTAL);
199 fast[3] = AvailMem(MEMF_FAST | MEMF_LARGEST);
200 fast[1] = fast[2] - fast[0];
201 total[0] = AvailMem(MEMF_ANY);
202 total[2] = AvailMem(MEMF_ANY | MEMF_TOTAL);
203 total[3] = AvailMem(MEMF_ANY | MEMF_LARGEST);
204 total[1] = total[2] - total[0];
206 Permit();
208 #if (__WORDSIZE == 64)
209 if (PutStr("Type Available In-Use Maximum Largest\n") < 0 ||
210 #else
211 if (PutStr("Type Available In-Use Maximum Largest\n") < 0 ||
212 #endif
213 printm("chip", chip, 4) < 0 ||
214 printm("fast", fast, 4) < 0 ||
215 printm("total", total, 4) < 0)
217 error = RETURN_ERROR;
222 FreeArgs(rda);
224 else
226 error = RETURN_FAIL;
229 if(error != RETURN_OK && bPrintErr)
231 PrintFault(IoErr(), "Avail");
234 return error;
237 static
238 void fmtlarge(UBYTE *buf, IPTR num)
240 UQUAD d;
241 UBYTE ch;
242 struct
244 IPTR val;
245 IPTR dec;
246 } array =
248 num,
252 if (num >= 0x40000000)
254 array.val = num >> 30;
255 d = ((UQUAD)num * 100 + 0x20000000) / 0x40000000;
256 array.dec = d % 100;
257 ch = 'G';
259 else if (num >= 0x100000)
261 array.val = num >> 20;
262 d = ((UQUAD)num * 100 + 0x80000) / 0x100000;
263 array.dec = d % 100;
264 ch = 'M';
266 else if (num >= 0x400)
268 array.val = num >> 10;
269 d = (num * 100 + 0x200) / 0x400;
270 array.dec = d % 100;
271 ch = 'K';
273 else
275 array.val = num;
276 array.dec = 0;
277 d = 0;
278 ch = 'B';
281 if (!array.dec && (d > array.val * 100))
283 array.val++;
286 RawDoFmt(array.dec ? "%iu.%02iu" : "%iu", (RAWARG)&array, NULL, buf);
287 while (*buf) { buf++; }
288 *buf++ = ch;
289 *buf = '\0';
292 LONG printm(CONST_STRPTR head, IPTR *array, LONG num)
294 LONG res = -1;
295 CONST_STRPTR fmt;
296 UBYTE buf[10];
298 if (head)
300 ULONG len = 18 - strlen(head);
301 RawDoFmt(aHuman ? "%%%lds" : "%%%ldiu", (RAWARG)&len, NULL, buf);
302 fmt = buf;
303 PutStr(head);
305 else
307 fmt = aHuman ? AVAIL_ARCHSTR : AVAIL_ARCHVAL;
310 if (aHuman)
312 if (num == 1)
314 fmtlarge(buf, *array);
315 res = PutStr(buf);
317 else
319 while (num--)
321 UBYTE tmp[10];
323 fmtlarge(tmp, *array);
324 res = Printf(fmt, tmp);
325 if (res < 0)
326 break;
328 fmt = " " AVAIL_ARCHSTR;
329 array++;
333 else
335 if (num == 1)
337 res = VPrintf("%iu", (RAWARG)array);
339 else
341 while (num--)
343 res = VPrintf(fmt, (RAWARG)array);
344 if (res < 0)
345 break;
347 fmt = " " AVAIL_ARCHVAL;
348 array++;
352 PutStr("\n");
354 return res;