]> git.ipfire.org Git - thirdparty/mlmmj.git/commitdiff
Improve algorithm for list text substitutions.
authorBen Schmidt <none@none>
Thu, 29 Dec 2011 13:20:21 +0000 (00:20 +1100)
committerBen Schmidt <none@none>
Thu, 29 Dec 2011 13:20:21 +0000 (00:20 +1100)
Now the string is processed character by character, so multiple substitutions
on a single line will work when substitutions do not actually take place, and
it is more efficient.

ChangeLog
include/prepstdreply.h
src/prepstdreply.c

index c0f4ab5eb6ad9e059241955f0599ca5c2a49ecec..5eb9060acbceb9586b3fb6441124e1f0d0bda57c 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,4 +1,5 @@
  o Allow a space in $originalmail N$ substitution
+ o Improve algorithm for list text substitutions
  o Add $text T$ substitution
  o Add $$ substitution
  o Allow list texts to include real UTF-8 characters, as documented
index 1a8d86405d75db5a5ae41fb7cd170a05976d5e21..45a6b66e2d9bbf90d3310e32790fa8c3c2065be2 100644 (file)
@@ -1,4 +1,5 @@
 /* Copyright (C) 2004 Mads Martin Joergensen <mmj at mmj.dk>
+ * Copyright (C) 2011 Ben Schmidt <mail_ben_schmidt at yahoo.com.au>
  *
  * $Id$
  *
@@ -26,8 +27,6 @@
 
 char *substitute(const char *line, const char *listaddr, const char *listdelim,
                size_t datacount, char **data, const char *listdir);
-char *substitute_one(const char *line, const char *listaddr,
-               const char *listdelim, size_t datacount, char **data, const char *listdir);
 int open_listtext(const char *listdir, const char *filename);
 char *prepstdreply(const char *listdir, const char *purpose, const char *action,
                const char *reason, const char *type, const char *compat,
index 36c50b229e4a6d79d770689455b0233e846247bc..90595ecdfa39cb45b6ebeda7157296d2020fb046 100644 (file)
@@ -1,5 +1,6 @@
 /* Copyright (C) 2004 Mads Martin Joergensen <mmj at mmj.dk>
  * Copyright (C) 2007 Morten K. Poulsen <morten at afdelingp.dk>
+ * Copyright (C) 2011 Ben Schmidt <mail_ben_schmidt at yahoo.com.au>
  *
  * $Id$
  *
 #include "getlistdelim.h"
 #include "unistr.h"
 
-char *substitute(const char *line, const char *listaddr, const char *listdelim,
-                size_t datacount, char **data, const char *listdir)
-{
-       char *s1, *s2;
-
-       s1 = substitute_one(line, listaddr, listdelim, datacount, data,
-                       listdir);
-       while(s1) {
-               s2 = substitute_one(s1, listaddr, listdelim, datacount, data,
-                               listdir);
-               if(s2) {
-                       myfree(s1);
-                       s1 = s2;
-               } else
-                       return s1;
+
+static char *alphanum_token(char *token) {
+       char *pos;
+       if (*token == '\0') return NULL;
+       for(pos = token; *pos != '\0'; pos++) {
+               if(*pos >= '0' && *pos <= '9') continue;
+               if(*pos >= 'A' && *pos <= 'Z') continue;
+               if(*pos >= 'a' && *pos <= 'z') continue;
+               break;
        }
-               
-       return mystrdup(line);
+       if (*pos != '\0') return NULL;
+       return token;
 }
 
-char *substitute_one(const char *line, const char *listaddr,
+
+static void substitute_one(char **line_p, char **pos_p, const char *listaddr,
                        const char *listdelim, size_t datacount, char **data,
                        const char *listdir)
 {
-       char *fqdn, *listname, *d1, *d2, *token, *value = NULL;
-       char *retstr, *origline;
-       size_t len, i;
-
-       if(line == NULL)
-               return NULL;
-
-       origline = mystrdup(line);
-
-       d1 = strchr(origline, '$');
-
-       if(d1 == NULL) {
-               myfree(origline);
-               return NULL;
-       } else
-               d2 = strchr(d1 + 1, '$');
-       
-       if(d1 && d2) {
-               len = d2 - d1;
-               token = mymalloc(len + 1);
-               snprintf(token, len, "%s", d1 + 1);
-       } else {
-               myfree(origline);
-               return NULL;
+       char *line = *line_p;
+       char *pos = *pos_p;
+       char *token = pos + 1;
+       char *endpos;
+       char *fqdn, *listname;
+       char *value = NULL;
+       size_t i;
+
+       endpos = strchr(token, '$');
+       if (endpos == NULL) {
+               (*pos_p)++;
+               return;
        }
 
-       *d1 = '\0';
+       *pos = '\0';
+       *endpos = '\0';
 
        fqdn = genlistfqdn(listaddr);
        listname = genlistname(listaddr);
 
        if(strcmp(token, "") == 0) {
                value = mystrdup("$");
-               goto concatandreturn;
        } else if(strcmp(token, "listaddr") == 0) {
                /* DEPRECATED: use $list$@$domain$ instead */
                value = mystrdup(listaddr);
-               goto concatandreturn;
        } else if(strcmp(token, "list+") == 0) {
                value = concatstr(2, listname, listdelim);
-               goto concatandreturn;
        } else if(strcmp(token, "list") == 0) {
                value = mystrdup(listname);
-               goto concatandreturn;
        } else if(strcmp(token, "domain") == 0) {
                value = mystrdup(fqdn);
-               goto concatandreturn;
        } else if(strcmp(token, "listowner") == 0) {
                /* DEPRECATED: use $list+$owner@$domain$ instead */
                value = concatstr(4, listname, listdelim, "owner@", fqdn);
-               goto concatandreturn;
        } else if(strcmp(token, "helpaddr") == 0) {
                /* DEPRECATED: use $list+$help@$domain$ instead */
                value = concatstr(4, listname, listdelim, "help@", fqdn);
-               goto concatandreturn;
        } else if(strcmp(token, "faqaddr") == 0) {
                /* DEPRECATED: use $list+$faq@$domain$ instead */
                value = concatstr(4, listname, listdelim, "faq@", fqdn);
-               goto concatandreturn;
        } else if(strcmp(token, "listgetN") == 0) {
                /* DEPRECATED: use $list+$get-N@$domain$ instead */
                value = concatstr(4, listname, listdelim, "get-N@", fqdn);
-               goto concatandreturn;
        } else if(strcmp(token, "listunsubaddr") == 0) {
                /* DEPRECATED: use $list+$unsubscribe@$domain$ instead */
                value = concatstr(4, listname, listdelim, "unsubscribe@", fqdn);
-               goto concatandreturn;
        } else if(strcmp(token, "digestunsubaddr") == 0) {
                /* DEPRECATED: use $list+$unsubscribe-digest@$domain$ instead */
                value = concatstr(4, listname, listdelim,
                                  "unsubscribe-digest@", fqdn);
-               goto concatandreturn;
        } else if(strcmp(token, "nomailunsubaddr") == 0) {
                /* DEPRECATED: use $list+$unsubscribe-nomail@$domain$ instead */
                value = concatstr(4, listname, listdelim,
                                  "unsubscribe-nomail@", fqdn);
-               goto concatandreturn;
        } else if(strcmp(token, "listsubaddr") == 0) {
                /* DEPRECATED: use $list+$subscribe@$domain$ instead */
                value = concatstr(4, listname, listdelim, "subscribe@", fqdn);
-               goto concatandreturn;
        } else if(strcmp(token, "digestsubaddr") == 0) {
                /* DEPRECATED: use $list+$subscribe-digest@$domain$ instead */
                value = concatstr(4, listname, listdelim, "subscribe-digest@",
                                  fqdn);
-               goto concatandreturn;
        } else if(strcmp(token, "nomailsubaddr") == 0) {
                /* DEPRECATED: use $list+$subscribe-nomail@$domain$ instead */
                value = concatstr(4, listname, listdelim, "subscribe-nomail@",
                                  fqdn);
-               goto concatandreturn;
        } else if(strncmp(token, "control ", 8) == 0) {
-               value = token + 8;
-               if(*value == '\0') {
-                       value = mystrdup("");
-                       goto concatandreturn;
-               }
-               for(; *value != '\0'; value++) {
-                       if(*value >= '0' && *value <= '9') continue;
-                       if(*value >= 'A' && *value <= 'Z') continue;
-                       if(*value >= 'a' && *value <= 'z') continue;
-                       break;
-               }
-               if(*value != '\0') {
-                       value = mystrdup(token + 8);
-                       goto concatandreturn;
-               }
-               value = token + 8;
-               value = ctrlcontent(listdir, value);
-               if (value == NULL)
-                       value = mystrdup("");
-               goto concatandreturn;
+               token = alphanum_token(token + 8);
+               if (token != NULL) value = ctrlcontent(listdir, token);
        } else if(strncmp(token, "text ", 5) == 0) {
-               value = token + 5;
-               if(*value == '\0') {
-                       value = mystrdup("");
-                       goto concatandreturn;
-               }
-               for(; *value != '\0'; value++) {
-                       if(*value >= '0' && *value <= '9') continue;
-                       if(*value >= 'A' && *value <= 'Z') continue;
-                       if(*value >= 'a' && *value <= 'z') continue;
-                       break;
-               }
-               if(*value != '\0') {
-                       value = mystrdup(token + 5);
-                       goto concatandreturn;
-               }
-               value = token + 5;
-               value = textcontent(listdir, value);
-               if (value == NULL)
-                       value = mystrdup("");
-               goto concatandreturn;
+               token = alphanum_token(token + 5);
+               if (token != NULL) value = textcontent(listdir, token);
        } else if(data) {
                for(i = 0; i < datacount; i++) {
                        if(strcmp(token, data[i*2]) == 0) {
                                value = mystrdup(data[(i*2)+1]);
-                               goto concatandreturn;
+                               break;
                        }
                }
        }
 
-       myfree(origline);
-       return NULL;
-
-concatandreturn:
-       retstr = concatstr(3, origline, value, d2 + 1);
-       myfree(origline);
-       myfree(value);
-       myfree(token);
+       if (value != NULL) {
+               line = concatstr(3, line, value, endpos + 1);
+               *pos_p = line + (*pos_p - *line_p);
+               if (strcmp(value, "$") == 0) (*pos_p)++;
+               myfree(*line_p);
+               *line_p = line;
+               myfree(value);
+       } else {
+               *pos = '$';
+               *endpos = '$';
+               (*pos_p)++;
+       }
        myfree(fqdn);
        myfree(listname);
+}
 
-       return retstr;
+
+char *substitute(const char *line, const char *listaddr, const char *listdelim,
+                size_t datacount, char **data, const char *listdir)
+{
+       char *new;
+       char *pos;
+
+       new = mystrdup(line);
+       pos = new;
+
+       while (*pos != '\0') {
+               if (*pos == '$') {
+                       substitute_one(&new, &pos,
+                                       listaddr, listdelim,
+                                       datacount, data, listdir);
+                       /* The function sets up for the next character
+                        * to process, so continue straight away. */
+                       continue;
+               }
+               pos++;
+       }
+
+       return new;
 }