cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

parser.y (15608B)


      1/* SPDX-License-Identifier: GPL-2.0 */
      2/*
      3 * Copyright (C) 2002 Roman Zippel <zippel@linux-m68k.org>
      4 */
      5%{
      6
      7#include <ctype.h>
      8#include <stdarg.h>
      9#include <stdio.h>
     10#include <stdlib.h>
     11#include <string.h>
     12#include <stdbool.h>
     13
     14#include "lkc.h"
     15#include "internal.h"
     16
     17#define printd(mask, fmt...) if (cdebug & (mask)) printf(fmt)
     18
     19#define PRINTD		0x0001
     20#define DEBUG_PARSE	0x0002
     21
     22int cdebug = PRINTD;
     23
     24static void yyerror(const char *err);
     25static void zconfprint(const char *err, ...);
     26static void zconf_error(const char *err, ...);
     27static bool zconf_endtoken(const char *tokenname,
     28			   const char *expected_tokenname);
     29
     30struct symbol *symbol_hash[SYMBOL_HASHSIZE];
     31
     32struct menu *current_menu, *current_entry;
     33
     34%}
     35
     36%union
     37{
     38	char *string;
     39	struct symbol *symbol;
     40	struct expr *expr;
     41	struct menu *menu;
     42	enum symbol_type type;
     43	enum variable_flavor flavor;
     44}
     45
     46%token <string> T_HELPTEXT
     47%token <string> T_WORD
     48%token <string> T_WORD_QUOTE
     49%token T_BOOL
     50%token T_CHOICE
     51%token T_CLOSE_PAREN
     52%token T_COLON_EQUAL
     53%token T_COMMENT
     54%token T_CONFIG
     55%token T_DEFAULT
     56%token T_DEF_BOOL
     57%token T_DEF_TRISTATE
     58%token T_DEPENDS
     59%token T_ENDCHOICE
     60%token T_ENDIF
     61%token T_ENDMENU
     62%token T_HELP
     63%token T_HEX
     64%token T_IF
     65%token T_IMPLY
     66%token T_INT
     67%token T_MAINMENU
     68%token T_MENU
     69%token T_MENUCONFIG
     70%token T_MODULES
     71%token T_ON
     72%token T_OPEN_PAREN
     73%token T_OPTIONAL
     74%token T_PLUS_EQUAL
     75%token T_PROMPT
     76%token T_RANGE
     77%token T_SELECT
     78%token T_SOURCE
     79%token T_STRING
     80%token T_TRISTATE
     81%token T_VISIBLE
     82%token T_EOL
     83%token <string> T_ASSIGN_VAL
     84
     85%left T_OR
     86%left T_AND
     87%left T_EQUAL T_UNEQUAL
     88%left T_LESS T_LESS_EQUAL T_GREATER T_GREATER_EQUAL
     89%nonassoc T_NOT
     90
     91%type <symbol> nonconst_symbol
     92%type <symbol> symbol
     93%type <type> type logic_type default
     94%type <expr> expr
     95%type <expr> if_expr
     96%type <string> end
     97%type <menu> if_entry menu_entry choice_entry
     98%type <string> word_opt assign_val
     99%type <flavor> assign_op
    100
    101%destructor {
    102	fprintf(stderr, "%s:%d: missing end statement for this entry\n",
    103		$$->file->name, $$->lineno);
    104	if (current_menu == $$)
    105		menu_end_menu();
    106} if_entry menu_entry choice_entry
    107
    108%%
    109input: mainmenu_stmt stmt_list | stmt_list;
    110
    111/* mainmenu entry */
    112
    113mainmenu_stmt: T_MAINMENU T_WORD_QUOTE T_EOL
    114{
    115	menu_add_prompt(P_MENU, $2, NULL);
    116};
    117
    118stmt_list:
    119	  /* empty */
    120	| stmt_list assignment_stmt
    121	| stmt_list choice_stmt
    122	| stmt_list comment_stmt
    123	| stmt_list config_stmt
    124	| stmt_list if_stmt
    125	| stmt_list menu_stmt
    126	| stmt_list menuconfig_stmt
    127	| stmt_list source_stmt
    128	| stmt_list T_WORD error T_EOL	{ zconf_error("unknown statement \"%s\"", $2); }
    129	| stmt_list error T_EOL		{ zconf_error("invalid statement"); }
    130;
    131
    132stmt_list_in_choice:
    133	  /* empty */
    134	| stmt_list_in_choice comment_stmt
    135	| stmt_list_in_choice config_stmt
    136	| stmt_list_in_choice if_stmt_in_choice
    137	| stmt_list_in_choice error T_EOL	{ zconf_error("invalid statement"); }
    138;
    139
    140/* config/menuconfig entry */
    141
    142config_entry_start: T_CONFIG nonconst_symbol T_EOL
    143{
    144	$2->flags |= SYMBOL_OPTIONAL;
    145	menu_add_entry($2);
    146	printd(DEBUG_PARSE, "%s:%d:config %s\n", zconf_curname(), zconf_lineno(), $2->name);
    147};
    148
    149config_stmt: config_entry_start config_option_list
    150{
    151	printd(DEBUG_PARSE, "%s:%d:endconfig\n", zconf_curname(), zconf_lineno());
    152};
    153
    154menuconfig_entry_start: T_MENUCONFIG nonconst_symbol T_EOL
    155{
    156	$2->flags |= SYMBOL_OPTIONAL;
    157	menu_add_entry($2);
    158	printd(DEBUG_PARSE, "%s:%d:menuconfig %s\n", zconf_curname(), zconf_lineno(), $2->name);
    159};
    160
    161menuconfig_stmt: menuconfig_entry_start config_option_list
    162{
    163	if (current_entry->prompt)
    164		current_entry->prompt->type = P_MENU;
    165	else
    166		zconfprint("warning: menuconfig statement without prompt");
    167	printd(DEBUG_PARSE, "%s:%d:endconfig\n", zconf_curname(), zconf_lineno());
    168};
    169
    170config_option_list:
    171	  /* empty */
    172	| config_option_list config_option
    173	| config_option_list depends
    174	| config_option_list help
    175;
    176
    177config_option: type prompt_stmt_opt T_EOL
    178{
    179	menu_set_type($1);
    180	printd(DEBUG_PARSE, "%s:%d:type(%u)\n",
    181		zconf_curname(), zconf_lineno(),
    182		$1);
    183};
    184
    185config_option: T_PROMPT T_WORD_QUOTE if_expr T_EOL
    186{
    187	menu_add_prompt(P_PROMPT, $2, $3);
    188	printd(DEBUG_PARSE, "%s:%d:prompt\n", zconf_curname(), zconf_lineno());
    189};
    190
    191config_option: default expr if_expr T_EOL
    192{
    193	menu_add_expr(P_DEFAULT, $2, $3);
    194	if ($1 != S_UNKNOWN)
    195		menu_set_type($1);
    196	printd(DEBUG_PARSE, "%s:%d:default(%u)\n",
    197		zconf_curname(), zconf_lineno(),
    198		$1);
    199};
    200
    201config_option: T_SELECT nonconst_symbol if_expr T_EOL
    202{
    203	menu_add_symbol(P_SELECT, $2, $3);
    204	printd(DEBUG_PARSE, "%s:%d:select\n", zconf_curname(), zconf_lineno());
    205};
    206
    207config_option: T_IMPLY nonconst_symbol if_expr T_EOL
    208{
    209	menu_add_symbol(P_IMPLY, $2, $3);
    210	printd(DEBUG_PARSE, "%s:%d:imply\n", zconf_curname(), zconf_lineno());
    211};
    212
    213config_option: T_RANGE symbol symbol if_expr T_EOL
    214{
    215	menu_add_expr(P_RANGE, expr_alloc_comp(E_RANGE,$2, $3), $4);
    216	printd(DEBUG_PARSE, "%s:%d:range\n", zconf_curname(), zconf_lineno());
    217};
    218
    219config_option: T_MODULES T_EOL
    220{
    221	if (modules_sym)
    222		zconf_error("symbol '%s' redefines option 'modules' already defined by symbol '%s'",
    223			    current_entry->sym->name, modules_sym->name);
    224	modules_sym = current_entry->sym;
    225};
    226
    227/* choice entry */
    228
    229choice: T_CHOICE word_opt T_EOL
    230{
    231	struct symbol *sym = sym_lookup($2, SYMBOL_CHOICE);
    232	sym->flags |= SYMBOL_NO_WRITE;
    233	menu_add_entry(sym);
    234	menu_add_expr(P_CHOICE, NULL, NULL);
    235	free($2);
    236	printd(DEBUG_PARSE, "%s:%d:choice\n", zconf_curname(), zconf_lineno());
    237};
    238
    239choice_entry: choice choice_option_list
    240{
    241	$$ = menu_add_menu();
    242};
    243
    244choice_end: end
    245{
    246	if (zconf_endtoken($1, "choice")) {
    247		menu_end_menu();
    248		printd(DEBUG_PARSE, "%s:%d:endchoice\n", zconf_curname(), zconf_lineno());
    249	}
    250};
    251
    252choice_stmt: choice_entry stmt_list_in_choice choice_end
    253;
    254
    255choice_option_list:
    256	  /* empty */
    257	| choice_option_list choice_option
    258	| choice_option_list depends
    259	| choice_option_list help
    260;
    261
    262choice_option: T_PROMPT T_WORD_QUOTE if_expr T_EOL
    263{
    264	menu_add_prompt(P_PROMPT, $2, $3);
    265	printd(DEBUG_PARSE, "%s:%d:prompt\n", zconf_curname(), zconf_lineno());
    266};
    267
    268choice_option: logic_type prompt_stmt_opt T_EOL
    269{
    270	menu_set_type($1);
    271	printd(DEBUG_PARSE, "%s:%d:type(%u)\n",
    272	       zconf_curname(), zconf_lineno(), $1);
    273};
    274
    275choice_option: T_OPTIONAL T_EOL
    276{
    277	current_entry->sym->flags |= SYMBOL_OPTIONAL;
    278	printd(DEBUG_PARSE, "%s:%d:optional\n", zconf_curname(), zconf_lineno());
    279};
    280
    281choice_option: T_DEFAULT nonconst_symbol if_expr T_EOL
    282{
    283	menu_add_symbol(P_DEFAULT, $2, $3);
    284	printd(DEBUG_PARSE, "%s:%d:default\n",
    285	       zconf_curname(), zconf_lineno());
    286};
    287
    288type:
    289	  logic_type
    290	| T_INT			{ $$ = S_INT; }
    291	| T_HEX			{ $$ = S_HEX; }
    292	| T_STRING		{ $$ = S_STRING; }
    293
    294logic_type:
    295	  T_BOOL		{ $$ = S_BOOLEAN; }
    296	| T_TRISTATE		{ $$ = S_TRISTATE; }
    297
    298default:
    299	  T_DEFAULT		{ $$ = S_UNKNOWN; }
    300	| T_DEF_BOOL		{ $$ = S_BOOLEAN; }
    301	| T_DEF_TRISTATE	{ $$ = S_TRISTATE; }
    302
    303/* if entry */
    304
    305if_entry: T_IF expr T_EOL
    306{
    307	printd(DEBUG_PARSE, "%s:%d:if\n", zconf_curname(), zconf_lineno());
    308	menu_add_entry(NULL);
    309	menu_add_dep($2);
    310	$$ = menu_add_menu();
    311};
    312
    313if_end: end
    314{
    315	if (zconf_endtoken($1, "if")) {
    316		menu_end_menu();
    317		printd(DEBUG_PARSE, "%s:%d:endif\n", zconf_curname(), zconf_lineno());
    318	}
    319};
    320
    321if_stmt: if_entry stmt_list if_end
    322;
    323
    324if_stmt_in_choice: if_entry stmt_list_in_choice if_end
    325;
    326
    327/* menu entry */
    328
    329menu: T_MENU T_WORD_QUOTE T_EOL
    330{
    331	menu_add_entry(NULL);
    332	menu_add_prompt(P_MENU, $2, NULL);
    333	printd(DEBUG_PARSE, "%s:%d:menu\n", zconf_curname(), zconf_lineno());
    334};
    335
    336menu_entry: menu menu_option_list
    337{
    338	$$ = menu_add_menu();
    339};
    340
    341menu_end: end
    342{
    343	if (zconf_endtoken($1, "menu")) {
    344		menu_end_menu();
    345		printd(DEBUG_PARSE, "%s:%d:endmenu\n", zconf_curname(), zconf_lineno());
    346	}
    347};
    348
    349menu_stmt: menu_entry stmt_list menu_end
    350;
    351
    352menu_option_list:
    353	  /* empty */
    354	| menu_option_list visible
    355	| menu_option_list depends
    356;
    357
    358source_stmt: T_SOURCE T_WORD_QUOTE T_EOL
    359{
    360	printd(DEBUG_PARSE, "%s:%d:source %s\n", zconf_curname(), zconf_lineno(), $2);
    361	zconf_nextfile($2);
    362	free($2);
    363};
    364
    365/* comment entry */
    366
    367comment: T_COMMENT T_WORD_QUOTE T_EOL
    368{
    369	menu_add_entry(NULL);
    370	menu_add_prompt(P_COMMENT, $2, NULL);
    371	printd(DEBUG_PARSE, "%s:%d:comment\n", zconf_curname(), zconf_lineno());
    372};
    373
    374comment_stmt: comment comment_option_list
    375;
    376
    377comment_option_list:
    378	  /* empty */
    379	| comment_option_list depends
    380;
    381
    382/* help option */
    383
    384help_start: T_HELP T_EOL
    385{
    386	printd(DEBUG_PARSE, "%s:%d:help\n", zconf_curname(), zconf_lineno());
    387	zconf_starthelp();
    388};
    389
    390help: help_start T_HELPTEXT
    391{
    392	if (current_entry->help) {
    393		free(current_entry->help);
    394		zconfprint("warning: '%s' defined with more than one help text -- only the last one will be used",
    395			   current_entry->sym->name ?: "<choice>");
    396	}
    397
    398	/* Is the help text empty or all whitespace? */
    399	if ($2[strspn($2, " \f\n\r\t\v")] == '\0')
    400		zconfprint("warning: '%s' defined with blank help text",
    401			   current_entry->sym->name ?: "<choice>");
    402
    403	current_entry->help = $2;
    404};
    405
    406/* depends option */
    407
    408depends: T_DEPENDS T_ON expr T_EOL
    409{
    410	menu_add_dep($3);
    411	printd(DEBUG_PARSE, "%s:%d:depends on\n", zconf_curname(), zconf_lineno());
    412};
    413
    414/* visibility option */
    415visible: T_VISIBLE if_expr T_EOL
    416{
    417	menu_add_visibility($2);
    418};
    419
    420/* prompt statement */
    421
    422prompt_stmt_opt:
    423	  /* empty */
    424	| T_WORD_QUOTE if_expr
    425{
    426	menu_add_prompt(P_PROMPT, $1, $2);
    427};
    428
    429end:	  T_ENDMENU T_EOL	{ $$ = "menu"; }
    430	| T_ENDCHOICE T_EOL	{ $$ = "choice"; }
    431	| T_ENDIF T_EOL		{ $$ = "if"; }
    432;
    433
    434if_expr:  /* empty */			{ $$ = NULL; }
    435	| T_IF expr			{ $$ = $2; }
    436;
    437
    438expr:	  symbol				{ $$ = expr_alloc_symbol($1); }
    439	| symbol T_LESS symbol			{ $$ = expr_alloc_comp(E_LTH, $1, $3); }
    440	| symbol T_LESS_EQUAL symbol		{ $$ = expr_alloc_comp(E_LEQ, $1, $3); }
    441	| symbol T_GREATER symbol		{ $$ = expr_alloc_comp(E_GTH, $1, $3); }
    442	| symbol T_GREATER_EQUAL symbol		{ $$ = expr_alloc_comp(E_GEQ, $1, $3); }
    443	| symbol T_EQUAL symbol			{ $$ = expr_alloc_comp(E_EQUAL, $1, $3); }
    444	| symbol T_UNEQUAL symbol		{ $$ = expr_alloc_comp(E_UNEQUAL, $1, $3); }
    445	| T_OPEN_PAREN expr T_CLOSE_PAREN	{ $$ = $2; }
    446	| T_NOT expr				{ $$ = expr_alloc_one(E_NOT, $2); }
    447	| expr T_OR expr			{ $$ = expr_alloc_two(E_OR, $1, $3); }
    448	| expr T_AND expr			{ $$ = expr_alloc_two(E_AND, $1, $3); }
    449;
    450
    451/* For symbol definitions, selects, etc., where quotes are not accepted */
    452nonconst_symbol: T_WORD { $$ = sym_lookup($1, 0); free($1); };
    453
    454symbol:	  nonconst_symbol
    455	| T_WORD_QUOTE	{ $$ = sym_lookup($1, SYMBOL_CONST); free($1); }
    456;
    457
    458word_opt: /* empty */			{ $$ = NULL; }
    459	| T_WORD
    460
    461/* assignment statement */
    462
    463assignment_stmt:  T_WORD assign_op assign_val T_EOL	{ variable_add($1, $3, $2); free($1); free($3); }
    464
    465assign_op:
    466	  T_EQUAL	{ $$ = VAR_RECURSIVE; }
    467	| T_COLON_EQUAL	{ $$ = VAR_SIMPLE; }
    468	| T_PLUS_EQUAL	{ $$ = VAR_APPEND; }
    469;
    470
    471assign_val:
    472	/* empty */		{ $$ = xstrdup(""); };
    473	| T_ASSIGN_VAL
    474;
    475
    476%%
    477
    478void conf_parse(const char *name)
    479{
    480	struct symbol *sym;
    481	int i;
    482
    483	zconf_initscan(name);
    484
    485	_menu_init();
    486
    487	if (getenv("ZCONF_DEBUG"))
    488		yydebug = 1;
    489	yyparse();
    490
    491	/* Variables are expanded in the parse phase. We can free them here. */
    492	variable_all_del();
    493
    494	if (yynerrs)
    495		exit(1);
    496	if (!modules_sym)
    497		modules_sym = sym_find( "n" );
    498
    499	if (!menu_has_prompt(&rootmenu)) {
    500		current_entry = &rootmenu;
    501		menu_add_prompt(P_MENU, "Main menu", NULL);
    502	}
    503
    504	menu_finalize(&rootmenu);
    505	for_all_symbols(i, sym) {
    506		if (sym_check_deps(sym))
    507			yynerrs++;
    508	}
    509	if (yynerrs)
    510		exit(1);
    511	conf_set_changed(true);
    512}
    513
    514static bool zconf_endtoken(const char *tokenname,
    515			   const char *expected_tokenname)
    516{
    517	if (strcmp(tokenname, expected_tokenname)) {
    518		zconf_error("unexpected '%s' within %s block",
    519			    tokenname, expected_tokenname);
    520		yynerrs++;
    521		return false;
    522	}
    523	if (current_menu->file != current_file) {
    524		zconf_error("'%s' in different file than '%s'",
    525			    tokenname, expected_tokenname);
    526		fprintf(stderr, "%s:%d: location of the '%s'\n",
    527			current_menu->file->name, current_menu->lineno,
    528			expected_tokenname);
    529		yynerrs++;
    530		return false;
    531	}
    532	return true;
    533}
    534
    535static void zconfprint(const char *err, ...)
    536{
    537	va_list ap;
    538
    539	fprintf(stderr, "%s:%d: ", zconf_curname(), zconf_lineno());
    540	va_start(ap, err);
    541	vfprintf(stderr, err, ap);
    542	va_end(ap);
    543	fprintf(stderr, "\n");
    544}
    545
    546static void zconf_error(const char *err, ...)
    547{
    548	va_list ap;
    549
    550	yynerrs++;
    551	fprintf(stderr, "%s:%d: ", zconf_curname(), zconf_lineno());
    552	va_start(ap, err);
    553	vfprintf(stderr, err, ap);
    554	va_end(ap);
    555	fprintf(stderr, "\n");
    556}
    557
    558static void yyerror(const char *err)
    559{
    560	fprintf(stderr, "%s:%d: %s\n", zconf_curname(), zconf_lineno() + 1, err);
    561}
    562
    563static void print_quoted_string(FILE *out, const char *str)
    564{
    565	const char *p;
    566	int len;
    567
    568	putc('"', out);
    569	while ((p = strchr(str, '"'))) {
    570		len = p - str;
    571		if (len)
    572			fprintf(out, "%.*s", len, str);
    573		fputs("\\\"", out);
    574		str = p + 1;
    575	}
    576	fputs(str, out);
    577	putc('"', out);
    578}
    579
    580static void print_symbol(FILE *out, struct menu *menu)
    581{
    582	struct symbol *sym = menu->sym;
    583	struct property *prop;
    584
    585	if (sym_is_choice(sym))
    586		fprintf(out, "\nchoice\n");
    587	else
    588		fprintf(out, "\nconfig %s\n", sym->name);
    589	switch (sym->type) {
    590	case S_BOOLEAN:
    591		fputs("  bool\n", out);
    592		break;
    593	case S_TRISTATE:
    594		fputs("  tristate\n", out);
    595		break;
    596	case S_STRING:
    597		fputs("  string\n", out);
    598		break;
    599	case S_INT:
    600		fputs("  integer\n", out);
    601		break;
    602	case S_HEX:
    603		fputs("  hex\n", out);
    604		break;
    605	default:
    606		fputs("  ???\n", out);
    607		break;
    608	}
    609	for (prop = sym->prop; prop; prop = prop->next) {
    610		if (prop->menu != menu)
    611			continue;
    612		switch (prop->type) {
    613		case P_PROMPT:
    614			fputs("  prompt ", out);
    615			print_quoted_string(out, prop->text);
    616			if (!expr_is_yes(prop->visible.expr)) {
    617				fputs(" if ", out);
    618				expr_fprint(prop->visible.expr, out);
    619			}
    620			fputc('\n', out);
    621			break;
    622		case P_DEFAULT:
    623			fputs( "  default ", out);
    624			expr_fprint(prop->expr, out);
    625			if (!expr_is_yes(prop->visible.expr)) {
    626				fputs(" if ", out);
    627				expr_fprint(prop->visible.expr, out);
    628			}
    629			fputc('\n', out);
    630			break;
    631		case P_CHOICE:
    632			fputs("  #choice value\n", out);
    633			break;
    634		case P_SELECT:
    635			fputs( "  select ", out);
    636			expr_fprint(prop->expr, out);
    637			fputc('\n', out);
    638			break;
    639		case P_IMPLY:
    640			fputs( "  imply ", out);
    641			expr_fprint(prop->expr, out);
    642			fputc('\n', out);
    643			break;
    644		case P_RANGE:
    645			fputs( "  range ", out);
    646			expr_fprint(prop->expr, out);
    647			fputc('\n', out);
    648			break;
    649		case P_MENU:
    650			fputs( "  menu ", out);
    651			print_quoted_string(out, prop->text);
    652			fputc('\n', out);
    653			break;
    654		case P_SYMBOL:
    655			fputs( "  symbol ", out);
    656			fprintf(out, "%s\n", prop->menu->sym->name);
    657			break;
    658		default:
    659			fprintf(out, "  unknown prop %d!\n", prop->type);
    660			break;
    661		}
    662	}
    663	if (menu->help) {
    664		int len = strlen(menu->help);
    665		while (menu->help[--len] == '\n')
    666			menu->help[len] = 0;
    667		fprintf(out, "  help\n%s\n", menu->help);
    668	}
    669}
    670
    671void zconfdump(FILE *out)
    672{
    673	struct property *prop;
    674	struct symbol *sym;
    675	struct menu *menu;
    676
    677	menu = rootmenu.list;
    678	while (menu) {
    679		if ((sym = menu->sym))
    680			print_symbol(out, menu);
    681		else if ((prop = menu->prompt)) {
    682			switch (prop->type) {
    683			case P_COMMENT:
    684				fputs("\ncomment ", out);
    685				print_quoted_string(out, prop->text);
    686				fputs("\n", out);
    687				break;
    688			case P_MENU:
    689				fputs("\nmenu ", out);
    690				print_quoted_string(out, prop->text);
    691				fputs("\n", out);
    692				break;
    693			default:
    694				;
    695			}
    696			if (!expr_is_yes(prop->visible.expr)) {
    697				fputs("  depends ", out);
    698				expr_fprint(prop->visible.expr, out);
    699				fputc('\n', out);
    700			}
    701		}
    702
    703		if (menu->list)
    704			menu = menu->list;
    705		else if (menu->next)
    706			menu = menu->next;
    707		else while ((menu = menu->parent)) {
    708			if (menu->prompt && menu->prompt->type == P_MENU)
    709				fputs("\nendmenu\n", out);
    710			if (menu->next) {
    711				menu = menu->next;
    712				break;
    713			}
    714		}
    715	}
    716}