write.c revision 5dfecf96
15dfecf96Smrg/* 25dfecf96Smrg * Copyright (c) 2002 by The XFree86 Project, Inc. 35dfecf96Smrg * 45dfecf96Smrg * Permission is hereby granted, free of charge, to any person obtaining a 55dfecf96Smrg * copy of this software and associated documentation files (the "Software"), 65dfecf96Smrg * to deal in the Software without restriction, including without limitation 75dfecf96Smrg * the rights to use, copy, modify, merge, publish, distribute, sublicense, 85dfecf96Smrg * and/or sell copies of the Software, and to permit persons to whom the 95dfecf96Smrg * Software is furnished to do so, subject to the following conditions: 105dfecf96Smrg * 115dfecf96Smrg * The above copyright notice and this permission notice shall be included in 125dfecf96Smrg * all copies or substantial portions of the Software. 135dfecf96Smrg * 145dfecf96Smrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 155dfecf96Smrg * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 165dfecf96Smrg * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 175dfecf96Smrg * THE XFREE86 PROJECT BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 185dfecf96Smrg * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF 195dfecf96Smrg * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 205dfecf96Smrg * SOFTWARE. 215dfecf96Smrg * 225dfecf96Smrg * Except as contained in this notice, the name of the XFree86 Project shall 235dfecf96Smrg * not be used in advertising or otherwise to promote the sale, use or other 245dfecf96Smrg * dealings in this Software without prior written authorization from the 255dfecf96Smrg * XFree86 Project. 265dfecf96Smrg * 275dfecf96Smrg * Author: Paulo César Pereira de Andrade 285dfecf96Smrg */ 295dfecf96Smrg 305dfecf96Smrg/* $XFree86: xc/programs/xedit/lisp/write.c,v 1.31tsi Exp $ */ 315dfecf96Smrg 325dfecf96Smrg#include "lisp/write.h" 335dfecf96Smrg#include "lisp/hash.h" 345dfecf96Smrg#include <math.h> 355dfecf96Smrg#include <ctype.h> 365dfecf96Smrg 375dfecf96Smrg#define FLOAT_PREC 17 385dfecf96Smrg 395dfecf96Smrg#define UPCASE 0 405dfecf96Smrg#define DOWNCASE 1 415dfecf96Smrg#define CAPITALIZE 2 425dfecf96Smrg 435dfecf96Smrg#define INCDEPTH() \ 445dfecf96Smrg if (++info->depth > MAX_STACK_DEPTH / 2) \ 455dfecf96Smrg LispDestroy("stack overflow") 465dfecf96Smrg#define DECDEPTH() --info->depth 475dfecf96Smrg 485dfecf96Smrg/* 495dfecf96Smrg * Types 505dfecf96Smrg */ 515dfecf96Smrgtypedef struct _circle_info { 525dfecf96Smrg long circle_nth; /* nth circular list */ 535dfecf96Smrg LispObj *object; /* the circular object */ 545dfecf96Smrg} circle_info; 555dfecf96Smrg 565dfecf96Smrgtypedef struct _write_info { 575dfecf96Smrg long depth; 585dfecf96Smrg long level; /* current level */ 595dfecf96Smrg long length; /* current length */ 605dfecf96Smrg long print_level; /* *print-level* when started printing */ 615dfecf96Smrg long print_length; /* *print-length* when started printing */ 625dfecf96Smrg 635dfecf96Smrg int print_escape; 645dfecf96Smrg int print_case; 655dfecf96Smrg 665dfecf96Smrg long circle_count; 675dfecf96Smrg /* used while building circle info */ 685dfecf96Smrg LispObj **objects; 695dfecf96Smrg long num_objects; 705dfecf96Smrg /* the circular lists */ 715dfecf96Smrg circle_info *circles; 725dfecf96Smrg long num_circles; 735dfecf96Smrg} write_info; 745dfecf96Smrg 755dfecf96Smrg/* 765dfecf96Smrg * Prototypes 775dfecf96Smrg */ 785dfecf96Smrgstatic void check_stream(LispObj*, LispFile**, LispString**, int); 795dfecf96Smrgstatic void parse_double(char*, int*, double, int); 805dfecf96Smrgstatic int float_string_inc(char*, int); 815dfecf96Smrgstatic void format_integer(char*, long, int); 825dfecf96Smrgstatic int LispWriteCPointer(LispObj*, void*); 835dfecf96Smrgstatic int LispWriteCString(LispObj*, char*, long, write_info*); 845dfecf96Smrgstatic int LispDoFormatExponentialFloat(LispObj*, LispObj*, 855dfecf96Smrg int, int, int*, int, int, 865dfecf96Smrg int, int, int, int); 875dfecf96Smrg 885dfecf96Smrgstatic int LispWriteInteger(LispObj*, LispObj*); 895dfecf96Smrgstatic int LispWriteCharacter(LispObj*, LispObj*, write_info*); 905dfecf96Smrgstatic int LispWriteString(LispObj*, LispObj*, write_info*); 915dfecf96Smrgstatic int LispWriteFloat(LispObj*, LispObj*); 925dfecf96Smrgstatic int LispWriteAtom(LispObj*, LispObj*, write_info*); 935dfecf96Smrgstatic int LispDoWriteAtom(LispObj*, char*, int, int); 945dfecf96Smrgstatic int LispWriteList(LispObj*, LispObj*, write_info*, int); 955dfecf96Smrgstatic int LispWriteArray(LispObj*, LispObj*, write_info*); 965dfecf96Smrgstatic int LispWriteStruct(LispObj*, LispObj*, write_info*); 975dfecf96Smrgstatic int LispDoWriteObject(LispObj*, LispObj*, write_info*, int); 985dfecf96Smrgstatic void LispBuildCircle(LispObj*, write_info*); 995dfecf96Smrgstatic void LispDoBuildCircle(LispObj*, write_info*); 1005dfecf96Smrgstatic long LispCheckCircle(LispObj*, write_info*); 1015dfecf96Smrgstatic int LispPrintCircle(LispObj*, LispObj*, long, int*, write_info*); 1025dfecf96Smrgstatic int LispWriteAlist(LispObj*, LispArgList*, write_info*); 1035dfecf96Smrg 1045dfecf96Smrg/* 1055dfecf96Smrg * Initialization 1065dfecf96Smrg */ 1075dfecf96SmrgLispObj *Oprint_level, *Oprint_length, *Oprint_circle, 1085dfecf96Smrg *Oprint_escape, *Oprint_case; 1095dfecf96SmrgLispObj *Kupcase, *Kdowncase, *Kcapitalize; 1105dfecf96Smrg 1115dfecf96Smrg/* 1125dfecf96Smrg * Implementation 1135dfecf96Smrg */ 1145dfecf96Smrgvoid 1155dfecf96SmrgLispWriteInit(void) 1165dfecf96Smrg{ 1175dfecf96Smrg Oprint_level = STATIC_ATOM("*PRINT-LEVEL*"); 1185dfecf96Smrg LispProclaimSpecial(Oprint_level, NIL, NIL); 1195dfecf96Smrg LispExportSymbol(Oprint_level); 1205dfecf96Smrg 1215dfecf96Smrg Oprint_length = STATIC_ATOM("*PRINT-LENGTH*"); 1225dfecf96Smrg LispProclaimSpecial(Oprint_length, NIL, NIL); 1235dfecf96Smrg LispExportSymbol(Oprint_length); 1245dfecf96Smrg 1255dfecf96Smrg Oprint_circle = STATIC_ATOM("*PRINT-CIRCLE*"); 1265dfecf96Smrg LispProclaimSpecial(Oprint_circle, T, NIL); 1275dfecf96Smrg LispExportSymbol(Oprint_circle); 1285dfecf96Smrg 1295dfecf96Smrg Oprint_escape = STATIC_ATOM("*PRINT-ESCAPE*"); 1305dfecf96Smrg LispProclaimSpecial(Oprint_escape, T, NIL); 1315dfecf96Smrg LispExportSymbol(Oprint_escape); 1325dfecf96Smrg 1335dfecf96Smrg Kupcase = KEYWORD("UPCASE"); 1345dfecf96Smrg Kdowncase = KEYWORD("DOWNCASE"); 1355dfecf96Smrg Kcapitalize = KEYWORD("CAPITALIZE"); 1365dfecf96Smrg Oprint_case = STATIC_ATOM("*PRINT-CASE*"); 1375dfecf96Smrg LispProclaimSpecial(Oprint_case, Kupcase, NIL); 1385dfecf96Smrg LispExportSymbol(Oprint_case); 1395dfecf96Smrg} 1405dfecf96Smrg 1415dfecf96SmrgLispObj * 1425dfecf96SmrgLisp_FreshLine(LispBuiltin *builtin) 1435dfecf96Smrg/* 1445dfecf96Smrg fresh-line &optional output-stream 1455dfecf96Smrg */ 1465dfecf96Smrg{ 1475dfecf96Smrg LispObj *output_stream; 1485dfecf96Smrg 1495dfecf96Smrg output_stream = ARGUMENT(0); 1505dfecf96Smrg 1515dfecf96Smrg if (output_stream == UNSPEC) 1525dfecf96Smrg output_stream = NIL; 1535dfecf96Smrg else if (output_stream != NIL) { 1545dfecf96Smrg CHECK_STREAM(output_stream); 1555dfecf96Smrg } 1565dfecf96Smrg if (LispGetColumn(output_stream)) { 1575dfecf96Smrg LispWriteChar(output_stream, '\n'); 1585dfecf96Smrg if (output_stream == NIL || 1595dfecf96Smrg (output_stream->data.stream.type == LispStreamStandard && 1605dfecf96Smrg output_stream->data.stream.source.file == Stdout)) 1615dfecf96Smrg LispFflush(Stdout); 1625dfecf96Smrg return (T); 1635dfecf96Smrg } 1645dfecf96Smrg 1655dfecf96Smrg return (NIL); 1665dfecf96Smrg} 1675dfecf96Smrg 1685dfecf96SmrgLispObj * 1695dfecf96SmrgLisp_Prin1(LispBuiltin *builtin) 1705dfecf96Smrg/* 1715dfecf96Smrg prin1 object &optional output-stream 1725dfecf96Smrg */ 1735dfecf96Smrg{ 1745dfecf96Smrg LispObj *object, *output_stream; 1755dfecf96Smrg 1765dfecf96Smrg output_stream = ARGUMENT(1); 1775dfecf96Smrg object = ARGUMENT(0); 1785dfecf96Smrg 1795dfecf96Smrg if (output_stream == UNSPEC) 1805dfecf96Smrg output_stream = NIL; 1815dfecf96Smrg LispPrint(object, output_stream, 0); 1825dfecf96Smrg 1835dfecf96Smrg return (object); 1845dfecf96Smrg} 1855dfecf96Smrg 1865dfecf96SmrgLispObj * 1875dfecf96SmrgLisp_Princ(LispBuiltin *builtin) 1885dfecf96Smrg/* 1895dfecf96Smrg princ object &optional output-stream 1905dfecf96Smrg */ 1915dfecf96Smrg{ 1925dfecf96Smrg int head; 1935dfecf96Smrg LispObj *object, *output_stream; 1945dfecf96Smrg 1955dfecf96Smrg output_stream = ARGUMENT(1); 1965dfecf96Smrg object = ARGUMENT(0); 1975dfecf96Smrg 1985dfecf96Smrg if (output_stream == UNSPEC) 1995dfecf96Smrg output_stream = NIL; 2005dfecf96Smrg head = lisp__data.env.length; 2015dfecf96Smrg LispAddVar(Oprint_escape, NIL); 2025dfecf96Smrg ++lisp__data.env.head; 2035dfecf96Smrg LispPrint(object, output_stream, 0); 2045dfecf96Smrg lisp__data.env.head = lisp__data.env.length = head; 2055dfecf96Smrg 2065dfecf96Smrg return (object); 2075dfecf96Smrg} 2085dfecf96Smrg 2095dfecf96SmrgLispObj * 2105dfecf96SmrgLisp_Print(LispBuiltin *builtin) 2115dfecf96Smrg/* 2125dfecf96Smrg print object &optional output-stream 2135dfecf96Smrg */ 2145dfecf96Smrg{ 2155dfecf96Smrg LispObj *object, *output_stream; 2165dfecf96Smrg 2175dfecf96Smrg output_stream = ARGUMENT(1); 2185dfecf96Smrg object = ARGUMENT(0); 2195dfecf96Smrg 2205dfecf96Smrg if (output_stream == UNSPEC) 2215dfecf96Smrg output_stream = NIL; 2225dfecf96Smrg LispWriteChar(output_stream, '\n'); 2235dfecf96Smrg LispPrint(object, output_stream, 0); 2245dfecf96Smrg LispWriteChar(output_stream, ' '); 2255dfecf96Smrg 2265dfecf96Smrg return (object); 2275dfecf96Smrg} 2285dfecf96Smrg 2295dfecf96SmrgLispObj * 2305dfecf96SmrgLisp_Terpri(LispBuiltin *builtin) 2315dfecf96Smrg/* 2325dfecf96Smrg terpri &optional output-stream 2335dfecf96Smrg */ 2345dfecf96Smrg{ 2355dfecf96Smrg LispObj *output_stream; 2365dfecf96Smrg 2375dfecf96Smrg output_stream = ARGUMENT(0); 2385dfecf96Smrg 2395dfecf96Smrg if (output_stream == UNSPEC) 2405dfecf96Smrg output_stream = NIL; 2415dfecf96Smrg else if (output_stream != NIL) { 2425dfecf96Smrg CHECK_STREAM(output_stream); 2435dfecf96Smrg } 2445dfecf96Smrg LispWriteChar(output_stream, '\n'); 2455dfecf96Smrg if (output_stream == NIL || 2465dfecf96Smrg (output_stream->data.stream.type == LispStreamStandard && 2475dfecf96Smrg output_stream->data.stream.source.file == Stdout)) 2485dfecf96Smrg LispFflush(Stdout); 2495dfecf96Smrg 2505dfecf96Smrg return (NIL); 2515dfecf96Smrg} 2525dfecf96Smrg 2535dfecf96SmrgLispObj * 2545dfecf96SmrgLisp_Write(LispBuiltin *builtin) 2555dfecf96Smrg/* 2565dfecf96Smrg write object &key case circle escape length level lines pretty readably right-margin stream 2575dfecf96Smrg */ 2585dfecf96Smrg{ 2595dfecf96Smrg int head = lisp__data.env.length; 2605dfecf96Smrg 2615dfecf96Smrg LispObj *object, *ocase, *circle, *escape, *length, *level, *stream; 2625dfecf96Smrg 2635dfecf96Smrg stream = ARGUMENT(10); 2645dfecf96Smrg level = ARGUMENT(5); 2655dfecf96Smrg length = ARGUMENT(4); 2665dfecf96Smrg escape = ARGUMENT(3); 2675dfecf96Smrg circle = ARGUMENT(2); 2685dfecf96Smrg ocase = ARGUMENT(1); 2695dfecf96Smrg object = ARGUMENT(0); 2705dfecf96Smrg 2715dfecf96Smrg if (stream == UNSPEC) 2725dfecf96Smrg stream = NIL; 2735dfecf96Smrg else if (stream != NIL) { 2745dfecf96Smrg CHECK_STREAM(stream); 2755dfecf96Smrg } 2765dfecf96Smrg 2775dfecf96Smrg /* prepare the printer environment */ 2785dfecf96Smrg if (circle != UNSPEC) 2795dfecf96Smrg LispAddVar(Oprint_circle, circle); 2805dfecf96Smrg if (length != UNSPEC) 2815dfecf96Smrg LispAddVar(Oprint_length, length); 2825dfecf96Smrg if (level != UNSPEC) 2835dfecf96Smrg LispAddVar(Oprint_level, level); 2845dfecf96Smrg if (ocase != UNSPEC) 2855dfecf96Smrg LispAddVar(Oprint_case, ocase); 2865dfecf96Smrg if (escape != UNSPEC) 2875dfecf96Smrg LispAddVar(Oprint_escape, escape); 2885dfecf96Smrg 2895dfecf96Smrg lisp__data.env.head = lisp__data.env.length; 2905dfecf96Smrg 2915dfecf96Smrg (void)LispWriteObject(stream, object); 2925dfecf96Smrg 2935dfecf96Smrg lisp__data.env.head = lisp__data.env.length = head; 2945dfecf96Smrg 2955dfecf96Smrg return (object); 2965dfecf96Smrg} 2975dfecf96Smrg 2985dfecf96SmrgLispObj * 2995dfecf96SmrgLisp_WriteChar(LispBuiltin *builtin) 3005dfecf96Smrg/* 3015dfecf96Smrg write-char character &optional output-stream 3025dfecf96Smrg */ 3035dfecf96Smrg{ 3045dfecf96Smrg int ch; 3055dfecf96Smrg 3065dfecf96Smrg LispObj *character, *output_stream; 3075dfecf96Smrg 3085dfecf96Smrg output_stream = ARGUMENT(1); 3095dfecf96Smrg character = ARGUMENT(0); 3105dfecf96Smrg 3115dfecf96Smrg if (output_stream == UNSPEC) 3125dfecf96Smrg output_stream = NIL; 3135dfecf96Smrg CHECK_SCHAR(character); 3145dfecf96Smrg ch = SCHAR_VALUE(character); 3155dfecf96Smrg 3165dfecf96Smrg LispWriteChar(output_stream, ch); 3175dfecf96Smrg 3185dfecf96Smrg return (character); 3195dfecf96Smrg} 3205dfecf96Smrg 3215dfecf96SmrgLispObj * 3225dfecf96SmrgLisp_WriteLine(LispBuiltin *builtin) 3235dfecf96Smrg/* 3245dfecf96Smrg write-line string &optional output-stream &key start end 3255dfecf96Smrg */ 3265dfecf96Smrg{ 3275dfecf96Smrg return (LispWriteString_(builtin, 1)); 3285dfecf96Smrg} 3295dfecf96Smrg 3305dfecf96SmrgLispObj * 3315dfecf96SmrgLisp_WriteString(LispBuiltin *builtin) 3325dfecf96Smrg/* 3335dfecf96Smrg write-string string &optional output-stream &key start end 3345dfecf96Smrg */ 3355dfecf96Smrg{ 3365dfecf96Smrg return (LispWriteString_(builtin, 0)); 3375dfecf96Smrg} 3385dfecf96Smrg 3395dfecf96Smrg 3405dfecf96Smrgint 3415dfecf96SmrgLispWriteObject(LispObj *stream, LispObj *object) 3425dfecf96Smrg{ 3435dfecf96Smrg write_info info; 3445dfecf96Smrg int bytes; 3455dfecf96Smrg LispObj *level, *length, *circle, *oescape, *ocase; 3465dfecf96Smrg 3475dfecf96Smrg /* current state */ 3485dfecf96Smrg info.depth = info.level = info.length = 0; 3495dfecf96Smrg 3505dfecf96Smrg /* maximum level to descend */ 3515dfecf96Smrg level = LispGetVar(Oprint_level); 3525dfecf96Smrg if (level && INDEXP(level)) 3535dfecf96Smrg info.print_level = FIXNUM_VALUE(level); 3545dfecf96Smrg else 3555dfecf96Smrg info.print_level = -1; 3565dfecf96Smrg 3575dfecf96Smrg /* maximum list length */ 3585dfecf96Smrg length = LispGetVar(Oprint_length); 3595dfecf96Smrg if (length && INDEXP(length)) 3605dfecf96Smrg info.print_length = FIXNUM_VALUE(length); 3615dfecf96Smrg else 3625dfecf96Smrg info.print_length = -1; 3635dfecf96Smrg 3645dfecf96Smrg /* detect circular/shared objects? */ 3655dfecf96Smrg circle = LispGetVar(Oprint_circle); 3665dfecf96Smrg info.circle_count = 0; 3675dfecf96Smrg info.objects = NULL; 3685dfecf96Smrg info.num_objects = 0; 3695dfecf96Smrg info.circles = NULL; 3705dfecf96Smrg info.num_circles = 0; 3715dfecf96Smrg if (circle && circle != NIL) { 3725dfecf96Smrg LispBuildCircle(object, &info); 3735dfecf96Smrg /* free this data now */ 3745dfecf96Smrg if (info.num_objects) { 3755dfecf96Smrg LispFree(info.objects); 3765dfecf96Smrg info.num_objects = 0; 3775dfecf96Smrg } 3785dfecf96Smrg } 3795dfecf96Smrg 3805dfecf96Smrg /* escape characters and strings? */ 3815dfecf96Smrg oescape = LispGetVar(Oprint_escape); 3825dfecf96Smrg if (oescape != NULL) 3835dfecf96Smrg info.print_escape = oescape == NIL; 3845dfecf96Smrg else 3855dfecf96Smrg info.print_escape = -1; 3865dfecf96Smrg 3875dfecf96Smrg /* don't use the default case printing? */ 3885dfecf96Smrg ocase = LispGetVar(Oprint_case); 3895dfecf96Smrg if (ocase == Kdowncase) 3905dfecf96Smrg info.print_case = DOWNCASE; 3915dfecf96Smrg else if (ocase == Kcapitalize) 3925dfecf96Smrg info.print_case = CAPITALIZE; 3935dfecf96Smrg else 3945dfecf96Smrg info.print_case = UPCASE; 3955dfecf96Smrg 3965dfecf96Smrg bytes = LispDoWriteObject(stream, object, &info, 1); 3975dfecf96Smrg if (circle && circle != NIL && info.num_circles) 3985dfecf96Smrg LispFree(info.circles); 3995dfecf96Smrg 4005dfecf96Smrg return (bytes); 4015dfecf96Smrg} 4025dfecf96Smrg 4035dfecf96Smrgstatic void 4045dfecf96SmrgLispBuildCircle(LispObj *object, write_info *info) 4055dfecf96Smrg{ 4065dfecf96Smrg LispObj *list; 4075dfecf96Smrg 4085dfecf96Smrg switch (OBJECT_TYPE(object)) { 4095dfecf96Smrg case LispCons_t: 4105dfecf96Smrg LispDoBuildCircle(object, info); 4115dfecf96Smrg break; 4125dfecf96Smrg case LispArray_t: 4135dfecf96Smrg /* Currently arrays are implemented as lists, but only 4145dfecf96Smrg * the elements could/should be circular */ 4155dfecf96Smrg if (LispCheckCircle(object, info) >= 0) 4165dfecf96Smrg return; 4175dfecf96Smrg LispDoBuildCircle(object, info); 4185dfecf96Smrg for (list = object->data.array.list; 4195dfecf96Smrg CONSP(list); list = CDR(list)) 4205dfecf96Smrg LispBuildCircle(CAR(list), info); 4215dfecf96Smrg break; 4225dfecf96Smrg case LispStruct_t: 4235dfecf96Smrg /* Like arrays, structs are currently implemented as lists, 4245dfecf96Smrg * but only the elements could/should be circular */ 4255dfecf96Smrg if (LispCheckCircle(object, info) >= 0) 4265dfecf96Smrg return; 4275dfecf96Smrg LispDoBuildCircle(object, info); 4285dfecf96Smrg for (list = object->data.struc.fields; 4295dfecf96Smrg CONSP(list); list = CDR(list)) 4305dfecf96Smrg LispBuildCircle(CAR(list), info); 4315dfecf96Smrg break; 4325dfecf96Smrg case LispQuote_t: 4335dfecf96Smrg case LispBackquote_t: 4345dfecf96Smrg case LispFunctionQuote_t: 4355dfecf96Smrg LispDoBuildCircle(object, info); 4365dfecf96Smrg LispBuildCircle(object->data.quote, info); 4375dfecf96Smrg break; 4385dfecf96Smrg case LispComma_t: 4395dfecf96Smrg LispDoBuildCircle(object, info); 4405dfecf96Smrg LispBuildCircle(object->data.comma.eval, info); 4415dfecf96Smrg break; 4425dfecf96Smrg case LispLambda_t: 4435dfecf96Smrg /* Circularity in a function body should fail elsewhere... */ 4445dfecf96Smrg if (LispCheckCircle(object, info) >= 0) 4455dfecf96Smrg return; 4465dfecf96Smrg LispDoBuildCircle(object, info); 4475dfecf96Smrg LispBuildCircle(object->data.lambda.code, info); 4485dfecf96Smrg break; 4495dfecf96Smrg default: 4505dfecf96Smrg break; 4515dfecf96Smrg } 4525dfecf96Smrg} 4535dfecf96Smrg 4545dfecf96Smrgstatic void 4555dfecf96SmrgLispDoBuildCircle(LispObj *object, write_info *info) 4565dfecf96Smrg{ 4575dfecf96Smrg long i; 4585dfecf96Smrg 4595dfecf96Smrg if (LispCheckCircle(object, info) >= 0) 4605dfecf96Smrg return; 4615dfecf96Smrg 4625dfecf96Smrg for (i = 0; i < info->num_objects; i++) 4635dfecf96Smrg if (info->objects[i] == object) { 4645dfecf96Smrg /* circularity found */ 4655dfecf96Smrg info->circles = LispRealloc(info->circles, sizeof(circle_info) * 4665dfecf96Smrg (info->num_circles + 1)); 4675dfecf96Smrg info->circles[info->num_circles].circle_nth = 0; 4685dfecf96Smrg info->circles[info->num_circles].object = object; 4695dfecf96Smrg ++info->num_circles; 4705dfecf96Smrg return; 4715dfecf96Smrg } 4725dfecf96Smrg 4735dfecf96Smrg /* object pointer not yet recorded */ 4745dfecf96Smrg if ((i % 16) == 0) 4755dfecf96Smrg info->objects = LispRealloc(info->objects, sizeof(LispObj*) * 4765dfecf96Smrg (info->num_objects + 16)); 4775dfecf96Smrg info->objects[info->num_objects++] = object; 4785dfecf96Smrg 4795dfecf96Smrg if (CONSP(object)) { 4805dfecf96Smrg if (CONSP(CAR(object))) 4815dfecf96Smrg LispDoBuildCircle(CAR(object), info); 4825dfecf96Smrg else 4835dfecf96Smrg LispBuildCircle(CAR(object), info); 4845dfecf96Smrg if (CONSP(CDR(object))) 4855dfecf96Smrg LispDoBuildCircle(CDR(object), info); 4865dfecf96Smrg else 4875dfecf96Smrg LispBuildCircle(CDR(object), info); 4885dfecf96Smrg } 4895dfecf96Smrg} 4905dfecf96Smrg 4915dfecf96Smrgstatic long 4925dfecf96SmrgLispCheckCircle(LispObj *object, write_info *info) 4935dfecf96Smrg{ 4945dfecf96Smrg long i; 4955dfecf96Smrg 4965dfecf96Smrg for (i = 0; i < info->num_circles; i++) 4975dfecf96Smrg if (info->circles[i].object == object) 4985dfecf96Smrg return (i); 4995dfecf96Smrg 5005dfecf96Smrg return (-1); 5015dfecf96Smrg} 5025dfecf96Smrg 5035dfecf96Smrgstatic int 5045dfecf96SmrgLispPrintCircle(LispObj *stream, LispObj *object, long circle, 5055dfecf96Smrg int *length, write_info *info) 5065dfecf96Smrg{ 5075dfecf96Smrg char stk[32]; 5085dfecf96Smrg 5095dfecf96Smrg if (!info->circles[circle].circle_nth) { 5105dfecf96Smrg sprintf(stk, "#%ld=", ++info->circle_count); 5115dfecf96Smrg *length += LispWriteStr(stream, stk, strlen(stk)); 5125dfecf96Smrg info->circles[circle].circle_nth = info->circle_count; 5135dfecf96Smrg 5145dfecf96Smrg return (1); 5155dfecf96Smrg } 5165dfecf96Smrg sprintf(stk, "#%ld#", info->circles[circle].circle_nth); 5175dfecf96Smrg *length += LispWriteStr(stream, stk, strlen(stk)); 5185dfecf96Smrg 5195dfecf96Smrg return (0); 5205dfecf96Smrg} 5215dfecf96Smrg 5225dfecf96Smrgstatic int 5235dfecf96SmrgLispWriteAlist(LispObj *stream, LispArgList *alist, write_info *info) 5245dfecf96Smrg{ 5255dfecf96Smrg char *name; 5265dfecf96Smrg int i, length = 0, need_space = 0; 5275dfecf96Smrg 5285dfecf96Smrg#define WRITE_ATOM(object) \ 5295dfecf96Smrg name = ATOMID(object); \ 5305dfecf96Smrg length += LispDoWriteAtom(stream, name, strlen(name), \ 5315dfecf96Smrg info->print_case) 5325dfecf96Smrg#define WRITE_STRING(string) \ 5335dfecf96Smrg length += LispDoWriteAtom(stream, string, strlen(string), \ 5345dfecf96Smrg info->print_case) 5355dfecf96Smrg#define WRITE_OBJECT(object) \ 5365dfecf96Smrg length += LispDoWriteObject(stream, object, info, 1) 5375dfecf96Smrg#define WRITE_OPAREN() \ 5385dfecf96Smrg length += LispWriteChar(stream, '(') 5395dfecf96Smrg#define WRITE_SPACE() \ 5405dfecf96Smrg length += LispWriteChar(stream, ' ') 5415dfecf96Smrg#define WRITE_CPAREN() \ 5425dfecf96Smrg length += LispWriteChar(stream, ')') 5435dfecf96Smrg 5445dfecf96Smrg WRITE_OPAREN(); 5455dfecf96Smrg for (i = 0; i < alist->normals.num_symbols; i++) { 5465dfecf96Smrg WRITE_ATOM(alist->normals.symbols[i]); 5475dfecf96Smrg if (i + 1 < alist->normals.num_symbols) 5485dfecf96Smrg WRITE_SPACE(); 5495dfecf96Smrg else 5505dfecf96Smrg need_space = 1; 5515dfecf96Smrg } 5525dfecf96Smrg if (alist->optionals.num_symbols) { 5535dfecf96Smrg if (need_space) 5545dfecf96Smrg WRITE_SPACE(); 5555dfecf96Smrg WRITE_STRING(Soptional); 5565dfecf96Smrg WRITE_SPACE(); 5575dfecf96Smrg for (i = 0; i < alist->optionals.num_symbols; i++) { 5585dfecf96Smrg WRITE_OPAREN(); 5595dfecf96Smrg WRITE_ATOM(alist->optionals.symbols[i]); 5605dfecf96Smrg WRITE_SPACE(); 5615dfecf96Smrg WRITE_OBJECT(alist->optionals.defaults[i]); 5625dfecf96Smrg if (alist->optionals.sforms[i]) { 5635dfecf96Smrg WRITE_SPACE(); 5645dfecf96Smrg WRITE_ATOM(alist->optionals.sforms[i]); 5655dfecf96Smrg } 5665dfecf96Smrg WRITE_CPAREN(); 5675dfecf96Smrg if (i + 1 < alist->optionals.num_symbols) 5685dfecf96Smrg WRITE_SPACE(); 5695dfecf96Smrg } 5705dfecf96Smrg need_space = 1; 5715dfecf96Smrg } 5725dfecf96Smrg if (alist->keys.num_symbols) { 5735dfecf96Smrg if (need_space) 5745dfecf96Smrg WRITE_SPACE(); 5755dfecf96Smrg length += LispDoWriteAtom(stream, Skey, 4, info->print_case); 5765dfecf96Smrg WRITE_SPACE(); 5775dfecf96Smrg for (i = 0; i < alist->keys.num_symbols; i++) { 5785dfecf96Smrg WRITE_OPAREN(); 5795dfecf96Smrg if (alist->keys.keys[i]) { 5805dfecf96Smrg WRITE_OPAREN(); 5815dfecf96Smrg WRITE_ATOM(alist->keys.keys[i]); 5825dfecf96Smrg WRITE_SPACE(); 5835dfecf96Smrg } 5845dfecf96Smrg WRITE_ATOM(alist->keys.symbols[i]); 5855dfecf96Smrg if (alist->keys.keys[i]) 5865dfecf96Smrg WRITE_CPAREN(); 5875dfecf96Smrg WRITE_SPACE(); 5885dfecf96Smrg WRITE_OBJECT(alist->keys.defaults[i]); 5895dfecf96Smrg if (alist->keys.sforms[i]) { 5905dfecf96Smrg WRITE_SPACE(); 5915dfecf96Smrg WRITE_ATOM(alist->keys.sforms[i]); 5925dfecf96Smrg } 5935dfecf96Smrg WRITE_CPAREN(); 5945dfecf96Smrg if (i + 1 < alist->keys.num_symbols) 5955dfecf96Smrg WRITE_SPACE(); 5965dfecf96Smrg } 5975dfecf96Smrg need_space = 1; 5985dfecf96Smrg } 5995dfecf96Smrg if (alist->rest) { 6005dfecf96Smrg if (need_space) 6015dfecf96Smrg WRITE_SPACE(); 6025dfecf96Smrg WRITE_STRING(Srest); 6035dfecf96Smrg WRITE_SPACE(); 6045dfecf96Smrg WRITE_ATOM(alist->rest); 6055dfecf96Smrg need_space = 1; 6065dfecf96Smrg } 6075dfecf96Smrg if (alist->auxs.num_symbols) { 6085dfecf96Smrg if (need_space) 6095dfecf96Smrg WRITE_SPACE(); 6105dfecf96Smrg WRITE_STRING(Saux); 6115dfecf96Smrg WRITE_SPACE(); 6125dfecf96Smrg for (i = 0; i < alist->auxs.num_symbols; i++) { 6135dfecf96Smrg WRITE_OPAREN(); 6145dfecf96Smrg WRITE_ATOM(alist->auxs.symbols[i]); 6155dfecf96Smrg WRITE_SPACE(); 6165dfecf96Smrg WRITE_OBJECT(alist->auxs.initials[i]); 6175dfecf96Smrg WRITE_CPAREN(); 6185dfecf96Smrg if (i + 1 < alist->auxs.num_symbols) 6195dfecf96Smrg WRITE_SPACE(); 6205dfecf96Smrg } 6215dfecf96Smrg } 6225dfecf96Smrg WRITE_CPAREN(); 6235dfecf96Smrg 6245dfecf96Smrg#undef WRITE_ATOM 6255dfecf96Smrg#undef WRITE_STRING 6265dfecf96Smrg#undef WRITE_OBJECT 6275dfecf96Smrg#undef WRITE_OPAREN 6285dfecf96Smrg#undef WRITE_SPACE 6295dfecf96Smrg#undef WRITE_CPAREN 6305dfecf96Smrg 6315dfecf96Smrg return (length); 6325dfecf96Smrg} 6335dfecf96Smrg 6345dfecf96Smrgstatic void 6355dfecf96Smrgcheck_stream(LispObj *stream, 6365dfecf96Smrg LispFile **file, LispString **string, int check_writable) 6375dfecf96Smrg{ 6385dfecf96Smrg /* NIL is UNIX stdout, *STANDARD-OUTPUT* may not be UNIX stdout */ 6395dfecf96Smrg if (stream == NIL) { 6405dfecf96Smrg *file = Stdout; 6415dfecf96Smrg *string = NULL; 6425dfecf96Smrg } 6435dfecf96Smrg else { 6445dfecf96Smrg if (!STREAMP(stream)) 6455dfecf96Smrg LispDestroy("%s is not a stream", STROBJ(stream)); 6465dfecf96Smrg if (check_writable && !stream->data.stream.writable) 6475dfecf96Smrg LispDestroy("%s is not writable", STROBJ(stream)); 6485dfecf96Smrg else if (stream->data.stream.type == LispStreamString) { 6495dfecf96Smrg *string = SSTREAMP(stream); 6505dfecf96Smrg *file = NULL; 6515dfecf96Smrg } 6525dfecf96Smrg else { 6535dfecf96Smrg if (stream->data.stream.type == LispStreamPipe) 6545dfecf96Smrg *file = OPSTREAMP(stream); 6555dfecf96Smrg else 6565dfecf96Smrg *file = stream->data.stream.source.file; 6575dfecf96Smrg *string = NULL; 6585dfecf96Smrg } 6595dfecf96Smrg } 6605dfecf96Smrg} 6615dfecf96Smrg 6625dfecf96Smrg/* Assumes buffer has enough storage, 64 bytes should be more than enough */ 6635dfecf96Smrgstatic void 6645dfecf96Smrgparse_double(char *buffer, int *exponent, double value, int d) 6655dfecf96Smrg{ 6665dfecf96Smrg char stk[64], fmt[32], *ptr, *fract = NULL; 6675dfecf96Smrg int positive = value >= 0.0; 6685dfecf96Smrg 6695dfecf96Smrgparse_double_again: 6705dfecf96Smrg if (d >= 8) { 6715dfecf96Smrg double dcheck; 6725dfecf96Smrg int icheck, count; 6735dfecf96Smrg 6745dfecf96Smrg /* this should to do the correct rounding */ 6755dfecf96Smrg for (count = 2; count >= 0; count--) { 6765dfecf96Smrg icheck = d <= 0 ? 0 : d > FLOAT_PREC ? FLOAT_PREC - count : d - count; 6775dfecf96Smrg sprintf(fmt, "%%.%de", icheck); 6785dfecf96Smrg sprintf(stk, fmt, value); 6795dfecf96Smrg if (count) { 6805dfecf96Smrg /* if the value read back is the same formatted */ 6815dfecf96Smrg sscanf(stk, "%lf", &dcheck); 6825dfecf96Smrg if (dcheck == value) 6835dfecf96Smrg break; 6845dfecf96Smrg } 6855dfecf96Smrg } 6865dfecf96Smrg } 6875dfecf96Smrg else { 6885dfecf96Smrg sprintf(fmt, "%%.%de", d <= 0 ? 0 : d > FLOAT_PREC ? FLOAT_PREC : d); 6895dfecf96Smrg sprintf(stk, fmt, value); 6905dfecf96Smrg } 6915dfecf96Smrg 6925dfecf96Smrg /* this "should" never fail */ 6935dfecf96Smrg ptr = strchr(stk, 'e'); 6945dfecf96Smrg if (ptr) { 6955dfecf96Smrg *ptr++ = '\0'; 6965dfecf96Smrg *exponent = atoi(ptr); 6975dfecf96Smrg } 6985dfecf96Smrg else 6995dfecf96Smrg *exponent = 0; 7005dfecf96Smrg 7015dfecf96Smrg /* find start of number representation */ 7025dfecf96Smrg for (ptr = stk; *ptr && !isdigit(*ptr); ptr++) 7035dfecf96Smrg ; 7045dfecf96Smrg 7055dfecf96Smrg /* check if did not trim any significant digit, 7065dfecf96Smrg * this may happen because '%.e' puts only one digit before the '.' */ 7075dfecf96Smrg if (d > 0 && d < FLOAT_PREC && fabs(value) >= 10.0 && 7085dfecf96Smrg strlen(ptr) - 1 - !positive <= *exponent) { 7095dfecf96Smrg d += *exponent - (strlen(ptr) - 1 - !positive) + 1; 7105dfecf96Smrg goto parse_double_again; 7115dfecf96Smrg } 7125dfecf96Smrg 7135dfecf96Smrg /* this "should" never fail */ 7145dfecf96Smrg fract = strchr(ptr, '.'); 7155dfecf96Smrg if (fract) 7165dfecf96Smrg *fract++ = '\0'; 7175dfecf96Smrg 7185dfecf96Smrg /* store number representation in buffer */ 7195dfecf96Smrg *buffer = positive ? '+' : '-'; 7205dfecf96Smrg strcpy(buffer + 1, ptr); 7215dfecf96Smrg if (fract) 7225dfecf96Smrg strcpy(buffer + strlen(buffer), fract); 7235dfecf96Smrg} 7245dfecf96Smrg 7255dfecf96Smrgstatic void 7265dfecf96Smrgformat_integer(char *buffer, long value, int radix) 7275dfecf96Smrg{ 7285dfecf96Smrg if (radix == 10) 7295dfecf96Smrg sprintf(buffer, "%ld", value); 7305dfecf96Smrg else if (radix == 16) 7315dfecf96Smrg sprintf(buffer, "%lx", value); 7325dfecf96Smrg else if (radix == 8) 7335dfecf96Smrg sprintf(buffer, "%lo", value); 7345dfecf96Smrg else { 7355dfecf96Smrg /* use bignum routine to convert number to string */ 7365dfecf96Smrg mpi integer; 7375dfecf96Smrg 7385dfecf96Smrg mpi_init(&integer); 7395dfecf96Smrg mpi_seti(&integer, value); 7405dfecf96Smrg mpi_getstr(buffer, &integer, radix); 7415dfecf96Smrg mpi_clear(&integer); 7425dfecf96Smrg } 7435dfecf96Smrg} 7445dfecf96Smrg 7455dfecf96Smrgstatic int 7465dfecf96SmrgLispWriteCPointer(LispObj *stream, void *data) 7475dfecf96Smrg{ 7485dfecf96Smrg char stk[32]; 7495dfecf96Smrg 7505dfecf96Smrg#ifdef LONG64 7515dfecf96Smrg sprintf(stk, "0x%016lx", (long)data); 7525dfecf96Smrg#else 7535dfecf96Smrg sprintf(stk, "0x%08lx", (long)data); 7545dfecf96Smrg#endif 7555dfecf96Smrg 7565dfecf96Smrg return (LispWriteStr(stream, stk, strlen(stk))); 7575dfecf96Smrg} 7585dfecf96Smrg 7595dfecf96Smrgstatic int 7605dfecf96SmrgLispWriteCString(LispObj *stream, char *string, long length, write_info *info) 7615dfecf96Smrg{ 7625dfecf96Smrg int result; 7635dfecf96Smrg 7645dfecf96Smrg if (!info->print_escape) { 7655dfecf96Smrg char *base, *ptr, *end; 7665dfecf96Smrg 7675dfecf96Smrg result = LispWriteChar(stream, '"'); 7685dfecf96Smrg for (base = ptr = string, end = string + length; ptr < end; ptr++) { 7695dfecf96Smrg if (*ptr == '\\' || *ptr == '"') { 7705dfecf96Smrg result += LispWriteStr(stream, base, ptr - base); 7715dfecf96Smrg result += LispWriteChar(stream, '\\'); 7725dfecf96Smrg result += LispWriteChar(stream, *ptr); 7735dfecf96Smrg base = ptr + 1; 7745dfecf96Smrg } 7755dfecf96Smrg } 7765dfecf96Smrg result += LispWriteStr(stream, base, end - base); 7775dfecf96Smrg result += LispWriteChar(stream, '"'); 7785dfecf96Smrg } 7795dfecf96Smrg else 7805dfecf96Smrg result = LispWriteStr(stream, string, length); 7815dfecf96Smrg 7825dfecf96Smrg return (result); 7835dfecf96Smrg} 7845dfecf96Smrg 7855dfecf96Smrgstatic int 7865dfecf96SmrgLispWriteList(LispObj *stream, LispObj *object, write_info *info, int paren) 7875dfecf96Smrg{ 7885dfecf96Smrg int length = 0; 7895dfecf96Smrg long circle = 0; 7905dfecf96Smrg 7915dfecf96Smrg INCDEPTH(); 7925dfecf96Smrg if (info->print_level < 0 || info->level <= info->print_level) { 7935dfecf96Smrg LispObj *car, *cdr; 7945dfecf96Smrg long print_length = info->length; 7955dfecf96Smrg 7965dfecf96Smrg if (info->circles && (circle = LispCheckCircle(object, info)) >= 0) { 7975dfecf96Smrg if (!paren) { 7985dfecf96Smrg length += LispWriteStr(stream, ". ", 2); 7995dfecf96Smrg paren = 1; 8005dfecf96Smrg } 8015dfecf96Smrg if (LispPrintCircle(stream, object, circle, &length, info) == 0) { 8025dfecf96Smrg DECDEPTH(); 8035dfecf96Smrg 8045dfecf96Smrg return (length); 8055dfecf96Smrg } 8065dfecf96Smrg } 8075dfecf96Smrg 8085dfecf96Smrg car = CAR(object); 8095dfecf96Smrg cdr = CDR(object); 8105dfecf96Smrg 8115dfecf96Smrg if (cdr == NIL) { 8125dfecf96Smrg if (paren) 8135dfecf96Smrg length += LispWriteChar(stream, '('); 8145dfecf96Smrg if (info->print_length < 0 || info->length < info->print_length) { 8155dfecf96Smrg info->length = 0; 8165dfecf96Smrg length += LispDoWriteObject(stream, car, info, 1); 8175dfecf96Smrg info->length = print_length + 1; 8185dfecf96Smrg } 8195dfecf96Smrg else 8205dfecf96Smrg length += LispWriteStr(stream, "...", 3); 8215dfecf96Smrg if (paren) 8225dfecf96Smrg length += LispWriteChar(stream, ')'); 8235dfecf96Smrg } 8245dfecf96Smrg else { 8255dfecf96Smrg if (paren) 8265dfecf96Smrg length += LispWriteChar(stream, '('); 8275dfecf96Smrg if (info->print_length < 0 || info->length < info->print_length) { 8285dfecf96Smrg info->length = 0; 8295dfecf96Smrg length += LispDoWriteObject(stream, car, info, 1); 8305dfecf96Smrg info->length = print_length + 1; 8315dfecf96Smrg if (!CONSP(cdr)) { 8325dfecf96Smrg length += LispWriteStr(stream, " . ", 3); 8335dfecf96Smrg info->length = 0; 8345dfecf96Smrg length += LispDoWriteObject(stream, cdr, info, 0); 8355dfecf96Smrg } 8365dfecf96Smrg else { 8375dfecf96Smrg length += LispWriteChar(stream, ' '); 8385dfecf96Smrg if (info->print_length < 0 || 8395dfecf96Smrg info->length < info->print_length) 8405dfecf96Smrg length += LispWriteList(stream, cdr, info, 0); 8415dfecf96Smrg else 8425dfecf96Smrg length += LispWriteStr(stream, "...", 3); 8435dfecf96Smrg } 8445dfecf96Smrg } 8455dfecf96Smrg else 8465dfecf96Smrg length += LispWriteStr(stream, "...", 3); 8475dfecf96Smrg if (paren) 8485dfecf96Smrg length += LispWriteChar(stream, ')'); 8495dfecf96Smrg } 8505dfecf96Smrg info->length = print_length; 8515dfecf96Smrg } 8525dfecf96Smrg else 8535dfecf96Smrg length += LispWriteChar(stream, '#'); 8545dfecf96Smrg DECDEPTH(); 8555dfecf96Smrg 8565dfecf96Smrg return (length); 8575dfecf96Smrg} 8585dfecf96Smrg 8595dfecf96Smrgstatic int 8605dfecf96SmrgLispDoWriteObject(LispObj *stream, LispObj *object, write_info *info, int paren) 8615dfecf96Smrg{ 8625dfecf96Smrg long print_level; 8635dfecf96Smrg int length = 0; 8645dfecf96Smrg char stk[64], *string = NULL; 8655dfecf96Smrg 8665dfecf96Smrgwrite_again: 8675dfecf96Smrg switch (OBJECT_TYPE(object)) { 8685dfecf96Smrg case LispNil_t: 8695dfecf96Smrg if (object == NIL) 8705dfecf96Smrg string = Snil; 8715dfecf96Smrg else if (object == T) 8725dfecf96Smrg string = St; 8735dfecf96Smrg else if (object == DOT) 8745dfecf96Smrg string = "#<DOT>"; 8755dfecf96Smrg else if (object == UNSPEC) 8765dfecf96Smrg string = "#<UNSPEC>"; 8775dfecf96Smrg else if (object == UNBOUND) 8785dfecf96Smrg string = "#<UNBOUND>"; 8795dfecf96Smrg else 8805dfecf96Smrg string = "#<ERROR>"; 8815dfecf96Smrg length += LispDoWriteAtom(stream, string, strlen(string), 8825dfecf96Smrg info->print_case); 8835dfecf96Smrg break; 8845dfecf96Smrg case LispOpaque_t: { 8855dfecf96Smrg char *desc = LispIntToOpaqueType(object->data.opaque.type); 8865dfecf96Smrg 8875dfecf96Smrg length += LispWriteChar(stream, '#'); 8885dfecf96Smrg length += LispWriteCPointer(stream, object->data.opaque.data); 8895dfecf96Smrg length += LispWriteStr(stream, desc, strlen(desc)); 8905dfecf96Smrg } break; 8915dfecf96Smrg case LispAtom_t: 8925dfecf96Smrg length += LispWriteAtom(stream, object, info); 8935dfecf96Smrg break; 8945dfecf96Smrg case LispFunction_t: 8955dfecf96Smrg if (object->data.atom->a_function) { 8965dfecf96Smrg object = object->data.atom->property->fun.function; 8975dfecf96Smrg goto write_lambda; 8985dfecf96Smrg } 8995dfecf96Smrg length += LispWriteStr(stream, "#<", 2); 9005dfecf96Smrg if (object->data.atom->a_compiled) 9015dfecf96Smrg LispDoWriteAtom(stream, "COMPILED", 8, info->print_case); 9025dfecf96Smrg else if (object->data.atom->a_builtin) 9035dfecf96Smrg LispDoWriteAtom(stream, "BUILTIN", 7, info->print_case); 9045dfecf96Smrg /* XXX the function does not exist anymore */ 9055dfecf96Smrg /* FIXME not sure if I want this fixed... */ 9065dfecf96Smrg else 9075dfecf96Smrg LispDoWriteAtom(stream, "UNBOUND", 7, info->print_case); 9085dfecf96Smrg LispDoWriteAtom(stream, "-FUNCTION", 9, info->print_case); 9095dfecf96Smrg length += LispWriteChar(stream, ' '); 9105dfecf96Smrg length += LispWriteAtom(stream, object->data.atom->object, info); 9115dfecf96Smrg length += LispWriteChar(stream, '>'); 9125dfecf96Smrg break; 9135dfecf96Smrg case LispString_t: 9145dfecf96Smrg length += LispWriteString(stream, object, info); 9155dfecf96Smrg break; 9165dfecf96Smrg case LispSChar_t: 9175dfecf96Smrg length += LispWriteCharacter(stream, object, info); 9185dfecf96Smrg break; 9195dfecf96Smrg case LispDFloat_t: 9205dfecf96Smrg length += LispWriteFloat(stream, object); 9215dfecf96Smrg break; 9225dfecf96Smrg case LispFixnum_t: 9235dfecf96Smrg case LispInteger_t: 9245dfecf96Smrg case LispBignum_t: 9255dfecf96Smrg length += LispWriteInteger(stream, object); 9265dfecf96Smrg break; 9275dfecf96Smrg case LispRatio_t: 9285dfecf96Smrg format_integer(stk, object->data.ratio.numerator, 10); 9295dfecf96Smrg length += LispWriteStr(stream, stk, strlen(stk)); 9305dfecf96Smrg length += LispWriteChar(stream, '/'); 9315dfecf96Smrg format_integer(stk, object->data.ratio.denominator, 10); 9325dfecf96Smrg length += LispWriteStr(stream, stk, strlen(stk)); 9335dfecf96Smrg break; 9345dfecf96Smrg case LispBigratio_t: { 9355dfecf96Smrg int sz; 9365dfecf96Smrg char *ptr; 9375dfecf96Smrg 9385dfecf96Smrg sz = mpi_getsize(mpr_num(object->data.mp.ratio), 10) + 1 + 9395dfecf96Smrg mpi_getsize(mpr_den(object->data.mp.ratio), 10) + 1 + 9405dfecf96Smrg (mpi_sgn(mpr_num(object->data.mp.ratio)) < 0); 9415dfecf96Smrg if (sz > sizeof(stk)) 9425dfecf96Smrg ptr = LispMalloc(sz); 9435dfecf96Smrg else 9445dfecf96Smrg ptr = stk; 9455dfecf96Smrg mpr_getstr(ptr, object->data.mp.ratio, 10); 9465dfecf96Smrg length += LispWriteStr(stream, ptr, sz - 1); 9475dfecf96Smrg if (ptr != stk) 9485dfecf96Smrg LispFree(ptr); 9495dfecf96Smrg } break; 9505dfecf96Smrg case LispComplex_t: 9515dfecf96Smrg length += LispWriteStr(stream, "#C(", 3); 9525dfecf96Smrg length += LispDoWriteObject(stream, 9535dfecf96Smrg object->data.complex.real, info, 0); 9545dfecf96Smrg length += LispWriteChar(stream, ' '); 9555dfecf96Smrg length += LispDoWriteObject(stream, 9565dfecf96Smrg object->data.complex.imag, info, 0); 9575dfecf96Smrg length += LispWriteChar(stream, ')'); 9585dfecf96Smrg break; 9595dfecf96Smrg case LispCons_t: 9605dfecf96Smrg print_level = info->level; 9615dfecf96Smrg ++info->level; 9625dfecf96Smrg length += LispWriteList(stream, object, info, paren); 9635dfecf96Smrg info->level = print_level; 9645dfecf96Smrg break; 9655dfecf96Smrg case LispQuote_t: 9665dfecf96Smrg length += LispWriteChar(stream, '\''); 9675dfecf96Smrg paren = 1; 9685dfecf96Smrg object = object->data.quote; 9695dfecf96Smrg goto write_again; 9705dfecf96Smrg case LispBackquote_t: 9715dfecf96Smrg length += LispWriteChar(stream, '`'); 9725dfecf96Smrg paren = 1; 9735dfecf96Smrg object = object->data.quote; 9745dfecf96Smrg goto write_again; 9755dfecf96Smrg case LispComma_t: 9765dfecf96Smrg if (object->data.comma.atlist) 9775dfecf96Smrg length += LispWriteStr(stream, ",@", 2); 9785dfecf96Smrg else 9795dfecf96Smrg length += LispWriteChar(stream, ','); 9805dfecf96Smrg paren = 1; 9815dfecf96Smrg object = object->data.comma.eval; 9825dfecf96Smrg goto write_again; 9835dfecf96Smrg break; 9845dfecf96Smrg case LispFunctionQuote_t: 9855dfecf96Smrg length += LispWriteStr(stream, "#'", 2); 9865dfecf96Smrg paren = 1; 9875dfecf96Smrg object = object->data.quote; 9885dfecf96Smrg goto write_again; 9895dfecf96Smrg case LispArray_t: 9905dfecf96Smrg length += LispWriteArray(stream, object, info); 9915dfecf96Smrg break; 9925dfecf96Smrg case LispStruct_t: 9935dfecf96Smrg length += LispWriteStruct(stream, object, info); 9945dfecf96Smrg break; 9955dfecf96Smrg case LispLambda_t: 9965dfecf96Smrg write_lambda: 9975dfecf96Smrg switch (object->funtype) { 9985dfecf96Smrg case LispLambda: 9995dfecf96Smrg string = "#<LAMBDA "; 10005dfecf96Smrg break; 10015dfecf96Smrg case LispFunction: 10025dfecf96Smrg string = "#<FUNCTION "; 10035dfecf96Smrg break; 10045dfecf96Smrg case LispMacro: 10055dfecf96Smrg string = "#<MACRO "; 10065dfecf96Smrg break; 10075dfecf96Smrg case LispSetf: 10085dfecf96Smrg string = "#<SETF "; 10095dfecf96Smrg break; 10105dfecf96Smrg } 10115dfecf96Smrg length += LispDoWriteAtom(stream, string, strlen(string), 10125dfecf96Smrg info->print_case); 10135dfecf96Smrg if (object->funtype != LispLambda) { 10145dfecf96Smrg length += LispWriteAtom(stream, object->data.lambda.name, info); 10155dfecf96Smrg length += LispWriteChar(stream, ' '); 10165dfecf96Smrg length += LispWriteAlist(stream, object->data.lambda.name 10175dfecf96Smrg ->data.atom->property->alist, info); 10185dfecf96Smrg } 10195dfecf96Smrg else { 10205dfecf96Smrg length += LispDoWriteAtom(stream, Snil, 3, info->print_case); 10215dfecf96Smrg length += LispWriteChar(stream, ' '); 10225dfecf96Smrg length += LispWriteAlist(stream, (LispArgList*)object-> 10235dfecf96Smrg data.lambda.name->data.opaque.data, 10245dfecf96Smrg info); 10255dfecf96Smrg } 10265dfecf96Smrg length += LispWriteChar(stream, ' '); 10275dfecf96Smrg length += LispDoWriteObject(stream, 10285dfecf96Smrg object->data.lambda.code, info, 0); 10295dfecf96Smrg length += LispWriteChar(stream, '>'); 10305dfecf96Smrg break; 10315dfecf96Smrg case LispStream_t: 10325dfecf96Smrg length += LispWriteStr(stream, "#<", 2); 10335dfecf96Smrg if (object->data.stream.type == LispStreamFile) 10345dfecf96Smrg string = "FILE-STREAM "; 10355dfecf96Smrg else if (object->data.stream.type == LispStreamString) 10365dfecf96Smrg string = "STRING-STREAM "; 10375dfecf96Smrg else if (object->data.stream.type == LispStreamStandard) 10385dfecf96Smrg string = "STANDARD-STREAM "; 10395dfecf96Smrg else if (object->data.stream.type == LispStreamPipe) 10405dfecf96Smrg string = "PIPE-STREAM "; 10415dfecf96Smrg length += LispDoWriteAtom(stream, string, strlen(string), 10425dfecf96Smrg info->print_case); 10435dfecf96Smrg 10445dfecf96Smrg if (!object->data.stream.readable && !object->data.stream.writable) 10455dfecf96Smrg length += LispDoWriteAtom(stream, "CLOSED", 10465dfecf96Smrg 6, info->print_case); 10475dfecf96Smrg else { 10485dfecf96Smrg if (object->data.stream.readable) 10495dfecf96Smrg length += LispDoWriteAtom(stream, "READ", 10505dfecf96Smrg 4, info->print_case); 10515dfecf96Smrg if (object->data.stream.writable) { 10525dfecf96Smrg if (object->data.stream.readable) 10535dfecf96Smrg length += LispWriteChar(stream, '-'); 10545dfecf96Smrg length += LispDoWriteAtom(stream, "WRITE", 10555dfecf96Smrg 5, info->print_case); 10565dfecf96Smrg } 10575dfecf96Smrg } 10585dfecf96Smrg if (object->data.stream.type != LispStreamString) { 10595dfecf96Smrg length += LispWriteChar(stream, ' '); 10605dfecf96Smrg length += LispDoWriteObject(stream, 10615dfecf96Smrg object->data.stream.pathname, 10625dfecf96Smrg info, 1); 10635dfecf96Smrg /* same address/size for pipes */ 10645dfecf96Smrg length += LispWriteChar(stream, ' '); 10655dfecf96Smrg length += LispWriteCPointer(stream, 10665dfecf96Smrg object->data.stream.source.file); 10675dfecf96Smrg if (object->data.stream.readable && 10685dfecf96Smrg object->data.stream.type == LispStreamFile && 10695dfecf96Smrg !object->data.stream.source.file->binary) { 10705dfecf96Smrg length += LispWriteStr(stream, " @", 2); 10715dfecf96Smrg format_integer(stk, object->data.stream.source.file->line, 10); 10725dfecf96Smrg length += LispWriteStr(stream, stk, strlen(stk)); 10735dfecf96Smrg } 10745dfecf96Smrg } 10755dfecf96Smrg length += LispWriteChar(stream, '>'); 10765dfecf96Smrg break; 10775dfecf96Smrg case LispPathname_t: 10785dfecf96Smrg length += LispWriteStr(stream, "#P", 2); 10795dfecf96Smrg paren = 1; 10805dfecf96Smrg object = CAR(object->data.quote); 10815dfecf96Smrg goto write_again; 10825dfecf96Smrg case LispPackage_t: 10835dfecf96Smrg length += LispDoWriteAtom(stream, "#<PACKAGE ", 10845dfecf96Smrg 10, info->print_case); 10855dfecf96Smrg length += LispWriteStr(stream, 10865dfecf96Smrg THESTR(object->data.package.name), 10875dfecf96Smrg STRLEN(object->data.package.name)); 10885dfecf96Smrg length += LispWriteChar(stream, '>'); 10895dfecf96Smrg break; 10905dfecf96Smrg case LispRegex_t: 10915dfecf96Smrg length += LispDoWriteAtom(stream, "#<REGEX ", 10925dfecf96Smrg 8, info->print_case); 10935dfecf96Smrg length += LispDoWriteObject(stream, 10945dfecf96Smrg object->data.regex.pattern, info, 1); 10955dfecf96Smrg if (object->data.regex.options & RE_NOSPEC) 10965dfecf96Smrg length += LispDoWriteAtom(stream, " :NOSPEC", 10975dfecf96Smrg 8, info->print_case); 10985dfecf96Smrg if (object->data.regex.options & RE_ICASE) 10995dfecf96Smrg length += LispDoWriteAtom(stream, " :ICASE", 11005dfecf96Smrg 7, info->print_case); 11015dfecf96Smrg if (object->data.regex.options & RE_NOSUB) 11025dfecf96Smrg length += LispDoWriteAtom(stream, " :NOSUB", 11035dfecf96Smrg 7, info->print_case); 11045dfecf96Smrg if (object->data.regex.options & RE_NEWLINE) 11055dfecf96Smrg length += LispDoWriteAtom(stream, " :NEWLINE", 11065dfecf96Smrg 9, info->print_case); 11075dfecf96Smrg length += LispWriteChar(stream, '>'); 11085dfecf96Smrg break; 11095dfecf96Smrg case LispBytecode_t: 11105dfecf96Smrg length += LispDoWriteAtom(stream, "#<BYTECODE ", 11115dfecf96Smrg 11, info->print_case); 11125dfecf96Smrg length += LispWriteCPointer(stream, 11135dfecf96Smrg object->data.bytecode.bytecode); 11145dfecf96Smrg length += LispWriteChar(stream, '>'); 11155dfecf96Smrg break; 11165dfecf96Smrg case LispHashTable_t: 11175dfecf96Smrg length += LispDoWriteAtom(stream, "#<HASH-TABLE ", 11185dfecf96Smrg 13, info->print_case); 11195dfecf96Smrg length += LispWriteAtom(stream, object->data.hash.test, info); 11205dfecf96Smrg snprintf(stk, sizeof(stk), " %g %g", 11215dfecf96Smrg object->data.hash.table->rehash_size, 11225dfecf96Smrg object->data.hash.table->rehash_threshold); 11235dfecf96Smrg length += LispWriteStr(stream, stk, strlen(stk)); 11245dfecf96Smrg snprintf(stk, sizeof(stk), " %ld/%ld>", 11255dfecf96Smrg object->data.hash.table->count, 11265dfecf96Smrg object->data.hash.table->num_entries); 11275dfecf96Smrg length += LispWriteStr(stream, stk, strlen(stk)); 11285dfecf96Smrg break; 11295dfecf96Smrg } 11305dfecf96Smrg 11315dfecf96Smrg return (length); 11325dfecf96Smrg} 11335dfecf96Smrg 11345dfecf96Smrg/* return current column number in stream */ 11355dfecf96Smrgint 11365dfecf96SmrgLispGetColumn(LispObj *stream) 11375dfecf96Smrg{ 11385dfecf96Smrg LispFile *file; 11395dfecf96Smrg LispString *string; 11405dfecf96Smrg 11415dfecf96Smrg check_stream(stream, &file, &string, 0); 11425dfecf96Smrg if (file != NULL) 11435dfecf96Smrg return (file->column); 11445dfecf96Smrg return (string->column); 11455dfecf96Smrg} 11465dfecf96Smrg 11475dfecf96Smrg/* write a character to stream */ 11485dfecf96Smrgint 11495dfecf96SmrgLispWriteChar(LispObj *stream, int character) 11505dfecf96Smrg{ 11515dfecf96Smrg LispFile *file; 11525dfecf96Smrg LispString *string; 11535dfecf96Smrg 11545dfecf96Smrg check_stream(stream, &file, &string, 1); 11555dfecf96Smrg if (file != NULL) 11565dfecf96Smrg return (LispFputc(file, character)); 11575dfecf96Smrg 11585dfecf96Smrg return (LispSputc(string, character)); 11595dfecf96Smrg} 11605dfecf96Smrg 11615dfecf96Smrg/* write a character count times to stream */ 11625dfecf96Smrgint 11635dfecf96SmrgLispWriteChars(LispObj *stream, int character, int count) 11645dfecf96Smrg{ 11655dfecf96Smrg int length = 0; 11665dfecf96Smrg 11675dfecf96Smrg if (count > 0) { 11685dfecf96Smrg char stk[64]; 11695dfecf96Smrg LispFile *file; 11705dfecf96Smrg LispString *string; 11715dfecf96Smrg 11725dfecf96Smrg check_stream(stream, &file, &string, 1); 11735dfecf96Smrg if (count >= sizeof(stk)) { 11745dfecf96Smrg memset(stk, character, sizeof(stk)); 11755dfecf96Smrg for (; count >= sizeof(stk); count -= sizeof(stk)) { 11765dfecf96Smrg if (file != NULL) 11775dfecf96Smrg length += LispFwrite(file, stk, sizeof(stk)); 11785dfecf96Smrg else 11795dfecf96Smrg length += LispSwrite(string, stk, sizeof(stk)); 11805dfecf96Smrg } 11815dfecf96Smrg } 11825dfecf96Smrg else 11835dfecf96Smrg memset(stk, character, count); 11845dfecf96Smrg 11855dfecf96Smrg if (count) { 11865dfecf96Smrg if (file != NULL) 11875dfecf96Smrg length += LispFwrite(file, stk, count); 11885dfecf96Smrg else 11895dfecf96Smrg length += LispSwrite(string, stk, count); 11905dfecf96Smrg } 11915dfecf96Smrg } 11925dfecf96Smrg 11935dfecf96Smrg return (length); 11945dfecf96Smrg} 11955dfecf96Smrg 11965dfecf96Smrg/* write a string to stream */ 11975dfecf96Smrgint 11985dfecf96SmrgLispWriteStr(LispObj *stream, char *buffer, long length) 11995dfecf96Smrg{ 12005dfecf96Smrg LispFile *file; 12015dfecf96Smrg LispString *string; 12025dfecf96Smrg 12035dfecf96Smrg check_stream(stream, &file, &string, 1); 12045dfecf96Smrg if (file != NULL) 12055dfecf96Smrg return (LispFwrite(file, buffer, length)); 12065dfecf96Smrg return (LispSwrite(string, buffer, length)); 12075dfecf96Smrg} 12085dfecf96Smrg 12095dfecf96Smrgstatic int 12105dfecf96SmrgLispDoWriteAtom(LispObj *stream, char *string, int length, int print_case) 12115dfecf96Smrg{ 12125dfecf96Smrg int bytes = 0, cap = 0; 12135dfecf96Smrg char buffer[128], *ptr; 12145dfecf96Smrg 12155dfecf96Smrg switch (print_case) { 12165dfecf96Smrg case DOWNCASE: 12175dfecf96Smrg for (ptr = buffer; length > 0; length--, string++) { 12185dfecf96Smrg if (isupper(*string)) 12195dfecf96Smrg *ptr = tolower(*string); 12205dfecf96Smrg else 12215dfecf96Smrg *ptr = *string; 12225dfecf96Smrg ++ptr; 12235dfecf96Smrg if (ptr - buffer >= sizeof(buffer)) { 12245dfecf96Smrg bytes += LispWriteStr(stream, buffer, ptr - buffer); 12255dfecf96Smrg ptr = buffer; 12265dfecf96Smrg } 12275dfecf96Smrg } 12285dfecf96Smrg if (ptr > buffer) 12295dfecf96Smrg bytes += LispWriteStr(stream, buffer, ptr - buffer); 12305dfecf96Smrg break; 12315dfecf96Smrg case CAPITALIZE: 12325dfecf96Smrg for (ptr = buffer; length > 0; length--, string++) { 12335dfecf96Smrg if (isalnum(*string)) { 12345dfecf96Smrg if (cap && isupper(*string)) 12355dfecf96Smrg *ptr = tolower(*string); 12365dfecf96Smrg else 12375dfecf96Smrg *ptr = *string; 12385dfecf96Smrg cap = 1; 12395dfecf96Smrg } 12405dfecf96Smrg else { 12415dfecf96Smrg *ptr = *string; 12425dfecf96Smrg cap = 0; 12435dfecf96Smrg } 12445dfecf96Smrg ++ptr; 12455dfecf96Smrg if (ptr - buffer >= sizeof(buffer)) { 12465dfecf96Smrg bytes += LispWriteStr(stream, buffer, ptr - buffer); 12475dfecf96Smrg ptr = buffer; 12485dfecf96Smrg } 12495dfecf96Smrg } 12505dfecf96Smrg if (ptr > buffer) 12515dfecf96Smrg bytes += LispWriteStr(stream, buffer, ptr - buffer); 12525dfecf96Smrg break; 12535dfecf96Smrg default: 12545dfecf96Smrg /* Strings are already stored upcase/quoted */ 12555dfecf96Smrg bytes += LispWriteStr(stream, string, length); 12565dfecf96Smrg break; 12575dfecf96Smrg } 12585dfecf96Smrg 12595dfecf96Smrg return (bytes); 12605dfecf96Smrg} 12615dfecf96Smrg 12625dfecf96Smrgstatic int 12635dfecf96SmrgLispWriteAtom(LispObj *stream, LispObj *object, write_info *info) 12645dfecf96Smrg{ 12655dfecf96Smrg int length = 0; 12665dfecf96Smrg LispAtom *atom = object->data.atom; 12675dfecf96Smrg Atom_id id = atom->string; 12685dfecf96Smrg 12695dfecf96Smrg if (atom->package != PACKAGE) { 12705dfecf96Smrg if (atom->package == lisp__data.keyword) 12715dfecf96Smrg length += LispWriteChar(stream, ':'); 12725dfecf96Smrg else if (atom->package == NULL) 12735dfecf96Smrg length += LispWriteStr(stream, "#:", 2); 12745dfecf96Smrg else { 12755dfecf96Smrg /* Check if the symbol is visible */ 12765dfecf96Smrg int i, visible = 0; 12775dfecf96Smrg 12785dfecf96Smrg if (atom->ext) { 12795dfecf96Smrg for (i = lisp__data.pack->use.length - 1; i >= 0; i--) { 12805dfecf96Smrg if (lisp__data.pack->use.pairs[i] == atom->package) { 12815dfecf96Smrg visible = 1; 12825dfecf96Smrg break; 12835dfecf96Smrg } 12845dfecf96Smrg } 12855dfecf96Smrg } 12865dfecf96Smrg 12875dfecf96Smrg if (!visible) { 12885dfecf96Smrg /* XXX this assumes that package names are always "readable" */ 12895dfecf96Smrg length += 12905dfecf96Smrg LispDoWriteAtom(stream, 12915dfecf96Smrg THESTR(atom->package->data.package.name), 12925dfecf96Smrg STRLEN(atom->package->data.package.name), 12935dfecf96Smrg info->print_case); 12945dfecf96Smrg length += LispWriteChar(stream, ':'); 12955dfecf96Smrg if (!atom->ext) 12965dfecf96Smrg length += LispWriteChar(stream, ':'); 12975dfecf96Smrg } 12985dfecf96Smrg } 12995dfecf96Smrg } 13005dfecf96Smrg if (atom->unreadable) 13015dfecf96Smrg length += LispWriteChar(stream, '|'); 13025dfecf96Smrg length += LispDoWriteAtom(stream, id, strlen(id), 13035dfecf96Smrg atom->unreadable ? UPCASE : info->print_case); 13045dfecf96Smrg if (atom->unreadable) 13055dfecf96Smrg length += LispWriteChar(stream, '|'); 13065dfecf96Smrg 13075dfecf96Smrg return (length); 13085dfecf96Smrg} 13095dfecf96Smrg 13105dfecf96Smrgstatic int 13115dfecf96SmrgLispWriteInteger(LispObj *stream, LispObj *object) 13125dfecf96Smrg{ 13135dfecf96Smrg return (LispFormatInteger(stream, object, 10, 0, 0, 0, 0, 0, 0)); 13145dfecf96Smrg} 13155dfecf96Smrg 13165dfecf96Smrgstatic int 13175dfecf96SmrgLispWriteCharacter(LispObj *stream, LispObj *object, write_info *info) 13185dfecf96Smrg{ 13195dfecf96Smrg return (LispFormatCharacter(stream, object, !info->print_escape, 0)); 13205dfecf96Smrg} 13215dfecf96Smrg 13225dfecf96Smrgstatic int 13235dfecf96SmrgLispWriteString(LispObj *stream, LispObj *object, write_info *info) 13245dfecf96Smrg{ 13255dfecf96Smrg return (LispWriteCString(stream, THESTR(object), STRLEN(object), info)); 13265dfecf96Smrg} 13275dfecf96Smrg 13285dfecf96Smrgstatic int 13295dfecf96SmrgLispWriteFloat(LispObj *stream, LispObj *object) 13305dfecf96Smrg{ 13315dfecf96Smrg double value = DFLOAT_VALUE(object); 13325dfecf96Smrg 13335dfecf96Smrg if (value == 0.0 || (fabs(value) < 1.0E7 && fabs(value) > 1.0E-4)) 13345dfecf96Smrg return (LispFormatFixedFloat(stream, object, 0, 0, NULL, 0, 0, 0)); 13355dfecf96Smrg 13365dfecf96Smrg return (LispDoFormatExponentialFloat(stream, object, 0, 0, NULL, 13375dfecf96Smrg 0, 1, 0, ' ', 'E', 0)); 13385dfecf96Smrg} 13395dfecf96Smrg 13405dfecf96Smrgstatic int 13415dfecf96SmrgLispWriteArray(LispObj *stream, LispObj *object, write_info *info) 13425dfecf96Smrg{ 13435dfecf96Smrg int length = 0; 13445dfecf96Smrg long print_level = info->level, circle; 13455dfecf96Smrg 13465dfecf96Smrg if (info->circles && (circle = LispCheckCircle(object, info)) >= 0 && 13475dfecf96Smrg LispPrintCircle(stream, object, circle, &length, info) == 0) 13485dfecf96Smrg return (length); 13495dfecf96Smrg 13505dfecf96Smrg if (object->data.array.rank == 0) { 13515dfecf96Smrg length += LispWriteStr(stream, "#0A", 3); 13525dfecf96Smrg length += LispDoWriteObject(stream, object->data.array.list, info, 1); 13535dfecf96Smrg return (length); 13545dfecf96Smrg } 13555dfecf96Smrg 13565dfecf96Smrg INCDEPTH(); 13575dfecf96Smrg ++info->level; 13585dfecf96Smrg if (info->print_level < 0 || info->level <= info->print_level) { 13595dfecf96Smrg if (object->data.array.rank == 1) 13605dfecf96Smrg length += LispWriteStr(stream, "#(", 2); 13615dfecf96Smrg else { 13625dfecf96Smrg char stk[32]; 13635dfecf96Smrg 13645dfecf96Smrg format_integer(stk, object->data.array.rank, 10); 13655dfecf96Smrg length += LispWriteChar(stream, '#'); 13665dfecf96Smrg length += LispWriteStr(stream, stk, strlen(stk)); 13675dfecf96Smrg length += LispWriteStr(stream, "A(", 2); 13685dfecf96Smrg } 13695dfecf96Smrg 13705dfecf96Smrg if (!object->data.array.zero) { 13715dfecf96Smrg long print_length = info->length, local_length = 0; 13725dfecf96Smrg 13735dfecf96Smrg if (object->data.array.rank == 1) { 13745dfecf96Smrg LispObj *ary; 13755dfecf96Smrg long count; 13765dfecf96Smrg 13775dfecf96Smrg for (ary = object->data.array.dim, count = 1; 13785dfecf96Smrg ary != NIL; ary = CDR(ary)) 13795dfecf96Smrg count *= FIXNUM_VALUE(CAR(ary)); 13805dfecf96Smrg for (ary = object->data.array.list; count > 0; 13815dfecf96Smrg ary = CDR(ary), count--) { 13825dfecf96Smrg if (info->print_length < 0 || 13835dfecf96Smrg ++local_length <= info->print_length) { 13845dfecf96Smrg info->length = 0; 13855dfecf96Smrg length += LispDoWriteObject(stream, CAR(ary), info, 1); 13865dfecf96Smrg } 13875dfecf96Smrg else { 13885dfecf96Smrg length += LispWriteStr(stream, "...", 3); 13895dfecf96Smrg break; 13905dfecf96Smrg } 13915dfecf96Smrg if (count - 1 > 0) 13925dfecf96Smrg length += LispWriteChar(stream, ' '); 13935dfecf96Smrg } 13945dfecf96Smrg } 13955dfecf96Smrg else { 13965dfecf96Smrg LispObj *ary; 13975dfecf96Smrg int i, k, rank, *dims, *loop; 13985dfecf96Smrg 13995dfecf96Smrg rank = object->data.array.rank; 14005dfecf96Smrg dims = LispMalloc(sizeof(int) * rank); 14015dfecf96Smrg loop = LispCalloc(1, sizeof(int) * (rank - 1)); 14025dfecf96Smrg 14035dfecf96Smrg /* fill dim */ 14045dfecf96Smrg for (i = 0, ary = object->data.array.dim; ary != NIL; 14055dfecf96Smrg i++, ary = CDR(ary)) 14065dfecf96Smrg dims[i] = FIXNUM_VALUE(CAR(ary)); 14075dfecf96Smrg 14085dfecf96Smrg i = 0; 14095dfecf96Smrg ary = object->data.array.list; 14105dfecf96Smrg while (loop[0] < dims[0]) { 14115dfecf96Smrg if (info->print_length < 0 || 14125dfecf96Smrg local_length < info->print_length) { 14135dfecf96Smrg for (; i < rank - 1; i++) 14145dfecf96Smrg length += LispWriteChar(stream, '('); 14155dfecf96Smrg --i; 14165dfecf96Smrg for (;;) { 14175dfecf96Smrg ++loop[i]; 14185dfecf96Smrg if (i && loop[i] >= dims[i]) 14195dfecf96Smrg loop[i] = 0; 14205dfecf96Smrg else 14215dfecf96Smrg break; 14225dfecf96Smrg --i; 14235dfecf96Smrg } 14245dfecf96Smrg for (k = 0; k < dims[rank - 1] - 1; 14255dfecf96Smrg k++, ary = CDR(ary)) { 14265dfecf96Smrg if (info->print_length < 0 || 14275dfecf96Smrg k < info->print_length) { 14285dfecf96Smrg ++local_length; 14295dfecf96Smrg info->length = 0; 14305dfecf96Smrg length += LispDoWriteObject(stream, 14315dfecf96Smrg CAR(ary), info, 1); 14325dfecf96Smrg length += LispWriteChar(stream, ' '); 14335dfecf96Smrg } 14345dfecf96Smrg } 14355dfecf96Smrg if (info->print_length < 0 || k < info->print_length) { 14365dfecf96Smrg ++local_length; 14375dfecf96Smrg info->length = 0; 14385dfecf96Smrg length += LispDoWriteObject(stream, 14395dfecf96Smrg CAR(ary), info, 0); 14405dfecf96Smrg } 14415dfecf96Smrg else 14425dfecf96Smrg length += LispWriteStr(stream, "...", 3); 14435dfecf96Smrg for (k = rank - 1; k > i; k--) 14445dfecf96Smrg length += LispWriteChar(stream, ')'); 14455dfecf96Smrg if (loop[0] < dims[0]) 14465dfecf96Smrg length += LispWriteChar(stream, ' '); 14475dfecf96Smrg ary = CDR(ary); 14485dfecf96Smrg } 14495dfecf96Smrg else { 14505dfecf96Smrg ++local_length; 14515dfecf96Smrg length += LispWriteStr(stream, "...)", 4); 14525dfecf96Smrg for (; local_length < dims[0] - 1; local_length++) 14535dfecf96Smrg length += LispWriteStr(stream, " ...)", 5); 14545dfecf96Smrg if (local_length <= dims[0]) 14555dfecf96Smrg length += LispWriteStr(stream, " ...", 4); 14565dfecf96Smrg break; 14575dfecf96Smrg } 14585dfecf96Smrg } 14595dfecf96Smrg LispFree(dims); 14605dfecf96Smrg LispFree(loop); 14615dfecf96Smrg } 14625dfecf96Smrg info->length = print_length; 14635dfecf96Smrg } 14645dfecf96Smrg length += LispWriteChar(stream, ')'); 14655dfecf96Smrg } 14665dfecf96Smrg else 14675dfecf96Smrg length += LispWriteChar(stream, '#'); 14685dfecf96Smrg info->level = print_level; 14695dfecf96Smrg DECDEPTH(); 14705dfecf96Smrg 14715dfecf96Smrg return (length); 14725dfecf96Smrg} 14735dfecf96Smrg 14745dfecf96Smrgstatic int 14755dfecf96SmrgLispWriteStruct(LispObj *stream, LispObj *object, write_info *info) 14765dfecf96Smrg{ 14775dfecf96Smrg int length; 14785dfecf96Smrg long circle; 14795dfecf96Smrg LispObj *symbol; 14805dfecf96Smrg LispObj *def = object->data.struc.def; 14815dfecf96Smrg LispObj *field = object->data.struc.fields; 14825dfecf96Smrg 14835dfecf96Smrg if (info->circles && (circle = LispCheckCircle(object, info)) >= 0 && 14845dfecf96Smrg LispPrintCircle(stream, object, circle, &length, info) == 0) 14855dfecf96Smrg return (length); 14865dfecf96Smrg 14875dfecf96Smrg INCDEPTH(); 14885dfecf96Smrg length = LispWriteStr(stream, "#S(", 3); 14895dfecf96Smrg symbol = SYMBOLP(CAR(def)) ? CAR(def) : CAAR(def); 14905dfecf96Smrg length += LispWriteAtom(stream, symbol, info); 14915dfecf96Smrg def = CDR(def); 14925dfecf96Smrg for (; def != NIL; def = CDR(def), field = CDR(field)) { 14935dfecf96Smrg length += LispWriteChar(stream, ' '); 14945dfecf96Smrg symbol = SYMBOLP(CAR(def)) ? CAR(def) : CAAR(def); 14955dfecf96Smrg length += LispWriteAtom(stream, symbol, info); 14965dfecf96Smrg length += LispWriteChar(stream, ' '); 14975dfecf96Smrg length += LispDoWriteObject(stream, CAR(field), info, 1); 14985dfecf96Smrg } 14995dfecf96Smrg length += LispWriteChar(stream, ')'); 15005dfecf96Smrg DECDEPTH(); 15015dfecf96Smrg 15025dfecf96Smrg return (length); 15035dfecf96Smrg} 15045dfecf96Smrg 15055dfecf96Smrgint 15065dfecf96SmrgLispFormatInteger(LispObj *stream, LispObj *object, int radix, 15075dfecf96Smrg int atsign, int collon, int mincol, 15085dfecf96Smrg int padchar, int commachar, int commainterval) 15095dfecf96Smrg{ 15105dfecf96Smrg char stk[128], *str = stk; 15115dfecf96Smrg int i, length, sign, intervals; 15125dfecf96Smrg 15135dfecf96Smrg if (LONGINTP(object)) 15145dfecf96Smrg format_integer(stk, LONGINT_VALUE(object), radix); 15155dfecf96Smrg else { 15165dfecf96Smrg if (mpi_getsize(object->data.mp.integer, radix) >= sizeof(stk)) 15175dfecf96Smrg str = mpi_getstr(NULL, object->data.mp.integer, radix); 15185dfecf96Smrg else 15195dfecf96Smrg mpi_getstr(str, object->data.mp.integer, radix); 15205dfecf96Smrg } 15215dfecf96Smrg 15225dfecf96Smrg sign = *str == '-'; 15235dfecf96Smrg length = strlen(str); 15245dfecf96Smrg 15255dfecf96Smrg /* if collon, update length for the number of commachars to be printed */ 15265dfecf96Smrg if (collon && commainterval > 0 && commachar) { 15275dfecf96Smrg intervals = length / commainterval; 15285dfecf96Smrg length += intervals; 15295dfecf96Smrg } 15305dfecf96Smrg else 15315dfecf96Smrg intervals = 0; 15325dfecf96Smrg 15335dfecf96Smrg /* if sign must be printed, and number is positive */ 15345dfecf96Smrg if (atsign && !sign) 15355dfecf96Smrg ++length; 15365dfecf96Smrg 15375dfecf96Smrg /* if need padding */ 15385dfecf96Smrg if (padchar && mincol > length) 15395dfecf96Smrg LispWriteChars(stream, padchar, mincol - length); 15405dfecf96Smrg 15415dfecf96Smrg /* if need to print number sign */ 15425dfecf96Smrg if (sign || atsign) 15435dfecf96Smrg LispWriteChar(stream, sign ? '-' : '+'); 15445dfecf96Smrg 15455dfecf96Smrg /* if need to print commas to separate groups of numbers */ 15465dfecf96Smrg if (intervals) { 15475dfecf96Smrg int j; 15485dfecf96Smrg char *ptr; 15495dfecf96Smrg 15505dfecf96Smrg i = (length - atsign) - intervals; 15515dfecf96Smrg j = i % commainterval; 15525dfecf96Smrg /* make the loop below easier */ 15535dfecf96Smrg if (j == 0) 15545dfecf96Smrg j = commainterval; 15555dfecf96Smrg i -= j; 15565dfecf96Smrg ptr = str + sign; 15575dfecf96Smrg for (; j > 0; j--, ptr++) 15585dfecf96Smrg LispWriteChar(stream, *ptr); 15595dfecf96Smrg for (; i > 0; i -= commainterval) { 15605dfecf96Smrg LispWriteChar(stream, commachar); 15615dfecf96Smrg for (j = 0; j < commainterval; j++, ptr++) 15625dfecf96Smrg LispWriteChar(stream, *ptr); 15635dfecf96Smrg } 15645dfecf96Smrg } 15655dfecf96Smrg /* else, just print the string */ 15665dfecf96Smrg else 15675dfecf96Smrg LispWriteStr(stream, str + sign, length - sign); 15685dfecf96Smrg 15695dfecf96Smrg /* if number required more than sizeof(stk) bytes */ 15705dfecf96Smrg if (str != stk) 15715dfecf96Smrg LispFree(str); 15725dfecf96Smrg 15735dfecf96Smrg return (length); 15745dfecf96Smrg} 15755dfecf96Smrg 15765dfecf96Smrgint 15775dfecf96SmrgLispFormatRomanInteger(LispObj *stream, long value, int new_roman) 15785dfecf96Smrg{ 15795dfecf96Smrg char stk[32]; 15805dfecf96Smrg int length; 15815dfecf96Smrg 15825dfecf96Smrg length = 0; 15835dfecf96Smrg while (value > 1000) { 15845dfecf96Smrg stk[length++] = 'M'; 15855dfecf96Smrg value -= 1000; 15865dfecf96Smrg } 15875dfecf96Smrg if (new_roman) { 15885dfecf96Smrg if (value >= 900) { 15895dfecf96Smrg strcpy(stk + length, "CM"); 15905dfecf96Smrg length += 2, 15915dfecf96Smrg value -= 900; 15925dfecf96Smrg } 15935dfecf96Smrg else if (value < 500 && value >= 400) { 15945dfecf96Smrg strcpy(stk + length, "CD"); 15955dfecf96Smrg length += 2; 15965dfecf96Smrg value -= 400; 15975dfecf96Smrg } 15985dfecf96Smrg } 15995dfecf96Smrg if (value >= 500) { 16005dfecf96Smrg stk[length++] = 'D'; 16015dfecf96Smrg value -= 500; 16025dfecf96Smrg } 16035dfecf96Smrg while (value >= 100) { 16045dfecf96Smrg stk[length++] = 'C'; 16055dfecf96Smrg value -= 100; 16065dfecf96Smrg } 16075dfecf96Smrg if (new_roman) { 16085dfecf96Smrg if (value >= 90) { 16095dfecf96Smrg strcpy(stk + length, "XC"); 16105dfecf96Smrg length += 2, 16115dfecf96Smrg value -= 90; 16125dfecf96Smrg } 16135dfecf96Smrg else if (value < 50 && value >= 40) { 16145dfecf96Smrg strcpy(stk + length, "XL"); 16155dfecf96Smrg length += 2; 16165dfecf96Smrg value -= 40; 16175dfecf96Smrg } 16185dfecf96Smrg } 16195dfecf96Smrg if (value >= 50) { 16205dfecf96Smrg stk[length++] = 'L'; 16215dfecf96Smrg value -= 50; 16225dfecf96Smrg } 16235dfecf96Smrg while (value >= 10) { 16245dfecf96Smrg stk[length++] = 'X'; 16255dfecf96Smrg value -= 10; 16265dfecf96Smrg } 16275dfecf96Smrg if (new_roman) { 16285dfecf96Smrg if (value == 9) { 16295dfecf96Smrg strcpy(stk + length, "IX"); 16305dfecf96Smrg length += 2, 16315dfecf96Smrg value -= 9; 16325dfecf96Smrg } 16335dfecf96Smrg else if (value == 4) { 16345dfecf96Smrg strcpy(stk + length, "IV"); 16355dfecf96Smrg length += 2; 16365dfecf96Smrg value -= 4; 16375dfecf96Smrg } 16385dfecf96Smrg } 16395dfecf96Smrg if (value >= 5) { 16405dfecf96Smrg stk[length++] = 'V'; 16415dfecf96Smrg value -= 5; 16425dfecf96Smrg } 16435dfecf96Smrg while (value) { 16445dfecf96Smrg stk[length++] = 'I'; 16455dfecf96Smrg --value; 16465dfecf96Smrg } 16475dfecf96Smrg 16485dfecf96Smrg stk[length] = '\0'; 16495dfecf96Smrg 16505dfecf96Smrg return (LispWriteStr(stream, stk, length)); 16515dfecf96Smrg} 16525dfecf96Smrg 16535dfecf96Smrgint 16545dfecf96SmrgLispFormatEnglishInteger(LispObj *stream, long number, int ordinal) 16555dfecf96Smrg{ 16565dfecf96Smrg static char *ds[] = { 16575dfecf96Smrg "", "one", "two", "three", "four", 16585dfecf96Smrg "five", "six", "seven", "eight", "nine", 16595dfecf96Smrg "ten", "eleven", "twelve", "thirteen", "fourteen", 16605dfecf96Smrg "fifteen", "sixteen", "seventeen", "eighteen", "nineteen" 16615dfecf96Smrg }; 16625dfecf96Smrg static char *dsth[] = { 16635dfecf96Smrg "", "first", "second", "third", "fourth", 16645dfecf96Smrg "fifth", "sixth", "seventh", "eighth", "ninth", 16655dfecf96Smrg "tenth", "eleventh", "twelfth", "thirteenth", "fourteenth", 16665dfecf96Smrg "fifteenth", "sixteenth", "seventeenth", "eighteenth", "nineteenth" 16675dfecf96Smrg }; 16685dfecf96Smrg static char *hs[] = { 16695dfecf96Smrg "", "", "twenty", "thirty", "forty", 16705dfecf96Smrg "fifty", "sixty", "seventy", "eighty", "ninety" 16715dfecf96Smrg }; 16725dfecf96Smrg static char *hsth[] = { 16735dfecf96Smrg "", "", "twentieth", "thirtieth", "fortieth", 16745dfecf96Smrg "fiftieth", "sixtieth", "seventieth", "eightieth", "ninetieth" 16755dfecf96Smrg }; 16765dfecf96Smrg static char *ts[] = { 16775dfecf96Smrg "", "thousand", "million" 16785dfecf96Smrg }; 16795dfecf96Smrg static char *tsth[] = { 16805dfecf96Smrg "", "thousandth", "millionth" 16815dfecf96Smrg }; 16825dfecf96Smrg char stk[256]; 16835dfecf96Smrg int length, sign; 16845dfecf96Smrg 16855dfecf96Smrg sign = number < 0; 16865dfecf96Smrg if (sign) 16875dfecf96Smrg number = -number; 16885dfecf96Smrg length = 0; 16895dfecf96Smrg 16905dfecf96Smrg#define SIGNLEN 6 /* strlen("minus ") */ 16915dfecf96Smrg if (sign) { 16925dfecf96Smrg strcpy(stk, "minus "); 16935dfecf96Smrg length += SIGNLEN; 16945dfecf96Smrg } 16955dfecf96Smrg else if (number == 0) { 16965dfecf96Smrg if (ordinal) { 16975dfecf96Smrg strcpy(stk, "zeroth"); 16985dfecf96Smrg length += 6; /* strlen("zeroth") */ 16995dfecf96Smrg } 17005dfecf96Smrg else { 17015dfecf96Smrg strcpy(stk, "zero"); 17025dfecf96Smrg length += 4; /* strlen("zero") */ 17035dfecf96Smrg } 17045dfecf96Smrg } 17055dfecf96Smrg for (;;) { 17065dfecf96Smrg int count, temp; 17075dfecf96Smrg char *t, *h, *d; 17085dfecf96Smrg long value = number; 17095dfecf96Smrg 17105dfecf96Smrg for (count = 0; value >= 1000; value /= 1000, count++) 17115dfecf96Smrg ; 17125dfecf96Smrg 17135dfecf96Smrg t = ds[value / 100]; 17145dfecf96Smrg if (ordinal && !count && (value % 10) == 0) 17155dfecf96Smrg h = hsth[(value % 100) / 10]; 17165dfecf96Smrg else 17175dfecf96Smrg h = hs[(value % 100) / 10]; 17185dfecf96Smrg 17195dfecf96Smrg if (ordinal && !count) 17205dfecf96Smrg d = *h ? dsth[value % 10] : dsth[value % 20]; 17215dfecf96Smrg else 17225dfecf96Smrg d = *h ? ds[value % 10] : ds[value % 20]; 17235dfecf96Smrg 17245dfecf96Smrg if (((!sign && length) || length > SIGNLEN) && (*t || *h || *d)) { 17255dfecf96Smrg if (!ordinal || count || *h || *t) { 17265dfecf96Smrg strcpy(stk + length, ", "); 17275dfecf96Smrg length += 2; 17285dfecf96Smrg } 17295dfecf96Smrg else { 17305dfecf96Smrg strcpy(stk + length, " "); 17315dfecf96Smrg ++length; 17325dfecf96Smrg } 17335dfecf96Smrg } 17345dfecf96Smrg 17355dfecf96Smrg if (*t) { 17365dfecf96Smrg if (ordinal && !count && (value % 100) == 0) 17375dfecf96Smrg temp = sprintf(stk + length, "%s hundredth", t); 17385dfecf96Smrg else 17395dfecf96Smrg temp = sprintf(stk + length, "%s hundred", t); 17405dfecf96Smrg length += temp; 17415dfecf96Smrg } 17425dfecf96Smrg 17435dfecf96Smrg if (*h) { 17445dfecf96Smrg if (*t) { 17455dfecf96Smrg if (ordinal && !count) { 17465dfecf96Smrg strcpy(stk + length, " "); 17475dfecf96Smrg ++length; 17485dfecf96Smrg } 17495dfecf96Smrg else { 17505dfecf96Smrg strcpy(stk + length, " and "); 17515dfecf96Smrg length += 5; /* strlen(" and ") */ 17525dfecf96Smrg } 17535dfecf96Smrg } 17545dfecf96Smrg strcpy(stk + length, h); 17555dfecf96Smrg length += strlen(h); 17565dfecf96Smrg } 17575dfecf96Smrg 17585dfecf96Smrg if (*d) { 17595dfecf96Smrg if (*h) { 17605dfecf96Smrg strcpy(stk + length, "-"); 17615dfecf96Smrg ++length; 17625dfecf96Smrg } 17635dfecf96Smrg else if (*t) { 17645dfecf96Smrg if (ordinal && !count) { 17655dfecf96Smrg strcpy(stk + length, " "); 17665dfecf96Smrg ++length; 17675dfecf96Smrg } 17685dfecf96Smrg else { 17695dfecf96Smrg strcpy(stk + length, " and "); 17705dfecf96Smrg length += 5; /* strlen(" and ") */ 17715dfecf96Smrg } 17725dfecf96Smrg } 17735dfecf96Smrg strcpy(stk + length, d); 17745dfecf96Smrg length += strlen(d); 17755dfecf96Smrg } 17765dfecf96Smrg 17775dfecf96Smrg if (!count) 17785dfecf96Smrg break; 17795dfecf96Smrg else 17805dfecf96Smrg temp = count; 17815dfecf96Smrg 17825dfecf96Smrg if (count > 1) { 17835dfecf96Smrg value *= 1000; 17845dfecf96Smrg while (--count) 17855dfecf96Smrg value *= 1000; 17865dfecf96Smrg number -= value; 17875dfecf96Smrg } 17885dfecf96Smrg else 17895dfecf96Smrg number %= 1000; 17905dfecf96Smrg 17915dfecf96Smrg if (ordinal && number == 0 && !*t && !*h) 17925dfecf96Smrg temp = sprintf(stk + length, " %s", tsth[temp]); 17935dfecf96Smrg else 17945dfecf96Smrg temp = sprintf(stk + length, " %s", ts[temp]); 17955dfecf96Smrg length += temp; 17965dfecf96Smrg 17975dfecf96Smrg if (!number) 17985dfecf96Smrg break; 17995dfecf96Smrg } 18005dfecf96Smrg 18015dfecf96Smrg return (LispWriteStr(stream, stk, length)); 18025dfecf96Smrg} 18035dfecf96Smrg 18045dfecf96Smrgint 18055dfecf96SmrgLispFormatCharacter(LispObj *stream, LispObj *object, 18065dfecf96Smrg int atsign, int collon) 18075dfecf96Smrg{ 18085dfecf96Smrg int length = 0; 18095dfecf96Smrg int ch = SCHAR_VALUE(object); 18105dfecf96Smrg 18115dfecf96Smrg if (atsign && !collon) 18125dfecf96Smrg length += LispWriteStr(stream, "#\\", 2); 18135dfecf96Smrg if ((atsign || collon) && (ch <= ' ' || ch == 0177)) { 18145dfecf96Smrg char *name = LispChars[ch].names[0]; 18155dfecf96Smrg 18165dfecf96Smrg length += LispWriteStr(stream, name, strlen(name)); 18175dfecf96Smrg } 18185dfecf96Smrg else 18195dfecf96Smrg length += LispWriteChar(stream, ch); 18205dfecf96Smrg 18215dfecf96Smrg return (length); 18225dfecf96Smrg} 18235dfecf96Smrg 18245dfecf96Smrg/* returns 1 if string size must grow, done inplace */ 18255dfecf96Smrgstatic int 18265dfecf96Smrgfloat_string_inc(char *buffer, int offset) 18275dfecf96Smrg{ 18285dfecf96Smrg int i; 18295dfecf96Smrg 18305dfecf96Smrg for (i = offset; i >= 0; i--) { 18315dfecf96Smrg if (buffer[i] == '9') 18325dfecf96Smrg buffer[i] = '0'; 18335dfecf96Smrg else if (buffer[i] != '.') { 18345dfecf96Smrg ++buffer[i]; 18355dfecf96Smrg break; 18365dfecf96Smrg } 18375dfecf96Smrg } 18385dfecf96Smrg if (i < 0) { 18395dfecf96Smrg int length = strlen(buffer); 18405dfecf96Smrg 18415dfecf96Smrg /* string size must change */ 18425dfecf96Smrg memmove(buffer + 1, buffer, length + 1); 18435dfecf96Smrg buffer[0] = '1'; 18445dfecf96Smrg 18455dfecf96Smrg return (1); 18465dfecf96Smrg } 18475dfecf96Smrg 18485dfecf96Smrg return (0); 18495dfecf96Smrg} 18505dfecf96Smrg 18515dfecf96Smrgint 18525dfecf96SmrgLispFormatFixedFloat(LispObj *stream, LispObj *object, 18535dfecf96Smrg int atsign, int w, int *pd, int k, int overflowchar, 18545dfecf96Smrg int padchar) 18555dfecf96Smrg{ 18565dfecf96Smrg char buffer[512], stk[64]; 18575dfecf96Smrg int sign, exponent, length, offset, d = pd ? *pd : FLOAT_PREC, again; 18585dfecf96Smrg double value = DFLOAT_VALUE(object); 18595dfecf96Smrg 18605dfecf96Smrg if (value == 0.0) { 18615dfecf96Smrg exponent = k = 0; 18625dfecf96Smrg strcpy(stk, "+0"); 18635dfecf96Smrg } 18645dfecf96Smrg else 18655dfecf96Smrg /* calculate format parameters, adjusting scale factor */ 18665dfecf96Smrg parse_double(stk, &exponent, value, d + 1 + k); 18675dfecf96Smrg 18685dfecf96Smrg /* make sure k won't cause overflow */ 18695dfecf96Smrg if (k > 128) 18705dfecf96Smrg k = 128; 18715dfecf96Smrg else if (k < -128) 18725dfecf96Smrg k = -128; 18735dfecf96Smrg 18745dfecf96Smrg /* make sure d won't cause overflow */ 18755dfecf96Smrg if (d > 128) 18765dfecf96Smrg d = 128; 18775dfecf96Smrg else if (d < -128) 18785dfecf96Smrg d = -128; 18795dfecf96Smrg 18805dfecf96Smrg /* adjust scale factor, exponent is used as an index in stk */ 18815dfecf96Smrg exponent += k + 1; 18825dfecf96Smrg 18835dfecf96Smrg /* how many bytes in float representation */ 18845dfecf96Smrg length = strlen(stk) - 1; 18855dfecf96Smrg 18865dfecf96Smrg /* need to print a sign? */ 18875dfecf96Smrg sign = atsign || (stk[0] == '-'); 18885dfecf96Smrg 18895dfecf96Smrg /* format number, cannot overflow, as control variables were checked */ 18905dfecf96Smrg offset = 0; 18915dfecf96Smrg if (sign) 18925dfecf96Smrg buffer[offset++] = stk[0]; 18935dfecf96Smrg if (exponent > 0) { 18945dfecf96Smrg if (exponent > length) { 18955dfecf96Smrg memcpy(buffer + offset, stk + 1, length); 18965dfecf96Smrg memset(buffer + offset + length, '0', exponent - length); 18975dfecf96Smrg } 18985dfecf96Smrg else 18995dfecf96Smrg memcpy(buffer + offset, stk + 1, exponent); 19005dfecf96Smrg offset += exponent; 19015dfecf96Smrg buffer[offset++] = '.'; 19025dfecf96Smrg if (length > exponent) { 19035dfecf96Smrg memcpy(buffer + offset, stk + 1 + exponent, length - exponent); 19045dfecf96Smrg offset += length - exponent; 19055dfecf96Smrg } 19065dfecf96Smrg else 19075dfecf96Smrg buffer[offset++] = '0'; 19085dfecf96Smrg } 19095dfecf96Smrg else { 19105dfecf96Smrg buffer[offset++] = '0'; 19115dfecf96Smrg buffer[offset++] = '.'; 19125dfecf96Smrg while (exponent < 0) { 19135dfecf96Smrg buffer[offset++] = '0'; 19145dfecf96Smrg exponent++; 19155dfecf96Smrg } 19165dfecf96Smrg memcpy(buffer + offset, stk + 1, length); 19175dfecf96Smrg offset += length; 19185dfecf96Smrg } 19195dfecf96Smrg buffer[offset] = '\0'; 19205dfecf96Smrg 19215dfecf96Smrg again = 0; 19225dfecf96Smrgfixed_float_check_again: 19235dfecf96Smrg /* make sure only d digits are printed after decimal point */ 19245dfecf96Smrg if (d > 0) { 19255dfecf96Smrg char *dptr = strchr(buffer, '.'); 19265dfecf96Smrg 19275dfecf96Smrg length = strlen(dptr) - 1; 19285dfecf96Smrg /* check if need to remove excess digits */ 19295dfecf96Smrg if (length > d) { 19305dfecf96Smrg int digit; 19315dfecf96Smrg 19325dfecf96Smrg offset = (dptr - buffer) + 1 + d; 19335dfecf96Smrg digit = buffer[offset]; 19345dfecf96Smrg 19355dfecf96Smrg /* remove extra digits */ 19365dfecf96Smrg buffer[offset] = '\0'; 19375dfecf96Smrg 19385dfecf96Smrg /* check if need to round */ 19395dfecf96Smrg if (!again && offset > 1 && isdigit(digit) && digit >= '5' && 19405dfecf96Smrg isdigit(buffer[offset - 1]) && 19415dfecf96Smrg float_string_inc(buffer, offset - 1)) 19425dfecf96Smrg ++offset; 19435dfecf96Smrg } 19445dfecf96Smrg /* check if need to add extra zero digits to fill space */ 19455dfecf96Smrg else if (length < d) { 19465dfecf96Smrg offset += d - length; 19475dfecf96Smrg for (++length; length <= d; length++) 19485dfecf96Smrg dptr[length] = '0'; 19495dfecf96Smrg dptr[length] = '\0'; 19505dfecf96Smrg } 19515dfecf96Smrg } 19525dfecf96Smrg else { 19535dfecf96Smrg /* no digits after decimal point */ 19545dfecf96Smrg int digit, inc = 0; 19555dfecf96Smrg char *dptr = strchr(buffer, '.') + 1; 19565dfecf96Smrg 19575dfecf96Smrg digit = *dptr; 19585dfecf96Smrg if (!again && digit >= '5' && dptr >= buffer + 2 && isdigit(dptr[-2])) 19595dfecf96Smrg inc = float_string_inc(buffer, dptr - buffer - 2); 19605dfecf96Smrg 19615dfecf96Smrg offset = (dptr - buffer) + inc; 19625dfecf96Smrg buffer[offset] = '\0'; 19635dfecf96Smrg } 19645dfecf96Smrg 19655dfecf96Smrg /* if d was not specified, remove any extra zeros */ 19665dfecf96Smrg if (pd == NULL) { 19675dfecf96Smrg while (offset > 2 && buffer[offset - 2] != '.' && 19685dfecf96Smrg buffer[offset - 1] == '0') 19695dfecf96Smrg --offset; 19705dfecf96Smrg buffer[offset] = '\0'; 19715dfecf96Smrg } 19725dfecf96Smrg 19735dfecf96Smrg if (w > 0 && offset > w) { 19745dfecf96Smrg /* first check if can remove extra fractional digits */ 19755dfecf96Smrg if (pd == NULL) { 19765dfecf96Smrg char *ptr = strchr(buffer, '.') + 1; 19775dfecf96Smrg 19785dfecf96Smrg if (ptr - buffer < w) { 19795dfecf96Smrg d = w - (ptr - buffer); 19805dfecf96Smrg goto fixed_float_check_again; 19815dfecf96Smrg } 19825dfecf96Smrg } 19835dfecf96Smrg 19845dfecf96Smrg /* remove leading "zero" to save space */ 19855dfecf96Smrg if ((!sign && buffer[0] == '0') || (sign && buffer[1] == '0')) { 19865dfecf96Smrg /* ending nul also copied */ 19875dfecf96Smrg memmove(buffer + sign, buffer + sign + 1, offset); 19885dfecf96Smrg --offset; 19895dfecf96Smrg } 19905dfecf96Smrg /* remove leading '+' to "save" space */ 19915dfecf96Smrg if (offset > w && buffer[0] == '+') { 19925dfecf96Smrg /* ending nul also copied */ 19935dfecf96Smrg memmove(buffer, buffer + 1, offset); 19945dfecf96Smrg --offset; 19955dfecf96Smrg } 19965dfecf96Smrg } 19975dfecf96Smrg 19985dfecf96Smrg /* if cannot represent number in given width */ 19995dfecf96Smrg if (overflowchar && offset > w) { 20005dfecf96Smrg again = 1; 20015dfecf96Smrg goto fixed_float_overflow; 20025dfecf96Smrg } 20035dfecf96Smrg 20045dfecf96Smrg length = 0; 20055dfecf96Smrg /* print padding if required */ 20065dfecf96Smrg if (w > offset) 20075dfecf96Smrg length += LispWriteChars(stream, padchar, w - offset); 20085dfecf96Smrg 20095dfecf96Smrg /* print float number representation */ 20105dfecf96Smrg return (LispWriteStr(stream, buffer, offset) + length); 20115dfecf96Smrg 20125dfecf96Smrgfixed_float_overflow: 20135dfecf96Smrg return (LispWriteChars(stream, overflowchar, w)); 20145dfecf96Smrg} 20155dfecf96Smrg 20165dfecf96Smrgint 20175dfecf96SmrgLispFormatExponentialFloat(LispObj *stream, LispObj *object, 20185dfecf96Smrg int atsign, int w, int *pd, int e, int k, 20195dfecf96Smrg int overflowchar, int padchar, int exponentchar) 20205dfecf96Smrg{ 20215dfecf96Smrg return (LispDoFormatExponentialFloat(stream, object, atsign, w, 20225dfecf96Smrg pd, e, k, overflowchar, padchar, 20235dfecf96Smrg exponentchar, 1)); 20245dfecf96Smrg} 20255dfecf96Smrg 20265dfecf96Smrgint 20275dfecf96SmrgLispDoFormatExponentialFloat(LispObj *stream, LispObj *object, 20285dfecf96Smrg int atsign, int w, int *pd, int e, int k, 20295dfecf96Smrg int overflowchar, int padchar, int exponentchar, 20305dfecf96Smrg int format) 20315dfecf96Smrg{ 20325dfecf96Smrg char buffer[512], stk[64]; 20335dfecf96Smrg int sign, exponent, length, offset, d = pd ? *pd : FLOAT_PREC; 20345dfecf96Smrg double value = DFLOAT_VALUE(object); 20355dfecf96Smrg 20365dfecf96Smrg if (value == 0.0) { 20375dfecf96Smrg exponent = 0; 20385dfecf96Smrg k = 1; 20395dfecf96Smrg strcpy(stk, "+0"); 20405dfecf96Smrg } 20415dfecf96Smrg else 20425dfecf96Smrg /* calculate format parameters, adjusting scale factor */ 20435dfecf96Smrg parse_double(stk, &exponent, value, d + k - 1); 20445dfecf96Smrg 20455dfecf96Smrg /* set e to a value that won't overflow */ 20465dfecf96Smrg if (e > 16) 20475dfecf96Smrg e = 16; 20485dfecf96Smrg 20495dfecf96Smrg /* set k to a value that won't overflow */ 20505dfecf96Smrg if (k > 128) 20515dfecf96Smrg k = 128; 20525dfecf96Smrg else if (k < -128) 20535dfecf96Smrg k = -128; 20545dfecf96Smrg 20555dfecf96Smrg /* set d to a value that won't overflow */ 20565dfecf96Smrg if (d > 128) 20575dfecf96Smrg d = 128; 20585dfecf96Smrg else if (d < -128) 20595dfecf96Smrg d = -128; 20605dfecf96Smrg 20615dfecf96Smrg /* how many bytes in float representation */ 20625dfecf96Smrg length = strlen(stk) - 1; 20635dfecf96Smrg 20645dfecf96Smrg /* need to print a sign? */ 20655dfecf96Smrg sign = atsign || (stk[0] == '-'); 20665dfecf96Smrg 20675dfecf96Smrg /* adjust number of digits after decimal point */ 20685dfecf96Smrg if (k > 0) 20695dfecf96Smrg d -= k - 1; 20705dfecf96Smrg 20715dfecf96Smrg /* adjust exponent, based on scale factor */ 20725dfecf96Smrg exponent -= k - 1; 20735dfecf96Smrg 20745dfecf96Smrg /* format number, cannot overflow, as control variables were checked */ 20755dfecf96Smrg offset = 0; 20765dfecf96Smrg if (sign) 20775dfecf96Smrg buffer[offset++] = stk[0]; 20785dfecf96Smrg if (k > 0) { 20795dfecf96Smrg if (k > length) { 20805dfecf96Smrg memcpy(buffer + offset, stk + 1, length); 20815dfecf96Smrg offset += length; 20825dfecf96Smrg } 20835dfecf96Smrg else { 20845dfecf96Smrg memcpy(buffer + offset, stk + 1, k); 20855dfecf96Smrg offset += k; 20865dfecf96Smrg } 20875dfecf96Smrg buffer[offset++] = '.'; 20885dfecf96Smrg if (length > k) { 20895dfecf96Smrg memcpy(buffer + offset, stk + 1 + k, length - k); 20905dfecf96Smrg offset += length - k; 20915dfecf96Smrg } 20925dfecf96Smrg else 20935dfecf96Smrg buffer[offset++] = '0'; 20945dfecf96Smrg } 20955dfecf96Smrg else { 20965dfecf96Smrg int tmp = k; 20975dfecf96Smrg 20985dfecf96Smrg buffer[offset++] = '0'; 20995dfecf96Smrg buffer[offset++] = '.'; 21005dfecf96Smrg while (tmp < 0) { 21015dfecf96Smrg buffer[offset++] = '0'; 21025dfecf96Smrg tmp++; 21035dfecf96Smrg } 21045dfecf96Smrg memcpy(buffer + offset, stk + 1, length); 21055dfecf96Smrg offset += length; 21065dfecf96Smrg } 21075dfecf96Smrg 21085dfecf96Smrg /* if format, then always add a sign to exponent */ 21095dfecf96Smrg buffer[offset++] = exponentchar; 21105dfecf96Smrg if (format || exponent < 0) 21115dfecf96Smrg buffer[offset++] = exponent < 0 ? '-' : '+'; 21125dfecf96Smrg 21135dfecf96Smrg /* XXX destroy stk contents */ 21145dfecf96Smrg sprintf(stk, "%%0%dd", e); 21155dfecf96Smrg /* format scale factor*/ 21165dfecf96Smrg length = sprintf(buffer + offset, stk, 21175dfecf96Smrg exponent < 0 ? -exponent : exponent); 21185dfecf96Smrg /* check for overflow in exponent */ 21195dfecf96Smrg if (length > e && overflowchar) 21205dfecf96Smrg goto exponential_float_overflow; 21215dfecf96Smrg offset += length; 21225dfecf96Smrg 21235dfecf96Smrg /* make sure only d digits are printed after decimal point */ 21245dfecf96Smrg if (d > 0) { 21255dfecf96Smrg int currd; 21265dfecf96Smrg char *dptr = strchr(buffer, '.'), 21275dfecf96Smrg *eptr = strchr(dptr, exponentchar); 21285dfecf96Smrg 21295dfecf96Smrg currd = eptr - dptr - 1; 21305dfecf96Smrg length = strlen(eptr); 21315dfecf96Smrg 21325dfecf96Smrg /* check if need to remove excess digits */ 21335dfecf96Smrg if (currd > d) { 21345dfecf96Smrg int digit, dpos; 21355dfecf96Smrg 21365dfecf96Smrg dpos = offset = (dptr - buffer) + 1 + d; 21375dfecf96Smrg digit = buffer[offset]; 21385dfecf96Smrg 21395dfecf96Smrg memmove(buffer + offset, eptr, length + 1); 21405dfecf96Smrg /* also copy ending nul character */ 21415dfecf96Smrg 21425dfecf96Smrg /* adjust offset to length of total string */ 21435dfecf96Smrg offset += length; 21445dfecf96Smrg 21455dfecf96Smrg /* check if need to round */ 21465dfecf96Smrg if (dpos > 1 && isdigit(digit) && digit >= '5' && 21475dfecf96Smrg isdigit(buffer[dpos - 1]) && 21485dfecf96Smrg float_string_inc(buffer, dpos - 1)) 21495dfecf96Smrg ++offset; 21505dfecf96Smrg } 21515dfecf96Smrg /* check if need to add extra zero digits to fill space */ 21525dfecf96Smrg else if (pd && currd < d) { 21535dfecf96Smrg memmove(eptr + d - currd, eptr, length + 1); 21545dfecf96Smrg /* also copy ending nul character */ 21555dfecf96Smrg 21565dfecf96Smrg offset += d - currd; 21575dfecf96Smrg for (++currd; currd <= d; currd++) 21585dfecf96Smrg dptr[currd] = '0'; 21595dfecf96Smrg } 21605dfecf96Smrg /* check if need to remove zeros */ 21615dfecf96Smrg else if (pd == NULL) { 21625dfecf96Smrg int zeros = 1; 21635dfecf96Smrg 21645dfecf96Smrg while (eptr[-zeros] == '0') 21655dfecf96Smrg ++zeros; 21665dfecf96Smrg if (eptr[-zeros] == '.') 21675dfecf96Smrg --zeros; 21685dfecf96Smrg if (zeros > 1) { 21695dfecf96Smrg memmove(eptr - zeros + 1, eptr, length + 1); 21705dfecf96Smrg offset -= zeros - 1; 21715dfecf96Smrg } 21725dfecf96Smrg } 21735dfecf96Smrg } 21745dfecf96Smrg else { 21755dfecf96Smrg /* no digits after decimal point */ 21765dfecf96Smrg int digit, inc = 0; 21775dfecf96Smrg char *dptr = strchr(buffer, '.'), 21785dfecf96Smrg *eptr = strchr(dptr, exponentchar); 21795dfecf96Smrg 21805dfecf96Smrg digit = dptr[1]; 21815dfecf96Smrg 21825dfecf96Smrg offset = (dptr - buffer) + 1; 21835dfecf96Smrg length = strlen(eptr); 21845dfecf96Smrg memmove(buffer + offset, eptr, length + 1); 21855dfecf96Smrg /* also copy ending nul character */ 21865dfecf96Smrg 21875dfecf96Smrg if (digit >= '5' && dptr >= buffer + 2 && 21885dfecf96Smrg isdigit(dptr[-2])) 21895dfecf96Smrg inc = float_string_inc(buffer, dptr - buffer - 2); 21905dfecf96Smrg 21915dfecf96Smrg /* adjust offset to length of total string */ 21925dfecf96Smrg offset += length + inc; 21935dfecf96Smrg } 21945dfecf96Smrg 21955dfecf96Smrg if (w > 0 && offset > w) { 21965dfecf96Smrg /* remove leading "zero" to save space */ 21975dfecf96Smrg if ((!sign && buffer[0] == '0') || (sign && buffer[1] == '0')) { 21985dfecf96Smrg /* ending nul also copied */ 21995dfecf96Smrg memmove(buffer + sign, buffer + sign + 1, offset); 22005dfecf96Smrg --offset; 22015dfecf96Smrg } 22025dfecf96Smrg /* remove leading '+' to "save" space */ 22035dfecf96Smrg if (offset > w && buffer[0] == '+') { 22045dfecf96Smrg /* ending nul also copied */ 22055dfecf96Smrg memmove(buffer, buffer + 1, offset); 22065dfecf96Smrg --offset; 22075dfecf96Smrg } 22085dfecf96Smrg } 22095dfecf96Smrg 22105dfecf96Smrg /* if cannot represent number in given width */ 22115dfecf96Smrg if (overflowchar && offset > w) 22125dfecf96Smrg goto exponential_float_overflow; 22135dfecf96Smrg 22145dfecf96Smrg length = 0; 22155dfecf96Smrg /* print padding if required */ 22165dfecf96Smrg if (w > offset) 22175dfecf96Smrg length += LispWriteChars(stream, padchar, w - offset); 22185dfecf96Smrg 22195dfecf96Smrg /* print float number representation */ 22205dfecf96Smrg return (LispWriteStr(stream, buffer, offset) + length); 22215dfecf96Smrg 22225dfecf96Smrgexponential_float_overflow: 22235dfecf96Smrg return (LispWriteChars(stream, overflowchar, w)); 22245dfecf96Smrg} 22255dfecf96Smrg 22265dfecf96Smrgint 22275dfecf96SmrgLispFormatGeneralFloat(LispObj *stream, LispObj *object, 22285dfecf96Smrg int atsign, int w, int *pd, int e, int k, 22295dfecf96Smrg int overflowchar, int padchar, int exponentchar) 22305dfecf96Smrg{ 22315dfecf96Smrg char stk[64]; 22325dfecf96Smrg int length, exponent, n, dd, ee, ww, d = pd ? *pd : FLOAT_PREC; 22335dfecf96Smrg double value = DFLOAT_VALUE(object); 22345dfecf96Smrg 22355dfecf96Smrg if (value == 0.0) { 22365dfecf96Smrg exponent = 0; 22375dfecf96Smrg n = 0; 22385dfecf96Smrg d = 1; 22395dfecf96Smrg strcpy(stk, "+0"); 22405dfecf96Smrg } 22415dfecf96Smrg else { 22425dfecf96Smrg /* calculate format parameters, adjusting scale factor */ 22435dfecf96Smrg parse_double(stk, &exponent, value, d + k - 1); 22445dfecf96Smrg n = exponent + 1; 22455dfecf96Smrg } 22465dfecf96Smrg 22475dfecf96Smrg /* Let ee equal e+2, or 4 if e is omitted. */ 22485dfecf96Smrg if (e) 22495dfecf96Smrg ee = e + 2; 22505dfecf96Smrg else 22515dfecf96Smrg ee = 4; 22525dfecf96Smrg 22535dfecf96Smrg /* Let ww equal w-ee, or nil if w is omitted. */ 22545dfecf96Smrg if (w) 22555dfecf96Smrg ww = w - ee; 22565dfecf96Smrg else 22575dfecf96Smrg ww = 0; 22585dfecf96Smrg 22595dfecf96Smrg dd = d - n; 22605dfecf96Smrg if (d >= dd && dd >= 0) { 22615dfecf96Smrg length = LispFormatFixedFloat(stream, object, atsign, ww, 22625dfecf96Smrg &dd, 0, overflowchar, padchar); 22635dfecf96Smrg 22645dfecf96Smrg /* ~ee@T */ 22655dfecf96Smrg length += LispWriteChars(stream, padchar, ee); 22665dfecf96Smrg } 22675dfecf96Smrg else 22685dfecf96Smrg length = LispFormatExponentialFloat(stream, object, atsign, 22695dfecf96Smrg w, pd, e, k, overflowchar, 22705dfecf96Smrg padchar, exponentchar); 22715dfecf96Smrg 22725dfecf96Smrg return (length); 22735dfecf96Smrg} 22745dfecf96Smrg 22755dfecf96Smrgint 22765dfecf96SmrgLispFormatDollarFloat(LispObj *stream, LispObj *object, 22775dfecf96Smrg int atsign, int collon, int d, int n, int w, int padchar) 22785dfecf96Smrg{ 22795dfecf96Smrg char buffer[512], stk[64]; 22805dfecf96Smrg int sign, exponent, length, offset; 22815dfecf96Smrg double value = DFLOAT_VALUE(object); 22825dfecf96Smrg 22835dfecf96Smrg if (value == 0.0) { 22845dfecf96Smrg exponent = 0; 22855dfecf96Smrg strcpy(stk, "+0"); 22865dfecf96Smrg } 22875dfecf96Smrg else 22885dfecf96Smrg /* calculate format parameters, adjusting scale factor */ 22895dfecf96Smrg parse_double(stk, &exponent, value, d == 0 ? FLOAT_PREC : d + 1); 22905dfecf96Smrg 22915dfecf96Smrg /* set d to a "sane" value */ 22925dfecf96Smrg if (d > 128) 22935dfecf96Smrg d = 128; 22945dfecf96Smrg 22955dfecf96Smrg /* set n to a "sane" value */ 22965dfecf96Smrg if (n > 128) 22975dfecf96Smrg n = 128; 22985dfecf96Smrg 22995dfecf96Smrg /* use exponent as index in stk */ 23005dfecf96Smrg ++exponent; 23015dfecf96Smrg 23025dfecf96Smrg /* don't put sign in buffer, 23035dfecf96Smrg * if collon specified, must go before padding */ 23045dfecf96Smrg sign = atsign || (stk[0] == '-'); 23055dfecf96Smrg 23065dfecf96Smrg offset = 0; 23075dfecf96Smrg 23085dfecf96Smrg /* pad with zeros if required */ 23095dfecf96Smrg if (exponent > 0) 23105dfecf96Smrg n -= exponent; 23115dfecf96Smrg while (n > 0) { 23125dfecf96Smrg buffer[offset++] = '0'; 23135dfecf96Smrg n--; 23145dfecf96Smrg } 23155dfecf96Smrg 23165dfecf96Smrg /* how many bytes in float representation */ 23175dfecf96Smrg length = strlen(stk) - 1; 23185dfecf96Smrg 23195dfecf96Smrg if (exponent > 0) { 23205dfecf96Smrg if (exponent > length) { 23215dfecf96Smrg memcpy(buffer + offset, stk + 1, length); 23225dfecf96Smrg memset(buffer + offset + length, '0', exponent - length); 23235dfecf96Smrg } 23245dfecf96Smrg else 23255dfecf96Smrg memcpy(buffer + offset, stk + 1, exponent); 23265dfecf96Smrg offset += exponent; 23275dfecf96Smrg buffer[offset++] = '.'; 23285dfecf96Smrg if (length > exponent) { 23295dfecf96Smrg memcpy(buffer + offset, stk + 1 + exponent, length - exponent); 23305dfecf96Smrg offset += length - exponent; 23315dfecf96Smrg } 23325dfecf96Smrg else 23335dfecf96Smrg buffer[offset++] = '0'; 23345dfecf96Smrg } 23355dfecf96Smrg else { 23365dfecf96Smrg if (n > 0) 23375dfecf96Smrg buffer[offset++] = '0'; 23385dfecf96Smrg buffer[offset++] = '.'; 23395dfecf96Smrg while (exponent < 0) { 23405dfecf96Smrg buffer[offset++] = '0'; 23415dfecf96Smrg exponent++; 23425dfecf96Smrg } 23435dfecf96Smrg memcpy(buffer + offset, stk + 1, length); 23445dfecf96Smrg offset += length; 23455dfecf96Smrg } 23465dfecf96Smrg buffer[offset] = '\0'; 23475dfecf96Smrg 23485dfecf96Smrg /* make sure only d digits are printed after decimal point */ 23495dfecf96Smrg if (d > 0) { 23505dfecf96Smrg char *dptr = strchr(buffer, '.'); 23515dfecf96Smrg 23525dfecf96Smrg length = strlen(dptr) - 1; 23535dfecf96Smrg /* check if need to remove excess digits */ 23545dfecf96Smrg if (length > d) { 23555dfecf96Smrg int digit; 23565dfecf96Smrg 23575dfecf96Smrg offset = (dptr - buffer) + 1 + d; 23585dfecf96Smrg digit = buffer[offset]; 23595dfecf96Smrg 23605dfecf96Smrg /* remove extra digits */ 23615dfecf96Smrg buffer[offset] = '\0'; 23625dfecf96Smrg 23635dfecf96Smrg /* check if need to round */ 23645dfecf96Smrg if (offset > 1 && isdigit(digit) && digit >= '5' && 23655dfecf96Smrg isdigit(buffer[offset - 1]) && 23665dfecf96Smrg float_string_inc(buffer, offset - 1)) 23675dfecf96Smrg ++offset; 23685dfecf96Smrg } 23695dfecf96Smrg /* check if need to add extra zero digits to fill space */ 23705dfecf96Smrg else if (length < d) { 23715dfecf96Smrg offset += d - length; 23725dfecf96Smrg for (++length; length <= d; length++) 23735dfecf96Smrg dptr[length] = '0'; 23745dfecf96Smrg dptr[length] = '\0'; 23755dfecf96Smrg } 23765dfecf96Smrg } 23775dfecf96Smrg else { 23785dfecf96Smrg /* no digits after decimal point */ 23795dfecf96Smrg int digit, inc = 0; 23805dfecf96Smrg char *dptr = strchr(buffer, '.') + 1; 23815dfecf96Smrg 23825dfecf96Smrg digit = *dptr; 23835dfecf96Smrg if (digit >= '5' && dptr >= buffer + 2 && isdigit(dptr[-2])) 23845dfecf96Smrg inc = float_string_inc(buffer, dptr - buffer - 2); 23855dfecf96Smrg 23865dfecf96Smrg offset = (dptr - buffer) + inc; 23875dfecf96Smrg buffer[offset] = '\0'; 23885dfecf96Smrg } 23895dfecf96Smrg 23905dfecf96Smrg length = 0; 23915dfecf96Smrg if (sign) { 23925dfecf96Smrg ++offset; 23935dfecf96Smrg if (atsign && collon) 23945dfecf96Smrg length += LispWriteChar(stream, value >= 0.0 ? '+' : '-'); 23955dfecf96Smrg } 23965dfecf96Smrg 23975dfecf96Smrg /* print padding if required */ 23985dfecf96Smrg if (w > offset) 23995dfecf96Smrg length += LispWriteChars(stream, padchar, w - offset); 24005dfecf96Smrg 24015dfecf96Smrg if (atsign && !collon) 24025dfecf96Smrg length += LispWriteChar(stream, value >= 0.0 ? '+' : '-'); 24035dfecf96Smrg 24045dfecf96Smrg /* print float number representation */ 24055dfecf96Smrg return (LispWriteStr(stream, buffer, offset) + length); 24065dfecf96Smrg} 2407