rc.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
       ---
       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 };