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