Commit 41f4765afb8d8d4749b08beefb8e0636cfce51ca

Authored by Georg Hopp
0 parents

Initial repository layout

  1 +Georg Steffers <georg@steffers.org>
  1 +0.0.1: First test with a bison grammar and flex scanner. Process simple
  2 + statement as in the examples contained in the bison docs.
  3 +0.0.2: more work on grammar (add loops and conditionals, experiments),
  4 + also add tplparser.[ch] that serves for general purpose grammer
  5 + actions.
  6 +0.0.3: brought the grammar to a more or less final state.
  7 + Add several functions for procession different expressions.
  8 + Add variables.
  9 + Do some leak checking.
  10 +0.0.4: Finalize variables with adding support for arrays and hashes.
  11 + A word to variables:
  12 + - There is no need to declare a variable. As soon as one assigns
  13 + something to an identifier, that identifier holds that value.
  14 + - It is an error to use a variable that has no assigned value
  15 + within an expression.
  16 + - Assigning a new value to a variable simply overwrites its
  17 + previous content. There is no way to recover the previous
  18 + content.
  19 + - The above is also true if the variable was an array or hash.
  20 + - Variables can be of type INT, FLOAT or STRING. If you use
  21 + Variables or values of different type within an expression
  22 + implicit casts are done. For rules of implicit casts see below.
  23 + - There is actually no way to explicitly cast a variable, but that
  24 + may change in future.
  25 + - Rules for implicit casts are:
  26 + * normally the first operand of an expression specifies the
  27 + resulting type. All following operands are implicitly cast to
  28 + the type of the first operand.
  29 + * The only exception to this is if one of the operands is a
  30 + sting. Then all other operands are implicitly cast to string.
  31 + Again do some leak and memchecks.
  32 +
  33 +0.0.5: implement explicit casts
  34 + put all things in a sane autobuild package.
  35 + called the whole thing: tepal "TEpal is a template PArsing Library"
  36 +
  37 +0.0.6: 25/11/2006 lots of code cleanups to prepare to code to use AST
  38 + all expressions have now an own datatype. That reduces the grammar
  39 + file a lot (and makes it easier to keep it conflict-free) because
  40 + i do not need to distinguish between int, float and string in the
  41 + grammar right now.
  42 + Also expression computation has become much cleaned.
  43 + I also change the behaviour of freeing data. No function frees
  44 + any of it calling parameters. This results in a lot of
  45 + memory leaks right now. !!!IMPORTANT!!! That has to be fixed soon!
  46 + ---
  47 + Already fixed some leaks, but some still remain.
  48 +
  49 + 26/11/2006 more leaks resolved
  50 + well, right now no leaks remain when i use tepal with my test
  51 + index.html
  52 + ---
  53 + If an undefined variable is used an error message is given.
  54 + !!!FIXME!!! I need a way to maintain the complete variable identifier
  55 + to tell it with the error message.
  56 +
  57 +0.0.7: AST implemented
  58 + a very big step is done. An ast is implemented. Everything works as
  59 + before, but right now to demontrate the functionality of the ast also
  60 + if statements are computed correctly.
  1 +DEFS = -DHAS_CONFIG @DEFS@
  2 +
  3 +nobase_include_HEADERS = index.tpl
  4 +
  5 +ACLOCAL_AMFLAGS = -I m4
  6 +
  7 +# EXTRA_DIST =
  8 +
  9 +SUBDIRS = src include
  1 +tepal is a Template Parsing Library, written in C.
  2 +
  3 +It's origin lies in my unhappieness with PHP, JSP and other
  4 +languages designed for web-development. Lately i learned a little
  5 +about template system and worked a little with smarty and after a
  6 +while i got the idea that if one wants to seperate program logic
  7 +from display logic it is also possible to write you application
  8 +in C as i prefer. The FastCGI interface is as fast or even faster than
  9 +the PHP interface. The only thing needed is a library that does the
  10 +same things as smarty, set template variables, parse a template and
  11 +write the result.
  12 +
  13 +Well, it turns out that this only thing was more work than i first
  14 +thought, especially because i never wrote an interpreter or compiler
  15 +before. And i had not college courses on that issue too. So i had to
  16 +find out everything by my own. Thanks go to the excellent documentation
  17 +of flex and bison and the Telos GmbH that published a simple interpreter.
  18 +
  19 +While i was writing this I recognised that it might be usefull at other
  20 +things too. Everything that can be created by a cleartext template
  21 +and some application logic can be created with this lib.
  1 +for version 0.0.*
  2 +
  3 +- implement blocks
  4 + * every block has to have its own identifier list. Additional
  5 + a reference to to the upper block should be part of a block
  6 + to realize variable lookup in upper blocks.
  7 + * every block contains a statement list, that hold all statements
  8 + that occured within the block.
  9 + * a block is as itself a statement, that could be part of a statement
  10 + list.
  11 + * blocklocal, global and parent variables
  12 + variables in general are block local. This means, using varable a
  13 + within a sub-block does not affect an existing variable a within a
  14 + parent block.
  15 + Every block can contain one optional globals declaration section. This
  16 + is a special block, wich declares identifiers to be used as global
  17 + (topmost block) identifiers. If a non-existent identifier is deklared
  18 + in such a section a global variable is created.
  19 + Additionally there will be a _parent_ operator for use with an identifier.
  20 + This will allow one to access a variable used (and therefor deklared)
  21 + somewhere above the local block. If no variable with this identifier can
  22 + be found an error message is shown and processing will stop.
  23 +
  24 +- implement loops and conditionals
  25 + * first the statement directly following the loop or conditional
  26 + tokens is saved.
  27 + * the this is executed 0..n times depending on the loop or conditional.
  28 +
  29 +- ich habe herausgefunden das alle Ausdrücken in denen Variablen vorkommen
  30 + auch in einen statement stack aufgenommen werden müssen. Nur konstante
  31 + Ausdrücken können direkt ausgewertet werden und muessen nicht in
  32 + den AST (abstract statement tree, ist faktisch aber eher ein stack da
  33 + jeder branch unmittelbar ausgeführt wird). Ups, sorry this is
  34 + accidently german.
  35 +
  36 +- Add an interface to access the variable space of the interpreter from
  37 + within a C program in an easy way.
  38 +
  39 +- add CGI-lib for parsing of requests.
  40 +
  41 +- write a first test-webapp.
  42 +
  43 +- code cleanups
  44 +
  45 +- comment the code more completely.
  46 +
  47 +- date Datentyp hinzufügen
  48 +
  49 +- Modifizierer für das Ausgabeformat hinzufügen.
  50 +
  51 +=> we come to version 0.1.0
  52 +=========================================================================
  53 +
  54 +for version 0.1.*
  55 +
  56 +- implement Sessions
  57 + * How to work with cookies?
  58 + * Sessionvariables will be saves within a BerkDB.
  59 +
  60 +- maybe begin of an application-server, that preserves the state of an
  61 + application between its calls via cgi.
  62 +
  63 +- allow and implement includes within templates.
  1 +#!/bin/sh
  2 +# Script for cleaning all autogenerated files.
  3 +
  4 +test ! -f Makefile || make distclean
  5 +
  6 +# Generated by aclocal.
  7 +rm -f aclocal.m4
  8 +
  9 +# Generated by autoconf.
  10 +rm -f configure
  11 +
  12 +# Generated by autoheader
  13 +rm -f config.h.in
  14 +
  15 +# Generated or brought in by automake.
  16 +rm -f Makefile.in
  17 +rm -f src/Makefile.in
  18 +rm -f include/Makefile.in
  19 +rm -f INSTALL
  20 +rm -f COPYING
  21 +
  22 +# Generated by all in config
  23 +rm -rf config
  24 +
  25 +rm -rf autom4te.cache
  1 +#!/bin/sh
  2 +# Script for regenerating all autogenerated files.
  3 +
  4 +mkdir config
  5 +
  6 +aclocal
  7 +autoconf
  8 +autoheader
  9 +libtoolize -c -f
  10 +automake -a -c
  1 +AC_PREREQ(2.59)
  2 +AC_INIT(tepal, 0.0.7, georg@steffers.org)
  3 +AC_CONFIG_AUX_DIR([config])
  4 +AC_CONFIG_SRCDIR([src/tepal.c])
  5 +AC_CONFIG_HEADER([config.h])
  6 +AM_INIT_AUTOMAKE
  7 +
  8 +AC_CANONICAL_HOST
  9 +
  10 +# Checks for programs.
  11 +AC_PROG_CC
  12 +AC_PROG_MAKE_SET
  13 +AC_LIBTOOL_WIN32_DLL
  14 +AC_PROG_LIBTOOL
  15 +AC_PROG_YACC
  16 +AC_PROG_LEX
  17 +
  18 +# Checks for header files.
  19 +AC_HEADER_STDC
  20 +AC_CHECK_HEADERS([libintl.h locale.h stdlib.h string.h unistd.h wchar.h])
  21 +
  22 +# Checks for libraries.
  23 +AC_MSG_CHECKING([for Win32])
  24 +case "$host" in
  25 + *-*-mingw*)
  26 + win32="yes, use windows threads"
  27 + ;;
  28 + *)
  29 + win32="no"
  30 + ;;
  31 +esac
  32 +AC_MSG_RESULT([$win32])
  33 +
  34 +AM_CONDITIONAL(WIN32, test "x$win32" != "xno")
  35 +
  36 +# Checks for typedefs, structures, and compiler characteristics.
  37 +AC_C_CONST
  38 +
  39 +# Checks for library functions.
  40 +AC_CHECK_FUNCS([memset setlocale])
  41 +
  42 +AC_CONFIG_FILES([Makefile])
  43 +AC_CONFIG_FILES([src/Makefile])
  44 +AC_CONFIG_FILES([include/Makefile])
  45 +
  46 +AC_OUTPUT
  1 +nobase_include_HEADERS = tepal.h helper.h \
  2 + evalExpr.h evalCond.h expValue.h \
  3 + ident.h identList.h bbtree.h \
  4 + variable.h assign.h cast.h \
  5 + statement.h stmtQueue.h block.h
  6 +
  1 +#ifndef _ASSIGN_H_
  2 +#define _ASSIGN_H_
  3 +
  4 +#include <ident.h>
  5 +#include <expValue.h>
  6 +
  7 +s_expVal * assign (s_ident *, s_expVal *);
  8 +
  9 +#endif /* _ASSIGN_H_ */
  1 +#ifndef _BBTREE_H_
  2 +#define _BBTREE_H_
  3 +
  4 +/* this is only here for testing. In final version
  5 + * it should be in bbtree.c */
  6 +typedef
  7 +struct bbTreeNode
  8 +{
  9 + void * value;
  10 +
  11 + long height;
  12 +
  13 + struct bbTreeNode * left;
  14 + struct bbTreeNode * right;
  15 +
  16 +} s_bbTreeNode;
  17 +
  18 +#define BBTREE_LEFT_HEIGHT(t) ((t)->left ? (t)->left->height : -1)
  19 +#define BBTREE_RIGHT_HEIGHT(t) ((t)->right ? (t)->right->height : -1)
  20 +#define BBTREE_AVL(t) (BBTREE_RIGHT_HEIGHT ((t)) - \
  21 + BBTREE_LEFT_HEIGHT ((t)))
  22 +
  23 +
  24 +/*
  25 + * comparison for tree-node values.
  26 + * Has to be defined by user and set
  27 + * with bbTreeNew.
  28 + *
  29 + * params:
  30 + * left: pointer to left value
  31 + * right: pointer to right value
  32 + *
  33 + * returns:
  34 + * 0: if values equal
  35 + * 1: if right greater left
  36 + * -1: if left greater right
  37 + */
  38 +typedef int (* t_bbTreeCmp) (void *, void *);
  39 +
  40 +typedef
  41 +struct bbTree
  42 +{
  43 + struct bbTreeNode * root;
  44 +
  45 + t_bbTreeCmp cmp;
  46 +} s_bbTree;
  47 +
  48 +
  49 +/* constructor, destructor */
  50 +s_bbTree * bbTreeNew (t_bbTreeCmp);
  51 +void bbTreeFree (s_bbTree *);
  52 +
  53 +/* data manipulation */
  54 +void * bbTreeInsert (s_bbTree *, void *);
  55 +void * bbTreeSeek (s_bbTree *, void *);
  56 +void * bbTreeRemove (s_bbTree *, void *);
  57 +
  58 +/* analysation */
  59 +void * bbTreeMin (s_bbTree *);
  60 +void * bbTreeMax (s_bbTree *);
  61 +int bbTreeSize (s_bbTree *);
  62 +
  63 +/* bbTree to other Datastructure */
  64 +void ** bbTreeInOrder (s_bbTree *, void **);
  65 +
  66 +#endif /* _BBTREE_H_ */
  1 +#ifndef _BLOCK_H_
  2 +#define _BLOCK_H_
  3 +
  4 +typedef struct block s_block;
  5 +
  6 +#include <identList.h>
  7 +#include <stmtQueue.h>
  8 +
  9 +s_block * blockNew (s_stmtQueue *);
  10 +void blockFree (s_block *);
  11 +void blockSetNonLocalId (s_block *, s_ident *);
  12 +s_block * blockPush (s_block **, s_block *);
  13 +s_block * blockPop (s_block **);
  14 +s_block * blockPrev (s_block *);
  15 +s_stmtQueue * blockStmts (s_block *);
  16 +s_identList * blockIdl (s_block *);
  17 +
  18 +#endif /* _BLOCK_H_ */
  1 +#ifndef _CAST_H_
  2 +#define _CAST_H_
  3 +
  4 +#include "expValue.h"
  5 +
  6 +s_expVal * castExprToInt (s_expVal *);
  7 +s_expVal * castExprToFloat (s_expVal *);
  8 +s_expVal * castExprToString (s_expVal *);
  9 +
  10 +#endif /* _CAST_H_ */
  1 +#ifndef _EVALCOND_H_
  2 +#define _EVALCOND_H_
  3 +
  4 +#include "expValue.h"
  5 +
  6 +int evalCondExpr (s_expVal *);
  7 +int evalComp (int, s_expVal *, s_expVal *);
  8 +
  9 +#endif /* _EVALCOND_H_ */
  1 +#ifndef _EVAL_EXPR_H_
  2 +#define _EVAL_EXPR_H_
  3 +
  4 +#include <tepal_pars.h>
  5 +#include <expValue.h>
  6 +
  7 +#define PLUS '+'
  8 +#define MINUS '-'
  9 +#define TIMES '*'
  10 +#define OVER '/'
  11 +#define MODULO '%'
  12 +
  13 +s_expVal * evalExpr (int, s_expVal *, s_expVal *);
  14 +
  15 +#endif /* _EVAL_EXPR_H_ */
  1 +#ifndef _EXP_VALUE_H_
  2 +#define _EXP_VALUE_H_
  3 +
  4 +#define EXP_TYP_INT 'i'
  5 +#define EXP_TYP_FLOAT 'f'
  6 +#define EXP_TYP_STRING 's'
  7 +
  8 +/* Typdeklaration, etc */
  9 +typedef struct expVal s_expVal;
  10 +
  11 +
  12 +/* Constructoren / Destructoren */
  13 +s_expVal * expValueIntNew (long);
  14 +s_expVal * expValueFloatNew (double);
  15 +s_expVal * expValueStringNew (char *);
  16 +
  17 +s_expVal * expValueClone (s_expVal *);
  18 +
  19 +void expValueFree (s_expVal *);
  20 +
  21 +
  22 +/* Accessors */
  23 +long expValueInt (s_expVal *);
  24 +double expValueFloat (s_expVal *);
  25 +char * expValueString (s_expVal *);
  26 +
  27 +/* analyse expValue */
  28 +int expValueGetType (s_expVal *);
  29 +
  30 +
  31 +#endif /* _EXP_VALUE_H_ */
  1 +#ifndef _HELPER_H_
  2 +#define _HELPER_H_
  3 +
  4 +#define ABS(a) ((a)<0 ? -(a) : (a))
  5 +#define MAX(a,b) ((a) > (b) ? (a) : (b))
  6 +
  7 +#endif /* _HELPER_H */
  1 +#ifndef _IDENT_H_
  2 +#define _IDENT_H_
  3 +
  4 +#define ID_TYP_UNDEF 'n'
  5 +#define ID_TYP_EXP 'e'
  6 +#define ID_TYP_IDL 'L'
  7 +
  8 +struct ident;
  9 +typedef struct ident s_ident;
  10 +
  11 +#include <expValue.h>
  12 +#include <identList.h>
  13 +
  14 +/* identifier constructors/destructors */
  15 +s_ident * identNew (int, const char *);
  16 +s_ident * identUndefNew (int, const char *);
  17 +s_ident * identExpNew (int, const char *, s_expVal *);
  18 +s_ident * identIdlNew (int, const char *, s_identList *);
  19 +void identFree (s_ident *);
  20 +
  21 +/* analyse ident */
  22 +int identIsQueued (s_ident *);
  23 +void identEnqueue (s_ident *);
  24 +void identDequeue (s_ident *);
  25 +int identGetType (s_ident *);
  26 +char * identGetKey (s_ident *);
  27 +int identGetIdx (s_ident *);
  28 +
  29 +/* identifier to value */
  30 +s_expVal * identExp (s_ident *);
  31 +s_identList * identIdl (s_ident *);
  32 +s_ident * identSetExp (s_ident *, s_expVal *);
  33 +s_ident * identSetIdl (s_ident *, s_identList *);
  34 +
  35 +#endif /* _IDENT_H_ */
  1 +#ifndef _IDENT_LIST_H_
  2 +#define _IDENT_LIST_H_
  3 +
  4 +typedef struct identList s_identList;
  5 +
  6 +#include <ident.h>
  7 +#include <expValue.h>
  8 +
  9 +/* constructor/destructor for new identList */
  10 +s_identList * identListNew (void);
  11 +void identListFree (s_identList *);
  12 +
  13 +/* insertions or deletion into a list */
  14 +s_ident * identListPutVal (s_identList *, s_ident *);
  15 +s_ident * identListPutExpByIdx (s_identList *, int, s_expVal *);
  16 +s_ident * identListPutIdlByIdx (s_identList *, int, s_identList *);
  17 +s_ident * identListPutExpByKey (s_identList *, const char *, s_expVal *);
  18 +s_ident * identListPutIdlByKey (s_identList *, const char *, s_identList *);
  19 +void identListRemoveByIdx (s_identList *, int);
  20 +void identListRemoveByKey (s_identList *, const char *);
  21 +
  22 +/* seeking in list */
  23 +s_ident * identListSeekIdx (s_identList *, int);
  24 +s_ident * identListSeekKey (s_identList *, const char *);
  25 +
  26 +/* identList to other DataStructures */
  27 +s_ident ** identListToArray (s_identList *);
  28 +
  29 +#endif /* _IDENT_LIST_H_ */
  1 +#ifndef _STMT_H_
  2 +#define _STMT_H_
  3 +
  4 +#define STMT_CONST 0
  5 +#define STMT_BLOCK 1
  6 +
  7 +#define STMT_PRINT 10
  8 +#define STMT_IF 11
  9 +#define STMT_FOREACH 12
  10 +#define STMT_REPEAT 13
  11 +#define STMT_ASSIGN 14
  12 +#define STMT_UNSET 15
  13 +
  14 +#define STMT_EVAL_PLUS 20
  15 +#define STMT_EVAL_MINUS 21
  16 +#define STMT_EVAL_TIMES 22
  17 +#define STMT_EVAL_OVER 23
  18 +#define STMT_EVAL_MODULO 24
  19 +#define STMT_EVAL_NEG 25
  20 +
  21 +#define STMT_IDENT_VAR 30
  22 +#define STMT_IDENT_ARRAY 31
  23 +#define STMT_IDENT_VAL 32
  24 +
  25 +#define STMT_CAST_INT 40
  26 +#define STMT_CAST_FLOAT 41
  27 +#define STMT_CAST_STRING 42
  28 +
  29 +#define STMT_COMP_EQ 50
  30 +#define STMT_COMP_NE 51
  31 +#define STMT_COMP_LT 52
  32 +#define STMT_COMP_GT 53
  33 +#define STMT_COMP_LE 54
  34 +#define STMT_COMP_GE 55
  35 +
  36 +#define STMT_COND_EXPR 60
  37 +#define STMT_COND_AND 61
  38 +#define STMT_COND_OR 62
  39 +#define STMT_COND_NEG 63
  40 +
  41 +
  42 +
  43 +#define STYP_NONE 0
  44 +#define STYP_COND 1
  45 +#define STYP_EVAL 2
  46 +#define STYP_IDVAL 3
  47 +
  48 +/*
  49 + * Deklaration und Definition
  50 + */
  51 +union stmtType
  52 +{
  53 + int cond;
  54 + struct expVal * eVal;
  55 + struct ident * idVal;
  56 +};
  57 +
  58 +typedef struct stmt s_stmt;
  59 +typedef union stmtType u_stmtType;
  60 +
  61 +#include <stmtQueue.h>
  62 +#include <block.h>
  63 +
  64 +/*
  65 + * Interface
  66 + */
  67 +s_stmt * stmtNew (int, s_stmtQueue *, int, u_stmtType);
  68 +void stmtFree (s_stmt *);
  69 +s_stmtQueue * stmtGetArgs (s_stmt *);
  70 +u_stmtType stmtGetVal (s_stmt *);
  71 +int stmtGetConstTyp (s_stmt *);
  72 +u_stmtType stmtDo (s_stmt *, s_block *);
  73 +
  74 +#endif /* _STMT_H_ */
  1 +#ifndef _STMT_QUEUE_H_
  2 +#define _STMT_QUEUE_H_
  3 +
  4 +#include <ident.h>
  5 +
  6 +typedef struct stmtQueue s_stmtQueue;
  7 +
  8 +#include <statement.h>
  9 +
  10 +s_stmtQueue * stmtQueueNew (void);
  11 +void stmtQueueFree (s_stmtQueue *);
  12 +
  13 +void stmtQueueEnqueue (s_stmtQueue *, s_stmt *);
  14 +s_stmt * stmtQueueDequeue (s_stmtQueue *);
  15 +s_stmtQueue * stmtQueueConcat (s_stmtQueue *, s_stmtQueue *);
  16 +
  17 +s_stmt * stmtQueueGet (s_stmtQueue *, unsigned int);
  18 +void stmtQueueDo (s_stmtQueue *);
  19 +
  20 +unsigned int stmtQueueGetSize (s_stmtQueue *);
  21 +
  22 +#endif /* _STMT_QUEUE_H_ */
  1 +#ifndef __HTMLPARS_H__
  2 +#define __HTMLPARS_H__
  3 +
  4 +#include "expValue.h"
  5 +
  6 +#define ERR_UNDEF_VAR 0
  7 +#define ERR_NO_INDEX 1
  8 +#define ERR_STRING_OPERATOR 2
  9 +#define ERR_FLOAT_OPERATOR 3
  10 +
  11 +void exitError (int, ...);
  12 +void printExpr (s_expVal *);
  13 +
  14 +#endif /* __HTMLPARS_H__ */
  1 +#ifndef _VARIABLE_H_
  2 +#define _VARIABLE_H_
  3 +
  4 +#include <ident.h>
  5 +#include <expValue.h>
  6 +#include <block.h>
  7 +
  8 +s_ident * getVariable (s_block *, char *);
  9 +s_ident * getArray (s_ident *, s_expVal *);
  10 +
  11 +#endif /* _VARIABLE_H_ */
  1 +<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN"
  2 + "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
  3 +<html xmlns="http://www.w3.org/1999/xhtml">
  4 + <head>
  5 + <title>Test Page for Apache Installation</title>
  6 + </head>
  7 +
  8 + <body>
  9 + <p>If you can see this, it means that the installation of the <a
  10 + href="http://www.apache.org/foundation/preFAQ.html">Apache web server</a>
  11 + software on this system was successful. You may now add content to this
  12 + directory and replace this page.</p>
  13 +
  14 + <hr style="width: <# 100 #>%; height: 3px;" />
  15 +
  16 + <h2 style="text-align: center">Seeing this instead of the website you expected?</h2>
  17 +
  18 + <# "[Ausdruck 5 + 5] " + (5 + 5) + eol #>
  19 +
  20 + <# if (! 'HALLO' == 'HALLO'): #>
  21 + <p>This page is here because the site administrator has changed the
  22 + configuration of this web server. Please <strong>contact the person
  23 + responsible for maintaining this server with questions.</strong>
  24 + The Apache Software Foundation, which wrote the web server software
  25 + this site administrator is using, has nothing to do with
  26 + maintaining this site and cannot help resolve configuration
  27 + issues.</p>
  28 + <# end #>
  29 +
  30 + <#
  31 + if (! (12 < 13 && 12 < 10))
  32 +
  33 + :
  34 + "[Zuweisung yahoo = 15] " + eol; yahoo = 15;
  35 + "[Ausdruck yahoo] " + yahoo + eol;
  36 +
  37 + end
  38 +
  39 + "[Ausdruck 10 % 3] " + (10 % 3) + eol;;;;
  40 + "[Ausdruck 12.3 - 18] " + (12.3 - 18) + eol;
  41 + "[Ausdruck -47.78] " + -47.78 + eol;
  42 + "[Ausdruck 'HALLO'] " + 'HALLO' + eol;
  43 + '[Ausdruck -"WALLO"] ' + -"WALLO" + eol;
  44 + "[Ausdruck 'hokus ' + 'pokus'] " + ('hokus ' + 'pokus') + eol;
  45 +
  46 + repeat (bla count=10)
  47 + "[Ausdruck 32.56 * 10] " + 32.56 * 10 + eol;
  48 +
  49 + "[Zuweisung a = 250]" + eol; a = 250;
  50 + "[Zuweisung b=3.4-0.9]" + eol; b=3.4-0.9;
  51 + '[Zuweisung z="bla" + "bla"]' + eol; z="bla" + "bla";
  52 +
  53 + "[Ausdruck a] " + a + eol;
  54 + "[Ausdruck a*10 + a*2] " + (a*10 + a*2) + eol;
  55 +
  56 + "[Zuweisung a = -'Georg']" + eol; a = -'Georg';
  57 + "[Ausdruck -a] " + -a + eol;
  58 + "[Ausdruck a] " + a + eol;
  59 +
  60 + if (a == b)
  61 + "[Ausdruck 152 - 38] " + (152 - 38) + eol;
  62 + else
  63 + "[Ausdruck 'Harry' + -'hcsriH'] " + 'Harry' + -'hcsriH' + eol;
  64 +
  65 + foreach (harry as key, val): end
  66 +
  67 + "[Zuweisung jo ['terror'][12] = 53] " + eol; jo ['terror'][12] = 53;
  68 + "[Zuweisung onken = 'Falada']" + eol; onken = 'Falada';
  69 + "[Ausdruck onken + jo ['terror'][12]] " + (onken + jo['terror'][12]) + eol;
  70 + "[Zuweisung toll[42] = 'Jedi']" + eol; toll[42] = 'Jedi';
  71 + "[Ausdruck -toll[42]] " + -toll[42] + eol;
  72 +
  73 + "[Zuweisung harry = 12.0]" + eol; harry = 12.0;
  74 + "[Ausdruck harry*32] " + (harry*32) + eol;
  75 + "[Zuweisung dieter = 0]" + eol; dieter = 0;
  76 + "[Ausdruck 12.4+dieter] " + (12.4+dieter) + eol;
  77 + "[Zuweisung bonbon = 0.12]" + eol; bonbon = 0.12;
  78 + '[Ausdruck "Knall"+bonbon] ' + "Knall"+bonbon + eol;
  79 + "[Zuweisung mann = 'Mann']" + eol; mann = 'Mann';
  80 + "[Zuweisung oh = '-o-']" + eol; oh = '-o-';
  81 + "[Ausdruck mann+oh+mann] " + (mann+oh+mann) + eol;
  82 + '[Ausdruck 13 + "5"] ' + (13 + "5") + eol;
  83 + '[Ausdruck "Hallo" + 12] ' + ("Hallo" + 12) + eol;
  84 + '[Ausdruck b + (int) "32"] ' + (b + (int) "32") + eol;
  85 + #>
  86 +
  87 + <hr style="width: 100%; height: 3px;" />
  88 +
  89 + <# repeat (hoho count=100) #>
  90 + <p>The Apache documentation is available
  91 + <a href="http://httpd.apache.org/docs-2.0/">online</a> or has been installed
  92 + <a href="/manual/">locally</a>.</p>
  93 +
  94 + <# foreach (jokus as key, val): #>
  95 + <p>You are free to use the image below on an Apache-powered web
  96 + server. Thanks for using Apache!</p>
  97 + <# end #>
  98 +
  99 + <div style="text-align: center"><img src="apache_pb.gif" alt="" /></div>
  100 + </body>
  101 +</html>
  1 +tepal_source = tepal.c tepal_pars.c tepal_scan.c \
  2 + evalExpr.c evalCond.c expValue.c \
  3 + variable.c assign.c cast.c \
  4 + ident.c identList.c bbtree.c \
  5 + statement.c stmtQueue.c block.c
  6 +
  7 +nobase_include_HEADERS = tepal_pars.y tepal_scan.l
  8 +
  9 +BUILT_SOURCES = tepal_pars.c tepal_scan.c
  10 +CLEANFILES = tepal_pars.c tepal_scan.c ../include/tepal_pars.h
  11 +
  12 +
  13 +bin_PROGRAMS = tepal
  14 +
  15 +tepal_SOURCES = $(tepal_source)
  16 +tepal_CFLAGS = -I../include
  17 +
  18 +tepal_pars.c: Makefile tepal_pars.y
  19 + $(YACC) -d tepal_pars.y
  20 + mv y.tab.c tepal_pars.c
  21 + mv y.tab.h ../include/tepal_pars.h
  22 +
  23 +tepal_scan.c: Makefile tepal_scan.l
  24 + $(LEX) tepal_scan.l
  25 + mv lex.yy.c tepal_scan.c
  1 +#include <stdio.h>
  2 +#include <malloc.h>
  3 +#include <stdlib.h>
  4 +
  5 +#include <expValue.h>
  6 +#include <ident.h>
  7 +#include <assign.h>
  8 +#include <tepal.h>
  9 +
  10 + s_expVal *
  11 +assign (s_ident * to, s_expVal * from)
  12 +{
  13 + if (identGetType (to) == ID_TYP_IDL)
  14 + {
  15 + char * key = identGetKey (to);
  16 + exitError (ERR_NO_INDEX, key);
  17 + }
  18 +
  19 + /* !!!IMPORTANT!!! work here */
  20 + /*identListPutVal (block, to);*/
  21 + identSetExp (to, from);
  22 +
  23 + return from;
  24 +}
  1 +/*
  2 + * bbTree (balanced binary tree)
  3 + */
  4 +#include <malloc.h>
  5 +#include <stdio.h>
  6 +#include <string.h>
  7 +
  8 +#include <helper.h>
  9 +#include <bbtree.h>
  10 +
  11 +
  12 +/*
  13 + * statisch Funktionen
  14 + */
  15 +static
  16 + s_bbTreeNode *
  17 +bbTreeNodeNew (void * value)
  18 +{
  19 + s_bbTreeNode * new = (s_bbTreeNode *) malloc (sizeof (s_bbTreeNode));
  20 +
  21 + new->value = value;
  22 + new->left = NULL;
  23 + new->right = NULL;
  24 + new->height = 0;
  25 +
  26 + return new;
  27 +}
  28 +
  29 +static
  30 + void
  31 +bbTreeNodeFree (s_bbTreeNode * t)
  32 +{
  33 + if (t == NULL)
  34 + return;
  35 +
  36 + while (t->left != NULL)
  37 + {
  38 + bbTreeNodeFree (t->left);
  39 + t->left = NULL;
  40 + }
  41 +
  42 + while (t->right != NULL)
  43 + {
  44 + bbTreeNodeFree (t->right);
  45 + t->right = NULL;
  46 + }
  47 +
  48 + free (t);
  49 +}
  50 +
  51 +static
  52 + void
  53 +bbTreeNodeRotLeft (s_bbTreeNode * node)
  54 +{
  55 + s_bbTreeNode * left = node->left;
  56 + s_bbTreeNode * right = node->right;
  57 + void * value = node->value;
  58 +
  59 + node->right = right->right;
  60 + node->left = right;
  61 + right->right = right->left;
  62 + right->left = left;
  63 +
  64 + node->value = right->value;
  65 + right->value = value;
  66 +
  67 + node->right->height =
  68 + 1 + MAX (BBTREE_LEFT_HEIGHT (node->left),
  69 + BBTREE_RIGHT_HEIGHT (node->left));
  70 +}
  71 +
  72 +static
  73 + void
  74 +bbTreeNodeRotRight (s_bbTreeNode * node)
  75 +{
  76 + s_bbTreeNode * left = node->left;
  77 + s_bbTreeNode * right = node->right;
  78 + void * value = node->value;
  79 +
  80 + node->left = left->left;
  81 + node->right = left;
  82 + left->left = left->right;
  83 + left->right = right;
  84 +
  85 + node->value = left->value;
  86 + left->value = value;
  87 +
  88 + node->right->height =
  89 + 1 + MAX (BBTREE_LEFT_HEIGHT (node->right),
  90 + BBTREE_RIGHT_HEIGHT (node->right));
  91 +}
  92 +
  93 +static
  94 + void
  95 +bbTreeNodeBalance (s_bbTreeNode * node)
  96 +{
  97 + if (BBTREE_AVL (node) == -2)
  98 + /* left is to long */
  99 + {
  100 + if (BBTREE_AVL (node->left) == 1)
  101 + bbTreeNodeRotLeft (node->left);
  102 + bbTreeNodeRotRight (node);
  103 + }
  104 +
  105 + if (BBTREE_AVL (node) == -2)
  106 + /* right is to long */
  107 + {
  108 + if (BBTREE_AVL (node->right) == 1)
  109 + bbTreeNodeRotRight (node->right);
  110 + bbTreeNodeRotLeft (node);
  111 + }
  112 +}
  113 +
  114 +/*
  115 + * This function returns either, NULL if a new node was inserted, or
  116 + * a node containing the old value if an existing node was modified.
  117 + */
  118 +static
  119 + s_bbTreeNode *
  120 +bbTreeNodeInsert (s_bbTreeNode ** _node, t_bbTreeCmp cmp, void * value)
  121 +{
  122 + s_bbTreeNode * node = *_node;
  123 + s_bbTreeNode * ret;
  124 +
  125 + if (node == NULL)
  126 + /* This happens only when bbTree::root is NULL
  127 + * on bbTreeInsert call */
  128 + {
  129 + *_node = bbTreeNodeNew (value);
  130 + return NULL;
  131 + }
  132 +
  133 + if (cmp (value, node->value) == 0)
  134 + /* The key is already in the tree.
  135 + * In this case a node containing the old value is returned. */
  136 + {
  137 + ret = bbTreeNodeNew (node->value);
  138 + node->value = value;
  139 + return ret;
  140 + }
  141 +
  142 + if (cmp (value, node->value) < 0)
  143 + if (node->left == NULL)
  144 + {
  145 + node->left = bbTreeNodeNew (value);
  146 + ret = NULL;
  147 +
  148 + if (BBTREE_AVL (node) == -2 || BBTREE_AVL (node) == 2)
  149 + bbTreeNodeBalance (node);
  150 +
  151 + node->height = 1 + MAX (
  152 + BBTREE_LEFT_HEIGHT (node), BBTREE_RIGHT_HEIGHT (node));
  153 + }
  154 + else
  155 + ret = bbTreeNodeInsert (&node->left, cmp, value);
  156 +
  157 + if (cmp (value, node->value) > 0)
  158 + if (node->right == NULL)
  159 + {
  160 + node->right = bbTreeNodeNew (value);
  161 + ret = NULL;
  162 +
  163 + if (BBTREE_AVL (node) == -2 || BBTREE_AVL (node) == 2)
  164 + bbTreeNodeBalance (node);
  165 +
  166 + node->height = 1 + MAX (
  167 + BBTREE_LEFT_HEIGHT (node), BBTREE_RIGHT_HEIGHT (node));
  168 + }
  169 + else
  170 + ret = bbTreeNodeInsert (&node->right, cmp, value);
  171 +
  172 + /* if we come here a new node was inserted a returned node
  173 + * containing {NULL, NULL} as value reflects this fact. */
  174 + return ret;
  175 +}
  176 +
  177 +static
  178 + s_bbTreeNode *
  179 +bbTreeNodeSeek (s_bbTreeNode * node, t_bbTreeCmp cmp, void * value)
  180 +{
  181 + if (node == NULL)
  182 + return NULL;
  183 +
  184 + if (cmp (value, node->value) == 0)
  185 + return node;
  186 +
  187 + if (cmp (value, node->value) < 0)
  188 + return bbTreeNodeSeek (node->left, cmp, value);
  189 +
  190 + if (cmp (value, node->value) > 0)
  191 + return bbTreeNodeSeek (node->right, cmp, value);
  192 +
  193 + return NULL;
  194 +}
  195 +
  196 +static
  197 + s_bbTreeNode *
  198 +bbTreeNodeMax (s_bbTreeNode * node)
  199 +{
  200 + if (node != NULL && node->right != NULL)
  201 + return bbTreeNodeMax (node->right);
  202 +
  203 + return node;
  204 +}
  205 +
  206 +static
  207 + s_bbTreeNode *
  208 +bbTreeNodeMin (s_bbTreeNode * node)
  209 +{
  210 + if (node != NULL && node->left != NULL)
  211 + return bbTreeNodeMin (node->left);
  212 +
  213 + return node;
  214 +}
  215 +
  216 +static
  217 + int
  218 +bbTreeNodeSize (s_bbTreeNode * node)
  219 +{
  220 + int size = 0;
  221 +
  222 + if (node == NULL)
  223 + return 0;
  224 +
  225 + size += bbTreeNodeSize (node->left);
  226 + size += bbTreeNodeSize (node->right);
  227 +
  228 + return size + 1;
  229 +}
  230 +/*
  231 + * This functions removes nodes from the tree and returns a pointer
  232 + * to the removed node or NULL if no node was found.
  233 + * !!!FIXME!!!: This function isn't thread save because of the static
  234 + * valiables. Don't use with multiple threads.
  235 + */
  236 +static
  237 + s_bbTreeNode *
  238 +bbTreeNodeRemove (s_bbTreeNode ** _node, t_bbTreeCmp cmp, void * value)
  239 +{
  240 + s_bbTreeNode * ret = NULL;
  241 + s_bbTreeNode * node = *_node;
  242 +
  243 + if (node == NULL)
  244 + return NULL;
  245 +
  246 + if (cmp (value, node->value) == 0)
  247 + /* found the element left */
  248 + {
  249 + if (node->left == NULL && node->right == NULL)
  250 + /* found a leaf */
  251 + {
  252 + ret = bbTreeNodeNew (node->value);
  253 + free (node);
  254 + *_node = NULL;
  255 + }
  256 + else if (node->left != NULL && node->left != NULL)
  257 + /* left & right subtree exists use either max(left) or min(right) */
  258 + {
  259 + s_bbTreeNode * maxLeft;
  260 +
  261 + maxLeft = bbTreeNodeMax (node->left);
  262 + node->value = maxLeft->value;
  263 + ret = bbTreeNodeRemove (&node->left, cmp, maxLeft->value);
  264 +
  265 + if (BBTREE_AVL (node) == -2 || BBTREE_AVL (node) == 2)
  266 + bbTreeNodeBalance (node);
  267 +
  268 + node->height = 1 + MAX (
  269 + BBTREE_LEFT_HEIGHT (node), BBTREE_RIGHT_HEIGHT (node));
  270 + }
  271 + else if ((node->left == NULL) != (node->right == NULL) /* ^^ */)
  272 + /* there is only one subtree */
  273 + /* This subtree must be a leaf, because the tree is balanced */
  274 + {
  275 + ret = bbTreeNodeNew (node->value);
  276 +
  277 + if (node->left != NULL)
  278 + /* found left node */
  279 + {
  280 + node->value = node->left->value;
  281 + free (node->left);
  282 + node->left = NULL;
  283 + }
  284 + else
  285 + /* found right node */
  286 + {
  287 + node->value = node->right->value;
  288 + free (node->right);
  289 + node->right = NULL;
  290 + }
  291 + }
  292 +
  293 + return ret;
  294 + }
  295 +
  296 + if (cmp (value, node->value) < 0)
  297 + ret = bbTreeNodeRemove (&node->left, cmp, value);
  298 +
  299 + if (cmp (value, node->value) > 0)
  300 + ret = bbTreeNodeRemove (&node->right, cmp, value);
  301 +
  302 + return ret;
  303 +}
  304 +
  305 +static
  306 + void
  307 +bbTreeNodeInOrder (const s_bbTreeNode * node, void *** ret)
  308 +{
  309 + if (node != NULL && node->left != NULL)
  310 + bbTreeNodeInOrder (node->left, ret);
  311 +
  312 + if (node != NULL)
  313 + **ret = node->value; (*ret)++;
  314 +
  315 + if (node != NULL && node->right != NULL)
  316 + bbTreeNodeInOrder (node->right, ret);
  317 +}
  318 +
  319 +/*
  320 + * Interface (non-static functions)
  321 + */
  322 + s_bbTree *
  323 +bbTreeNew (t_bbTreeCmp cmp)
  324 +{
  325 + s_bbTree * new = (s_bbTree *) malloc (sizeof (s_bbTree));
  326 +
  327 + new->root = NULL;
  328 + new->cmp = cmp;
  329 +
  330 + return new;
  331 +}
  332 +
  333 + void
  334 +bbTreeFree (s_bbTree * t)
  335 +{
  336 + bbTreeNodeFree (t->root);
  337 +
  338 + free (t);
  339 +}
  340 +
  341 + void *
  342 +bbTreeInsert (s_bbTree * t, void * value)
  343 +{
  344 + s_bbTreeNode * oldNode = bbTreeNodeInsert (&t->root, t->cmp, value);
  345 +
  346 + if (oldNode != NULL)
  347 + {
  348 + value = oldNode->value;
  349 + free (oldNode);
  350 +
  351 + return value;
  352 + }
  353 +
  354 + return NULL;
  355 +}
  356 +
  357 + void *
  358 +bbTreeSeek (s_bbTree * t, void * value)
  359 +{
  360 + s_bbTreeNode * seek = bbTreeNodeSeek (t->root, t->cmp, value);
  361 +
  362 + return (seek != NULL) ? seek->value : NULL;
  363 +}
  364 +
  365 + void *
  366 +bbTreeRemove (s_bbTree * t, void * value)
  367 +{
  368 + s_bbTreeNode * oldNode = bbTreeNodeRemove (&t->root, t->cmp, value);
  369 +
  370 + if (oldNode != NULL)
  371 + {
  372 + value = oldNode->value;
  373 + free (oldNode);
  374 +
  375 + return value;
  376 + }
  377 +
  378 + return NULL;
  379 +}
  380 +
  381 + void *
  382 +bbTreeMax (s_bbTree * t)
  383 +{
  384 + s_bbTreeNode * max = bbTreeNodeMax (t->root);
  385 +
  386 + return max == NULL ? max : max->value;
  387 +}
  388 +
  389 + void *
  390 +bbTreeMin (s_bbTree * t)
  391 +{
  392 + s_bbTreeNode * max = bbTreeNodeMin (t->root);
  393 +
  394 + return max == NULL ? max : max->value;
  395 +}
  396 +
  397 + int
  398 +bbTreeSize (s_bbTree * t)
  399 +{
  400 + return bbTreeNodeSize (t->root);
  401 +}
  402 +
  403 + void **
  404 +bbTreeInOrder (s_bbTree * t, void ** buffer)
  405 +{
  406 + void ** tmp = buffer;
  407 +
  408 + bbTreeNodeInOrder (t->root, &tmp);
  409 +
  410 + return buffer;
  411 +}
  1 +#include <identList.h>
  2 +#include <stmtQueue.h>
  3 +
  4 +typedef struct block s_block;
  5 +
  6 +struct block /* a stack of used blocks. */
  7 +{
  8 + s_stmtQueue * stmts;
  9 + s_identList * idl;
  10 +
  11 + s_block * prev;
  12 +};
  13 +
  14 +
  15 + s_block *
  16 +blockNew (s_stmtQueue * stmts)
  17 +{
  18 + s_block * new = (s_block *) malloc (sizeof (s_block));
  19 +
  20 + new->stmts = stmts;
  21 + new->prev = NULL;
  22 + new->idl = identListNew (new);
  23 +
  24 + return new;
  25 +}
  26 +
  27 + void
  28 +blockFree (s_block * bs)
  29 +{
  30 + if (bs->prev != NULL)
  31 + blockFree (bs->prev);
  32 +
  33 + if (bs->stmts != NULL)
  34 + stmtQueueFree (bs->stmts);
  35 +
  36 + identListFree (bs->idl);
  37 +
  38 + free (bs);
  39 +}
  40 +
  41 + void
  42 +blockSetNonLocalId (s_block * bs, s_ident * id)
  43 +{
  44 + s_identListPutVal (bs->idl, id);
  45 +}
  46 +
  47 + s_block *
  48 +blockPush (s_block ** bs, s_block * new)
  49 +{
  50 + new->prev = *bs;
  51 +
  52 + *bs = new;
  53 +
  54 + return *bs;
  55 +}
  56 +
  57 + s_block *
  58 +blockPop (s_block ** bs)
  59 +{
  60 + s_block * ret = *bs;
  61 + *bs = (*bs)->prev;
  62 +
  63 + return ret;
  64 +}
  65 +
  66 + s_block *
  67 +blockPrev (s_block * bs)
  68 +{
  69 + return bs->prev;
  70 +}
  71 +
  72 + s_stmtQueue *
  73 +blockStmts (s_block * bs)
  74 +{
  75 + return bs->stmts;
  76 +}
  77 +
  78 + s_identList *
  79 +blockIdl (s_block * bs)
  80 +{
  81 + return bs->idl;
  82 +}
  1 +#include <stdio.h>
  2 +#include <stdlib.h>
  3 +#include <malloc.h>
  4 +#include <string.h>
  5 +
  6 +#include <expValue.h>
  7 +#include <cast.h>
  8 +
  9 + s_expVal *
  10 +castExprToInt (s_expVal * eVal)
  11 +{
  12 + return expValueIntNew (expValueInt (eVal));
  13 +}
  14 +
  15 + s_expVal *
  16 +castExprToFloat (s_expVal * eVal)
  17 +{
  18 + return expValueFloatNew (expValueFloat (eVal));
  19 +}
  20 +
  21 + s_expVal *
  22 +castExprToString (s_expVal * eVal)
  23 +{
  24 + char * val = expValueString (eVal);
  25 + s_expVal * ret = expValueStringNew (val);
  26 +
  27 + free (val);
  28 +
  29 + return ret;
  30 +}
  1 +#include <string.h>
  2 +#include <stdlib.h>
  3 +#include <stdio.h>
  4 +
  5 +#include <expValue.h>
  6 +#include <tepal_pars.h>
  7 +#include <evalCond.h>
  8 +
  9 +
  10 +/*
  11 + * static function (internal only)
  12 + */
  13 +static
  14 + int
  15 +evalIntComp (int op, s_expVal * _op1, s_expVal * _op2)
  16 +{
  17 + long op1 = expValueInt (_op1);
  18 + long op2 = expValueInt (_op2);
  19 +
  20 + switch (op)
  21 + {
  22 + case EQ: return (op1 == op2);
  23 + case NE: return (op1 != op2);
  24 + case LT: return (op1 < op2);
  25 + case GT: return (op1 > op2);
  26 + case LE: return (op1 <= op2);
  27 + case GE: return (op1 >= op2);
  28 + }
  29 +}
  30 +
  31 +static
  32 + int
  33 +evalFloatComp (int op, s_expVal * _op1, s_expVal * _op2)
  34 +{
  35 + double op1 = expValueFloat (_op1);
  36 + double op2 = expValueFloat (_op2);
  37 +
  38 + switch (op)
  39 + {
  40 + case EQ: return (op1 == op2);
  41 + case NE: return (op1 != op2);
  42 + case LT: return (op1 < op2);
  43 + case GT: return (op1 > op2);
  44 + case LE: return (op1 <= op2);
  45 + case GE: return (op1 >= op2);
  46 + }
  47 +}
  48 +
  49 +static
  50 + int
  51 +evalStringComp (int op, s_expVal * _op1, s_expVal * _op2)
  52 +{
  53 + char * op1 = expValueString (_op1);
  54 + char * op2 = expValueString (_op2);
  55 + long ret;
  56 +
  57 + switch (op)
  58 + {
  59 + case EQ: ret = (! strcmp (op1, op2));
  60 + case NE: ret = strcmp (op1, op2);
  61 + case LT: ret = (strcmp (op1, op2) < 0) ? 1 : 0;
  62 + case GT: ret = (strcmp (op1, op2) > 0) ? 1 : 0;
  63 + case LE: ret = (strcmp (op1, op2) <= 0) ? 1 : 0;
  64 + case GE: ret = (strcmp (op1, op2) >= 0) ? 1 : 0;
  65 + }
  66 +
  67 + free (op1);
  68 + free (op2);
  69 +
  70 + return ret;
  71 +}
  72 +
  73 +
  74 +
  75 +/*
  76 + * public functions (interface)
  77 + */
  78 + int
  79 +evalCondExpr (s_expVal * _op)
  80 +{
  81 + switch (expValueGetType (_op))
  82 + {
  83 + case EXP_TYP_INT: return expValueInt (_op);
  84 + case EXP_TYP_FLOAT: return expValueInt (_op);
  85 + case EXP_TYP_STRING:
  86 + {
  87 + char * op = expValueString (_op);
  88 + long ret = strlen (op);
  89 +
  90 + free (op);
  91 +
  92 + return ret;
  93 + }
  94 + }
  95 +
  96 + return 0;
  97 +}
  98 +
  99 + int
  100 +evalComp (int op, s_expVal * op1, s_expVal * op2)
  101 +{
  102 + switch (expValueGetType (op1))
  103 + {
  104 + case EXP_TYP_INT:
  105 + return evalIntComp (op, op1, op2);
  106 +
  107 + case EXP_TYP_FLOAT:
  108 + return evalFloatComp (op, op1, op2);
  109 +
  110 + case EXP_TYP_STRING:
  111 + return evalStringComp (op, op1, op2);
  112 + }
  113 +}
  1 +#include <malloc.h>
  2 +#include <string.h>
  3 +#include <stdlib.h>
  4 +#include <stdio.h>
  5 +
  6 +#include <expValue.h>
  7 +#include <tepal.h>
  8 +#include <tepal_pars.h>
  9 +#include <evalExpr.h>
  10 +
  11 +
  12 +/*
  13 + * static function (internal only)
  14 + */
  15 +static
  16 +inline
  17 + s_expVal *
  18 +stringPlus (s_expVal * _op1, s_expVal * _op2)
  19 +{
  20 + s_expVal * ret;
  21 + char * op1 = expValueString (_op1);
  22 + char * op2 = expValueString (_op2);
  23 + char * retVal = (char *) malloc (
  24 + sizeof (char) * (strlen (op1) + strlen (op2) + 1));
  25 +
  26 + strcpy (retVal, op1);
  27 + strcat (retVal, op2);
  28 + ret = expValueStringNew (retVal);
  29 +
  30 + free (retVal);
  31 + free (op2);
  32 + free (op1);
  33 +
  34 + return ret;
  35 +}
  36 +
  37 +static
  38 +inline
  39 + s_expVal *
  40 +stringNeg (s_expVal * _op)
  41 +{
  42 + s_expVal * ret;
  43 + int i;
  44 +
  45 + char * op = expValueString (_op);
  46 + int len = strlen (op) - 1;
  47 +
  48 + for (i=0; i<=(len/2); i++)
  49 + {
  50 + char tmp = op[i];
  51 + op[i] = op[len-i];
  52 + op[len-i] = tmp;
  53 + }
  54 +
  55 + ret = expValueStringNew (op);
  56 + free (op);
  57 + return ret;
  58 +}
  59 +
  60 +static
  61 +inline
  62 + s_expVal *
  63 +evalIntExp (int op, s_expVal * _op1, s_expVal * _op2)
  64 +{
  65 + long op1 = expValueInt (_op1);
  66 + long op2 = (_op2 != NULL) ? expValueInt (_op2) : 0;
  67 +
  68 + if (op == NEG) return expValueIntNew (- op1);
  69 +
  70 + switch (expValueGetType (_op2))
  71 + {
  72 + case EXP_TYP_INT:
  73 + case EXP_TYP_FLOAT:
  74 + switch (op)
  75 + {
  76 + case PLUS: return expValueIntNew (op1 + op2);
  77 + case MINUS: return expValueIntNew (op1 - op2);
  78 + case TIMES: return expValueIntNew (op1 * op2);
  79 + case OVER: return expValueIntNew (op1 / op2);
  80 + case MODULO: return expValueIntNew (op1 % op2);
  81 + }
  82 +
  83 + case EXP_TYP_STRING:
  84 + if (op == PLUS)
  85 + return stringPlus (_op1, _op2);
  86 + exitError (ERR_STRING_OPERATOR, op);
  87 + }
  88 +}
  89 +
  90 +static
  91 +inline
  92 + s_expVal *
  93 +evalFloatExp (int op, s_expVal * _op1, s_expVal * _op2)
  94 +{
  95 + double op1 = expValueFloat (_op1);
  96 + double op2 = (_op2 != NULL) ? expValueFloat (_op2) : 0.0;
  97 +
  98 + if (op == NEG) return expValueFloatNew (- op1);
  99 +
  100 + switch (expValueGetType (_op2))
  101 + {
  102 + case EXP_TYP_INT:
  103 + case EXP_TYP_FLOAT:
  104 + switch (op)
  105 + {
  106 + case MODULO: exitError (ERR_FLOAT_OPERATOR, op);
  107 + case PLUS: return expValueFloatNew (op1 + op2);
  108 + case MINUS: return expValueFloatNew (op1 - op2);
  109 + case TIMES: return expValueFloatNew (op1 * op2);
  110 + case OVER: return expValueFloatNew (op1 / op2);
  111 + }
  112 +
  113 + case EXP_TYP_STRING:
  114 + if (op == PLUS)
  115 + return stringPlus (_op1, _op2);
  116 + exitError (ERR_STRING_OPERATOR, op);
  117 + }
  118 +}
  119 +
  120 +
  121 +
  122 +/*
  123 + * public functions (interface)
  124 + */
  125 + s_expVal *
  126 +evalExpr (int op, s_expVal * op1, s_expVal * op2)
  127 +{
  128 + switch (expValueGetType (op1))
  129 + {
  130 + case EXP_TYP_INT:
  131 + return evalIntExp (op, op1, op2);
  132 +
  133 + case EXP_TYP_FLOAT:
  134 + if (op != MODULO)
  135 + return evalFloatExp (op, op1, op2);
  136 + exitError (ERR_FLOAT_OPERATOR, op);
  137 +
  138 + case EXP_TYP_STRING:
  139 + if (op == PLUS)
  140 + return stringPlus (op1, op2);
  141 + if (op == NEG)
  142 + return stringNeg (op1);
  143 + exitError (ERR_STRING_OPERATOR, op);
  144 + }
  145 +}
  1 +#include <string.h>
  2 +#include <malloc.h>
  3 +#include <stdio.h>
  4 +
  5 +#include <expValue.h>
  6 +
  7 +union expType
  8 +{
  9 + long iVal;
  10 + double fVal;
  11 + char * cPtr;
  12 +};
  13 +
  14 +struct expVal
  15 +{
  16 + int type;
  17 +
  18 + union expType val;
  19 +};
  20 +
  21 +/*
  22 + * Constructoren / Destructoren
  23 + */
  24 + s_expVal *
  25 +expValueIntNew (long val)
  26 +{
  27 + s_expVal * ret = (s_expVal *) malloc (sizeof (s_expVal));
  28 +
  29 + ret->type = EXP_TYP_INT;
  30 + ret->val.iVal = val;
  31 +
  32 + return ret;
  33 +}
  34 +
  35 + s_expVal *
  36 +expValueFloatNew (double val)
  37 +{
  38 + s_expVal * ret = (s_expVal *) malloc (sizeof (s_expVal));
  39 +
  40 + ret->type = EXP_TYP_FLOAT;
  41 + ret->val.fVal = val;
  42 +
  43 + return ret;
  44 +}
  45 +
  46 + s_expVal *
  47 +expValueStringNew (char * val)
  48 +{
  49 + s_expVal * ret = (s_expVal *) malloc (sizeof (s_expVal));
  50 +
  51 + ret->type = EXP_TYP_STRING;
  52 + ret->val.cPtr = (char *) malloc (sizeof (char) * (strlen (val) + 1));
  53 + strcpy (ret->val.cPtr, val);
  54 +
  55 + return ret;
  56 +}
  57 +
  58 + s_expVal *
  59 +expValueClone (s_expVal * eVal)
  60 +{
  61 + s_expVal * ret = (s_expVal *) malloc (sizeof (s_expVal));
  62 +
  63 + ret->type = eVal->type;
  64 +
  65 + switch (eVal->type)
  66 + {
  67 + case EXP_TYP_INT: ret->val.iVal = eVal->val.iVal; break;
  68 + case EXP_TYP_FLOAT: ret->val.fVal = eVal->val.fVal; break;
  69 + case EXP_TYP_STRING:
  70 + {
  71 + ret->val.cPtr = (char *) malloc (
  72 + sizeof (char) * (strlen (eVal->val.cPtr) + 1));
  73 + strcpy (ret->val.cPtr, eVal->val.cPtr);
  74 + }
  75 + }
  76 +
  77 + return ret;
  78 +}
  79 +
  80 + void
  81 +expValueFree (s_expVal * eVal)
  82 +{
  83 + if (eVal->type == EXP_TYP_STRING)
  84 + free (eVal->val.cPtr);
  85 + free (eVal);
  86 +}
  87 +
  88 +
  89 +/*
  90 + * Accessors
  91 + */
  92 + long
  93 +expValueInt (s_expVal * eVal)
  94 +{
  95 + switch (eVal->type)
  96 + {
  97 + case EXP_TYP_INT: return eVal->val.iVal;
  98 + case EXP_TYP_FLOAT: return (long) eVal->val.fVal;
  99 + case EXP_TYP_STRING: return atoi (eVal->val.cPtr);
  100 + }
  101 +}
  102 +
  103 + double
  104 +expValueFloat (s_expVal * eVal)
  105 +{
  106 + switch (eVal->type)
  107 + {
  108 + case EXP_TYP_INT: return (double) eVal->val.iVal;
  109 + case EXP_TYP_FLOAT: return eVal->val.fVal;
  110 + case EXP_TYP_STRING: return atof (eVal->val.cPtr);
  111 + }
  112 +}
  113 +
  114 + char *
  115 +expValueString (s_expVal * eVal)
  116 +{
  117 + char buf[40];
  118 + char * ret = NULL;
  119 +
  120 + switch (eVal->type)
  121 + {
  122 + case EXP_TYP_INT:
  123 + sprintf (buf, "%d", eVal->val.iVal);
  124 + ret = (char *) malloc (sizeof (char) * (strlen (buf) + 1));
  125 + strcpy (ret, buf);
  126 + break;
  127 +
  128 + case EXP_TYP_FLOAT:
  129 + sprintf (buf, "%f", eVal->val.fVal);
  130 + ret = (char *) malloc (sizeof (char) * (strlen (buf) + 1));
  131 + strcpy (ret, buf);
  132 + break;
  133 +
  134 + case EXP_TYP_STRING:
  135 + ret = (char *) malloc (sizeof (char) * (strlen (eVal->val.cPtr) + 1));
  136 + strcpy (ret, eVal->val.cPtr);
  137 + break;
  138 + }
  139 +
  140 + return ret;
  141 +}
  142 +
  143 +/*
  144 + * analyse expValue
  145 + */
  146 + int
  147 +expValueGetType (s_expVal * eVal)
  148 +{
  149 + return eVal->type;
  150 +}
  1 +#include <string.h>
  2 +#include <malloc.h>
  3 +#include <stdio.h>
  4 +#include <stdlib.h>
  5 +
  6 +#include <expValue.h>
  7 +#include <identList.h>
  8 +#include <tepal.h>
  9 +#include <ident.h>
  10 +
  11 +
  12 +/*
  13 + * Typdeklaration, etc
  14 + */
  15 +union identTypes
  16 +{
  17 + s_expVal * base;
  18 + s_identList * idl;
  19 +};
  20 +
  21 +struct ident
  22 +{
  23 + char * key;
  24 + int idx;
  25 +
  26 + int queued;
  27 +
  28 + union identTypes val;
  29 +};
  30 +
  31 +
  32 +/*
  33 + * statische Funktionen (interner gebrauch)
  34 + */
  35 +
  36 +/*
  37 + * nicht statische Funktionen (Interface)
  38 + */
  39 +
  40 +/*
  41 + * Contructors / Destructors for ident
  42 + */
  43 + s_ident *
  44 +identNew (int idx, const char * key)
  45 +{
  46 + int keyLen = (key == NULL) ? 2 : 2 + strlen (key);
  47 + s_ident * ident = (s_ident *) malloc (sizeof (s_ident));
  48 +
  49 + ident->idx = idx;
  50 + ident->key = (char *) malloc (sizeof (char) * keyLen);
  51 +
  52 + ident->key[0] = ID_TYP_UNDEF;
  53 + ident->key[1] = '\0';
  54 +
  55 + if (key != NULL)
  56 + strcpy (ident->key + 1, key);
  57 +
  58 + ident->queued = 0;
  59 +
  60 + return ident;
  61 +}
  62 +
  63 + s_ident *
  64 +identUndefNew (int idx, const char * key)
  65 +{
  66 +#ifdef DEBUG2
  67 + printf ("[!DEBUG!] identUndefNew: %d/%s\n", idx, key);
  68 +#endif
  69 +
  70 + return identNew (idx, key);
  71 +}
  72 +
  73 + s_ident *
  74 +identExpNew (int idx, const char * key, s_expVal * val)
  75 +{
  76 + s_ident * ident = identNew (idx, key);
  77 +
  78 +#ifdef DEBUG2
  79 + printf ("[!DEBUG!] identExpNew: %d/%s\n", idx, key);
  80 +#endif
  81 +
  82 + ident->key[0] = ID_TYP_EXP;
  83 + ident->val.base = expValueClone (val);
  84 +
  85 + return ident;
  86 +}
  87 +
  88 + s_ident *
  89 +identIdlNew (int idx, const char * key, s_identList * val)
  90 +{
  91 + s_ident * ident = identNew (idx, key);
  92 +
  93 +#ifdef DEBUG2
  94 + printf ("[!DEBUG!] identIdlNew: %d/%s\n", idx, key);
  95 +#endif
  96 +
  97 + ident->key[0] = ID_TYP_IDL;
  98 + ident->val.idl = val;
  99 +
  100 + return ident;
  101 +}
  102 +
  103 + void
  104 +identFree (s_ident * id)
  105 +{
  106 +#ifdef DEBUG2
  107 + printf ("[!DEBUG!] identFree: %d/%s\n", id->idx, id->key);
  108 +#endif
  109 +
  110 + switch (identGetType (id))
  111 + {
  112 + case ID_TYP_EXP: expValueFree (id->val.base); break;
  113 + case ID_TYP_IDL: identListFree (id->val.idl); break;
  114 + }
  115 +
  116 + free (id->key);
  117 + free (id);
  118 +}
  119 +
  120 +/*
  121 + * analyse ident
  122 + */
  123 + int
  124 +identIsQueued (s_ident * id)
  125 +{
  126 + return id->queued;
  127 +}
  128 +
  129 + void
  130 +identEnqueue (s_ident * id)
  131 +{
  132 + id->queued ++;
  133 +}
  134 +
  135 + void
  136 +identDequeue (s_ident * id)
  137 +{
  138 + id->queued --;
  139 +}
  140 +
  141 + int
  142 +identGetType (s_ident * id)
  143 +{
  144 + return id->key[0];
  145 +}
  146 +
  147 + char *
  148 +identGetKey (s_ident * id)
  149 +{
  150 + return id->key + 1;
  151 +}
  152 +
  153 + int
  154 +identGetIdx (s_ident * id)
  155 +{
  156 + return id->idx;
  157 +}
  158 +
  159 +/* identifier to value */
  160 + s_expVal *
  161 +identExp (s_ident * id)
  162 +{
  163 + s_expVal * ret = NULL;
  164 +
  165 + if (id == NULL)
  166 + exitError (ERR_UNDEF_VAR, identGetKey (id));
  167 +
  168 + if (identGetType (id) == ID_TYP_EXP)
  169 + {
  170 + ret = expValueClone (id->val.base);
  171 + }
  172 +
  173 + return ret;
  174 +}
  175 +
  176 + s_identList *
  177 +identIdl (s_ident * id)
  178 +{
  179 + s_identList * ret = NULL;
  180 +
  181 + if (identGetType (id) == ID_TYP_IDL)
  182 + {
  183 + ret = id->val.idl;
  184 + }
  185 +
  186 + return ret;
  187 +}
  188 +
  189 + s_ident *
  190 +identSetExp (s_ident * id, s_expVal * val)
  191 +{
  192 + switch (identGetType (id))
  193 + {
  194 + case ID_TYP_EXP: expValueFree (id->val.base); break;
  195 + case ID_TYP_IDL: identListFree (id->val.idl); break;
  196 + }
  197 +
  198 + id->key[0] = ID_TYP_EXP;
  199 + id->val.base = expValueClone (val);
  200 +
  201 + return id;
  202 +}
  203 +
  204 + s_ident *
  205 +identSetIdl (s_ident * id, s_identList * val)
  206 +{
  207 + switch (identGetType (id))
  208 + {
  209 + case ID_TYP_EXP: expValueFree (id->val.base);
  210 + case ID_TYP_IDL: identListFree (id->val.idl);
  211 + }
  212 +
  213 + id->key[0] = ID_TYP_IDL;
  214 + id->val.idl = val;
  215 +
  216 + return id;
  217 +}
  1 +#include <string.h>
  2 +#include <malloc.h>
  3 +#include <stdio.h>
  4 +#include <stdlib.h>
  5 +
  6 +#include <expValue.h>
  7 +#include <bbtree.h>
  8 +#include <ident.h>
  9 +#include <identList.h>
  10 +
  11 +
  12 +struct identList
  13 +{
  14 + s_bbTree * idIdx;
  15 + s_bbTree * idHash;
  16 +};
  17 +
  18 +
  19 +/*
  20 + * statische Funktionen (interner gebrauch)
  21 + */
  22 +static
  23 + int
  24 +idHashCmp (void * _a, void * _b)
  25 +{
  26 + s_ident * a = (s_ident *) _a;
  27 + s_ident * b = (s_ident *) _b;
  28 +
  29 + return strcmp (identGetKey (a), identGetKey (b));
  30 +}
  31 +
  32 +static
  33 + int
  34 +idIdxCmp (void * _a, void * _b)
  35 +{
  36 + s_ident * a = (s_ident *) _a;
  37 + s_ident * b = (s_ident *) _b;
  38 +
  39 + return identGetIdx (a) - identGetIdx (b);
  40 +}
  41 +
  42 +
  43 +/*
  44 + * nicht statische Funktionen (Interface)
  45 + */
  46 +
  47 +/*
  48 + * Contructors / Destructors for identList
  49 + */
  50 + s_identList *
  51 +identListNew (void)
  52 +{
  53 + s_identList * ret = (s_identList *) malloc (sizeof (s_identList));
  54 +
  55 + ret->idIdx = bbTreeNew (idIdxCmp);
  56 + ret->idHash = bbTreeNew (idHashCmp);
  57 +
  58 + return ret;
  59 +}
  60 +
  61 +void
  62 +identListFree (s_identList * l)
  63 +{
  64 + s_ident ** idArray,
  65 + ** _run;
  66 +
  67 + for (_run = idArray = (s_ident **) identListToArray (l);
  68 + *_run != NULL;
  69 + _run++)
  70 + {
  71 + identDequeue (*_run);
  72 + if (! identIsQueued (*_run))
  73 + identFree (*_run);
  74 + }
  75 +
  76 + free (idArray);
  77 +
  78 + bbTreeFree (l->idIdx);
  79 + bbTreeFree (l->idHash);
  80 +
  81 + free (l);
  82 +}
  83 +
  84 +/*
  85 + * insertions or deletion into a identList
  86 + */
  87 + s_ident *
  88 +identListPutVal (s_identList * l, s_ident * val)
  89 +{
  90 + s_ident * oldVal;
  91 + int idx = identGetIdx (val);
  92 + char * key = identGetKey (val);
  93 +
  94 + identEnqueue (val);
  95 +
  96 + if ((idx < 0 && key[0] == '\0') || idx != -1 && key[0] != '\0')
  97 + /* calling error: either key or idx must be valid. But not both. */
  98 + return NULL;
  99 +
  100 + if (idx >= 0)
  101 + oldVal = (s_ident *) bbTreeInsert (l->idIdx, val);
  102 + else
  103 + oldVal = (s_ident *) bbTreeInsert (l->idHash, val);
  104 +
  105 + if (oldVal != NULL)
  106 + /*
  107 + * these are few lines with a lot behind them. The not obvious question
  108 + * here is: What happens if oldval points to the same address than val?
  109 + * well, this could only happen if val was was formally queued, because
  110 + * else oldVal would be NULL. Knowing this makes clear that the queue
  111 + * state is not changed at all, because first it was increased above with
  112 + * identEnqueue and the it will be decreased in this if block again. But as
  113 + * it was formally queued it will not be freed (Good)!
  114 + */
  115 + {
  116 + identDequeue (oldVal);
  117 + if (! identIsQueued (oldVal))
  118 + identFree (oldVal);
  119 + }
  120 +
  121 + return val;
  122 +}
  123 +
  124 + s_ident *
  125 +identListPutExpByIdx (s_identList * l, int idx, s_expVal * val)
  126 +{
  127 + return identListPutVal (l, identExpNew (idx, NULL, val));
  128 +}
  129 +
  130 + s_ident *
  131 +identListPutIdlByIdx (s_identList * l, int idx, s_identList * val)
  132 +{
  133 + return identListPutVal (l, identIdlNew (idx, NULL, val));
  134 +}
  135 +
  136 + s_ident *
  137 +identListPutExpByKey (s_identList * l, const char * key, s_expVal * val)
  138 +{
  139 + return identListPutVal (l, identExpNew (-1, key, val));
  140 +}
  141 +
  142 + s_ident *
  143 +identListPutIdlByKey (s_identList * l, const char * key, s_identList * val)
  144 +{
  145 + return identListPutVal (l, identIdlNew (-1, key, val));
  146 +}
  147 +
  148 + void
  149 +identListRemoveByIdx (s_identList * l, int idx)
  150 +{
  151 + s_ident * seek = (s_ident *) identNew (idx, NULL);
  152 + s_ident * val = bbTreeRemove (l->idIdx, seek);
  153 +
  154 +#ifdef DEBUG2
  155 + printf ("[!DEBUG!] seek (remove) identNew: %d/%s\n", idx, "");
  156 +#endif
  157 +
  158 + identFree (seek);
  159 +
  160 + if (val != NULL)
  161 + {
  162 + identDequeue (val);
  163 + if (! identIsQueued (val))
  164 + identFree (val);
  165 + }
  166 +}
  167 +
  168 + void
  169 +identListRemoveByKey (s_identList * l, const char * key)
  170 +{
  171 + s_ident * seek = (s_ident *) identNew (-1, key);
  172 + s_ident * val = bbTreeRemove (l->idIdx, seek);
  173 +
  174 +#ifdef DEBUG2
  175 + printf ("[!DEBUG!] seek (remove) identNew: %d/%s\n", -1, key);
  176 +#endif
  177 +
  178 + identFree (seek);
  179 +
  180 + if (val != NULL)
  181 + {
  182 + identDequeue (val);
  183 + if (! identIsQueued (val))
  184 + identFree (val);
  185 + }
  186 +}
  187 +
  188 +/*
  189 + * seeking in identList
  190 + */
  191 + s_ident *
  192 +identListSeekIdx (s_identList * l, int idx)
  193 +{
  194 + s_ident * seek = (s_ident *) identNew (idx, NULL);
  195 + s_ident * val = (s_ident *) bbTreeSeek (l->idIdx, seek);
  196 +
  197 +#ifdef DEBUG2
  198 + printf ("[!DEBUG!] seek identNew: %d/%s\n", idx, "");
  199 +#endif
  200 +
  201 + identFree (seek);
  202 +
  203 + return val;
  204 +}
  205 +
  206 + s_ident *
  207 +identListSeekKey (s_identList * l, const char * key)
  208 +{
  209 + s_ident * seek = (s_ident *) identNew (-1, key);
  210 + s_ident * val = (s_ident *) bbTreeSeek (l->idHash, seek);
  211 +
  212 +#ifdef DEBUG2
  213 + printf ("[!DEBUG!] seek identNew: %d/%s\n", -1, key);
  214 +#endif
  215 +
  216 + identFree (seek);
  217 +
  218 + return val;
  219 +}
  220 +
  221 +/*
  222 + * identList to other DataStructures
  223 + */
  224 + s_ident **
  225 +identListToArray (s_identList * l)
  226 +{
  227 + int idIdxLen = bbTreeSize (l->idIdx);
  228 + int idHashLen = bbTreeSize (l->idHash);
  229 + int retLen = idIdxLen + idHashLen + 1;
  230 + s_ident ** ret = (s_ident **) malloc (sizeof (s_ident *) * retLen);
  231 +
  232 + memset (ret, 0, sizeof (s_ident **) * retLen);
  233 +
  234 + bbTreeInOrder (l->idIdx, (void **) ret);
  235 + bbTreeInOrder (l->idHash, (void **) &(ret[idIdxLen]));
  236 +
  237 + return ret;
  238 +}
  1 +#include <malloc.h>
  2 +#include <stdio.h>
  3 +
  4 +#include <expValue.h>
  5 +#include <ident.h>
  6 +#include <evalExpr.h>
  7 +#include <evalCond.h>
  8 +#include <variable.h>
  9 +#include <assign.h>
  10 +#include <cast.h>
  11 +#include <tepal_pars.h>
  12 +#include <block.h>
  13 +
  14 +#include <statement.h>
  15 +
  16 +/*
  17 + * Deklaration und Definition
  18 + */
  19 +#include <stmtQueue.h>
  20 +
  21 +struct stmt
  22 +{
  23 + int sId;
  24 + s_stmtQueue * sQueue;
  25 + u_stmtType sConst;
  26 + int sConstTyp;
  27 +};
  28 +
  29 +/*
  30 + * statische Funktionen (interner gebrauch)
  31 + */
  32 +static
  33 +inline
  34 + u_stmtType
  35 +stmtEval (s_stmt * stmt, s_block * actBlock, int op)
  36 +{
  37 + s_stmtQueue * args = stmt->sQueue;
  38 + s_expVal * op1 = stmtDo (stmtQueueGet (args, 0), actBlock).eVal,
  39 + * op2 = stmtDo (stmtQueueGet (args, 1), actBlock).eVal,
  40 + * ret;
  41 +
  42 + ret = evalExpr (op, op1, op2);
  43 +
  44 + if (op1 != NULL) expValueFree (op1);
  45 + if (op2 != NULL) expValueFree (op2);
  46 +
  47 + return (u_stmtType) ret;
  48 +}
  49 +
  50 +static
  51 +inline
  52 + u_stmtType
  53 +stmtIdentVar (s_stmt * stmt, s_block * actBlock)
  54 +{
  55 + s_ident * ret = NULL;
  56 +
  57 + s_stmtQueue * args = stmt->sQueue;
  58 + s_expVal * _op = stmtDo (stmtQueueGet (args, 0), actBlock).eVal;
  59 + char * op = expValueString (_op);
  60 + s_block * run = actBlock;
  61 +
  62 + while (ret == NULL && run != NULL)
  63 + {
  64 + ret = identListSeekKey (blockIdl (run), op);
  65 + run = blockPrev (run);
  66 + }
  67 +
  68 + if (ret == NULL)
  69 + ret = identListPutVal (blockIdl (actBlock), identUndefNew (-1, op));
  70 +
  71 + expValueFree (_op);
  72 + free (op);
  73 +
  74 + return (u_stmtType) ret;
  75 +}
  76 +
  77 +static
  78 +inline
  79 + u_stmtType
  80 +stmtIdentArray (s_stmt * stmt, s_block * actBlock)
  81 +{
  82 + s_stmtQueue * args = stmt->sQueue;
  83 + s_ident * op1 = stmtDo (stmtQueueGet (args, 0), actBlock).idVal;
  84 + s_expVal * op2 = stmtDo (stmtQueueGet (args, 1), actBlock).eVal;
  85 + s_ident * ret;
  86 +
  87 + ret = getArray (op1, op2);
  88 +
  89 + if (op2 != NULL) expValueFree (op2);
  90 +
  91 + return (u_stmtType) ret;
  92 +}
  93 +
  94 +static
  95 +inline
  96 + u_stmtType
  97 +stmtIdentVal (s_stmt * stmt, s_block * actBlock)
  98 +{
  99 + s_stmtQueue * args = stmt->sQueue;
  100 + s_ident * op1 = stmtDo (stmtQueueGet (args, 0), actBlock).idVal;
  101 +
  102 + return (u_stmtType) identExp (op1);
  103 +}
  104 +
  105 +static
  106 +inline
  107 + u_stmtType
  108 +stmtEvalComp (s_stmt * stmt, s_block * actBlock, int op)
  109 +{
  110 + s_stmtQueue * args = stmt->sQueue;
  111 + s_expVal * op1 = stmtDo (stmtQueueGet (args, 0), actBlock).eVal,
  112 + * op2 = stmtDo (stmtQueueGet (args, 1), actBlock).eVal;
  113 + int ret;
  114 +
  115 + ret = evalComp (op, op1, op2);
  116 +
  117 + if (op1 != NULL) expValueFree (op1);
  118 + if (op2 != NULL) expValueFree (op2);
  119 +
  120 + return (u_stmtType) ret;
  121 +}
  122 +
  123 +static
  124 +inline
  125 + u_stmtType
  126 +stmtAssign (s_stmt * stmt, s_block * actBlock)
  127 +{
  128 + s_stmtQueue * args = stmt->sQueue;
  129 + s_ident * op1 = stmtDo (stmtQueueGet (args, 0), actBlock).idVal;
  130 + s_expVal * op2 = stmtDo (stmtQueueGet (args, 1), actBlock).eVal,
  131 + * ret;
  132 +
  133 + if (op1 == NULL)
  134 + op1 = getVariable (NULL, NULL);
  135 +
  136 + ret = assign (op1, op2);
  137 +
  138 + if (op2 != NULL) expValueFree (op2);
  139 +
  140 + return (u_stmtType) ret;
  141 +}
  142 +
  143 +static
  144 +inline
  145 + u_stmtType
  146 +stmtPrint (s_stmt * stmt, s_block * actBlock)
  147 +{
  148 + s_stmtQueue * args = stmt->sQueue;
  149 + s_expVal * op = stmtDo (stmtQueueGet (args, 0), actBlock).eVal;
  150 +
  151 + if (op != NULL)
  152 + {
  153 + printExpr (op);
  154 + expValueFree (op);
  155 + }
  156 +
  157 + return (u_stmtType) 0;
  158 +}
  159 +
  160 +static
  161 +inline
  162 + u_stmtType
  163 +stmtEvalCondExpr (s_stmt * stmt, s_block * actBlock)
  164 +{
  165 + s_stmtQueue * args = stmt->sQueue;
  166 + s_expVal * op = stmtDo (stmtQueueGet (args, 0), actBlock).eVal;
  167 + int ret;
  168 +
  169 + ret = evalCondExpr (op);
  170 +
  171 + if (op != NULL) expValueFree (op);
  172 +
  173 + return (u_stmtType) ret;
  174 +}
  175 +
  176 +static
  177 +inline
  178 + u_stmtType
  179 +stmtEvalCond (s_stmt * stmt, s_block * actBlock, int op)
  180 +{
  181 + s_stmtQueue * args = stmt->sQueue;
  182 + int op1 = stmtDo (stmtQueueGet (args, 0), actBlock).cond;
  183 +
  184 + switch (op)
  185 + {
  186 + case LOGAND:
  187 + {
  188 + int op2 = stmtDo (stmtQueueGet (args, 1), actBlock).cond;
  189 + return (u_stmtType) (op1 && op2);
  190 + }
  191 +
  192 + case LOGOR:
  193 + {
  194 + int op2 = stmtDo (stmtQueueGet (args, 1), actBlock).cond;
  195 + return (u_stmtType) (op1 || op2);
  196 + }
  197 +
  198 + case LOGNEG:
  199 + return (u_stmtType) (! op1);
  200 + }
  201 +}
  202 +
  203 +static
  204 +inline
  205 + u_stmtType
  206 +stmtCastInt (s_stmt * stmt, s_block * actBlock)
  207 +{
  208 + s_stmtQueue * args = stmt->sQueue;
  209 + s_expVal * op = stmtDo (stmtQueueGet (args, 0), actBlock).eVal,
  210 + * ret;
  211 +
  212 + ret = castExprToInt (op);
  213 +
  214 + if (op != NULL) expValueFree (op);
  215 +
  216 + return (u_stmtType) ret;
  217 +}
  218 +
  219 +static
  220 +inline
  221 + u_stmtType
  222 +stmtCastFloat (s_stmt * stmt, s_block * actBlock)
  223 +{
  224 + s_stmtQueue * args = stmt->sQueue;
  225 + s_expVal * op = stmtDo (stmtQueueGet (args, 0), actBlock).eVal,
  226 + * ret;
  227 +
  228 + ret = castExprToFloat (op);
  229 +
  230 + if (op != NULL) expValueFree (op);
  231 +
  232 + return (u_stmtType) ret;
  233 +}
  234 +
  235 +static
  236 +inline
  237 + u_stmtType
  238 +stmtCastString (s_stmt * stmt, s_block * actBlock)
  239 +{
  240 + s_stmtQueue * args = stmt->sQueue;
  241 + s_expVal * op = stmtDo (stmtQueueGet (args, 0), actBlock).eVal,
  242 + * ret;
  243 +
  244 + ret = castExprToString (op);
  245 +
  246 + if (op != NULL) expValueFree (op);
  247 +
  248 + return (u_stmtType) ret;
  249 +}
  250 +
  251 +static
  252 +inline
  253 + u_stmtType
  254 +stmtBlock (s_stmt * stmt, s_block * actBlock)
  255 +{
  256 + unsigned int i;
  257 +
  258 + s_stmtQueue * gIds = stmtQueueGet (stmt->sQueue, 0)->sQueue;
  259 + s_stmtQueue * args = stmtQueueGet (stmt->sQueue, 1)->sQueue;
  260 + s_block * gBlock = NULL;
  261 +
  262 + gBlock = actBlock = blockPush (&actBlock, blockNew (args));
  263 +
  264 + /* find the global block */
  265 + while (blockPrev (gBlock) != NULL)
  266 + gBlock = blockPrev (gBlock);
  267 +
  268 + if (gIds != NULL)
  269 + {
  270 + for (i = 0; i < stmtQueueGetSize (gIds); i++)
  271 + {
  272 + s_expVal * tmp = stmtDo (stmtQueueGet (gIds, i), actBlock).eVal;
  273 + char * _id;
  274 + s_ident * id;
  275 +
  276 + if (tmp == NULL)
  277 + exitError (0);
  278 +
  279 + _id = expValueString (tmp);
  280 + id = identListSeekKey (blockGetIdl (gBlock), _id);
  281 + expValueFree (tmp);
  282 + free (_id);
  283 +
  284 + if (id == NULL)
  285 + exitError (0);
  286 +
  287 + blockSetNonLocalId (args, id);
  288 + }
  289 + }
  290 +
  291 + blockDo (actBlock);
  292 + blockFree (actBlock);
  293 +
  294 + return (u_stmtType) 0;
  295 +}
  296 +
  297 +static
  298 +inline
  299 + u_stmtType
  300 +stmtIf (s_stmt * stmt, s_block * actBlock)
  301 +{
  302 + s_stmtQueue * args = stmt->sQueue;
  303 + int cond = stmtDo (stmtQueueGet (args, 0), actBlock).cond;
  304 + s_stmt * _do;
  305 +
  306 + if (cond)
  307 + _do = stmtQueueGet (args, 1);
  308 + else
  309 + _do = stmtQueueGet (args, 2);
  310 +
  311 + if (_do != NULL)
  312 + stmtDo (_do);
  313 +
  314 + return (u_stmtType) 0;
  315 +}
  316 +
  317 +static
  318 +inline
  319 + u_stmtType
  320 +stmtForeach (s_stmt * stmt, s_block * actBlock)
  321 +{
  322 + s_stmtQueue * args = stmt->sQueue;
  323 + s_expVal * _id = stmtDo (stmtQueueGet (args, 0), actBlock).eVal,
  324 + * _key = stmtDo (stmtQueueGet (args, 1), actBlock).eVal,
  325 + * _val = stmtDo (stmtQueueGet (args, 2), actBlock).eVal;
  326 + char * id = expValueString (_id);
  327 + char * key = expValueString (_key);
  328 + char * val = expValueString (_val);
  329 +
  330 + printf ("[DEBUG]found foreach statement: id=%s, key=%s, val=%s\n",
  331 + id, key, val);
  332 +
  333 + free (id);
  334 + free (key);
  335 + free (val);
  336 +
  337 + expValueFree (_id);
  338 + expValueFree (_key);
  339 + expValueFree (_val);
  340 +
  341 + return (u_stmtType) 0;
  342 +}
  343 +
  344 +static
  345 +inline
  346 + u_stmtType
  347 +stmtRepeat (s_stmt * stmt, s_block * actBlock)
  348 +{
  349 + s_stmtQueue * args = stmt->sQueue;
  350 + s_expVal * _id = stmtDo (stmtQueueGet (args, 0), actBlock).eVal,
  351 + * _count = stmtDo (stmtQueueGet (args, 1), actBlock).eVal;
  352 + char * id = expValueString (_id);
  353 + int count = expValueInt (_count);
  354 +
  355 + printf ("[DEBUG]found repeat statement: id=%s, count=%d\n", id, count);
  356 +
  357 + free (id);
  358 +
  359 + expValueFree (_id);
  360 + expValueFree (_count);
  361 +
  362 + return (u_stmtType) 0;
  363 +}
  364 +
  365 +/*
  366 + * Interface
  367 + */
  368 + s_stmt *
  369 +stmtNew (int id, s_stmtQueue * queue, int conTyp, u_stmtType con)
  370 +{
  371 + s_stmt * new = (s_stmt *) malloc (sizeof (s_stmt));
  372 +
  373 + new->sId = id;
  374 + new->sQueue = queue;
  375 + new->sConstTyp = conTyp;
  376 + new->sConst = con;
  377 +
  378 + return new;
  379 +}
  380 +
  381 + s_stmtQueue *
  382 +stmtGetArgs (s_stmt * stmt)
  383 +{
  384 + return stmt->sQueue;
  385 +}
  386 +
  387 + u_stmtType
  388 +stmtGetVal (s_stmt * stmt)
  389 +{
  390 + return stmt->sConst;
  391 +}
  392 +
  393 + int
  394 +stmtGetConstTyp (s_stmt * stmt)
  395 +{
  396 + return stmt->sConstTyp;
  397 +}
  398 +
  399 + void
  400 +stmtFree (s_stmt * stmt)
  401 +{
  402 + if (stmt == NULL)
  403 + return;
  404 +
  405 + switch (stmt->sConstTyp)
  406 + {
  407 + case STYP_NONE: stmtQueueFree (stmt->sQueue); break;
  408 + case STYP_EVAL: expValueFree (stmt->sConst.eVal); break;
  409 + case STYP_IDVAL: identFree (stmt->sConst.idVal); break;
  410 + }
  411 +
  412 + free (stmt);
  413 +}
  414 +
  415 + u_stmtType
  416 +stmtDo (s_stmt * stmt, s_block * actBlock)
  417 +{
  418 + if (stmt == NULL)
  419 + return (u_stmtType) 0;
  420 +
  421 + switch (stmt->sId)
  422 + {
  423 + case STMT_CONST: return (u_stmtType) expValueClone (stmt->sConst.eVal);
  424 + case STMT_BLOCK: return stmtBlock (stmt, actBlock);
  425 +
  426 + case STMT_PRINT: return stmtPrint (stmt, actBlock);
  427 + case STMT_IF: return stmtIf (stmt, actBlock);
  428 + case STMT_FOREACH: return stmtForeach (stmt, actBlock);
  429 + case STMT_REPEAT: return stmtRepeat (stmt, actBlock);
  430 + case STMT_ASSIGN: return stmtAssign (stmt, actBlock);
  431 + case STMT_UNSET: return (u_stmtType) 0;
  432 +
  433 + case STMT_EVAL_PLUS: return stmtEval (stmt, actBlock, PLUS);
  434 + case STMT_EVAL_MINUS: return stmtEval (stmt, actBlock, MINUS);
  435 + case STMT_EVAL_TIMES: return stmtEval (stmt, actBlock, TIMES);
  436 + case STMT_EVAL_OVER: return stmtEval (stmt, actBlock, OVER);
  437 + case STMT_EVAL_MODULO: return stmtEval (stmt, actBlock, MODULO);
  438 + case STMT_EVAL_NEG: return stmtEval (stmt, actBlock, NEG);
  439 +
  440 + case STMT_IDENT_VAR: return stmtIdentVar (stmt, actBlock);
  441 + case STMT_IDENT_ARRAY: return stmtIdentArray (stmt, actBlock);
  442 + case STMT_IDENT_VAL: return stmtIdentVal (stmt, actBlock);
  443 +
  444 + case STMT_CAST_INT: return stmtCastInt (stmt, actBlock);
  445 + case STMT_CAST_FLOAT: return stmtCastFloat (stmt, actBlock);
  446 + case STMT_CAST_STRING: return stmtCastString (stmt, actBlock);
  447 +
  448 + case STMT_COMP_EQ: return stmtEvalComp (stmt, actBlock, EQ);
  449 + case STMT_COMP_NE: return stmtEvalComp (stmt, actBlock, NE);
  450 + case STMT_COMP_LT: return stmtEvalComp (stmt, actBlock, LT);
  451 + case STMT_COMP_GT: return stmtEvalComp (stmt, actBlock, GT);
  452 + case STMT_COMP_LE: return stmtEvalComp (stmt, actBlock, LE);
  453 + case STMT_COMP_GE: return stmtEvalComp (stmt, actBlock, GE);
  454 +
  455 + case STMT_COND_EXPR: return stmtEvalCondExpr (stmt, actBlock);
  456 + case STMT_COND_AND: return stmtEvalCond (stmt, actBlock, LOGAND);
  457 + case STMT_COND_OR: return stmtEvalCond (stmt, actBlock, LOGOR);
  458 + case STMT_COND_NEG: return stmtEvalCond (stmt, actBlock, LOGNEG);
  459 + }
  460 +}
  1 +#include <malloc.h>
  2 +#include <string.h>
  3 +
  4 +#include <ident.h>
  5 +#include <statement.h>
  6 +#include <block.h>
  7 +
  8 +#include <stmtQueue.h>
  9 +
  10 +/* give the queue an initial size for 10 statements */
  11 +#define QUEUE_GROW_SIZE 10
  12 +
  13 +
  14 +struct stmtQueue
  15 +{
  16 + s_stmt ** stmts; /* a dynamically growing array of statements. */
  17 +
  18 + unsigned int size; /* the actual size of the array in statements */
  19 + unsigned int maxIdx; /* the maximum index used in the array. */
  20 +};
  21 +
  22 + s_stmtQueue *
  23 +stmtQueueNew (void)
  24 +{
  25 + s_stmtQueue * new = (s_stmtQueue *) malloc (sizeof (s_stmtQueue));
  26 +
  27 + new->size = QUEUE_GROW_SIZE;
  28 + new->maxIdx = 0;
  29 + new->stmts = (s_stmt **) calloc (sizeof (s_stmt *), new->size);
  30 + memset (new->stmts, 0, sizeof (s_stmt *) * new->size);
  31 +
  32 + return new;
  33 +}
  34 +
  35 +/*
  36 + * This concat does not change a or b, as opposed to the c strcat function
  37 + */
  38 + s_stmtQueue *
  39 +stmtQueueConcat (s_stmtQueue * a, s_stmtQueue * b)
  40 +{
  41 + s_stmtQueue * new = (s_stmtQueue *) malloc (sizeof (s_stmtQueue));
  42 +
  43 + new->size = a->size + b->size;
  44 + new->maxIdx = a->maxIdx + b->maxIdx;
  45 + new->stmts = (s_stmt **) calloc (sizeof (s_stmt *), new->size);
  46 + memset (new->stmts, 0, sizeof (s_stmt *) * new->size);
  47 +
  48 + memcpy (new->stmts, a->stmts, sizeof (s_stmt *) * a->maxIdx);
  49 + memcpy (&(new->stmts[a->maxIdx]), b->stmts, sizeof (s_stmt *) * b->maxIdx);
  50 +
  51 + return new;
  52 +}
  53 +
  54 + void
  55 +stmtQueueFree (s_stmtQueue * sQueue)
  56 +{
  57 + unsigned int i;
  58 +
  59 + if (sQueue == NULL)
  60 + return;
  61 +
  62 + /* freeing the queue is the final step. All stmts should be freed too! */
  63 + for (i = 0; i < sQueue->maxIdx; i++)
  64 + stmtFree (sQueue->stmts [i]);
  65 +
  66 + free (sQueue->stmts);
  67 + free (sQueue);
  68 +}
  69 +
  70 + void
  71 +stmtQueueEnqueue (s_stmtQueue * sQueue, s_stmt * stmt)
  72 +{
  73 + if (sQueue->maxIdx >= sQueue->size)
  74 + {
  75 + s_stmt ** stmtsOld = sQueue->stmts;
  76 + unsigned int newSize = sQueue->size + QUEUE_GROW_SIZE;
  77 +
  78 + sQueue->stmts = (s_stmt **) calloc (sizeof (s_stmt *), newSize);
  79 + memcpy (sQueue->stmts, stmtsOld, sizeof (s_stmt **) * sQueue->size);
  80 + free (stmtsOld); /* free the old queue but keep the statements */
  81 + memset (
  82 + &(sQueue->stmts[sQueue->size]),
  83 + 0,
  84 + sizeof (s_stmt **) * QUEUE_GROW_SIZE);
  85 + sQueue->size = newSize;;
  86 + }
  87 +
  88 + sQueue->stmts[sQueue->maxIdx ++] = stmt;
  89 +}
  90 +
  91 + s_stmt *
  92 +stmtQueueDequeue (s_stmtQueue * sQueue)
  93 +{
  94 + s_stmt * ret = sQueue->stmts[sQueue->maxIdx - 1];
  95 +
  96 + sQueue->stmts[-- sQueue->maxIdx] = NULL;
  97 +
  98 + return ret;
  99 +}
  100 +
  101 + s_stmt *
  102 +stmtQueueGet (s_stmtQueue * sQueue, unsigned int idx)
  103 +{
  104 + if (idx < sQueue->size)
  105 + return sQueue->stmts [idx];
  106 + else
  107 + return NULL;
  108 +}
  109 +
  110 + void
  111 +stmtQueueDo (s_stmtQueue * sQueue)
  112 +{
  113 + int i;
  114 +
  115 + if (sQueue == NULL)
  116 + return;
  117 +
  118 + for (i = 0; i < sQueue->maxIdx; i++)
  119 + stmtDo (sQueue->stmts[i]);
  120 +}
  121 +
  122 + unsigned
  123 + int
  124 +stmtQueueGetSize (s_stmtQueue * sQueue)
  125 +{
  126 + return sQueue->size;
  127 +}
  1 +#include <stdio.h>
  2 +#include <string.h>
  3 +#include <malloc.h>
  4 +#include <stdlib.h>
  5 +#include <stdarg.h>
  6 +
  7 +#include <tepal_pars.h>
  8 +#include <expValue.h>
  9 +#include <ident.h>
  10 +#include <tepal.h>
  11 +
  12 +char * tepalErrMsg[] =
  13 +{
  14 + "[ERROR] using uninitialized variable: %s\n",
  15 + "[ERROR] using array identifier without index: %s\n",
  16 + "[ERROR] unknown string operator: %c\n",
  17 + "[ERROR] unknown float operator: %c\n"
  18 +};
  19 +
  20 + void
  21 +exitError (int errNum, ...)
  22 +{
  23 + va_list ap;
  24 +
  25 + va_start (ap, errNum);
  26 +
  27 + switch (errNum)
  28 + {
  29 + case ERR_UNDEF_VAR:
  30 + fprintf (stderr, tepalErrMsg[errNum], va_arg(ap, char *));
  31 + break;
  32 +
  33 + case ERR_NO_INDEX:
  34 + fprintf (stderr, tepalErrMsg[errNum], va_arg(ap, char *));
  35 + break;
  36 +
  37 + case ERR_STRING_OPERATOR:
  38 + fprintf (stderr, tepalErrMsg[errNum], va_arg(ap, int));
  39 + break;
  40 +
  41 + case ERR_FLOAT_OPERATOR:
  42 + fprintf (stderr, tepalErrMsg[errNum], va_arg(ap, int));
  43 + break;
  44 + }
  45 +
  46 + va_end (ap);
  47 + exit (errNum);
  48 +}
  49 +
  50 +void
  51 +printExpr (s_expVal * val)
  52 +{
  53 + switch (expValueGetType (val))
  54 + {
  55 + case EXP_TYP_INT: printf ("%d", expValueInt (val)); break;
  56 + case EXP_TYP_FLOAT: printf ("%f", expValueFloat (val)); break;
  57 + case EXP_TYP_STRING:
  58 + {
  59 + char * v = expValueString (val);
  60 + printf (v);
  61 + free (v);
  62 + }
  63 + }
  64 +}
  65 +
  1 +%{
  2 +#include <malloc.h>
  3 +#include <string.h>
  4 +#include <stdio.h>
  5 +#include <stdlib.h>
  6 +
  7 +#include <tepal.h>
  8 +#include <evalCond.h>
  9 +#include <evalExpr.h>
  10 +#include <ident.h>
  11 +#include <identList.h>
  12 +#include <expValue.h>
  13 +#include <assign.h>
  14 +#include <variable.h>
  15 +#include <cast.h>
  16 +#include <stmtQueue.h>
  17 +#include <statement.h>
  18 +
  19 +extern int yylex (void);
  20 +
  21 + int
  22 +yywrap ()
  23 +{
  24 + return 1;
  25 +}
  26 +
  27 + void
  28 +yyerror (char const * s)
  29 +{
  30 + fprintf(stderr, "%s\n", s);
  31 +}
  32 +
  33 +/*
  34 + * globale Variablen
  35 + */
  36 +extern FILE * yyin;
  37 +extern s_block * _globalBlock_;
  38 +
  39 +s_stmtQueue * astRoot;
  40 +
  41 +/*
  42 + * statische Funktionen (zum lokalen gebrauch)
  43 + */
  44 +static
  45 +inline
  46 + s_stmtQueue *
  47 +enqStmt (s_stmtQueue * sQueue, s_stmt * stmt)
  48 +{
  49 + s_stmtQueue * ret = (sQueue == NULL) ? stmtQueueNew () : sQueue;
  50 +
  51 + stmtQueueEnqueue (ret, stmt);
  52 + return ret;
  53 +}
  54 +
  55 +static
  56 +inline
  57 + s_stmtQueue *
  58 +enqGlobId (s_stmtQueue * sQueue, char * id)
  59 +{
  60 + s_stmtQueue * ret = (sQueue == NULL) ? stmtQueueNew () : sQueue;
  61 + s_stmt * val = stmtNew (STMT_CONST, NULL, STYP_EVAL, (u_stmtType) id);
  62 +
  63 + stmtQueueEnqueue (ret, id);
  64 +
  65 + return ret;
  66 +}
  67 +
  68 +static
  69 +inline
  70 + s_stmtQueue *
  71 +genBlockQue (s_stmtQueue * _gI, s_stmtQueue * _st)
  72 +{
  73 + s_stmtQueue * ret = stmtQueueNew ();
  74 + s_stmt * gIds = stmtNew (STMT_BLOCK, _gI, STYP_NONE, (u_stmtType) 0);
  75 + s_stmt * stmts = stmtNew (STMT_BLOCK, _st, STYP_NONE, (u_stmtType) 0);
  76 +
  77 + stmtQueueEnqueue (ret, gIds);
  78 + stmtQueueEnqueue (ret, stmts);
  79 +
  80 + return ret;
  81 +}
  82 +
  83 +static
  84 +inline
  85 + s_stmt *
  86 +genIntStmt (long iVal)
  87 +{
  88 + return stmtNew (
  89 + STMT_CONST,
  90 + NULL,
  91 + STYP_EVAL,
  92 + (u_stmtType) expValueIntNew (iVal));
  93 +}
  94 +
  95 +static
  96 +inline
  97 + s_stmt *
  98 +genFloatStmt (double fVal)
  99 +{
  100 + return stmtNew (
  101 + STMT_CONST,
  102 + NULL,
  103 + STYP_EVAL,
  104 + (u_stmtType) expValueFloatNew (fVal));
  105 +}
  106 +
  107 +static
  108 +inline
  109 + s_stmt *
  110 +genStringStmt (s_stmt * stmt, char * string)
  111 +{
  112 + s_stmt * ret = NULL;
  113 + s_expVal * eVal = NULL;
  114 +
  115 + char * new = NULL;
  116 +
  117 + if (stmt != NULL)
  118 + {
  119 + char * old = expValueString (stmtGetVal (stmt).eVal);
  120 + size_t len = strlen (old) + strlen (string) + 1;
  121 +
  122 + new = (char *) calloc (sizeof (char), len);
  123 + strcpy (new, old);
  124 + strcat (new, string);
  125 +
  126 + stmtFree (stmt);
  127 + free (old);
  128 + }
  129 + else
  130 + {
  131 + new = (char *)calloc (sizeof (char), strlen (string) + 1);
  132 + strcpy (new, string);
  133 + }
  134 +
  135 + eVal = expValueStringNew (new);
  136 + ret = stmtNew (STMT_CONST, NULL, STYP_EVAL, (u_stmtType) eVal);
  137 + free (new);
  138 +
  139 + free (string);
  140 +
  141 + return ret;
  142 +}
  143 +
  144 +static
  145 +inline
  146 + s_stmt *
  147 +genBlockStmt (s_stmtQueue * sQueue)
  148 +{
  149 + return stmtNew (STMT_BLOCK, sQueue, STYP_NONE, (u_stmtType) 0);
  150 +}
  151 +
  152 +static
  153 +inline
  154 + s_stmt *
  155 +genPrintStmt (s_stmt * stmt)
  156 +{
  157 + s_stmtQueue * sQueue = stmtQueueNew ();
  158 +
  159 + stmtQueueEnqueue (sQueue, stmt);
  160 + return stmtNew (STMT_PRINT, sQueue, STYP_NONE, (u_stmtType) 0);
  161 +}
  162 +
  163 +static
  164 +inline
  165 + s_stmt *
  166 +genIfStmt (s_stmt * cond, s_stmt * _then, s_stmt * _else)
  167 +{
  168 + s_stmtQueue * sQueue = stmtQueueNew ();
  169 +
  170 + stmtQueueEnqueue (sQueue, cond);
  171 + stmtQueueEnqueue (sQueue, _then);
  172 + stmtQueueEnqueue (sQueue, _else);
  173 +
  174 + return stmtNew (STMT_IF, sQueue, STYP_NONE, (u_stmtType) 0);
  175 +}
  176 +
  177 +static
  178 +inline
  179 + s_stmt *
  180 +genRepStmt (char * _ident, long _count, s_stmt * stmt)
  181 +{
  182 + u_stmtType _id = (u_stmtType) expValueStringNew (_ident);
  183 + u_stmtType _co = (u_stmtType) expValueIntNew (_count);
  184 + s_stmt * ident = stmtNew (STMT_CONST, NULL, STYP_EVAL, _id);
  185 + s_stmt * count = stmtNew (STMT_CONST, NULL, STYP_EVAL, _co);
  186 +
  187 + s_stmtQueue * sQueue = stmtQueueNew ();
  188 +
  189 + free (_ident);
  190 +
  191 + stmtQueueEnqueue (sQueue, ident);
  192 + stmtQueueEnqueue (sQueue, count);
  193 + stmtQueueEnqueue (sQueue, stmt);
  194 +
  195 + return stmtNew (STMT_REPEAT, sQueue, STYP_NONE, (u_stmtType) 0);
  196 +}
  197 +
  198 +static
  199 +inline
  200 + s_stmt *
  201 +genForeStmt (char * _ident, char * _key, char * _val, s_stmt * stmt)
  202 +{
  203 + u_stmtType _id = (u_stmtType) expValueStringNew (_ident);
  204 + u_stmtType _k = (u_stmtType) expValueStringNew (_key);
  205 + u_stmtType _v = (u_stmtType) expValueStringNew (_val);
  206 + s_stmt * ident = stmtNew (STMT_CONST, NULL, STYP_EVAL, _id);
  207 + s_stmt * key = stmtNew (STMT_CONST, NULL, STYP_EVAL, _k);
  208 + s_stmt * val = stmtNew (STMT_CONST, NULL, STYP_EVAL, _v);
  209 +
  210 + s_stmtQueue * sQueue = stmtQueueNew ();
  211 +
  212 + free (_ident);
  213 + free (_key);
  214 + free (_val);
  215 +
  216 + stmtQueueEnqueue (sQueue, ident);
  217 + stmtQueueEnqueue (sQueue, key);
  218 + stmtQueueEnqueue (sQueue, val);
  219 + stmtQueueEnqueue (sQueue, stmt);
  220 +
  221 + return stmtNew (STMT_FOREACH, sQueue, STYP_NONE, (u_stmtType) 0);
  222 +}
  223 +
  224 +static
  225 +inline
  226 + s_stmt *
  227 +genCondExprStmt (s_stmt * stmt)
  228 +{
  229 + s_stmtQueue * sQueue = stmtQueueNew ();
  230 +
  231 + stmtQueueEnqueue (sQueue, stmt);
  232 + return stmtNew (STMT_COND_EXPR, sQueue, STYP_NONE, (u_stmtType) 0);
  233 +}
  234 +
  235 +static
  236 +inline
  237 + s_stmt *
  238 +genOpStmt (int op, s_stmt * op1, s_stmt * op2)
  239 +{
  240 + s_stmtQueue * sQueue = stmtQueueNew ();
  241 + int stmtId;
  242 +
  243 + stmtQueueEnqueue (sQueue, op1);
  244 + stmtQueueEnqueue (sQueue, op2);
  245 +
  246 + switch (op)
  247 + {
  248 + case LOGNEG: stmtId = STMT_COND_NEG; break;
  249 + case LOGAND: stmtId = STMT_COND_AND; break;
  250 + case LOGOR: stmtId = STMT_COND_OR; break;
  251 + case EQ: stmtId = STMT_COMP_EQ; break;
  252 + case NE: stmtId = STMT_COMP_NE; break;
  253 + case LT: stmtId = STMT_COMP_LT; break;
  254 + case GT: stmtId = STMT_COMP_GT; break;
  255 + case LE: stmtId = STMT_COMP_LE; break;
  256 + case GE: stmtId = STMT_COMP_GE; break;
  257 + case NEG: stmtId = STMT_EVAL_NEG; break;
  258 + case PLUS: stmtId = STMT_EVAL_PLUS; break;
  259 + case MINUS: stmtId = STMT_EVAL_MINUS; break;
  260 + case TIMES: stmtId = STMT_EVAL_TIMES; break;
  261 + case OVER: stmtId = STMT_EVAL_OVER; break;
  262 + case MODULO: stmtId = STMT_EVAL_MODULO; break;
  263 + }
  264 +
  265 + return stmtNew (stmtId, sQueue, STYP_NONE, (u_stmtType) 0);
  266 +}
  267 +
  268 +static
  269 +inline
  270 + s_stmt *
  271 +genAssignStmt (s_stmt * var, s_stmt * val)
  272 +{
  273 + s_stmtQueue * sQueue = stmtQueueNew ();
  274 +
  275 + stmtQueueEnqueue (sQueue, var);
  276 + stmtQueueEnqueue (sQueue, val);
  277 +
  278 + return stmtNew (STMT_ASSIGN, sQueue, STYP_NONE, (u_stmtType) 0);
  279 +}
  280 +
  281 +static
  282 +inline
  283 + s_stmt *
  284 +genIdMkGlobStmt (s_stmtQueue * sQueue)
  285 +{
  286 + return stmtNew (/*another ID here*/STMT_BLOCK,
  287 + sQueue, STYP_NONE, (u_stmtType) 0);
  288 +}
  289 +
  290 +static
  291 +inline
  292 + s_stmt *
  293 +genIdentVarStmt (char * _ident)
  294 +{
  295 + u_stmtType _id = (u_stmtType) expValueStringNew (_ident);
  296 + s_stmt * ident = stmtNew (STMT_CONST, NULL, STYP_EVAL, _id);
  297 +
  298 + s_stmtQueue * sQueue = stmtQueueNew ();
  299 +
  300 + free (_ident);
  301 +
  302 + stmtQueueEnqueue (sQueue, ident);
  303 + return stmtNew (STMT_IDENT_VAR, sQueue, STYP_NONE, (u_stmtType) 0);
  304 +}
  305 +
  306 +static
  307 +inline
  308 + s_stmt *
  309 +genIdentArrStmt (s_stmt * base, s_stmt * idx)
  310 +{
  311 + s_stmtQueue * sQueue = stmtQueueNew ();
  312 +
  313 + stmtQueueEnqueue (sQueue, base);
  314 + stmtQueueEnqueue (sQueue, idx);
  315 +
  316 + return stmtNew (STMT_IDENT_ARRAY, sQueue, STYP_NONE, (u_stmtType) 0);
  317 +}
  318 +
  319 +static
  320 +inline
  321 + s_stmt *
  322 +genIdentValStmt (s_stmt * stmt)
  323 +{
  324 + s_stmtQueue * sQueue = stmtQueueNew ();
  325 +
  326 + stmtQueueEnqueue (sQueue, stmt);
  327 + return stmtNew (STMT_IDENT_VAL, sQueue, STYP_NONE, (u_stmtType) 0);
  328 +}
  329 +
  330 +static
  331 +inline
  332 + s_stmt *
  333 +genCastIntStmt (s_stmt * stmt)
  334 +{
  335 + s_stmtQueue * sQueue = stmtQueueNew ();
  336 +
  337 + stmtQueueEnqueue (sQueue, stmt);
  338 + return stmtNew (STMT_CAST_INT, sQueue, STYP_NONE, (u_stmtType) 0);
  339 +}
  340 +
  341 +static
  342 +inline
  343 + s_stmt *
  344 +genCastFloatStmt (s_stmt * stmt)
  345 +{
  346 + s_stmtQueue * sQueue = stmtQueueNew ();
  347 +
  348 + stmtQueueEnqueue (sQueue, stmt);
  349 + return stmtNew (STMT_CAST_FLOAT, sQueue, STYP_NONE, (u_stmtType) 0);
  350 +}
  351 +
  352 +static
  353 +inline
  354 + s_stmt *
  355 +genCastStringStmt (s_stmt * stmt)
  356 +{
  357 + s_stmtQueue * sQueue = stmtQueueNew ();
  358 +
  359 + stmtQueueEnqueue (sQueue, stmt);
  360 + return stmtNew (STMT_CAST_STRING, sQueue, STYP_NONE, (u_stmtType) 0);
  361 +}
  362 +
  363 +%}
  364 +
  365 +%token STMT_END ';' REPEAT COUNT FOREACH AS IF ELSE BLOCK_END UNSET
  366 +%token ICAST FCAST SCAST GLOBAL /* for explicit casts */
  367 +%token <cPtr> IDENT
  368 +%token <cPtr> HTML
  369 +%token <iVal> INT
  370 +%token <fVal> FLOAT
  371 +%token <cPtr> STRING
  372 +%token <cPtr> EOL
  373 +
  374 +%left LOGAND LOGOR
  375 +%left LOGNEG
  376 +%nonassoc NE EQ LT GT LE GE
  377 +
  378 +%right '='
  379 +%left '+' '-'
  380 +%left '*' '/' '%'
  381 +%left NEG
  382 +%nonassoc '(' ')'
  383 +
  384 +%union {
  385 + long iVal;
  386 + double fVal;
  387 + char * cPtr;
  388 + struct stmt * stmt;
  389 + struct stmtQueue * sQue;
  390 +}
  391 +
  392 +/* Es wird wohl darauf hinauslaufen das alles erstmal ein stmt wird
  393 + und in den AST wandert, und erst dann ausgewertet wird. Anders
  394 + wird es wohl nicht gehen. */
  395 +%type <stmt> assig;
  396 +%type <stmt> ident;
  397 +%type <stmt> cond;
  398 +%type <stmt> comp;
  399 +%type <stmt> expr;
  400 +%type <stmt> html;
  401 +%type <stmt> block_stmt;
  402 +%type <stmt> gdecl_block;
  403 +%type <stmt> simple_stmt;
  404 +%type <stmt> if_stmt;
  405 +%type <stmt> rep_stmt;
  406 +%type <stmt> fore_stmt;
  407 +%type <stmt> stmt;
  408 +%type <sQue> stmt_queue;
  409 +%type <sQue> block_queue;
  410 +%type <sQue> glob_decl;
  411 +
  412 +%expect 1
  413 +
  414 +%start script
  415 +
  416 +%%
  417 +
  418 +script : stmt_queue { astRoot = $1; }
  419 +;
  420 +
  421 +stmt_queue : stmt { $$ = enqStmt (NULL, $1); }
  422 + | stmt_queue stmt { $$ = enqStmt ($1, $2); }
  423 +;
  424 +
  425 +stmt : simple_stmt
  426 + | block_stmt
  427 + | if_stmt
  428 + | rep_stmt
  429 + | fore_stmt
  430 + | stmt_end stmt { $$ = $2; }
  431 +;
  432 +
  433 +simple_stmt : html stmt_end { $$ = genPrintStmt ($1); }
  434 + | expr stmt_end { $$ = genPrintStmt ($1); }
  435 + | assig stmt_end
  436 +;
  437 +
  438 +html : HTML { $$ = genStringStmt (NULL, $1); }
  439 + | html HTML { $$ = genStringStmt ($1, $2); }
  440 +;
  441 +
  442 +stmt_end : STMT_END
  443 + | ';'
  444 +;
  445 +
  446 +block_stmt : ':' BLOCK_END { $$ = genBlockStmt (NULL); }
  447 + | ':' block_queue BLOCK_END { $$ = genBlockStmt ($2); }
  448 +;
  449 +
  450 +block_queue : stmt_queue { $$ = genBlockQue (NULL, $1); }
  451 + | gdecl_block stmt_queue { $$ = genBlockQue ($1, $2); }
  452 +;
  453 +
  454 +/*
  455 + * Here follows the definitions for the "globals definition block"
  456 + * This is more complicated than first guessed, because these are no
  457 + * normal statements as all other constructs are. Escpecially in those
  458 + * block a newline should not be interpreted as statmend-end.
  459 + * ------
  460 + */
  461 +gdecl_block : GLOBAL ':' glob_decl BLOCK_END
  462 + { $$ = $3); }
  463 +;
  464 +
  465 +glob_decl : IDENT { $$ = enqGlobId (NULL, $1); }
  466 + | glob_decl ',' IDENT { $$ = enqGlobId ($1, $3); }
  467 +;
  468 +/*
  469 + * ------
  470 + */
  471 +
  472 +/* here is 1 shift/reduce conflict, but thats ok. */
  473 +if_stmt : IF '(' cond ')' stmt { $$ = genIfStmt ($3, $5, NULL); }
  474 + | IF '(' cond ')' stmt ELSE stmt
  475 + { $$ = genIfStmt ($3, $5, $7); }
  476 +;
  477 +
  478 +rep_stmt : REPEAT '(' IDENT COUNT '=' INT ')' stmt
  479 + { $$ = genRepStmt ($3, $6, $8); }
  480 +;
  481 +
  482 +fore_stmt : FOREACH '(' IDENT AS IDENT ',' IDENT ')' stmt
  483 + { $$ = genForeStmt ($3, $5, $7, $9); }
  484 +;
  485 +
  486 +cond : expr { $$ = genCondExprStmt ($1); }
  487 + | comp { $$ = $1; }
  488 + | '(' comp ')' { $$ = $2; }
  489 + | '!' cond %prec LOGNEG { $$ = genOpStmt (LOGNEG, $2, NULL); }
  490 + | '(' '!' cond ')' %prec LOGNEG
  491 + { $$ = genOpStmt (LOGNEG, $3, NULL); }
  492 + | cond LOGAND cond { $$ = genOpStmt (LOGAND, $1, $3); }
  493 + | '(' cond LOGAND cond ')' { $$ = genOpStmt (LOGAND, $2, $4); }
  494 + | cond LOGOR cond { $$ = genOpStmt (LOGOR, $1, $3); }
  495 + | '(' cond LOGOR cond ')' { $$ = genOpStmt (LOGOR, $2, $4); }
  496 +;
  497 +
  498 +comp : expr EQ expr { $$ = genOpStmt (EQ, $1, $3); }
  499 + | expr NE expr { $$ = genOpStmt (NE, $1, $3); }
  500 + | expr LT expr { $$ = genOpStmt (LT, $1, $3); }
  501 + | expr GT expr { $$ = genOpStmt (GT, $1, $3); }
  502 + | expr LE expr { $$ = genOpStmt (LE, $1, $3); }
  503 + | expr GE expr { $$ = genOpStmt (GE, $1, $3); }
  504 +;
  505 +
  506 +assig : ident '=' expr { $$ = genAssignStmt ($1, $3); }
  507 + | ident '=' assig { $$ = genAssignStmt ($1, $3); }
  508 +;
  509 +
  510 +ident : IDENT { $$ = genIdentVarStmt ($1); }
  511 + | ident '[' expr ']' { $$ = genIdentArrStmt ($1, $3); }
  512 +;
  513 +
  514 +expr : ident { $$ = genIdentValStmt ($1); }
  515 + | INT { $$ = genIntStmt ($1); }
  516 + | FLOAT { $$ = genFloatStmt ($1); }
  517 + | STRING { $$ = genStringStmt (NULL, $1); }
  518 + | EOL { $$ = genStringStmt (NULL, $1); }
  519 +
  520 + | '(' ICAST ')' expr { $$ = genCastIntStmt ($4); }
  521 + | '(' FCAST ')' expr { $$ = genCastFloatStmt ($4); }
  522 + | '(' SCAST ')' expr { $$ = genCastStringStmt ($4); }
  523 + | '(' expr ')' { $$ = $2; }
  524 +
  525 + | '-' expr %prec NEG { $$ = genOpStmt (NEG, $2, NULL); }
  526 + | expr '+' expr { $$ = genOpStmt (PLUS, $1, $3); }
  527 + | expr '-' expr { $$ = genOpStmt (MINUS, $1, $3); }
  528 + | expr '*' expr { $$ = genOpStmt (TIMES, $1, $3); }
  529 + | expr '/' expr { $$ = genOpStmt (OVER, $1, $3); }
  530 + | expr '%' expr { $$ = genOpStmt (MODULO, $1, $3); }
  531 +;
  532 +
  533 +%%
  534 +
  535 +int
  536 +main (int argc, void * argv [])
  537 +{
  538 + if (argc >= 2)
  539 + {
  540 + if ((yyin = fopen (argv[1], "r")) == NULL)
  541 + {
  542 + fprintf (stderr, "Could not open input file: %s\n", argv[1]);
  543 + fprintf (stderr, "Using stdin\n");
  544 + yyin = stdin;
  545 + }
  546 + }
  547 + /*
  548 + * normally we would read from stdin if no file is given but for
  549 + * demonstration purpose we read a file from a standard location.
  550 + */
  551 + else
  552 + {
  553 + if ((yyin = fopen ("/var/www/localhost/tpl/index.tpl", "r")) == NULL)
  554 + {
  555 + fprintf (stderr, "Could not open input file: %s\n", argv[1]);
  556 + fprintf (stderr, "Using stdin\n");
  557 + yyin = stdin;
  558 + }
  559 + }
  560 +
  561 + printf ("Content-type: text/html\n\n");
  562 +
  563 + astRoot = NULL;
  564 + yyparse ();
  565 +
  566 + _globalBlock_ = blockNew (astRoot);
  567 +
  568 + blockDo (_globalBlock_);
  569 +
  570 + if (_globalBlock_ != NULL);
  571 + blockFree (_globalBlock_);
  572 +
  573 + if (argc >= 2)
  574 + fclose (yyin);
  575 +}
  1 +%{
  2 +#include <malloc.h>
  3 +#include <string.h>
  4 +#include <stdlib.h>
  5 +
  6 +#include <tepal_pars.h>
  7 +%}
  8 +
  9 +%x TOK
  10 +
  11 +DIGITS [0-9]+
  12 +INT {DIGITS}
  13 +FLOAT {DIGITS}(.{DIGITS})?
  14 +STRING ('[^']*')|(\"[^\"]*\")
  15 +IDENT [a-zA-Z][_0-9a-zA-Z]*|_[0-9a-zA-Z]+
  16 +OPERATOR [+\-*/%=,!:\[\]\(\);]
  17 +
  18 +ICAST int
  19 +FCAST float
  20 +SCAST string
  21 +
  22 +S_TOK [ \t]*<#
  23 +E_TOK #>
  24 +TEXT (\<[^#].*)|([^\<]*)
  25 +
  26 +%%
  27 +
  28 +{TEXT} {
  29 + char tok[2];
  30 + size_t len = strlen (yytext);
  31 +
  32 + yylval.cPtr = (char *) malloc (len + 2);
  33 + memset (yylval.cPtr, 0, len + 2);
  34 + memcpy (yylval.cPtr, yytext, len);
  35 +
  36 + tok[0] = input ();
  37 + tok[1] = input ();
  38 +
  39 + if (tok[1] == '#' || tok[0] == EOF)
  40 + {
  41 + unput ('#');
  42 + unput ('<');
  43 + }
  44 + else
  45 + {
  46 + if (tok[1] != EOF)
  47 + unput (tok[1]);
  48 + yylval.cPtr[len] = tok[0];
  49 + }
  50 +
  51 + #ifdef DEBUG
  52 + printf ("[TOKEN] HTML\n");
  53 + #endif
  54 +
  55 + return HTML;
  56 + }
  57 +
  58 +{S_TOK} {
  59 + BEGIN (TOK);
  60 + #ifdef DEBUG
  61 + printf ("[TOKEN] STMT_END {[ \\t]*<#}\n");
  62 + #endif
  63 + return STMT_END;
  64 + }
  65 +
  66 +<TOK>{E_TOK}\n? {
  67 + BEGIN (INITIAL);
  68 +
  69 + #ifdef DEBUG
  70 + printf ("[TOKEN] STMT_END {#>\\n?}\n");
  71 + #endif
  72 +
  73 + return STMT_END;
  74 + }
  75 +
  76 +<TOK>{OPERATOR} {
  77 + #ifdef DEBUG
  78 + printf ("[TOKEN] %c\n", yytext[0]);
  79 + #endif
  80 + yylval.iVal = yytext[0];
  81 + return yytext[0];
  82 + }
  83 +
  84 +<TOK>== {
  85 + #ifdef DEBUG
  86 + printf ("[TOKEN] EQ\n");
  87 + #endif
  88 +
  89 + return EQ;
  90 + }
  91 +<TOK>!= {
  92 + #ifdef DEBUG
  93 + printf ("[TOKEN] NE\n");
  94 + #endif
  95 +
  96 + return NE;
  97 + }
  98 +<TOK>\< {
  99 + #ifdef DEBUG
  100 + printf ("[TOKEN] EQ\n");
  101 + #endif
  102 +
  103 + return LT;
  104 + }
  105 +<TOK>\> {
  106 + #ifdef DEBUG
  107 + printf ("[TOKEN] EQ\n");
  108 + #endif
  109 +
  110 + return GT;
  111 + }
  112 +<TOK>\<= {
  113 + #ifdef DEBUG
  114 + printf ("[TOKEN] EQ\n");
  115 + #endif
  116 +
  117 + return LE;
  118 + }
  119 +<TOK>\>= {
  120 + #ifdef DEBUG
  121 + printf ("[TOKEN] EQ\n");
  122 + #endif
  123 +
  124 + return GE;
  125 + }
  126 +
  127 +<TOK>&& {
  128 + #ifdef DEBUG
  129 + printf ("[TOKEN] LOGAND\n");
  130 + #endif
  131 +
  132 + return LOGAND;
  133 + }
  134 +<TOK>\|\| {
  135 + #ifdef DEBUG
  136 + printf ("[TOKEN] LOGOR\n");
  137 + #endif
  138 +
  139 + return LOGOR;
  140 + }
  141 +
  142 +<TOK>{INT} {
  143 + yylval.iVal = atol (yytext);
  144 +
  145 + #ifdef DEBUG
  146 + printf ("[TOKEN] INT\n");
  147 + #endif
  148 +
  149 + return INT;
  150 + }
  151 +
  152 +<TOK>{FLOAT} {
  153 + yylval.fVal = atof (yytext);
  154 +
  155 + #ifdef DEBUG
  156 + printf ("[TOKEN] FLOAT\n");
  157 + #endif
  158 +
  159 + return FLOAT;
  160 + }
  161 +
  162 +<TOK>{STRING} {
  163 + yylval.cPtr = (char *) malloc (strlen (yytext) - 1);
  164 + memset (yylval.cPtr, 0, strlen (yytext) - 1);
  165 + memcpy (yylval.cPtr, yytext + 1, strlen (yytext) - 2);
  166 +
  167 + #ifdef DEBUG
  168 + printf ("[TOKEN] STRING\n");
  169 + #endif
  170 +
  171 + return STRING;
  172 + }
  173 +
  174 +<TOK>repeat {
  175 + #ifdef DEBUG
  176 + printf ("[TOKEN] REPEAT\n");
  177 + #endif
  178 +
  179 + return REPEAT;
  180 + }
  181 +<TOK>count {
  182 + #ifdef DEBUG
  183 + printf ("[TOKEN] COUNT\n");
  184 + #endif
  185 +
  186 + return COUNT;
  187 + }
  188 +
  189 +<TOK>foreach {
  190 + #ifdef DEBUG
  191 + printf ("[TOKEN] FOREACH\n");
  192 + #endif
  193 +
  194 + return FOREACH;
  195 + }
  196 +<TOK>as {
  197 + #ifdef DEBUG
  198 + printf ("[TOKEN] AS\n");
  199 + #endif
  200 +
  201 + return AS;
  202 + }
  203 +
  204 +<TOK>if {
  205 + #ifdef DEBUG
  206 + printf ("[TOKEN] IF\n");
  207 + #endif
  208 +
  209 + return IF;
  210 + }
  211 +<TOK>else {
  212 + #ifdef DEBUG
  213 + printf ("[TOKEN] ELSE\n");
  214 + #endif
  215 +
  216 + return ELSE;
  217 + }
  218 +
  219 +<TOK>end {
  220 + #ifdef DEBUG
  221 + printf ("[TOKEN] BLOCK_END\n");
  222 + #endif
  223 +
  224 + return BLOCK_END;
  225 + }
  226 +
  227 +<TOK>unset {
  228 + #ifdef DEBUG
  229 + printf ("[TOKEN] UNSET\n");
  230 + #endif
  231 +
  232 + return UNSET;
  233 + }
  234 +
  235 +<TOK>eol {
  236 + yylval.cPtr = (char *) calloc (sizeof (char), 2);
  237 + yylval.cPtr[0] = '\n';
  238 + yylval.cPtr[1] = '\0';
  239 + #ifdef DEBUG
  240 + printf ("[TOKEN] EOL\n");
  241 + #endif
  242 +
  243 + return EOL;
  244 + }
  245 +
  246 +<TOK>parent {
  247 + #ifdef DEBUG
  248 + printf ("[TOKEN] PARENT\n");
  249 + #endif
  250 +
  251 + return PARENT;
  252 + }
  253 +
  254 +<TOK>global {
  255 + #ifdef DEBUG
  256 + printf ("[TOKEN] GLOBAL\n");
  257 + #endif
  258 +
  259 + return GLOBAL;
  260 + }
  261 +
  262 +<TOK>{ICAST} {
  263 + #ifdef DEBUG
  264 + printf ("[TOKEN] ICAST\n");
  265 + #endif
  266 +
  267 + return ICAST;
  268 + }
  269 +<TOK>{FCAST} {
  270 + #ifdef DEBUG
  271 + printf ("[TOKEN] FCAST\n");
  272 + #endif
  273 +
  274 + return FCAST;
  275 + }
  276 +<TOK>{SCAST} {
  277 + #ifdef DEBUG
  278 + printf ("[TOKEN] SCAST\n");
  279 + #endif
  280 +
  281 + return SCAST;
  282 + }
  283 +
  284 +<TOK>{IDENT} {
  285 + yylval.cPtr = (char *) malloc (strlen (yytext) + 1);
  286 + strcpy (yylval.cPtr, yytext);
  287 +
  288 + #ifdef DEBUG
  289 + printf ("[TOKEN] IDENT\n");
  290 + #endif
  291 +
  292 + return IDENT;
  293 + }
  294 +
  295 +<TOK>[ \t\r\n] { /* eat tokens */ }
  1 +#include <stdio.h>
  2 +#include <malloc.h>
  3 +
  4 +#include <ident.h>
  5 +#include <expValue.h>
  6 +#include <variable.h>
  7 +#include <identList.h>
  8 +
  9 +
  10 + s_ident *
  11 +getVariable (identList * iList, char * id)
  12 +{
  13 + return identListSeekKey (iList, id);
  14 +}
  15 +
  16 + s_ident *
  17 +getArray (s_ident * var, s_expVal * eVal)
  18 +{
  19 + s_ident * ret = NULL;
  20 +
  21 + /* generate new idl if ident isn't, discard prev val */
  22 + if (identGetType (var) != ID_TYP_IDL)
  23 + identSetIdl (var, identListNew (NULL));
  24 +
  25 + /* now seek or generate the actual ident */
  26 + switch (expValueGetType (eVal))
  27 + {
  28 + case EXP_TYP_INT:
  29 + {
  30 + int idx = expValueInt (eVal);
  31 +
  32 + ret = identListSeekIdx (identIdl (var), idx);
  33 +
  34 + if (ret == NULL)
  35 + ret = identListPutVal (
  36 + identIdl (var), identUndefNew (idx, NULL));
  37 +
  38 + break;
  39 + }
  40 +
  41 + case EXP_TYP_STRING:
  42 + {
  43 + char * key = expValueString (eVal);
  44 +
  45 + ret = identListSeekKey (identIdl (var), key);
  46 +
  47 + if (ret == NULL)
  48 + ret = identListPutVal (
  49 + identIdl (var), identUndefNew (-1, key));
  50 +
  51 + free (key);
  52 + }
  53 + }
  54 +
  55 + return ret;
  56 +}
Please register or login to post a comment