+/*
+ * Put the given string before the current character
+ * in the current line, thus inserting it into the input stream.
+ */
+
+public insertinput (s)
+String s;
+{
+ register char *p, *q;
+ int need, avail, shift;
+
+ q = s;
+ need = strlen(q);
+ avail = curchar - &scanner_linebuf[0];
+ if (need <= avail) {
+ curchar = &scanner_linebuf[avail - need];
+ p = curchar;
+ while (*q != '\0') {
+ *p++ = *q++;
+ }
+ } else {
+ p = curchar;
+ while (*p != '\0') {
+ ++p;
+ }
+ shift = need - avail;
+ if (p + shift >= &scanner_linebuf[MAXLINESIZE]) {
+ error("alias expansion too large");
+ }
+ for (;;) {
+ *(p + shift) = *p;
+ if (p == curchar) {
+ break;
+ }
+ --p;
+ }
+ p = &scanner_linebuf[0];
+ while (*q != '\0') {
+ *p++ = *q++;
+ }
+ curchar = &scanner_linebuf[0];
+ }
+}
+
+/*
+ * Get the actuals for a macro call.
+ */
+
+private String movetochar (str, c)
+String str;
+char c;
+{
+ register char *p;
+
+ while (*p != c) {
+ if (*p == '\0') {
+ error("missing ')' in macro call");
+ } else if (*p == ')') {
+ error("not enough parameters in macro call");
+ } else if (*p == ',') {
+ error("too many parameters in macro call");
+ }
+ ++p;
+ }
+ return p;
+}
+
+private String *getactuals (n)
+integer n;
+{
+ String *a;
+ register char *p;
+ int i;
+
+ a = newarr(String, n);
+ p = curchar;
+ while (*p != '(') {
+ if (lexclass[*p] != WHITE) {
+ error("missing actuals for macro");
+ }
+ ++p;
+ }
+ ++p;
+ for (i = 0; i < n - 1; i++) {
+ a[i] = p;
+ p = movetochar(p, ',');
+ *p = '\0';
+ ++p;
+ }
+ a[n-1] = p;
+ p = movetochar(p, ')');
+ *p = '\0';
+ curchar = p + 1;
+ return a;
+}
+
+/*
+ * Do command macro expansion, assuming curchar points to the beginning
+ * of the actuals, and we are not in shell mode.
+ */
+
+private expand (pl, str)
+List pl;
+String str;
+{
+ char buf[4096], namebuf[100];
+ register char *p, *q, *r;
+ String *actual;
+ Name n;
+ integer i;
+ boolean match;
+
+ if (pl == nil) {
+ insertinput(str);
+ } else {
+ actual = getactuals(list_size(pl));
+ p = buf;
+ q = str;
+ while (*q != '\0') {
+ if (p >= &buf[4096]) {
+ error("alias expansion too large");
+ }
+ if (lexclass[*q] == ALPHA) {
+ r = namebuf;
+ do {
+ *r++ = *q++;
+ } while (isalnum(*q));
+ *r = '\0';
+ i = 0;
+ match = false;
+ foreach(Name, n, pl)
+ if (streq(ident(n), namebuf)) {
+ match = true;
+ break;
+ }
+ ++i;
+ endfor
+ if (match) {
+ r = actual[i];
+ } else {
+ r = namebuf;
+ }
+ while (*r != '\0') {
+ *p++ = *r++;
+ }
+ } else {
+ *p++ = *q++;
+ }
+ }
+ *p = '\0';
+ insertinput(buf);
+ }
+}
+