blob: e25665141637d5fb2df92c167200f7946edb927c [file] [log] [blame]
#include "mk.h"
/*
* This file contains functions that depend on the shell's syntax. Most
* of the routines extract strings observing the shell's escape conventions.
*/
/*
* skip a token in quotes.
*/
static char *
squote(char *cp, int c)
{
Rune r;
int n;
while(*cp){
n = chartorune(&r, cp);
if(r == c)
return cp;
if(r == '\\')
n += chartorune(&r, cp+n);
cp += n;
}
SYNERR(-1); /* should never occur */
fprint(2, "missing closing '\n");
return 0;
}
/*
* search a string for unescaped characters in a pattern set
*/
static char *
shcharin(char *cp, char *pat)
{
Rune r;
int n, vargen;
vargen = 0;
while(*cp){
n = chartorune(&r, cp);
switch(r){
case '\\': /* skip escaped char */
cp += n;
n = chartorune(&r, cp);
break;
case '\'': /* skip quoted string */
case '"':
cp = squote(cp+1, r); /* 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.
*/
static char*
shexpandquote(char *s, Rune esc, Bufblock *b)
{
Rune r;
if (esc == '\\') {
s += chartorune(&r, s);
rinsert(b, r);
return s;
}
while(*s){
s += chartorune(&r, s);
if(r == esc)
return s;
if (r == '\\') {
rinsert(b, r);
s += chartorune(&r, s);
}
rinsert(b, r);
}
return 0;
}
/*
* Input an escaped token. Possible escape chars are single-quote,
* double-quote and backslash.
*/
static int
shescapetoken(Biobuf *bp, Bufblock *buf, int preserve, int esc)
{
int c, line;
if(esc == '\\') {
c = Bgetrune(bp);
if(c == '\r')
c = Bgetrune(bp);
if (c == '\n')
mkinline++;
rinsert(buf, c);
return 1;
}
line = mkinline;
while((c = nextrune(bp, 0)) >= 0){
if(c == esc){
if(preserve)
rinsert(buf, c);
return 1;
}
if(c == '\\') {
rinsert(buf, c);
c = Bgetrune(bp);
if(c == '\r')
c = Bgetrune(bp);
if (c < 0)
break;
if (c == '\n')
mkinline++;
}
rinsert(buf, c);
}
SYNERR(line); fprint(2, "missing closing %c\n", esc);
return 0;
}
/*
* copy a quoted string; s points to char after opening quote
*/
static char *
copysingle(char *s, Rune q, Bufblock *buf)
{
Rune r;
while(*s){
s += chartorune(&r, s);
rinsert(buf, r);
if(r == q)
break;
}
return s;
}
/*
* check for quoted strings. backquotes are handled here; single quotes above.
* s points to char after opening quote, q.
*/
static char *
shcopyq(char *s, Rune q, Bufblock *buf)
{
if(q == '\'' || q == '"') /* copy quoted string */
return copysingle(s, q, buf);
if(q != '`') /* not quoted */
return s;
while(*s){ /* copy backquoted string */
s += chartorune(&q, s);
rinsert(buf, q);
if(q == '`')
break;
if(q == '\'' || q == '"')
s = copysingle(s, q, buf); /* copy quoted string */
}
return s;
}
static int
shmatchname(char *name)
{
USED(name);
return 1;
}
Shell shshell = {
"sh",
"\"'= \t", /*used in parse.c to isolate assignment attribute*/
' ', /* inter-word separator in env */
shcharin,
shexpandquote,
shescapetoken,
shcopyq,
shmatchname
};