1 /* GNU Mailutils -- a suite of utilities for electronic mail
2 Copyright (C) 1999-2021 Free Software Foundation, Inc.
3
4 GNU Mailutils is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation; either version 3, or (at your option)
7 any later version.
8
9 GNU Mailutils is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
13
14 You should have received a copy of the GNU General Public License
15 along with GNU Mailutils. If not, see <http://www.gnu.org/licenses/>. */
16
17 /* fmtcheck */
18
19 #include <mh.h>
20
21 static char prog_doc[] = N_("Check MH format string");
22 static char args_doc[] = N_("[FILE]");
23
24 static char *format_str;
25 static struct mu_locus_point locus = MU_LOCUS_POINT_INITIALIZER;
26 static mh_format_t format;
27 static int dump_option;
28 static int disass_option;
29 static int debug_option;
30 static char *input_file;
31 static size_t width;
32 static size_t msgno;
33 static int pc_option;
34
35 void
opt_formfile(struct mu_parseopt * po,struct mu_option * opt,char const * arg)36 opt_formfile (struct mu_parseopt *po, struct mu_option *opt, char const *arg)
37 {
38 free (format_str);
39 if (mh_read_formfile (arg, &format_str))
40 exit (1);
41 mu_locus_point_set_file (&locus, arg);
42 locus.mu_line = 1;
43 locus.mu_col = 0;
44 }
45
46 void
opt_format(struct mu_parseopt * po,struct mu_option * opt,char const * arg)47 opt_format (struct mu_parseopt *po, struct mu_option *opt, char const *arg)
48 {
49 free (format_str);
50 format_str = mu_strdup (arg);
51 }
52
53 static struct mu_option options[] = {
54 { "form", 0, N_("FILE"), MU_OPTION_DEFAULT,
55 N_("read format from given file"),
56 mu_c_string, NULL, opt_formfile },
57
58 { "format", 0, N_("FORMAT"), MU_OPTION_DEFAULT,
59 N_("use this format string"),
60 mu_c_string, NULL, opt_format },
61 { "dump", 0, NULL, MU_OPTION_DEFAULT,
62 N_("dump the listing of compiled format code"),
63 mu_c_bool, &dump_option },
64 { "disassemble", 0, NULL, MU_OPTION_DEFAULT,
65 N_("dump disassembled format code"),
66 mu_c_bool, &disass_option },
67 { "pc", 0, NULL, MU_OPTION_DEFAULT,
68 N_("print program counter along with disassembled code (implies --disassemble)"),
69 mu_c_bool, &pc_option },
70 { "debug", 0, NULL, MU_OPTION_DEFAULT,
71 N_("enable parser debugging output"),
72 mu_c_bool, &debug_option },
73 { "width", 0, N_("NUMBER"), MU_OPTION_DEFAULT,
74 N_("set output width"),
75 mu_c_size, &width },
76 { "msgno", 0, N_("NUMBER"), MU_OPTION_DEFAULT,
77 N_("set message number"),
78 mu_c_size, &msgno },
79
80 MU_OPTION_END
81 };
82
83 static int
msg_uid(mu_message_t msg MU_ARG_UNUSED,size_t * ret)84 msg_uid (mu_message_t msg MU_ARG_UNUSED, size_t *ret)
85 {
86 if (!ret)
87 return MU_ERR_OUT_PTR_NULL;
88 *ret = msgno;
89 return 0;
90 }
91
92 static void
run(void)93 run (void)
94 {
95 mu_message_t msg = mh_file_to_message (NULL, input_file);
96 mh_fvm_t fvm;
97
98 MU_ASSERT (mu_message_set_uid (msg, msg_uid, mu_message_get_owner (msg)));
99
100 mh_fvm_create (&fvm, MH_FMT_FORCENL);
101 mh_fvm_set_width (fvm, width ? width : mh_width ());
102 mh_fvm_set_format (fvm, format);
103 mh_fvm_run (fvm, msg);
104 mh_fvm_destroy (&fvm);
105 }
106
107 int
main(int argc,char ** argv)108 main (int argc, char **argv)
109 {
110 mh_getopt (&argc, &argv, options, 0, args_doc, prog_doc, NULL);
111 if (pc_option)
112 disass_option = 1;
113 switch (argc)
114 {
115 case 0:
116 if (!disass_option)
117 dump_option = 1;
118 break;
119
120 case 1:
121 input_file = argv[0];
122 break;
123
124 default:
125 mu_error (_("too many arguments"));
126 return 1;
127 }
128
129 if (!format_str)
130 {
131 mu_error (_("Format string not specified"));
132 return 1;
133 }
134 if (mh_format_string_parse (&format, format_str, &locus,
135 MH_FMT_PARSE_TREE
136 | (debug_option ? MH_FMT_PARSE_DEBUG : 0)))
137 return 1;
138
139 if (dump_option)
140 mh_format_dump_code (format);
141 if (disass_option)
142 mh_format_dump_disass (format, pc_option);
143
144 if (input_file)
145 run ();
146
147 return 0;
148 }
149