summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndrew J. Schorr <aschorr@telemetry-investments.com>2017-03-09 20:44:09 -0500
committerAndrew J. Schorr <aschorr@telemetry-investments.com>2017-03-09 20:44:09 -0500
commit39c46265139aa8faf87160b30710876bde4c6ba9 (patch)
tree7d55e7d483a2e35ec675223cf0b3e5755b693a61
parentfeb12baf11e39f60e57b988d29aa96bda4dddcff (diff)
downloadgawk-39c46265139aa8faf87160b30710876bde4c6ba9.tar.gz
For API input field parsing, use an array of structs instead of an array of integers.
-rw-r--r--ChangeLog19
-rw-r--r--awk.h2
-rw-r--r--extension/ChangeLog7
-rw-r--r--extension/readdir_test.c19
-rw-r--r--field.c17
-rw-r--r--gawkapi.h23
-rw-r--r--io.c11
7 files changed, 69 insertions, 29 deletions
diff --git a/ChangeLog b/ChangeLog
index a5fa974c..1d211a02 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,22 @@
+2017-03-09 Andrew J. Schorr <aschorr@telemetry-investments.com>
+
+ * gawkapi.h (awk_input_field_info_t): Define new structure to contain
+ API field parsing info.
+ (awk_input_buf_t): Update get_record prototype to use an array of
+ awk_input_field_info_t instead of integers.
+ * awk.h (set_record): Change 3rd argument from 'const int *' to
+ 'const awk_input_field_info_t *'.
+ * field.c (api_fw): Now points to an array of awk_input_field_info_t
+ instead of integers.
+ (set_record): Change 3rd argument to point to an array of
+ awk_input_field_info_t.
+ (api_parse_field): Update parsing logic to use awk_input_field_info_t
+ structures instead of an array of integers.
+ * io.c (inrec, do_getline_redir, do_getline): Change field_width type
+ from 'const int *' to 'const awk_input_field_info_t *'.
+ (get_a_record): Change field_width argument type from 'const int **'
+ to 'const awk_input_field_info_t **'.
+
2017-03-09 Arnold D. Robbins <arnold@skeeve.com>
* field.c: Minor style edits.
diff --git a/awk.h b/awk.h
index be6a6479..7acb2714 100644
--- a/awk.h
+++ b/awk.h
@@ -1510,7 +1510,7 @@ extern NODE *get_actual_argument(NODE *, int, bool);
#endif
/* field.c */
extern void init_fields(void);
-extern void set_record(const char *buf, int cnt, const int *);
+extern void set_record(const char *buf, int cnt, const awk_input_field_info_t *);
extern void reset_record(void);
extern void rebuild_record(void);
extern void set_NF(void);
diff --git a/extension/ChangeLog b/extension/ChangeLog
index 5d9a194e..bb99f9d8 100644
--- a/extension/ChangeLog
+++ b/extension/ChangeLog
@@ -1,3 +1,10 @@
+2017-03-09 Andrew J. Schorr <aschorr@telemetry-investments.com>
+
+ * readdir_test.c (open_directory_t): Update field_width type from an
+ array of integers to an array of awk_input_field_info_t.
+ (dir_get_record): Ditto.
+ (dir_take_control_of): Ditto.
+
2017-03-07 Andrew J. Schorr <aschorr@telemetry-investments.com>
* Makefile.am (pkgextension_LTLIBRARIES): Remove testext.la, since it
diff --git a/extension/readdir_test.c b/extension/readdir_test.c
index cc23081e..e023b67c 100644
--- a/extension/readdir_test.c
+++ b/extension/readdir_test.c
@@ -85,7 +85,7 @@ int plugin_is_GPL_compatible;
typedef struct open_directory {
DIR *dp;
char *buf;
- int field_width[7];
+ awk_input_field_info_t field_width[4];
} open_directory_t;
/* ftype --- return type of file as a single character string */
@@ -169,7 +169,8 @@ get_inode(struct dirent *entry, const char *dirname)
static int
dir_get_record(char **out, awk_input_buf_t *iobuf, int *errcode,
- char **rt_start, size_t *rt_len, const int **field_width)
+ char **rt_start, size_t *rt_len,
+ const awk_input_field_info_t **field_width)
{
DIR *dp;
struct dirent *dirent;
@@ -206,13 +207,13 @@ dir_get_record(char **out, awk_input_buf_t *iobuf, int *errcode,
#else
len = sprintf(the_dir->buf, "%llu", ino);
#endif
- the_dir->field_width[1] = len;
+ the_dir->field_width[0].len = len;
len += (flen = sprintf(the_dir->buf + len, "/%s", dirent->d_name));
- the_dir->field_width[3] = flen-1;
+ the_dir->field_width[1].len = flen-1;
ftstr = ftype(dirent, iobuf->name);
len += (flen = sprintf(the_dir->buf + len, "/%s", ftstr));
- the_dir->field_width[5] = flen-1;
+ the_dir->field_width[2].len = flen-1;
*out = the_dir->buf;
@@ -284,10 +285,10 @@ dir_take_control_of(awk_input_buf_t *iobuf)
emalloc(the_dir, open_directory_t *, sizeof(open_directory_t), "dir_take_control_of");
the_dir->dp = dp;
/* pre-populate the field_width array with constant values: */
- the_dir->field_width[0] = 0; /* no leading space */
- the_dir->field_width[2] = 1; /* single slash sign separator*/
- the_dir->field_width[4] = 1; /* single slash sign separator*/
- the_dir->field_width[6] = -1; /* terminate it after 3 fields */
+ the_dir->field_width[0].skip = 0; /* no leading space */
+ the_dir->field_width[1].skip = 1; /* single '/' separator */
+ the_dir->field_width[2].skip = 1; /* single '/' separator */
+ the_dir->field_width[3].skip = -1; /* terminate after 3 fields */
size = sizeof(struct dirent) + 21 /* max digits in inode */ + 2 /* slashes */;
emalloc(the_dir->buf, char *, size, "dir_take_control_of");
diff --git a/field.c b/field.c
index 5bdc05f7..5ef4d74b 100644
--- a/field.c
+++ b/field.c
@@ -59,7 +59,7 @@ static long fw_parse_field(long, char **, int, NODE *,
Regexp *, Setfunc, NODE *, NODE *, bool);
static long api_parse_field(long, char **, int, NODE *,
Regexp *, Setfunc, NODE *, NODE *, bool);
-static const int *api_fw = NULL;
+static const awk_input_field_info_t *api_fw = NULL;
static long fpat_parse_field(long, char **, int, NODE *,
Regexp *, Setfunc, NODE *, NODE *, bool);
static void set_element(long num, char * str, long len, NODE *arr);
@@ -262,7 +262,7 @@ rebuild_record()
* but better correct than fast.
*/
void
-set_record(const char *buf, int cnt, const int *fw)
+set_record(const char *buf, int cnt, const awk_input_field_info_t *fw)
{
NODE *n;
static char *databuf;
@@ -802,24 +802,25 @@ api_parse_field(long up_to, /* parse only up to this field number */
long nf = parse_high_water;
char *end = scan + len;
int skiplen;
+ size_t flen;
if (up_to == UNLIMITED)
nf = 0;
if (len == 0)
return nf;
while (nf < up_to) {
- if (((skiplen = api_fw[2*nf]) < 0) ||
- ((len = api_fw[2*nf+1]) < 0)) {
+ if ((skiplen = api_fw[nf].skip) < 0) {
*buf = end;
return nf;
}
if (skiplen > end - scan)
skiplen = end - scan;
scan += skiplen;
- if (len > end - scan)
- len = end - scan;
- (*set)(++nf, scan, (long) len, n);
- scan += len;
+ flen = api_fw[nf].len;
+ if (flen > end - scan)
+ flen = end - scan;
+ (*set)(++nf, scan, (long) flen, n);
+ scan += flen;
}
*buf = scan;
return nf;
diff --git a/gawkapi.h b/gawkapi.h
index 6fa022ca..e744a0fc 100644
--- a/gawkapi.h
+++ b/gawkapi.h
@@ -117,6 +117,19 @@ typedef enum awk_bool {
awk_true
} awk_bool_t; /* we don't use <stdbool.h> on purpose */
+/*
+ * If the input parser would like to specify the field positions in the input
+ * record, it may populate an array of awk_input_field_info_t structures
+ * to indicate the location of each field. The 0th array element contains
+ * the information about field $1, and the NFth element should set skip
+ * to a negative value. For both skip and len, the value should be in
+ * bytes, not (potentially multi-byte) characters.
+ */
+typedef struct {
+ int skip; /* # of bytes to skip before field starts */
+ size_t len; /* # of bytes in field */
+} awk_input_field_info_t;
+
/* The information about input files that input parsers need to know: */
typedef struct awk_input {
const char *name; /* filename */
@@ -149,12 +162,10 @@ typedef struct awk_input {
*
* If field_width is non-NULL, then its value will be initialized
* to NULL, and the function may set it to point to an array of
- * integers supplying field width information to override the default
+ * structures supplying field width information to override the default
* gawk field parsing mechanism. The field_width array should have
- * at least 2*NF+1 elements, and the value of field_width[2*NF]
- * must be negative. The first entry field_width[0] should contain
- * the number of bytes to skip before $1; field_width[1] contains
- * the number of bytes in $1. Note that these values are specified
+ * at least NF+1 elements, and the value of field_width[NF].skip
+ * must be negative. Note that these values are specified
* in bytes, not (potentially multi-byte) characters! And note that this
* array will not be copied by gawk; it must persist at least until the
* next call to get_record or close_func. Note that field_width will
@@ -163,7 +174,7 @@ typedef struct awk_input {
*/
int (*get_record)(char **out, struct awk_input *iobuf, int *errcode,
char **rt_start, size_t *rt_len,
- const int **field_width);
+ const awk_input_field_info_t **field_width);
/*
* No argument prototype on read_func to allow for older systems
diff --git a/io.c b/io.c
index 8aa9da82..b049851f 100644
--- a/io.c
+++ b/io.c
@@ -287,7 +287,7 @@ static RECVALUE rsrescan(IOBUF *iop, struct recmatch *recm, SCANSTATE *state);
static RECVALUE (*matchrec)(IOBUF *iop, struct recmatch *recm, SCANSTATE *state) = rs1scan;
-static int get_a_record(char **out, IOBUF *iop, int *errcode, const int **field_width);
+static int get_a_record(char **out, IOBUF *iop, int *errcode, const awk_input_field_info_t **field_width);
static void free_rp(struct redirect *rp);
@@ -590,7 +590,7 @@ inrec(IOBUF *iop, int *errcode)
char *begin;
int cnt;
bool retval = true;
- const int *field_width = NULL;
+ const awk_input_field_info_t *field_width = NULL;
if (at_eof(iop) && no_data_left(iop))
cnt = EOF;
@@ -2619,7 +2619,7 @@ do_getline_redir(int into_variable, enum redirval redirtype)
NODE *redir_exp = NULL;
NODE **lhs = NULL;
int redir_error = 0;
- const int *field_width = NULL;
+ const awk_input_field_info_t *field_width = NULL;
if (into_variable)
lhs = POP_ADDRESS();
@@ -2688,7 +2688,7 @@ do_getline(int into_variable, IOBUF *iop)
int cnt = EOF;
char *s = NULL;
int errcode;
- const int *field_width = NULL;
+ const awk_input_field_info_t *field_width = NULL;
if (iop == NULL) { /* end of input */
if (into_variable)
@@ -3657,7 +3657,8 @@ static int
get_a_record(char **out, /* pointer to pointer to data */
IOBUF *iop, /* input IOP */
int *errcode, /* pointer to error variable */
- const int **field_width)/* pointer to pointer to field_width array */
+ const awk_input_field_info_t **field_width)
+ /* pointer to pointer to field_width array */
{
struct recmatch recm;
SCANSTATE state;