reg: use snprintf for string values in num_str()
[neatroff.git] / roff.c
blobf5f44818c921c379892dba195083602a37537242
1 /*
2 * NEATROFF TYPESETTING SYSTEM
4 * Copyright (C) 2012-2016 Ali Gholami Rudi <ali at rudi dot ir>
6 * Permission to use, copy, modify, and/or distribute this software for any
7 * purpose with or without fee is hereby granted, provided that the above
8 * copyright notice and this permission notice appear in all copies.
10 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
18 #include <stdarg.h>
19 #include <stdio.h>
20 #include <string.h>
21 #include <stdlib.h>
22 #include "roff.h"
24 void errmsg(char *fmt, ...)
26 va_list ap;
27 va_start(ap, fmt);
28 vfprintf(stderr, fmt, ap);
29 va_end(ap);
32 void errdie(char *msg)
34 fprintf(stderr, "%s", msg);
35 exit(1);
38 void *mextend(void *old, long oldsz, long newsz, int memsz)
40 void *new = xmalloc(newsz * memsz);
41 memcpy(new, old, oldsz * memsz);
42 memset(new + oldsz * memsz, 0, (newsz - oldsz) * memsz);
43 free(old);
44 return new;
47 void *xmalloc(long len)
49 void *m = malloc(len);
50 if (!m)
51 errdie("neatroff: malloc() failed\n");
52 return m;
55 static int xopens(char *path)
57 FILE *filp = fopen(path, "r");
58 if (filp)
59 fclose(filp);
60 return filp != NULL;
63 /* parse the argument of -r and -d options */
64 static void cmddef(char *arg, int *reg, char **def)
66 char regname[RNLEN] = "";
67 char *eq = strchr(arg, '=');
68 memcpy(regname, arg, eq ? MIN(RNLEN - 1, eq - arg) : 1);
69 *reg = map(regname);
70 *def = eq ? eq + 1 : arg + 1;
73 /* find the macro specified with -m option */
74 static int cmdmac(char *dir, char *arg)
76 char path[PATHLEN];
77 snprintf(path, sizeof(path), "%s/%s.tmac", dir, arg);
78 if (!xopens(path))
79 snprintf(path, sizeof(path), "%s/tmac.%s", dir, arg);
80 if (!xopens(path))
81 snprintf(path, sizeof(path), "%s/%s", dir, arg);
82 if (!xopens(path))
83 return 1;
84 in_queue(path);
85 return 0;
88 static char *usage =
89 "Usage: neatroff [options] input\n\n"
90 "Options:\n"
91 " -mx \tinclude macro x\n"
92 " -rx=y \tset number register x to y\n"
93 " -dx=y \tdefine string register x as y\n"
94 " -C \tenable compatibility mode\n"
95 " -Tdev \tset output device\n"
96 " -Fdir \tset font directory (" TROFFFDIR ")\n"
97 " -Mdir \tset macro directory (" TROFFMDIR ")\n";
99 int main(int argc, char **argv)
101 char *fdir = getenv("NEATROFF_F"); /* fonts directory */
102 char *mdir = getenv("NEATROFF_M"); /* macro packages directory */
103 char *dev = getenv("NEATROFF_T"); /* output device */
104 char *mac, *def;
105 int reg, ret;
106 int i;
107 if (dev == NULL)
108 dev = "utf";
109 if (fdir == NULL)
110 fdir = TROFFFDIR;
111 if (mdir == NULL)
112 mdir = TROFFMDIR;
113 for (i = 1; i < argc; i++) {
114 if (argv[i][0] != '-' || !argv[i][1])
115 break;
116 switch (argv[i][1]) {
117 case 'C':
118 n_cp = 1;
119 break;
120 case 'm':
121 mac = argv[i] + 2;
122 if (strchr(mac, '/') || (cmdmac(mdir, mac) && cmdmac(".", mac)))
123 in_queue(mac);
124 break;
125 case 'r':
126 cmddef(argv[i][2] ? argv[i] + 2 : argv[++i], &reg, &def);
127 num_set(reg, eval_re(def, num_get(reg), 'u'));
128 break;
129 case 'd':
130 cmddef(argv[i][2] ? argv[i] + 2 : argv[++i], &reg, &def);
131 str_set(reg, def);
132 break;
133 case 'F':
134 fdir = argv[i][2] ? argv[i] + 2 : argv[++i];
135 break;
136 case 'M':
137 mdir = argv[i][2] ? argv[i] + 2 : argv[++i];
138 break;
139 case 'T':
140 dev = argv[i][2] ? argv[i] + 2 : argv[++i];
141 break;
142 default:
143 fprintf(stderr, "%s", usage);
144 return 1;
147 if (dev_open(fdir, dev)) {
148 fprintf(stderr, "neatroff: cannot open device %s\n", dev);
149 return 1;
151 hyph_init();
152 env_init();
153 tr_init();
154 if (i == argc)
155 in_queue(NULL); /* reading from standard input */
156 for (; i < argc; i++)
157 in_queue(!strcmp("-", argv[i]) ? NULL : argv[i]);
158 out("s%d\n", n_s);
159 out("f%d\n", n_f);
160 ret = render();
161 out("V%d\n", n_p);
162 hyph_done();
163 tr_done();
164 env_done();
165 dev_close();
166 map_done();
167 dir_done();
168 return ret;