zconf.l 8.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455
  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. zconf_curname(), zconf_lineno(), 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. }
  201. }
  202. <HELP>{
  203. [ \t]+ {
  204. ts = 0;
  205. for (i = 0; i < yyleng; i++) {
  206. if (yytext[i] == '\t')
  207. ts = (ts & ~7) + 8;
  208. else
  209. ts++;
  210. }
  211. last_ts = ts;
  212. if (first_ts) {
  213. if (ts < first_ts) {
  214. zconf_endhelp();
  215. return T_HELPTEXT;
  216. }
  217. ts -= first_ts;
  218. while (ts > 8) {
  219. append_string(" ", 8);
  220. ts -= 8;
  221. }
  222. append_string(" ", ts);
  223. }
  224. }
  225. [ \t]*\n/[^ \t\n] {
  226. zconf_endhelp();
  227. return T_HELPTEXT;
  228. }
  229. [ \t]*\n {
  230. append_string("\n", 1);
  231. }
  232. [^ \t\n].* {
  233. while (yyleng) {
  234. if ((yytext[yyleng-1] != ' ') && (yytext[yyleng-1] != '\t'))
  235. break;
  236. yyleng--;
  237. }
  238. append_string(yytext, yyleng);
  239. if (!first_ts)
  240. first_ts = last_ts;
  241. }
  242. <<EOF>> {
  243. zconf_endhelp();
  244. return T_HELPTEXT;
  245. }
  246. }
  247. <<EOF>> {
  248. if (current_file) {
  249. zconf_endfile();
  250. return T_EOL;
  251. }
  252. fclose(yyin);
  253. yyterminate();
  254. }
  255. %%
  256. static char *expand_token(const char *in, size_t n)
  257. {
  258. char *out;
  259. int c;
  260. char c2;
  261. const char *rest, *end;
  262. new_string();
  263. append_string(in, n);
  264. /* get the whole line because we do not know the end of token. */
  265. while ((c = input()) != EOF) {
  266. if (c == '\n') {
  267. unput(c);
  268. break;
  269. }
  270. c2 = c;
  271. append_string(&c2, 1);
  272. }
  273. rest = text;
  274. out = expand_one_token(&rest);
  275. /* push back unused characters to the input stream */
  276. end = rest + strlen(rest);
  277. while (end > rest)
  278. unput(*--end);
  279. free(text);
  280. return out;
  281. }
  282. static void append_expanded_string(const char *str)
  283. {
  284. const char *end;
  285. char *res;
  286. str++;
  287. res = expand_dollar(&str);
  288. /* push back unused characters to the input stream */
  289. end = str + strlen(str);
  290. while (end > str)
  291. unput(*--end);
  292. append_string(res, strlen(res));
  293. free(res);
  294. }
  295. void zconf_starthelp(void)
  296. {
  297. new_string();
  298. last_ts = first_ts = 0;
  299. BEGIN(HELP);
  300. }
  301. static void zconf_endhelp(void)
  302. {
  303. yylval.string = text;
  304. BEGIN(INITIAL);
  305. }
  306. /*
  307. * Try to open specified file with following names:
  308. * ./name
  309. * $(srctree)/name
  310. * The latter is used when srctree is separate from objtree
  311. * when compiling the kernel.
  312. * Return NULL if file is not found.
  313. */
  314. FILE *zconf_fopen(const char *name)
  315. {
  316. char *env, fullname[PATH_MAX+1];
  317. FILE *f;
  318. f = fopen(name, "r");
  319. if (!f && name != NULL && name[0] != '/') {
  320. env = getenv(SRCTREE);
  321. if (env) {
  322. sprintf(fullname, "%s/%s", env, name);
  323. f = fopen(fullname, "r");
  324. }
  325. }
  326. return f;
  327. }
  328. void zconf_initscan(const char *name)
  329. {
  330. yyin = zconf_fopen(name);
  331. if (!yyin) {
  332. fprintf(stderr, "can't find file %s\n", name);
  333. exit(1);
  334. }
  335. current_buf = xmalloc(sizeof(*current_buf));
  336. memset(current_buf, 0, sizeof(*current_buf));
  337. current_file = file_lookup(name);
  338. yylineno = 1;
  339. }
  340. void zconf_nextfile(const char *name)
  341. {
  342. struct file *iter;
  343. struct file *file = file_lookup(name);
  344. struct buffer *buf = xmalloc(sizeof(*buf));
  345. memset(buf, 0, sizeof(*buf));
  346. current_buf->state = YY_CURRENT_BUFFER;
  347. yyin = zconf_fopen(file->name);
  348. if (!yyin) {
  349. fprintf(stderr, "%s:%d: can't open file \"%s\"\n",
  350. zconf_curname(), zconf_lineno(), file->name);
  351. exit(1);
  352. }
  353. yy_switch_to_buffer(yy_create_buffer(yyin, YY_BUF_SIZE));
  354. buf->parent = current_buf;
  355. current_buf = buf;
  356. current_file->lineno = yylineno;
  357. file->parent = current_file;
  358. for (iter = current_file; iter; iter = iter->parent) {
  359. if (!strcmp(iter->name, file->name)) {
  360. fprintf(stderr,
  361. "Recursive inclusion detected.\n"
  362. "Inclusion path:\n"
  363. " current file : %s\n", file->name);
  364. iter = file;
  365. do {
  366. iter = iter->parent;
  367. fprintf(stderr, " included from: %s:%d\n",
  368. iter->name, iter->lineno - 1);
  369. } while (strcmp(iter->name, file->name));
  370. exit(1);
  371. }
  372. }
  373. yylineno = 1;
  374. current_file = file;
  375. }
  376. static void zconf_endfile(void)
  377. {
  378. struct buffer *parent;
  379. current_file = current_file->parent;
  380. if (current_file)
  381. yylineno = current_file->lineno;
  382. parent = current_buf->parent;
  383. if (parent) {
  384. fclose(yyin);
  385. yy_delete_buffer(YY_CURRENT_BUFFER);
  386. yy_switch_to_buffer(parent->state);
  387. }
  388. free(current_buf);
  389. current_buf = parent;
  390. }
  391. int zconf_lineno(void)
  392. {
  393. return current_pos.lineno;
  394. }
  395. const char *zconf_curname(void)
  396. {
  397. return current_pos.file ? current_pos.file->name : "<none>";
  398. }