Logo Search packages:      
Sourcecode: ksh version File versions  Download package

excc.c

/***********************************************************************
*                                                                      *
*               This software is part of the ast package               *
*          Copyright (c) 1989-2007 AT&T Intellectual Property          *
*                      and is licensed under the                       *
*                  Common Public License, Version 1.0                  *
*                    by AT&T Intellectual Property                     *
*                                                                      *
*                A copy of the License is available at                 *
*            http://www.opensource.org/licenses/cpl1.0.txt             *
*         (with md5 checksum 059e8cd6165cb4c31e351f2b69388fd9)         *
*                                                                      *
*              Information and Software Systems Research               *
*                            AT&T Research                             *
*                           Florham Park NJ                            *
*                                                                      *
*                 Glenn Fowler <gsf@research.att.com>                  *
*                                                                      *
***********************************************************************/
#pragma prototyped
/*
 * Glenn Fowler
 * AT&T Research
 *
 * expression library C program generator
 */

#define _EX_CC_PRIVATE_ \
      char*       id;         /* prefix + _                 */ \
      int         lastop;           /* last op              */ \
      int         tmp;        /* temp var index       */ \
      Exccdisc_t* ccdisc;           /* excc() discipline          */

#include "exlib.h"

#define EX_CC_DUMP      0x8000

static const char quote[] = "\"";

static void       gen(Excc_t*, Exnode_t*);

/*
 * return C name for op
 */

static char*
opname(int op)
{
      static char buf[16];

      switch (op)
      {
      case '!':
            return "!";
      case '%':
            return "%";
      case '&':
            return "&";
      case '(':
            return "(";
      case '*':
            return "*";
      case '+':
            return "+";
      case ',':
            return ",";
      case '-':
            return "-";
      case '/':
            return "/";
      case ':':
            return ":";
      case '<':
            return "<";
      case '=':
            return "=";
      case '>':
            return ">";
      case '?':
            return "?";
      case '^':
            return "^";
      case '|':
            return "|";
      case '~':
            return "~";
      case AND:
            return "&&";
      case EQ:
            return "==";
      case GE:
            return ">=";
      case LE:
            return "<=";
      case LS:
            return "<<";
      case NE:
            return "!=";
      case OR:
            return "||";
      case RS:
            return ">>";
      }
      sfsprintf(buf, sizeof(buf) - 1, "(OP=%03o)", op);
      return buf;
}

/*
 * generate printf()
 */

static void
print(Excc_t* cc, Exnode_t* expr)
{
      register Print_t* x;
      register int            i;

      if (x = expr->data.print.args)
      {
            sfprintf(cc->ccdisc->text, "sfprintf(%s, \"%s", expr->data.print.descriptor->op == CONSTANT && expr->data.print.descriptor->data.constant.value.integer == 2 ? "sfstderr" : "sfstdout", fmtesq(x->format, quote));
            while (x = x->next)
                  sfprintf(cc->ccdisc->text, "%s", fmtesq(x->format, quote));
            sfprintf(cc->ccdisc->text, "\"");
            for (x = expr->data.print.args; x; x = x->next)
            {
                  if (x->arg)
                  {
                        for (i = 0; i < elementsof(x->param) && x->param[i]; i++)
                        {
                              sfprintf(cc->ccdisc->text, ", (");
                              gen(cc, x->param[i]);
                              sfprintf(cc->ccdisc->text, ")");
                        }
                        sfprintf(cc->ccdisc->text, ", (");
                        gen(cc, x->arg);
                        sfprintf(cc->ccdisc->text, ")");
                  }
            }
            sfprintf(cc->ccdisc->text, ");\n");
      }
}

/*
 * generate scanf()
 */

static void
scan(Excc_t* cc, Exnode_t* expr)
{
      register Print_t* x;
      register int            i;

      if (x = expr->data.print.args)
      {
            sfprintf(cc->ccdisc->text, "sfscanf(sfstdin, \"%s", fmtesq(x->format, quote));
            while (x = x->next)
                  sfprintf(cc->ccdisc->text, "%s", fmtesq(x->format, quote));
            sfprintf(cc->ccdisc->text, "\"");
            for (x = expr->data.print.args; x; x = x->next)
            {
                  if (x->arg)
                  {
                        for (i = 0; i < elementsof(x->param) && x->param[i]; i++)
                        {
                              sfprintf(cc->ccdisc->text, ", &(");
                              gen(cc, x->param[i]);
                              sfprintf(cc->ccdisc->text, ")");
                        }
                        sfprintf(cc->ccdisc->text, ", &(");
                        gen(cc, x->arg);
                        sfprintf(cc->ccdisc->text, ")");
                  }
            }
            sfprintf(cc->ccdisc->text, ");\n");
      }
}

/*
 * internal excc
 */

static void
gen(Excc_t* cc, register Exnode_t* expr)
{
      register Exnode_t*      x;
      register Exnode_t*      y;
      register int            n;
      register int            m;
      register int            t;
      char*             s;
      Extype_t*         v;
      Extype_t**        p;

      if (!expr)
            return;
      x = expr->data.operand.left;
      switch (expr->op)
      {
      case BREAK:
            sfprintf(cc->ccdisc->text, "break;\n");
            return;
      case CONTINUE:
            sfprintf(cc->ccdisc->text, "continue;\n");
            return;
      case CONSTANT:
            switch (expr->type)
            {
            case FLOATING:
                  sfprintf(cc->ccdisc->text, "%g", expr->data.constant.value.floating);
                  break;
            case STRING:
                  sfprintf(cc->ccdisc->text, "\"%s\"", fmtesq(expr->data.constant.value.string, quote));
                  break;
            case UNSIGNED:
                  sfprintf(cc->ccdisc->text, "%I*u", sizeof(expr->data.constant.value.integer), expr->data.constant.value.integer);
                  break;
            default:
                  sfprintf(cc->ccdisc->text, "%I*d", sizeof(expr->data.constant.value.integer), expr->data.constant.value.integer);
                  break;
            }
            return;
      case DEC:
            sfprintf(cc->ccdisc->text, "%s--", x->data.variable.symbol->name);
            return;
      case DYNAMIC:
            sfprintf(cc->ccdisc->text, "%s", expr->data.variable.symbol->name);
            return;
      case EXIT:
            sfprintf(cc->ccdisc->text, "exit(");
            gen(cc, x);
            sfprintf(cc->ccdisc->text, ");\n");
            return;
      case IF:
            sfprintf(cc->ccdisc->text, "if (");
            gen(cc, x);
            sfprintf(cc->ccdisc->text, ") {\n");
            gen(cc, expr->data.operand.right->data.operand.left);
            if (expr->data.operand.right->data.operand.right)
            {
                  sfprintf(cc->ccdisc->text, "} else {\n");
                  gen(cc, expr->data.operand.right->data.operand.right);
            }
            sfprintf(cc->ccdisc->text, "}\n");
            return;
      case FOR:
            sfprintf(cc->ccdisc->text, "for (;");
            gen(cc, x);
            sfprintf(cc->ccdisc->text, ");");
            if (expr->data.operand.left)
            {
                  sfprintf(cc->ccdisc->text, "(");
                  gen(cc, expr->data.operand.left);
                  sfprintf(cc->ccdisc->text, ")");
            }
            sfprintf(cc->ccdisc->text, ") {");
            if (expr->data.operand.right)
                  gen(cc, expr->data.operand.right);
            sfprintf(cc->ccdisc->text, "}");
            return;
      case ID:
            if (cc->ccdisc->ccf)
                  (*cc->ccdisc->ccf)(cc, expr, expr->data.variable.symbol, expr->data.variable.reference, expr->data.variable.index, cc->ccdisc);
            else
                  sfprintf(cc->ccdisc->text, "%s", expr->data.variable.symbol->name);
            return;
      case INC:
            sfprintf(cc->ccdisc->text, "%s++", x->data.variable.symbol->name);
            return;
      case ITERATE:
            if (expr->op == DYNAMIC)
            {
                  sfprintf(cc->ccdisc->text, "{ Exassoc_t* %stmp_%d;", cc->id, ++cc->tmp);
                  sfprintf(cc->ccdisc->text, "for (%stmp_%d = (Exassoc_t*)dtfirst(%s); %stmp_%d && (%s = %stmp_%d->name); %stmp_%d = (Exassoc_t*)dtnext(%s, %stmp_%d)) {", cc->id, cc->tmp, expr->data.generate.array->data.variable.symbol->name, cc->id, cc->tmp, expr->data.generate.index->name, cc->id, cc->tmp, cc->id, cc->tmp, expr->data.generate.array->data.variable.symbol->name, cc->id, cc->tmp);
                  gen(cc, expr->data.generate.statement);
                  sfprintf(cc->ccdisc->text, "} }");
            }
            return;
      case PRINTF:
            print(cc, expr);
            return;
      case RETURN:
            sfprintf(cc->ccdisc->text, "return(");
            gen(cc, x);
            sfprintf(cc->ccdisc->text, ");\n");
            return;
      case SCANF:
            scan(cc, expr);
            return;
      case SWITCH:
            t = x->type;
            sfprintf(cc->ccdisc->text, "{ %s %stmp_%d = ", extype(t), cc->id, ++cc->tmp);
            gen(cc, x);
            sfprintf(cc->ccdisc->text, ";");
            x = expr->data.operand.right;
            y = x->data.select.statement;
            n = 0;
            while (x = x->data.select.next)
            {
                  if (n)
                        sfprintf(cc->ccdisc->text, "else ");
                  if (!(p = x->data.select.constant))
                        y = x->data.select.statement;
                  else
                  {
                        m = 0;
                        while (v = *p++)
                        {
                              if (m)
                                    sfprintf(cc->ccdisc->text, "||");
                              else
                              {
                                    m = 1;
                                    sfprintf(cc->ccdisc->text, "if (");
                              }
                              if (t == STRING)
                                    sfprintf(cc->ccdisc->text, "strmatch(%stmp_%d, \"%s\")", cc->id, cc->tmp, fmtesq(v->string, quote));
                              else
                              {
                                    sfprintf(cc->ccdisc->text, "%stmp_%d == ", cc->id, cc->tmp);
                                    switch (t)
                                    {
                                    case INTEGER:
                                    case UNSIGNED:
                                          sfprintf(cc->ccdisc->text, "%I*u", sizeof(v->integer), v->integer);
                                          break;
                                    default:
                                          sfprintf(cc->ccdisc->text, "%g", v->floating);
                                          break;
                                    }
                              }
                        }
                        sfprintf(cc->ccdisc->text, ") {");
                        gen(cc, x->data.select.statement);
                        sfprintf(cc->ccdisc->text, "}");
                  }
            }
            if (y)
            {
                  if (n)
                        sfprintf(cc->ccdisc->text, "else ");
                  sfprintf(cc->ccdisc->text, "{");
                  gen(cc, y);
                  sfprintf(cc->ccdisc->text, "}");
            }
            sfprintf(cc->ccdisc->text, "}");
            return;
      case WHILE:
            sfprintf(cc->ccdisc->text, "while (");
            gen(cc, x);
            sfprintf(cc->ccdisc->text, ") {");
            if (expr->data.operand.right)
                  gen(cc, expr->data.operand.right);
            sfprintf(cc->ccdisc->text, "}");
            return;
      case '=':
            sfprintf(cc->ccdisc->text, "(%s%s=", x->data.variable.symbol->name, expr->subop == '=' ? "" : opname(expr->subop));
            gen(cc, expr->data.operand.right);
            sfprintf(cc->ccdisc->text, ")");
            return;
      case ';':
            for (;;)
            {
                  if (!(x = expr->data.operand.right))
                        switch (cc->lastop = expr->data.operand.left->op)
                        {
                        case FOR:
                        case IF:
                        case PRINTF:
                        case RETURN:
                        case WHILE:
                              break;
                        default:
                              sfprintf(cc->ccdisc->text, "_%svalue=", cc->id);
                              break;
                        }
                  gen(cc, expr->data.operand.left);
                  sfprintf(cc->ccdisc->text, ";\n");
                  if (!(expr = x))
                        break;
                  switch (cc->lastop = expr->op)
                  {
                  case ';':
                        continue;
                  case FOR:
                  case IF:
                  case PRINTF:
                  case RETURN:
                  case WHILE:
                        break;
                  default:
                        sfprintf(cc->ccdisc->text, "_%svalue=", cc->id);
                        break;
                  }
                  gen(cc, expr);
                  sfprintf(cc->ccdisc->text, ";\n");
                  break;
            }
            return;
      case ',':
            sfprintf(cc->ccdisc->text, "(");
            gen(cc, x);
            while ((expr = expr->data.operand.right) && expr->op == ',')
            {
                  sfprintf(cc->ccdisc->text, "), (");
                  gen(cc, expr->data.operand.left);
            }
            if (expr)
            {
                  sfprintf(cc->ccdisc->text, "), (");
                  gen(cc, expr);
            }
            sfprintf(cc->ccdisc->text, ")");
            return;
      case '?':
            sfprintf(cc->ccdisc->text, "(");
            gen(cc, x);
            sfprintf(cc->ccdisc->text, ") ? (");
            gen(cc, expr->data.operand.right->data.operand.left);
            sfprintf(cc->ccdisc->text, ") : (");
            gen(cc, expr->data.operand.right->data.operand.right);
            sfprintf(cc->ccdisc->text, ")");
            return;
      case AND:
            sfprintf(cc->ccdisc->text, "(");
            gen(cc, x);
            sfprintf(cc->ccdisc->text, ") && (");
            gen(cc, expr->data.operand.right);
            sfprintf(cc->ccdisc->text, ")");
            return;
      case OR:
            sfprintf(cc->ccdisc->text, "(");
            gen(cc, x);
            sfprintf(cc->ccdisc->text, ") || (");
            gen(cc, expr->data.operand.right);
            sfprintf(cc->ccdisc->text, ")");
            return;
      case F2I:
            sfprintf(cc->ccdisc->text, "(%s)(", extype(INTEGER));
            gen(cc, x);
            sfprintf(cc->ccdisc->text, ")");
            return;
      case I2F:
            sfprintf(cc->ccdisc->text, "(%s)(", extype(FLOATING));
            gen(cc, x);
            sfprintf(cc->ccdisc->text, ")");
            return;
      case S2I:
            sfprintf(cc->ccdisc->text, "strto%s(", sizeof(intmax_t) > sizeof(long) ? "ll" : "l");
            gen(cc, x);
            sfprintf(cc->ccdisc->text, ",(char**)0,0)");
            return;
      }
      y = expr->data.operand.right;
      if (x->type == STRING)
      {
            switch (expr->op)
            {
            case S2B:
                  sfprintf(cc->ccdisc->text, "*(");
                  gen(cc, x);
                  sfprintf(cc->ccdisc->text, ")!=0");
                  return;
            case S2F:
                  sfprintf(cc->ccdisc->text, "strtod(");
                  gen(cc, x);
                  sfprintf(cc->ccdisc->text, ",0)");
                  return;
            case S2I:
                  sfprintf(cc->ccdisc->text, "strtol(");
                  gen(cc, x);
                  sfprintf(cc->ccdisc->text, ",0,0)");
                  return;
            case S2X:
                  sfprintf(cc->ccdisc->text, "** cannot convert string value to external **");
                  return;
            case NE:
                  sfprintf(cc->ccdisc->text, "!");
                  /*FALLTHROUGH*/
            case EQ:
                  sfprintf(cc->ccdisc->text, "strmatch(");
                  gen(cc, x);
                  sfprintf(cc->ccdisc->text, ",");
                  gen(cc, y);
                  sfprintf(cc->ccdisc->text, ")");
                  return;
            case '+':
            case '|':
            case '&':
            case '^':
            case '%':
            case '*':
                  sfprintf(cc->ccdisc->text, "** string bits not supported **");
                  return;
            }
            switch (expr->op)
            {
            case '<':
                  s = "<0";
                  break;
            case LE:
                  s = "<=0";
                  break;
            case GE:
                  s = ">=0";
                  break;
            case '>':
                  s = ">0";
                  break;
            default:
                  s = "** unknown string op **";
                  break;
            }
            sfprintf(cc->ccdisc->text, "strcoll(");
            gen(cc, x);
            sfprintf(cc->ccdisc->text, ",");
            gen(cc, y);
            sfprintf(cc->ccdisc->text, ")%s", s);
            return;
      }
      else
      {
            if (!y)
                  sfprintf(cc->ccdisc->text, "%s", opname(expr->op));
            sfprintf(cc->ccdisc->text, "(");
            gen(cc, x);
            if (y)
            {
                  sfprintf(cc->ccdisc->text, ")%s(", opname(expr->op));
                  gen(cc, y);
            }
            sfprintf(cc->ccdisc->text, ")");
      }
      return;
}

/*
 * generate global declarations
 */

static int
global(Dt_t* table, void* object, void* handle)
{
      register Excc_t*  cc = (Excc_t*)handle;
      register Exid_t*  sym = (Exid_t*)object;

      if (sym->lex == DYNAMIC)
            sfprintf(cc->ccdisc->text, "static %s     %s;\n", extype(sym->type), sym->name);
      return 0;
}

/*
 * open C program generator context
 */

Excc_t*
exccopen(Expr_t* expr, Exccdisc_t* disc)
{
      register Excc_t*  cc;
      char*             id;

      if (!(id = disc->id))
            id = "";
      if (!(cc = newof(0, Excc_t, 1, strlen(id) + 2)))
            return 0;
      cc->expr = expr;
      cc->disc = expr->disc;
      cc->id = (char*)(cc + 1);
      cc->ccdisc = disc;
      if (!(disc->flags & EX_CC_DUMP))
      {
            sfprintf(disc->text, "/* : : generated by %s : : */\n", exversion);
            sfprintf(disc->text, "\n#include <ast.h>\n");
            if (*id)
                  sfsprintf(cc->id, strlen(id) + 2, "%s_", id);
            sfprintf(disc->text, "\n");
            dtwalk(expr->symbols, global, cc);
      }
      return cc;
}

/*
 * close C program generator context
 */

int
exccclose(Excc_t* cc)
{
      int   r = 0;

      if (!cc)
            r = -1;
      else
      {
            if (!(cc->ccdisc->flags & EX_CC_DUMP))
            {
                  if (cc->ccdisc->text)
                        sfclose(cc->ccdisc->text);
                  else
                        r = -1;
            }
            free(cc);
      }
      return r;
}

/*
 * generate the program for name or sym coerced to type
 */

int
excc(Excc_t* cc, const char* name, Exid_t* sym, int type)
{
      register char*    t;

      if (!cc)
            return -1;
      if (!sym)
            sym = name ? (Exid_t*)dtmatch(cc->expr->symbols, name) : &cc->expr->main;
      if (sym && sym->lex == PROCEDURE && sym->value)
      {
            t = extype(type);
            sfprintf(cc->ccdisc->text, "\n%s %s%s(data) char** data; {\n%s _%svalue = 0;\n", t, cc->id, sym->name, t, cc->id);
            gen(cc, sym->value->data.procedure.body);
            sfprintf(cc->ccdisc->text, ";\n");
            if (cc->lastop != RETURN)
                  sfprintf(cc->ccdisc->text, "return _%svalue;\n", cc->id);
            sfprintf(cc->ccdisc->text, "}\n");
            return 0;
      }
      return -1;
}

/*
 * dump an expression tree on sp
 */

int
exdump(Expr_t* expr, Exnode_t* node, Sfio_t* sp)
{
      Excc_t*           cc;
      Exccdisc_t  ccdisc;
      Exid_t*           sym;

      memset(&ccdisc, 0, sizeof(ccdisc));
      ccdisc.flags = EX_CC_DUMP;
      ccdisc.text = sp;
      if (!(cc = exccopen(expr, &ccdisc)))
            return -1;
      if (node)
            gen(cc, node);
      else
            for (sym = (Exid_t*)dtfirst(expr->symbols); sym; sym = (Exid_t*)dtnext(expr->symbols, sym))
                  if (sym->lex == PROCEDURE && sym->value)
                  {
                        sfprintf(sp, "%s:\n", sym->name);
                        gen(cc, sym->value->data.procedure.body);
                  }
      sfprintf(sp, "\n");
      return exccclose(cc);
}

Generated by  Doxygen 1.6.0   Back to index