input.c 3.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250
  1. /*
  2. * This file is part of the UCB release of Plan 9. It is subject to the license
  3. * terms in the LICENSE file found in the top-level directory of this
  4. * distribution and at http://akaros.cs.berkeley.edu/files/Plan9License. No
  5. * part of the UCB release of Plan 9, including this file, may be copied,
  6. * modified, propagated, or distributed except according to the terms contained
  7. * in the LICENSE file.
  8. */
  9. /*
  10. * Read input files.
  11. */
  12. #include "a.h"
  13. typedef struct Istack Istack;
  14. struct Istack
  15. {
  16. Rune unget[3];
  17. int nunget;
  18. Biobuf *b;
  19. Rune *p;
  20. Rune *ep;
  21. Rune *s;
  22. int lineno;
  23. Rune *name;
  24. Istack *next;
  25. void (*fn)(void);
  26. };
  27. Istack *istack;
  28. Istack *ibottom;
  29. static void
  30. setname(void)
  31. {
  32. Rune *r, *p;
  33. if(istack == nil || istack->name == nil)
  34. return;
  35. _nr(L(".F"), istack->name);
  36. r = erunestrdup(istack->name);
  37. p = runestrchr(r, '.');
  38. if(p)
  39. *p = 0;
  40. _nr(L(".B"), r);
  41. free(r);
  42. }
  43. static void
  44. ipush(Istack *is)
  45. {
  46. if(istack == nil)
  47. ibottom = is;
  48. else
  49. is->next = istack;
  50. istack = is;
  51. setname();
  52. }
  53. static void
  54. iqueue(Istack *is)
  55. {
  56. if(ibottom == nil){
  57. istack = is;
  58. setname();
  59. }else
  60. ibottom->next = is;
  61. ibottom = is;
  62. }
  63. int
  64. _inputfile(Rune *s, void (*push)(Istack*))
  65. {
  66. Istack *is;
  67. Biobuf *b;
  68. char *t;
  69. t = esmprint("%S", s);
  70. if((b = Bopen(t, OREAD)) == nil){
  71. free(t);
  72. fprint(2, "%s: open %S: %r\n", argv0, s);
  73. return -1;
  74. }
  75. free(t);
  76. is = emalloc(sizeof *is);
  77. is->b = b;
  78. is->name = erunestrdup(s);
  79. is->lineno = 1;
  80. push(is);
  81. return 0;
  82. }
  83. int
  84. pushinputfile(Rune *s)
  85. {
  86. return _inputfile(s, ipush);
  87. }
  88. int
  89. queueinputfile(Rune *s)
  90. {
  91. return _inputfile(s, iqueue);
  92. }
  93. int
  94. _inputstdin(void (*push)(Istack*))
  95. {
  96. Biobuf *b;
  97. Istack *is;
  98. if((b = Bopen("/dev/null", OREAD)) == nil){
  99. fprint(2, "%s: open /dev/null: %r\n", argv0);
  100. return -1;
  101. }
  102. dup(0, b->fid);
  103. is = emalloc(sizeof *is);
  104. is->b = b;
  105. is->name = erunestrdup(L("stdin"));
  106. is->lineno = 1;
  107. push(is);
  108. return 0;
  109. }
  110. int
  111. pushstdin(void)
  112. {
  113. return _inputstdin(ipush);
  114. }
  115. int
  116. queuestdin(void)
  117. {
  118. return _inputstdin(iqueue);
  119. }
  120. void
  121. _inputstring(Rune *s, void (*push)(Istack*))
  122. {
  123. Istack *is;
  124. is = emalloc(sizeof *is);
  125. is->s = erunestrdup(s);
  126. is->p = is->s;
  127. is->ep = is->p+runestrlen(is->p);
  128. push(is);
  129. }
  130. void
  131. pushinputstring(Rune *s)
  132. {
  133. _inputstring(s, ipush);
  134. }
  135. void
  136. inputnotify(void (*fn)(void))
  137. {
  138. if(istack)
  139. istack->fn = fn;
  140. }
  141. int
  142. popinput(void)
  143. {
  144. Istack *is;
  145. is = istack;
  146. if(is == nil)
  147. return 0;
  148. istack = istack->next;
  149. if(is->b)
  150. Bterm(is->b);
  151. free(is->s);
  152. free(is->name);
  153. if(is->fn)
  154. is->fn();
  155. free(is);
  156. setname();
  157. return 1;
  158. }
  159. int
  160. getrune(void)
  161. {
  162. Rune r;
  163. int c;
  164. top:
  165. if(istack == nil)
  166. return -1;
  167. if(istack->nunget)
  168. return istack->unget[--istack->nunget];
  169. else if(istack->p){
  170. if(istack->p >= istack->ep){
  171. popinput();
  172. goto top;
  173. }
  174. r = *istack->p++;
  175. }else if(istack->b){
  176. if((c = Bgetrune(istack->b)) < 0){
  177. popinput();
  178. goto top;
  179. }
  180. r = c;
  181. }else{
  182. r = 0;
  183. sysfatal("getrune - can't happen");
  184. }
  185. if(r == '\n')
  186. istack->lineno++;
  187. return r;
  188. }
  189. void
  190. ungetrune(Rune r)
  191. {
  192. if(istack == nil || istack->nunget >= nelem(istack->unget))
  193. pushinputstring(L(""));
  194. istack->unget[istack->nunget++] = r;
  195. }
  196. int
  197. linefmt(Fmt *f)
  198. {
  199. Istack *is;
  200. for(is=istack; is && !is->b; is=is->next)
  201. ;
  202. if(is)
  203. return fmtprint(f, "%S:%d", is->name, is->lineno);
  204. else
  205. return fmtprint(f, "<no input>");
  206. }
  207. void
  208. setlinenumber(Rune *s, int n)
  209. {
  210. Istack *is;
  211. for(is=istack; is && !is->name; is=is->next)
  212. ;
  213. if(is){
  214. if(s){
  215. free(is->name);
  216. is->name = erunestrdup(s);
  217. }
  218. is->lineno = n;
  219. }
  220. }