1 /* copy-mode character interpretation */
7 static int cp_blkdep
; /* input block depth (text in \{ and \}) */
8 static int cp_cpmode
; /* disable the interpretation of \w and \E */
9 static int cp_reqdep
; /* the block depth of current request line */
11 /* just like cp_next(), but remove c_ni characters */
12 static int cp_noninext(void)
20 /* return 1 if \*[] includes a space */
21 static int cparg(char *d
, int len
)
23 int c
= cp_noninext();
26 i
+= utf8next(d
+ i
, cp_noninext
);
27 i
+= utf8next(d
+ i
, cp_noninext
);
28 } else if (!n_cp
&& c
== '[') {
30 while (c
>= 0 && c
!= ']' && c
!= ' ') {
39 utf8next(d
, cp_noninext
);
44 static int regid(void)
47 cparg(regname
, sizeof(regname
));
51 /* interpolate \n(xy */
52 static void cp_num(void)
55 int c
= cp_noninext();
57 if (c
!= '-' && c
!= '+')
60 if (c
== '-' || c
== '+')
61 num_inc(id
, c
== '+');
62 if ((s
= num_str(id
)) != NULL
)
66 /* interpolate \*(xy */
67 static void cp_str(void)
70 char *args
[NARGS
+ 2] = {reg
};
72 if (cparg(reg
, sizeof(reg
))) {
73 buf
= tr_args(args
+ 1, ']', cp_noninext
, cp_back
);
76 if (str_get(map(reg
)))
77 in_push(str_get(map(reg
)), buf
? args
: NULL
);
79 tr_req(map(reg
), args
);
83 /* interpolate \g(xy */
84 static void cp_numfmt(void)
86 in_push(num_getfmt(regid()), NULL
);
89 /* interpolate \$*, \$@, and \$^ */
90 static void cp_args(int quote
, int escape
)
96 for (i
= 1; i
< in_nargs(); i
++) {
97 sbuf_append(&sb
, i
> 1 ? " " : "");
98 sbuf_append(&sb
, quote
? "\"" : "");
101 sbuf_append(&sb
, escape
&& *s
== '"' ? "\"" : "");
102 sbuf_add(&sb
, (unsigned char) *s
++);
104 sbuf_append(&sb
, quote
? "\"" : "");
106 in_push(sbuf_buf(&sb
), NULL
);
110 /* interpolate \$1 */
111 static void cp_arg(void)
116 cparg(argname
, sizeof(argname
));
117 if (!strcmp("@", argname
)) {
121 if (!strcmp("*", argname
)) {
125 if (!strcmp("^", argname
)) {
129 argnum
= atoi(argname
);
130 if (argnum
>= 0 && argnum
< NARGS
)
131 arg
= in_arg(argnum
);
136 /* interpolate \w'xyz' */
137 static void cp_width(void)
140 sprintf(wid
, "%d", ren_wid(cp_next
, cp_back
));
144 /* define a register as \R'xyz expr' */
145 static void cp_numdef(void)
147 char *arg
= quotednext(cp_noninext
, cp_back
);
149 while (*s
&& *s
!= ' ')
156 num_set(map(arg
), eval_re(s
, num_get(map(arg
)), 'u'));
160 /* conditional interpolation as \?'cond@expr1@expr2@' */
161 static void cp_cond(void)
163 char delim
[GNLEN
], cs
[GNLEN
];
167 char *arg
= quotednext(cp_noninext
, cp_back
);
169 n
= eval_up(&s
, '\0');
170 if (charread(&s
, delim
) < 0) {
174 if (!strcmp(delim
, "\\&") && charread(&s
, delim
) < 0) {
180 while (charread_delim(&s
, cs
, delim
) >= 0)
185 while (charread_delim(&s
, cs
, delim
) >= 0)
188 in_push(n
> 0 ? s1
: s2
, NULL
);
192 static int cp_raw(void)
220 /* replace \{ and \} with a space if not in copy mode */
221 if (c
== '}' && !cp_cpmode
) {
225 if (c
== '{' && !cp_cpmode
) {
243 if (c
== 'E' && !cp_cpmode
)
246 while (c
>= 0 && c
!= '\n')
248 } else if (c
== '#') {
249 while (c
>= 0 && c
!= '\n')
253 } else if (c
== 'w' && !cp_cpmode
) {
256 } else if (c
== 'n') {
259 } else if (c
== '*') {
262 } else if (c
== 'g') {
265 } else if (c
== '$') {
268 } else if (c
== '?') {
271 } else if (c
== 'R' && !cp_cpmode
) {
282 void cp_blk(int skip
)
286 while (c
>= 0 && (c
!= '\n' || cp_blkdep
> cp_reqdep
))
292 /* push back if the space is not inserted due to \{ and \} */
298 void cp_copymode(int mode
)
303 /* beginning of a request; save current cp_blkdep */
306 cp_reqdep
= cp_blkdep
;