#include "externals.h" #include "config.h" #include "util.h" #include "idf.h" void tolow(char *p) { while (*p) { if (*p >= 'A' && *p <= 'Z') *p |= 0x20; p ++; } } int strlowcmp(const char *s, const char *d) { int rc; char *ss = NULL; char *dd = NULL; ss = strdup(s); dd = strdup(d); if (!ss || !dd) { rc = strcmp(s, d); goto err; } tolow(ss); tolow(dd); rc = strcmp(ss, dd); err: if (ss) free(ss); if (dd) free(dd); return rc; } char *getfilepath(const char *d, const char *n) { int i = ((d)?strlen(d):0) + ((n)?strlen(n):0) + 3; char *p = malloc(i); if (p) { p[0] = 0; if (d) { strcpy(p, d); strcat(p, "/"); } strcat(p, n); unix_path(p); } return p; } char *getpath(const char *d, const char *n) { char *p = getfilepath(d, n); strcat(p, "/"); return p; } int is_space(int c) { return (c == ' ' || c == '\t'); } int is_empty(const char *str) { if (!str || !*str) return 1; while (*str && !is_space(*str++)) return 0; return 1; } char *strip(char *s) { char *e; while (is_space(*s)) s ++; if (!*s) return s; e = s + strlen(s) - 1; while (e != s && is_space(*e)) { *e = 0; e --; } return s; } int process_cmd(char *n, char *v, struct parser *cmd_parser) { int i; n = strip(n); v = strip(v); for (i = 0; cmd_parser[i].cmd; i++) { if (!strcmp(cmd_parser[i].cmd, n)) { return cmd_parser[i].fn(v, cmd_parser[i].p); } } return -1; } static int fgetsesc(char *oline, size_t size, char *(*getl)(void *p, char *s, int size), void *fp) { int nr = 0; char line[4096]; *oline = 0; *line = 0; while (getl(fp, line, sizeof(line))) { int i; nr ++; i = strcspn(line, "\n\r"); if (!i || !line[i]) break; line[i] = 0; if (line[i - 1] == '\\') { line[i - 1] = 0; strncat(oline, line, size); line[0] = 0; size -= strlen(line); if (size <= 0) return nr; } else { break; } } strncat(oline, line, size); return nr; } char *find_in_esc(const char *l, const char *s) { int esc = 0; for (; *l; l++) { if (esc) { esc = 0; continue; } l += strcspn(l, s); if (*l == '\\') { esc = 1; continue; } if (!esc) return (char*)l; } return NULL; } static void comments_zap(char *p) { char *l = find_in_esc(p, "\\;\n"); if (l) *l = 0; } int parse_all(void *fp, char *(*getl)(void *p, char *s, int size), const char *path, struct parser *cmd_parser) { int nr; int rc = 0; int line_nr = 1; char line[4096]; if (!fp) return -1; while ((nr = fgetsesc(line, sizeof(line), getl, fp))) { char *p = line; char *val; int len; line_nr += nr; p += strspn(p, " \t"); if (*p == ';') continue; len = strcspn(p, "="); if (p[len] != '=') /* just ignore it */ continue; p[len] = 0; val = p + len + 1; len = strcspn(p, " \t"); p[len] = 0; // printf("%s\n", p); val += strspn(val, " \t"); comments_zap(val); // val[strcspn(val, ";\n")] = 0; if (process_cmd(p, val, cmd_parser)) { rc = -1; fprintf(stderr, "Can't process cmd '%s' on line %d in '%s': %s\n", p, line_nr - nr, path, strerror(errno)); } } return rc; } static char *file_gets(void *fd, char *s, int size) { return fgets(s, size, (FILE *)fd); } static char *idff_gets(void *fd, char *s, int size) { return idf_gets((idff_t)fd, s, size); } int parse_ini(const char *path, struct parser *cmd_parser) { int rc = 0; FILE *fp; fp = fopen(path, "rb"); if (!fp) return -1; rc = parse_all(fp, file_gets, path, cmd_parser); fclose(fp); return rc; } int parse_idff(idff_t idff, const char *path, struct parser *cmd_parser) { if (!idff) return -1; return parse_all(idff, idff_gets, path, cmd_parser); } int parse_string(const char *v, void *data) { char **p = ((char **)data); if (*p) free(*p); *p = strdup(v); if (!*p) return -1; return 0; } char *encode_esc_string(const char *v) { char *r, *p; if (!v) return NULL; p = r = malloc((strlen(v)*2) + 1); if (!r) return NULL; while (*v) { switch (*v) { case ' ': *p ++ = '\\'; *p ++ = ' '; break; case '"': *p ++ = '\\'; *p ++ = '"'; break; case '\'': *p ++ = '\\'; *p ++ = '\''; break; case '\\': *p ++ = '\\'; *p ++ = '\\'; break; case '\n': *p ++ ='\\'; *p ++ ='\n'; break; default: *p ++ = *v; } v ++; } *p ++ = 0; return r; } int parse_esc_string(const char *v, void *data) { int esc = 0; char *ptr; char **p = ((char **)data); if (*p) free(*p); *p = strdup(v); if (!*p) return -1; for (ptr = *p; *v; v ++) { if (esc) { switch (*v) { case 'n': *ptr = '\n'; break; case '$': *ptr = '$'; break; case '\\': *ptr = '\\'; break; case ';': *ptr = ';'; break; case 'r': *ptr = '\n'; break; default: *ptr = *v; break; } esc = 0; ptr ++; continue; } else if (*v != '\\') { *ptr = *v; ptr ++; continue; } else esc = 1; } *ptr = 0; return 0; } int parse_int(const char *v, void *data) { int *i = (int *)data; char *eptr = NULL; *i = strtol(v, &eptr, 0); if (!eptr || *eptr) return -1; return 0; } int parse_float(const char *v, void *data) { float *f = (float *)data; if (sscanf(v, "%f", f) != 1) return -1; return 0; } static int parse_path(const char *v, void *data) { char **p = ((char **)data); if (*p) free(*p); if (!v[0]) { *p = strdup(""); return (*p)?0:-1; } *p = strdup(v); if (!*p) return -1; *p = sdl_path(*p); return 0; } extern int theme_relative; /* hack, theme layer here :( */ int parse_full_path(const char *v, void *data) { char cwd[PATH_MAX]; char **p = ((char **)data); if (theme_relative || !strncmp(v, "blank:", 6) || !strncmp(v, "box:", 4) || !strncmp(v, "spr:", 4)) /* hack for special files*/ return parse_path(v, data); if (*p) free(*p); if (!v[0]) { *p = strdup(""); return (*p)?0:-1; } getdir(cwd, sizeof(cwd)); *p = malloc(strlen(v) + strlen(cwd) + 2); if (!*p) return -1; strcpy(*p, cwd); strcat(*p,"/"); strcat(*p, v); *p = sdl_path(*p); return 0; } void unix_path(char *path) { char *p = path; if (!path) return; while (*p) { /* bad bad Windows!!! */ if (*p == '\\') *p = '/'; p ++; } return; } static char *lookup_tag_all(const char *tag, const char *comm, char *(*getl)(void *p, char *s, int size), void *fp) { int brk = 0; char *l; char line[1024]; while ((l = getl(fp, line, sizeof(line))) && !brk) { l = parse_tag(l, tag, comm, &brk); if (l) return l; } return NULL; } char *lookup_tag(const char *fname, const char *tag, const char *comm) { char *l; FILE *fd = fopen(fname, "rb"); if (!fd) return NULL; l = lookup_tag_all(tag, comm, file_gets, fd); fclose(fd); return l; } char *lookup_lang_tag(const char *fname, const char *tag, const char *comm) { char lang_tag[1024]; char *l; snprintf(lang_tag, sizeof(lang_tag), "%s(%s)", tag, opt_lang); l = lookup_tag(fname, lang_tag, comm); if (!l) l = lookup_tag(fname, tag, comm); return l; } char *lookup_lang_tag_idf(idff_t idf, const char *tag, const char *comm) { char lang_tag[1024]; char *l; if (!idf) return NULL; snprintf(lang_tag, sizeof(lang_tag), "%s(%s)", tag, opt_lang); l = lookup_tag_all(lang_tag, comm, idff_gets, idf); if (!l) { idf_seek(idf, 0, SEEK_SET); l = lookup_tag_all(tag, comm, idff_gets, idf); } return l; } char *parse_tag(char *line, const char *tag, const char *comm, int *brk) { char *l = line; char *ns = NULL; char ftag[1024]; snprintf(ftag, sizeof(ftag), "$%s:", tag); l += strspn(l, " \t"); if (strncmp(l, comm, strlen(comm))) { /* non coment block */ *brk = 1; return NULL; } l += strlen(comm); l += strspn(l, " \t"); if (strncmp(l, ftag, strlen(ftag))) return NULL; l += strlen(ftag); l += strspn(l, " \t"); ns = l; l = find_in_esc(l, "\\$"); if (l) *l = 0; l = ns; ns = NULL; if (parse_esc_string(l, &ns)) return NULL; ns[strcspn(ns, "\n\r")] = 0; return ns; } #ifdef _HAVE_ICONV #define CHAR_MAX_LEN 4 char *decode(iconv_t hiconv, const char *s) { size_t s_size, chs_size, outsz, insz; char *inbuf, *outbuf, *chs_buf; if (!s || hiconv == (iconv_t)(-1)) return NULL; s_size = strlen(s) + 1; chs_size = s_size * CHAR_MAX_LEN; if ((chs_buf = malloc(chs_size + CHAR_MAX_LEN))==NULL) goto exitf; outsz = chs_size; outbuf = chs_buf; insz = s_size; inbuf = (char*)s; while (insz) { if (iconv(hiconv, &inbuf, &insz, &outbuf, &outsz) == (size_t)(-1)) goto exitf; } *outbuf++ = 0; return chs_buf; exitf: if(chs_buf) free(chs_buf); return NULL; } #endif int remove_dir(const char *path) { DIR *d; struct dirent *de; if (!path) return 0; d = opendir(path); if (!d) { if (!access(path, F_OK)) { unlink(path); } return -1; } while ((de = readdir(d))) { char *p; if (!strcmp(de->d_name, ".") || !strcmp(de->d_name, "..")) continue; p = getfilepath(path, de->d_name); if (p) { remove_dir(p); free(p); } } closedir(d); rmdir(path); return 0; }