/*
* Maketool - GTK-based front end for gmake
* Copyright (c) 1999-2003 Greg Banks
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* 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 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
*/
#include "util.h"
#include <stdarg.h>
CVSID("$Id: util.c,v 1.19 2003/10/03 12:18:33 gnb Exp $");
/*-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*/
void
estring_init(estring *e)
{
e->data = 0;
e->length = 0;
e->available = 0;
}
#define _estring_expand_by(e, dl) \
if ((e)->length + (dl) + 1 > (e)->available) \
{ \
(e)->available += MIN(1024, ((e)->length + (dl) + 1 - (e)->available)); \
(e)->data = ((e)->data == 0 ? g_new(char, (e)->available) : g_renew(char, (e)->data, (e)->available)); \
}
void
estring_append_string(estring *e, const char *str)
{
if (str != 0 && *str != '\0')
estring_append_chars(e, str, strlen(str));
}
void
estring_append_char(estring *e, char c)
{
_estring_expand_by(e, 1);
e->data[e->length++] = c;
e->data[e->length] = '\0';
}
void
estring_append_chars(estring *e, const char *buf, int len)
{
_estring_expand_by(e, len);
memcpy(&e->data[e->length], buf, len);
e->length += len;
e->data[e->length] = '\0';
}
void
estring_append_printf(estring *e, const char *fmt, ...)
{
va_list args;
int len;
/* ensure enough space exists for result, possibly too much */
va_start(args, fmt);
len = g_printf_string_upper_bound(fmt, args);
va_end(args);
_estring_expand_by(e, len);
/* format the string into the new space */
va_start(args, fmt);
vsprintf(e->data+e->length, fmt, args);
va_end(args);
e->length += strlen(e->data+e->length);
}
void
estring_truncate(estring *e)
{
e->length = 0;
if (e->data != 0)
e->data[0] = '\0';
}
/* remove leading whitespace */
void
estring_chug(estring *e)
{
int skip;
for (skip = 0 ;
skip < e->length && isspace(e->data[skip]) ;
skip++)
;
if (skip != 0)
{
e->length -= skip;
memmove(e->data, e->data+skip, e->length);
e->data[e->length] = '\0';
}
}
/* remove trailing whitespace */
void
estring_chomp(estring *e)
{
int len;
for (len = e->length ;
len > 0 && isspace(e->data[len-1]) ;
len--)
;
if (len != e->length)
{
e->length = len;
e->data[len] = '\0';
}
}
void
estring_free(estring *e)
{
if (e->data != 0)
{
g_free(e->data);
e->data = 0;
e->length = 0;
e->available = 0;
}
}
/*-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*/
const char _util_metachars[] = "'`\"&|$(){};<>\\#*?";
int
strprefix(const char *str, const char *pref)
{
int sl = strlen(str), pl = strlen(pref);
if (sl < pl)
return -1;
return strncmp(str, pref, pl);
}
char *
strescape(const char *s)
{
estring e;
estring_init(&e);
for ( ; *s ; s++)
{
if (ismetachar(*s) || isspace(*s))
estring_append_char(&e, '\\');
estring_append_char(&e, *s);
}
return (e.length == 0 ? g_strdup("") : e.data);
}
/*-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*/
#define LEFT_CURLY '{'
#define RIGHT_CURLY '}'
static void
do_expands(const char *in, estring *out, const char *expands[256])
{
while (*in)
{
if (*in == '%')
{
if (in[1] == LEFT_CURLY)
{
char *x;
int len;
gboolean doit = FALSE;
if ((x = strchr(in, RIGHT_CURLY)) == 0)
return;
len = (x - in) + 1;
switch (in[4])
{
case '+':
doit = (expands[(int)in[2]] != 0);
break;
}
if (doit)
{
int sublen = len-6;
char *sub = g_new(char, sublen+1);
memcpy(sub, in+5, sublen);
sub[sublen] = '\0';
do_expands(sub, out, expands);
g_free(sub);
}
in += len;
}
else
{
estring_append_string(out, expands[(int)in[1]]);
in += 2;
}
}
else
estring_append_char(out, *in++);
}
}
char *
expand_string(const char *in, const char *expands[256])
{
estring out;
estring_init(&out);
do_expands(in, &out, expands);
#if DEBUG
fprintf(stderr, "expand_string(): \"%s\" -> \"%s\"\n", in, out.data);
#endif
return out.data;
}
/*-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*/
gboolean
file_exists(const char *pathname)
{
struct stat sb;
return (stat(pathname, &sb) >= 0 && S_ISREG(sb.st_mode));
}
/*-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*/
const char *
file_home(void)
{
static char *home = 0;
if (home == 0)
{
home = getenv("HOME");
if (home == 0)
home = "";
home = g_strdup(home);
}
assert(home != 0);
return home;
}
/*-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*/
static char *currdir = 0;
const char *
file_current(void)
{
if (currdir == 0)
currdir = g_get_current_dir();
return currdir;
}
int
file_change_current(const char *dir)
{
if (chdir(dir) < 0)
return -1;
if (currdir != 0)
{
g_free(currdir);
currdir = 0;
}
return 0;
}
/*-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*/
/* TODO: handle path components "." and ".." */
char *
file_normalise(const char *path)
{
if (path[0] == '/')
return g_strdup(path);
return g_strconcat(file_current(), "/", path, 0);
}
/*-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*/
/*
* If `pref' is the initial subset of pathname components of `path',
* return a new string, else return 0. The returned string has
* the prefix replaced with `replace1', or `replace0' if the
* prefix is the whole path.
*/
static char *
file_denormalise_1(
const char *path,
const char *pref,
const char *replace0,
const char *replace1)
{
int preflen = strlen(pref);
if (!strncmp(path, pref, preflen) &&
(path[preflen] == '\0' || path[preflen] == '/'))
{
path += preflen;
while (*path == '/')
path++;
if (*path == '\0')
return g_strdup(replace0);
return g_strconcat(replace1, path, 0);
}
return 0;
}
char *
file_denormalise(const char *path, unsigned flags)
{
char *d;
if ((flags & DEN_PWD) &&
(d = file_denormalise_1(path, file_current(), ".", "")) != 0)
return d;
if ((flags & DEN_HOME) &&
(d = file_denormalise_1(path, file_home(), "~", "~/")) != 0)
return d;
return g_strdup(path);
}
/*-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*/
/*END*/
syntax highlighted by Code2HTML, v. 0.9.1