home *** CD-ROM | disk | FTP | other *** search
/ minnie.tuhs.org / unixen.tar / unixen / PDP-11 / Distributions / ucb / spencer_2bsd.tar.gz / 2bsd.tar / src / ex / ex_addr.c < prev    next >
C/C++ Source or Header  |  1980-02-17  |  5KB  |  274 lines

  1. /* Copyright (c) 1979 Regents of the University of California */
  2. #include "ex.h"
  3. #include "ex_re.h"
  4.  
  5. /*
  6.  * Routines for address parsing and assignment and checking of address bounds
  7.  * in command mode.  The routine address is called from ex_cmds.c
  8.  * to parse each component of a command (terminated by , ; or the beginning
  9.  * of the command itself.  It is also called by the scanning routine
  10.  * in ex_voperate.c from within open/visual.
  11.  *
  12.  * Other routines here manipulate the externals addr1 and addr2.
  13.  * These are the first and last lines for the current command.
  14.  *
  15.  * The variable bigmove remembers whether a non-local glitch of . was
  16.  * involved in an address expression, so we can set the previous context
  17.  * mark '' when such a motion occurs.
  18.  */
  19.  
  20. static    bool bigmove;
  21.  
  22. /*
  23.  * Set up addr1 and addr2 for commands whose default address is dot.
  24.  */
  25. setdot()
  26. {
  27.  
  28.     setdot1();
  29.     if (bigmove)
  30.         markDOT();
  31. }
  32.  
  33. /*
  34.  * Call setdot1 to set up default addresses without ever
  35.  * setting the previous context mark.
  36.  */
  37. setdot1()
  38. {
  39.  
  40.     if (addr2 == 0)
  41.         addr1 = addr2 = dot;
  42.     if (addr1 > addr2) {
  43.         notempty();
  44.         error("Addr1 > addr2|First address exceeds second");
  45.     }
  46. }
  47.  
  48. /*
  49.  * Ex allows you to say
  50.  *    delete 5
  51.  * to delete 5 lines, etc.
  52.  * Such nonsense is implemented by setcount.
  53.  */
  54. setcount()
  55. {
  56.     register int cnt;
  57.  
  58.     pastwh();
  59.     if (!isdigit(peekchar())) {
  60.         setdot();
  61.         return;
  62.     }
  63.     addr1 = addr2;
  64.     setdot();
  65.     cnt = getnum();
  66.     if (cnt <= 0)
  67.         error("Bad count|Nonzero count required");
  68.     addr2 += cnt - 1;
  69.     if (addr2 > dol)
  70.         addr2 = dol;
  71.     nonzero();
  72. }
  73.  
  74. /*
  75.  * Parse a number out of the command input stream.
  76.  */
  77. getnum()
  78. {
  79.     register int cnt;
  80.  
  81.     for (cnt = 0; isdigit(peekcd());)
  82.         cnt = cnt * 10 + getchar() - '0';
  83.     return (cnt);
  84. }
  85.  
  86. /*
  87.  * Set the default addresses for commands which use the whole
  88.  * buffer as default, notably write.
  89.  */
  90. setall()
  91. {
  92.  
  93.     if (addr2 == 0) {
  94.         addr1 = one;
  95.         addr2 = dol;
  96.         if (dol == zero) {
  97.             dot = zero;
  98.             return;
  99.         }
  100.     }
  101.     /*
  102.      * Don't want to set previous context mark so use setdot1().
  103.      */
  104.     setdot1();
  105. }
  106.  
  107. /*
  108.  * No address allowed on, e.g. the file command.
  109.  */
  110. setnoaddr()
  111. {
  112.  
  113.     if (addr2 != 0)
  114.         error("No address allowed@on this command");
  115. }
  116.  
  117. /*
  118.  * Parse an address.
  119.  * Just about any sequence of address characters is legal.
  120.  *
  121.  * If you are tricky you can use this routine and the = command
  122.  * to do simple addition and subtraction of cardinals less
  123.  * than the number of lines in the file.
  124.  */
  125. line *
  126. address()
  127. {
  128.     register line *addr;
  129.     register int offset, c;
  130.     short lastsign;
  131.  
  132.     bigmove = 0;
  133.     lastsign = 0;
  134.     offset = 0;
  135.     addr = 0;
  136.     for (;;) {
  137.         if (isdigit(peekcd())) {
  138.             if (addr == 0) {
  139.                 addr = zero;
  140.                 bigmove = 1;
  141.             }
  142.             loc1 = 0;
  143.             addr += offset;
  144.             offset = getnum();
  145.             if (lastsign >= 0)
  146.                 addr += offset;
  147.             else
  148.                 addr -= offset;
  149.             lastsign = 0;
  150.             offset = 0;
  151.         }
  152.         switch (c = getcd()) {
  153.  
  154.         case '?':
  155.         case '/':
  156.         case '$':
  157.         case '\'':
  158.         case '\\':
  159.             bigmove++;
  160.         case '.':
  161.             if (addr || offset)
  162.                 error("Badly formed address");
  163.         }
  164.         offset += lastsign;
  165.         lastsign = 0;
  166.         switch (c) {
  167.  
  168.         case ' ':
  169.         case '\t':
  170.             continue;
  171.  
  172.         case '+':
  173.             lastsign = 1;
  174.             if (addr == 0)
  175.                 addr = dot;
  176.             continue;
  177.  
  178.         case '^':
  179.         case '-':
  180.             lastsign = -1;
  181.             if (addr == 0)
  182.                 addr = dot;
  183.             continue;
  184.  
  185.         case '\\':
  186.         case '?':
  187.         case '/':
  188.             c = compile(c, 1);
  189.             notempty();
  190.             savere(scanre);
  191.             addr = dot;
  192.             for (;;) {
  193.                 if (c == '/') {
  194.                     addr++;
  195.                     if (addr > dol) {
  196.                         if (value(WRAPSCAN) == 0)
  197.                             error("No match to BOTTOM|Address search hit BOTTOM without matching pattern");
  198.                         addr = zero;
  199.                     }
  200.                 } else {
  201.                     addr--;
  202.                     if (addr < zero) {
  203.                         if (value(WRAPSCAN) == 0)
  204.                             error("No match to TOP|Address search hit TOP without matching pattern");
  205.                         addr = dol;
  206.                     }
  207.                 }
  208.                 if (execute(0, addr))
  209.                     break;
  210.                 if (addr == dot)
  211.                     error("Fail|Pattern not found");
  212.             }
  213.             continue;
  214.  
  215.         case '$':
  216.             addr = dol;
  217.             continue;
  218.  
  219.         case '.':
  220.             addr = dot;
  221.             continue;
  222.  
  223.         case '\'':
  224.             c = markreg(getchar());
  225.             if (c == 0)
  226.                 error("Marks are ' and a-z");
  227.             addr = getmark(c);
  228.             if (addr == 0)
  229.                 error("Undefined mark@referenced");
  230.             break;
  231.  
  232.         default:
  233.             ungetchar(c);
  234.             if (offset) {
  235.                 if (addr == 0)
  236.                     addr = dot;
  237.                 addr += offset;
  238.                 loc1 = 0;
  239.             }
  240.             if (addr == 0) {
  241.                 bigmove = 0;
  242.                 return (0);
  243.             }
  244.             if (addr != zero)
  245.                 notempty();
  246.             addr += lastsign;
  247.             if (addr < zero)
  248.                 error("Negative address@- first buffer line is 1");
  249.             if (addr > dol)
  250.                 error("Not that many lines@in buffer");
  251.             return (addr);
  252.         }
  253.     }
  254. }
  255.  
  256. /*
  257.  * Abbreviations to make code smaller
  258.  * Left over from squashing ex version 1.1 into
  259.  * 11/34's and 11/40's.
  260.  */
  261. setCNL()
  262. {
  263.  
  264.     setcount();
  265.     newline();
  266. }
  267.  
  268. setNAEOL()
  269. {
  270.  
  271.     setnoaddr();
  272.     eol();
  273. }
  274.