LCOV - code coverage report
Current view: top level - src/common - tables.cpp (source / functions) Hit Total Coverage
Test: flower-f.info Lines: 315 399 78.9 %
Date: 2022-06-10 00:44:15 Functions: 47 50 94.0 %

          Line data    Source code
       1             : #include <iostream>
       2             : #include <cstring>
       3             : #include <vector>
       4             : #include "config.hpp"
       5             : #include "common/tables.hpp"
       6             : #include "common/obstacle.hpp"
       7             : #include "common/exprtype.hpp"
       8             : //#include "common/util.hpp"
       9             : 
      10         236 : bool charEqual(const char* a, const char* b) {
      11         236 :     bool ret = true;
      12         236 :     int i = 0;
      13         780 :     while (ret && (a[i] != '\0') && (b[i] != '\0')) {
      14         544 :         ret = ret && (a[i] == b[i]);
      15         544 :         i++;
      16             :     }
      17         236 :     ret = ret && (a[i] == '\0') && (b[i] == '\0');
      18         236 :     return ret;
      19             : }
      20             : 
      21         841 : IdentTable::IdentTable(void) {
      22         841 :     valType = _NONE_;
      23         841 :     structName = nullptr;
      24         841 :     name = nullptr;
      25         841 :     fadedName = nullptr;
      26         841 :     def = false;
      27         841 :     func = false;
      28         841 :     reg = false;
      29         841 :     val = nullptr;
      30         841 :     ord = 0;
      31         841 :     params = 0;
      32         841 :     offset = 0;
      33         841 :     next = nullptr;
      34         841 :     shared = false;
      35         841 :     mainTable = nullptr;
      36         841 : }
      37             : 
      38          96 : IdentTable::IdentTable(const IdentTable & templateIT) {
      39          96 :     valType = templateIT.valType;
      40          96 :     def = templateIT.def;
      41          96 :     ord = templateIT.ord;
      42          96 :     offset = templateIT.offset;
      43          96 :     func = templateIT.func;
      44          96 :     reg = templateIT.reg;
      45          96 :     params = templateIT.params;
      46          96 :     shared = templateIT.shared;
      47          96 :     mainTable = templateIT.mainTable;
      48             : 
      49          96 :     if (templateIT.structName != nullptr) {
      50           6 :         structName = new char[strnlen(templateIT.structName, MAXIDENT) + 1];
      51           6 :         memccpy(structName, templateIT.structName, '\0', strnlen(templateIT.structName, MAXIDENT) + 1);
      52          90 :     } else structName = nullptr;
      53             : 
      54          96 :     if (templateIT.name != nullptr) {
      55          96 :         name = new char[strnlen(templateIT.name, MAXIDENT) + 1];
      56          96 :         memccpy(name, templateIT.name, '\0', strnlen(templateIT.name, MAXIDENT) + 1);
      57           0 :     } else name = nullptr;
      58             : 
      59          96 :     if (templateIT.fadedName != nullptr) {
      60           0 :         fadedName = new char[strnlen(templateIT.fadedName, MAXIDENT) + 1];
      61           0 :         memccpy(fadedName, templateIT.fadedName, '\0', strnlen(templateIT.fadedName, MAXIDENT) + 1);
      62          96 :     } else fadedName = nullptr;
      63             :     
      64          96 :     if (templateIT.valType == _STRUCT_)
      65           6 :         val = new IdentTable( * static_cast<IdentTable *>(templateIT.val));
      66          90 :     else val = templateIT.val;
      67             : 
      68          96 :     if (templateIT.next->getType() != _NONE_)
      69          60 :         next = new IdentTable(*templateIT.next);
      70          36 :     else next = new IdentTable;
      71          96 : }
      72             : 
      73           0 : IdentTable & IdentTable::operator=(const IdentTable & templateIT) {
      74           0 :     if (this == &templateIT) return *this;
      75             : 
      76           0 :     valType = templateIT.valType;
      77           0 :     def = templateIT.def;
      78           0 :     ord = templateIT.ord;
      79           0 :     offset = templateIT.offset;
      80           0 :     func = templateIT.func;
      81           0 :     reg = templateIT.reg;
      82           0 :     params = templateIT.params;
      83           0 :     shared = templateIT.shared;
      84           0 :     mainTable = templateIT.mainTable;
      85             : 
      86           0 :     if (templateIT.structName != nullptr) {
      87           0 :         structName = new char[strnlen(templateIT.structName, MAXIDENT) + 1];
      88           0 :         memccpy(structName, templateIT.structName, '\0', strnlen(templateIT.structName, MAXIDENT) + 1);
      89           0 :     } else structName = nullptr;
      90             : 
      91           0 :     if (templateIT.name != nullptr) {
      92           0 :         name = new char[strnlen(templateIT.name, MAXIDENT) + 1];
      93           0 :         memccpy(name, templateIT.name, '\0', strnlen(templateIT.name, MAXIDENT) + 1);
      94           0 :     } else name = nullptr;
      95             : 
      96           0 :     if (templateIT.fadedName != nullptr) {
      97           0 :         fadedName = new char[strnlen(templateIT.fadedName, MAXIDENT) + 1];
      98           0 :         memccpy(fadedName, templateIT.fadedName, '\0', strnlen(templateIT.fadedName, MAXIDENT) + 1);
      99           0 :     } else fadedName = nullptr;
     100             :     
     101           0 :     if (templateIT.valType == _STRUCT_)
     102           0 :         val = new IdentTable( * static_cast<IdentTable *>(templateIT.val));
     103           0 :     else val = templateIT.val;
     104             : 
     105           0 :     if (templateIT.next->getType() != _NONE_)
     106           0 :         next = new IdentTable(*templateIT.next);
     107           0 :     else next = new IdentTable;
     108             :     
     109           0 :     return *this;
     110             : }
     111             : 
     112             : // Получаем последний объект списка
     113        1998 : IdentTable * IdentTable::last(void) {
     114        1998 :     IdentTable * p = this;
     115       19583 :     while (p->next != nullptr) p = p->next;
     116        1998 :     return p;
     117             : }
     118             : 
     119             : // Сохраняем идентификатор переменной
     120         400 : void IdentTable::pushId(char* ident) {
     121         400 :     IdentTable * p = this;
     122        3912 :     while (p->next != nullptr) {
     123        3513 :         if ((p->name != nullptr) && (ident != nullptr) && (strcmp(p->name, ident) == 0)) {
     124           1 :             delete [] ident;
     125           1 :             throw Obstacle(IDENT_DUP);
     126             :         }
     127        3512 :         p = p->next;
     128             :     }
     129         399 :     p->name = ident;
     130         399 : }
     131             : 
     132             : // Сохраняем тип переменной
     133         633 : void IdentTable::pushType(type_t t) {
     134         633 :     last()->valType = t;
     135         633 : }
     136             : 
     137          23 : void IdentTable::pushStruct(char * name) {
     138          23 :     last()->structName = name;
     139          23 : }
     140             : 
     141             : // Сохраняем значение переменной
     142         435 : void IdentTable::pushVal(void* v) {
     143         435 :     IdentTable * l = last();
     144         435 :     l->val = v;
     145         435 :     l->def = true;
     146         435 : }
     147             : 
     148             : // Всё, что могло быть известно, мы узнали. Переключаемся на новый объект.
     149         687 : IdentTable * IdentTable::confirm(void) {
     150         687 :     IdentTable * l = last();
     151             : 
     152             :     #ifdef DEBUG
     153             :     std::cout << "Создан новый объект: ";
     154             :     l->whoami();
     155             :     std::cout << std::endl;
     156             :     #endif
     157             : 
     158         687 :     IdentTable * newIdent = new IdentTable;
     159         687 :     l->next = newIdent;
     160         687 :     l->next->ord = l->ord + 1;
     161         687 :     newIdent->mainTable = l->mainTable;
     162             : 
     163         687 :     return l;
     164             : }
     165             : 
     166             : // Дублирование типа для выражений вида:
     167             : // int a, b, c;
     168         122 : void IdentTable::dupType(void) {
     169         122 :     IdentTable * p = this;
     170         122 :     if (last()->valType == _NONE_) {
     171         172 :         while (p->next->next != nullptr) p = p->next;
     172          33 :         p->next->valType = p->valType;
     173          33 :         p->next->shared = p->shared;
     174          33 :         if (p->structName != nullptr) {
     175           7 :             p->next->structName = new char[strnlen(p->structName, MAXIDENT) + 1];
     176           7 :             memccpy(p->next->structName, p->structName, '\0', strnlen(p->structName, MAXIDENT) + 1);
     177             :         }
     178          33 :         if (p->valType == _STRUCT_) {
     179           7 :             p->next->val = new IdentTable(* static_cast<IdentTable *>(p->val));
     180           7 :             p = static_cast<IdentTable *>(p->next->val);
     181          30 :             while (p->next != nullptr) {
     182          23 :                 if (p->valType != _STRUCT_)
     183          21 :                     p->val = nullptr;
     184          23 :                 p->def = false;
     185          23 :                 p = p->next;
     186             :             }
     187             :         }
     188             :     }
     189         122 : }
     190             : 
     191        1171 : type_t IdentTable::getType(void) const {
     192        1171 :     return valType;
     193             : }
     194             : 
     195          22 : void IdentTable::setType(type_t newType) {
     196          22 :     valType = newType;
     197          22 : }
     198             : 
     199          65 : char * IdentTable::getStruct(void) const {
     200          65 :     return structName;
     201             : }
     202             : 
     203          26 : void IdentTable::setFunc(void) {
     204          26 :     func = true;
     205          26 : }
     206             : 
     207         268 : bool IdentTable::isFunc(void) const {
     208         268 :     return func;
     209             : }
     210             : 
     211          20 : void IdentTable::setOrd(int x) {
     212          20 :     ord = x;
     213          20 : }
     214             : 
     215          29 : void IdentTable::setReg(bool x) {
     216          29 :     reg = x;
     217          29 : }
     218             : 
     219         903 : bool IdentTable::isReg(void) const {
     220         903 :     return reg;
     221             : }
     222             : 
     223          24 : void IdentTable::setParams(int x) {
     224          24 :     params = x;
     225          24 : }
     226             : 
     227          20 : int IdentTable::getParams(void) const {
     228          20 :     return params;
     229             : }
     230             : 
     231         512 : IdentTable * IdentTable::getIT(char * name, bool autodel) {
     232         512 :     IdentTable * p = this;
     233             : 
     234        2584 :     while ((p->name == nullptr) || (strcmp(p->name, name) != 0)) {
     235        2088 :         if (p->next->valType != _NONE_) p = p->next;
     236             :         else {
     237          16 :             if (autodel) delete [] name;
     238          16 :             throw Obstacle(IDENT_NOT_DEF);
     239             :         }
     240             :     }
     241             : 
     242         496 :     delete [] name;
     243             : 
     244         496 :     return p;
     245             : }
     246             : 
     247           0 : void IdentTable::whoami() {
     248             : 
     249           0 :     std::cout << '[' << typetostr(valType) << ' ';
     250           0 :     if (valType == _STRUCT_) {
     251           0 :         std::cout << structName << ' ';
     252           0 :         if (name != nullptr) std::cout << name;
     253           0 :         else std::cout << "? ";
     254           0 :         if (func) std::cout << "FUNCTION ";
     255           0 :         std::cout << " = [";
     256           0 :         IdentTable * fields = static_cast<IdentTable *>(val);
     257           0 :         while (fields->next != nullptr) {
     258           0 :             fields->whoami();
     259           0 :             fields = fields->next;
     260             :         }
     261           0 :         std::cout << " ]";
     262             :     } else {
     263           0 :         if (func) std::cout << "FUNCTION ";
     264           0 :         if (name != nullptr)
     265           0 :             std::cout << name;
     266           0 :         if (fadedName != nullptr) 
     267           0 :             std::cout << '(' << fadedName << ") ";
     268           0 :         if (func) std::cout << " (params num: " << params << ")";
     269           0 :         else if (def) {
     270           0 :             std::cout << "= ";
     271           0 :             switch (valType) {
     272           0 :                 case _INT_: case _LABEL_:
     273           0 :                     std::cout << * static_cast<int *>  ( val ); break;
     274           0 :                 case _REAL_:
     275           0 :                     std::cout << * static_cast<float *>( val ); break;
     276           0 :                 case _STRING_:
     277           0 :                     std::cout <<   static_cast<char *> ( val ); break;
     278           0 :                 case _BOOLEAN_:
     279           0 :                     std::cout << * static_cast<bool *> ( val ); break;
     280           0 :                 default: 
     281           0 :                     std::cout << "?"; break;
     282             :             }
     283           0 :         } else std::cout << "= ?";
     284             :     }
     285           0 :     std::cout << ']';
     286             : 
     287           0 : }
     288             : 
     289           0 : void IdentTable::repr(void) {
     290           0 :     IdentTable * p = this;
     291           0 :     std::cout << "IdentTable:" << std::endl;
     292           0 :     while (p->next != nullptr) {
     293           0 :         std::cout << p << " ";
     294           0 :         p->whoami();
     295           0 :         std::cout << std::endl;
     296           0 :         p = p->next;
     297             :     }
     298           0 : }
     299             : 
     300          38 : void IdentTable::setId(char * name) {
     301          38 :     if (this->name != nullptr) delete [] this->name;
     302          38 :     this->name = name;
     303          38 : }
     304             : 
     305          11 : char * IdentTable::getId(void) const {
     306          11 :     return this->name;
     307             : }
     308             : 
     309         292 : void * IdentTable::getVal(void) const {
     310         292 :     return val;
     311             : }
     312             : 
     313         155 : void IdentTable::setVal(void * val) {
     314         155 :     this->val = val;
     315         155 :     def = true;
     316         155 : }
     317             : 
     318         436 : void IdentTable::setOffset(int x) {
     319         436 :     offset = x;
     320         436 : }
     321             : 
     322         675 : int IdentTable::getOffset(void) const {
     323         675 :     return offset;
     324             : }
     325             : 
     326          87 : int IdentTable::getOrd(void) const {
     327          87 :     return ord;
     328             : }
     329             : 
     330         410 : void IdentTable::writeValToStream(std::ostream & s) {
     331         410 :     if (func) return;
     332             :     
     333         394 :     if (!def) {
     334         118 :         switch (valType) {
     335          58 :             case _INT_: case _LABEL_:
     336          58 :                 val = new int (0); break;
     337          30 :             case _REAL_:
     338          30 :                 val = new float (0); break;
     339           9 :             case _STRING_:
     340           9 :                 val = new char[1];
     341           9 :                 static_cast<char*>(val)[0] = '\0'; 
     342           9 :                 break;
     343          12 :             case _BOOLEAN_:
     344          12 :                 val = new bool (false); break;
     345           9 :             case _STRUCT_: break;
     346           0 :             default:
     347           0 :                 throw Obstacle(PANIC);
     348             :         }
     349         118 :         def = true;
     350             :     }
     351             :     IdentTable * ITp;
     352         394 :     switch (valType) {
     353         225 :         case _INT_: case _LABEL_:
     354         225 :             s.write(static_cast<char*>(val), sizeof(int)); break;
     355          44 :         case _REAL_:
     356          44 :             s.write(static_cast<char*>(val), sizeof(float)); break;
     357          73 :         case _STRING_:
     358          73 :             s.write("\0\0\0\0\0\0\0\0", sizeof(void*));
     359          73 :             s.write(static_cast<char*>(val), sizeof(char) * (strlen(static_cast<char*>(val)) + 1));
     360          73 :             break;
     361          24 :         case _BOOLEAN_:
     362          24 :             s.write(static_cast<char*>(val), sizeof(bool)); break;
     363          28 :         case _STRUCT_:
     364          28 :             ITp = static_cast<IdentTable*>(val);
     365         109 :             while (ITp->next != nullptr) {
     366          81 :                 ITp->setOffset((int)s.tellp());
     367          81 :                 ITp->writeValToStream(s);
     368          81 :                 ITp = ITp->next;
     369             :             }
     370          28 :             break;
     371           0 :         default:
     372           0 :             throw Obstacle(PANIC);
     373             :     }
     374             : }
     375             : 
     376          29 : IdentTable * IdentTable::deleteLabels(void) {
     377          29 :     IdentTable *p = this, *head = this, *temp;
     378             : 
     379          29 :     while ((p->next != nullptr) && (p->next->valType == _LABEL_))
     380           0 :         p = p->next;
     381             : 
     382          29 :     if (head->valType == _LABEL_)
     383          29 :         head = p->next;
     384             : 
     385          29 :     p = head;
     386             : 
     387          29 :     if (p == nullptr) return p;
     388             : 
     389         383 :     while (p->next != nullptr) {
     390         354 :         if (p->next->valType == _LABEL_) {
     391         103 :             temp = p->next;
     392         103 :             p->next = p->next->next;
     393         103 :             temp->next = nullptr;
     394         103 :             delete temp;
     395         251 :         } else p = p->next;
     396             :     }    
     397             : 
     398          29 :     return head;
     399             : }
     400             : 
     401         118 : bool IdentTable::isDef(void) const {
     402         118 :     return def;
     403             : }
     404             : 
     405        4104 : bool operator==(IdentTable & a, IdentTable & b) {
     406        4104 :     if (&a == &b) return true;
     407             : 
     408        4104 :     if ((a.name == nullptr) && (b.name == nullptr)) {
     409        2777 :         if (a.valType != b.valType) return false;
     410         929 :         if ((a.val == nullptr) && (b.val == nullptr))
     411          20 :             return true;
     412         909 :         if ((a.val == nullptr) || (b.val == nullptr))
     413         105 :             return false;
     414             :         bool ret;
     415         804 :         switch (a.valType) {
     416         219 :             case _INT_:
     417         219 :                 ret = ((*static_cast<int *>(a.val)) == (*static_cast<int *>(b.val)));
     418         219 :                 break;
     419           2 :             case _REAL_:
     420           2 :                 ret = ((*static_cast<float *>(a.val)) == (*static_cast<float *>(b.val)));
     421           2 :                 break;
     422         116 :             case _STRING_:
     423         116 :                 ret = charEqual(static_cast<char *>(a.val), static_cast<char *>(b.val));
     424         116 :                 break;
     425           1 :             case _BOOLEAN_:
     426           1 :                 ret = ((*static_cast<bool *>(a.val)) == (*static_cast<bool *>(b.val)));
     427           1 :                 break;
     428         466 :             default:
     429         466 :                 ret = false;
     430             :         }
     431         804 :         return ret;
     432             :     }
     433             : 
     434        1327 :     if ((a.name != nullptr) && (b.name != nullptr))
     435         120 :         return charEqual(a.name, b.name);
     436             : 
     437        1207 :     return false;
     438             : }
     439             : 
     440         138 : void IdentTable::fade(void) {
     441         138 :     fadedName = name;
     442         138 :     name = nullptr;
     443         138 : }
     444             : 
     445         292 : bool IdentTable::isShared(void) const {
     446         292 :     return shared;
     447             : }
     448             : 
     449          10 : void IdentTable::setShared(void) {
     450          10 :     shared = true;
     451          10 : }
     452             : 
     453         355 : void IdentTable::setMainTable(IdentTable* table) {
     454         355 :     mainTable = table;
     455         355 :     if (structName != nullptr) {
     456          33 :         static_cast<IdentTable*>(val)->setMainTable(table);
     457             :     }
     458         355 :     if (next != nullptr) {
     459         205 :         next->setMainTable(table);
     460             :     }
     461         355 : }
     462             : 
     463          38 : IdentTable* IdentTable::getMainTable(void) {
     464          38 :     return mainTable;
     465             : }
     466             : 
     467           1 : void IdentTable::setStruct(char * name) {
     468           1 :     structName = name;
     469           1 : }
     470             : 
     471        1874 : IdentTable::~IdentTable() {
     472         937 :     if (name != nullptr) delete [] name;
     473         937 :     if (fadedName != nullptr) delete [] fadedName;
     474             : 
     475         937 :     if ((val != nullptr) && (!func)) {
     476         690 :         switch (valType) {
     477         475 :             case _INT_: case _LABEL_:
     478         475 :                 delete static_cast<int *>( val ); break;
     479          46 :             case _REAL_:
     480          46 :                 delete static_cast<float *>( val ); break;
     481          26 :             case _BOOLEAN_:
     482          26 :                 delete static_cast<bool *>( val ); break;
     483         107 :             case _STRING_: 
     484         107 :                 delete [] static_cast<char *>( val ); break;
     485          36 :             case _STRUCT_: 
     486          36 :                 delete static_cast<IdentTable*>(val); break;
     487           0 :             default: break;
     488             :         }
     489             :     }
     490         937 :     if (structName != nullptr) delete [] structName;
     491             : 
     492         937 :     if (next != nullptr) delete next;
     493         937 : }
     494             : 
     495          69 : StructTable * StructTable::last(void) {
     496          69 :     StructTable * p = this;
     497          92 :     while (p->next != nullptr) p = p->next;
     498          69 :     return p;
     499             : }
     500             : 
     501          16 : void StructTable::pushName(char * name) {
     502          16 :     last()->name = name;
     503          16 : }
     504             : 
     505          37 : void StructTable::pushField(type_t type, char * name, char * structName, bool shared) {
     506          37 :     StructTable * l = last();
     507          37 :     l->fields.pushType(type);
     508          37 :     l->fields.pushId(name);
     509          37 :     if (shared) l->fields.setShared();
     510          37 :     if (structName != nullptr) {
     511           3 :         l->fields.pushStruct(structName);
     512           3 :         IdentTable & templateIT = getStruct(structName)->getFields();
     513           3 :         l->fields.pushVal(new IdentTable(templateIT));
     514             :     }
     515          37 :     l->fields.confirm();
     516          37 : }
     517             : 
     518          16 : StructTable * StructTable::confirm(void) {
     519          16 :     StructTable * p = last();
     520             : 
     521             :     #ifdef DEBUG
     522             :     std::cout << "Описана новая структура: " << p->name << '{';
     523             :     IdentTable * targetFields = & p->fields;
     524             :     targetFields->whoami();
     525             :     while (targetFields->next->next != nullptr) {
     526             :         std::cout << ", ";
     527             :         targetFields = targetFields->next;
     528             :         targetFields->whoami();
     529             :     }
     530             :     std::cout << '}' << std::endl;
     531             :     #endif
     532             : 
     533          16 :     p->next = new StructTable;
     534             : 
     535          16 :     return p;
     536             : }
     537             : 
     538          43 : StructTable * StructTable::getStruct(char * name) {
     539          43 :     StructTable * p = this;
     540             : 
     541          52 :     while (p != nullptr) {
     542          52 :         if (strcmp(p->name, name) == 0) break;
     543           9 :         p = p->next;
     544             :     }
     545             : 
     546          43 :     if (p == nullptr)
     547           0 :         throw Obstacle(STRUCT_UNDEF);
     548             : 
     549          43 :     return p;
     550             : }
     551             : 
     552          25 : IdentTable & StructTable::getFields(void) {
     553          25 :     return fields;
     554             : }
     555             : 
     556          18 : std::vector<type_t> StructTable::getTypes(char * name) {
     557          18 :     std::vector<type_t> result;
     558             : 
     559          18 :     IdentTable * targetFields = & getStruct(name)->fields;
     560          68 :     while (targetFields->next != nullptr) {
     561          50 :         type_t type = targetFields->getType();
     562          50 :         if (type == _STRUCT_) {
     563           2 :             std::vector<type_t> part = getTypes(targetFields->getStruct());
     564           2 :             result.reserve(result.size() + part.size());
     565           2 :             result.insert(result.end(), part.begin(), part.end());
     566          48 :         } else result.push_back(type);
     567          50 :         targetFields = targetFields->next;
     568             :     }
     569             : 
     570          18 :     return result;
     571             : }
     572             : 
     573          67 : StructTable::~StructTable(void) {
     574          67 :     if (name != nullptr) delete [] name;
     575          67 :     if (next != nullptr) delete next;
     576          67 : }

Generated by: LCOV version 1.14