diff options
Diffstat (limited to 'cpp/demo/book/map_filesystem/Parser.cpp')
-rw-r--r-- | cpp/demo/book/map_filesystem/Parser.cpp | 438 |
1 files changed, 438 insertions, 0 deletions
diff --git a/cpp/demo/book/map_filesystem/Parser.cpp b/cpp/demo/book/map_filesystem/Parser.cpp new file mode 100644 index 00000000000..cb4c3411d97 --- /dev/null +++ b/cpp/demo/book/map_filesystem/Parser.cpp @@ -0,0 +1,438 @@ +// ********************************************************************** +// +// Copyright (c) 2003-2009 ZeroC, Inc. All rights reserved. +// +// This copy of Ice is licensed to you under the terms described in the +// ICE_LICENSE file included in this distribution. +// +// ********************************************************************** + +#include <IceUtil/DisableWarnings.h> +#include <Parser.h> + +#ifdef HAVE_READLINE +# include <readline/readline.h> +# include <readline/history.h> +#endif + +using namespace std; +using namespace Filesystem; + +extern FILE* yyin; + +Parser* parser; + +Parser::Parser(const DirectoryPrx& root) +{ + _dirs.push_front(root); +} + +void +Parser::usage() +{ + cout << + "help Print this message.\n" + "pwd Print current directory (/ = root).\n" + "cd [DIR] Change directory (/ or empty = root).\n" + "ls List current directory.\n" + "lr Recursively list current directory.\n" + "mkdir DIR [DIR...] Create directories DIR in current directory.\n" + "mkfile FILE [FILE...] Create files FILE in current directory.\n" + "rm NAME [NAME...] Delete directory or file NAME (rm * to delete all).\n" + "cat FILE List the contents of FILE.\n" + "write FILE [STRING...] Write STRING to FILE.\n" + "exit, quit Exit this program.\n"; +} + +// Print the contents of directory "dir". If recursive is true, +// print in tree fashion. +// For files, show the contents of each file. The "depth" +// parameter is the current nesting level (for indentation). + +void +Parser::list(bool recursive) +{ + list(_dirs.front(), recursive, 0); +} + +void +Parser::list(const DirectoryPrx& dir, bool recursive, int depth) +{ + string indent(depth++, '\t'); + + NodeDescSeq contents = dir->list(); + + for(NodeDescSeq::const_iterator i = contents.begin(); i != contents.end(); ++i) + { + DirectoryPrx d = i->type == DirType ? DirectoryPrx::uncheckedCast(i->proxy) : (DirectoryPrx)0; + cout << indent << i->name << (d ? " (directory)" : " (file)"); + if(d && recursive) + { + cout << ":" << endl; + list(d, true, depth); + } + else + { + cout << endl; + } + } +} + +void +Parser::createFile(const std::list<string>& names) +{ + DirectoryPrx dir = _dirs.front(); + + for(std::list<string>::const_iterator i = names.begin(); i != names.end(); ++i) + { + if(*i == "..") + { + cout << "Cannot create a file named `..'" << endl; + continue; + } + + try + { + dir->createFile(*i); + } + catch(const NameInUse&) + { + cout << "`" << *i << "' exists already" << endl; + } + } +} + +void +Parser::createDir(const std::list<string>& names) +{ + DirectoryPrx dir = _dirs.front(); + + for(std::list<string>::const_iterator i = names.begin(); i != names.end(); ++i) + { + if(*i == "..") + { + cout << "Cannot create a directory named `.'" << endl; + continue; + } + + try + { + dir->createDirectory(*i); + } + catch(const NameInUse&) + { + cout << "`" << *i << "' exists already" << endl; + } + } +} + +void +Parser::pwd() +{ + if(_dirs.size() == 1) + { + cout << "/"; + } + else + { + // COMPILERFIX: Should be const_reverse_iterator, but that won't compile with + // gcc because operator!= is missing. + // + std::list<DirectoryPrx>::reverse_iterator i = _dirs.rbegin(); + ++i; + while(i != _dirs.rend()) + { + cout << "/" << (*i)->name(); + ++i; + } + } + cout << endl; +} + +void +Parser::cd(const string& name) +{ + if(name == "/") + { + while(_dirs.size() > 1) + { + _dirs.pop_front(); + } + return; + } + + if(name == "..") + { + if(_dirs.size() > 1) + { + _dirs.pop_front(); + } + return; + } + + DirectoryPrx dir = _dirs.front(); + NodeDesc d; + try + { + d = dir->find(name); + } + catch(const NoSuchName&) + { + cout << "`" << name << "': no such directory" << endl; + return; + } + if(d.type == FileType) + { + cout << "`" << name << "': not a directory" << endl; + return; + } + _dirs.push_front(DirectoryPrx::uncheckedCast(d.proxy)); +} + +void +Parser::cat(const string& name) +{ + DirectoryPrx dir = _dirs.front(); + NodeDesc d; + try + { + d = dir->find(name); + } + catch(const NoSuchName&) + { + cout << "`" << name << "': no such file" << endl; + return; + } + if(d.type == DirType) + { + cout << "`" << name << "': not a file" << endl; + return; + } + FilePrx f = FilePrx::uncheckedCast(d.proxy); + Lines l = f->read(); + for(Lines::const_iterator i = l.begin(); i != l.end(); ++i) + { + cout << *i << endl; + } +} + +void +Parser::write(std::list<string>& args) +{ + DirectoryPrx dir = _dirs.front(); + string name = args.front(); + args.pop_front(); + NodeDesc d; + try + { + d = dir->find(name); + } + catch(const NoSuchName&) + { + cout << "`" << name << "': no such file" << endl; + return; + } + if(d.type == DirType) + { + cout << "`" << name << "': not a file" << endl; + return; + } + FilePrx f = FilePrx::uncheckedCast(d.proxy); + + Lines l; + for(std::list<string>::const_iterator i = args.begin(); i != args.end(); ++i) + { + l.push_back(*i); + } + f->write(l); +} + +void +Parser::destroy(const std::list<string>& names) +{ + DirectoryPrx dir = _dirs.front(); + + for(std::list<string>::const_iterator i = names.begin(); i != names.end(); ++i) + { + if(*i == "*") + { + NodeDescSeq nodes = dir->list(); + for(NodeDescSeq::iterator j = nodes.begin(); j != nodes.end(); ++j) + { + try + { + j->proxy->destroy(); + } + catch(const PermissionDenied& ex) + { + cout << "cannot remove `" << j->name << "': " << ex.reason << endl; + } + } + return; + } + else + { + NodeDesc d; + try + { + d = dir->find(*i); + } + catch(const NoSuchName&) + { + cout << "`" << *i << "': no such file or directory" << endl; + return; + } + try + { + d.proxy->destroy(); + } + catch(const PermissionDenied& ex) + { + cout << "cannot remove `" << *i << "': " << ex.reason << endl; + } + } + } +} + +void +Parser::getInput(char* buf, int& result, int maxSize) +{ +#ifdef HAVE_READLINE + + const char* prompt = parser->getPrompt(); + char* line = readline(const_cast<char*>(prompt)); + if(!line) + { + result = 0; + } + else + { + if(*line) + { + add_history(line); + } + + result = strlen(line) + 1; + if(result > maxSize) + { + free(line); + error("input line too long"); + result = 0; + } + else + { + strcpy(buf, line); + strcat(buf, "\n"); + free(line); + } + } + +#else + + cout << parser->getPrompt() << flush; + + string line; + while(true) + { + char c = static_cast<char>(getc(yyin)); + if(c == EOF) + { + if(line.size()) + { + line += '\n'; + } + break; + } + + line += c; + + if(c == '\n') + { + break; + } + } + + result = static_cast<int>(line.length()); + if(result > maxSize) + { + error("input line too long"); + buf[0] = EOF; + result = 1; + } + else + { + strcpy(buf, line.c_str()); + } + +#endif +} + +void +Parser::continueLine() +{ + _continue = true; +} + +const char* +Parser::getPrompt() +{ + if(_continue) + { + _continue = false; + return "(cont) "; + } + else + { + return "> "; + } +} + +void +Parser::error(const char* s) +{ + cerr << "error: " << s << endl; + _errors++; +} + +void +Parser::error(const string& s) +{ + error(s.c_str()); +} + +void +Parser::warning(const char* s) +{ + cerr << "warning: " << s << endl; +} + +void +Parser::warning(const string& s) +{ + warning(s.c_str()); +} + +int +Parser::parse(bool debug) +{ + extern int yydebug; + yydebug = debug ? 1 : 0; + + assert(!parser); + parser = this; + + _errors = 0; + yyin = stdin; + assert(yyin); + + _continue = false; + + int status = yyparse(); + if(_errors) + { + status = EXIT_FAILURE; + } + + parser = 0; + return status; +} |