|
Lines 151-157
typedef struct {
Link Here
|
| 151 |
char *prefix; /* hostname prefix */ |
151 |
char *prefix; /* hostname prefix */ |
| 152 |
unsigned long num; /* numeric suffix */ |
152 |
unsigned long num; /* numeric suffix */ |
| 153 |
|
153 |
|
| 154 |
/* string representation of numeric suffix |
154 |
/* string representation of numeric suffix, and trailing chars |
| 155 |
* points into `hostname' */ |
155 |
* points into `hostname' */ |
| 156 |
char *suffix; |
156 |
char *suffix; |
| 157 |
} hostname_t; |
157 |
} hostname_t; |
|
Lines 159-164
typedef struct {
Link Here
|
| 159 |
/* hostrange type: A single prefix with `hi' and `lo' numeric suffix values */ |
159 |
/* hostrange type: A single prefix with `hi' and `lo' numeric suffix values */ |
| 160 |
typedef struct { |
160 |
typedef struct { |
| 161 |
char *prefix; /* alphanumeric prefix: */ |
161 |
char *prefix; /* alphanumeric prefix: */ |
|
|
162 |
char *suffix; |
| 162 |
|
163 |
|
| 163 |
/* beginning (lo) and end (hi) of suffix range */ |
164 |
/* beginning (lo) and end (hi) of suffix range */ |
| 164 |
unsigned long lo, hi; |
165 |
unsigned long lo, hi; |
|
Lines 283-301
static int _width_equiv(unsigned long, int *, unsigned long, int *);
Link Here
|
| 283 |
|
284 |
|
| 284 |
static int host_prefix_end(const char *, int dims); |
285 |
static int host_prefix_end(const char *, int dims); |
| 285 |
static hostname_t *hostname_create(const char *); |
286 |
static hostname_t *hostname_create(const char *); |
|
|
287 |
static hostname_t *hostname_copy(const hostname_t *); |
| 286 |
static void hostname_destroy(hostname_t *); |
288 |
static void hostname_destroy(hostname_t *); |
| 287 |
static int hostname_suffix_is_valid(hostname_t *); |
289 |
static int hostname_suffix_is_valid(hostname_t *); |
| 288 |
static int hostname_suffix_width(hostname_t *); |
290 |
static int hostname_suffix_width(hostname_t *, int); |
|
|
291 |
static char *hostname_suffix_extra(hostname_t *, int); |
| 289 |
|
292 |
|
| 290 |
static hostrange_t *hostrange_new(void); |
293 |
static hostrange_t *hostrange_new(void); |
| 291 |
static hostrange_t *hostrange_create_single(const char *); |
294 |
static hostrange_t *hostrange_create_single(const char *); |
| 292 |
static hostrange_t *hostrange_create(char *, unsigned long, unsigned long, int); |
295 |
static hostrange_t *hostrange_create(char *, unsigned long, unsigned long, int, char *); |
| 293 |
static unsigned long hostrange_count(hostrange_t *); |
296 |
static unsigned long hostrange_count(hostrange_t *); |
| 294 |
static hostrange_t *hostrange_copy(hostrange_t *); |
297 |
static hostrange_t *hostrange_copy(hostrange_t *); |
| 295 |
static void hostrange_destroy(hostrange_t *); |
298 |
static void hostrange_destroy(hostrange_t *); |
| 296 |
static hostrange_t *hostrange_delete_host(hostrange_t *, unsigned long); |
299 |
static hostrange_t *hostrange_delete_host(hostrange_t *, unsigned long); |
| 297 |
static int hostrange_cmp(hostrange_t *, hostrange_t *); |
300 |
static int hostrange_cmp(hostrange_t *, hostrange_t *); |
| 298 |
static int hostrange_prefix_cmp(hostrange_t *, hostrange_t *); |
301 |
static int hostrange_prefix_cmp(hostrange_t *, hostrange_t *); |
|
|
302 |
static int hostrange_prefix_suffix_cmp(hostrange_t *, hostrange_t *); |
| 299 |
static int hostrange_within_range(hostrange_t *, hostrange_t *); |
303 |
static int hostrange_within_range(hostrange_t *, hostrange_t *); |
| 300 |
static int hostrange_width_combine(hostrange_t *, hostrange_t *); |
304 |
static int hostrange_width_combine(hostrange_t *, hostrange_t *); |
| 301 |
static int hostrange_empty(hostrange_t *); |
305 |
static int hostrange_empty(hostrange_t *); |
|
Lines 314-320
static int hostlist_resize(hostlist_t, size_t);
Link Here
|
| 314 |
static int hostlist_expand(hostlist_t); |
318 |
static int hostlist_expand(hostlist_t); |
| 315 |
static int hostlist_push_range(hostlist_t, hostrange_t *); |
319 |
static int hostlist_push_range(hostlist_t, hostrange_t *); |
| 316 |
static int hostlist_push_hr(hostlist_t, char *, unsigned long, |
320 |
static int hostlist_push_hr(hostlist_t, char *, unsigned long, |
| 317 |
unsigned long, int); |
321 |
unsigned long, int, char *); |
| 318 |
static int hostlist_insert_range(hostlist_t, hostrange_t *, int); |
322 |
static int hostlist_insert_range(hostlist_t, hostrange_t *, int); |
| 319 |
static void hostlist_delete_range(hostlist_t, int n); |
323 |
static void hostlist_delete_range(hostlist_t, int n); |
| 320 |
static void hostlist_coalesce(hostlist_t hl); |
324 |
static void hostlist_coalesce(hostlist_t hl); |
|
Lines 489-494
static hostname_t *hostname_create_dims(const char *hostname, int dims)
Link Here
|
| 489 |
char *p; |
493 |
char *p; |
| 490 |
int idx = 0; |
494 |
int idx = 0; |
| 491 |
int hostlist_base; |
495 |
int hostlist_base; |
|
|
496 |
int suffix_len; |
| 492 |
|
497 |
|
| 493 |
xassert(hostname); |
498 |
xassert(hostname); |
| 494 |
|
499 |
|
|
Lines 518-530
static hostname_t *hostname_create_dims(const char *hostname, int dims)
Link Here
|
| 518 |
} |
523 |
} |
| 519 |
|
524 |
|
| 520 |
hn->suffix = hn->hostname + idx + 1; |
525 |
hn->suffix = hn->hostname + idx + 1; |
|
|
526 |
suffix_len = hostname_suffix_width(hn, dims); |
| 521 |
|
527 |
|
| 522 |
if ((dims > 1) && (strlen(hn->suffix) != dims)) |
528 |
if ((dims > 1) && (suffix_len != dims)) |
| 523 |
hostlist_base = 10; |
529 |
hostlist_base = 10; |
| 524 |
|
530 |
|
| 525 |
hn->num = strtoul(hn->suffix, &p, hostlist_base); |
531 |
hn->num = strtoul(hn->suffix, &p, hostlist_base); |
| 526 |
|
532 |
|
| 527 |
if (*p == '\0') { |
533 |
if (p - hn->suffix == suffix_len) { |
| 528 |
if (!(hn->prefix = malloc((idx + 2)))) { |
534 |
if (!(hn->prefix = malloc((idx + 2)))) { |
| 529 |
hostname_destroy(hn); |
535 |
hostname_destroy(hn); |
| 530 |
out_of_memory("hostname prefix create"); |
536 |
out_of_memory("hostname prefix create"); |
|
Lines 551-556
static hostname_t *hostname_create(const char *hostname)
Link Here
|
| 551 |
return hostname_create_dims(hostname, dims); |
557 |
return hostname_create_dims(hostname, dims); |
| 552 |
} |
558 |
} |
| 553 |
|
559 |
|
|
|
560 |
/* |
| 561 |
* make a copy of a hostname object |
| 562 |
*/ |
| 563 |
static hostname_t *hostname_copy(const hostname_t *hn) |
| 564 |
{ |
| 565 |
hostname_t *ret; |
| 566 |
|
| 567 |
if (hn == NULL) |
| 568 |
return NULL; |
| 569 |
|
| 570 |
if ((ret = malloc(sizeof(*ret))) == NULL) |
| 571 |
out_of_memory("hostname copy"); |
| 572 |
|
| 573 |
ret->hostname = strdup(hn->hostname); |
| 574 |
ret->prefix = strdup(hn->prefix); |
| 575 |
ret->suffix = hn->suffix ? ret->hostname + (hn->suffix - hn->hostname) : NULL; |
| 576 |
ret->num = hn->num; |
| 577 |
|
| 578 |
if (!ret->hostname || !ret->prefix) { |
| 579 |
hostname_destroy(ret); |
| 580 |
ret = NULL; |
| 581 |
out_of_memory("hostname copy"); |
| 582 |
} |
| 583 |
|
| 584 |
return ret; |
| 585 |
} |
| 586 |
|
| 554 |
/* free a hostname object |
587 |
/* free a hostname object |
| 555 |
*/ |
588 |
*/ |
| 556 |
static void hostname_destroy(hostname_t *hn) |
589 |
static void hostname_destroy(hostname_t *hn) |
|
Lines 576-594
static int hostname_suffix_is_valid(hostname_t *hn)
Link Here
|
| 576 |
|
609 |
|
| 577 |
/* return the width (in characters) of the numeric part of the hostname |
610 |
/* return the width (in characters) of the numeric part of the hostname |
| 578 |
*/ |
611 |
*/ |
| 579 |
static int hostname_suffix_width(hostname_t *hn) |
612 |
static int hostname_suffix_width(hostname_t *hn, int dims) |
| 580 |
{ |
613 |
{ |
|
|
614 |
int idx = 0; |
| 581 |
if (!hn) |
615 |
if (!hn) |
| 582 |
return -1; |
616 |
return -1; |
| 583 |
xassert(hn->suffix); |
617 |
xassert(hn->suffix); |
| 584 |
return (int) strlen(hn->suffix); |
618 |
|
|
|
619 |
if (dims > 1) |
| 620 |
return (int) strlen(hn->suffix); |
| 621 |
while (hn->suffix[idx] != '\0' && isdigit(hn->suffix[idx])) |
| 622 |
idx++; |
| 623 |
return idx; |
| 585 |
} |
624 |
} |
| 586 |
|
625 |
|
|
|
626 |
/* return a pointer to extra data after the numeric suffix, or NULL if none |
| 627 |
*/ |
| 628 |
static char *hostname_suffix_extra(hostname_t *hn, int dims) |
| 629 |
{ |
| 630 |
int width = hostname_suffix_width(hn, dims); |
| 631 |
if (width > 0 && strlen(hn->suffix) > width) |
| 632 |
return hn->suffix + width; |
| 633 |
return NULL; |
| 634 |
} |
| 587 |
|
635 |
|
| 588 |
/* ----[ hostrange_t functions ]---- */ |
636 |
/* ----[ hostrange_t functions ]---- */ |
| 589 |
|
637 |
|
| 590 |
/* allocate a new hostrange object |
638 |
/* allocate a new hostrange object |
| 591 |
*/ |
639 |
*/ |
| 592 |
static hostrange_t *hostrange_new(void) |
640 |
static hostrange_t *hostrange_new(void) |
| 593 |
{ |
641 |
{ |
| 594 |
hostrange_t *new = malloc(sizeof(*new)); |
642 |
hostrange_t *new = malloc(sizeof(*new)); |
|
Lines 616-621
static hostrange_t *hostrange_create_single(const char *prefix)
Link Here
|
| 616 |
new->lo = 0L; |
664 |
new->lo = 0L; |
| 617 |
new->hi = 0L; |
665 |
new->hi = 0L; |
| 618 |
new->width = 0; |
666 |
new->width = 0; |
|
|
667 |
new->suffix = NULL; |
| 619 |
|
668 |
|
| 620 |
return new; |
669 |
return new; |
| 621 |
|
670 |
|
|
Lines 629-635
error1:
Link Here
|
| 629 |
/* Create a hostrange object with a prefix, hi, lo, and format width |
678 |
/* Create a hostrange object with a prefix, hi, lo, and format width |
| 630 |
*/ |
679 |
*/ |
| 631 |
static hostrange_t *hostrange_create(char *prefix, unsigned long lo, |
680 |
static hostrange_t *hostrange_create(char *prefix, unsigned long lo, |
| 632 |
unsigned long hi, int width) |
681 |
unsigned long hi, int width, char *suffix) |
| 633 |
{ |
682 |
{ |
| 634 |
hostrange_t *new; |
683 |
hostrange_t *new; |
| 635 |
|
684 |
|
|
Lines 641-646
static hostrange_t *hostrange_create(char *prefix, unsigned long lo,
Link Here
|
| 641 |
if ((new->prefix = strdup(prefix)) == NULL) |
690 |
if ((new->prefix = strdup(prefix)) == NULL) |
| 642 |
goto error2; |
691 |
goto error2; |
| 643 |
|
692 |
|
|
|
693 |
new->suffix = NULL; |
| 694 |
if (suffix && ((new->suffix = strdup(suffix)) == NULL)) |
| 695 |
goto error3; |
| 696 |
|
| 644 |
new->lo = lo; |
697 |
new->lo = lo; |
| 645 |
new->hi = hi; |
698 |
new->hi = hi; |
| 646 |
new->width = width; |
699 |
new->width = width; |
|
Lines 649-654
static hostrange_t *hostrange_create(char *prefix, unsigned long lo,
Link Here
|
| 649 |
|
702 |
|
| 650 |
return new; |
703 |
return new; |
| 651 |
|
704 |
|
|
|
705 |
error3: |
| 706 |
free(new->prefix); |
| 652 |
error2: |
707 |
error2: |
| 653 |
free(new); |
708 |
free(new); |
| 654 |
error1: |
709 |
error1: |
|
Lines 675-683
static hostrange_t *hostrange_copy(hostrange_t *hr)
Link Here
|
| 675 |
|
730 |
|
| 676 |
if (hr->singlehost) |
731 |
if (hr->singlehost) |
| 677 |
return hostrange_create_single(hr->prefix); |
732 |
return hostrange_create_single(hr->prefix); |
| 678 |
else |
733 |
return hostrange_create(hr->prefix, hr->lo, hr->hi, hr->width, hr->suffix); |
| 679 |
return hostrange_create(hr->prefix, hr->lo, hr->hi, |
|
|
| 680 |
hr->width); |
| 681 |
} |
734 |
} |
| 682 |
|
735 |
|
| 683 |
|
736 |
|
|
Lines 689-694
static void hostrange_destroy(hostrange_t *hr)
Link Here
|
| 689 |
return; |
742 |
return; |
| 690 |
if (hr->prefix) |
743 |
if (hr->prefix) |
| 691 |
free(hr->prefix); |
744 |
free(hr->prefix); |
|
|
745 |
if (hr->suffix) |
| 746 |
free(hr->suffix); |
| 692 |
free(hr); |
747 |
free(hr); |
| 693 |
} |
748 |
} |
| 694 |
|
749 |
|
|
Lines 727-734
extern int hostlist_cmp_first(hostlist_t hl1, hostlist_t hl2)
Link Here
|
| 727 |
/* hostrange_cmp() is used to sort hostrange objects. It will |
782 |
/* hostrange_cmp() is used to sort hostrange objects. It will |
| 728 |
* sort based on the following (in order): |
783 |
* sort based on the following (in order): |
| 729 |
* o result of xstrcmp on prefixes |
784 |
* o result of xstrcmp on prefixes |
|
|
785 |
* o result of xstrcmp on suffixes |
| 730 |
* o if widths are compatible, then: |
786 |
* o if widths are compatible, then: |
| 731 |
* sort based on lowest suffix in range |
787 |
* sort based on lowest number in range |
| 732 |
* else |
788 |
* else |
| 733 |
* sort based on width */ |
789 |
* sort based on width */ |
| 734 |
static int hostrange_cmp(hostrange_t *h1, hostrange_t *h2) |
790 |
static int hostrange_cmp(hostrange_t *h1, hostrange_t *h2) |
|
Lines 737-745
static int hostrange_cmp(hostrange_t *h1, hostrange_t *h2)
Link Here
|
| 737 |
|
793 |
|
| 738 |
xassert(h1 && h2); |
794 |
xassert(h1 && h2); |
| 739 |
|
795 |
|
| 740 |
if ((retval = hostrange_prefix_cmp(h1, h2)) == 0) |
796 |
if ((retval = hostrange_prefix_cmp(h1, h2)) == 0) { |
| 741 |
retval = hostrange_width_combine(h1, h2) ? |
797 |
if (retval == 0) { |
| 742 |
h1->lo - h2->lo : h1->width - h2->width; |
798 |
if (h1->suffix && !h2->suffix) |
|
|
799 |
retval = 1; |
| 800 |
else if (!h1->suffix && h2->suffix) |
| 801 |
retval = -1; |
| 802 |
else if (h1->suffix && h2->suffix) |
| 803 |
retval = strnatcmp(h1->suffix, h2->suffix); |
| 804 |
} |
| 805 |
if (retval == 0) |
| 806 |
retval = hostrange_width_combine(h1, h2) ? |
| 807 |
h1->lo - h2->lo : h1->width - h2->width; |
| 808 |
} |
| 743 |
|
809 |
|
| 744 |
return retval; |
810 |
return retval; |
| 745 |
} |
811 |
} |
|
Lines 764-769
static int hostrange_prefix_cmp(hostrange_t *h1, hostrange_t *h2)
Link Here
|
| 764 |
return retval == 0 ? h2->singlehost - h1->singlehost : retval; |
830 |
return retval == 0 ? h2->singlehost - h1->singlehost : retval; |
| 765 |
} |
831 |
} |
| 766 |
|
832 |
|
|
|
833 |
/* compare the prefixes and suffixes of two hostrange objects |
| 834 |
* returns: |
| 835 |
* 0 if both are the same |
| 836 |
* non-0 if different |
| 837 |
* |
| 838 |
* (not lexicographic, do not use in sorting) */ |
| 839 |
static int hostrange_prefix_suffix_cmp(hostrange_t *h1, hostrange_t *h2) |
| 840 |
{ |
| 841 |
if (hostrange_prefix_cmp(h1, h2)) |
| 842 |
return 1; |
| 843 |
if (h1->suffix == NULL && h2->suffix == NULL) |
| 844 |
return 0; |
| 845 |
if (h1->suffix != NULL && h2->suffix != NULL) |
| 846 |
return strnatcmp(h1->suffix, h2->suffix); |
| 847 |
return 1; |
| 848 |
} |
| 849 |
|
| 767 |
/* returns true if h1 and h2 would be included in the same bracketed hostlist. |
850 |
/* returns true if h1 and h2 would be included in the same bracketed hostlist. |
| 768 |
* h1 and h2 will be in the same bracketed list iff: |
851 |
* h1 and h2 will be in the same bracketed list iff: |
| 769 |
* |
852 |
* |
|
Lines 775-781
static int hostrange_prefix_cmp(hostrange_t *h1, hostrange_t *h2)
Link Here
|
| 775 |
*/ |
858 |
*/ |
| 776 |
static int hostrange_within_range(hostrange_t *h1, hostrange_t *h2) |
859 |
static int hostrange_within_range(hostrange_t *h1, hostrange_t *h2) |
| 777 |
{ |
860 |
{ |
| 778 |
if (hostrange_prefix_cmp(h1, h2) == 0) |
861 |
if (hostrange_prefix_suffix_cmp(h1, h2) == 0) |
| 779 |
return h1->singlehost || h2->singlehost ? 0 : 1; |
862 |
return h1->singlehost || h2->singlehost ? 0 : 1; |
| 780 |
else |
863 |
else |
| 781 |
return 0; |
864 |
return 0; |
|
Lines 803-808
static int hostrange_empty(hostrange_t *hr)
Link Here
|
| 803 |
return ((hr->hi < hr->lo) || (hr->hi == (unsigned long) -1)); |
886 |
return ((hr->hi < hr->lo) || (hr->hi == (unsigned long) -1)); |
| 804 |
} |
887 |
} |
| 805 |
|
888 |
|
|
|
889 |
/* Convert existing single hostrange with no suffix into numeric range with a suffix |
| 890 |
*/ |
| 891 |
static int hostrange_convert_suffix(hostrange_t *hr, unsigned long n, unsigned long width, unsigned long suffix_idx) |
| 892 |
{ |
| 893 |
size_t prefix_len; |
| 894 |
xassert(hr && hr->prefix); |
| 895 |
|
| 896 |
prefix_len = strlen(hr->prefix); |
| 897 |
|
| 898 |
if (hostrange_count(hr) != 1 || hr->suffix || suffix_idx >= prefix_len || width == 0) |
| 899 |
return 0; |
| 900 |
|
| 901 |
if (!(hr->suffix = malloc(strlen(hr->prefix) - suffix_idx + hr->width + 1))) |
| 902 |
return 0; |
| 903 |
|
| 904 |
/* copy previous numeric suffix in (if any) */ |
| 905 |
if (hr->width) |
| 906 |
sprintf(hr->suffix, "%s%0*lu", hr->prefix + suffix_idx, hr->width, hr->lo); |
| 907 |
else |
| 908 |
strcpy(hr->suffix, hr->prefix + suffix_idx); |
| 909 |
|
| 910 |
/* truncate the prefix */ |
| 911 |
hr->prefix[suffix_idx - width] = 0; |
| 912 |
/* reset numeric settings */ |
| 913 |
hr->width = width; |
| 914 |
hr->lo = n; |
| 915 |
hr->hi = n; |
| 916 |
hr->singlehost = 0; |
| 917 |
return 1; |
| 918 |
} |
| 919 |
|
| 920 |
|
| 921 |
/* Attempt to extract a number of the given width from a string, |
| 922 |
* return 0 on success, and set *res to extracted number, |
| 923 |
* 1 on failure |
| 924 |
*/ |
| 925 |
static int |
| 926 |
_extract_num_width(char *buf, size_t width, unsigned long *res) |
| 927 |
{ |
| 928 |
char *endptr; |
| 929 |
unsigned long x = strtoul(buf, &endptr, 10); |
| 930 |
if (x == ULONG_MAX || endptr - buf != width) |
| 931 |
return 1; |
| 932 |
*res = x; |
| 933 |
return 0; |
| 934 |
} |
| 935 |
|
| 936 |
/* Compare left suffix == right suffix + number |
| 937 |
* 0 on success, 1 on failure, like strcmp */ |
| 938 |
static int |
| 939 |
_compare_str_num(char *left, char *right, unsigned long idx, unsigned long width) |
| 940 |
{ |
| 941 |
if (strncmp(left, right, strlen(right))) |
| 942 |
return 1; |
| 943 |
if (width) { |
| 944 |
unsigned long num; |
| 945 |
if (_extract_num_width(left+ strlen(right), width, &num) || |
| 946 |
num != idx) |
| 947 |
return 1; |
| 948 |
} |
| 949 |
return 0; |
| 950 |
} |
| 951 |
|
| 952 |
/* Compare two hostranges to see if they have a numeric part in the middle |
| 953 |
* of the prefix and can be combined into one range. |
| 954 |
* If they can, return hr1 if they can be combined into it, otherwise |
| 955 |
* try to fix up both to have a common suffix and return NULL |
| 956 |
*/ |
| 957 |
static hostrange_t * |
| 958 |
hostrange_combine_suffix(hostrange_t *hr1, hostrange_t *hr2) |
| 959 |
{ |
| 960 |
int i; |
| 961 |
|
| 962 |
xassert(hr1 && hr2); |
| 963 |
/* First test, to see if we can combine two single host ranges into a range |
| 964 |
* with a numerical part in the middle. |
| 965 |
* Can only combine if the current numeric suffix is the same, and the |
| 966 |
* length of the prefixes is the same, and we don't have a prefix/suffix split already, |
| 967 |
* and any numeric suffix is the same */ |
| 968 |
if ((hr1->singlehost != hr2->singlehost) || |
| 969 |
(strlen(hr1->prefix) != strlen(hr2->prefix)) || |
| 970 |
hr1->suffix || hr2->suffix || |
| 971 |
hr1->lo != hr2->lo || |
| 972 |
hr1->hi != hr2->hi || |
| 973 |
hostrange_count(hr1) != 1 || |
| 974 |
hr1->width != hr2->width) { |
| 975 |
/* Another possibility - if this is adding a single host to an existing range, |
| 976 |
* and the numeric suffix of hr2 would match the string suffix of hr1 */ |
| 977 |
if (!hr1->singlehost && hr1->suffix && |
| 978 |
hostrange_count(hr2) == 1 && hr2->suffix == NULL) { |
| 979 |
size_t hr1_prefix_len = strlen(hr1->prefix); |
| 980 |
size_t hr2_prefix_len = strlen(hr2->prefix); |
| 981 |
unsigned long hr2_idx; |
| 982 |
/* Total length should match */ |
| 983 |
if (hr1_prefix_len + hr1->width + strlen(hr1->suffix) != |
| 984 |
hr2_prefix_len + hr2->width) |
| 985 |
return NULL; |
| 986 |
/* We now may have two ranges of the form: |
| 987 |
* |
| 988 |
* /-- hr1 prefix |
| 989 |
* | /-- hr1 lo |
| 990 |
* | | /--- hr1 suffix |
| 991 |
* foo-1234-111 |
| 992 |
* foo-1235-111 |
| 993 |
* | ^ hr2 lo |
| 994 |
* \-- hr2 prefix |
| 995 |
* |
| 996 |
* Walk along hr2 and compare to hr1 |
| 997 |
*/ |
| 998 |
/* Compare prefix */ |
| 999 |
if (strncmp(hr1->prefix, hr2->prefix, hr1_prefix_len)) |
| 1000 |
return NULL; |
| 1001 |
/* Extract numeric portion */ |
| 1002 |
if (_extract_num_width(hr2->prefix + hr1_prefix_len, hr1->width, &hr2_idx)) |
| 1003 |
return NULL; |
| 1004 |
/* compare the suffix */ |
| 1005 |
if (hr1_prefix_len + hr1->width >= hr2_prefix_len || |
| 1006 |
_compare_str_num(hr1->suffix, hr2->prefix + hr1_prefix_len + hr1->width, hr2->lo, hr2->width)) |
| 1007 |
return NULL; |
| 1008 |
/* If the numbers are not consecutive, we still want to convert the second entry to |
| 1009 |
* prefix/suffix form so that printouts can combine them */ |
| 1010 |
if (hr2_idx != hr1->hi + 1) { |
| 1011 |
hostrange_convert_suffix(hr2, hr2_idx, hr1->width, hr1_prefix_len + hr1->width); |
| 1012 |
return NULL; |
| 1013 |
} |
| 1014 |
/* At this point everything matches, expand the range of hr1 */ |
| 1015 |
hr1->hi++; |
| 1016 |
return hr1; |
| 1017 |
} |
| 1018 |
return NULL; |
| 1019 |
} |
| 1020 |
|
| 1021 |
/* Here we have two single host ranges with a numeric suffix, attempt to find |
| 1022 |
* a common ascending range of numbers between the two */ |
| 1023 |
for (i = 0; i < strlen(hr1->prefix); i++) { |
| 1024 |
if (isdigit(hr1->prefix[i])) { |
| 1025 |
unsigned long p1, p2; |
| 1026 |
char *endp1, *endp2; |
| 1027 |
p1 = strtoul(hr1->prefix + i, &endp1, 10); |
| 1028 |
p2 = strtoul(hr2->prefix + i, &endp2, 10); |
| 1029 |
/* widths of numeric field should match, but |
| 1030 |
* the numbers themselves should be consecutive */ |
| 1031 |
if ((endp1 - hr1->prefix) == (endp2 - hr2->prefix) && (p1 != p2)) { |
| 1032 |
int prefix_len = i; |
| 1033 |
|
| 1034 |
/* the rest of the prefix should match as well */ |
| 1035 |
i = endp1 - hr1->prefix; |
| 1036 |
if (strcmp(hr1->prefix + i, hr2->prefix + i) != 0) { |
| 1037 |
return NULL; |
| 1038 |
} |
| 1039 |
/* Ok, we have a match, convert them to the correct suffix |
| 1040 |
* so that they can be coalesced above */ |
| 1041 |
hostrange_convert_suffix(hr1, p1, i - prefix_len, i); |
| 1042 |
/* if they are consecutive, extend the first range, |
| 1043 |
* otherwise leave them distinct so they can be grouped in printout */ |
| 1044 |
if (p2 - p1 == 1) { |
| 1045 |
hr1->hi = p2; |
| 1046 |
return hr1; |
| 1047 |
} |
| 1048 |
hostrange_convert_suffix(hr2, p2, i - prefix_len, i); |
| 1049 |
return NULL; |
| 1050 |
} |
| 1051 |
} |
| 1052 |
} |
| 1053 |
return NULL; |
| 1054 |
} |
| 1055 |
|
| 1056 |
|
| 806 |
/* return the string representation of the last host in hostrange hr |
1057 |
/* return the string representation of the last host in hostrange hr |
| 807 |
* and remove that host from the range (i.e. decrement hi if possible) |
1058 |
* and remove that host from the range (i.e. decrement hi if possible) |
| 808 |
* |
1059 |
* |
|
Lines 823-828
static char *hostrange_pop(hostrange_t *hr)
Link Here
|
| 823 |
out_of_memory("hostrange pop"); |
1074 |
out_of_memory("hostrange pop"); |
| 824 |
} else if (hostrange_count(hr) > 0) { |
1075 |
} else if (hostrange_count(hr) > 0) { |
| 825 |
size = strlen(hr->prefix) + hr->width + 16; |
1076 |
size = strlen(hr->prefix) + hr->width + 16; |
|
|
1077 |
if (hr->suffix) size += strlen(hr->suffix); |
| 826 |
if (!(host = malloc(size))) |
1078 |
if (!(host = malloc(size))) |
| 827 |
out_of_memory("hostrange pop"); |
1079 |
out_of_memory("hostrange pop"); |
| 828 |
if ((dims > 1) && (hr->width == dims)) { |
1080 |
if ((dims > 1) && (hr->width == dims)) { |
|
Lines 832-837
static char *hostrange_pop(hostrange_t *hr)
Link Here
|
| 832 |
|
1084 |
|
| 833 |
hostlist_parse_int_to_array(hr->hi, coord, dims, 0); |
1085 |
hostlist_parse_int_to_array(hr->hi, coord, dims, 0); |
| 834 |
|
1086 |
|
|
|
1087 |
xassert(!hr->suffix); |
| 835 |
len = snprintf(host, size, "%s", hr->prefix); |
1088 |
len = snprintf(host, size, "%s", hr->prefix); |
| 836 |
if (len >= 0 && len + dims < size) { |
1089 |
if (len >= 0 && len + dims < size) { |
| 837 |
while (i2 < dims) |
1090 |
while (i2 < dims) |
|
Lines 840-847
static char *hostrange_pop(hostrange_t *hr)
Link Here
|
| 840 |
} |
1093 |
} |
| 841 |
hr->hi--; |
1094 |
hr->hi--; |
| 842 |
} else { |
1095 |
} else { |
| 843 |
snprintf(host, size, "%s%0*lu", hr->prefix, |
1096 |
snprintf(host, size, "%s%0*lu%s", hr->prefix, |
| 844 |
hr->width, hr->hi--); |
1097 |
hr->width, hr->hi--, hr->suffix ? hr->suffix : ""); |
| 845 |
} |
1098 |
} |
| 846 |
} |
1099 |
} |
| 847 |
|
1100 |
|
|
Lines 865-870
static char *hostrange_shift(hostrange_t *hr, int dims)
Link Here
|
| 865 |
out_of_memory("hostrange shift"); |
1118 |
out_of_memory("hostrange shift"); |
| 866 |
} else if (hostrange_count(hr) > 0) { |
1119 |
} else if (hostrange_count(hr) > 0) { |
| 867 |
size = strlen(hr->prefix) + hr->width + 16; |
1120 |
size = strlen(hr->prefix) + hr->width + 16; |
|
|
1121 |
if (hr->suffix) size += strlen(hr->suffix); |
| 868 |
if (!(host = malloc(size))) |
1122 |
if (!(host = malloc(size))) |
| 869 |
out_of_memory("hostrange shift"); |
1123 |
out_of_memory("hostrange shift"); |
| 870 |
if ((dims > 1) && (hr->width == dims)) { |
1124 |
if ((dims > 1) && (hr->width == dims)) { |
|
Lines 874-879
static char *hostrange_shift(hostrange_t *hr, int dims)
Link Here
|
| 874 |
|
1128 |
|
| 875 |
hostlist_parse_int_to_array(hr->lo, coord, dims, 0); |
1129 |
hostlist_parse_int_to_array(hr->lo, coord, dims, 0); |
| 876 |
|
1130 |
|
|
|
1131 |
xassert(!hr->suffix); |
| 877 |
len = snprintf(host, size, "%s", hr->prefix); |
1132 |
len = snprintf(host, size, "%s", hr->prefix); |
| 878 |
if (len >= 0 && len + dims < size) { |
1133 |
if (len >= 0 && len + dims < size) { |
| 879 |
while (i2 < dims) |
1134 |
while (i2 < dims) |
|
Lines 882-889
static char *hostrange_shift(hostrange_t *hr, int dims)
Link Here
|
| 882 |
} |
1137 |
} |
| 883 |
hr->lo++; |
1138 |
hr->lo++; |
| 884 |
} else { |
1139 |
} else { |
| 885 |
snprintf(host, size, "%s%0*lu", hr->prefix, |
1140 |
snprintf(host, size, "%s%0*lu%s", hr->prefix, |
| 886 |
hr->width, hr->lo++); |
1141 |
hr->width, hr->lo++, hr->suffix ? hr->suffix : ""); |
| 887 |
} |
1142 |
} |
| 888 |
} |
1143 |
} |
| 889 |
|
1144 |
|
|
Lines 911-917
static int hostrange_join(hostrange_t *h1, hostrange_t *h2)
Link Here
|
| 911 |
xassert(h1 && h2); |
1166 |
xassert(h1 && h2); |
| 912 |
xassert(hostrange_cmp(h1, h2) <= 0); |
1167 |
xassert(hostrange_cmp(h1, h2) <= 0); |
| 913 |
|
1168 |
|
| 914 |
if (hostrange_prefix_cmp(h1, h2) == 0 && |
1169 |
if (hostrange_prefix_suffix_cmp(h1, h2) == 0 && |
| 915 |
hostrange_width_combine(h1, h2)) { |
1170 |
hostrange_width_combine(h1, h2)) { |
| 916 |
|
1171 |
|
| 917 |
if (h1->singlehost && h2->singlehost) { /* matching singlets */ |
1172 |
if (h1->singlehost && h2->singlehost) { /* matching singlets */ |
|
Lines 949-955
static hostrange_t *hostrange_intersect(hostrange_t *h1, hostrange_t *h2)
Link Here
|
| 949 |
xassert(hostrange_cmp(h1, h2) <= 0); |
1204 |
xassert(hostrange_cmp(h1, h2) <= 0); |
| 950 |
|
1205 |
|
| 951 |
if ((h1->hi > h2->lo) |
1206 |
if ((h1->hi > h2->lo) |
| 952 |
&& (hostrange_prefix_cmp(h1, h2) == 0) |
1207 |
&& (hostrange_prefix_suffix_cmp(h1, h2) == 0) |
| 953 |
&& (hostrange_width_combine(h1, h2))) { |
1208 |
&& (hostrange_width_combine(h1, h2))) { |
| 954 |
|
1209 |
|
| 955 |
if (!(new = hostrange_copy(h1))) |
1210 |
if (!(new = hostrange_copy(h1))) |
|
Lines 964-971
static hostrange_t *hostrange_intersect(hostrange_t *h1, hostrange_t *h2)
Link Here
|
| 964 |
/* return 1 if hostname hn is within the hostrange hr |
1219 |
/* return 1 if hostname hn is within the hostrange hr |
| 965 |
* 0 if not. |
1220 |
* 0 if not. |
| 966 |
*/ |
1221 |
*/ |
| 967 |
static int hostrange_hn_within(hostrange_t *hr, hostname_t *hn, int dims) |
1222 |
static int hostrange_hn_within(hostrange_t *hr, hostname_t *hn_orig, int dims) |
| 968 |
{ |
1223 |
{ |
|
|
1224 |
hostname_t *hn = hn_orig; |
| 1225 |
int ret = 0; |
| 1226 |
|
| 969 |
if (hr->singlehost) { |
1227 |
if (hr->singlehost) { |
| 970 |
/* |
1228 |
/* |
| 971 |
* If the current hostrange [hr] is a `singlehost' (no valid |
1229 |
* If the current hostrange [hr] is a `singlehost' (no valid |
|
Lines 1024-1041
static int hostrange_hn_within(hostrange_t *hr, hostname_t *hn, int dims)
Link Here
|
| 1024 |
if (len1 == len2) |
1282 |
if (len1 == len2) |
| 1025 |
return 0; |
1283 |
return 0; |
| 1026 |
|
1284 |
|
|
|
1285 |
/* Make a copy of the hostname to mess with */ |
| 1286 |
hn = hostname_copy(hn_orig); |
| 1287 |
|
| 1288 |
if (!hn) |
| 1289 |
return 0; |
| 1290 |
|
| 1027 |
ldiff = len1 - len2; |
1291 |
ldiff = len1 - len2; |
| 1028 |
|
1292 |
|
| 1029 |
if (ldiff > 0 && (strlen(hn->suffix) >= ldiff)) { |
1293 |
if (ldiff > 0 && (hostname_suffix_width(hn, dims) >= ldiff)) { |
| 1030 |
/* Tack on ldiff of the hostname's suffix to |
1294 |
/* Tack on ldiff of the hostname's suffix to |
| 1031 |
* that of it's prefix */ |
1295 |
* that of it's prefix */ |
| 1032 |
hn->prefix = realloc(hn->prefix, len2+ldiff+1); |
1296 |
hn->prefix = realloc(hn->prefix, len2+ldiff+1); |
|
|
1297 |
if (!hn->prefix) { |
| 1298 |
goto free_cpy; |
| 1299 |
} |
| 1033 |
strncat(hn->prefix, hn->suffix, ldiff); |
1300 |
strncat(hn->prefix, hn->suffix, ldiff); |
| 1034 |
} else if (ldiff < 0) { |
1301 |
} else if (ldiff < 0) { |
| 1035 |
/* strip off the ldiff here */ |
1302 |
/* strip off the ldiff here */ |
| 1036 |
hn->prefix[len2+ldiff] = '\0'; |
1303 |
hn->prefix[len2+ldiff] = '\0'; |
| 1037 |
} else |
1304 |
} |
| 1038 |
return 0; |
|
|
| 1039 |
|
1305 |
|
| 1040 |
/* Now adjust the suffix of the hostname object. */ |
1306 |
/* Now adjust the suffix of the hostname object. */ |
| 1041 |
hn->suffix += ldiff; |
1307 |
hn->suffix += ldiff; |
|
Lines 1051-1070
static int hostrange_hn_within(hostrange_t *hr, hostname_t *hn, int dims)
Link Here
|
| 1051 |
|
1317 |
|
| 1052 |
/* Now compare them and see if they match */ |
1318 |
/* Now compare them and see if they match */ |
| 1053 |
if (strcmp(hr->prefix, hn->prefix) != 0) |
1319 |
if (strcmp(hr->prefix, hn->prefix) != 0) |
| 1054 |
return 0; |
1320 |
goto free_cpy; |
| 1055 |
} |
1321 |
} |
| 1056 |
|
1322 |
|
|
|
1323 |
/* And check the suffix if any */ |
| 1324 |
if (hr->suffix && hostname_suffix_extra(hn, dims) && |
| 1325 |
strcmp(hr->suffix, hostname_suffix_extra(hn, dims)) != 0) |
| 1326 |
goto free_cpy; |
| 1327 |
|
| 1057 |
/* |
1328 |
/* |
| 1058 |
* Finally, check whether [hn], with a valid numeric suffix, |
1329 |
* Finally, check whether [hn], with a valid numeric suffix, |
| 1059 |
* falls within the range of [hr]. |
1330 |
* falls within the range of [hr]. |
| 1060 |
*/ |
1331 |
*/ |
| 1061 |
if (hn->num <= hr->hi && hn->num >= hr->lo) { |
1332 |
if (hn->num <= hr->hi && hn->num >= hr->lo) { |
| 1062 |
int width = hostname_suffix_width(hn); |
1333 |
int width = hostname_suffix_width(hn, dims); |
| 1063 |
int num = hn->num; |
1334 |
int num = hn->num; |
| 1064 |
return (_width_equiv(hr->lo, &hr->width, num, &width)); |
1335 |
ret = (_width_equiv(hr->lo, &hr->width, num, &width)); |
| 1065 |
} |
1336 |
} |
| 1066 |
|
1337 |
|
| 1067 |
return 0; |
1338 |
free_cpy: |
|
|
1339 |
if (hn != hn_orig) |
| 1340 |
hostname_destroy(hn); |
| 1341 |
return ret; |
| 1068 |
} |
1342 |
} |
| 1069 |
|
1343 |
|
| 1070 |
|
1344 |
|
|
Lines 1103-1108
static size_t hostrange_to_string(hostrange_t *hr, size_t n, char *buf,
Link Here
|
| 1103 |
int i2 = 0; |
1377 |
int i2 = 0; |
| 1104 |
int coord[dims]; |
1378 |
int coord[dims]; |
| 1105 |
|
1379 |
|
|
|
1380 |
xassert(!hr->suffix); |
| 1106 |
hostlist_parse_int_to_array(i, coord, dims, 0); |
1381 |
hostlist_parse_int_to_array(i, coord, dims, 0); |
| 1107 |
ret = snprintf(buf + len, n - len, "%s", hr->prefix); |
1382 |
ret = snprintf(buf + len, n - len, "%s", hr->prefix); |
| 1108 |
if (ret < 0 || (len += ret) >= n || len + dims >= n) |
1383 |
if (ret < 0 || (len += ret) >= n || len + dims >= n) |
|
Lines 1110-1117
static size_t hostrange_to_string(hostrange_t *hr, size_t n, char *buf,
Link Here
|
| 1110 |
while (i2 < dims) |
1385 |
while (i2 < dims) |
| 1111 |
buf[len++] = alpha_num[coord[i2++]]; |
1386 |
buf[len++] = alpha_num[coord[i2++]]; |
| 1112 |
} else { |
1387 |
} else { |
| 1113 |
ret = snprintf(buf + len, n - len, "%s%0*lu", |
1388 |
ret = snprintf(buf + len, n - len, "%s%0*lu%s", |
| 1114 |
hr->prefix, hr->width, i); |
1389 |
hr->prefix, hr->width, i, hr->suffix ? hr->suffix : ""); |
| 1115 |
if (ret < 0 || (len += ret) >= n) |
1390 |
if (ret < 0 || (len += ret) >= n) |
| 1116 |
goto truncated; |
1391 |
goto truncated; |
| 1117 |
} |
1392 |
} |
|
Lines 1274-1280
static int hostlist_push_range(hostlist_t hl, hostrange_t *hr)
Link Here
|
| 1274 |
|
1549 |
|
| 1275 |
if (hl->nranges > 0 |
1550 |
if (hl->nranges > 0 |
| 1276 |
&& tail->hi == hr->lo - 1 |
1551 |
&& tail->hi == hr->lo - 1 |
| 1277 |
&& hostrange_prefix_cmp(tail, hr) == 0 |
1552 |
&& hostrange_prefix_suffix_cmp(tail, hr) == 0 |
| 1278 |
&& hostrange_width_combine(tail, hr)) { |
1553 |
&& hostrange_width_combine(tail, hr)) { |
| 1279 |
tail->hi = hr->hi; |
1554 |
tail->hi = hr->hi; |
| 1280 |
} else { |
1555 |
} else { |
|
Lines 1302-1310
error:
Link Here
|
| 1302 |
*/ |
1577 |
*/ |
| 1303 |
static int |
1578 |
static int |
| 1304 |
hostlist_push_hr(hostlist_t hl, char *prefix, unsigned long lo, |
1579 |
hostlist_push_hr(hostlist_t hl, char *prefix, unsigned long lo, |
| 1305 |
unsigned long hi, int width) |
1580 |
unsigned long hi, int width, char *suffix) |
| 1306 |
{ |
1581 |
{ |
| 1307 |
hostrange_t *hr = hostrange_create(prefix, lo, hi, width); |
1582 |
hostrange_t *hr = hostrange_create(prefix, lo, hi, width, suffix); |
| 1308 |
int retval = hostlist_push_range(hl, hr); |
1583 |
int retval = hostlist_push_range(hl, hr); |
| 1309 |
hostrange_destroy(hr); |
1584 |
hostrange_destroy(hr); |
| 1310 |
return retval; |
1585 |
return retval; |
|
Lines 1509-1515
hostlist_t _hostlist_create(const char *hostlist, char *sep, char *r_op,
Link Here
|
| 1509 |
} else { |
1784 |
} else { |
| 1510 |
if (high < low) |
1785 |
if (high < low) |
| 1511 |
high = low; |
1786 |
high = low; |
| 1512 |
hostlist_push_hr(new, prefix, low, high, fmt); |
1787 |
hostlist_push_hr(new, prefix, low, high, fmt, NULL); |
| 1513 |
} |
1788 |
} |
| 1514 |
|
1789 |
|
| 1515 |
error = 0; |
1790 |
error = 0; |
|
Lines 1711-1717
static int _parse_range_list(char *str,
Link Here
|
| 1711 |
* RET 0 on success, -1 on failure (invalid prefix) */ |
1986 |
* RET 0 on success, -1 on failure (invalid prefix) */ |
| 1712 |
static int |
1987 |
static int |
| 1713 |
_push_range_list(hostlist_t hl, char *prefix, struct _range *range, |
1988 |
_push_range_list(hostlist_t hl, char *prefix, struct _range *range, |
| 1714 |
int n, int dims) |
1989 |
int n, int dims, char *suffix) |
| 1715 |
{ |
1990 |
{ |
| 1716 |
int i, k, nr, rc = 0, rc1; |
1991 |
int i, k, nr, rc = 0, rc1; |
| 1717 |
char *p, *q; |
1992 |
char *p, *q; |
|
Lines 1749-1755
_push_range_list(hostlist_t hl, char *prefix, struct _range *range,
Link Here
|
| 1749 |
if (recurse) { |
2024 |
if (recurse) { |
| 1750 |
rc1 = _push_range_list(hl, new_prefix, |
2025 |
rc1 = _push_range_list(hl, new_prefix, |
| 1751 |
saved_range, |
2026 |
saved_range, |
| 1752 |
n, dims); |
2027 |
n, dims, suffix); |
| 1753 |
rc = MAX(rc, rc1); |
2028 |
rc = MAX(rc, rc1); |
| 1754 |
} else { |
2029 |
} else { |
| 1755 |
range = saved_range; |
2030 |
range = saved_range; |
|
Lines 1757-1763
_push_range_list(hostlist_t hl, char *prefix, struct _range *range,
Link Here
|
| 1757 |
hostlist_push_hr(hl, new_prefix, |
2032 |
hostlist_push_hr(hl, new_prefix, |
| 1758 |
range->lo, |
2033 |
range->lo, |
| 1759 |
range->hi, |
2034 |
range->hi, |
| 1760 |
range->width); |
2035 |
range->width, suffix); |
| 1761 |
range++; |
2036 |
range++; |
| 1762 |
} |
2037 |
} |
| 1763 |
} |
2038 |
} |
|
Lines 1771-1777
_push_range_list(hostlist_t hl, char *prefix, struct _range *range,
Link Here
|
| 1771 |
|
2046 |
|
| 1772 |
for (k = 0; k < n; k++) { |
2047 |
for (k = 0; k < n; k++) { |
| 1773 |
hostlist_push_hr(hl, prefix, |
2048 |
hostlist_push_hr(hl, prefix, |
| 1774 |
range->lo, range->hi, range->width); |
2049 |
range->lo, range->hi, range->width, suffix); |
| 1775 |
range++; |
2050 |
range++; |
| 1776 |
} |
2051 |
} |
| 1777 |
return 0; |
2052 |
return 0; |
|
Lines 1801-1812
_hostlist_create_bracketed(const char *hostlist, char *sep,
Link Here
|
| 1801 |
|
2076 |
|
| 1802 |
while ((tok = _next_tok(sep, &str)) != NULL) { |
2077 |
while ((tok = _next_tok(sep, &str)) != NULL) { |
| 1803 |
if ((p = strrchr(tok, '[')) != NULL) { |
2078 |
if ((p = strrchr(tok, '[')) != NULL) { |
| 1804 |
char *q, *prefix = tok; |
2079 |
char *q, *prefix = tok, *suffix = NULL; |
| 1805 |
*p++ = '\0'; |
2080 |
*p++ = '\0'; |
| 1806 |
|
2081 |
|
| 1807 |
if ((q = strchr(p, ']'))) { |
2082 |
if ((q = strchr(p, ']'))) { |
| 1808 |
if ((q[1] != ',') && (q[1] != '\0')) |
2083 |
if ((q[1] != ',') && (q[1] != '\0')) { |
| 1809 |
goto error; |
2084 |
/* suffix only supported for dims == 1 */ |
|
|
2085 |
if (dims == 1) |
| 2086 |
suffix = q+1; |
| 2087 |
else |
| 2088 |
goto error; |
| 2089 |
} |
| 1810 |
*q = '\0'; |
2090 |
*q = '\0'; |
| 1811 |
nr = _parse_range_list(p, |
2091 |
nr = _parse_range_list(p, |
| 1812 |
&ranges, |
2092 |
&ranges, |
|
Lines 1815-1821
_hostlist_create_bracketed(const char *hostlist, char *sep,
Link Here
|
| 1815 |
if (nr < 0) |
2095 |
if (nr < 0) |
| 1816 |
goto error; |
2096 |
goto error; |
| 1817 |
if (_push_range_list( |
2097 |
if (_push_range_list( |
| 1818 |
new, prefix, ranges, nr, dims)) |
2098 |
new, prefix, ranges, nr, dims, suffix)) |
| 1819 |
goto error; |
2099 |
goto error; |
| 1820 |
} else { |
2100 |
} else { |
| 1821 |
/* The hostname itself contains a '[' |
2101 |
/* The hostname itself contains a '[' |
|
Lines 1961-1967
int hostlist_push_host_dims(hostlist_t hl, const char *str, int dims)
Link Here
|
| 1961 |
|
2241 |
|
| 1962 |
if (hostname_suffix_is_valid(hn)) |
2242 |
if (hostname_suffix_is_valid(hn)) |
| 1963 |
hr = hostrange_create(hn->prefix, hn->num, hn->num, |
2243 |
hr = hostrange_create(hn->prefix, hn->num, hn->num, |
| 1964 |
hostname_suffix_width(hn)); |
2244 |
hostname_suffix_width(hn, dims), hostname_suffix_extra(hn, dims)); |
| 1965 |
else |
2245 |
else |
| 1966 |
hr = hostrange_create_single(str); |
2246 |
hr = hostrange_create_single(str); |
| 1967 |
|
2247 |
|
|
Lines 2246-2251
static char *_hostrange_string(hostrange_t *hr, int depth)
Link Here
|
| 2246 |
int i2 = 0; |
2526 |
int i2 = 0; |
| 2247 |
int coord[dims]; |
2527 |
int coord[dims]; |
| 2248 |
|
2528 |
|
|
|
2529 |
xassert(!hr->suffix); |
| 2249 |
hostlist_parse_int_to_array( |
2530 |
hostlist_parse_int_to_array( |
| 2250 |
hr->lo + depth, coord, dims, 0); |
2531 |
hr->lo + depth, coord, dims, 0); |
| 2251 |
|
2532 |
|
|
Lines 2253-2260
static char *_hostrange_string(hostrange_t *hr, int depth)
Link Here
|
| 2253 |
buf[len++] = alpha_num[coord[i2++]]; |
2534 |
buf[len++] = alpha_num[coord[i2++]]; |
| 2254 |
buf[len] = '\0'; |
2535 |
buf[len] = '\0'; |
| 2255 |
} else { |
2536 |
} else { |
| 2256 |
len = snprintf(buf + len, size - len, "%0*lu", |
2537 |
len = snprintf(buf + len, size - len, "%0*lu%s", |
| 2257 |
hr->width, hr->lo + depth); |
2538 |
hr->width, hr->lo + depth, hr->suffix ? hr->suffix : ""); |
| 2258 |
if (len < 0 || len >= size) |
2539 |
if (len < 0 || len >= size) |
| 2259 |
return NULL; |
2540 |
return NULL; |
| 2260 |
} |
2541 |
} |
|
Lines 2424-2431
static void hostlist_collapse(hostlist_t hl)
Link Here
|
| 2424 |
hostrange_t *hprev = hl->hr[i - 1]; |
2705 |
hostrange_t *hprev = hl->hr[i - 1]; |
| 2425 |
hostrange_t *hnext = hl->hr[i]; |
2706 |
hostrange_t *hnext = hl->hr[i]; |
| 2426 |
|
2707 |
|
| 2427 |
if (hprev->hi == hnext->lo - 1 && |
2708 |
if ((hprev->hi == hnext->lo - 1 || hprev->hi == hnext->lo) && |
| 2428 |
hostrange_prefix_cmp(hprev, hnext) == 0 && |
2709 |
hostrange_prefix_suffix_cmp(hprev, hnext) == 0 && |
| 2429 |
hostrange_width_combine(hprev, hnext)) { |
2710 |
hostrange_width_combine(hprev, hnext)) { |
| 2430 |
hprev->hi = hnext->hi; |
2711 |
hprev->hi = hnext->hi; |
| 2431 |
hostlist_delete_range(hl, i); |
2712 |
hostlist_delete_range(hl, i); |
|
Lines 2444-2449
static void hostlist_coalesce(hostlist_t hl)
Link Here
|
| 2444 |
|
2725 |
|
| 2445 |
LOCK_HOSTLIST(hl); |
2726 |
LOCK_HOSTLIST(hl); |
| 2446 |
|
2727 |
|
|
|
2728 |
for (i = 0; i < hl->nranges - 1; i++) { |
| 2729 |
new = hostrange_combine_suffix(hl->hr[i], hl->hr[i+1]); |
| 2730 |
if (new) { |
| 2731 |
/* combined, we can delete the second range */ |
| 2732 |
hostlist_delete_range(hl, i+1); |
| 2733 |
/* try to combine this one with the next one again */ |
| 2734 |
i--; |
| 2735 |
} |
| 2736 |
} |
| 2737 |
|
| 2447 |
for (i = hl->nranges - 1; i > 0; i--) { |
2738 |
for (i = hl->nranges - 1; i > 0; i--) { |
| 2448 |
|
2739 |
|
| 2449 |
new = hostrange_intersect(hl->hr[i - 1], hl->hr[i]); |
2740 |
new = hostrange_intersect(hl->hr[i - 1], hl->hr[i]); |
|
Lines 2465-2471
static void hostlist_coalesce(hostlist_t hl)
Link Here
|
| 2465 |
while (new->lo <= new->hi) { |
2756 |
while (new->lo <= new->hi) { |
| 2466 |
hostrange_t *hr = hostrange_create(new->prefix, |
2757 |
hostrange_t *hr = hostrange_create(new->prefix, |
| 2467 |
new->lo, new->lo, |
2758 |
new->lo, new->lo, |
| 2468 |
new->width); |
2759 |
new->width, new->suffix); |
| 2469 |
|
2760 |
|
| 2470 |
if (new->lo > hprev->hi) |
2761 |
if (new->lo > hprev->hi) |
| 2471 |
hostlist_insert_range(hl, hr, j++); |
2762 |
hostlist_insert_range(hl, hr, j++); |
|
Lines 2624-2630
_get_bracketed_list(hostlist_t hl, int *start, const size_t n, char *buf,
Link Here
|
| 2624 |
int brackets) |
2915 |
int brackets) |
| 2625 |
{ |
2916 |
{ |
| 2626 |
hostrange_t **hr = hl->hr; |
2917 |
hostrange_t **hr = hl->hr; |
| 2627 |
int i = *start; |
2918 |
int i = *start, first = *start; |
| 2628 |
int m, len = 0; |
2919 |
int m, len = 0; |
| 2629 |
int bracket_needed = brackets ? _is_bracket_needed(hl, i) : 0; |
2920 |
int bracket_needed = brackets ? _is_bracket_needed(hl, i) : 0; |
| 2630 |
int zeropad = 0; |
2921 |
int zeropad = 0; |
|
Lines 2670-2675
_get_bracketed_list(hostlist_t hl, int *start, const size_t n, char *buf,
Link Here
|
| 2670 |
if (bracket_needed) |
2961 |
if (bracket_needed) |
| 2671 |
buf[len++] = ']'; |
2962 |
buf[len++] = ']'; |
| 2672 |
|
2963 |
|
|
|
2964 |
/* All grouped ranges should have the same suffix, use the first */ |
| 2965 |
if (hr[first]->suffix) { |
| 2966 |
xassert(n - len > 1); |
| 2967 |
len += snprintf(buf + len, n - len - 1, "%s", hr[first]->suffix); |
| 2968 |
if (n - len < 1) /* no space left in buffer */ |
| 2969 |
return len; |
| 2970 |
} |
| 2971 |
|
| 2673 |
buf[len] = '\0'; |
2972 |
buf[len] = '\0'; |
| 2674 |
*start = i; |
2973 |
*start = i; |
| 2675 |
return len; |
2974 |
return len; |
|
Lines 3374-3379
char *hostlist_next_dims(hostlist_iterator_t i, int dims)
Link Here
|
| 3374 |
i->hr->width, i->hr->lo + i->depth); |
3673 |
i->hr->width, i->hr->lo + i->depth); |
| 3375 |
if (len < 0 || len >= size) |
3674 |
if (len < 0 || len >= size) |
| 3376 |
goto no_next; |
3675 |
goto no_next; |
|
|
3676 |
if (i->hr->suffix) { |
| 3677 |
len += snprintf(buf + len, size - len, "%s", i->hr->suffix); |
| 3678 |
if (len < 0 || len >= size) |
| 3679 |
goto no_next; |
| 3680 |
} |
| 3377 |
} |
3681 |
} |
| 3378 |
} |
3682 |
} |
| 3379 |
UNLOCK_HOSTLIST(i->hl); |
3683 |
UNLOCK_HOSTLIST(i->hl); |