9base

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

word.c (2717B)


      1 #include	"mk.h"
      2 
      3 static	Word	*nextword(char**);
      4 
      5 Word*
      6 newword(char *s)
      7 {
      8 	Word *w;
      9 
     10 	w = (Word *)Malloc(sizeof(Word));
     11 	w->s = strdup(s);
     12 	w->next = 0;
     13 	return(w);
     14 }
     15 
     16 Word *
     17 stow(char *s)
     18 {
     19 	Word *head, *w, *new;
     20 
     21 	w = head = 0;
     22 	while(*s){
     23 		new = nextword(&s);
     24 		if(new == 0)
     25 			break;
     26 		if (w)
     27 			w->next = new;
     28 		else
     29 			head = w = new;
     30 		while(w->next)
     31 			w = w->next;
     32 		
     33 	}
     34 	if (!head)
     35 		head = newword("");
     36 	return(head);
     37 }
     38 
     39 char *
     40 wtos(Word *w, int sep)
     41 {
     42 	Bufblock *buf;
     43 	char *cp;
     44 
     45 	buf = newbuf();
     46 	for(; w; w = w->next){
     47 		for(cp = w->s; *cp; cp++)
     48 			insert(buf, *cp);
     49 		if(w->next)
     50 			insert(buf, sep);
     51 	}
     52 	insert(buf, 0);
     53 	cp = strdup(buf->start);
     54 	freebuf(buf);
     55 	return(cp);
     56 }
     57 
     58 Word*
     59 wdup(Word *w)
     60 {
     61 	Word *v, *new, *base;
     62 
     63 	v = base = 0;
     64 	while(w){
     65 		new = newword(w->s);
     66 		if(v)
     67 			v->next = new;
     68 		else
     69 			base = new;
     70 		v = new;
     71 		w = w->next;
     72 	}
     73 	return base;
     74 }
     75 
     76 void
     77 delword(Word *w)
     78 {
     79 	Word *v;
     80 
     81 	while(v = w){
     82 		w = w->next;
     83 		if(v->s)
     84 			free(v->s);
     85 		free(v);
     86 	}
     87 }
     88 
     89 /*
     90  *	break out a word from a string handling quotes, executions,
     91  *	and variable expansions.
     92  */
     93 static Word*
     94 nextword(char **s)
     95 {
     96 	Bufblock *b;
     97 	Word *head, *tail, *w;
     98 	Rune r;
     99 	char *cp;
    100 	int empty;
    101 
    102 	cp = *s;
    103 	b = newbuf();
    104 restart:
    105 	head = tail = 0;
    106 	while(*cp == ' ' || *cp == '\t')		/* leading white space */
    107 		cp++;
    108 	empty = 1;
    109 	while(*cp){
    110 		cp += chartorune(&r, cp);
    111 		switch(r)
    112 		{
    113 		case ' ':
    114 		case '\t':
    115 		case '\n':
    116 			goto out;
    117 		case '\\':
    118 		case '\'':
    119 		case '"':
    120 			empty = 0;
    121 			cp = shellt->expandquote(cp, r, b);
    122 			if(cp == 0){
    123 				fprint(2, "missing closing quote: %s\n", *s);
    124 				Exit();
    125 			}
    126 			break;
    127 		case '$':
    128 			w = varsub(&cp);
    129 			if(w == 0){
    130 				if(empty)
    131 					goto restart;
    132 				break;
    133 			}
    134 			empty = 0;
    135 			if(b->current != b->start){
    136 				bufcpy(b, w->s, strlen(w->s));
    137 				insert(b, 0);
    138 				free(w->s);
    139 				w->s = strdup(b->start);
    140 				b->current = b->start;
    141 			}
    142 			if(head){
    143 				bufcpy(b, tail->s, strlen(tail->s));
    144 				bufcpy(b, w->s, strlen(w->s));
    145 				insert(b, 0);
    146 				free(tail->s);
    147 				tail->s = strdup(b->start);
    148 				tail->next = w->next;
    149 				free(w->s);
    150 				free(w);
    151 				b->current = b->start;
    152 			} else
    153 				tail = head = w;
    154 			while(tail->next)
    155 				tail = tail->next;
    156 			break;
    157 		default:
    158 			empty = 0;
    159 			rinsert(b, r);
    160 			break;
    161 		}
    162 	}
    163 out:
    164 	*s = cp;
    165 	if(b->current != b->start){
    166 		if(head){
    167 			cp = b->current;
    168 			bufcpy(b, tail->s, strlen(tail->s));
    169 			bufcpy(b, b->start, cp-b->start);
    170 			insert(b, 0);
    171 			free(tail->s);
    172 			tail->s = strdup(cp);
    173 		} else {
    174 			insert(b, 0);
    175 			head = newword(b->start);
    176 		}
    177 	}
    178 	freebuf(b);
    179 	return head;
    180 }
    181 
    182 void
    183 dumpw(char *s, Word *w)
    184 {
    185 	Bprint(&bout, "%s", s);
    186 	for(; w; w = w->next)
    187 		Bprint(&bout, " '%s'", w->s);
    188 	Bputc(&bout, '\n');
    189 }