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 <hash.h> 12 #include <hashtable.h> 13 #include <xalloc.h> 14 #include "lkc.h" 15 16 /* hash table of all parsed Kconfig files */ 17 static HASHTABLE_DEFINE(file_hashtable, 1U << 11); 18 19 struct file { 20 struct hlist_node node; 21 struct { 22 const char *name; 23 int lineno; 24 } parent; 25 char name[]; 26 }; 27 28 static void die_duplicated_include(struct file *file, 29 const char *parent, int lineno) 30 { 31 fprintf(stderr, 32 "%s:%d: error: repeated inclusion of %s\n" 33 "%s:%d: note: location of first inclusion of %s\n", 34 parent, lineno, file->name, 35 file->parent.name, file->parent.lineno, file->name); 36 exit(1); 37 } 38 39 /* file already present in list? If not add it */ 40 const char *file_lookup(const char *name, 41 const char *parent_name, int parent_lineno) 42 { 43 const char *parent = NULL; 44 struct file *file; 45 size_t len; 46 int hash = hash_str(name); 47 48 if (parent_name) 49 parent = file_lookup(parent_name, NULL, 0); 50 51 hash_for_each_possible(file_hashtable, file, node, hash) 52 if (!strcmp(name, file->name)) { 53 if (!parent_name) 54 return file->name; 55 die_duplicated_include(file, parent, parent_lineno); 56 } 57 58 len = strlen(name); 59 file = xmalloc(sizeof(*file) + len + 1); 60 memset(file, 0, sizeof(*file)); 61 memcpy(file->name, name, len); 62 file->name[len] = '\0'; 63 file->parent.name = parent; 64 file->parent.lineno = parent_lineno; 65 66 hash_add(file_hashtable, &file->node, hash); 67 68 str_printf(&autoconf_cmd, "\t%s \\\n", name); 69 70 return file->name; 71 } 72 73 /* Allocate initial growable string */ 74 struct gstr str_new(void) 75 { 76 struct gstr gs; 77 gs.s = xmalloc(sizeof(char) * 64); 78 gs.len = 64; 79 gs.max_width = 0; 80 strcpy(gs.s, "\0"); 81 return gs; 82 } 83 84 /* Free storage for growable string */ 85 void str_free(struct gstr *gs) 86 { 87 free(gs->s); 88 gs->s = NULL; 89 gs->len = 0; 90 } 91 92 /* Append to growable string */ 93 void str_append(struct gstr *gs, const char *s) 94 { 95 size_t l; 96 if (s) { 97 l = strlen(gs->s) + strlen(s) + 1; 98 if (l > gs->len) { 99 gs->s = xrealloc(gs->s, l); 100 gs->len = l; 101 } 102 strcat(gs->s, s); 103 } 104 } 105 106 /* Append printf formatted string to growable string */ 107 void str_printf(struct gstr *gs, const char *fmt, ...) 108 { 109 va_list ap; 110 char s[10000]; /* big enough... */ 111 va_start(ap, fmt); 112 vsnprintf(s, sizeof(s), fmt, ap); 113 str_append(gs, s); 114 va_end(ap); 115 } 116 117 /* Retrieve value of growable string */ 118 char *str_get(const struct gstr *gs) 119 { 120 return gs->s; 121 } 122