|
Packit Service |
f629e6 |
/*
|
|
Packit Service |
f629e6 |
* rwarray.c - Builtin functions to binary read / write arrays to a file.
|
|
Packit Service |
f629e6 |
*
|
|
Packit Service |
f629e6 |
* Arnold Robbins
|
|
Packit Service |
f629e6 |
* May 2009
|
|
Packit Service |
f629e6 |
* Redone June 2012
|
|
Packit Service |
f629e6 |
* Improved September 2017
|
|
Packit Service |
f629e6 |
*/
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
/*
|
|
Packit Service |
f629e6 |
* Copyright (C) 2009-2014, 2017 the Free Software Foundation, Inc.
|
|
Packit Service |
f629e6 |
*
|
|
Packit Service |
f629e6 |
* This file is part of GAWK, the GNU implementation of the
|
|
Packit Service |
f629e6 |
* AWK Programming Language.
|
|
Packit Service |
f629e6 |
*
|
|
Packit Service |
f629e6 |
* GAWK is free software; you can redistribute it and/or modify
|
|
Packit Service |
f629e6 |
* it under the terms of the GNU General Public License as published by
|
|
Packit Service |
f629e6 |
* the Free Software Foundation; either version 3 of the License, or
|
|
Packit Service |
f629e6 |
* (at your option) any later version.
|
|
Packit Service |
f629e6 |
*
|
|
Packit Service |
f629e6 |
* GAWK is distributed in the hope that it will be useful,
|
|
Packit Service |
f629e6 |
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
Packit Service |
f629e6 |
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
Packit Service |
f629e6 |
* GNU General Public License for more details.
|
|
Packit Service |
f629e6 |
*
|
|
Packit Service |
f629e6 |
* You should have received a copy of the GNU General Public License
|
|
Packit Service |
f629e6 |
* along with this program; if not, write to the Free Software
|
|
Packit Service |
f629e6 |
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
|
Packit Service |
f629e6 |
*/
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
#ifdef HAVE_CONFIG_H
|
|
Packit Service |
f629e6 |
#include <config.h>
|
|
Packit Service |
f629e6 |
#endif
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
#include <stdio.h>
|
|
Packit Service |
f629e6 |
#include <assert.h>
|
|
Packit Service |
f629e6 |
#include <errno.h>
|
|
Packit Service |
f629e6 |
#include <fcntl.h>
|
|
Packit Service |
f629e6 |
#include <stdlib.h>
|
|
Packit Service |
f629e6 |
#include <string.h>
|
|
Packit Service |
f629e6 |
#include <unistd.h>
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
#ifdef __MINGW32__
|
|
Packit Service |
f629e6 |
#include <winsock2.h>
|
|
Packit Service |
f629e6 |
#include <stdint.h>
|
|
Packit Service |
f629e6 |
#else
|
|
Packit Service |
f629e6 |
#include <arpa/inet.h>
|
|
Packit Service |
f629e6 |
#endif
|
|
Packit Service |
f629e6 |
#include <sys/types.h>
|
|
Packit Service |
f629e6 |
#include <sys/stat.h>
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
#include "gawkapi.h"
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
#include "gettext.h"
|
|
Packit Service |
f629e6 |
#define _(msgid) gettext(msgid)
|
|
Packit Service |
f629e6 |
#define N_(msgid) msgid
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
#define MAGIC "awkrulz\n"
|
|
Packit Service |
f629e6 |
#define MAJOR 3
|
|
Packit Service |
f629e6 |
#define MINOR 1
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
static const gawk_api_t *api; /* for convenience macros to work */
|
|
Packit Service |
f629e6 |
static awk_ext_id_t ext_id;
|
|
Packit Service |
f629e6 |
static const char *ext_version = "rwarray extension: version 1.2";
|
|
Packit Service |
f629e6 |
static awk_bool_t (*init_func)(void) = NULL;
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
int plugin_is_GPL_compatible;
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
static awk_bool_t write_array(FILE *fp, awk_array_t array);
|
|
Packit Service |
f629e6 |
static awk_bool_t write_elem(FILE *fp, awk_element_t *element);
|
|
Packit Service |
f629e6 |
static awk_bool_t write_value(FILE *fp, awk_value_t *val);
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
static awk_bool_t read_array(FILE *fp, awk_array_t array);
|
|
Packit Service |
f629e6 |
static awk_bool_t read_elem(FILE *fp, awk_element_t *element);
|
|
Packit Service |
f629e6 |
static awk_bool_t read_value(FILE *fp, awk_value_t *value);
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
/*
|
|
Packit Service |
f629e6 |
* Format of array info:
|
|
Packit Service |
f629e6 |
*
|
|
Packit Service |
f629e6 |
* MAGIC 8 bytes
|
|
Packit Service |
f629e6 |
* Major version 4 bytes - network order
|
|
Packit Service |
f629e6 |
* Minor version 4 bytes - network order
|
|
Packit Service |
f629e6 |
* Element count 4 bytes - network order
|
|
Packit Service |
f629e6 |
* Elements
|
|
Packit Service |
f629e6 |
*
|
|
Packit Service |
f629e6 |
* For each element:
|
|
Packit Service |
f629e6 |
* Length of index val: 4 bytes - network order
|
|
Packit Service |
f629e6 |
* Index val as characters (N bytes)
|
|
Packit Service |
f629e6 |
* Value type 4 bytes (0 = string, 1 = number, 2 = array, 3 = regex, 4 = strnum, 5 = undefined)
|
|
Packit Service |
f629e6 |
* IF string:
|
|
Packit Service |
f629e6 |
* Length of value 4 bytes
|
|
Packit Service |
f629e6 |
* Value as characters (N bytes)
|
|
Packit Service |
f629e6 |
* ELSE IF number:
|
|
Packit Service |
f629e6 |
* 8 bytes as native double
|
|
Packit Service |
f629e6 |
* ELSE
|
|
Packit Service |
f629e6 |
* Element count
|
|
Packit Service |
f629e6 |
* Elements
|
|
Packit Service |
f629e6 |
* END IF
|
|
Packit Service |
f629e6 |
*/
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
/* do_writea --- write an array */
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
static awk_value_t *
|
|
Packit Service |
f629e6 |
do_writea(int nargs, awk_value_t *result, struct awk_ext_func *unused)
|
|
Packit Service |
f629e6 |
{
|
|
Packit Service |
f629e6 |
awk_value_t filename, array;
|
|
Packit Service |
f629e6 |
FILE *fp = NULL;
|
|
Packit Service |
f629e6 |
uint32_t major = MAJOR;
|
|
Packit Service |
f629e6 |
uint32_t minor = MINOR;
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
assert(result != NULL);
|
|
Packit Service |
f629e6 |
make_number(0.0, result);
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
if (nargs < 2)
|
|
Packit Service |
f629e6 |
goto out;
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
/* filename is first arg, array to dump is second */
|
|
Packit Service |
f629e6 |
if (! get_argument(0, AWK_STRING, & filename)) {
|
|
Packit Service |
f629e6 |
fprintf(stderr, _("do_writea: argument 0 is not a string\n"));
|
|
Packit Service |
f629e6 |
errno = EINVAL;
|
|
Packit Service |
f629e6 |
goto done1;
|
|
Packit Service |
f629e6 |
}
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
if (! get_argument(1, AWK_ARRAY, & array)) {
|
|
Packit Service |
f629e6 |
fprintf(stderr, _("do_writea: argument 1 is not an array\n"));
|
|
Packit Service |
f629e6 |
errno = EINVAL;
|
|
Packit Service |
f629e6 |
goto done1;
|
|
Packit Service |
f629e6 |
}
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
/* open the file, if error, set ERRNO and return */
|
|
Packit Service |
f629e6 |
fp = fopen(filename.str_value.str, "wb");
|
|
Packit Service |
f629e6 |
if (fp == NULL)
|
|
Packit Service |
f629e6 |
goto done1;
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
if (fwrite(MAGIC, 1, strlen(MAGIC), fp) != strlen(MAGIC))
|
|
Packit Service |
f629e6 |
goto done1;
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
major = htonl(major);
|
|
Packit Service |
f629e6 |
if (fwrite(& major, 1, sizeof(major), fp) != sizeof(major))
|
|
Packit Service |
f629e6 |
goto done1;
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
minor = htonl(minor);
|
|
Packit Service |
f629e6 |
if (fwrite(& minor, 1, sizeof(minor), fp) != sizeof(minor))
|
|
Packit Service |
f629e6 |
goto done1;
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
if (write_array(fp, array.array_cookie)) {
|
|
Packit Service |
f629e6 |
make_number(1.0, result);
|
|
Packit Service |
f629e6 |
goto done0;
|
|
Packit Service |
f629e6 |
}
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
done1:
|
|
Packit Service |
f629e6 |
update_ERRNO_int(errno);
|
|
Packit Service |
f629e6 |
unlink(filename.str_value.str);
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
done0:
|
|
Packit Service |
f629e6 |
fclose(fp);
|
|
Packit Service |
f629e6 |
out:
|
|
Packit Service |
f629e6 |
return result;
|
|
Packit Service |
f629e6 |
}
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
/* write_array --- write out an array or a sub-array */
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
static awk_bool_t
|
|
Packit Service |
f629e6 |
write_array(FILE *fp, awk_array_t array)
|
|
Packit Service |
f629e6 |
{
|
|
Packit Service |
f629e6 |
uint32_t i;
|
|
Packit Service |
f629e6 |
uint32_t count;
|
|
Packit Service |
f629e6 |
awk_flat_array_t *flat_array;
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
if (! flatten_array(array, & flat_array)) {
|
|
Packit Service |
f629e6 |
fprintf(stderr, _("write_array: could not flatten array\n"));
|
|
Packit Service |
f629e6 |
return awk_false;
|
|
Packit Service |
f629e6 |
}
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
count = htonl(flat_array->count);
|
|
Packit Service |
f629e6 |
if (fwrite(& count, 1, sizeof(count), fp) != sizeof(count))
|
|
Packit Service |
f629e6 |
return awk_false;
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
for (i = 0; i < flat_array->count; i++) {
|
|
Packit Service |
f629e6 |
if (! write_elem(fp, & flat_array->elements[i])) {
|
|
Packit Service |
f629e6 |
(void) release_flattened_array(array, flat_array);
|
|
Packit Service |
f629e6 |
return awk_false;
|
|
Packit Service |
f629e6 |
}
|
|
Packit Service |
f629e6 |
}
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
if (! release_flattened_array(array, flat_array)) {
|
|
Packit Service |
f629e6 |
fprintf(stderr, _("write_array: could not release flattened array\n"));
|
|
Packit Service |
f629e6 |
return awk_false;
|
|
Packit Service |
f629e6 |
}
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
return awk_true;
|
|
Packit Service |
f629e6 |
}
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
/* write_elem --- write out a single element */
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
static awk_bool_t
|
|
Packit Service |
f629e6 |
write_elem(FILE *fp, awk_element_t *element)
|
|
Packit Service |
f629e6 |
{
|
|
Packit Service |
f629e6 |
uint32_t indexval_len;
|
|
Packit Service |
f629e6 |
ssize_t write_count;
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
indexval_len = htonl(element->index.str_value.len);
|
|
Packit Service |
f629e6 |
if (fwrite(& indexval_len, 1, sizeof(indexval_len), fp) != sizeof(indexval_len))
|
|
Packit Service |
f629e6 |
return awk_false;
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
if (element->index.str_value.len > 0) {
|
|
Packit Service |
f629e6 |
write_count = fwrite(element->index.str_value.str,
|
|
Packit Service |
f629e6 |
1, element->index.str_value.len, fp);
|
|
Packit Service |
f629e6 |
if (write_count != (ssize_t) element->index.str_value.len)
|
|
Packit Service |
f629e6 |
return awk_false;
|
|
Packit Service |
f629e6 |
}
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
return write_value(fp, & element->value);
|
|
Packit Service |
f629e6 |
}
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
/* write_value --- write a number or a string or a strnum or a regex or an array */
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
static awk_bool_t
|
|
Packit Service |
f629e6 |
write_value(FILE *fp, awk_value_t *val)
|
|
Packit Service |
f629e6 |
{
|
|
Packit Service |
f629e6 |
uint32_t code, len;
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
if (val->val_type == AWK_ARRAY) {
|
|
Packit Service |
f629e6 |
code = htonl(2);
|
|
Packit Service |
f629e6 |
if (fwrite(& code, 1, sizeof(code), fp) != sizeof(code))
|
|
Packit Service |
f629e6 |
return awk_false;
|
|
Packit Service |
f629e6 |
return write_array(fp, val->array_cookie);
|
|
Packit Service |
f629e6 |
}
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
if (val->val_type == AWK_NUMBER) {
|
|
Packit Service |
f629e6 |
code = htonl(1);
|
|
Packit Service |
f629e6 |
if (fwrite(& code, 1, sizeof(code), fp) != sizeof(code))
|
|
Packit Service |
f629e6 |
return awk_false;
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
if (fwrite(& val->num_value, 1, sizeof(val->num_value), fp) != sizeof(val->num_value))
|
|
Packit Service |
f629e6 |
return awk_false;
|
|
Packit Service |
f629e6 |
} else {
|
|
Packit Service |
f629e6 |
switch (val->val_type) {
|
|
Packit Service |
f629e6 |
case AWK_STRING:
|
|
Packit Service |
f629e6 |
code = htonl(0);
|
|
Packit Service |
f629e6 |
break;
|
|
Packit Service |
f629e6 |
case AWK_STRNUM:
|
|
Packit Service |
f629e6 |
code = htonl(4);
|
|
Packit Service |
f629e6 |
break;
|
|
Packit Service |
f629e6 |
case AWK_REGEX:
|
|
Packit Service |
f629e6 |
code = htonl(3);
|
|
Packit Service |
f629e6 |
break;
|
|
Packit Service |
f629e6 |
case AWK_UNDEFINED:
|
|
Packit Service |
f629e6 |
code = htonl(5);
|
|
Packit Service |
f629e6 |
break;
|
|
Packit Service |
f629e6 |
default:
|
|
Packit Service |
f629e6 |
/* XXX can this happen? */
|
|
Packit Service |
f629e6 |
code = htonl(0);
|
|
Packit Service |
f629e6 |
warning(ext_id, _("array value has unknown type %d"), val->val_type);
|
|
Packit Service |
f629e6 |
break;
|
|
Packit Service |
f629e6 |
}
|
|
Packit Service |
f629e6 |
if (fwrite(& code, 1, sizeof(code), fp) != sizeof(code))
|
|
Packit Service |
f629e6 |
return awk_false;
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
len = htonl(val->str_value.len);
|
|
Packit Service |
f629e6 |
if (fwrite(& len, 1, sizeof(len), fp) != sizeof(len))
|
|
Packit Service |
f629e6 |
return awk_false;
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
if (fwrite(val->str_value.str, 1, val->str_value.len, fp)
|
|
Packit Service |
f629e6 |
!= (ssize_t) val->str_value.len)
|
|
Packit Service |
f629e6 |
return awk_false;
|
|
Packit Service |
f629e6 |
}
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
return awk_true;
|
|
Packit Service |
f629e6 |
}
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
/* do_reada --- read an array */
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
static awk_value_t *
|
|
Packit Service |
f629e6 |
do_reada(int nargs, awk_value_t *result, struct awk_ext_func *unused)
|
|
Packit Service |
f629e6 |
{
|
|
Packit Service |
f629e6 |
awk_value_t filename, array;
|
|
Packit Service |
f629e6 |
FILE *fp = NULL;
|
|
Packit Service |
f629e6 |
uint32_t major;
|
|
Packit Service |
f629e6 |
uint32_t minor;
|
|
Packit Service |
f629e6 |
char magic_buf[30];
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
assert(result != NULL);
|
|
Packit Service |
f629e6 |
make_number(0.0, result);
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
if (nargs < 2)
|
|
Packit Service |
f629e6 |
goto out;
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
/* directory is first arg, array to read is second */
|
|
Packit Service |
f629e6 |
if (! get_argument(0, AWK_STRING, & filename)) {
|
|
Packit Service |
f629e6 |
fprintf(stderr, _("do_reada: argument 0 is not a string\n"));
|
|
Packit Service |
f629e6 |
errno = EINVAL;
|
|
Packit Service |
f629e6 |
goto done1;
|
|
Packit Service |
f629e6 |
}
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
if (! get_argument(1, AWK_ARRAY, & array)) {
|
|
Packit Service |
f629e6 |
fprintf(stderr, _("do_reada: argument 1 is not an array\n"));
|
|
Packit Service |
f629e6 |
errno = EINVAL;
|
|
Packit Service |
f629e6 |
goto done1;
|
|
Packit Service |
f629e6 |
}
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
fp = fopen(filename.str_value.str, "rb");
|
|
Packit Service |
f629e6 |
if (fp == NULL)
|
|
Packit Service |
f629e6 |
goto done1;
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
memset(magic_buf, '\0', sizeof(magic_buf));
|
|
Packit Service |
f629e6 |
if (fread(magic_buf, 1, strlen(MAGIC), fp) != strlen(MAGIC)) {
|
|
Packit Service |
f629e6 |
errno = EBADF;
|
|
Packit Service |
f629e6 |
goto done1;
|
|
Packit Service |
f629e6 |
}
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
if (strcmp(magic_buf, MAGIC) != 0) {
|
|
Packit Service |
f629e6 |
errno = EBADF;
|
|
Packit Service |
f629e6 |
goto done1;
|
|
Packit Service |
f629e6 |
}
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
if (fread(& major, 1, sizeof(major), fp) != sizeof(major)) {
|
|
Packit Service |
f629e6 |
errno = EBADF;
|
|
Packit Service |
f629e6 |
goto done1;
|
|
Packit Service |
f629e6 |
}
|
|
Packit Service |
f629e6 |
major = ntohl(major);
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
if (major != MAJOR) {
|
|
Packit Service |
f629e6 |
errno = EBADF;
|
|
Packit Service |
f629e6 |
goto done1;
|
|
Packit Service |
f629e6 |
}
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
if (fread(& minor, 1, sizeof(minor), fp) != sizeof(minor)) {
|
|
Packit Service |
f629e6 |
/* read() sets errno */
|
|
Packit Service |
f629e6 |
goto done1;
|
|
Packit Service |
f629e6 |
}
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
minor = ntohl(minor);
|
|
Packit Service |
f629e6 |
if (minor != MINOR) {
|
|
Packit Service |
f629e6 |
errno = EBADF;
|
|
Packit Service |
f629e6 |
goto done1;
|
|
Packit Service |
f629e6 |
}
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
if (! clear_array(array.array_cookie)) {
|
|
Packit Service |
f629e6 |
errno = ENOMEM;
|
|
Packit Service |
f629e6 |
fprintf(stderr, _("do_reada: clear_array failed\n"));
|
|
Packit Service |
f629e6 |
goto done1;
|
|
Packit Service |
f629e6 |
}
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
if (read_array(fp, array.array_cookie)) {
|
|
Packit Service |
f629e6 |
make_number(1.0, result);
|
|
Packit Service |
f629e6 |
goto done0;
|
|
Packit Service |
f629e6 |
}
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
done1:
|
|
Packit Service |
f629e6 |
update_ERRNO_int(errno);
|
|
Packit Service |
f629e6 |
done0:
|
|
Packit Service |
f629e6 |
if (fp != NULL)
|
|
Packit Service |
f629e6 |
fclose(fp);
|
|
Packit Service |
f629e6 |
out:
|
|
Packit Service |
f629e6 |
return result;
|
|
Packit Service |
f629e6 |
}
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
/* read_array --- read in an array or sub-array */
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
static awk_bool_t
|
|
Packit Service |
f629e6 |
read_array(FILE *fp, awk_array_t array)
|
|
Packit Service |
f629e6 |
{
|
|
Packit Service |
f629e6 |
uint32_t i;
|
|
Packit Service |
f629e6 |
uint32_t count;
|
|
Packit Service |
f629e6 |
awk_element_t new_elem;
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
if (fread(& count, 1, sizeof(count), fp) != sizeof(count))
|
|
Packit Service |
f629e6 |
return awk_false;
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
count = ntohl(count);
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
for (i = 0; i < count; i++) {
|
|
Packit Service |
f629e6 |
if (read_elem(fp, & new_elem)) {
|
|
Packit Service |
f629e6 |
/* add to array */
|
|
Packit Service |
f629e6 |
if (! set_array_element_by_elem(array, & new_elem)) {
|
|
Packit Service |
f629e6 |
fprintf(stderr, _("read_array: set_array_element failed\n"));
|
|
Packit Service |
f629e6 |
return awk_false;
|
|
Packit Service |
f629e6 |
}
|
|
Packit Service |
f629e6 |
} else
|
|
Packit Service |
f629e6 |
break;
|
|
Packit Service |
f629e6 |
}
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
if (i != count)
|
|
Packit Service |
f629e6 |
return awk_false;
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
return awk_true;
|
|
Packit Service |
f629e6 |
}
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
/* read_elem --- read in a single element */
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
static awk_bool_t
|
|
Packit Service |
f629e6 |
read_elem(FILE *fp, awk_element_t *element)
|
|
Packit Service |
f629e6 |
{
|
|
Packit Service |
f629e6 |
uint32_t index_len;
|
|
Packit Service |
f629e6 |
static char *buffer;
|
|
Packit Service |
f629e6 |
static uint32_t buflen;
|
|
Packit Service |
f629e6 |
ssize_t ret;
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
if ((ret = fread(& index_len, 1, sizeof(index_len), fp)) != sizeof(index_len)) {
|
|
Packit Service |
f629e6 |
return awk_false;
|
|
Packit Service |
f629e6 |
}
|
|
Packit Service |
f629e6 |
index_len = ntohl(index_len);
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
memset(element, 0, sizeof(*element));
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
if (index_len > 0) {
|
|
Packit Service |
f629e6 |
if (buffer == NULL) {
|
|
Packit Service |
f629e6 |
/* allocate buffer */
|
|
Packit Service |
f629e6 |
emalloc(buffer, char *, index_len, "read_elem");
|
|
Packit Service |
f629e6 |
buflen = index_len;
|
|
Packit Service |
f629e6 |
} else if (buflen < index_len) {
|
|
Packit Service |
f629e6 |
/* reallocate buffer */
|
|
Packit Service |
f629e6 |
char *cp = gawk_realloc(buffer, index_len);
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
if (cp == NULL)
|
|
Packit Service |
f629e6 |
return awk_false;
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
buffer = cp;
|
|
Packit Service |
f629e6 |
buflen = index_len;
|
|
Packit Service |
f629e6 |
}
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
if (fread(buffer, 1, index_len, fp) != (ssize_t) index_len) {
|
|
Packit Service |
f629e6 |
return awk_false;
|
|
Packit Service |
f629e6 |
}
|
|
Packit Service |
f629e6 |
make_const_string(buffer, index_len, & element->index);
|
|
Packit Service |
f629e6 |
} else {
|
|
Packit Service |
f629e6 |
make_null_string(& element->index);
|
|
Packit Service |
f629e6 |
}
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
if (! read_value(fp, & element->value))
|
|
Packit Service |
f629e6 |
return awk_false;
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
return awk_true;
|
|
Packit Service |
f629e6 |
}
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
/* read_value --- read a number or a string */
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
static awk_bool_t
|
|
Packit Service |
f629e6 |
read_value(FILE *fp, awk_value_t *value)
|
|
Packit Service |
f629e6 |
{
|
|
Packit Service |
f629e6 |
uint32_t code, len;
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
if (fread(& code, 1, sizeof(code), fp) != sizeof(code))
|
|
Packit Service |
f629e6 |
return awk_false;
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
code = ntohl(code);
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
if (code == 2) {
|
|
Packit Service |
f629e6 |
awk_array_t array = create_array();
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
if (! read_array(fp, array))
|
|
Packit Service |
f629e6 |
return awk_false;
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
/* hook into value */
|
|
Packit Service |
f629e6 |
value->val_type = AWK_ARRAY;
|
|
Packit Service |
f629e6 |
value->array_cookie = array;
|
|
Packit Service |
f629e6 |
} else if (code == 1) {
|
|
Packit Service |
f629e6 |
double d;
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
if (fread(& d, 1, sizeof(d), fp) != sizeof(d))
|
|
Packit Service |
f629e6 |
return awk_false;
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
/* hook into value */
|
|
Packit Service |
f629e6 |
value->val_type = AWK_NUMBER;
|
|
Packit Service |
f629e6 |
value->num_value = d;
|
|
Packit Service |
f629e6 |
} else {
|
|
Packit Service |
f629e6 |
if (fread(& len, 1, sizeof(len), fp) != sizeof(len)) {
|
|
Packit Service |
f629e6 |
return awk_false;
|
|
Packit Service |
f629e6 |
}
|
|
Packit Service |
f629e6 |
len = ntohl(len);
|
|
Packit Service |
f629e6 |
switch (code) {
|
|
Packit Service |
f629e6 |
case 0:
|
|
Packit Service |
f629e6 |
value->val_type = AWK_STRING;
|
|
Packit Service |
f629e6 |
break;
|
|
Packit Service |
f629e6 |
case 3:
|
|
Packit Service |
f629e6 |
value->val_type = AWK_REGEX;
|
|
Packit Service |
f629e6 |
break;
|
|
Packit Service |
f629e6 |
case 4:
|
|
Packit Service |
f629e6 |
value->val_type = AWK_STRNUM;
|
|
Packit Service |
f629e6 |
break;
|
|
Packit Service |
f629e6 |
case 5:
|
|
Packit Service |
f629e6 |
value->val_type = AWK_UNDEFINED;
|
|
Packit Service |
f629e6 |
break;
|
|
Packit Service |
f629e6 |
default:
|
|
Packit Service |
f629e6 |
/* this cannot happen! */
|
|
Packit Service |
f629e6 |
warning(ext_id, _("treating recovered value with unknown type code %d as a string"), code);
|
|
Packit Service |
f629e6 |
value->val_type = AWK_STRING;
|
|
Packit Service |
f629e6 |
break;
|
|
Packit Service |
f629e6 |
}
|
|
Packit Service |
f629e6 |
value->str_value.len = len;
|
|
Packit Service |
f629e6 |
value->str_value.str = gawk_malloc(len + 1);
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
if (fread(value->str_value.str, 1, len, fp) != (ssize_t) len) {
|
|
Packit Service |
f629e6 |
gawk_free(value->str_value.str);
|
|
Packit Service |
f629e6 |
return awk_false;
|
|
Packit Service |
f629e6 |
}
|
|
Packit Service |
f629e6 |
value->str_value.str[len] = '\0';
|
|
Packit Service |
f629e6 |
}
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
return awk_true;
|
|
Packit Service |
f629e6 |
}
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
static awk_ext_func_t func_table[] = {
|
|
Packit Service |
f629e6 |
{ "writea", do_writea, 2, 2, awk_false, NULL },
|
|
Packit Service |
f629e6 |
{ "reada", do_reada, 2, 2, awk_false, NULL },
|
|
Packit Service |
f629e6 |
};
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
/* define the dl_load function using the boilerplate macro */
|
|
Packit Service |
f629e6 |
|
|
Packit Service |
f629e6 |
dl_load_func(func_table, rwarray, "")
|