git.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH] Documentation: document the string-list macros.
@ 2010-09-05 17:51 Thiago Farina
  2010-09-05 20:03 ` [demo/patch 0/3] " Jonathan Nieder
  0 siblings, 1 reply; 6+ messages in thread
From: Thiago Farina @ 2010-09-05 17:51 UTC (permalink / raw)
  To: git; +Cc: jrnieder

Add basic documentation about the string-list.h macros
that can be used to initialize the string_list structure.

Signed-off-by: Thiago Farina <tfransosi@gmail.com>
---
 Documentation/technical/api-string-list.txt |   12 ++++++++++++
 1 files changed, 12 insertions(+), 0 deletions(-)

diff --git a/Documentation/technical/api-string-list.txt b/Documentation/technical/api-string-list.txt
index 3f575bd..cec11b5 100644
--- a/Documentation/technical/api-string-list.txt
+++ b/Documentation/technical/api-string-list.txt
@@ -52,6 +52,18 @@ However, if you use the list to check if a certain string was added
 already, you should not do that (using unsorted_string_list_has_string()),
 because the complexity would be quadratic again (but with a worse factor).
 
+Macros
+------
+
+`STRING_LIST_INIT_NODUP`::
+
+	Initialize the members and set the `strdup_strings` member to 0.
+
+`STRING_LIST_INIT_DUP`::
+
+	Initialize the members and set the `strdup_strings` member to 1.
+
+
 Functions
 ---------
 
-- 
1.7.2.3.313.gcd15

^ permalink raw reply related	[flat|nested] 6+ messages in thread

* [demo/patch 0/3] Re: [PATCH] Documentation: document the string-list macros.
  2010-09-05 17:51 [PATCH] Documentation: document the string-list macros Thiago Farina
@ 2010-09-05 20:03 ` Jonathan Nieder
  2010-09-05 20:04   ` [demo/PATCH 1/3] string-list: introduce string_list_init() Jonathan Nieder
                     ` (3 more replies)
  0 siblings, 4 replies; 6+ messages in thread
From: Jonathan Nieder @ 2010-09-05 20:03 UTC (permalink / raw)
  To: Thiago Farina; +Cc: git

Thiago Farina wrote:

> --- a/Documentation/technical/api-string-list.txt
> +++ b/Documentation/technical/api-string-list.txt
> @@ -52,6 +52,18 @@ However, if you use the list to check if a certain string was added
>  already, you should not do that (using unsorted_string_list_has_string()),
>  because the complexity would be quadratic again (but with a worse factor).
>  
> +Macros
> +------
> +
> +`STRING_LIST_INIT_NODUP`::
> +
> +	Initialize the members and set the `strdup_strings` member to 0.
> +
> +`STRING_LIST_INIT_DUP`::
> +
> +	Initialize the members and set the `strdup_strings` member to 1.

After reading that, one might be tempted to write

	struct string_list x;
	STRING_LIST_INIT_NODUP(x);

, no?  In other words, I don't find the text very clear.

If you like working by example (like I do) then api-strbuf.txt might
give a good indication of how this sort of thing can be helpfully
documented.

Maybe something in this direction?

Patch #3 in particular is very rough and ought to be split up for
easier review.  This is not meant for application, just to give an
idea.

Jonathan Nieder (3):
  string-list: introduce string_list_init()
  string-list: document ...
  Make initialization of string_lists more consistent

 Documentation/technical/api-string-list.txt |   18 +++++++++------
 builtin/apply.c                             |    8 +++---
 builtin/blame.c                             |    4 +-
 builtin/clean.c                             |    2 +-
 builtin/commit.c                            |    4 +-
 builtin/fetch.c                             |   13 ++++-------
 builtin/fmt-merge-msg.c                     |   13 ++++++-----
 builtin/log.c                               |    9 ++-----
 builtin/mailsplit.c                         |    1 +
 builtin/notes.c                             |    4 +-
 builtin/remote.c                            |   30 +++++++++++++-------------
 builtin/shortlog.c                          |   25 ++++++++++++---------
 diff-no-index.c                             |    1 +
 mailmap.c                                   |   17 +++++++++-----
 mailmap.h                                   |    2 +-
 merge-recursive.c                           |   16 ++++++++------
 notes.c                                     |    4 +-
 pretty.c                                    |    5 ++-
 reflog-walk.c                               |    1 +
 resolve-undo.c                              |    8 +++---
 revision.c                                  |    7 ++++-
 string-list.c                               |   28 +++++++++++++++++++++---
 string-list.h                               |    4 +++
 submodule.c                                 |    4 +-
 wt-status.c                                 |    6 ++--
 25 files changed, 137 insertions(+), 97 deletions(-)

-- 
1.7.2.3

^ permalink raw reply	[flat|nested] 6+ messages in thread

* [demo/PATCH 1/3] string-list: introduce string_list_init()
  2010-09-05 20:03 ` [demo/patch 0/3] " Jonathan Nieder
@ 2010-09-05 20:04   ` Jonathan Nieder
  2010-09-05 20:06   ` [demo/PATCH 1/3] string-list: Document STRING_LIST_INIT_* and string_list_init() Jonathan Nieder
                     ` (2 subsequent siblings)
  3 siblings, 0 replies; 6+ messages in thread
From: Jonathan Nieder @ 2010-09-05 20:04 UTC (permalink / raw)
  To: Thiago Farina; +Cc: git

Instead of asking callers to

	memset(&list, 0, sizeof(list));
	list.strdup_strings = strdup_strings;

we can take care of that ourselves, providing the flexibility
to change the details of string_list layout later if wanted.

Signed-off-by: Jonathan Nieder <jrnieder@gmail.com>
---
 string-list.c |    7 +++++++
 string-list.h |    1 +
 2 files changed, 8 insertions(+), 0 deletions(-)

diff --git a/string-list.c b/string-list.c
index 9b023a2..8e992a7 100644
--- a/string-list.c
+++ b/string-list.c
@@ -102,6 +102,13 @@ int for_each_string_list(struct string_list *list,
 	return ret;
 }
 
+void string_list_init(struct string_list *list, int strdup_strings)
+{
+	list->items = NULL;
+	list->nr = list->alloc = 0;
+	list->strdup_strings = strdup_strings ? 1 : 0;
+}
+
 void string_list_clear(struct string_list *list, int free_util)
 {
 	if (list->items) {
diff --git a/string-list.h b/string-list.h
index 4946938..07e075c 100644
--- a/string-list.h
+++ b/string-list.h
@@ -15,6 +15,7 @@ struct string_list
 #define STRING_LIST_INIT_NODUP { NULL, 0, 0, 0 }
 #define STRING_LIST_INIT_DUP   { NULL, 0, 0, 1 }
 
+void string_list_init(struct string_list *list, int strdup_strings);
 void print_string_list(const struct string_list *p, const char *text);
 void string_list_clear(struct string_list *list, int free_util);
 
-- 
1.7.2.3

^ permalink raw reply related	[flat|nested] 6+ messages in thread

* [demo/PATCH 1/3] string-list: Document STRING_LIST_INIT_* and string_list_init()
  2010-09-05 20:03 ` [demo/patch 0/3] " Jonathan Nieder
  2010-09-05 20:04   ` [demo/PATCH 1/3] string-list: introduce string_list_init() Jonathan Nieder
@ 2010-09-05 20:06   ` Jonathan Nieder
  2010-09-05 20:08   ` [demo/PATCH 3/3] Make initialization of string_lists more consistent Jonathan Nieder
  2010-09-05 23:19   ` [demo/patch 0/3] Re: [PATCH] Documentation: document the string-list macros Thiago Farina
  3 siblings, 0 replies; 6+ messages in thread
From: Jonathan Nieder @ 2010-09-05 20:06 UTC (permalink / raw)
  To: Thiago Farina; +Cc: git

Clarify the modern ways to initialize a string_list.  Text roughly
based on the analogous passage from api-strbuf.txt.

Signed-off-by: Jonathan Nieder <jrnieder@gmail.com>
---
 Documentation/technical/api-string-list.txt |   18 +++++++++++-------
 1 files changed, 11 insertions(+), 7 deletions(-)

diff --git a/Documentation/technical/api-string-list.txt b/Documentation/technical/api-string-list.txt
index 3f575bd..0f0e579 100644
--- a/Documentation/technical/api-string-list.txt
+++ b/Documentation/technical/api-string-list.txt
@@ -9,12 +9,17 @@ because it is not specific to paths.
 
 The caller:
 
-. Allocates and clears a `struct string_list` variable.
+. Allocates a `struct string_list` variable
 
-. Initializes the members. You might want to set the flag `strdup_strings`
-  if the strings should be strdup()ed. For example, this is necessary
-  when you add something like git_path("..."), since that function returns
-  a static buffer that will change with the next call to git_path().
+. Initializes the members. A string_list has to be initialized by
+  `string_list_init()` or by `= STRING_LIST_INIT_DUP` or
+  `= STRING_LIST_INIT_NODUP` before it can be used.
++
+Strings in lists initialized with the _DUP variant will be
+automatically strdup()ed on insertion and free()ed on removal.
+For example, this is necessary when you add something like
+git_path("..."), since that function returns a static buffer
+that will change with the next call to git_path().
 +
 If you need something advanced, you can manually malloc() the `items`
 member (you need this if you add things later) and you should set the
@@ -34,10 +39,9 @@ member (you need this if you add things later) and you should set the
 Example:
 
 ----
-struct string_list list;
+struct string_list list STRING_LIST_INIT_NODUP;
 int i;
 
-memset(&list, 0, sizeof(struct string_list));
 string_list_append(&list, "foo");
 string_list_append(&list, "bar");
 for (i = 0; i < list.nr; i++)
-- 
1.7.2.3

^ permalink raw reply related	[flat|nested] 6+ messages in thread

* [demo/PATCH 3/3] Make initialization of string_lists more consistent
  2010-09-05 20:03 ` [demo/patch 0/3] " Jonathan Nieder
  2010-09-05 20:04   ` [demo/PATCH 1/3] string-list: introduce string_list_init() Jonathan Nieder
  2010-09-05 20:06   ` [demo/PATCH 1/3] string-list: Document STRING_LIST_INIT_* and string_list_init() Jonathan Nieder
@ 2010-09-05 20:08   ` Jonathan Nieder
  2010-09-05 23:19   ` [demo/patch 0/3] Re: [PATCH] Documentation: document the string-list macros Thiago Farina
  3 siblings, 0 replies; 6+ messages in thread
From: Jonathan Nieder @ 2010-09-05 20:08 UTC (permalink / raw)
  To: Thiago Farina; +Cc: git

The strdup_strings member of a string_list should be constant
from when it is initialized until the string_list_clear() call,
or there can be memory leaks and double-free()ing.  Clarify
some calling conventions to ensure this.

Actually it might be even better to have a completely distinct
string_list_dup type, so the compiler could catch that kind of
error, but this patch doesn't do that.

Possible portability hazard: this casts function pointers in
weird ways.

Signed-off-by: Jonathan Nieder <jrnieder@gmail.com>
but not intended for application yet
---
 builtin/apply.c         |    8 ++++----
 builtin/blame.c         |    4 ++--
 builtin/clean.c         |    2 +-
 builtin/commit.c        |    4 ++--
 builtin/fetch.c         |   13 +++++--------
 builtin/fmt-merge-msg.c |   13 +++++++------
 builtin/log.c           |    9 +++------
 builtin/mailsplit.c     |    1 +
 builtin/notes.c         |    4 ++--
 builtin/remote.c        |   30 +++++++++++++++---------------
 builtin/shortlog.c      |   25 ++++++++++++++-----------
 diff-no-index.c         |    1 +
 mailmap.c               |   17 +++++++++++------
 mailmap.h               |    2 +-
 merge-recursive.c       |   16 +++++++++-------
 notes.c                 |    4 ++--
 pretty.c                |    5 +++--
 reflog-walk.c           |    1 +
 resolve-undo.c          |    8 ++++----
 revision.c              |    7 +++++--
 string-list.c           |   21 +++++++++++++++++----
 string-list.h           |    3 +++
 submodule.c             |    4 ++--
 wt-status.c             |    6 +++---
 24 files changed, 118 insertions(+), 90 deletions(-)

diff --git a/builtin/apply.c b/builtin/apply.c
index 23c18c5..e9f16ce 100644
--- a/builtin/apply.c
+++ b/builtin/apply.c
@@ -223,7 +223,7 @@ struct image {
  * the case where more than one patches touch the same file.
  */
 
-static struct string_list fn_table;
+static struct string_list fn_table = STRING_LIST_INIT_NODUP;
 
 static uint32_t hash_line(const char *cp, size_t len)
 {
@@ -3560,7 +3560,7 @@ static int write_out_results(struct patch *list, int skipped_patch)
 
 static struct lock_file lock_file;
 
-static struct string_list limit_by_name;
+static struct string_list limit_by_name = STRING_LIST_INIT_NODUP;
 static int has_include;
 static void add_name_limit(const char *name, int exclude)
 {
@@ -3635,8 +3635,8 @@ static int apply_patch(int fd, const char *filename, int options)
 	struct patch *list = NULL, **listp = &list;
 	int skipped_patch = 0;
 
-	/* FIXME - memory leak when using multiple patch files as inputs */
-	memset(&fn_table, 0, sizeof(struct string_list));
+	string_list_clear(&fn_table, 0);
+	string_list_init(&fn_table, 0);
 	patch_input_file = filename;
 	read_patch_file(&buf, fd);
 	offset = 0;
diff --git a/builtin/blame.c b/builtin/blame.c
index 1015354..bc89a48 100644
--- a/builtin/blame.c
+++ b/builtin/blame.c
@@ -45,7 +45,7 @@ static int xdl_opts;
 static enum date_mode blame_date_mode = DATE_ISO8601;
 static size_t blame_date_width;
 
-static struct string_list mailmap;
+static struct string_list mailmap = STRING_LIST_INIT_DUP;
 
 #ifndef DEBUG
 #define DEBUG 0
@@ -2498,7 +2498,7 @@ parse_done:
 	sb.ent = ent;
 	sb.path = path;
 
-	read_mailmap(&mailmap, NULL);
+	mailmap_read(&mailmap, NULL);
 
 	if (!incremental)
 		setup_pager();
diff --git a/builtin/clean.c b/builtin/clean.c
index b508d2c..c8798f5 100644
--- a/builtin/clean.c
+++ b/builtin/clean.c
@@ -44,7 +44,7 @@ int cmd_clean(int argc, const char **argv, const char *prefix)
 	struct dir_struct dir;
 	static const char **pathspec;
 	struct strbuf buf = STRBUF_INIT;
-	struct string_list exclude_list = { NULL, 0, 0, 0 };
+	struct string_list exclude_list = STRING_LIST_INIT_NODUP;
 	const char *qname;
 	char *seen = NULL;
 	struct option options[] = {
diff --git a/builtin/commit.c b/builtin/commit.c
index 66fdd22..ab9d974 100644
--- a/builtin/commit.c
+++ b/builtin/commit.c
@@ -205,6 +205,7 @@ static int list_paths(struct string_list *list, const char *with_tree,
 	int i;
 	char *m;
 
+	assert(list->strdup_strings);
 	for (i = 0; pattern[i]; i++)
 		;
 	m = xcalloc(1, i);
@@ -379,8 +380,7 @@ static char *prepare_index(int argc, const char **argv, const char *prefix, int
 	if (in_merge)
 		die("cannot do a partial commit during a merge.");
 
-	memset(&partial, 0, sizeof(partial));
-	partial.strdup_strings = 1;
+	string_list_init(&partial, 1);
 	if (list_paths(&partial, initial_commit ? NULL : "HEAD", prefix, pathspec))
 		exit(1);
 
diff --git a/builtin/fetch.c b/builtin/fetch.c
index fab3fce..9a1c46c 100644
--- a/builtin/fetch.c
+++ b/builtin/fetch.c
@@ -732,7 +732,7 @@ static int get_one_remote_for_fetch(struct remote *remote, void *priv)
 {
 	struct string_list *list = priv;
 	if (!remote->skip_default_update)
-		string_list_append(list, remote->name);
+		string_list_append_take_ownership(list, (char *) remote->name);
 	return 0;
 }
 
@@ -751,8 +751,8 @@ static int get_remote_group(const char *key, const char *value, void *priv)
 		int space = strcspn(value, " \t\n");
 		while (*value) {
 			if (space > 1) {
-				string_list_append(g->list,
-						   xstrndup(value, space));
+				string_list_append_take_ownership(
+					g->list, xstrndup(value, space));
 			}
 			value += space + (value[space] != '\0');
 			space = strcspn(value, " \t\n");
@@ -774,7 +774,7 @@ static int add_remote_or_group(const char *name, struct string_list *list)
 		if (!remote_is_configured(name))
 			return 0;
 		remote = remote_get(name);
-		string_list_append(list, remote->name);
+		string_list_append_take_ownership(list, (char *) remote->name);
 	}
 	return 1;
 }
@@ -877,7 +877,7 @@ static int fetch_one(struct remote *remote, int argc, const char **argv)
 int cmd_fetch(int argc, const char **argv, const char *prefix)
 {
 	int i;
-	struct string_list list = STRING_LIST_INIT_NODUP;
+	struct string_list list = STRING_LIST_INIT_DUP;
 	struct remote *remote;
 	int result = 0;
 
@@ -921,9 +921,6 @@ int cmd_fetch(int argc, const char **argv, const char *prefix)
 		}
 	}
 
-	/* All names were strdup()ed or strndup()ed */
-	list.strdup_strings = 1;
 	string_list_clear(&list, 0);
-
 	return result;
 }
diff --git a/builtin/fmt-merge-msg.c b/builtin/fmt-merge-msg.c
index e7e12ee..621c074 100644
--- a/builtin/fmt-merge-msg.c
+++ b/builtin/fmt-merge-msg.c
@@ -30,12 +30,13 @@ struct src_data {
 	int head_status;
 };
 
-void init_src_data(struct src_data *data)
+static void init_src_data(struct src_data *data)
 {
-	data->branch.strdup_strings = 1;
-	data->tag.strdup_strings = 1;
-	data->r_branch.strdup_strings = 1;
-	data->generic.strdup_strings = 1;
+	string_list_init(&data->branch, 1);
+	string_list_init(&data->tag, 1);
+	string_list_init(&data->r_branch, 1);
+	string_list_init(&data->generic, 1);
+	data->head_status = 0;
 }
 
 static struct string_list srcs = STRING_LIST_INIT_DUP;
@@ -83,7 +84,7 @@ static int handle_line(char *line)
 	item = unsorted_string_list_lookup(&srcs, src);
 	if (!item) {
 		item = string_list_append(&srcs, src);
-		item->util = xcalloc(1, sizeof(struct src_data));
+		item->util = xmalloc(sizeof(struct src_data));
 		init_src_data(item->util);
 	}
 	src_data = item->util;
diff --git a/builtin/log.c b/builtin/log.c
index eaa1ee0..7e8f0e2 100644
--- a/builtin/log.c
+++ b/builtin/log.c
@@ -521,9 +521,9 @@ static int auto_number = 1;
 
 static char *default_attach = NULL;
 
-static struct string_list extra_hdr;
-static struct string_list extra_to;
-static struct string_list extra_cc;
+static struct string_list extra_hdr = STRING_LIST_INIT_DUP;
+static struct string_list extra_to = STRING_LIST_INIT_DUP;
+static struct string_list extra_cc = STRING_LIST_INIT_DUP;
 
 static void add_header(const char *value)
 {
@@ -1048,9 +1048,6 @@ int cmd_format_patch(int argc, const char **argv, const char *prefix)
 		OPT_END()
 	};
 
-	extra_hdr.strdup_strings = 1;
-	extra_to.strdup_strings = 1;
-	extra_cc.strdup_strings = 1;
 	git_config(git_format_config, NULL);
 	init_revisions(&rev, prefix);
 	rev.commit_format = CMIT_FMT_EMAIL;
diff --git a/builtin/mailsplit.c b/builtin/mailsplit.c
index 99654d0..17f247b 100644
--- a/builtin/mailsplit.c
+++ b/builtin/mailsplit.c
@@ -108,6 +108,7 @@ static int populate_maildir_list(struct string_list *list, const char *path)
 	char *subs[] = { "cur", "new", NULL };
 	char **sub;
 
+	assert(list->strdup_strings);
 	for (sub = subs; *sub; ++sub) {
 		snprintf(name, sizeof(name), "%s/%s", path, *sub);
 		if ((dir = opendir(name)) == NULL) {
diff --git a/builtin/notes.c b/builtin/notes.c
index fbc347c..35e139f 100644
--- a/builtin/notes.c
+++ b/builtin/notes.c
@@ -363,8 +363,8 @@ struct notes_rewrite_cfg *init_copy_notes_for_rewrite(const char *cmd)
 	c->cmd = cmd;
 	c->enabled = 1;
 	c->combine = combine_notes_concatenate;
-	c->refs = xcalloc(1, sizeof(struct string_list));
-	c->refs->strdup_strings = 1;
+	c->refs = xmalloc(sizeof(struct string_list));
+	string_list_init(c->refs, 1);
 	c->refs_from_env = 0;
 	c->mode_from_env = 0;
 	if (rewrite_mode_env) {
diff --git a/builtin/remote.c b/builtin/remote.c
index 48e0a6b..9ab36ed 100644
--- a/builtin/remote.c
+++ b/builtin/remote.c
@@ -230,7 +230,7 @@ struct branch_info {
 	int rebase;
 };
 
-static struct string_list branch_list;
+static struct string_list branch_list = STRING_LIST_INIT_NODUP;
 
 static const char *abbrev_ref(const char *name, const char *prefix)
 {
@@ -302,6 +302,10 @@ struct ref_states {
 	int queried;
 };
 
+#define REF_STATES_INIT { NULL, \
+	STRING_LIST_INIT_DUP, STRING_LIST_INIT_DUP, STRING_LIST_INIT_DUP, STRING_LIST_INIT_DUP, \
+	STRING_LIST_INIT_DUP, 0 }
+
 static int get_ref_states(const struct ref *remote_refs, struct ref_states *states)
 {
 	struct ref *fetch_map = NULL, **tail = &fetch_map;
@@ -313,9 +317,9 @@ static int get_ref_states(const struct ref *remote_refs, struct ref_states *stat
 			die("Could not get fetch map for refspec %s",
 				states->remote->fetch_refspec[i]);
 
-	states->new.strdup_strings = 1;
-	states->tracked.strdup_strings = 1;
-	states->stale.strdup_strings = 1;
+	assert(states->new.strdup_strings);
+	assert(states->tracked.strdup_strings);
+	assert(states->stale.strdup_strings);
 	for (ref = fetch_map; ref; ref = ref->next) {
 		unsigned char sha1[20];
 		if (!ref->peer_ref || read_ref(ref->peer_ref->name, sha1))
@@ -366,7 +370,7 @@ static int get_push_ref_states(const struct ref *remote_refs,
 	match_refs(local_refs, &push_map, remote->push_refspec_nr,
 		   remote->push_refspec, MATCH_REFS_NONE);
 
-	states->push.strdup_strings = 1;
+	assert(states->push.strdup_strings);
 	for (ref = push_map; ref; ref = ref->next) {
 		struct string_list_item *item;
 		struct push_info *info;
@@ -409,7 +413,7 @@ static int get_push_ref_states_noquery(struct ref_states *states)
 	if (remote->mirror)
 		return 0;
 
-	states->push.strdup_strings = 1;
+	assert(states->push.strdup_strings);
 	if (!remote->push_refspec_nr) {
 		item = string_list_append(&states->push, "(matching)");
 		info = item->util = xcalloc(sizeof(struct push_info), 1);
@@ -442,7 +446,7 @@ static int get_head_names(const struct ref *remote_refs, struct ref_states *stat
 	refspec.force = 0;
 	refspec.pattern = 1;
 	refspec.src = refspec.dst = "refs/heads/*";
-	states->heads.strdup_strings = 1;
+	assert(states->heads.strdup_strings);
 	get_fetch_map(remote_refs, &refspec, &fetch_map_tail, 0);
 	matches = guess_remote_head(find_ref_by_name(remote_refs, "HEAD"),
 				    fetch_map, 1);
@@ -1043,7 +1047,7 @@ static int show(int argc, const char **argv)
 		OPT_BOOLEAN('n', NULL, &no_query, "do not query remotes"),
 		OPT_END()
 	};
-	struct ref_states states;
+	struct ref_states states = REF_STATES_INIT;
 	struct string_list info_list = STRING_LIST_INIT_NODUP;
 	struct show_info info;
 
@@ -1056,7 +1060,6 @@ static int show(int argc, const char **argv)
 	if (!no_query)
 		query_flag = (GET_REF_STATES | GET_HEAD_NAMES | GET_PUSH_REF_STATES);
 
-	memset(&states, 0, sizeof(states));
 	memset(&info, 0, sizeof(info));
 	info.states = &states;
 	info.list = &info_list;
@@ -1158,8 +1161,7 @@ static int set_head(int argc, const char **argv)
 	if (!opt_a && !opt_d && argc == 2) {
 		head_name = xstrdup(argv[1]);
 	} else if (opt_a && !opt_d && argc == 1) {
-		struct ref_states states;
-		memset(&states, 0, sizeof(states));
+		struct ref_states states = REF_STATES_INIT;
 		get_remote_ref_states(argv[0], &states, GET_HEAD_NAMES);
 		if (!states.heads.nr)
 			result |= error("Cannot determine remote HEAD");
@@ -1219,12 +1221,11 @@ static int prune(int argc, const char **argv)
 static int prune_remote(const char *remote, int dry_run)
 {
 	int result = 0, i;
-	struct ref_states states;
+	struct ref_states states = REF_STATES_INIT;
 	const char *dangling_msg = dry_run
 		? " %s will become dangling!\n"
 		: " %s has become dangling!\n";
 
-	memset(&states, 0, sizeof(states));
 	get_remote_ref_states(remote, &states, GET_REF_STATES);
 
 	if (states.stale.nr) {
@@ -1483,10 +1484,9 @@ static int get_one_entry(struct remote *remote, void *priv)
 
 static int show_all(void)
 {
-	struct string_list list = STRING_LIST_INIT_NODUP;
+	struct string_list list = STRING_LIST_INIT_DUP;
 	int result;
 
-	list.strdup_strings = 1;
 	result = for_each_remote(get_one_entry, &list);
 
 	if (!result) {
diff --git a/builtin/shortlog.c b/builtin/shortlog.c
index 2135b0d..5843c0a 100644
--- a/builtin/shortlog.c
+++ b/builtin/shortlog.c
@@ -16,9 +16,9 @@ static char const * const shortlog_usage[] = {
 	NULL
 };
 
-static int compare_by_number(const void *a1, const void *a2)
+static int compare_by_number(const struct string_list_item *i1,
+			     const struct string_list_item *i2)
 {
-	const struct string_list_item *i1 = a1, *i2 = a2;
 	const struct string_list *l1 = i1->util, *l2 = i2->util;
 
 	if (l1->nr < l2->nr)
@@ -84,9 +84,12 @@ static void insert_one_record(struct shortlog *log,
 		snprintf(namebuf + len, room, " <%.*s>", maillen, emailbuf);
 	}
 
+	assert(log->list.strdup_strings);
 	item = string_list_insert(&log->list, namebuf);
-	if (item->util == NULL)
-		item->util = xcalloc(1, sizeof(struct string_list));
+	if (!item->util) {
+		item->util = xmalloc(sizeof(struct string_list));
+		string_list_init(item->util, 1);
+	}
 
 	/* Skip any leading whitespace, including any blank lines. */
 	while (*oneline && isspace(*oneline))
@@ -115,7 +118,7 @@ static void insert_one_record(struct shortlog *log,
 		}
 	}
 
-	string_list_append(item->util, buffer);
+	string_list_append_take_ownership(item->util, buffer);
 }
 
 static void read_from_stdin(struct shortlog *log)
@@ -236,10 +239,11 @@ static int parse_wrap_args(const struct option *opt, const char *arg, int unset)
 void shortlog_init(struct shortlog *log)
 {
 	memset(log, 0, sizeof(*log));
+	string_list_init(&log->list, 1);
+	string_list_init(&log->mailmap, 1);
 
-	read_mailmap(&log->mailmap, &log->common_repo_prefix);
+	mailmap_read(&log->mailmap, &log->common_repo_prefix);
 
-	log->list.strdup_strings = 1;
 	log->wrap = DEFAULT_WRAPLEN;
 	log->in1 = DEFAULT_INDENT1;
 	log->in2 = DEFAULT_INDENT2;
@@ -320,8 +324,7 @@ void shortlog_output(struct shortlog *log)
 	struct strbuf sb = STRBUF_INIT;
 
 	if (log->sort_by_number)
-		qsort(log->list.items, log->list.nr, sizeof(struct string_list_item),
-			compare_by_number);
+		sort_string_list_by(&log->list, compare_by_number);
 	for (i = 0; i < log->list.nr; i++) {
 		struct string_list *onelines = log->list.items[i].util;
 
@@ -343,14 +346,14 @@ void shortlog_output(struct shortlog *log)
 			putchar('\n');
 		}
 
-		onelines->strdup_strings = 1;
+		assert(onelines->strdup_strings);
 		string_list_clear(onelines, 0);
 		free(onelines);
 		log->list.items[i].util = NULL;
 	}
 
 	strbuf_release(&sb);
-	log->list.strdup_strings = 1;
+	assert(log->list.strdup_strings);
 	string_list_clear(&log->list, 1);
 	clear_mailmap(&log->mailmap);
 }
diff --git a/diff-no-index.c b/diff-no-index.c
index ce9e783..68da01a 100644
--- a/diff-no-index.c
+++ b/diff-no-index.c
@@ -24,6 +24,7 @@ static int read_directory(const char *path, struct string_list *list)
 	if (!(dir = opendir(path)))
 		return error("Could not open directory %s", path);
 
+	assert(list->strdup_strings);
 	while ((e = readdir(dir)))
 		if (strcmp(".", e->d_name) && strcmp("..", e->d_name))
 			string_list_insert(list, e->d_name);
diff --git a/mailmap.c b/mailmap.c
index f80b701..b7f2796 100644
--- a/mailmap.c
+++ b/mailmap.c
@@ -33,6 +33,12 @@ static void free_mailmap_info(void *p, const char *s)
 	free(mi->email);
 }
 
+static void init_mailmap_entry(struct mailmap_entry *p)
+{
+	p->name = p->email = NULL;
+	string_list_init(&p->namemap, 1);
+}
+
 static void free_mailmap_entry(void *p, const char *s)
 {
 	struct mailmap_entry *me = (struct mailmap_entry *)p;
@@ -41,7 +47,7 @@ static void free_mailmap_entry(void *p, const char *s)
 	free(me->name);
 	free(me->email);
 
-	me->namemap.strdup_strings = 1;
+	assert(me->namemap.strdup_strings);
 	string_list_clear_func(&me->namemap, free_mailmap_info);
 }
 
@@ -71,8 +77,7 @@ static void add_mapping(struct string_list *map,
 		/* create mailmap entry */
 		struct string_list_item *item = string_list_insert_at_index(map, index, old_email);
 		item->util = xmalloc(sizeof(struct mailmap_entry));
-		memset(item->util, 0, sizeof(struct mailmap_entry));
-		((struct mailmap_entry *)item->util)->namemap.strdup_strings = 1;
+		init_mailmap_entry((struct mailmap_entry *)item->util);
 	}
 	me = (struct mailmap_entry *)map->items[index].util;
 
@@ -170,9 +175,9 @@ static int read_single_mailmap(struct string_list *map, const char *filename, ch
 	return 0;
 }
 
-int read_mailmap(struct string_list *map, char **repo_abbrev)
+int mailmap_read(struct string_list *map, char **repo_abbrev)
 {
-	map->strdup_strings = 1;
+	assert(map->strdup_strings);
 	/* each failure returns 1, so >1 means both calls failed */
 	return read_single_mailmap(map, ".mailmap", repo_abbrev) +
 	       read_single_mailmap(map, git_mailmap_file, repo_abbrev) > 1;
@@ -181,7 +186,7 @@ int read_mailmap(struct string_list *map, char **repo_abbrev)
 void clear_mailmap(struct string_list *map)
 {
 	debug_mm("mailmap: clearing %d entries...\n", map->nr);
-	map->strdup_strings = 1;
+	assert(map->strdup_strings);
 	string_list_clear_func(map, free_mailmap_entry);
 	debug_mm("mailmap: cleared\n");
 }
diff --git a/mailmap.h b/mailmap.h
index d5c3664..f0b3861 100644
--- a/mailmap.h
+++ b/mailmap.h
@@ -1,7 +1,7 @@
 #ifndef MAILMAP_H
 #define MAILMAP_H
 
-int read_mailmap(struct string_list *map, char **repo_abbrev);
+int mailmap_read(struct string_list *map, char **repo_abbrev);
 void clear_mailmap(struct string_list *map);
 
 int map_user(struct string_list *mailmap,
diff --git a/merge-recursive.c b/merge-recursive.c
index 20e1779..7a44e25 100644
--- a/merge-recursive.c
+++ b/merge-recursive.c
@@ -232,6 +232,9 @@ static int save_files_dirs(const unsigned char *sha1,
 	memcpy(newpath + baselen, path, len);
 	newpath[baselen + len] = '\0';
 
+	assert(o->current_directory_set.strdup_strings);
+	assert(o->current_file_set.strdup_strings);
+
 	if (S_ISDIR(mode))
 		string_list_insert(&o->current_directory_set, newpath);
 	else
@@ -277,10 +280,10 @@ static struct stage_data *insert_stage_data(const char *path,
  */
 static struct string_list *get_unmerged(void)
 {
-	struct string_list *unmerged = xcalloc(1, sizeof(struct string_list));
+	struct string_list *unmerged = xmalloc(sizeof(struct string_list));
 	int i;
 
-	unmerged->strdup_strings = 1;
+	string_list_init(unmerged, 1);
 
 	for (i = 0; i < active_nr; i++) {
 		struct string_list_item *item;
@@ -327,7 +330,8 @@ static struct string_list *get_renames(struct merge_options *o,
 	struct string_list *renames;
 	struct diff_options opts;
 
-	renames = xcalloc(1, sizeof(struct string_list));
+	renames = xmalloc(sizeof(struct string_list));
+	string_list_init(renames, 0);
 	diff_setup(&opts);
 	DIFF_OPT_SET(&opts, RECURSIVE);
 	opts.detect_rename = DIFF_DETECT_RENAME;
@@ -1539,8 +1543,6 @@ void init_merge_options(struct merge_options *o)
 	if (o->verbosity >= 5)
 		o->buffer_output = 0;
 	strbuf_init(&o->obuf, 0);
-	memset(&o->current_file_set, 0, sizeof(struct string_list));
-	o->current_file_set.strdup_strings = 1;
-	memset(&o->current_directory_set, 0, sizeof(struct string_list));
-	o->current_directory_set.strdup_strings = 1;
+	string_list_init(&o->current_file_set, 1);
+	string_list_init(&o->current_directory_set, 1);
 }
diff --git a/notes.c b/notes.c
index 7fd2035..2ab0bb1 100644
--- a/notes.c
+++ b/notes.c
@@ -70,7 +70,7 @@ struct non_note {
 
 struct notes_tree default_notes_tree;
 
-static struct string_list display_notes_refs;
+static struct string_list display_notes_refs = STRING_LIST_INIT_DUP;
 static struct notes_tree **display_notes_trees;
 
 static void load_subtree(struct notes_tree *t, struct leaf_node *subtree,
@@ -958,8 +958,8 @@ void init_display_notes(struct display_notes_opt *opt)
 {
 	char *display_ref_env;
 	int load_config_refs = 0;
-	display_notes_refs.strdup_strings = 1;
 
+	assert(display_notes_refs.strdup_strings);
 	assert(!display_notes_trees);
 
 	if (!opt || !opt->suppress_default_notes) {
diff --git a/pretty.c b/pretty.c
index f85444b..89b37eb 100644
--- a/pretty.c
+++ b/pretty.c
@@ -434,8 +434,9 @@ static int mailmap_name(char *email, int email_len, char *name, int name_len)
 {
 	static struct string_list *mail_map;
 	if (!mail_map) {
-		mail_map = xcalloc(1, sizeof(*mail_map));
-		read_mailmap(mail_map, NULL);
+		mail_map = xmalloc(sizeof(*mail_map));
+		string_list_init(mail_map, 1);
+		mailmap_read(mail_map, NULL);
 	}
 	return mail_map->nr && map_user(mail_map, email, email_len, name, name_len);
 }
diff --git a/reflog-walk.c b/reflog-walk.c
index 4879615..a2ccdea 100644
--- a/reflog-walk.c
+++ b/reflog-walk.c
@@ -135,6 +135,7 @@ struct reflog_walk_info {
 void init_reflog_walk(struct reflog_walk_info** info)
 {
 	*info = xcalloc(sizeof(struct reflog_walk_info), 1);
+	string_list_init(&(*info)->complete_reflogs, 0);
 }
 
 int add_reflog_for_walk(struct reflog_walk_info *info,
diff --git a/resolve-undo.c b/resolve-undo.c
index 72b4612..6ba8538 100644
--- a/resolve-undo.c
+++ b/resolve-undo.c
@@ -15,8 +15,8 @@ void record_resolve_undo(struct index_state *istate, struct cache_entry *ce)
 		return;
 
 	if (!istate->resolve_undo) {
-		resolve_undo = xcalloc(1, sizeof(*resolve_undo));
-		resolve_undo->strdup_strings = 1;
+		resolve_undo = xmalloc(sizeof(*resolve_undo));
+		string_list_init(resolve_undo, 1);
 		istate->resolve_undo = resolve_undo;
 	}
 	resolve_undo = istate->resolve_undo;
@@ -56,8 +56,8 @@ struct string_list *resolve_undo_read(const char *data, unsigned long size)
 	char *endptr;
 	int i;
 
-	resolve_undo = xcalloc(1, sizeof(*resolve_undo));
-	resolve_undo->strdup_strings = 1;
+	resolve_undo = xmalloc(sizeof(*resolve_undo));
+	string_list_init(resolve_undo, 1);
 
 	while (size) {
 		struct string_list_item *lost;
diff --git a/revision.c b/revision.c
index b1c1890..e18522c 100644
--- a/revision.c
+++ b/revision.c
@@ -1319,8 +1319,10 @@ static int handle_revision_opt(struct rev_info *revs, int argc, const char **arg
 		struct strbuf buf = STRBUF_INIT;
 		revs->show_notes = 1;
 		revs->show_notes_given = 1;
-		if (!revs->notes_opt.extra_notes_refs)
-			revs->notes_opt.extra_notes_refs = xcalloc(1, sizeof(struct string_list));
+		if (!revs->notes_opt.extra_notes_refs) {
+			revs->notes_opt.extra_notes_refs = xmalloc(sizeof(struct string_list));
+			string_list_init(revs->notes_opt.extra_notes_refs, 0);
+		}
 		if (!prefixcmp(arg+13, "refs/"))
 			/* happy */;
 		else if (!prefixcmp(arg+13, "notes/"))
@@ -1328,6 +1330,7 @@ static int handle_revision_opt(struct rev_info *revs, int argc, const char **arg
 		else
 			strbuf_addstr(&buf, "refs/notes/");
 		strbuf_addstr(&buf, arg+13);
+		/* NEEDSWORK: leak. */
 		string_list_append(revs->notes_opt.extra_notes_refs,
 				   strbuf_detach(&buf, NULL));
 	} else if (!strcmp(arg, "--no-notes")) {
diff --git a/string-list.c b/string-list.c
index 8e992a7..9684819 100644
--- a/string-list.c
+++ b/string-list.c
@@ -163,16 +163,29 @@ struct string_list_item *string_list_append(struct string_list *list, const char
 	return list->items + list->nr++;
 }
 
-static int cmp_items(const void *a, const void *b)
+struct string_list_item *string_list_append_take_ownership(struct string_list *list, char *string)
+{
+	assert(list->strdup_strings);
+	ALLOC_GROW(list->items, list->nr + 1, list->alloc);
+	list->items[list->nr].string = string;
+	return list->items + list->nr++;
+}
+
+
+static int cmp_items(const struct string_list_item *one, const struct string_list_item *two)
 {
-	const struct string_list_item *one = a;
-	const struct string_list_item *two = b;
 	return strcmp(one->string, two->string);
 }
 
 void sort_string_list(struct string_list *list)
 {
-	qsort(list->items, list->nr, sizeof(*list->items), cmp_items);
+	sort_string_list_by(list, cmp_items);
+}
+
+void sort_string_list_by(struct string_list *list, string_list_compare_func compare)
+{
+	qsort(list->items, list->nr, sizeof(*list->items),
+				(int(*)(const void *, const void *)) compare);
 }
 
 struct string_list_item *unsorted_string_list_lookup(struct string_list *list,
diff --git a/string-list.h b/string-list.h
index 07e075c..d14f3e0 100644
--- a/string-list.h
+++ b/string-list.h
@@ -42,7 +42,10 @@ struct string_list_item *string_list_lookup(struct string_list *list, const char
 
 /* Use these functions only on unsorted lists: */
 struct string_list_item *string_list_append(struct string_list *list, const char *string);
+struct string_list_item *string_list_append_take_ownership(struct string_list *list, char *string);
 void sort_string_list(struct string_list *list);
+typedef int (*string_list_compare_func)(const struct string_list_item *a, const struct string_list_item *b);
+void sort_string_list_by(struct string_list *list, string_list_compare_func compare);
 int unsorted_string_list_has_string(struct string_list *list, const char *string);
 struct string_list_item *unsorted_string_list_lookup(struct string_list *list,
 						     const char *string);
diff --git a/submodule.c b/submodule.c
index 91a4758..1c7ab8c 100644
--- a/submodule.c
+++ b/submodule.c
@@ -9,8 +9,8 @@
 #include "refs.h"
 #include "string-list.h"
 
-struct string_list config_name_for_path;
-struct string_list config_ignore_for_name;
+struct string_list config_name_for_path = STRING_LIST_INIT_NODUP;
+struct string_list config_ignore_for_name = STRING_LIST_INIT_NODUP;
 
 static int add_submodule_odb(const char *path)
 {
diff --git a/wt-status.c b/wt-status.c
index 54b6b03..0e137b8 100644
--- a/wt-status.c
+++ b/wt-status.c
@@ -44,9 +44,9 @@ void wt_status_prepare(struct wt_status *s)
 	s->reference = "HEAD";
 	s->fp = stdout;
 	s->index_file = get_index_file();
-	s->change.strdup_strings = 1;
-	s->untracked.strdup_strings = 1;
-	s->ignored.strdup_strings = 1;
+	string_list_init(&s->change, 1);
+	string_list_init(&s->untracked, 1);
+	string_list_init(&s->ignored, 1);
 }
 
 static void wt_status_print_unmerged_header(struct wt_status *s)
-- 
1.7.2.3

^ permalink raw reply related	[flat|nested] 6+ messages in thread

* Re: [demo/patch 0/3] Re: [PATCH] Documentation: document the string-list macros.
  2010-09-05 20:03 ` [demo/patch 0/3] " Jonathan Nieder
                     ` (2 preceding siblings ...)
  2010-09-05 20:08   ` [demo/PATCH 3/3] Make initialization of string_lists more consistent Jonathan Nieder
@ 2010-09-05 23:19   ` Thiago Farina
  3 siblings, 0 replies; 6+ messages in thread
From: Thiago Farina @ 2010-09-05 23:19 UTC (permalink / raw)
  To: Jonathan Nieder; +Cc: git

On Sun, Sep 5, 2010 at 5:03 PM, Jonathan Nieder <jrnieder@gmail.com> wrote:
> Thiago Farina wrote:
>
>> --- a/Documentation/technical/api-string-list.txt
>> +++ b/Documentation/technical/api-string-list.txt
>> @@ -52,6 +52,18 @@ However, if you use the list to check if a certain string was added
>>  already, you should not do that (using unsorted_string_list_has_string()),
>>  because the complexity would be quadratic again (but with a worse factor).
>>
>> +Macros
>> +------
>> +
>> +`STRING_LIST_INIT_NODUP`::
>> +
>> +     Initialize the members and set the `strdup_strings` member to 0.
>> +
>> +`STRING_LIST_INIT_DUP`::
>> +
>> +     Initialize the members and set the `strdup_strings` member to 1.
>
> After reading that, one might be tempted to write
>
>        struct string_list x;
>        STRING_LIST_INIT_NODUP(x);
>
> , no?  In other words, I don't find the text very clear.
>
Yeah, you are right.

> If you like working by example (like I do) then api-strbuf.txt might
> give a good indication of how this sort of thing can be helpfully
> documented.
>
I have looked into it :-)

> Maybe something in this direction?
>
> Patch #3 in particular is very rough
Oh yeah :)

>  This is not meant for application, just to give an
> idea.
>
I like the idea. I will improve the Documentation based on or version.

Thanks.

^ permalink raw reply	[flat|nested] 6+ messages in thread

end of thread, other threads:[~2010-09-05 23:19 UTC | newest]

Thread overview: 6+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2010-09-05 17:51 [PATCH] Documentation: document the string-list macros Thiago Farina
2010-09-05 20:03 ` [demo/patch 0/3] " Jonathan Nieder
2010-09-05 20:04   ` [demo/PATCH 1/3] string-list: introduce string_list_init() Jonathan Nieder
2010-09-05 20:06   ` [demo/PATCH 1/3] string-list: Document STRING_LIST_INIT_* and string_list_init() Jonathan Nieder
2010-09-05 20:08   ` [demo/PATCH 3/3] Make initialization of string_lists more consistent Jonathan Nieder
2010-09-05 23:19   ` [demo/patch 0/3] Re: [PATCH] Documentation: document the string-list macros Thiago Farina

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).