PageRenderTime 55ms CodeModel.GetById 24ms RepoModel.GetById 1ms app.codeStats 0ms

/Zend/zend_ini_scanner.l

http://github.com/php/php-src
LEX | 662 lines | 435 code | 102 blank | 125 comment | 0 complexity | bef2bc567faaf9261b770d75ac0f20fe MD5 | raw file
Possible License(s): BSD-2-Clause, BSD-3-Clause, MPL-2.0-no-copyleft-exception, LGPL-2.1
  1. /*
  2. +----------------------------------------------------------------------+
  3. | Zend Engine |
  4. +----------------------------------------------------------------------+
  5. | Copyright (c) Zend Technologies Ltd. (http://www.zend.com) |
  6. +----------------------------------------------------------------------+
  7. | This source file is subject to version 2.00 of the Zend license, |
  8. | that is bundled with this package in the file LICENSE, and is |
  9. | available through the world-wide-web at the following url: |
  10. | http://www.zend.com/license/2_00.txt. |
  11. | If you did not receive a copy of the Zend license and are unable to |
  12. | obtain it through the world-wide-web, please send a note to |
  13. | license@zend.com so we can mail you a copy immediately. |
  14. +----------------------------------------------------------------------+
  15. | Authors: Zeev Suraski <zeev@php.net> |
  16. | Jani Taskinen <jani@php.net> |
  17. | Marcus Boerger <helly@php.net> |
  18. | Nuno Lopes <nlopess@php.net> |
  19. | Scott MacVicar <scottmac@php.net> |
  20. +----------------------------------------------------------------------+
  21. */
  22. #include <errno.h>
  23. #include "zend.h"
  24. #include "zend_API.h"
  25. #include "zend_globals.h"
  26. #include <zend_ini_parser.h>
  27. #include "zend_ini_scanner.h"
  28. #ifdef YYDEBUG
  29. #undef YYDEBUG
  30. #endif
  31. #if 0
  32. # define YYDEBUG(s, c) printf("state: %d char: %c\n", s, c)
  33. #else
  34. # define YYDEBUG(s, c)
  35. #endif
  36. #include "zend_ini_scanner_defs.h"
  37. #define YYCTYPE unsigned char
  38. /* allow the scanner to read one null byte after the end of the string (from ZEND_MMAP_AHEAD)
  39. * so that if will be able to terminate to match the current token (e.g. non-enclosed string) */
  40. #define YYFILL(n) { if (YYCURSOR > YYLIMIT) return 0; }
  41. #define YYCURSOR SCNG(yy_cursor)
  42. #define YYLIMIT SCNG(yy_limit)
  43. #define YYMARKER SCNG(yy_marker)
  44. #define YYGETCONDITION() SCNG(yy_state)
  45. #define YYSETCONDITION(s) SCNG(yy_state) = s
  46. #define STATE(name) yyc##name
  47. /* emulate flex constructs */
  48. #define BEGIN(state) YYSETCONDITION(STATE(state))
  49. #define YYSTATE YYGETCONDITION()
  50. #define yytext ((char*)SCNG(yy_text))
  51. #define yyleng SCNG(yy_leng)
  52. #define yyless(x) do { YYCURSOR = (unsigned char*)yytext + x; \
  53. yyleng = (unsigned int)x; } while(0)
  54. /* #define yymore() goto yymore_restart */
  55. /* perform sanity check. If this message is triggered you should
  56. increase the ZEND_MMAP_AHEAD value in the zend_streams.h file */
  57. /*!max:re2c */
  58. #if ZEND_MMAP_AHEAD < (YYMAXFILL + 1)
  59. # error ZEND_MMAP_AHEAD should be greater than YYMAXFILL
  60. #endif
  61. /* How it works (for the core ini directives):
  62. * ===========================================
  63. *
  64. * 1. Scanner scans file for tokens and passes them to parser.
  65. * 2. Parser parses the tokens and passes the name/value pairs to the callback
  66. * function which stores them in the configuration hash table.
  67. * 3. Later REGISTER_INI_ENTRIES() is called which triggers the actual
  68. * registering of ini entries and uses zend_get_configuration_directive()
  69. * to fetch the previously stored name/value pair from configuration hash table
  70. * and registers the static ini entries which match the name to the value
  71. * into EG(ini_directives) hash table.
  72. * 4. PATH section entries are used per-request from down to top, each overriding
  73. * previous if one exists. zend_alter_ini_entry() is called for each entry.
  74. * Settings in PATH section are ZEND_INI_SYSTEM accessible and thus mimics the
  75. * php_admin_* directives used within Apache httpd.conf when PHP is compiled as
  76. * module for Apache.
  77. * 5. User defined ini files (like .htaccess for apache) are parsed for each request and
  78. * stored in separate hash defined by SAPI.
  79. */
  80. /* TODO: (ordered by importance :-)
  81. * ===============================================================================
  82. *
  83. * - Separate constant lookup totally from plain strings (using CONSTANT pattern)
  84. * - Add #if .. #else .. #endif and ==, !=, <, > , <=, >= operators
  85. * - Add #include "some.ini"
  86. * - Allow variables to refer to options also when using parse_ini_file()
  87. *
  88. */
  89. /* Globals Macros */
  90. #define SCNG INI_SCNG
  91. #ifdef ZTS
  92. ZEND_API ts_rsrc_id ini_scanner_globals_id;
  93. ZEND_API size_t ini_scanner_globals_offset;
  94. #else
  95. ZEND_API zend_ini_scanner_globals ini_scanner_globals;
  96. #endif
  97. #define ZEND_SYSTEM_INI CG(ini_parser_unbuffered_errors)
  98. /* Eat leading whitespace */
  99. #define EAT_LEADING_WHITESPACE() \
  100. while (yyleng) { \
  101. if (yytext[0] == ' ' || yytext[0] == '\t') { \
  102. SCNG(yy_text)++; \
  103. yyleng--; \
  104. } else { \
  105. break; \
  106. } \
  107. }
  108. /* Eat trailing whitespace + extra char */
  109. #define EAT_TRAILING_WHITESPACE_EX(ch) \
  110. while (yyleng && ( \
  111. (ch != 'X' && yytext[yyleng - 1] == ch) || \
  112. yytext[yyleng - 1] == '\n' || \
  113. yytext[yyleng - 1] == '\r' || \
  114. yytext[yyleng - 1] == '\t' || \
  115. yytext[yyleng - 1] == ' ') \
  116. ) { \
  117. yyleng--; \
  118. }
  119. /* Eat trailing whitespace */
  120. #define EAT_TRAILING_WHITESPACE() EAT_TRAILING_WHITESPACE_EX('X')
  121. #define zend_ini_copy_value(retval, str, len) \
  122. ZVAL_NEW_STR(retval, zend_string_init(str, len, ZEND_SYSTEM_INI))
  123. #define RETURN_TOKEN(type, str, len) { \
  124. if (SCNG(scanner_mode) == ZEND_INI_SCANNER_TYPED && \
  125. (YYSTATE == STATE(ST_VALUE) || YYSTATE == STATE(ST_RAW))) {\
  126. zend_ini_copy_typed_value(ini_lval, type, str, len); \
  127. } else { \
  128. zend_ini_copy_value(ini_lval, str, len); \
  129. } \
  130. return type; \
  131. }
  132. static inline int convert_to_number(zval *retval, const char *str, const int str_len)
  133. {
  134. zend_uchar type;
  135. int overflow;
  136. zend_long lval;
  137. double dval;
  138. if ((type = is_numeric_string_ex(str, str_len, &lval, &dval, 0, &overflow)) != 0) {
  139. if (type == IS_LONG) {
  140. ZVAL_LONG(retval, lval);
  141. return SUCCESS;
  142. } else if (type == IS_DOUBLE && !overflow) {
  143. ZVAL_DOUBLE(retval, dval);
  144. return SUCCESS;
  145. }
  146. }
  147. return FAILURE;
  148. }
  149. static void zend_ini_copy_typed_value(zval *retval, const int type, const char *str, int len)
  150. {
  151. switch (type) {
  152. case BOOL_FALSE:
  153. case BOOL_TRUE:
  154. ZVAL_BOOL(retval, type == BOOL_TRUE);
  155. break;
  156. case NULL_NULL:
  157. ZVAL_NULL(retval);
  158. break;
  159. case TC_NUMBER:
  160. if (convert_to_number(retval, str, len) == SUCCESS) {
  161. break;
  162. }
  163. /* intentional fall-through */
  164. default:
  165. zend_ini_copy_value(retval, str, len);
  166. }
  167. }
  168. static void _yy_push_state(int new_state)
  169. {
  170. zend_stack_push(&SCNG(state_stack), (void *) &YYGETCONDITION());
  171. YYSETCONDITION(new_state);
  172. }
  173. #define yy_push_state(state_and_tsrm) _yy_push_state(yyc##state_and_tsrm)
  174. static void yy_pop_state(void)
  175. {
  176. int *stack_state = zend_stack_top(&SCNG(state_stack));
  177. YYSETCONDITION(*stack_state);
  178. zend_stack_del_top(&SCNG(state_stack));
  179. }
  180. static void yy_scan_buffer(char *str, unsigned int len)
  181. {
  182. YYCURSOR = (YYCTYPE*)str;
  183. SCNG(yy_start) = YYCURSOR;
  184. YYLIMIT = YYCURSOR + len;
  185. }
  186. #define ini_filename SCNG(filename)
  187. /* {{{ init_ini_scanner()
  188. */
  189. static int init_ini_scanner(int scanner_mode, zend_file_handle *fh)
  190. {
  191. /* Sanity check */
  192. if (scanner_mode != ZEND_INI_SCANNER_NORMAL && scanner_mode != ZEND_INI_SCANNER_RAW && scanner_mode != ZEND_INI_SCANNER_TYPED) {
  193. zend_error(E_WARNING, "Invalid scanner mode");
  194. return FAILURE;
  195. }
  196. SCNG(lineno) = 1;
  197. SCNG(scanner_mode) = scanner_mode;
  198. SCNG(yy_in) = fh;
  199. if (fh != NULL) {
  200. ini_filename = zend_strndup(fh->filename, strlen(fh->filename));
  201. } else {
  202. ini_filename = NULL;
  203. }
  204. zend_stack_init(&SCNG(state_stack), sizeof(int));
  205. BEGIN(INITIAL);
  206. return SUCCESS;
  207. }
  208. /* }}} */
  209. /* {{{ shutdown_ini_scanner()
  210. */
  211. void shutdown_ini_scanner(void)
  212. {
  213. zend_stack_destroy(&SCNG(state_stack));
  214. if (ini_filename) {
  215. free(ini_filename);
  216. }
  217. }
  218. /* }}} */
  219. /* {{{ zend_ini_scanner_get_lineno()
  220. */
  221. ZEND_COLD int zend_ini_scanner_get_lineno(void)
  222. {
  223. return SCNG(lineno);
  224. }
  225. /* }}} */
  226. /* {{{ zend_ini_scanner_get_filename()
  227. */
  228. ZEND_COLD char *zend_ini_scanner_get_filename(void)
  229. {
  230. return ini_filename ? ini_filename : "Unknown";
  231. }
  232. /* }}} */
  233. /* {{{ zend_ini_open_file_for_scanning()
  234. */
  235. int zend_ini_open_file_for_scanning(zend_file_handle *fh, int scanner_mode)
  236. {
  237. char *buf;
  238. size_t size;
  239. if (zend_stream_fixup(fh, &buf, &size) == FAILURE) {
  240. return FAILURE;
  241. }
  242. if (init_ini_scanner(scanner_mode, fh) == FAILURE) {
  243. zend_file_handle_dtor(fh);
  244. return FAILURE;
  245. }
  246. yy_scan_buffer(buf, (unsigned int)size);
  247. return SUCCESS;
  248. }
  249. /* }}} */
  250. /* {{{ zend_ini_prepare_string_for_scanning()
  251. */
  252. int zend_ini_prepare_string_for_scanning(char *str, int scanner_mode)
  253. {
  254. int len = (int)strlen(str);
  255. if (init_ini_scanner(scanner_mode, NULL) == FAILURE) {
  256. return FAILURE;
  257. }
  258. yy_scan_buffer(str, len);
  259. return SUCCESS;
  260. }
  261. /* }}} */
  262. /* {{{ zend_ini_escape_string()
  263. */
  264. static void zend_ini_escape_string(zval *lval, char *str, int len, char quote_type)
  265. {
  266. register char *s, *t;
  267. char *end;
  268. zend_ini_copy_value(lval, str, len);
  269. /* convert escape sequences */
  270. s = t = Z_STRVAL_P(lval);
  271. end = s + Z_STRLEN_P(lval);
  272. while (s < end) {
  273. if (*s == '\\') {
  274. s++;
  275. if (s >= end) {
  276. *t++ = '\\';
  277. continue;
  278. }
  279. switch (*s) {
  280. case '"':
  281. if (*s != quote_type) {
  282. *t++ = '\\';
  283. *t++ = *s;
  284. break;
  285. }
  286. case '\\':
  287. case '$':
  288. *t++ = *s;
  289. Z_STRLEN_P(lval)--;
  290. break;
  291. default:
  292. *t++ = '\\';
  293. *t++ = *s;
  294. break;
  295. }
  296. } else {
  297. *t++ = *s;
  298. }
  299. if (*s == '\n' || (*s == '\r' && (*(s+1) != '\n'))) {
  300. SCNG(lineno)++;
  301. }
  302. s++;
  303. }
  304. *t = 0;
  305. }
  306. /* }}} */
  307. int ini_lex(zval *ini_lval)
  308. {
  309. restart:
  310. SCNG(yy_text) = YYCURSOR;
  311. /* yymore_restart: */
  312. /* detect EOF */
  313. if (YYCURSOR >= YYLIMIT) {
  314. if (YYSTATE == STATE(ST_VALUE) || YYSTATE == STATE(ST_RAW)) {
  315. BEGIN(INITIAL);
  316. return END_OF_LINE;
  317. }
  318. return 0;
  319. }
  320. /* Eat any UTF-8 BOM we find in the first 3 bytes */
  321. if (YYCURSOR == SCNG(yy_start) && YYCURSOR + 3 < YYLIMIT) {
  322. if (memcmp(YYCURSOR, "\xef\xbb\xbf", 3) == 0) {
  323. YYCURSOR += 3;
  324. goto restart;
  325. }
  326. }
  327. /*!re2c
  328. re2c:yyfill:check = 0;
  329. LNUM [0-9]+
  330. DNUM ([0-9]*[\.][0-9]+)|([0-9]+[\.][0-9]*)
  331. NUMBER [-]?{LNUM}|{DNUM}
  332. ANY_CHAR (.|[\n\t])
  333. NEWLINE ("\r"|"\n"|"\r\n")
  334. TABS_AND_SPACES [ \t]
  335. WHITESPACE [ \t]+
  336. CONSTANT [a-zA-Z_][a-zA-Z0-9_]*
  337. LABEL [^=\n\r\t;&|^$~(){}!"\[]+
  338. TOKENS [:,.\[\]"'()&|^+-/*=%$!~<>?@{}]
  339. OPERATORS [&|^~()!]
  340. DOLLAR_CURLY "${"
  341. SECTION_RAW_CHARS [^\]\n\r]
  342. SINGLE_QUOTED_CHARS [^']
  343. RAW_VALUE_CHARS [^\n\r;\000]
  344. LITERAL_DOLLAR ("$"([^{\000]|("\\"{ANY_CHAR})))
  345. VALUE_CHARS ([^$= \t\n\r;&|^~()!"'\000]|{LITERAL_DOLLAR})
  346. SECTION_VALUE_CHARS ([^$\n\r;"'\]\\]|("\\"{ANY_CHAR})|{LITERAL_DOLLAR})
  347. <!*> := yyleng = YYCURSOR - SCNG(yy_text);
  348. <INITIAL>"[" { /* Section start */
  349. /* Enter section data lookup state */
  350. if (SCNG(scanner_mode) == ZEND_INI_SCANNER_RAW) {
  351. BEGIN(ST_SECTION_RAW);
  352. } else {
  353. BEGIN(ST_SECTION_VALUE);
  354. }
  355. return TC_SECTION;
  356. }
  357. <ST_VALUE,ST_SECTION_VALUE,ST_OFFSET>"'"{SINGLE_QUOTED_CHARS}+"'" { /* Raw string */
  358. /* Eat leading and trailing single quotes */
  359. if (yytext[0] == '\'' && yytext[yyleng - 1] == '\'') {
  360. SCNG(yy_text)++;
  361. yyleng = yyleng - 2;
  362. }
  363. RETURN_TOKEN(TC_RAW, yytext, yyleng);
  364. }
  365. <ST_SECTION_RAW,ST_SECTION_VALUE>"]"{TABS_AND_SPACES}*{NEWLINE}? { /* End of section */
  366. BEGIN(INITIAL);
  367. SCNG(lineno)++;
  368. return ']';
  369. }
  370. <INITIAL>{LABEL}"["{TABS_AND_SPACES}* { /* Start of option with offset */
  371. /* Eat leading whitespace */
  372. EAT_LEADING_WHITESPACE();
  373. /* Eat trailing whitespace and [ */
  374. EAT_TRAILING_WHITESPACE_EX('[');
  375. /* Enter offset lookup state */
  376. BEGIN(ST_OFFSET);
  377. RETURN_TOKEN(TC_OFFSET, yytext, yyleng);
  378. }
  379. <ST_OFFSET>{TABS_AND_SPACES}*"]" { /* End of section or an option offset */
  380. BEGIN(INITIAL);
  381. return ']';
  382. }
  383. <ST_DOUBLE_QUOTES,ST_SECTION_VALUE,ST_VALUE,ST_OFFSET>{DOLLAR_CURLY} { /* Variable start */
  384. yy_push_state(ST_VARNAME);
  385. return TC_DOLLAR_CURLY;
  386. }
  387. <ST_VARNAME>{LABEL} { /* Variable name */
  388. /* Eat leading whitespace */
  389. EAT_LEADING_WHITESPACE();
  390. /* Eat trailing whitespace */
  391. EAT_TRAILING_WHITESPACE();
  392. RETURN_TOKEN(TC_VARNAME, yytext, yyleng);
  393. }
  394. <ST_VARNAME>"}" { /* Variable end */
  395. yy_pop_state();
  396. return '}';
  397. }
  398. <INITIAL,ST_VALUE>("true"|"on"|"yes"){TABS_AND_SPACES}* { /* TRUE value (when used outside option value/offset this causes parse error!) */
  399. RETURN_TOKEN(BOOL_TRUE, "1", 1);
  400. }
  401. <INITIAL,ST_VALUE>("false"|"off"|"no"|"none"){TABS_AND_SPACES}* { /* FALSE value (when used outside option value/offset this causes parse error!)*/
  402. RETURN_TOKEN(BOOL_FALSE, "", 0);
  403. }
  404. <INITIAL,ST_VALUE>("null"){TABS_AND_SPACES}* {
  405. RETURN_TOKEN(NULL_NULL, "", 0);
  406. }
  407. <INITIAL>{LABEL} { /* Get option name */
  408. /* Eat leading whitespace */
  409. EAT_LEADING_WHITESPACE();
  410. /* Eat trailing whitespace */
  411. EAT_TRAILING_WHITESPACE();
  412. RETURN_TOKEN(TC_LABEL, yytext, yyleng);
  413. }
  414. <INITIAL>{TABS_AND_SPACES}*[=]{TABS_AND_SPACES}* { /* Start option value */
  415. if (SCNG(scanner_mode) == ZEND_INI_SCANNER_RAW) {
  416. BEGIN(ST_RAW);
  417. } else {
  418. BEGIN(ST_VALUE);
  419. }
  420. return '=';
  421. }
  422. <ST_RAW>{RAW_VALUE_CHARS} { /* Raw value, only used when SCNG(scanner_mode) == ZEND_INI_SCANNER_RAW. */
  423. unsigned char *sc = NULL;
  424. EAT_LEADING_WHITESPACE();
  425. while (YYCURSOR < YYLIMIT) {
  426. switch (*YYCURSOR) {
  427. case '\n':
  428. case '\r':
  429. goto end_raw_value_chars;
  430. break;
  431. case ';':
  432. if (sc == NULL) {
  433. sc = YYCURSOR;
  434. }
  435. YYCURSOR++;
  436. break;
  437. case '"':
  438. if (yytext[0] == '"') {
  439. sc = NULL;
  440. }
  441. YYCURSOR++;
  442. break;
  443. default:
  444. YYCURSOR++;
  445. break;
  446. }
  447. }
  448. end_raw_value_chars:
  449. if (sc) {
  450. yyleng = sc - SCNG(yy_text);
  451. } else {
  452. yyleng = YYCURSOR - SCNG(yy_text);
  453. }
  454. EAT_TRAILING_WHITESPACE();
  455. /* Eat leading and trailing double quotes */
  456. if (yyleng > 1 && yytext[0] == '"' && yytext[yyleng - 1] == '"') {
  457. SCNG(yy_text)++;
  458. yyleng = yyleng - 2;
  459. }
  460. RETURN_TOKEN(TC_RAW, yytext, yyleng);
  461. }
  462. <ST_SECTION_RAW>{SECTION_RAW_CHARS}+ { /* Raw value, only used when SCNG(scanner_mode) == ZEND_INI_SCANNER_RAW. */
  463. RETURN_TOKEN(TC_RAW, yytext, yyleng);
  464. }
  465. <ST_VALUE,ST_RAW>{TABS_AND_SPACES}*{NEWLINE} { /* End of option value */
  466. BEGIN(INITIAL);
  467. SCNG(lineno)++;
  468. return END_OF_LINE;
  469. }
  470. <ST_SECTION_VALUE,ST_VALUE,ST_OFFSET>{CONSTANT} { /* Get constant option value */
  471. RETURN_TOKEN(TC_CONSTANT, yytext, yyleng);
  472. }
  473. <ST_SECTION_VALUE,ST_VALUE,ST_OFFSET>{NUMBER} { /* Get number option value as string */
  474. RETURN_TOKEN(TC_NUMBER, yytext, yyleng);
  475. }
  476. <INITIAL>{TOKENS} { /* Disallow these chars outside option values */
  477. return yytext[0];
  478. }
  479. <ST_VALUE>{OPERATORS}{TABS_AND_SPACES}* { /* Boolean operators */
  480. return yytext[0];
  481. }
  482. <ST_VALUE>[=] { /* Make = used in option value to trigger error */
  483. yyless(0);
  484. BEGIN(INITIAL);
  485. return END_OF_LINE;
  486. }
  487. <ST_VALUE>{VALUE_CHARS}+ { /* Get everything else as option/offset value */
  488. RETURN_TOKEN(TC_STRING, yytext, yyleng);
  489. }
  490. <ST_SECTION_VALUE,ST_OFFSET>{SECTION_VALUE_CHARS}+ { /* Get rest as section/offset value */
  491. RETURN_TOKEN(TC_STRING, yytext, yyleng);
  492. }
  493. <ST_SECTION_VALUE,ST_VALUE,ST_OFFSET>{TABS_AND_SPACES}*["] { /* Double quoted '"' string start */
  494. yy_push_state(ST_DOUBLE_QUOTES);
  495. return '"';
  496. }
  497. <ST_DOUBLE_QUOTES>["]{TABS_AND_SPACES}* { /* Double quoted '"' string ends */
  498. yy_pop_state();
  499. return '"';
  500. }
  501. <ST_DOUBLE_QUOTES>[^] { /* Escape double quoted string contents */
  502. if (YYCURSOR > YYLIMIT) {
  503. return 0;
  504. }
  505. while (YYCURSOR < YYLIMIT) {
  506. switch (*YYCURSOR++) {
  507. case '"':
  508. if (YYCURSOR < YYLIMIT && YYCURSOR[-2] == '\\' && *YYCURSOR != '\r' && *YYCURSOR != '\n') {
  509. continue;
  510. }
  511. break;
  512. case '$':
  513. if (*YYCURSOR == '{') {
  514. break;
  515. }
  516. continue;
  517. case '\\':
  518. if (YYCURSOR < YYLIMIT && *YYCURSOR != '"') {
  519. YYCURSOR++;
  520. }
  521. /* fall through */
  522. default:
  523. continue;
  524. }
  525. YYCURSOR--;
  526. break;
  527. }
  528. yyleng = YYCURSOR - SCNG(yy_text);
  529. zend_ini_escape_string(ini_lval, yytext, yyleng, '"');
  530. return TC_QUOTED_STRING;
  531. }
  532. <ST_SECTION_VALUE,ST_VALUE,ST_OFFSET>{WHITESPACE} {
  533. RETURN_TOKEN(TC_WHITESPACE, yytext, yyleng);
  534. }
  535. <INITIAL,ST_RAW>{TABS_AND_SPACES}+ {
  536. /* eat whitespace */
  537. goto restart;
  538. }
  539. <INITIAL>{TABS_AND_SPACES}*{NEWLINE} {
  540. SCNG(lineno)++;
  541. return END_OF_LINE;
  542. }
  543. <INITIAL,ST_VALUE,ST_RAW>{TABS_AND_SPACES}*[;][^\r\n]*{NEWLINE} { /* Comment */
  544. BEGIN(INITIAL);
  545. SCNG(lineno)++;
  546. return END_OF_LINE;
  547. }
  548. <ST_VALUE,ST_RAW>[^] { /* End of option value (if EOF is reached before EOL */
  549. BEGIN(INITIAL);
  550. return END_OF_LINE;
  551. }
  552. <*>[^] {
  553. return 0;
  554. }
  555. */
  556. }