| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301 |
- /*
- * The contents of this file are subject to the Initial
- * Developer's Public License Version 1.0 (the "License");
- * you may not use this file except in compliance with the
- * License. You may obtain a copy of the License at
- * http://www.ibphoenix.com/main.nfs?a=ibphoenix&page=ibp_idpl.
- *
- * Software distributed under the License is distributed AS IS,
- * WITHOUT WARRANTY OF ANY KIND, either express or implied.
- * See the License for the specific language governing rights
- * and limitations under the License.
- *
- * The Original Code was created by Claudio Valderrama on 5-Oct-2007
- * for the Firebird Open Source RDBMS project.
- *
- * Copyright (c) 2007 Claudio Valderrama
- * and all contributors signed below.
- *
- * All Rights Reserved.
- * Contributor(s): ______________________________________.
- *
- */
- #include "firebird.h"
- #if defined(DARWIN) && !defined(IOS)
- #if defined(i386) || defined(__x86_64__)
- #include <architecture/i386/io.h>
- #else
- #include <io.h>
- #endif
- #endif
- #ifdef HAVE_UNISTD_H
- #include <unistd.h>
- #endif
- #include "../common/utils_proto.h"
- #include "InputDevices.h"
- using Firebird::PathName;
- InputDevices::indev::indev()
- : indev_fpointer(0), indev_line(0), indev_aux(0), indev_next(0),
- indev_fn(*getDefaultMemoryPool()), indev_fn_display(*getDefaultMemoryPool())
- {
- makeFullFileName();
- }
- InputDevices::indev::indev(FILE* fp, const char* fn, const char* fn_display)
- : indev_fpointer(fp), indev_line(0), indev_aux(0), indev_next(0),
- indev_fn(*getDefaultMemoryPool()), indev_fn_display(*getDefaultMemoryPool())
- {
- indev_fn = fn;
- indev_fn_display = fn_display;
- makeFullFileName();
- }
- // Performs the same task that one of the constructors, but called manually.
- // File handle and file name are assumed to be valid and the rest of the data
- // members aren't copied but reset.
- void InputDevices::indev::init(FILE* fp, const char* fn, const char* fn_display)
- {
- indev_fpointer = fp;
- indev_line = 0;
- indev_aux = 0;
- indev_fn = fn;
- indev_fn_display = fn_display;
- indev_next = 0;
- makeFullFileName();
- }
- // Copies only the file handle and file name from one indev to another.
- // File handle and file name are assumed to be valid.
- void InputDevices::indev::init(const indev& src)
- {
- indev_fpointer = src.indev_fpointer;
- indev_line = 0;
- indev_aux = 0;
- indev_fn = src.indev_fn;
- indev_fn_display = src.indev_fn_display;
- indev_next = 0;
- }
- //InputDevices::indev::~indev()
- //{
- // Nothing for now. Let the owner or caller close the file pointer if needed.
- //}
- // Initializes one indev with another. Useful for method of the owning class
- // that needs to copy from the input indev to the top of the stack and vice-versa.
- void InputDevices::indev::copy_from(const indev* src)
- {
- fb_assert(src);
- indev_fpointer = src->indev_fpointer;
- indev_line = src->indev_line;
- indev_aux = src->indev_aux;
- indev_fn = src->indev_fn;
- indev_fn_display = src->indev_fn_display;
- // indev_next not copied.
- }
- // Drop a file associated with an indev.
- void InputDevices::indev::drop()
- {
- fb_assert(indev_fpointer != stdin);
- fb_assert(!indev_fn.isEmpty()); // Some name should exist.
- fclose(indev_fpointer);
- unlink(indev_fn.c_str());
- }
- // Save the reading position in the parameter.
- void InputDevices::indev::getPos(fpos_t* out) const
- {
- fb_assert(out);
- fb_assert(indev_fpointer);
- fb_io::fgetpos(indev_fpointer, out);
- }
- // Restore a previously stored reading position held in the parameter.
- void InputDevices::indev::setPos(const fpos_t* in)
- {
- fb_assert(in);
- fb_assert(indev_fpointer);
- #ifdef SFIO
- // hack to fix bad sfio header
- fb_io::fsetpos(indev_fpointer, const_cast<fpos_t*>(in));
- #else
- fb_io::fsetpos(indev_fpointer, in);
- #endif
- }
- void InputDevices::indev::makeFullFileName()
- {
- if (!indev_fn.isEmpty() && PathUtils::isRelative(indev_fn))
- {
- PathName name = indev_fn;
- PathName path;
- fb_utils::getCwd(path);
- PathUtils::concatPath(indev_fn, path, name);
- }
- }
- // Clear the chain of indev, closing file handles.
- void InputDevices::clear(FILE* fpointer)
- {
- while (m_head)
- {
- FILE* const p = m_head->indev_fpointer;
- if (fpointer && p == fpointer)
- break;
- if (p != stdin && p != m_ofp.indev_fpointer)
- fclose(p);
- indev* const flist = m_head->indev_next;
- delete m_head;
- m_head = flist;
- --m_count;
- }
- if (m_ifp.indev_fpointer && // In case we called clear(NULL) manually before.
- m_ifp.indev_fpointer != stdin && m_ifp.indev_fpointer != m_ofp.indev_fpointer)
- {
- fclose(m_ifp.indev_fpointer);
- m_ifp.indev_fpointer = 0;
- }
- fb_assert(m_count == 0 || fpointer != 0);
- if (!fpointer)
- {
- m_head = 0;
- m_count = 0;
- }
- }
- // Insert an indev in the chain, always in LIFO way.
- bool InputDevices::insert(FILE* fp, const char* name, const char* display)
- {
- if (!m_head)
- {
- fb_assert(m_count == 0);
- m_head = FB_NEW indev(fp, name, display);
- }
- else
- {
- fb_assert(m_count > 0);
- indev* p = m_head;
- m_head = FB_NEW indev(fp, name, display);
- m_head->indev_next = p;
- }
- ++m_count;
- return true;
- }
- // Shortcut for inserting the currently input file in the indev chain.
- bool InputDevices::insertIfp()
- {
- if (insert(NULL, "", ""))
- {
- m_head->copy_from(&m_ifp);
- return true;
- }
- return false;
- }
- // Remove the top (last inserted) indev in the chain.
- bool InputDevices::remove()
- {
- if (m_head)
- {
- fb_assert(m_count > 0);
- indev* p = m_head;
- m_head = m_head->indev_next;
- delete p;
- --m_count;
- return true;
- }
- return false;
- }
- // Shortcut for moving the top indev in the chain to the current input file.
- void InputDevices::removeIntoIfp()
- {
- fb_assert(m_head && m_count > 0);
- m_ifp.copy_from(m_head);
- // When we come back from inout(), we continue inside the get_statement loop.
- // If we are inside do_isql() due to Ctrl-C, it doesn't cause any harm.
- m_ifp.indev_line = m_ifp.indev_aux;
- remove();
- }
- // Shortcut for testing whether current input and output handles are the same.
- // This may happen if we are reading from the command history file that's filled
- // automatically with every interactive SQL command (isql commands aren't logged).
- bool InputDevices::sameInputAndOutput() const
- {
- return m_ifp.indev_fpointer && (m_ifp.indev_fpointer == m_ofp.indev_fpointer);
- }
- // Save SQL command (not isql's own commands) to a history file only if we
- // are in interactive mode.
- void InputDevices::saveCommand(const char* statement, const char* term)
- {
- if (m_ifp.indev_fpointer == stdin)
- {
- FILE* f = m_ofp.indev_fpointer;
- if (f)
- {
- fputs(statement, f);
- fputs(term, f);
- // Add newline to make the file more readable.
- fputc('\n', f);
- }
- else
- {
- Command* command = FB_NEW Command(statement, term);
- commands.add(command);
- }
- }
- }
- // Are we reading from stdin now or from a file?
- bool InputDevices::readingStdin() const
- {
- fb_assert(m_ifp.indev_fpointer);
- return m_ifp.indev_fpointer == stdin;
- }
- // Go to end of file if we are reading from a file (not stdin).
- void InputDevices::gotoEof()
- {
- fb_assert(m_ifp.indev_fpointer);
- if (m_ifp.indev_fpointer != stdin)
- fseek(m_ifp.indev_fpointer, 0, SEEK_END);
- }
- InputDevices::Command::Command(const char* statement, const char* term)
- : m_statement(getPool())
- {
- m_statement = statement;
- m_statement += term;
- }
- void InputDevices::Command::toFile(FILE* f)
- {
- fputs(m_statement.c_str(), f);
- // Add newline to make the file more readable.
- fputc('\n', f);
- }
- void InputDevices::commandsToFile(FILE* f)
- {
- for (unsigned n = 0; n < commands.getCount(); ++n)
- {
- commands[n]->toFile(f);
- delete commands[n];
- }
- commands.clear();
- }
|