/************************************************************************** * * Queryer.cpp -- simple interactive query program * Copyright (C) 1999 Rodger McNab * * 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., 675 Mass Ave, Cambridge, MA 02139, USA. * **************************************************************************/ #define _XOPEN_SOURCE 1 #define _XOPEN_SOURCE_EXTENDED 1 /* getopt is in posix.2, so cygwin should have it in unistd, but doesn't */ #if defined (__WIN32__) || defined (__CYGWIN__) # include "getopt_old.h" #else # include #endif #include "MGQuery.h" #include "TextGet.h" #include "messages.h" #include "mg_files.h" #include "GSDLQueryParser.h" void printHelp() { cout << "commands available are:\n" << "\t.q\t\tquit\n" << "\t.h\t\tprint the help message\n" << "\t.i\t\tchange the search level (enter the new level at the prompt)\n" << "\t.l\t\tchange the result level ( \"\" \"\" )\n" << "\t.b\t\tfull text browse (enter a word or fragment at the prompt)\n" << "\t.r0/.r1\t\tranking off/on\n" << "\t.t0/.t1\t\tquery type some/all\n" << "\t.c0/.c1\t\tcasefolding off/on\n" << "\t.s0/.s1\t\tstemming off/on\n" << "\t.o0/.o1\t\tshort output off/on\n\n" << "\t.p\t\tprint a document (enter the docnum at the prompt)\n" << "otherwise just enter a query\n\n"; } int main (int argc, char **argv) { int ch; char *textfilename = ""; char *indexfilename = ""; char *basePath = ""; opterr = 0; msg_prefix = argv[0]; // process the command line arguments while ((ch = getopt (argc, argv, "f:t:d:h")) != -1) { switch (ch) { case 'f': /* input file */ indexfilename = optarg; break; case 't': textfilename = optarg; break; case 'd': basePath = optarg; set_basepath (basePath); break; case 'h': case '?': fprintf (stderr, "usage: %s [-h] [-d directory] -f indexname -t textname\n", argv[0]); exit (1); } } if (textfilename[0] == '\0' || indexfilename[0] == '\0') { FatalError (1, "Index and text file names must be specified with -f and -t \n"); } // init the text system TextData textData; if (!textData.LoadData (basePath, textfilename)) { FatalError (1, "Couldn't load text information for \"%s\"", textfilename); } // init the query system IndexData indexData; if (!indexData.LoadData (basePath, indexfilename)) { FatalError (1, "Couldn't load index information for \"%s\"", indexfilename); } // debug output cerr << "num docs: "< "; cin.getline(query, 2048, '\n'); SetCStr (queryArray, query); // check for commands if (queryArray.size() >= 2 && queryArray[0] == '.') { if (queryArray[1] == 'q') break; // quit if (queryArray[1] == 'h') { // help printHelp(); } else if (queryArray[1] == 'i') { cout << "current index="<< queryInfo.docLevel << "\nchange to index:"; cin >> query; UCArrayClear(queryInfo.docLevel); SetCStr(queryInfo.docLevel, query); cout << "index set to " << queryInfo.docLevel <<"\n"; cin.getline(query, 2048, '\n'); } else if (queryArray[1] == 'l') { cout << "current level="<< level << "\nchange to level:"; cin >> query; UCArrayClear(level); SetCStr(level, query); cout << "level set to " << level <<"\n"; cin.getline(query, 2048, '\n'); } else if (queryArray[1] == 'p') { // print UCArray docText; unsigned long docNum = 0; cin >> docNum; cin.getline(query, 2048, '\n'); // eat up return if (!GetDocText (textData, queryInfo.docLevel, docNum, docText)) { FatalError (1, "Error while trying to get document %u", docNum); } cout << docText << "\n"; } else if (queryArray[1] == 't') { // query type - all/some if (queryArray[2] == '1') defaultBoolCombine = 1; else if (queryArray[2] == '0') defaultBoolCombine = 0; else { cout << "Error: please enter .t0 (some) or .t1 (all)\n"; } } else if (queryArray[1] == 'r') { // ranking - on/off if (queryArray[2] == '1') queryInfo.sortByRank = true; else if (queryArray[2] == '0') queryInfo.sortByRank = false; else { cout << "Error: please enter .r0 (non-ranked) or .r1 (ranked)\n"; } } else if (queryArray[1] == 'c') { // casefolding - on/off if (queryArray[2] == '1') defaultStemMethod |= 1; else if (queryArray[2] == '0') defaultStemMethod &= 0xe; else { cout << "Error: please enter .c0 (case sensitive) or .c1 (casefolded)\n"; } } else if (queryArray[1] == 's') { // stemming - on/off if (queryArray[2] == '1') defaultStemMethod |=2; else if (queryArray[2] == '0') defaultStemMethod &=0xd; else { cout << "Error: please enter .s0 (unstemmed) or .s1 (stemmed)\n"; } } else if (queryArray[1] == 'o') { // output - short/long if (queryArray[2] == '1') shortOutput = true; else if (queryArray[2] == '0') shortOutput = false; else { cout << "Error: please enter .o0 (long output) or .o1 (short output)\n"; } } else if (queryArray[1] == 'b') { // full text browse cout<<"enter a few letters to start browsing from:"; cin>>query; UCArrayClear(browseNode.term); SetCStr(browseNode.term, query); cin.getline(query, 2048, '\n'); // get rest of line // print the query PrintNode (cout, &browseNode); MGBrowseQuery(indexData, docLevel, browseNode, browseResult); cout << browseResult; cout << "\n"; } else { // bad option cout << "bad command\n\n"; printHelp(); } } // if a .x query else { // regular query queryTree = ParseQuery (queryArray, defaultBoolCombine, defaultStemMethod); if (queryTree == NULL) { cout << "invalid syntax\n"; } else { // print the query PrintNode (cout, queryTree); MGQuery (indexData, queryInfo, queryTree, queryResult, level); if (shortOutput) { queryResult.printShort(cout); cout << "\n"; } else { cout << queryResult; cout << "\n"; } // delete the query delete queryTree; queryTree = NULL; } } } // clean up, everybody clean up textData.UnloadData (); indexData.UnloadData (); return (0); }