/cpp/demo/Freeze/phonebook/Parser.cpp

https://bitbucket.org/cleto/zeroc-ice-package · C++ · 476 lines · 422 code · 46 blank · 8 comment · 37 complexity · 725073574e69cfe5d38b3bbc0c6007d4 MD5 · raw file

  1. // **********************************************************************
  2. //
  3. // Copyright (c) 2003-2013 ZeroC, Inc. All rights reserved.
  4. //
  5. // This copy of Ice is licensed to you under the terms described in the
  6. // ICE_LICENSE file included in this distribution.
  7. //
  8. // **********************************************************************
  9. #include <IceUtil/DisableWarnings.h>
  10. #include <Parser.h>
  11. #ifdef HAVE_READLINE
  12. # include <readline/readline.h>
  13. # include <readline/history.h>
  14. #endif
  15. using namespace std;
  16. using namespace Demo;
  17. extern FILE* yyin;
  18. Parser* parser;
  19. void
  20. Parser::usage()
  21. {
  22. cout <<
  23. "help Print this message.\n"
  24. "exit, quit Exit this program.\n"
  25. "add NAMES... Create new contacts for NAMES in the phonebook.\n"
  26. "find NAME Find all contacts in the phonebook that match NAME.\n"
  27. " Set the current contact to the first one found.\n"
  28. "next Set the current contact to the next one that was found.\n"
  29. "current Display the current contact.\n"
  30. "name NAME Set the name for the current contact to NAME.\n"
  31. "address ADDRESS Set the address for the current contact to ADDRESS.\n"
  32. "phone PHONE Set the phone number for the current contact to PHONE.\n"
  33. "remove Permanently remove the current contact from the phonebook.\n"
  34. "size SIZE Set the evictor size for contacts to SIZE.\n"
  35. "shutdown Shut the phonebook server down.\n";
  36. }
  37. Parser::Parser(const PhoneBookPrx& phoneBook) :
  38. _phoneBook(phoneBook)
  39. {
  40. }
  41. void
  42. Parser::addContacts(const list<string>& args)
  43. {
  44. if(args.empty())
  45. {
  46. error("`add' requires at least one argument (type `help' for more info)");
  47. return;
  48. }
  49. try
  50. {
  51. for(list<string>::const_iterator p = args.begin(); p != args.end(); ++p)
  52. {
  53. ContactPrx contact = _phoneBook->createContact();
  54. contact->setName(*p);
  55. cout << "added new contact for `" << *p << "'" << endl;
  56. }
  57. }
  58. catch(const DatabaseException& ex)
  59. {
  60. error(ex.message);
  61. }
  62. catch(const Ice::Exception& ex)
  63. {
  64. ostringstream s;
  65. s << ex;
  66. error(s.str());
  67. }
  68. }
  69. void
  70. Parser::findContacts(const list<string>& args)
  71. {
  72. if(args.size() != 1)
  73. {
  74. error("`find' requires exactly one argument (type `help' for more info)");
  75. return;
  76. }
  77. try
  78. {
  79. _foundContacts = _phoneBook->findContacts(args.front());
  80. _current = _foundContacts.begin();
  81. cout << "number of contacts found: " << _foundContacts.size() << endl;
  82. printCurrent();
  83. }
  84. catch(const DatabaseException& ex)
  85. {
  86. error(ex.message);
  87. }
  88. catch(const Ice::Exception& ex)
  89. {
  90. ostringstream s;
  91. s << ex;
  92. error(s.str());
  93. }
  94. }
  95. void
  96. Parser::nextFoundContact()
  97. {
  98. if(_current != _foundContacts.end())
  99. {
  100. ++_current;
  101. }
  102. printCurrent();
  103. }
  104. void
  105. Parser::printCurrent()
  106. {
  107. try
  108. {
  109. if(_current != _foundContacts.end())
  110. {
  111. cout << "current contact is:" << endl;
  112. cout << "name: " << (*_current)->getName() << endl;
  113. cout << "address: " << (*_current)->getAddress() << endl;
  114. cout << "phone: " << (*_current)->getPhone() << endl;
  115. }
  116. else
  117. {
  118. cout << "no current contact" << endl;
  119. }
  120. }
  121. catch(const Ice::ObjectNotExistException&)
  122. {
  123. cout << "current contact no longer exists" << endl;
  124. }
  125. catch(const DatabaseException& ex)
  126. {
  127. error(ex.message);
  128. }
  129. catch(const Ice::Exception& ex)
  130. {
  131. ostringstream s;
  132. s << ex;
  133. error(s.str());
  134. }
  135. }
  136. void
  137. Parser::setCurrentName(const list<string>& args)
  138. {
  139. if(args.size() != 1)
  140. {
  141. error("`name' requires exactly one argument (type `help' for more info)");
  142. return;
  143. }
  144. try
  145. {
  146. if(_current != _foundContacts.end())
  147. {
  148. (*_current)->setName(args.front());
  149. cout << "changed name to `" << args.front() << "'" << endl;
  150. }
  151. else
  152. {
  153. cout << "no current contact" << endl;
  154. }
  155. }
  156. catch(const Ice::ObjectNotExistException&)
  157. {
  158. cout << "current contact no longer exists" << endl;
  159. }
  160. catch(const DatabaseException& ex)
  161. {
  162. error(ex.message);
  163. }
  164. catch(const Ice::Exception& ex)
  165. {
  166. ostringstream s;
  167. s << ex;
  168. error(s.str());
  169. }
  170. }
  171. void
  172. Parser::setCurrentAddress(const list<string>& args)
  173. {
  174. if(args.size() != 1)
  175. {
  176. error("`address' requires exactly one argument (type `help' for more info)");
  177. return;
  178. }
  179. try
  180. {
  181. if(_current != _foundContacts.end())
  182. {
  183. (*_current)->setAddress(args.front());
  184. cout << "changed address to `" << args.front() << "'" << endl;
  185. }
  186. else
  187. {
  188. cout << "no current contact" << endl;
  189. }
  190. }
  191. catch(const Ice::ObjectNotExistException&)
  192. {
  193. cout << "current contact no longer exists" << endl;
  194. }
  195. catch(const DatabaseException& ex)
  196. {
  197. error(ex.message);
  198. }
  199. catch(const Ice::Exception& ex)
  200. {
  201. ostringstream s;
  202. s << ex;
  203. error(s.str());
  204. }
  205. }
  206. void
  207. Parser::setCurrentPhone(const list<string>& args)
  208. {
  209. if(args.size() != 1)
  210. {
  211. error("`phone' requires exactly one argument (type `help' for more info)");
  212. return;
  213. }
  214. try
  215. {
  216. if(_current != _foundContacts.end())
  217. {
  218. (*_current)->setPhone(args.front());
  219. cout << "changed phone number to `" << args.front() << "'" << endl;
  220. }
  221. else
  222. {
  223. cout << "no current contact" << endl;
  224. }
  225. }
  226. catch(const Ice::ObjectNotExistException&)
  227. {
  228. cout << "current contact no longer exists" << endl;
  229. }
  230. catch(const DatabaseException& ex)
  231. {
  232. error(ex.message);
  233. }
  234. catch(const Ice::Exception& ex)
  235. {
  236. ostringstream s;
  237. s << ex;
  238. error(s.str());
  239. }
  240. }
  241. void
  242. Parser::removeCurrent()
  243. {
  244. try
  245. {
  246. if(_current != _foundContacts.end())
  247. {
  248. (*_current)->destroy();
  249. cout << "removed current contact" << endl;
  250. }
  251. else
  252. {
  253. cout << "no current contact" << endl;
  254. }
  255. }
  256. catch(const Ice::ObjectNotExistException&)
  257. {
  258. cout << "current contact no longer exists" << endl;
  259. }
  260. catch(const DatabaseException& ex)
  261. {
  262. error(ex.message);
  263. }
  264. catch(const Ice::Exception& ex)
  265. {
  266. ostringstream s;
  267. s << ex;
  268. error(s.str());
  269. }
  270. }
  271. void
  272. Parser::setEvictorSize(const list<string>& args)
  273. {
  274. if(args.size() != 1)
  275. {
  276. error("`size' requires exactly one argument (type `help' for more info)");
  277. return;
  278. }
  279. try
  280. {
  281. _phoneBook->setEvictorSize(atoi(args.front().c_str()));
  282. }
  283. catch(const DatabaseException& ex)
  284. {
  285. error(ex.message);
  286. }
  287. catch(const Ice::Exception& ex)
  288. {
  289. ostringstream s;
  290. s << ex;
  291. error(s.str());
  292. }
  293. }
  294. void
  295. Parser::shutdown()
  296. {
  297. try
  298. {
  299. _phoneBook->shutdown();
  300. }
  301. catch(const Ice::Exception& ex)
  302. {
  303. ostringstream s;
  304. s << ex;
  305. error(s.str());
  306. }
  307. }
  308. void
  309. Parser::getInput(char* buf, int& result, int maxSize)
  310. {
  311. #ifdef HAVE_READLINE
  312. const char* prompt = parser->getPrompt();
  313. char* line = readline(const_cast<char*>(prompt));
  314. if(!line)
  315. {
  316. result = 0;
  317. }
  318. else
  319. {
  320. if(*line)
  321. {
  322. add_history(line);
  323. }
  324. result = strlen(line) + 1;
  325. if(result > maxSize)
  326. {
  327. free(line);
  328. error("input line too long");
  329. result = 0;
  330. }
  331. else
  332. {
  333. strcpy(buf, line);
  334. strcat(buf, "\n");
  335. free(line);
  336. }
  337. }
  338. #else
  339. cout << parser->getPrompt() << flush;
  340. string line;
  341. while(true)
  342. {
  343. char c = static_cast<char>(getc(yyin));
  344. if(c == EOF)
  345. {
  346. if(line.size())
  347. {
  348. line += '\n';
  349. }
  350. break;
  351. }
  352. line += c;
  353. if(c == '\n')
  354. {
  355. break;
  356. }
  357. }
  358. result = static_cast<int>(line.length());
  359. if(result > maxSize)
  360. {
  361. error("input line too long");
  362. buf[0] = EOF;
  363. result = 1;
  364. }
  365. else
  366. {
  367. strcpy(buf, line.c_str());
  368. }
  369. #endif
  370. }
  371. void
  372. Parser::continueLine()
  373. {
  374. _continue = true;
  375. }
  376. const char*
  377. Parser::getPrompt()
  378. {
  379. if(_continue)
  380. {
  381. _continue = false;
  382. return "(cont) ";
  383. }
  384. else
  385. {
  386. return ">>> ";
  387. }
  388. }
  389. void
  390. Parser::error(const char* s)
  391. {
  392. cerr << "error: " << s << endl;
  393. _errors++;
  394. }
  395. void
  396. Parser::error(const string& s)
  397. {
  398. error(s.c_str());
  399. }
  400. void
  401. Parser::warning(const char* s)
  402. {
  403. cerr << "warning: " << s << endl;
  404. }
  405. void
  406. Parser::warning(const string& s)
  407. {
  408. warning(s.c_str());
  409. }
  410. int
  411. Parser::parse(bool debug)
  412. {
  413. extern int yydebug;
  414. yydebug = debug ? 1 : 0;
  415. assert(!parser);
  416. parser = this;
  417. _errors = 0;
  418. yyin = stdin;
  419. assert(yyin);
  420. _continue = false;
  421. _foundContacts.clear();
  422. _current = _foundContacts.end();
  423. int status = yyparse();
  424. if(_errors)
  425. {
  426. status = EXIT_FAILURE;
  427. }
  428. parser = 0;
  429. return status;
  430. }