static ScmObj conv_name(int dir, ScmPort *remote, const char *from, const char *to) { ScmObj out = Scm_MakeOutputStringPort(TRUE); Scm_Printf(SCM_PORT(out), "[conv(%s->%s) %s %S]", from, to, (dir == SCM_PORT_INPUT? "from" : "to"), Scm_PortName(remote)); return Scm_GetOutputStringUnsafe(SCM_PORT(out), 0); }
/* * Scm_WriteLimited - Write to limited length. * * Characters exceeding WIDTH are truncated. * If the output fits within WIDTH, # of characters actually written * is returned. Othewise, -1 is returned. * * Currently this API is only used from Scm_Printf, for 'format' has been * moved to libfmt.scm. I don't like the way this is implemented and would * like to share this with libfmt.scm eventually. */ int Scm_WriteLimited(ScmObj obj, ScmObj p, int mode, int width) { if (!SCM_OPORTP(p)) { Scm_Error("output port required, but got %S", p); } ScmPort *port = SCM_PORT(p); /* The walk pass does not produce any output, so we don't bother to create an intermediate string port. */ if (PORT_LOCK_OWNER_P(port, Scm_VM()) && PORT_WALKER_P(port)) { SCM_ASSERT(PORT_RECURSIVE_P(port)); write_walk(obj, port); return 0; /* doesn't really matter */ } ScmObj out = Scm_MakeOutputStringPort(TRUE); SCM_PORT(out)->writeState = SCM_PORT(port)->writeState; ScmWriteContext ctx; write_context_init(&ctx, mode, 0, width); /* We don't need to lock 'out', nor clean it up, for it is private. */ /* This part is a bit confusing - we only need to call write_ss if we're at the toplevel call. */ if (PORT_RECURSIVE_P(SCM_PORT(port))) { write_rec(obj, SCM_PORT(out), &ctx); } else if (WRITER_NEED_2PASS(&ctx)) { write_ss(obj, SCM_PORT(out), &ctx); } else { write_rec(obj, SCM_PORT(out), &ctx); } ScmString *str = SCM_STRING(Scm_GetOutputString(SCM_PORT(out), 0)); int nc = SCM_STRING_BODY_LENGTH(SCM_STRING_BODY(str)); if (nc > width) { ScmObj sub = Scm_Substring(str, 0, width, FALSE); SCM_PUTS(sub, port); /* this locks port */ return -1; } else { SCM_PUTS(str, port); /* this locks port */ return nc; } }