⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 psqlscan.l

📁 PostgreSQL 8.1.4的源码 适用于Linux下的开源数据库系统
💻 L
📖 第 1 页 / 共 3 页
字号:
	/*	 * These rules are specific to psql --- they implement parenthesis	 * counting and detection of command-ending semicolon.  These must	 * appear before the {self} rule so that they take precedence over it.	 */"("				{					cur_state->paren_depth++;					ECHO;				}")"				{					if (cur_state->paren_depth > 0)						cur_state->paren_depth--;					ECHO;				}";"				{					ECHO;					if (cur_state->paren_depth == 0)					{						/* Terminate lexing temporarily */						return LEXRES_SEMI;					}				}	/*	 * psql-specific rules to handle backslash commands and variable	 * substitution.  We want these before {self}, also.	 */"\\"[;:]		{					/* Force a semicolon or colon into the query buffer */					emit(yytext + 1, 1);				}"\\"			{					/* Terminate lexing temporarily */					return LEXRES_BACKSLASH;				}:[A-Za-z0-9_]+	{					/* Possible psql variable substitution */					const char *value;					value = GetVariable(pset.vars, yytext + 1);					if (value)					{						/* It is a variable, perform substitution */						push_new_buffer(value);						/* yy_scan_string already made buffer active */					}					else					{						/*						 * if the variable doesn't exist we'll copy the						 * string as is						 */						ECHO;					}				}	/*	 * Back to backend-compatible rules.	 */{self}			{					ECHO;				}{operator}		{					/*					 * Check for embedded slash-star or dash-dash; those					 * are comment starts, so operator must stop there.					 * Note that slash-star or dash-dash at the first					 * character will match a prior rule, not this one.					 */					int		nchars = yyleng;					char   *slashstar = strstr(yytext, "/*");					char   *dashdash = strstr(yytext, "--");					if (slashstar && dashdash)					{						/* if both appear, take the first one */						if (slashstar > dashdash)							slashstar = dashdash;					}					else if (!slashstar)						slashstar = dashdash;					if (slashstar)						nchars = slashstar - yytext;					/*					 * For SQL compatibility, '+' and '-' cannot be the					 * last char of a multi-char operator unless the operator					 * contains chars that are not in SQL operators.					 * The idea is to lex '=-' as two operators, but not					 * to forbid operator names like '?-' that could not be					 * sequences of SQL operators.					 */					while (nchars > 1 &&						   (yytext[nchars-1] == '+' ||							yytext[nchars-1] == '-'))					{						int		ic;						for (ic = nchars-2; ic >= 0; ic--)						{							if (strchr("~!@#^&|`?%", yytext[ic]))								break;						}						if (ic >= 0)							break; /* found a char that makes it OK */						nchars--; /* else remove the +/-, and check again */					}					if (nchars < yyleng)					{						/* Strip the unwanted chars from the token */						yyless(nchars);					}					ECHO;				}{param}			{					ECHO;				}{integer}		{					ECHO;				}{decimal}		{					ECHO;				}{real}			{					ECHO;				}{realfail1}		{					/*					 * throw back the [Ee], and treat as {decimal}.  Note					 * that it is possible the input is actually {integer},					 * but since this case will almost certainly lead to a					 * syntax error anyway, we don't bother to distinguish.					 */					yyless(yyleng-1);					ECHO;				}{realfail2}		{					/* throw back the [Ee][+-], and proceed as above */					yyless(yyleng-2);					ECHO;				}{identifier}	{					ECHO;				}{other}			{					ECHO;				}	/*	 * Everything from here down is psql-specific.	 */<<EOF>>			{					StackElem  *stackelem = cur_state->buffer_stack;					if (stackelem == NULL)						return LEXRES_EOL; /* end of input reached */					/*					 * We were expanding a variable, so pop the inclusion					 * stack and keep lexing					 */					cur_state->buffer_stack = stackelem->next;					yy_delete_buffer(stackelem->buf);					free(stackelem->bufstring);					if (stackelem->origstring)						free(stackelem->origstring);					free(stackelem);					stackelem = cur_state->buffer_stack;					if (stackelem != NULL)					{						yy_switch_to_buffer(stackelem->buf);						cur_state->curline = stackelem->bufstring;						cur_state->refline = stackelem->origstring ? stackelem->origstring : stackelem->bufstring;					}					else					{						yy_switch_to_buffer(cur_state->scanbufhandle);						cur_state->curline = cur_state->scanbuf;						cur_state->refline = cur_state->scanline;					}				}	/*	 * Exclusive lexer states to handle backslash command lexing	 */<xslashcmd>{	/* command name ends at whitespace or backslash; eat all else */{space}|"\\"	{					yyless(0);					return LEXRES_OK;				}{other}			{ ECHO; }}<xslasharg>{	/* eat any whitespace, then decide what to do at first nonblank */{space}+		{ }"\\"			{					/*					 * backslash is end of command or next command, do not eat					 *					 * XXX this means we can't conveniently accept options					 * that start with a backslash; therefore, option					 * processing that encourages use of backslashes is rather					 * broken.					 */					yyless(0);					return LEXRES_OK;				}{quote}			{					*option_quote = '\'';					BEGIN(xslashquote);				}"`"				{					if (option_type == OT_VERBATIM)					{						/* in verbatim mode, backquote is not special */						ECHO;						BEGIN(xslashdefaultarg);					}					else					{						*option_quote = '`';						BEGIN(xslashbackquote);					}				}:[A-Za-z0-9_]*	{					/* Possible psql variable substitution */					if (option_type == OT_VERBATIM)						ECHO;					else					{						const char *value;						value = GetVariable(pset.vars, yytext + 1);						/*						 * The variable value is just emitted without any						 * further examination.  This is consistent with the						 * pre-8.0 code behavior, if not with the way that						 * variables are handled outside backslash commands.						 */						if (value)							appendPQExpBufferStr(output_buf, value);					}					*option_quote = ':';					return LEXRES_OK;				}"|"				{					ECHO;					if (option_type == OT_FILEPIPE)					{						/* treat like whole-string case */						BEGIN(xslashwholeline);					}					else					{						/* treat like default case */						BEGIN(xslashdefaultarg);					}				}{dquote}		{					*option_quote = '"';					ECHO;					BEGIN(xslashquotedarg);				}{other}			{					ECHO;					BEGIN(xslashdefaultarg);				}}<xslashquote>{	/* single-quoted text: copy literally except for backslash sequences */{quote}			{ return LEXRES_OK; }"\\n"			{ appendPQExpBufferChar(output_buf, '\n'); }"\\t"			{ appendPQExpBufferChar(output_buf, '\t'); }"\\b"			{ appendPQExpBufferChar(output_buf, '\b'); }"\\r"			{ appendPQExpBufferChar(output_buf, '\r'); }"\\f"			{ appendPQExpBufferChar(output_buf, '\f'); }{xqoctesc}		{					/* octal case */					appendPQExpBufferChar(output_buf,										  (char) strtol(yytext + 1, NULL, 8));				}{xqhexesc}		{					/* hex case */					appendPQExpBufferChar(output_buf,										  (char) strtol(yytext + 2, NULL, 16));				}"\\".			{ emit(yytext + 1, 1); }{other}|\n		{ ECHO; }}<xslashbackquote>{	/*	 * backticked text: copy everything until next backquote or end of line.	 * Invocation of the command will happen in psql_scan_slash_option.	 */"`"				{ return LEXRES_OK; }{other}|\n		{ ECHO; }}<xslashdefaultarg>{	/*	 * Copy everything until unquoted whitespace or end of line.  Quotes	 * do not get stripped yet.	 */{space}			{					yyless(0);					return LEXRES_OK;				}"\\"			{					/*					 * unquoted backslash is end of command or next command,					 * do not eat					 *					 * (this was not the behavior pre-8.0, but it seems					 * consistent)					 */					yyless(0);					return LEXRES_OK;				}{dquote}		{					*option_quote = '"';					ECHO;					BEGIN(xslashquotedarg);				}{other}			{ ECHO; }}<xslashquotedarg>{	/* double-quoted text within a default-type argument: copy */{dquote}		{					ECHO;					BEGIN(xslashdefaultarg);				}{other}|\n		{ ECHO; }}<xslashwholeline>{	/* copy everything until end of input line */	/* but suppress leading whitespace */{space}+		{					if (output_buf->len > 0)						ECHO;				}{other}			{ ECHO; }}<xslashend>{	/* at end of command, eat a double backslash, but not anything else */"\\\\"			{ return LEXRES_OK; }{other}|\n		{					yyless(0);					return LEXRES_OK;				}}%%/* * Create a lexer working state struct. */PsqlScanStatepsql_scan_create(void){	PsqlScanState state;	state = (PsqlScanStateData *) pg_malloc_zero(sizeof(PsqlScanStateData));	psql_scan_reset(state);	return state;}/* * Destroy a lexer working state struct, releasing all resources. */voidpsql_scan_destroy(PsqlScanState state){	psql_scan_finish(state);	psql_scan_reset(state);	free(state);}/* * Set up to perform lexing of the given input line. * * The text at *line, extending for line_len bytes, will be scanned by * subsequent calls to the psql_scan routines.  psql_scan_finish should * be called when scanning is complete.  Note that the lexer retains * a pointer to the storage at *line --- this string must not be altered * or freed until after psql_scan_finish is called. */voidpsql_scan_setup(PsqlScanState state,				const char *line, int line_len){	/* Mustn't be scanning already */	psql_assert(state->scanbufhandle == NULL);	psql_assert(state->buffer_stack == NULL);	/* Do we need to hack the character set encoding? */	state->encoding = pset.encoding;	state->safe_encoding = PG_VALID_BE_ENCODING(state->encoding);	/* needed for prepare_buffer */	cur_state = state;	/* Set up flex input buffer with appropriate translation and padding */	state->scanbufhandle = prepare_buffer(line, line_len,										  &state->scanbuf);	state->scanline = line;	/* Set lookaside data in case we have to map unsafe encoding */	state->curline = state->scanbuf;	state->refline = state->scanline;}/* * Do lexical analysis of SQL command text. * * The text previously passed to psql_scan_setup is scanned, and appended * (possibly with transformation) to query_buf. * * The return value indicates the condition that stopped scanning: * * PSCAN_SEMICOLON: found a command-ending semicolon.  (The semicolon is * transferred to query_buf.)  The command accumulated in query_buf should * be executed, then clear query_buf and call again to scan the remainder * of the line. * * PSCAN_BACKSLASH: found a backslash that starts a psql special command. * Any previous data on the line has been transferred to query_buf. * The caller will typically next call psql_scan_slash_command(), * perhaps psql_scan_slash_option(), and psql_scan_slash_command_end(). * * PSCAN_INCOMPLETE: the end of the line was reached, but we have an * incomplete SQL command.  *prompt is set to the appropriate prompt type. * * PSCAN_EOL: the end of the line was reached, and there is no lexical * reason to consider the command incomplete.  The caller may or may not * choose to send it.  *prompt is set to the appropriate prompt type if * the caller chooses to collect more input. * * In the PSCAN_INCOMPLETE and PSCAN_EOL cases, psql_scan_finish() should * be called next, then the cycle may be repeated with a fresh input line. * * In all cases, *prompt is set to an appropriate prompt type code for the * next line-input operation. */PsqlScanResultpsql_scan(PsqlScanState state,		  PQExpBuffer query_buf,		  promptStatus_t *prompt){	PsqlScanResult result;	int			lexresult;	/* Must be scanning already */	psql_assert(state->scanbufhandle);	/* Set up static variables that will be used by yylex */	cur_state = state;	output_buf = query_buf;	if (state->buffer_stack != NULL)		yy_switch_to_buffer(state->buffer_stack->buf);	else		yy_switch_to_buffer(state->scanbufhandle);	BEGIN(state->start_state);	/* And lex. */	lexresult = yylex();	/* Update static vars back to the state struct */	state->start_state = YY_START;	/*	 * Check termination state and return appropriate result info.	 */	switch (lexresult)

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -