| #include "mk.h" |
| |
| char *termchars = "'= \t"; /*used in parse.c to isolate assignment attribute*/ |
| char *shflags = "-I"; /* rc flag to force non-interactive mode */ |
| int IWS = '\1'; /* inter-word separator in env - not used in plan 9 */ |
| |
| /* |
| * This file contains functions that depend on rc's syntax. Most |
| * of the routines extract strings observing rc's escape conventions |
| */ |
| |
| |
| /* |
| * skip a token in single quotes. |
| */ |
| static char * |
| squote(char *cp) |
| { |
| Rune r; |
| int n; |
| |
| while(*cp){ |
| n = chartorune(&r, cp); |
| if(r == '\'') { |
| n += chartorune(&r, cp+n); |
| if(r != '\'') |
| return(cp); |
| } |
| cp += n; |
| } |
| SYNERR(-1); /* should never occur */ |
| fprint(2, "missing closing '\n"); |
| return 0; |
| } |
| |
| /* |
| * search a string for characters in a pattern set |
| * characters in quotes and variable generators are escaped |
| */ |
| char * |
| charin(char *cp, char *pat) |
| { |
| Rune r; |
| int n, vargen; |
| |
| vargen = 0; |
| while(*cp){ |
| n = chartorune(&r, cp); |
| switch(r){ |
| case '\'': /* skip quoted string */ |
| cp = squote(cp+1); /* n must = 1 */ |
| if(!cp) |
| return 0; |
| break; |
| case '$': |
| if(*(cp+1) == '{') |
| vargen = 1; |
| break; |
| case '}': |
| if(vargen) |
| vargen = 0; |
| else if(utfrune(pat, r)) |
| return cp; |
| break; |
| default: |
| if(vargen == 0 && utfrune(pat, r)) |
| return cp; |
| break; |
| } |
| cp += n; |
| } |
| if(vargen){ |
| SYNERR(-1); |
| fprint(2, "missing closing } in pattern generator\n"); |
| } |
| return 0; |
| } |
| |
| /* |
| * extract an escaped token. Possible escape chars are single-quote, |
| * double-quote,and backslash. Only the first is valid for rc. the |
| * others are just inserted into the receiving buffer. |
| */ |
| char* |
| expandquote(char *s, Rune r, Bufblock *b) |
| { |
| if (r != '\'') { |
| rinsert(b, r); |
| return s; |
| } |
| |
| while(*s){ |
| s += chartorune(&r, s); |
| if(r == '\'') { |
| if(*s == '\'') |
| s++; |
| else |
| return s; |
| } |
| rinsert(b, r); |
| } |
| return 0; |
| } |
| |
| /* |
| * Input an escaped token. Possible escape chars are single-quote, |
| * double-quote and backslash. Only the first is a valid escape for |
| * rc; the others are just inserted into the receiving buffer. |
| */ |
| int |
| escapetoken(Biobuf *bp, Bufblock *buf, int preserve, int esc) |
| { |
| int c, line; |
| |
| if(esc != '\'') |
| return 1; |
| |
| line = mkinline; |
| while((c = nextrune(bp, 0)) > 0){ |
| if(c == '\''){ |
| if(preserve) |
| rinsert(buf, c); |
| c = Bgetrune(bp); |
| if (c < 0) |
| break; |
| if(c != '\''){ |
| Bungetrune(bp); |
| return 1; |
| } |
| } |
| rinsert(buf, c); |
| } |
| SYNERR(line); fprint(2, "missing closing %c\n", esc); |
| return 0; |
| } |
| |
| /* |
| * copy a single-quoted string; s points to char after opening quote |
| */ |
| static char * |
| copysingle(char *s, Bufblock *buf) |
| { |
| Rune r; |
| |
| while(*s){ |
| s += chartorune(&r, s); |
| rinsert(buf, r); |
| if(r == '\'') |
| break; |
| } |
| return s; |
| } |
| /* |
| * check for quoted strings. backquotes are handled here; single quotes above. |
| * s points to char after opening quote, q. |
| */ |
| char * |
| copyq(char *s, Rune q, Bufblock *buf) |
| { |
| if(q == '\'') /* copy quoted string */ |
| return copysingle(s, buf); |
| |
| if(q != '`') /* not quoted */ |
| return s; |
| |
| while(*s){ /* copy backquoted string */ |
| s += chartorune(&q, s); |
| rinsert(buf, q); |
| if(q == '}') |
| break; |
| if(q == '\'') |
| s = copysingle(s, buf); /* copy quoted string */ |
| } |
| return s; |
| } |