/* ** Copyright (C) 2002-2004 Daniel Caujolle-Bert ** ** This program is free software; you can redistribute it and/or modify ** it under the terms of the GNU General Public License as published by ** the Free Software Foundation; either version 2 of the License, or ** (at your option) any later version. ** ** This program is distributed in the hope that it will be useful, ** but WITHOUT ANY WARRANTY; without even the implied warranty of ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ** GNU General Public License for more details. ** ** You should have received a copy of the GNU General Public License ** along with this program; if not, write to the Free Software ** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. ** */ #ifdef HAVE_CONFIG_H #include "config.h" #endif #include #include #include #include #include "common.h" #include "utils.h" /* * Push first command in remain queue to current command. */ static void toxine_parse_destock_remain(toxine_t *tox) { char *p, *pp, *c; char *pbuf; char commandline[BUFSIZ]; char remaining[BUFSIZ]; /* * Remain and line are already filled, perhaps a forced command line * happen here: don't handle it here */ if((tox->command.remain) && (tox->command.line)) return; if((tox->command.remain == NULL) && (tox->command.line && (strchr(tox->command.line, ';')))) { tox->command.remain = strdup(tox->command.line); toxine_free(tox->command.line); } if(tox->command.remain && ((tox->command.line == NULL) || ((tox->command.line != NULL) && (strlen(tox->command.line) == 0)))) { memset(&commandline, 0, sizeof(commandline)); memset(&remaining, 0, sizeof(remaining)); if((p = strchr(tox->command.remain, ';')) != NULL) { pp = tox->command.remain; pbuf = commandline; while(pp < p) { *pbuf = *pp; pp++; pbuf++; } *pbuf = '\0'; if(strlen(commandline)) { c = &commandline[strlen(commandline)]; while((*c == ';') && (c >= commandline)) { *c = '\0'; c--; } } c = toxine_atoa(commandline); if(*p == ';') p++; if(p) sprintf(remaining, "%s", (toxine_atoa(p))); if(tox->command.line) tox->command.line = (char *) realloc(tox->command.line, sizeof(char *) * (strlen(c) + 1)); else tox->command.line = (char *) xine_xmalloc(sizeof(char *) * (strlen(c) + 1)); sprintf(tox->command.line, "%s", c); if(p) { /* remove last ';' */ if(strchr(remaining, ';')) { p = &remaining[strlen(remaining)]; while((*p == ';') && (p >= remaining)) { *p = '\0'; p--; } } if(strlen(remaining)) { tox->command.remain = (char *) realloc(tox->command.remain, sizeof(char *) * (strlen(remaining) + 1)); sprintf(tox->command.remain, "%s", remaining); } else { toxine_free(tox->command.remain); } } else { toxine_free(tox->command.remain); } } else { /* no ';' in remain, copy AS IS remain to line */ if(tox->command.line) tox->command.line = (char *) realloc(tox->command.line, sizeof(char *) * (strlen(tox->command.remain) + 1)); else tox->command.line = (char *) xine_xmalloc(sizeof(char *) * (strlen(tox->command.remain) + 1)); sprintf(tox->command.line, "%s", tox->command.remain); toxine_free(tox->command.remain); } } } /* * handle multicommand line. */ static void toxine_parse_handle_multicommands(toxine_t *tox) { if(tox->command.remain) perr("Ooch, Unexpected state, remain isn't empty\n"); else { tox->command.remain = strdup(tox->command.line); toxine_parse_destock_remain(tox); } } /* * parse command, extract arguments. */ void toxine_parse_command(toxine_t *tox) { char *cmd, *cmdl; int i = 0; toxine_parse_destock_remain(tox); if(strchr(tox->command.line, ';')) toxine_parse_handle_multicommands(tox); cmdl = tox->command.line; if(tox->command.num_args) { for(i = 0; i < tox->command.num_args; i++) memset(tox->command.args[i], 0, sizeof(tox->command.args[i])); } tox->command.num_args = 0; while((*cmdl == ' ') || (*cmdl == '\t')) cmdl++; cmd = cmdl; while(*cmd != '\0' && (*cmd != ' ' && *(cmd - 1) != '\\') && *cmd != '\t') cmd++; if(cmd >= (cmdl + strlen(cmdl))) cmd = NULL; if(cmd) { if(tox->command.command) tox->command.command = (char *) realloc(tox->command.command, strlen(cmdl) - strlen(cmd) + 1); else tox->command.command = (char *) xine_xmalloc(strlen(cmdl) - strlen(cmd) + 1); memset(tox->command.command, 0, sizeof(tox->command.command)); snprintf(tox->command.command, (strlen(cmdl) - strlen(cmd))+1, "%s", cmdl); cmd = toxine_atoa(cmd); /* * Extract and store args */ if(cmd < (cmdl + strlen(cmdl))) { char *pcmd, *pb, buf[256]; int nargs = 0; int get_quote = 0, get_dbl_quote = 0; pcmd = cmd; memset(&buf, 0, sizeof(buf)); pb = buf; while(*(pcmd - 1) != '\0') { switch(*pcmd) { case '"': case '\'': if(*(pcmd - 1) != '\\') { if(*pcmd == '\'') { if(!get_dbl_quote) get_quote++; } else if(*pcmd == '"') { if(!get_quote) get_dbl_quote++; } if(get_quote == 2) get_quote = 0; else if(get_dbl_quote == 2) get_dbl_quote = 0; } else { pb--; goto __store_char; } break; case '\t': if((!get_quote) && (!get_dbl_quote)) goto __end_args; else goto __store_char; break; case '\0': goto __end_args; break; case ' ': if((*(pcmd - 1) != '\\') && ((get_quote == 0) && (get_dbl_quote == 0))) { __end_args: sprintf(tox->command.args[nargs], "%s", buf); nargs++; memset(&buf, 0, sizeof(buf)); pb = buf; } else { if(*(pcmd - 1) == '\\') pb--; goto __store_char; } break; default: __store_char: *pb = *pcmd; pb++; break; } pcmd++; } tox->command.num_args = nargs; } } else { if(tox->command.command) tox->command.command = (char *) realloc(tox->command.command, strlen(cmdl) + 1); else tox->command.command = (char *) xine_xmalloc(strlen(cmdl) + 1); memset(tox->command.command, 0, sizeof(tox->command.command)); sprintf(tox->command.command, "%s", cmdl); } #if 0 { int k; pinfo("tox->command = '%s'\n", tox->command.command); if(tox->command.num_args) for(k = 0; k < tox->command.num_args; k++) pinfo("tox->command_arg[%d] = '%s'\n", k, tox->command.args[k]); } #endif }