sdbuniq.c (1874B)
1 #include "std.h" 2 3 static char *file; 4 static char *key[256]; 5 6 static int 7 iskey(char *attr) 8 { 9 ulong i; 10 11 for (i = 0; key[i]; ++i) 12 if (!strcmp(attr, key[i])) 13 return 1; 14 return 0; 15 } 16 17 static int 18 isnew(Sdbr r0, Sdbr r1, char *attr) 19 { 20 String val[2]; 21 22 val[0] = sdbr_val(r0, attr); 23 val[1] = sdbr_val(r1, attr); 24 if (!val[1].s 25 || (val[0].s && !strcmp(val[0].s, val[1].s)) 26 ) 27 return 0; 28 return 1; 29 } 30 31 static void 32 usage(void) 33 { 34 fprint(2, "sdbuniq: [-f file] [attr]...\n"); 35 exits("usage"); 36 } 37 38 void 39 main(int argc, char *argv[]) 40 { 41 Sdb db; 42 Sdbr r, cr, nr, *sr; 43 char *attr; 44 ulong i, nk; 45 46 ARGBEGIN { 47 case 'f': 48 file = EARGF(usage()); 49 break; 50 default: 51 usage(); 52 } ARGEND; 53 for (nk = 0; *argv; ++nk) 54 key[nk] = *argv++; 55 sdbr_init(&cr); 56 sdbr_init(&nr); 57 sdbr_init(&r); 58 sdb_open(&db, file); 59 if (!sdb_next(&db)) 60 exits(0); 61 sdbr_dup(&cr, db.r[db.n]); 62 sdbr_dup(&nr, db.r[db.n]); 63 for (;sdb_next(&db);) { 64 sr = db.r + db.n; 65 /* first attribute is always a key, regardless of name */ 66 if (strcmp(sr->val[0].s, cr.val[0].s)) { 67 if (sdbr_n(nr) > nk + 1) 68 sdbr_print(nr); 69 sdbr_dup(&cr, *sr); 70 sdbr_dup(&nr, *sr); 71 continue; 72 } 73 /* 74 * check each key for changes and update internal 75 * current record (cr) state 76 */ 77 for (i = 0; i < nk; ++i) { 78 if (!isnew(cr, *sr, key[i])) 79 continue; 80 if (sdbr_n(nr) > nk + 1) 81 sdbr_print(nr); 82 sdbr_zero(&nr); 83 sdbr_add(&nr, cr.attr[0], cr.val[0]); 84 for (i = 0; i < nk; ++i) 85 sdbr_add(&nr, Str(key[i]) 86 , sdbr_val(*sr, key[i]) 87 ); 88 sdbr_edit(&cr, nr); 89 break; 90 } 91 for (i = 1; i < sdbr_n(*sr); ++i) { 92 attr = sr->attr[i].s; 93 if (iskey(attr) || !isnew(cr, *sr, attr)) 94 continue; 95 sdbr_add(&r, Str(attr), sdbr_val(*sr, attr)); 96 } 97 if (sdbr_n(r)) { 98 sdbr_edit(&cr, r); 99 sdbr_edit(&nr, r); 100 sdbr_zero(&r); 101 } 102 } 103 if (sdbr_n(nr) > nk + 1) 104 sdbr_print(nr); 105 exits(0); 106 }