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