diff options
author | Sergey Poznyakoff <gray@gnu.org.ua> | 2009-10-06 00:12:44 +0300 |
---|---|---|
committer | Sergey Poznyakoff <gray@gnu.org.ua> | 2009-10-06 00:12:44 +0300 |
commit | 9fdb64f20ef8a310cb2d6e240e497e1b70d49306 (patch) | |
tree | c728d61b3e9118b572ecb68e515c3b380cb7ed9f | |
parent | 7c94a5dc87cff630f2629b054b287372fc71991d (diff) | |
download | mailfromd-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.c | 355 | ||||
-rw-r--r-- | mfd/engine.c | 1 | ||||
-rw-r--r-- | mfd/gram.y | 3 | ||||
-rw-r--r-- | mfd/lex.l | 8 | ||||
-rw-r--r-- | mfd/mailfromd.h | 25 | ||||
-rw-r--r-- | mfd/main.c | 1 | ||||
-rw-r--r-- | mfd/pp.c | 2 |
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) { @@ -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; @@ -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); @@ -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(); @@ -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) |