static char * CompletionFunction(const char *text, int state) { char *cp; char *cmdstart; ArgvInfo ai; int bUsed; CommandPtr cmdp; static int flags; if (state == 0) { flags = -1; cmdstart = FindStartOfCurrentCommand(); if (cmdstart == NULL) return NULL; if (HaveCommandNameOnly(cmdstart)) { flags = -2; /* special case */ cp = CommandCompletionFunction(text, state); return cp; } (void) memset(&ai, 0, sizeof(ai)); bUsed = MakeArgv(cmdstart, &ai.cargc, ai.cargv, (int) (sizeof(ai.cargv) / sizeof(char *)), ai.argbuf, sizeof(ai.argbuf), ai.noglobargv, 1); if (bUsed <= 0) return NULL; if (ai.cargc == 0) return NULL; cmdp = GetCommandByName(ai.cargv[0], 0); if (cmdp == kAmbiguousCommand) { return NULL; } else if (cmdp == kNoCommand) { return NULL; } flags = cmdp->flags; } if (flags == (-2)) { cp = CommandCompletionFunction(text, state); return cp; } if (flags < 0) return NULL; if ((flags & (kCompleteLocalFile|kCompleteLocalDir)) != 0) { cp = gl_local_filename_completion_proc(text, state); return cp; } else if ((flags & kCompleteRemoteFile) != 0) { gl_filename_quoting_desired = 1; cp = RemoteFileCompletionFunction(text, state); return cp; } else if ((flags & kCompleteRemoteDir) != 0) { gl_filename_quoting_desired = 1; cp = RemoteDirCompletionFunction(text, state); return cp; } else if ((flags & kCompleteBookmark) != 0) { cp = BookmarkCompletionFunction(text, state); return cp; } else if ((flags & kCompletePrefOpt) != 0) { cp = PrefOptCompletionFunction(text, state); return cp; } return NULL; } /* CompletionFunction */
ZChatCmd* ZChatCmdManager::MakeArgv(char* szLine, ZChatCmdArgvInfo* pAI) { int nLen = (int)strlen(szLine); if (nLen >= 2048) NULL; char szBuffer[2048]; strcpy(szBuffer, szLine); // 문자열 끝의 스페이스 제거 for (int pos = nLen-1; pos >= 0; pos--) { if (IsSpace(szBuffer[pos])) szBuffer[pos] = '\0'; else break; } ZChatCmd* pCmd = NULL; int c; char* scp; char* dcp; char* dlim; char* arg; int nArgcMax, nCmdArgcMax; nCmdArgcMax = nArgcMax = (sizeof(pAI->cargv) / sizeof(char*)); scp = szBuffer; dcp = pAI->argbuf; dlim = dcp + sizeof(pAI->argbuf) - 1; for (pAI->cargc = 0; pAI->cargc < nArgcMax; ) { for ( ; ; scp++) { c = *scp; if (IsSpace(c)) continue; if ( (c == '\0') || (c == '\n') ) { pAI->cargv[pAI->cargc] = NULL; return pCmd; } break; } arg = dcp; pAI->cargv[pAI->cargc] = arg; (pAI->cargc)++; for ( ; ; ) { c = *scp; if ( (c == '\0') || (c == '\n')) break; // 마지막 인자는 무조건 문자열 마지막까지의 값이다. if (pAI->cargc != nCmdArgcMax) { if (IsSpace(c)) break; } scp++; // 작은 따옴표 처리 if (c == '\'') { // for ( ; ; ) // { // c = *scp++; // 따옴표가 하나만 있으면 널 리턴 // if (c == '\0') return NULL; // if (c == '\'') break; // 너무 길다 // if (dcp >= dlim) return NULL; *dcp++ = c; // } } else if (c == '"') // 큰따옴표처리 { // for ( ; ; ) // { // c = *scp++; // if (c == '\0') return NULL; // if (c == '"') break; // if (dcp >= dlim) return NULL; *dcp++ = c; // } } else { if (dcp >= dlim) return NULL; *dcp++ = c; } } *dcp++ = '\0'; if (pAI->cargc == 1) { pCmd = GetCommandByName(pAI->cargv[0]); if (pCmd != NULL) { if (pCmd->GetMaxArgs() != ARGVNoMin) { nCmdArgcMax = pCmd->GetMaxArgs() + 1; } } else { return NULL; } } } return NULL; }
/* Parse a command line into an array of arguments. */ int MakeArgv(char *line, int *cargc, const char **cargv, int cargcmax, char *dbuf, size_t dbufsize, int *noglobargv, int readlineHacks) { int c; int retval; char *dlim; char *dcp; char *scp; char *arg; *cargc = 0; scp = line; dlim = dbuf + dbufsize - 1; dcp = dbuf; for (*cargc = 0; *cargc < cargcmax; ) { /* Eat preceding junk. */ for ( ; ; scp++) { c = *scp; if (c == '\0') goto done; if (isspace(c)) continue; if ((c == ';') || (c == '\n')) { scp++; goto done; } break; } arg = dcp; cargv[*cargc] = arg; noglobargv[*cargc] = 0; (*cargc)++; /* Special hack so that "!cmd" is always split into "!" "cmd" */ if ((*cargc == 1) && (*scp == '!')) { if (scp[1] == '!') { scp[1] = '\0'; } else if ((scp[1] != '\0') && (!isspace((int) scp[1]))) { cargv[0] = "!"; scp++; arg = dcp; cargv[*cargc] = arg; noglobargv[*cargc] = 0; (*cargc)++; } } /* Add characters to the new argument. */ for ( ; ; ) { c = *scp; if (c == '\0') break; if (isspace(c)) break; if ((c == ';') || (c == '\n')) { break; } scp++; if (c == '\'') { for ( ; ; ) { c = *scp++; if (c == '\0') { if (readlineHacks != 0) break; /* Syntax error */ (void) fprintf(stderr, "Error: Unbalanced quotes.\n"); return (-1); } if (c == '\'') break; /* Add char. */ if (dcp >= dlim) goto toolong; *dcp++ = c; if (strchr(kGlobChars, c) != NULL) { /* User quoted glob characters, * so mark this argument for * noglob. */ noglobargv[*cargc - 1] = 1; } } } else if (c == '"') { for ( ; ; ) { c = *scp++; if (c == '\0') { if (readlineHacks != 0) break; /* Syntax error */ (void) fprintf(stderr, "Error: Unbalanced quotes.\n"); return (-1); } if (c == '"') break; /* Add char. */ if (dcp >= dlim) goto toolong; *dcp++ = c; if (strchr(kGlobChars, c) != NULL) { /* User quoted glob characters, * so mark this argument for * noglob. */ noglobargv[*cargc - 1] = 1; } } } else #if defined(WIN32) || defined(_WINDOWS) if (c == '|') { #else if (c == '\\') { #endif /* Add next character, verbatim. */ c = *scp++; if (c == '\0') break; /* Add char. */ if (dcp >= dlim) goto toolong; *dcp++ = c; } else { /* Add char. */ if (dcp >= dlim) goto toolong; *dcp++ = c; } } *dcp++ = '\0'; } (void) fprintf(stderr, "Error: Argument list too long.\n"); *cargc = 0; cargv[*cargc] = NULL; return (-1); done: retval = (int) (scp - line); cargv[*cargc] = NULL; return (retval); toolong: (void) fprintf(stderr, "Error: Line too long.\n"); *cargc = 0; cargv[*cargc] = NULL; return (-1); } /* MakeArgv */ static int DoCommand(const ArgvInfoPtr aip) { CommandPtr cmdp; int flags; int cargc, cargcm1; cmdp = GetCommandByName(aip->cargv[0], 0); if (cmdp == kAmbiguousCommand) { (void) printf("%s: ambiguous command name.\n", aip->cargv[0]); return (-1); } else if (cmdp == kNoCommand) { (void) printf("%s: no such command.\n", aip->cargv[0]); return (-1); } cargc = aip->cargc; cargcm1 = cargc - 1; flags = cmdp->flags; if (((flags & kCmdMustBeConnected) != 0) && (gConn.connected == 0)) { (void) printf("%s: must be connected to do that.\n", aip->cargv[0]); } else if (((flags & kCmdMustBeDisconnected) != 0) && (gConn.connected != 0)) { (void) printf("%s: must be disconnected to do that.\n", aip->cargv[0]); } else if ((cmdp->minargs != kNoMin) && (cmdp->minargs > cargcm1)) { PrintCmdUsage(cmdp); } else if ((cmdp->maxargs != kNoMax) && (cmdp->maxargs < cargcm1)) { PrintCmdUsage(cmdp); } else { (*cmdp->proc)(cargc, aip->cargv, cmdp, aip); } return (0); } /* DoCommand */