word.c 2.6 KB

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