zconf.l 8.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457
  1. %option nostdinit noyywrap never-interactive full ecs
  2. %option 8bit nodefault yylineno
  3. %x COMMAND HELP STRING PARAM ASSIGN_VAL
  4. %{
  5. /*
  6. * Copyright (C) 2002 Roman Zippel <zippel@linux-m68k.org>
  7. * Released under the terms of the GNU GPL v2.0.
  8. */
  9. #include <assert.h>
  10. #include <limits.h>
  11. #include <stdio.h>
  12. #include <stdlib.h>
  13. #include <string.h>
  14. #include <unistd.h>
  15. #include "lkc.h"
  16. #define START_STRSIZE 16
  17. static struct {
  18. struct file *file;
  19. int lineno;
  20. } current_pos;
  21. static char *text;
  22. static int text_size, text_asize;
  23. struct buffer {
  24. struct buffer *parent;
  25. YY_BUFFER_STATE state;
  26. };
  27. struct buffer *current_buf;
  28. static int last_ts, first_ts;
  29. static char *expand_token(const char *in, size_t n);
  30. static void append_expanded_string(const char *in);
  31. static void zconf_endhelp(void);
  32. static void zconf_endfile(void);
  33. static void new_string(void)
  34. {
  35. text = xmalloc(START_STRSIZE);
  36. text_asize = START_STRSIZE;
  37. text_size = 0;
  38. *text = 0;
  39. }
  40. static void append_string(const char *str, int size)
  41. {
  42. int new_size = text_size + size + 1;
  43. if (new_size > text_asize) {
  44. new_size += START_STRSIZE - 1;
  45. new_size &= -START_STRSIZE;
  46. text = xrealloc(text, new_size);
  47. text_asize = new_size;
  48. }
  49. memcpy(text + text_size, str, size);
  50. text_size += size;
  51. text[text_size] = 0;
  52. }
  53. static void alloc_string(const char *str, int size)
  54. {
  55. text = xmalloc(size + 1);
  56. memcpy(text, str, size);
  57. text[size] = 0;
  58. }
  59. static void warn_ignored_character(char chr)
  60. {
  61. fprintf(stderr,
  62. "%s:%d:warning: ignoring unsupported character '%c'\n",
  63. current_file->name, yylineno, chr);
  64. }
  65. %}
  66. n [A-Za-z0-9_-]
  67. %%
  68. int str = 0;
  69. int ts, i;
  70. [ \t]*#.*\n |
  71. [ \t]*\n {
  72. return T_EOL;
  73. }
  74. [ \t]*#.*
  75. [ \t]+ {
  76. BEGIN(COMMAND);
  77. }
  78. . {
  79. unput(yytext[0]);
  80. BEGIN(COMMAND);
  81. }
  82. <COMMAND>{
  83. {n}+ {
  84. const struct kconf_id *id = kconf_id_lookup(yytext, yyleng);
  85. current_pos.file = current_file;
  86. current_pos.lineno = yylineno;
  87. if (id && id->flags & TF_COMMAND) {
  88. BEGIN(PARAM);
  89. yylval.id = id;
  90. return id->token;
  91. }
  92. alloc_string(yytext, yyleng);
  93. yylval.string = text;
  94. return T_VARIABLE;
  95. }
  96. ({n}|$)+ {
  97. /* this token includes at least one '$' */
  98. yylval.string = expand_token(yytext, yyleng);
  99. if (strlen(yylval.string))
  100. return T_VARIABLE;
  101. free(yylval.string);
  102. }
  103. "=" { BEGIN(ASSIGN_VAL); yylval.flavor = VAR_RECURSIVE; return T_ASSIGN; }
  104. ":=" { BEGIN(ASSIGN_VAL); yylval.flavor = VAR_SIMPLE; return T_ASSIGN; }
  105. "+=" { BEGIN(ASSIGN_VAL); yylval.flavor = VAR_APPEND; return T_ASSIGN; }
  106. [[:blank:]]+
  107. . warn_ignored_character(*yytext);
  108. \n {
  109. BEGIN(INITIAL);
  110. return T_EOL;
  111. }
  112. }
  113. <ASSIGN_VAL>{
  114. [^[:blank:]\n]+.* {
  115. alloc_string(yytext, yyleng);
  116. yylval.string = text;
  117. return T_ASSIGN_VAL;
  118. }
  119. \n { BEGIN(INITIAL); return T_EOL; }
  120. .
  121. }
  122. <PARAM>{
  123. "&&" return T_AND;
  124. "||" return T_OR;
  125. "(" return T_OPEN_PAREN;
  126. ")" return T_CLOSE_PAREN;
  127. "!" return T_NOT;
  128. "=" return T_EQUAL;
  129. "!=" return T_UNEQUAL;
  130. "<=" return T_LESS_EQUAL;
  131. ">=" return T_GREATER_EQUAL;
  132. "<" return T_LESS;
  133. ">" return T_GREATER;
  134. \"|\' {
  135. str = yytext[0];
  136. new_string();
  137. BEGIN(STRING);
  138. }
  139. \n BEGIN(INITIAL); return T_EOL;
  140. ({n}|[/.])+ {
  141. const struct kconf_id *id = kconf_id_lookup(yytext, yyleng);
  142. if (id && id->flags & TF_PARAM) {
  143. yylval.id = id;
  144. return id->token;
  145. }
  146. alloc_string(yytext, yyleng);
  147. yylval.string = text;
  148. return T_WORD;
  149. }
  150. ({n}|[/.$])+ {
  151. /* this token includes at least one '$' */
  152. yylval.string = expand_token(yytext, yyleng);
  153. if (strlen(yylval.string))
  154. return T_WORD;
  155. free(yylval.string);
  156. }
  157. #.* /* comment */
  158. \\\n ;
  159. [[:blank:]]+
  160. . warn_ignored_character(*yytext);
  161. <<EOF>> {
  162. BEGIN(INITIAL);
  163. }
  164. }
  165. <STRING>{
  166. "$".* append_expanded_string(yytext);
  167. [^$'"\\\n]+/\n {
  168. append_string(yytext, yyleng);
  169. yylval.string = text;
  170. return T_WORD_QUOTE;
  171. }
  172. [^$'"\\\n]+ {
  173. append_string(yytext, yyleng);
  174. }
  175. \\.?/\n {
  176. append_string(yytext + 1, yyleng - 1);
  177. yylval.string = text;
  178. return T_WORD_QUOTE;
  179. }
  180. \\.? {
  181. append_string(yytext + 1, yyleng - 1);
  182. }
  183. \'|\" {
  184. if (str == yytext[0]) {
  185. BEGIN(PARAM);
  186. yylval.string = text;
  187. return T_WORD_QUOTE;
  188. } else
  189. append_string(yytext, 1);
  190. }
  191. \n {
  192. fprintf(stderr,
  193. "%s:%d:warning: multi-line strings not supported\n",
  194. zconf_curname(), zconf_lineno());
  195. BEGIN(INITIAL);
  196. return T_EOL;
  197. }
  198. <<EOF>> {
  199. BEGIN(INITIAL);
  200. yylval.string = text;
  201. return T_WORD_QUOTE;
  202. }
  203. }
  204. <HELP>{
  205. [ \t]+ {
  206. ts = 0;
  207. for (i = 0; i < yyleng; i++) {
  208. if (yytext[i] == '\t')
  209. ts = (ts & ~7) + 8;
  210. else
  211. ts++;
  212. }
  213. last_ts = ts;
  214. if (first_ts) {
  215. if (ts < first_ts) {
  216. zconf_endhelp();
  217. return T_HELPTEXT;
  218. }
  219. ts -= first_ts;
  220. while (ts > 8) {
  221. append_string(" ", 8);
  222. ts -= 8;
  223. }
  224. append_string(" ", ts);
  225. }
  226. }
  227. [ \t]*\n/[^ \t\n] {
  228. zconf_endhelp();
  229. return T_HELPTEXT;
  230. }
  231. [ \t]*\n {
  232. append_string("\n", 1);
  233. }
  234. [^ \t\n].* {
  235. while (yyleng) {
  236. if ((yytext[yyleng-1] != ' ') && (yytext[yyleng-1] != '\t'))
  237. break;
  238. yyleng--;
  239. }
  240. append_string(yytext, yyleng);
  241. if (!first_ts)
  242. first_ts = last_ts;
  243. }
  244. <<EOF>> {
  245. zconf_endhelp();
  246. return T_HELPTEXT;
  247. }
  248. }
  249. <<EOF>> {
  250. if (current_file) {
  251. zconf_endfile();
  252. return T_EOL;
  253. }
  254. fclose(yyin);
  255. yyterminate();
  256. }
  257. %%
  258. static char *expand_token(const char *in, size_t n)
  259. {
  260. char *out;
  261. int c;
  262. char c2;
  263. const char *rest, *end;
  264. new_string();
  265. append_string(in, n);
  266. /* get the whole line because we do not know the end of token. */
  267. while ((c = input()) != EOF) {
  268. if (c == '\n') {
  269. unput(c);
  270. break;
  271. }
  272. c2 = c;
  273. append_string(&c2, 1);
  274. }
  275. rest = text;
  276. out = expand_one_token(&rest);
  277. /* push back unused characters to the input stream */
  278. end = rest + strlen(rest);
  279. while (end > rest)
  280. unput(*--end);
  281. free(text);
  282. return out;
  283. }
  284. static void append_expanded_string(const char *str)
  285. {
  286. const char *end;
  287. char *res;
  288. str++;
  289. res = expand_dollar(&str);
  290. /* push back unused characters to the input stream */
  291. end = str + strlen(str);
  292. while (end > str)
  293. unput(*--end);
  294. append_string(res, strlen(res));
  295. free(res);
  296. }
  297. void zconf_starthelp(void)
  298. {
  299. new_string();
  300. last_ts = first_ts = 0;
  301. BEGIN(HELP);
  302. }
  303. static void zconf_endhelp(void)
  304. {
  305. yylval.string = text;
  306. BEGIN(INITIAL);
  307. }
  308. /*
  309. * Try to open specified file with following names:
  310. * ./name
  311. * $(srctree)/name
  312. * The latter is used when srctree is separate from objtree
  313. * when compiling the kernel.
  314. * Return NULL if file is not found.
  315. */
  316. FILE *zconf_fopen(const char *name)
  317. {
  318. char *env, fullname[PATH_MAX+1];
  319. FILE *f;
  320. f = fopen(name, "r");
  321. if (!f && name != NULL && name[0] != '/') {
  322. env = getenv(SRCTREE);
  323. if (env) {
  324. sprintf(fullname, "%s/%s", env, name);
  325. f = fopen(fullname, "r");
  326. }
  327. }
  328. return f;
  329. }
  330. void zconf_initscan(const char *name)
  331. {
  332. yyin = zconf_fopen(name);
  333. if (!yyin) {
  334. fprintf(stderr, "can't find file %s\n", name);
  335. exit(1);
  336. }
  337. current_buf = xmalloc(sizeof(*current_buf));
  338. memset(current_buf, 0, sizeof(*current_buf));
  339. current_file = file_lookup(name);
  340. yylineno = 1;
  341. }
  342. void zconf_nextfile(const char *name)
  343. {
  344. struct file *iter;
  345. struct file *file = file_lookup(name);
  346. struct buffer *buf = xmalloc(sizeof(*buf));
  347. memset(buf, 0, sizeof(*buf));
  348. current_buf->state = YY_CURRENT_BUFFER;
  349. yyin = zconf_fopen(file->name);
  350. if (!yyin) {
  351. fprintf(stderr, "%s:%d: can't open file \"%s\"\n",
  352. zconf_curname(), zconf_lineno(), file->name);
  353. exit(1);
  354. }
  355. yy_switch_to_buffer(yy_create_buffer(yyin, YY_BUF_SIZE));
  356. buf->parent = current_buf;
  357. current_buf = buf;
  358. current_file->lineno = yylineno;
  359. file->parent = current_file;
  360. for (iter = current_file; iter; iter = iter->parent) {
  361. if (!strcmp(iter->name, file->name)) {
  362. fprintf(stderr,
  363. "Recursive inclusion detected.\n"
  364. "Inclusion path:\n"
  365. " current file : %s\n", file->name);
  366. iter = file;
  367. do {
  368. iter = iter->parent;
  369. fprintf(stderr, " included from: %s:%d\n",
  370. iter->name, iter->lineno - 1);
  371. } while (strcmp(iter->name, file->name));
  372. exit(1);
  373. }
  374. }
  375. yylineno = 1;
  376. current_file = file;
  377. }
  378. static void zconf_endfile(void)
  379. {
  380. struct buffer *parent;
  381. current_file = current_file->parent;
  382. if (current_file)
  383. yylineno = current_file->lineno;
  384. parent = current_buf->parent;
  385. if (parent) {
  386. fclose(yyin);
  387. yy_delete_buffer(YY_CURRENT_BUFFER);
  388. yy_switch_to_buffer(parent->state);
  389. }
  390. free(current_buf);
  391. current_buf = parent;
  392. }
  393. int zconf_lineno(void)
  394. {
  395. return current_pos.lineno;
  396. }
  397. const char *zconf_curname(void)
  398. {
  399. return current_pos.file ? current_pos.file->name : "<none>";
  400. }