/* bttest.c: BIT TABLE TEST * * $Id$ * Copyright (c) 2001-2014 Ravenbrook Limited. See end of file for license. */ #include "mpm.h" #include "mps.h" #include "mpsavm.h" #include "testlib.h" #include "mpslib.h" #include "mpstd.h" #include /* fflush, fgets, printf, putchar, puts */ #include /* exit, strtol */ SRCID(bttest, "$Id$"); static BT bt; /* the BT which we will use */ static Size btSize; /* the size of the current BT */ static Arena arena; /* the arena which we use to allocate the BT */ #define MAX_ARGS 3 static Word args[MAX_ARGS]; static Count argCount; static Bool argInRange(Index arg) { if (bt == NULL) { printf("no BT\n"); return FALSE; } if (args[arg] >= btSize) { printf("out of range\n"); return FALSE; } return TRUE; } static Bool checkDefaultRange(Index arg) { if (bt == NULL) { printf("no BT\n"); return FALSE; } if (argCount == arg+1) { printf("range half-specified\n"); return FALSE; } if (argCount == arg) { /* use default range */ args[arg] = 0; args[arg+1] = btSize; return TRUE; } if (args[arg] >= args[arg+1]) { printf("range ill-formed\n"); return FALSE; } if (args[arg+1] > btSize) { printf("range too high\n"); return FALSE; } return TRUE; /* explicit valid range */ } static void quit(void) { exit(0); } static void destroy(void) { if (bt != NULL) { BTDestroy(bt, arena, btSize); bt = NULL; } else { printf("No BT to destroy\n"); } } static void create(void) { Res res; if (args[0] < 1) { printf("can't create a BT of size 0\n"); return; } if (bt != NULL) destroy(); res = BTCreate(&bt, arena, args[0]); if (res == ResOK) { btSize = args[0]; BTResRange(bt, 0, btSize); } else { printf("BTCreate returned %d\n",res); } } static void set(void) { if (argInRange(0)) (BTSet)(bt, args[0]); } static void reset(void) { if (argInRange(0)) (BTRes)(bt, args[0]); } static void get(void) { if (argInRange(0)) { Bool b = (BTGet)(bt, args[0]); puts(b ? "TRUE" : "FALSE"); } } static void setRange(void) { if (checkDefaultRange(0)) BTSetRange(bt, args[0], args[1]); } static void resetRange(void) { if (checkDefaultRange(0)) BTResRange(bt, args[0], args[1]); } static void isSetRange(void) { if (checkDefaultRange(0)) { Bool b = BTIsSetRange(bt, args[0], args[1]); puts(b ? "TRUE" : "FALSE"); } } static void isResRange(void) { if (checkDefaultRange(0)) { Bool b = BTIsResRange(bt, args[0], args[1]); puts(b ? "TRUE" : "FALSE"); } } static void findShortResRange(void) { if (checkDefaultRange(1)) { if (args[0] > (args[2] - args[1])) { printf("can't fit length in range\n"); } else { Index base, limit; Bool b = BTFindShortResRange(&base, &limit, bt, args[1], args[2], args[0]); if (b) printf("%"PRIuLONGEST" - %"PRIuLONGEST"\n", (ulongest_t)base, (ulongest_t)limit); else printf("FALSE\n"); } } } static void findShortResRangeHigh(void) { if (checkDefaultRange(1)) { if (args[0] > (args[2] - args[1])) { printf("can't fit length in range\n"); } else { Index base, limit; Bool b = BTFindShortResRangeHigh(&base, &limit, bt, args[1], args[2], args[0]); if (b) printf("%"PRIuLONGEST" - %"PRIuLONGEST"\n", (ulongest_t)base, (ulongest_t)limit); else printf("FALSE\n"); } } } static void findLongResRange(void) { if (checkDefaultRange(1)) { if (args[0] > (args[2] - args[1])) { printf("can't fit length in range\n"); } else { Index base, limit; Bool b = BTFindLongResRange(&base, &limit, bt, args[1], args[2], args[0]); if (b) printf("%"PRIuLONGEST" - %"PRIuLONGEST"\n", (ulongest_t)base, (ulongest_t)limit); else printf("FALSE\n"); } } } static void help(void) { printf("c create a BT of size 's'\n" "d destroy the current BT\n" "s set the bit index 'i'\n" "r reset the bit index 'i'\n" "g get the bit index 'i'\n"); printf("sr [ ] set the specified range\n" "rr [ ] reset the specified range\n" "is [ ] is the specified range set?\n" "ir [ ] is the specified range reset?\n"); printf("f [ ] find a reset range of length 'l'.\n" "fh [ ] find a reset range length 'l', working downwards\n" "fl [ ] find a reset range of length at least 'l'\n" "q quit\n" "? print this message\n"); printf("\n" "No way of testing BTSize, BTRangesSame, or BTCopyInvertRange.\n"); } static struct commandShapeStruct { const char *name; Count min_args; Count max_args; void (*fun)(void); } commandShapes[] = { {"c", 1, 1, create}, {"d", 0, 0, destroy}, {"s", 1, 1, set}, {"r", 1, 1, reset}, {"g", 1, 1, get}, {"sr", 0, 2, setRange}, {"rr", 0, 2, resetRange}, {"is", 0, 2, isSetRange}, {"ir", 0, 2, isResRange}, {"f", 1, 3, findShortResRange}, {"fh", 1, 3, findShortResRangeHigh}, {"fl", 1, 3, findLongResRange}, {"?", 0, 0, help}, {"q", 0, 0, quit}, { NULL, 0, 0, NULL} }; typedef struct commandShapeStruct *commandShape; static void obeyCommand(const char *command) { commandShape shape = commandShapes; while(shape->name != NULL) { const char *csp = shape->name; const char *p = command; while (*csp == *p) { csp++; p++; } if ((*csp == 0) && ((*p == '\n') || (*p == ' '))) { /* complete match */ argCount = 0; while ((*p == ' ') && (argCount < shape->max_args)) { /* get an argument */ char *newP; long l; l = strtol(p, &newP, 0); if(l < 0) { /* negative integer */ printf("negative integer arguments are invalid\n"); return; } args[argCount] = (unsigned long)l; if (newP == p) { /* strtoul failed */ printf("couldn't parse an integer argument\n"); return; } p = newP; ++ argCount; } if (argCount < shape->min_args) { printf("insufficient arguments to command\n"); } else if (*p != '\n') { printf("too many arguments to command\n"); } else { /* do the command */ shape->fun(); } return; } else { ++ shape; /* try next command */ } } printf("command not understood\n"); help(); } static void showBT(void) { Index i; char c; if (bt == NULL) return; i = 0; while((i < btSize) && (i < 50)) { if (i % 10 == 0) c = (char)(((i / 10) % 10) + '0'); else c = ' '; putchar(c); ++ i; } putchar('\n'); i = 0; while((i < btSize) && (i < 50)) { c = (char)((i % 10) +'0'); putchar(c); ++ i; } putchar('\n'); i = 0; while(i < btSize) { if (BTGet(bt,i)) c = 'O'; else c = '.'; putchar(c); ++ i; if (i % 50 == 0) putchar('\n'); } putchar('\n'); } #define testArenaSIZE (((size_t)64)<<20) extern int main(int argc, char *argv[]) { bt = NULL; btSize = 0; testlib_init(argc, argv); die(mps_arena_create((mps_arena_t*)&arena, mps_arena_class_vm(), testArenaSIZE), "mps_arena_create"); while(1) { char input[100]; printf("bt test> "); (void)fflush(stdout); if (fgets(input, 100, stdin)) { obeyCommand(input); showBT(); } else { return 0; } } } /* C. COPYRIGHT AND LICENSE * * Copyright (C) 2001-2014 Ravenbrook Limited . * All rights reserved. This is an open source license. Contact * Ravenbrook for commercial licensing options. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * 3. Redistributions in any form must be accompanied by information on how * to obtain complete source code for this software and any accompanying * software that uses this software. The source code must either be * included in the distribution or be available for no more than the cost * of distribution plus a nominal fee, and must be freely redistributable * under reasonable conditions. For an executable file, complete source * code means the source code for all modules it contains. It does not * include source code for modules or files that typically accompany the * major components of the operating system on which the executable file * runs. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR * PURPOSE, OR NON-INFRINGEMENT, ARE DISCLAIMED. IN NO EVENT SHALL THE * COPYRIGHT HOLDERS AND CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */