diff options
Diffstat (limited to 'src/lib/util/plaparse.cpp')
-rw-r--r-- | src/lib/util/plaparse.cpp | 352 |
1 files changed, 186 insertions, 166 deletions
diff --git a/src/lib/util/plaparse.cpp b/src/lib/util/plaparse.cpp index d1e7c679f97..9f4d1c0bc14 100644 --- a/src/lib/util/plaparse.cpp +++ b/src/lib/util/plaparse.cpp @@ -1,22 +1,24 @@ // license:BSD-3-Clause -// copyright-holders:Aaron Giles, hap +// copyright-holders:Aaron Giles, Curt Coder, hap /*************************************************************************** - plaparse.h + plaparse.cpp - Simple parser for Berkeley standard PLA files into raw fusemaps. - It supports no more than one output matrix, and is limited to - keywords: i, o, p, phase, e + Parser for Berkeley standard (aka Espresso) PLA files into raw fusemaps. + It supports no more than one output matrix, and is limited to keywords: + i, o, p, phase, e ***************************************************************************/ -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <ctype.h> -#include "jedparse.h" #include "plaparse.h" +#include "ioprocs.h" + +#include <cstdio> +#include <cstdlib> +#include <cstring> +#include <cctype> + /*************************************************************************** @@ -33,10 +35,10 @@ struct parse_info { - uint32_t inputs; /* number of input columns */ - uint32_t outputs; /* number of output columns */ - uint32_t terms; /* number of terms */ - uint32_t xorval[JED_MAX_FUSES/64]; /* output polarity */ + uint32_t inputs; // number of input columns + uint32_t outputs; // number of output columns + uint32_t terms; // number of terms + uint32_t xorval[JED_MAX_FUSES/64]; // output polarity uint32_t xorptr; }; @@ -61,19 +63,30 @@ static bool iscrlf(char c) character stream -------------------------------------------------*/ -static uint32_t suck_number(const uint8_t **src, const uint8_t *srcend) +static uint32_t suck_number(util::random_read &src) { uint32_t value = 0; // find first digit - while (*src < srcend && !iscrlf(**src) && !isdigit(**src)) - (*src)++; - - // loop over and accumulate digits - while (*src < srcend && isdigit(**src)) + bool found = false; + while (true) { - value = value * 10 + (**src) - '0'; - (*src)++; + uint8_t ch; + auto const [err, actual] = read(src, &ch, 1); + if (err || (1 != actual)) + break; + + // loop over and accumulate digits + if (isdigit(ch)) + { + found = true; + value = value * 10 + ch - '0'; + } + else if (found || iscrlf(ch)) + { + src.seek(-1, SEEK_CUR); + break; + } } return value; @@ -89,89 +102,85 @@ static uint32_t suck_number(const uint8_t **src, const uint8_t *srcend) process_terms - process input/output matrix -------------------------------------------------*/ -static bool process_terms(jed_data *data, const uint8_t **src, const uint8_t *srcend, parse_info *pinfo) +static bool process_terms(jed_data *data, util::random_read &src, uint8_t ch, parse_info *pinfo) { uint32_t curinput = 0; uint32_t curoutput = 0; bool outputs = false; - // symbols for 0, 1, dont_care, no_meaning - // PLA format documentation also describes them as simply 0, 1, 2, 3 - static const char symbols[] = { "01-~" }; - - while (*src < srcend && **src != '.' && **src != '#') + while (ch != '.' && ch != '#') { if (!outputs) { // and-matrix - if (strrchr(symbols, **src)) + switch (ch) + { + case '0': curinput++; + jed_set_fuse(data, data->numfuses++, 0); + jed_set_fuse(data, data->numfuses++, 1); + if (LOG_PARSE) printf("01"); + break; - switch (**src) - { - case '0': - jed_set_fuse(data, data->numfuses++, 0); - jed_set_fuse(data, data->numfuses++, 1); - - if (LOG_PARSE) printf("01"); - break; - - case '1': - jed_set_fuse(data, data->numfuses++, 1); - jed_set_fuse(data, data->numfuses++, 0); - - if (LOG_PARSE) printf("10"); - break; - - // anything goes - case '-': - jed_set_fuse(data, data->numfuses++, 1); - jed_set_fuse(data, data->numfuses++, 1); - - if (LOG_PARSE) printf("11"); - break; - - // this product term is inhibited - case '~': - jed_set_fuse(data, data->numfuses++, 0); - jed_set_fuse(data, data->numfuses++, 0); - - if (LOG_PARSE) printf("00"); - break; - - case ' ': case '\t': - if (curinput > 0) - { - outputs = true; - if (LOG_PARSE) printf(" "); - } - break; - - default: - break; + case '1': + curinput++; + jed_set_fuse(data, data->numfuses++, 1); + jed_set_fuse(data, data->numfuses++, 0); + if (LOG_PARSE) printf("10"); + break; + + // anything goes + case '-': + curinput++; + jed_set_fuse(data, data->numfuses++, 1); + jed_set_fuse(data, data->numfuses++, 1); + if (LOG_PARSE) printf("11"); + break; + + // this product term is inhibited + case '~': + curinput++; + jed_set_fuse(data, data->numfuses++, 0); + jed_set_fuse(data, data->numfuses++, 0); + if (LOG_PARSE) printf("00"); + break; + + case ' ': case '\t': + if (curinput > 0) + { + outputs = true; + if (LOG_PARSE) printf(" "); + } + break; + + default: + break; } } else { // or-matrix - if (strrchr(symbols, **src)) + switch (ch) { + case '1': curoutput++; - if (**src == '1') - { - jed_set_fuse(data, data->numfuses++, 0); - if (LOG_PARSE) printf("0"); - } - else - { - // write 1 for anything else - jed_set_fuse(data, data->numfuses++, 1); - if (LOG_PARSE) printf("1"); - } + jed_set_fuse(data, data->numfuses++, 0); + if (LOG_PARSE) printf("0"); + break; + + // write 1 for anything else + case '0': case '-': case '~': + curoutput++; + jed_set_fuse(data, data->numfuses++, 1); + if (LOG_PARSE) printf("1"); + break; + + default: + break; } } - if (iscrlf(**src) && outputs) + if (iscrlf(ch) && outputs) { outputs = false; if (LOG_PARSE) printf("\n"); @@ -183,9 +192,14 @@ static bool process_terms(jed_data *data, const uint8_t **src, const uint8_t *sr curoutput = 0; } - (*src)++; + auto const [err, actual] = read(src, &ch, 1); + if (err) + return false; + if (actual != 1) + return true; } + src.seek(-1, SEEK_CUR); return true; } @@ -195,7 +209,7 @@ static bool process_terms(jed_data *data, const uint8_t **src, const uint8_t *sr process_field - process a single field -------------------------------------------------*/ -static bool process_field(jed_data *data, const uint8_t **src, const uint8_t *srcend, parse_info *pinfo) +static bool process_field(jed_data *data, util::random_read &src, parse_info *pinfo) { // valid keywords static const char *const keywords[] = { "i", "o", "p", "phase", "e", "\0" }; @@ -212,15 +226,18 @@ static bool process_field(jed_data *data, const uint8_t **src, const uint8_t *sr // find keyword char dest[0x10]; - memset(dest, 0, ARRAY_LENGTH(dest)); - const uint8_t *seek = *src; + memset(dest, 0, sizeof(dest)); int destptr = 0; - while (seek < srcend && isalpha(*seek) && destptr < ARRAY_LENGTH(dest) - 1) + uint8_t seek; + while (true) { - dest[destptr] = tolower(*seek); - seek++; - destptr++; + auto const [err, actual] = read(src, &seek, 1); + if (err || (actual != 1) || !isalpha(seek)) + break; + dest[destptr++] = tolower(seek); + if (destptr == sizeof(dest)) + break; } uint8_t find = 0; @@ -230,58 +247,58 @@ static bool process_field(jed_data *data, const uint8_t **src, const uint8_t *sr if (find == KW_INVALID) return false; - (*src) += strlen(keywords[find]); - // handle it switch (find) { - // number of inputs - case KW_INPUTS: - pinfo->inputs = suck_number(src, srcend); - if (pinfo->inputs == 0 || pinfo->inputs >= (JED_MAX_FUSES/2)) - return false; - - if (LOG_PARSE) printf("Inputs: %u\n", pinfo->inputs); - break; - - // number of outputs - case KW_OUTPUTS: - pinfo->outputs = suck_number(src, srcend); - if (pinfo->outputs == 0 || pinfo->outputs >= (JED_MAX_FUSES/2)) - return false; - - if (LOG_PARSE) printf("Outputs: %u\n", pinfo->outputs); - break; - - // number of product terms (optional) - case KW_TERMS: - pinfo->terms = suck_number(src, srcend); - if (pinfo->terms == 0 || pinfo->terms >= (JED_MAX_FUSES/2)) - return false; - - if (LOG_PARSE) printf("Terms: %u\n", pinfo->terms); - break; - - // output polarity (optional) - case KW_PHASE: - if (LOG_PARSE) printf("Phase...\n"); - while (*src < srcend && !iscrlf(**src) && pinfo->xorptr < (JED_MAX_FUSES/2)) + // number of inputs + case KW_INPUTS: + pinfo->inputs = suck_number(src); + if (pinfo->inputs == 0 || pinfo->inputs >= (JED_MAX_FUSES/2)) + return false; + + if (LOG_PARSE) printf("Inputs: %u\n", pinfo->inputs); + break; + + // number of outputs + case KW_OUTPUTS: + pinfo->outputs = suck_number(src); + if (pinfo->outputs == 0 || pinfo->outputs >= (JED_MAX_FUSES/2)) + return false; + + if (LOG_PARSE) printf("Outputs: %u\n", pinfo->outputs); + break; + + // number of product terms (optional) + case KW_TERMS: + pinfo->terms = suck_number(src); + if (pinfo->terms == 0 || pinfo->terms >= (JED_MAX_FUSES/2)) + return false; + + if (LOG_PARSE) printf("Terms: %u\n", pinfo->terms); + break; + + // output polarity (optional) + case KW_PHASE: + if (LOG_PARSE) printf("Phase...\n"); + while (true) + { + auto const [err, actual] = read(src, &seek, 1); + if (err || (actual != 1) || iscrlf(seek) || (pinfo->xorptr >= (JED_MAX_FUSES / 2))) + break; + if (seek == '0' || seek == '1') { - if (**src == '0' || **src == '1') - { - // 0 is negative - if (**src == '0') - pinfo->xorval[pinfo->xorptr/32] |= 1 << (pinfo->xorptr & 31); - pinfo->xorptr++; - } - (*src)++; + // 0 is negative + if (seek == '0') + pinfo->xorval[pinfo->xorptr/32] |= 1 << (pinfo->xorptr & 31); + pinfo->xorptr++; } - break; + } + break; - // end of file (optional) - case KW_END: - if (LOG_PARSE) printf("End of file\n"); - break; + // end of file (optional) + case KW_END: + if (LOG_PARSE) printf("End of file\n"); + break; } return true; @@ -295,54 +312,57 @@ static bool process_field(jed_data *data, const uint8_t **src, const uint8_t *sr -------------------------------------------------*/ /** - * @fn int pla_parse(const void *data, size_t length, jed_data *result) + * @fn int pla_parse(util::random_read &src, jed_data *result) * * @brief Pla parse. * - * @param data The data. - * @param length The length. + * @param src The source file. * @param [out] result If non-null, the result. * * @return An int. */ -int pla_parse(const void *data, size_t length, jed_data *result) +int pla_parse(util::random_read &src, jed_data *result) { - const uint8_t *src = (const uint8_t *)data; - const uint8_t *srcend = src + length; - parse_info pinfo; memset(&pinfo, 0, sizeof(pinfo)); result->numfuses = 0; memset(result->fusemap, 0, sizeof(result->fusemap)); - while (src < srcend) + while (true) { - switch (*src) + std::error_condition err; + size_t actual; + uint8_t ch; + std::tie(err, actual) = read(src, &ch, 1); + if (err || (actual != 1)) + break; + switch (ch) { - // comment line - case '#': - while (src < srcend && !iscrlf(*src)) - src++; - break; + // comment line + case '#': + do + { + std::tie(err, actual) = read(src, &ch, 1); + } + while (!err && (actual == 1) && !iscrlf(ch)); + break; - // keyword - case '.': - src++; - if (!process_field(result, &src, srcend, &pinfo)) - return JEDERR_INVALID_DATA; - break; + // keyword + case '.': + if (!process_field(result, src, &pinfo)) + return JEDERR_INVALID_DATA; + break; - // terms - case '0': case '1': case '-': case '~': - if (!process_terms(result, &src, srcend, &pinfo)) - return JEDERR_INVALID_DATA; - break; + // terms + case '0': case '1': case '-': case '~': + if (!process_terms(result, src, ch, &pinfo)) + return JEDERR_INVALID_DATA; + break; - default: - src++; - break; + default: + break; } } |