Added a description for my extensions (README-my-extensions.html).
[parsecvs/imz-RCS2git-use-cases.git] / tags.c
blobbbc6e95af959966ecd6d50345bfd43c2c52a25a3
1 #include <stdint.h>
2 #include <stdlib.h>
3 #include <stdio.h>
4 #include "cvs.h"
6 static Tag *table[4096];
8 Tag *all_tags;
10 static int tag_hash(char *name)
12 uintptr_t l = (uintptr_t)name;
13 int res = 0;
14 while (l) {
15 res ^= l;
16 l >>= 12;
18 return res & 4095;
21 static Tag *find_tag(char *name)
23 int hash = tag_hash(name);
24 Tag *tag;
25 for (tag = table[hash]; tag; tag = tag->hash_next)
26 if (tag->name == name)
27 return tag;
28 tag = calloc(1, sizeof(Tag));
29 tag->name = name;
30 tag->hash_next = table[hash];
31 table[hash] = tag;
32 tag->next = all_tags;
33 all_tags = tag;
34 return tag;
37 /* the last argument is a sham */
38 void tag_commit(rev_commit *c, char *name)
40 Tag *tag = find_tag(name);
41 if (tag->last == this_file->name) {
42 fprintf(stderr, "duplicate tag %s in %s, ignoring\n",
43 name, this_file->name);
44 return;
46 tag->last = this_file->name;
47 if (!tag->left) {
48 Chunk *v = malloc(sizeof(Chunk));
49 v->next = tag->commits;
50 tag->commits = v;
51 tag->left = Ncommits;
53 tag->commits->v[--tag->left] = c;
54 tag->count++;
57 rev_commit **tagged(Tag *tag)
59 rev_commit **v = NULL;
61 if (tag->count) {
62 rev_commit **p = malloc(tag->count * sizeof(*p));
63 Chunk *c = tag->commits;
64 int n = Ncommits - tag->left;
66 v = p;
67 memcpy(p, c->v + tag->left, n * sizeof(*p));
69 for (c = c->next, p += n; c; c = c->next, p += Ncommits)
70 memcpy(p, c->v, Ncommits * sizeof(*p));
72 return v;
75 void discard_tags(void)
77 Tag *tag = all_tags;
78 all_tags = NULL;
79 while (tag) {
80 Tag *p = tag->next;
81 Chunk *c = tag->commits;
82 while (c) {
83 Chunk *next = c->next;
84 free(c);
85 c = next;
87 free(tag);
88 tag = p;