Further work on print; still not working properly.

This commit is contained in:
Simon Brooke 2026-04-18 17:20:19 +01:00
parent 9a0f186f29
commit 0e8712a076

View file

@ -11,8 +11,8 @@
* Licensed under GPL version 2.0, or, at your option, any later version. * Licensed under GPL version 2.0, or, at your option, any later version.
*/ */
#include <stdbool.h>
#include <ctype.h> #include <ctype.h>
#include <stdbool.h>
#include <stdint.h> #include <stdint.h>
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
@ -43,58 +43,78 @@
#include "ops/truth.h" #include "ops/truth.h"
struct pso_pointer in_write( struct pso_pointer p, URL_FILE * output, struct pso_pointer in_write(struct pso_pointer p, URL_FILE *output,
bool escape ); bool escape);
struct pso_pointer print_string_like_thing( struct pso_pointer p, /**
URL_FILE *output, bool escape ) { * @brief write this character `wc` to this `output` stream, escaping it if
switch ( get_tag_value( p ) ) { * 1. `escape` is true; and
case KEYTV: * 2. it is a character which the reader would otherwise not cope with.
url_fputwc( L':', output ); *
break; * TODO: this does not yet even nearly cope with all the possible special
case STRINGTV: * cases.
if ( !escape ) */
url_fputwc( L'"', output ); void write_char( wchar_t wc, URL_FILE * output, bool escape) {
break; if (escape && !iswprint(wc)) {
} url_fwprintf(output, L"\\%04x", wc);
// url_fputwc(L'\\', output);
if ( keywordp( p ) || stringp( p ) || symbolp( p ) ) { } else {
for ( struct pso_pointer cursor = p; !nilp( cursor ); url_fputwc(wc, output);
cursor = pointer_to_object( cursor )->payload.string.cdr ) {
url_fputwc( pointer_to_object( cursor )->payload.character.
character, output );
}
}
if ( stringp( p ) ) {
if ( !escape )
url_fputwc( L'"', output );
} }
} }
struct pso_pointer print_list_content( struct pso_pointer p, URL_FILE *output,
bool escape ) { struct pso_pointer print_string_like_thing(struct pso_pointer p,
URL_FILE *output, bool escape) {
switch (get_tag_value(p)) {
case KEYTV:
url_fputwc(L':', output);
break;
case STRINGTV:
if (escape)
url_fputwc(L'"', output);
break;
}
if (keywordp(p) || stringp(p) || symbolp(p)) {
for (struct pso_pointer cursor = p; !nilp(cursor);
cursor = pointer_to_object(cursor)->payload.string.cdr) {
wchar_t wc = pointer_to_object(cursor)->payload.string.character;
write_char( wc, output, escape);
}
}
if (stringp(p)) {
if (escape)
url_fputwc(L'"', output);
}
return p;
}
struct pso_pointer write_list_content(struct pso_pointer p, URL_FILE *output,
bool escape) {
struct pso_pointer result = nil; struct pso_pointer result = nil;
if ( consp( p ) ) { if (consp(p)) {
for ( ; consp( p ); p = c_cdr( p ) ) { for (; consp(p); p = c_cdr(p)) {
struct pso2 *object = pointer_to_object( p ); struct pso2 *object = pointer_to_object(p);
result = in_write( object->payload.cons.car, output, escape ); result = in_write(object->payload.cons.car, output, escape);
if ( exceptionp( result ) ) if (exceptionp(result))
break; break;
switch ( get_tag_value( object->payload.cons.cdr ) ) { switch (get_tag_value(object->payload.cons.cdr)) {
case NILTV: case NILTV:
break; break;
case CONSTV: case CONSTV:
url_fputwc( L' ', output ); url_fputwc(L' ', output);
break; break;
default: default:
url_fputws( L" . ", output ); url_fputws(L" . ", output);
result = result = in_write(object->payload.cons.cdr, output, escape);
in_write( object->payload.cons.cdr, output, escape );
} }
} }
} else { } else {
@ -114,43 +134,43 @@ struct pso_pointer print_list_content( struct pso_pointer p, URL_FILE *output,
* reader; otherwise, print it appropriately for human readers. * reader; otherwise, print it appropriately for human readers.
* @return p on success, exception on failure. * @return p on success, exception on failure.
*/ */
struct pso_pointer in_write( struct pso_pointer p, URL_FILE *output, struct pso_pointer in_write(struct pso_pointer p, URL_FILE *output,
bool escape ) { bool escape) {
struct pso2 *object = pointer_to_object( p ); struct pso2 *object = pointer_to_object(p);
struct pso_pointer result = nil; struct pso_pointer result = nil;
if ( object != NULL ) { if (object != NULL) {
uint32_t v = get_tag_value( p ); uint32_t v = get_tag_value(p);
switch ( v ) { switch (v) {
case CHARACTERTV: case CHARACTERTV:
url_fputwc( object->payload.character.character, output ); write_char(object->payload.character.character, output, escape);
break; break;
case CONSTV: case CONSTV:
url_fputwc( L'(', output ); url_fputwc(L'(', output);
result = print_list_content( p, output, escape ); result = write_list_content(p, output, escape);
url_fputwc( L')', output ); url_fputwc(L')', output);
break; break;
case INTEGERTV: case INTEGERTV:
url_fwprintf( output, L"%d", url_fwprintf(output, L"%d",
( int64_t ) ( object->payload.integer.value ) ); (int64_t)(object->payload.integer.value));
break; break;
case KEYTV: case KEYTV:
case STRINGTV: case STRINGTV:
case SYMBOLTV: case SYMBOLTV:
print_string_like_thing( p, output, escape ); print_string_like_thing(p, output, escape);
break; break;
case NILTV: case NILTV:
url_fputws( L"nil", output ); url_fputws(L"nil", output);
break; break;
case READTV: case READTV:
case WRITETV: case WRITETV:
url_fwprintf( output, L"<%s stream: ", url_fwprintf(output, L"<%s stream: ",
v == READTV ? "read" : "write" ); v == READTV ? "read" : "write");
in_write( object->payload.stream.meta, output, escape ); in_write(object->payload.stream.meta, output, escape);
url_fputwc( L'>', output ); url_fputwc(L'>', output);
break; break;
case TRUETV: case TRUETV:
url_fputwc( L't', output ); url_fputwc(L't', output);
break; break;
default: default:
// TODO: return exception // TODO: return exception
@ -174,29 +194,28 @@ struct pso_pointer in_write( struct pso_pointer p, URL_FILE *output,
* @param nl_after if true, print a newline *after* printing `p`; else a space. * @param nl_after if true, print a newline *after* printing `p`; else a space.
* @return p on success, exception on failure. * @return p on success, exception on failure.
*/ */
struct pso_pointer write( struct pso_pointer p, struct pso_pointer stream, struct pso_pointer write(struct pso_pointer p, struct pso_pointer stream,
bool escape, bool nl_before, bool nl_after ) { bool escape, bool nl_before, bool nl_after) {
struct pso_pointer result = p; struct pso_pointer result = p;
URL_FILE *output = writep( stream ) URL_FILE *output = writep(stream)
? pointer_to_object( stream )->payload.stream.stream ? pointer_to_object(stream)->payload.stream.stream
: file_to_url_file( stdout ); : file_to_url_file(stdout);
if ( writep( stream ) ) { if (writep(stream)) {
inc_ref( stream ); inc_ref(stream);
if ( nl_before ) if (nl_before)
url_fputwc( L'\n', output ); url_fputwc(L'\n', output);
result = in_write( p, output, true ); result = in_write(p, output, true);
url_fputwc( nl_after ? L'\n' : L' ', output ); url_fputwc(nl_after ? L'\n' : L' ', output);
dec_ref( stream ); dec_ref(stream);
} else { } else {
result = result = make_exception(
make_exception( c_string_to_lisp_string c_string_to_lisp_string(L"Bad write stream passed to write."), nil,
( L"Bad write stream passed to write." ), nil, nil, nil, nil);
nil );
} }
return result; return result;
@ -209,13 +228,13 @@ struct pso_pointer write( struct pso_pointer p, struct pso_pointer stream,
* @param stream if a pointer to an open write stream, print to there. * @param stream if a pointer to an open write stream, print to there.
* @return struct pso_pointer `nil`, or an exception if some erroe occurred. * @return struct pso_pointer `nil`, or an exception if some erroe occurred.
*/ */
struct pso_pointer c_print( struct pso_pointer p, struct pso_pointer stream ) { struct pso_pointer c_print(struct pso_pointer p, struct pso_pointer stream) {
return write( p, stream, true, true, false ); return write(p, stream, true, true, false);
} }
/** /**
* @brief princ is pretty much like print except things are printed `unescaped` * @brief princ is pretty much like print except things are printed `unescaped`
*/ */
struct pso_pointer c_princ( struct pso_pointer p, struct pso_pointer stream ) { struct pso_pointer c_princ(struct pso_pointer p, struct pso_pointer stream) {
return write( p, stream, false, true, false ); return write(p, stream, false, true, false);
} }