/* * Modeled after strcmp(), compare two version-ids for a Prefix * Match as defined in JSR 56. */ int JLI_PrefixVersionId(const char *id1, char *id2) { char *s1 = JLI_StringDup(id1); char *s2 = JLI_StringDup(id2); char *m1 = s1; char *m2 = s2; char *end1 = NULL; char *end2 = NULL; int res = 0; do { if ((s1 != NULL) && ((end1 = JLI_StrPBrk(s1, ".-_")) != NULL)) *end1 = '\0'; if ((s2 != NULL) && ((end2 = JLI_StrPBrk(s2, ".-_")) != NULL)) *end2 = '\0'; res = comp_string(s1, s2); if (end1 != NULL) s1 = end1 + 1; else s1 = NULL; if (end2 != NULL) s2 = end2 + 1; else s2 = NULL; } while (res == 0 && ((s1 != NULL) && (s2 != NULL))); JLI_MemFree(m1); JLI_MemFree(m2); return (res); }
/* * Return true if this is a valid simple-element (as defined in JSR 56). * * The official grammar for a simple-element is: * * simple-element ::= version-id | version-id modifier * modifier ::= '+' | '*' * version-id ::= string ( separator string )* * string ::= char ( char )* * char ::= Any ASCII character except a space, an * ampersand, a separator or a modifier * separator ::= '.' | '-' | '_' * * However, for efficiency, it is time to abandon the top down parser * implementation. After deleting the potential trailing modifier, we * are left with a version-id. * * Note that a valid version-id has three simple properties: * * 1) Doesn't contain a space, an ampersand or a modifier. * * 2) Doesn't begin or end with a separator. * * 3) Doesn't contain two adjacent separators. * * Any other line noise constitutes a valid version-id. */ static int valid_simple_element(char *simple_element) { char *last; size_t len; if ((simple_element == NULL) || ((len = JLI_StrLen(simple_element)) == 0)) return (0); last = simple_element + len - 1; if (*last == '*' || *last == '+') { if (--len == 0) return (0); *last-- = '\0'; } if (JLI_StrPBrk(simple_element, " &+*") != NULL) /* Property #1 */ return (0); if ((JLI_StrChr(".-_", *simple_element) != NULL) || /* Property #2 */ (JLI_StrChr(".-_", *last) != NULL)) return (0); for (; simple_element != last; simple_element++) /* Property #3 */ if ((JLI_StrChr(".-_", *simple_element) != NULL) && (JLI_StrChr(".-_", *(simple_element + 1)) != NULL)) return (0); return (1); }
/* * Modeled after strcmp(), compare two version-ids for an Exact * Match as defined in JSR 56. */ int JLI_ExactVersionId(const char *id1, char *id2) { char *s1 = JLI_StringDup(id1); char *s2 = JLI_StringDup(id2); char *m1 = s1; char *m2 = s2; char *end1 = NULL; char *end2 = NULL; int res = 0; do { if ((s1 != NULL) && ((end1 = JLI_StrPBrk(s1, separators)) != NULL)) *end1 = '\0'; if ((s2 != NULL) && ((end2 = JLI_StrPBrk(s2, separators)) != NULL)) *end2 = '\0'; if ((s1 != NULL) && (s2 == NULL)) res = comp_string(s1, zero_string); else if ((s1 == NULL) && (s2 != NULL)) res = comp_string(zero_string, s2); else res = comp_string(s1, s2); if (end1 != NULL) s1 = end1 + 1; else s1 = NULL; if (end2 != NULL) s2 = end2 + 1; else s2 = NULL; } while (res == 0 && ((s1 != NULL) || (s2 != NULL))); JLI_MemFree(m1); JLI_MemFree(m2); return (res); }
/* * Parse a Manifest file header entry into a distinct "name" and "value". * Continuation lines are joined into a single "value". The documented * syntax for a header entry is: * * header: name ":" value * * name: alphanum *headerchar * * value: SPACE *otherchar newline *continuation * * continuation: SPACE *otherchar newline * * newline: CR LF | LF | CR (not followed by LF) * * alphanum: {"A"-"Z"} | {"a"-"z"} | {"0"-"9"} * * headerchar: alphanum | "-" | "_" * * otherchar: any UTF-8 character except NUL, CR and LF * * Note that a manifest file may be composed of multiple sections, * each of which may contain multiple headers. * * section: *header +newline * * nonempty-section: +header +newline * * (Note that the point of "nonempty-section" is unclear, because it isn't * referenced elsewhere in the full specification for the Manifest file.) * * Arguments: * lp pointer to a character pointer which points to the start * of a valid header. * name pointer to a character pointer which will be set to point * to the name portion of the header (nul terminated). * value pointer to a character pointer which will be set to point * to the value portion of the header (nul terminated). * * Returns: * 1 Successful parsing of an NV pair. lp is updated to point to the * next character after the terminating newline in the string * representing the Manifest file. name and value are updated to * point to the strings parsed. * 0 A valid end of section indicator was encountered. lp, name, and * value are not modified. * -1 lp does not point to a valid header. Upon return, the values of * lp, name, and value are undefined. */ static int parse_nv_pair(char **lp, char **name, char **value) { char *nl; char *cp; /* * End of the section - return 0. The end of section condition is * indicated by either encountering a blank line or the end of the * Manifest "string" (EOF). */ if (**lp == '\0' || **lp == '\n' || **lp == '\r') return (0); /* * Getting to here, indicates that *lp points to an "otherchar". * Turn the "header" into a string on its own. */ nl = JLI_StrPBrk(*lp, "\n\r"); if (nl == NULL) { nl = JLI_StrChr(*lp, (int)'\0'); } else { cp = nl; /* For merging continuation lines */ if (*nl == '\r' && *(nl+1) == '\n') *nl++ = '\0'; *nl++ = '\0'; /* * Process any "continuation" line(s), by making them part of the * "header" line. Yes, I know that we are "undoing" the NULs we * just placed here, but continuation lines are the fairly rare * case, so we shouldn't unnecessarily complicate the code above. * * Note that an entire continuation line is processed each iteration * through the outer while loop. */ while (*nl == ' ') { nl++; /* First character to be moved */ while (*nl != '\n' && *nl != '\r' && *nl != '\0') *cp++ = *nl++; /* Shift string */ if (*nl == '\0') return (-1); /* Error: newline required */ *cp = '\0'; if (*nl == '\r' && *(nl+1) == '\n') *nl++ = '\0'; *nl++ = '\0'; } } /* * Separate the name from the value; */ cp = JLI_StrChr(*lp, (int)':'); if (cp == NULL) return (-1); *cp++ = '\0'; /* The colon terminates the name */ if (*cp != ' ') return (-1); *cp++ = '\0'; /* Eat the required space */ *name = *lp; *value = cp; *lp = nl; return (1); }