public inbox for gentoo-commits@lists.gentoo.org
 help / color / mirror / Atom feed
* [gentoo-commits] proj/portage-utils:master commit in: /, tests/atom_explode/, libq/
@ 2020-01-01 12:51 Fabian Groffen
  0 siblings, 0 replies; only message in thread
From: Fabian Groffen @ 2020-01-01 12:51 UTC (permalink / raw
  To: gentoo-commits

commit:     c6537da04a6695656d655bf4e48813fb041ec010
Author:     Fabian Groffen <grobian <AT> gentoo <DOT> org>
AuthorDate: Wed Jan  1 12:50:18 2020 +0000
Commit:     Fabian Groffen <grobian <AT> gentoo <DOT> org>
CommitDate: Wed Jan  1 12:50:18 2020 +0000
URL:        https://gitweb.gentoo.org/proj/portage-utils.git/commit/?id=c6537da0

libq/atom: stick to PMS for PVR

rework allocations somewhat, and make sure PVR does NOT include -r0, in
addition add PF to the structure, so this one can be grabbed more easily

Signed-off-by: Fabian Groffen <grobian <AT> gentoo.org>

 TODO.md                   |   9 +--
 libq/atom.c               | 149 ++++++++++++++++++++++++++--------------------
 libq/atom.h               |   1 +
 tests/atom_explode/test.c |  22 +++++--
 4 files changed, 107 insertions(+), 74 deletions(-)

diff --git a/TODO.md b/TODO.md
index dffaa91..cd4f2b2 100644
--- a/TODO.md
+++ b/TODO.md
@@ -22,13 +22,8 @@
 - replace all strtok by strtok\_r, because the latter is already used,
   so we can
 
-# Atoms
-
-- only 32bit values are supported for revision (-r#)
-- only 64bit values are supported in any individual version component
-  foo-(1234)\_alpha(56789)
-- these limits should not be an issue for all practical purposes
-- make PVR match PMS https://dev.gentoo.org/~ulm/pms/head/pms.html#x1-10800011
+- parse package.accept\_keywords such that we can provide the latest
+  "available" version like Portage
 
 # qmerge
 

diff --git a/libq/atom.c b/libq/atom.c
index 05b138c..6f70847 100644
--- a/libq/atom.c
+++ b/libq/atom.c
@@ -1,5 +1,5 @@
 /*
- * Copyright 2005-2019 Gentoo Foundation
+ * Copyright 2005-2020 Gentoo Foundation
  * Distributed under the terms of the GNU General Public License v2
  *
  * Copyright 2005-2008 Ned Ludd        - <solar@gentoo.org>
@@ -39,6 +39,9 @@ const char * const atom_op_str[] = {
 
 const char * const booga[] = {"!!!", "!=", "==", ">", "<"};
 
+/* split string into individual components, known as an atom
+ * for a definition of which variable contains what, see:
+ * https://dev.gentoo.org/~ulm/pms/head/pms.html#x1-10800011 */
 depend_atom *
 atom_explode(const char *atom)
 {
@@ -48,18 +51,33 @@ atom_explode(const char *atom)
 	size_t slen;
 	size_t idx;
 	size_t sidx;
-
-	/* we allocate mem for atom struct and two strings (strlen(atom)).
-	 * the first string is for CAT/PN/PV while the second is for PVR.
-	 * PVR needs 3 extra bytes for possible implicit '-r0'. */
-	slen = strlen(atom);
-	len = sizeof(*ret) + (slen + 1) * sizeof(*atom) * 3 + 3;
+	char *lastpv = NULL;
+	char *pv;
+
+	/* PMS 11.1 recap:
+	 * CAT  The package’s category                    app-editors
+	 * PF   Package name, version, and revision (if any)          vim-7.0.174-r1
+	 * PVR  Package version and revision (if any)                     7.0.174-r1
+	 * P    Package name and version, without the revision part   vim-7.0.174
+	 * PV   Package version, with no revision                         7.0.174
+	 * PN   Package name                                          vim
+	 * PR   Package revision, or r0 if none exists                            r1
+	 *
+	 * Thus, CAT/PF is the full allocation of the input string, for the
+	 * rest (P, PN, PV, PR, PVR) we need copies.  We represent PR as an
+	 * integer, which leaves the set to PN, P and PV.
+	 * PVR is an offset inside PF, likewise, PV is an offset inside P.
+	 * We allocate memory for atom struct, one string for CAT/PF + PVR,
+	 * another to cover PN and a final one for P + PV. */
+	slen = strlen(atom) + 1;
+	len = sizeof(*ret) + (slen * 3);
 	ret = xmalloc(len);
 	memset(ret, '\0', sizeof(*ret));
-	ptr = (char *)ret;
-	ret->P = ptr + sizeof(*ret);
-	ret->PVR = ret->P + slen + 1;
-	ret->CATEGORY = ret->PVR + slen + 1 + 3;
+
+	/* assign pointers to the three storage containers */
+	ret->CATEGORY = (char *)ret + sizeof(*ret);     /* CAT PF PVR */
+	ret->P        = ret->CATEGORY + slen;           /* P   PV     */
+	ret->PN       = ret->P + slen;                  /* PN         */
 
 	/* check for blocker operators */
 	ret->blocker = ATOM_BL_NONE;
@@ -95,13 +113,15 @@ atom_explode(const char *atom)
 		ret->pfx_op += ATOM_OP_EQUAL;
 		atom++;
 	}
+
+	/* fill in full block */
 	strcpy(ret->CATEGORY, atom);
 
 	/* eat file name crap when given an (autocompleted) path */
 	if ((ptr = strstr(ret->CATEGORY, ".ebuild")) != NULL)
 		*ptr = '\0';
 
-	/* chip off the trailing [::REPO] as needed */
+	/* chip off the trailing ::REPO as needed */
 	if ((ptr = strstr(ret->CATEGORY, "::")) != NULL) {
 		ret->REPO = ptr + 2;
 		*ptr = '\0';
@@ -172,7 +192,7 @@ atom_explode(const char *atom)
 		*ptr++ = '\0';
 	}
 
-	/* chip off the trailing [:SLOT] as needed */
+	/* chip off the trailing :SLOT as needed */
 	if ((ptr = strrchr(ret->CATEGORY, ':')) != NULL) {
 		*ptr++ = '\0';
 		ret->SLOT = ptr;
@@ -205,14 +225,14 @@ atom_explode(const char *atom)
 		*ptr = '\0';
 	}
 
-	/* break up the CATEGORY and PVR */
+	/* break up the CATEGORY, PF and PVR */
 	if ((ptr = strrchr(ret->CATEGORY, '/')) != NULL) {
-		ret->PN = ptr + 1;
-		*ptr = '\0';
+		*ptr++ = '\0';
+		ret->PF = ptr;
 
 		/* set PN to NULL if there's nothing */
-		if (ret->PN[0] == '\0')
-			ret->PN = NULL;
+		if (ret->PF[0] == '\0')
+			ret->PF = NULL;
 
 		/* eat extra crap in case it exists, this is a feature to allow
 		 * /path/to/pkg.ebuild, doesn't work with prefix operators
@@ -220,75 +240,81 @@ atom_explode(const char *atom)
 		if ((ptr = strrchr(ret->CATEGORY, '/')) != NULL)
 			ret->CATEGORY = ptr + 1;
 	} else {
-		ret->PN = ret->CATEGORY;
+		ret->PF = ret->CATEGORY;
 		ret->CATEGORY = NULL;
 	}
 
-	if (ret->PN == NULL) {
+	if (ret->PF == NULL) {
 		/* atom has no name, this is it */
 		ret->P = NULL;
+		ret->PN = NULL;
 		ret->PVR = NULL;
+
 		return ret;
 	}
 
-	/* CATEGORY should be all set here, PN contains everything up to
+	/* CATEGORY should be all set here, PF contains everything up to
 	 * SLOT, REPO or '*'
-	 * PN must not end in a hyphen followed by anything matching version
-	 * syntax, version syntax starts with a number, so "-[0-9]" is a
-	 * separator from PN to PV* -- except it doesn't when the thing
-	 * doesn't validate as version :( */
-
-	ptr = ret->PN;
-	{
-		char *lastpv = NULL;
-		char *pv;
-
-		while ((ptr = strchr(ptr, '-')) != NULL) {
-			ptr++;
-			if (!isdigit(*ptr))
-				continue;
+	 * PMS 3.1.2 says PN must not end in a hyphen followed by
+	 * anything matching version syntax.  PMS 3.2 version syntax
+	 * starts with a number, so "-[0-9]" is a separator from PN to
+	 * PV* -- except it doesn't when the thing doesn't validate as
+	 * version :( */
+
+	ptr = ret->PF;
+	while ((ptr = strchr(ptr, '-')) != NULL) {
+		ptr++;
+		if (!isdigit(*ptr))
+			continue;
 
-			/* so we should have something like "-2" here, see if this
-			 * checks out as valid version string */
-			pv = ptr;
-			while (*++ptr != '\0') {
-				if (*ptr != '.' && !isdigit(*ptr))
-					break;
-			}
-			/* allow for 1 optional suffix letter */
-			if (*ptr >= 'a' && *ptr <= 'z')
-				ret->letter = *ptr++;
-			if (*ptr == '_' || *ptr == '-' || *ptr == '\0') {
-				lastpv = pv;
-				continue;  /* valid, keep searching */
-			}
-			ret->letter = '\0';
+		/* so we should have something like "-2" here, see if this
+		 * checks out as valid version string */
+		pv = ptr;
+		while (*++ptr != '\0') {
+			if (*ptr != '.' && !isdigit(*ptr))
+				break;
+		}
+		/* allow for 1 optional suffix letter */
+		if (*ptr >= 'a' && *ptr <= 'z')
+			ret->letter = *ptr++;
+		if (*ptr == '_' || *ptr == '-' || *ptr == '\0') {
+			lastpv = pv;
+			continue;  /* valid, keep searching */
 		}
-		ptr = lastpv;
+		ret->letter = '\0';
 	}
+	ptr = lastpv;
 
 	if (ptr == NULL) {
 		/* atom has no version, this is it */
-		strcpy(ret->P, ret->PN);
-		ret->PVR = NULL;
+		ret->P = ret->PN = ret->PF;
+		ret->PV = ret->PVR = NULL;
+
 		return ret;
 	}
-	ret->PV = ptr;
+
+	ret->PVR = ptr;
+	snprintf(ret->PN, slen, "%.*s", (int)(ret->PVR - 1 - ret->PF), ret->PF);
 
 	/* find -r# */
-	ptr = ret->PV + strlen(ret->PV) - 1;
-	while (*ptr && ptr > ret->PV) {
-		if (!isdigit(*ptr)) {
+	pv = NULL;
+	ptr = ret->PVR + strlen(ret->PVR) - 1;
+	while (*ptr && ptr > ret->PVR) {
+		if (!isdigit((int)*ptr)) {
 			if (ptr[0] == 'r' && ptr[-1] == '-') {
 				ret->PR_int = atoi(ptr + 1);
-				ptr[-1] = '\0';
+				pv = &ptr[-1];
 			}
 			break;
 		}
 		ptr--;
 	}
-	strcpy(ret->P, ret->PN);
-	ret->PV[-1] = '\0';
+	if (pv != NULL) {
+		snprintf(ret->P, slen, "%.*s", (int)(pv - ret->PF), ret->PF);
+	} else {
+		ret->P = ret->PF;
+	}
+	ret->PV = ret->P + (ret->PVR - ret->PF);
 
 	/* break out all the suffixes */
 	sidx = 0;
@@ -325,9 +351,6 @@ atom_explode(const char *atom)
 		ret->suffixes[idx] = t;
 	}
 
-	/* size is malloced above with the required space in mind */
-	sprintf(ret->PVR, "%s-r%i", ret->PV, ret->PR_int);
-
 	return ret;
 }
 

diff --git a/libq/atom.h b/libq/atom.h
index a5175b0..1548dd9 100644
--- a/libq/atom.h
+++ b/libq/atom.h
@@ -74,6 +74,7 @@ typedef struct {
 	char *CATEGORY;
 	char *PN;
 	char *PV;
+	char *PF;
 	unsigned int PR_int;
 	char letter;
 	atom_suffix *suffixes;

diff --git a/tests/atom_explode/test.c b/tests/atom_explode/test.c
index 21a5f1d..b794d3b 100644
--- a/tests/atom_explode/test.c
+++ b/tests/atom_explode/test.c
@@ -1,5 +1,5 @@
 /*
- * Copyright 2005-2019 Gentoo Foundation
+ * Copyright 2005-2020 Gentoo Foundation
  * Distributed under the terms of the GNU General Public License v2
  *
  * Copyright 2005-2008 Ned Ludd        - <solar@gentoo.org>
@@ -19,9 +19,23 @@ FILE *warnout;
 
 static inline void boom(depend_atom *a, char *s)
 {
-	printf("%s -> %s / [%s] %s - %s [%s] [r%i]\n",
-	       s, (a->CATEGORY?:"null"), a->P, a->PN,
-	       a->PVR, a->PV, a->PR_int);
+	/* python code:
+	 *  CATEGORY = cpv[0]
+	 *  PN = cpv[1]
+	 *  PV = cpv[2]
+	 *  PR_int = cpv[3]
+	 *  P = PN + "-" + PV
+	 *  PVR = PV + "-" + cpv[3]
+	 *  print(a+" -> "+CATEGORY+" / ["+P+"] "+PN+" - "+PVR+" ["+PV+"] ["+PR_int+"]")
+	 * this most notably doesn't test PVR in compliance with PMS */
+	printf("%s -> %s / [%s] %s - %s%s [%s] [r%i]\n",
+			s,
+			(a->CATEGORY ? a->CATEGORY : "null"),
+			a->P,
+			a->PN,
+			a->PVR, (a->PVR != NULL && a->PR_int == 0) ? "-r0" : "",
+			a->PV,
+			a->PR_int);
 }
 
 int main(int argc, char *argv[])


^ permalink raw reply related	[flat|nested] only message in thread

only message in thread, other threads:[~2020-01-01 12:51 UTC | newest]

Thread overview: (only message) (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2020-01-01 12:51 [gentoo-commits] proj/portage-utils:master commit in: /, tests/atom_explode/, libq/ Fabian Groffen

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox