Hint added.
[AROS.git] / workbench / c / Avail.c
blob53f56f3a2fe288c23e9a2d8a0096033a0add0dbd
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 "%9s"
72 #define AVAIL_ARCHVAL "%9iu"
73 #else
74 #define AVAIL_ARCHSTR "%12s"
75 #define AVAIL_ARCHVAL "%12iu"
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 (PutStr("Type Available In-Use Maximum Largest\n") < 0 ||
209 printm("chip", chip, 4) < 0 ||
210 printm("fast", fast, 4) < 0 ||
211 printm("total", total, 4) < 0)
213 error = RETURN_ERROR;
218 FreeArgs(rda);
220 else
222 error = RETURN_FAIL;
225 if(error != RETURN_OK && bPrintErr)
227 PrintFault(IoErr(), "Avail");
230 return error;
233 static
234 void fmtlarge(UBYTE *buf, IPTR num)
236 UQUAD d;
237 UBYTE ch;
238 struct
240 IPTR val;
241 IPTR dec;
242 } array =
244 num,
248 if (num >= 0x40000000)
250 array.val = num >> 30;
251 d = ((UQUAD)num * 100 + 0x20000000) / 0x40000000;
252 array.dec = d % 100;
253 ch = 'G';
255 else if (num >= 0x100000)
257 array.val = num >> 20;
258 d = ((UQUAD)num * 100 + 0x80000) / 0x100000;
259 array.dec = d % 100;
260 ch = 'M';
262 else if (num >= 0x400)
264 array.val = num >> 10;
265 d = (num * 100 + 0x200) / 0x400;
266 array.dec = d % 100;
267 ch = 'K';
269 else
271 array.val = num;
272 array.dec = 0;
273 d = 0;
274 ch = 'B';
277 if (!array.dec && (d > array.val * 100))
279 array.val++;
282 RawDoFmt(array.dec ? "%iu.%02iu" : "%iu", (RAWARG)&array, NULL, buf);
283 while (*buf) { buf++; }
284 *buf++ = ch;
285 *buf = '\0';
288 LONG printm(CONST_STRPTR head, IPTR *array, LONG num)
290 LONG res = -1;
291 CONST_STRPTR fmt;
292 UBYTE buf[10];
294 if (head)
296 ULONG len = 16 - strlen(head);
297 RawDoFmt(aHuman ? "%%%lds" : "%%%ldiu", (RAWARG)&len, NULL, buf);
298 fmt = buf;
299 PutStr(head);
301 else
303 fmt = aHuman ? AVAIL_ARCHSTR : AVAIL_ARCHVAL;
306 if (aHuman)
308 if (num == 1)
310 fmtlarge(buf, *array);
311 res = PutStr(buf);
313 else
315 while (num--)
317 UBYTE tmp[10];
319 fmtlarge(tmp, *array);
320 res = Printf(fmt, tmp);
321 if (res < 0)
322 break;
324 fmt = " " AVAIL_ARCHSTR;
325 array++;
329 else
331 if (num == 1)
333 res = VPrintf("%iu", (RAWARG)array);
335 else
337 while (num--)
339 res = VPrintf(fmt, (RAWARG)array);
340 if (res < 0)
341 break;
343 fmt = " " AVAIL_ARCHVAL;
344 array++;
348 PutStr("\n");
350 return res;