static void compresuflen( const char * const *lines, const char * const *endline, const charset *bodychars, int body, int pre, int suf, int *ppre, int *psuf ) /* lines is an array of strings, up to but not including endline. */ /* Writes into *ppre and *psuf the comprelen and comsuflen of the */ /* lines in lines. Assumes that they have already been determined */ /* to be at least pre and suf. endline must not equal lines. */ { const char *start, *end, *knownstart, * const *line, *p1, *p2, *knownend, *knownstart2; start = *lines; end = knownstart = start + pre; if (body) while (*end) ++end; else while (*end && !csmember(*end, bodychars)) ++end; for (line = lines + 1; line < endline; ++line) { for (p1 = knownstart, p2 = *line + pre; p1 < end && *p1 == *p2; ++p1, ++p2); end = p1; } if (body) for (p1 = end; p1 > knownstart; ) if (*--p1 != ' ') if (csmember(*p1, bodychars)) end = p1; else break; *ppre = end - start; knownstart = *lines + *ppre; for (end = knownstart; *end; ++end); knownend = end - suf; if (body) start = knownstart; else for (start = knownend; start > knownstart && !csmember(start[-1], bodychars); --start); for (line = lines + 1; line < endline; ++line) { knownstart2 = *line + *ppre; for (p2 = knownstart2; *p2; ++p2); for (p1 = knownend, p2 -= suf; p1 > start && p2 > knownstart2 && p1[-1] == p2[-1]; --p1, --p2); start = p1; } if (body) { for (p1 = start; start < knownend && (*start == ' ' || csmember(*start, bodychars)); ++start); if (start > p1 && start[-1] == ' ') --start; } else while (end - start >= 2 && *start == ' ' && start[1] == ' ') ++start; *psuf = end - start; }
static void setaffixes( const char * const *inlines, const char * const *endline, const lineprop *props, const charset *bodychars, const charset *quotechars, int hang, int body, int quote, int *pafp, int *pfs, int *pprefix, int *psuffix ) /* inlines is an array of strings, up to but not including endline, */ /* representing an IP. inlines and endline must not be equal. props */ /* is the the parallel array of lineprop structures. *pafp and *pfs */ /* are set to the augmented fallback prelen and fallback suflen of the */ /* IP. If either of *pprefix, *psuffix is less than 0, it is set to a */ /* default value as specified in "par.doc". */ { int numin, pre, suf; const char *p; numin = endline - inlines; if ((*pprefix < 0 || *psuffix < 0) && numin > hang + 1) compresuflen(inlines + hang, endline, bodychars, body, 0, 0, &pre, &suf); p = *inlines + props->p; if (numin == 1 && quote) while (*p && csmember (*p, quotechars)) ++p; *pafp = p - *inlines; *pfs = props->s; if (*pprefix < 0) *pprefix = numin > hang + 1 ? pre : *pafp; if (*psuffix < 0) *psuffix = numin > hang + 1 ? suf : *pfs; }
static charset *csud( int u, const charset *cset1, const charset *cset2, errmsg_t errmsg ) /* Returns the union of cset1 and cset2 if u is 1, or the set */ /* difference cset1 - cset2 if u is 0. Returns NULL on failure. */ { charset *csu; buffer *inbuf = NULL, *outbuf = NULL; wchar_t *lists[4], **list, *p, nullchar = L'\0'; csu = malloc(sizeof (charset)); if (!csu) { wcscpy(errmsg,outofmem); goto csuderror; } inbuf = newbuffer(sizeof (wchar_t), errmsg); if (*errmsg) goto csuderror; outbuf = newbuffer(sizeof (wchar_t), errmsg); if (*errmsg) goto csuderror; csu->inlist = csu->outlist = NULL; csu->flags = u ? cset1->flags | cset2->flags : cset1->flags & ~cset2->flags; lists[0] = cset1->inlist; lists[1] = cset1->outlist; lists[2] = cset2->inlist; lists[3] = cset2->outlist; for (list = lists; list < lists + 4; ++list) if (*list) { for (p = *list; *p; ++p) if (u ? csmember(*p, cset1) || csmember(*p, cset2) : csmember(*p, cset1) && !csmember(*p, cset2)) { if (!csmember(*p, csu)) { additem(inbuf,p,errmsg); if (*errmsg) goto csuderror; } } else if (csmember(*p, csu)) { additem(outbuf,p,errmsg); if (*errmsg) goto csuderror; } } additem(inbuf, &nullchar, errmsg); if (*errmsg) goto csuderror; additem(outbuf, &nullchar, errmsg); if (*errmsg) goto csuderror; csu->inlist = copyitems(inbuf,errmsg); if (*errmsg) goto csuderror; csu->outlist = copyitems(outbuf,errmsg); if (*errmsg) goto csuderror; csudcleanup: if (inbuf) freebuffer(inbuf); if (outbuf) freebuffer(outbuf); return csu; csuderror: if (csu) freecharset(csu); csu = NULL; goto csudcleanup; }
int main(int argc, const char * const *argv) { int help = 0, version = 0, hang = 0, prefix = -1, repeat = 0, suffix = -1, Tab = 1, width = 72, body = 0, cap = 0, div = 0, Err = 0, expel = 0, fit = 0, guess = 0, invis = 0, just = 0, last = 0, quote = 0, Report = 0, touch = -1; int prefixbak, suffixbak, c, sawnonblank, oweblank, n, i, afp, fs; charset *bodychars = NULL, *protectchars = NULL, *quotechars = NULL; char *parinit = NULL, *arg, **inlines = NULL, **endline, **firstline, *end, **nextline, **outlines = NULL, **line; const char *env, * const whitechars = " \f\n\r\t\v"; errmsg_t errmsg = { '\0' }; lineprop *props = NULL, *firstprop, *nextprop; FILE *errout; /* Process environment variables: */ env = getenv("PARBODY"); if (!env) env = ""; bodychars = parsecharset(env,errmsg); if (*errmsg) { help = 1; goto parcleanup; } env = getenv("PARPROTECT"); if (!env) env = ""; protectchars = parsecharset(env,errmsg); if (*errmsg) { help = 1; goto parcleanup; } env = getenv("PARQUOTE"); if (!env) env = "> "; quotechars = parsecharset(env,errmsg); if (*errmsg) { help = 1; goto parcleanup; } env = getenv("PARINIT"); if (env) { parinit = malloc((strlen(env) + 1) * sizeof (char)); if (!parinit) { strcpy(errmsg,outofmem); goto parcleanup; } strcpy(parinit,env); arg = strtok(parinit,whitechars); while (arg) { parsearg(arg, &help, &version, bodychars, protectchars, quotechars, &hang, &prefix, &repeat, &suffix, &Tab, &width, &body, &cap, &div, &Err, &expel, &fit, &guess, &invis, &just, &last, "e, &Report, &touch, errmsg ); if (*errmsg || help || version) goto parcleanup; arg = strtok(NULL,whitechars); } free(parinit); parinit = NULL; } /* Process command line arguments: */ while (*++argv) { parsearg(*argv, &help, &version, bodychars, protectchars, quotechars, &hang, &prefix, &repeat, &suffix, &Tab, &width, &body, &cap, &div, &Err, &expel, &fit, &guess, &invis, &just, &last, "e, &Report, &touch, errmsg ); if (*errmsg || help || version) goto parcleanup; } if (Tab == 0) { strcpy(errmsg, "<Tab> must not be 0.\n"); goto parcleanup; } if (touch < 0) touch = fit || last; prefixbak = prefix; suffixbak = suffix; /* Main loop: */ for (sawnonblank = oweblank = 0; ; ) { for (;;) { c = getchar(); if (expel && c == '\n') { oweblank = sawnonblank; continue; } if (csmember((char) c, protectchars)) { sawnonblank = 1; if (oweblank) { putchar('\n'); oweblank = 0; } while (c != '\n' && c != EOF) { putchar(c); c = getchar(); } } if (c != '\n') break; putchar(c); } if (c == EOF) break; ungetc(c,stdin); inlines = readlines(&props, protectchars, quotechars, Tab, invis, quote, errmsg); if (*errmsg) goto parcleanup; for (endline = inlines; *endline; ++endline); if (endline == inlines) { free(inlines); inlines = NULL; continue; } sawnonblank = 1; if (oweblank) { putchar('\n'); oweblank = 0; } delimit((const char * const *) inlines, (const char * const *) endline, bodychars, repeat, body, div, 0, 0, props); if (expel) marksuperf((const char * const *) inlines, (const char * const *) endline, props); firstline = inlines, firstprop = props; do { if (isbodiless(firstprop)) { if (!isinvis(firstprop) && !(expel && issuperf(firstprop))) { for (end = *firstline; *end; ++end); if (!repeat || firstprop->rc == ' ' && !firstprop->s) { while (end > *firstline && end[-1] == ' ') --end; *end = '\0'; puts(*firstline); } else { n = width - firstprop->p - firstprop->s; if (n < 0) { sprintf(errmsg,impossibility,5); goto parcleanup; } printf("%.*s", firstprop->p, *firstline); for (i = n; i; --i) putchar(firstprop->rc); puts(end - firstprop->s); } } ++firstline, ++firstprop; continue; } for (nextline = firstline + 1, nextprop = firstprop + 1; nextline < endline && !isbodiless(nextprop) && !isfirst(nextprop); ++nextline, ++nextprop); prefix = prefixbak, suffix = suffixbak; setaffixes((const char * const *) firstline, (const char * const *) nextline, firstprop, bodychars, quotechars, hang, body, quote, &afp, &fs, &prefix, &suffix); if (width <= prefix + suffix) { sprintf(errmsg, "<width> (%d) <= <prefix> (%d) + <suffix> (%d)\n", width, prefix, suffix); goto parcleanup; } outlines = reformat((const char * const *) firstline, (const char * const *) nextline, afp, fs, hang, prefix, suffix, width, cap, fit, guess, just, last, Report, touch, errmsg); if (*errmsg) goto parcleanup; for (line = outlines; *line; ++line) puts(*line); freelines(outlines); outlines = NULL; firstline = nextline, firstprop = nextprop; } while (firstline < endline); freelines(inlines); inlines = NULL; free(props); props = NULL; } parcleanup: if (bodychars) freecharset(bodychars); if (protectchars) freecharset(protectchars); if (quotechars) freecharset(quotechars); if (parinit) free(parinit); if (inlines) freelines(inlines); if (props) free(props); if (outlines) freelines(outlines); errout = Err ? stderr : stdout; if (*errmsg) fprintf(errout, "par error:\n%.*s", errmsg_size, errmsg); if (version) fputs("par 1.50\n",errout); if (help) fputs(usagemsg,errout); return *errmsg ? EXIT_FAILURE : EXIT_SUCCESS; }