1/*
2 * mutool -- swiss army knife of pdf manipulation tools
3 */
4
5#include "mupdf/fitz.h"
6
7#include <string.h>
8#include <stdio.h>
9
10#ifdef _MSC_VER
11#define main main_utf8
12#endif
13
14int muconvert_main(int argc, char *argv[]);
15int mudraw_main(int argc, char *argv[]);
16int mutrace_main(int argc, char *argv[]);
17int murun_main(int argc, char *argv[]);
18
19int pdfclean_main(int argc, char *argv[]);
20int pdfextract_main(int argc, char *argv[]);
21int pdfinfo_main(int argc, char *argv[]);
22int pdfposter_main(int argc, char *argv[]);
23int pdfshow_main(int argc, char *argv[]);
24int pdfpages_main(int argc, char *argv[]);
25int pdfcreate_main(int argc, char *argv[]);
26int pdfmerge_main(int argc, char *argv[]);
27int pdfsign_main(int argc, char *argv[]);
28
29int cmapdump_main(int argc, char *argv[]);
30
31static struct {
32 int (*func)(int argc, char *argv[]);
33 char *name;
34 char *desc;
35} tools[] = {
36#if FZ_ENABLE_PDF
37 { pdfclean_main, "clean", "rewrite pdf file" },
38#endif
39 { muconvert_main, "convert", "convert document" },
40#if FZ_ENABLE_PDF
41 { pdfcreate_main, "create", "create pdf document" },
42#endif
43 { mudraw_main, "draw", "convert document" },
44 { mutrace_main, "trace", "trace device calls" },
45#if FZ_ENABLE_PDF
46 { pdfextract_main, "extract", "extract font and image resources" },
47#endif
48#if FZ_ENABLE_PDF
49 { pdfinfo_main, "info", "show information about pdf resources" },
50 { pdfmerge_main, "merge", "merge pages from multiple pdf sources into a new pdf" },
51 { pdfpages_main, "pages", "show information about pdf pages" },
52 { pdfposter_main, "poster", "split large page into many tiles" },
53 { pdfsign_main, "sign", "manipulate PDF digital signatures" },
54#endif
55#if FZ_ENABLE_JS
56 { murun_main, "run", "run javascript" },
57#endif
58#if FZ_ENABLE_PDF
59 { pdfshow_main, "show", "show internal pdf objects" },
60#ifndef NDEBUG
61 { cmapdump_main, "cmapdump", "dump CMap resource as C source file" },
62#endif
63#endif
64};
65
66static int
67namematch(const char *end, const char *start, const char *match)
68{
69 size_t len = strlen(match);
70 return ((end-len >= start) && (strncmp(end-len, match, len) == 0));
71}
72
73#ifdef GPERF
74#include "gperftools/profiler.h"
75
76static int profiled_main(int argc, char **argv);
77
78int main(int argc, char **argv)
79{
80 int ret;
81 ProfilerStart("mutool.prof");
82 ret = profiled_main(argc, argv);
83 ProfilerStop();
84 return ret;
85}
86
87static int profiled_main(int argc, char **argv)
88#else
89int main(int argc, char **argv)
90#endif
91{
92 char *start, *end;
93 char buf[32];
94 int i;
95
96 if (argc == 0)
97 {
98 fprintf(stderr, "No command name found!\n");
99 return 1;
100 }
101
102 /* Check argv[0] */
103
104 if (argc > 0)
105 {
106 end = start = argv[0];
107 while (*end)
108 end++;
109 if ((end-4 >= start) && (end[-4] == '.') && (end[-3] == 'e') && (end[-2] == 'x') && (end[-1] == 'e'))
110 end = end-4;
111 for (i = 0; i < nelem(tools); i++)
112 {
113 strcpy(buf, "mupdf");
114 strcat(buf, tools[i].name);
115 if (namematch(end, start, buf) || namematch(end, start, buf+2))
116 return tools[i].func(argc, argv);
117 strcpy(buf, "mu");
118 strcat(buf, tools[i].name);
119 if (namematch(end, start, buf))
120 return tools[i].func(argc, argv);
121 }
122 }
123
124 /* Check argv[1] */
125
126 if (argc > 1)
127 {
128 for (i = 0; i < nelem(tools); i++)
129 if (!strcmp(tools[i].name, argv[1]))
130 return tools[i].func(argc - 1, argv + 1);
131 if (!strcmp(argv[1], "-v"))
132 {
133 fprintf(stderr, "mutool version %s\n", FZ_VERSION);
134 return 0;
135 }
136 }
137
138 /* Print usage */
139
140 fprintf(stderr, "usage: mutool <command> [options]\n");
141
142 for (i = 0; i < nelem(tools); i++)
143 fprintf(stderr, "\t%s\t-- %s\n", tools[i].name, tools[i].desc);
144
145 return 1;
146}
147
148#ifdef _MSC_VER
149int wmain(int argc, wchar_t *wargv[])
150{
151 char **argv = fz_argv_from_wargv(argc, wargv);
152 int ret = main(argc, argv);
153 fz_free_argv(argc, argv);
154 return ret;
155}
156#endif
157