about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--ChangeLog6
-rw-r--r--Src/glob.c32
-rw-r--r--Src/init.c16
-rw-r--r--Src/utils.c73
4 files changed, 74 insertions, 53 deletions
diff --git a/ChangeLog b/ChangeLog
index bc612e563..5d053e56f 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,9 @@
+2000-09-17  Bart Schaefer  <schaefer@zsh.org>
+
+	* 12829: Src/glob.c, Src/init.c, Src/utils.c: Move dyncat() and
+	tricat() to utils.c; rewrite 12814, 12818, 12827 and 12828 for
+	less allocation-intensive behavior.
+
 2000-09-18  Clint Adams  <schizo@debian.org>
 
 	* 12828: Src/utils.c: dynamically allocate 'dir' in mailstat.
diff --git a/Src/glob.c b/Src/glob.c
index dbe1d2d58..28cf81f24 100644
--- a/Src/glob.c
+++ b/Src/glob.c
@@ -1661,38 +1661,6 @@ xpandredir(struct redir *fn, LinkList tab)
     return ret;
 }
 
-/* concatenate s1 and s2 in dynamically allocated buffer */
-
-/**/
-mod_export char *
-dyncat(char *s1, char *s2)
-{
-    /* This version always uses space from the current heap. */
-    char *ptr;
-    int l1 = strlen(s1);
-
-    ptr = (char *)zhalloc(l1 + strlen(s2) + 1);
-    strcpy(ptr, s1);
-    strcpy(ptr + l1, s2);
-    return ptr;
-}
-
-/* concatenate s1, s2, and s3 in dynamically allocated buffer */
-
-/**/
-mod_export char *
-tricat(char const *s1, char const *s2, char const *s3)
-{
-    /* This version always uses permanently-allocated space. */
-    char *ptr;
-
-    ptr = (char *)zalloc(strlen(s1) + strlen(s2) + strlen(s3) + 1);
-    strcpy(ptr, s1);
-    strcat(ptr, s2);
-    strcat(ptr, s3);
-    return ptr;
-}
-
 /* brace expansion */
 
 /**/
diff --git a/Src/init.c b/Src/init.c
index 02749cc0a..341173889 100644
--- a/Src/init.c
+++ b/Src/init.c
@@ -1020,22 +1020,18 @@ source(char *s)
 void
 sourcehome(char *s)
 {
-    char *buf;
     char *h;
 
     if (emulation == EMULATE_SH || emulation == EMULATE_KSH ||
 	!(h = getsparam("ZDOTDIR")))
 	h = home;
-/* Let source() complain if it's too long */
-#if 0
-    if (strlen(h) + strlen(s) + 1 >= PATH_MAX) {
-	zerr("path too long: %s", s, 0);
-	return;
+
+    {
+	/* Let source() complain if path is too long */
+	VARARR(char, buf, strlen(h) + strlen(s) + 2);
+	sprintf(buf, "%s/%s", h, s);
+	source(buf);
     }
-#endif
-    buf = tricat(h, "/", s);
-    source(buf);
-    zsfree(buf);
 }
 
 /**/
diff --git a/Src/utils.c b/Src/utils.c
index d5f383c99..3ffb4388a 100644
--- a/Src/utils.c
+++ b/Src/utils.c
@@ -3468,19 +3468,54 @@ appstr(char *base, char const *append)
     return strcat(realloc(base, strlen(base) + strlen(append) + 1), append);
 }
 
+/* concatenate s1, s2, and s3 in dynamically allocated buffer */
+
+/**/
+mod_export char *
+tricat(char const *s1, char const *s2, char const *s3)
+{
+    /* This version always uses permanently-allocated space. */
+    char *ptr;
+    size_t l1 = strlen(s1);
+    size_t l2 = strlen(s2);
+
+    ptr = (char *)zalloc(l1 + l2 + strlen(s3) + 1);
+    strcpy(ptr, s1);
+    strcpy(ptr + l1, s2);
+    strcpy(ptr + l1 + l2, s3);
+    return ptr;
+}
+
 /**/
 mod_export char *
 zhtricat(char const *s1, char const *s2, char const *s3)
 {
     char *ptr;
+    size_t l1 = strlen(s1);
+    size_t l2 = strlen(s2);
     
-    ptr = (char *)zhalloc(strlen(s1) + strlen(s2) + strlen(s3) + 1);
+    ptr = (char *)zhalloc(l1 + l2 + strlen(s3) + 1);
     strcpy(ptr, s1);
-    strcat(ptr, s2);
-    strcat(ptr, s3);
+    strcpy(ptr + l1, s2);
+    strcpy(ptr + l1 + l2, s3);
     return ptr;
 }
 
+/* concatenate s1 and s2 in dynamically allocated buffer */
+
+/**/
+mod_export char *
+dyncat(char *s1, char *s2)
+{
+    /* This version always uses space from the current heap. */
+    char *ptr;
+    size_t l1 = strlen(s1);
+
+    ptr = (char *)zhalloc(l1 + strlen(s2) + 1);
+    strcpy(ptr, s1);
+    strcpy(ptr + l1, s2);
+    return ptr;
+}
 
 /**/
 static int
@@ -3781,6 +3816,8 @@ mode_to_octal(mode_t mode)
  *
  *     This is good enough for most mail-checking applications.
  */
+
+/**/
 int
 mailstat(char *path, struct stat *st)
 {
@@ -3788,9 +3825,10 @@ mailstat(char *path, struct stat *st)
        struct                  dirent *fn;
        struct stat             st_ret, st_tmp;
        static struct stat      st_new_last, st_ret_last;
-       char                    *dir, *file;
+       char                    *dir, *file = 0;
        int                     i;
        time_t                  atime = 0, mtime = 0;
+       size_t                  plen = strlen(path), dlen;
 
        /* First see if it's a directory. */
        if ((i = stat(path, st)) != 0 || !S_ISDIR(st->st_mode))
@@ -3804,17 +3842,19 @@ mailstat(char *path, struct stat *st)
        st_ret.st_mode  |= S_IFREG;
 
        /* See if cur/ is present */
-       dir = dyncat(path, "/cur");
+       dir = appstr(ztrdup(path), "/cur");
        if (stat(dir, &st_tmp) || !S_ISDIR(st_tmp.st_mode)) return 0;
        st_ret.st_atime = st_tmp.st_atime;
 
        /* See if tmp/ is present */
-       dir = dyncat(path, "/tmp");
+       dir[plen] = 0;
+       dir = appstr(dir, "/tmp");
        if (stat(dir, &st_tmp) || !S_ISDIR(st_tmp.st_mode)) return 0;
        st_ret.st_mtime = st_tmp.st_mtime;
 
        /* And new/ */
-       dir = dyncat(path, "/new");
+       dir[plen] = 0;
+       dir = appstr(dir, "/new");
        if (stat(dir, &st_tmp) || !S_ISDIR(st_tmp.st_mode)) return 0;
        st_ret.st_mtime = st_tmp.st_mtime;
 
@@ -3830,14 +3870,23 @@ mailstat(char *path, struct stat *st)
 
        /* Loop over new/ and cur/ */
        for (i = 0; i < 2; i++) {
-	   dir = tricat(path, "/", i ? "cur" : "new");
-	   if ((dd = opendir(dir)) == NULL)
+	   dir[plen] = 0;
+	   dir = appstr(dir, i ? "/cur" : "/new");
+	   if ((dd = opendir(dir)) == NULL) {
+	       zsfree(file);
+	       zsfree(dir);
 	       return 0;
+	   }
+	   dlen = strlen(dir) + 1; /* include the "/" */
 	   while ((fn = readdir(dd)) != NULL) {
 	       if (fn->d_name[0] == '.')
 		   continue;
-
-	       file = zhtricat(dir, "/", fn->d.name);
+	       if (file) {
+		   file[dlen] = 0;
+		   file = appstr(file, fn->d_name);
+	       } else {
+		   file = tricat(dir, "/", fn->d_name);
+	       }
 	       if (stat(file, &st_tmp) != 0)
 		   continue;
 	       st_ret.st_size += st_tmp.st_size;
@@ -3850,6 +3899,8 @@ mailstat(char *path, struct stat *st)
 	   }
 	   closedir(dd);
        }
+       zsfree(file);
+       zsfree(dir);
 
        if (atime) st_ret.st_atime = atime;
        if (mtime) st_ret.st_mtime = mtime;