Česky
Kamil Dudka

IFJ 05 (C language)

File detail

Name:Downloadvariables.c [Download]
Location: ifj05 > src
Size:7.2 KB
Last modification:2007-08-29 02:18

Source code

/*
 * Projekt: IFJ05
 * Resitele: xbarin02, xdudka00, xfilak01, xhefka00, xhradi08
 *
 * Soubor: variables.c - modul tabulky konstant a promenych
 * Autor: David Barina, xbarin02
 */
 
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
 
#include "ifj05.h"
#include "variables.h"
#include "scanner.h"
 
/***
 * struct _TVariable
 *   vlastni typ promene (i konstanty)
 */
struct _TVariable
       {
         TVarType VarType;   // jaky je typ promene/konstanty
         void *VarValue;     // ukazatel na jeji hodnotu (nepracujte primo!)
                             //   (char **, int *, double *)
         PVariable next;     // ukazatel na dalsi prvek
       };
 
 
/***
 * ErrorFatal()
 *   moje pomocna funkce pro nahlaseni kriticke chyby a ukonceni programu
 *   vyuziva globalni funkci pro hlaseni chyb GlobalErr()
 *   parametry stejne jako funkce GlobalErr resp. printf()
 */
extern void ErrorFatal(const char *fmt, ...);
 
/***
 * ConstantsCreate()
 *   vytvori tabulku konstant a vrati jeji adresu 
 */
PConstantTable ConstantsCreate()
{
  PConstantTable table = (PConstantTable)malloc(sizeof(TConstantTable));
  if(table == NULL)
    ErrorFatal("Not enough of memory");
  table->first = NULL;
  return(table);
}
 
/***
 * ConstantsInsert()
 *   vlozi prvek do tabulky konstant a vrati ukazatel na nej
 *   1. parametr - typ konstanty
 *   2. parametr - adresa konstanty   
 */
PVariable ConstantsInsert(PConstantTable table, TVarType type, void *value)
{
#ifndef NDEBUG
  if(table == NULL)
    ErrorFatal("Internal error - inserting to uninitialized constant table");
#endif
  switch(type)
  {
    case vtUninit:
    {
#ifndef NDEBUG
      ErrorFatal("Internal error - constant cannot be uninitialized");
#endif
    } break;
    case vtInt:
    case vtFloat:
    case vtString:
    {
      PVariable *constant = &(table->first);
      while(*constant != NULL)
      {
        // konstanty neni treba vkladad vicekrat
        if((*constant)->VarType == type)
        {
          // typ se shoduje, shoduje se i obsah?
          switch(type)
          {
            case vtInt:
            {
              int *new_value = (int *)(value);
              int *cur_value = (int *)((*constant)->VarValue);
              if( (*new_value) == (*cur_value) )
              {
                free(value);
                return(*constant);
              }
            } break;
            case vtFloat:
            {
              double *new_value = (double *)(value);
              double *cur_value = (double *)((*constant)->VarValue);
              if( (*new_value) == (*cur_value) )
              {
                free(value);
                return(*constant);
              }
            } break;
            case vtString:
            {
              char *new_value = (char *)(value);
              char *cur_value = (char *)((*constant)->VarValue);
              if( 0 == strcmp((new_value),(cur_value)) )
              {
                free(value);
                return(*constant);
              }
            } break;
            default:
            {
              // sem se to nikdy nedostane
            }
          }
        }
        constant = &((*constant)->next);
      }
      // musime ji vlozit
      *constant = (PVariable)malloc(sizeof(TVariable));
      if( *constant == NULL)
        ErrorFatal("Not enough of memory");
      (*constant)->VarType = type;
      (*constant)->VarValue = value;
      (*constant)->next = NULL;
      return(*constant);
 
    } break;
    default:
    {
#ifndef NDEBUG
      ErrorFatal("Internal error - unknown variable type");
#endif
    }
  }
#ifndef NDEBUG
  ErrorFatal("Internal error - unhandled constant inserting");
#endif
  return(NULL);
}
 
/***
 * ConstantsDestroy()
 *   zrusi tabulku konstant i s obsahem (vsechny konstanty)
 */
void ConstantsDestroy(PConstantTable table)
{
#ifndef NDEBUG
  if(table == NULL)
    ErrorFatal("Internal error - destroying uninitialized table");
#endif
  PVariable tmp = table->first, tmp2;
  while(tmp != NULL)
  {
    tmp2 = tmp->next;
    free(tmp->VarValue);
    free(tmp);
    tmp = tmp2;
  }
  free(table);
}
 
/***
 * VariablesCreate()
 *   vytvori tabulku promenych a vrati jeji adresu 
 */
PVariableTable VariablesCreate()
{
  PVariableTable table = (PVariableTable)malloc(sizeof(TVariableTable));
  if(table == NULL)
    ErrorFatal("Not enough of memory");
  table->first = NULL;
  return(table);
}
 
/***
 * VariablesInsert()
 *   vlozi prvek do tabulky promenych a vrati ukazatel na nej
 *   promena je napocatku neinicializovana 
 *   parametr - tabulka promennych
 */
PVariable VariablesInsert(PVariableTable table)
{
#ifndef NDEBUG
  if(table == NULL)
    ErrorFatal("Internal error - inserting to uninitialized variable table");
#endif
  PVariable variable = (PVariable)malloc(sizeof(TVariable));
  variable->next = table->first;
  variable->VarType = vtUninit;
  variable->VarValue = NULL;
  table->first = variable;
  return(variable);
}
 
/***
 * VariablesDestroy()
 *   zrusi tabulku promenych i s jejim obsahem (vsechny promene)
 */
void VariablesDestroy(PVariableTable table)
{
#ifndef NDEBUG
  if(table == NULL)
    ErrorFatal("Internal error - destroying uninitialized table");
#endif
  PVariable tmp = table->first, tmp2;
  while(tmp != NULL)
  {
    tmp2 = tmp->next;
    free(tmp->VarValue);
    free(tmp);
    tmp = tmp2;
  }
  free(table);
}
 
/***
 * VariablesStore()
 *   funkce store (pro runtime), kt. ulozi do promene hodnotu
 *   1. parametr - promena
 *   2. parametr - typ noveho obsahu
 *   3. parametr - hodnota noveho obsahu (srara se uvolni)
 */
void VariablesStore(PVariable variable, TVarType type, void *value)
{
#ifndef NDEBUG
  if(variable == NULL)
    ErrorFatal("Internal error - NULL variable pointer");
  if(type == vtUninit)
    ErrorFatal("Internal error - could not uninitialize value");
#endif
  // free(NULL) je korektni operace, neprovede nic
  free(variable->VarValue);
  variable->VarType = type;
  variable->VarValue = value;
}
 
/***
 * VariablesGetType()
 *   funkce get_type (pro runtime) 
 *   vrati typ promene
 *   1. parametr - promena 
 */
TVarType VariablesGetType(PVariable variable)
{
#ifndef NDEBUG
  if(variable == NULL)
    ErrorFatal("Internal error - NULL variable pointer");
#endif
  return(variable->VarType);
}
 
/***
 * VariablesGetValue()
 *   funkce get_value (pro runtime)
 *   vrati obsah promene (nemente ji sami!) 
 *   1. parametr - promena 
 */
void *VariablesGetValue(PVariable variable)
{
#ifndef NDEBUG
  if(variable == NULL)
    ErrorFatal("Internal error - NULL variable pointer");
#endif
  return(variable->VarValue);
}
 
#ifndef NDEBUG
/***
 * ConstantPrint()
 *   vypise typ a obsah konstanty na stdout, ladici funkce
 *   parametr adresa konstanty  
 */
void ConstantPrint(PVariable constant)
{
  if(constant == NULL)
    ErrorFatal("Internal error - NULL constant pointer");
  switch(constant->VarType)
  {
    case vtInt:
    {
      printf("(int)    ");
      int *i = constant->VarValue;
      printf("%i",*i);
    } break;
    case vtFloat:
    {
      printf("(float)  ");
      double *d = constant->VarValue;
      printf("%g",*d);
    } break;
    case vtString:
    {
      printf("(string) ");
      char *c = constant->VarValue;
      printf("'%s'",c);
    } break;
    case vtUninit:
    {
      printf("(uninit) ERROR");
    } break;
    default:
    {
      printf("(unknown)ERROR");
    }
  }
}
#endif