| %{ |
| /* $Id: tmesh-input.y,v 1.4 2006/11/15 23:11:31 fredette Exp $ */ |
| |
| /* tmesh/tmesh-input.y - the tme shell scanner and parser: */ |
| |
| /* |
| * Copyright (c) 2003 Matt Fredette |
| * All rights reserved. |
| * |
| * Redistribution and use in source and binary forms, with or without |
| * modification, are permitted provided that the following conditions |
| * are met: |
| * 1. Redistributions of source code must retain the above copyright |
| * notice, this list of conditions and the following disclaimer. |
| * 2. Redistributions in binary form must reproduce the above copyright |
| * notice, this list of conditions and the following disclaimer in the |
| * documentation and/or other materials provided with the distribution. |
| * 3. All advertising materials mentioning features or use of this software |
| * must display the following acknowledgement: |
| * This product includes software developed by Matt Fredette. |
| * 4. The name of the author may not be used to endorse or promote products |
| * derived from this software without specific prior written permission. |
| * |
| * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR |
| * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED |
| * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE |
| * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, |
| * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES |
| * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR |
| * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) |
| * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, |
| * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN |
| * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE |
| * POSSIBILITY OF SUCH DAMAGE. |
| */ |
| |
| #include <tme/common.h> |
| _TME_RCSID("$Id: tmesh-input.y,v 1.4 2006/11/15 23:11:31 fredette Exp $"); |
| |
| /* includes: */ |
| #include <tme/threads.h> |
| #include <stdio.h> |
| #include <stdlib.h> |
| #include <ctype.h> |
| #include "tmesh-impl.h" |
| |
| /* macros: */ |
| |
| /* internal token numbers: */ |
| #define TMESH_TOKEN_UNDEF (-1) |
| #define TMESH_TOKEN_EOF (0) |
| |
| /* internal character numbers: */ |
| #define TMESH_C_EOF_SEMICOLON (TMESH_C_YIELD - 1) |
| #define TMESH_C_UNDEF (TMESH_C_EOF_SEMICOLON - 2) |
| |
| #define YYSTYPE struct tmesh_parser_value |
| #define YYDEBUG 1 |
| #define YYMAXDEPTH 10000 |
| |
| /* types: */ |
| |
| /* globals: */ |
| static tme_mutex_t _tmesh_input_mutex; |
| static struct tmesh *_tmesh_input; |
| static char **_tmesh_output; |
| static int _tmesh_input_yielding; |
| static YYSTYPE *_tmesh_input_parsed; |
| |
| /* prototypes: */ |
| static int yylex _TME_P((void)); |
| static void yyerror _TME_P((char *)); |
| static void _tmesh_scanner_in_args _TME_P((void)); |
| static void _tmesh_parser_argv_arg _TME_P((struct tmesh_parser_argv *, char *, int)); |
| |
| %} |
| |
| /* the tokens: */ |
| %token TMESH_TOKEN_SOURCE |
| %token TMESH_TOKEN_MKDIR |
| %token TMESH_TOKEN_RMDIR |
| %token TMESH_TOKEN_CD |
| %token TMESH_TOKEN_PWD |
| %token TMESH_TOKEN_LS |
| %token TMESH_TOKEN_CONNECT |
| %token TMESH_TOKEN_RM |
| %token TMESH_TOKEN_MV |
| %token TMESH_TOKEN_COMMAND |
| %token TMESH_TOKEN_LOG |
| %token TMESH_TOKEN_ALIAS |
| %token TMESH_TOKEN_AT |
| %token TMESH_TOKEN_PATHNAME |
| %token TMESH_TOKEN_ARG |
| %token TMESH_TOKEN_OPTS |
| |
| %% |
| |
| /* a tmesh command: */ |
| command: command_source { *_tmesh_input_parsed = $1; YYACCEPT; } |
| | command_mkdir { *_tmesh_input_parsed = $1; YYACCEPT; } |
| | command_rmdir { *_tmesh_input_parsed = $1; YYACCEPT; } |
| | command_cd { *_tmesh_input_parsed = $1; YYACCEPT; } |
| | command_pwd { *_tmesh_input_parsed = $1; YYACCEPT; } |
| | command_ls { *_tmesh_input_parsed = $1; YYACCEPT; } |
| | command_connect { *_tmesh_input_parsed = $1; YYACCEPT; } |
| | command_rm { *_tmesh_input_parsed = $1; YYACCEPT; } |
| | command_mv { *_tmesh_input_parsed = $1; YYACCEPT; } |
| | command_command { *_tmesh_input_parsed = $1; YYACCEPT; } |
| | command_log { *_tmesh_input_parsed = $1; YYACCEPT; } |
| | command_alias { *_tmesh_input_parsed = $1; YYACCEPT; } |
| | error ';' { YYABORT; } |
| | ';' |
| { _tmesh_input_parsed->tmesh_parser_value_token = TMESH_TOKEN_UNDEF; YYACCEPT; } |
| ; |
| |
| /* the 'source' command: */ |
| command_source: TMESH_TOKEN_SOURCE pathname ';' |
| { $$ = $2; $$.tmesh_parser_value_token = $1.tmesh_parser_value_token; } |
| |
| /* the 'mkdir' command: */ |
| command_mkdir: TMESH_TOKEN_MKDIR pathname ';' |
| { $$ = $2; $$.tmesh_parser_value_token = $1.tmesh_parser_value_token; } |
| ; |
| |
| /* the 'rmdir' command: */ |
| command_rmdir: TMESH_TOKEN_RMDIR pathname ';' |
| { $$ = $2; $$.tmesh_parser_value_token = $1.tmesh_parser_value_token; } |
| ; |
| |
| /* the 'cd' command: */ |
| command_cd: TMESH_TOKEN_CD pathname ';' |
| { $$ = $2; $$.tmesh_parser_value_token = $1.tmesh_parser_value_token; } |
| ; |
| |
| /* the 'pwd' command: */ |
| command_pwd: TMESH_TOKEN_PWD ';' |
| |
| /* the 'ls' command: */ |
| command_ls: TMESH_TOKEN_LS opts_opt pathname_opt ';' |
| { |
| $$ = $2; |
| $$.tmesh_parser_value_strings[1] = $3.tmesh_parser_value_strings[0]; |
| $$.tmesh_parser_value_token = $1.tmesh_parser_value_token; |
| } |
| ; |
| |
| /* the 'connect' command: */ |
| command_connect: TMESH_TOKEN_CONNECT connection ';' |
| { $$ = $2; $$.tmesh_parser_value_token = $1.tmesh_parser_value_token; } |
| command_connect: connection ';' |
| { $$ = $1; $$.tmesh_parser_value_token = TMESH_TOKEN_CONNECT; } |
| ; |
| |
| /* the 'rm' command: */ |
| command_rm: TMESH_TOKEN_RM pathname ';' |
| { $$ = $2; $$.tmesh_parser_value_token = $1.tmesh_parser_value_token; } |
| ; |
| |
| /* the 'mv' command: */ |
| command_mv: TMESH_TOKEN_MV pathname pathname ';' |
| { |
| $$ = $2; |
| $$.tmesh_parser_value_strings[1] = $3.tmesh_parser_value_strings[0]; |
| $$.tmesh_parser_value_token = $1.tmesh_parser_value_token; |
| } |
| ; |
| |
| /* the 'command' command: */ |
| command_command: TMESH_TOKEN_COMMAND pathname_args ';' |
| { $$ = $2; $$.tmesh_parser_value_token = $1.tmesh_parser_value_token; } |
| ; |
| |
| /* the 'log' command: */ |
| command_log: TMESH_TOKEN_LOG pathname_args ';' |
| { $$ = $2; $$.tmesh_parser_value_token = $1.tmesh_parser_value_token; } |
| ; |
| |
| /* the 'alias' command: */ |
| command_alias: TMESH_TOKEN_ALIAS pathname pathname ';' |
| { |
| $$ = $2; |
| $$.tmesh_parser_value_strings[1] = $3.tmesh_parser_value_strings[0]; |
| $$.tmesh_parser_value_token = $1.tmesh_parser_value_token; |
| } |
| ; |
| |
| /* a pathname: */ |
| pathname: TMESH_TOKEN_PATHNAME |
| ; |
| |
| /* an optional pathname: */ |
| pathname_opt: TMESH_TOKEN_PATHNAME |
| | /* empty */ |
| { $$.tmesh_parser_value_strings[0] = NULL; } |
| ; |
| |
| /* a pathname followed by optional arguments: */ |
| pathname_args: TMESH_TOKEN_PATHNAME |
| { |
| _tmesh_parser_argv_arg(&$$.tmesh_parser_value_argvs[0], |
| $1.tmesh_parser_value_pathname0, |
| TRUE); |
| _tmesh_scanner_in_args(); |
| } |
| | pathname_args TMESH_TOKEN_ARG |
| { |
| $$ = $1; |
| _tmesh_parser_argv_arg(&$$.tmesh_parser_value_argvs[0], |
| $2.tmesh_parser_value_arg, |
| FALSE); |
| } |
| ; |
| |
| /* arguments: */ |
| args: TMESH_TOKEN_ARG |
| { |
| _tmesh_parser_argv_arg(&$$.tmesh_parser_value_argvs[0], |
| $1.tmesh_parser_value_arg, |
| TRUE); |
| } |
| | args TMESH_TOKEN_ARG |
| { |
| $$ = $1; |
| _tmesh_parser_argv_arg(&$$.tmesh_parser_value_argvs[0], |
| $2.tmesh_parser_value_arg, |
| FALSE); |
| } |
| |
| /* a colon: */ |
| colon: ':' { _tmesh_scanner_in_args(); } ; |
| |
| /* an 'at': */ |
| at: TMESH_TOKEN_AT { _tmesh_scanner_in_args(); } ; |
| |
| /* a connection specification: */ |
| connection: pathname_args colon args |
| { |
| if ($1.tmesh_parser_value_argvs[0].tmesh_parser_argv_argc > 1) { |
| yyerror(_("expected 'at'")); |
| YYERROR; |
| } |
| $$.tmesh_parser_value_argvs[0] = $1.tmesh_parser_value_argvs[0]; |
| $$.tmesh_parser_value_argvs[1].tmesh_parser_argv_argv = NULL; |
| $$.tmesh_parser_value_argvs[2] = $3.tmesh_parser_value_argvs[0]; |
| } |
| | pathname_args at args colon args |
| { |
| $$.tmesh_parser_value_argvs[0] = $1.tmesh_parser_value_argvs[0]; |
| $$.tmesh_parser_value_argvs[1] = $3.tmesh_parser_value_argvs[0]; |
| $$.tmesh_parser_value_argvs[2] = $5.tmesh_parser_value_argvs[0]; |
| } |
| | pathname_args at args |
| { |
| $$.tmesh_parser_value_argvs[0] = $1.tmesh_parser_value_argvs[0]; |
| $$.tmesh_parser_value_argvs[1] = $3.tmesh_parser_value_argvs[0]; |
| $$.tmesh_parser_value_argvs[2].tmesh_parser_argv_argv = NULL; |
| } |
| ; |
| |
| /* options: */ |
| opts_opt: TMESH_TOKEN_OPTS |
| | /* empty */ |
| { $$.tmesh_parser_value_strings[0] = NULL; } |
| ; |
| |
| %% |
| |
| /* this adds a new argument to an argument vector: */ |
| static void |
| _tmesh_parser_argv_arg(struct tmesh_parser_argv *argv, char *arg, int new) |
| { |
| |
| /* if we're starting a new argv, allocate the initial vector, else |
| make sure the argv has enough room for the new argument and a |
| trailing NULL that _tmesh_command_connect will add later: */ |
| if (new) { |
| argv->tmesh_parser_argv_size = 8; |
| argv->tmesh_parser_argv_argv = |
| _tmesh_gc_new(_tmesh_input, |
| char *, |
| argv->tmesh_parser_argv_size); |
| argv->tmesh_parser_argv_argc = 0; |
| } |
| else if ((argv->tmesh_parser_argv_argc + 1) |
| >= argv->tmesh_parser_argv_size) { |
| argv->tmesh_parser_argv_size += |
| (2 |
| + (argv->tmesh_parser_argv_size >> 1)); |
| argv->tmesh_parser_argv_argv = |
| _tmesh_gc_renew(_tmesh_input, |
| char *, |
| argv->tmesh_parser_argv_argv, |
| argv->tmesh_parser_argv_size); |
| } |
| |
| /* put in the new argument: */ |
| argv->tmesh_parser_argv_argv[argv->tmesh_parser_argv_argc++] = arg; |
| } |
| |
| /* this is called by the parser when it encounters an error: */ |
| static void |
| yyerror(char *msg) |
| { |
| tme_output_append(_tmesh_output, msg); |
| _tmesh_input->tmesh_scanner.tmesh_scanner_in_args = FALSE; |
| } |
| |
| /* this is called by the parser when args can be expected: */ |
| static void |
| _tmesh_scanner_in_args(void) |
| { |
| _tmesh_input->tmesh_scanner.tmesh_scanner_in_args = TRUE; |
| } |
| |
| /* this matches a collected token: */ |
| static int |
| _tmesh_scanner_token(struct tmesh_scanner *scanner) |
| { |
| int token; |
| char *string; |
| int keep_string; |
| |
| /* if we have no collected token, return no token: */ |
| if (scanner->tmesh_scanner_token_string_size == 0 |
| || scanner->tmesh_scanner_token_string_len == 0) { |
| return (TMESH_TOKEN_UNDEF); |
| } |
| |
| /* get the collected token: */ |
| string = scanner->tmesh_scanner_token_string; |
| string[scanner->tmesh_scanner_token_string_len] = '\0'; |
| |
| /* assume we won't need to keep this string: */ |
| keep_string = FALSE; |
| |
| /* the reserved word "at" is always recognized, since it can |
| terminate a list of arguments: */ |
| if (!strcmp(string, "at")) { |
| token = TMESH_TOKEN_AT; |
| scanner->tmesh_scanner_in_args = FALSE; |
| } |
| |
| /* if we're in arguments, every other collected token is an argument: */ |
| else if (scanner->tmesh_scanner_in_args) { |
| token = TMESH_TOKEN_ARG; |
| keep_string = TRUE; |
| } |
| |
| /* otherwise, if we're not in arguments, every other collected token |
| is either a reserved word, options, or a pathname: */ |
| else { |
| if (!strcmp(string, "source")) { |
| token = TMESH_TOKEN_SOURCE; |
| } |
| else if (!strcmp(string, "cd")) { |
| token = TMESH_TOKEN_CD; |
| } |
| else if (!strcmp(string, "pwd")) { |
| token = TMESH_TOKEN_CD; |
| } |
| else if (!strcmp(string, "ls")) { |
| token = TMESH_TOKEN_LS; |
| } |
| else if (!strcmp(string, "rm")) { |
| token = TMESH_TOKEN_RM; |
| } |
| else if (!strcmp(string, "connect")) { |
| token = TMESH_TOKEN_CONNECT; |
| } |
| else if (!strcmp(string, "mkdir")) { |
| token = TMESH_TOKEN_MKDIR; |
| } |
| else if (!strcmp(string, "rmdir")) { |
| token = TMESH_TOKEN_RMDIR; |
| } |
| else if (!strcmp(string, "mv")) { |
| token = TMESH_TOKEN_MV; |
| } |
| else if (!strcmp(string, "command")) { |
| token = TMESH_TOKEN_COMMAND; |
| } |
| else if (!strcmp(string, "log")) { |
| token = TMESH_TOKEN_LOG; |
| } |
| else if (!strcmp(string, "alias")) { |
| token = TMESH_TOKEN_ALIAS; |
| } |
| else if (string[0] == '-') { |
| token = TMESH_TOKEN_OPTS; |
| keep_string = TRUE; |
| } |
| else { |
| token = TMESH_TOKEN_PATHNAME; |
| keep_string = TRUE; |
| } |
| } |
| |
| /* if we need to keep this string, put it in yylval, else recycle it: */ |
| yylval.tmesh_parser_value_token = token; |
| if (keep_string) { |
| yylval.tmesh_parser_value_strings[0] = string; |
| scanner->tmesh_scanner_token_string_size = 0; |
| } |
| else { |
| yylval.tmesh_parser_value_strings[0] = NULL; |
| scanner->tmesh_scanner_token_string_len = 0; |
| } |
| |
| return (token); |
| } |
| |
| /* our scanner: */ |
| int |
| yylex(void) |
| { |
| struct tmesh_scanner *scanner; |
| struct tmesh_io_stack *stack; |
| struct tmesh_io *source; |
| int token, c; |
| |
| /* recover our scanner state: */ |
| scanner = &_tmesh_input->tmesh_scanner; |
| stack = _tmesh_input->tmesh_io_stack; |
| source = &stack->tmesh_io_stack_io; |
| |
| /* bump the input line: */ |
| source->tmesh_io_input_line += scanner->tmesh_scanner_next_line; |
| scanner->tmesh_scanner_next_line = 0; |
| |
| /* if we previously scanned the next token to return, return it |
| and clear it, unless it's EOF, which sticks: */ |
| token = scanner->tmesh_scanner_token_next; |
| if (token != TMESH_TOKEN_UNDEF) { |
| if (token != TMESH_TOKEN_EOF) { |
| scanner->tmesh_scanner_token_next = TMESH_TOKEN_UNDEF; |
| } |
| return (token); |
| } |
| |
| /* loop forever: */ |
| for (;;) { |
| |
| /* get the next character: */ |
| c = scanner->tmesh_scanner_c_next; |
| if (c == TMESH_C_UNDEF) { |
| c = (*source->tmesh_io_getc)(source); |
| } |
| scanner->tmesh_scanner_c_next = TMESH_C_UNDEF; |
| |
| /* if this is an EOF: */ |
| if (c == TMESH_C_EOF) { |
| |
| /* turn c into the EOF semicolon: */ |
| c = TMESH_C_EOF_SEMICOLON; |
| |
| /* if we have collected a token, save the EOF semicolon and return the token: */ |
| token = _tmesh_scanner_token(scanner); |
| if (token != TMESH_TOKEN_UNDEF) { |
| scanner->tmesh_scanner_c_next = c; |
| return (token); |
| } |
| } |
| |
| /* if this is an EOF semicolon: */ |
| if (c == TMESH_C_EOF_SEMICOLON) { |
| |
| /* quoted strings and comments (and commands, for that matter) cannot cross EOF boundaries: */ |
| scanner->tmesh_scanner_in_quotes = FALSE; |
| scanner->tmesh_scanner_in_comment = FALSE; |
| |
| /* close the now-finished source: */ |
| (*source->tmesh_io_close)(source, |
| (stack->tmesh_io_stack_next != NULL |
| ? &stack->tmesh_io_stack_next->tmesh_io_stack_io |
| : NULL)); |
| |
| /* pop the io stack: */ |
| _tmesh_input->tmesh_io_stack = stack->tmesh_io_stack_next; |
| tme_free(source->tmesh_io_name); |
| tme_free(stack); |
| |
| /* if we have emptied the source stack, we are really at EOF, |
| and the next time we're called we will return that: */ |
| stack = _tmesh_input->tmesh_io_stack; |
| source = &stack->tmesh_io_stack_io; |
| if (stack == NULL) { |
| scanner->tmesh_scanner_token_next = TMESH_TOKEN_EOF; |
| return (TMESH_TOKEN_EOF); |
| } |
| |
| /* return the EOF semicolon: */ |
| return (';'); |
| } |
| |
| /* if this is a yield: */ |
| if (c == TMESH_C_YIELD) { |
| |
| /* we are yielding: */ |
| _tmesh_input_yielding = TRUE; |
| |
| /* return an EOF token: */ |
| return (TMESH_TOKEN_EOF); |
| } |
| |
| /* if we're in a comment: */ |
| if (scanner->tmesh_scanner_in_comment) { |
| if (c != '\n') { |
| continue; |
| } |
| scanner->tmesh_scanner_in_comment = FALSE; |
| } |
| |
| /* if this is quotation marks: */ |
| if (c == '"') { |
| scanner->tmesh_scanner_in_quotes = !scanner->tmesh_scanner_in_quotes; |
| continue; |
| } |
| |
| /* other than quotation marks, every character either delimits |
| tokens or is collected into the current token: */ |
| if ( |
| |
| /* any character inside quotes is collected: */ |
| scanner->tmesh_scanner_in_quotes |
| |
| /* any alphanumeric character is collected: */ |
| || isalnum(c) |
| |
| /* any period, slash, hyphen, and underscore character is collected: */ |
| || c == '.' |
| || c == '/' |
| || c == '-' |
| || c == '_' |
| ) { |
| |
| /* allocate or grow the token buffer as needed. we always |
| make sure there's room for this new character, and a trailing |
| NUL that _tmesh_scanner_token may add: */ |
| if (scanner->tmesh_scanner_token_string_size == 0) { |
| scanner->tmesh_scanner_token_string_len = 0; |
| scanner->tmesh_scanner_token_string_size = 8; |
| scanner->tmesh_scanner_token_string = |
| _tmesh_gc_new(_tmesh_input, |
| char, |
| scanner->tmesh_scanner_token_string_size); |
| } |
| else if ((scanner->tmesh_scanner_token_string_len + 1) |
| >= scanner->tmesh_scanner_token_string_size) { |
| scanner->tmesh_scanner_token_string_size += |
| (2 |
| + (scanner->tmesh_scanner_token_string_size >> 1)); |
| scanner->tmesh_scanner_token_string = |
| _tmesh_gc_renew(_tmesh_input, |
| char, |
| scanner->tmesh_scanner_token_string, |
| scanner->tmesh_scanner_token_string_size); |
| } |
| |
| /* collect the character into the buffer: */ |
| scanner->tmesh_scanner_token_string[scanner->tmesh_scanner_token_string_len++] = c; |
| } |
| |
| /* delimit this token: */ |
| else { |
| |
| /* if we have collected a token, save the delimiter and return the token: */ |
| token = _tmesh_scanner_token(scanner); |
| if (token != TMESH_TOKEN_UNDEF) { |
| scanner->tmesh_scanner_c_next = c; |
| return (token); |
| } |
| |
| /* a carriage return or a newline becomes a semicolon, and |
| a pound sign begins a comment: */ |
| if (c == '\n') { |
| c = ';'; |
| scanner->tmesh_scanner_next_line = 1; |
| } |
| else if (c == '\r') { |
| c = ';'; |
| } |
| else if (c == '#') { |
| scanner->tmesh_scanner_in_comment = TRUE; |
| scanner->tmesh_scanner_in_args = FALSE; |
| continue; |
| } |
| |
| /* return a non-whitespace delimiter as a token, and this resets |
| the args state: */ |
| if (!isspace(c)) { |
| scanner->tmesh_scanner_in_args = FALSE; |
| return (c); |
| } |
| } |
| } |
| /* NOTREACHED */ |
| } |
| |
| /* this is called to parse input: */ |
| int |
| _tmesh_yyparse(struct tmesh *tmesh, struct tmesh_parser_value *value, char **_output, int *_yield) |
| { |
| struct tmesh_scanner *scanner; |
| int rc; |
| int command; |
| |
| /* initialize the scanner: */ |
| scanner = &tmesh->tmesh_scanner; |
| scanner->tmesh_scanner_token_next = TMESH_TOKEN_UNDEF; |
| scanner->tmesh_scanner_c_next = TMESH_C_UNDEF; |
| scanner->tmesh_scanner_in_comment = FALSE; |
| scanner->tmesh_scanner_in_quotes = FALSE; |
| scanner->tmesh_scanner_in_args = FALSE; |
| scanner->tmesh_scanner_token_string_size = 0; |
| |
| /* lock the input mutex: */ |
| tme_mutex_lock(&_tmesh_input_mutex); |
| |
| /* set this tmesh for input: */ |
| _tmesh_input = tmesh; |
| _tmesh_output = _output; |
| |
| /* assume that we will not have to yield: */ |
| _tmesh_input_yielding = FALSE; |
| |
| /* call the parser: */ |
| _tmesh_input_parsed = value; |
| rc = (yyparse() |
| ? EINVAL |
| : TME_OK); |
| |
| /* tell our caller if we're yielding: */ |
| *_yield = _tmesh_input_yielding; |
| |
| /* unlock the input mutex: */ |
| tme_mutex_unlock(&_tmesh_input_mutex); |
| |
| /* if the parse was successful, map the command token number to a command number: */ |
| if (rc == TME_OK && !*_yield) { |
| switch (value->tmesh_parser_value_token) { |
| default: assert(FALSE); |
| case TMESH_TOKEN_UNDEF: command = TMESH_COMMAND_NOP; break; |
| case TMESH_TOKEN_SOURCE: command = TMESH_COMMAND_SOURCE; break; |
| case TMESH_TOKEN_MKDIR: command = TMESH_COMMAND_MKDIR; break; |
| case TMESH_TOKEN_RMDIR: command = TMESH_COMMAND_RMDIR; break; |
| case TMESH_TOKEN_CD: command = TMESH_COMMAND_CD; break; |
| case TMESH_TOKEN_PWD: command = TMESH_COMMAND_PWD; break; |
| case TMESH_TOKEN_LS: command = TMESH_COMMAND_LS; break; |
| case TMESH_TOKEN_CONNECT: command = TMESH_COMMAND_CONNECT; break; |
| case TMESH_TOKEN_RM: command = TMESH_COMMAND_RM; break; |
| case TMESH_TOKEN_COMMAND: command = TMESH_COMMAND_COMMAND; break; |
| case TMESH_TOKEN_LOG: command = TMESH_COMMAND_LOG; break; |
| case TMESH_TOKEN_ALIAS: command = TMESH_COMMAND_ALIAS; break; |
| } |
| value->tmesh_parser_value_command = command; |
| } |
| |
| /* done: */ |
| return (rc); |
| } |