1#include <myaw.h>
  2
  3#define get_this_mw_status(value)  _pw_get_this_struct_ptr(MwStatusData*, mthis, (value))
  4
  5uint16_t PwTypeId_MwStatus = 0;
  6
  7uint16_t MW_END_OF_BLOCK = 0;
  8uint16_t MW_PARSE_ERROR = 0;
  9
 10_PwValue _mw_parser_error(MwParser* parser, char* source_file_name, unsigned source_line_number,
 11                          unsigned line_number, unsigned char_pos, char* description, ...)
 12{
 13    _PwValue status = PW_NULL;
 14    if (!pw_create(PwTypeId_MwStatus, &status)) {
 15        // this never happens because init always returns true
 16        return PwStatus(PW_ERROR);
 17    }
 18    // status is PW_SUCCESS by default
 19    if (status.status_code != PW_SUCCESS) {
 20        // this should never happen
 21        return status;
 22    }
 23
 24    // mandatory fields must be initialized first
 25    _pw_set_status_location(&status, source_file_name, source_line_number);
 26
 27    // the base Status constructor does not allocate struct_data for PW_SUCCESS
 28    // do this by setting status code and description
 29
 30    status.status_code = MW_PARSE_ERROR;
 31    _pw_set_status_desc(&status, "");
 32    if (status.struct_data == nullptr) {
 33        return PwStatus(PW_ERROR_OOM);
 34    }
 35
 36    MwStatusData* status_data = _mw_status_data_ptr(&status);
 37    status_data->line_number = line_number;
 38    status_data->position = char_pos;
 39
 40    va_list ap;
 41    va_start(ap);
 42    _pw_set_status_desc_ap(&status, description, ap);
 43    va_end(ap);
 44    return status;
 45}
 46
 47static bool mw_status_hash(PwMethod_Basic_hash* mthis, PwValuePtr self, PwHashContext* ctx, _PwCompoundChain* tail)
 48{
 49    if (!pw_super(mthis, self, ctx,tail)) {
 50        return false;
 51    }
 52    MwStatusData* data = get_this_mw_status(self);
 53    _pw_hash_uint64(ctx, data->line_number);
 54    _pw_hash_uint64(ctx, data->position);
 55    return true;
 56}
 57
 58static bool mw_status_dump(PwMethod_Basic_dump* mthis, PwValuePtr self, FILE* fp, int indent, _PwCompoundChain* tail)
 59{
 60    if (!pw_super(mthis, self, fp, indent, tail)) {
 61        return false;
 62    }
 63    _pw_print_indent(fp, indent);
 64    MwStatusData* data = get_this_mw_status(self);
 65    fprintf(fp, "Line %u, position %u\n",  data->line_number, data->position);
 66    return true;
 67}
 68
 69static bool mw_status_to_string(PwMethod_Basic_to_string* mthis, PwValuePtr self, PwValuePtr result, _PwCompoundChain* tail)
 70{
 71    if (!pw_super(mthis, self, result, tail)) {
 72        return false;
 73    }
 74    MwStatusData* data = _mw_status_data_ptr(self);
 75
 76    char location[48];
 77    snprintf(location, sizeof(location), " Line %u, position %u: ",
 78             data->line_number, data->position);
 79
 80    return pw_string_append(result, location, nullptr);
 81}
 82
 83static PwInterface_Basic mw_status_basic_interface = {
 84    .hash      = { .func = mw_status_hash },
 85    .dump      = { .func = mw_status_dump },
 86    .to_string = { .func = mw_status_to_string }
 87};
 88
 89[[ gnu::constructor ]]
 90static void init_mw_status()
 91{
 92    _pw_init_types();
 93
 94    if (PwTypeId_MwStatus) {
 95        return;
 96    }
 97
 98    PwTypeId_MwStatus = pw_add_type2("MwStatus", MwStatusData,
 99                                     PW_PARENTS,
100                                        PwTypeId_Status,
101                                     PW_INTERFACES,
102                                        PwInterfaceId_Basic, &mw_status_basic_interface);
103    // init status codes
104    MW_END_OF_BLOCK = pw_define_status("END_OF_BLOCK");
105    MW_PARSE_ERROR  = pw_define_status("PARSE_ERROR");
106}