/* * Put long, in radix "r". */ static void eputl(long l, int r) { long q; if (l < 0) { eputc('-'); l = -l; } if ((q = l / r) != 0) eputl(q, r); eputc((int)(l % r) + '0'); }
/* * Put integer, in radix "r". */ static void eputi(int i, int r) { int q; if (i < 0) { eputc('-'); i = -i; } if ((q = i / r) != 0) eputi(q, r); eputc(i % r + '0'); }
/*------------------------------------------------------------------------ * echoch -- echo a character with visual and output crlf options *------------------------------------------------------------------------ */ local void echoch( char ch, /* character to echo */ struct ttycblk *typtr, /* ptr to ttytab entry */ struct uart_csreg *uptr /* address of UART's CSRs */ ) { if ((ch==TY_NEWLINE || ch==TY_RETURN) && typtr->tyecrlf) { eputc(TY_RETURN, typtr, uptr); eputc(TY_NEWLINE, typtr, uptr); } else if ( (ch<TY_BLANK||ch==0177) && typtr->tyevis) { eputc(TY_UPARROW, typtr, uptr); /* print ^x */ eputc(ch+0100, typtr, uptr); /* make it printable */ } else { eputc(ch, typtr, uptr); } }
/* * Put string. */ static void eputs(const char *s) { int c; while ((c = *s++) != '\0') eputc(c); }
void printString(char *String) { while(*String) { eputc(*String); String++; } }
int fputc(int fd, char c) { if (fd == 1) putchar(c); else if (fd == 2) eputc(c); else return write(fd, &c, 1); return 0; }
void eputc(int c) { if (c == '\n') eputc('\r'); while (!(at91_dbgu[USART_CSR / 4] & USART_CSR_TXRDY)) continue; at91_dbgu[USART_THR / 4] = c; }
/* * Put character. Watch for control characters, and for the line getting * too long. */ static void eputc(char c) { if (ttcol + 2 < ncol) { if (ISCTRL(c)) { eputc('^'); c = CCHR(c); } ttputc(c); ++ttcol; } }
int fputc(int fd, char c) { if(list_empty(&console_list)) { if(!fd) console_putc(0, c); return 0; } if (fd == 1) putchar(c); else if (fd == 2) eputc(c); else return write(fd, &c, 1); return 0; }
/*------------------------------------------------------------------------ * erase1 -- erase one character honoring erasing backspace *------------------------------------------------------------------------ */ local void erase1( struct ttycblk *typtr, /* ptr to ttytab entry */ struct uart_csreg *uptr /* address of UART's CSRs */ ) { char ch; /* character to erase */ if ( (--typtr->tyitail) < typtr->tyibuff) { typtr->tyitail += TY_IBUFLEN; } /* Pick up char to erase */ ch = *typtr->tyitail; if (typtr->tyiecho) { /* Are we echoing? */ if (ch < TY_BLANK || ch == 0177) { /* Nonprintable */ if (typtr->tyevis) { /* Visual cntl chars */ eputc(TY_BACKSP, typtr, uptr); if (typtr->tyieback) { /* erase char */ eputc(TY_BLANK, typtr, uptr); eputc(TY_BACKSP, typtr, uptr); } } eputc(TY_BACKSP, typtr, uptr);/* bypass up arrow*/ if (typtr->tyieback) { eputc(TY_BLANK, typtr, uptr); eputc(TY_BACKSP, typtr, uptr); } } else { /* A normal character that is printable */ eputc(TY_BACKSP, typtr, uptr); if (typtr->tyieback) { /* erase the character */ eputc(TY_BLANK, typtr, uptr); eputc(TY_BACKSP, typtr, uptr); } } } return; }
/* * Printf style formatting. This is called by both "ewprintf" and "ereply" * to provide formatting services to their clients. The move to the start * of the echo line, and the erase to the end of the echo line, is done by * the caller. * %c prints the "name" of the supplied character. * %k prints the name of the current key (and takes no arguments). * %d prints a decimal integer * %o prints an octal integer * %p prints a pointer * %s prints a string * %ld prints a long word * Anything else is echoed verbatim */ static void eformat(const char *fp, va_list ap) { char kname[NKNAME], tmp[100], *cp; int c; while ((c = *fp++) != '\0') { if (c != '%') eputc(c); else { c = *fp++; switch (c) { case 'c': getkeyname(kname, sizeof(kname), va_arg(ap, int)); eputs(kname); break; case 'k': for (cp = kname, c = 0; c < key.k_count; c++) { if (c) *cp++ = ' '; cp = getkeyname(cp, sizeof(kname) - (cp - kname) - 1, key.k_chars[c]); } eputs(kname); break; case 'd': eputi(va_arg(ap, int), 10); break; case 'o': eputi(va_arg(ap, int), 8); break; case 'p': snprintf(tmp, sizeof(tmp), "%p", va_arg(ap, void *)); eputs(tmp); break; case 's': eputs(va_arg(ap, char *)); break; case 'l': /* explicit longword */ c = *fp++; switch (c) { case 'd': eputl(va_arg(ap, long), 10); break; default: eputc(c); break; } break; default: eputc(c); } } } }
/* * Do completion on a list of objects. * c is SPACE, TAB, or CR * return TRUE if matched (or partially matched) * FALSE is result is ambiguous, * ABORT on error. */ static int complt(int flags, int c, char *buf, size_t nbuf, int cpos, int *nx) { struct list *lh, *lh2; struct list *wholelist = NULL; int i, nxtra, nhits, bxtra, msglen, nshown; int wflag = FALSE; char *msg; lh = lh2 = NULL; if ((flags & EFFUNC) != 0) { buf[cpos] = '\0'; wholelist = lh = complete_function_list(buf); } else if ((flags & EFBUF) != 0) { lh = &(bheadp->b_list); } else if ((flags & EFFILE) != 0) { buf[cpos] = '\0'; wholelist = lh = make_file_list(buf); } else panic("broken complt call: flags"); if (c == ' ') wflag = TRUE; else if (c != '\t' && c != CCHR('M')) panic("broken complt call: c"); nhits = 0; nxtra = HUGE; for (; lh != NULL; lh = lh->l_next) { if (memcmp(buf, lh->l_name, cpos) != 0) continue; if (nhits == 0) lh2 = lh; ++nhits; if (lh->l_name[cpos] == '\0') nxtra = -1; /* exact match */ else { bxtra = getxtra(lh, lh2, cpos, wflag); if (bxtra < nxtra) nxtra = bxtra; lh2 = lh; } } if (nhits == 0) msg = " [No match]"; else if (nhits > 1 && nxtra == 0) msg = " [Ambiguous. Ctrl-G to cancel]"; else { /* * Being lazy - ought to check length, but all things * autocompleted have known types/lengths. */ if (nxtra < 0 && nhits > 1 && c == ' ') nxtra = 1; /* ??? */ for (i = 0; i < nxtra && cpos < nbuf; ++i) { buf[cpos] = lh2->l_name[cpos]; eputc(buf[cpos++]); } /* XXX should grow nbuf */ ttflush(); free_file_list(wholelist); *nx = nxtra; if (nxtra < 0 && c != CCHR('M')) /* exact */ *nx = 0; return (TRUE); } /* * wholelist is NULL if we are doing buffers. Want to free lists * that were created for us, but not the buffer list! */ free_file_list(wholelist); /* Set up backspaces, etc., being mindful of echo line limit. */ msglen = strlen(msg); nshown = (ttcol + msglen + 2 > ncol) ? ncol - ttcol - 2 : msglen; eputs(msg); ttcol -= (i = nshown); /* update ttcol! */ while (i--) /* move back before msg */ ttputc('\b'); ttflush(); /* display to user */ i = nshown; while (i--) /* blank out on next flush */ eputc(' '); ttcol -= (i = nshown); /* update ttcol on BS's */ while (i--) ttputc('\b'); /* update ttcol again! */ *nx = nxtra; return ((nhits > 0) ? TRUE : FALSE); }
static char * veread(const char *fp, char *buf, size_t nbuf, int flag, va_list ap) { int dynbuf = (buf == NULL); int cpos, epos; /* cursor, end position in buf */ int c, i, y; int cplflag = FALSE; /* display completion list */ int cwin = FALSE; /* completion list created */ int mr = 0; /* match left arrow */ int ml = 0; /* match right arrow */ int esc = 0; /* position in esc pattern */ struct buffer *bp; /* completion list buffer */ struct mgwin *wp; /* window for compl list */ int match; /* esc match found */ int cc, rr; /* saved ttcol, ttrow */ char *ret; /* return value */ static char emptyval[] = ""; /* XXX hackish way to return err msg*/ if (inmacro) { if (dynbuf) { if ((buf = malloc(maclcur->l_used + 1)) == NULL) return (NULL); } else if (maclcur->l_used >= nbuf) return (NULL); bcopy(maclcur->l_text, buf, maclcur->l_used); buf[maclcur->l_used] = '\0'; maclcur = maclcur->l_fp; return (buf); } epos = cpos = 0; ml = mr = esc = 0; cplflag = FALSE; if ((flag & EFNEW) != 0 || ttrow != nrow - 1) { ttcolor(CTEXT); ttmove(nrow - 1, 0); epresf = TRUE; } else eputc(' '); eformat(fp, ap); if ((flag & EFDEF) != 0) { if (buf == NULL) return (NULL); eputs(buf); epos = cpos += strlen(buf); } tteeol(); ttflush(); for (;;) { c = getkey(FALSE); if ((flag & EFAUTO) != 0 && c == CCHR('I')) { if (cplflag == TRUE) { complt_list(flag, buf, cpos); cwin = TRUE; } else if (complt(flag, c, buf, nbuf, epos, &i) == TRUE) { cplflag = TRUE; epos += i; cpos = epos; } continue; } cplflag = FALSE; if (esc > 0) { /* ESC sequence started */ match = 0; if (ml == esc && key_left[ml] && c == key_left[ml]) { match++; if (key_left[++ml] == '\0') { c = CCHR('B'); esc = 0; } } if (mr == esc && key_right[mr] && c == key_right[mr]) { match++; if (key_right[++mr] == '\0') { c = CCHR('F'); esc = 0; } } if (match == 0) { esc = 0; continue; /* hack. how do we know esc pattern is done? */ } if (esc > 0) { esc++; continue; } } switch (c) { case CCHR('A'): /* start of line */ while (cpos > 0) { if (ISCTRL(buf[--cpos]) != FALSE) { ttputc('\b'); --ttcol; } ttputc('\b'); --ttcol; } ttflush(); break; case CCHR('D'): if (cpos != epos) { tteeol(); epos--; rr = ttrow; cc = ttcol; for (i = cpos; i < epos; i++) { buf[i] = buf[i + 1]; eputc(buf[i]); } ttmove(rr, cc); ttflush(); } break; case CCHR('E'): /* end of line */ while (cpos < epos) { eputc(buf[cpos++]); } ttflush(); break; case CCHR('B'): /* back */ if (cpos > 0) { if (ISCTRL(buf[--cpos]) != FALSE) { ttputc('\b'); --ttcol; } ttputc('\b'); --ttcol; ttflush(); } break; case CCHR('F'): /* forw */ if (cpos < epos) { eputc(buf[cpos++]); ttflush(); } break; case CCHR('Y'): /* yank from kill buffer */ i = 0; while ((y = kremove(i++)) >= 0 && y != '\n') { int t; if (dynbuf && epos + 1 >= nbuf) { void *newp; size_t newsize = epos + epos + 16; if ((newp = realloc(buf, newsize)) == NULL) goto memfail; buf = newp; nbuf = newsize; } if (!dynbuf && epos + 1 >= nbuf) { ewprintf("Line too long"); return (emptyval); } for (t = epos; t > cpos; t--) buf[t] = buf[t - 1]; buf[cpos++] = (char)y; epos++; eputc((char)y); cc = ttcol; rr = ttrow; for (t = cpos; t < epos; t++) eputc(buf[t]); ttmove(rr, cc); } ttflush(); break; case CCHR('K'): /* copy here-EOL to kill buffer */ kdelete(); for (i = cpos; i < epos; i++) kinsert(buf[i], KFORW); tteeol(); epos = cpos; ttflush(); break; case CCHR('['): ml = mr = esc = 1; break; case CCHR('J'): c = CCHR('M'); /* FALLTHROUGH */ case CCHR('M'): /* return, done */ /* if there's nothing in the minibuffer, abort */ if (epos == 0 && !(flag & EFNUL)) { (void)ctrlg(FFRAND, 0); ttflush(); return (NULL); } if ((flag & EFFUNC) != 0) { if (complt(flag, c, buf, nbuf, epos, &i) == FALSE) continue; if (i > 0) epos += i; } buf[epos] = '\0'; if ((flag & EFCR) != 0) { ttputc(CCHR('M')); ttflush(); } if (macrodef) { struct line *lp; if ((lp = lalloc(cpos)) == NULL) goto memfail; lp->l_fp = maclcur->l_fp; maclcur->l_fp = lp; lp->l_bp = maclcur; maclcur = lp; bcopy(buf, lp->l_text, cpos); } ret = buf; goto done; case CCHR('G'): /* bell, abort */ eputc(CCHR('G')); (void)ctrlg(FFRAND, 0); ttflush(); ret = NULL; goto done; case CCHR('H'): /* rubout, erase */ case CCHR('?'): if (cpos != 0) { y = buf[--cpos]; epos--; ttputc('\b'); ttcol--; if (ISCTRL(y) != FALSE) { ttputc('\b'); ttcol--; } rr = ttrow; cc = ttcol; for (i = cpos; i < epos; i++) { buf[i] = buf[i + 1]; eputc(buf[i]); } ttputc(' '); if (ISCTRL(y) != FALSE) { ttputc(' '); ttputc('\b'); } ttputc('\b'); ttmove(rr, cc); ttflush(); } break; case CCHR('X'): /* kill line */ case CCHR('U'): while (cpos != 0) { ttputc('\b'); ttputc(' '); ttputc('\b'); --ttcol; if (ISCTRL(buf[--cpos]) != FALSE) { ttputc('\b'); ttputc(' '); ttputc('\b'); --ttcol; } epos--; } ttflush(); break; case CCHR('W'): /* kill to beginning of word */ while ((cpos > 0) && !ISWORD(buf[cpos - 1])) { ttputc('\b'); ttputc(' '); ttputc('\b'); --ttcol; if (ISCTRL(buf[--cpos]) != FALSE) { ttputc('\b'); ttputc(' '); ttputc('\b'); --ttcol; } epos--; } while ((cpos > 0) && ISWORD(buf[cpos - 1])) { ttputc('\b'); ttputc(' '); ttputc('\b'); --ttcol; if (ISCTRL(buf[--cpos]) != FALSE) { ttputc('\b'); ttputc(' '); ttputc('\b'); --ttcol; } epos--; } ttflush(); break; case CCHR('\\'): case CCHR('Q'): /* quote next */ c = getkey(FALSE); /* FALLTHROUGH */ default: if (dynbuf && epos + 1 >= nbuf) { void *newp; size_t newsize = epos + epos + 16; if ((newp = realloc(buf, newsize)) == NULL) goto memfail; buf = newp; nbuf = newsize; } if (!dynbuf && epos + 1 >= nbuf) { ewprintf("Line too long"); return (emptyval); } for (i = epos; i > cpos; i--) buf[i] = buf[i - 1]; buf[cpos++] = (char)c; epos++; eputc((char)c); cc = ttcol; rr = ttrow; for (i = cpos; i < epos; i++) eputc(buf[i]); ttmove(rr, cc); ttflush(); } } done: if (cwin == TRUE) { /* blow away cpltion window */ bp = bfind("*Completions*", TRUE); if ((wp = popbuf(bp, WEPHEM)) != NULL) { if (wp->w_flag & WEPHEM) { curwp = wp; delwind(FFRAND, 1); } else { killbuffer(bp); } } } return (ret); memfail: if (dynbuf && buf) free(buf); ewprintf("Out of memory"); return (emptyval); }
/*------------------------------------------------------------------------ * ttyInter_in -- handle one arriving char (interrupts disabled) *------------------------------------------------------------------------ */ void ttyInter_in ( struct ttycblk *typtr, /* ptr to ttytab entry */ struct uart_csreg *uptr /* address of UART's CSRs */ ) { char ch; /* next char from device */ int32 avail; /* chars available in buffer */ ch = uptr->buffer; /* extract char. from device */ /* Compute chars available */ avail = semcount(typtr->tyisem); if (avail < 0) { /* one or more processes waiting*/ avail = 0; } /* Handle raw mode */ if (typtr->tyimode == TY_IMRAW) { if (avail >= TY_IBUFLEN) { /* no space => ignore input */ return; } /* Place char in buffer with no editing */ *typtr->tyitail++ = ch; /* Wrap buffer pointer */ if (typtr->tyitail >= &typtr->tyibuff[TY_IBUFLEN]) { typtr->tyitail = typtr->tyibuff; } /* Signal input semaphore and return */ signal(typtr->tyisem); return; } /* Handle cooked and cbreak modes (common part) */ if ( (ch == TY_RETURN) && typtr->tyicrlf ) { ch = TY_NEWLINE; } /* If flow control is in effect, handle ^S and ^Q */ if (typtr->tyoflow) { if (ch == typtr->tyostart) { /* ^Q starts output */ typtr->tyoheld = FALSE; ttyKickOut(typtr, uptr); return; } else if (ch == typtr->tyostop) { /* ^S stops output */ typtr->tyoheld = TRUE; return; } } typtr->tyoheld = FALSE; /* Any other char starts output */ if (typtr->tyimode == TY_IMCBREAK) { /* Just cbreak mode */ /* If input buffer is full, send bell to user */ if (avail >= TY_IBUFLEN) { eputc(typtr->tyifullc, typtr, uptr); } else { /* Input buffer has space for this char */ *typtr->tyitail++ = ch; /* Wrap around buffer */ if (typtr->tyitail>=&typtr->tyibuff[TY_IBUFLEN]) { typtr->tyitail = typtr->tyibuff; } if (typtr->tyiecho) { /* are we echoing chars?*/ echoch(ch, typtr, uptr); } } return; } else { /* Just cooked mode (see common code above) */ /* Line kill character arrives - kill entire line */ if (ch == typtr->tyikillc && typtr->tyikill) { typtr->tyitail -= typtr->tyicursor; if (typtr->tyitail < typtr->tyibuff) { typtr->tyihead += TY_IBUFLEN; } typtr->tyicursor = 0; eputc(TY_RETURN, typtr, uptr); eputc(TY_NEWLINE, typtr, uptr); return; } /* Erase (backspace) character */ if ( (ch == typtr->tyierasec) && typtr->tyierase) { if (typtr->tyicursor > 0) { typtr->tyicursor--; erase1(typtr, uptr); } return; } /* End of line */ if ( (ch == TY_NEWLINE) || (ch == TY_RETURN) ) { if (typtr->tyiecho) { echoch(ch, typtr, uptr); } *typtr->tyitail++ = ch; if (typtr->tyitail>=&typtr->tyibuff[TY_IBUFLEN]) { typtr->tyitail = typtr->tyibuff; } /* Make entire line (plus \n or \r) available */ signaln(typtr->tyisem, typtr->tyicursor + 1); typtr->tyicursor = 0; /* Reset for next line */ return; } /* Character to be placed in buffer - send bell if */ /* buffer has overflowed */ avail = semcount(typtr->tyisem); if (avail < 0) { avail = 0; } if ((avail + typtr->tyicursor) >= TY_IBUFLEN-1) { eputc(typtr->tyifullc, typtr, uptr); return; } /* EOF character: recognize at beginning of line, but */ /* print and ignore otherwise. */ if (ch == typtr->tyeofch && typtr->tyeof) { if (typtr->tyiecho) { echoch(ch, typtr, uptr); } if (typtr->tyicursor != 0) { return; } *typtr->tyitail++ = ch; signal(typtr->tyisem); return; } /* Echo the character */ if (typtr->tyiecho) { echoch(ch, typtr, uptr); } /* Insert character in the input buffer */ typtr->tyicursor++; *typtr->tyitail++ = ch; /* Wrap around if needed */ if (typtr->tyitail >= &typtr->tyibuff[TY_IBUFLEN]) { typtr->tyitail = typtr->tyibuff; } return; } }