1 /* relational.c:
2 *
3 ****************************************************************
4 * Copyright (C) 2003 Tom Lord
5 *
6 * See the file "COPYING" for further information about
7 * the copyright and warranty status of this work.
8 */
9
10
11 #include "hackerlab/bugs/panic.h"
12 #include "hackerlab/os/stdarg.h"
13 #include "hackerlab/vu/safe.h"
14 #include "hackerlab/vu/safe-vu-utils-vfdbuf.h"
15 #include "hackerlab/arrays/ar.h"
16 #include "hackerlab/sort/qsort.h"
17 #include "hackerlab/char/char-class.h"
18 #include "hackerlab/char/str.h"
19 #include "hackerlab/char/pika-escaping-utils.h"
20 #include "tla/libawk/relational.h"
21
22
23 /* __STDC__ prototypes for static functions */
24 static int rec_cmp_by_field (void * va, void * vb, void * vdata);
25 static int rec_cmp_by_field_fn (void * va, void * vb, void * vdata);
26 static int rec_cmp_by_fields (void * va, void * vb, void * vdata);
27 static int cmp_fields (rel_table table1,
28 ssize_t r1,
29 ssize_t c1,
30 rel_table table2,
31 ssize_t r2,
32 ssize_t c2);
33 static rel_record rel_read_record (int fd,
34 int n_fields,
35 const char * err_name,
36 const char * err_src);
37 static void rel_print_record (int fd, rel_record rec);
38 static void rel_print_pika_escape_iso8859_1_record (int fd, int escape_classes, rel_record rec);
39 static void rel_print_record_sp (int fd, rel_record rec);
40 static void rel_print_pika_escape_iso8859_1_record_sp (int fd, int escape_classes, rel_record rec);
41
42
43 int
rel_n_records(rel_table r)44 rel_n_records (rel_table r)
45 {
46 return ar_size ((void *)r._r, 0, sizeof (rel_record));
47 }
48
49
50 int
rel_n_fields(rel_record r)51 rel_n_fields (rel_record r)
52 {
53 return ar_size ((void *)r._c, 0, sizeof (rel_field));
54 }
55
56
57
58 rel_record
rel_peek_record(rel_table r,ssize_t row)59 rel_peek_record (rel_table r, ssize_t row)
60 {
61 rel_record rec;
62
63 if ((row < 0) || (row > rel_n_records (r)))
64 return rel_record_nil;
65
66 rec = r._r[row];
67
68 return rec;
69 }
70
71
72 rel_field
rel_get_field(rel_table r,ssize_t row,ssize_t col)73 rel_get_field (rel_table r, ssize_t row, ssize_t col)
74 {
75 rel_record rec;
76
77 if ((row < 0) || (row > rel_n_records (r)))
78 return rel_field_nil;
79
80 rec = r._r[row];
81
82 if ((col < 0) || (col > rel_n_fields (rec)))
83 return rel_field_nil;
84
85 dstr_ref (rec._c[col]._d);
86
87 return rec._c[col];
88 }
89
90
91 t_dstr
rel_get_dstr(rel_table r,ssize_t row,ssize_t col)92 rel_get_dstr (rel_table r, ssize_t row, ssize_t col)
93 {
94 t_dstr answer;
95
96 answer = rel_peek_dstr (r, row, col);
97 dstr_ref (answer);
98 return answer;
99 }
100
101
102 t_dstr
rel_peek_dstr(rel_table r,ssize_t row,ssize_t col)103 rel_peek_dstr (rel_table r, ssize_t row, ssize_t col)
104 {
105 rel_record rec;
106
107 if ((row < 0) || (row > rel_n_records (r)))
108 return 0;
109
110 rec = r._r[row];
111
112 if ((col < 0) || (col > rel_n_fields (rec)))
113 return 0;
114
115 return rec._c[col]._d;
116 }
117
118
119 const t_uchar *
rel_peek_str(rel_table r,ssize_t row,ssize_t col)120 rel_peek_str (rel_table r, ssize_t row, ssize_t col)
121 {
122 t_dstr it;
123
124 it = rel_peek_dstr (r, row, col);
125 return dstr_data (0, it);
126 }
127
128
129 t_dstr
rel_rec_peek_dstr(rel_record rec,ssize_t col)130 rel_rec_peek_dstr (rel_record rec, ssize_t col)
131 {
132 if ((col < 0) || (col > rel_n_fields (rec)))
133 return 0;
134
135 return rec._c[col]._d;
136 }
137
138
139 const t_uchar *
rel_rec_peek_str(rel_record rec,ssize_t col)140 rel_rec_peek_str (rel_record rec, ssize_t col)
141 {
142 t_dstr it;
143
144 it = rel_rec_peek_dstr (rec, col);
145 return dstr_data (0, it);
146 }
147
148
149 int
rel_set_taking(rel_table r,ssize_t row,ssize_t col,rel_field d)150 rel_set_taking (rel_table r,
151 ssize_t row,
152 ssize_t col,
153 rel_field d)
154 {
155 rel_record rec;
156
157 if ((row < 0) || (row > rel_n_records (r)))
158 return -1;
159
160 rec = r._r[row];
161
162 if ((col < 0) || (col > rel_n_fields (rec)))
163 return -1;
164
165 dstr_unref (rec._c[col]._d);
166 rec._c[col] = d;
167
168 return 0;
169 }
170
171
172 int
rel_set_record(rel_table r,ssize_t row,rel_record rec)173 rel_set_record (rel_table r, ssize_t row, rel_record rec)
174 {
175 rel_record old_rec;
176
177 if ((row < 0) || (row > rel_n_records (r)))
178 return -1;
179
180 old_rec = r._r[row];
181
182 r._r[row] = rec;
183
184 rel_free_record (old_rec);
185
186 return 0;
187 }
188
189
190 rel_record
rel_make_record_0(void)191 rel_make_record_0 (void)
192 {
193 return rel_record_nil;
194 }
195
196
197 rel_record
rel_make_record_1_taking(rel_field f0)198 rel_make_record_1_taking (rel_field f0)
199 {
200 rel_record answer;
201 answer = rel_record_nil;
202 *(rel_field *)ar_push ((void **)&answer._c, 0, sizeof (rel_field)) = f0;
203 return answer;
204 }
205
206
207 rel_record
rel_make_record_2_taking(rel_field f0,rel_field f1)208 rel_make_record_2_taking (rel_field f0,
209 rel_field f1)
210 {
211 rel_record answer;
212 answer = rel_record_nil;
213 *(rel_field *)ar_push ((void **)&answer._c, 0, sizeof (rel_field)) = f0;
214 *(rel_field *)ar_push ((void **)&answer._c, 0, sizeof (rel_field)) = f1;
215 return answer;
216 }
217
218
219 rel_record
rel_make_record_3_taking(rel_field f0,rel_field f1,rel_field f2)220 rel_make_record_3_taking (rel_field f0,
221 rel_field f1,
222 rel_field f2)
223 {
224 rel_record answer;
225 answer = rel_record_nil;
226 *(rel_field *)ar_push ((void **)&answer._c, 0, sizeof (rel_field)) = f0;
227 *(rel_field *)ar_push ((void **)&answer._c, 0, sizeof (rel_field)) = f1;
228 *(rel_field *)ar_push ((void **)&answer._c, 0, sizeof (rel_field)) = f2;
229 return answer;
230 }
231
232
233 rel_record
rel_make_record_4_taking(rel_field f0,rel_field f1,rel_field f2,rel_field f3)234 rel_make_record_4_taking (rel_field f0,
235 rel_field f1,
236 rel_field f2,
237 rel_field f3)
238 {
239 rel_record answer;
240 answer = rel_record_nil;
241 *(rel_field *)ar_push ((void **)&answer._c, 0, sizeof (rel_field)) = f0;
242 *(rel_field *)ar_push ((void **)&answer._c, 0, sizeof (rel_field)) = f1;
243 *(rel_field *)ar_push ((void **)&answer._c, 0, sizeof (rel_field)) = f2;
244 *(rel_field *)ar_push ((void **)&answer._c, 0, sizeof (rel_field)) = f3;
245 return answer;
246 }
247
248
249 rel_record
rel_make_record_5_taking(rel_field f0,rel_field f1,rel_field f2,rel_field f3,rel_field f4)250 rel_make_record_5_taking (rel_field f0,
251 rel_field f1,
252 rel_field f2,
253 rel_field f3,
254 rel_field f4)
255 {
256 rel_record answer;
257 answer = rel_record_nil;
258 *(rel_field *)ar_push ((void **)&answer._c, 0, sizeof (rel_field)) = f0;
259 *(rel_field *)ar_push ((void **)&answer._c, 0, sizeof (rel_field)) = f1;
260 *(rel_field *)ar_push ((void **)&answer._c, 0, sizeof (rel_field)) = f2;
261 *(rel_field *)ar_push ((void **)&answer._c, 0, sizeof (rel_field)) = f3;
262 *(rel_field *)ar_push ((void **)&answer._c, 0, sizeof (rel_field)) = f4;
263 return answer;
264 }
265
266
267 rel_record
rel_make_record_6_taking(rel_field f0,rel_field f1,rel_field f2,rel_field f3,rel_field f4,rel_field f5)268 rel_make_record_6_taking (rel_field f0,
269 rel_field f1,
270 rel_field f2,
271 rel_field f3,
272 rel_field f4,
273 rel_field f5)
274 {
275 rel_record answer;
276 answer = rel_record_nil;
277 *(rel_field *)ar_push ((void **)&answer._c, 0, sizeof (rel_field)) = f0;
278 *(rel_field *)ar_push ((void **)&answer._c, 0, sizeof (rel_field)) = f1;
279 *(rel_field *)ar_push ((void **)&answer._c, 0, sizeof (rel_field)) = f2;
280 *(rel_field *)ar_push ((void **)&answer._c, 0, sizeof (rel_field)) = f3;
281 *(rel_field *)ar_push ((void **)&answer._c, 0, sizeof (rel_field)) = f4;
282 *(rel_field *)ar_push ((void **)&answer._c, 0, sizeof (rel_field)) = f5;
283 return answer;
284 }
285
286
287 rel_record
rel_make_record_7_taking(rel_field f0,rel_field f1,rel_field f2,rel_field f3,rel_field f4,rel_field f5,rel_field f6)288 rel_make_record_7_taking (rel_field f0,
289 rel_field f1,
290 rel_field f2,
291 rel_field f3,
292 rel_field f4,
293 rel_field f5,
294 rel_field f6)
295 {
296 rel_record answer;
297 answer = rel_record_nil;
298 *(rel_field *)ar_push ((void **)&answer._c, 0, sizeof (rel_field)) = f0;
299 *(rel_field *)ar_push ((void **)&answer._c, 0, sizeof (rel_field)) = f1;
300 *(rel_field *)ar_push ((void **)&answer._c, 0, sizeof (rel_field)) = f2;
301 *(rel_field *)ar_push ((void **)&answer._c, 0, sizeof (rel_field)) = f3;
302 *(rel_field *)ar_push ((void **)&answer._c, 0, sizeof (rel_field)) = f4;
303 *(rel_field *)ar_push ((void **)&answer._c, 0, sizeof (rel_field)) = f5;
304 *(rel_field *)ar_push ((void **)&answer._c, 0, sizeof (rel_field)) = f6;
305 return answer;
306 }
307
308
309 rel_record
rel_make_record_8_taking(rel_field f0,rel_field f1,rel_field f2,rel_field f3,rel_field f4,rel_field f5,rel_field f6,rel_field f7)310 rel_make_record_8_taking (rel_field f0,
311 rel_field f1,
312 rel_field f2,
313 rel_field f3,
314 rel_field f4,
315 rel_field f5,
316 rel_field f6,
317 rel_field f7)
318 {
319 rel_record answer;
320 answer = rel_record_nil;
321 *(rel_field *)ar_push ((void **)&answer._c, 0, sizeof (rel_field)) = f0;
322 *(rel_field *)ar_push ((void **)&answer._c, 0, sizeof (rel_field)) = f1;
323 *(rel_field *)ar_push ((void **)&answer._c, 0, sizeof (rel_field)) = f2;
324 *(rel_field *)ar_push ((void **)&answer._c, 0, sizeof (rel_field)) = f3;
325 *(rel_field *)ar_push ((void **)&answer._c, 0, sizeof (rel_field)) = f4;
326 *(rel_field *)ar_push ((void **)&answer._c, 0, sizeof (rel_field)) = f5;
327 *(rel_field *)ar_push ((void **)&answer._c, 0, sizeof (rel_field)) = f6;
328 *(rel_field *)ar_push ((void **)&answer._c, 0, sizeof (rel_field)) = f7;
329 return answer;
330 }
331
332 const rel_record rel_record_null = { 0 } ; /* make this equivalent with rec_record_nil... maybe they are meant to be the same and should be a single variable? */
333
334 void
rel_add_records(rel_table * table,...)335 rel_add_records (rel_table * table, ...)
336 {
337 va_list rp;
338 rel_record r;
339
340 va_start (rp, table);
341 for (r = va_arg (rp, rel_record); r._c; r = va_arg (rp, rel_record))
342 {
343 *(rel_record *)ar_push ((void **)&table->_r, 0, sizeof (rel_record)) = r;
344 }
345 va_end (rp);
346 }
347
348
349 void
rel_add_field_taking(rel_record * r,rel_field field)350 rel_add_field_taking (rel_record * r, rel_field field)
351 {
352 *(rel_field *)ar_push ((void **)&r->_c, 0, sizeof (rel_field)) = field;
353 }
354
355
356 void
rel_add_field_to_row_taking(rel_table table,ssize_t row,rel_field field)357 rel_add_field_to_row_taking (rel_table table, ssize_t row, rel_field field)
358 {
359 invariant ((0 <= row) && (row < rel_n_records (table)));
360
361 *(rel_field *)ar_push ((void **)&table._r[row]._c, 0, sizeof (rel_field)) = field;
362 }
363
364
365 rel_record
rel_singleton_record_taking(rel_field field)366 rel_singleton_record_taking (rel_field field)
367 {
368 rel_record answer = rel_record_nil;
369
370 *(rel_field *)ar_push ((void **)&answer._c, 0, sizeof (rel_field)) = field;
371 return answer;
372 }
373
374
375
376
377 void
rel_free_table(rel_table t)378 rel_free_table (rel_table t)
379 {
380 int lim;
381 int x;
382
383 lim = rel_n_records (t);
384 for (x = 0; x < lim; ++x)
385 rel_free_record (t._r[x]);
386
387 ar_free ((void **)&t._r, 0);
388 }
389
390 void
rel_free_record(rel_record r)391 rel_free_record (rel_record r)
392 {
393 int lim;
394 int x;
395
396 lim = rel_n_fields (r);
397 for (x = 0; x < lim; ++x)
398 dstr_unref (r._c[x]._d);
399 ar_free ((void **)&r._c, 0);
400 }
401
402
403
404 rel_field
rel_field_ref(rel_field f)405 rel_field_ref (rel_field f)
406 {
407 dstr_ref (f._d);
408 return f;
409 }
410
411
412 void
rel_field_unref(rel_field f)413 rel_field_unref (rel_field f)
414 {
415 dstr_unref (f._d);
416 }
417
418
419 const t_uchar *
rel_field_str(rel_field f)420 rel_field_str (rel_field f)
421 {
422 return dstr_data (0, f._d);
423 }
424
425
426 rel_field
rel_make_field_str(const t_uchar * s)427 rel_make_field_str (const t_uchar * s)
428 {
429 rel_field f;
430
431 f._d = dstr_save (0, s);
432 return f;
433 }
434
435
436 rel_field
rel_make_field_str_n(const t_uchar * s,ssize_t len)437 rel_make_field_str_n (const t_uchar * s, ssize_t len)
438 {
439 rel_field f;
440
441 f._d = dstr_save_n (0, s, len);
442 return f;
443 }
444
445
446 rel_table
rel_ws_split(const t_uchar * string)447 rel_ws_split (const t_uchar * string)
448 {
449 rel_table answer = rel_table_nil;
450 const t_uchar * start;
451 const t_uchar * end;
452
453 if (!string)
454 return rel_table_nil;
455
456 start = string;
457
458 while (1)
459 {
460 while (char_is_space (*start))
461 ++start;
462
463 if (!*start)
464 return answer;
465
466 end = start;
467
468 while (*end && !char_is_space (*end))
469 ++end;
470
471 rel_add_records (&answer, rel_singleton_record_taking (rel_make_field_str_n (start, end - start)), rel_record_null);
472
473 start = end;
474 }
475 }
476
477 rel_table
rel_nl_split(const t_uchar * string)478 rel_nl_split (const t_uchar * string)
479 {
480 rel_table answer = rel_table_nil;
481 const t_uchar * start;
482 const t_uchar * end;
483
484 if (!string)
485 return rel_table_nil;
486
487 start = string;
488
489 while (1)
490 {
491 if (!*start)
492 return answer;
493
494 end = start;
495
496 while (*end && (*end != '\n'))
497 ++end;
498
499 rel_add_records (&answer, rel_singleton_record_taking (rel_make_field_str_n (start, end - start)), rel_record_null);
500
501 if (*end)
502 start = end + 1;
503 else
504 start = end;
505 }
506 }
507
508
509
510
511 rel_table
rel_copy_table(rel_table t)512 rel_copy_table (rel_table t)
513 {
514 rel_table answer;
515 int records;
516 int r;
517
518 records = rel_n_records (t);
519
520 answer = rel_table_nil;
521 ar_setsize ((void **)&answer._r, 0, records, sizeof (rel_record));
522 for (r = 0; r < records; ++r)
523 answer._r[r] = rel_copy_record (t._r[r]);
524
525 return answer;
526 }
527
528
529 rel_record
rel_copy_record(rel_record r)530 rel_copy_record (rel_record r)
531 {
532 rel_record answer;
533 int fields;
534 int f;
535
536 fields = rel_n_fields (r);
537
538 answer = rel_record_nil;
539 ar_setsize ((void **)&answer._c, 0, fields, sizeof (rel_field));
540 for (f = 0; f < fields; ++f)
541 {
542 dstr_ref (r._c[f]._d);
543 answer._c[f] = r._c[f];
544 }
545
546 return answer;
547 }
548
549
550 void
rel_append_x(rel_table * out,rel_table t)551 rel_append_x (rel_table * out, rel_table t)
552 {
553 int lim;
554 int x;
555
556 lim = rel_n_records (t);
557
558 for (x = 0; x < lim; ++x)
559 {
560 *(rel_record *)ar_push ((void **)&out->_r, 0, sizeof (rel_record)) = rel_copy_record (t._r[x]);
561 }
562 }
563
564
565
566 void
rel_reverse_table(rel_table t)567 rel_reverse_table (rel_table t)
568 {
569 int a;
570 int b;
571
572 a = 0;
573 b = rel_n_records (t) - 1;
574
575 while (a < b)
576 {
577 rel_record tmp;
578
579 tmp = t._r[a];
580 t._r[a] = t._r[b];
581 t._r[b] = tmp;
582
583 ++a;
584 --b;
585 }
586 }
587
588
589 struct rel_sort_spec
590 {
591 int reverse_p;
592 int field;
593 };
594
595
596 void
rel_sort_table_by_field(int reverse_p,rel_table t,int field_n)597 rel_sort_table_by_field (int reverse_p,
598 rel_table t,
599 int field_n)
600 {
601 struct rel_sort_spec spec;
602
603 spec.reverse_p = reverse_p;
604 spec.field = field_n;
605
606 quicksort ((void *)t._r, rel_n_records (t), sizeof (rel_record), rec_cmp_by_field, (void *)&spec);
607 }
608
609
610 static int
rec_cmp_by_field(void * va,void * vb,void * vdata)611 rec_cmp_by_field (void * va, void * vb, void * vdata)
612 {
613 rel_record * a;
614 rel_record * b;
615 struct rel_sort_spec * spec;
616 t_dstr da;
617 t_dstr db;
618 int raw_cmp;
619
620 a = (rel_record *)va;
621 b = (rel_record *)vb;
622 spec = (struct rel_sort_spec *)vdata;
623
624 da = (*a)._c[spec->field]._d;
625 db = (*b)._c[spec->field]._d;
626
627 raw_cmp = dstr_cmp (da, db);
628
629 if (!raw_cmp && (da != db))
630 {
631 if ((unsigned long)da < ((unsigned long)db))
632 {
633 dstr_ref (da);
634 dstr_unref (db);
635 (*b)._c[spec->field]._d = da;
636 }
637 else
638 {
639 dstr_ref (db);
640 dstr_unref (da);
641 (*a)._c[spec->field]._d = db;
642 }
643 }
644
645 if (spec->reverse_p)
646 {
647 return -raw_cmp;
648 }
649 else
650 {
651 return raw_cmp;
652 }
653 }
654
655
656
657 struct rel_sort_by_fn_spec
658 {
659 int reverse_p;
660 int field;
661 int (*fn) (const t_uchar * va, const t_uchar * vb);
662 };
663
664
665 void
rel_sort_table_by_field_fn(int reverse_p,rel_table t,int field_n,int (* fn)(const t_uchar *,const t_uchar *))666 rel_sort_table_by_field_fn (int reverse_p,
667 rel_table t,
668 int field_n,
669 int (*fn)(const t_uchar *, const t_uchar *))
670 {
671 struct rel_sort_by_fn_spec spec;
672
673 spec.reverse_p = reverse_p;
674 spec.field = field_n;
675 spec.fn = fn;
676
677 quicksort ((void *)t._r, rel_n_records (t), sizeof (rel_record), rec_cmp_by_field_fn, (void *)&spec);
678 }
679
680
681 static int
rec_cmp_by_field_fn(void * va,void * vb,void * vdata)682 rec_cmp_by_field_fn (void * va, void * vb, void * vdata)
683 {
684 rel_record * a;
685 rel_record * b;
686 struct rel_sort_by_fn_spec * spec;
687
688 a = (rel_record *)va;
689 b = (rel_record *)vb;
690 spec = (struct rel_sort_by_fn_spec *)vdata;
691
692 if (spec->reverse_p)
693 {
694 return -spec->fn (dstr_data (0, (*a)._c[spec->field]._d), dstr_data (0, (*b)._c[spec->field]._d));
695 }
696 else
697 {
698 return spec->fn (dstr_data (0, (*a)._c[spec->field]._d), dstr_data (0, (*b)._c[spec->field]._d));
699 }
700 }
701
702
703
704 struct rel_nsort_spec
705 {
706 int reverse_p;
707 int * fields;
708 };
709
710
711 void
rel_sort_table_by_fields(int reverse_p,rel_table t,int * fields)712 rel_sort_table_by_fields (int reverse_p,
713 rel_table t,
714 int * fields)
715 {
716 struct rel_nsort_spec spec;
717
718 spec.reverse_p = reverse_p;
719 spec.fields = fields;
720
721 quicksort ((void *)t._r, rel_n_records (t), sizeof (rel_record), rec_cmp_by_fields, (void *)&spec);
722 }
723
724
725 int *
rel_sort_fields(int f,...)726 rel_sort_fields (int f, ...)
727 {
728 va_list fp;
729 int * answer;
730
731 answer = 0;
732 *(int *)ar_push ((void **)&answer, 0, sizeof (int)) = f;
733
734 va_start (fp, f);
735 while (1)
736 {
737 f = va_arg (fp, int);
738 *(int *)ar_push ((void **)&answer, 0, sizeof (int)) = f;
739 if (f < 0)
740 break;
741 }
742 va_end (fp);
743 return answer;
744 }
745
746
747 static int
rec_cmp_by_fields(void * va,void * vb,void * vdata)748 rec_cmp_by_fields (void * va, void * vb, void * vdata)
749 {
750 rel_record * a;
751 rel_record * b;
752 struct rel_nsort_spec * spec;
753 int nth;
754
755 a = (rel_record *)va;
756 b = (rel_record *)vb;
757 spec = (struct rel_nsort_spec *)vdata;
758
759 for (nth = 0; spec->fields[nth] >= 0; ++nth)
760 {
761 t_dstr da;
762 t_dstr db;
763 int raw_cmp;
764 int cmp;
765
766 da = (*a)._c[spec->fields[nth]]._d;
767 db = (*b)._c[spec->fields[nth]]._d;
768
769 raw_cmp = dstr_cmp (da, db);
770
771 if (!raw_cmp && (da != db))
772 {
773 if ((unsigned long)da < ((unsigned long)db))
774 {
775 dstr_ref (da);
776 dstr_unref (db);
777 (*b)._c[spec->fields[nth]]._d = da;
778 }
779 else
780 {
781 dstr_ref (db);
782 dstr_unref (da);
783 (*a)._c[spec->fields[nth]]._d = db;
784 }
785 }
786
787 if (spec->reverse_p)
788 {
789 cmp = -raw_cmp;
790 }
791 else
792 {
793 cmp = raw_cmp;
794 }
795
796 if (cmp)
797 return cmp;
798 }
799
800 return 0;
801 }
802
803
804
805 void
rel_uniq_by_field(rel_table * table,int field)806 rel_uniq_by_field (rel_table * table,
807 int field)
808 {
809 int lim;
810 int dest;
811 int src;
812
813 lim = rel_n_records (*table);
814 for (dest = 0, src = 0; src < lim; ++dest, ++src)
815 {
816 table->_r[dest] = table->_r[src];
817
818 while ((src < (lim - 1)) && !cmp_fields (*table, dest, field, *table, src + 1, field))
819 {
820 rel_free_record (table->_r[src + 1]);
821 ++src;
822 }
823 }
824 ar_setsize ((void **)&table->_r, 0, dest, sizeof (rel_record));
825 }
826
827
828
829 rel_table
rel_cut(rel_cut_spec fields,rel_table t)830 rel_cut (rel_cut_spec fields, rel_table t)
831 {
832 rel_table answer;
833 int lim;
834 int x;
835
836 answer = rel_table_nil;
837
838 lim = ar_size ((void *)t._r, 0, sizeof (rel_record));
839 for (x = 0; x < lim; ++x)
840 {
841 rel_add_records (&answer, rel_cut_record (fields, t._r[x]), rel_record_null);
842 }
843
844 return answer;
845 }
846
847
848 rel_record
rel_cut_record(rel_cut_spec fields,rel_record r)849 rel_cut_record (rel_cut_spec fields, rel_record r)
850 {
851 rel_record answer;
852 int x;
853
854 answer = rel_record_nil;
855 for (x = 0; fields[x] >= 0; ++x)
856 {
857 dstr_ref (r._c[fields[x]]._d);
858 *(rel_field *)ar_push ((void **)&answer._c, 0, sizeof (t_uchar *)) = r._c[fields[x]];
859 }
860 return answer;
861 }
862
863
864 rel_cut_spec
rel_cut_list(int field,...)865 rel_cut_list (int field, ...)
866 {
867 va_list fp;
868 rel_cut_spec answer;
869
870 answer = 0;
871 *(int *)ar_push ((void **)&answer, 0, sizeof (int)) = field;
872
873 va_start (fp, field);
874 while (1)
875 {
876 field = va_arg (fp, int);
877 *(int *)ar_push ((void **)&answer, 0, sizeof (int)) = field;
878 if (field < 0)
879 break;
880 }
881 va_end (fp);
882 return answer;
883 }
884
885
886 static int
cmp_fields(rel_table table1,ssize_t r1,ssize_t c1,rel_table table2,ssize_t r2,ssize_t c2)887 cmp_fields (rel_table table1,
888 ssize_t r1,
889 ssize_t c1,
890 rel_table table2,
891 ssize_t r2,
892 ssize_t c2)
893 {
894 t_dstr d1;
895 t_dstr d2;
896 int cmp;
897
898 d1 = table1._r[r1]._c[c1]._d;
899 d2 = table2._r[r2]._c[c2]._d;
900
901 cmp = dstr_cmp (d1, d2);
902
903 if (!cmp && (d1 != d2))
904 {
905 if ((unsigned long)d1 < (unsigned long)d2)
906 {
907 dstr_ref (d1);
908 dstr_unref (d2);
909 table2._r[r2]._c[c2]._d = d1;
910 }
911 else
912 {
913 dstr_ref (d2);
914 dstr_unref (d1);
915 table1._r[r1]._c[c1]._d = d2;
916 }
917 }
918
919 return cmp;
920 }
921
922
923 rel_table
rel_join(int absence_table,struct rel_join_output_spec * output,int table1_field,int table2_field,rel_table table1,rel_table table2)924 rel_join (int absence_table,
925 struct rel_join_output_spec * output,
926 int table1_field,
927 int table2_field,
928 rel_table table1,
929 rel_table table2)
930 {
931 int f1_len;
932 int f2_len;
933 int f1_pos;
934 int f2_pos;
935 int n_output_fields;
936 rel_table answer;
937
938 /* How curious that such a simple loop can do so many useful things.
939 */
940
941 answer = rel_table_nil;
942
943 f1_len = rel_n_records (table1);
944 f2_len = rel_n_records (table2);
945
946 for (n_output_fields = 0; output[n_output_fields].table != -1; ++n_output_fields)
947 ;
948
949 f1_pos = 0;
950 f2_pos = 0;
951
952 while ((f1_pos < f1_len) || (f2_pos < f2_len))
953 {
954 int cmp;
955 int want_output;
956
957 if (f2_pos == f2_len)
958 cmp = -1;
959 else if (f1_pos == f1_len)
960 cmp = 1;
961 else
962 cmp = cmp_fields (table1, f1_pos, table1_field, table2, f2_pos, table2_field);
963
964 if (absence_table < 0)
965 want_output = !cmp;
966 else if (absence_table == 1)
967 want_output = (cmp < 0);
968 else
969 want_output = (cmp > 0);
970
971 if (want_output)
972 {
973 rel_record r;
974 rel_record f1_rec;
975 rel_record f2_rec;
976 int x;
977
978 r = rel_record_nil;
979 f1_rec = ((f1_pos < f1_len) ? table1._r[f1_pos] : r);
980 f2_rec = ((f2_pos < f2_len) ? table2._r[f2_pos] : r);
981 for (x = 0; x < n_output_fields; ++x)
982 {
983 rel_field field;
984
985 field = (((output[x].table == 1)
986 ? f1_rec
987 : f2_rec)
988 ._c[output[x].field]);
989
990 dstr_ref (field._d);
991 *(rel_field *)ar_push ((void **)&r._c, 0, sizeof (char *)) = field;
992 }
993 *(rel_record *)ar_push ((void **)&answer._r, 0, sizeof (rel_record)) = r;
994 }
995
996 if ((f1_pos < f1_len) && (cmp <= 0))
997 ++f1_pos;
998
999 if ((f2_pos < f2_len) && (cmp >= 0))
1000 ++f2_pos;
1001 }
1002
1003 return answer;
1004 }
1005
1006
1007 struct rel_join_output_spec *
rel_join_output(int table,int field,...)1008 rel_join_output (int table,
1009 int field, ...)
1010 {
1011 va_list ap;
1012 struct rel_join_output_spec * answer;
1013 struct rel_join_output_spec * item;
1014 int x;
1015
1016 static struct rel_join_output_spec ** cache = 0;
1017
1018 answer = 0;
1019
1020 for (x = 0; !answer && x < ar_size (cache, 0, sizeof (struct rel_join_output_spec *)); ++x)
1021 {
1022 item = cache[x];
1023
1024 if (item->table != table || item->field != field)
1025 continue;
1026
1027 va_start (ap, field);
1028 while (1)
1029 {
1030 int tmp_table;
1031 int tmp_field;
1032
1033 ++item;
1034 tmp_table = va_arg (ap, int);
1035 if (tmp_table < 0)
1036 tmp_field = -1;
1037 else
1038 tmp_field = va_arg (ap, int);
1039
1040 if (item->table != tmp_table || item->field != tmp_field)
1041 break;
1042 if (item->table == -1)
1043 {
1044 answer = cache[x];
1045 break;
1046 }
1047 }
1048 va_end (ap);
1049 }
1050
1051 if (!answer)
1052 {
1053 item = (struct rel_join_output_spec *)ar_push ((void **)&answer, 0, sizeof (struct rel_join_output_spec));
1054 item->table = table;
1055 item->field = field;
1056
1057 va_start (ap, field);
1058 while (1)
1059 {
1060 table = va_arg (ap, int);
1061 if (table < 0)
1062 break;
1063 field = va_arg (ap, int);
1064
1065 item = (struct rel_join_output_spec *)ar_push ((void **)&answer, 0, sizeof (struct rel_join_output_spec));
1066 item->table = table;
1067 item->field = field;
1068 }
1069 va_end (ap);
1070
1071 item = (struct rel_join_output_spec *)ar_push ((void **)&answer, 0, sizeof (struct rel_join_output_spec));
1072 item->table = -1;
1073 item->field = -1;
1074
1075 *(struct rel_join_output_spec **)ar_push ((void **)&cache, 0, sizeof (struct rel_join_output_spec *)) = answer;
1076 }
1077
1078 return answer;
1079 }
1080
1081
1082 rel_table
rel_read_table(int fd,int n_fields,const char * err_name,const char * err_src)1083 rel_read_table (int fd,
1084 int n_fields,
1085 const char * err_name,
1086 const char * err_src)
1087 {
1088 rel_record rec;
1089 rel_table answer;
1090
1091 answer = rel_table_nil;
1092 while (1)
1093 {
1094 rec = rel_read_record (fd, n_fields, err_name, err_src);
1095 if (!rec._c)
1096 break;
1097 *(rel_record *)ar_push ((void **)&answer._r, 0, sizeof (rel_record)) = rec;
1098 }
1099 return answer;
1100 }
1101
1102
1103 static rel_record
rel_read_record(int fd,int n_fields,const char * err_name,const char * err_src)1104 rel_read_record (int fd,
1105 int n_fields,
1106 const char * err_name,
1107 const char * err_src)
1108 {
1109 t_uchar * line;
1110 long len;
1111 t_uchar * pos;
1112 int f;
1113 rel_record answer;
1114
1115 safe_next_line (&line, &len, fd);
1116 if (!line)
1117 return rel_record_nil;
1118
1119 answer = rel_record_nil;
1120 ar_setsize ((void **)&answer._c, 0, n_fields, sizeof (rel_field));
1121
1122 pos = line;
1123 for (f = 0; f < n_fields; ++f)
1124 {
1125
1126 while (len && !char_is_space (*pos))
1127 {
1128 ++pos;
1129 --len;
1130 }
1131
1132 if (!len || (pos == line))
1133 {
1134 if (err_name)
1135 {
1136 safe_printfmt (2, "%s: ill formated input\n", err_name);
1137 safe_printfmt (2, " input source: %s\n", err_src);
1138 exit (2);
1139 }
1140 }
1141
1142 answer._c[f]._d = dstr_save_n (0, line, pos - line);
1143
1144 while (len && char_is_space (*pos))
1145 {
1146 ++pos;
1147 --len;
1148 }
1149
1150 line = pos;
1151 }
1152
1153 return answer;
1154 }
1155
1156
1157
1158 void
rel_print_table(int fd,rel_table table)1159 rel_print_table (int fd, rel_table table)
1160 {
1161 int recs;
1162 int r;
1163
1164 recs = ar_size ((void *)table._r, 0, sizeof (rel_record));
1165
1166 for (r = 0; r < recs; ++r)
1167 rel_print_record (fd, table._r[r]);
1168 }
1169
1170
1171 void
rel_print_pika_escape_iso8859_1_table(int fd,int escape_classes,rel_table table)1172 rel_print_pika_escape_iso8859_1_table (int fd, int escape_classes, rel_table table)
1173 {
1174 int recs;
1175 int r;
1176
1177 recs = ar_size ((void *)table._r, 0, sizeof (rel_record));
1178
1179 for (r = 0; r < recs; ++r)
1180 rel_print_pika_escape_iso8859_1_record (fd, escape_classes, table._r[r]);
1181 }
1182
1183
1184 void
rel_print_table_sp(int fd,rel_table file)1185 rel_print_table_sp (int fd, rel_table file)
1186 {
1187 int recs;
1188 int r;
1189
1190 recs = ar_size ((void *)file._r, 0, sizeof (rel_record));
1191
1192 for (r = 0; r < recs; ++r)
1193 rel_print_record_sp (fd, file._r[r]);
1194 }
1195
1196
1197 void
rel_print_pika_escape_iso8859_1_table_sp(int fd,int escape_classes,rel_table file)1198 rel_print_pika_escape_iso8859_1_table_sp (int fd, int escape_classes, rel_table file)
1199 {
1200 int recs;
1201 int r;
1202
1203 recs = ar_size ((void *)file._r, 0, sizeof (rel_record));
1204
1205 for (r = 0; r < recs; ++r)
1206 rel_print_pika_escape_iso8859_1_record_sp (fd, escape_classes, file._r[r]);
1207 }
1208
1209
1210 static void
rel_print_record(int fd,rel_record rec)1211 rel_print_record (int fd, rel_record rec)
1212 {
1213 int fields;
1214 int f;
1215
1216 fields = ar_size ((void *)rec._c, 0, sizeof (rel_field));
1217
1218 for (f = 0; f < fields; ++f)
1219 {
1220 safe_printfmt (fd, "%s%s", (f ? "\t" : ""), dstr_data (0, rec._c[f]._d));
1221 }
1222
1223 if (f)
1224 safe_printfmt (fd, "\n");
1225 }
1226
1227
1228 static void
rel_print_pika_escape_iso8859_1_record(int fd,int escape_classes,rel_record rec)1229 rel_print_pika_escape_iso8859_1_record (int fd, int escape_classes, rel_record rec)
1230 {
1231 int fields;
1232 int f;
1233
1234 fields = ar_size ((void *)rec._c, 0, sizeof (rel_field));
1235
1236 for (f = 0; f < fields; ++f)
1237 {
1238 t_uchar * item;
1239
1240 item = pika_save_escape_iso8859_1 (0, 0, escape_classes, dstr_data (0, rec._c[f]._d));
1241 safe_printfmt (fd, "%s%s", (f ? "\t" : ""), item);
1242 lim_free (0, item);
1243 }
1244
1245 if (f)
1246 safe_printfmt (fd, "\n");
1247 }
1248
1249
1250 static void
rel_print_record_sp(int fd,rel_record rec)1251 rel_print_record_sp (int fd, rel_record rec)
1252 {
1253 int fields;
1254 int f;
1255
1256 fields = ar_size ((void *)rec._c, 0, sizeof (rel_field));
1257
1258 for (f = 0; f < fields; ++f)
1259 {
1260 safe_printfmt (fd, "%s%s", (f ? " " : ""), dstr_data (0, rec._c[f]._d));
1261 }
1262
1263 if (f)
1264 safe_printfmt (fd, "\n");
1265 }
1266
1267
1268 static void
rel_print_pika_escape_iso8859_1_record_sp(int fd,int escape_classes,rel_record rec)1269 rel_print_pika_escape_iso8859_1_record_sp (int fd, int escape_classes, rel_record rec)
1270 {
1271 int fields;
1272 int f;
1273
1274 fields = ar_size ((void *)rec._c, 0, sizeof (rel_field));
1275
1276 for (f = 0; f < fields; ++f)
1277 {
1278 t_uchar * item;
1279
1280 item = pika_save_escape_iso8859_1 (0, 0, escape_classes, dstr_data (0, rec._c[f]._d));
1281 safe_printfmt (fd, "%s%s", (f ? " " : ""), item);
1282 lim_free (0, item);
1283 }
1284
1285 if (f)
1286 safe_printfmt (fd, "\n");
1287 }
1288
1289 rel_table
rel_table_substract(rel_table t,rel_table t2)1290 rel_table_substract (rel_table t, rel_table t2)
1291 {
1292 rel_table answer = rel_table_nil;
1293 int lim;
1294 int x;
1295
1296 lim = rel_n_records (t);
1297
1298 for (x = 0; x < lim; ++x)
1299 {
1300 if (!rel_table_contains(t2, t._r[x]))
1301 *(rel_record *)ar_push ((void **)&answer._r, 0, sizeof (rel_record)) = rel_copy_record (t._r[x]);
1302 }
1303
1304 return answer;
1305 }
1306
1307 int
rel_table_contains(rel_table t,rel_record r)1308 rel_table_contains(rel_table t, rel_record r)
1309 { /* assuming the table is one column only */
1310 int lim;
1311 int x;
1312 t_dstr d1;
1313 t_dstr d2;
1314
1315 d2 = r._c[0]._d;
1316
1317 lim = rel_n_records(t);
1318
1319 for (x = 0; x < lim; x++)
1320 {
1321 d1 = t._r[x]._c[0]._d;
1322 if (dstr_cmp(d1, d2) == 0)
1323 return 1;
1324
1325 }
1326 return 0;
1327
1328 }
1329
1330
1331
1332
1333 /* tag: Tom Lord Mon May 5 12:50:00 2003 (relational.c)
1334 */
1335