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