| Expr_eq of whenexpr * whenexpr
| Expr_ge of whenexpr * whenexpr
| Expr_gt of whenexpr * whenexpr
+ | Expr_ne of whenexpr * whenexpr
| Expr_not of whenexpr
| Expr_add of whenexpr * whenexpr
| Expr_sub of whenexpr * whenexpr
| Expr_mul of whenexpr * whenexpr
| Expr_div of whenexpr * whenexpr
| Expr_mod of whenexpr * whenexpr
+ | Expr_len of whenexpr
| Expr_changes of string
| Expr_increases of string
| Expr_decreases of string
type variables = variable StringMap.t
+type preinfo = {
+ pi_job_name : string;
+ pi_serial : Big_int.big_int;
+ pi_variables : (string * variable) list;
+ pi_running : preinfo_running_job list;
+}
+and preinfo_running_job = {
+ pirun_job_name : string;
+ pirun_serial : Big_int.big_int;
+ pirun_start_time : float;
+ pirun_pid : int;
+}
+
+type result = {
+ res_job_name : string;
+ res_serial : Big_int.big_int;
+ res_code : int;
+ res_tmpdir : string;
+ res_output : string;
+ res_start_time : float;
+}
+
+type pre = preinfo -> bool
+type post = result -> unit
+
type job_cond =
| When_job of whenexpr
| Every_job of periodexpr
type job = {
job_loc : Loc.t;
job_name : string;
+ job_pre : pre option;
+ job_post : post option;
job_cond : job_cond;
job_script : shell_script;
}
| IExpr_app (">", exprs) ->
two_params _loc ">" exprs (fun e1 e2 -> Expr_gt (e1, e2))
+ | IExpr_app (("!="|"<>"), exprs) ->
+ two_params _loc "<>" exprs (fun e1 e2 -> Expr_ne (e1, e2))
+
| IExpr_app ("!", exprs) ->
one_param _loc "!" exprs (fun e1 -> Expr_not e1)
| IExpr_app ("mod", exprs) ->
two_params _loc "+" exprs (fun e1 e2 -> Expr_mod (e1, e2))
+ | IExpr_app (("len"|"length"|"size"), exprs) ->
+ one_param _loc "len" exprs (fun e1 -> Expr_len e1)
+
| IExpr_app (("change"|"changes"|"changed"), [IExpr_var v]) ->
Expr_changes v
sprintf "%s >= %s" (string_of_whenexpr e1) (string_of_whenexpr e2)
| Expr_gt (e1, e2) ->
sprintf "%s > %s" (string_of_whenexpr e1) (string_of_whenexpr e2)
+ | Expr_ne (e1, e2) ->
+ sprintf "%s <> %s" (string_of_whenexpr e1) (string_of_whenexpr e2)
| Expr_not e -> sprintf "! %s" (string_of_whenexpr e)
| Expr_add (e1, e2) ->
sprintf "%s + %s" (string_of_whenexpr e1) (string_of_whenexpr e2)
sprintf "%s / %s" (string_of_whenexpr e1) (string_of_whenexpr e2)
| Expr_mod (e1, e2) ->
sprintf "%s mod %s" (string_of_whenexpr e1) (string_of_whenexpr e2)
+ | Expr_len e -> sprintf "len %s" (string_of_whenexpr e)
| Expr_changes v -> sprintf "changes %s" v
| Expr_increases v -> sprintf "increases %s" v
| Expr_decreases v -> sprintf "decreases %s" v
| Expr_eq (e1, e2)
| Expr_ge (e1, e2)
| Expr_gt (e1, e2)
+ | Expr_ne (e1, e2)
| Expr_add (e1, e2)
| Expr_sub (e1, e2)
| Expr_mul (e1, e2)
| Expr_div (e1, e2)
| Expr_mod (e1, e2) ->
dependencies_of_whenexpr e1 @ dependencies_of_whenexpr e2
- | Expr_not e ->
+ | Expr_not e
+ | Expr_len e ->
dependencies_of_whenexpr e
| Expr_changes v
| Expr_increases v
else
T_bool false
+ | Expr_ne (e1, e2) ->
+ let e1 = eval_whenexpr variables prev_variables onload e1
+ and e2 = eval_whenexpr variables prev_variables onload e2 in
+ if compare_values e1 e2 <> 0 then
+ T_bool true
+ else
+ T_bool false
+
| Expr_not e ->
if not (eval_whenexpr_as_bool variables prev_variables onload e) then
T_bool true
and e2 = eval_whenexpr variables prev_variables onload e2 in
mod_values e1 e2
+ | Expr_len e ->
+ let e = eval_whenexpr variables prev_variables onload e in
+ let e = string_of_variable e in
+ T_int (big_int_of_int (String.length e))
+
| Expr_changes v ->
let prev_value, curr_value = get_prev_curr_value variables prev_variables v in
if compare_values prev_value curr_value <> 0 then
let t0 = Date.make 1970 1 1 in
let t' = Date.add t0 (Date.Period.month months) in
Date.to_unixfloat t'
+
+let check_valid_variable_name name =
+ (* Don't permit certain names. *)
+ if name = "JOBSERIAL" then
+ failwith "JOBSERIAL variable cannot be set";
+
+ let len = String.length name in
+ if len = 0 then
+ failwith "variable name is an empty string";
+ if name.[0] <> '_' && not (isalpha name.[0]) then
+ failwith "variable name must start with alphabetic character or underscore";
+
+ let rec loop i =
+ if i >= len then ()
+ else if name.[i] <> '_' && not (isalnum name.[i]) then
+ failwith "variable name contains non-alphanumeric non-underscore character"
+ else loop (i+1)
+ in
+ loop 1