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*); 93f765521fSmrgstatic int LispDoWriteAtom(LispObj*, const 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{ 525f14f4646Smrg Atom_id name; 5265dfecf96Smrg int i, length = 0, need_space = 0; 5275dfecf96Smrg 5285dfecf96Smrg#define WRITE_ATOM(object) \ 5295dfecf96Smrg name = ATOMID(object); \ 530f14f4646Smrg length += LispDoWriteAtom(stream, name->value, name->length, \ 5315dfecf96Smrg info->print_case) 532f14f4646Smrg#define WRITE_ATOMID(atomid) \ 533f14f4646Smrg length += LispDoWriteAtom(stream, atomid->value, atomid->length, \ 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(); 555f14f4646Smrg WRITE_ATOMID(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(); 575f14f4646Smrg length += LispDoWriteAtom(stream, Skey->value, 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(); 602f14f4646Smrg WRITE_ATOMID(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(); 610f14f4646Smrg WRITE_ATOMID(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 625f14f4646Smrg#undef WRITE_ATOMID 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; 864f765521fSmrg char stk[64]; 865f765521fSmrg const char *string = NULL; 8665dfecf96Smrg 8675dfecf96Smrgwrite_again: 8685dfecf96Smrg switch (OBJECT_TYPE(object)) { 8695dfecf96Smrg case LispNil_t: 8705dfecf96Smrg if (object == NIL) 871f14f4646Smrg string = Snil->value; 8725dfecf96Smrg else if (object == T) 873f14f4646Smrg string = St->value; 8745dfecf96Smrg else if (object == DOT) 8755dfecf96Smrg string = "#<DOT>"; 8765dfecf96Smrg else if (object == UNSPEC) 8775dfecf96Smrg string = "#<UNSPEC>"; 8785dfecf96Smrg else if (object == UNBOUND) 8795dfecf96Smrg string = "#<UNBOUND>"; 8805dfecf96Smrg else 8815dfecf96Smrg string = "#<ERROR>"; 8825dfecf96Smrg length += LispDoWriteAtom(stream, string, strlen(string), 8835dfecf96Smrg info->print_case); 8845dfecf96Smrg break; 8855dfecf96Smrg case LispOpaque_t: { 8865dfecf96Smrg char *desc = LispIntToOpaqueType(object->data.opaque.type); 8875dfecf96Smrg 8885dfecf96Smrg length += LispWriteChar(stream, '#'); 8895dfecf96Smrg length += LispWriteCPointer(stream, object->data.opaque.data); 8905dfecf96Smrg length += LispWriteStr(stream, desc, strlen(desc)); 8915dfecf96Smrg } break; 8925dfecf96Smrg case LispAtom_t: 8935dfecf96Smrg length += LispWriteAtom(stream, object, info); 8945dfecf96Smrg break; 8955dfecf96Smrg case LispFunction_t: 8965dfecf96Smrg if (object->data.atom->a_function) { 8975dfecf96Smrg object = object->data.atom->property->fun.function; 8985dfecf96Smrg goto write_lambda; 8995dfecf96Smrg } 9005dfecf96Smrg length += LispWriteStr(stream, "#<", 2); 9015dfecf96Smrg if (object->data.atom->a_compiled) 9025dfecf96Smrg LispDoWriteAtom(stream, "COMPILED", 8, info->print_case); 9035dfecf96Smrg else if (object->data.atom->a_builtin) 9045dfecf96Smrg LispDoWriteAtom(stream, "BUILTIN", 7, info->print_case); 9055dfecf96Smrg /* XXX the function does not exist anymore */ 9065dfecf96Smrg /* FIXME not sure if I want this fixed... */ 9075dfecf96Smrg else 9085dfecf96Smrg LispDoWriteAtom(stream, "UNBOUND", 7, info->print_case); 9095dfecf96Smrg LispDoWriteAtom(stream, "-FUNCTION", 9, info->print_case); 9105dfecf96Smrg length += LispWriteChar(stream, ' '); 9115dfecf96Smrg length += LispWriteAtom(stream, object->data.atom->object, info); 9125dfecf96Smrg length += LispWriteChar(stream, '>'); 9135dfecf96Smrg break; 9145dfecf96Smrg case LispString_t: 9155dfecf96Smrg length += LispWriteString(stream, object, info); 9165dfecf96Smrg break; 9175dfecf96Smrg case LispSChar_t: 9185dfecf96Smrg length += LispWriteCharacter(stream, object, info); 9195dfecf96Smrg break; 9205dfecf96Smrg case LispDFloat_t: 9215dfecf96Smrg length += LispWriteFloat(stream, object); 9225dfecf96Smrg break; 9235dfecf96Smrg case LispFixnum_t: 9245dfecf96Smrg case LispInteger_t: 9255dfecf96Smrg case LispBignum_t: 9265dfecf96Smrg length += LispWriteInteger(stream, object); 9275dfecf96Smrg break; 9285dfecf96Smrg case LispRatio_t: 9295dfecf96Smrg format_integer(stk, object->data.ratio.numerator, 10); 9305dfecf96Smrg length += LispWriteStr(stream, stk, strlen(stk)); 9315dfecf96Smrg length += LispWriteChar(stream, '/'); 9325dfecf96Smrg format_integer(stk, object->data.ratio.denominator, 10); 9335dfecf96Smrg length += LispWriteStr(stream, stk, strlen(stk)); 9345dfecf96Smrg break; 9355dfecf96Smrg case LispBigratio_t: { 9365dfecf96Smrg int sz; 9375dfecf96Smrg char *ptr; 9385dfecf96Smrg 9395dfecf96Smrg sz = mpi_getsize(mpr_num(object->data.mp.ratio), 10) + 1 + 9405dfecf96Smrg mpi_getsize(mpr_den(object->data.mp.ratio), 10) + 1 + 9415dfecf96Smrg (mpi_sgn(mpr_num(object->data.mp.ratio)) < 0); 9425dfecf96Smrg if (sz > sizeof(stk)) 9435dfecf96Smrg ptr = LispMalloc(sz); 9445dfecf96Smrg else 9455dfecf96Smrg ptr = stk; 9465dfecf96Smrg mpr_getstr(ptr, object->data.mp.ratio, 10); 9475dfecf96Smrg length += LispWriteStr(stream, ptr, sz - 1); 9485dfecf96Smrg if (ptr != stk) 9495dfecf96Smrg LispFree(ptr); 9505dfecf96Smrg } break; 9515dfecf96Smrg case LispComplex_t: 9525dfecf96Smrg length += LispWriteStr(stream, "#C(", 3); 9535dfecf96Smrg length += LispDoWriteObject(stream, 9545dfecf96Smrg object->data.complex.real, info, 0); 9555dfecf96Smrg length += LispWriteChar(stream, ' '); 9565dfecf96Smrg length += LispDoWriteObject(stream, 9575dfecf96Smrg object->data.complex.imag, info, 0); 9585dfecf96Smrg length += LispWriteChar(stream, ')'); 9595dfecf96Smrg break; 9605dfecf96Smrg case LispCons_t: 9615dfecf96Smrg print_level = info->level; 9625dfecf96Smrg ++info->level; 9635dfecf96Smrg length += LispWriteList(stream, object, info, paren); 9645dfecf96Smrg info->level = print_level; 9655dfecf96Smrg break; 9665dfecf96Smrg case LispQuote_t: 9675dfecf96Smrg length += LispWriteChar(stream, '\''); 9685dfecf96Smrg paren = 1; 9695dfecf96Smrg object = object->data.quote; 9705dfecf96Smrg goto write_again; 9715dfecf96Smrg case LispBackquote_t: 9725dfecf96Smrg length += LispWriteChar(stream, '`'); 9735dfecf96Smrg paren = 1; 9745dfecf96Smrg object = object->data.quote; 9755dfecf96Smrg goto write_again; 9765dfecf96Smrg case LispComma_t: 9775dfecf96Smrg if (object->data.comma.atlist) 9785dfecf96Smrg length += LispWriteStr(stream, ",@", 2); 9795dfecf96Smrg else 9805dfecf96Smrg length += LispWriteChar(stream, ','); 9815dfecf96Smrg paren = 1; 9825dfecf96Smrg object = object->data.comma.eval; 9835dfecf96Smrg goto write_again; 9845dfecf96Smrg break; 9855dfecf96Smrg case LispFunctionQuote_t: 9865dfecf96Smrg length += LispWriteStr(stream, "#'", 2); 9875dfecf96Smrg paren = 1; 9885dfecf96Smrg object = object->data.quote; 9895dfecf96Smrg goto write_again; 9905dfecf96Smrg case LispArray_t: 9915dfecf96Smrg length += LispWriteArray(stream, object, info); 9925dfecf96Smrg break; 9935dfecf96Smrg case LispStruct_t: 9945dfecf96Smrg length += LispWriteStruct(stream, object, info); 9955dfecf96Smrg break; 9965dfecf96Smrg case LispLambda_t: 9975dfecf96Smrg write_lambda: 9985dfecf96Smrg switch (object->funtype) { 9995dfecf96Smrg case LispLambda: 10005dfecf96Smrg string = "#<LAMBDA "; 10015dfecf96Smrg break; 10025dfecf96Smrg case LispFunction: 10035dfecf96Smrg string = "#<FUNCTION "; 10045dfecf96Smrg break; 10055dfecf96Smrg case LispMacro: 10065dfecf96Smrg string = "#<MACRO "; 10075dfecf96Smrg break; 10085dfecf96Smrg case LispSetf: 10095dfecf96Smrg string = "#<SETF "; 10105dfecf96Smrg break; 10115dfecf96Smrg } 10125dfecf96Smrg length += LispDoWriteAtom(stream, string, strlen(string), 10135dfecf96Smrg info->print_case); 10145dfecf96Smrg if (object->funtype != LispLambda) { 10155dfecf96Smrg length += LispWriteAtom(stream, object->data.lambda.name, info); 10165dfecf96Smrg length += LispWriteChar(stream, ' '); 10175dfecf96Smrg length += LispWriteAlist(stream, object->data.lambda.name 10185dfecf96Smrg ->data.atom->property->alist, info); 10195dfecf96Smrg } 10205dfecf96Smrg else { 1021f14f4646Smrg length += LispDoWriteAtom(stream, "NIL", 3, info->print_case); 10225dfecf96Smrg length += LispWriteChar(stream, ' '); 10235dfecf96Smrg length += LispWriteAlist(stream, (LispArgList*)object-> 10245dfecf96Smrg data.lambda.name->data.opaque.data, 10255dfecf96Smrg info); 10265dfecf96Smrg } 10275dfecf96Smrg length += LispWriteChar(stream, ' '); 10285dfecf96Smrg length += LispDoWriteObject(stream, 10295dfecf96Smrg object->data.lambda.code, info, 0); 10305dfecf96Smrg length += LispWriteChar(stream, '>'); 10315dfecf96Smrg break; 10325dfecf96Smrg case LispStream_t: 10335dfecf96Smrg length += LispWriteStr(stream, "#<", 2); 10345dfecf96Smrg if (object->data.stream.type == LispStreamFile) 10355dfecf96Smrg string = "FILE-STREAM "; 10365dfecf96Smrg else if (object->data.stream.type == LispStreamString) 10375dfecf96Smrg string = "STRING-STREAM "; 10385dfecf96Smrg else if (object->data.stream.type == LispStreamStandard) 10395dfecf96Smrg string = "STANDARD-STREAM "; 10405dfecf96Smrg else if (object->data.stream.type == LispStreamPipe) 10415dfecf96Smrg string = "PIPE-STREAM "; 10425dfecf96Smrg length += LispDoWriteAtom(stream, string, strlen(string), 10435dfecf96Smrg info->print_case); 10445dfecf96Smrg 10455dfecf96Smrg if (!object->data.stream.readable && !object->data.stream.writable) 10465dfecf96Smrg length += LispDoWriteAtom(stream, "CLOSED", 10475dfecf96Smrg 6, info->print_case); 10485dfecf96Smrg else { 10495dfecf96Smrg if (object->data.stream.readable) 10505dfecf96Smrg length += LispDoWriteAtom(stream, "READ", 10515dfecf96Smrg 4, info->print_case); 10525dfecf96Smrg if (object->data.stream.writable) { 10535dfecf96Smrg if (object->data.stream.readable) 10545dfecf96Smrg length += LispWriteChar(stream, '-'); 10555dfecf96Smrg length += LispDoWriteAtom(stream, "WRITE", 10565dfecf96Smrg 5, info->print_case); 10575dfecf96Smrg } 10585dfecf96Smrg } 10595dfecf96Smrg if (object->data.stream.type != LispStreamString) { 10605dfecf96Smrg length += LispWriteChar(stream, ' '); 10615dfecf96Smrg length += LispDoWriteObject(stream, 10625dfecf96Smrg object->data.stream.pathname, 10635dfecf96Smrg info, 1); 10645dfecf96Smrg /* same address/size for pipes */ 10655dfecf96Smrg length += LispWriteChar(stream, ' '); 10665dfecf96Smrg length += LispWriteCPointer(stream, 10675dfecf96Smrg object->data.stream.source.file); 10685dfecf96Smrg if (object->data.stream.readable && 10695dfecf96Smrg object->data.stream.type == LispStreamFile && 10705dfecf96Smrg !object->data.stream.source.file->binary) { 10715dfecf96Smrg length += LispWriteStr(stream, " @", 2); 10725dfecf96Smrg format_integer(stk, object->data.stream.source.file->line, 10); 10735dfecf96Smrg length += LispWriteStr(stream, stk, strlen(stk)); 10745dfecf96Smrg } 10755dfecf96Smrg } 10765dfecf96Smrg length += LispWriteChar(stream, '>'); 10775dfecf96Smrg break; 10785dfecf96Smrg case LispPathname_t: 10795dfecf96Smrg length += LispWriteStr(stream, "#P", 2); 10805dfecf96Smrg paren = 1; 10815dfecf96Smrg object = CAR(object->data.quote); 10825dfecf96Smrg goto write_again; 10835dfecf96Smrg case LispPackage_t: 10845dfecf96Smrg length += LispDoWriteAtom(stream, "#<PACKAGE ", 10855dfecf96Smrg 10, info->print_case); 10865dfecf96Smrg length += LispWriteStr(stream, 10875dfecf96Smrg THESTR(object->data.package.name), 10885dfecf96Smrg STRLEN(object->data.package.name)); 10895dfecf96Smrg length += LispWriteChar(stream, '>'); 10905dfecf96Smrg break; 10915dfecf96Smrg case LispRegex_t: 10925dfecf96Smrg length += LispDoWriteAtom(stream, "#<REGEX ", 10935dfecf96Smrg 8, info->print_case); 10945dfecf96Smrg length += LispDoWriteObject(stream, 10955dfecf96Smrg object->data.regex.pattern, info, 1); 10965dfecf96Smrg if (object->data.regex.options & RE_NOSPEC) 10975dfecf96Smrg length += LispDoWriteAtom(stream, " :NOSPEC", 10985dfecf96Smrg 8, info->print_case); 10995dfecf96Smrg if (object->data.regex.options & RE_ICASE) 11005dfecf96Smrg length += LispDoWriteAtom(stream, " :ICASE", 11015dfecf96Smrg 7, info->print_case); 11025dfecf96Smrg if (object->data.regex.options & RE_NOSUB) 11035dfecf96Smrg length += LispDoWriteAtom(stream, " :NOSUB", 11045dfecf96Smrg 7, info->print_case); 11055dfecf96Smrg if (object->data.regex.options & RE_NEWLINE) 11065dfecf96Smrg length += LispDoWriteAtom(stream, " :NEWLINE", 11075dfecf96Smrg 9, info->print_case); 11085dfecf96Smrg length += LispWriteChar(stream, '>'); 11095dfecf96Smrg break; 11105dfecf96Smrg case LispBytecode_t: 11115dfecf96Smrg length += LispDoWriteAtom(stream, "#<BYTECODE ", 11125dfecf96Smrg 11, info->print_case); 11135dfecf96Smrg length += LispWriteCPointer(stream, 11145dfecf96Smrg object->data.bytecode.bytecode); 11155dfecf96Smrg length += LispWriteChar(stream, '>'); 11165dfecf96Smrg break; 11175dfecf96Smrg case LispHashTable_t: 11185dfecf96Smrg length += LispDoWriteAtom(stream, "#<HASH-TABLE ", 11195dfecf96Smrg 13, info->print_case); 11205dfecf96Smrg length += LispWriteAtom(stream, object->data.hash.test, info); 11215dfecf96Smrg snprintf(stk, sizeof(stk), " %g %g", 11225dfecf96Smrg object->data.hash.table->rehash_size, 11235dfecf96Smrg object->data.hash.table->rehash_threshold); 11245dfecf96Smrg length += LispWriteStr(stream, stk, strlen(stk)); 11255dfecf96Smrg snprintf(stk, sizeof(stk), " %ld/%ld>", 11265dfecf96Smrg object->data.hash.table->count, 11275dfecf96Smrg object->data.hash.table->num_entries); 11285dfecf96Smrg length += LispWriteStr(stream, stk, strlen(stk)); 11295dfecf96Smrg break; 11305dfecf96Smrg } 11315dfecf96Smrg 11325dfecf96Smrg return (length); 11335dfecf96Smrg} 11345dfecf96Smrg 11355dfecf96Smrg/* return current column number in stream */ 11365dfecf96Smrgint 11375dfecf96SmrgLispGetColumn(LispObj *stream) 11385dfecf96Smrg{ 11395dfecf96Smrg LispFile *file; 11405dfecf96Smrg LispString *string; 11415dfecf96Smrg 11425dfecf96Smrg check_stream(stream, &file, &string, 0); 11435dfecf96Smrg if (file != NULL) 11445dfecf96Smrg return (file->column); 11455dfecf96Smrg return (string->column); 11465dfecf96Smrg} 11475dfecf96Smrg 11485dfecf96Smrg/* write a character to stream */ 11495dfecf96Smrgint 11505dfecf96SmrgLispWriteChar(LispObj *stream, int character) 11515dfecf96Smrg{ 11525dfecf96Smrg LispFile *file; 11535dfecf96Smrg LispString *string; 11545dfecf96Smrg 11555dfecf96Smrg check_stream(stream, &file, &string, 1); 11565dfecf96Smrg if (file != NULL) 11575dfecf96Smrg return (LispFputc(file, character)); 11585dfecf96Smrg 11595dfecf96Smrg return (LispSputc(string, character)); 11605dfecf96Smrg} 11615dfecf96Smrg 11625dfecf96Smrg/* write a character count times to stream */ 11635dfecf96Smrgint 11645dfecf96SmrgLispWriteChars(LispObj *stream, int character, int count) 11655dfecf96Smrg{ 11665dfecf96Smrg int length = 0; 11675dfecf96Smrg 11685dfecf96Smrg if (count > 0) { 11695dfecf96Smrg char stk[64]; 11705dfecf96Smrg LispFile *file; 11715dfecf96Smrg LispString *string; 11725dfecf96Smrg 11735dfecf96Smrg check_stream(stream, &file, &string, 1); 11745dfecf96Smrg if (count >= sizeof(stk)) { 11755dfecf96Smrg memset(stk, character, sizeof(stk)); 11765dfecf96Smrg for (; count >= sizeof(stk); count -= sizeof(stk)) { 11775dfecf96Smrg if (file != NULL) 11785dfecf96Smrg length += LispFwrite(file, stk, sizeof(stk)); 11795dfecf96Smrg else 11805dfecf96Smrg length += LispSwrite(string, stk, sizeof(stk)); 11815dfecf96Smrg } 11825dfecf96Smrg } 11835dfecf96Smrg else 11845dfecf96Smrg memset(stk, character, count); 11855dfecf96Smrg 11865dfecf96Smrg if (count) { 11875dfecf96Smrg if (file != NULL) 11885dfecf96Smrg length += LispFwrite(file, stk, count); 11895dfecf96Smrg else 11905dfecf96Smrg length += LispSwrite(string, stk, count); 11915dfecf96Smrg } 11925dfecf96Smrg } 11935dfecf96Smrg 11945dfecf96Smrg return (length); 11955dfecf96Smrg} 11965dfecf96Smrg 11975dfecf96Smrg/* write a string to stream */ 11985dfecf96Smrgint 1199f765521fSmrgLispWriteStr(LispObj *stream, const char *buffer, long length) 12005dfecf96Smrg{ 12015dfecf96Smrg LispFile *file; 12025dfecf96Smrg LispString *string; 12035dfecf96Smrg 12045dfecf96Smrg check_stream(stream, &file, &string, 1); 12055dfecf96Smrg if (file != NULL) 12065dfecf96Smrg return (LispFwrite(file, buffer, length)); 12075dfecf96Smrg return (LispSwrite(string, buffer, length)); 12085dfecf96Smrg} 12095dfecf96Smrg 12105dfecf96Smrgstatic int 1211f765521fSmrgLispDoWriteAtom(LispObj *stream, const char *string, int length, int print_case) 12125dfecf96Smrg{ 12135dfecf96Smrg int bytes = 0, cap = 0; 12145dfecf96Smrg char buffer[128], *ptr; 12155dfecf96Smrg 12165dfecf96Smrg switch (print_case) { 12175dfecf96Smrg case DOWNCASE: 12185dfecf96Smrg for (ptr = buffer; length > 0; length--, string++) { 12195dfecf96Smrg if (isupper(*string)) 12205dfecf96Smrg *ptr = tolower(*string); 12215dfecf96Smrg else 12225dfecf96Smrg *ptr = *string; 12235dfecf96Smrg ++ptr; 12245dfecf96Smrg if (ptr - buffer >= sizeof(buffer)) { 12255dfecf96Smrg bytes += LispWriteStr(stream, buffer, ptr - buffer); 12265dfecf96Smrg ptr = buffer; 12275dfecf96Smrg } 12285dfecf96Smrg } 12295dfecf96Smrg if (ptr > buffer) 12305dfecf96Smrg bytes += LispWriteStr(stream, buffer, ptr - buffer); 12315dfecf96Smrg break; 12325dfecf96Smrg case CAPITALIZE: 12335dfecf96Smrg for (ptr = buffer; length > 0; length--, string++) { 12345dfecf96Smrg if (isalnum(*string)) { 12355dfecf96Smrg if (cap && isupper(*string)) 12365dfecf96Smrg *ptr = tolower(*string); 12375dfecf96Smrg else 12385dfecf96Smrg *ptr = *string; 12395dfecf96Smrg cap = 1; 12405dfecf96Smrg } 12415dfecf96Smrg else { 12425dfecf96Smrg *ptr = *string; 12435dfecf96Smrg cap = 0; 12445dfecf96Smrg } 12455dfecf96Smrg ++ptr; 12465dfecf96Smrg if (ptr - buffer >= sizeof(buffer)) { 12475dfecf96Smrg bytes += LispWriteStr(stream, buffer, ptr - buffer); 12485dfecf96Smrg ptr = buffer; 12495dfecf96Smrg } 12505dfecf96Smrg } 12515dfecf96Smrg if (ptr > buffer) 12525dfecf96Smrg bytes += LispWriteStr(stream, buffer, ptr - buffer); 12535dfecf96Smrg break; 12545dfecf96Smrg default: 12555dfecf96Smrg /* Strings are already stored upcase/quoted */ 12565dfecf96Smrg bytes += LispWriteStr(stream, string, length); 12575dfecf96Smrg break; 12585dfecf96Smrg } 12595dfecf96Smrg 12605dfecf96Smrg return (bytes); 12615dfecf96Smrg} 12625dfecf96Smrg 12635dfecf96Smrgstatic int 12645dfecf96SmrgLispWriteAtom(LispObj *stream, LispObj *object, write_info *info) 12655dfecf96Smrg{ 12665dfecf96Smrg int length = 0; 12675dfecf96Smrg LispAtom *atom = object->data.atom; 1268f14f4646Smrg Atom_id id = atom->key; 12695dfecf96Smrg 12705dfecf96Smrg if (atom->package != PACKAGE) { 12715dfecf96Smrg if (atom->package == lisp__data.keyword) 12725dfecf96Smrg length += LispWriteChar(stream, ':'); 12735dfecf96Smrg else if (atom->package == NULL) 12745dfecf96Smrg length += LispWriteStr(stream, "#:", 2); 12755dfecf96Smrg else { 12765dfecf96Smrg /* Check if the symbol is visible */ 12775dfecf96Smrg int i, visible = 0; 12785dfecf96Smrg 12795dfecf96Smrg if (atom->ext) { 12805dfecf96Smrg for (i = lisp__data.pack->use.length - 1; i >= 0; i--) { 12815dfecf96Smrg if (lisp__data.pack->use.pairs[i] == atom->package) { 12825dfecf96Smrg visible = 1; 12835dfecf96Smrg break; 12845dfecf96Smrg } 12855dfecf96Smrg } 12865dfecf96Smrg } 12875dfecf96Smrg 12885dfecf96Smrg if (!visible) { 12895dfecf96Smrg /* XXX this assumes that package names are always "readable" */ 12905dfecf96Smrg length += 12915dfecf96Smrg LispDoWriteAtom(stream, 12925dfecf96Smrg THESTR(atom->package->data.package.name), 12935dfecf96Smrg STRLEN(atom->package->data.package.name), 12945dfecf96Smrg info->print_case); 12955dfecf96Smrg length += LispWriteChar(stream, ':'); 12965dfecf96Smrg if (!atom->ext) 12975dfecf96Smrg length += LispWriteChar(stream, ':'); 12985dfecf96Smrg } 12995dfecf96Smrg } 13005dfecf96Smrg } 13015dfecf96Smrg if (atom->unreadable) 13025dfecf96Smrg length += LispWriteChar(stream, '|'); 1303f14f4646Smrg length += LispDoWriteAtom(stream, id->value, id->length, 13045dfecf96Smrg atom->unreadable ? UPCASE : info->print_case); 13055dfecf96Smrg if (atom->unreadable) 13065dfecf96Smrg length += LispWriteChar(stream, '|'); 13075dfecf96Smrg 13085dfecf96Smrg return (length); 13095dfecf96Smrg} 13105dfecf96Smrg 13115dfecf96Smrgstatic int 13125dfecf96SmrgLispWriteInteger(LispObj *stream, LispObj *object) 13135dfecf96Smrg{ 13145dfecf96Smrg return (LispFormatInteger(stream, object, 10, 0, 0, 0, 0, 0, 0)); 13155dfecf96Smrg} 13165dfecf96Smrg 13175dfecf96Smrgstatic int 13185dfecf96SmrgLispWriteCharacter(LispObj *stream, LispObj *object, write_info *info) 13195dfecf96Smrg{ 13205dfecf96Smrg return (LispFormatCharacter(stream, object, !info->print_escape, 0)); 13215dfecf96Smrg} 13225dfecf96Smrg 13235dfecf96Smrgstatic int 13245dfecf96SmrgLispWriteString(LispObj *stream, LispObj *object, write_info *info) 13255dfecf96Smrg{ 13265dfecf96Smrg return (LispWriteCString(stream, THESTR(object), STRLEN(object), info)); 13275dfecf96Smrg} 13285dfecf96Smrg 13295dfecf96Smrgstatic int 13305dfecf96SmrgLispWriteFloat(LispObj *stream, LispObj *object) 13315dfecf96Smrg{ 13325dfecf96Smrg double value = DFLOAT_VALUE(object); 13335dfecf96Smrg 13345dfecf96Smrg if (value == 0.0 || (fabs(value) < 1.0E7 && fabs(value) > 1.0E-4)) 13355dfecf96Smrg return (LispFormatFixedFloat(stream, object, 0, 0, NULL, 0, 0, 0)); 13365dfecf96Smrg 13375dfecf96Smrg return (LispDoFormatExponentialFloat(stream, object, 0, 0, NULL, 13385dfecf96Smrg 0, 1, 0, ' ', 'E', 0)); 13395dfecf96Smrg} 13405dfecf96Smrg 13415dfecf96Smrgstatic int 13425dfecf96SmrgLispWriteArray(LispObj *stream, LispObj *object, write_info *info) 13435dfecf96Smrg{ 13445dfecf96Smrg int length = 0; 13455dfecf96Smrg long print_level = info->level, circle; 13465dfecf96Smrg 13475dfecf96Smrg if (info->circles && (circle = LispCheckCircle(object, info)) >= 0 && 13485dfecf96Smrg LispPrintCircle(stream, object, circle, &length, info) == 0) 13495dfecf96Smrg return (length); 13505dfecf96Smrg 13515dfecf96Smrg if (object->data.array.rank == 0) { 13525dfecf96Smrg length += LispWriteStr(stream, "#0A", 3); 13535dfecf96Smrg length += LispDoWriteObject(stream, object->data.array.list, info, 1); 13545dfecf96Smrg return (length); 13555dfecf96Smrg } 13565dfecf96Smrg 13575dfecf96Smrg INCDEPTH(); 13585dfecf96Smrg ++info->level; 13595dfecf96Smrg if (info->print_level < 0 || info->level <= info->print_level) { 13605dfecf96Smrg if (object->data.array.rank == 1) 13615dfecf96Smrg length += LispWriteStr(stream, "#(", 2); 13625dfecf96Smrg else { 13635dfecf96Smrg char stk[32]; 13645dfecf96Smrg 13655dfecf96Smrg format_integer(stk, object->data.array.rank, 10); 13665dfecf96Smrg length += LispWriteChar(stream, '#'); 13675dfecf96Smrg length += LispWriteStr(stream, stk, strlen(stk)); 13685dfecf96Smrg length += LispWriteStr(stream, "A(", 2); 13695dfecf96Smrg } 13705dfecf96Smrg 13715dfecf96Smrg if (!object->data.array.zero) { 13725dfecf96Smrg long print_length = info->length, local_length = 0; 13735dfecf96Smrg 13745dfecf96Smrg if (object->data.array.rank == 1) { 13755dfecf96Smrg LispObj *ary; 13765dfecf96Smrg long count; 13775dfecf96Smrg 13785dfecf96Smrg for (ary = object->data.array.dim, count = 1; 13795dfecf96Smrg ary != NIL; ary = CDR(ary)) 13805dfecf96Smrg count *= FIXNUM_VALUE(CAR(ary)); 13815dfecf96Smrg for (ary = object->data.array.list; count > 0; 13825dfecf96Smrg ary = CDR(ary), count--) { 13835dfecf96Smrg if (info->print_length < 0 || 13845dfecf96Smrg ++local_length <= info->print_length) { 13855dfecf96Smrg info->length = 0; 13865dfecf96Smrg length += LispDoWriteObject(stream, CAR(ary), info, 1); 13875dfecf96Smrg } 13885dfecf96Smrg else { 13895dfecf96Smrg length += LispWriteStr(stream, "...", 3); 13905dfecf96Smrg break; 13915dfecf96Smrg } 13925dfecf96Smrg if (count - 1 > 0) 13935dfecf96Smrg length += LispWriteChar(stream, ' '); 13945dfecf96Smrg } 13955dfecf96Smrg } 13965dfecf96Smrg else { 13975dfecf96Smrg LispObj *ary; 13985dfecf96Smrg int i, k, rank, *dims, *loop; 13995dfecf96Smrg 14005dfecf96Smrg rank = object->data.array.rank; 14015dfecf96Smrg dims = LispMalloc(sizeof(int) * rank); 14025dfecf96Smrg loop = LispCalloc(1, sizeof(int) * (rank - 1)); 14035dfecf96Smrg 14045dfecf96Smrg /* fill dim */ 14055dfecf96Smrg for (i = 0, ary = object->data.array.dim; ary != NIL; 14065dfecf96Smrg i++, ary = CDR(ary)) 14075dfecf96Smrg dims[i] = FIXNUM_VALUE(CAR(ary)); 14085dfecf96Smrg 14095dfecf96Smrg i = 0; 14105dfecf96Smrg ary = object->data.array.list; 14115dfecf96Smrg while (loop[0] < dims[0]) { 14125dfecf96Smrg if (info->print_length < 0 || 14135dfecf96Smrg local_length < info->print_length) { 14145dfecf96Smrg for (; i < rank - 1; i++) 14155dfecf96Smrg length += LispWriteChar(stream, '('); 14165dfecf96Smrg --i; 14175dfecf96Smrg for (;;) { 14185dfecf96Smrg ++loop[i]; 14195dfecf96Smrg if (i && loop[i] >= dims[i]) 14205dfecf96Smrg loop[i] = 0; 14215dfecf96Smrg else 14225dfecf96Smrg break; 14235dfecf96Smrg --i; 14245dfecf96Smrg } 14255dfecf96Smrg for (k = 0; k < dims[rank - 1] - 1; 14265dfecf96Smrg k++, ary = CDR(ary)) { 14275dfecf96Smrg if (info->print_length < 0 || 14285dfecf96Smrg k < info->print_length) { 14295dfecf96Smrg ++local_length; 14305dfecf96Smrg info->length = 0; 14315dfecf96Smrg length += LispDoWriteObject(stream, 14325dfecf96Smrg CAR(ary), info, 1); 14335dfecf96Smrg length += LispWriteChar(stream, ' '); 14345dfecf96Smrg } 14355dfecf96Smrg } 14365dfecf96Smrg if (info->print_length < 0 || k < info->print_length) { 14375dfecf96Smrg ++local_length; 14385dfecf96Smrg info->length = 0; 14395dfecf96Smrg length += LispDoWriteObject(stream, 14405dfecf96Smrg CAR(ary), info, 0); 14415dfecf96Smrg } 14425dfecf96Smrg else 14435dfecf96Smrg length += LispWriteStr(stream, "...", 3); 14445dfecf96Smrg for (k = rank - 1; k > i; k--) 14455dfecf96Smrg length += LispWriteChar(stream, ')'); 14465dfecf96Smrg if (loop[0] < dims[0]) 14475dfecf96Smrg length += LispWriteChar(stream, ' '); 14485dfecf96Smrg ary = CDR(ary); 14495dfecf96Smrg } 14505dfecf96Smrg else { 14515dfecf96Smrg ++local_length; 14525dfecf96Smrg length += LispWriteStr(stream, "...)", 4); 14535dfecf96Smrg for (; local_length < dims[0] - 1; local_length++) 14545dfecf96Smrg length += LispWriteStr(stream, " ...)", 5); 14555dfecf96Smrg if (local_length <= dims[0]) 14565dfecf96Smrg length += LispWriteStr(stream, " ...", 4); 14575dfecf96Smrg break; 14585dfecf96Smrg } 14595dfecf96Smrg } 14605dfecf96Smrg LispFree(dims); 14615dfecf96Smrg LispFree(loop); 14625dfecf96Smrg } 14635dfecf96Smrg info->length = print_length; 14645dfecf96Smrg } 14655dfecf96Smrg length += LispWriteChar(stream, ')'); 14665dfecf96Smrg } 14675dfecf96Smrg else 14685dfecf96Smrg length += LispWriteChar(stream, '#'); 14695dfecf96Smrg info->level = print_level; 14705dfecf96Smrg DECDEPTH(); 14715dfecf96Smrg 14725dfecf96Smrg return (length); 14735dfecf96Smrg} 14745dfecf96Smrg 14755dfecf96Smrgstatic int 14765dfecf96SmrgLispWriteStruct(LispObj *stream, LispObj *object, write_info *info) 14775dfecf96Smrg{ 14785dfecf96Smrg int length; 14795dfecf96Smrg long circle; 14805dfecf96Smrg LispObj *symbol; 14815dfecf96Smrg LispObj *def = object->data.struc.def; 14825dfecf96Smrg LispObj *field = object->data.struc.fields; 14835dfecf96Smrg 14845dfecf96Smrg if (info->circles && (circle = LispCheckCircle(object, info)) >= 0 && 14855dfecf96Smrg LispPrintCircle(stream, object, circle, &length, info) == 0) 14865dfecf96Smrg return (length); 14875dfecf96Smrg 14885dfecf96Smrg INCDEPTH(); 14895dfecf96Smrg length = LispWriteStr(stream, "#S(", 3); 14905dfecf96Smrg symbol = SYMBOLP(CAR(def)) ? CAR(def) : CAAR(def); 14915dfecf96Smrg length += LispWriteAtom(stream, symbol, info); 14925dfecf96Smrg def = CDR(def); 14935dfecf96Smrg for (; def != NIL; def = CDR(def), field = CDR(field)) { 14945dfecf96Smrg length += LispWriteChar(stream, ' '); 14955dfecf96Smrg symbol = SYMBOLP(CAR(def)) ? CAR(def) : CAAR(def); 14965dfecf96Smrg length += LispWriteAtom(stream, symbol, info); 14975dfecf96Smrg length += LispWriteChar(stream, ' '); 14985dfecf96Smrg length += LispDoWriteObject(stream, CAR(field), info, 1); 14995dfecf96Smrg } 15005dfecf96Smrg length += LispWriteChar(stream, ')'); 15015dfecf96Smrg DECDEPTH(); 15025dfecf96Smrg 15035dfecf96Smrg return (length); 15045dfecf96Smrg} 15055dfecf96Smrg 15065dfecf96Smrgint 15075dfecf96SmrgLispFormatInteger(LispObj *stream, LispObj *object, int radix, 15085dfecf96Smrg int atsign, int collon, int mincol, 15095dfecf96Smrg int padchar, int commachar, int commainterval) 15105dfecf96Smrg{ 15115dfecf96Smrg char stk[128], *str = stk; 15125dfecf96Smrg int i, length, sign, intervals; 15135dfecf96Smrg 15145dfecf96Smrg if (LONGINTP(object)) 15155dfecf96Smrg format_integer(stk, LONGINT_VALUE(object), radix); 15165dfecf96Smrg else { 15175dfecf96Smrg if (mpi_getsize(object->data.mp.integer, radix) >= sizeof(stk)) 15185dfecf96Smrg str = mpi_getstr(NULL, object->data.mp.integer, radix); 15195dfecf96Smrg else 15205dfecf96Smrg mpi_getstr(str, object->data.mp.integer, radix); 15215dfecf96Smrg } 15225dfecf96Smrg 15235dfecf96Smrg sign = *str == '-'; 15245dfecf96Smrg length = strlen(str); 15255dfecf96Smrg 15265dfecf96Smrg /* if collon, update length for the number of commachars to be printed */ 15275dfecf96Smrg if (collon && commainterval > 0 && commachar) { 15285dfecf96Smrg intervals = length / commainterval; 15295dfecf96Smrg length += intervals; 15305dfecf96Smrg } 15315dfecf96Smrg else 15325dfecf96Smrg intervals = 0; 15335dfecf96Smrg 15345dfecf96Smrg /* if sign must be printed, and number is positive */ 15355dfecf96Smrg if (atsign && !sign) 15365dfecf96Smrg ++length; 15375dfecf96Smrg 15385dfecf96Smrg /* if need padding */ 15395dfecf96Smrg if (padchar && mincol > length) 15405dfecf96Smrg LispWriteChars(stream, padchar, mincol - length); 15415dfecf96Smrg 15425dfecf96Smrg /* if need to print number sign */ 15435dfecf96Smrg if (sign || atsign) 15445dfecf96Smrg LispWriteChar(stream, sign ? '-' : '+'); 15455dfecf96Smrg 15465dfecf96Smrg /* if need to print commas to separate groups of numbers */ 15475dfecf96Smrg if (intervals) { 15485dfecf96Smrg int j; 15495dfecf96Smrg char *ptr; 15505dfecf96Smrg 15515dfecf96Smrg i = (length - atsign) - intervals; 15525dfecf96Smrg j = i % commainterval; 15535dfecf96Smrg /* make the loop below easier */ 15545dfecf96Smrg if (j == 0) 15555dfecf96Smrg j = commainterval; 15565dfecf96Smrg i -= j; 15575dfecf96Smrg ptr = str + sign; 15585dfecf96Smrg for (; j > 0; j--, ptr++) 15595dfecf96Smrg LispWriteChar(stream, *ptr); 15605dfecf96Smrg for (; i > 0; i -= commainterval) { 15615dfecf96Smrg LispWriteChar(stream, commachar); 15625dfecf96Smrg for (j = 0; j < commainterval; j++, ptr++) 15635dfecf96Smrg LispWriteChar(stream, *ptr); 15645dfecf96Smrg } 15655dfecf96Smrg } 15665dfecf96Smrg /* else, just print the string */ 15675dfecf96Smrg else 15685dfecf96Smrg LispWriteStr(stream, str + sign, length - sign); 15695dfecf96Smrg 15705dfecf96Smrg /* if number required more than sizeof(stk) bytes */ 15715dfecf96Smrg if (str != stk) 15725dfecf96Smrg LispFree(str); 15735dfecf96Smrg 15745dfecf96Smrg return (length); 15755dfecf96Smrg} 15765dfecf96Smrg 15775dfecf96Smrgint 15785dfecf96SmrgLispFormatRomanInteger(LispObj *stream, long value, int new_roman) 15795dfecf96Smrg{ 15805dfecf96Smrg char stk[32]; 15815dfecf96Smrg int length; 15825dfecf96Smrg 15835dfecf96Smrg length = 0; 15845dfecf96Smrg while (value > 1000) { 15855dfecf96Smrg stk[length++] = 'M'; 15865dfecf96Smrg value -= 1000; 15875dfecf96Smrg } 15885dfecf96Smrg if (new_roman) { 15895dfecf96Smrg if (value >= 900) { 15905dfecf96Smrg strcpy(stk + length, "CM"); 15915dfecf96Smrg length += 2, 15925dfecf96Smrg value -= 900; 15935dfecf96Smrg } 15945dfecf96Smrg else if (value < 500 && value >= 400) { 15955dfecf96Smrg strcpy(stk + length, "CD"); 15965dfecf96Smrg length += 2; 15975dfecf96Smrg value -= 400; 15985dfecf96Smrg } 15995dfecf96Smrg } 16005dfecf96Smrg if (value >= 500) { 16015dfecf96Smrg stk[length++] = 'D'; 16025dfecf96Smrg value -= 500; 16035dfecf96Smrg } 16045dfecf96Smrg while (value >= 100) { 16055dfecf96Smrg stk[length++] = 'C'; 16065dfecf96Smrg value -= 100; 16075dfecf96Smrg } 16085dfecf96Smrg if (new_roman) { 16095dfecf96Smrg if (value >= 90) { 16105dfecf96Smrg strcpy(stk + length, "XC"); 16115dfecf96Smrg length += 2, 16125dfecf96Smrg value -= 90; 16135dfecf96Smrg } 16145dfecf96Smrg else if (value < 50 && value >= 40) { 16155dfecf96Smrg strcpy(stk + length, "XL"); 16165dfecf96Smrg length += 2; 16175dfecf96Smrg value -= 40; 16185dfecf96Smrg } 16195dfecf96Smrg } 16205dfecf96Smrg if (value >= 50) { 16215dfecf96Smrg stk[length++] = 'L'; 16225dfecf96Smrg value -= 50; 16235dfecf96Smrg } 16245dfecf96Smrg while (value >= 10) { 16255dfecf96Smrg stk[length++] = 'X'; 16265dfecf96Smrg value -= 10; 16275dfecf96Smrg } 16285dfecf96Smrg if (new_roman) { 16295dfecf96Smrg if (value == 9) { 16305dfecf96Smrg strcpy(stk + length, "IX"); 16315dfecf96Smrg length += 2, 16325dfecf96Smrg value -= 9; 16335dfecf96Smrg } 16345dfecf96Smrg else if (value == 4) { 16355dfecf96Smrg strcpy(stk + length, "IV"); 16365dfecf96Smrg length += 2; 16375dfecf96Smrg value -= 4; 16385dfecf96Smrg } 16395dfecf96Smrg } 16405dfecf96Smrg if (value >= 5) { 16415dfecf96Smrg stk[length++] = 'V'; 16425dfecf96Smrg value -= 5; 16435dfecf96Smrg } 16445dfecf96Smrg while (value) { 16455dfecf96Smrg stk[length++] = 'I'; 16465dfecf96Smrg --value; 16475dfecf96Smrg } 16485dfecf96Smrg 16495dfecf96Smrg stk[length] = '\0'; 16505dfecf96Smrg 16515dfecf96Smrg return (LispWriteStr(stream, stk, length)); 16525dfecf96Smrg} 16535dfecf96Smrg 16545dfecf96Smrgint 16555dfecf96SmrgLispFormatEnglishInteger(LispObj *stream, long number, int ordinal) 16565dfecf96Smrg{ 1657f765521fSmrg static const char *ds[] = { 16585dfecf96Smrg "", "one", "two", "three", "four", 16595dfecf96Smrg "five", "six", "seven", "eight", "nine", 16605dfecf96Smrg "ten", "eleven", "twelve", "thirteen", "fourteen", 16615dfecf96Smrg "fifteen", "sixteen", "seventeen", "eighteen", "nineteen" 16625dfecf96Smrg }; 1663f765521fSmrg static const char *dsth[] = { 16645dfecf96Smrg "", "first", "second", "third", "fourth", 16655dfecf96Smrg "fifth", "sixth", "seventh", "eighth", "ninth", 16665dfecf96Smrg "tenth", "eleventh", "twelfth", "thirteenth", "fourteenth", 16675dfecf96Smrg "fifteenth", "sixteenth", "seventeenth", "eighteenth", "nineteenth" 16685dfecf96Smrg }; 1669f765521fSmrg static const char *hs[] = { 16705dfecf96Smrg "", "", "twenty", "thirty", "forty", 16715dfecf96Smrg "fifty", "sixty", "seventy", "eighty", "ninety" 16725dfecf96Smrg }; 1673f765521fSmrg static const char *hsth[] = { 16745dfecf96Smrg "", "", "twentieth", "thirtieth", "fortieth", 16755dfecf96Smrg "fiftieth", "sixtieth", "seventieth", "eightieth", "ninetieth" 16765dfecf96Smrg }; 1677f765521fSmrg static const char *ts[] = { 16785dfecf96Smrg "", "thousand", "million" 16795dfecf96Smrg }; 1680f765521fSmrg static const char *tsth[] = { 16815dfecf96Smrg "", "thousandth", "millionth" 16825dfecf96Smrg }; 16835dfecf96Smrg char stk[256]; 16845dfecf96Smrg int length, sign; 16855dfecf96Smrg 16865dfecf96Smrg sign = number < 0; 16875dfecf96Smrg if (sign) 16885dfecf96Smrg number = -number; 16895dfecf96Smrg length = 0; 16905dfecf96Smrg 16915dfecf96Smrg#define SIGNLEN 6 /* strlen("minus ") */ 16925dfecf96Smrg if (sign) { 16935dfecf96Smrg strcpy(stk, "minus "); 16945dfecf96Smrg length += SIGNLEN; 16955dfecf96Smrg } 16965dfecf96Smrg else if (number == 0) { 16975dfecf96Smrg if (ordinal) { 16985dfecf96Smrg strcpy(stk, "zeroth"); 16995dfecf96Smrg length += 6; /* strlen("zeroth") */ 17005dfecf96Smrg } 17015dfecf96Smrg else { 17025dfecf96Smrg strcpy(stk, "zero"); 17035dfecf96Smrg length += 4; /* strlen("zero") */ 17045dfecf96Smrg } 17055dfecf96Smrg } 17065dfecf96Smrg for (;;) { 17075dfecf96Smrg int count, temp; 1708f765521fSmrg const char *t, *h, *d; 17095dfecf96Smrg long value = number; 17105dfecf96Smrg 17115dfecf96Smrg for (count = 0; value >= 1000; value /= 1000, count++) 17125dfecf96Smrg ; 17135dfecf96Smrg 17145dfecf96Smrg t = ds[value / 100]; 17155dfecf96Smrg if (ordinal && !count && (value % 10) == 0) 17165dfecf96Smrg h = hsth[(value % 100) / 10]; 17175dfecf96Smrg else 17185dfecf96Smrg h = hs[(value % 100) / 10]; 17195dfecf96Smrg 17205dfecf96Smrg if (ordinal && !count) 17215dfecf96Smrg d = *h ? dsth[value % 10] : dsth[value % 20]; 17225dfecf96Smrg else 17235dfecf96Smrg d = *h ? ds[value % 10] : ds[value % 20]; 17245dfecf96Smrg 17255dfecf96Smrg if (((!sign && length) || length > SIGNLEN) && (*t || *h || *d)) { 17265dfecf96Smrg if (!ordinal || count || *h || *t) { 17275dfecf96Smrg strcpy(stk + length, ", "); 17285dfecf96Smrg length += 2; 17295dfecf96Smrg } 17305dfecf96Smrg else { 17315dfecf96Smrg strcpy(stk + length, " "); 17325dfecf96Smrg ++length; 17335dfecf96Smrg } 17345dfecf96Smrg } 17355dfecf96Smrg 17365dfecf96Smrg if (*t) { 17375dfecf96Smrg if (ordinal && !count && (value % 100) == 0) 17385dfecf96Smrg temp = sprintf(stk + length, "%s hundredth", t); 17395dfecf96Smrg else 17405dfecf96Smrg temp = sprintf(stk + length, "%s hundred", t); 17415dfecf96Smrg length += temp; 17425dfecf96Smrg } 17435dfecf96Smrg 17445dfecf96Smrg if (*h) { 17455dfecf96Smrg if (*t) { 17465dfecf96Smrg if (ordinal && !count) { 17475dfecf96Smrg strcpy(stk + length, " "); 17485dfecf96Smrg ++length; 17495dfecf96Smrg } 17505dfecf96Smrg else { 17515dfecf96Smrg strcpy(stk + length, " and "); 17525dfecf96Smrg length += 5; /* strlen(" and ") */ 17535dfecf96Smrg } 17545dfecf96Smrg } 17555dfecf96Smrg strcpy(stk + length, h); 17565dfecf96Smrg length += strlen(h); 17575dfecf96Smrg } 17585dfecf96Smrg 17595dfecf96Smrg if (*d) { 17605dfecf96Smrg if (*h) { 17615dfecf96Smrg strcpy(stk + length, "-"); 17625dfecf96Smrg ++length; 17635dfecf96Smrg } 17645dfecf96Smrg else if (*t) { 17655dfecf96Smrg if (ordinal && !count) { 17665dfecf96Smrg strcpy(stk + length, " "); 17675dfecf96Smrg ++length; 17685dfecf96Smrg } 17695dfecf96Smrg else { 17705dfecf96Smrg strcpy(stk + length, " and "); 17715dfecf96Smrg length += 5; /* strlen(" and ") */ 17725dfecf96Smrg } 17735dfecf96Smrg } 17745dfecf96Smrg strcpy(stk + length, d); 17755dfecf96Smrg length += strlen(d); 17765dfecf96Smrg } 17775dfecf96Smrg 17785dfecf96Smrg if (!count) 17795dfecf96Smrg break; 17805dfecf96Smrg else 17815dfecf96Smrg temp = count; 17825dfecf96Smrg 17835dfecf96Smrg if (count > 1) { 17845dfecf96Smrg value *= 1000; 17855dfecf96Smrg while (--count) 17865dfecf96Smrg value *= 1000; 17875dfecf96Smrg number -= value; 17885dfecf96Smrg } 17895dfecf96Smrg else 17905dfecf96Smrg number %= 1000; 17915dfecf96Smrg 17925dfecf96Smrg if (ordinal && number == 0 && !*t && !*h) 17935dfecf96Smrg temp = sprintf(stk + length, " %s", tsth[temp]); 17945dfecf96Smrg else 17955dfecf96Smrg temp = sprintf(stk + length, " %s", ts[temp]); 17965dfecf96Smrg length += temp; 17975dfecf96Smrg 17985dfecf96Smrg if (!number) 17995dfecf96Smrg break; 18005dfecf96Smrg } 18015dfecf96Smrg 18025dfecf96Smrg return (LispWriteStr(stream, stk, length)); 18035dfecf96Smrg} 18045dfecf96Smrg 18055dfecf96Smrgint 18065dfecf96SmrgLispFormatCharacter(LispObj *stream, LispObj *object, 18075dfecf96Smrg int atsign, int collon) 18085dfecf96Smrg{ 18095dfecf96Smrg int length = 0; 18105dfecf96Smrg int ch = SCHAR_VALUE(object); 18115dfecf96Smrg 18125dfecf96Smrg if (atsign && !collon) 18135dfecf96Smrg length += LispWriteStr(stream, "#\\", 2); 18145dfecf96Smrg if ((atsign || collon) && (ch <= ' ' || ch == 0177)) { 1815f765521fSmrg const char *name = LispChars[ch].names[0]; 18165dfecf96Smrg 18175dfecf96Smrg length += LispWriteStr(stream, name, strlen(name)); 18185dfecf96Smrg } 18195dfecf96Smrg else 18205dfecf96Smrg length += LispWriteChar(stream, ch); 18215dfecf96Smrg 18225dfecf96Smrg return (length); 18235dfecf96Smrg} 18245dfecf96Smrg 18255dfecf96Smrg/* returns 1 if string size must grow, done inplace */ 18265dfecf96Smrgstatic int 18275dfecf96Smrgfloat_string_inc(char *buffer, int offset) 18285dfecf96Smrg{ 18295dfecf96Smrg int i; 18305dfecf96Smrg 18315dfecf96Smrg for (i = offset; i >= 0; i--) { 18325dfecf96Smrg if (buffer[i] == '9') 18335dfecf96Smrg buffer[i] = '0'; 18345dfecf96Smrg else if (buffer[i] != '.') { 18355dfecf96Smrg ++buffer[i]; 18365dfecf96Smrg break; 18375dfecf96Smrg } 18385dfecf96Smrg } 18395dfecf96Smrg if (i < 0) { 18405dfecf96Smrg int length = strlen(buffer); 18415dfecf96Smrg 18425dfecf96Smrg /* string size must change */ 18435dfecf96Smrg memmove(buffer + 1, buffer, length + 1); 18445dfecf96Smrg buffer[0] = '1'; 18455dfecf96Smrg 18465dfecf96Smrg return (1); 18475dfecf96Smrg } 18485dfecf96Smrg 18495dfecf96Smrg return (0); 18505dfecf96Smrg} 18515dfecf96Smrg 18525dfecf96Smrgint 18535dfecf96SmrgLispFormatFixedFloat(LispObj *stream, LispObj *object, 18545dfecf96Smrg int atsign, int w, int *pd, int k, int overflowchar, 18555dfecf96Smrg int padchar) 18565dfecf96Smrg{ 18575dfecf96Smrg char buffer[512], stk[64]; 18585dfecf96Smrg int sign, exponent, length, offset, d = pd ? *pd : FLOAT_PREC, again; 18595dfecf96Smrg double value = DFLOAT_VALUE(object); 18605dfecf96Smrg 18615dfecf96Smrg if (value == 0.0) { 18625dfecf96Smrg exponent = k = 0; 18635dfecf96Smrg strcpy(stk, "+0"); 18645dfecf96Smrg } 18655dfecf96Smrg else 18665dfecf96Smrg /* calculate format parameters, adjusting scale factor */ 18675dfecf96Smrg parse_double(stk, &exponent, value, d + 1 + k); 18685dfecf96Smrg 18695dfecf96Smrg /* make sure k won't cause overflow */ 18705dfecf96Smrg if (k > 128) 18715dfecf96Smrg k = 128; 18725dfecf96Smrg else if (k < -128) 18735dfecf96Smrg k = -128; 18745dfecf96Smrg 18755dfecf96Smrg /* make sure d won't cause overflow */ 18765dfecf96Smrg if (d > 128) 18775dfecf96Smrg d = 128; 18785dfecf96Smrg else if (d < -128) 18795dfecf96Smrg d = -128; 18805dfecf96Smrg 18815dfecf96Smrg /* adjust scale factor, exponent is used as an index in stk */ 18825dfecf96Smrg exponent += k + 1; 18835dfecf96Smrg 18845dfecf96Smrg /* how many bytes in float representation */ 18855dfecf96Smrg length = strlen(stk) - 1; 18865dfecf96Smrg 18875dfecf96Smrg /* need to print a sign? */ 18885dfecf96Smrg sign = atsign || (stk[0] == '-'); 18895dfecf96Smrg 18905dfecf96Smrg /* format number, cannot overflow, as control variables were checked */ 18915dfecf96Smrg offset = 0; 18925dfecf96Smrg if (sign) 18935dfecf96Smrg buffer[offset++] = stk[0]; 18945dfecf96Smrg if (exponent > 0) { 18955dfecf96Smrg if (exponent > length) { 18965dfecf96Smrg memcpy(buffer + offset, stk + 1, length); 18975dfecf96Smrg memset(buffer + offset + length, '0', exponent - length); 18985dfecf96Smrg } 18995dfecf96Smrg else 19005dfecf96Smrg memcpy(buffer + offset, stk + 1, exponent); 19015dfecf96Smrg offset += exponent; 19025dfecf96Smrg buffer[offset++] = '.'; 19035dfecf96Smrg if (length > exponent) { 19045dfecf96Smrg memcpy(buffer + offset, stk + 1 + exponent, length - exponent); 19055dfecf96Smrg offset += length - exponent; 19065dfecf96Smrg } 19075dfecf96Smrg else 19085dfecf96Smrg buffer[offset++] = '0'; 19095dfecf96Smrg } 19105dfecf96Smrg else { 19115dfecf96Smrg buffer[offset++] = '0'; 19125dfecf96Smrg buffer[offset++] = '.'; 19135dfecf96Smrg while (exponent < 0) { 19145dfecf96Smrg buffer[offset++] = '0'; 19155dfecf96Smrg exponent++; 19165dfecf96Smrg } 19175dfecf96Smrg memcpy(buffer + offset, stk + 1, length); 19185dfecf96Smrg offset += length; 19195dfecf96Smrg } 19205dfecf96Smrg buffer[offset] = '\0'; 19215dfecf96Smrg 19225dfecf96Smrg again = 0; 19235dfecf96Smrgfixed_float_check_again: 19245dfecf96Smrg /* make sure only d digits are printed after decimal point */ 19255dfecf96Smrg if (d > 0) { 19265dfecf96Smrg char *dptr = strchr(buffer, '.'); 19275dfecf96Smrg 19285dfecf96Smrg length = strlen(dptr) - 1; 19295dfecf96Smrg /* check if need to remove excess digits */ 19305dfecf96Smrg if (length > d) { 19315dfecf96Smrg int digit; 19325dfecf96Smrg 19335dfecf96Smrg offset = (dptr - buffer) + 1 + d; 19345dfecf96Smrg digit = buffer[offset]; 19355dfecf96Smrg 19365dfecf96Smrg /* remove extra digits */ 19375dfecf96Smrg buffer[offset] = '\0'; 19385dfecf96Smrg 19395dfecf96Smrg /* check if need to round */ 19405dfecf96Smrg if (!again && offset > 1 && isdigit(digit) && digit >= '5' && 19415dfecf96Smrg isdigit(buffer[offset - 1]) && 19425dfecf96Smrg float_string_inc(buffer, offset - 1)) 19435dfecf96Smrg ++offset; 19445dfecf96Smrg } 19455dfecf96Smrg /* check if need to add extra zero digits to fill space */ 19465dfecf96Smrg else if (length < d) { 19475dfecf96Smrg offset += d - length; 19485dfecf96Smrg for (++length; length <= d; length++) 19495dfecf96Smrg dptr[length] = '0'; 19505dfecf96Smrg dptr[length] = '\0'; 19515dfecf96Smrg } 19525dfecf96Smrg } 19535dfecf96Smrg else { 19545dfecf96Smrg /* no digits after decimal point */ 19555dfecf96Smrg int digit, inc = 0; 19565dfecf96Smrg char *dptr = strchr(buffer, '.') + 1; 19575dfecf96Smrg 19585dfecf96Smrg digit = *dptr; 19595dfecf96Smrg if (!again && digit >= '5' && dptr >= buffer + 2 && isdigit(dptr[-2])) 19605dfecf96Smrg inc = float_string_inc(buffer, dptr - buffer - 2); 19615dfecf96Smrg 19625dfecf96Smrg offset = (dptr - buffer) + inc; 19635dfecf96Smrg buffer[offset] = '\0'; 19645dfecf96Smrg } 19655dfecf96Smrg 19665dfecf96Smrg /* if d was not specified, remove any extra zeros */ 19675dfecf96Smrg if (pd == NULL) { 19685dfecf96Smrg while (offset > 2 && buffer[offset - 2] != '.' && 19695dfecf96Smrg buffer[offset - 1] == '0') 19705dfecf96Smrg --offset; 19715dfecf96Smrg buffer[offset] = '\0'; 19725dfecf96Smrg } 19735dfecf96Smrg 19745dfecf96Smrg if (w > 0 && offset > w) { 19755dfecf96Smrg /* first check if can remove extra fractional digits */ 19765dfecf96Smrg if (pd == NULL) { 19775dfecf96Smrg char *ptr = strchr(buffer, '.') + 1; 19785dfecf96Smrg 19795dfecf96Smrg if (ptr - buffer < w) { 19805dfecf96Smrg d = w - (ptr - buffer); 19815dfecf96Smrg goto fixed_float_check_again; 19825dfecf96Smrg } 19835dfecf96Smrg } 19845dfecf96Smrg 19855dfecf96Smrg /* remove leading "zero" to save space */ 19865dfecf96Smrg if ((!sign && buffer[0] == '0') || (sign && buffer[1] == '0')) { 19875dfecf96Smrg /* ending nul also copied */ 19885dfecf96Smrg memmove(buffer + sign, buffer + sign + 1, offset); 19895dfecf96Smrg --offset; 19905dfecf96Smrg } 19915dfecf96Smrg /* remove leading '+' to "save" space */ 19925dfecf96Smrg if (offset > w && buffer[0] == '+') { 19935dfecf96Smrg /* ending nul also copied */ 19945dfecf96Smrg memmove(buffer, buffer + 1, offset); 19955dfecf96Smrg --offset; 19965dfecf96Smrg } 19975dfecf96Smrg } 19985dfecf96Smrg 19995dfecf96Smrg /* if cannot represent number in given width */ 20005dfecf96Smrg if (overflowchar && offset > w) { 20015dfecf96Smrg again = 1; 20025dfecf96Smrg goto fixed_float_overflow; 20035dfecf96Smrg } 20045dfecf96Smrg 20055dfecf96Smrg length = 0; 20065dfecf96Smrg /* print padding if required */ 20075dfecf96Smrg if (w > offset) 20085dfecf96Smrg length += LispWriteChars(stream, padchar, w - offset); 20095dfecf96Smrg 20105dfecf96Smrg /* print float number representation */ 20115dfecf96Smrg return (LispWriteStr(stream, buffer, offset) + length); 20125dfecf96Smrg 20135dfecf96Smrgfixed_float_overflow: 20145dfecf96Smrg return (LispWriteChars(stream, overflowchar, w)); 20155dfecf96Smrg} 20165dfecf96Smrg 20175dfecf96Smrgint 20185dfecf96SmrgLispFormatExponentialFloat(LispObj *stream, LispObj *object, 20195dfecf96Smrg int atsign, int w, int *pd, int e, int k, 20205dfecf96Smrg int overflowchar, int padchar, int exponentchar) 20215dfecf96Smrg{ 20225dfecf96Smrg return (LispDoFormatExponentialFloat(stream, object, atsign, w, 20235dfecf96Smrg pd, e, k, overflowchar, padchar, 20245dfecf96Smrg exponentchar, 1)); 20255dfecf96Smrg} 20265dfecf96Smrg 20275dfecf96Smrgint 20285dfecf96SmrgLispDoFormatExponentialFloat(LispObj *stream, LispObj *object, 20295dfecf96Smrg int atsign, int w, int *pd, int e, int k, 20305dfecf96Smrg int overflowchar, int padchar, int exponentchar, 20315dfecf96Smrg int format) 20325dfecf96Smrg{ 20335dfecf96Smrg char buffer[512], stk[64]; 20345dfecf96Smrg int sign, exponent, length, offset, d = pd ? *pd : FLOAT_PREC; 20355dfecf96Smrg double value = DFLOAT_VALUE(object); 20365dfecf96Smrg 20375dfecf96Smrg if (value == 0.0) { 20385dfecf96Smrg exponent = 0; 20395dfecf96Smrg k = 1; 20405dfecf96Smrg strcpy(stk, "+0"); 20415dfecf96Smrg } 20425dfecf96Smrg else 20435dfecf96Smrg /* calculate format parameters, adjusting scale factor */ 20445dfecf96Smrg parse_double(stk, &exponent, value, d + k - 1); 20455dfecf96Smrg 20465dfecf96Smrg /* set e to a value that won't overflow */ 20475dfecf96Smrg if (e > 16) 20485dfecf96Smrg e = 16; 20495dfecf96Smrg 20505dfecf96Smrg /* set k to a value that won't overflow */ 20515dfecf96Smrg if (k > 128) 20525dfecf96Smrg k = 128; 20535dfecf96Smrg else if (k < -128) 20545dfecf96Smrg k = -128; 20555dfecf96Smrg 20565dfecf96Smrg /* set d to a value that won't overflow */ 20575dfecf96Smrg if (d > 128) 20585dfecf96Smrg d = 128; 20595dfecf96Smrg else if (d < -128) 20605dfecf96Smrg d = -128; 20615dfecf96Smrg 20625dfecf96Smrg /* how many bytes in float representation */ 20635dfecf96Smrg length = strlen(stk) - 1; 20645dfecf96Smrg 20655dfecf96Smrg /* need to print a sign? */ 20665dfecf96Smrg sign = atsign || (stk[0] == '-'); 20675dfecf96Smrg 20685dfecf96Smrg /* adjust number of digits after decimal point */ 20695dfecf96Smrg if (k > 0) 20705dfecf96Smrg d -= k - 1; 20715dfecf96Smrg 20725dfecf96Smrg /* adjust exponent, based on scale factor */ 20735dfecf96Smrg exponent -= k - 1; 20745dfecf96Smrg 20755dfecf96Smrg /* format number, cannot overflow, as control variables were checked */ 20765dfecf96Smrg offset = 0; 20775dfecf96Smrg if (sign) 20785dfecf96Smrg buffer[offset++] = stk[0]; 20795dfecf96Smrg if (k > 0) { 20805dfecf96Smrg if (k > length) { 20815dfecf96Smrg memcpy(buffer + offset, stk + 1, length); 20825dfecf96Smrg offset += length; 20835dfecf96Smrg } 20845dfecf96Smrg else { 20855dfecf96Smrg memcpy(buffer + offset, stk + 1, k); 20865dfecf96Smrg offset += k; 20875dfecf96Smrg } 20885dfecf96Smrg buffer[offset++] = '.'; 20895dfecf96Smrg if (length > k) { 20905dfecf96Smrg memcpy(buffer + offset, stk + 1 + k, length - k); 20915dfecf96Smrg offset += length - k; 20925dfecf96Smrg } 20935dfecf96Smrg else 20945dfecf96Smrg buffer[offset++] = '0'; 20955dfecf96Smrg } 20965dfecf96Smrg else { 20975dfecf96Smrg int tmp = k; 20985dfecf96Smrg 20995dfecf96Smrg buffer[offset++] = '0'; 21005dfecf96Smrg buffer[offset++] = '.'; 21015dfecf96Smrg while (tmp < 0) { 21025dfecf96Smrg buffer[offset++] = '0'; 21035dfecf96Smrg tmp++; 21045dfecf96Smrg } 21055dfecf96Smrg memcpy(buffer + offset, stk + 1, length); 21065dfecf96Smrg offset += length; 21075dfecf96Smrg } 21085dfecf96Smrg 21095dfecf96Smrg /* if format, then always add a sign to exponent */ 21105dfecf96Smrg buffer[offset++] = exponentchar; 21115dfecf96Smrg if (format || exponent < 0) 21125dfecf96Smrg buffer[offset++] = exponent < 0 ? '-' : '+'; 21135dfecf96Smrg 21145dfecf96Smrg /* XXX destroy stk contents */ 21155dfecf96Smrg sprintf(stk, "%%0%dd", e); 21165dfecf96Smrg /* format scale factor*/ 21175dfecf96Smrg length = sprintf(buffer + offset, stk, 21185dfecf96Smrg exponent < 0 ? -exponent : exponent); 21195dfecf96Smrg /* check for overflow in exponent */ 21205dfecf96Smrg if (length > e && overflowchar) 21215dfecf96Smrg goto exponential_float_overflow; 21225dfecf96Smrg offset += length; 21235dfecf96Smrg 21245dfecf96Smrg /* make sure only d digits are printed after decimal point */ 21255dfecf96Smrg if (d > 0) { 21265dfecf96Smrg int currd; 21275dfecf96Smrg char *dptr = strchr(buffer, '.'), 21285dfecf96Smrg *eptr = strchr(dptr, exponentchar); 21295dfecf96Smrg 21305dfecf96Smrg currd = eptr - dptr - 1; 21315dfecf96Smrg length = strlen(eptr); 21325dfecf96Smrg 21335dfecf96Smrg /* check if need to remove excess digits */ 21345dfecf96Smrg if (currd > d) { 21355dfecf96Smrg int digit, dpos; 21365dfecf96Smrg 21375dfecf96Smrg dpos = offset = (dptr - buffer) + 1 + d; 21385dfecf96Smrg digit = buffer[offset]; 21395dfecf96Smrg 21405dfecf96Smrg memmove(buffer + offset, eptr, length + 1); 21415dfecf96Smrg /* also copy ending nul character */ 21425dfecf96Smrg 21435dfecf96Smrg /* adjust offset to length of total string */ 21445dfecf96Smrg offset += length; 21455dfecf96Smrg 21465dfecf96Smrg /* check if need to round */ 21475dfecf96Smrg if (dpos > 1 && isdigit(digit) && digit >= '5' && 21485dfecf96Smrg isdigit(buffer[dpos - 1]) && 21495dfecf96Smrg float_string_inc(buffer, dpos - 1)) 21505dfecf96Smrg ++offset; 21515dfecf96Smrg } 21525dfecf96Smrg /* check if need to add extra zero digits to fill space */ 21535dfecf96Smrg else if (pd && currd < d) { 21545dfecf96Smrg memmove(eptr + d - currd, eptr, length + 1); 21555dfecf96Smrg /* also copy ending nul character */ 21565dfecf96Smrg 21575dfecf96Smrg offset += d - currd; 21585dfecf96Smrg for (++currd; currd <= d; currd++) 21595dfecf96Smrg dptr[currd] = '0'; 21605dfecf96Smrg } 21615dfecf96Smrg /* check if need to remove zeros */ 21625dfecf96Smrg else if (pd == NULL) { 21635dfecf96Smrg int zeros = 1; 21645dfecf96Smrg 21655dfecf96Smrg while (eptr[-zeros] == '0') 21665dfecf96Smrg ++zeros; 21675dfecf96Smrg if (eptr[-zeros] == '.') 21685dfecf96Smrg --zeros; 21695dfecf96Smrg if (zeros > 1) { 21705dfecf96Smrg memmove(eptr - zeros + 1, eptr, length + 1); 21715dfecf96Smrg offset -= zeros - 1; 21725dfecf96Smrg } 21735dfecf96Smrg } 21745dfecf96Smrg } 21755dfecf96Smrg else { 21765dfecf96Smrg /* no digits after decimal point */ 21775dfecf96Smrg int digit, inc = 0; 21785dfecf96Smrg char *dptr = strchr(buffer, '.'), 21795dfecf96Smrg *eptr = strchr(dptr, exponentchar); 21805dfecf96Smrg 21815dfecf96Smrg digit = dptr[1]; 21825dfecf96Smrg 21835dfecf96Smrg offset = (dptr - buffer) + 1; 21845dfecf96Smrg length = strlen(eptr); 21855dfecf96Smrg memmove(buffer + offset, eptr, length + 1); 21865dfecf96Smrg /* also copy ending nul character */ 21875dfecf96Smrg 21885dfecf96Smrg if (digit >= '5' && dptr >= buffer + 2 && 21895dfecf96Smrg isdigit(dptr[-2])) 21905dfecf96Smrg inc = float_string_inc(buffer, dptr - buffer - 2); 21915dfecf96Smrg 21925dfecf96Smrg /* adjust offset to length of total string */ 21935dfecf96Smrg offset += length + inc; 21945dfecf96Smrg } 21955dfecf96Smrg 21965dfecf96Smrg if (w > 0 && offset > w) { 21975dfecf96Smrg /* remove leading "zero" to save space */ 21985dfecf96Smrg if ((!sign && buffer[0] == '0') || (sign && buffer[1] == '0')) { 21995dfecf96Smrg /* ending nul also copied */ 22005dfecf96Smrg memmove(buffer + sign, buffer + sign + 1, offset); 22015dfecf96Smrg --offset; 22025dfecf96Smrg } 22035dfecf96Smrg /* remove leading '+' to "save" space */ 22045dfecf96Smrg if (offset > w && buffer[0] == '+') { 22055dfecf96Smrg /* ending nul also copied */ 22065dfecf96Smrg memmove(buffer, buffer + 1, offset); 22075dfecf96Smrg --offset; 22085dfecf96Smrg } 22095dfecf96Smrg } 22105dfecf96Smrg 22115dfecf96Smrg /* if cannot represent number in given width */ 22125dfecf96Smrg if (overflowchar && offset > w) 22135dfecf96Smrg goto exponential_float_overflow; 22145dfecf96Smrg 22155dfecf96Smrg length = 0; 22165dfecf96Smrg /* print padding if required */ 22175dfecf96Smrg if (w > offset) 22185dfecf96Smrg length += LispWriteChars(stream, padchar, w - offset); 22195dfecf96Smrg 22205dfecf96Smrg /* print float number representation */ 22215dfecf96Smrg return (LispWriteStr(stream, buffer, offset) + length); 22225dfecf96Smrg 22235dfecf96Smrgexponential_float_overflow: 22245dfecf96Smrg return (LispWriteChars(stream, overflowchar, w)); 22255dfecf96Smrg} 22265dfecf96Smrg 22275dfecf96Smrgint 22285dfecf96SmrgLispFormatGeneralFloat(LispObj *stream, LispObj *object, 22295dfecf96Smrg int atsign, int w, int *pd, int e, int k, 22305dfecf96Smrg int overflowchar, int padchar, int exponentchar) 22315dfecf96Smrg{ 22325dfecf96Smrg char stk[64]; 22335dfecf96Smrg int length, exponent, n, dd, ee, ww, d = pd ? *pd : FLOAT_PREC; 22345dfecf96Smrg double value = DFLOAT_VALUE(object); 22355dfecf96Smrg 22365dfecf96Smrg if (value == 0.0) { 22375dfecf96Smrg exponent = 0; 22385dfecf96Smrg n = 0; 22395dfecf96Smrg d = 1; 22405dfecf96Smrg strcpy(stk, "+0"); 22415dfecf96Smrg } 22425dfecf96Smrg else { 22435dfecf96Smrg /* calculate format parameters, adjusting scale factor */ 22445dfecf96Smrg parse_double(stk, &exponent, value, d + k - 1); 22455dfecf96Smrg n = exponent + 1; 22465dfecf96Smrg } 22475dfecf96Smrg 22485dfecf96Smrg /* Let ee equal e+2, or 4 if e is omitted. */ 22495dfecf96Smrg if (e) 22505dfecf96Smrg ee = e + 2; 22515dfecf96Smrg else 22525dfecf96Smrg ee = 4; 22535dfecf96Smrg 22545dfecf96Smrg /* Let ww equal w-ee, or nil if w is omitted. */ 22555dfecf96Smrg if (w) 22565dfecf96Smrg ww = w - ee; 22575dfecf96Smrg else 22585dfecf96Smrg ww = 0; 22595dfecf96Smrg 22605dfecf96Smrg dd = d - n; 22615dfecf96Smrg if (d >= dd && dd >= 0) { 22625dfecf96Smrg length = LispFormatFixedFloat(stream, object, atsign, ww, 22635dfecf96Smrg &dd, 0, overflowchar, padchar); 22645dfecf96Smrg 22655dfecf96Smrg /* ~ee@T */ 22665dfecf96Smrg length += LispWriteChars(stream, padchar, ee); 22675dfecf96Smrg } 22685dfecf96Smrg else 22695dfecf96Smrg length = LispFormatExponentialFloat(stream, object, atsign, 22705dfecf96Smrg w, pd, e, k, overflowchar, 22715dfecf96Smrg padchar, exponentchar); 22725dfecf96Smrg 22735dfecf96Smrg return (length); 22745dfecf96Smrg} 22755dfecf96Smrg 22765dfecf96Smrgint 22775dfecf96SmrgLispFormatDollarFloat(LispObj *stream, LispObj *object, 22785dfecf96Smrg int atsign, int collon, int d, int n, int w, int padchar) 22795dfecf96Smrg{ 22805dfecf96Smrg char buffer[512], stk[64]; 22815dfecf96Smrg int sign, exponent, length, offset; 22825dfecf96Smrg double value = DFLOAT_VALUE(object); 22835dfecf96Smrg 22845dfecf96Smrg if (value == 0.0) { 22855dfecf96Smrg exponent = 0; 22865dfecf96Smrg strcpy(stk, "+0"); 22875dfecf96Smrg } 22885dfecf96Smrg else 22895dfecf96Smrg /* calculate format parameters, adjusting scale factor */ 22905dfecf96Smrg parse_double(stk, &exponent, value, d == 0 ? FLOAT_PREC : d + 1); 22915dfecf96Smrg 22925dfecf96Smrg /* set d to a "sane" value */ 22935dfecf96Smrg if (d > 128) 22945dfecf96Smrg d = 128; 22955dfecf96Smrg 22965dfecf96Smrg /* set n to a "sane" value */ 22975dfecf96Smrg if (n > 128) 22985dfecf96Smrg n = 128; 22995dfecf96Smrg 23005dfecf96Smrg /* use exponent as index in stk */ 23015dfecf96Smrg ++exponent; 23025dfecf96Smrg 23035dfecf96Smrg /* don't put sign in buffer, 23045dfecf96Smrg * if collon specified, must go before padding */ 23055dfecf96Smrg sign = atsign || (stk[0] == '-'); 23065dfecf96Smrg 23075dfecf96Smrg offset = 0; 23085dfecf96Smrg 23095dfecf96Smrg /* pad with zeros if required */ 23105dfecf96Smrg if (exponent > 0) 23115dfecf96Smrg n -= exponent; 23125dfecf96Smrg while (n > 0) { 23135dfecf96Smrg buffer[offset++] = '0'; 23145dfecf96Smrg n--; 23155dfecf96Smrg } 23165dfecf96Smrg 23175dfecf96Smrg /* how many bytes in float representation */ 23185dfecf96Smrg length = strlen(stk) - 1; 23195dfecf96Smrg 23205dfecf96Smrg if (exponent > 0) { 23215dfecf96Smrg if (exponent > length) { 23225dfecf96Smrg memcpy(buffer + offset, stk + 1, length); 23235dfecf96Smrg memset(buffer + offset + length, '0', exponent - length); 23245dfecf96Smrg } 23255dfecf96Smrg else 23265dfecf96Smrg memcpy(buffer + offset, stk + 1, exponent); 23275dfecf96Smrg offset += exponent; 23285dfecf96Smrg buffer[offset++] = '.'; 23295dfecf96Smrg if (length > exponent) { 23305dfecf96Smrg memcpy(buffer + offset, stk + 1 + exponent, length - exponent); 23315dfecf96Smrg offset += length - exponent; 23325dfecf96Smrg } 23335dfecf96Smrg else 23345dfecf96Smrg buffer[offset++] = '0'; 23355dfecf96Smrg } 23365dfecf96Smrg else { 23375dfecf96Smrg if (n > 0) 23385dfecf96Smrg buffer[offset++] = '0'; 23395dfecf96Smrg buffer[offset++] = '.'; 23405dfecf96Smrg while (exponent < 0) { 23415dfecf96Smrg buffer[offset++] = '0'; 23425dfecf96Smrg exponent++; 23435dfecf96Smrg } 23445dfecf96Smrg memcpy(buffer + offset, stk + 1, length); 23455dfecf96Smrg offset += length; 23465dfecf96Smrg } 23475dfecf96Smrg buffer[offset] = '\0'; 23485dfecf96Smrg 23495dfecf96Smrg /* make sure only d digits are printed after decimal point */ 23505dfecf96Smrg if (d > 0) { 23515dfecf96Smrg char *dptr = strchr(buffer, '.'); 23525dfecf96Smrg 23535dfecf96Smrg length = strlen(dptr) - 1; 23545dfecf96Smrg /* check if need to remove excess digits */ 23555dfecf96Smrg if (length > d) { 23565dfecf96Smrg int digit; 23575dfecf96Smrg 23585dfecf96Smrg offset = (dptr - buffer) + 1 + d; 23595dfecf96Smrg digit = buffer[offset]; 23605dfecf96Smrg 23615dfecf96Smrg /* remove extra digits */ 23625dfecf96Smrg buffer[offset] = '\0'; 23635dfecf96Smrg 23645dfecf96Smrg /* check if need to round */ 23655dfecf96Smrg if (offset > 1 && isdigit(digit) && digit >= '5' && 23665dfecf96Smrg isdigit(buffer[offset - 1]) && 23675dfecf96Smrg float_string_inc(buffer, offset - 1)) 23685dfecf96Smrg ++offset; 23695dfecf96Smrg } 23705dfecf96Smrg /* check if need to add extra zero digits to fill space */ 23715dfecf96Smrg else if (length < d) { 23725dfecf96Smrg offset += d - length; 23735dfecf96Smrg for (++length; length <= d; length++) 23745dfecf96Smrg dptr[length] = '0'; 23755dfecf96Smrg dptr[length] = '\0'; 23765dfecf96Smrg } 23775dfecf96Smrg } 23785dfecf96Smrg else { 23795dfecf96Smrg /* no digits after decimal point */ 23805dfecf96Smrg int digit, inc = 0; 23815dfecf96Smrg char *dptr = strchr(buffer, '.') + 1; 23825dfecf96Smrg 23835dfecf96Smrg digit = *dptr; 23845dfecf96Smrg if (digit >= '5' && dptr >= buffer + 2 && isdigit(dptr[-2])) 23855dfecf96Smrg inc = float_string_inc(buffer, dptr - buffer - 2); 23865dfecf96Smrg 23875dfecf96Smrg offset = (dptr - buffer) + inc; 23885dfecf96Smrg buffer[offset] = '\0'; 23895dfecf96Smrg } 23905dfecf96Smrg 23915dfecf96Smrg length = 0; 23925dfecf96Smrg if (sign) { 23935dfecf96Smrg ++offset; 23945dfecf96Smrg if (atsign && collon) 23955dfecf96Smrg length += LispWriteChar(stream, value >= 0.0 ? '+' : '-'); 23965dfecf96Smrg } 23975dfecf96Smrg 23985dfecf96Smrg /* print padding if required */ 23995dfecf96Smrg if (w > offset) 24005dfecf96Smrg length += LispWriteChars(stream, padchar, w - offset); 24015dfecf96Smrg 24025dfecf96Smrg if (atsign && !collon) 24035dfecf96Smrg length += LispWriteChar(stream, value >= 0.0 ? '+' : '-'); 24045dfecf96Smrg 24055dfecf96Smrg /* print float number representation */ 24065dfecf96Smrg return (LispWriteStr(stream, buffer, offset) + length); 24075dfecf96Smrg} 2408