kopia lustrzana https://github.com/sp9skp/spdxl
552 wiersze
8.9 KiB
C
552 wiersze
8.9 KiB
C
/*
|
|
* dxlAPRS toolchain
|
|
*
|
|
* Copyright (C) Hannes Schmelzer <oe5hpm@oevsv.at>
|
|
* Copyright (C) Christian Rabler <oe5dxl@oevsv.at>
|
|
*
|
|
* SPDX-License-Identifier: GPL-2.0+
|
|
*/
|
|
#define _LARGEFILE64_SOURCE
|
|
#define _GNU_SOURCE
|
|
|
|
#include <fcntl.h>
|
|
#include <sys/types.h>
|
|
#include <stdint.h>
|
|
#include <stdlib.h>
|
|
#include <unistd.h>
|
|
#include <stdio.h>
|
|
#include <math.h>
|
|
#include <assert.h>
|
|
#include <time.h>
|
|
#include <errno.h>
|
|
|
|
#include "osic.h"
|
|
|
|
#undef DEBUG
|
|
#ifdef DEBUG
|
|
# define DBG(...) printf(__VA_ARGS__)
|
|
#else
|
|
# define DBG(...) do { } while (0)
|
|
#endif
|
|
|
|
#define FNLENCHECK 1
|
|
|
|
/* Does not exist - and is not necessary - on MacOS */
|
|
#ifndef O_LARGEFILE
|
|
# define O_LARGEFILE 0
|
|
#endif
|
|
|
|
static int osic_argc, argc_delivered;
|
|
static char **osic_argv;
|
|
|
|
void osic_flush(void)
|
|
{
|
|
fflush(stdout);
|
|
fflush(stderr);
|
|
}
|
|
|
|
void osic_WrLn(void)
|
|
{
|
|
fprintf(stdout, "\n");
|
|
fflush(stdout);
|
|
}
|
|
|
|
void osic_WerrLn(void)
|
|
{
|
|
fprintf(stderr, "\n");
|
|
fflush(stderr);
|
|
}
|
|
|
|
void osic_WrStr(char s[], uint32_t s_len)
|
|
{
|
|
size_t len;
|
|
|
|
len = strnlen(s, s_len);
|
|
fprintf(stdout, "%.*s", len, s);
|
|
}
|
|
|
|
void osic_WrStrLn(char s[], uint32_t s_len)
|
|
{
|
|
size_t len;
|
|
|
|
len = strnlen(s, s_len);
|
|
fprintf(stdout, "%.*s", len, s);
|
|
osic_WrLn();
|
|
}
|
|
|
|
void osic_WerrStr(char s[], uint32_t s_len)
|
|
{
|
|
size_t len;
|
|
|
|
len = strnlen(s, s_len);
|
|
fprintf(stderr, "%.*s", len, s);
|
|
}
|
|
|
|
void osic_WerrStrLn(char s[], uint32_t s_len)
|
|
{
|
|
size_t len;
|
|
|
|
len = strnlen(s, s_len);
|
|
fprintf(stderr, "%.*s", len, s);
|
|
osic_WrLn();
|
|
}
|
|
|
|
void osic_WrUINT32(uint32_t x, uint32_t witdh)
|
|
{
|
|
fprintf(stdout, "%*d", (int)witdh, x);
|
|
}
|
|
|
|
void osic_WrINT32(int32_t x, uint32_t witdh)
|
|
{
|
|
fprintf(stdout, "%*d", (int)witdh, x);
|
|
}
|
|
|
|
void osic_WrFixed(float x, int32_t place, uint32_t witdh)
|
|
{
|
|
fprintf(stdout, "%*.*f", (int)witdh, (int)place, x);
|
|
}
|
|
|
|
void osic_WrHex(uint32_t n, uint32_t f)
|
|
{
|
|
fprintf(stdout, "%*X", (int)f, (uint32_t)n);
|
|
fflush(stdout);
|
|
}
|
|
|
|
int osic_getptsname(int fd, char *name, int len)
|
|
{
|
|
#ifndef MACOS
|
|
return ptsname_r(fd, name, len);
|
|
#else
|
|
{
|
|
/* MacOS does not have ptsname_r, emulate it with ptsname */
|
|
if (name == NULL)
|
|
return -EINVAL;
|
|
char *n = ptsname(fd);
|
|
if (n == NULL)
|
|
return -ENOTTY;
|
|
if (len < strlen(n))
|
|
return -ERANGE;
|
|
strncpy(name, n, len);
|
|
|
|
return 0;
|
|
}
|
|
#endif
|
|
}
|
|
|
|
int osic_grantpts(int fd)
|
|
{
|
|
return grantpt(fd);
|
|
}
|
|
|
|
int osic_unlockpts(int fd)
|
|
{
|
|
return unlockpt(fd);
|
|
}
|
|
|
|
int32_t osic_OpenAppendLong(char fn[], uint32_t fn_len)
|
|
{
|
|
if (FNLENCHECK && strnlen(fn, fn_len) > fn_len)
|
|
return -1;
|
|
return open(fn, O_WRONLY | O_APPEND | O_LARGEFILE);
|
|
}
|
|
|
|
int32_t osic_OpenAppend(char fn[], uint32_t fn_len)
|
|
{
|
|
if (FNLENCHECK && strnlen(fn, fn_len) > fn_len)
|
|
return -1;
|
|
return open(fn, O_WRONLY | O_APPEND);
|
|
}
|
|
|
|
int32_t osic_OpenWrite(char fn[], uint32_t fn_len)
|
|
{
|
|
if (FNLENCHECK && strnlen(fn, fn_len) > fn_len)
|
|
return -1;
|
|
return creat(fn, 0664);
|
|
}
|
|
|
|
int32_t osic_OpenReadLong(char fn[], uint32_t fn_len)
|
|
{
|
|
if (FNLENCHECK && strnlen(fn, fn_len) > fn_len)
|
|
return -1;
|
|
return open(fn, O_RDONLY | O_LARGEFILE);
|
|
}
|
|
|
|
int32_t osic_OpenRead(char fn[], uint32_t fn_len)
|
|
{
|
|
if (FNLENCHECK && strnlen(fn, fn_len) > fn_len)
|
|
return -1;
|
|
return open(fn, O_RDONLY);
|
|
}
|
|
|
|
int32_t osic_OpenRW(char fn[], uint32_t fn_len)
|
|
{
|
|
if (FNLENCHECK && strnlen(fn, fn_len) > fn_len)
|
|
return -1;
|
|
return open(fn, O_RDWR);
|
|
}
|
|
|
|
int32_t osic_OpenNONBLOCK(char fn[], uint32_t fn_len)
|
|
{
|
|
if (FNLENCHECK && strnlen(fn, fn_len) > fn_len)
|
|
return -1;
|
|
return open(fn, O_RDWR | O_NONBLOCK);
|
|
}
|
|
|
|
char osic_FdValid(int32_t fd)
|
|
{
|
|
return (fd >= 0);
|
|
}
|
|
|
|
void osic_Close(int32_t fd)
|
|
{
|
|
close(fd);
|
|
}
|
|
|
|
void osic_CloseSock(int32_t fd)
|
|
{
|
|
close(fd);
|
|
}
|
|
|
|
int32_t osic_RdBin(int32_t fd, char buf[], uint32_t buf_len, uint32_t size)
|
|
{
|
|
if (size > buf_len)
|
|
size = buf_len;
|
|
return read(fd, (char *)buf, size);
|
|
}
|
|
|
|
void osic_WrBin(int32_t fd, char buf[], uint32_t buf_len, uint32_t size)
|
|
{
|
|
int rc;
|
|
if (size > buf_len)
|
|
size = buf_len;
|
|
rc = write(fd, (char *)buf, size);
|
|
(void)rc;
|
|
}
|
|
|
|
void osic_Rename(char fname[], uint32_t fname_len,
|
|
char newname[], uint32_t newname_len)
|
|
{
|
|
if (FNLENCHECK && strnlen(fname, fname_len) >= fname_len)
|
|
return;
|
|
if (FNLENCHECK && strnlen(newname, newname_len) >= newname_len)
|
|
return;
|
|
rename(fname, newname);
|
|
}
|
|
|
|
int osic_Size(int fd)
|
|
{
|
|
struct stat st = { };
|
|
|
|
fstat(fd, &st);
|
|
return st.st_size;
|
|
}
|
|
|
|
void osic_Seek(int32_t fd, uint32_t pos)
|
|
{
|
|
lseek(fd, (int32_t)pos, SEEK_SET);
|
|
}
|
|
|
|
void osic_Seekcur(int32_t fd, int32_t rel)
|
|
{
|
|
#ifndef MACOS
|
|
if (lseek64(fd, rel, (uint32_t)SEEK_CUR) < 0)
|
|
lseek(fd, 0, SEEK_SET);
|
|
#else
|
|
/* MacOS has no lseek64 */
|
|
if (lseek(fd, rel, (uint32_t)SEEK_CUR) < 0)
|
|
lseek(fd, 0, SEEK_SET);
|
|
#endif
|
|
}
|
|
|
|
void osic_Remove(char fname[], uint32_t fname_len, char *done)
|
|
{
|
|
int rc;
|
|
|
|
rc = remove(fname);
|
|
if (rc == 0)
|
|
*done = 1;
|
|
else
|
|
*done = 0;
|
|
}
|
|
|
|
char osic_Exists(char fname[], uint32_t fname_len)
|
|
{
|
|
if (access(fname, F_OK) != -1)
|
|
return 1;
|
|
return 0;
|
|
}
|
|
|
|
int osic_symblink(char *existing, char *newname)
|
|
{
|
|
return symlink(existing, newname);
|
|
}
|
|
|
|
void osic_NextArg(char s[], uint32_t s_len)
|
|
{
|
|
if (argc_delivered >= osic_argc-1) {
|
|
s[0] = 0;
|
|
return;
|
|
}
|
|
strncpy(s, osic_argv[argc_delivered+1], s_len);
|
|
argc_delivered++;
|
|
}
|
|
|
|
void osic_Fill(char *buf, uint32_t len, char byte)
|
|
{
|
|
memset(buf, byte, len);
|
|
}
|
|
|
|
double osic_Random(void)
|
|
{
|
|
return (rand() / (double)RAND_MAX);
|
|
}
|
|
|
|
void X2C_BEGIN(int *argc, char *argv[],
|
|
int gc_auto, int32_t gc_threshold, int32_t heap_limit)
|
|
{
|
|
if (osic_argc != 0)
|
|
return;
|
|
osic_argc = *argc;
|
|
osic_argv = argv;
|
|
}
|
|
|
|
void X2C_PCOPY(void **ppcpy, size_t size)
|
|
{
|
|
void *pnew;
|
|
|
|
pnew = malloc(size);
|
|
if (pnew == NULL)
|
|
return;
|
|
memcpy(pnew, *ppcpy, size);
|
|
*ppcpy = pnew;
|
|
}
|
|
|
|
int32_t X2C_TRUNCI(double x, int32_t min0, int32_t max0)
|
|
{
|
|
int32_t i;
|
|
|
|
if (x < (double)min0 || x > (double)max0)
|
|
assert(0);
|
|
i = (int32_t)x;
|
|
if (x > 0.0) {
|
|
if ((double)i > x)
|
|
--i;
|
|
} else if ((double)i < x) {
|
|
++i;
|
|
}
|
|
return i;
|
|
}
|
|
|
|
uint32_t X2C_TRUNCC(double x, uint32_t min0, uint32_t max0)
|
|
{
|
|
uint32_t i;
|
|
|
|
if (x < (double)min0)
|
|
i = (uint32_t)min0;
|
|
if (x > (double)max0)
|
|
i = (uint32_t)max0;
|
|
|
|
i = (uint32_t)x;
|
|
if ((double)i > x)
|
|
--i;
|
|
return i;
|
|
}
|
|
|
|
float osic_cos(float x)
|
|
{
|
|
return cos(x);
|
|
}
|
|
|
|
float osic_ln(float x)
|
|
{
|
|
if (x <= 0.0)
|
|
assert(0);
|
|
return log(x);
|
|
}
|
|
|
|
float osic_sqrt(float x)
|
|
{
|
|
if (x < 0.0)
|
|
assert(0);
|
|
return sqrt(x);
|
|
}
|
|
|
|
float osic_sin(float x)
|
|
{
|
|
return sin(x);
|
|
}
|
|
float osic_arctan(float x)
|
|
{
|
|
return atan(x);
|
|
}
|
|
|
|
float osic_tan(float x)
|
|
{
|
|
return tan(x);
|
|
}
|
|
|
|
float osic_exp(float x)
|
|
{
|
|
return exp(x);
|
|
}
|
|
|
|
float osic_power(float base, float exponent)
|
|
{
|
|
if (base <= 0.0)
|
|
assert(0);
|
|
return pow(base, exponent);
|
|
}
|
|
|
|
float osic_arccos(float x)
|
|
{
|
|
return acos(x);
|
|
}
|
|
|
|
float osic_floor(float x)
|
|
{
|
|
return floorf(x);
|
|
}
|
|
|
|
void osic_alloc(X2C_ADDRESS *p, uint32_t size)
|
|
{
|
|
void *pmem;
|
|
|
|
pmem = malloc(size);
|
|
if (pmem == NULL)
|
|
return;
|
|
*p = pmem;
|
|
}
|
|
|
|
void osic_free(X2C_ADDRESS *a, uint32_t size)
|
|
{
|
|
assert(*a);
|
|
free(*a);
|
|
}
|
|
|
|
uint32_t osic_time(void)
|
|
{
|
|
return time(NULL);
|
|
}
|
|
|
|
uint32_t X2C_LSH(uint32_t a, int32_t length, int32_t n)
|
|
{
|
|
uint32_t m;
|
|
|
|
m = 0;
|
|
m = (length == 32) ? 0xFFFFFFFFl : (1 << length) - 1;
|
|
if (n > 0) {
|
|
if (n >= (int32_t)length)
|
|
return 0;
|
|
return (a << n) & m;
|
|
}
|
|
|
|
if (n <= (int32_t)-length)
|
|
return 0;
|
|
return (a >> -n) & m;
|
|
}
|
|
|
|
char X2C_IN(uint32_t i, uint32_t bits, uint32_t set)
|
|
{
|
|
if (i < bits)
|
|
return (((1 << (int)i) & set) != 0);
|
|
return 0;
|
|
}
|
|
|
|
char X2C_INL(uint32_t i, uint32_t bits, uint32_t *set)
|
|
{
|
|
if (i < bits)
|
|
return (set[(int)i / X2C_LSET_SIZE] & (1 << ((int)i % X2C_LSET_SIZE))) != 0;
|
|
return 0;
|
|
}
|
|
|
|
void X2C_INCL(uint32_t *set, uint32_t i, uint32_t bits)
|
|
{
|
|
if (i >= bits)
|
|
assert(0);
|
|
set[(int)i / X2C_LSET_SIZE] |= 1L << ((int)i % X2C_LSET_SIZE);
|
|
}
|
|
|
|
void X2C_EXCL(uint32_t *set, uint32_t i, uint32_t bits)
|
|
{
|
|
if (i >= bits)
|
|
assert(0);
|
|
set[(int)i / X2C_LSET_SIZE] &= ~(1L << ((int)i % X2C_LSET_SIZE));
|
|
}
|
|
|
|
uint32_t *X2C_COMPLEMENT(uint32_t *res, uint32_t *a, uint32_t length)
|
|
{
|
|
uint32_t *pres = res;
|
|
while (length--)
|
|
*res++ = ~(*a++);
|
|
|
|
return pres;
|
|
}
|
|
|
|
struct xrMM_Dynarr {
|
|
char *a;
|
|
size_t n[15];
|
|
};
|
|
|
|
size_t xrMM_DynarrDescSize(size_t i)
|
|
{
|
|
return (sizeof(char *) + i * sizeof(size_t) * 2);
|
|
}
|
|
|
|
void X2C_InitDesc(struct xrMM_Dynarr *d, size_t *size, size_t lens[], size_t dims)
|
|
{
|
|
uint32_t i;
|
|
uint32_t tmp;
|
|
|
|
d->n[(dims - 1) * 2] = lens[0];
|
|
tmp = dims - 1;
|
|
i = 1;
|
|
if (i <= tmp) {
|
|
for (;; i++) {
|
|
*size = *size * lens[dims-i];
|
|
d->n[i * 2 - 1] = *size;
|
|
d->n[(dims - i) * 2 - 2] = lens[i];
|
|
if (i == tmp)
|
|
break;
|
|
}
|
|
}
|
|
*size = *size*lens[0];
|
|
}
|
|
|
|
void X2C_DYNALLOCATE(char **a, size_t size, size_t lens[], size_t dims)
|
|
{
|
|
struct xrMM_Dynarr *desc;
|
|
|
|
*a = 0;
|
|
desc = malloc(xrMM_DynarrDescSize(dims));
|
|
if (desc) {
|
|
X2C_InitDesc(desc, &size, lens, dims);
|
|
desc->a = malloc(size);
|
|
if (desc->a == 0) {
|
|
free(desc);
|
|
} else {
|
|
DBG("%s: %p (%d bytes) with child %p (%d bytes)\n",
|
|
__func__, desc, xrMM_DynarrDescSize(dims),
|
|
desc->a, size);
|
|
*a = (char *)desc;
|
|
}
|
|
}
|
|
}
|
|
|
|
void X2C_DYNDEALLOCATE(char **a)
|
|
{
|
|
struct xrMM_Dynarr *d;
|
|
|
|
if (*a) {
|
|
d = (struct xrMM_Dynarr *)*a;
|
|
DBG("%s: have %p with child %p\n", __func__, d, d->a);
|
|
free(d->a);
|
|
free(d);
|
|
}
|
|
}
|
|
|
|
void *osic_chkptr(void *p)
|
|
{
|
|
assert(p);
|
|
return p;
|
|
}
|