lex.c 2.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133
  1. #include "mk.h"
  2. static int bquote(Biobuf*, Bufblock*);
  3. /*
  4. * Assemble a line skipping blank lines, comments, and eliding
  5. * escaped newlines
  6. */
  7. int
  8. assline(Biobuf *bp, Bufblock *buf)
  9. {
  10. int c;
  11. int lastc;
  12. buf->current=buf->start;
  13. while ((c = nextrune(bp, 1)) >= 0){
  14. switch(c)
  15. {
  16. case '\r': /* consumes CRs for Win95 */
  17. continue;
  18. case '\n':
  19. if (buf->current != buf->start) {
  20. insert(buf, 0);
  21. return 1;
  22. }
  23. break; /* skip empty lines */
  24. case '\\':
  25. case '\'':
  26. case '"':
  27. rinsert(buf, c);
  28. if (escapetoken(bp, buf, 1, c) == 0)
  29. Exit();
  30. break;
  31. case '`':
  32. if (bquote(bp, buf) == 0)
  33. Exit();
  34. break;
  35. case '#':
  36. lastc = '#';
  37. while ((c = Bgetc(bp)) != '\n') {
  38. if (c < 0)
  39. goto eof;
  40. if(c != '\r')
  41. lastc = c;
  42. }
  43. mkinline++;
  44. if (lastc == '\\')
  45. break; /* propagate escaped newlines??*/
  46. if (buf->current != buf->start) {
  47. insert(buf, 0);
  48. return 1;
  49. }
  50. break;
  51. default:
  52. rinsert(buf, c);
  53. break;
  54. }
  55. }
  56. eof:
  57. insert(buf, 0);
  58. return *buf->start != 0;
  59. }
  60. /*
  61. * assemble a back-quoted shell command into a buffer
  62. */
  63. static int
  64. bquote(Biobuf *bp, Bufblock *buf)
  65. {
  66. int c, line, term;
  67. int start;
  68. line = mkinline;
  69. while((c = Bgetrune(bp)) == ' ' || c == '\t')
  70. ;
  71. if(c == '{'){
  72. term = '}'; /* rc style */
  73. while((c = Bgetrune(bp)) == ' ' || c == '\t')
  74. ;
  75. } else
  76. term = '`'; /* sh style */
  77. start = buf->current-buf->start;
  78. for(;c > 0; c = nextrune(bp, 0)){
  79. if(c == term){
  80. insert(buf, '\n');
  81. insert(buf,0);
  82. buf->current = buf->start+start;
  83. execinit();
  84. execsh(0, buf->current, buf, envy);
  85. return 1;
  86. }
  87. if(c == '\n')
  88. break;
  89. if(c == '\'' || c == '"' || c == '\\'){
  90. insert(buf, c);
  91. if(!escapetoken(bp, buf, 1, c))
  92. return 0;
  93. continue;
  94. }
  95. rinsert(buf, c);
  96. }
  97. SYNERR(line);
  98. fprint(2, "missing closing %c after `\n", term);
  99. return 0;
  100. }
  101. /*
  102. * get next character stripping escaped newlines
  103. * the flag specifies whether escaped newlines are to be elided or
  104. * replaced with a blank.
  105. */
  106. int
  107. nextrune(Biobuf *bp, int elide)
  108. {
  109. int c;
  110. for (;;) {
  111. c = Bgetrune(bp);
  112. if (c == '\\') {
  113. if (Bgetrune(bp) == '\n') {
  114. mkinline++;
  115. if (elide)
  116. continue;
  117. return ' ';
  118. }
  119. Bungetrune(bp);
  120. }
  121. if (c == '\n')
  122. mkinline++;
  123. return c;
  124. }
  125. }