1
0
mirror of https://github.com/TREX-CoE/qmckl.git synced 2024-11-19 12:32:40 +01:00
qmckl/src/qmckl_error.org

194 lines
6.6 KiB
Org Mode
Raw Normal View History

2021-03-05 03:45:30 +01:00
# This file is part of the qmckl.h file
** Error handling
:PROPERTIES:
:c: qmckl_error.c
:c_test: test_qmckl_error.c
:fh: qmckl_f.f90
:h: qmckl.h
:END:
This file is written in C because it is more natural to express the
error handling in C than in Fortran.
2 files are produced:
- a source file : =qmckl_error.c=
- a test file : =test_qmckl_error.c=
*** Headers :noexport:
#+BEGIN_SRC C :tangle (org-entry-get nil "c" t)
#include "qmckl.h"
#include <math.h>
#include <string.h>
#include <errno.h>
#include <assert.h>
#+END_SRC
#+BEGIN_SRC C :tangle (org-entry-get nil "c_test" t)
#include "qmckl.h"
#include "munit.h"
MunitResult test_qmckl_error() {
#+END_SRC
*** Error handling
The library should never make the calling programs abort, nor
perform any input/output operations. This decision has to be taken
by the developer of the code calling the library.
All the functions return with an <<<exit code>>>, defined as
#+NAME: type-exit-code
#+BEGIN_SRC C :comments org :tangle qmckl.h
typedef int32_t qmckl_exit_code;
#+END_SRC
The exit code returns the completion status of the function to the
calling program. When a function call completed successfully, the
~QMCKL_SUCCESS~ exit code is returned. If one of the functions of
the library fails to complete the requested task, an appropriate
error code is returned to the program.
Here is the complete list of exit codes.
#+NAME: table-exit-codes
| ~QMCKL_SUCCESS~ | 0 |
| ~QMCKL_INVALID_ARG_1~ | 1 |
| ~QMCKL_INVALID_ARG_2~ | 2 |
| ~QMCKL_INVALID_ARG_3~ | 3 |
| ~QMCKL_INVALID_ARG_4~ | 4 |
| ~QMCKL_INVALID_ARG_5~ | 5 |
| ~QMCKL_INVALID_ARG_6~ | 6 |
| ~QMCKL_INVALID_ARG_7~ | 7 |
| ~QMCKL_INVALID_ARG_8~ | 8 |
| ~QMCKL_INVALID_ARG_9~ | 9 |
| ~QMCKL_INVALID_ARG_10~ | 10 |
| ~QMCKL_NULL_CONTEXT~ | 101 |
| ~QMCKL_FAILURE~ | 102 |
| ~QMCKL_ERRNO~ | 103 |
| ~QMCKL_INVALID_EXIT_CODE~ | 104 |
# We need to force Emacs not to indent the Python code:
# -*- org-src-preserve-indentation: t
#+BEGIN_SRC python :var table=table-exit-codes :results drawer :exports result
""" This script generates the C and Fortran constants for the error
codes from the org-mode table.
"""
result = [ "#+BEGIN_SRC C :comments org :tangle qmckl.h" ]
for (text, code) in table:
text=text.replace("~","")
result += [ f"#define {text:30s} {code:d}" ]
result += [ "#+END_SRC" ]
result += [ "" ]
result += [ "#+BEGIN_SRC f90 :comments org :tangle qmckl_f.f90" ]
for (text, code) in table:
text=text.replace("~","")
result += [ f" integer, parameter :: {text:30s} = {code:d}" ]
result += [ "#+END_SRC" ]
return '\n'.join(result)
#+END_SRC
#+RESULTS:
:results:
#+BEGIN_SRC C :comments org :tangle qmckl.h
#define QMCKL_SUCCESS 0
#define QMCKL_INVALID_ARG_1 1
#define QMCKL_INVALID_ARG_2 2
#define QMCKL_INVALID_ARG_3 3
#define QMCKL_INVALID_ARG_4 4
#define QMCKL_INVALID_ARG_5 5
#define QMCKL_INVALID_ARG_6 6
#define QMCKL_INVALID_ARG_7 7
#define QMCKL_INVALID_ARG_8 8
#define QMCKL_INVALID_ARG_9 9
#define QMCKL_INVALID_ARG_10 10
#define QMCKL_NULL_CONTEXT 101
#define QMCKL_FAILURE 102
#define QMCKL_ERRNO 103
#define QMCKL_INVALID_EXIT_CODE 104
#+END_SRC
#+BEGIN_SRC f90 :comments org :tangle qmckl_f.f90
integer, parameter :: QMCKL_SUCCESS = 0
integer, parameter :: QMCKL_INVALID_ARG_1 = 1
integer, parameter :: QMCKL_INVALID_ARG_2 = 2
integer, parameter :: QMCKL_INVALID_ARG_3 = 3
integer, parameter :: QMCKL_INVALID_ARG_4 = 4
integer, parameter :: QMCKL_INVALID_ARG_5 = 5
integer, parameter :: QMCKL_INVALID_ARG_6 = 6
integer, parameter :: QMCKL_INVALID_ARG_7 = 7
integer, parameter :: QMCKL_INVALID_ARG_8 = 8
integer, parameter :: QMCKL_INVALID_ARG_9 = 9
integer, parameter :: QMCKL_INVALID_ARG_10 = 10
integer, parameter :: QMCKL_NULL_CONTEXT = 101
integer, parameter :: QMCKL_FAILURE = 102
integer, parameter :: QMCKL_ERRNO = 103
integer, parameter :: QMCKL_INVALID_EXIT_CODE = 104
#+END_SRC
:end:
To make a function fail, the <<<~qmckl_failwith~>>> function should be
called, such that information about the failure is stored in
the context. The desired exit code is given as an argument, as
well as the name of the function and an error message. The return
code of the function is the desired return code.
#+BEGIN_SRC C :comments org :tangle qmckl.h
qmckl_exit_code qmckl_failwith(qmckl_context context,
const qmckl_exit_code exit_code,
const char* function,
const char* message) ;
#+END_SRC
#+BEGIN_SRC C :comments org :tangle qmckl_error.c
qmckl_exit_code qmckl_failwith(qmckl_context context,
const qmckl_exit_code exit_code,
const char* function,
const char* message) {
if (context == 0) return QMCKL_NULL_CONTEXT;
assert (exit_code > 0);
assert (exit_code < QMCKL_INVALID_EXIT_CODE);
assert (function != NULL);
assert (message != NULL);
assert (strlen(function) < QMCKL_MAX_FUN_LEN);
assert (strlen(message) < QMCKL_MAX_MSG_LEN);
context = qmckl_context_set_error(context, exit_code, function, message);
return exit_code;
}
#+END_SRC
For example, this function can be used as
#+BEGIN_SRC C :tangle no
if (x < 0) {
return qmckl_failwith(context,
QMCKL_INVALID_ARG_2,
"qmckl_function",
"Expected x >= 0");
}
#+END_SRC
# To decode the error messages, the <<<~qmckl_strerror~>>> converts an
# error code into a string.
*** End of files :noexport:
***** Test
#+BEGIN_SRC C :comments link :tangle (org-entry-get nil "c_test" t)
return MUNIT_OK;
}
#+END_SRC
# -*- mode: org -*-
# vim: syntax=c
# -*- mode: org -*-
# vim: syntax=c