# include "dgd.h"
# include "str.h"
# include "array.h"
# include "object.h"
# include "xfloat.h"
# include "interpret.h"
# include "data.h"
# include "path.h"
# include "node.h"
# include "compile.h"
/*
* NAME: path->resolve()
* DESCRIPTION: resolve a path
*/
char *path_resolve(buf, file)
char *buf, *file;
{
register char *p, *q, *d;
strncpy(buf, file, STRINGSZ - 1);
buf[STRINGSZ - 1] = '\0';
d = p = q = buf;
for (;;) {
if (*p == '/' || *p == '\0') {
/* reached a directory separator */
if (q - 1 == d && d[0] == '.') {
/* . */
q = d;
} else if (q - 2 == d && d[0] == '.' && d[1] == '.') {
/* .. */
q = d;
if (q != buf) {
for (--q; q != buf && *--q != '/'; ) ;
}
}
if (q != buf) {
if (q[-1] == '/') {
/* // or path/ */
--q;
}
*q++ = *p;
}
d = q;
if (*p == '\0') {
break;
}
p++;
} else {
*q++ = *p++;
}
}
if (q == buf) {
/* "" -> "." */
*q++ = '.';
*q = '\0';
}
return buf;
}
/*
* NAME: path_string()
* DESCRIPTION: check and resolve a string path
*/
char *path_string(buf, file, len)
char *buf, *file;
unsigned int len;
{
if (len >= STRINGSZ || strlen(file) != len) {
return (char *) NULL;
}
return path_resolve(buf, file);
}
/*
* NAME: path->from()
* DESCRIPTION: resolve a (possibly relative) path
*/
char *path_from(buf, from, file)
register char *buf, *from, *file;
{
char buf2[STRINGSZ];
if (file[0] != '/' && strlen(from) + strlen(file) < STRINGSZ - 4) {
sprintf(buf2, "%s/../%s", from, file);
file = buf2;
}
return path_resolve(buf, file);
}
/*
* NAME: path->ed_read()
* DESCRIPTION: resolve an editor read file path
*/
char *path_ed_read(buf, file)
char *buf, *file;
{
register frame *f;
f = cframe;
if (OBJR(f->oindex)->flags & O_DRIVER) {
return path_resolve(buf, file);
} else {
PUSH_STRVAL(f, str_new(file, (long) strlen(file)));
call_driver_object(f, "path_read", 1);
if (f->sp->type != T_STRING) {
i_del_value(f->sp++);
return (char *) NULL;
}
path_resolve(buf, f->sp->u.string->text);
str_del((f->sp++)->u.string);
return buf;
}
}
/*
* NAME: path->ed_write()
* DESCRIPTION: resolve an editor write file path
*/
char *path_ed_write(buf, file)
char *buf, *file;
{
register frame *f;
f = cframe;
if (OBJR(f->oindex)->flags & O_DRIVER) {
return path_resolve(buf, file);
} else {
PUSH_STRVAL(f, str_new(file, (long) strlen(file)));
call_driver_object(f, "path_write", 1);
if (f->sp->type != T_STRING) {
i_del_value(f->sp++);
return (char *) NULL;
}
path_resolve(buf, f->sp->u.string->text);
str_del((f->sp++)->u.string);
return buf;
}
}
/*
* NAME: path->include()
* DESCRIPTION: resolve an include path
*/
char *path_include(buf, from, file)
char *buf, *from, *file;
{
register frame *f;
if (c_autodriver()) {
return path_from(buf, from, file);
}
f = cframe;
PUSH_STRVAL(f, str_new((char *) NULL, strlen(from) + 1L));
f->sp->u.string->text[0] = '/';
strcpy(f->sp->u.string->text + 1, from);
PUSH_STRVAL(f, str_new(file, (long) strlen(file)));
if (!call_driver_object(f, "path_include", 2)) {
f->sp++;
return path_from(buf, from, file);
}
if (f->sp->type != T_STRING) {
i_del_value(f->sp++);
return (char *) NULL;
}
path_resolve(buf, f->sp->u.string->text);
str_del((f->sp++)->u.string);
return buf;
}