ref: 73e0f630cdbbeb348edeb7eada032b368968b624
dir: /cp.c/
/* copy-mode character interpretation */ #include <stdio.h> #include <stdlib.h> #include "roff.h" static int cp_nblk; /* input block depth (text in \{ and \}) */ static int cp_sblk[NIES]; /* skip \} escape at this depth, if set */ static int cp_widreq = 1; /* inline \w requests */ static void cparg(char *d) { int c = cp_next(); int i = 0; if (c == '(') { d[i++] = cp_next(); d[i++] = cp_next(); } else if (!n_cp && c == '[') { c = cp_next(); while (i < NMLEN - 1 && c >= 0 && c != ']') { d[i++] = c; c = cp_next(); } } else { d[i++] = c; } d[i] = '\0'; } static int regid(void) { char regname[NMLEN]; cparg(regname); return map(regname); } static void cp_num(void) { int id; int c = cp_next(); if (c != '-' && c != '+') cp_back(c); id = regid(); if (c == '-' || c == '+') num_get(id, c == '+' ? 1 : -1); if (num_str(id)) in_push(num_str(id), NULL); } static void cp_str(void) { char *buf = str_get(regid()); if (buf) in_push(buf, NULL); } static void cp_numfmt(void) { in_push(num_getfmt(regid()), NULL); } static void cp_arg(void) { char argname[NMLEN]; char *arg = NULL; int argnum; cparg(argname); argnum = atoi(argname); if (argnum > 0 && argnum < NARGS + 1) arg = in_arg(argnum); if (arg) in_push(arg, NULL); } static void cp_width(void) { char wid[16]; sprintf(wid, "%d", ren_wid(cp_next, cp_back)); in_push(wid, NULL); } static int cp_raw(void) { int c; if (in_top() >= 0) return in_next(); do { c = in_next(); } while (c == c_ni); if (c == c_ec) { do { c = in_next(); } while (c == c_ni); if (c == '\n') return cp_raw(); if (c == '.') return '.'; if (c == '\\') { in_back('\\'); return c_ni; } if (c == 't') { in_back('\t'); return c_ni; } if (c == 'a') { in_back(''); return c_ni; } if (c == '{' && cp_nblk < LEN(cp_sblk)) cp_sblk[cp_nblk++] = 0; if (c == '}' && cp_nblk > 0) if (cp_sblk[--cp_nblk]) return cp_raw(); in_back(c); return c_ec; } return c; } int cp_next(void) { int c; if (in_top() >= 0) return in_next(); c = cp_raw(); if (c == c_ec) { c = cp_raw(); if (c == '"') { while (c >= 0 && c != '\n') c = cp_raw(); } else if (c == 'w' && cp_widreq) { cp_width(); c = cp_next(); } else if (c == 'n') { cp_num(); c = cp_next(); } else if (c == '*') { cp_str(); c = cp_next(); } else if (c == 'g') { cp_numfmt(); c = cp_next(); } else if (c == '$') { cp_arg(); c = cp_next(); } else { cp_back(c); c = c_ec; } } return c; } void cp_blk(int skip) { int c; int nblk = cp_nblk; do { c = skip ? cp_raw() : cp_next(); } while (c == ' ' || c == '\t'); if (skip) { while (c >= 0 && (c != '\n' || cp_nblk > nblk)) c = cp_raw(); } else { if (c == c_ec && in_top() == '{') { /* a troff \{ \} block */ cp_sblk[nblk] = 1; cp_raw(); } else { cp_back(c); } } } void cp_wid(int enable) { cp_widreq = enable; }