MBDyn-1.7.3
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups
parser.cc
Go to the documentation of this file.
1 /* $Header: /var/cvs/mbdyn/mbdyn/mbdyn-1.0/libraries/libmbutil/parser.cc,v 1.90 2017/01/12 14:44:05 masarati Exp $ */
2 /*
3  * MBDyn (C) is a multibody analysis code.
4  * http://www.mbdyn.org
5  *
6  * Copyright (C) 1996-2017
7  *
8  * Pierangelo Masarati <masarati@aero.polimi.it>
9  * Paolo Mantegazza <mantegazza@aero.polimi.it>
10  *
11  * Dipartimento di Ingegneria Aerospaziale - Politecnico di Milano
12  * via La Masa, 34 - 20156 Milano, Italy
13  * http://www.aero.polimi.it
14  *
15  * Changing this copyright notice is forbidden.
16  *
17  * This program is free software; you can redistribute it and/or modify
18  * it under the terms of the GNU General Public License as published by
19  * the Free Software Foundation (version 2 of the License).
20  *
21  *
22  * This program is distributed in the hope that it will be useful,
23  * but WITHOUT ANY WARRANTY; without even the implied warranty of
24  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
25  * GNU General Public License for more details.
26  *
27  * You should have received a copy of the GNU General Public License
28  * along with this program; if not, write to the Free Software
29  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
30  */
31 
32 /* parser */
33 
34 #include "mbconfig.h" /* This goes first in every *.c,*.cc file */
35 
36 #include <cstring>
37 #include <stdlib.h>
38 #include <stack>
39 #include <map>
40 
41 #include "mathtyp.h"
42 #include "parser.h"
43 #include "filename.h"
44 #include "Rot.hh"
45 
46 /* LowParser - begin */
47 
48 static int
49 skip_remarks(HighParser& HP, InputStream& In, char &cIn)
50 {
51 skip_again:;
52  for (cIn = In.get(); isspace(cIn); cIn = In.get()) {
53  // this is here in case in some implementation isspace returns success for EOF
54  if (In.eof()) {
55  return -1;
56  }
57  }
58 
59  if (In.eof()) {
60  return -1;
61  }
62 
63  switch (cIn) {
64  case -1: // should be EOF!
65  return -1;
66 
68  for (cIn = In.get(); cIn != '\n'; cIn = In.get()) {
69  if (cIn == '\\') {
70  cIn = In.get();
71  if (In.eof()) {
72  return -1;
73  }
74  if (cIn == '\r') {
75  /* if input file was prepared
76  * under DOS/Windows */
77  cIn = In.get();
78  if (In.eof()) {
79  return -1;
80  }
81  }
82  }
83  if (In.eof()) {
84  return -1;
85  }
86  }
87  goto skip_again;
88 
89  case '/':
90  cIn = In.get();
91  if (In.eof()) {
92  return -1;
93 
94  } else if (cIn == '*') {
95  for (cIn = In.get(); !In.eof(); cIn = In.get()) {
96  if (cIn == '*') {
97 end_of_comment:;
98  cIn = In.get();
99  if (In.eof()) {
100  return -1;
101  }
102  if (cIn == '/') {
103  goto skip_again;
104  }
105 
106  } else if (cIn == '/') {
107  cIn = In.get();
108  if (In.eof()) {
109  return -1;
110  }
111  if (cIn == '*') {
112  silent_cerr("warning: '/*' inside a comment "
113  "at line " << HP.GetLineData()
114  << std::endl);
115  goto end_of_comment;
116  }
117  }
118  }
119  if (In.eof()) {
120  return -1;
121  }
122 
123  } else {
124  In.putback(cIn);
125  return 0;
126  }
127  }
128 
129  return 0;
130 }
131 
133 : HP(hp), sCurrWordBuf(0), iBufSize(iDefaultBufSize)
134 {
136 }
137 
139 {
140  if (sCurrWordBuf) {
142  }
143 }
144 
145 void
147 {
148  unsigned iCur = 0;
149  char cIn;
150 
151  /* note: no remarks allowed inside words */
152  for (cIn = In.get(); !In.eof(); cIn = In.get()) {
153  switch (cIn) {
154  case COLON:
155  case COMMA:
156  case SEMICOLON:
157  goto end_of_word;
158 
159  default:
160  if (!isspace(cIn)) {
161  sCurrWordBuf[iCur] = cIn;
162  iCur++;
163  if (iCur == iBufSize - 1) {
164  char *s = NULL;
165  unsigned i = 2*iBufSize;
166 
167  /* FIXME: no limit on max size? */
168 
169  SAFENEWARR(s, char, i);
170  memcpy(s, sCurrWordBuf, iBufSize);
172  sCurrWordBuf = s;
173  iBufSize = i;
174  }
175  }
176  }
177  }
178 
180 
181 end_of_word:;
182 
183  sCurrWordBuf[iCur] = '\0';
184  In.putback(cIn);
185 }
186 
187 
190 {
191  /* toglie gli spazi iniziali e tutti i commenti */
192  char cIn;
193  if (skip_remarks(HP, In, cIn)) {
195  }
196 
197  if (isalpha(cIn) || cIn == '_') {
198  PackWords(In.putback(cIn));
199  return CurrToken = LowParser::WORD;
200  }
201 
202  switch (cIn) {
203  case ',':
204  return CurrToken = LowParser::COMMA;
205 
206  case ':':
207  return CurrToken = LowParser::COLON;
208 
209  case ';':
211 
212  case '.':
213  case '-':
214  case '+':
215 is_digit:;
216  In.putback(cIn) >> dCurrNumber;
217  return CurrToken = LowParser::NUMBER;
218 
219  default:
220  if (isdigit(cIn)) {
221  goto is_digit;
222  }
223  In.putback(cIn);
224  return CurrToken = LowParser::UNKNOWN;
225  }
226 }
227 
228 
231 {
232  return dCurrNumber;
233 }
234 
235 
236 integer
238 {
239  return integer(dCurrNumber);
240 }
241 
242 
243 char*
245 {
246  return sCurrWordBuf;
247 }
248 
249 /* LowParser - end */
250 
251 
252 /* KeyTable - begin */
253 
254 KeyTable::KeyTable(HighParser& hp, const char* const sTable[])
255 : sKeyWords(0), oldKey(0), HP(hp)
256 {
257  sKeyWords = (char* const*)sTable;
258  oldKey = HP.PutKeyTable(*this);
259 }
260 
261 
263 {
264  if (oldKey) {
265  (void)HP.PutKeyTable(*oldKey);
266  }
267 }
268 
269 
270 int
271 KeyTable::Find(const char* sToFind) const
272 {
273  for (int iCnt = 0; sKeyWords[iCnt]; iCnt++) {
274  if (strcasecmp(sKeyWords[iCnt], sToFind) == 0) {
275  return iCnt;
276  }
277  }
278 
279  return -1;
280 }
281 
282 /* KeyTable - end */
283 
284 
285 /* DescRead - begin */
286 
287 /* bag that contains functions to parse descriptions */
288 
289 typedef std::map<std::string, DescRead *, ltstrcase> DescFuncMapType;
291 
293  bool IsWord(const std::string& s) const {
294  return DescFuncMap.find(s) != DescFuncMap.end();
295  };
296 };
297 
299 
300 bool
301 SetDescData(const std::string& name, DescRead *rf)
302 {
303  pedantic_cout("registering description \"" << name << "\"" << std::endl);
304  return DescFuncMap.insert(DescFuncMapType::value_type(name, rf)).second;
305 }
306 
307 /* Reads descriptions */
308 
309 bool
310 ReadDescription(HighParser& HP, const std::string& desc)
311 {
312  DEBUGCOUTFNAME("ReadDescription()");
313 
314  bool bRC(false);
315  DescFuncMapType::iterator func = DescFuncMap.find(desc);
316  if (func != DescFuncMap.end()) {
317  HP.GotDescription();
318  if (!HP.IsArg() && !HP.IsDescription()) {
319  silent_cerr("Parser error in ReadDescription(),"
320  " colon or semicolon expected after description at line "
321  << HP.GetLineData() << std::endl);
323  }
324 
325  bRC = func->second->Read(HP);
326 
327  if (HP.IsArg()) {
328  silent_cerr("semicolon expected at line " << HP.GetLineData() << std::endl);
330  }
331  }
332 
333  return bRC;
334 }
335 
337 {
338  NO_OP;
339 }
340 
341 struct RemarkDR : public DescRead {
342 public:
343  bool Read(HighParser& HP);
344 };
345 
346 bool
348 {
349  silent_cout("line " << HP.GetLineData());
350 
351  char prefix = ':';
352  while (HP.IsArg()) {
353  TypedValue v;
354  v = HP.GetValue(v);
355  silent_cout(prefix << ' ' << v);
356 
357  if (prefix == ':') {
358  prefix = ',';
359  }
360  }
361 
362  silent_cout(std::endl);
363 
364  return true;
365 }
366 
367 struct PrintSymbolTableDR : public DescRead {
368 public:
369  bool Read(HighParser& HP);
370 };
371 
372 bool
374 {
375  if (!HP.IsArg()) {
376  silent_cout( "math parser symbol table at line "
377  << HP.GetLineData() << ":" << std::endl
378  << HP.GetMathParser().GetSymbolTable() << std::endl);
379  return true;
380  }
381 
382  if (HP.IsKeyWord("all")) {
384  for (MathParser::NameSpaceMap::const_iterator i = ns.begin(); i != ns.end(); ++i) {
385  const std::string& sName = i->second->sGetName();
386  const Table *pT = i->second->GetTable();
387  if (pT != 0) {
388  silent_cout( "namespace \"" << sName << "\" symbol table at line "
389  << HP.GetLineData() << ":" << std::endl
390  << *pT << std::endl);
391  }
392  }
393 
394  return true;
395  }
396 
397  while (HP.IsArg()) {
398  const char *sName = HP.GetString();
400  if (pN == 0) {
401  silent_cerr("PrintSymbolTableDR::Read(): warning, unable to find namespace \"" << sName << "\" at line "
402  << HP.GetLineData() << std::endl);
403 
404  } else {
405  Table *pT = pN->GetTable();
406  if (pT == 0) {
407  silent_cerr("PrintSymbolTableDR::Read(): warning, namespace \"" << sName << "\" "
408  "has no symbol table at line " << HP.GetLineData() << std::endl);
409 
410  } else {
411  silent_cout( "namespace \"" << sName << "\" symbol table at line "
412  << HP.GetLineData() << ":" << std::endl
413  << *pT << std::endl);
414  }
415  }
416  }
417 
418  return true;
419 }
420 
421 struct SetDR : public DescRead {
422 public:
423  bool Read(HighParser& HP);
424 };
425 
426 bool
428 {
429  if (!HP.IsArg()) {
430  silent_cerr("Parser error in SetDR::Read(), "
431  "arg expected at line "
432  << HP.GetLineData() << std::endl);
434  }
435 
436  TypedValue v;
437  HP.GetValue(v);
438 
439  return true;
440 }
441 
442 struct SetEnvDR : public DescRead {
443 public:
444  bool Read(HighParser& HP);
445 };
446 
447 bool
449 {
450 #ifdef HAVE_SETENV
451  if (!HP.IsArg()) {
452  silent_cerr("Parser error in SetEnvDR::Read(), "
453  "arg(s) expected at line "
454  << HP.GetLineData() << std::endl);
456  }
457 
458  int overwrite = 0;
459  if (HP.IsKeyWord("overwrite")) {
460  bool b = HP.GetYesNoOrBool();
461  overwrite = b ? 1 : 0;
462  }
463 
464  const char *ava = HP.GetStringWithDelims();
465  if (ava == NULL) {
466  silent_cerr("unable to get AVA for \"setenv\" at line "
467  << HP.GetLineData() << std::endl);
469  }
470 
471  char *avasep = std::strchr(const_cast<char *>(ava), '=');
472  if (avasep == NULL) {
473 #ifdef HAVE_UNSETENV
474  unsetenv(ava);
475 #elif defined(HAVE_PUTENV)
476  if (putenv(ava)) {
477  silent_cerr("unable to unset the environment variable "
478  "\"" << ava << "\" at line "
479  << HP.GetLineData() << std::endl);
481  }
482 #endif /* !HAVE_UNSETENV && !HAVE_PUTENV */
483 
484  } else {
485  if (avasep == ava) {
486  silent_cerr("illegal AVA \"" << ava
487  << "\" at line "
488  << HP.GetLineData() << std::endl);
490  }
491 
492  avasep[0] = '\0';
493  avasep++;
494  bool bPresent(getenv(ava) != NULL);
495  int rc = setenv(ava, avasep, overwrite);
496  if (rc) {
497  silent_cerr("unable to set the environment variable \""
498  << ava << "\" to \"" << avasep
499  << "\" at line " << HP.GetLineData()
500  << std::endl);
502  }
503 
504  if (bPresent && overwrite == 0) {
505  silent_cout("Environment variable \"" << ava
506  << "\" _not_ overwritten with \"" << avasep
507  << "\" (current value is \"" << getenv(ava)
508  << "\") at line " << HP.GetLineData()
509  << std::endl);
510 
511  } else if (!bPresent) {
512  silent_cout("Environment variable \"" << ava
513  << "\" set to \"" << avasep
514  << "\" at line " << HP.GetLineData()
515  << std::endl);
516 
517  } else {
518  silent_cout("Environment variable \"" << ava
519  << "\" overwritten to \"" << avasep
520  << "\" at line " << HP.GetLineData()
521  << std::endl);
522  }
523  }
524 #else // ! HAVE_SETENV
525  silent_cerr("SetEnvDR::Read(): warning, setenv() not available; ignored at line "
526  << HP.GetLineData() << std::endl);
527 #endif // !HAVE_SETENV
528  return true;
529 }
530 
531 struct ExitDR : public DescRead {
532 public:
533  bool Read(HighParser& HP);
534 };
535 
536 bool
538 {
539  if (!HP.IsDescription()) {
540  silent_cerr("Parser error in ExitDR::Read(),"
541  " semicolon expected at line "
542  << HP.GetLineData() << std::endl);
544  }
545 
546  /* exits with no error */
547  throw NoErr(MBDYN_EXCEPT_ARGS);
548 }
549 
550 static unsigned desc_done;
551 
552 static void
554 {
555  if (::desc_done++ > 0) {
556  return;
557  }
558 
559  SetDescData("remark", new RemarkDR);
560  SetDescData("print" "symbol" "table", new PrintSymbolTableDR);
561  SetDescData("set", new SetDR);
562  SetDescData("setenv", new SetEnvDR);
563  SetDescData("exit", new ExitDR);
564 
565  /* NOTE: add here initialization of new built-in descriptions;
566  * alternative ways to register new custom descriptions are:
567  * - call SetDescData() from anywhere in the code
568  * - write a module that calls SetDescData() from inside a function
569  * called module_init(), and run-time load it using "module load"
570  * in the input file.
571  */
572 }
573 
574 static void
576 {
577  if (::desc_done == 0) {
578  silent_cerr("DestroyDescData() called once too many" << std::endl);
580  }
581 
582  if (--::desc_done > 0) {
583  return;
584  }
585 
586  /* free stuff */
587  for (DescFuncMapType::iterator i = DescFuncMap.begin(); i != DescFuncMap.end(); ++i) {
588  delete i->second;
589  }
590  DescFuncMap.clear();
591 }
592 
593 /* DescRead - end */
594 
595 
596 /* HighParser - begin */
597 
598 static std::stack<const HighParser *> pHP;
599 
600 static const HighParser::ErrOut unknownErr = { "(unknown)", "(unknown)", 0 };
601 
604 {
605  if (!pHP.empty()) {
606  return pHP.top()->GetLineData();
607  }
608 
609  return unknownErr;
610 }
611 
612 std::ostream&
613 mbdyn_print_line_data(std::ostream& out)
614 {
615  if (!pHP.empty()) {
616  out << pHP.top()->GetLineData();
617  }
618 
619  return out;
620 }
621 
623 : ESCAPE_CHAR('\\'),
624 LowP(*this),
625 pIn(&streamIn),
626 pf(NULL),
627 MathP(MP),
628 KeyT(0)
629 {
630  DEBUGCOUTFNAME("HighParser::HighParser");
632 
633  InitDescData();
634 
635  pHP.push(this);
636 }
637 
638 
640 {
641  DEBUGCOUTFNAME("HighParser::~HighParser");
642  Close();
643  ASSERT(pHP.top() == this);
644  pHP.pop();
645 
646  DestroyDescData();
647 }
648 
649 
650 void
652 {
653  NO_OP;
654 }
655 
656 
657 const KeyTable*
659 {
660  const KeyTable* oldKey = KeyT;
661 
662  KeyT = &KT;
663 
664  return oldKey;
665 }
666 
667 MathParser&
669 {
670  return MathP;
671 }
672 
673 int
675 {
676  return const_cast<InputStream *>(pIn)->GetLineNumber();
677 }
678 
679 
682 {
683  ErrOut LineData;
684  LineData.iLineNumber = GetLineNumber();
685  LineData.sFileName = NULL;
686  LineData.sPathName = NULL;
687  return LineData;
688 }
689 
690 
691 bool
693 {
695 }
696 
699 {
700  return FirstToken();
701 }
702 
703 int
705 {
706  int i = -1;
707 
708  if (KeyT) {
709  i = KeyT->Find(s);
710  }
711 
712  if (FirstToken() == HighParser::UNKNOWN) {
713  silent_cerr("Parser error in HighParser::iGetDescription_int(), "
714  "semicolon expected at line "
715  << GetLineData() << std::endl);
717  }
718 
719  return i;
720 }
721 
722 
723 void
725 {
727 }
728 
729 int
731 {
732  /* Checks if current token is a description */
733  if (!IsDescription()) {
734  silent_cerr("Parser error in HighParser::GetDescription, "
735  "invalid call to GetDescription at line "
736  << GetLineData() << std::endl);
738  }
739 
740 restart_parsing:;
741 
743  if (CurrLowToken != LowParser::WORD) {
744  if (pIn->eof()) {
745  Eof();
746  goto restart_parsing;
747  }
748 
749  silent_cerr("Parser error in HighParser::GetDescription, "
750  << "keyword expected at line "
751  << GetLineData() << std::endl);
753  }
754 
755  /* Description corrente */
756  char* s = LowP.sGetWord();
757 
758  if (ReadDescription(*this, s)) {
759  goto restart_parsing;
760  }
761 
762  return iGetDescription_int(s);
763 }
764 
765 
768 {
770 
771  switch (CurrLowToken) {
772  case LowParser::COLON:
774  break;
775 
778  break;
779 
780  default:
782  break;
783  }
784 
785  return CurrToken;
786 }
787 
788 void
790 {
791  /* forces the next expected token to be a "description"
792  * e.g. a keyword followed by a colon (deprecated) */
794 }
795 
796 
797 void
799 {
800  /* forces the next expected token to be an argument
801  * e.g. a keyword followed by a separator (deprecated) */
803 }
804 
805 
806 bool
808 {
809  return (CurrToken == ARG);
810 }
811 
812 void
814 {
816  pIn->putback(';');
817  }
818 }
819 
820 
821 void
822 HighParser::NextToken(const char* sFuncName)
823 {
825  switch (CurrLowToken) {
826  case LowParser::COMMA:
828  break;
829 
832  break;
833 
834  default:
835  silent_cerr("Parser error in "
836  << sFuncName << ", missing separator at line "
837  << GetLineData() << std::endl);
839  }
840 }
841 
842 int
843 HighParser::ParseWord(unsigned flags)
844 {
845  char* sBuf = sStringBuf;
846  char* sBufWithSpaces = sStringBufWithSpaces;
847 
848  char cIn;
849  if (skip_remarks(*this, *pIn, cIn)) {
851  }
852 
853  if (!isalpha(cIn) && cIn != '_') {
854  pIn->putback(cIn);
855  return -1;
856  }
857 
858  *sBufWithSpaces++ = cIn;
859 
860  if (flags & LOWER) {
861  *sBuf++ = tolower(cIn);
862 
863  } else if (flags & UPPER) {
864  *sBuf++ = toupper(cIn);
865 
866  } else {
867  *sBuf++ = cIn;
868  }
869 
870  for (cIn = pIn->get(); isalnum(cIn) || cIn == '_' || isspace(cIn); cIn = pIn->get()) {
871  *sBufWithSpaces++ = cIn;
872  if (sBufWithSpaces >= sStringBufWithSpaces + iDefaultBufSize - 1) {
873  break;
874  }
875 
876  if (isspace(cIn)) {
877  continue;
878  }
879 
880  if (flags & LOWER) {
881  *sBuf++ = tolower(cIn);
882 
883  } else if (flags & UPPER) {
884  *sBuf++ = toupper(cIn);
885 
886  } else {
887  *sBuf++ = cIn;
888  }
889  }
890  pIn->putback(cIn);
891 
892  *sBuf = '\0';
893  *sBufWithSpaces = '\0';
894 
895  return 0;
896 }
897 
898 void
900 {
901  char* sBufWithSpaces = sStringBufWithSpaces + strlen(sStringBufWithSpaces);
902 
903 
904  while (sBufWithSpaces > sStringBufWithSpaces) {
905  pIn->putback(*--sBufWithSpaces);
906  }
907 }
908 
909 bool
910 HighParser::IsKeyWord(const char* sKeyWord)
911 {
912  const char sFuncName[] = "HighParser::IsKeyWord()";
913 
914  if (CurrToken != HighParser::ARG) {
915  return false;
916  }
917 
918  switch (ParseWord()) {
919  case 0:
920  break;
921 
923  return true;
924 
925  default:
926  return false;
927  }
928 
929  if (!strcasecmp(sStringBuf, sKeyWord)) {
930  NextToken(sFuncName);
931  return true;
932  }
933 
934  PutbackWord();
935 
936  return false;
937 }
938 
939 int
941 {
942  const char sFuncName[] = "HighParser::IsKeyWord()";
943 
944  if (CurrToken != HighParser::ARG) {
945  return -1;
946  }
947 
948  switch (ParseWord()) {
949  case 0:
950  break;
951 
953  return HighParser::ENDOFFILE;
954 
955  default:
956  return -1;
957  }
958 
959  int iKW = -1;
960 
961  if (KeyT) {
962  iKW = KeyT->Find(sStringBuf);
963  }
964 
965  if (iKW >= 0) {
966  NextToken(sFuncName);
967  return iKW;
968  }
969 
970  PutbackWord();
971 
972  return -1;
973 }
974 
975 /* 1 se l'argomento successivo e' una parola in un WordSet */
976 const char *
978 {
979  const char sFuncName[] = "HighParser::IsWord()";
980 
981  if (CurrToken != HighParser::ARG) {
982  return 0;
983  }
984 
985  switch (ParseWord()) {
986  case 0:
987  break;
988 
989  default:
990  return 0;
991  }
992 
993  if (ws.IsWord(std::string(sStringBuf))) {
994  NextToken(sFuncName);
995  return sStringBuf;
996  }
997 
998  PutbackWord();
999 
1000  return 0;
1001 }
1002 
1003 TypedValue
1005 {
1006  return GetValue<range_any<TypedValue> >(vDefVal, range_any<TypedValue>());
1007 }
1008 
1009 bool
1010 HighParser::GetBool(bool bDefVal)
1011 {
1012  TypedValue v(bDefVal);
1013  v = GetValue(v);
1014  return v.GetBool();
1015 }
1016 
1017 /*
1018  * Read a boolean as "yes" or "no" and put the result in bRet
1019  * return true in case of success, false otherwise (bRet undefined)
1020  */
1021 bool
1023 {
1024  if (IsKeyWord("yes")) {
1025  bRet = true;
1026 
1027  } else if (IsKeyWord("no")) {
1028  bRet = false;
1029 
1030  } else {
1031  return false;
1032  }
1033 
1034  return true;
1035 }
1036 
1037 bool
1039 {
1040  bool bRet;
1041 
1042  if (!GetYesNo(bRet)) {
1043  bRet = GetBool(bDefval);
1044  }
1045 
1046  return bRet;
1047 }
1048 
1049 integer
1051 {
1052  return GetInt<range_any<integer> >(iDefVal, range_any<integer>());
1053 }
1054 
1055 doublereal
1057 {
1058  return GetReal<range_any<doublereal> >(dDefVal, range_any<doublereal>());
1059 }
1060 
1061 mbsleep_t
1063 {
1064  doublereal d;
1065  mbsleep_sleep2real(&DefVal, &d);
1066  TypedValue v(d);
1067  v = GetValue(v);
1068  mbsleep_t newval;
1069  mbsleep_real2sleep(v.GetReal(), &newval);
1070  return newval;
1071 }
1072 
1073 std::string
1074 HighParser::GetString(const std::string& sDefVal)
1075 {
1076  TypedValue v(sDefVal);
1077  v = GetValue(v);
1078  return v.GetString();
1079 }
1080 
1081 
1082 int
1084 {
1085  const char sFuncName[] = "HighParser::GetWord()";
1086 
1087  if (CurrToken != HighParser::ARG) {
1088  silent_cerr("Parser error in "
1089  << sFuncName << ", keyword arg expected at line "
1090  << GetLineData() << std::endl);
1092  }
1093 
1095  if (CurrLowToken != LowParser::WORD) {
1096  silent_cerr("Parser error in "
1097  << sFuncName << ", keyword expected at line "
1098  << GetLineData() << std::endl);
1100  }
1101 
1102  int i = -1;
1103  if (KeyT) {
1104  i = KeyT->Find(LowP.sGetWord());
1105  }
1106 
1107  NextToken(sFuncName);
1108 
1109  return i;
1110 }
1111 
1112 const char*
1113 HighParser::GetString(unsigned flags)
1114 {
1115  const char sFuncName[] = "HighParser::GetString()";
1116 
1117  pedantic_cout("use of deprecated method \"GetString\" at line"
1118  << GetLineData() << std::endl);
1119 
1120  if (CurrToken != HighParser::ARG) {
1121  silent_cerr("Parser error in "
1122  << sFuncName << ", string arg expected at line "
1123  << GetLineData() << std::endl);
1125  }
1126 
1127  char* s = sStringBuf;
1128  char* sTmp = s;
1129 
1130  char cIn = '\0';
1131 
1132  while (isspace(cIn = pIn->get())) {
1133  NO_OP;
1134  }
1135 
1136  if (pIn->eof()) {
1138  return NULL;
1139  }
1140 
1141  pIn->putback(cIn);
1142  for (cIn = pIn->get(); cIn != ',' && cIn != ';'; cIn = pIn->get()) {
1143  /* Attenzione! cosi' la legge tutta,
1144  * ma ne tiene solo iBufSize-1 caratteri */
1145  if (pIn->eof()) {
1147  *sTmp = '\0';
1148  return s;
1149 
1150  } else if (sTmp < s + iDefaultBufSize - 1) {
1151  if (!(flags & HighParser::EATSPACES) || !isspace(cIn)) {
1152  if (flags & HighParser::LOWER) {
1153  cIn = tolower(cIn);
1154 
1155  } else if (flags & HighParser::UPPER) {
1156  cIn = toupper(cIn);
1157  }
1158 
1159  *sTmp++ = cIn;
1160  }
1161  }
1162  }
1163 
1164  pIn->putback(cIn);
1165  *sTmp = '\0';
1166 
1167  NextToken(sFuncName);
1168 
1169  return s;
1170 }
1171 
1172 void
1173 HighParser::SetDelims(enum Delims Del, char &cLdelim, char &cRdelim) const
1174 {
1175  cLdelim = '\0';
1176  cRdelim = '\0';
1177 
1178  switch (Del) {
1179  case PLAINBRACKETS:
1180  cLdelim = '(';
1181  cRdelim = ')';
1182  break;
1183 
1184  case SQUAREBRACKETS:
1185  cLdelim = '[';
1186  cRdelim = ']';
1187  break;
1188 
1189  case CURLYBRACKETS:
1190  cLdelim = '{';
1191  cRdelim = '}';
1192  break;
1193 
1194  case SINGLEQUOTE:
1195  cLdelim = '`';
1196  cRdelim = '\'';
1197  break;
1198 
1199  default:
1200  case UNKNOWNDELIM:
1201  case DEFAULTDELIM:
1202  case DOUBLEQUOTE:
1203  cLdelim = '"';
1204  cRdelim = '"';
1205  break;
1206  }
1207 }
1208 
1209 bool
1211 {
1212  char cLdelim, cRdelim;
1213  SetDelims(Del, cLdelim, cRdelim);
1214 
1215  char cIn;
1216  if (skip_remarks(*this, *pIn, cIn)) {
1217  return false;
1218  }
1219 
1220  /* put back the first non-remark char */
1221  pIn->putback(cIn);
1222 
1223  /* if the left delimiter is found, true */
1224  return (cIn == cLdelim);
1225 }
1226 
1227 const char*
1229 {
1230  const char sFuncName[] = "HighParser::GetStringWithDelims()";
1231 
1232  if (CurrToken != HighParser::ARG) {
1233  silent_cerr("Parser error in "
1234  << sFuncName << ", string arg expected at line "
1235  << GetLineData() << std::endl);
1237  }
1238 
1239  char* s = sStringBuf;
1240  char* sTmp = s;
1241 
1242  char cLdelim, cRdelim;
1243  SetDelims(Del, cLdelim, cRdelim);
1244 
1245  char cIn;
1246  if (skip_remarks(*this, *pIn, cIn)) {
1247  return NULL;
1248  }
1249 
1250  /* Se trova il delimitatore sinistro, legge la stringa */
1251  if (cIn == cLdelim) {
1252  for (cIn = pIn->get(); cIn != cRdelim; cIn = pIn->get()) {
1253  /* Attenzione! cosi' la legge tutta,
1254  * ma ne tiene solo iBufSize-1 caratteri */
1255  if (pIn->eof()) {
1256  /* FIXME: this should be an error ... */
1257  sTmp[0] = '\0';
1258  return s;
1259 
1260  } else if (sTmp < s + iDefaultBufSize - 1) {
1261  if (cIn == ESCAPE_CHAR) {
1262  cIn = pIn->get();
1263  if (cIn == '\n') {
1264 
1265  /*
1266  * eat the newline as well, so that
1267 
1268  "first line\
1269  second line"
1270 
1271  * actually results in "first linesecond line"
1272  */
1273 
1274  cIn = pIn->get();
1275 
1276  } else if (cIn == '\r') {
1277  cIn = pIn->get();
1278  if (cIn != '\n') {
1279  pIn->putback(cIn);
1280  goto escaped_generic;
1281  }
1282  cIn = pIn->get();
1283 
1284  } else if ((cIn == ESCAPE_CHAR) || (cIn == cRdelim)) {
1285  if (!escape) {
1286  sTmp[0] = ESCAPE_CHAR;
1287  ++sTmp;
1288  }
1289 
1290  } else {
1291 escaped_generic:;
1292  if (escape) {
1293  int i, c = 0;
1294  char hex[3];
1295 
1296  /*
1297  * allow non-printable chars in the form "<hexpair>",
1298  * so that "\78" is equivalent to "x";
1299  * "<non-hexpair>" is treated as an error.
1300  */
1301 
1302  hex[0] = cIn;
1303  hex[1] = pIn->get();
1304  hex[2] = '\0';
1305 
1306  for (i = 0; i < 2; i++) {
1307  int shift = 4*(1 - i), h = 0;
1308 
1309  /* NOTE: this conversion relies
1310  * on 0-9, a-f, A-F being consecutive,
1311  * which is true for ASCII, but might
1312  * not be for other encodings;
1313  * bah, not critical right now */
1314  if (hex[i] >= '0' && hex[i] <= '9') {
1315  h = hex[i] - '0';
1316  } else if (hex[i] >= 'a' && hex[i] <= 'f') {
1317  h = hex[i] - 'a';
1318  } else if (hex[i] >= 'A' && hex[i] <= 'F') {
1319  h = hex[i] - 'A';
1320  } else {
1321  silent_cerr("invalid escape sequence "
1322  "\"\\" << hex << "\" "
1323  "at line " << GetLineData()
1324  << std::endl);
1326  }
1327 
1328  c += (h << shift);
1329  }
1330  cIn = c;
1331 
1332  } else {
1333  sTmp[0] = ESCAPE_CHAR;
1334  ++sTmp;
1335  }
1336  }
1337  }
1338  sTmp[0] = cIn;
1339  ++sTmp;
1340  }
1341  }
1342 
1343  /* Se trova una virgola o un punto e virgola, le rimette nello stream
1344  * e passa oltre, restituendo un puntatore nullo. Il chiamante deve
1345  * occuparsi della gestione del valore di default */
1346  } else if (cIn == ',' || cIn == ';') {
1347  pIn->putback(cIn);
1348  goto nullstring;
1349 
1350  /* Altrimenti c'e' qualcosa senza delimitatore. Adesso da' errore,
1351  * forse e' piu' corretto fargli ritornare lo stream intatto */
1352  } else {
1353  silent_cerr("Parser error in "
1354  << sFuncName << std::endl
1355  << "first non-blank char at line "
1356  << GetLineData() << " isn't a valid left-delimiter"
1357  << std::endl);
1359  }
1360 
1361  /* Mette zero al termine della stringa */
1362  *sTmp = '\0';
1363 
1364 nullstring:;
1365  NextToken(sFuncName);
1366  return s;
1367 }
1368 
1369 /* HighParser - end */
1370 
1371 std::ostream&
1372 operator << (std::ostream& out, const HighParser::ErrOut& err)
1373 {
1374  out << err.iLineNumber;
1375 
1376  if (err.sFileName != 0) {
1377  out << ", file <";
1378  if (err.sPathName != 0) {
1379  out << err.sPathName << DIR_SEP;
1380  }
1381  out << err.sFileName << '>';
1382  }
1383 
1384  return out;
1385 }
1386 
1387 /* HighParser - end */
1388 
char * sCurrWordBuf
Definition: parser.h:164
const char * sFileName
Definition: parser.h:304
const char ESCAPE_CHAR
Definition: parser.h:300
std::map< std::string, NameSpace * > NameSpaceMap
Definition: mathp.h:351
static const char ONE_LINE_REMARK
Definition: mathp.h:188
void PutbackWord(void)
Definition: parser.cc:899
Real GetReal(void) const
Definition: mathp.cc:1228
char * sGetWord(void)
Definition: parser.cc:244
#define MBDYN_EXCEPT_ARGS
Definition: except.h:63
#define DEBUGCOUTFNAME(fname)
Definition: myassert.h:256
virtual integer GetInt(integer iDefval=0)
Definition: parser.cc:1050
bool IsDescription(void) const
Definition: parser.cc:692
virtual const char * IsWord(const HighParser::WordSet &ws)
Definition: parser.cc:977
virtual void ExpectArg(void)
Definition: parser.cc:798
unsigned int iLineNumber
Definition: parser.h:306
const KeyTable * oldKey
Definition: parser.h:187
virtual ~KeyTable(void)
Definition: parser.cc:262
LowParser(HighParser &hp)
Definition: parser.cc:132
bool SetDescData(const std::string &name, DescRead *rf)
Definition: parser.cc:301
virtual bool GetBool(bool bDefval=false)
Definition: parser.cc:1010
unsigned long mbsleep_t
Definition: mbsleep.h:51
int mbsleep_sleep2real(const mbsleep_t *t, doublereal *d)
Definition: mbsleep.c:74
bool ReadDescription(HighParser &HP, const std::string &desc)
Definition: parser.cc:310
virtual HighParser::ErrOut GetLineData(void) const
Definition: parser.cc:681
#define SAFEDELETEARR(pnt)
Definition: mynewmem.h:713
std::ostream & operator<<(std::ostream &out, const HighParser::ErrOut &err)
Definition: parser.cc:1372
enum Token CurrToken
Definition: parser.h:163
HighParser(MathParser &MP, InputStream &streamIn)
Definition: parser.cc:622
static const HighParser::ErrOut unknownErr
Definition: parser.cc:600
Token CurrToken
Definition: parser.h:435
virtual ~HighParser(void)
Definition: parser.cc:639
virtual void Close(void)
Definition: parser.cc:651
#define NO_OP
Definition: myassert.h:74
integer iGetInt(void) const
Definition: parser.cc:237
char get(void)
Definition: input.h:99
virtual void Eof(void)
Definition: parser.cc:724
char sStringBufWithSpaces[iDefaultBufSize]
Definition: parser.h:424
Token GotDescription(void)
Definition: parser.cc:698
~LowParser(void)
Definition: parser.cc:138
virtual bool GetYesNoOrBool(bool bDefval=false)
Definition: parser.cc:1038
virtual TypedValue GetValue(const TypedValue &v)
Definition: parser.cc:1004
Definition: parser.cc:421
virtual void ExpectDescription(void)
Definition: parser.cc:789
void func(const T &u, const T &v, const T &w, doublereal e, T &f)
LowParser LowP
Definition: parser.h:416
static DescWordSetType DescWordSet
Definition: parser.cc:298
std::map< std::string, DescRead *, ltstrcase > DescFuncMapType
Definition: parser.cc:289
virtual const KeyTable * PutKeyTable(const KeyTable &KT)
Definition: parser.cc:658
int Find(const char *sToFind) const
Definition: parser.cc:271
Token GetToken(InputStream &In)
Definition: parser.cc:189
bool Read(HighParser &HP)
Definition: parser.cc:537
InputStream & putback(char ch)
Definition: input.h:121
LowParser::Token CurrLowToken
Definition: parser.h:434
bool Read(HighParser &HP)
Definition: parser.cc:427
virtual bool IsKeyWord(const char *sKeyWord)
Definition: parser.cc:910
bool Read(HighParser &HP)
Definition: parser.cc:347
static DescFuncMapType DescFuncMap
Definition: parser.cc:290
int GetDescription(void)
Definition: parser.cc:730
virtual ~DescRead(void)
Definition: parser.cc:336
virtual const char * GetStringWithDelims(enum Delims Del=DEFAULTDELIM, bool escape=true)
Definition: parser.cc:1228
const NameSpaceMap & GetNameSpaceMap(void) const
Definition: mathp.cc:1984
HighParser & HP
Definition: parser.h:162
const KeyTable * KeyT
Definition: parser.h:431
const char DIR_SEP
Definition: filename.h:88
const unsigned int iDefaultBufSize
Definition: parser.h:133
void PackWords(InputStream &In)
Definition: parser.cc:146
const std::string & GetString(void) const
Definition: mathp.cc:1247
virtual MathParser & GetMathParser(void)
Definition: parser.cc:668
static int skip_remarks(HighParser &HP, InputStream &In, char &cIn)
Definition: parser.cc:49
static void InitDescData(void)
Definition: parser.cc:553
virtual mbsleep_t GetTimeout(const mbsleep_t &DefVal)
Definition: parser.cc:1062
#define ASSERT(expression)
Definition: colamd.c:977
virtual HighParser::Token FirstToken(void)
Definition: parser.cc:767
unsigned iBufSize
Definition: parser.h:165
std::ostream & mbdyn_print_line_data(std::ostream &out)
Definition: parser.cc:613
MathParser & MathP
Definition: parser.h:428
bool Read(HighParser &HP)
Definition: parser.cc:373
Definition: except.h:79
virtual bool IsWord(const std::string &s) const =0
KeyTable(HighParser &hp, const char *const sTable[])
Definition: parser.cc:254
static std::stack< cleanup * > c
Definition: cleanup.cc:59
virtual std::string GetString(const std::string &sDefVal)
Definition: parser.cc:1074
NameSpace * GetNameSpace(const std::string &name) const
Definition: mathp.cc:4620
virtual bool GetYesNo(bool &bRet)
Definition: parser.cc:1022
virtual bool IsArg(void)
Definition: parser.cc:807
virtual int IsKeyWord(void)
Definition: parser.cc:940
doublereal dGetReal(void) const
Definition: parser.cc:230
virtual void NextToken(const char *sFuncName)
Definition: parser.cc:822
HighParser & HP
Definition: parser.h:188
virtual bool IsStringWithDelims(enum Delims Del=DEFAULTDELIM)
Definition: parser.cc:1210
virtual int GetWord(void)
Definition: parser.cc:1083
InputStream * pIn
Definition: parser.h:419
int iGetDescription_int(const char *const s)
Definition: parser.cc:704
HighParser::ErrOut mbdyn_get_line_data(void)
Definition: parser.cc:603
doublereal dCurrNumber
Definition: parser.h:166
#define SAFENEWARR(pnt, item, sz)
Definition: mynewmem.h:701
virtual int GetLineNumber(void) const
Definition: parser.cc:674
virtual void SetDelims(enum Delims Del, char &cLdelim, char &cRdelim) const
Definition: parser.cc:1173
Definition: table.h:43
char *const * sKeyWords
Definition: parser.h:186
virtual Table * GetTable(void)=0
char sStringBuf[iDefaultBufSize]
Definition: parser.h:423
int mbsleep_real2sleep(doublereal d, mbsleep_t *t)
Definition: mbsleep.c:49
double doublereal
Definition: colamd.c:52
long int integer
Definition: colamd.c:51
static std::stack< const HighParser * > pHP
Definition: parser.cc:598
bool GetBool(void) const
Definition: mathp.cc:1188
Table & GetSymbolTable(void) const
Definition: mathp.cc:1931
virtual void PutBackSemicolon(void)
Definition: parser.cc:813
bool Read(HighParser &HP)
Definition: parser.cc:448
static unsigned desc_done
Definition: parser.cc:550
static void DestroyDescData(void)
Definition: parser.cc:575
bool eof(void) const
Definition: input.h:139
int ParseWord(unsigned flags=HighParser::NONE)
Definition: parser.cc:843
bool IsWord(const std::string &s) const
Definition: parser.cc:293
const char * sPathName
Definition: parser.h:305
virtual doublereal GetReal(const doublereal &dDefval=0.0)
Definition: parser.cc:1056