9base

revived minimalist port of Plan 9 userland to Unix
git clone git://git.suckless.org/9base
Log | Files | Refs | README | LICENSE

rc.c (3271B)


      1 #include	"mk.h"
      2 
      3 /*
      4  *	This file contains functions that depend on rc's syntax.  Most
      5  *	of the routines extract strings observing rc's escape conventions
      6  */
      7 
      8 
      9 /*
     10  *	skip a token in single quotes.
     11  */
     12 static char *
     13 squote(char *cp)
     14 {
     15 	Rune r;
     16 	int n;
     17 
     18 	while(*cp){
     19 		n = chartorune(&r, cp);
     20 		if(r == '\'') {
     21 			n += chartorune(&r, cp+n);
     22 			if(r != '\'')
     23 				return(cp);
     24 		}
     25 		cp += n;
     26 	}
     27 	SYNERR(-1);		/* should never occur */
     28 	fprint(2, "missing closing '\n");
     29 	return 0;
     30 }
     31 
     32 /*
     33  *	search a string for characters in a pattern set
     34  *	characters in quotes and variable generators are escaped
     35  */
     36 char *
     37 rccharin(char *cp, char *pat)
     38 {
     39 	Rune r;
     40 	int n, vargen;
     41 
     42 	vargen = 0;
     43 	while(*cp){
     44 		n = chartorune(&r, cp);
     45 		switch(r){
     46 		case '\'':			/* skip quoted string */
     47 			cp = squote(cp+1);	/* n must = 1 */
     48 			if(!cp)
     49 				return 0;
     50 			break;
     51 		case '$':
     52 			if(*(cp+1) == '{')
     53 				vargen = 1;
     54 			break;
     55 		case '}':
     56 			if(vargen)
     57 				vargen = 0;
     58 			else if(utfrune(pat, r))
     59 				return cp;
     60 			break;
     61 		default:
     62 			if(vargen == 0 && utfrune(pat, r))
     63 				return cp;
     64 			break;
     65 		}
     66 		cp += n;
     67 	}
     68 	if(vargen){
     69 		SYNERR(-1);
     70 		fprint(2, "missing closing } in pattern generator\n");
     71 	}
     72 	return 0;
     73 }
     74 
     75 /*
     76  *	extract an escaped token.  Possible escape chars are single-quote,
     77  *	double-quote,and backslash.  Only the first is valid for rc. the
     78  *	others are just inserted into the receiving buffer.
     79  */
     80 char*
     81 rcexpandquote(char *s, Rune r, Bufblock *b)
     82 {
     83 	if (r != '\'') {
     84 		rinsert(b, r);
     85 		return s;
     86 	}
     87 
     88 	while(*s){
     89 		s += chartorune(&r, s);
     90 		if(r == '\'') {
     91 			if(*s == '\'')
     92 				s++;
     93 			else
     94 				return s;
     95 		}
     96 		rinsert(b, r);
     97 	}
     98 	return 0;
     99 }
    100 
    101 /*
    102  *	Input an escaped token.  Possible escape chars are single-quote,
    103  *	double-quote and backslash.  Only the first is a valid escape for
    104  *	rc; the others are just inserted into the receiving buffer.
    105  */
    106 int
    107 rcescapetoken(Biobuf *bp, Bufblock *buf, int preserve, int esc)
    108 {
    109 	int c, line;
    110 
    111 	if(esc != '\'')
    112 		return 1;
    113 
    114 	line = mkinline;
    115 	while((c = nextrune(bp, 0)) > 0){
    116 		if(c == '\''){
    117 			if(preserve)
    118 				rinsert(buf, c);
    119 			c = Bgetrune(bp);
    120 			if (c < 0)
    121 				break;
    122 			if(c != '\''){
    123 				Bungetrune(bp);
    124 				return 1;
    125 			}
    126 		}
    127 		rinsert(buf, c);
    128 	}
    129 	SYNERR(line); fprint(2, "missing closing %c\n", esc);
    130 	return 0;
    131 }
    132 
    133 /*
    134  *	copy a single-quoted string; s points to char after opening quote
    135  */
    136 static char *
    137 copysingle(char *s, Bufblock *buf)
    138 {
    139 	Rune r;
    140 
    141 	while(*s){
    142 		s += chartorune(&r, s);
    143 		rinsert(buf, r);
    144 		if(r == '\'')
    145 			break;
    146 	}
    147 	return s;
    148 }
    149 /*
    150  *	check for quoted strings.  backquotes are handled here; single quotes above.
    151  *	s points to char after opening quote, q.
    152  */
    153 char *
    154 rccopyq(char *s, Rune q, Bufblock *buf)
    155 {
    156 	if(q == '\'')				/* copy quoted string */
    157 		return copysingle(s, buf);
    158 
    159 	if(q != '`')				/* not quoted */
    160 		return s;
    161 
    162 	while(*s){				/* copy backquoted string */
    163 		s += chartorune(&q, s);
    164 		rinsert(buf, q);
    165 		if(q == '}')
    166 			break;
    167 		if(q == '\'')
    168 			s = copysingle(s, buf);	/* copy quoted string */
    169 	}
    170 	return s;
    171 }
    172 
    173 static int
    174 rcmatchname(char *name)
    175 {
    176 	char *p;
    177 
    178 	if((p = strrchr(name, '/')) != nil)
    179 		name = p+1;
    180 	if(name[0] == 'r' && name[1] == 'c')
    181 		return 1;
    182 	return 0;
    183 }
    184 
    185 Shell rcshell = {
    186 	"rc",
    187 	"'= \t",
    188 	'\1',
    189 	rccharin,
    190 	rcexpandquote,
    191 	rcescapetoken,
    192 	rccopyq,
    193 	rcmatchname
    194 };