Exemplo n.º 1
0
/* This routine will create the value object */
static exprVal *exprCreateVal(char *name, EXPRTYPE val, EXPRTYPE * addr)
{
	exprVal *tmp;
	char *vtmp;

	/* Name already tested in exprValListAdd */

	/* Create it */
	tmp = exprAllocMem(sizeof(exprVal));
	if (tmp == NULL)
		return NULL;

	/* Allocate space for the name */
	vtmp = exprAllocMem(strlen(name) + 1);

	if (vtmp == NULL) {
		exprFreeMem(tmp);
		return NULL;
	}

	/* Copy the data over */
	strcpy(vtmp, name);
	tmp->vname = vtmp;
	tmp->vval = val;
	tmp->vptr = addr;

	return tmp;
}
Exemplo n.º 2
0
/* This routine will create the function object */
exprFunc *exprCreateFunc(exprFuncType ptr, char *name, int min, int max, int refmin, int refmax)
    {
    exprFunc *tmp;
    char *vtmp;

    /* Make sure the name is valid */
    if(!exprValidIdent(name))
        return NULL;

    /* Create it */
    tmp = exprAllocMem(sizeof(exprFunc));
    if(tmp == NULL)
        return NULL;

    /* Allocate space for the name */
    vtmp = exprAllocMem(strlen(name) + 1);

    if(vtmp == NULL)
        {
        exprFreeMem(tmp);
        return NULL;
        }

    /* Set the memory to zero */
    memset(tmp, 0, sizeof(exprFunc));

    /* Copy the data over */
    strcpy(vtmp, name);
    tmp->fname = vtmp;
    tmp->fptr = ptr;
    tmp->min = min;
    tmp->max = max;
    tmp->refmin = refmin;
    tmp->refmax = refmax;

    return tmp;
    }
Exemplo n.º 3
0
/* This function creates the value list, */
int exprValListCreate(exprValList ** vlist)
{
	exprValList *tmp;

	if (vlist == NULL)
		return EXPR_ERROR_NULLPOINTER;

	*vlist = NULL;				/* Set to NULL initially */

	tmp = exprAllocMem(sizeof(exprValList));

	if (tmp == NULL)
		return EXPR_ERROR_MEMORY;	/* Could not allocate memory */

	/* Update pointer */
	*vlist = tmp;

	return EXPR_ERROR_NOERROR;
}
Exemplo n.º 4
0
/* This function creates the function list, */
int exprFuncListCreate(exprFuncList **f)
    {
    exprFuncList *tmp;

    if(f == NULL)
        return EXPR_ERROR_NULLPOINTER;

    *f = NULL; /* Set to NULL initially */

    tmp = exprAllocMem(sizeof(exprFuncList));

    if(tmp == NULL)
        return EXPR_ERROR_MEMORY; /* Could not allocate memory */

    /* Clear memory */
    memset(tmp, 0, sizeof(exprFuncList));
    *f = tmp;

    return EXPR_ERROR_NOERROR;
    }
Exemplo n.º 5
0
/* Allocate a list of nodes */
exprNode *exprAllocNodes(size_t count)
{
	return exprAllocMem(count * sizeof(exprNode));
}
Exemplo n.º 6
0
/* This converts an expression string to a token list */
int exprStringToTokenList(exprObj *obj, char *expr, exprToken **tokens, int *count)
{
  int found;
  exprToken *list;
  int pass;
  int pos, len;
  int tpos;
  int comment; /* Is a comment active */
  int start, ilen;
  char buf[EXPR_MAXIDENTSIZE + 1];

  /* Set initial variables */
  found = 0;
  tpos = 0;
  list = NULL;
  comment = 0;
  *tokens = NULL;
  *count = 0;


  /* Check string length */
  len = strlen(expr);
  if(len == 0)
    return EXPR_ERROR_EMPTYEXPR;

  /* Two passes, one to count, one to tokenize */
  for(pass = 0; pass <= 1; pass++)
    {
      for(pos = 0; pos < len; pos++)
        {
          switch(expr[pos])
            {
              /* Comment */
              case '#':
                {
                  /* Only set it if a comment is not already active */
                  if(!comment)
                    comment = 1;

                  break;
                }

                /* Newline characters turn off comments */
              case '\r':
              case '\n':
                {
                  /* If a comment is active, unset it */
                  if(comment)
                    comment = 0;

                  break;
                }

                /* Open parenthesis */
              case '(':
                {
                  if(!comment)
                    {
                      if(pass == 0)
                        found++;
                      else
                        {
                          list[tpos].type = EXPR_TOKEN_OPAREN;
                          list[tpos].start = pos;
                          list[tpos].end = pos;
                          tpos++;
                        }
                    }

                  break;
                }

                /* Close parenthesis */
              case ')':
                {
                  if(!comment)
                    {
                      if(pass == 0)
                        found++;
                      else
                        {
                          list[tpos].type = EXPR_TOKEN_CPAREN;
                          list[tpos].start = pos;
                          list[tpos].end = pos;
                          tpos++;
                        }
                    }

                  break;
                }

                /* Plus */
              case '+':
                {
                  if(!comment)
                    {
                      if(pass == 0)
                        found++;
                      else
                        {
                          list[tpos].type = EXPR_TOKEN_PLUS;
                          list[tpos].start = pos;
                          list[tpos].end = pos;
                          tpos++;
                        }
                    }

                  break;
                }

                /* Hyphen */
              case '-':
                {
                  if(!comment)
                    {
                      if(pass == 0)
                        found++;
                      else
                        {
                          list[tpos].type = EXPR_TOKEN_HYPHEN;
                          list[tpos].start = pos;
                          list[tpos].end = pos;
                          tpos++;
                        }
                    }

                  break;
                }

                /* Asterisk */
              case '*':
                {
                  if(!comment)
                    {
                      if(pass == 0)
                        found++;
                      else
                        {
                          list[tpos].type = EXPR_TOKEN_ASTERISK;
                          list[tpos].start = pos;
                          list[tpos].end = pos;
                          tpos++;
                        }
                    }

                  break;
                }

                /* Forward slash */
              case '/':
                {
                  if(!comment)
                    {
                      if(pass == 0)
                        found++;
                      else
                        {
                          list[tpos].type = EXPR_TOKEN_FSLASH;
                          list[tpos].start = pos;
                          list[tpos].end = pos;
                          tpos++;
                        }
                    }

                  break;
                }

                /* Hat */
              case '^':
                {
                  if(!comment)
                    {
                      if(pass == 0)
                        found++;
                      else
                        {
                          list[tpos].type = EXPR_TOKEN_HAT;
                          list[tpos].start = pos;
                          list[tpos].end = pos;
                          tpos++;
                        }
                    }

                  break;
                }

                /* Ampersand */
              case '&':
                {
                  if(!comment)
                    {
                      if(pass == 0)
                        found++;
                      else
                        {
                          list[tpos].type = EXPR_TOKEN_AMPERSAND;
                          list[tpos].start = pos;
                          list[tpos].end = pos;
                          tpos++;
                        }
                    }

                  break;
                }

                /* Semicolon */
              case ';':
                {
                  if(!comment)
                    {
                      if(pass == 0)
                        found++;
                      else
                        {
                          list[tpos].type = EXPR_TOKEN_SEMICOLON;
                          list[tpos].start = pos;
                          list[tpos].end = pos;
                          tpos++;
                        }
                    }

                  break;
                }

                /* Comma */
              case ',':
                {
                  if(!comment)
                    {
                      if(pass == 0)
                        found++;
                      else
                        {
                          list[tpos].type = EXPR_TOKEN_COMMA;
                          list[tpos].start = pos;
                          list[tpos].end = pos;
                          tpos++;
                        }
                    }

                  break;
                }

                /* Equal sign */
              case '=':
                {
                  if(!comment)
                    {
                      if(pass == 0)
                        found++;
                      else
                        {
                          list[tpos].type = EXPR_TOKEN_EQUAL;
                          list[tpos].start = pos;
                          list[tpos].end = pos;
                          tpos++;
                        }
                    }

                  break;
                }

                /* Identifiers and values */
              default:
                {
                  if(!comment)
                    {
                      if(expr[pos] == '.' || isdigit(expr[pos]))
                        {
                          /* Value */
                          start = pos;

                          /* Find digits before a period */
                          while(isdigit(expr[pos]))
                            pos++;

                          /* Find a period */
                          if(expr[pos] == '.')
                            pos++;

                          /* Find digits after a period */
                          while(isdigit(expr[pos]))
                            pos++;

                          /* pos is AFTER last item, back up */
                          pos--;

                          if(pass == 0)
                            found++;
                          else
                            {
                              ilen = pos - start + 1;

                              /* Is the value to large */
                              if(ilen > EXPR_MAXIDENTSIZE)
                                {
                                  obj->starterr = start;
                                  obj->enderr = pos;
                                  exprFreeTokenList(list, found);
                                  return EXPR_ERROR_BADIDENTIFIER;
                                }

                              /* Create value token */
                              strncpy(buf, expr + start, ilen);
                              buf[ilen] = '\0';

                              list[tpos].type = EXPR_TOKEN_VALUE;
                              list[tpos].start = start;
                              list[tpos].end = pos;
                              list[tpos].data.val = (EXPRTYPE)atof(buf);
                              tpos++;
                            }
                        }
                      else if(expr[pos] == '_' || isalpha(expr[pos]))
                        {
                          /* Identifier */
                          start = pos;

                          /* Find rest of identifier */
                          while(expr[pos] == '_' || isalnum(expr[pos]))
                            pos++;

                          /* pos is AFTER last item, back up */
                          pos--;

                          if(pass == 0)
                            found++;
                          else
                            {
                              ilen = pos - start + 1;

                              /* Is the value to large */
                              if(ilen > EXPR_MAXIDENTSIZE)
                                {
                                  obj->starterr = start;
                                  obj->enderr = pos;
                                  exprFreeTokenList(list, found);
                                  return EXPR_ERROR_BADIDENTIFIER;
                                }

                              /* Create value token */
                              strncpy(buf, expr + start, ilen);
                              buf[ilen] = '\0';

                              /* Allocate memory for identifier */
                              list[tpos].data.str = exprAllocMem(ilen + 1);
                              if(list[tpos].data.str == NULL)
                                {
                                  exprFreeTokenList(list, found);
                                  return EXPR_ERROR_MEMORY;
                                }

                              list[tpos].type = EXPR_TOKEN_IDENTIFIER;
                              list[tpos].start = start;
                              list[tpos].end = pos;
                              strcpy(list[tpos].data.str, buf);
                              tpos++;
                            }
                        }
                      else if(isspace(expr[pos]))
                        {
                          /* Spaces are ignored, do nothing */
                        }
                      else
                        {
                          /* Unknown */
                          obj->starterr = obj->enderr = pos;
                          exprFreeTokenList(list, found);
                          return EXPR_ERROR_INVALIDCHAR;
                        }
                    }

                  break;
                }
            }
        }

      /* If pass is 0, allocate memory for next pass */
      if(pass == 0)
        {
          /* First, make sure all comments were ended */
          if(comment)
            comment = 0;

          /* Make sure the expression is not empty */
          if(found == 0)
            return EXPR_ERROR_EMPTYEXPR;

          /* Allocate memory for token list */
          list = exprAllocMem(found * sizeof(exprToken));
          if(list == NULL)
            return EXPR_ERROR_MEMORY;

          tpos = 0;
        }
    }

  *count = found;
  *tokens = list;
  return EXPR_ERROR_NOERROR;
}
Exemplo n.º 7
0
/* Function will parse a call to a function */
int exprInternalParseFunction(exprObj *obj, exprNode *node, exprToken *tokens, int start, int end, int p1, int p2)
{
  int pos;
  int num, cur;
  int refnum, refcur;
  int plevel = 0;
  int lv, err;
  exprNode *tmp;
  exprFuncType fptr;
  int argmin, argmax;
  int refargmin, refargmax;
  int type;
  exprFuncList *l;
  exprValList *vars;
  EXPRTYPE *addr;
  EXPRTYPE **reftmp;

  /* We should have a function list */
  l = exprGetFuncList(obj);
  if(l == NULL)
    return EXPR_ERROR_NOSUCHFUNCTION;

  /* check paren. location */
  if(p2 <= p1)
    return EXPR_ERROR_SYNTAX;

  /* second paren. should not be after the end */
  if(p2 > end)
    return EXPR_ERROR_SYNTAX;

  /* Item before parenthesis should be an identifier */
  if(tokens[p1 - 1].type != EXPR_TOKEN_IDENTIFIER)
    {
      obj->starterr = tokens[p1 - 1].start;
      obj->enderr = tokens[p1].end;
      return EXPR_ERROR_SYNTAX;
    }


  /* Look up the function */
  err = exprFuncListGet(l, tokens[p1 - 1].data.str, &fptr, &type, &argmin, &argmax, &refargmin, &refargmax);
  if(err != EXPR_ERROR_NOERROR)
    {
      if(err == EXPR_ERROR_NOTFOUND)
        {
          obj->starterr = tokens[p1 - 1].start;
          obj->enderr = tokens[p1 - 1].end;
          return EXPR_ERROR_NOSUCHFUNCTION;
        }
      else
        return err;
    }

  /* Make sure the function exists */
  if(fptr == NULL && type == 0)
    {
      obj->starterr = tokens[p1 - 1].start;
      obj->enderr = tokens[p1 - 1].end;
      return EXPR_ERROR_NOSUCHFUNCTION;
    }

  /* Count arguments */
  if(p2 == p1 + 1)
    {
      num = 0;
      refnum = 0;
    }
  else
    {
      num = 1;
      refnum = 0;


      /* count commas */
      for(pos = p1 + 1; pos < p2; pos++)
        {
          switch(tokens[pos].type)
            {
              case EXPR_TOKEN_OPAREN:
                plevel++;
                break;

              case EXPR_TOKEN_CPAREN:
                plevel--;
                if(plevel < 0)
                  {
                    obj->starterr = tokens[pos].start;
                    obj->enderr = tokens[pos].end;
                    return EXPR_ERROR_UNMATCHEDPAREN;
                  }
                break;

              case EXPR_TOKEN_COMMA:
                /* Found comma */
                if(plevel == 0)
                  num++;
                break;

              case EXPR_TOKEN_AMPERSAND:
                /* Found reference mark */
                if(plevel == 0)
                  {
                    /* This may only occur after the open parenthesis or comma */
                    if(tokens[pos - 1].type == EXPR_TOKEN_OPAREN || tokens[pos - 1].type == EXPR_TOKEN_COMMA)
                      refnum++;
                    else
                      return EXPR_ERROR_SYNTAX;
                  }
                break;
            }
        }

      /* plevel should be zero */
      if(plevel != 0)
        return EXPR_ERROR_UNMATCHEDPAREN;
    }

  /* We now have the number of total arguments and
     number of ref arguments.  Get number of normal
     arguments */
  num = num - refnum;

  /* Make sure number of arguments is correct */
  /* Here we make sure the limits are greater
     or equal to zero because any negative number
     could be used to specify no limit */
  if(argmin >= 0 && num < argmin)
    {
      obj->starterr = tokens[p1 - 1].start;
      obj->enderr = tokens[p2].end;
      return EXPR_ERROR_BADNUMBERARGUMENTS;
    }

  if(argmax >= 0 && num > argmax)
    {
      obj->starterr = tokens[p1 - 1].start;
      obj->enderr = tokens[p2].end;
      return EXPR_ERROR_BADNUMBERARGUMENTS;
    }

  if(refargmin >= 0 && refnum < refargmin)
    {
      obj->starterr = tokens[p1 - 1].start;
      obj->enderr = tokens[p2].end;
      return EXPR_ERROR_BADNUMBERARGUMENTS;
    }

  if(refargmax >= 0 && refnum > refargmax)
    {
      obj->starterr = tokens[p1 - 1].start;
      obj->enderr = tokens[p2].end;
      return EXPR_ERROR_BADNUMBERARGUMENTS;
    }

  /* Set tmp to null in case of no arguments */
  tmp = NULL;
  reftmp = NULL;

  if(num > 0)
    {
      /* Allocate subnodes */
      tmp = exprAllocNodes(num);
      if(tmp == NULL)
        return EXPR_ERROR_MEMORY;
    }

  if(refnum > 0)
    {
      /* Allocate ref pointers */
      reftmp = exprAllocMem(sizeof(EXPRTYPE*) * refnum);
      if(reftmp == NULL)
        {
          exprFreeMem(tmp);
          return EXPR_ERROR_MEMORY;
        }
    }



  /* Set this node's data */
  node->type = EXPR_NODETYPE_FUNCTION;
  node->data.function.fptr = fptr;
  node->data.function.nodecount = num;
  node->data.function.nodes = tmp;
  node->data.function.refcount = refnum;
  node->data.function.refs = reftmp;
  node->data.function.type = type;

  /* parse each subnode */
  if(num + refnum > 0)
    {
      plevel = 0;
      cur = 0;
      refcur = 0;
      lv = p1 + 1;

      /* look for commas if more than 1 arg */
      if(num + refnum > 1)
        {
          for(pos = p1 + 1; pos < p2; pos++)
            {
              switch(tokens[pos].type)
                {
                  case EXPR_TOKEN_OPAREN:
                    plevel++;
                    break;

                  case EXPR_TOKEN_CPAREN:
                    plevel--;
                    break; /* Already checked paren nesting above */

                  case EXPR_TOKEN_COMMA:
                    /* Found comma */
                    if(plevel == 0)
                      {
                        /* parse inside */
                        if(tokens[lv].type == EXPR_TOKEN_AMPERSAND)
                          {
                            if(lv != pos - 2)
                              {
                                obj->starterr = tokens[lv].start;
                                obj->enderr = tokens[pos].end;
                                return EXPR_ERROR_SYNTAX;
                              }

                            /* It is a reference */
                            if(tokens[lv + 1].type != EXPR_TOKEN_IDENTIFIER)
                              {
                                obj->starterr = tokens[lv].start;
                                obj->enderr = tokens[lv + 1].end;
                                return EXPR_ERROR_SYNTAX;
                              }


                            /* Make sure it is not a constant */
                            vars = exprGetConstList(obj);
                            if(vars)
                              {
                                exprValListGetAddress(vars, tokens[lv + 1].data.str, &addr);
                                if(addr)
                                  {
                                    obj->starterr = tokens[lv].start;
                                    obj->enderr = tokens[lv + 1].start;
                                    return EXPR_ERROR_REFCONSTANT;
                                  }
                              }

                            /* Get variable list */
                            vars = exprGetVarList(obj);
                            if(vars == NULL)
                              return EXPR_ERROR_NOVARLIST;

                            /* Get variable address */
                            exprValListGetAddress(vars, tokens[lv + 1].data.str, &addr);
                            if(addr == NULL)
                              {
                                /* Add variable to list */
                                exprValListAdd(vars, tokens[lv + 1].data.str, 0.0);

                                /* Try to get address again */
                                exprValListGetAddress(vars, tokens[lv + 1].data.str, &addr);
                                if(addr == NULL)
                                  return EXPR_ERROR_MEMORY; /* Could not add variable */
                              }

                            /* Set reference item */
                            reftmp[refcur] = addr;

                            /* increase ref arg number and lv position*/
                            refcur++;
                            lv = pos + 1;
                          }
                        else
                          {
                            err = exprInternalParse(obj, &(tmp[cur]), tokens, lv, pos - 1);
                            if(err != EXPR_ERROR_NOERROR)
                              return err;

                            /* increase arg number and lv position*/
                            lv = pos + 1;
                            cur++;
                          }
                      }
                    break;
                }
            }
        }

      /* lv should point after the last comma, or open paren. if only 1 arg */
      if(tokens[lv].type == EXPR_TOKEN_AMPERSAND)
        {
          if(lv != p2 - 2)
            {
              obj->starterr = tokens[lv].start;
              obj->enderr = tokens[p2].end;
              return EXPR_ERROR_SYNTAX;
            }

          /* It is a reference */
          if(tokens[lv + 1].type != EXPR_TOKEN_IDENTIFIER)
            {
              obj->starterr = tokens[lv].start;
              obj->enderr = tokens[lv + 1].end;
              return EXPR_ERROR_SYNTAX;
            }

          /* Make sure it is not a constant */
          vars = exprGetConstList(obj);
          if(vars)
            {
              exprValListGetAddress(vars, tokens[lv + 1].data.str, &addr);
              if(addr)
                {
                  obj->starterr = tokens[lv].start;
                  obj->enderr = tokens[lv + 1].start;
                  return EXPR_ERROR_REFCONSTANT;
                }
            }

          /* Get variable list */
          vars = exprGetVarList(obj);
          if(vars == NULL)
            return EXPR_ERROR_NOVARLIST;

          /* Get variable address */
          exprValListGetAddress(vars, tokens[lv + 1].data.str, &addr);
          if(addr == NULL)
            {
              /* Add variable to list */
              exprValListAdd(vars, tokens[lv + 1].data.str, 0.0);

              /* Try to get address again */
              exprValListGetAddress(vars, tokens[lv + 1].data.str, &addr);
              if(addr == NULL)
                return EXPR_ERROR_MEMORY; /* Could not add variable */
            }

          /* Set reference item */
          reftmp[refcur] = addr;
        }
      else
        {
          err = exprInternalParse(obj, &(tmp[cur]), tokens, lv, p2 - 1);
          if(err != EXPR_ERROR_NOERROR)
            return err;
        }
    }


  return EXPR_ERROR_NOERROR;
}