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