/* * puts — C99 fputs(s, stdout) + '\n'. * * Turbo-C convention: stdio's `puts` is the FAST path with NO attribute * control — backed by ESTEX PCHARS ($5C). Cursor cell attributes are * whatever ESTEX has cached (usually the shell's default). * * For coloured output use cputs() / cprintf() from . * * Implementation notes: * - PCHARS does NOT translate '\n' to CR LF, so we copy the string * into a static buffer expanding each '\n' to CR LF, then append * the trailing CR LF before the NUL. * - Avoid trailing PUTCHAR after PCHARS — empirically that sometimes * drops the next char. Embed the line ending inside the PCHARS * buffer instead. * - Strings longer than the buffer fall back to per-char putchar so * we never silently truncate. */ #include #include #define PUTS_BUF_SIZE 256 /* body bytes before CR expansion */ static char puts_buf[PUTS_BUF_SIZE + 3]; /* +3 for trailing CR LF NUL */ static void pchars(const char *s) __naked { (void)s; __asm push ix ld c, #0x5C rst #0x10 pop ix ret __endasm; } int puts(const char *s) { uint16_t n = 0; uint16_t i = 0; while (s[i] && n < PUTS_BUF_SIZE - 1) { char c = s[i++]; if (c == '\n') { puts_buf[n++] = '\r'; puts_buf[n++] = '\n'; } else { puts_buf[n++] = c; } } if (s[i]) { /* Overflow — char-by-char fallback so we never truncate. */ for (uint16_t k = 0; s[k]; k++) putchar((unsigned char)s[k]); putchar('\n'); return 0; } puts_buf[n++] = '\r'; puts_buf[n++] = '\n'; puts_buf[n] = 0; pchars(puts_buf); return 0; }