ON THU, FEB 28, 2008 AT 02:05:13AM +0100, MATHIAS KENDE WROTE:
> MY QUESTION IS ABOUT CATCHING IN C SOME EXCEPTIONS RAISED BY CAML CODE
> CALLED FROM THE C CODE.
> I WAS THINKING THAT AN EXCEPTION IS APPROXIMATELY A BLOCK WHOSE FIRST
> FIELD IS THE EXCEPTION VALUE, AND SECOND FIELD IS THE ONLY ARGUMENT (AS
THIS ISN'T QUITE CORRECT:
TRY
IGNORE (UNIX.OPENFILE "/NOFILE" [] 0)
WITH
EXN ->
PRINTF.PRINTF "%DN" (OBJ.SIZE (OBJ.REPR EXN))
PRINTS 4 (WORDS), SO EXCEPTION TAG + 3 ARGUMENTS.
TRY
IGNORE (LIST.ASSOC 0 [])
WITH
EXN ->
PRINTF.PRINTF "%DN" (OBJ.SIZE (OBJ.REPR EXN))
PRINTS 1 (WORD), JUST THE EXCEPTION TAG.
TRY
FAILWITH "FOO"
WITH
EXN ->
PRINTF.PRINTF "%DN" (OBJ.SIZE (OBJ.REPR EXN))
PRINTS 2 (WORDS), EXCEPTION TAG + SINGLE ARGUMENT.
> I UNDERSTAND IT, AN EXCEPTION CAN HAVE ONLY ONE ARGUMENT AND SO
> EXCEPTION E OF INT*INT
> IS EQUIVALENT TO
> EXCEPTION E OF (INT*INT)
> (AS OPPOSED TO A TYPE DECLARATION - IF I AM RIGHT, THIS IS NOT VERY
> BEAUTIFUL).
EXCEPTIONS CANNOT BE SIMPLE TYPE DECLARATIONS. THE REASON IS RATHER
COMPLICATED, TO DO WITH WHAT OCAML DOES AT LINK TIME (AND AT DYNAMIC
LOAD TIME) WHERE IT HAS TO GET A GLOBAL PICTURE OF ALL POSSIBLE
EXCEPTIONS AND ASSIGN THEM UNIQUE NUMERIC EXCEPTION TAGS.
INTERNALLY AN EXCEPTION POINTER IS RECOGNISED BY LOOKING AT THE LOWER
TWO BITS OF THE VALUE, THUS:
BIT1 BIT0
- - - - - - -+------+------+
(ANY) | 1 | INTEGER
- - - - - - -+------+------+
- - - - - - -+------+------+
| 0 | 0 | POINTER / BOXED VALUE
- - - - - - -+------+------+
- - - - - - -+------+------+
| 1 | 0 | EXCEPTION
- - - - - - -+------+------+
AND THE EXCEPTION POINTER IS THEN "EXTRACTED" (LOWER TWO BITS ARE SET
TO 0 0) AND IT BECOMES A POINTER TO A BLOCK OF SIZE 1 OR MORE WORDS:
+-------------+-------------+-------------+- - -
| EXCEPTION | OPTIONAL | OPTIONAL |
| TAG | ARGUMENT | ARGUMENT |
+-------------+-------------+-------------+- - -
IN THE CASE OF UNIX.UNIX_ERROR THERE ARE THREE ARGUMENTS.
> BUT I'M TRYING TO ACCESS TO A UNIX.UNIX_ERROR EXCEPTION WITH THE
> FOLLOWING CODE :
>
> V = CAML_CALLBACK_EXN(*CAML_LSTAT,CAML_COPY_STRING(PATH));
> IF (IS_EXCEPTION_RESULT(V))
> {
> V = EXTRACT_EXCEPTION(V);
> IF (FIELD(V,0) == *UNIX_ERROR)
> {
> RES = - INT_UNIX_ERROR(INT_VAL(FIELD(V,1)));
> }
> ELSE
> {
> CAML_RAISE(V);
> }
> }
>
> IT IS GLOBALLY WORKING (IT ONLY SELDOM RAISE A SEGFAULT), WHEREAS, IF A
IT'S NOT GLOBALLY WORKING IF IT "ONLY SELDOM" RAISES A SEGFAULT. BUT
YOU DON'T EXPLAIN WHERE *UNIX_ERROR COMES FROM. HOPEFULLY FROM A
REGISTERED EXCEPTION AS EXPLAINED HERE:
HTTP://CAML.INRIA.FR/PUB/DOCS/MANUAL-OCAML/MANUAL032.HTML#S:REGISTER-EXN
AND WHAT IS INT_UNIX_ERROR? CONVERTING FIELD (V,1) TO AN INT ISN'T
ALWAYS SAFE BECAUSE OF THE 'EUNKNOWNERR OF INT' CASE.
> REPLACE THE ?¿INT_VAL(FIELD(V,1)) CALL TO ?¿INT_VAL(FIELD(FIELD(V,1),0))
> WHICH IS WHAT I WOULD BE EXPECTING AS I TRY TO ACCESS THE FIRST MEMBER
> (THE UNIX.ERROR CODE) OF THE ARGUMENT OF THE EXCEPTION, THEN THE CODE
> ALWAYS SEGFAULTS.
>
> I HOPE THAT SOMEONE CAN EXPLAIN ME WHAT IS THE GOOD WAY TO CATCH THIS
> EXCEPTION.
WE NEED TO SEE MORE OF THE CODE.
RICH.
--
RICHARD JONES
RED HAT
.