1 /* namespace.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/fmt/cvt.h"
13 #include "hackerlab/char/char-class.h"
14 #include "hackerlab/char/str.h"
15 #include "hackerlab/sort/qsort.h"
16 #include "hackerlab/vu/safe.h"
17 #include "tla/libfsutils/safety.h"
18 #include "tla/libarch/my.h"
19 #include "tla/libarch/namespace.h"
20
21
22 /* __STDC__ prototypes for static functions */
23 static const t_uchar * over_opt_archive_prefix (const t_uchar * name);
24 static const t_uchar * over_archive_name (const t_uchar * in);
25 static const t_uchar * over_basename (const t_uchar * in);
26 static const t_uchar * over_separator (const t_uchar * in);
27 static const t_uchar * over_version (const t_uchar * in);
28 static const t_uchar * over_patch_level (const t_uchar * in);
29
30
31
32 int
arch_valid_id(const t_uchar * id)33 arch_valid_id (const t_uchar * id)
34 {
35 const t_uchar * non_empty_marker;
36
37 /* This isn't exactly the same as larch's version --
38 * it's a superset. Both are wrong, really. :-)
39 */
40
41 while (char_is_alnum (*id)
42 || char_is_space (*id)
43 || (char_is_punct (*id) && (*id != '<')))
44 ++id;
45
46 if (*id != '<')
47 return 0;
48
49 ++id;
50
51 non_empty_marker = id;
52
53 while (char_is_alnum (*id)
54 || (*id == '-')
55 || (*id == '+')
56 || (*id == '_')
57 || (*id == '.'))
58 ++id;
59
60 if (id == non_empty_marker)
61 return 0;
62
63 if (*id != '@')
64 return 0;
65
66 ++id;
67
68 non_empty_marker = id;
69
70 while (char_is_alnum (*id)
71 || (*id == '-')
72 || (*id == '_')
73 || (*id == '.'))
74 ++id;
75
76 if (*id != '>')
77 return 0;
78
79 ++id;
80
81 if (*id)
82 return 0;
83
84 return 1;
85 }
86
87 int
arch_valid_archive_name(const t_uchar * name)88 arch_valid_archive_name (const t_uchar * name)
89 {
90 const t_uchar * end;
91
92 if (!name)
93 return 0;
94
95 end = over_archive_name (name);
96
97 if (!end || *end)
98 return 0;
99 else
100 return 1;
101 }
102
103 int
arch_valid_patch_level_name(const t_uchar * name)104 arch_valid_patch_level_name (const t_uchar * name)
105 {
106 t_uchar * lvl;
107
108 if (!str_cmp (name, "base-0"))
109 return 1;
110
111 if (str_cmp_prefix ("patch-", name) && str_cmp_prefix ("version-", name) && str_cmp_prefix ("versionfix-", name))
112 return 0;
113
114 lvl = str_chr_index (name, '-');
115 if (!lvl)
116 return 0;
117
118 ++lvl;
119
120 if (!*lvl)
121 return 0;
122
123 while (char_is_digit (*lvl))
124 ++lvl;
125
126 if (*lvl)
127 return 0;
128 else
129 return 1;
130 }
131
132 int
arch_valid_config_name(const t_uchar * name)133 arch_valid_config_name (const t_uchar * name)
134 {
135 return is_non_upwards_relative_path (name);
136 }
137
138
139 /*(c arch_valid_package_name)
140 * int arch_valid_package_name (const t_uchar * name,
141 * enum arch_valid_package_name_archive archive_disposition,
142 * enum arch_valid_package_name_types type,
143 * int tolerant);
144 *
145 * Return non-0 if `name' is a valid arch name of the sort described by
146 * the other arguments.
147 *
148 * `archive_disposition' may be any of the values:
149 *
150 * arch_no_archive the name must not be fully qualified (must have no
151 * no archive name component)
152 *
153 * arch_maybe_archive the name _may_ be fully qualified
154 *
155 * arch_req_archive the name _must_ be fully qualified
156 *
157 *
158 * `type' may be any of the values:
159 *
160 * arch_req_category the name must have at least a category
161 *
162 * arch_req_package the name must have a category and may
163 * have a branch label
164 *
165 * arch_req_version the name must have a version id
166 * (and therefore must have a category and
167 * may have a branch label)
168 *
169 * arch_req_patch_level the name must have a category, may have a
170 * branch label, must have a version id, and
171 * must have a revision name
172 *
173 * `tolerant':
174 *
175 * if 0, then the name may not have any components beyond those
176 * required by `type'. For example, if type is `arch_req_category',
177 * then the name may not have a branch label or version id.
178 *
179 * if 1, then the name may have additional components
180 */
181 int
arch_valid_package_name(const t_uchar * name,enum arch_valid_package_name_archive archive_disposition,enum arch_valid_package_name_types type,int tolerant)182 arch_valid_package_name (const t_uchar * name,
183 enum arch_valid_package_name_archive archive_disposition,
184 enum arch_valid_package_name_types type,
185 int tolerant)
186 {
187 int has_archive;
188 int has_category;
189 int has_branch;
190 int has_version;
191 int has_patch_level;
192 const t_uchar * next;
193
194 if (!name)
195 return 0;
196
197 has_archive = 0;
198 has_category = 0;
199 has_branch = 0;
200 has_version = 0;
201 has_patch_level = 0;
202
203 next = over_opt_archive_prefix (name);
204
205 has_archive = (next && (next != name));
206
207 switch (archive_disposition)
208 {
209 case arch_maybe_archive:
210 {
211 if (!next)
212 return 0;
213 break;
214 }
215
216 case arch_req_archive:
217 {
218 if (!next || (next == name))
219 return 0;
220 break;
221 }
222
223 case arch_no_archive:
224 {
225 if (!next || (next != name))
226 return 0;
227 break;
228 }
229 }
230
231 name = next;
232
233
234 name = over_basename (name);
235 if (!name)
236 return 0;
237 else
238 has_category = 1;
239
240 if (*name)
241 {
242 name = over_separator (name);
243 if (!name)
244 return 0;
245
246 next = over_basename (name);
247 if (next)
248 {
249 has_branch = 1;
250 name = next;
251 if (*name)
252 {
253 name = over_separator (name);
254 if (!name)
255 return 0;
256 }
257 }
258
259 if (*name)
260 {
261 name = over_version (name);
262 if (!name)
263 return 0;
264 has_version = 1;
265
266 if (*name)
267 {
268 name = over_separator (name);
269 if (!name)
270 return 0;
271
272 name = over_patch_level (name);
273 if (!name || *name)
274 return 0;
275
276 has_patch_level = 1;
277 }
278 }
279 }
280
281 switch (type)
282 {
283 case arch_req_category:
284 {
285 if (tolerant)
286 return 1;
287 else
288 return !has_branch && !has_version;
289 break;
290 }
291
292 case arch_req_package:
293 {
294 if (tolerant)
295 return 1;
296 else
297 return !has_version;
298 break;
299 }
300
301 case arch_req_version:
302 {
303 if (tolerant)
304 return has_version;
305 else
306 return has_version && !has_patch_level;
307 break;
308 }
309
310 case arch_req_patch_level:
311 {
312 return has_patch_level;
313 }
314
315 default:
316 {
317 panic ("arch_valid_package_name: bad argument.");
318 return 0;
319 }
320 }
321 }
322
323
324
325 /*(c arch_is_system_package_name)
326 * int arch_is_system_package_name (const t_uchar * name);
327 *
328 * Return non-0 if `name' is a system package name.
329 */
330 int
arch_is_system_package_name(const t_uchar * name)331 arch_is_system_package_name (const t_uchar * name)
332 {
333 t_uchar * package = 0;
334 int answer;
335
336 package = arch_parse_package_name (arch_ret_package, 0, name);
337 answer = !!str_chr_index (name, '%');
338 lim_free (0, package);
339 return answer;
340 }
341
342
343 /*(c arch_parse_package_name)
344 * t_uchar * arch_parse_package_name (enum arch_parse_package_name_type type,
345 * const t_uchar * default_archive,
346 * const t_uchar * name);
347 *
348 * Parse a package name.
349 *
350 * `type' may be any of the values:
351 *
352 * arch_ret_archive Return the archive component of the name,
353 * or the value `default_archive' if the name
354 * is not fully qualified.
355 *
356 * arch_ret_non_archive Return all of the name except its (optional)
357 * archive component.
358 *
359 * arch_ret_category Return just the category name.
360 *
361 * arch_ret_package Return the category--branch if the name has a
362 * branch label, just category otherwise.
363 *
364 * arch_ret_version Return just the version id of the name.
365 *
366 * arch_ret_package_version Return the category(--branch)?--version
367 * of the name
368 *
369 * arch_ret_patch_level Return just the revision id of the name
370 *
371 *
372 * Note that there is no `arch_ret_branch' (since not all names have branch labels)
373 * and no `arch_ret_package_patch_level' (since `arch_ret_non_archive' will do that
374 * job).
375 *
376 * `default_archive' is the archive name to use for `arch_ret_archive' if the
377 * name is not fully qualified. Typically, the value of `default_archive'
378 * is taken from a command-line -A argument or the user's .arch-params/=default-archive
379 * file.
380 *
381 * `name' is the name to parse.
382 *
383 */
384 t_uchar *
arch_parse_package_name(enum arch_parse_package_name_type type,const t_uchar * default_archive,const t_uchar * name)385 arch_parse_package_name (enum arch_parse_package_name_type type,
386 const t_uchar * default_archive,
387 const t_uchar * name)
388 {
389 if (!arch_valid_package_name (name, arch_maybe_archive, arch_req_package, 1))
390 {
391 safe_printfmt(2, "Invalid revision name %s provided\n", name);
392 return 0;
393 }
394 /*invariant (arch_valid_package_name (name, arch_maybe_archive, arch_req_package, 1));*/
395
396 switch (type)
397 {
398 default:
399 panic ("bad argument to arch_parse_package_name");
400 return 0; /* notreached */
401 break;
402
403 case arch_ret_archive:
404 {
405 t_uchar * slash;
406
407 slash = str_chr_index (name, '/');
408 if (!slash)
409 {
410 t_uchar * answer = 0;
411 answer = arch_my_default_archive (default_archive);
412 if (!answer)
413 {
414 safe_printfmt (2, "arch: no default archive set\n");
415 exit (2);
416 }
417 return answer;
418 }
419 else
420 {
421 return str_save_n (0, name, slash - name);
422 }
423 break;
424 }
425
426 case arch_ret_non_archive:
427 {
428 t_uchar * slash;
429
430 slash = str_chr_index (name, '/');
431 if (!slash)
432 return str_save (0, name);
433 else
434 return str_save (0, slash + 1);
435
436 break;
437 }
438
439 case arch_ret_category:
440 {
441 const t_uchar * cat_end;
442
443 name = over_opt_archive_prefix (name);
444 cat_end = over_basename (name);
445 return str_save_n (0, name, cat_end - name);
446 break;
447 }
448
449 case arch_ret_branch:
450 {
451 const t_uchar * branch_end;
452
453 name = over_opt_archive_prefix (name);
454 name = over_basename (name); /* over category */
455 name = over_separator (name);
456 if (!name)
457 return str_save (0, "");
458 branch_end = over_basename (name);
459 if (!branch_end)
460 return str_save (0, "");
461 return str_save_n (0, name, branch_end - name);
462 break;
463 }
464
465 case arch_ret_package:
466 {
467 const t_uchar * branch_end;
468 const t_uchar * t;
469
470 name = over_opt_archive_prefix (name);
471 branch_end = over_basename (name);
472 t = over_separator (branch_end);
473 if (!t)
474 return str_save (0, name); /* only category provided */
475 branch_end = over_basename (t); /* over category */
476 if (!branch_end)
477 return str_save_n (0, name, (t - 2) - name); /* category--version */
478 else
479 return str_save_n (0, name, branch_end - name);
480 break;
481 }
482
483 case arch_ret_version:
484 {
485 const t_uchar * version_start;
486 const t_uchar * version_end;
487 const t_uchar * t;
488
489 name = over_opt_archive_prefix (name);
490 version_end = over_basename (name); /* over category */
491 version_end = over_separator (version_end);
492 invariant (!!version_end);
493 version_start = version_end;
494 t = over_basename (version_start); /* maybe over explicit branch */
495 if (t)
496 {
497 version_end = over_separator (t);
498 invariant (!!version_end);
499 version_start = version_end;
500 }
501 version_end = over_version (version_end);
502 invariant (!!version_end);
503 return str_save_n (0, version_start, version_end - version_start);
504 break;
505 }
506
507 case arch_ret_patch_level:
508 {
509 const t_uchar * t;
510
511 name = over_opt_archive_prefix (name);
512 invariant (!!name);
513 name = over_basename (name);
514 invariant (!!name);
515 name = over_separator (name);
516 invariant (!!name);
517 t = over_basename (name); /* maybe over explicit branch */
518 if (t)
519 {
520 name = over_separator (t);
521 invariant (!!name);
522 }
523 name = over_version (name);
524 invariant (!!name);
525 invariant (name[0]);
526 name = over_separator (name);
527 invariant (!!name);
528 invariant (name[0]);
529 return str_save (0, name);
530 break;
531 }
532
533 case arch_ret_package_version:
534 {
535 const t_uchar * version_start;
536 const t_uchar * version_end;
537 const t_uchar * t;
538
539 name = over_opt_archive_prefix (name);
540 version_end = over_basename (name); /* over category */
541 version_end = over_separator (version_end);
542 invariant (!!version_end);
543 version_start = version_end;
544 t = over_basename (version_start); /* maybe over explicit branch */
545 if (t)
546 {
547 version_end = over_separator (t);
548 invariant (!!version_end);
549 version_start = version_end;
550 }
551 version_end = over_version (version_end);
552 invariant (!!version_end);
553 return str_save_n (0, name, version_end - name);
554 break;
555 }
556 }
557 }
558
559 t_uchar *
arch_fully_qualify(const t_uchar * default_archive,const t_uchar * name)560 arch_fully_qualify (const t_uchar * default_archive,
561 const t_uchar * name)
562 {
563 invariant (arch_valid_package_name (name, arch_maybe_archive, arch_req_package, 1));
564 if (default_archive)
565 invariant (arch_valid_archive_name (default_archive));
566
567 if (str_chr_index (name, '/'))
568 return str_save (0, name);
569 else
570 {
571 if (!default_archive)
572 default_archive = arch_my_default_archive (0);
573
574 if (!default_archive)
575 panic ("arch: no default archive set");
576
577 return str_alloc_cat_many (0, default_archive, "/", name, str_end);
578 }
579 }
580
581 int
arch_names_cmp(const t_uchar * a,const t_uchar * b)582 arch_names_cmp (const t_uchar * a,
583 const t_uchar * b)
584 {
585 const t_uchar * a_nxt;
586 const t_uchar * b_nxt;
587 int res;
588
589 /* compare archive name
590 */
591 a_nxt = over_opt_archive_prefix (a);
592 b_nxt = over_opt_archive_prefix (b);
593
594 res = str_cmp_n (a, a_nxt - a, b, b_nxt - b);
595
596 if (res)
597 return res;
598
599 a = a_nxt;
600 b = b_nxt;
601
602 /* compare category name
603 */
604
605 a_nxt = over_basename (a);
606 b_nxt = over_basename (b);
607
608 res = str_cmp_n (a, a_nxt - a, b, b_nxt - b);
609
610 if (res)
611 return res;
612
613 if (!*a_nxt && !*b_nxt)
614 return 0;
615
616 if (!*a_nxt)
617 return -1;
618
619 if (!*b_nxt)
620 return 1;
621
622 a = over_separator (a_nxt);
623 b = over_separator (b_nxt);
624
625
626 /* compare branch names
627 */
628
629 a_nxt = over_basename (a);
630 b_nxt = over_basename (b);
631
632 if (a_nxt && !b_nxt)
633 {
634 /* a has a branch, b does not */
635 return 1;
636 }
637 else if (!a_nxt && b_nxt)
638 {
639 /* b has a branch, a does not */
640 return -1;
641 }
642 else if (a_nxt && b_nxt)
643 {
644 /* both have branch names */
645
646 res = str_cmp_n (a, a_nxt - a, b, b_nxt - b);
647
648 if (res)
649 return res;
650
651 if (!*a_nxt && !*b_nxt)
652 return 0;
653
654 if (!*a_nxt)
655 return -1;
656
657 if (!*b_nxt)
658 return 1;
659
660 a = over_separator (a_nxt);
661 b = over_separator (b_nxt);
662 }
663
664 /* compare version names
665 */
666
667 a_nxt = over_version (a);
668 b_nxt = over_version (b);
669
670 {
671 int a_vsn_len;
672 int b_vsn_len;
673
674 a_vsn_len = a_nxt - a;
675 b_vsn_len = b_nxt - b;
676
677 /* precondition:
678 * a and b point to a version number component
679 * a_vsn_len and b_vsn_len tell how many chars remain in the version id
680 *
681 * postcondition:
682 * RETURNS if version ids differ
683 * a and b point past version id otherwise
684 *
685 * goal:
686 * compare dot-separated components numerically
687 * noting that a and b may have different numbers of components
688 */
689 while (1)
690 {
691 int errn;
692 const t_uchar * a_comp_end;
693 const t_uchar * b_comp_end;
694 t_ulong a_comp;
695 t_ulong b_comp;
696
697 a_comp_end = str_chr_index_n (a, a_vsn_len, '.');
698 if (!a_comp_end)
699 a_comp_end = a + a_vsn_len;
700
701 b_comp_end = str_chr_index_n (b, b_vsn_len, '.');
702 if (!b_comp_end)
703 b_comp_end = b + b_vsn_len;
704
705 invariant (!cvt_decimal_to_ulong (&errn, &a_comp, a, a_comp_end - a));
706 invariant (!cvt_decimal_to_ulong (&errn, &b_comp, b, b_comp_end - b));
707
708 if (a_comp < b_comp)
709 return -1;
710 else if (a_comp > b_comp)
711 return 1;
712 else
713 {
714 a_vsn_len -= (a_comp_end - a);
715 b_vsn_len -= (b_comp_end - b);
716
717 if (a_vsn_len && b_vsn_len)
718 {
719 /* both have additional components
720 */
721 a = a_comp_end + 1;
722 b = b_comp_end + 1;
723 --a_vsn_len;
724 --b_vsn_len;
725 }
726 else if (!a_vsn_len && b_vsn_len)
727 {
728 /* b has more components, a doesn't.
729 */
730 return -1;
731 }
732 else if (a_vsn_len && !b_vsn_len)
733 {
734 /* a has more components, b doesn't.
735 */
736 return 1;
737 }
738 else
739 {
740 /* neither has more components
741 */
742 a = a_comp_end;
743 b = b_comp_end;
744 break;
745 }
746 }
747 }
748
749 a_nxt = over_separator (a);
750 b_nxt = over_separator (b);
751
752 if (!a_nxt && !b_nxt)
753 return 0;
754 else if (a_nxt && !b_nxt)
755 return 1;
756 else if (!a_nxt && b_nxt)
757 return -1;
758 else
759 {
760 a = a_nxt;
761 b = b_nxt;
762 }
763 }
764
765
766
767 /* compare patch level phase
768 */
769 {
770 t_uchar * a_dash;
771 t_uchar * b_dash;
772
773 a_dash = str_chr_index (a, '-');
774 b_dash = str_chr_index (b, '-');
775
776 invariant (a && b);
777
778 res = str_cmp_n (a, a_dash - a, b, b_dash - b);
779 if (res)
780 return res;
781
782 a = a_dash + 1;
783 b = b_dash + 1;
784 }
785
786 /* compare patch level numbers
787 */
788 {
789 int errn;
790 t_ulong a_lvl;
791 t_ulong b_lvl;
792
793 invariant (!cvt_decimal_to_ulong (&errn, &a_lvl, a, str_length (a)));
794 invariant (!cvt_decimal_to_ulong (&errn, &b_lvl, b, str_length (b)));
795
796 if (a_lvl < b_lvl)
797 return -1;
798 else if (a_lvl > b_lvl)
799 return 1;
800 else
801 return 0;
802 }
803 }
804
805 void
arch_sort_table_by_name_field(int reverse_p,rel_table table,int field)806 arch_sort_table_by_name_field (int reverse_p, rel_table table, int field)
807 {
808 rel_sort_table_by_field_fn (reverse_p, table, field, arch_names_cmp);
809 }
810
811 void
arch_sort_table_by_patch_level_field(int reverse_p,rel_table table,int field)812 arch_sort_table_by_patch_level_field (int reverse_p, rel_table table, int field)
813 {
814 rel_sort_table_by_field_fn (reverse_p, table, field, arch_patch_lvl_cmp);
815 }
816
817 int
arch_patch_lvl_cmp(const t_uchar * a,const t_uchar * b)818 arch_patch_lvl_cmp (const t_uchar * a,
819 const t_uchar * b)
820 {
821 t_uchar * a_dash;
822 t_uchar * b_dash;
823 int res;
824 t_ulong a_lvl;
825 t_ulong b_lvl;
826 int errn;
827
828 a_dash = str_chr_index (a, '-');
829 b_dash = str_chr_index (b, '-');
830 invariant (a_dash && b_dash);
831
832 res = str_cmp_n (a, a_dash - a, b, b_dash - b);
833 if (res)
834 return res;
835
836 invariant (!cvt_decimal_to_ulong (&errn, &a_lvl, a_dash + 1, str_length (a_dash + 1)));
837 invariant (!cvt_decimal_to_ulong (&errn, &b_lvl, b_dash + 1, str_length (b_dash + 1)));
838
839 if (a_lvl < b_lvl)
840 return -1;
841 else if (a_lvl > b_lvl)
842 return 1;
843 else
844 return 0;
845 }
846
847
848 rel_table
arch_pick_archives_by_field(rel_table in,int field)849 arch_pick_archives_by_field (rel_table in, int field)
850 {
851 rel_table answer = rel_table_nil;
852 int x;
853
854 for (x = 0; x < rel_n_records (in); ++x)
855 {
856 if (arch_valid_archive_name (rel_peek_str (in, x, field)))
857 rel_add_records (&answer, rel_copy_record (rel_peek_record (in, x)), rel_record_null);
858 }
859
860 return answer;
861 }
862
863
864 rel_table
arch_pick_categories_by_field(rel_table in,int field)865 arch_pick_categories_by_field (rel_table in, int field)
866 {
867 rel_table answer = rel_table_nil;
868 int x;
869
870 for (x = 0; x < rel_n_records (in); ++x)
871 {
872 if (arch_valid_package_name (rel_peek_str (in, x, field), arch_no_archive, arch_req_category, 0))
873 rel_add_records (&answer, rel_copy_record (rel_peek_record (in, x)), rel_record_null);
874 }
875
876 return answer;
877 }
878
879 rel_table
arch_pick_branches_by_field(rel_table in,int field)880 arch_pick_branches_by_field (rel_table in, int field)
881 {
882 rel_table answer = rel_table_nil;
883 int x;
884
885 for (x = 0; x < rel_n_records (in); ++x)
886 {
887 if (arch_valid_package_name (rel_peek_str (in, x, field), arch_no_archive, arch_req_package, 0))
888 rel_add_records (&answer, rel_copy_record (rel_peek_record (in, x)), rel_record_null);
889 }
890
891 return answer;
892 }
893
894 rel_table
arch_pick_versions_by_field(rel_table in,int field)895 arch_pick_versions_by_field (rel_table in, int field)
896 {
897 rel_table answer = rel_table_nil;
898 int x;
899
900 for (x = 0; x < rel_n_records (in); ++x)
901 {
902 if (arch_valid_package_name (rel_peek_str (in, x, field), arch_no_archive, arch_req_version, 0))
903 rel_add_records (&answer, rel_copy_record (rel_peek_record (in, x)), rel_record_null);
904 }
905
906 return answer;
907 }
908
909 rel_table
arch_pick_revisions_by_field(rel_table in,int field)910 arch_pick_revisions_by_field (rel_table in, int field)
911 {
912 rel_table answer = rel_table_nil;
913 int x;
914
915 for (x = 0; x < rel_n_records (in); ++x)
916 {
917 if (arch_valid_package_name (rel_peek_str (in, x, field), arch_no_archive, arch_req_patch_level, 0))
918 rel_add_records (&answer, rel_copy_record (rel_peek_record (in, x)), rel_record_null);
919 }
920
921 return answer;
922 }
923
924 rel_table
arch_pick_patch_levels_by_field(rel_table in,int field)925 arch_pick_patch_levels_by_field (rel_table in, int field)
926 {
927 rel_table answer = rel_table_nil;
928 int x;
929
930 for (x = 0; x < rel_n_records (in); ++x)
931 {
932 if (arch_valid_patch_level_name (rel_peek_str (in, x, field)))
933 rel_add_records (&answer, rel_copy_record (rel_peek_record (in, x)), rel_record_null);
934 }
935
936 return answer;
937 }
938
939
940 enum arch_patch_level_type
arch_analyze_patch_level(t_ulong * n,const t_uchar * patch_level)941 arch_analyze_patch_level (t_ulong * n,
942 const t_uchar * patch_level)
943 {
944 int ign;
945 enum arch_patch_level_type type;
946 const t_uchar * n_str;
947
948 if (!str_cmp ("base-0", patch_level))
949 {
950 *n = 0;
951 return arch_is_base0_level;
952 }
953 else if (!str_cmp_prefix ("patch-", patch_level))
954 {
955 type = arch_is_patch_level;
956 n_str = patch_level + sizeof ("patch-") - 1;
957 }
958 else if (!str_cmp_prefix ("version-", patch_level))
959 {
960 type = arch_is_version_level;
961 n_str = patch_level + sizeof ("version-") - 1;
962 }
963 else if (!str_cmp_prefix ("versionfix-", patch_level))
964 {
965 type = arch_is_versionfix_level;
966 n_str = patch_level + sizeof ("versionfix-") - 1;
967 }
968 else
969 panic ("illegal patch_level in arch_analyze_patch_level");
970
971 if (cvt_decimal_to_ulong (&ign, n, n_str, str_length (n_str)))
972 panic ("illegal patch_level in arch_analyze_patch_level");
973
974 return type;
975 }
976
977
978 t_uchar *
arch_form_patch_level(enum arch_patch_level_type type,t_ulong n)979 arch_form_patch_level (enum arch_patch_level_type type, t_ulong n)
980 {
981 t_uchar n_buf[64];
982
983 cvt_ulong_to_decimal (n_buf, n);
984
985 switch (type)
986 {
987 case arch_is_base0_level:
988 {
989 return str_save (0, "base-0");
990 }
991 case arch_is_patch_level:
992 {
993 return str_alloc_cat (0, "patch-", n_buf);
994 }
995 case arch_is_version_level:
996 {
997 return str_alloc_cat (0, "version-", n_buf);
998 }
999 case arch_is_versionfix_level:
1000 {
1001 return str_alloc_cat (0, "versionfix-", n_buf);
1002 }
1003 default:
1004 {
1005 panic ("not reached in arch_form_patch_level");
1006 return 0;
1007 }
1008 }
1009 }
1010
1011
1012
1013 static const t_uchar *
over_opt_archive_prefix(const t_uchar * name)1014 over_opt_archive_prefix (const t_uchar * name)
1015 {
1016 const t_uchar * slash;
1017 const t_uchar * archive_name_end;
1018
1019 slash = (const t_uchar *)str_chr_index (name, '/');
1020
1021 if (!slash)
1022 return name;
1023
1024 archive_name_end = over_archive_name (name);
1025
1026 if (archive_name_end != slash)
1027 return 0;
1028
1029 return slash + 1;
1030 }
1031
1032
1033 #define char_is_alnum_or_dash(c) (char_is_alnum (c) || (c == '-'))
1034
1035 static const t_uchar *
over_archive_name(const t_uchar * in)1036 over_archive_name (const t_uchar * in)
1037 {
1038 if (!char_is_alnum_or_dash (*in))
1039 return 0;
1040
1041 while (1)
1042 {
1043 while (char_is_alnum_or_dash (*in))
1044 ++in;
1045
1046 if (*in != '.' && *in != '_')
1047 break;
1048
1049 if (!char_is_alnum_or_dash (in[1]))
1050 return 0;
1051
1052 ++in;
1053 }
1054
1055 if (*in != '@')
1056 return 0;
1057
1058 ++in;
1059
1060 while (char_is_alnum_or_dash(*in) || (*in == '.'))
1061 {
1062 if ((*in == '-') && (in[1] == '-'))
1063 break;
1064 ++in;
1065 }
1066
1067 if (!*in || (*in == '/'))
1068 return in;
1069
1070 if ((in[0] != '-') || (in[1] != '-'))
1071 return 0;
1072
1073 in += 2;
1074
1075 while (char_is_alnum_or_dash(*in) || (*in == '.'))
1076 ++in;
1077
1078 if (*in && (*in != '/'))
1079 return 0;
1080
1081 return in;
1082 }
1083
1084
1085 static const t_uchar *
over_basename(const t_uchar * in)1086 over_basename (const t_uchar * in)
1087 {
1088 if (!char_is_alpha (*in))
1089 return 0;
1090 ++in;
1091
1092 while (1)
1093 {
1094 if (!*in)
1095 return in;
1096 else if ((char_is_alnum (*in)) || (*in == '%') || (*in == ','))
1097 ++in;
1098 else if (*in == '-')
1099 {
1100 if (in[1] == '-')
1101 return in;
1102 else
1103 ++in;
1104 }
1105 else
1106 break;
1107 }
1108 return 0;
1109 }
1110
1111 static const t_uchar *
over_separator(const t_uchar * in)1112 over_separator (const t_uchar * in)
1113 {
1114 if ((*in == '-') && (in[1] == '-'))
1115 return in + 2;
1116 else
1117 return 0;
1118 }
1119
1120 static const t_uchar *
over_version(const t_uchar * in)1121 over_version (const t_uchar * in)
1122 {
1123 while (1)
1124 {
1125 if (!*in)
1126 break;
1127 else if (!char_is_digit (*in))
1128 break;
1129 else
1130 {
1131 while (char_is_digit (*in))
1132 ++in;
1133 if (!*in)
1134 return in;
1135 else if (*in == '.')
1136 ++in;
1137 else if ((*in == '-') && (in[1] == '-'))
1138 return in;
1139 else
1140 break;
1141 }
1142 }
1143 return 0;
1144 }
1145
1146 static const t_uchar *
over_patch_level(const t_uchar * in)1147 over_patch_level (const t_uchar * in)
1148 {
1149 if (!str_cmp (in, "base-0"))
1150 return in + sizeof ("base-0") - 1;
1151 else
1152 {
1153 int prefix_len;
1154
1155 if (!str_cmp_prefix ("patch-", in))
1156 prefix_len = sizeof ("patch-") - 1;
1157 else if (!str_cmp_prefix ("version-", in))
1158 prefix_len = sizeof ("version-") - 1;
1159 else if (!str_cmp_prefix ("versionfix-", in))
1160 prefix_len = sizeof ("versionfix-") - 1;
1161 else
1162 return 0;
1163
1164 in += prefix_len;
1165
1166 if (!char_is_digit (*in))
1167 return 0;
1168
1169 while (char_is_digit (*in))
1170 ++in;
1171
1172 if (*in)
1173 return 0;
1174
1175 return in;
1176 }
1177 }
1178
1179
1180
1181
1182 /* tag: Tom Lord Mon May 12 10:17:47 2003 (namespace.c)
1183 */
1184