ren: include indentation in diversion width
[neatroff.git] / cp.c
blobc26c592d287d21ca3873b3c3a279eb0a6703025b
1 #include <stdio.h>
2 #include <stdlib.h>
3 #include "roff.h"
5 static int cp_nblk; /* input block depth (text in \{ and \}) */
6 static int cp_sblk[NIES]; /* skip \} escape at this depth, if set */
7 static int cp_widreq = 1; /* inline \w requests */
9 static void cparg(char *d)
11 int c = cp_next();
12 int i = 0;
13 if (c == '(') {
14 d[i++] = cp_next();
15 d[i++] = cp_next();
16 } else if (!n_cp && c == '[') {
17 c = cp_next();
18 while (i < NMLEN - 1 && c >= 0 && c != ']') {
19 d[i++] = c;
20 c = cp_next();
22 } else {
23 d[i++] = c;
25 d[i] = '\0';
28 static int regid(void)
30 char regname[NMLEN];
31 cparg(regname);
32 return map(regname);
35 static void cp_num(void)
37 int id;
38 int c = cp_next();
39 if (c != '-' && c != '+')
40 cp_back(c);
41 id = regid();
42 if (c == '-' || c == '+')
43 num_get(id, c == '+' ? 1 : -1);
44 if (num_str(id))
45 in_push(num_str(id), NULL);
48 static void cp_str(void)
50 char *buf = str_get(regid());
51 if (buf)
52 in_push(buf, NULL);
55 static void cp_numfmt(void)
57 in_push(num_getfmt(regid()), NULL);
60 static void cp_arg(void)
62 char argname[NMLEN];
63 char *arg = NULL;
64 int argnum;
65 cparg(argname);
66 argnum = atoi(argname);
67 if (argnum > 0 && argnum < NARGS + 1)
68 arg = in_arg(argnum);
69 if (arg)
70 in_push(arg, NULL);
73 static void cp_width(void)
75 char wid[16];
76 sprintf(wid, "%d", ren_wid(cp_next, cp_back));
77 in_push(wid, NULL);
80 static int cp_raw(void)
82 int c;
83 if (in_top() >= 0)
84 return in_next();
85 do {
86 c = in_next();
87 } while (c == c_ni);
88 if (c == c_ec) {
89 do {
90 c = in_next();
91 } while (c == c_ni);
92 if (c == '\n')
93 return cp_raw();
94 if (c == '.')
95 return '.';
96 if (c == '\\') {
97 in_back('\\');
98 return c_ni;
100 if (c == 't') {
101 in_back('\t');
102 return c_ni;
104 if (c == 'a') {
105 in_back('\x01');
106 return c_ni;
108 if (c == '{' && cp_nblk < LEN(cp_sblk))
109 cp_sblk[cp_nblk++] = 0;
110 if (c == '}' && cp_nblk > 0)
111 if (cp_sblk[--cp_nblk])
112 return cp_raw();
113 in_back(c);
114 return c_ec;
116 return c;
119 int cp_next(void)
121 int c;
122 if (in_top() >= 0)
123 return in_next();
124 c = cp_raw();
125 if (c == c_ec) {
126 c = cp_raw();
127 if (c == '"') {
128 while (c >= 0 && c != '\n')
129 c = cp_raw();
130 } else if (c == 'w' && cp_widreq) {
131 cp_width();
132 c = cp_next();
133 } else if (c == 'n') {
134 cp_num();
135 c = cp_next();
136 } else if (c == '*') {
137 cp_str();
138 c = cp_next();
139 } else if (c == 'g') {
140 cp_numfmt();
141 c = cp_next();
142 } else if (c == '$') {
143 cp_arg();
144 c = cp_next();
145 } else {
146 cp_back(c);
147 c = c_ec;
150 return c;
153 void cp_blk(int skip)
155 int c;
156 int nblk = cp_nblk;
157 do {
158 c = skip ? cp_raw() : cp_next();
159 } while (c == ' ' || c == '\t');
160 if (skip) {
161 while (c >= 0 && (c != '\n' || cp_nblk > nblk))
162 c = cp_raw();
163 } else {
164 if (c == c_ec && in_top() == '{') { /* a troff \{ \} block */
165 cp_sblk[nblk] = 1;
166 cp_raw();
167 } else {
168 cp_back(c);
173 void cp_wid(int enable)
175 cp_widreq = enable;