ren: add local motion functions
[neatroff.git] / cp.c
blob6fada4507126d4bcc05425db12b416ae379b5759
1 #include <stdio.h>
2 #include <stdlib.h>
3 #include "xroff.h"
5 #define CPBUF 4
7 static int cp_buf[CPBUF]; /* pushed character stack */
8 static int cp_backed; /* number of pushed characters */
9 static int cp_nblk; /* input block depth (text in \{ and \}) */
10 static int cp_sblk[NIES]; /* skip \} escape at this depth, if set */
12 static int regid(void)
14 int c1;
15 int c2 = 0;
16 c1 = cp_next();
17 if (c1 == '(') {
18 c1 = cp_next();
19 c2 = cp_next();
21 return REG(c1, c2);
24 static void cp_num(void)
26 int id;
27 int c = cp_next();
28 if (c != '-' && c != '+')
29 cp_back(c);
30 id = regid();
31 if (c == '-' || c == '+')
32 num_get(id, c == '+' ? 1 : -1);
33 if (num_str(id))
34 in_push(num_str(id), NULL);
37 static void cp_str(void)
39 char *buf = str_get(regid());
40 if (buf)
41 in_push(buf, NULL);
44 static void cp_arg(void)
46 int c;
47 char *arg = NULL;
48 c = cp_next();
49 if (c >= '1' && c <= '9')
50 arg = in_arg(c - '0');
51 if (arg)
52 in_push(arg, NULL);
55 static int cp_raw(void)
57 int c;
58 if (cp_backed)
59 return cp_buf[--cp_backed];
60 c = in_next();
61 if (c == '\\') {
62 c = in_next();
63 if (c == '\n')
64 return in_next();
65 if (c == '.')
66 return '.';
67 if (c == '{' && cp_nblk < LEN(cp_sblk))
68 cp_sblk[cp_nblk++] = 0;
69 if (c == '}' && cp_nblk > 0)
70 if (cp_sblk[--cp_nblk])
71 return cp_raw();
72 cp_back(c);
73 return '\\';
75 return c;
78 int cp_next(void)
80 int c;
81 if (cp_backed)
82 return cp_buf[--cp_backed];
83 c = cp_raw();
84 if (c == '\\') {
85 c = cp_raw();
86 if (c == '"') {
87 while (c >= 0 && c != '\n')
88 c = cp_raw();
89 } else if (c == 'n') {
90 cp_num();
91 c = cp_raw();
92 } else if (c == '*') {
93 cp_str();
94 c = cp_raw();
95 } else if (c == '$') {
96 cp_arg();
97 c = cp_raw();
98 } else {
99 cp_back(c);
100 c = '\\';
103 return c;
106 void cp_back(int c)
108 if (cp_backed < CPBUF)
109 cp_buf[cp_backed++] = c;
112 static int cp_top(void)
114 return cp_backed ? cp_buf[cp_backed - 1] : -1;
117 void cp_blk(int skip)
119 int c;
120 int nblk = cp_nblk;
121 do {
122 c = cp_raw();
123 } while (c == ' ' || c == '\t');
124 if (c == '\\' && cp_top() == '{') { /* a troff \{ \} block */
125 if (skip) {
126 while (skip && cp_nblk > nblk && c >= 0)
127 c = cp_raw();
128 } else {
129 cp_sblk[nblk] = 1;
130 cp_raw();
132 } else {
133 if (!skip)
134 cp_back(c);
136 while (skip && c != '\n') /* skip until the end of the line */
137 c = cp_raw();