aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSergey Poznyakoff <gray@gnu.org.ua>2009-10-06 00:12:44 +0300
committerSergey Poznyakoff <gray@gnu.org.ua>2009-10-06 00:12:44 +0300
commit9fdb64f20ef8a310cb2d6e240e497e1b70d49306 (patch)
treec728d61b3e9118b572ecb68e515c3b380cb7ed9f
parent7c94a5dc87cff630f2629b054b287372fc71991d (diff)
downloadmailfromd-9fdb64f20ef8a310cb2d6e240e497e1b70d49306.tar.gz
mailfromd-9fdb64f20ef8a310cb2d6e240e497e1b70d49306.tar.bz2
Re-introduce fixup script (partial port of 7cba79054 from master).
* mfd/deprecation.c (add_fixup_command, add_fixup_command_fmt) (add_fixup_command_locus): New functions. (fixup_create_script): New functions. * mfd/gram.y: Issue fix-up statements for every deprecation warning. * mfd/lex.l: Likewise. * mfd/mailfromd.h (fixup_op): New enumeration. (add_fixup_command,add_fixup_command_fmt) (add_fixup_command_locus, fixup_create_script): New functions. * mfd/main.c (main): Call fixup_create_script.
-rw-r--r--mfd/deprecation.c355
-rw-r--r--mfd/engine.c1
-rw-r--r--mfd/gram.y3
-rw-r--r--mfd/lex.l8
-rw-r--r--mfd/mailfromd.h25
-rw-r--r--mfd/main.c1
-rw-r--r--mfd/pp.c2
7 files changed, 391 insertions, 4 deletions
diff --git a/mfd/deprecation.c b/mfd/deprecation.c
index 04d45fec..5f1ccb5a 100644
--- a/mfd/deprecation.c
+++ b/mfd/deprecation.c
@@ -74,3 +74,358 @@ final_deprecation_warning()
" or set it to `yes' to see detailed diagnostics"));
}
}
+
+
+
+static int fixup_opweight[] = {
+ 0, /* fixup_noop */
+ 90, /* fixup_delete_line */
+ 91, /* fixup_insert_line */
+ 92, /* fixup_append_line */
+ 93, /* fixup_replace_line */
+ 0, /* fixup_delete_chars */
+ 1, /* fixup_insert_chars */
+ 2, /* fixup_replace_chars */
+ 100, /* fixup_rename_file */
+ 1000 /* fixup_end */
+};
+
+struct fixup_cmd {
+ enum fixup_op opcode;
+ mf_yyltype_t locus;
+ char *arg;
+};
+
+static struct obstack fixup_stk;
+static struct obstack fixup_literal_stk;
+static size_t fixup_cnt;
+
+void
+add_fixup_command(enum fixup_op opcode, mf_yyltype_t *locus, char *arg)
+{
+ struct fixup_cmd cmd;
+
+ if (!enable_deprecation_warnings())
+ return;
+ if (opcode < 0 || opcode > fixup_end)
+ abort();
+ if (fixup_cnt == 0) {
+ obstack_init(&fixup_stk);
+ obstack_init(&fixup_literal_stk);
+ }
+ cmd.opcode = opcode;
+ if (locus)
+ cmd.locus = *locus;
+ else
+ memset(&cmd.locus, 0, sizeof(cmd.locus));
+ cmd.arg = arg;
+ obstack_grow(&fixup_stk, &cmd, sizeof(cmd));
+ fixup_cnt++;
+}
+
+void
+add_fixup_command_fmt(enum fixup_op opcode, mf_yyltype_t *locus,
+ const char *fmt, ...)
+{
+ va_list ap;
+ char *str;
+ va_start(ap, fmt);
+ vasprintf(&str, fmt, ap);
+ va_end(ap);
+ obstack_grow(&fixup_literal_stk, str, strlen(str));
+ obstack_1grow(&fixup_literal_stk, 0);
+ free(str);
+ add_fixup_command(opcode, locus, obstack_finish(&fixup_literal_stk));
+}
+
+void
+add_fixup_command_locus(enum fixup_op opcode, const struct locus *beg,
+ char *arg)
+{
+ mf_yyltype_t locus;
+ locus.beg = *beg;
+ add_fixup_command(opcode, &locus, arg);
+}
+
+static int
+fixup_cmd_comp(const void *a, const void *b)
+{
+ const struct fixup_cmd *acmd = a;
+ const struct fixup_cmd *bcmd = b;
+ int rc;
+
+ if (acmd->opcode == fixup_end)
+ return 1;
+ else if (bcmd->opcode == fixup_end)
+ return -1;
+ rc = strcmp(acmd->locus.beg.file, bcmd->locus.beg.file);
+ if (rc)
+ return rc;
+
+ if (acmd->opcode != bcmd->opcode)
+ return fixup_opweight[acmd->opcode] -
+ fixup_opweight[bcmd->opcode];
+
+ switch (acmd->opcode) {
+ case fixup_delete_line:
+ case fixup_replace_line:
+ if (acmd->locus.beg.line > bcmd->locus.beg.line)
+ rc = -1;
+ else if (acmd->locus.beg.line < bcmd->locus.beg.line)
+ rc = 1;
+ else
+ rc = 0;
+ break;
+
+ case fixup_insert_line:
+ case fixup_delete_chars:
+ case fixup_insert_chars:
+ case fixup_replace_chars:
+ if (acmd->locus.beg.line > bcmd->locus.beg.line)
+ rc = 1;
+ else if (acmd->locus.beg.line < bcmd->locus.beg.line)
+ rc = -1;
+ else if (acmd->locus.beg.point > bcmd->locus.beg.point)
+ rc = -1;
+ else if (acmd->locus.beg.point < bcmd->locus.beg.point)
+ rc = 1;
+ else
+ rc = 0;
+ break;
+
+ case fixup_append_line:
+ case fixup_rename_file:
+ case fixup_end:
+ case fixup_noop:
+ rc = 0;
+ }
+ return rc;
+}
+
+static void
+fprint_ml(FILE *fp, const char *arg)
+{
+ /* FIXME: Quote (escape) arg */
+ while (*arg) {
+ int len = strcspn(arg, "\n");
+ fwrite(arg, len, 1, fp);
+ arg += len;
+ if (*arg) {
+ fprintf(fp, "\\\n");
+ arg++;
+ }
+ }
+}
+
+void
+format_fixup_cmd(FILE *fp, const struct fixup_cmd *cmd)
+{
+ switch (cmd->opcode) {
+ case fixup_delete_line:
+ fprintf(fp, "%lud\n", (unsigned long) cmd->locus.beg.line);
+ break;
+
+ case fixup_insert_line:
+ fprintf(fp, "%lui\\\n", (unsigned long) cmd->locus.beg.line);
+ fprint_ml(fp, cmd->arg);
+ fprintf(fp, "\n");
+ break;
+
+ case fixup_append_line:
+ fprintf(fp, "$a\\\n");
+ fprint_ml(fp, cmd->arg);
+ fprintf(fp, "\n");
+ break;
+
+ case fixup_replace_line:
+ fprintf(fp, "%luc\\\n", cmd->locus.beg.line);
+ fprint_ml(fp, cmd->arg);
+ fprintf(fp, "\n");
+ break;
+
+ case fixup_delete_chars:
+ fprintf(fp, "%lus/\\(.\\{%lu\\}\\)\\(.\\{%lu\\}\\)\\(.*\\)/\\1\\3/\n",
+ cmd->locus.beg.line,
+ cmd->locus.beg.point,
+ cmd->locus.end.point - cmd->locus.beg.point);
+ break;
+
+ case fixup_insert_chars:
+ fprintf(fp, "%lus/\\(.\\{%lu\\}\\)\\(.*\\)/\\1%s\\2/\n",
+ cmd->locus.beg.line,
+ cmd->locus.beg.point,
+ cmd->arg);
+ break;
+
+ case fixup_replace_chars:
+ fprintf(fp, "%lus/\\(.\\{%lu\\}\\)\\(.\\{%lu\\}\\)\\(.*\\)/\\1%s\\3/\n",
+ cmd->locus.beg.line,
+ cmd->locus.beg.point,
+ cmd->locus.end.point - cmd->locus.beg.point,
+ cmd->arg);
+ break;
+
+ case fixup_noop:
+ case fixup_rename_file:
+ case fixup_end:
+ break;
+ }
+}
+
+
+static void
+condense_append_line(struct fixup_cmd *cmd, size_t start, size_t *pend)
+{
+ size_t i;
+ const char *last_file;
+
+ if (cmd[start+1].opcode != fixup_append_line) {
+ *pend = start+1;
+ return;
+ }
+ last_file = cmd[start].locus.beg.file;
+ for (i = start; i < fixup_cnt; i++) {
+ if (cmd[i].opcode != fixup_append_line
+ || strcmp(cmd[i].locus.beg.file, last_file))
+ break;
+ if (i > start)
+ obstack_1grow(&fixup_literal_stk, '\n');
+ obstack_grow(&fixup_literal_stk, cmd[i].arg,
+ strlen(cmd[i].arg));
+ cmd[i].opcode = fixup_noop;
+ }
+ obstack_1grow(&fixup_literal_stk, 0);
+ cmd[start].opcode = fixup_append_line;
+ cmd[start].arg = obstack_finish(&fixup_literal_stk);
+ *pend = i;
+}
+
+/* Condense fixup_append_lines */
+static void
+condense_all_appends(struct fixup_cmd *cmd)
+{
+ size_t i;
+ for (i = 0; i < fixup_cnt; i++) {
+ if (cmd[i].opcode == fixup_end)
+ break;
+ if (cmd[i].opcode == fixup_append_line)
+ condense_append_line(cmd, i, &i);
+ else
+ i++;
+ }
+}
+
+
+static void
+script_prologue(FILE *fp)
+{
+ time_t now;
+ fprintf(fp, "#! /bin/sh\n");
+ fprintf(fp, "# Conversion script created by mailfromd on %s",
+ ctime (&now));
+ fprintf(fp, "# Run this script to fix mailfromd deprecation warnings\n\n");
+ fprintf(fp, "set -e\n\n");
+
+ fprintf(fp,
+ "modfiles=\n"
+ "script=newconf.$$\n"
+ "trap \"rm -f $script\" 1 2 13 15\n");
+}
+
+char script_epilogue[] = "\
+rm -f $script\n\
+set -- $modfiles\n\
+while test $# -ne 0\n\
+do\n\
+ orig=$1\n\
+ shift\n\
+ file=$1\n\
+ shift\n\
+ mv $orig $orig.bak\n\
+ mv $orig.tmp $file\n\
+done\n";
+
+
+void
+fixup_create_script()
+{
+ struct fixup_cmd *cmd, *cmdbase;
+ size_t i;
+ FILE *fp;
+ const char *file_name = "/tmp/mailfromd-newconf.sh";
+ const char *last_file;
+ const char *new_name;
+
+ if (fixup_cnt == 0)
+ return;
+
+ fp = fopen(file_name, "w");
+ if (fp) {
+ mu_diag_output(MU_DIAG_INFO,
+ _("run script %s to fix the above warnings"),
+ file_name);
+ } else
+ fp = stdout;
+
+ add_fixup_command(fixup_end, NULL, NULL);
+ cmdbase = obstack_finish(&fixup_stk);
+ qsort(cmdbase, fixup_cnt, sizeof(*cmd), fixup_cmd_comp);
+
+ condense_all_appends(cmdbase);
+
+ script_prologue(fp);
+
+ new_name = NULL;
+ last_file = cmdbase->locus.beg.file;
+ fprintf(fp, "#\n# Fix %s\n#\n", last_file);
+ fprintf(fp, "cat > $script <<'EOT'\n");
+ for (i = 0, cmd = cmdbase; i < fixup_cnt; i++, cmd++) {
+ if (cmd->opcode == fixup_end
+ || strcmp(cmd->locus.beg.file, last_file)) {
+
+ /* Terminate current here-document */
+ fprintf(fp, "EOT\n");
+
+ /* Check if the last_file has not been modified
+ in between */
+ fprintf(fp,
+ "if test %s -nt $0; then\n"
+ " echo >&2 \"$0: %s is updated, re-run mailfromd --lint\"\n"
+ " exit 1\n"
+ "fi\n",
+ last_file, last_file);
+
+ /* Modify the file */
+ fprintf(fp, "test -r %s || "
+ "echo \"# File generated by $0 on `date`\" > %s\n",
+ last_file, last_file);
+ fprintf(fp, "sed -f $script < %s > %s.tmp\n",
+ last_file, last_file);
+ fprintf(fp, "if cmp %s %s.tmp >/dev/null 2>&1; then\n",
+ last_file, last_file);
+ fprintf(fp, " rm %s.tmp\n", last_file);
+ fprintf(fp, "else\n modfiles=\"$modfiles %s %s\"\nfi\n",
+ last_file, new_name ? new_name : last_file);
+
+ if (cmd->opcode == fixup_end)
+ break;
+ new_name = NULL;
+ last_file = cmd->locus.beg.file;
+ fprintf(fp, "#\n# Fix %s\n#\n", last_file);
+ fprintf(fp, "cat > $script <<'EOT'\n");
+ }
+ if (cmd->opcode == fixup_rename_file)
+ new_name = cmd->arg;
+ else
+ format_fixup_cmd(fp, cmd);
+ }
+
+ fprintf(fp, "#\n# Flush changes\n#\n");
+ fprintf(fp, "%s\n", script_epilogue);
+ fprintf(fp, "# EOF\n");
+ fclose(fp);
+
+ /* Free allocated memory */
+ obstack_free(&fixup_stk, NULL);
+ obstack_free(&fixup_literal_stk, NULL);
+}
diff --git a/mfd/engine.c b/mfd/engine.c
index 48af651e..13075fa5 100644
--- a/mfd/engine.c
+++ b/mfd/engine.c
@@ -1577,7 +1577,6 @@ save_cmdline(int argc, char **argv)
x_argv[i] = NULL;
}
-
static RETSIGTYPE
sig_stop(int sig)
{
diff --git a/mfd/gram.y b/mfd/gram.y
index b4773935..dbbbe56e 100644
--- a/mfd/gram.y
+++ b/mfd/gram.y
@@ -966,7 +966,8 @@ parm : T_TYPE varname
/* FIXME: Is this still needed? */
| T_TYPE
{
- deprecation_warning(_("unnamed formal parameters are deprecated"));
+ parse_warning_locus(&@1.beg,
+ _("unnamed formal parameters are deprecated"));
$$ = xmalloc(sizeof *$$);
$$->next = NULL;
$$->type = $1;
diff --git a/mfd/lex.l b/mfd/lex.l
index c4735b80..49ba0e30 100644
--- a/mfd/lex.l
+++ b/mfd/lex.l
@@ -576,6 +576,10 @@ bye return T_BYE;
compose_add_builtin_const(yytext + 2, yyleng - 3);
}
<INITIAL,ONBLOCK>\%{IDENT} {
+ mf_yyltype_t loc = yylloc;
+ loc.end = loc.beg;
+ loc.end.point++;
+ add_fixup_command(fixup_delete_chars, &loc, NULL);
deprecation_warning(_("unnecessary %% in front of a variable or constant"));
string(yytext + 1, yyleng - 1);
return variable_or_const();
@@ -585,6 +589,10 @@ bye return T_BYE;
compose_add_variable_or_const(variable_or_const());
}
<INITIAL,ONBLOCK>\%\{{IDENT}\} {
+ mf_yyltype_t loc = yylloc;
+ loc.end = loc.beg;
+ loc.end.point++;
+ add_fixup_command(fixup_delete_chars, &loc, NULL);
deprecation_warning(_("unnecessary %% in front of a variable or constant"));
string(yytext + 2, yyleng - 3);
return variable_or_const();
diff --git a/mfd/mailfromd.h b/mfd/mailfromd.h
index 381e62dd..704757d5 100644
--- a/mfd/mailfromd.h
+++ b/mfd/mailfromd.h
@@ -788,7 +788,7 @@ int preprocess_input(void);
void require_module(const char *modname, struct import_rule *import_rules);
int parse_include(const char *text, int once);
-int parse_require(const char *text);
+int parse_require(const char *text, mf_yyltype_t *loc);
int parse_line(char *text, struct locus *ploc);
void parse_line_cpp(char *text, struct locus *ploc);
void alloc_ext_pp(void);
@@ -1063,3 +1063,26 @@ void deprecation_warning_locus(const struct locus *locus, const char *fmt, ...)
void final_deprecation_warning(void);
int enable_deprecation_warnings(void);
+
+
+enum fixup_op
+{
+ fixup_noop,
+ fixup_delete_line,
+ fixup_insert_line,
+ fixup_append_line,
+ fixup_replace_line,
+ fixup_delete_chars,
+ fixup_insert_chars,
+ fixup_replace_chars,
+ fixup_rename_file,
+ fixup_end
+};
+
+void add_fixup_command(enum fixup_op opcode, mf_yyltype_t *locus, char *arg);
+void add_fixup_command_fmt(enum fixup_op opcode, mf_yyltype_t *locus,
+ const char *fmt, ...)
+ MU_PRINTFLIKE(3,4);
+void add_fixup_command_locus(enum fixup_op opcode, const struct locus *locus,
+ char *arg);
+void fixup_create_script(void);
diff --git a/mfd/main.c b/mfd/main.c
index ff3c5f15..a18c4374 100644
--- a/mfd/main.c
+++ b/mfd/main.c
@@ -2398,6 +2398,7 @@ main(int argc, char **argv)
if (parse_program(script_file, script_ydebug))
exit(EX_CONFIG);
}
+ fixup_create_script();
process_options();
fixup_state_dir_names();
diff --git a/mfd/pp.c b/mfd/pp.c
index 0ad579cb..ef9888f6 100644
--- a/mfd/pp.c
+++ b/mfd/pp.c
@@ -182,7 +182,7 @@ parse_include(const char *text, int once)
char *tmp = NULL;
char *p = NULL;
int rc = 1;
-
+
if (mu_argcv_get(text, "", NULL, &argc, &argv))
parse_error(_("Cannot parse include line"));
else if (argc != 2)

Return to:

Send suggestions and report system problems to the System administrator.