summaryrefslogtreecommitdiffstatshomepage
path: root/src/lib/util/plaparse.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/lib/util/plaparse.cpp')
-rw-r--r--src/lib/util/plaparse.cpp352
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;
}
}