/*
* nwc, a NanoWasm compiler
* Copyright (C) 2025 Xavier Del Campo Romero
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see .
*/
/*
* Adapted from:
*
* nanowasm, a tiny WebAssembly/Wasm interpreter
* Copyright (C) 2023-2024 Xavier Del Campo Romero
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
*
* Which, in turn, was adapted from the wac project:
* https://github.com/kanaka/wac
*
* Copyright (C) Joel Martin
* The wac project is licensed under the MPL 2.0 (Mozilla Public License
* 2.0). The text of the MPL 2.0 license is included below and can be
* found at https://www.mozilla.org/MPL/2.0/
*/
#include "types.h"
#include
#include
#include
static int read_leb128(FILE *const f, const unsigned maxbits, const bool sign,
unsigned long long *const out)
{
uint8_t byte;
unsigned long long result = 0;
unsigned shift = 0, bcnt = 0;
for (;;)
{
if (!fread(&byte, sizeof byte, 1, f))
{
if (ferror(f))
fprintf(stderr, "%s: ferror\n", __func__);
return -1;
}
result |= (unsigned long long)(byte & 0x7f) << shift;
shift += 7;
if (!(byte & 0x80))
break;
else if (++bcnt > (maxbits + 7u - 1u) / 7u)
{
fprintf(stderr, "%s: overflow\n", __func__);
return -1;
}
}
if (sign && (shift < maxbits) && (byte & 0x40))
result |= -1ll << shift;
*out = result;
return 0;
}
int read_varint1(FILE *const f, varint1 *const out)
{
unsigned long long res;
if (read_leb128(f, 1, true, &res))
return -1;
*out = res;
return 0;
}
int read_varint7(FILE *const f, varint7 *const out)
{
unsigned long long res;
if (read_leb128(f, 7, true, &res))
return -1;
*out = res;
return 0;
}
int read_value_type(FILE *const f, value_type *const out)
{
return read_varint7(f, out);
}
int read_varint32(FILE *const f, varint32 *const out)
{
unsigned long long res;
if (read_leb128(f, 32, true, &res))
return -1;
*out = res;
return 0;
}
int read_varint64(FILE *const f, varint64 *const out)
{
unsigned long long res;
if (read_leb128(f, 64, true, &res))
return -1;
*out = res;
return 0;
}
int read_varuint1(FILE *const f, varuint1 *const out)
{
unsigned long long res;
if (read_leb128(f, 1, false, &res))
return -1;
*out = res;
return 0;
}
int read_varuint7(FILE *const f, varuint7 *const out)
{
unsigned long long res;
if (read_leb128(f, 7, false, &res))
return -1;
*out = res;
return 0;
}
int read_varuint32(FILE *const f, varuint32 *const out)
{
unsigned long long res;
if (read_leb128(f, 32, false, &res))
return -1;
*out = res;
return 0;
}
int read_varuint64(FILE *const f, varuint64 *const out)
{
unsigned long long res;
if (read_leb128(f, 64, false, &res))
return -1;
*out = res;
return 0;
}