示例#1
0
 /**
  * Runs eval on the code tree, and if it returns an ival, resolves it.
  *
  * @param c
  * @param env
  * @return
  */
 public Construct seval(ParseTree c, final Environment env) {
   Construct ret = eval(c, env);
   while (ret instanceof IVariable) {
     IVariable cur = (IVariable) ret;
     ret = env.getEnv(GlobalEnv.class).GetVarList().get(cur.getName(), cur.getTarget()).ival();
   }
   return ret;
 }
示例#2
0
  public Construct eval(ParseTree c, final Environment env) throws CancelCommandException {
    final Construct m = c.getData();
    CurrentEnv = env;
    // TODO: Reevaluate if this line is needed. The script doesn't know the label inherently, the
    // environment does, and setting it this way taints the environment.
    CurrentEnv.getEnv(GlobalEnv.class).SetLabel(this.label);
    if (m.getCType() == ConstructType.FUNCTION) {
      env.getEnv(GlobalEnv.class).SetScript(this);
      if (m.val().matches("^_[^_].*")) {
        // Not really a function, so we can't put it in Function.
        Procedure p = getProc(m.val());
        if (p == null) {
          throw new ConfigRuntimeException(
              "Unknown procedure \"" + m.val() + "\"",
              ExceptionType.InvalidProcedureException,
              m.getTarget());
        }
        Environment newEnv = env;
        try {
          newEnv = env.clone();
        } catch (Exception e) {
        }
        ProfilePoint pp =
            env.getEnv(GlobalEnv.class).GetProfiler().start(m.val() + " execution", LogLevel.INFO);
        Construct ret = p.cexecute(c.getChildren(), newEnv, m.getTarget());
        pp.stop();
        return ret;
      }
      final Function f;
      try {
        f = (Function) FunctionList.getFunction(m);
      } catch (ConfigCompileException e) {
        // Turn it into a config runtime exception. This shouldn't ever happen though.
        throw new ConfigRuntimeException("Unable to find function " + m.val(), m.getTarget());
      }
      // We have special handling for loop and other control flow functions
      if (f instanceof assign) {
        if (c.getChildAt(0).getData() instanceof CFunction) {
          CFunction test = (CFunction) c.getChildAt(0).getData();
          if (test.val().equals("array_get")) {
            env.getEnv(GlobalEnv.class).SetFlag("array_get_alt_mode", true);
            Construct arrayAndIndex = eval(c.getChildAt(0), env);
            env.getEnv(GlobalEnv.class).ClearFlag("array_get_alt_mode");
            return ((assign) f)
                .array_assign(m.getTarget(), env, arrayAndIndex, eval(c.getChildAt(1), env));
          }
        }
      }

      if (f.useSpecialExec()) {
        ProfilePoint p = null;
        if (f.shouldProfile()
            && env.getEnv(GlobalEnv.class).GetProfiler() != null
            && env.getEnv(GlobalEnv.class).GetProfiler().isLoggable(f.profileAt())) {
          p =
              env.getEnv(GlobalEnv.class)
                  .GetProfiler()
                  .start(f.profileMessageS(c.getChildren()), f.profileAt());
        }
        Construct ret =
            f.execs(m.getTarget(), env, this, c.getChildren().toArray(new ParseTree[] {}));
        if (p != null) {
          p.stop();
        }
        return ret;
      }

      ArrayList<Construct> args = new ArrayList<Construct>();
      for (ParseTree c2 : c.getChildren()) {
        args.add(eval(c2, env));
      }
      if (f.isRestricted()) {
        boolean perm = Static.hasCHPermission(f.getName(), env);
        if (!perm) {
          throw new ConfigRuntimeException(
              "You do not have permission to use the " + f.getName() + " function.",
              ExceptionType.InsufficientPermissionException,
              m.getTarget());
        }
      }
      Object[] a = args.toArray();
      Construct[] ca = new Construct[a.length];
      for (int i = 0; i < a.length; i++) {
        ca[i] = (Construct) a[i];
        // CArray, CBoolean, CDouble, CInt, CNull, CString, CVoid, CEntry, CLabel (only to sconcat).
        if (!(ca[i] instanceof CArray
                || ca[i] instanceof CBoolean
                || ca[i] instanceof CDouble
                || ca[i] instanceof CInt
                || ca[i] instanceof CNull
                || ca[i] instanceof CString
                || ca[i] instanceof CVoid
                || ca[i] instanceof IVariable
                || ca[i] instanceof CEntry
                || ca[i] instanceof CLabel)
            && (!f.getName().equals("__autoconcat__") && (ca[i] instanceof CLabel))) {
          throw new ConfigRuntimeException(
              "Invalid Construct ("
                  + ca[i].getClass()
                  + ") being passed as an argument to a function ("
                  + f.getName()
                  + ")",
              null,
              m.getTarget());
        }
        if (env.getEnv(GlobalEnv.class).GetFlag("array_get_alt_mode") == Boolean.TRUE && i == 0) {
          continue;
        }
        while (f.preResolveVariables() && ca[i] instanceof IVariable) {
          IVariable cur = (IVariable) ca[i];
          ca[i] =
              env.getEnv(GlobalEnv.class).GetVarList().get(cur.getName(), cur.getTarget()).ival();
        }
      }

      {
        // It takes a moment to generate the toString of some things, so lets not do it
        // if we actually aren't going to profile
        ProfilePoint p = null;
        if (f.shouldProfile()
            && env.getEnv(GlobalEnv.class).GetProfiler() != null
            && env.getEnv(GlobalEnv.class).GetProfiler().isLoggable(f.profileAt())) {
          p = env.getEnv(GlobalEnv.class).GetProfiler().start(f.profileMessage(ca), f.profileAt());
        }
        Construct ret = f.exec(m.getTarget(), env, ca);
        if (p != null) {
          p.stop();
        }
        return ret;
      }

    } else if (m.getCType() == ConstructType.VARIABLE) {
      return new CString(m.val(), m.getTarget());
    } else {
      return m;
    }
  }
    @Override
    public Construct execs(Target t, Environment env, Script parent, ParseTree... nodes) {
      if (nodes.length < 5) {
        throw new ConfigRuntimeException(
            "bind accepts 5 or more parameters", ExceptionType.InsufficientArgumentsException, t);
      }
      Construct name = parent.seval(nodes[0], env);
      Construct options = parent.seval(nodes[1], env);
      Construct prefilter = parent.seval(nodes[2], env);
      Construct event_obj = parent.eval(nodes[3], env);
      IVariableList custom_params = new IVariableList();
      for (int a = 0; a < nodes.length - 5; a++) {
        Construct var = parent.eval(nodes[4 + a], env);
        if (!(var instanceof IVariable)) {
          throw new ConfigRuntimeException(
              "The custom parameters must be ivariables", ExceptionType.CastException, t);
        }
        IVariable cur = (IVariable) var;
        custom_params.set(
            env.getEnv(GlobalEnv.class).GetVarList().get(cur.getName(), cur.getTarget()));
      }
      Environment newEnv = env;
      try {
        newEnv = env.clone();
      } catch (Exception e) {
      }
      newEnv.getEnv(GlobalEnv.class).SetVarList(custom_params);
      ParseTree tree = nodes[nodes.length - 1];

      // Check to see if our arguments are correct
      if (!(options instanceof CNull || options instanceof CArray)) {
        throw new ConfigRuntimeException(
            "The options must be an array or null", ExceptionType.CastException, t);
      }
      if (!(prefilter instanceof CNull || prefilter instanceof CArray)) {
        throw new ConfigRuntimeException(
            "The prefilters must be an array or null", ExceptionType.CastException, t);
      }
      if (!(event_obj instanceof IVariable)) {
        throw new ConfigRuntimeException(
            "The event object must be an IVariable", ExceptionType.CastException, t);
      }
      CString id;
      if (options instanceof CNull) {
        options = null;
      }
      if (prefilter instanceof CNull) {
        prefilter = null;
      }
      Event event;
      try {
        BoundEvent be =
            new BoundEvent(
                name.val(),
                (CArray) options,
                (CArray) prefilter,
                ((IVariable) event_obj).getName(),
                newEnv,
                tree,
                t);
        EventUtils.RegisterEvent(be);
        id = new CString(be.getId(), t);
        event = EventList.getEvent(be.getEventName());
      } catch (EventException ex) {
        throw new ConfigRuntimeException(ex.getMessage(), ExceptionType.BindException, t);
      }

      // Set up our bind counter, but only if the event is supposed to be added to the counter
      if (event.addCounter()) {
        synchronized (bindCounter) {
          if (bindCounter.get() == 0) {
            env.getEnv(GlobalEnv.class).GetDaemonManager().activateThread(null);
            StaticLayer.GetConvertor()
                .addShutdownHook(
                    new Runnable() {

                      @Override
                      public void run() {
                        synchronized (bindCounter) {
                          bindCounter.set(0);
                        }
                      }
                    });
          }
          bindCounter.incrementAndGet();
        }
      }
      return id;
    }