1 | // SPDX-License-Identifier: GPL-2.0 |
2 | /* |
3 | * Copyright (C) 2002-2005 Roman Zippel <zippel@linux-m68k.org> |
4 | * Copyright (C) 2002-2005 Sam Ravnborg <sam@ravnborg.org> |
5 | */ |
6 | |
7 | #include <stdarg.h> |
8 | #include <stdlib.h> |
9 | #include <string.h> |
10 | |
11 | #include "hashtable.h" |
12 | #include "lkc.h" |
13 | |
14 | unsigned int strhash(const char *s) |
15 | { |
16 | /* fnv32 hash */ |
17 | unsigned int hash = 2166136261U; |
18 | |
19 | for (; *s; s++) |
20 | hash = (hash ^ *s) * 0x01000193; |
21 | return hash; |
22 | } |
23 | |
24 | /* hash table of all parsed Kconfig files */ |
25 | static HASHTABLE_DEFINE(file_hashtable, 1U << 11); |
26 | |
27 | struct file { |
28 | struct hlist_node node; |
29 | char name[]; |
30 | }; |
31 | |
32 | /* file already present in list? If not add it */ |
33 | const char *file_lookup(const char *name) |
34 | { |
35 | struct file *file; |
36 | size_t len; |
37 | int hash = strhash(s: name); |
38 | |
39 | hash_for_each_possible(file_hashtable, file, node, hash) |
40 | if (!strcmp(s1: name, s2: file->name)) |
41 | return file->name; |
42 | |
43 | len = strlen(s: name); |
44 | file = xmalloc(size: sizeof(*file) + len + 1); |
45 | memset(s: file, c: 0, n: sizeof(*file)); |
46 | memcpy(dest: file->name, src: name, n: len); |
47 | file->name[len] = '\0'; |
48 | |
49 | hash_add(file_hashtable, &file->node, hash); |
50 | |
51 | str_printf(gs: &autoconf_cmd, fmt: "\t%s \\\n" , name); |
52 | |
53 | return file->name; |
54 | } |
55 | |
56 | /* Allocate initial growable string */ |
57 | struct gstr str_new(void) |
58 | { |
59 | struct gstr gs; |
60 | gs.s = xmalloc(size: sizeof(char) * 64); |
61 | gs.len = 64; |
62 | gs.max_width = 0; |
63 | strcpy(dest: gs.s, src: "\0" ); |
64 | return gs; |
65 | } |
66 | |
67 | /* Free storage for growable string */ |
68 | void str_free(struct gstr *gs) |
69 | { |
70 | free(ptr: gs->s); |
71 | gs->s = NULL; |
72 | gs->len = 0; |
73 | } |
74 | |
75 | /* Append to growable string */ |
76 | void str_append(struct gstr *gs, const char *s) |
77 | { |
78 | size_t l; |
79 | if (s) { |
80 | l = strlen(s: gs->s) + strlen(s: s) + 1; |
81 | if (l > gs->len) { |
82 | gs->s = xrealloc(p: gs->s, size: l); |
83 | gs->len = l; |
84 | } |
85 | strcat(dest: gs->s, src: s); |
86 | } |
87 | } |
88 | |
89 | /* Append printf formatted string to growable string */ |
90 | void str_printf(struct gstr *gs, const char *fmt, ...) |
91 | { |
92 | va_list ap; |
93 | char s[10000]; /* big enough... */ |
94 | va_start(ap, fmt); |
95 | vsnprintf(s: s, maxlen: sizeof(s), format: fmt, arg: ap); |
96 | str_append(gs, s); |
97 | va_end(ap); |
98 | } |
99 | |
100 | /* Retrieve value of growable string */ |
101 | char *str_get(struct gstr *gs) |
102 | { |
103 | return gs->s; |
104 | } |
105 | |
106 | void *xmalloc(size_t size) |
107 | { |
108 | void *p = malloc(size: size); |
109 | if (p) |
110 | return p; |
111 | fprintf(stderr, format: "Out of memory.\n" ); |
112 | exit(status: 1); |
113 | } |
114 | |
115 | void *xcalloc(size_t nmemb, size_t size) |
116 | { |
117 | void *p = calloc(nmemb: nmemb, size: size); |
118 | if (p) |
119 | return p; |
120 | fprintf(stderr, format: "Out of memory.\n" ); |
121 | exit(status: 1); |
122 | } |
123 | |
124 | void *xrealloc(void *p, size_t size) |
125 | { |
126 | p = realloc(ptr: p, size: size); |
127 | if (p) |
128 | return p; |
129 | fprintf(stderr, format: "Out of memory.\n" ); |
130 | exit(status: 1); |
131 | } |
132 | |
133 | char *xstrdup(const char *s) |
134 | { |
135 | char *p; |
136 | |
137 | p = strdup(s: s); |
138 | if (p) |
139 | return p; |
140 | fprintf(stderr, format: "Out of memory.\n" ); |
141 | exit(status: 1); |
142 | } |
143 | |
144 | char *xstrndup(const char *s, size_t n) |
145 | { |
146 | char *p; |
147 | |
148 | p = strndup(string: s, n: n); |
149 | if (p) |
150 | return p; |
151 | fprintf(stderr, format: "Out of memory.\n" ); |
152 | exit(status: 1); |
153 | } |
154 | |