1#pragma once
  2
  3#include <stdio.h>
  4
  5#include <pw_types.h>
  6#include <pw_task.h>
  7
  8#ifdef __cplusplus
  9extern "C" {
 10#endif
 11
 12// kinds of status
 13#define PwStatusKind_Basic     0  // PetWay and user-defined errors
 14#define PwStatusKind_Errno     1  // errno
 15#define PwStatusKind_VA_END    2  // special: used as a terminator for variadic arguments
 16
 17// PetWay errors for basic kind of status
 18#define PweSuccess                  0
 19#define PweBasic                    1  // basic error, for simple use cases
 20#define PweException                2  // status code for exception kind of status
 21#define PweAssertion                3
 22#define PweNotImplemented           4
 23#define PweIncompatibleType         5
 24#define PweInterfaceNotDefined      6
 25#define PweIterationInProgress      7
 26#define PweEOF                      8
 27#define PweTimeout                  9
 28#define PwePrintf                  10
 29#define PweStringTooLong           11
 30#define PweDataSizeTooBig          12
 31#define PweIndexOutOfRange         13
 32#define PweParseError              14
 33#define PweBadNumber               15
 34#define PweBadDatetime             16
 35#define PweBadTimestamp            17
 36#define PweNumericOverflow         18
 37#define PweBadInput                19
 38#define PweImmutableRequired       20
 39
 40// array errors
 41#define PweExtractFromEmptyArray   21
 42#define PweDeleteFromEmptyArray    22
 43
 44// map errors
 45#define PweKeyNotFound             23
 46
 47// File errors
 48#define PweFileNotFound            24
 49#define PweFileAlreadyOpened       25
 50#define PweFdAlreadySet            26
 51#define PweCantSetFilename         27
 52#define PweFileClosed              28
 53#define PweNotRegularFile          29
 54#define PweNotBufferedFile         30
 55
 56// PetMachine errors
 57#define PweControlStackOverflow    31
 58#define PweDataStackOverflow       32
 59#define PweNoTasksToRun            33
 60
 61
 62uint16_t pw_define_status(char* description);
 63/*
 64 * Define Basic status code in the global table.
 65 * Return status code.
 66 *
 67 * This function should be called from the very beginning of main() function
 68 * or from constructors that are called before main().
 69 */
 70
 71char* pw_get_basic_error_description(uint16_t status_code);
 72/*
 73 * Return description for the Basic status code or "unknown".
 74 */
 75
 76char* pw_get_status_description(PwValuePtr status);
 77/*
 78 * Return description associated with status.
 79 */
 80
 81PW_STRUCT(PwCtorArgs);  // forward declaration; this file is included by pw_interfaces.h
 82
 83PW_STRUCT(PwStatusCtorArgs) {
 84    PwCtorArgs* next;
 85    uint16_t type_id;
 86
 87    union {
 88        uint16_t status_code;
 89        int16_t  pw_errno;
 90    };
 91    uint32_t kind: 2,
 92             line_number: 30;
 93    char* file_desc;  // string this pointer points to must be static
 94};
 95
 96#define pw_is_basic_error(status, code)  \
 97    (pw_is_status(status)  \
 98     && (status)->kind == PwStatusKind_Basic  \
 99     && (status)->status_code == (code)  \
100    )
101
102static inline bool pw_is_va_end(PwValuePtr status)
103{
104    if (!pw_is_status(status)) {
105        return false;
106    }
107    return status->kind == PwStatusKind_VA_END;
108}
109
110/*
111 * Applications always "withdraws" status from the current task for checking.
112 * This ensures the status is Null if the application handles some errors.
113 * For exceptions wrapping it is important to keep status Null when things are going okay.
114 */
115#define pw_get_status()  \
116    __extension__ \
117    ({  \
118        _PwValue status = PW_NULL;  \
119        pw_move(&status, &current_task->status);  \
120        status;  \
121    })
122
123#define pw_set_status(_status) _Generic((_status), \
124          _PwValue: _pw_set_status_by_value,  \
125        PwValuePtr: _pw_set_status_by_ptr     \
126    )((_status))
127
128static inline void _pw_set_status_by_value(_PwValue status)
129{
130    pw_destroy(&current_task->status);
131    current_task->status = status;
132}
133
134static inline void _pw_set_status_by_ptr(PwValuePtr status)
135{
136    pw_move(&current_task->status, status);
137}
138
139#ifdef __cplusplus
140}
141#endif