/* ENVIRON.H - Contains miscellaneous definitions of things which differ
               between Linux, OS/9 and MS-DOS

               Linux environment
               -----------------

   environ - C programming support functions
   Copyright (C) 2005  Martin C Gregorie
   
   This program is free software; you can redistribute it and/or
   modify it under the terms of the Lesser GNU General Public License.
   
   This program is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   GNU General Public License for more details.
  
   You should have received a copy of the Lesser GNU General Public License
   along with this program; if not, write to the Free Software
   Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
  
   Contact Martin Gregorie at martin@gregorie.org

*/

#include <stdio.h>
#include <dirent.h>
#include <time.h>

#define LINUX         "Linux"

#define PRINTER       "/dev/printer"
#define FORM_FEED     0x0c

#define BLANK         ' '

#define MAXLINE       161   /* Max length of a printline including
                               formatting characters */
#define TABSPACE      8
#define NAMELTH       256   /* Max length of a path name */

#ifndef TRUE
#define     TRUE      1
#endif
#ifndef FALSE
#define     FALSE     0
#endif

/* CONSTANTS */
/* ========= */

/* Reply values returned by argparse (getopt, getarg) */

#ifndef EOF
#       define EOF    (-1)
#endif

#ifndef NULL
#       define NULL   (0)
#endif

#define FOUND         1
#define NOTHING       0

/* Constants used by autodate and autotime */

#define AUTOFMT       0
#define DDMMMYY       1
#define MANUAL        2

/* Constants for diracc (diropen, dirclose, dirread) */

#ifdef OS9
#define NAMESIZE      29       /* Size of a name in a directory entry   */
#define DIRENT        32       /* Total size of a directory entry       */
#define PATHSEP       "/"
#define SEPCHAR       '/'
#define SEARCHSEP     ':'
#endif

#ifdef MSDOS
#define NAMESIZE      12       /* Max size of a DOS file name           */
#define ATTRIBUTE     11       /* File attribute byte offset            */
#define DIRENT        32       /* Total size of a directory entry       */
#define PATHSEP       "\\"
#define SEPCHAR       '\\'
#define SEARCHSEP     ';'
#endif

#ifdef LINUX
#define NAMESIZE      1024     /* Max size of a Linux file name         */
#define PATHSEP       "/"
#define SEPCHAR       '/'
#define SEARCHSEP     ':'
#endif

#define DIR_EOF       0
#define DIR_NULL      1
#define DIR_FILE      2
#define DIR_SUBDIR    3

#define FIRSTCALL     1
#define NEXTCALL      2

/* Constants used by fixext, fixname, fixpath */

#ifdef OS9
#define MAXPATH       512
#define MAXNAME       28
#define MAXFILE       26
#define MAXEXT        26
#define SEPARATOR     '/'
#endif

#ifdef MSDOS
#define MAXPATH       80
#define MAXNAME       12
#define MAXFILE       8
#define MAXEXT        3
#define SEPARATOR     '\\'
#endif

#ifdef LINUX
#define MAXPATH       1024
#define MAXNAME       512
#define MAXFILE       256
#define MAXEXT        256
#define SEPARATOR     '/'
#endif

#define DOT           '.'
#define UNDERSCORE    '_'

/* Constants for logmsg (logsetup, logmsg, logdump) */

#define DIRECT_LOG    1
#define INDIRECT_LOG  0

#define STDOUT_LOG    1
#define STDERR_LOG    2

/* Constants for setpause */

#define P_RECORD      1
#define P_PAUSE       2
#define P_NOPAUSE     3
#define P_RESTORE     4

/* Constants for tempstore (tsopen, tsclose, tsputc, 
                            tsgetc, tsputstr, tsgetstr)
*/

#define TSLIM 16384


/* TYPE DEFINITIONS */
/* ================ */

/* Used by autodate and autotime */

typedef char* CHARDATE;
typedef char* CHARTIME;

/* Used by the circular buffer functions. */

typedef struct {
   int   size;
   char  *buff;
   int   read_ptr;
   int   write_ptr;
} CIRC_BUFF;

/* Structure containing national information used by country() */

struct  COUNTRY {
	            int  co_date;
	            char co_curr[5];
	            char co_thsep[2];
	            char co_desep[2];
	            char co_dtsep[2];
	            char co_tmsep[2];
	            char co_currstyle;
	            char co_digits;
	            char co_time;
	            long co_case;
	            char co_dasep[2];
	            char co_fill[10];
                };

/* used by diracc (diropen, dirclose, dirread) */

typedef unsigned char BYTE;

#ifdef OS9
typedef struct {
                    FILE    *p;
                    char    path[NAMELTH];
               }
                    DIRPATH;
#endif

#ifdef MSDOS
typedef struct {
                    struct  ffblk *p;
                    int     status;
                    char    path[NAMELTH];
               }
                    DIRPATH;

#endif

#ifdef LINUX
typedef struct {
                    DIR    *p;
                    char   path[NAMESIZE];
               }
                    DIRPATH;
#endif

/* Used by tempstore (tsopen, tsclose, tsputc, tsgetc, tsputstr, tsgetstr) */

typedef struct {
                    char  *buffer;
    	            int   fileused;
    	            char  *filename;
    	            FILE* fil;
    	            int   inptr;
    	            int   outptr;
    	            int   size;
               }
                    tempstore;
    
/* GLOBAL VARIABLES */
/* ================ */

/* Variables used by the extended version of 'getopt' */

extern char *optstart;          /* string containing valid option markers */
extern int  optbad;             /* contents returned for a bad option */
extern int  optchar;            /* char beginning a given argument */
extern int  opterrfd;           /* file no for error messages */
extern int  optmaybe;           /* marker for optional arguments */
extern int  optneed;            /* marker for mandatory arguments */
extern int  optcase;            /* controls option case sensitivity */

/*      Global variables used by all versions of 'getopt' */

extern char *optarg;            /* argument of the option */
extern int  opterr;             /* set to 0 to suppress error messages */
extern int  optind;             /* index of current argv[] */
extern int  optopt;             /* the actual option */

/* FUNCTIONS */
/* ========= */

/* Functions defined as macros */

#define min(a,b) ( a<b ? a : b )
#define max(a,b) ( a>b ? a : b )

/* Function templates */

int            argval(char *s, int d);
CHARDATE       autodate(struct tm *tbp, int fmt, int code);
CHARTIME       autotime(struct tm *tbp);
char           *bitsout(int v, int n);
CIRC_BUFF      *buff_create(int size);
int            buff_size(CIRC_BUFF *b);
void           buff_reset(CIRC_BUFF *b);
CIRC_BUFF      *buff_delete(CIRC_BUFF *b);
int            buff_freespace(CIRC_BUFF *b);
int            buff_usedspace(CIRC_BUFF *b);
void           buff_add_string(CIRC_BUFF *b, char *s, int n);
int            buff_extract_string(CIRC_BUFF *b,
                                   char *s,
                                   int  n,
                                   int  sep_active,
                                   int  sep_extern,
                                   char set_marker);
int            buff_add_one(CIRC_BUFF *b, char c);
int            buff_extract_one(CIRC_BUFF *b);
char           *byteout(char c);
char           *capitalise(char *s);
void           check_range(int val, int low, int high, char *desc);
int            chopinsert(void **Table,
                          int *Items,
                          int Tablimit,
                          void *NewItem,
                          int InsertPoint);
void           *chopsearch(void *Target,
                           void **Table,
                           int Items,
                           int *InsertHere,
                           int (*Compare)(const void*, const void*));
void           config_close(FILE *cf);
int            config_getline(FILE *cf, char *line, int lth);
FILE           *config_open(char *prog, char *name, int debug);
struct COUNTRY *country(int xcode, struct COUNTRY *cp);
DIRPATH        *diropen(char *p);
int            dirclose(DIRPATH *dp);
int            dirread(DIRPATH *dp, char *name);
void           dumphex(FILE *f, char *buff, int lth);
void           error(char *f, char *e, char *p);
void           *expand_space(void *pp, size_t n);
long           filesize(char *name);
char*          fixext(char *name, char *ext);
char*          fixname(char *name, char *ext, char *type);
char*          fixpath(char *path, char *ext, char *type);
char           *get_sigtrap_name(int e);
int            get_sigtrap_type();
void           *get_space(size_t n);
int            getarg(int nargc, char **nargv);
char           getdelcode(void);
char           getkey(void);
int            getopt(int nargc,
                      char * const nargv[],
                      const char *ostr);
char           *getpath(int argc, char *argv[], FILE *pathlist, int listflag);
char           *itoa(int i, char *a, int r);
void           logsetup(int r, int f, int s);
void           logtime(int t);
void           logmsg(char* fmt, ...);
void           logdump(void);
char           *ltoa(long i, char *a, int r);
int            numconv(char *s);
char*          numdisp(int n, char* units);
void*          plugin_getref(void *handle, char *name);
void*          pluginlib_open();
void           pluginlib_close(void *handle);
char           *pluginlib_error();
char           *progname(void);
char           *prstat(int status);
int            question(char *prompt);
void           *release_space(void *p);
void           set_sigtrap_debug(int d);
int            set_sigtraps();
FILE           *searchpath(char *list,
                           char *name,
                           char *mode1,
                           char *mode2,
                           int debug);
int            setpause(int action, int pathno);
void           setprog(char *name);
static void    sighandler(int sig);
char           *strhex(char *s);
char           *strlwr(char *s);
char           *strmfe(char *fullname, char *name, char *ext);
char           *strupr(char *s);
int            swapdir(char *path);
void           tabclear(char *tabstops);
int            tabdefault();
int            tabexpand(char dest[], int i, char *tabstops, char fill);
void           tabnormal(char *tabstops);
int            tabout(FILE *fn, int i, char *tabstops);
int            tabpos(int col, char *tabstops);
void           tabset(int col, char state, char *tabstops);
void           tabspread(int gap, char *tabstops);
void           trim(char *trimmed, char *s);
void           trimchars(char *trimmed, char *s, char *u);
tempstore*     tsopen(long s, int d);
tempstore*     tsclose(tempstore *ptr);
int            tsputc(tempstore *ptr, int c);
int            tsgetc(tempstore *ptr);
int            tsputstr(tempstore *ptr, char *str);
int            tsgetstr(tempstore *ptr, char *str, int n);
void           warn(char *f, char *e, char *p);

