finishInput(int exitstatus, void *arg) #endif { #ifdef USE_READLINE if (useHistory) { char *home; char *psql_history; home = getenv("HOME"); if (home) { psql_history = (char *) malloc(strlen(home) + 1 + strlen(PSQLHISTORY) + 1); if (psql_history) { int hist_size; hist_size = GetVariableNum(pset.vars, "HISTSIZE", -1, -1, true); if (hist_size >= 0) stifle_history(hist_size); sprintf(psql_history, "%s/%s", home, PSQLHISTORY); write_history(psql_history); free(psql_history); } } } #endif }
void CMatrixDoc::TurnString(CString &sdata) { CString * pVal=NULL; int num=GetVariableNum(sdata,pVal); int debug=num; for(int i=0;i<num;i++) { sdata.Replace(pVal[i],"@"); } CString temp=sdata; num=0; for(int j=0;j<lstrlen(temp);j++) { if(temp[j]!=TCHAR(' ')) { sdata.SetAt(num,temp[j]); num++; } else continue; } if(num<lstrlen(temp)) { sdata.SetAt(num,'\0'); sdata.GetBufferSetLength(lstrlen(sdata)); } if(pVal!=NULL) delete []pVal; }
finishInput(int exitstatus, void *arg) #endif { #ifdef USE_READLINE if (useHistory && psql_history) { int hist_size; hist_size = GetVariableNum(pset.vars, "HISTSIZE", 500, -1, true); saveHistory(psql_history, hist_size, true, true); free(psql_history); psql_history = NULL; } #endif }
static void finishInput(void) { #ifdef USE_READLINE if (useHistory && psql_history) { int hist_size; hist_size = GetVariableNum(pset.vars, "HISTSIZE", 500, -1, true); (void) saveHistory(psql_history, hist_size); free(psql_history); psql_history = NULL; } #endif }
/* * Main processing loop for reading lines of input * and sending them to the backend. * * This loop is re-entrant. May be called by \i command * which reads input from a file. */ int MainLoop(FILE *source) { PsqlScanState scan_state; /* lexer working state */ volatile PQExpBuffer query_buf; /* buffer for query being accumulated */ volatile PQExpBuffer previous_buf; /* if there isn't anything in the new * buffer yet, use this one for \e, * etc. */ PQExpBuffer history_buf; /* earlier lines of a multi-line command, not * yet saved to readline history */ char *line; /* current line of input */ int added_nl_pos; bool success; bool line_saved_in_history; volatile int successResult = EXIT_SUCCESS; volatile backslashResult slashCmdStatus = PSQL_CMD_UNKNOWN; volatile promptStatus_t prompt_status = PROMPT_READY; volatile int count_eof = 0; volatile bool die_on_error = false; /* Save the prior command source */ FILE *prev_cmd_source; bool prev_cmd_interactive; uint64 prev_lineno; /* Save old settings */ prev_cmd_source = pset.cur_cmd_source; prev_cmd_interactive = pset.cur_cmd_interactive; prev_lineno = pset.lineno; /* Establish new source */ pset.cur_cmd_source = source; pset.cur_cmd_interactive = ((source == stdin) && !pset.notty); pset.lineno = 0; /* Create working state */ scan_state = psql_scan_create(); query_buf = createPQExpBuffer(); previous_buf = createPQExpBuffer(); history_buf = createPQExpBuffer(); if (PQExpBufferBroken(query_buf) || PQExpBufferBroken(previous_buf) || PQExpBufferBroken(history_buf)) { psql_error("out of memory\n"); exit(EXIT_FAILURE); } /* main loop to get queries and execute them */ while (successResult == EXIT_SUCCESS) { /* * Clean up after a previous Control-C */ if (cancel_pressed) { if (!pset.cur_cmd_interactive) { /* * You get here if you stopped a script with Ctrl-C. */ successResult = EXIT_USER; break; } cancel_pressed = false; } /* * Establish longjmp destination for exiting from wait-for-input. We * must re-do this each time through the loop for safety, since the * jmpbuf might get changed during command execution. */ if (sigsetjmp(sigint_interrupt_jmp, 1) != 0) { /* got here with longjmp */ /* reset parsing state */ psql_scan_finish(scan_state); psql_scan_reset(scan_state); resetPQExpBuffer(query_buf); resetPQExpBuffer(history_buf); count_eof = 0; slashCmdStatus = PSQL_CMD_UNKNOWN; prompt_status = PROMPT_READY; cancel_pressed = false; if (pset.cur_cmd_interactive) putc('\n', stdout); else { successResult = EXIT_USER; break; } } fflush(stdout); /* * get another line */ if (pset.cur_cmd_interactive) { /* May need to reset prompt, eg after \r command */ if (query_buf->len == 0) prompt_status = PROMPT_READY; line = gets_interactive(get_prompt(prompt_status)); } else { line = gets_fromFile(source); if (!line && ferror(source)) successResult = EXIT_FAILURE; } /* * query_buf holds query already accumulated. line is the malloc'd * new line of input (note it must be freed before looping around!) */ /* No more input. Time to quit, or \i done */ if (line == NULL) { if (pset.cur_cmd_interactive) { /* This tries to mimic bash's IGNOREEOF feature. */ count_eof++; if (count_eof < GetVariableNum(pset.vars, "IGNOREEOF", 0, 10, false)) { if (!pset.quiet) printf(_("Use \"\\q\" to leave %s.\n"), pset.progname); continue; } puts(pset.quiet ? "" : "\\q"); } break; } count_eof = 0; pset.lineno++; /* ignore UTF-8 Unicode byte-order mark */ if (pset.lineno == 1 && pset.encoding == PG_UTF8 && strncmp(line, "\xef\xbb\xbf", 3) == 0) memmove(line, line + 3, strlen(line + 3) + 1); /* nothing left on line? then ignore */ if (line[0] == '\0' && !psql_scan_in_quote(scan_state)) { free(line); continue; } /* A request for help? Be friendly and give them some guidance */ if (pset.cur_cmd_interactive && query_buf->len == 0 && pg_strncasecmp(line, "help", 4) == 0 && (line[4] == '\0' || line[4] == ';' || isspace((unsigned char) line[4]))) { free(line); puts(_("You are using psql, the command-line interface to PostgreSQL.")); printf(_("Type: \\copyright for distribution terms\n" " \\h for help with SQL commands\n" " \\? for help with psql commands\n" " \\g or terminate with semicolon to execute query\n" " \\q to quit\n")); fflush(stdout); continue; } /* echo back if flag is set */ if (pset.echo == PSQL_ECHO_ALL && !pset.cur_cmd_interactive) puts(line); fflush(stdout); /* insert newlines into query buffer between source lines */ if (query_buf->len > 0) { appendPQExpBufferChar(query_buf, '\n'); added_nl_pos = query_buf->len; } else added_nl_pos = -1; /* flag we didn't add one */ /* Setting this will not have effect until next line. */ die_on_error = pset.on_error_stop; /* * Parse line, looking for command separators. */ psql_scan_setup(scan_state, line, strlen(line)); success = true; line_saved_in_history = false; while (success || !die_on_error) { PsqlScanResult scan_result; promptStatus_t prompt_tmp = prompt_status; scan_result = psql_scan(scan_state, query_buf, &prompt_tmp); prompt_status = prompt_tmp; if (PQExpBufferBroken(query_buf)) { psql_error("out of memory\n"); exit(EXIT_FAILURE); } /* * Send command if semicolon found, or if end of line and we're in * single-line mode. */ if (scan_result == PSCAN_SEMICOLON || (scan_result == PSCAN_EOL && pset.singleline)) { /* * Save query in history. We use history_buf to accumulate * multi-line queries into a single history entry. */ if (pset.cur_cmd_interactive && !line_saved_in_history) { pg_append_history(line, history_buf); pg_send_history(history_buf); line_saved_in_history = true; } /* execute query */ success = SendQuery(query_buf->data); slashCmdStatus = success ? PSQL_CMD_SEND : PSQL_CMD_ERROR; /* transfer query to previous_buf by pointer-swapping */ { PQExpBuffer swap_buf = previous_buf; previous_buf = query_buf; query_buf = swap_buf; } resetPQExpBuffer(query_buf); added_nl_pos = -1; /* we need not do psql_scan_reset() here */ } else if (scan_result == PSCAN_BACKSLASH) { /* handle backslash command */ /* * If we added a newline to query_buf, and nothing else has * been inserted in query_buf by the lexer, then strip off the * newline again. This avoids any change to query_buf when a * line contains only a backslash command. Also, in this * situation we force out any previous lines as a separate * history entry; we don't want SQL and backslash commands * intermixed in history if at all possible. */ if (query_buf->len == added_nl_pos) { query_buf->data[--query_buf->len] = '\0'; pg_send_history(history_buf); } added_nl_pos = -1; /* save backslash command in history */ if (pset.cur_cmd_interactive && !line_saved_in_history) { pg_append_history(line, history_buf); pg_send_history(history_buf); line_saved_in_history = true; } /* execute backslash command */ slashCmdStatus = HandleSlashCmds(scan_state, query_buf->len > 0 ? query_buf : previous_buf); success = slashCmdStatus != PSQL_CMD_ERROR; if ((slashCmdStatus == PSQL_CMD_SEND || slashCmdStatus == PSQL_CMD_NEWEDIT) && query_buf->len == 0) { /* copy previous buffer to current for handling */ appendPQExpBufferStr(query_buf, previous_buf->data); } if (slashCmdStatus == PSQL_CMD_SEND) { success = SendQuery(query_buf->data); /* transfer query to previous_buf by pointer-swapping */ { PQExpBuffer swap_buf = previous_buf; previous_buf = query_buf; query_buf = swap_buf; } resetPQExpBuffer(query_buf); /* flush any paren nesting info after forced send */ psql_scan_reset(scan_state); } else if (slashCmdStatus == PSQL_CMD_NEWEDIT) { /* rescan query_buf as new input */ psql_scan_finish(scan_state); free(line); line = pg_strdup(query_buf->data); resetPQExpBuffer(query_buf); /* reset parsing state since we are rescanning whole line */ psql_scan_reset(scan_state); psql_scan_setup(scan_state, line, strlen(line)); line_saved_in_history = false; prompt_status = PROMPT_READY; } else if (slashCmdStatus == PSQL_CMD_TERMINATE) break; } /* fall out of loop if lexer reached EOL */ if (scan_result == PSCAN_INCOMPLETE || scan_result == PSCAN_EOL) break; } /* Add line to pending history if we didn't execute anything yet */ if (pset.cur_cmd_interactive && !line_saved_in_history) pg_append_history(line, history_buf); psql_scan_finish(scan_state); free(line); if (slashCmdStatus == PSQL_CMD_TERMINATE) { successResult = EXIT_SUCCESS; break; } if (!pset.cur_cmd_interactive) { if (!success && die_on_error) successResult = EXIT_USER; /* Have we lost the db connection? */ else if (!pset.db) successResult = EXIT_BADCONN; } } /* while !endoffile/session */ /* * Process query at the end of file without a semicolon */ if (query_buf->len > 0 && !pset.cur_cmd_interactive && successResult == EXIT_SUCCESS) { /* save query in history */ if (pset.cur_cmd_interactive) pg_send_history(history_buf); /* execute query */ success = SendQuery(query_buf->data); if (!success && die_on_error) successResult = EXIT_USER; else if (pset.db == NULL) successResult = EXIT_BADCONN; } /* * Let's just make real sure the SIGINT handler won't try to use * sigint_interrupt_jmp after we exit this routine. If there is an outer * MainLoop instance, it will reset sigint_interrupt_jmp to point to * itself at the top of its loop, before any further interactive input * happens. */ sigint_interrupt_enabled = false; destroyPQExpBuffer(query_buf); destroyPQExpBuffer(previous_buf); destroyPQExpBuffer(history_buf); psql_scan_destroy(scan_state); pset.cur_cmd_source = prev_cmd_source; pset.cur_cmd_interactive = prev_cmd_interactive; pset.lineno = prev_lineno; return successResult; } /* MainLoop() */
/* * Main processing loop for reading lines of input * and sending them to the backend. * * This loop is re-entrant. May be called by \i command * which reads input from a file. */ int MainLoop(FILE *source) { PsqlScanState scan_state; /* lexer working state */ PQExpBuffer query_buf; /* buffer for query being accumulated */ PQExpBuffer previous_buf; /* if there isn't anything in the new * buffer yet, use this one for \e, etc. */ char *line; /* current line of input */ int added_nl_pos; bool success; volatile int successResult = EXIT_SUCCESS; volatile backslashResult slashCmdStatus = CMD_UNKNOWN; volatile promptStatus_t prompt_status = PROMPT_READY; volatile int count_eof = 0; volatile bool die_on_error = false; /* Save the prior command source */ FILE *prev_cmd_source; bool prev_cmd_interactive; unsigned int prev_lineno; /* Save old settings */ prev_cmd_source = pset.cur_cmd_source; prev_cmd_interactive = pset.cur_cmd_interactive; prev_lineno = pset.lineno; /* Establish new source */ pset.cur_cmd_source = source; pset.cur_cmd_interactive = ((source == stdin) && !pset.notty); pset.lineno = 0; /* Create working state */ scan_state = psql_scan_create(); query_buf = createPQExpBuffer(); previous_buf = createPQExpBuffer(); if (!query_buf || !previous_buf) { psql_error("out of memory\n"); exit(EXIT_FAILURE); } /* main loop to get queries and execute them */ while (successResult == EXIT_SUCCESS) { /* * Welcome code for Control-C */ if (cancel_pressed) { if (!pset.cur_cmd_interactive) { /* * You get here if you stopped a script with Ctrl-C and a * query cancel was issued. In that case we don't do the * longjmp, so the query routine can finish nicely. */ successResult = EXIT_USER; break; } cancel_pressed = false; } #ifndef WIN32 if (sigsetjmp(main_loop_jmp, 1) != 0) { /* got here with longjmp */ /* reset parsing state */ resetPQExpBuffer(query_buf); psql_scan_finish(scan_state); psql_scan_reset(scan_state); count_eof = 0; slashCmdStatus = CMD_UNKNOWN; prompt_status = PROMPT_READY; if (pset.cur_cmd_interactive) putc('\n', stdout); else { successResult = EXIT_USER; break; } } /* * establish the control-C handler only after main_loop_jmp is * ready */ pqsignal(SIGINT, handle_sigint); /* control-C => cancel */ #else /* WIN32 */ setup_cancel_handler(); #endif fflush(stdout); if (slashCmdStatus == CMD_NEWEDIT) { /* * just returned from editing the line? then just copy to the * input buffer */ line = pg_strdup(query_buf->data); /* reset parsing state since we are rescanning whole line */ resetPQExpBuffer(query_buf); psql_scan_reset(scan_state); slashCmdStatus = CMD_UNKNOWN; prompt_status = PROMPT_READY; } /* * otherwise, get another line */ else if (pset.cur_cmd_interactive) { /* May need to reset prompt, eg after \r command */ if (query_buf->len == 0) prompt_status = PROMPT_READY; line = gets_interactive(get_prompt(prompt_status)); } else line = gets_fromFile(source); /* * query_buf holds query already accumulated. line is the * malloc'd new line of input (note it must be freed before * looping around!) */ /* No more input. Time to quit, or \i done */ if (line == NULL) { if (pset.cur_cmd_interactive) { /* This tries to mimic bash's IGNOREEOF feature. */ count_eof++; if (count_eof < GetVariableNum(pset.vars, "IGNOREEOF", 0, 10, false)) { if (!QUIET()) printf(gettext("Use \"\\q\" to leave %s.\n"), pset.progname); continue; } puts(QUIET() ? "" : "\\q"); } break; } count_eof = 0; pset.lineno++; /* nothing left on line? then ignore */ if (line[0] == '\0' && !psql_scan_in_quote(scan_state)) { free(line); continue; } /* echo back if flag is set */ if (!pset.cur_cmd_interactive && VariableEquals(pset.vars, "ECHO", "all")) puts(line); fflush(stdout); /* insert newlines into query buffer between source lines */ if (query_buf->len > 0) { appendPQExpBufferChar(query_buf, '\n'); added_nl_pos = query_buf->len; } else added_nl_pos = -1; /* flag we didn't add one */ /* Setting this will not have effect until next line. */ die_on_error = GetVariableBool(pset.vars, "ON_ERROR_STOP"); /* * Parse line, looking for command separators. */ psql_scan_setup(scan_state, line, strlen(line)); success = true; while (success || !die_on_error) { PsqlScanResult scan_result; promptStatus_t prompt_tmp = prompt_status; scan_result = psql_scan(scan_state, query_buf, &prompt_tmp); prompt_status = prompt_tmp; /* * Send command if semicolon found, or if end of line and * we're in single-line mode. */ if (scan_result == PSCAN_SEMICOLON || (scan_result == PSCAN_EOL && GetVariableBool(pset.vars, "SINGLELINE"))) { /* execute query */ success = SendQuery(query_buf->data); slashCmdStatus = success ? CMD_SEND : CMD_ERROR; resetPQExpBuffer(previous_buf); appendPQExpBufferStr(previous_buf, query_buf->data); resetPQExpBuffer(query_buf); added_nl_pos = -1; /* we need not do psql_scan_reset() here */ } else if (scan_result == PSCAN_BACKSLASH) { /* handle backslash command */ /* * If we added a newline to query_buf, and nothing else * has been inserted in query_buf by the lexer, then strip * off the newline again. This avoids any change to * query_buf when a line contains only a backslash * command. */ if (query_buf->len == added_nl_pos) query_buf->data[--query_buf->len] = '\0'; added_nl_pos = -1; slashCmdStatus = HandleSlashCmds(scan_state, query_buf->len > 0 ? query_buf : previous_buf); success = slashCmdStatus != CMD_ERROR; if ((slashCmdStatus == CMD_SEND || slashCmdStatus == CMD_NEWEDIT) && query_buf->len == 0) { /* copy previous buffer to current for handling */ appendPQExpBufferStr(query_buf, previous_buf->data); } if (slashCmdStatus == CMD_SEND) { success = SendQuery(query_buf->data); resetPQExpBuffer(previous_buf); appendPQExpBufferStr(previous_buf, query_buf->data); resetPQExpBuffer(query_buf); /* flush any paren nesting info after forced send */ psql_scan_reset(scan_state); } if (slashCmdStatus == CMD_TERMINATE) break; } /* fall out of loop if lexer reached EOL */ if (scan_result == PSCAN_INCOMPLETE || scan_result == PSCAN_EOL) break; } psql_scan_finish(scan_state); free(line); if (slashCmdStatus == CMD_TERMINATE) { successResult = EXIT_SUCCESS; break; } if (!pset.cur_cmd_interactive) { if (!success && die_on_error) successResult = EXIT_USER; /* Have we lost the db connection? */ else if (!pset.db) successResult = EXIT_BADCONN; } } /* while !endoffile/session */ /* * Process query at the end of file without a semicolon */ if (query_buf->len > 0 && !pset.cur_cmd_interactive && successResult == EXIT_SUCCESS) { success = SendQuery(query_buf->data); if (!success && die_on_error) successResult = EXIT_USER; else if (pset.db == NULL) successResult = EXIT_BADCONN; } /* * Reset SIGINT handler because main_loop_jmp will be invalid as soon * as we exit this routine. If there is an outer MainLoop instance, * it will re-enable ^C catching as soon as it gets back to the top of * its loop and resets main_loop_jmp to point to itself. */ #ifndef WIN32 pqsignal(SIGINT, SIG_DFL); #endif destroyPQExpBuffer(query_buf); destroyPQExpBuffer(previous_buf); psql_scan_destroy(scan_state); pset.cur_cmd_source = prev_cmd_source; pset.cur_cmd_interactive = prev_cmd_interactive; pset.lineno = prev_lineno; return successResult; } /* MainLoop() */
BOOL CMatrixDoc::GetResult(const CString &data,CArrayMatrix & matrix) { //在这可以通过修改data字符串和m_VariablePtrList变量链表来实现 //具体方法是首先假如data是包含多个运算符的 CString sDataString=data; sDataString.TrimLeft("\n"); sDataString.TrimRight("\n"); CString *pVar; CArrayMatrix result; bool ok; int VarNum=GetVariableNum(sDataString,pVar); if(VarNum==0) return FALSE; CTypedPtrList<CObList,CArrayMatrix *> tpVarList; if(!StringsToMatrixs(pVar,tpVarList,VarNum)) { if(pVar!=NULL) delete []pVar; return FALSE; } TurnString(sDataString); //表达式求值 { sDataString=sDataString+"#"; CStack<TCHAR> OPTR; CStack<CArrayMatrix *> OPND; OPTR.Push('#'); int index=0; TCHAR c=sDataString[index]; int nVarIndex=0; while(c!=TCHAR('#')||OPTR.GetTop()!=TCHAR('#')) { if(!IsOperator(c)) { POSITION pos=tpVarList.GetHeadPosition(); CArrayMatrix * pt=NULL; for(int i=0;i<=nVarIndex&&i<tpVarList.GetCount();i++) { pt=tpVarList.GetAt(pos); tpVarList.GetNext(pos); } if(pt==NULL) return FALSE; OPND.Push(pt); nVarIndex++; index++; c=sDataString[index]; } else { switch(Precede(OPTR.GetTop(),c)) { case -1: { OPTR.Push(c); index++; c=sDataString[index]; break; } case 0: { TCHAR x; OPTR.Pop(x); index++; c=sDataString[index]; break; } case 1: { TCHAR theta; OPTR.Pop(theta); CArrayMatrix * b=NULL; CArrayMatrix * a=NULL; OPND.Pop(b); OPND.Pop(a); OPND.Push(Operate(a,theta,b,ok)); break; } } } } result=*(OPND.GetTop()); } //销毁tpvarlist变量里面的东西 { POSITION pos=tpVarList.GetHeadPosition(); int len=tpVarList.GetCount(); for(int i=0;i<len;i++) { CArrayMatrix * tp=tpVarList.GetAt(pos); delete tp; tpVarList.GetNext(pos); } tpVarList.RemoveAll(); } if(pVar!=NULL) delete []pVar; if(!ok) return FALSE; matrix=result; return TRUE; }