From 1030dc837b10a03a02a85d5504cbeec168ce49e2 Mon Sep 17 00:00:00 2001 From: Bernie Innocenti Date: Mon, 03 May 2010 21:53:47 +0000 Subject: Import XaoS r489 (trunk after version 3.5) --- (limited to 'src/util/xstdio.c') diff --git a/src/util/xstdio.c b/src/util/xstdio.c new file mode 100644 index 0000000..fc7eb42 --- /dev/null +++ b/src/util/xstdio.c @@ -0,0 +1,488 @@ +#ifndef _plan9_ +#include +#if defined(__EMX__) || defined(__APPLE__) +#include +#endif +#include +#include +#include +#include +#else +#include +#include +#endif +#include +#include +#include +#include +#include +#ifdef _WIN32 +#define strcmp stricmp +#endif +#ifdef DJGPP +#define strcmp stricmp +#endif + +/* We reserve character 01 to application directory so we can easily refer to data files */ +char *xio_appdir; +char *xio_homedir; + +char *xio_fixpath(CONST char *c) +{ + if (c[0] == '~') { + char *c1 = (char *) malloc(strlen(c) + strlen(xio_homedir) + 5); + sprintf(c1, "%s%s", xio_homedir, c + 1); + return c1; + } + if (c[0] == '\01') { + char *c1 = (char *) malloc(strlen(c) + strlen(xio_appdir) + 5); + sprintf(c1, "%s%s", xio_appdir, c + 1); + return c1; + } + return mystrdup(c); +} + +int +xio_getfiles(xio_constpath path1, char ***names, char ***dirs, + int *nnames2, int *ndirs2) +{ +#ifdef _plan9_ + *nnames2 = *ndirs2 = 0; +#else + char *path = xio_fixpath(path1); + int maxnames = 200, maxdirs = 200; + int nnames = 0, ndirs = 0; + DIR *dir = opendir(path); + struct stat buf; + char buff[4096]; + int pathlen; + struct dirent *e; + if (dir == NULL) + return 0; + *nnames2 = 0; + *ndirs2 = 0; + e = readdir(dir); + strcpy(buff, path); + pathlen = (int) strlen(path); + if (buff[pathlen - 1] != XIO_PATHSEP) + buff[pathlen] = XIO_PATHSEP; + else + pathlen--; + *names = (char **) malloc(maxnames * sizeof(**names)); + *dirs = (char **) malloc(maxdirs * sizeof(**dirs)); + free(path); + while (e != NULL) { + char *n = mystrdup(e->d_name); + strcpy(buff + pathlen + 1, e->d_name); + stat(buff, &buf); + if (S_ISDIR(buf.st_mode)) { + if (ndirs == maxdirs) + maxdirs *= 2, *dirs = + (char **) realloc(*dirs, maxdirs * sizeof(**dirs)); + (*dirs)[ndirs] = n; + ndirs++; + } else { + if (nnames == maxnames) + maxnames *= 2, *names = + (char **) realloc(*names, maxnames * sizeof(**names)); + (*names)[nnames] = n; + nnames++; + } + e = readdir(dir); + } + if (nnames) + *names = (char **) realloc(*names, nnames * sizeof(**names)); + else + free(*names), *names = NULL; + if (ndirs) + *dirs = (char **) realloc(*dirs, ndirs * sizeof(**dirs)); + else + free(*dirs), *dirs = NULL; + *nnames2 = nnames; + *ndirs2 = ndirs; + closedir(dir); + return 1; +#endif +} + +xio_path xio_getdirectory(xio_constpath filename) +{ + int i; + xio_pathdata directory; + for (i = (int) strlen(filename); i && filename[i] != '/' && + filename[i] != '\\' && filename[i] != XIO_PATHSEP; i--); + if (filename[i] == '/' || filename[i] == '\\' + || filename[i] == XIO_PATHSEP) + i++; + directory[i] = 0; + i--; + for (; i >= 0; i--) + directory[i] = filename[i]; + return (mystrdup(directory)); +} + +xio_path xio_getfilename(CONST char *basename, CONST char *extension) +{ + static char name[40]; + int nimage = 0; +#ifdef _plan9_ +#ifdef _plan9v4_ +#define DIRLEN 116 + uchar edir[DIRLEN]; +#else + char edir[DIRLEN]; +#endif +#else + struct stat sb; +#endif + char *base = xio_fixpath(basename); + do { + sprintf(name, "%s%i%s", base, nimage++, extension); + } +#ifndef _plan9_ + while (stat(name, &sb) != -1); +#else +#ifdef _plan9v4_ + while (stat(name, edir, DIRLEN) != -1); +#else + while (stat(name, edir) != -1); +#endif +#endif + free(base); + return (name); +} + +xio_file xio_getrandomexample(xio_path name) +{ +#ifndef _plan9_ + static CONST char *CONST paths[] = { /*Where examples should be located? */ + EXAMPLESPATH, /*Data path when XaoS is propertly installed */ + "\01" XIO_PATHSEPSTR "examples", + /*XaoS was started from root of source tree */ + "\01" XIO_PATHSEPSTR ".." XIO_PATHSEPSTR "examples", + "." XIO_PATHSEPSTR "examples", + /*XaoS was started from root of source tree */ + ".." XIO_PATHSEPSTR "examples", + /*XaoS was started from bin directory in source tree */ + XIO_EMPTYPATH, /*Oops...it's not. Try curent directory */ + }; + int i = -1, p; + DIR *d = NULL; + xio_file f; + struct dirent *dir; + int n; + int max = 0; + char *realpath = NULL; + + for (p = 0; p < (int) (sizeof(paths) / sizeof(char *)) && d == NULL; + p++) { + char *pp = xio_fixpath(paths[p]); + d = opendir(pp); + free(pp); + if (d != NULL) { + realpath = xio_fixpath(paths[p]); + max = 800 - (int) strlen(realpath); + for (i = 0; (dir = readdir(d)) != NULL; i++) { + int s = (int) strlen(dir->d_name); + if (s > max || s < 4 + || strcmp(".xpf", dir->d_name + s - 4)) + i--; + /*free(dir); */ + } + if (!i) { + /*uih->errstring = "No *.xpf files found"; */ + closedir(d); + free(realpath); + d = NULL; + continue; + } + break; + } + } + if (d == NULL) { + /*uih->errstring = "Can not open examples directory"; */ + return NULL; + } + + + + rewinddir(d); + dir = NULL; + n = (int) ((number_t) i * rand() / (RAND_MAX + 1.0)); + + for (i = 0; i <= n; i++) { + int s; + do { + /*if(dir!=NULL) free(dir); */ + dir = readdir(d); + if (dir == NULL) { + /*uih->errstring = "Reading of examples directory failed"; */ + closedir(d); + free(realpath); + return NULL; + } + s = (int) strlen(dir->d_name); + } + while (s > max || s < 4 || strcmp(".xpf", dir->d_name + s - 4)); + } + if (dir == NULL) { + /*uih->errstring = "Reading of examples directory failed"; */ + closedir(d); + free(realpath); + return NULL; + } + strcpy(name, realpath); + if (name[strlen(name) - 1] != XIO_PATHSEP) + strcat(name, XIO_PATHSEPSTR); + strcat(name, dir->d_name); + closedir(d); + /*free(dir); */ + + f = xio_ropen(name); + free(realpath); + return (f); +#endif +} + +xio_file xio_getcatalog(CONST char *name) +{ + static CONST xio_constpath paths[] = { /*Where catalogs should be located? */ + CATALOGSPATH, /*Data path when XaoS is propertly installed */ +#ifndef _plan9_ + "\01" XIO_PATHSEPSTR "catalogs" XIO_PATHSEPSTR, + "\01" XIO_PATHSEPSTR ".." XIO_PATHSEPSTR "catalogs" XIO_PATHSEPSTR, + "." XIO_PATHSEPSTR "catalogs" XIO_PATHSEPSTR, + /*XaoS was started from root of source tree */ + ".." XIO_PATHSEPSTR "catalogs" XIO_PATHSEPSTR, + /*XaoS was started from bin directory in source tree */ +#else + "./catalogs/", + /*XaoS was started from root of source tree */ + "../catalogs/", + /*XaoS was started from bin directory in source tree */ +#endif + XIO_EMPTYPATH, /*Oops...it's not. Try curent directory */ + }; + int i; + xio_file f = XIO_FAILED; + xio_pathdata tmp; + for (i = 0; + i < (int) (sizeof(paths) / sizeof(char *)) && f == XIO_FAILED; + i++) { + char *p = xio_fixpath(paths[i]); + xio_addfname(tmp, p, name); + free(p); + f = xio_ropen(tmp); + if (f == XIO_FAILED) { + xio_addextension(tmp, ".cat"); + f = xio_ropen(tmp); + } + } + return (f); +} + +xio_file xio_gethelp(void) +{ + static CONST xio_constpath paths[] = { /*Where help should be located? */ + HELPPATH, /*Data path when XaoS is propertly installed */ +#ifndef _plan9_ + "\01" XIO_PATHSEPSTR "help" XIO_PATHSEPSTR "xaos.hlp", + "\01" XIO_PATHSEPSTR ".." XIO_PATHSEPSTR "help" XIO_PATHSEPSTR + "xaos.hlp", + "." XIO_PATHSEPSTR "help" XIO_PATHSEPSTR "xaos.hlp", + /*XaoS was started from root of source tree */ + ".." XIO_PATHSEPSTR "help" XIO_PATHSEPSTR "xaos.hlp", + /*XaoS was started from bin directory in source tree */ + "." XIO_PATHSEPSTR "xaos.hlp", +#else + "./help/xaos.hlp", + /*XaoS was started from root of source tree */ + "../help/xaos.hlp", + /*XaoS was started from bin directory in source tree */ + "./xaos.hlp", +#endif + /*Oops...it's not. Try curent directory */ + }; + int i; + xio_file f = XIO_FAILED; + for (i = 0; + i < (int) (sizeof(paths) / sizeof(char *)) && f == XIO_FAILED; + i++) { + char *p = xio_fixpath(paths[i]); + f = xio_ropen(p); + free(p); + } + return (f); +} + +xio_file xio_gettutorial(CONST char *name, xio_path tmp) +{ + int i; + xio_file f = XIO_FAILED; + static CONST xio_constpath paths[] = { /*Where tutorials should be located? */ + TUTORIALPATH, /*Data path when XaoS is propertly installed */ +#ifndef _plan9_ + "\01" XIO_PATHSEPSTR "tutorial" XIO_PATHSEPSTR, + "\01" XIO_PATHSEPSTR ".." XIO_PATHSEPSTR "tutorial" XIO_PATHSEPSTR, + "." XIO_PATHSEPSTR "tutorial" XIO_PATHSEPSTR, /*XaoS was started from root of source tree */ + ".." XIO_PATHSEPSTR "tutorial" XIO_PATHSEPSTR, /*XaoS was started from bin directory in source tree */ +#else + "./tutorial/", /*XaoS was started from root of source tree */ + "../tutorial/", /*XaoS was started from bin directory in source tree */ +#endif + XIO_EMPTYPATH, /*Oops...it's not. Try curent directory */ + }; + + for (i = 0; + i < (int) (sizeof(paths) / sizeof(char *)) && f == XIO_FAILED; + i++) { + char *p = xio_fixpath(paths[i]); + xio_addfname(tmp, p, name); + f = xio_ropen(tmp); + free(p); + } + return (f); +} + +int xio_exist(xio_constpath name) +{ +#ifdef _plan9_ + return (0); +#else + struct stat buf; + return (!stat(name, &buf)); +#endif +} + +static int sputc(int c, xio_file f) +{ + return putc(c, (FILE *) f->data); +} + +static int sputs(CONST char *c, xio_file f) +{ + return fputs(c, (FILE *) f->data); +} + +static int sungetc(int c, xio_file f) +{ + return ungetc(c, (FILE *) f->data); +} + +static int sgetc(xio_file f) +{ + return getc((FILE *) f->data); +} + +static int sfeof(xio_file f) +{ + return feof((FILE *) f->data); +} + +static int sflush(xio_file f) +{ + return fflush((FILE *) f->data); +} + +static int ssclose(xio_file f) +{ + int r = fclose((FILE *) f->data); + free(f); + return r; +} + +xio_file xio_ropen(CONST char *name) +{ + xio_file f = (xio_file) calloc(1, sizeof(*f)); + name = xio_fixpath(name); + f->data = (void *) fopen(name, "rt"); + /*free (name); */ + if (!f->data) { + free(f); + return 0; + } + f->fclose = ssclose; + f->xeof = sfeof; + f->fgetc = sgetc; + f->fungetc = sungetc; + return f; +} + +xio_file xio_wopen(CONST char *name) +{ + xio_file f = (xio_file) calloc(1, sizeof(*f)); + name = xio_fixpath(name); + f->data = (void *) fopen(name, "wt"); + /*free (name); */ + if (!f->data) { + free(f); + return 0; + } + f->fputc = sputc; + f->fputs = sputs; + f->fclose = ssclose; + f->flush = sflush; + return f; +} + +#ifdef DJGPP +#define DRIVES +#endif +#ifdef _WIN32 +#define DRIVES +#endif +void xio_init(CONST char *name) +{ + if (getenv("HOME")) + xio_homedir = mystrdup(getenv("HOME")); + else + xio_homedir = mystrdup("./"); + if ( +#ifdef DRIVES + (((name[0] >= 'a' && name[0] <= 'z') + || (name[0] >= 'A' && name[0] <= 'Z')) && name[1] == ':' + && (name[2] == '\\' || name[2] == '/')) || +#endif + name[0] == '/' || name[0] == '\\' || name[0] == XIO_PATHSEP + || name[0] == '~') { + char *c = mystrdup(name); + int i; + int pos = 0; + for (i = 0; i < (int) strlen(c); i++) + if (name[i] == '/' || name[i] == '\\' + || name[i] == XIO_PATHSEP) + pos = i; + c[pos] = 0; + xio_appdir = xio_fixpath(c); + free(c); + } else { + char buf[4096]; + buf[0] = '.'; + buf[1] = 0; +#ifndef _plan9_ + getcwd(buf, sizeof(buf)); +#endif + xio_appdir = mystrdup(buf); + { + char *c = mystrdup(name), *c1; + int i; + int pos = 0; + for (i = 0; i < (int) strlen(c); i++) + if (name[i] == '/' || name[i] == '\\' + || name[i] == XIO_PATHSEP) + pos = i; + c[pos] = 0; + c1 = (char *) malloc(strlen(c) + strlen(xio_appdir) + 2); + sprintf(c1, "%s%s%s", xio_appdir, XIO_PATHSEPSTR, c); + free(c); + free(xio_appdir); + xio_appdir = c1; + } + } +} + +void xio_uninit() +{ + free(xio_appdir); + free(xio_homedir); +} -- cgit v0.9.1