xref: /plan9/sys/src/cmd/mk/word.c (revision d3907fe5a68251e8b016f54f72acf8767ba044bb)
1 #include	"mk.h"
2 
3 static	Word	*nextword(char**);
4 
5 Word*
newword(char * s)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 *
stow(char * s)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 *
wtos(Word * w,int sep)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*
wdup(Word * w)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
delword(Word * w)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*
nextword(char ** s)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 = 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
dumpw(char * s,Word * w)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 }
190