word.c 2.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180
  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. cp = *s;
  88. b = newbuf();
  89. head = tail = 0;
  90. while(*cp == ' ' || *cp == '\t') /* leading white space */
  91. cp++;
  92. while(*cp){
  93. cp += chartorune(&r, cp);
  94. switch(r)
  95. {
  96. case ' ':
  97. case '\t':
  98. case '\n':
  99. goto out;
  100. case '\\':
  101. case '\'':
  102. case '"':
  103. cp = expandquote(cp, r, b);
  104. if(cp == 0){
  105. fprint(2, "missing closing quote: %s\n", *s);
  106. Exit();
  107. }
  108. break;
  109. case '$':
  110. w = varsub(&cp);
  111. if(w == 0)
  112. break;
  113. if(b->current != b->start){
  114. bufcpy(b, w->s, strlen(w->s));
  115. insert(b, 0);
  116. free(w->s);
  117. w->s = strdup(b->start);
  118. b->current = b->start;
  119. }
  120. if(head){
  121. bufcpy(b, tail->s, strlen(tail->s));
  122. bufcpy(b, w->s, strlen(w->s));
  123. insert(b, 0);
  124. free(tail->s);
  125. tail->s = strdup(b->start);
  126. tail->next = w->next;
  127. free(w->s);
  128. free(w);
  129. b->current = b->start;
  130. } else
  131. tail = head = w;
  132. while(tail->next)
  133. tail = tail->next;
  134. break;
  135. default:
  136. rinsert(b, r);
  137. break;
  138. }
  139. }
  140. out:
  141. *s = cp;
  142. if(b->current != b->start){
  143. if(head){
  144. cp = b->current;
  145. bufcpy(b, tail->s, strlen(tail->s));
  146. bufcpy(b, b->start, cp-b->start);
  147. insert(b, 0);
  148. free(tail->s);
  149. tail->s = strdup(cp);
  150. } else {
  151. insert(b, 0);
  152. head = newword(b->start);
  153. }
  154. }
  155. freebuf(b);
  156. return head;
  157. }
  158. void
  159. dumpw(char *s, Word *w)
  160. {
  161. Bprint(&bout, "%s", s);
  162. for(; w; w = w->next)
  163. Bprint(&bout, " '%s'", w->s);
  164. Bputc(&bout, '\n');
  165. }