1 /*- 2 * Copyright (c) 1990 The Regents of the University of California. 3 * All rights reserved. 4 * 5 * This code is derived from software contributed to Berkeley by 6 * Mike Olson. 7 * 8 * %sccs.include.redist.c% 9 */ 10 11 #if defined(LIBC_SCCS) && !defined(lint) 12 static char sccsid[] = "@(#)main.c 5.1 (Berkeley) 04/12/91"; 13 #endif /* LIBC_SCCS and not lint */ 14 15 /* 16 * test1.c -- simple btree test program. 17 */ 18 19 #include <stdio.h> 20 #include <ctype.h> 21 #include <sys/param.h> 22 #include <sys/types.h> 23 #include <sys/file.h> 24 #include <db.h> 25 #include <btree.h> 26 27 #define DICTIONARY "/usr/share/dict/words" 28 29 typedef struct cmd_table { 30 char *cmd; 31 int nargs; 32 int (*func)(); 33 char *descrip; 34 } cmd_table; 35 36 extern int cursor(), delcur(), delete(), first(), help(), insert(); 37 extern int last(), lookup(), next(), previous(); 38 39 cmd_table Commands[] = { 40 "cursor", 2, cursor, 41 "cursor <word>: point the scan cursor at <word>", 42 "delcur", 1, delcur, 43 "delcur: delete the word under the scan cursor", 44 "delete", 2, delete, 45 "delete <word>: delete <word> from the dictionary", 46 "first", 1, first, 47 "first: point the scan cursor at the first dictionary entry", 48 "help", 1, help, 49 "help: print this command summary", 50 "insert", 3, insert, 51 "insert <word> <def>: insert <word> into the dictionary with definition <def>", 52 "last", 1, last, 53 "last: point the scan cursor at the last dictionary entry", 54 "lookup", 2, lookup, 55 "lookup <word>: look up <word> in the dictionary", 56 "next", 1, next, 57 "next: move the scan cursor forward one word", 58 "previous", 1, previous, 59 "previous: move the scan cursor back one word", 60 (char *) NULL, 0, NULL, (char *) NULL, 61 }; 62 63 char *Usage = "[-p pagesize] [-c cachesize] [-u] [-l|b|n] [dbname]"; 64 65 main(argc, argv) 66 int argc; 67 char **argv; 68 { 69 char *dbname; 70 int c; 71 char *progname; 72 extern int strcmp(); 73 extern char *optarg; 74 extern int optind; 75 DB *t; 76 BTREEINFO b; 77 78 progname = *argv; 79 80 b.psize = 0; 81 b.cachesize = 0; 82 b.lorder = 0; 83 b.flags = R_DUP; 84 b.compare = strcmp; 85 86 while ((c = getopt(argc, argv, "p:c:ulb")) != EOF) { 87 switch (c) { 88 case 'p': 89 b.psize = atoi(optarg); 90 break; 91 92 case 'c': 93 b.cachesize = atoi(optarg); 94 break; 95 96 case 'u': 97 b.flags = 0; 98 break; 99 100 case 'l': 101 b.lorder = LITTLE_ENDIAN; 102 break; 103 104 case 'b': 105 b.lorder = BIG_ENDIAN; 106 break; 107 108 default: 109 fprintf(stderr, "%s: usage: %s\n", progname, Usage); 110 exit (1); 111 } 112 } 113 114 if (argv[optind] != (char *) NULL) 115 dbname = argv[optind]; 116 117 if ((t = btree_open(dbname, O_CREAT|O_RDWR, 0600, &b)) == (DB *) NULL) { 118 perror(progname); 119 exit (1); 120 } 121 122 load(t); 123 124 user(t); 125 } 126 127 load(t) 128 DB *t; 129 { 130 char *lbuf; 131 int i, l; 132 int status; 133 FILE *fp; 134 DBT key; 135 DBT data; 136 char word[64]; 137 char drow[64]; 138 139 printf("loading %s...\n", DICTIONARY); 140 fflush(stdout); 141 if ((fp = fopen(DICTIONARY, "r")) == (FILE *) NULL) { 142 perror("/usr/dict/words"); 143 (void) (*(t->close))(t->internal); 144 exit (1); 145 } 146 147 key.data = &word[0]; 148 data.data = &drow[0]; 149 while ((lbuf = fgets(word, 64, fp)) != (char *) NULL) { 150 l = strlen(lbuf) - 1; 151 lbuf[l] = '\0'; 152 for (i = 0; i < l; i++) 153 drow[l - (i + 1)] = word[i]; 154 drow[l] = '\0'; 155 156 key.size = data.size = l + 1; 157 158 status = (*(t->put))(t->internal, &key, &data, R_NOOVERWRITE); 159 160 switch (status) { 161 case RET_SUCCESS: 162 break; 163 164 case RET_ERROR: 165 perror("put"); 166 break; 167 168 case RET_SPECIAL: 169 fprintf(stderr, "%s is a duplicate key!\n", lbuf); 170 fflush(stderr); 171 break; 172 } 173 } 174 175 (void) fclose(fp); 176 printf("done\n"); 177 fflush(stdout); 178 } 179 180 user(t) 181 DB *t; 182 { 183 char *lbuf; 184 int argc; 185 int i; 186 char *argv[4]; 187 char buf[512]; 188 189 for (;;) { 190 printf("> "); 191 fflush(stdout); 192 if ((lbuf = fgets(&buf[0], 512, stdin)) == (char *) NULL) 193 break; 194 lbuf[strlen(lbuf) - 1] = '\0'; 195 196 if (strcmp(lbuf, "quit") == 0) 197 break; 198 199 argc = parse(lbuf, &argv[0], 3); 200 if (argc == 0) 201 continue; 202 203 for (i = 0; Commands[i].cmd != (char *) NULL; i++) { 204 if (strcmp(Commands[i].cmd, argv[0]) == 0) 205 break; 206 } 207 208 if (Commands[i].cmd == (char *) NULL) { 209 fprintf(stderr, 210 "%s: command unknown ('help' for help)\n", 211 lbuf); 212 fflush(stderr); 213 continue; 214 } 215 216 if (Commands[i].nargs != argc) { 217 fprintf(stderr, "arg count\n"); 218 fflush(stderr); 219 continue; 220 } 221 222 switch (argc) { 223 case 1: 224 (*(Commands[i].func))(t); 225 break; 226 case 2: 227 (*(Commands[i].func))(t, argv[1]); 228 break; 229 case 3: 230 (*(Commands[i].func))(t, argv[1], argv[2]); 231 break; 232 case 4: 233 (*(Commands[i].func))(t, argv[1], argv[2], argv[3]); 234 break; 235 } 236 } 237 (void) (*(t->close))(t->internal); 238 exit (0); 239 } 240 241 int 242 parse(lbuf, argv, maxargc) 243 char *lbuf; 244 char **argv; 245 int maxargc; 246 { 247 int argc = 0; 248 char *c; 249 250 c = lbuf; 251 while (isspace(*c)) 252 c++; 253 while (*c != '\0' && argc < maxargc) { 254 *argv++ = c; 255 argc++; 256 while (!isspace(*c) && *c != '\0') { 257 c++; 258 } 259 while (isspace(*c)) 260 *c++ = '\0'; 261 } 262 return (argc); 263 } 264 265 int 266 cursor(t, arg) 267 DB *t; 268 char *arg; 269 { 270 int status; 271 DBT key; 272 DBT data; 273 274 key.data = arg; 275 key.size = strlen(arg + 1); 276 status = (*(t->seq))(t->internal, &key, &data, R_CURSOR); 277 if (status == RET_SUCCESS) 278 show(&key, &data); 279 else 280 perror("cursor"); 281 } 282 283 int 284 delcur(t) 285 DB *t; 286 { 287 int status; 288 289 status = (*(t->delete))(t->internal, (DBT *) NULL, R_CURSOR); 290 291 if (status == RET_ERROR) 292 perror("delcur"); 293 } 294 295 int 296 delete(t, arg) 297 DB *t; 298 char *arg; 299 { 300 int status; 301 DBT key; 302 303 key.data = arg; 304 key.size = strlen(arg) + 1; 305 306 status = (*(t->delete))(t->internal, &key, 0); 307 switch (status) { 308 case RET_SUCCESS: 309 break; 310 311 case RET_ERROR: 312 perror("delete"); 313 break; 314 315 case RET_SPECIAL: 316 fprintf(stderr, "%s not found\n", arg); 317 fflush(stderr); 318 break; 319 } 320 } 321 322 int 323 first(t) 324 DB *t; 325 { 326 int status; 327 DBT key; 328 DBT data; 329 330 status = (*(t->seq))(t->internal, &key, &data, R_FIRST); 331 332 switch (status) { 333 case RET_ERROR: 334 perror("first"); 335 break; 336 337 case RET_SPECIAL: 338 printf("no more keys"); 339 break; 340 341 case RET_SUCCESS: 342 show(&key, &data); 343 break; 344 } 345 } 346 int 347 help(t) 348 DB *t; 349 { 350 int i; 351 352 #ifdef lint 353 t = t; 354 #endif /* lint */ 355 for (i = 0; Commands[i].cmd != (char *) NULL; i++) 356 printf("%s\n", Commands[i].descrip); 357 printf("type 'quit' to quit\n"); 358 } 359 360 int 361 insert(t, arg, def) 362 DB *t; 363 char *arg; 364 char *def; 365 { 366 int status; 367 DBT key; 368 DBT data; 369 370 key.data = arg; 371 key.size = strlen(arg) + 1; 372 data.data = def; 373 data.size = strlen(def) + 1; 374 375 status = (*(t->put))(t->internal, &key, &data, R_NOOVERWRITE); 376 switch (status) { 377 case RET_SUCCESS: 378 break; 379 380 case RET_ERROR: 381 perror("put"); 382 break; 383 384 case RET_SPECIAL: 385 fprintf(stderr, "%s is a duplicate key!\n", arg); 386 fflush(stderr); 387 break; 388 } 389 } 390 391 int 392 last(t) 393 DB *t; 394 { 395 int status; 396 DBT key; 397 DBT data; 398 399 status = (*(t->seq))(t->internal, &key, &data, R_LAST); 400 401 switch (status) { 402 case RET_ERROR: 403 perror("last"); 404 break; 405 406 case RET_SPECIAL: 407 printf("no more keys"); 408 break; 409 410 case RET_SUCCESS: 411 show(&key, &data); 412 break; 413 } 414 } 415 416 int 417 lookup(t, arg) 418 DB *t; 419 char *arg; 420 { 421 int status; 422 DBT key; 423 DBT data; 424 425 key.data = arg; 426 key.size = strlen(arg) + 1; 427 428 status = (*(t->get))(t->internal, &key, &data, 0); 429 430 switch (status) { 431 case RET_SPECIAL: 432 printf("not found\n"); 433 break; 434 case RET_SUCCESS: 435 show(&key, &data); 436 break; 437 case RET_ERROR: 438 perror("get"); 439 break; 440 } 441 } 442 443 int 444 next(t) 445 DB *t; 446 { 447 int status; 448 DBT key; 449 DBT data; 450 451 status = (*(t->seq))(t->internal, &key, &data, R_NEXT); 452 453 switch (status) { 454 case RET_ERROR: 455 perror("next"); 456 break; 457 458 case RET_SPECIAL: 459 printf("no more keys"); 460 break; 461 462 case RET_SUCCESS: 463 show(&key, &data); 464 break; 465 } 466 } 467 468 int 469 previous(t) 470 DB *t; 471 { 472 int status; 473 DBT key; 474 DBT data; 475 476 status = (*(t->seq))(t->internal, &key, &data, R_PREV); 477 478 switch (status) { 479 case RET_ERROR: 480 perror("previous"); 481 break; 482 483 case RET_SPECIAL: 484 printf("no more keys"); 485 break; 486 487 case RET_SUCCESS: 488 show(&key, &data); 489 break; 490 } 491 } 492 493 show(key, data) 494 DBT *key; 495 DBT *data; 496 { 497 if (key->size > 0) 498 printf("%s", key->data); 499 if (data->size > 0) 500 printf("/%s", data->data); 501 printf("\n"); 502 } 503