New memory management subsystem.
This commit is contained in:
parent
1801ca9c74
commit
9b4288cf9c
3
Makefile
3
Makefile
@ -12,7 +12,8 @@ CC ?= gcc
|
||||
#CC ?= tcc
|
||||
#CC ?= musl-tcc
|
||||
CFLAGS += -O2 -pedantic -g -Wall -Wextra
|
||||
CPPFLAGS += -DVERSION=$(VERSION) -D_FORTIFY_SOURCE=2
|
||||
# CPPFLAGS += -DVERSION=$(VERSION) -D_FORTIFY_SOURCE=2
|
||||
CPPFLAGS += -DVERSION=$(VERSION)
|
||||
LDFLAGS += -lm
|
||||
BIN ?= slidescript
|
||||
|
||||
|
0
src/compression.c
Executable file → Normal file
0
src/compression.c
Executable file → Normal file
259
src/eprintf.c
Normal file
259
src/eprintf.c
Normal file
@ -0,0 +1,259 @@
|
||||
/* ------------------------------------------------------------ */
|
||||
/* file information */
|
||||
/* ------------------------------------------------------------ */
|
||||
|
||||
// Filename: eprintf.c
|
||||
// Purpose: TTY and error-message routines
|
||||
// License: MIT/X. (c) OldCoder (Robert Kiraly) 1987-2021.
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
/* header files */
|
||||
/* ------------------------------------------------------------ */
|
||||
|
||||
/* The "EPRINTF_P" definition used below suppresses some of the */
|
||||
/* prototypes in "x3file.h" locally. This allows us to imple- */
|
||||
/* ment variable-length argument lists in a non-standard (but */
|
||||
/* generally portable) fashion. */
|
||||
|
||||
#define EPRINTF_P /* see explanation above */
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "inc/eprintf.h"
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
/* functions */
|
||||
/* ------------------------------------------------------------ */
|
||||
|
||||
/* Function: V_FUNC init_tty(NO_PARAM) */
|
||||
/* Summary: Initializes the UX3 TTY flags. */
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
|
||||
/* "init_tty()" sets three global character variables as fol- */
|
||||
/* lows: */
|
||||
/* */
|
||||
/* tty_in -- standard input stream TTY mode */
|
||||
/* tty_out -- standard output stream TTY mode */
|
||||
/* tty_err -- standard error stream TTY mode */
|
||||
|
||||
/* TTY modes are determined by the standard library function */
|
||||
/* "isatty()". */
|
||||
|
||||
/* E.g., "init_tty()" sets these three flags true if and only */
|
||||
/* if the associated streams are console devices. */
|
||||
|
||||
/* The global character variable "tty_set" flags the TTY */
|
||||
/* initialization status. "tty_set" is true if "init_tty()" */
|
||||
/* has been called previously. */
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
|
||||
V_FUNC init_tty (NO_PARAM)
|
||||
{
|
||||
tty_in = isatty (0); /* standard-input TTY flag */
|
||||
tty_out = isatty (1); /* standard-output TTY flag */
|
||||
tty_err = isatty (2); /* standard-error TTY flag */
|
||||
tty_set = TRUE; /* TTY initialization flag */
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
|
||||
/* "eprintf(s,...)" accepts a "printf()"-style argument list, */
|
||||
/* writes the specified message to the standard error stream, */
|
||||
/* and flushes the stream. */
|
||||
|
||||
/* This function may be system-dependent. */
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
|
||||
V_FUNC eprintf (s,a,b,c,d,e,f,g,h,i,j)
|
||||
char *s; /* format string */
|
||||
int a,b,c,d,e,f,g,h,i,j; /* dummy arguments */
|
||||
{
|
||||
fflush (stdout); /* flush standard output stream */
|
||||
|
||||
fprintf (stderr, /* print message to the */
|
||||
s,a,b,c,d,e,f,g,h,i,j); /* standard error stream */
|
||||
|
||||
fflush (stderr); /* flush standard error stream */
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
|
||||
/* "eprintf2(s,...)" accepts a "printf()"-style argument list, */
|
||||
/* writes the specified message to the standard error stream, */
|
||||
/* and flushes the stream. */
|
||||
|
||||
/* If the standard output and standard error TTY modes are */
|
||||
/* different, "eprintf2()" will write the message to the */
|
||||
/* standard output stream as well. TTY modes are determined by */
|
||||
/* the standard library function "isatty()". */
|
||||
|
||||
/* This function may be system-dependent. */
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
|
||||
V_FUNC eprintf2 (s,a,b,c,d,e,f,g,h,i,j)
|
||||
char *s; /* format string */
|
||||
int a,b,c,d,e,f,g,h,i,j; /* dummy arguments */
|
||||
{
|
||||
fflush (stdout); /* flush standard output stream */
|
||||
|
||||
fprintf (stderr, /* print message to the */
|
||||
s,a,b,c,d,e,f,g,h,i,j); /* standard error stream */
|
||||
|
||||
fflush (stderr); /* flush standard error stream */
|
||||
if (!tty_set) init_tty(); /* initialize TTY mode flags */
|
||||
|
||||
if (tty_out == tty_err) /* split the error stream? */
|
||||
{ /* no */
|
||||
return; /* done - exit */
|
||||
}
|
||||
|
||||
fprintf (stdout, /* print message to the stan- */
|
||||
s,a,b,c,d,e,f,g,h,i,j); /* dard output stream */
|
||||
|
||||
fflush (stdout); /* flush standard output stream */
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
|
||||
/* "z_msg(t_flag,pf,s,...)" accepts the following arguments: */
|
||||
/* */
|
||||
/* t_flag -- terminate-caller flag */
|
||||
/* pf -- prefix-string pointer */
|
||||
/* s, ... -- "printf()"-style argument list */
|
||||
|
||||
/* "z_msg()" writes the specified "printf()"-style message to */
|
||||
/* the standard error stream, appends a newline, and flushes */
|
||||
/* the stream. */
|
||||
|
||||
/* If the standard output and standard error TTY modes are */
|
||||
/* different, "z_msg()" will write the message to the standard */
|
||||
/* output stream as well. TTY modes are determined by the */
|
||||
/* standard library function "isatty()". */
|
||||
|
||||
/* If the prefix-string pointer "pf" is not NULL, "z_msg()" */
|
||||
/* prepends the specified string to the message produced. */
|
||||
|
||||
/* If the terminate-caller flag "t_flag" is true (nonzero), */
|
||||
/* "z_msg()" terminates the caller upon completion. */
|
||||
|
||||
/* This function may be system-dependent. */
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
|
||||
MODPRIV V_FUNC z_msg(t_flag,pf,s,a,b,c,d,e,f,g,h,i,j)
|
||||
int t_flag; /* terminate-caller flag */
|
||||
char *pf; /* prefix pointer (or NULL) */
|
||||
char *s; /* format string */
|
||||
int a,b,c,d,e,f,g,h,i,j; /* dummy arguments */
|
||||
{
|
||||
if ((pf != NULLCP) && (*pf != CH_EOS)) eprintf2 ("%s",pf);
|
||||
eprintf2 (s,a,b,c,d,e,f,g,h,i,j);
|
||||
eprintf2 ("\n"); /* append a newline */
|
||||
if (t_flag) exit (ONE); /* terminate the caller */
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
|
||||
/* "x_warn(s,...)" accepts a "printf()"-style argument list */
|
||||
/* and writes an warning message based on the argument list to */
|
||||
/* the standard error stream. */
|
||||
|
||||
/* If the standard output and standard error TTY modes are */
|
||||
/* different, "x_warn()" will write the message to the standard */
|
||||
/* output stream as well. TTY modes are determined by the */
|
||||
/* standard library function "isatty()". */
|
||||
|
||||
/* This function may be system-dependent. */
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
|
||||
V_FUNC x_warn(s,a,b,c,d,e,f,g,h,i,j)
|
||||
char *s; /* format string */
|
||||
int a,b,c,d,e,f,g,h,i,j; /* dummy arguments */
|
||||
{
|
||||
z_msg (FALSE, "Warning: ", s,a,b,c,d,e,f,g,h,i,j);
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
|
||||
/* "x_error(s,...)" accepts a "printf()"-style argument list, */
|
||||
/* writes an error message based on the argument list to the */
|
||||
/* standard error stream, and terminates the caller. */
|
||||
|
||||
/* If the standard output and standard error TTY modes are */
|
||||
/* different, "x_error()" will write the message to the */
|
||||
/* standard output stream as well. TTY modes are determined by */
|
||||
/* the standard library function "isatty()". */
|
||||
|
||||
/* This function may be system-dependent. */
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
|
||||
V_FUNC x_error(s,a,b,c,d,e,f,g,h,i,j)
|
||||
char *s; /* format string */
|
||||
int a,b,c,d,e,f,g,h,i,j; /* dummy arguments */
|
||||
{
|
||||
z_msg (TRUE, "Error: ", s,a,b,c,d,e,f,g,h,i,j);
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
|
||||
/* "x_panic(s,...)" accepts a "printf()"-style argument list, */
|
||||
/* writes an error message based on the argument list to the */
|
||||
/* standard error stream, and terminates the caller. */
|
||||
|
||||
/* If the standard output and standard error TTY modes are */
|
||||
/* different, "x_panic" will write the message to the standard */
|
||||
/* output stream as well. TTY modes are determined by the */
|
||||
/* standard library function "isatty()". */
|
||||
|
||||
/* "x_panic" is called primarily to handle internal consistency */
|
||||
/* errors. */
|
||||
|
||||
/* This function may be system-dependent. */
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
|
||||
V_FUNC x_panic (s,a,b,c,d,e,f,g,h,i,j)
|
||||
char *s; /* format string */
|
||||
int a,b,c,d,e,f,g,h,i,j; /* dummy arguments */
|
||||
{
|
||||
z_msg (TRUE, "Internal error: ",
|
||||
s,a,b,c,d,e,f,g,h,i,j);
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
|
||||
/* "n_panic(n)" prints an error message of the following form */
|
||||
/* and terminates the caller: */
|
||||
/* */
|
||||
/* Internal error: #123 */
|
||||
|
||||
/* The integer "n" is used for the "#..." portion of the */
|
||||
/* message. */
|
||||
|
||||
/* "n_panic()" writes the message to the standard error stream. */
|
||||
|
||||
/* If the standard output and standard error TTY modes are */
|
||||
/* different, "n_panic()" will write the message to the stan- */
|
||||
/* dard output stream as well. TTY modes are determined by the */
|
||||
/* standard library function "isatty()". */
|
||||
|
||||
/* "n_panic()" is called primarily to handle internal con- */
|
||||
/* sistency errors. */
|
||||
|
||||
/* This function may be system-dependent. */
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
|
||||
V_FUNC n_panic(n)
|
||||
REG_VAR int n; /* "panic" number */
|
||||
{
|
||||
x_panic ("#%d",n,0,0,0,0,0,0,0,0,0);
|
||||
}
|
0
src/inc/compression.h
Executable file → Normal file
0
src/inc/compression.h
Executable file → Normal file
0
src/inc/config.h
Executable file → Normal file
0
src/inc/config.h
Executable file → Normal file
0
src/inc/deps.h
Executable file → Normal file
0
src/inc/deps.h
Executable file → Normal file
0
src/inc/enc.h
Executable file → Normal file
0
src/inc/enc.h
Executable file → Normal file
45
src/inc/eprintf.h
Normal file
45
src/inc/eprintf.h
Normal file
@ -0,0 +1,45 @@
|
||||
/* ------------------------------------------------------------ */
|
||||
/* file information */
|
||||
/* ------------------------------------------------------------ */
|
||||
|
||||
// Filename: eprintf.h
|
||||
// Purpose: TTY and error-message routines
|
||||
// License: MIT/X. (c) OldCoder (Robert Kiraly) 1987-2021.
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
/* header file setup */
|
||||
/* ------------------------------------------------------------ */
|
||||
|
||||
#ifndef _EPRINTF_H /* skip this file if loaded */
|
||||
#define _EPRINTF_H 1 /* flag this file */
|
||||
|
||||
#include "x3basic.h"
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
/* TTY (console mode) flags */
|
||||
/* ------------------------------------------------------------ */
|
||||
|
||||
UX3_EXT char tty_in; /* standard-input TTY flag */
|
||||
UX3_EXT char tty_out; /* standard-output TTY flag */
|
||||
UX3_EXT char tty_err; /* standard-error TTY flag */
|
||||
UX3_EXT char tty_set; /* TTY initialization flag */
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
/* function prototypes */
|
||||
/* ------------------------------------------------------------ */
|
||||
|
||||
V_PROTO init_tty (NO_PARAM);
|
||||
|
||||
#ifndef EPRINTF_P /* see comments in "eprintf.c" */
|
||||
/*VARARGS*/ V_PROTO eprintf (argp2 (char *, ...));
|
||||
/*VARARGS*/ V_PROTO eprintf2 (argp2 (char *, ...));
|
||||
/*VARARGS*/ V_PROTO x_panic (argp2 (char *, ...));
|
||||
/*VARARGS*/ V_PROTO x_error (argp2 (char *, ...));
|
||||
/*VARARGS*/ V_PROTO x_warn (argp2 (char *, ...));
|
||||
#endif /* endif not EPRINTF_P */
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
/* wrap it up */
|
||||
/* ------------------------------------------------------------ */
|
||||
|
||||
#endif /* endif _EPRINTF_H */
|
0
src/inc/inset.h
Executable file → Normal file
0
src/inc/inset.h
Executable file → Normal file
0
src/inc/lexer.h
Executable file → Normal file
0
src/inc/lexer.h
Executable file → Normal file
0
src/inc/math.h
Executable file → Normal file
0
src/inc/math.h
Executable file → Normal file
0
src/inc/md5.h
Executable file → Normal file
0
src/inc/md5.h
Executable file → Normal file
0
src/inc/network.h
Executable file → Normal file
0
src/inc/network.h
Executable file → Normal file
0
src/inc/pipe.h
Executable file → Normal file
0
src/inc/pipe.h
Executable file → Normal file
0
src/inc/sbyteswap.h
Executable file → Normal file
0
src/inc/sbyteswap.h
Executable file → Normal file
0
src/inc/search.h
Executable file → Normal file
0
src/inc/search.h
Executable file → Normal file
6
src/inc/tar.h
Executable file → Normal file
6
src/inc/tar.h
Executable file → Normal file
@ -26,6 +26,12 @@ THE SOFTWARE
|
||||
#ifndef __TAR__
|
||||
#define __TAR__
|
||||
|
||||
#include "x3mem.h"
|
||||
|
||||
UX3_EXT QLIST QM_TAR [ONE]; // Dynamic-memory QLIST
|
||||
|
||||
extern void tar_free_pool (void);
|
||||
|
||||
#ifndef _DEFAULT_SOURCE
|
||||
#define _DEFAULT_SOURCE
|
||||
#endif
|
||||
|
0
src/inc/util.h
Executable file → Normal file
0
src/inc/util.h
Executable file → Normal file
0
src/inc/vars.h
Executable file → Normal file
0
src/inc/vars.h
Executable file → Normal file
275
src/inc/x3basic.h
Normal file
275
src/inc/x3basic.h
Normal file
@ -0,0 +1,275 @@
|
||||
/* ------------------------------------------------------------ */
|
||||
/* file information */
|
||||
/* ------------------------------------------------------------ */
|
||||
|
||||
// Filename: x3basic.h
|
||||
// Purpose: UX3 basic definitions
|
||||
// License: MIT/X. (c) OldCoder (Robert Kiraly) 1987-2021.
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
/* header file setup */
|
||||
/* ------------------------------------------------------------ */
|
||||
|
||||
#ifndef _X3BASIC_H /* skip this file if loaded */
|
||||
#define _X3BASIC_H 1 /* flag this file */
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
/* basic definitions */
|
||||
/* ------------------------------------------------------------ */
|
||||
|
||||
#ifndef ZERO
|
||||
#define ZERO 0
|
||||
#endif // Endif ZERO
|
||||
|
||||
#ifndef ONE
|
||||
#define ONE 1
|
||||
#endif // Endif ONE
|
||||
|
||||
#ifndef FALSE
|
||||
#define FALSE 0
|
||||
#endif // Endif FALSE
|
||||
|
||||
#ifndef TRUE
|
||||
#define TRUE 1
|
||||
#endif // Endif TRUE
|
||||
|
||||
#ifndef CH_EOS
|
||||
#define CH_EOS '\0'
|
||||
#endif // Endif CH_EOS
|
||||
|
||||
#ifndef x3u_char
|
||||
#define x3u_char unsigned char
|
||||
#endif
|
||||
|
||||
#ifndef x3u_int
|
||||
#define x3u_int unsigned int
|
||||
#endif
|
||||
|
||||
#ifndef x3u_long
|
||||
#define x3u_long unsigned long
|
||||
#endif
|
||||
|
||||
#ifndef MODPRIV // Module-private
|
||||
#define MODPRIV static
|
||||
#endif // Endif MODPRIV
|
||||
|
||||
#ifndef MODPUB // Module-public
|
||||
#define MODPUB
|
||||
#endif // Endif MODPUB
|
||||
|
||||
#ifndef REG_VAR
|
||||
#define REG_VAR
|
||||
#endif // Endif NULL_PTR
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
/* "erase item" macro functions */
|
||||
/* ------------------------------------------------------------ */
|
||||
|
||||
/* If "dp" is a data pointer (of any type) and "nb" is a short */
|
||||
/* or long integer, "b_clr(dp,nb)" clears "nb" bytes to zero, */
|
||||
/* starting with the first byte pointed to by "dp". */
|
||||
|
||||
/* Note: "nb" may use any integer data type, but the value of */
|
||||
/* "nb" should fit into an unsigned integer. */
|
||||
|
||||
#define b_clr(dp,nb) \
|
||||
{ \
|
||||
REG_VAR char *cp = (char *) (dp); \
|
||||
REG_VAR u_int x = (u_int) (nb); \
|
||||
while (x-- > ZERO) *cp++ = CH_EOS; \
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
|
||||
/* If "a[]" is an array, "a_clr(a)" clears the array (bytewise) */
|
||||
/* to zero. "a[]" must be an array and not a pointer. The */
|
||||
/* array must have a known fixed size. */
|
||||
|
||||
#define a_clr(a) b_clr ((char *) (&((a)[0])),sizeof(a))
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
|
||||
/* If "p" is a pointer to a structure or variable, "p_clr(p)" */
|
||||
/* clears the structure or variable. The pointer object must */
|
||||
/* have a known fixed size. */
|
||||
|
||||
#define p_clr(p) b_clr ((char *) (p),sizeof(*p))
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
|
||||
/* If "x" is a variable (and not an array), "v_clr(x)" clears */
|
||||
/* the variable (bytewise) to zero. The variable must have a */
|
||||
/* known fixed size. */
|
||||
|
||||
#define v_clr(x) b_clr ((char *) (&(x)),sizeof(x))
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
/* handle "void" data type */
|
||||
/* ------------------------------------------------------------ */
|
||||
|
||||
/* The following five symbols provide a portable interface to */
|
||||
/* the "void" data type. These five symbols are translated */
|
||||
/* appropriately for systems which don't support the "void" */
|
||||
/* type. */
|
||||
|
||||
/* (a) V_FUNC -- defines a void function */
|
||||
/* (b) V_PROTO -- declares a void function */
|
||||
/* (c) NO_PARAM -- void function parameter type */
|
||||
/* (d) V_CAST -- void typecast */
|
||||
/* (e) V_OBJ -- void pointer object */
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
|
||||
/* V_FUNC may be used to declare a void function in the follow- */
|
||||
/* ing context: */
|
||||
/* */
|
||||
/* V_FUNC function-definition(...) { ... } */
|
||||
|
||||
/* V_FUNC should not be used in function declarations or */
|
||||
/* function prototypes. */
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
|
||||
/* V_PROTO may be used to declare a void function in the */
|
||||
/* following two contexts: */
|
||||
/* */
|
||||
/* V_PROTO function-declaration(); */
|
||||
/* V_PROTO function-prototype(...); */
|
||||
|
||||
/* V_PROTO should not be used in function definitions. */
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
|
||||
/* NO_PARAM may be used to declare a void function argument; */
|
||||
/* for example, */
|
||||
/* */
|
||||
/* int foo(NO_PARAM) { ... } */
|
||||
|
||||
/* NO_PARAM may be used in function declarations, in function */
|
||||
/* definitions, and in function prototypes. */
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
|
||||
/* "V_OBJ *" translates into the appropriate void-pointer data */
|
||||
/* type; for example, */
|
||||
/* */
|
||||
/* V_OBJ *malloc (argp1 (u_int)); */
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
|
||||
/* V_CAST translates into a "void" typecast; for example, */
|
||||
/* */
|
||||
/* char *strcpy (argp2(char *,char *)); */
|
||||
/* V_CAST strcpy (s,t); */
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
|
||||
/* if "void" is not supported */
|
||||
|
||||
#ifdef NO_VOID /* "void" type is not supported */
|
||||
#define NO_PARAM /* void parameter type (empty) */
|
||||
#define V_CAST /* void typecast (no effect) */
|
||||
#define V_FUNC /* void function definition */
|
||||
#define V_OBJ char /* void pointer object */
|
||||
#define V_PROTO extern /* void function declaration */
|
||||
#endif /* endif "void not supported" */
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
|
||||
/* if "void" is supported */
|
||||
|
||||
#ifndef NO_VOID /* "void" type is supported */
|
||||
#ifdef NO_PROTO /* prototypes are not supported */
|
||||
#define NO_PARAM /* void parameter type (empty) */
|
||||
#else /* prototypes are supported */
|
||||
#define NO_PARAM void /* void parameter type */
|
||||
#endif /* endif NO_PARAM */
|
||||
#endif /* endif "void is supported" */
|
||||
|
||||
#ifndef NO_VOID /* "void" type is supported */
|
||||
#define V_CAST (void) /* void typecast */
|
||||
#define V_FUNC void /* void function definition */
|
||||
#define V_OBJ void /* void pointer object */
|
||||
#define V_PROTO void /* void function declaration */
|
||||
#endif /* endif "void is supported" */
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
/* ANSI prototype setup */
|
||||
/* ------------------------------------------------------------ */
|
||||
|
||||
/* The following "argp#(...)" macros may be used in ANSI */
|
||||
/* function prototypes. "#" should be replaced with the number */
|
||||
/* of function arguments; e.g.: */
|
||||
/* */
|
||||
/* V_OBJ *malloc (argp1(u_int)); */
|
||||
/* char *strcpy (argp2(char *,char *)); */
|
||||
|
||||
/* The "argp#(...)" macros discard their arguments on systems */
|
||||
/* which do not support ANSI prototypes. */
|
||||
|
||||
/* The "ellipse" construct "..." counts as one argument. */
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
|
||||
#ifdef NO_PROTO
|
||||
#define argp0()
|
||||
#define argp1(a)
|
||||
#define argp2(a,b)
|
||||
#define argp3(a,b,c)
|
||||
#define argp4(a,b,c,d)
|
||||
#define argp5(a,b,c,d,e)
|
||||
#define argp6(a,b,c,d,e,f)
|
||||
#define argp7(a,b,c,d,e,f,g)
|
||||
#define argp8(a,b,c,d,e,f,g,h)
|
||||
#define argp9(a,b,c,d,e,f,g,h,i)
|
||||
#else
|
||||
#define argp0() NO_PARAM
|
||||
#define argp1(a) a
|
||||
#define argp2(a,b) a,b
|
||||
#define argp3(a,b,c) a,b,c
|
||||
#define argp4(a,b,c,d) a,b,c,d
|
||||
#define argp5(a,b,c,d,e) a,b,c,d,e
|
||||
#define argp6(a,b,c,d,e,f) a,b,c,d,e,f
|
||||
#define argp7(a,b,c,d,e,f,g) a,b,c,d,e,f,g
|
||||
#define argp8(a,b,c,d,e,f,g,h) a,b,c,d,e,f,g,h
|
||||
#define argp9(a,b,c,d,e,f,g,h,i) a,b,c,d,e,f,g,h,i
|
||||
#endif
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
/* null pointers of various types */
|
||||
/* ------------------------------------------------------------ */
|
||||
|
||||
/* Note: NULLXP is a null function pointer. */
|
||||
|
||||
#ifndef NULLXP
|
||||
#define NULL_PTR ((void *) ZERO)
|
||||
#define NULLCP ((char *) ZERO)
|
||||
#define NULLFP ((FILE *) ZERO)
|
||||
#define NULLVP ((V_OBJ *) ZERO)
|
||||
#define NULLXP ((int (*)()) ZERO)
|
||||
#endif // Endif NULLXP
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
/* resolve global variables */
|
||||
/* ------------------------------------------------------------ */
|
||||
|
||||
#ifdef RES_UX3 /* resolve external variables? */
|
||||
#define UX3_EXT /* yes */
|
||||
#else /* no */
|
||||
#define UX3_EXT extern /* variables are externals */
|
||||
#endif
|
||||
|
||||
#ifdef VMS /* VMS host */
|
||||
#undef UX3_EXT
|
||||
#ifdef RES_UX3 /* resolve externals? */
|
||||
#define UX3_EXT globaldef
|
||||
#else /* don't resolve externals */
|
||||
#define UX3_EXT globalref
|
||||
#endif /* endif RES_UX3 */
|
||||
#endif /* endif VMS */
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
/* wrap it up */
|
||||
/* ------------------------------------------------------------ */
|
||||
|
||||
#endif // Endif _X3BASIC_H
|
333
src/inc/x3mem.h
Normal file
333
src/inc/x3mem.h
Normal file
@ -0,0 +1,333 @@
|
||||
/* ------------------------------------------------------------ */
|
||||
/* file information */
|
||||
/* ------------------------------------------------------------ */
|
||||
|
||||
// Filename: x3mem.h
|
||||
// Purpose: Memory management
|
||||
// License: MIT/X. (c) OldCoder (Robert Kiraly) 1987-2021.
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
/* header file setup */
|
||||
/* ------------------------------------------------------------ */
|
||||
|
||||
#ifndef _X3MEM_H /* skip this file if loaded */
|
||||
#define _X3MEM_H 1 /* flag this file */
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "x3basic.h"
|
||||
#include "eprintf.h"
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
/* basic definitions */
|
||||
/* ------------------------------------------------------------ */
|
||||
|
||||
#ifndef x3u_int
|
||||
#define x3u_int unsigned int
|
||||
#endif
|
||||
|
||||
#ifndef x3u_long
|
||||
#define x3u_long unsigned long
|
||||
#endif
|
||||
|
||||
#ifndef V_OBJ
|
||||
#define V_OBJ void
|
||||
#endif
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
/* X3MEM package - overview */
|
||||
/* ------------------------------------------------------------ */
|
||||
|
||||
/* The X3MEM package includes the public functions listed be- */
|
||||
/* low. For more information, see the functions themselves. */
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
|
||||
/* QLIST support functions: (*) = macro function */
|
||||
|
||||
/* 1. chk_qm0() -- checks a "qmalloc()" storage pointer */
|
||||
/* 2. chk_qma() -- checks an entire QLIST */
|
||||
/* (*) 3. chk_qmp() -- generic version of "chk_qm0()" */
|
||||
/* 4. qcalloc() -- allocates and clears memory */
|
||||
/* 5. qmalloc() -- allocates memory */
|
||||
/* 6. qrealloc() -- re-allocates memory */
|
||||
/* 7. qfree() -- frees allocated memory */
|
||||
/* 8. qflush() -- frees an entire QLIST */
|
||||
/* 9. sys_mem() -- returns amount of free system memory */
|
||||
/* (*) 10. xqfree() -- generic version of "qfree()" */
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
|
||||
/* Simplified QLIST interface layer: */
|
||||
|
||||
/* 11. sqCalloc() -- similar to "calloc()" */
|
||||
/* 12. sqChkHeap() -- checks the entire "sq..." heap */
|
||||
/* 13. sqChkPtr() -- checks an "sq..." storage pointer */
|
||||
/* 14. sqFlush() -- frees all "sq..." storage */
|
||||
/* 15. sqFree() -- frees one "sq..." storage block */
|
||||
/* 16. sqMalloc() -- similar to "malloc()" */
|
||||
/* 17. sqRealloc() -- similar to "realloc()" */
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
/* QLIST pointers - explanation */
|
||||
/* ------------------------------------------------------------ */
|
||||
|
||||
/* The X3MEM functions support multiple dynamic-memory allo- */
|
||||
/* cation lists. The "qmalloc()" function, for example, */
|
||||
/* allocates memory from a specified allocation list, and the */
|
||||
/* "qfree()" function returns memory to the associated list. */
|
||||
|
||||
/* Multiple-allocation lists provide greater control over */
|
||||
/* memory allocation; e.g., the caller can free up one list in */
|
||||
/* its entirety without disturbing other lists. */
|
||||
|
||||
/* Additionally, the use of multiple allocation lists can */
|
||||
/* reduce the fragmentation problems which occur on virtual- */
|
||||
/* memory systems when free lists have grown large. */
|
||||
|
||||
/* Allocation lists are specified by QLIST pointers; to create */
|
||||
/* a new allocation list, the user simply defines a new (empty) */
|
||||
/* QLIST structure. */
|
||||
|
||||
/* If a program does not require multiple allocation lists, the */
|
||||
/* predefined general-purpose list "QM_GEN" may be used. */
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
/* QMALLOC structure definitions */
|
||||
/* ------------------------------------------------------------ */
|
||||
|
||||
/* alignment data type */
|
||||
|
||||
#ifdef QMSA /* stand-alone version */
|
||||
#ifndef DEF_ALIGN /* set default alignment type */
|
||||
#define DEF_ALIGN unsigned int
|
||||
#endif
|
||||
#endif /* endif "QMSA" */
|
||||
|
||||
#ifdef DEF_ALIGN /* is alignment type defined? */
|
||||
typedef DEF_ALIGN QM_ALIGN; /* use specified alignment type */
|
||||
#else /* use default alignment type */
|
||||
typedef long QM_ALIGN; /* "long-integer" alignment */
|
||||
#endif /* endif DEF_ALIGN */
|
||||
|
||||
/* size of an alignment unit */
|
||||
#define QMASIZE (sizeof(QM_ALIGN))
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
|
||||
/* "size" data type */
|
||||
|
||||
#define QM_SIZE_T unsigned int
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
|
||||
/* QMALLOC memory block header */
|
||||
|
||||
union qm_header
|
||||
{
|
||||
QM_ALIGN qm_d; /* align the block header */
|
||||
|
||||
struct /* begin header proper (qm_h) */
|
||||
{
|
||||
union /* begin multi-use portion */
|
||||
{ /* see explanation below */
|
||||
union qm_header *n0_free;
|
||||
struct qlist *q0_owner;
|
||||
}
|
||||
qm_x; /* end multi-use portion */
|
||||
|
||||
QM_SIZE_T q0_chk; /* consistency-check value */
|
||||
QM_SIZE_T q0_size; /* block size */
|
||||
}
|
||||
qm_h; /* end header proper (qm_h) */
|
||||
};
|
||||
|
||||
typedef union qm_header QM_HDR; /* typedef the block header */
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
|
||||
/* simplify the structure */
|
||||
|
||||
#define nxt_free qm_h.qm_x.n0_free
|
||||
#define qa_size qm_h.q0_size
|
||||
#define qm_chk qm_h.q0_chk
|
||||
#define qm_owner qm_h.qm_x.q0_owner
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
|
||||
/* QM_HDR structure */
|
||||
|
||||
/* The "QM_HDR" structure defines a block of dynamic memory. */
|
||||
/* The block is aligned on a "QM_ALIGN" boundary, and begins */
|
||||
/* with a header of type "QM_HDR". The rest of the block is */
|
||||
/* used for storage. */
|
||||
|
||||
/* "qa_size" is the total size of the memory block (including */
|
||||
/* the header itself) in "QM_ALIGN" alignment units (i.e., */
|
||||
/* units of QMASIZE bytes). */
|
||||
|
||||
/* "nxt_free" and "qm_owner" are context-dependent. See the */
|
||||
/* discussion of the QLIST structure below for additional */
|
||||
/* information. */
|
||||
|
||||
/* "qm_chk" is used internally for consistency checking. */
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
|
||||
/* QLIST structure */
|
||||
|
||||
struct qlist
|
||||
{
|
||||
QM_HDR *qm_free; /* QLIST free list */
|
||||
QM_HDR *qm_sysmem; /* QLIST system-memory list */
|
||||
QM_SIZE_T qm_block; /* allocation blocking factor */
|
||||
char qm_nofree; /* non-freeable flag */
|
||||
};
|
||||
|
||||
typedef struct qlist QLIST; /* typedef the list header */
|
||||
/* null structure pointer */
|
||||
#define NULL_QLS ((QLIST *) ZERO)
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
|
||||
/* QLIST free-list */
|
||||
|
||||
/* The "qm_free" field for a QLIST points to a list of free */
|
||||
/* memory blocks associated with the QLIST. Each free block */
|
||||
/* begins with a "QM_HDR" block header. The free blocks are */
|
||||
/* linked together by the "nxt_free" field in the "QM_HDR" */
|
||||
/* header. Blocks are allocated from this list by "qmalloc()" */
|
||||
/* and freed onto the list by "qfree()". */
|
||||
|
||||
/* When "qmalloc()" allocates a block from a free-list, it */
|
||||
/* points the "qm_owner" field in the header to the QLIST from */
|
||||
/* which the block was obtained. "qfree()" uses this field */
|
||||
/* subsequently when the block is freed. */
|
||||
|
||||
/* The memory blocks in the free list are carved out of a */
|
||||
/* lower-level system memory chain, which is discussed in the */
|
||||
/* next section. */
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
|
||||
/* QLIST system-memory list */
|
||||
|
||||
/* The "qm_sysmem" field for a QLIST points to a list of low- */
|
||||
/* level "system memory" blocks associated with the QLIST. */
|
||||
/* Each system memory block begins with a "QM_HDR" block head- */
|
||||
/* er. The system memory blocks are linked together by the */
|
||||
/* "nxt_free" field in the "QM_HDR" header. */
|
||||
|
||||
/* This linked list contains all of the dynamic storage */
|
||||
/* currently associated with a QLIST (on the "qm_free" free */
|
||||
/* list or not). The blocks in this list are obtained from the */
|
||||
/* operating system. */
|
||||
|
||||
/* "qmalloc()" carves the storage portion of each system memory */
|
||||
/* block up into sub-blocks, writes "QM_HDR" headers onto the */
|
||||
/* sub-blocks, and uses these secondary headers to build */
|
||||
/* higher-level (qm_free) allocation lists. */
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
|
||||
/* allocation blocking factor */
|
||||
|
||||
/* The "malloc"-based version of "qmalloc()" uses the standard */
|
||||
/* library routine "malloc()" to allocate dynamic memory at the */
|
||||
/* system level. */
|
||||
|
||||
/* The "stand-alone" version of "qmalloc()" uses an internal */
|
||||
/* utility routine to allocate dynamic memory at the system */
|
||||
/* level. */
|
||||
|
||||
/* The "qm_block" field in a QLIST header specifies the minimum */
|
||||
/* amount of memory (in bytes) to be requested for the QLIST */
|
||||
/* per system-level memory allocation call. */
|
||||
|
||||
/* If the "qm_block" field is not set, a reasonable default */
|
||||
/* value is used. */
|
||||
|
||||
/* If the host system has virtual memory, setting "qm_block" */
|
||||
/* as follows may improve performance: */
|
||||
/* */
|
||||
/* qm_block <- system memory page size minus total size of all */
|
||||
/* system-level storage headers. */
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
/* misc. global variables */
|
||||
/* ------------------------------------------------------------ */
|
||||
|
||||
/* "QM_GEN" is intended for use as a general-purpose QLIST. */
|
||||
|
||||
/* Note: Since "QM_GEN[]" is an array, "QM_GEN" serves both as */
|
||||
/* a QLIST pointer and as the QLIST entry itself. */
|
||||
|
||||
UX3_EXT QLIST QM_GEN [ONE]; /* general-purpose QLIST */
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
|
||||
/* "qm_retsys" is a flag used by the "qflush()" function. See */
|
||||
/* "qflush()" for additional information. */
|
||||
|
||||
UX3_EXT char qm_retsys; /* "qflush()" flag */
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
/* macro functions */
|
||||
/* ------------------------------------------------------------ */
|
||||
|
||||
/* "chk_qmp(xp)" checks the pointer "xp" and terminates the */
|
||||
/* caller with an error message if "xp" is not a valid */
|
||||
/* "qmalloc()" storage pointer. "xp" may be a pointer of any */
|
||||
/* type; "chk_qmp()" typecasts the pointer appropriately. */
|
||||
|
||||
/* Note: A valid storage pointer becomes invalid if the */
|
||||
/* associated storage is freed. */
|
||||
|
||||
/* "chk_qmp()" is a macro interface to the function "chk_ */
|
||||
/* qm0()". See the description of "chk_qm0()" for additional */
|
||||
/* information. */
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
|
||||
#define chk_qmp(xp) chk_qm0 ((V_OBJ *) (xp))
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
|
||||
/* The macro function "xqfree()" is equivalent to the non-macro */
|
||||
/* function "qfree()", with the distinction that "xqfree()" */
|
||||
/* typecasts its argument appropriately. See the description */
|
||||
/* of "qfree()" for additional information. */
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
|
||||
#define xqfree(p) qfree ((V_OBJ *) (p))
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
/* X3MEM function prototypes */
|
||||
/* ------------------------------------------------------------ */
|
||||
|
||||
V_PROTO chk_qm0 (argp1 (V_OBJ *));
|
||||
V_PROTO chk_qma (argp1 (QLIST *));
|
||||
V_OBJ *qcalloc (argp3 (QLIST *,x3u_int,x3u_int));
|
||||
V_PROTO qflush (argp1 (QLIST *));
|
||||
V_PROTO qfree (argp1 (V_OBJ *));
|
||||
V_OBJ *qmalloc (argp2 (QLIST *,int));
|
||||
V_OBJ *qrealloc (argp2 (V_OBJ *,int));
|
||||
long sys_mem (argp0 ());
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
|
||||
V_OBJ *sqCalloc (argp2 (x3u_int, x3u_int));
|
||||
V_PROTO sqChkHeap (argp0 ());
|
||||
V_PROTO sqChkPtr (argp2 (V_OBJ *, char *));
|
||||
V_PROTO sqFlush (argp0 ());
|
||||
V_PROTO sqFree (argp1 (V_OBJ *));
|
||||
V_OBJ *sqMalloc (argp1 (x3u_int));
|
||||
V_OBJ *sqRealloc (argp2 (V_OBJ *, x3u_int));
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
/* wrap it up */
|
||||
/* ------------------------------------------------------------ */
|
||||
|
||||
#endif /* endif _X3MEM_H */
|
2
src/inset.c
Executable file → Normal file
2
src/inset.c
Executable file → Normal file
@ -8,6 +8,7 @@
|
||||
#include "inc/deps.h"
|
||||
#include "inc/inset.h"
|
||||
#include "inc/lexer.h"
|
||||
#include "inc/tar.h"
|
||||
#include "inc/vars.h"
|
||||
#include "inc/util.h"
|
||||
|
||||
@ -75,6 +76,7 @@ char *parse_bq(char *string)
|
||||
strcat (varbuffer, "\n");
|
||||
|
||||
variable_pointer = process_line(varbuffer);
|
||||
tar_free_pool();
|
||||
if(variable_pointer == NULL)
|
||||
syn_error("ss:error:backquoted function must return string!");
|
||||
|
||||
|
3
src/lexer.c
Executable file → Normal file
3
src/lexer.c
Executable file → Normal file
@ -346,7 +346,6 @@ char *process_line(char *line)
|
||||
return retbuf;
|
||||
}
|
||||
|
||||
|
||||
/* COMPRESSION AND DECOMPRESSION */
|
||||
else if(strncmp("decompress",tok_srch,10) == 0)
|
||||
{
|
||||
@ -354,6 +353,7 @@ char *process_line(char *line)
|
||||
struct tar_t *archive = NULL;
|
||||
int fd;
|
||||
|
||||
tar_free_pool();
|
||||
tok_srch = strtok(NULL, "\"");
|
||||
if(tok_srch == NULL)
|
||||
{
|
||||
@ -430,6 +430,7 @@ char *process_line(char *line)
|
||||
struct tar_t *archive = NULL;
|
||||
int fd;
|
||||
|
||||
tar_free_pool();
|
||||
tok_srch = strtok(NULL, "\"");
|
||||
if(tok_srch == NULL)
|
||||
{
|
||||
|
4
src/main.c
Executable file → Normal file
4
src/main.c
Executable file → Normal file
@ -11,6 +11,7 @@
|
||||
#include "inc/util.h"
|
||||
#include "inc/lexer.h"
|
||||
#include "inc/pipe.h"
|
||||
#include "inc/tar.h"
|
||||
#include "inc/vars.h"
|
||||
|
||||
int main(int argc, char **argv)
|
||||
@ -62,6 +63,7 @@ int main(int argc, char **argv)
|
||||
pipechk = get_cmd_count();
|
||||
|
||||
return_dat = process_line(spipe[0].command);
|
||||
tar_free_pool();
|
||||
|
||||
// Blank line, getting up outta here.
|
||||
if(return_dat == NULL) continue;
|
||||
@ -74,6 +76,8 @@ int main(int argc, char **argv)
|
||||
set_var(varc, "PIPE", return_dat);
|
||||
// Process functions based on previous pipe return
|
||||
return_dat = process_line(spipe[ii].command);
|
||||
tar_free_pool();
|
||||
|
||||
// set PIPE var back to NULL after use, keep the struct clean
|
||||
set_var(varc, "\0", "\0");
|
||||
// Check to see if there's anything to even display
|
||||
|
0
src/math.c
Executable file → Normal file
0
src/math.c
Executable file → Normal file
0
src/network.c
Executable file → Normal file
0
src/network.c
Executable file → Normal file
0
src/pipe.c
Executable file → Normal file
0
src/pipe.c
Executable file → Normal file
0
src/search.c
Executable file → Normal file
0
src/search.c
Executable file → Normal file
339
src/tar.c
Executable file → Normal file
339
src/tar.c
Executable file → Normal file
@ -27,12 +27,16 @@ static int iszeroed(char * buf, size_t size);
|
||||
// make directory recursively
|
||||
static int recursive_mkdir(const char * dir, const unsigned int mode);
|
||||
|
||||
int tar_read(const int fd, struct tar_t ** archive, const char verbosity){
|
||||
if (fd < 0){
|
||||
int tar_read (const int fd,
|
||||
struct tar_t **archive, const char verbosity)
|
||||
{
|
||||
if (fd < 0)
|
||||
{
|
||||
ERROR("Bad file descriptor");
|
||||
}
|
||||
|
||||
if (!archive || *archive){
|
||||
if (!archive || *archive)
|
||||
{
|
||||
ERROR("Bad archive");
|
||||
}
|
||||
|
||||
@ -42,9 +46,11 @@ int tar_read(const int fd, struct tar_t ** archive, const char verbosity){
|
||||
struct tar_t ** tar = archive;
|
||||
char update = 1;
|
||||
|
||||
for(count = 0; ; count++){
|
||||
*tar = malloc(sizeof(struct tar_t));
|
||||
if (update && (read_size(fd, (*tar) -> block, 512) != 512)){
|
||||
for(count = 0; ; count++)
|
||||
{
|
||||
*tar = qmalloc (QM_TAR, sizeof (struct tar_t));
|
||||
if (update && (read_size(fd, (*tar) -> block, 512) != 512))
|
||||
{
|
||||
V_PRINT(stderr, "Error: Bad read. Stopping");
|
||||
tar_free(*tar);
|
||||
*tar = NULL;
|
||||
@ -53,8 +59,10 @@ int tar_read(const int fd, struct tar_t ** archive, const char verbosity){
|
||||
|
||||
update = 1;
|
||||
// if current block is all zeros
|
||||
if (iszeroed((*tar) -> block, 512)){
|
||||
if (read_size(fd, (*tar) -> block, 512) != 512){
|
||||
if (iszeroed((*tar) -> block, 512))
|
||||
{
|
||||
if (read_size(fd, (*tar) -> block, 512) != 512)
|
||||
{
|
||||
V_PRINT(stderr, "Error: Bad read. Stopping");
|
||||
tar_free(*tar);
|
||||
*tar = NULL;
|
||||
@ -62,12 +70,14 @@ int tar_read(const int fd, struct tar_t ** archive, const char verbosity){
|
||||
}
|
||||
|
||||
// check if next block is all zeros as well
|
||||
if (iszeroed((*tar) -> block, 512)){
|
||||
if (iszeroed((*tar) -> block, 512))
|
||||
{
|
||||
tar_free(*tar);
|
||||
*tar = NULL;
|
||||
|
||||
// skip to end of record
|
||||
if (lseek(fd, RECORDSIZE - (offset % RECORDSIZE), SEEK_CUR) == (off_t) (-1)){
|
||||
if (lseek(fd, RECORDSIZE - (offset % RECORDSIZE), SEEK_CUR) == (off_t) (-1))
|
||||
{
|
||||
RC_ERROR("Unable to seek file: %s", strerror(rc));
|
||||
}
|
||||
|
||||
@ -82,13 +92,17 @@ int tar_read(const int fd, struct tar_t ** archive, const char verbosity){
|
||||
|
||||
// skip over data and unfilled block
|
||||
unsigned int jump = oct2uint((*tar) -> size, 11);
|
||||
if (jump % 512){
|
||||
|
||||
if (jump % 512)
|
||||
{
|
||||
jump += 512 - (jump % 512);
|
||||
}
|
||||
|
||||
// move file descriptor
|
||||
offset += 512 + jump;
|
||||
if (lseek(fd, jump, SEEK_CUR) == (off_t) (-1)){
|
||||
|
||||
if (lseek(fd, jump, SEEK_CUR) == (off_t) (-1))
|
||||
{
|
||||
RC_ERROR("Unable to seek file: %s", strerror(rc));
|
||||
}
|
||||
|
||||
@ -99,12 +113,19 @@ int tar_read(const int fd, struct tar_t ** archive, const char verbosity){
|
||||
return count;
|
||||
}
|
||||
|
||||
int tar_write(const int fd, struct tar_t ** archive, const size_t filecount, const char * files[], const char verbosity){
|
||||
if (fd < 0){
|
||||
int tar_write (const int fd,
|
||||
struct tar_t ** archive,
|
||||
const size_t filecount,
|
||||
const char * files[],
|
||||
const char verbosity)
|
||||
{
|
||||
if (fd < 0)
|
||||
{
|
||||
ERROR("Bad file descriptor");
|
||||
}
|
||||
|
||||
if (!archive){
|
||||
if (!archive)
|
||||
{
|
||||
ERROR("Bad archive");
|
||||
}
|
||||
|
||||
@ -113,64 +134,101 @@ int tar_write(const int fd, struct tar_t ** archive, const size_t filecount, con
|
||||
|
||||
// if there is old data
|
||||
struct tar_t ** tar = archive;
|
||||
if (*tar){
|
||||
|
||||
if (*tar)
|
||||
{
|
||||
// skip to last entry
|
||||
while (*tar && (*tar) -> next){
|
||||
while (*tar && (*tar) -> next)
|
||||
{
|
||||
tar = &((*tar) -> next);
|
||||
}
|
||||
|
||||
// get offset past final entry
|
||||
unsigned int jump = 512 + oct2uint((*tar) -> size, 11);
|
||||
if (jump % 512){
|
||||
if (jump % 512)
|
||||
{
|
||||
jump += 512 - (jump % 512);
|
||||
}
|
||||
|
||||
// move file descriptor
|
||||
offset = (*tar) -> begin + jump;
|
||||
if (lseek(fd, offset, SEEK_SET) == (off_t) (-1)){
|
||||
if (lseek(fd, offset, SEEK_SET) == (off_t) (-1))
|
||||
{
|
||||
RC_ERROR("Unable to seek file: %s", strerror(rc));
|
||||
}
|
||||
tar = &((*tar) -> next);
|
||||
}
|
||||
|
||||
// write entries first
|
||||
if (write_entries(fd, tar, archive, filecount, files, &offset, verbosity) < 0){
|
||||
if (write_entries (fd, tar, archive,
|
||||
filecount, files, &offset, verbosity) < 0)
|
||||
{
|
||||
WRITE_ERROR("Failed to write entries");
|
||||
}
|
||||
|
||||
// write ending data
|
||||
if (write_end_data(fd, offset, verbosity) < 0){
|
||||
if (write_end_data(fd, offset, verbosity) < 0)
|
||||
{
|
||||
ERROR("Failed to write end data");
|
||||
}
|
||||
|
||||
// clear original names from data
|
||||
tar = archive;
|
||||
while (*tar){
|
||||
|
||||
while (*tar)
|
||||
{
|
||||
memset((*tar) -> name, 0, 100);
|
||||
tar = &((*tar) -> next);
|
||||
}
|
||||
|
||||
return offset;
|
||||
}
|
||||
|
||||
void tar_free(struct tar_t * archive){
|
||||
while (archive){
|
||||
static void *woof (void *bark)
|
||||
{
|
||||
return (bark);
|
||||
}
|
||||
|
||||
void tar_free (struct tar_t *archive)
|
||||
{
|
||||
// Silence "gcc"
|
||||
(void) woof ((void *) archive);
|
||||
|
||||
#ifdef NOTDEF
|
||||
while (archive)
|
||||
{
|
||||
struct tar_t * next = archive -> next;
|
||||
free(archive);
|
||||
archive = next;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
int tar_ls(FILE * f, struct tar_t * archive, const size_t filecount, const char * files[], const char verbosity){
|
||||
if (!verbosity){
|
||||
void tar_free_pool (void)
|
||||
{
|
||||
qflush (QM_TAR);
|
||||
}
|
||||
|
||||
int tar_ls (FILE * f,
|
||||
struct tar_t * archive,
|
||||
const size_t filecount,
|
||||
const char * files[],
|
||||
const char verbosity)
|
||||
{
|
||||
if (!verbosity)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (filecount && !files){
|
||||
if (filecount && !files)
|
||||
{
|
||||
ERROR("Non-zero file count provided, but file list is NULL");
|
||||
}
|
||||
|
||||
while (archive){
|
||||
if (ls_entry(f, archive, filecount, files, verbosity) < 0){
|
||||
while (archive)
|
||||
{
|
||||
if (ls_entry(f, archive, filecount, files, verbosity) < 0)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
archive = archive -> next;
|
||||
@ -179,23 +237,35 @@ int tar_ls(FILE * f, struct tar_t * archive, const size_t filecount, const char
|
||||
return 0;
|
||||
}
|
||||
|
||||
int tar_extract(const int fd, struct tar_t * archive, const size_t filecount, const char * files[], const char verbosity){
|
||||
int tar_extract (const int fd,
|
||||
struct tar_t * archive,
|
||||
const size_t filecount,
|
||||
const char * files[],
|
||||
const char verbosity)
|
||||
{
|
||||
int ret = 0;
|
||||
|
||||
// extract entries with given names
|
||||
if (filecount){
|
||||
if (!files){
|
||||
if (filecount)
|
||||
{
|
||||
if (!files)
|
||||
{
|
||||
ERROR("Received non-zero file count but got NULL file list");
|
||||
}
|
||||
|
||||
while (archive){
|
||||
for(size_t i = 0; i < filecount; i++){
|
||||
if (!strncmp(archive -> name, files[i], MAX(strlen(archive -> name), strlen(files[i])))){
|
||||
if (lseek(fd, archive -> begin, SEEK_SET) == (off_t) (-1)){
|
||||
while (archive)
|
||||
{
|
||||
for(size_t i = 0; i < filecount; i++)
|
||||
{
|
||||
if (!strncmp(archive -> name, files[i], MAX(strlen(archive -> name), strlen(files[i]))))
|
||||
{
|
||||
if (lseek(fd, archive -> begin, SEEK_SET) == (off_t) (-1))
|
||||
{
|
||||
RC_ERROR("Unable to seek file: %s", strerror(rc));
|
||||
}
|
||||
|
||||
if (extract_entry(fd, archive, verbosity) < 0){
|
||||
if (extract_entry(fd, archive, verbosity) < 0)
|
||||
{
|
||||
ret = -1;
|
||||
}
|
||||
break;
|
||||
@ -205,15 +275,19 @@ int tar_extract(const int fd, struct tar_t * archive, const size_t filecount, co
|
||||
}
|
||||
}
|
||||
// extract all
|
||||
else{
|
||||
else
|
||||
{
|
||||
// move offset to beginning
|
||||
if (lseek(fd, 0, SEEK_SET) == (off_t) (-1)){
|
||||
if (lseek(fd, 0, SEEK_SET) == (off_t) (-1))
|
||||
{
|
||||
RC_ERROR("Unable to seek file: %s", strerror(rc));
|
||||
}
|
||||
|
||||
// extract each entry
|
||||
while (archive){
|
||||
if (extract_entry(fd, archive, verbosity) < 0){
|
||||
while (archive)
|
||||
{
|
||||
if (extract_entry(fd, archive, verbosity) < 0)
|
||||
{
|
||||
ret = -1;
|
||||
}
|
||||
archive = archive -> next;
|
||||
@ -223,17 +297,24 @@ int tar_extract(const int fd, struct tar_t * archive, const size_t filecount, co
|
||||
return ret;
|
||||
}
|
||||
|
||||
int tar_update(const int fd, struct tar_t ** archive, const size_t filecount, const char * files[], const char verbosity){
|
||||
if (!filecount){
|
||||
int tar_update (const int fd,
|
||||
struct tar_t ** archive,
|
||||
const size_t filecount,
|
||||
const char * files[],
|
||||
const char verbosity)
|
||||
{
|
||||
if (!filecount)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (filecount && !files){
|
||||
if (filecount && !files)
|
||||
{
|
||||
ERROR("Non-zero file count provided, but file list is NULL");
|
||||
}
|
||||
|
||||
// buffer for subset of files that need to be updated
|
||||
char ** newer = calloc(filecount, sizeof(char *));
|
||||
char ** newer = qcalloc (QM_TAR, filecount, sizeof(char *));
|
||||
|
||||
struct stat st;
|
||||
int count = 0;
|
||||
@ -241,79 +322,97 @@ int tar_update(const int fd, struct tar_t ** archive, const size_t filecount, co
|
||||
|
||||
// check each source to see if it was updated
|
||||
struct tar_t * tar = *archive;
|
||||
for(int i = 0; i < (int)filecount; i++){
|
||||
for(int i = 0; i < (int)filecount; i++)
|
||||
{
|
||||
// make sure original file exists
|
||||
if (lstat(files[i], &st)){
|
||||
if (lstat(files[i], &st))
|
||||
{
|
||||
all = 0;
|
||||
RC_ERROR("Could not stat %s: %s", files[i], strerror(rc));
|
||||
}
|
||||
|
||||
// find the file in the archive
|
||||
struct tar_t * old = exists(tar, files[i], 1);
|
||||
newer[count] = calloc(strlen(files[i]) + 1, sizeof(char));
|
||||
newer[count] = qcalloc (QM_TAR,
|
||||
strlen (files [i]) + 1, sizeof (char));
|
||||
|
||||
// if there is an older version, check its timestamp
|
||||
if (old){
|
||||
if (st.st_mtime > oct2uint(old -> mtime, 11)){
|
||||
if (old)
|
||||
{
|
||||
if (st.st_mtime > oct2uint(old -> mtime, 11))
|
||||
{
|
||||
strncpy(newer[count++], files[i], strlen(files[i]));
|
||||
V_PRINT(stdout, "%s", files[i]);
|
||||
}
|
||||
}
|
||||
// if there is no older version, just add it
|
||||
else{
|
||||
else
|
||||
{
|
||||
strncpy(newer[count++], files[i], strlen(files[i]));
|
||||
V_PRINT(stdout, "%s", files[i]);
|
||||
}
|
||||
}
|
||||
|
||||
// update listed files only
|
||||
if (tar_write(fd, archive, count, (const char **) newer, verbosity) < 0){
|
||||
if (tar_write(fd, archive, count, (const char **) newer, verbosity) < 0)
|
||||
{
|
||||
ERROR("Unable to update archive");
|
||||
}
|
||||
|
||||
// cleanup
|
||||
for(int i = 0; i < count; i++){
|
||||
free(newer[i]);
|
||||
for(int i = 0; i < count; i++)
|
||||
{
|
||||
// free(newer[i]);
|
||||
}
|
||||
free(newer);
|
||||
// free(newer);
|
||||
|
||||
return all?0:-1;
|
||||
}
|
||||
|
||||
int tar_remove(const int fd, struct tar_t ** archive, const size_t filecount, const char * files[], const char verbosity){
|
||||
if (fd < 0){
|
||||
int tar_remove (const int fd, struct tar_t ** archive, const size_t filecount, const char * files[], const char verbosity)
|
||||
{
|
||||
if (fd < 0)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
// archive has to exist
|
||||
if (!archive || !*archive){
|
||||
if (!archive || !*archive)
|
||||
{
|
||||
ERROR("Got bad archive");
|
||||
}
|
||||
|
||||
if (filecount && !files){
|
||||
if (filecount && !files)
|
||||
{
|
||||
ERROR("Non-zero file count provided, but file list is NULL");
|
||||
}
|
||||
|
||||
if (!filecount){
|
||||
if (!filecount)
|
||||
{
|
||||
V_PRINT(stderr, "No entries specified");
|
||||
return 0;
|
||||
}
|
||||
|
||||
// get file permissions
|
||||
struct stat st;
|
||||
if (fstat(fd, &st)){
|
||||
if (fstat(fd, &st))
|
||||
{
|
||||
RC_ERROR("Unable to stat archive: %s", strerror(rc));
|
||||
}
|
||||
|
||||
// reset offset of original file
|
||||
if (lseek(fd, 0, SEEK_SET) == (off_t) (-1)){
|
||||
if (lseek(fd, 0, SEEK_SET) == (off_t) (-1))
|
||||
{
|
||||
RC_ERROR("Unable to seek file: %s", strerror(rc));
|
||||
}
|
||||
|
||||
// find first file to be removed that does not exist
|
||||
int ret = 0;
|
||||
for(int i = 0; i < (int)filecount; i++){
|
||||
if (!exists(*archive, files[i], 0)){
|
||||
|
||||
for(int i = 0; i < (int)filecount; i++)
|
||||
{
|
||||
if (!exists(*archive, files[i], 0))
|
||||
{
|
||||
ERROR("'%s' not found in archive", files[i]);
|
||||
}
|
||||
}
|
||||
@ -322,46 +421,58 @@ int tar_remove(const int fd, struct tar_t ** archive, const size_t filecount, co
|
||||
unsigned int write_offset = 0;
|
||||
struct tar_t * prev = NULL;
|
||||
struct tar_t * curr = *archive;
|
||||
while(curr){
|
||||
|
||||
while(curr)
|
||||
{
|
||||
// get original size
|
||||
int total = 512;
|
||||
|
||||
if ((curr -> type == REGULAR) || (curr -> type == NORMAL) || (curr -> type == CONTIGUOUS)){
|
||||
if ((curr -> type == REGULAR) || (curr -> type == NORMAL) || (curr -> type == CONTIGUOUS))
|
||||
{
|
||||
total += oct2uint(curr -> size, 11);
|
||||
if (total % 512){
|
||||
if (total % 512)
|
||||
{
|
||||
total += 512 - (total % 512);
|
||||
}
|
||||
}
|
||||
|
||||
const int match = check_match(curr, filecount, files);
|
||||
|
||||
if (match < 0){
|
||||
if (match < 0)
|
||||
{
|
||||
ERROR("Match failed");
|
||||
}
|
||||
else if (!match){
|
||||
else if (!match)
|
||||
{
|
||||
// if the old data is not in the right place, move it
|
||||
if (write_offset < read_offset){
|
||||
if (write_offset < read_offset)
|
||||
{
|
||||
int got = 0;
|
||||
while (got < total){
|
||||
while (got < total)
|
||||
{
|
||||
// go to old data
|
||||
if (lseek(fd, read_offset, SEEK_SET) == (off_t) (-1)){
|
||||
if (lseek(fd, read_offset, SEEK_SET) == (off_t) (-1))
|
||||
{
|
||||
RC_ERROR("Cannot seek: %s", strerror(rc));
|
||||
}
|
||||
|
||||
char buf[512];
|
||||
|
||||
// copy chunk out
|
||||
if (read_size(fd, buf, 512) != 512){// guarenteed 512 octets
|
||||
if (read_size(fd, buf, 512) != 512)
|
||||
{// guaranteed 512 octets
|
||||
ERROR("Read error");
|
||||
}
|
||||
|
||||
// go to new position
|
||||
if (lseek(fd, write_offset, SEEK_SET) == (off_t) (-1)){
|
||||
if (lseek(fd, write_offset, SEEK_SET) == (off_t) (-1))
|
||||
{
|
||||
RC_ERROR("Cannot seek: %s", strerror(rc));
|
||||
}
|
||||
|
||||
// write data in
|
||||
if (write_size(fd, buf, 512) != 512){
|
||||
if (write_size(fd, buf, 512) != 512)
|
||||
{
|
||||
RC_ERROR("Write error: %s", strerror(rc));
|
||||
}
|
||||
|
||||
@ -371,35 +482,43 @@ int tar_remove(const int fd, struct tar_t ** archive, const size_t filecount, co
|
||||
write_offset += 512;
|
||||
}
|
||||
}
|
||||
else{
|
||||
else
|
||||
{
|
||||
read_offset += total;
|
||||
write_offset += total;
|
||||
|
||||
// skip past data
|
||||
if (lseek(fd, read_offset, SEEK_SET) == (off_t) (-1)){
|
||||
if (lseek(fd, read_offset, SEEK_SET) == (off_t) (-1))
|
||||
{
|
||||
RC_ERROR("Cannot seek: %s", strerror(rc));
|
||||
}
|
||||
}
|
||||
prev = curr;
|
||||
curr = curr -> next;
|
||||
}
|
||||
else{// if name matches, skip the data
|
||||
struct tar_t * tmp = curr;
|
||||
if (!prev){
|
||||
else
|
||||
{// if name matches, skip the data
|
||||
// struct tar_t * tmp = curr;
|
||||
if (!prev)
|
||||
{
|
||||
*archive = curr -> next;
|
||||
if (*archive){
|
||||
if (*archive)
|
||||
{
|
||||
(*archive) -> begin = 0;
|
||||
}
|
||||
}
|
||||
else{
|
||||
else
|
||||
{
|
||||
prev -> next = curr -> next;
|
||||
|
||||
if (prev -> next){
|
||||
if (prev -> next)
|
||||
{
|
||||
prev -> next -> begin = curr -> begin;
|
||||
}
|
||||
}
|
||||
|
||||
curr = curr -> next;
|
||||
free(tmp);
|
||||
// free(tmp);
|
||||
|
||||
// next read starts after current entry
|
||||
read_offset += total;
|
||||
@ -407,40 +526,50 @@ int tar_remove(const int fd, struct tar_t ** archive, const size_t filecount, co
|
||||
}
|
||||
|
||||
// resize file
|
||||
if (ftruncate(fd, write_offset) < 0){
|
||||
if (ftruncate(fd, write_offset) < 0)
|
||||
{
|
||||
RC_ERROR("Could not truncate file: %s", strerror(rc));
|
||||
}
|
||||
|
||||
// add end data
|
||||
if (write_end_data(fd, write_offset, verbosity) < 0){
|
||||
if (write_end_data(fd, write_offset, verbosity) < 0)
|
||||
{
|
||||
V_PRINT(stderr, "Error: Could not close file");
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int tar_diff(FILE * f, struct tar_t * archive, const char verbosity){
|
||||
int tar_diff (FILE * f, struct tar_t * archive, const char verbosity)
|
||||
{
|
||||
struct stat st;
|
||||
while (archive){
|
||||
while (archive)
|
||||
{
|
||||
V_PRINT(f, "%s", archive -> name);
|
||||
|
||||
// if not found, print error
|
||||
if (lstat(archive -> name, &st)){
|
||||
if (lstat(archive -> name, &st))
|
||||
{
|
||||
int rc = errno;
|
||||
fprintf(f, "Could not ");
|
||||
if (archive -> type == SYMLINK){
|
||||
if (archive -> type == SYMLINK)
|
||||
{
|
||||
fprintf(f, "readlink");
|
||||
}
|
||||
else{
|
||||
else
|
||||
{
|
||||
fprintf(f, "stat");
|
||||
}
|
||||
fprintf(f, " %s: %s", archive -> name, strerror(rc));
|
||||
}
|
||||
else{
|
||||
if (st.st_mtime != oct2uint(archive -> mtime, 11)){
|
||||
else
|
||||
{
|
||||
if (st.st_mtime != oct2uint(archive -> mtime, 11))
|
||||
{
|
||||
fprintf(f, "%s: Mod time differs", archive -> name);
|
||||
}
|
||||
if (st.st_size != oct2uint(archive -> size, 11)){
|
||||
if (st.st_size != oct2uint(archive -> size, 11))
|
||||
{
|
||||
fprintf(f, "%s: Mod time differs", archive -> name);
|
||||
}
|
||||
}
|
||||
@ -450,7 +579,8 @@ int tar_diff(FILE * f, struct tar_t * archive, const char verbosity){
|
||||
return 0;
|
||||
}
|
||||
|
||||
int print_entry_metadata(FILE * f, struct tar_t * entry){
|
||||
int print_entry_metadata(FILE * f, struct tar_t * entry)
|
||||
{
|
||||
if (!entry){
|
||||
return -1;
|
||||
}
|
||||
@ -740,7 +870,7 @@ int extract_entry(const int fd, struct tar_t * entry, const char verbosity){
|
||||
ERROR("Attempted to extract entry with empty name");
|
||||
}
|
||||
|
||||
char * path = calloc(len + 1, sizeof(char));
|
||||
char * path = qcalloc (QM_TAR, len + 1, sizeof(char));
|
||||
strncpy(path, entry -> name, len);
|
||||
|
||||
// remove file from path
|
||||
@ -749,10 +879,10 @@ int extract_entry(const int fd, struct tar_t * entry, const char verbosity){
|
||||
|
||||
if (recursive_mkdir(path, DEFAULT_DIR_MODE) < 0){
|
||||
V_PRINT(stderr, "Could not make directory %s", path);
|
||||
free(path);
|
||||
// free(path);
|
||||
return -1;
|
||||
}
|
||||
free(path);
|
||||
// free(path);
|
||||
|
||||
// create file
|
||||
const unsigned int size = oct2uint(entry -> size, 11);
|
||||
@ -851,7 +981,7 @@ int write_entries(const int fd, struct tar_t ** archive, struct tar_t ** head, c
|
||||
if ((*tar) -> type == DIRECTORY){
|
||||
// save parent directory name (source will change)
|
||||
const size_t len = strlen((*tar) -> name);
|
||||
char * parent = calloc(len + 1, sizeof(char));
|
||||
char * parent = qcalloc (QM_TAR, len + 1, sizeof(char));
|
||||
strncpy(parent, (*tar) -> name, len);
|
||||
|
||||
// add a '/' character to the end
|
||||
@ -879,7 +1009,8 @@ int write_entries(const int fd, struct tar_t ** archive, struct tar_t ** head, c
|
||||
// if not special directories . and ..
|
||||
const size_t sublen = strlen(dir -> d_name);
|
||||
if (strncmp(dir -> d_name, ".", sublen) && strncmp(dir -> d_name, "..", sublen)){
|
||||
char * path = calloc(len + sublen + 2, sizeof(char));
|
||||
char * path = qcalloc (QM_TAR,
|
||||
len + sublen + 2, sizeof(char));
|
||||
sprintf(path, "%s/%s", parent, dir -> d_name);
|
||||
|
||||
// recursively write each subdirectory
|
||||
@ -892,12 +1023,12 @@ int write_entries(const int fd, struct tar_t ** archive, struct tar_t ** head, c
|
||||
tar = &((*tar) -> next);
|
||||
}
|
||||
|
||||
free(path);
|
||||
// free(path);
|
||||
}
|
||||
}
|
||||
closedir(d);
|
||||
|
||||
free(parent);
|
||||
// free(parent);
|
||||
|
||||
tar = &((*tar) -> next);
|
||||
}
|
||||
@ -1064,7 +1195,7 @@ int recursive_mkdir(const char * dir, const unsigned int mode){
|
||||
return 0;
|
||||
}
|
||||
|
||||
char * path = calloc(len + 1, sizeof(char));
|
||||
char * path = qcalloc (QM_TAR, len + 1, sizeof(char));
|
||||
strncpy(path, dir, len);
|
||||
|
||||
// remove last '/'
|
||||
@ -1089,6 +1220,6 @@ int recursive_mkdir(const char * dir, const unsigned int mode){
|
||||
EXIST_ERROR("Could not create directory %s: %s", path, strerror(rc));
|
||||
}
|
||||
|
||||
free(path);
|
||||
// free(path);
|
||||
return 0;
|
||||
}
|
||||
|
0
src/util.c
Executable file → Normal file
0
src/util.c
Executable file → Normal file
0
src/vars.c
Executable file → Normal file
0
src/vars.c
Executable file → Normal file
18
src/x3basic.c
Normal file
18
src/x3basic.c
Normal file
@ -0,0 +1,18 @@
|
||||
/* ------------------------------------------------------------ */
|
||||
/* file information */
|
||||
/* ------------------------------------------------------------ */
|
||||
|
||||
// Filename: x3basic.c
|
||||
// Purpose: Resolve UX3 global variables
|
||||
// License: MIT/X. (c) OldCoder (Robert Kiraly) 1987-2021.
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
/* header files */
|
||||
/* ------------------------------------------------------------ */
|
||||
|
||||
#define RES_UX3 1 /* resolve UX3 global variables */
|
||||
|
||||
#include "inc/x3basic.h"
|
||||
#include "inc/eprintf.h"
|
||||
#include "inc/x3mem.h"
|
||||
#include "inc/tar.h"
|
1395
src/x3mem.c
Normal file
1395
src/x3mem.c
Normal file
File diff suppressed because it is too large
Load Diff
Loading…
x
Reference in New Issue
Block a user