00001
00002
00003
00004
00005
00006 #include <sys/stat.h>
00007 #include <ctype.h>
00008 #include <stdio.h>
00009 #include <stdlib.h>
00010 #include <string.h>
00011 #include <unistd.h>
00012
00013 #define LKC_DIRECT_LINK
00014 #include "lkc.h"
00015
00016 const char conf_def_filename[] = "../../../.rtai_config";
00017
00018 const char conf_defname[] = "base/arch/$ARCH/defconfig";
00019
00020 const char *conf_confnames[] = {
00021 "../../../.rtai_config",
00022 "/lib/modules/$UNAME_RELEASE/.rtai_config",
00023 "/etc/rtai-config",
00024 conf_defname,
00025 NULL
00026 };
00027
00028 static char *conf_expand_value(const char *in)
00029 {
00030 struct symbol *sym;
00031 const char *src;
00032 static char res_value[SYMBOL_MAXLENGTH];
00033 char *dst, name[SYMBOL_MAXLENGTH];
00034
00035 res_value[0] = 0;
00036 dst = name;
00037 while ((src = strchr(in, '$'))) {
00038 strncat(res_value, in, src - in);
00039 src++;
00040 dst = name;
00041 while (isalnum(*src) || *src == '_')
00042 *dst++ = *src++;
00043 *dst = 0;
00044 sym = sym_lookup(name, 0);
00045 sym_calc_value(sym);
00046 strcat(res_value, sym_get_string_value(sym));
00047 in = src;
00048 }
00049 strcat(res_value, in);
00050
00051 return res_value;
00052 }
00053
00054 char *conf_get_default_confname(void)
00055 {
00056 struct stat buf;
00057 static char fullname[PATH_MAX+1];
00058 char *env, *name;
00059
00060 name = conf_expand_value(conf_defname);
00061 env = getenv(SRCTREE);
00062 if (env) {
00063 sprintf(fullname, "%s/%s", env, name);
00064 if (!stat(fullname, &buf))
00065 return fullname;
00066 }
00067 return name;
00068 }
00069
00070 int conf_read(const char *name)
00071 {
00072 FILE *in = NULL;
00073 char line[1024];
00074 char *p, *p2;
00075 int lineno = 0;
00076 struct symbol *sym;
00077 struct property *prop;
00078 struct expr *e;
00079 int i;
00080
00081 if (name) {
00082 in = zconf_fopen(name);
00083 } else {
00084 const char **names = conf_confnames;
00085 while ((name = *names++)) {
00086 name = conf_expand_value(name);
00087 in = zconf_fopen(name);
00088 if (in) {
00089 printf("#\n"
00090 "# using defaults found in %s\n"
00091 "#\n", name);
00092 break;
00093 }
00094 }
00095 }
00096
00097 if (!in)
00098 return 1;
00099
00100 for_all_symbols(i, sym) {
00101 sym->flags |= SYMBOL_NEW | SYMBOL_CHANGED;
00102 sym->flags &= ~SYMBOL_VALID;
00103 switch (sym->type) {
00104 case S_INT:
00105 case S_HEX:
00106 case S_STRING:
00107 if (sym->user.val)
00108 free(sym->user.val);
00109 default:
00110 sym->user.val = NULL;
00111 sym->user.tri = no;
00112 }
00113 }
00114
00115 while (fgets(line, sizeof(line), in)) {
00116 lineno++;
00117 sym = NULL;
00118 switch (line[0]) {
00119 case '#':
00120 if (memcmp(line + 2, "CONFIG_", 7))
00121 continue;
00122 p = strchr(line + 9, ' ');
00123 if (!p)
00124 continue;
00125 *p++ = 0;
00126 if (strncmp(p, "is not set", 10))
00127 continue;
00128 sym = sym_find(line + 9);
00129 if (!sym) {
00130 fprintf(stderr, "%s:%d: trying to assign nonexistent symbol %s\n", name, lineno, line + 9);
00131 break;
00132 }
00133 switch (sym->type) {
00134 case S_BOOLEAN:
00135 case S_TRISTATE:
00136 sym->user.tri = no;
00137 sym->flags &= ~SYMBOL_NEW;
00138 break;
00139 default:
00140 ;
00141 }
00142 break;
00143 case 'C':
00144 if (memcmp(line, "CONFIG_", 7))
00145 continue;
00146 p = strchr(line + 7, '=');
00147 if (!p)
00148 continue;
00149 *p++ = 0;
00150 p2 = strchr(p, '\n');
00151 if (p2)
00152 *p2 = 0;
00153 sym = sym_find(line + 7);
00154 if (!sym) {
00155 fprintf(stderr, "%s:%d: trying to assign nonexistent symbol %s\n", name, lineno, line + 7);
00156 break;
00157 }
00158 switch (sym->type) {
00159 case S_TRISTATE:
00160 if (p[0] == 'm') {
00161 sym->user.tri = mod;
00162 sym->flags &= ~SYMBOL_NEW;
00163 break;
00164 }
00165 case S_BOOLEAN:
00166 if (p[0] == 'y') {
00167 sym->user.tri = yes;
00168 sym->flags &= ~SYMBOL_NEW;
00169 break;
00170 }
00171 if (p[0] == 'n') {
00172 sym->user.tri = no;
00173 sym->flags &= ~SYMBOL_NEW;
00174 break;
00175 }
00176 break;
00177 case S_STRING:
00178 if (*p++ != '"')
00179 break;
00180 for (p2 = p; (p2 = strpbrk(p2, "\"\\")); p2++) {
00181 if (*p2 == '"') {
00182 *p2 = 0;
00183 break;
00184 }
00185 memmove(p2, p2 + 1, strlen(p2));
00186 }
00187 if (!p2) {
00188 fprintf(stderr, "%s:%d: invalid string found\n", name, lineno);
00189 exit(1);
00190 }
00191 case S_INT:
00192 case S_HEX:
00193 if (sym_string_valid(sym, p)) {
00194 sym->user.val = strdup(p);
00195 sym->flags &= ~SYMBOL_NEW;
00196 } else {
00197 fprintf(stderr, "%s:%d: symbol value '%s' invalid for %s\n", name, lineno, p, sym->name);
00198 exit(1);
00199 }
00200 break;
00201 default:
00202 ;
00203 }
00204 break;
00205 case '\n':
00206 break;
00207 default:
00208 continue;
00209 }
00210 if (sym && sym_is_choice_value(sym)) {
00211 struct symbol *cs = prop_get_symbol(sym_get_choice_prop(sym));
00212 switch (sym->user.tri) {
00213 case no:
00214 break;
00215 case mod:
00216 if (cs->user.tri == yes)
00217 ;
00218 break;
00219 case yes:
00220 if (cs->user.tri != no)
00221 ;
00222 cs->user.val = sym;
00223 break;
00224 }
00225 cs->user.tri = E_OR(cs->user.tri, sym->user.tri);
00226 cs->flags &= ~SYMBOL_NEW;
00227 }
00228 }
00229 fclose(in);
00230
00231 for_all_symbols(i, sym) {
00232 sym_calc_value(sym);
00233 if (sym_has_value(sym) && !sym_is_choice_value(sym)) {
00234 if (sym->visible == no)
00235 sym->flags |= SYMBOL_NEW;
00236 switch (sym->type) {
00237 case S_STRING:
00238 case S_INT:
00239 case S_HEX:
00240 if (!sym_string_within_range(sym, sym->user.val))
00241 sym->flags |= SYMBOL_NEW;
00242 default:
00243 break;
00244 }
00245 }
00246 if (!sym_is_choice(sym))
00247 continue;
00248 prop = sym_get_choice_prop(sym);
00249 for (e = prop->expr; e; e = e->left.expr)
00250 if (e->right.sym->visible != no)
00251 sym->flags |= e->right.sym->flags & SYMBOL_NEW;
00252 }
00253
00254 sym_change_count = 1;
00255
00256 return 0;
00257 }
00258
00259 int conf_write(const char *name)
00260 {
00261 FILE *out;
00262 struct symbol *sym;
00263 struct menu *menu;
00264 const char *basename;
00265 char dirname[128], tmpname[128], newname[128];
00266 int type, l;
00267 const char *str;
00268
00269 dirname[0] = 0;
00270 if (name && name[0]) {
00271 char *slash = strrchr(name, '/');
00272 if (slash) {
00273 int size = slash - name + 1;
00274 memcpy(dirname, name, size);
00275 dirname[size] = 0;
00276 if (slash[1])
00277 basename = slash + 1;
00278 else
00279 basename = conf_def_filename;
00280 } else
00281 basename = name;
00282 } else
00283 basename = conf_def_filename;
00284
00285 sprintf(newname, "%s.tmpconfig.%d", dirname, getpid());
00286 out = fopen(newname, "w");
00287 if (!out)
00288 return 1;
00289 fprintf(out, "#\n"
00290 "# Automatically generated make config: don't edit\n"
00291 "#\n");
00292 if (!sym_change_count)
00293 sym_clear_all_valid();
00294
00295 menu = rootmenu.list;
00296 while (menu) {
00297 sym = menu->sym;
00298 if (!sym) {
00299 if (!menu_is_visible(menu))
00300 goto next;
00301 str = menu_get_prompt(menu);
00302 fprintf(out, "\n"
00303 "#\n"
00304 "# %s\n"
00305 "#\n", str);
00306 } else if (!(sym->flags & SYMBOL_CHOICE)) {
00307 sym_calc_value(sym);
00308 if (!(sym->flags & SYMBOL_WRITE))
00309 goto next;
00310 sym->flags &= ~SYMBOL_WRITE;
00311 type = sym->type;
00312 if (type == S_TRISTATE) {
00313 sym_calc_value(modules_sym);
00314 if (modules_sym->curr.tri == no)
00315 type = S_BOOLEAN;
00316 }
00317 switch (type) {
00318 case S_BOOLEAN:
00319 case S_TRISTATE:
00320 switch (sym_get_tristate_value(sym)) {
00321 case no:
00322 fprintf(out, "# CONFIG_%s is not set\n", sym->name);
00323 break;
00324 case mod:
00325 fprintf(out, "CONFIG_%s=m\n", sym->name);
00326 break;
00327 case yes:
00328 fprintf(out, "CONFIG_%s=y\n", sym->name);
00329 break;
00330 }
00331 break;
00332 case S_STRING:
00333
00334 str = sym_get_string_value(sym);
00335 fprintf(out, "CONFIG_%s=\"", sym->name);
00336 do {
00337 l = strcspn(str, "\"\\");
00338 if (l) {
00339 fwrite(str, l, 1, out);
00340 }
00341 str += l;
00342 while (*str == '\\' || *str == '"') {
00343 fprintf(out, "\\%c", *str);
00344 str++;
00345 }
00346 } while (*str);
00347 fputs("\"\n", out);
00348 break;
00349 case S_HEX:
00350 str = sym_get_string_value(sym);
00351 if (str[0] != '0' || (str[1] != 'x' && str[1] != 'X')) {
00352 fprintf(out, "CONFIG_%s=%s\n", sym->name, str);
00353 break;
00354 }
00355 case S_INT:
00356 str = sym_get_string_value(sym);
00357 fprintf(out, "CONFIG_%s=%s\n", sym->name, str);
00358 break;
00359 }
00360 }
00361
00362 next:
00363 if (menu->list) {
00364 menu = menu->list;
00365 continue;
00366 }
00367 if (menu->next)
00368 menu = menu->next;
00369 else while ((menu = menu->parent)) {
00370 if (menu->next) {
00371 menu = menu->next;
00372 break;
00373 }
00374 }
00375 }
00376 fclose(out);
00377
00378 if (!name || basename != conf_def_filename) {
00379 if (!name)
00380 name = conf_def_filename;
00381 sprintf(tmpname, "%s.old", name);
00382 rename(name, tmpname);
00383 }
00384 sprintf(tmpname, "%s%s", dirname, basename);
00385 if (rename(newname, tmpname))
00386 return 1;
00387
00388 sym_change_count = 0;
00389
00390 return 0;
00391 }