X-Git-Url: http://git.annexia.org/?a=blobdiff_plain;f=augeas-c.c;h=ae22dff4bcab0a9b69cb03d21db127870aa45ce3;hb=775f9763a4ff5422fca837c2fb213273adb772c9;hp=3952910510754760730c746773f3a24f60a90375;hpb=a467e365dc114868f948b8b5b18e551b42d64ddd;p=ocaml-augeas.git diff --git a/augeas-c.c b/augeas-c.c index 3952910..ae22dff 100644 --- a/augeas-c.c +++ b/augeas-c.c @@ -1,5 +1,5 @@ /* Augeas OCaml bindings - * Copyright (C) 2008-2012 Red Hat Inc., Richard W.M. Jones + * Copyright (C) 2008-2017 Red Hat Inc., Richard W.M. Jones * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -29,6 +29,37 @@ #include #include +#include + +#ifdef __GNUC__ + #define NORETURN __attribute__ ((noreturn)) +#else + #define NORETURN +#endif + +extern CAMLprim value ocaml_augeas_create (value rootv, value loadpathv, value flagsv); +extern CAMLprim value ocaml_augeas_close (value tv); +extern CAMLprim value ocaml_augeas_defnode (value tv, value namev, value exprv, value valv); +extern CAMLprim value ocaml_augeas_defvar (value tv, value namev, value exprv); +extern CAMLprim value ocaml_augeas_get (value tv, value pathv); +extern CAMLprim value ocaml_augeas_exists (value tv, value pathv); +extern CAMLprim value ocaml_augeas_insert (value tv, value beforev, value pathv, value labelv); +extern CAMLprim value ocaml_augeas_label (value tv, value pathv); +extern CAMLprim value ocaml_augeas_mv (value tv, value srcv, value destv); +extern CAMLprim value ocaml_augeas_rm (value tv, value pathv); +extern CAMLprim value ocaml_augeas_match (value tv, value pathv); +extern CAMLprim value ocaml_augeas_count_matches (value tv, value pathv); +extern CAMLprim value ocaml_augeas_save (value tv); +extern CAMLprim value ocaml_augeas_load (value tv); +extern CAMLprim value ocaml_augeas_set (value tv, value pathv, value valuev); +extern CAMLprim value ocaml_augeas_setm (value tv, value basev, value subv, value valv); +extern CAMLprim value ocaml_augeas_transform (value tv, value lensv, value filev, value modev); +extern CAMLprim value ocaml_augeas_source (value tv, value pathv) +#ifndef HAVE_AUG_SOURCE + NORETURN +#endif +; + typedef augeas *augeas_t; /* Map C aug_errcode_t to OCaml error_code. */ @@ -49,9 +80,11 @@ static const int error_map[] = { }; static const int error_map_len = sizeof error_map / sizeof error_map[0]; -/* Raise an Augeas.Error exception. */ +/* Raise an Augeas.Error exception, and optionally close the + * specified handle. + */ static void -raise_error (augeas_t t, const char *msg) +raise_error_and_maybe_close (augeas_t t, const char *msg, bool close_handle) { value *exn = caml_named_value ("Augeas.Error"); value args[4]; @@ -61,8 +94,11 @@ raise_error (augeas_t t, const char *msg) int ocaml_code = -1; int i; - if (code == AUG_ENOMEM) + if (code == AUG_ENOMEM) { + if (close_handle) + aug_close (t); caml_raise_out_of_memory (); + } aug_err_minor = aug_error_minor_message (t); aug_err_details = aug_error_details (t); @@ -83,8 +119,12 @@ raise_error (augeas_t t, const char *msg) args[2] = caml_copy_string (aug_err_minor ? : ""); args[3] = caml_copy_string (aug_err_details ? : ""); + if (close_handle) + aug_close (t); + caml_raise_with_args (*exn, 4, args); } +#define raise_error(t, msg) raise_error_and_maybe_close(t, msg, false) static void raise_init_error (const char *msg) @@ -101,14 +141,27 @@ raise_init_error (const char *msg) caml_raise_with_args (*exn, 4, args); } +static const char * +Optstring_val (value strv) +{ + if (strv == Val_int (0)) /* None */ + return NULL; + else /* Some string */ + return String_val (Field (strv, 0)); +} + /* Map OCaml flags to C flags. */ -static int flag_map[] = { +static const int flag_map[] = { /* AugSaveBackup */ AUG_SAVE_BACKUP, /* AugSaveNewFile */ AUG_SAVE_NEWFILE, /* AugTypeCheck */ AUG_TYPE_CHECK, /* AugNoStdinc */ AUG_NO_STDINC, /* AugSaveNoop */ AUG_SAVE_NOOP, /* AugNoLoad */ AUG_NO_LOAD, + /* AugNoModlAutoload */ AUG_NO_MODL_AUTOLOAD, + /* AugEnableSpan */ AUG_ENABLE_SPAN, + /* AugNoErrClose */ AUG_NO_ERR_CLOSE, + /* AugTraceModuleLoading */ AUG_TRACE_MODULE_LOADING, }; /* Wrap and unwrap augeas_t handles, with a finalizer. */ @@ -127,7 +180,8 @@ static struct custom_operations custom_operations = { custom_compare_default, custom_hash_default, custom_serialize_default, - custom_deserialize_default + custom_deserialize_default, + custom_compare_ext_default, }; static value Val_augeas_t (augeas_t t) @@ -154,28 +208,27 @@ CAMLprim value ocaml_augeas_create (value rootv, value loadpathv, value flagsv) { CAMLparam1 (rootv); - char *root = String_val (rootv); - char *loadpath; + const char *root = String_val (rootv); + const char *loadpath = Optstring_val (loadpathv); int flags = 0, i; augeas_t t; - /* Optional loadpath. */ - loadpath = - loadpathv == Val_int (0) - ? NULL - : String_val (Field (loadpathv, 0)); - /* Convert list of flags to C. */ for (; flagsv != Val_int (0); flagsv = Field (flagsv, 1)) { i = Int_val (Field (flagsv, 0)); flags |= flag_map[i]; } - t = aug_init (root, loadpath, flags); + /* Pass AUG_NO_ERR_CLOSE so we raise a detailed Augeas.Error. */ + t = aug_init (root, loadpath, flags | AUG_NO_ERR_CLOSE); if (t == NULL) raise_init_error ("Augeas.create"); + if (aug_error (t) != AUG_NOERROR) { + raise_error_and_maybe_close (t, "Augeas.init", true); + } + CAMLreturn (Val_augeas_t (t)); } @@ -194,6 +247,56 @@ ocaml_augeas_close (value tv) CAMLreturn (Val_unit); } +/* val defnode : t -> string -> string -> string option -> int * bool */ +CAMLprim value +ocaml_augeas_defnode (value tv, value namev, value exprv, value valv) +{ + CAMLparam4 (tv, namev, exprv, valv); + CAMLlocal2 (optv, v); + augeas_t t = Augeas_t_val (tv); + const char *name = String_val (namev); + const char *expr = String_val (exprv); + const char *val = Optstring_val (valv); + int r, created; + + r = aug_defnode (t, name, expr, val, &created); + if (r == -1) { + raise_error (t, "Augeas.defnode"); + } + + v = caml_alloc (2, 0); + Store_field (v, 0, Val_int (r)); + Store_field (v, 1, Val_bool (created)); + + CAMLreturn (v); +} + +/* val defvar : t -> string -> string option -> int option */ +CAMLprim value +ocaml_augeas_defvar (value tv, value namev, value exprv) +{ + CAMLparam3 (tv, namev, exprv); + CAMLlocal2 (optv, v); + augeas_t t = Augeas_t_val (tv); + const char *name = String_val (namev); + const char *expr = Optstring_val (exprv); + int r; + + r = aug_defvar (t, name, expr); + if (r > 0) { /* Return Some val */ + v = Val_int (r); + optv = caml_alloc (1, 0); + Field (optv, 0) = v; + } else if (r == 0) /* Return None */ + optv = Val_int (0); + else if (r == -1) /* Error or multiple matches */ + raise_error (t, "Augeas.defvar"); + else + caml_failwith ("Augeas.defvar: bad return value"); + + CAMLreturn (optv); +} + /* val get : t -> path -> value option */ CAMLprim value ocaml_augeas_get (value tv, value pathv) @@ -201,21 +304,21 @@ ocaml_augeas_get (value tv, value pathv) CAMLparam2 (tv, pathv); CAMLlocal2 (optv, v); augeas_t t = Augeas_t_val (tv); - char *path = String_val (pathv); + const char *path = String_val (pathv); const char *val; int r; r = aug_get (t, path, &val); - if (r == 1) { /* Return Some val */ + if (r == 1 && val) { /* Return Some val */ v = caml_copy_string (val); optv = caml_alloc (1, 0); Field (optv, 0) = v; - } else if (r == 0) /* Return None */ + } else if (r == 0 || !val) /* Return None */ optv = Val_int (0); else if (r == -1) /* Error or multiple matches */ raise_error (t, "Augeas.get"); else - failwith ("Augeas.get: bad return value"); + caml_failwith ("Augeas.get: bad return value"); CAMLreturn (optv); } @@ -227,7 +330,7 @@ ocaml_augeas_exists (value tv, value pathv) CAMLparam2 (tv, pathv); CAMLlocal1 (v); augeas_t t = Augeas_t_val (tv); - char *path = String_val (pathv); + const char *path = String_val (pathv); int r; r = aug_get (t, path, NULL); @@ -249,8 +352,8 @@ ocaml_augeas_insert (value tv, value beforev, value pathv, value labelv) { CAMLparam4 (tv, beforev, pathv, labelv); augeas_t t = Augeas_t_val (tv); - char *path = String_val (pathv); - char *label = String_val (labelv); + const char *path = String_val (pathv); + const char *label = String_val (labelv); int before; before = beforev == Val_int (0) ? 0 : Int_val (Field (beforev, 0)); @@ -261,13 +364,54 @@ ocaml_augeas_insert (value tv, value beforev, value pathv, value labelv) CAMLreturn (Val_unit); } +/* val label : t -> path -> string option */ +CAMLprim value +ocaml_augeas_label (value tv, value pathv) +{ + CAMLparam2 (tv, pathv); + CAMLlocal2 (optv, v); + augeas_t t = Augeas_t_val (tv); + const char *path = String_val (pathv); + const char *val; + int r; + + r = aug_label (t, path, &val); + if (r == 1 && val) { /* Return Some val */ + v = caml_copy_string (val); + optv = caml_alloc (1, 0); + Field (optv, 0) = v; + } else if (r == 0 || !val) /* Return None */ + optv = Val_int (0); + else if (r == -1) /* Error or multiple matches */ + raise_error (t, "Augeas.label"); + else + caml_failwith ("Augeas.label: bad return value"); + + CAMLreturn (optv); +} + +/* val mv : t -> path -> path -> unit */ +CAMLprim value +ocaml_augeas_mv (value tv, value srcv, value destv) +{ + CAMLparam3 (tv, srcv, destv); + augeas_t t = Augeas_t_val (tv); + const char *src = String_val (srcv); + const char *dest = String_val (destv); + + if (aug_mv (t, src, dest) == -1) + raise_error (t, "Augeas.mv"); + + CAMLreturn (Val_unit); +} + /* val rm : t -> path -> int */ CAMLprim value ocaml_augeas_rm (value tv, value pathv) { CAMLparam2 (tv, pathv); augeas_t t = Augeas_t_val (tv); - char *path = String_val (pathv); + const char *path = String_val (pathv); int r; r = aug_rm (t, path); @@ -284,7 +428,7 @@ ocaml_augeas_match (value tv, value pathv) CAMLparam2 (tv, pathv); CAMLlocal3 (rv, v, cons); augeas_t t = Augeas_t_val (tv); - char *path = String_val (pathv); + const char *path = String_val (pathv); char **matches; int r, i; @@ -314,7 +458,7 @@ ocaml_augeas_count_matches (value tv, value pathv) { CAMLparam2 (tv, pathv); augeas_t t = Augeas_t_val (tv); - char *path = String_val (pathv); + const char *path = String_val (pathv); int r; r = aug_match (t, path, NULL); @@ -357,15 +501,75 @@ ocaml_augeas_set (value tv, value pathv, value valuev) CAMLparam3 (tv, pathv, valuev); augeas_t t = Augeas_t_val (tv); const char *path = String_val (pathv); - const char *val; - - val = - valuev == Val_int (0) - ? NULL - : String_val (Field (valuev, 0)); + const char *val = Optstring_val (valuev); if (aug_set (t, path, val) == -1) raise_error (t, "Augeas.set"); CAMLreturn (Val_unit); } + +/* val setm : t -> path -> string option -> value option -> int */ +CAMLprim value +ocaml_augeas_setm (value tv, value basev, value subv, value valv) +{ + CAMLparam4 (tv, basev, subv, valv); + augeas_t t = Augeas_t_val (tv); + const char *base = String_val (basev); + const char *sub = Optstring_val (subv); + const char *val = Optstring_val (valv); + int r; + + r = aug_setm (t, base, sub, val); + if (r == -1) + raise_error (t, "Augeas.setm"); + + CAMLreturn (Val_int (r)); +} + +/* val transform : t -> string -> string -> transform_mode -> unit */ +CAMLprim value +ocaml_augeas_transform (value tv, value lensv, value filev, value modev) +{ + CAMLparam4 (tv, lensv, filev, modev); + augeas_t t = Augeas_t_val (tv); + const char *lens = String_val (lensv); + const char *file = String_val (filev); + const int excl = Int_val (modev) == 1 ? 1 : 0; + + if (aug_transform (t, lens, file, excl) == -1) + raise_error (t, "Augeas.transform"); + + CAMLreturn (Val_unit); +} + +/* val source : t -> path -> path option */ +CAMLprim value +ocaml_augeas_source (value tv, value pathv) +{ +#ifdef HAVE_AUG_SOURCE + CAMLparam2 (tv, pathv); + CAMLlocal2 (optv, v); + augeas_t t = Augeas_t_val (tv); + const char *path = String_val (pathv); + char *file_path; + int r; + + r = aug_source (t, path, &file_path); + if (r == 0) { + if (file_path) { /* Return Some file_path */ + v = caml_copy_string (file_path); + optv = caml_alloc (1, 0); + Field (optv, 0) = v; + free (file_path); + } else /* Return None */ + optv = Val_int (0); + } + else /* Error */ + raise_error (t, "Augeas.source"); + + CAMLreturn (optv); +#else + caml_failwith ("Augeas.source: function not implemented"); +#endif +}