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/read.c,v 1.36tsi Exp $ */ 315dfecf96Smrg 325dfecf96Smrg#include <errno.h> 335dfecf96Smrg#include "lisp/read.h" 345dfecf96Smrg#include "lisp/package.h" 355dfecf96Smrg#include "lisp/write.h" 365dfecf96Smrg#include <fcntl.h> 375dfecf96Smrg#include <stdarg.h> 385dfecf96Smrg 395dfecf96Smrg/* This should be visible only in read.c, but if an error is generated, 405dfecf96Smrg * the current code in write.c will print it as #<ERROR> */ 415dfecf96Smrg#define LABEL_BIT_COUNT 8 425dfecf96Smrg#define LABEL_BIT_MASK 0xff 435dfecf96Smrg#define MAX_LABEL_VALUE ((1L << (sizeof(long) * 8 - 9)) - 1) 445dfecf96Smrg#define READLABEL(label) \ 455dfecf96Smrg (LispObj*)(((label) << LABEL_BIT_COUNT) | READLABEL_MASK) 465dfecf96Smrg#define READLABELP(object) \ 475dfecf96Smrg (((unsigned long)(object) & LABEL_BIT_MASK) == READLABEL_MASK) 485dfecf96Smrg#define READLABEL_VALUE(object) \ 495dfecf96Smrg ((long)(object) >> LABEL_BIT_COUNT) 505dfecf96Smrg 515dfecf96Smrg#define READ_ENTER() \ 525dfecf96Smrg LispObj *read__stream = SINPUT; \ 535dfecf96Smrg int read__line = LispGetLine(read__stream) 545dfecf96Smrg#define READ_ERROR0(format) \ 555dfecf96Smrg LispReadError(read__stream, read__line, format) 565dfecf96Smrg#define READ_ERROR1(format, arg1) \ 575dfecf96Smrg LispReadError(read__stream, read__line, format, arg1) 585dfecf96Smrg#define READ_ERROR2(format, arg1, arg2) \ 595dfecf96Smrg LispReadError(read__stream, read__line, format, arg1, arg2) 605dfecf96Smrg 615dfecf96Smrg#define READ_ERROR_EOF() READ_ERROR0("unexpected end of input") 625dfecf96Smrg#define READ_ERROR_FIXNUM() READ_ERROR0("number is not a fixnum") 635dfecf96Smrg#define READ_ERROR_INVARG() READ_ERROR0("invalid argument") 645dfecf96Smrg 65c2cbb186Smrg#ifdef __APPLE__ 665dfecf96Smrg# define finite(x) isfinite(x) 675dfecf96Smrg#endif 685dfecf96Smrg 695dfecf96Smrg/* 705dfecf96Smrg * Types 715dfecf96Smrg */ 725dfecf96Smrgtypedef struct _object_info { 735dfecf96Smrg long label; /* the read label of this object */ 745dfecf96Smrg LispObj *object; /* the resulting object */ 755dfecf96Smrg long num_circles; /* references to object before it was completely read */ 765dfecf96Smrg} object_info; 775dfecf96Smrg 785dfecf96Smrgtypedef struct _read_info { 795dfecf96Smrg int level; /* level of open parentheses */ 805dfecf96Smrg 815dfecf96Smrg int nodot; /* flag set when reading a "special" list */ 825dfecf96Smrg 835dfecf96Smrg int discard; /* flag used when reading an unavailable feature */ 845dfecf96Smrg 855dfecf96Smrg long circle_count; /* if non zero, must resolve some labels */ 865dfecf96Smrg 875dfecf96Smrg /* information for #<number>= and #<number># */ 885dfecf96Smrg object_info *objects; 895dfecf96Smrg long num_objects; 905dfecf96Smrg 915dfecf96Smrg /* could use only the objects field as all circular data is known, 925dfecf96Smrg * but check every object so that circular/shared references generated 935dfecf96Smrg * by evaluations would not cause an infinite loop at read time */ 945dfecf96Smrg LispObj **circles; 955dfecf96Smrg long num_circles; 965dfecf96Smrg} read_info; 975dfecf96Smrg 985dfecf96Smrg/* 995dfecf96Smrg * Protypes 1005dfecf96Smrg */ 1015dfecf96Smrgstatic LispObj *LispReadChar(LispBuiltin*, int); 1025dfecf96Smrg 1035dfecf96Smrgstatic int LispGetLine(LispObj*); 1045dfecf96Smrg#ifdef __GNUC__ 1055dfecf96Smrg#define PRINTF_FORMAT __attribute__ ((format (printf, 3, 4))) 1065dfecf96Smrg#else 1075dfecf96Smrg#define PRINTF_FORMAT /**/ 1085dfecf96Smrg#endif 109f765521fSmrgstatic void LispReadError(LispObj*, int, const char*, ...); 1105dfecf96Smrg#undef PRINTF_FORMAT 1115dfecf96Smrgstatic void LispReadFixCircle(LispObj*, read_info*); 1125dfecf96Smrgstatic LispObj *LispReadLabelCircle(LispObj*, read_info*); 1135dfecf96Smrgstatic int LispReadCheckCircle(LispObj*, read_info*); 1145dfecf96Smrgstatic LispObj *LispDoRead(read_info*); 1155dfecf96Smrgstatic int LispSkipWhiteSpace(void); 1165dfecf96Smrgstatic LispObj *LispReadList(read_info*); 1175dfecf96Smrgstatic LispObj *LispReadQuote(read_info*); 1185dfecf96Smrgstatic LispObj *LispReadBackquote(read_info*); 1195dfecf96Smrgstatic LispObj *LispReadCommaquote(read_info*); 1205dfecf96Smrgstatic LispObj *LispReadObject(int, read_info*); 1215dfecf96Smrgstatic LispObj *LispParseAtom(char*, char*, int, int, LispObj*, int); 1225dfecf96Smrgstatic LispObj *LispParseNumber(char*, int, LispObj*, int); 1235dfecf96Smrgstatic int StringInRadix(char*, int, int); 1245dfecf96Smrgstatic int AtomSeparator(int, int, int); 1255dfecf96Smrgstatic LispObj *LispReadVector(read_info*); 1265dfecf96Smrgstatic LispObj *LispReadMacro(read_info*); 1275dfecf96Smrgstatic LispObj *LispReadFunction(read_info*); 1285dfecf96Smrgstatic LispObj *LispReadRational(int, read_info*); 1295dfecf96Smrgstatic LispObj *LispReadCharacter(read_info*); 1305dfecf96Smrgstatic void LispSkipComment(void); 1315dfecf96Smrgstatic LispObj *LispReadEval(read_info*); 1325dfecf96Smrgstatic LispObj *LispReadComplex(read_info*); 1335dfecf96Smrgstatic LispObj *LispReadPathname(read_info*); 1345dfecf96Smrgstatic LispObj *LispReadStruct(read_info*); 1355dfecf96Smrgstatic LispObj *LispReadMacroArg(read_info*); 1365dfecf96Smrgstatic LispObj *LispReadArray(long, read_info*); 1375dfecf96Smrgstatic LispObj *LispReadFeature(int, read_info*); 1385dfecf96Smrgstatic LispObj *LispEvalFeature(LispObj*); 1395dfecf96Smrg 1405dfecf96Smrg/* 1415dfecf96Smrg * Initialization 1425dfecf96Smrg */ 143f765521fSmrgstatic const char * const Char_Nul[] = {"Null", "Nul", NULL}; 144f765521fSmrgstatic const char * const Char_Soh[] = {"Soh", NULL}; 145f765521fSmrgstatic const char * const Char_Stx[] = {"Stx", NULL}; 146f765521fSmrgstatic const char * const Char_Etx[] = {"Etx", NULL}; 147f765521fSmrgstatic const char * const Char_Eot[] = {"Eot", NULL}; 148f765521fSmrgstatic const char * const Char_Enq[] = {"Enq", NULL}; 149f765521fSmrgstatic const char * const Char_Ack[] = {"Ack", NULL}; 150f765521fSmrgstatic const char * const Char_Bel[] = {"Bell", "Bel", NULL}; 151f765521fSmrgstatic const char * const Char_Bs[] = {"Backspace", "Bs", NULL}; 152f765521fSmrgstatic const char * const Char_Tab[] = {"Tab", NULL}; 153f765521fSmrgstatic const char * const Char_Nl[] = {"Newline", "Nl", "Lf", "Linefeed", NULL}; 154f765521fSmrgstatic const char * const Char_Vt[] = {"Vt", NULL}; 155f765521fSmrgstatic const char * const Char_Np[] = {"Page", "Np", NULL}; 156f765521fSmrgstatic const char * const Char_Cr[] = {"Return", "Cr", NULL}; 157f765521fSmrgstatic const char * const Char_Ff[] = {"So", "Ff", NULL}; 158f765521fSmrgstatic const char * const Char_Si[] = {"Si", NULL}; 159f765521fSmrgstatic const char * const Char_Dle[] = {"Dle", NULL}; 160f765521fSmrgstatic const char * const Char_Dc1[] = {"Dc1", NULL}; 161f765521fSmrgstatic const char * const Char_Dc2[] = {"Dc2", NULL}; 162f765521fSmrgstatic const char * const Char_Dc3[] = {"Dc3", NULL}; 163f765521fSmrgstatic const char * const Char_Dc4[] = {"Dc4", NULL}; 164f765521fSmrgstatic const char * const Char_Nak[] = {"Nak", NULL}; 165f765521fSmrgstatic const char * const Char_Syn[] = {"Syn", NULL}; 166f765521fSmrgstatic const char * const Char_Etb[] = {"Etb", NULL}; 167f765521fSmrgstatic const char * const Char_Can[] = {"Can", NULL}; 168f765521fSmrgstatic const char * const Char_Em[] = {"Em", NULL}; 169f765521fSmrgstatic const char * const Char_Sub[] = {"Sub", NULL}; 170f765521fSmrgstatic const char * const Char_Esc[] = {"Escape", "Esc", NULL}; 171f765521fSmrgstatic const char * const Char_Fs[] = {"Fs", NULL}; 172f765521fSmrgstatic const char * const Char_Gs[] = {"Gs", NULL}; 173f765521fSmrgstatic const char * const Char_Rs[] = {"Rs", NULL}; 174f765521fSmrgstatic const char * const Char_Us[] = {"Us", NULL}; 175f765521fSmrgstatic const char * const Char_Sp[] = {"Space", "Sp", NULL}; 176f765521fSmrgstatic const char * const Char_Del[] = {"Rubout", "Del", "Delete", NULL}; 177f765521fSmrg 178f765521fSmrgconst LispCharInfo LispChars[256] = { 1795dfecf96Smrg {Char_Nul}, 1805dfecf96Smrg {Char_Soh}, 1815dfecf96Smrg {Char_Stx}, 1825dfecf96Smrg {Char_Etx}, 1835dfecf96Smrg {Char_Eot}, 1845dfecf96Smrg {Char_Enq}, 1855dfecf96Smrg {Char_Ack}, 1865dfecf96Smrg {Char_Bel}, 1875dfecf96Smrg {Char_Bs}, 1885dfecf96Smrg {Char_Tab}, 1895dfecf96Smrg {Char_Nl}, 1905dfecf96Smrg {Char_Vt}, 1915dfecf96Smrg {Char_Np}, 1925dfecf96Smrg {Char_Cr}, 1935dfecf96Smrg {Char_Ff}, 1945dfecf96Smrg {Char_Si}, 1955dfecf96Smrg {Char_Dle}, 1965dfecf96Smrg {Char_Dc1}, 1975dfecf96Smrg {Char_Dc2}, 1985dfecf96Smrg {Char_Dc3}, 1995dfecf96Smrg {Char_Dc4}, 2005dfecf96Smrg {Char_Nak}, 2015dfecf96Smrg {Char_Syn}, 2025dfecf96Smrg {Char_Etb}, 2035dfecf96Smrg {Char_Can}, 2045dfecf96Smrg {Char_Em}, 2055dfecf96Smrg {Char_Sub}, 2065dfecf96Smrg {Char_Esc}, 2075dfecf96Smrg {Char_Fs}, 2085dfecf96Smrg {Char_Gs}, 2095dfecf96Smrg {Char_Rs}, 2105dfecf96Smrg {Char_Us}, 2115dfecf96Smrg {Char_Sp}, 2125dfecf96Smrg {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, 2135dfecf96Smrg {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, 2145dfecf96Smrg {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, 2155dfecf96Smrg {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, 2165dfecf96Smrg {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, 2175dfecf96Smrg {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, 2185dfecf96Smrg {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, 2195dfecf96Smrg {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, 2205dfecf96Smrg {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, 2215dfecf96Smrg {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, 2225dfecf96Smrg {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, 2235dfecf96Smrg {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, 2245dfecf96Smrg {Char_Del}, 2255dfecf96Smrg {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, 2265dfecf96Smrg {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, 2275dfecf96Smrg {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, 2285dfecf96Smrg {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, 2295dfecf96Smrg {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, 2305dfecf96Smrg {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, 2315dfecf96Smrg {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, 2325dfecf96Smrg {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, 2335dfecf96Smrg {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, 2345dfecf96Smrg {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, 2355dfecf96Smrg {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, 2365dfecf96Smrg {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, 2375dfecf96Smrg {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, 2385dfecf96Smrg {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, 2395dfecf96Smrg {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, 2405dfecf96Smrg {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL}, {NULL} 2415dfecf96Smrg 2425dfecf96Smrg}; 2435dfecf96Smrg 2445dfecf96SmrgAtom_id Sand, Sor, Snot; 2455dfecf96Smrg 2465dfecf96Smrg 2475dfecf96Smrg/* 2485dfecf96Smrg * Implementation 2495dfecf96Smrg */ 2505dfecf96SmrgLispObj * 2515dfecf96SmrgLisp_Read(LispBuiltin *builtin) 2525dfecf96Smrg/* 2535dfecf96Smrg read &optional input-stream eof-error-p eof-value recursive-p 2545dfecf96Smrg */ 2555dfecf96Smrg{ 2565dfecf96Smrg LispObj *result; 2575dfecf96Smrg 2585dfecf96Smrg LispObj *input_stream, *eof_error_p, *eof_value; 2595dfecf96Smrg 2605dfecf96Smrg eof_value = ARGUMENT(2); 2615dfecf96Smrg eof_error_p = ARGUMENT(1); 2625dfecf96Smrg input_stream = ARGUMENT(0); 2635dfecf96Smrg 2645dfecf96Smrg if (input_stream == UNSPEC) 2655dfecf96Smrg input_stream = NIL; 2665dfecf96Smrg else if (input_stream != NIL) { 2675dfecf96Smrg CHECK_STREAM(input_stream); 2685dfecf96Smrg else if (!input_stream->data.stream.readable) 2695dfecf96Smrg LispDestroy("%s: stream %s is not readable", 2705dfecf96Smrg STRFUN(builtin), STROBJ(input_stream)); 2715dfecf96Smrg LispPushInput(input_stream); 2725dfecf96Smrg } 2735dfecf96Smrg else if (CONSP(lisp__data.input_list)) { 2745dfecf96Smrg input_stream = STANDARD_INPUT; 2755dfecf96Smrg LispPushInput(input_stream); 2765dfecf96Smrg } 2775dfecf96Smrg 2785dfecf96Smrg if (eof_value == UNSPEC) 2795dfecf96Smrg eof_value = NIL; 2805dfecf96Smrg 2815dfecf96Smrg result = LispRead(); 2825dfecf96Smrg if (input_stream != NIL) 2835dfecf96Smrg LispPopInput(input_stream); 2845dfecf96Smrg 2855dfecf96Smrg if (result == NULL) { 2865dfecf96Smrg if (eof_error_p != NIL) 2875dfecf96Smrg LispDestroy("%s: EOF reading stream %s", 2885dfecf96Smrg STRFUN(builtin), STROBJ(input_stream)); 2895dfecf96Smrg else 2905dfecf96Smrg result = eof_value; 2915dfecf96Smrg } 2925dfecf96Smrg 2935dfecf96Smrg return (result); 2945dfecf96Smrg} 2955dfecf96Smrg 2965dfecf96Smrgstatic LispObj * 2975dfecf96SmrgLispReadChar(LispBuiltin *builtin, int nohang) 2985dfecf96Smrg{ 2995dfecf96Smrg int character; 3005dfecf96Smrg 3015dfecf96Smrg LispObj *input_stream, *eof_error_p, *eof_value; 3025dfecf96Smrg 3035dfecf96Smrg eof_value = ARGUMENT(2); 3045dfecf96Smrg eof_error_p = ARGUMENT(1); 3055dfecf96Smrg input_stream = ARGUMENT(0); 3065dfecf96Smrg 3075dfecf96Smrg if (input_stream == UNSPEC) 3085dfecf96Smrg input_stream = NIL; 3095dfecf96Smrg else if (input_stream != NIL) { 3105dfecf96Smrg CHECK_STREAM(input_stream); 3115dfecf96Smrg } 3125dfecf96Smrg else 3135dfecf96Smrg input_stream = lisp__data.input; 3145dfecf96Smrg 3155dfecf96Smrg if (eof_value == UNSPEC) 3165dfecf96Smrg eof_value = NIL; 3175dfecf96Smrg 3185dfecf96Smrg character = EOF; 3195dfecf96Smrg 3205dfecf96Smrg if (input_stream->data.stream.readable) { 3215dfecf96Smrg LispFile *file = NULL; 3225dfecf96Smrg 3235dfecf96Smrg switch (input_stream->data.stream.type) { 3245dfecf96Smrg case LispStreamStandard: 3255dfecf96Smrg case LispStreamFile: 3265dfecf96Smrg file = FSTREAMP(input_stream); 3275dfecf96Smrg break; 3285dfecf96Smrg case LispStreamPipe: 3295dfecf96Smrg file = IPSTREAMP(input_stream); 3305dfecf96Smrg break; 3315dfecf96Smrg case LispStreamString: 3325dfecf96Smrg character = LispSgetc(SSTREAMP(input_stream)); 3335dfecf96Smrg break; 3345dfecf96Smrg default: 3355dfecf96Smrg break; 3365dfecf96Smrg } 3375dfecf96Smrg if (file != NULL) { 3385dfecf96Smrg if (file->available || file->offset < file->length) 3395dfecf96Smrg character = LispFgetc(file); 3405dfecf96Smrg else { 3415dfecf96Smrg if (nohang && !file->nonblock) { 3425dfecf96Smrg if (fcntl(file->descriptor, F_SETFL, O_NONBLOCK) < 0) 3435dfecf96Smrg LispDestroy("%s: fcntl(%d): %s", 3445dfecf96Smrg STRFUN(builtin), file->descriptor, 3455dfecf96Smrg strerror(errno)); 3465dfecf96Smrg file->nonblock = 1; 3475dfecf96Smrg } 3485dfecf96Smrg else if (!nohang && file->nonblock) { 3495dfecf96Smrg if (fcntl(file->descriptor, F_SETFL, 0) < 0) 3505dfecf96Smrg LispDestroy("%s: fcntl(%d): %s", 3515dfecf96Smrg STRFUN(builtin), file->descriptor, 3525dfecf96Smrg strerror(errno)); 3535dfecf96Smrg file->nonblock = 0; 3545dfecf96Smrg } 3555dfecf96Smrg if (nohang) { 3565dfecf96Smrg unsigned char ch; 3575dfecf96Smrg 3585dfecf96Smrg if (read(file->descriptor, &ch, 1) == 1) 3595dfecf96Smrg character = ch; 3605dfecf96Smrg else if (errno == EAGAIN) 3615dfecf96Smrg return (NIL); /* XXX no character available */ 3625dfecf96Smrg else 3635dfecf96Smrg character = EOF; 3645dfecf96Smrg } 3655dfecf96Smrg else 3665dfecf96Smrg character = LispFgetc(file); 3675dfecf96Smrg } 3685dfecf96Smrg } 3695dfecf96Smrg } 3705dfecf96Smrg else 3715dfecf96Smrg LispDestroy("%s: stream %s is unreadable", 3725dfecf96Smrg STRFUN(builtin), STROBJ(input_stream)); 3735dfecf96Smrg 3745dfecf96Smrg if (character == EOF) { 3755dfecf96Smrg if (eof_error_p != NIL) 3765dfecf96Smrg LispDestroy("%s: EOF reading stream %s", 3775dfecf96Smrg STRFUN(builtin), STROBJ(input_stream)); 3785dfecf96Smrg 3795dfecf96Smrg return (eof_value); 3805dfecf96Smrg } 3815dfecf96Smrg 3825dfecf96Smrg return (SCHAR(character)); 3835dfecf96Smrg} 3845dfecf96Smrg 3855dfecf96SmrgLispObj * 3865dfecf96SmrgLisp_ReadChar(LispBuiltin *builtin) 3875dfecf96Smrg/* 3885dfecf96Smrg read-char &optional input-stream eof-error-p eof-value recursive-p 3895dfecf96Smrg */ 3905dfecf96Smrg{ 3915dfecf96Smrg return (LispReadChar(builtin, 0)); 3925dfecf96Smrg} 3935dfecf96Smrg 3945dfecf96SmrgLispObj * 3955dfecf96SmrgLisp_ReadCharNoHang(LispBuiltin *builtin) 3965dfecf96Smrg/* 3975dfecf96Smrg read-char-no-hang &optional input-stream eof-error-p eof-value recursive-p 3985dfecf96Smrg */ 3995dfecf96Smrg{ 4005dfecf96Smrg return (LispReadChar(builtin, 1)); 4015dfecf96Smrg} 4025dfecf96Smrg 4035dfecf96SmrgLispObj * 4045dfecf96SmrgLisp_ReadLine(LispBuiltin *builtin) 4055dfecf96Smrg/* 4065dfecf96Smrg read-line &optional input-stream eof-error-p eof-value recursive-p 4075dfecf96Smrg */ 4085dfecf96Smrg{ 4095dfecf96Smrg char *string; 4105dfecf96Smrg int ch, length; 4115dfecf96Smrg LispObj *result, *status = NIL; 4125dfecf96Smrg 4135dfecf96Smrg LispObj *input_stream, *eof_error_p, *eof_value; 4145dfecf96Smrg 4155dfecf96Smrg eof_value = ARGUMENT(2); 4165dfecf96Smrg eof_error_p = ARGUMENT(1); 4175dfecf96Smrg input_stream = ARGUMENT(0); 4185dfecf96Smrg 4195dfecf96Smrg if (input_stream == UNSPEC) 4205dfecf96Smrg input_stream = NIL; 4215dfecf96Smrg else if (input_stream == NIL) 4225dfecf96Smrg input_stream = STANDARD_INPUT; 4235dfecf96Smrg else { 4245dfecf96Smrg CHECK_STREAM(input_stream); 4255dfecf96Smrg } 4265dfecf96Smrg 4275dfecf96Smrg if (eof_value == UNSPEC) 4285dfecf96Smrg eof_value = NIL; 4295dfecf96Smrg 4305dfecf96Smrg result = NIL; 4315dfecf96Smrg string = NULL; 4325dfecf96Smrg length = 0; 4335dfecf96Smrg 4345dfecf96Smrg if (!input_stream->data.stream.readable) 4355dfecf96Smrg LispDestroy("%s: stream %s is unreadable", 4365dfecf96Smrg STRFUN(builtin), STROBJ(input_stream)); 4375dfecf96Smrg if (input_stream->data.stream.type == LispStreamString) { 4385dfecf96Smrg char *start, *end, *ptr; 4395dfecf96Smrg 4405dfecf96Smrg if (SSTREAMP(input_stream)->input >= 4415dfecf96Smrg SSTREAMP(input_stream)->length) { 4425dfecf96Smrg if (eof_error_p != NIL) 4435dfecf96Smrg LispDestroy("%s: EOS found reading %s", 4445dfecf96Smrg STRFUN(builtin), STROBJ(input_stream)); 4455dfecf96Smrg 4465dfecf96Smrg status = T; 4475dfecf96Smrg result = eof_value; 4485dfecf96Smrg goto read_line_done; 4495dfecf96Smrg } 4505dfecf96Smrg 4515dfecf96Smrg start = SSTREAMP(input_stream)->string + 4525dfecf96Smrg SSTREAMP(input_stream)->input; 4535dfecf96Smrg end = SSTREAMP(input_stream)->string + 4545dfecf96Smrg SSTREAMP(input_stream)->length; 4555dfecf96Smrg /* Search for a newline */ 4565dfecf96Smrg for (ptr = start; *ptr != '\n' && ptr < end; ptr++) 4575dfecf96Smrg ; 4585dfecf96Smrg if (ptr == end) 4595dfecf96Smrg status = T; 4605dfecf96Smrg else if (!SSTREAMP(input_stream)->binary) 4615dfecf96Smrg ++SSTREAMP(input_stream)->line; 4625dfecf96Smrg length = ptr - start; 4635dfecf96Smrg string = LispMalloc(length + 1); 4645dfecf96Smrg memcpy(string, start, length); 4655dfecf96Smrg string[length] = '\0'; 4665dfecf96Smrg result = LSTRING2(string, length); 4675dfecf96Smrg /* macro LSTRING2 does not make a copy of it's arguments, and 4685dfecf96Smrg * calls LispMused on it. */ 4695dfecf96Smrg SSTREAMP(input_stream)->input += length + (status == NIL); 4705dfecf96Smrg } 4715dfecf96Smrg else /*if (input_stream->data.stream.type == LispStreamFile || 4725dfecf96Smrg input_stream->data.stream.type == LispStreamStandard || 4735dfecf96Smrg input_stream->data.stream.type == LispStreamPipe)*/ { 4745dfecf96Smrg LispFile *file; 4755dfecf96Smrg 4765dfecf96Smrg if (input_stream->data.stream.type == LispStreamPipe) 4775dfecf96Smrg file = IPSTREAMP(input_stream); 4785dfecf96Smrg else 4795dfecf96Smrg file = FSTREAMP(input_stream); 4805dfecf96Smrg 4815dfecf96Smrg if (file->nonblock) { 4825dfecf96Smrg if (fcntl(file->descriptor, F_SETFL, 0) < 0) 4835dfecf96Smrg LispDestroy("%s: fcntl: %s", 4845dfecf96Smrg STRFUN(builtin), strerror(errno)); 4855dfecf96Smrg file->nonblock = 0; 4865dfecf96Smrg } 4875dfecf96Smrg 4885dfecf96Smrg while (1) { 4895dfecf96Smrg ch = LispFgetc(file); 4905dfecf96Smrg if (ch == EOF) { 4915dfecf96Smrg if (length) 4925dfecf96Smrg break; 4935dfecf96Smrg if (eof_error_p != NIL) 4945dfecf96Smrg LispDestroy("%s: EOF found reading %s", 4955dfecf96Smrg STRFUN(builtin), STROBJ(input_stream)); 4965dfecf96Smrg if (string) 4975dfecf96Smrg LispFree(string); 4985dfecf96Smrg 4995dfecf96Smrg status = T; 5005dfecf96Smrg result = eof_value; 5015dfecf96Smrg goto read_line_done; 5025dfecf96Smrg } 5035dfecf96Smrg else if (ch == '\n') 5045dfecf96Smrg break; 5055dfecf96Smrg else if ((length % 64) == 0) 5065dfecf96Smrg string = LispRealloc(string, length + 64); 5075dfecf96Smrg string[length++] = ch; 5085dfecf96Smrg } 5095dfecf96Smrg if (string) { 5105dfecf96Smrg if ((length % 64) == 0) 5115dfecf96Smrg string = LispRealloc(string, length + 1); 5125dfecf96Smrg string[length] = '\0'; 5135dfecf96Smrg result = LSTRING2(string, length); 5145dfecf96Smrg } 5155dfecf96Smrg else 5165dfecf96Smrg result = STRING(""); 5175dfecf96Smrg } 5185dfecf96Smrg 5195dfecf96Smrgread_line_done: 5205dfecf96Smrg RETURN(0) = status; 5215dfecf96Smrg RETURN_COUNT = 1; 5225dfecf96Smrg 5235dfecf96Smrg return (result); 5245dfecf96Smrg} 5255dfecf96Smrg 5265dfecf96SmrgLispObj * 5275dfecf96SmrgLispRead(void) 5285dfecf96Smrg{ 5295dfecf96Smrg READ_ENTER(); 5305dfecf96Smrg read_info info; 5315dfecf96Smrg LispObj *result, *code = COD; 5325dfecf96Smrg 5335dfecf96Smrg info.level = info.nodot = info.discard = 0; 5345dfecf96Smrg info.circle_count = 0; 5355dfecf96Smrg info.objects = NULL; 5365dfecf96Smrg info.num_objects = 0; 5375dfecf96Smrg 5385dfecf96Smrg result = LispDoRead(&info); 5395dfecf96Smrg 5405dfecf96Smrg /* fix circular/shared lists, note that this is done when returning to 5415dfecf96Smrg * the toplevel, so, if some circular/shared reference was evaluated, 5425dfecf96Smrg * it should have generated an expected error */ 5435dfecf96Smrg if (info.num_objects) { 5445dfecf96Smrg if (info.circle_count) { 5455dfecf96Smrg info.circles = NULL; 5465dfecf96Smrg info.num_circles = 0; 5475dfecf96Smrg LispReadFixCircle(result, &info); 5485dfecf96Smrg if (info.num_circles) 5495dfecf96Smrg LispFree(info.circles); 5505dfecf96Smrg } 5515dfecf96Smrg LispFree(info.objects); 5525dfecf96Smrg } 5535dfecf96Smrg 5545dfecf96Smrg if (result == EOLIST) 5555dfecf96Smrg READ_ERROR0("object cannot start with #\\)"); 5565dfecf96Smrg else if (result == DOT) 5575dfecf96Smrg READ_ERROR0("dot allowed only on lists"); 5585dfecf96Smrg 5595dfecf96Smrg if (result != NULL && POINTERP(result)) { 5605dfecf96Smrg if (code == NIL) 5615dfecf96Smrg COD = result; 5625dfecf96Smrg else 5635dfecf96Smrg COD = CONS(COD, result); 5645dfecf96Smrg } 5655dfecf96Smrg 5665dfecf96Smrg return (result); 5675dfecf96Smrg} 5685dfecf96Smrg 5695dfecf96Smrgstatic int 5705dfecf96SmrgLispGetLine(LispObj *stream) 5715dfecf96Smrg{ 5725dfecf96Smrg int line = -1; 5735dfecf96Smrg 5745dfecf96Smrg if (STREAMP(stream)) { 5755dfecf96Smrg switch (stream->data.stream.type) { 5765dfecf96Smrg case LispStreamStandard: 5775dfecf96Smrg case LispStreamFile: 5785dfecf96Smrg if (!FSTREAMP(stream)->binary) 5795dfecf96Smrg line = FSTREAMP(stream)->line; 5805dfecf96Smrg break; 5815dfecf96Smrg case LispStreamPipe: 5825dfecf96Smrg if (!IPSTREAMP(stream)->binary) 5835dfecf96Smrg line = IPSTREAMP(stream)->line; 5845dfecf96Smrg break; 5855dfecf96Smrg case LispStreamString: 5865dfecf96Smrg if (!SSTREAMP(stream)->binary) 5875dfecf96Smrg line = SSTREAMP(stream)->line; 5885dfecf96Smrg break; 5895dfecf96Smrg default: 5905dfecf96Smrg break; 5915dfecf96Smrg } 5925dfecf96Smrg } 5935dfecf96Smrg else if (stream == NIL && !Stdin->binary) 5945dfecf96Smrg line = Stdin->line; 5955dfecf96Smrg 5965dfecf96Smrg return (line); 5975dfecf96Smrg} 5985dfecf96Smrg 5995dfecf96Smrgstatic void 600f765521fSmrgLispReadError(LispObj *stream, int line, const char *fmt, ...) 6015dfecf96Smrg{ 602f765521fSmrg char string[128]; 603f765521fSmrg const char *buffer_string; 6045dfecf96Smrg LispObj *buffer = LSTRINGSTREAM("", STREAM_READ | STREAM_WRITE, 0); 6055dfecf96Smrg int length; 6065dfecf96Smrg va_list ap; 6075dfecf96Smrg 6085dfecf96Smrg va_start(ap, fmt); 6095dfecf96Smrg vsnprintf(string, sizeof(string), fmt, ap); 6105dfecf96Smrg va_end(ap); 6115dfecf96Smrg 6125dfecf96Smrg LispFwrite(Stderr, "*** Reading ", 12); 6135dfecf96Smrg LispWriteObject(buffer, stream); 6145dfecf96Smrg buffer_string = LispGetSstring(SSTREAMP(buffer), &length); 6155dfecf96Smrg LispFwrite(Stderr, buffer_string, length); 6165dfecf96Smrg LispFwrite(Stderr, " at line ", 9); 6175dfecf96Smrg if (line < 0) 6185dfecf96Smrg LispFwrite(Stderr, "?\n", 2); 6195dfecf96Smrg else { 6205dfecf96Smrg char str[32]; 6215dfecf96Smrg 6225dfecf96Smrg sprintf(str, "%d\n", line); 6235dfecf96Smrg LispFputs(Stderr, str); 6245dfecf96Smrg } 6255dfecf96Smrg 6265dfecf96Smrg LispDestroy("READ: %s", string); 6275dfecf96Smrg} 6285dfecf96Smrg 6295dfecf96Smrgstatic void 6305dfecf96SmrgLispReadFixCircle(LispObj *object, read_info *info) 6315dfecf96Smrg{ 6325dfecf96Smrg LispObj *cons; 6335dfecf96Smrg 6345dfecf96Smrgfix_again: 6355dfecf96Smrg switch (OBJECT_TYPE(object)) { 6365dfecf96Smrg case LispCons_t: 6375dfecf96Smrg for (cons = object; 6385dfecf96Smrg CONSP(object); 6395dfecf96Smrg cons = object, object = CDR(object)) { 6405dfecf96Smrg if (READLABELP(CAR(object))) 6415dfecf96Smrg CAR(object) = LispReadLabelCircle(CAR(object), info); 6425dfecf96Smrg else if (LispReadCheckCircle(object, info)) 6435dfecf96Smrg return; 6445dfecf96Smrg else 6455dfecf96Smrg LispReadFixCircle(CAR(object), info); 6465dfecf96Smrg } 6475dfecf96Smrg if (READLABELP(object)) 6485dfecf96Smrg CDR(cons) = LispReadLabelCircle(object, info); 6495dfecf96Smrg else 6505dfecf96Smrg goto fix_again; 6515dfecf96Smrg break; 6525dfecf96Smrg case LispArray_t: 6535dfecf96Smrg if (READLABELP(object->data.array.list)) 6545dfecf96Smrg object->data.array.list = 6555dfecf96Smrg LispReadLabelCircle(object->data.array.list, info); 6565dfecf96Smrg else if (!LispReadCheckCircle(object, info)) { 6575dfecf96Smrg object = object->data.array.list; 6585dfecf96Smrg goto fix_again; 6595dfecf96Smrg } 6605dfecf96Smrg break; 6615dfecf96Smrg case LispStruct_t: 6625dfecf96Smrg if (READLABELP(object->data.struc.fields)) 6635dfecf96Smrg object->data.struc.fields = 6645dfecf96Smrg LispReadLabelCircle(object->data.struc.fields, info); 6655dfecf96Smrg else if (!LispReadCheckCircle(object, info)) { 6665dfecf96Smrg object = object->data.struc.fields; 6675dfecf96Smrg goto fix_again; 6685dfecf96Smrg } 6695dfecf96Smrg break; 6705dfecf96Smrg case LispQuote_t: 6715dfecf96Smrg case LispBackquote_t: 6725dfecf96Smrg case LispFunctionQuote_t: 6735dfecf96Smrg if (READLABELP(object->data.quote)) 6745dfecf96Smrg object->data.quote = 6755dfecf96Smrg LispReadLabelCircle(object->data.quote, info); 6765dfecf96Smrg else { 6775dfecf96Smrg object = object->data.quote; 6785dfecf96Smrg goto fix_again; 6795dfecf96Smrg } 6805dfecf96Smrg break; 6815dfecf96Smrg case LispComma_t: 6825dfecf96Smrg if (READLABELP(object->data.comma.eval)) 6835dfecf96Smrg object->data.comma.eval = 6845dfecf96Smrg LispReadLabelCircle(object->data.comma.eval, info); 6855dfecf96Smrg else { 6865dfecf96Smrg object = object->data.comma.eval; 6875dfecf96Smrg goto fix_again; 6885dfecf96Smrg } 6895dfecf96Smrg break; 6905dfecf96Smrg case LispLambda_t: 6915dfecf96Smrg if (READLABELP(object->data.lambda.code)) 6925dfecf96Smrg object->data.lambda.code = 6935dfecf96Smrg LispReadLabelCircle(object->data.lambda.code, info); 6945dfecf96Smrg else if (!LispReadCheckCircle(object, info)) { 6955dfecf96Smrg object = object->data.lambda.code; 6965dfecf96Smrg goto fix_again; 6975dfecf96Smrg } 6985dfecf96Smrg break; 6995dfecf96Smrg default: 7005dfecf96Smrg break; 7015dfecf96Smrg } 7025dfecf96Smrg} 7035dfecf96Smrg 7045dfecf96Smrgstatic LispObj * 7055dfecf96SmrgLispReadLabelCircle(LispObj *label, read_info *info) 7065dfecf96Smrg{ 7075dfecf96Smrg long i, value = READLABEL_VALUE(label); 7085dfecf96Smrg 7095dfecf96Smrg for (i = 0; i < info->num_objects; i++) 7105dfecf96Smrg if (info->objects[i].label == value) 7115dfecf96Smrg return (info->objects[i].object); 7125dfecf96Smrg 7135dfecf96Smrg LispDestroy("READ: internal error"); 7145dfecf96Smrg /*NOTREACHED*/ 7155dfecf96Smrg return (label); 7165dfecf96Smrg} 7175dfecf96Smrg 7185dfecf96Smrgstatic int 7195dfecf96SmrgLispReadCheckCircle(LispObj *object, read_info *info) 7205dfecf96Smrg{ 7215dfecf96Smrg long i; 7225dfecf96Smrg 7235dfecf96Smrg for (i = 0; i < info->num_circles; i++) 7245dfecf96Smrg if (info->circles[i] == object) 7255dfecf96Smrg return (1); 7265dfecf96Smrg 7275dfecf96Smrg if ((info->num_circles % 16) == 0) 7285dfecf96Smrg info->circles = LispRealloc(info->circles, sizeof(LispObj*) * 7295dfecf96Smrg (info->num_circles + 16)); 7305dfecf96Smrg info->circles[info->num_circles++] = object; 7315dfecf96Smrg 7325dfecf96Smrg return (0); 7335dfecf96Smrg} 7345dfecf96Smrg 7355dfecf96Smrgstatic LispObj * 7365dfecf96SmrgLispDoRead(read_info *info) 7375dfecf96Smrg{ 7385dfecf96Smrg LispObj *object; 7395dfecf96Smrg int ch = LispSkipWhiteSpace(); 7405dfecf96Smrg 7415dfecf96Smrg switch (ch) { 7425dfecf96Smrg case '(': 7435dfecf96Smrg object = LispReadList(info); 7445dfecf96Smrg break; 7455dfecf96Smrg case ')': 7465dfecf96Smrg for (ch = LispGet(); ch != EOF && ch != '\n'; ch = LispGet()) { 7475dfecf96Smrg if (!isspace(ch)) { 7485dfecf96Smrg LispUnget(ch); 7495dfecf96Smrg break; 7505dfecf96Smrg } 7515dfecf96Smrg } 7525dfecf96Smrg return (EOLIST); 7535dfecf96Smrg case EOF: 7545dfecf96Smrg return (NULL); 7555dfecf96Smrg case '\'': 7565dfecf96Smrg object = LispReadQuote(info); 7575dfecf96Smrg break; 7585dfecf96Smrg case '`': 7595dfecf96Smrg object = LispReadBackquote(info); 7605dfecf96Smrg break; 7615dfecf96Smrg case ',': 7625dfecf96Smrg object = LispReadCommaquote(info); 7635dfecf96Smrg break; 7645dfecf96Smrg case '#': 7655dfecf96Smrg object = LispReadMacro(info); 7665dfecf96Smrg break; 7675dfecf96Smrg default: 7685dfecf96Smrg LispUnget(ch); 7695dfecf96Smrg object = LispReadObject(0, info); 7705dfecf96Smrg break; 7715dfecf96Smrg } 7725dfecf96Smrg 7735dfecf96Smrg return (object); 7745dfecf96Smrg} 7755dfecf96Smrg 7765dfecf96Smrgstatic LispObj * 7775dfecf96SmrgLispReadMacro(read_info *info) 7785dfecf96Smrg{ 7795dfecf96Smrg READ_ENTER(); 7805dfecf96Smrg LispObj *result = NULL; 7815dfecf96Smrg int ch = LispGet(); 7825dfecf96Smrg 7835dfecf96Smrg switch (ch) { 7845dfecf96Smrg case '(': 7855dfecf96Smrg result = LispReadVector(info); 7865dfecf96Smrg break; 7875dfecf96Smrg case '\'': 7885dfecf96Smrg result = LispReadFunction(info); 7895dfecf96Smrg break; 7905dfecf96Smrg case 'b': 7915dfecf96Smrg case 'B': 7925dfecf96Smrg result = LispReadRational(2, info); 7935dfecf96Smrg break; 7945dfecf96Smrg case 'o': 7955dfecf96Smrg case 'O': 7965dfecf96Smrg result = LispReadRational(8, info); 7975dfecf96Smrg break; 7985dfecf96Smrg case 'x': 7995dfecf96Smrg case 'X': 8005dfecf96Smrg result = LispReadRational(16, info); 8015dfecf96Smrg break; 8025dfecf96Smrg case '\\': 8035dfecf96Smrg result = LispReadCharacter(info); 8045dfecf96Smrg break; 8055dfecf96Smrg case '|': 8065dfecf96Smrg LispSkipComment(); 8075dfecf96Smrg result = LispDoRead(info); 8085dfecf96Smrg break; 8095dfecf96Smrg case '.': /* eval when compiling */ 8105dfecf96Smrg case ',': /* eval when loading */ 8115dfecf96Smrg result = LispReadEval(info); 8125dfecf96Smrg break; 8135dfecf96Smrg case 'c': 8145dfecf96Smrg case 'C': 8155dfecf96Smrg result = LispReadComplex(info); 8165dfecf96Smrg break; 8175dfecf96Smrg case 'p': 8185dfecf96Smrg case 'P': 8195dfecf96Smrg result = LispReadPathname(info); 8205dfecf96Smrg break; 8215dfecf96Smrg case 's': 8225dfecf96Smrg case 'S': 8235dfecf96Smrg result = LispReadStruct(info); 8245dfecf96Smrg break; 8255dfecf96Smrg case '+': 8265dfecf96Smrg result = LispReadFeature(1, info); 8275dfecf96Smrg break; 8285dfecf96Smrg case '-': 8295dfecf96Smrg result = LispReadFeature(0, info); 8305dfecf96Smrg break; 8315dfecf96Smrg case ':': 8325dfecf96Smrg /* Uninterned symbol */ 8335dfecf96Smrg result = LispReadObject(1, info); 8345dfecf96Smrg break; 8355dfecf96Smrg default: 8365dfecf96Smrg if (isdigit(ch)) { 8375dfecf96Smrg LispUnget(ch); 8385dfecf96Smrg result = LispReadMacroArg(info); 8395dfecf96Smrg } 8405dfecf96Smrg else if (!info->discard) 8415dfecf96Smrg READ_ERROR1("undefined dispatch macro character #%c", ch); 8425dfecf96Smrg break; 8435dfecf96Smrg } 8445dfecf96Smrg 8455dfecf96Smrg return (result); 8465dfecf96Smrg} 8475dfecf96Smrg 8485dfecf96Smrgstatic LispObj * 8495dfecf96SmrgLispReadMacroArg(read_info *info) 8505dfecf96Smrg{ 8515dfecf96Smrg READ_ENTER(); 8525dfecf96Smrg LispObj *result = NIL; 8535dfecf96Smrg long i, integer; 8545dfecf96Smrg int ch; 8555dfecf96Smrg 8565dfecf96Smrg /* skip leading zeros */ 8575dfecf96Smrg while (ch = LispGet(), ch != EOF && isdigit(ch) && ch == '0') 8585dfecf96Smrg ; 8595dfecf96Smrg 8605dfecf96Smrg if (ch == EOF) 8615dfecf96Smrg READ_ERROR_EOF(); 8625dfecf96Smrg 8635dfecf96Smrg /* if ch is not a number the argument was zero */ 8645dfecf96Smrg if (isdigit(ch)) { 8655dfecf96Smrg char stk[32], *str; 8665dfecf96Smrg int len = 1; 8675dfecf96Smrg 8685dfecf96Smrg stk[0] = ch; 8695dfecf96Smrg for (;;) { 8705dfecf96Smrg ch = LispGet(); 8715dfecf96Smrg if (!isdigit(ch)) 8725dfecf96Smrg break; 8735dfecf96Smrg if (len + 1 >= sizeof(stk)) 8745dfecf96Smrg READ_ERROR_FIXNUM(); 8755dfecf96Smrg stk[len++] = ch; 8765dfecf96Smrg } 8775dfecf96Smrg stk[len] = '\0'; 8785dfecf96Smrg errno = 0; 8795dfecf96Smrg integer = strtol(stk, &str, 10); 8805dfecf96Smrg /* number is positive because sign is not processed here */ 8815dfecf96Smrg if (*str || errno == ERANGE || integer > MOST_POSITIVE_FIXNUM) 8825dfecf96Smrg READ_ERROR_FIXNUM(); 8835dfecf96Smrg } 8845dfecf96Smrg else 8855dfecf96Smrg integer = 0; 8865dfecf96Smrg 8875dfecf96Smrg switch (ch) { 8885dfecf96Smrg case 'a': 8895dfecf96Smrg case 'A': 8905dfecf96Smrg if (integer == 1) { 8915dfecf96Smrg /* LispReadArray and LispReadList expect 8925dfecf96Smrg * the '(' being already read */ 8935dfecf96Smrg if ((ch = LispSkipWhiteSpace()) != '(') { 8945dfecf96Smrg if (info->discard) 8955dfecf96Smrg return (ch == EOF ? NULL : NIL); 8965dfecf96Smrg READ_ERROR0("bad array specification"); 8975dfecf96Smrg } 8985dfecf96Smrg result = LispReadVector(info); 8995dfecf96Smrg } 9005dfecf96Smrg else 9015dfecf96Smrg result = LispReadArray(integer, info); 9025dfecf96Smrg break; 9035dfecf96Smrg case 'r': 9045dfecf96Smrg case 'R': 9055dfecf96Smrg result = LispReadRational(integer, info); 9065dfecf96Smrg break; 9075dfecf96Smrg case '=': 9085dfecf96Smrg if (integer > MAX_LABEL_VALUE) 9095dfecf96Smrg READ_ERROR_FIXNUM(); 9105dfecf96Smrg if (!info->discard) { 9115dfecf96Smrg long num_objects = info->num_objects; 9125dfecf96Smrg 9135dfecf96Smrg /* check for duplicated label */ 9145dfecf96Smrg for (i = 0; i < info->num_objects; i++) { 9155dfecf96Smrg if (info->objects[i].label == integer) 9165dfecf96Smrg READ_ERROR1("label #%ld# defined more than once", 9175dfecf96Smrg integer); 9185dfecf96Smrg } 9195dfecf96Smrg info->objects = LispRealloc(info->objects, 9205dfecf96Smrg sizeof(object_info) * 9215dfecf96Smrg (num_objects + 1)); 9225dfecf96Smrg /* if this label is referenced it is a shared/circular object */ 9235dfecf96Smrg info->objects[num_objects].label = integer; 9245dfecf96Smrg info->objects[num_objects].object = NULL; 9255dfecf96Smrg info->objects[num_objects].num_circles = 0; 9265dfecf96Smrg ++info->num_objects; 9275dfecf96Smrg result = LispDoRead(info); 9285dfecf96Smrg if (READLABELP(result) && READLABEL_VALUE(result) == integer) 9295dfecf96Smrg READ_ERROR2("incorrect syntax #%ld= #%ld#", 9305dfecf96Smrg integer, integer); 9315dfecf96Smrg /* any reference to it now is not shared/circular */ 9325dfecf96Smrg info->objects[num_objects].object = result; 9335dfecf96Smrg } 9345dfecf96Smrg else 9355dfecf96Smrg result = LispDoRead(info); 9365dfecf96Smrg break; 9375dfecf96Smrg case '#': 9385dfecf96Smrg if (integer > MAX_LABEL_VALUE) 9395dfecf96Smrg READ_ERROR_FIXNUM(); 9405dfecf96Smrg if (!info->discard) { 9415dfecf96Smrg /* search object */ 9425dfecf96Smrg for (i = 0; i < info->num_objects; i++) { 9435dfecf96Smrg if (info->objects[i].label == integer) { 9445dfecf96Smrg result = info->objects[i].object; 9455dfecf96Smrg if (result == NULL) { 9465dfecf96Smrg ++info->objects[i].num_circles; 9475dfecf96Smrg ++info->circle_count; 9485dfecf96Smrg result = READLABEL(integer); 9495dfecf96Smrg } 9505dfecf96Smrg break; 9515dfecf96Smrg } 9525dfecf96Smrg } 9535dfecf96Smrg if (i == info->num_objects) 9545dfecf96Smrg READ_ERROR1("undefined label #%ld#", integer); 9555dfecf96Smrg } 9565dfecf96Smrg break; 9575dfecf96Smrg default: 9585dfecf96Smrg if (!info->discard) 9595dfecf96Smrg READ_ERROR1("undefined dispatch macro character #%c", ch); 9605dfecf96Smrg break; 9615dfecf96Smrg } 9625dfecf96Smrg 9635dfecf96Smrg return (result); 9645dfecf96Smrg} 9655dfecf96Smrg 9665dfecf96Smrgstatic int 9675dfecf96SmrgLispSkipWhiteSpace(void) 9685dfecf96Smrg{ 9695dfecf96Smrg int ch; 9705dfecf96Smrg 9715dfecf96Smrg for (;;) { 9725dfecf96Smrg while (ch = LispGet(), isspace(ch) && ch != EOF) 9735dfecf96Smrg ; 9745dfecf96Smrg if (ch == ';') { 9755dfecf96Smrg while (ch = LispGet(), ch != '\n' && ch != EOF) 9765dfecf96Smrg ; 9775dfecf96Smrg if (ch == EOF) 9785dfecf96Smrg return (EOF); 9795dfecf96Smrg } 9805dfecf96Smrg else 9815dfecf96Smrg break; 9825dfecf96Smrg } 9835dfecf96Smrg 9845dfecf96Smrg return (ch); 9855dfecf96Smrg} 9865dfecf96Smrg 9875dfecf96Smrg/* any data in the format '(' FORM ')' is read here */ 9885dfecf96Smrgstatic LispObj * 9895dfecf96SmrgLispReadList(read_info *info) 9905dfecf96Smrg{ 9915dfecf96Smrg READ_ENTER(); 9925dfecf96Smrg GC_ENTER(); 9935dfecf96Smrg LispObj *result, *cons, *object; 9945dfecf96Smrg int dot = 0; 9955dfecf96Smrg 9965dfecf96Smrg ++info->level; 9975dfecf96Smrg /* check for () */ 9985dfecf96Smrg object = LispDoRead(info); 9995dfecf96Smrg if (object == EOLIST) { 10005dfecf96Smrg --info->level; 10015dfecf96Smrg 10025dfecf96Smrg return (NIL); 10035dfecf96Smrg } 10045dfecf96Smrg 10055dfecf96Smrg if (object == DOT) 10065dfecf96Smrg READ_ERROR0("illegal start of dotted list"); 10075dfecf96Smrg 10085dfecf96Smrg result = cons = CONS(object, NIL); 10095dfecf96Smrg 10105dfecf96Smrg /* make sure GC will not release data being read */ 10115dfecf96Smrg GC_PROTECT(result); 10125dfecf96Smrg 10135dfecf96Smrg while ((object = LispDoRead(info)) != EOLIST) { 10145dfecf96Smrg if (object == NULL) 10155dfecf96Smrg READ_ERROR_EOF(); 10165dfecf96Smrg if (object == DOT) { 10175dfecf96Smrg if (info->nodot == info->level) 10185dfecf96Smrg READ_ERROR0("dotted list not allowed"); 10195dfecf96Smrg /* this is a dotted list */ 10205dfecf96Smrg if (dot) 10215dfecf96Smrg READ_ERROR0("more than one . in list"); 10225dfecf96Smrg dot = 1; 10235dfecf96Smrg } 10245dfecf96Smrg else { 10255dfecf96Smrg if (dot) { 10265dfecf96Smrg /* only one object after a dot */ 10275dfecf96Smrg if (++dot > 2) 10285dfecf96Smrg READ_ERROR0("more than one object after . in list"); 10295dfecf96Smrg RPLACD(cons, object); 10305dfecf96Smrg } 10315dfecf96Smrg else { 10325dfecf96Smrg RPLACD(cons, CONS(object, NIL)); 10335dfecf96Smrg cons = CDR(cons); 10345dfecf96Smrg } 10355dfecf96Smrg } 10365dfecf96Smrg } 10375dfecf96Smrg 10385dfecf96Smrg /* this will happen if last list element was a dot */ 10395dfecf96Smrg if (dot == 1) 10405dfecf96Smrg READ_ERROR0("illegal end of dotted list"); 10415dfecf96Smrg 10425dfecf96Smrg --info->level; 10435dfecf96Smrg GC_LEAVE(); 10445dfecf96Smrg 10455dfecf96Smrg return (result); 10465dfecf96Smrg} 10475dfecf96Smrg 10485dfecf96Smrgstatic LispObj * 10495dfecf96SmrgLispReadQuote(read_info *info) 10505dfecf96Smrg{ 10515dfecf96Smrg READ_ENTER(); 10525dfecf96Smrg LispObj *quote = LispDoRead(info), *result; 10535dfecf96Smrg 10545dfecf96Smrg if (INVALIDP(quote)) 10555dfecf96Smrg READ_ERROR_INVARG(); 10565dfecf96Smrg 10575dfecf96Smrg result = QUOTE(quote); 10585dfecf96Smrg 10595dfecf96Smrg return (result); 10605dfecf96Smrg} 10615dfecf96Smrg 10625dfecf96Smrgstatic LispObj * 10635dfecf96SmrgLispReadBackquote(read_info *info) 10645dfecf96Smrg{ 10655dfecf96Smrg READ_ENTER(); 10665dfecf96Smrg LispObj *backquote = LispDoRead(info), *result; 10675dfecf96Smrg 10685dfecf96Smrg if (INVALIDP(backquote)) 10695dfecf96Smrg READ_ERROR_INVARG(); 10705dfecf96Smrg 10715dfecf96Smrg result = BACKQUOTE(backquote); 10725dfecf96Smrg 10735dfecf96Smrg return (result); 10745dfecf96Smrg} 10755dfecf96Smrg 10765dfecf96Smrgstatic LispObj * 10775dfecf96SmrgLispReadCommaquote(read_info *info) 10785dfecf96Smrg{ 10795dfecf96Smrg READ_ENTER(); 10805dfecf96Smrg LispObj *comma, *result; 10815dfecf96Smrg int atlist = LispGet(); 10825dfecf96Smrg 10835dfecf96Smrg if (atlist == EOF) 10845dfecf96Smrg READ_ERROR_EOF(); 10855dfecf96Smrg else if (atlist != '@' && atlist != '.') 10865dfecf96Smrg LispUnget(atlist); 10875dfecf96Smrg 10885dfecf96Smrg comma = LispDoRead(info); 10895dfecf96Smrg if (comma == DOT) { 10905dfecf96Smrg atlist = '@'; 10915dfecf96Smrg comma = LispDoRead(info); 10925dfecf96Smrg } 10935dfecf96Smrg if (INVALIDP(comma)) 10945dfecf96Smrg READ_ERROR_INVARG(); 10955dfecf96Smrg 10965dfecf96Smrg result = COMMA(comma, atlist == '@' || atlist == '.'); 10975dfecf96Smrg 10985dfecf96Smrg return (result); 10995dfecf96Smrg} 11005dfecf96Smrg 11015dfecf96Smrg/* 11025dfecf96Smrg * Read anything that is not readily identifiable by it's first character 11035dfecf96Smrg * and also put the code for reading atoms, numbers and strings together. 11045dfecf96Smrg */ 11055dfecf96Smrgstatic LispObj * 11065dfecf96SmrgLispReadObject(int unintern, read_info *info) 11075dfecf96Smrg{ 11085dfecf96Smrg READ_ENTER(); 11095dfecf96Smrg LispObj *object; 11105dfecf96Smrg char stk[128], *string, *package, *symbol; 11115dfecf96Smrg int ch, length, backslash, size, quote, unreadable, collon; 11125dfecf96Smrg 11135dfecf96Smrg package = symbol = string = stk; 11145dfecf96Smrg size = sizeof(stk); 11155dfecf96Smrg backslash = quote = unreadable = collon = 0; 11165dfecf96Smrg length = 0; 11175dfecf96Smrg 11185dfecf96Smrg ch = LispGet(); 11195dfecf96Smrg if (unintern && (ch == ':' || ch == '"')) 11205dfecf96Smrg READ_ERROR0("syntax error after #:"); 11215dfecf96Smrg else if (ch == '"' || ch == '|') 11225dfecf96Smrg quote = ch; 11235dfecf96Smrg else if (ch == '\\') { 11245dfecf96Smrg unreadable = backslash = 1; 11255dfecf96Smrg string[length++] = ch; 11265dfecf96Smrg } 11275dfecf96Smrg else if (ch == ':') { 11285dfecf96Smrg collon = 1; 11295dfecf96Smrg string[length++] = ch; 11305dfecf96Smrg symbol = string + 1; 1131f14f4646Smrg ch = LispGet(); 1132f14f4646Smrg if (ch == '|') { 1133f14f4646Smrg quote = ch; 1134f14f4646Smrg unreadable = 1; 1135f14f4646Smrg } 1136f14f4646Smrg else if (ch != EOF) 1137f14f4646Smrg LispUnget(ch); 11385dfecf96Smrg } 11395dfecf96Smrg else if (ch) { 11405dfecf96Smrg if (islower(ch)) 11415dfecf96Smrg ch = toupper(ch); 11425dfecf96Smrg string[length++] = ch; 11435dfecf96Smrg } 11445dfecf96Smrg else 11455dfecf96Smrg unreadable = 1; 11465dfecf96Smrg 11475dfecf96Smrg /* read remaining data */ 11485dfecf96Smrg for (; ch;) { 11495dfecf96Smrg ch = LispGet(); 11505dfecf96Smrg 11515dfecf96Smrg if (ch == EOF) { 11525dfecf96Smrg if (quote) { 11535dfecf96Smrg /* if quote, file ended with an open quoted object */ 11545dfecf96Smrg if (string != stk) 11555dfecf96Smrg LispFree(string); 11565dfecf96Smrg return (NULL); 11575dfecf96Smrg } 11585dfecf96Smrg break; 11595dfecf96Smrg } 11605dfecf96Smrg else if (ch == '\0') 11615dfecf96Smrg break; 11625dfecf96Smrg 11635dfecf96Smrg if (ch == '\\') { 11645dfecf96Smrg backslash = !backslash; 11655dfecf96Smrg if (quote == '"') { 11665dfecf96Smrg /* only remove backslashs from strings */ 11675dfecf96Smrg if (backslash) 11685dfecf96Smrg continue; 11695dfecf96Smrg } 11705dfecf96Smrg else 11715dfecf96Smrg unreadable = 1; 11725dfecf96Smrg } 11735dfecf96Smrg else if (backslash) 11745dfecf96Smrg backslash = 0; 11755dfecf96Smrg else if (ch == quote) 11765dfecf96Smrg break; 11775dfecf96Smrg else if (!quote && !backslash) { 11785dfecf96Smrg if (islower(ch)) 11795dfecf96Smrg ch = toupper(ch); 11805dfecf96Smrg else if (isspace(ch)) 11815dfecf96Smrg break; 11825dfecf96Smrg else if (AtomSeparator(ch, 0, 0)) { 11835dfecf96Smrg LispUnget(ch); 11845dfecf96Smrg break; 11855dfecf96Smrg } 11865dfecf96Smrg else if (ch == ':') { 11875dfecf96Smrg if (collon == 0 || 11885dfecf96Smrg (collon == (1 - unintern) && symbol == string + length)) { 11895dfecf96Smrg ++collon; 11905dfecf96Smrg symbol = string + length + 1; 11915dfecf96Smrg } 11925dfecf96Smrg else 11935dfecf96Smrg READ_ERROR0("too many collons"); 11945dfecf96Smrg } 11955dfecf96Smrg } 11965dfecf96Smrg 11975dfecf96Smrg if (length + 2 >= size) { 11985dfecf96Smrg if (string == stk) { 11995dfecf96Smrg size = 1024; 12005dfecf96Smrg string = LispMalloc(size); 12015dfecf96Smrg strcpy(string, stk); 12025dfecf96Smrg } 12035dfecf96Smrg else { 12045dfecf96Smrg size += 1024; 12055dfecf96Smrg string = LispRealloc(string, size); 12065dfecf96Smrg } 12075dfecf96Smrg symbol = string + (symbol - package); 12085dfecf96Smrg package = string; 12095dfecf96Smrg } 12105dfecf96Smrg string[length++] = ch; 12115dfecf96Smrg } 12125dfecf96Smrg 12135dfecf96Smrg if (info->discard) { 12145dfecf96Smrg if (string != stk) 12155dfecf96Smrg LispFree(string); 12165dfecf96Smrg 12175dfecf96Smrg return (ch == EOF ? NULL : NIL); 12185dfecf96Smrg } 12195dfecf96Smrg 12205dfecf96Smrg string[length] = '\0'; 12215dfecf96Smrg 12225dfecf96Smrg if (unintern) { 12235dfecf96Smrg if (length == 0) 12245dfecf96Smrg READ_ERROR0("syntax error after #:"); 12255dfecf96Smrg object = UNINTERNED_ATOM(string); 12265dfecf96Smrg } 12275dfecf96Smrg 12285dfecf96Smrg else if (quote == '"') 12295dfecf96Smrg object = LSTRING(string, length); 12305dfecf96Smrg 12315dfecf96Smrg else if (collon) { 12325dfecf96Smrg /* Package specified in object name */ 12335dfecf96Smrg symbol[-1] = '\0'; 12345dfecf96Smrg if (collon > 1) 12355dfecf96Smrg symbol[-2] = '\0'; 12365dfecf96Smrg object = LispParseAtom(package, symbol, 12375dfecf96Smrg collon == 2, unreadable, 12385dfecf96Smrg read__stream, read__line); 12395dfecf96Smrg } 12405dfecf96Smrg 1241f14f4646Smrg else if (quote == '|' || (unreadable && !collon)) { 1242f14f4646Smrg /* Set unreadable field, this atom needs quoting to be read back */ 1243f14f4646Smrg object = ATOM(string); 1244f14f4646Smrg object->data.atom->unreadable = 1; 1245f14f4646Smrg } 1246f14f4646Smrg 12475dfecf96Smrg /* Check some common symbols */ 12485dfecf96Smrg else if (length == 1 && string[0] == 'T') 12495dfecf96Smrg /* The T */ 12505dfecf96Smrg object = T; 12515dfecf96Smrg 12525dfecf96Smrg else if (length == 1 && string[0] == '.') 12535dfecf96Smrg /* The dot */ 12545dfecf96Smrg object = DOT; 12555dfecf96Smrg 12565dfecf96Smrg else if (length == 3 && 12575dfecf96Smrg string[0] == 'N' && string[1] == 'I' && string[2] == 'L') 12585dfecf96Smrg /* The NIL */ 12595dfecf96Smrg object = NIL; 12605dfecf96Smrg 12615dfecf96Smrg else if (isdigit(string[0]) || string[0] == '.' || 12625dfecf96Smrg ((string[0] == '-' || string[0] == '+') && string[1])) 12635dfecf96Smrg /* Looks like a number */ 12645dfecf96Smrg object = LispParseNumber(string, 10, read__stream, read__line); 12655dfecf96Smrg 12665dfecf96Smrg else 12675dfecf96Smrg /* A normal atom */ 12685dfecf96Smrg object = ATOM(string); 12695dfecf96Smrg 12705dfecf96Smrg if (string != stk) 12715dfecf96Smrg LispFree(string); 12725dfecf96Smrg 12735dfecf96Smrg return (object); 12745dfecf96Smrg} 12755dfecf96Smrg 12765dfecf96Smrgstatic LispObj * 12775dfecf96SmrgLispParseAtom(char *package, char *symbol, int intern, int unreadable, 12785dfecf96Smrg LispObj *read__stream, int read__line) 12795dfecf96Smrg{ 12805dfecf96Smrg LispObj *object = NULL, *thepackage = NULL; 12815dfecf96Smrg LispPackage *pack = NULL; 12825dfecf96Smrg 12835dfecf96Smrg if (!unreadable) { 12845dfecf96Smrg /* Until NIL and T be treated as normal symbols */ 12855dfecf96Smrg if (symbol[0] == 'N' && symbol[1] == 'I' && 12865dfecf96Smrg symbol[2] == 'L' && symbol[3] == '\0') 12875dfecf96Smrg return (NIL); 12885dfecf96Smrg if (symbol[0] == 'T' && symbol[1] == '\0') 12895dfecf96Smrg return (T); 12905dfecf96Smrg unreadable = !LispCheckAtomString(symbol); 12915dfecf96Smrg } 12925dfecf96Smrg 12935dfecf96Smrg /* If package is empty, it is a keyword */ 12945dfecf96Smrg if (package[0] == '\0') { 12955dfecf96Smrg thepackage = lisp__data.keyword; 12965dfecf96Smrg pack = lisp__data.key; 12975dfecf96Smrg } 12985dfecf96Smrg 12995dfecf96Smrg else { 13005dfecf96Smrg /* Else, search it in the package list */ 13015dfecf96Smrg thepackage = LispFindPackageFromString(package); 13025dfecf96Smrg 13035dfecf96Smrg if (thepackage == NIL) 13045dfecf96Smrg READ_ERROR1("the package %s is not available", package); 13055dfecf96Smrg 13065dfecf96Smrg pack = thepackage->data.package.package; 13075dfecf96Smrg } 13085dfecf96Smrg 13095dfecf96Smrg if (pack == lisp__data.pack && intern) { 13105dfecf96Smrg /* Redundant package specification, since requesting a 13115dfecf96Smrg * intern symbol, create it if does not exist */ 13125dfecf96Smrg 13135dfecf96Smrg object = ATOM(symbol); 13145dfecf96Smrg if (unreadable) 13155dfecf96Smrg object->data.atom->unreadable = 1; 13165dfecf96Smrg } 13175dfecf96Smrg 13185dfecf96Smrg else if (intern || pack == lisp__data.key) { 13195dfecf96Smrg /* Symbol is created, or just fetched from the specified package */ 13205dfecf96Smrg 13215dfecf96Smrg LispPackage *savepack; 13225dfecf96Smrg LispObj *savepackage = PACKAGE; 13235dfecf96Smrg 13245dfecf96Smrg /* Remember curent package */ 13255dfecf96Smrg savepack = lisp__data.pack; 13265dfecf96Smrg 13275dfecf96Smrg /* Temporarily set another package */ 13285dfecf96Smrg lisp__data.pack = pack; 13295dfecf96Smrg PACKAGE = thepackage; 13305dfecf96Smrg 13315dfecf96Smrg /* Get the object pointer */ 13325dfecf96Smrg if (pack == lisp__data.key) 1333f14f4646Smrg object = KEYWORD(LispDoGetAtom(symbol, 0)->key->value); 13345dfecf96Smrg else 13355dfecf96Smrg object = ATOM(symbol); 13365dfecf96Smrg if (unreadable) 13375dfecf96Smrg object->data.atom->unreadable = 1; 13385dfecf96Smrg 13395dfecf96Smrg /* Restore current package */ 13405dfecf96Smrg lisp__data.pack = savepack; 13415dfecf96Smrg PACKAGE = savepackage; 13425dfecf96Smrg } 13435dfecf96Smrg 13445dfecf96Smrg else { 13455dfecf96Smrg /* Symbol must exist (and be extern) in the specified package */ 13465dfecf96Smrg 13475dfecf96Smrg LispAtom *atom; 13485dfecf96Smrg 1349f14f4646Smrg atom = (LispAtom *)hash_check(pack->atoms, symbol, strlen(symbol)); 1350f14f4646Smrg if (atom) 1351f14f4646Smrg object = atom->object; 13525dfecf96Smrg 13535dfecf96Smrg /* No object found */ 13545dfecf96Smrg if (object == NULL || object->data.atom->ext == 0) 13555dfecf96Smrg READ_ERROR2("no extern symbol %s in package %s", symbol, package); 13565dfecf96Smrg } 13575dfecf96Smrg 13585dfecf96Smrg return (object); 13595dfecf96Smrg} 13605dfecf96Smrg 13615dfecf96Smrgstatic LispObj * 13625dfecf96SmrgLispParseNumber(char *str, int radix, LispObj *read__stream, int read__line) 13635dfecf96Smrg{ 13645dfecf96Smrg int len; 13655dfecf96Smrg long integer; 13665dfecf96Smrg double dfloat; 13675dfecf96Smrg char *ratio, *ptr; 13685dfecf96Smrg LispObj *number; 13695dfecf96Smrg mpi *bignum; 13705dfecf96Smrg mpr *bigratio; 13715dfecf96Smrg 13725dfecf96Smrg if (radix < 2 || radix > 36) 13735dfecf96Smrg READ_ERROR1("radix %d is not in the range 2 to 36", radix); 13745dfecf96Smrg 13755dfecf96Smrg if (*str == '\0') 13765dfecf96Smrg return (NULL); 13775dfecf96Smrg 13785dfecf96Smrg ratio = strchr(str, '/'); 13795dfecf96Smrg if (ratio) { 13805dfecf96Smrg /* check if looks like a correctly specified ratio */ 13815dfecf96Smrg if (ratio[1] == '\0' || strchr(ratio + 1, '/') != NULL) 13825dfecf96Smrg return (ATOM(str)); 13835dfecf96Smrg 13845dfecf96Smrg /* ratio must point to an integer in radix base */ 13855dfecf96Smrg *ratio++ = '\0'; 13865dfecf96Smrg } 13875dfecf96Smrg else if (radix == 10) { 13885dfecf96Smrg int dot = 0; 13895dfecf96Smrg int type = 0; 13905dfecf96Smrg 13915dfecf96Smrg /* check if it is a floating point number */ 13925dfecf96Smrg ptr = str; 13935dfecf96Smrg if (*ptr == '-' || *ptr == '+') 13945dfecf96Smrg ++ptr; 13955dfecf96Smrg else if (*ptr == '.') { 13965dfecf96Smrg dot = 1; 13975dfecf96Smrg ++ptr; 13985dfecf96Smrg } 13995dfecf96Smrg while (*ptr) { 14005dfecf96Smrg if (*ptr == '.') { 14015dfecf96Smrg if (dot) 14025dfecf96Smrg return (ATOM(str)); 14035dfecf96Smrg /* ignore it if last char is a dot */ 14045dfecf96Smrg if (ptr[1] == '\0') { 14055dfecf96Smrg *ptr = '\0'; 14065dfecf96Smrg break; 14075dfecf96Smrg } 14085dfecf96Smrg dot = 1; 14095dfecf96Smrg } 14105dfecf96Smrg else if (!isdigit(*ptr)) 14115dfecf96Smrg break; 14125dfecf96Smrg ++ptr; 14135dfecf96Smrg } 14145dfecf96Smrg 14155dfecf96Smrg switch (*ptr) { 14165dfecf96Smrg case '\0': 14175dfecf96Smrg if (dot) /* if dot, it is default float */ 14185dfecf96Smrg type = 'E'; 14195dfecf96Smrg break; 14205dfecf96Smrg case 'E': case 'S': case 'F': case 'D': case 'L': 14215dfecf96Smrg type = *ptr; 14225dfecf96Smrg *ptr = 'E'; 14235dfecf96Smrg break; 14245dfecf96Smrg default: 14255dfecf96Smrg return (ATOM(str)); /* syntax error */ 14265dfecf96Smrg } 14275dfecf96Smrg 14285dfecf96Smrg /* if type set, it is not an integer specification */ 14295dfecf96Smrg if (type) { 14305dfecf96Smrg if (*ptr) { 14315dfecf96Smrg int itype = *ptr; 14325dfecf96Smrg char *ptype = ptr; 14335dfecf96Smrg 14345dfecf96Smrg ++ptr; 14355dfecf96Smrg if (*ptr == '+' || *ptr == '-') 14365dfecf96Smrg ++ptr; 14375dfecf96Smrg while (*ptr && isdigit(*ptr)) 14385dfecf96Smrg ++ptr; 14395dfecf96Smrg if (*ptr) { 14405dfecf96Smrg *ptype = itype; 14415dfecf96Smrg 14425dfecf96Smrg return (ATOM(str)); 14435dfecf96Smrg } 14445dfecf96Smrg } 14455dfecf96Smrg 14465dfecf96Smrg dfloat = strtod(str, NULL); 14475dfecf96Smrg if (!finite(dfloat)) 14485dfecf96Smrg READ_ERROR0("floating point overflow"); 14495dfecf96Smrg 14505dfecf96Smrg return (DFLOAT(dfloat)); 14515dfecf96Smrg } 14525dfecf96Smrg } 14535dfecf96Smrg 14545dfecf96Smrg /* check if correctly specified in the given radix */ 14555dfecf96Smrg len = strlen(str) - 1; 14565dfecf96Smrg if (!ratio && radix != 10 && str[len] == '.') 14575dfecf96Smrg str[len] = '\0'; 14585dfecf96Smrg 14595dfecf96Smrg if (ratio || radix != 10) { 14605dfecf96Smrg if (!StringInRadix(str, radix, 1)) { 14615dfecf96Smrg if (ratio) 14625dfecf96Smrg ratio[-1] = '/'; 14635dfecf96Smrg return (ATOM(str)); 14645dfecf96Smrg } 14655dfecf96Smrg if (ratio && !StringInRadix(ratio, radix, 0)) { 14665dfecf96Smrg ratio[-1] = '/'; 14675dfecf96Smrg return (ATOM(str)); 14685dfecf96Smrg } 14695dfecf96Smrg } 14705dfecf96Smrg 14715dfecf96Smrg bignum = NULL; 14725dfecf96Smrg bigratio = NULL; 14735dfecf96Smrg 14745dfecf96Smrg errno = 0; 14755dfecf96Smrg integer = strtol(str, NULL, radix); 14765dfecf96Smrg 14775dfecf96Smrg /* if does not fit in a long */ 147831de2854Smrg if (errno == ERANGE) { 14795dfecf96Smrg bignum = LispMalloc(sizeof(mpi)); 14805dfecf96Smrg mpi_init(bignum); 14815dfecf96Smrg mpi_setstr(bignum, str, radix); 14825dfecf96Smrg } 14835dfecf96Smrg 14845dfecf96Smrg 14855dfecf96Smrg if (ratio && integer != 0) { 14865dfecf96Smrg long denominator; 14875dfecf96Smrg 14885dfecf96Smrg errno = 0; 14895dfecf96Smrg denominator = strtol(ratio, NULL, radix); 14905dfecf96Smrg if (denominator == 0) 14915dfecf96Smrg READ_ERROR0("divide by zero"); 14925dfecf96Smrg 14935dfecf96Smrg if (bignum == NULL) { 14945dfecf96Smrg if (integer == MINSLONG || 14955dfecf96Smrg (denominator == LONG_MAX && errno == ERANGE)) { 14965dfecf96Smrg bigratio = LispMalloc(sizeof(mpr)); 14975dfecf96Smrg mpr_init(bigratio); 14985dfecf96Smrg mpi_seti(mpr_num(bigratio), integer); 14995dfecf96Smrg mpi_setstr(mpr_den(bigratio), ratio, radix); 15005dfecf96Smrg } 15015dfecf96Smrg } 15025dfecf96Smrg else { 15035dfecf96Smrg bigratio = LispMalloc(sizeof(mpr)); 15045dfecf96Smrg mpr_init(bigratio); 15055dfecf96Smrg mpi_set(mpr_num(bigratio), bignum); 15065dfecf96Smrg mpi_clear(bignum); 15075dfecf96Smrg LispFree(bignum); 15085dfecf96Smrg mpi_setstr(mpr_den(bigratio), ratio, radix); 15095dfecf96Smrg } 15105dfecf96Smrg 15115dfecf96Smrg if (bigratio) { 15125dfecf96Smrg mpr_canonicalize(bigratio); 15135dfecf96Smrg if (mpi_fiti(mpr_num(bigratio)) && 15145dfecf96Smrg mpi_fiti(mpr_den(bigratio))) { 15155dfecf96Smrg integer = mpi_geti(mpr_num(bigratio)); 15165dfecf96Smrg denominator = mpi_geti(mpr_den(bigratio)); 15175dfecf96Smrg mpr_clear(bigratio); 15185dfecf96Smrg LispFree(bigratio); 15195dfecf96Smrg if (denominator == 1) 15205dfecf96Smrg number = INTEGER(integer); 15215dfecf96Smrg else 15225dfecf96Smrg number = RATIO(integer, denominator); 15235dfecf96Smrg } 15245dfecf96Smrg else 15255dfecf96Smrg number = BIGRATIO(bigratio); 15265dfecf96Smrg } 15275dfecf96Smrg else { 15285dfecf96Smrg long num = integer, den = denominator, rest; 15295dfecf96Smrg 15305dfecf96Smrg if (num < 0) 15315dfecf96Smrg num = -num; 15325dfecf96Smrg for (;;) { 15335dfecf96Smrg if ((rest = den % num) == 0) 15345dfecf96Smrg break; 15355dfecf96Smrg den = num; 15365dfecf96Smrg num = rest; 15375dfecf96Smrg } 15385dfecf96Smrg if (den != 1) { 15395dfecf96Smrg denominator /= num; 15405dfecf96Smrg integer /= num; 15415dfecf96Smrg } 15425dfecf96Smrg if (denominator < 0) { 15435dfecf96Smrg integer = -integer; 15445dfecf96Smrg denominator = -denominator; 15455dfecf96Smrg } 15465dfecf96Smrg if (denominator == 1) 15475dfecf96Smrg number = INTEGER(integer); 15485dfecf96Smrg else 15495dfecf96Smrg number = RATIO(integer, denominator); 15505dfecf96Smrg } 15515dfecf96Smrg } 15525dfecf96Smrg else if (bignum) 15535dfecf96Smrg number = BIGNUM(bignum); 15545dfecf96Smrg else 15555dfecf96Smrg number = INTEGER(integer); 15565dfecf96Smrg 15575dfecf96Smrg return (number); 15585dfecf96Smrg} 15595dfecf96Smrg 15605dfecf96Smrgstatic int 15615dfecf96SmrgStringInRadix(char *str, int radix, int skip_sign) 15625dfecf96Smrg{ 15635dfecf96Smrg if (skip_sign && (*str == '-' || *str == '+')) 15645dfecf96Smrg ++str; 15655dfecf96Smrg while (*str) { 15665dfecf96Smrg if (*str >= '0' && *str <= '9') { 15675dfecf96Smrg if (*str - '0' >= radix) 15685dfecf96Smrg return (0); 15695dfecf96Smrg } 15705dfecf96Smrg else if (*str >= 'A' && *str <= 'Z') { 15715dfecf96Smrg if (radix <= 10 || *str - 'A' + 10 >= radix) 15725dfecf96Smrg return (0); 15735dfecf96Smrg } 15745dfecf96Smrg else 15755dfecf96Smrg return (0); 15765dfecf96Smrg str++; 15775dfecf96Smrg } 15785dfecf96Smrg 15795dfecf96Smrg return (1); 15805dfecf96Smrg} 15815dfecf96Smrg 15825dfecf96Smrgstatic int 15835dfecf96SmrgAtomSeparator(int ch, int check_space, int check_backslash) 15845dfecf96Smrg{ 15855dfecf96Smrg if (check_space && isspace(ch)) 15865dfecf96Smrg return (1); 15875dfecf96Smrg if (check_backslash && ch == '\\') 15885dfecf96Smrg return (1); 15895dfecf96Smrg return (strchr("(),\";'`#|,", ch) != NULL); 15905dfecf96Smrg} 15915dfecf96Smrg 15925dfecf96Smrgstatic LispObj * 15935dfecf96SmrgLispReadVector(read_info *info) 15945dfecf96Smrg{ 15955dfecf96Smrg LispObj *objects; 15965dfecf96Smrg int nodot = info->nodot; 15975dfecf96Smrg 15985dfecf96Smrg info->nodot = info->level + 1; 15995dfecf96Smrg objects = LispReadList(info); 16005dfecf96Smrg info->nodot = nodot; 16015dfecf96Smrg 16025dfecf96Smrg if (info->discard) 16035dfecf96Smrg return (objects); 16045dfecf96Smrg 16055dfecf96Smrg return (VECTOR(objects)); 16065dfecf96Smrg} 16075dfecf96Smrg 16085dfecf96Smrgstatic LispObj * 16095dfecf96SmrgLispReadFunction(read_info *info) 16105dfecf96Smrg{ 16115dfecf96Smrg READ_ENTER(); 16125dfecf96Smrg int nodot = info->nodot; 16135dfecf96Smrg LispObj *function; 16145dfecf96Smrg 16155dfecf96Smrg info->nodot = info->level + 1; 16165dfecf96Smrg function = LispDoRead(info); 16175dfecf96Smrg info->nodot = nodot; 16185dfecf96Smrg 16195dfecf96Smrg if (info->discard) 16205dfecf96Smrg return (function); 16215dfecf96Smrg 16225dfecf96Smrg if (INVALIDP(function)) 16235dfecf96Smrg READ_ERROR_INVARG(); 16245dfecf96Smrg else if (CONSP(function)) { 16255dfecf96Smrg if (CAR(function) != Olambda) 16265dfecf96Smrg READ_ERROR_INVARG(); 16275dfecf96Smrg 16285dfecf96Smrg return (FUNCTION_QUOTE(function)); 16295dfecf96Smrg } 16305dfecf96Smrg else if (!SYMBOLP(function)) 16315dfecf96Smrg READ_ERROR_INVARG(); 16325dfecf96Smrg 16335dfecf96Smrg return (FUNCTION_QUOTE(function)); 16345dfecf96Smrg} 16355dfecf96Smrg 16365dfecf96Smrgstatic LispObj * 16375dfecf96SmrgLispReadRational(int radix, read_info *info) 16385dfecf96Smrg{ 16395dfecf96Smrg READ_ENTER(); 16405dfecf96Smrg LispObj *number; 16415dfecf96Smrg int ch, len, size; 16425dfecf96Smrg char stk[128], *str; 16435dfecf96Smrg 16445dfecf96Smrg len = 0; 16455dfecf96Smrg str = stk; 16465dfecf96Smrg size = sizeof(stk); 16475dfecf96Smrg 16485dfecf96Smrg for (;;) { 16495dfecf96Smrg ch = LispGet(); 16505dfecf96Smrg if (ch == EOF || isspace(ch)) 16515dfecf96Smrg break; 16525dfecf96Smrg else if (AtomSeparator(ch, 0, 1)) { 16535dfecf96Smrg LispUnget(ch); 16545dfecf96Smrg break; 16555dfecf96Smrg } 16565dfecf96Smrg else if (islower(ch)) 16575dfecf96Smrg ch = toupper(ch); 16585dfecf96Smrg if ((ch < '0' || ch > '9') && (ch < 'A' || ch > 'Z') && 16595dfecf96Smrg ch != '+' && ch != '-' && ch != '/') { 16605dfecf96Smrg if (str != stk) 16615dfecf96Smrg LispFree(str); 16625dfecf96Smrg if (!info->discard) 16635dfecf96Smrg READ_ERROR1("bad character %c for rational number", ch); 16645dfecf96Smrg } 16655dfecf96Smrg if (len + 1 >= size) { 16665dfecf96Smrg if (str == stk) { 16675dfecf96Smrg size = 512; 16685dfecf96Smrg str = LispMalloc(size); 16695dfecf96Smrg strcpy(str + 1, stk + 1); 16705dfecf96Smrg } 16715dfecf96Smrg else { 16725dfecf96Smrg size += 512; 16735dfecf96Smrg str = LispRealloc(str, size); 16745dfecf96Smrg } 16755dfecf96Smrg } 16765dfecf96Smrg str[len++] = ch; 16775dfecf96Smrg } 16785dfecf96Smrg 16795dfecf96Smrg if (info->discard) { 16805dfecf96Smrg if (str != stk) 16815dfecf96Smrg LispFree(str); 16825dfecf96Smrg 16835dfecf96Smrg return (ch == EOF ? NULL : NIL); 16845dfecf96Smrg } 16855dfecf96Smrg 16865dfecf96Smrg str[len] = '\0'; 16875dfecf96Smrg 16885dfecf96Smrg number = LispParseNumber(str, radix, read__stream, read__line); 16895dfecf96Smrg if (str != stk) 16905dfecf96Smrg LispFree(str); 16915dfecf96Smrg 16925dfecf96Smrg if (!RATIONALP(number)) 16935dfecf96Smrg READ_ERROR0("bad rational number specification"); 16945dfecf96Smrg 16955dfecf96Smrg return (number); 16965dfecf96Smrg} 16975dfecf96Smrg 16985dfecf96Smrgstatic LispObj * 16995dfecf96SmrgLispReadCharacter(read_info *info) 17005dfecf96Smrg{ 17015dfecf96Smrg READ_ENTER(); 17025dfecf96Smrg long c; 17035dfecf96Smrg int ch, len; 17045dfecf96Smrg char stk[64]; 17055dfecf96Smrg 17065dfecf96Smrg ch = LispGet(); 17075dfecf96Smrg if (ch == EOF) 17085dfecf96Smrg return (NULL); 17095dfecf96Smrg 17105dfecf96Smrg stk[0] = ch; 17115dfecf96Smrg len = 1; 17125dfecf96Smrg 17135dfecf96Smrg for (;;) { 17145dfecf96Smrg ch = LispGet(); 17155dfecf96Smrg if (ch == EOF) 17165dfecf96Smrg break; 17175dfecf96Smrg else if (ch != '-' && !isalnum(ch)) { 17185dfecf96Smrg LispUnget(ch); 17195dfecf96Smrg break; 17205dfecf96Smrg } 17215dfecf96Smrg if (len + 1 < sizeof(stk)) 17225dfecf96Smrg stk[len++] = ch; 17235dfecf96Smrg } 17245dfecf96Smrg if (len > 1) { 1725f765521fSmrg const char * const *names; 17265dfecf96Smrg int found = 0; 17275dfecf96Smrg stk[len] = '\0'; 17285dfecf96Smrg 17295dfecf96Smrg for (c = ch = 0; ch <= ' ' && !found; ch++) { 17305dfecf96Smrg for (names = LispChars[ch].names; *names; names++) 17315dfecf96Smrg if (strcasecmp(*names, stk) == 0) { 17325dfecf96Smrg c = ch; 17335dfecf96Smrg found = 1; 17345dfecf96Smrg break; 17355dfecf96Smrg } 17365dfecf96Smrg } 17375dfecf96Smrg if (!found) { 17385dfecf96Smrg for (names = LispChars[0177].names; *names; names++) 17395dfecf96Smrg if (strcasecmp(*names, stk) == 0) { 17405dfecf96Smrg c = 0177; 17415dfecf96Smrg found = 1; 17425dfecf96Smrg break; 17435dfecf96Smrg } 17445dfecf96Smrg } 17455dfecf96Smrg 17465dfecf96Smrg if (!found) { 17475dfecf96Smrg if (info->discard) 17485dfecf96Smrg return (NIL); 17495dfecf96Smrg READ_ERROR1("unkwnown character %s", stk); 17505dfecf96Smrg } 17515dfecf96Smrg } 17525dfecf96Smrg else 17535dfecf96Smrg c = stk[0]; 17545dfecf96Smrg 17555dfecf96Smrg return (SCHAR(c)); 17565dfecf96Smrg} 17575dfecf96Smrg 17585dfecf96Smrgstatic void 17595dfecf96SmrgLispSkipComment(void) 17605dfecf96Smrg{ 17615dfecf96Smrg READ_ENTER(); 17625dfecf96Smrg int ch, comm = 1; 17635dfecf96Smrg 17645dfecf96Smrg for (;;) { 17655dfecf96Smrg ch = LispGet(); 17665dfecf96Smrg if (ch == '#') { 17675dfecf96Smrg ch = LispGet(); 17685dfecf96Smrg if (ch == '|') 17695dfecf96Smrg ++comm; 17705dfecf96Smrg continue; 17715dfecf96Smrg } 17725dfecf96Smrg while (ch == '|') { 17735dfecf96Smrg ch = LispGet(); 17745dfecf96Smrg if (ch == '#' && --comm == 0) 17755dfecf96Smrg return; 17765dfecf96Smrg } 17775dfecf96Smrg if (ch == EOF) 17785dfecf96Smrg READ_ERROR_EOF(); 17795dfecf96Smrg } 17805dfecf96Smrg} 17815dfecf96Smrg 17825dfecf96Smrgstatic LispObj * 17835dfecf96SmrgLispReadEval(read_info *info) 17845dfecf96Smrg{ 17855dfecf96Smrg READ_ENTER(); 17865dfecf96Smrg int nodot = info->nodot; 17875dfecf96Smrg LispObj *code; 17885dfecf96Smrg 17895dfecf96Smrg info->nodot = info->level + 1; 17905dfecf96Smrg code = LispDoRead(info); 17915dfecf96Smrg info->nodot = nodot; 17925dfecf96Smrg 17935dfecf96Smrg if (info->discard) 17945dfecf96Smrg return (code); 17955dfecf96Smrg 17965dfecf96Smrg if (INVALIDP(code)) 17975dfecf96Smrg READ_ERROR_INVARG(); 17985dfecf96Smrg 17995dfecf96Smrg return (EVAL(code)); 18005dfecf96Smrg} 18015dfecf96Smrg 18025dfecf96Smrgstatic LispObj * 18035dfecf96SmrgLispReadComplex(read_info *info) 18045dfecf96Smrg{ 18055dfecf96Smrg READ_ENTER(); 18065dfecf96Smrg GC_ENTER(); 18075dfecf96Smrg int nodot = info->nodot; 18085dfecf96Smrg LispObj *number, *arguments; 18095dfecf96Smrg 18105dfecf96Smrg info->nodot = info->level + 1; 18115dfecf96Smrg arguments = LispDoRead(info); 18125dfecf96Smrg info->nodot = nodot; 18135dfecf96Smrg 18145dfecf96Smrg /* form read */ 18155dfecf96Smrg if (info->discard) 18165dfecf96Smrg return (arguments); 18175dfecf96Smrg 18185dfecf96Smrg if (INVALIDP(arguments) || !CONSP(arguments)) 18195dfecf96Smrg READ_ERROR_INVARG(); 18205dfecf96Smrg 18215dfecf96Smrg GC_PROTECT(arguments); 18225dfecf96Smrg number = APPLY(Ocomplex, arguments); 18235dfecf96Smrg GC_LEAVE(); 18245dfecf96Smrg 18255dfecf96Smrg return (number); 18265dfecf96Smrg} 18275dfecf96Smrg 18285dfecf96Smrgstatic LispObj * 18295dfecf96SmrgLispReadPathname(read_info *info) 18305dfecf96Smrg{ 18315dfecf96Smrg READ_ENTER(); 18325dfecf96Smrg GC_ENTER(); 18335dfecf96Smrg int nodot = info->nodot; 18345dfecf96Smrg LispObj *path, *arguments; 18355dfecf96Smrg 18365dfecf96Smrg info->nodot = info->level + 1; 18375dfecf96Smrg arguments = LispDoRead(info); 18385dfecf96Smrg info->nodot = nodot; 18395dfecf96Smrg 18405dfecf96Smrg /* form read */ 18415dfecf96Smrg if (info->discard) 18425dfecf96Smrg return (arguments); 18435dfecf96Smrg 18445dfecf96Smrg if (INVALIDP(arguments)) 18455dfecf96Smrg READ_ERROR_INVARG(); 18465dfecf96Smrg 18475dfecf96Smrg GC_PROTECT(arguments); 18485dfecf96Smrg path = APPLY1(Oparse_namestring, arguments); 18495dfecf96Smrg GC_LEAVE(); 18505dfecf96Smrg 18515dfecf96Smrg return (path); 18525dfecf96Smrg} 18535dfecf96Smrg 18545dfecf96Smrgstatic LispObj * 18555dfecf96SmrgLispReadStruct(read_info *info) 18565dfecf96Smrg{ 18575dfecf96Smrg READ_ENTER(); 18585dfecf96Smrg GC_ENTER(); 18595dfecf96Smrg int len, nodot = info->nodot; 18605dfecf96Smrg char stk[128], *str; 18615dfecf96Smrg LispObj *struc, *fields; 18625dfecf96Smrg 18635dfecf96Smrg info->nodot = info->level + 1; 18645dfecf96Smrg fields = LispDoRead(info); 18655dfecf96Smrg info->nodot = nodot; 18665dfecf96Smrg 18675dfecf96Smrg /* form read */ 18685dfecf96Smrg if (info->discard) 18695dfecf96Smrg return (fields); 18705dfecf96Smrg 18715dfecf96Smrg if (INVALIDP(fields) || !CONSP(fields) || !SYMBOLP(CAR(fields))) 18725dfecf96Smrg READ_ERROR_INVARG(); 18735dfecf96Smrg 18745dfecf96Smrg GC_PROTECT(fields); 18755dfecf96Smrg 1876f14f4646Smrg len = ATOMID(CAR(fields))->length; 18775dfecf96Smrg /* MAKE- */ 18785dfecf96Smrg if (len + 6 > sizeof(stk)) 18795dfecf96Smrg str = LispMalloc(len + 6); 18805dfecf96Smrg else 18815dfecf96Smrg str = stk; 1882f14f4646Smrg sprintf(str, "MAKE-%s", ATOMID(CAR(fields))->value); 18835dfecf96Smrg RPLACA(fields, ATOM(str)); 18845dfecf96Smrg if (str != stk) 18855dfecf96Smrg LispFree(str); 18865dfecf96Smrg struc = APPLY(Omake_struct, fields); 18875dfecf96Smrg GC_LEAVE(); 18885dfecf96Smrg 18895dfecf96Smrg return (struc); 18905dfecf96Smrg} 18915dfecf96Smrg 18925dfecf96Smrg/* XXX This is broken, needs a rewritten as soon as true vector/arrays be 18935dfecf96Smrg * implemented. */ 18945dfecf96Smrgstatic LispObj * 18955dfecf96SmrgLispReadArray(long dimensions, read_info *info) 18965dfecf96Smrg{ 18975dfecf96Smrg READ_ENTER(); 18985dfecf96Smrg GC_ENTER(); 18995dfecf96Smrg long count; 19005dfecf96Smrg int nodot = info->nodot; 19015dfecf96Smrg LispObj *arguments, *initial, *dim, *cons, *array, *data; 19025dfecf96Smrg 19035dfecf96Smrg info->nodot = info->level + 1; 19045dfecf96Smrg data = LispDoRead(info); 19055dfecf96Smrg info->nodot = nodot; 19065dfecf96Smrg 19075dfecf96Smrg /* form read */ 19085dfecf96Smrg if (info->discard) 19095dfecf96Smrg return (data); 19105dfecf96Smrg 19115dfecf96Smrg if (INVALIDP(data)) 19125dfecf96Smrg READ_ERROR_INVARG(); 19135dfecf96Smrg 19145dfecf96Smrg initial = Kinitial_contents; 19155dfecf96Smrg 19165dfecf96Smrg dim = cons = NIL; 19175dfecf96Smrg if (dimensions) { 19185dfecf96Smrg LispObj *array; 19195dfecf96Smrg 19205dfecf96Smrg for (count = 0, array = data; count < dimensions; count++) { 19215dfecf96Smrg long length; 19225dfecf96Smrg LispObj *item; 19235dfecf96Smrg 19245dfecf96Smrg if (!CONSP(array)) 19255dfecf96Smrg READ_ERROR0("bad array for given dimension"); 19265dfecf96Smrg item = array; 19275dfecf96Smrg array = CAR(array); 19285dfecf96Smrg 19295dfecf96Smrg for (length = 0; CONSP(item); item = CDR(item), length++) 19305dfecf96Smrg ; 19315dfecf96Smrg 19325dfecf96Smrg if (dim == NIL) { 19335dfecf96Smrg dim = cons = CONS(FIXNUM(length), NIL); 19345dfecf96Smrg GC_PROTECT(dim); 19355dfecf96Smrg } 19365dfecf96Smrg else { 19375dfecf96Smrg RPLACD(cons, CONS(FIXNUM(length), NIL)); 19385dfecf96Smrg cons = CDR(cons); 19395dfecf96Smrg } 19405dfecf96Smrg } 19415dfecf96Smrg } 19425dfecf96Smrg 19435dfecf96Smrg arguments = CONS(dim, CONS(initial, CONS(data, NIL))); 19445dfecf96Smrg GC_PROTECT(arguments); 19455dfecf96Smrg array = APPLY(Omake_array, arguments); 19465dfecf96Smrg GC_LEAVE(); 19475dfecf96Smrg 19485dfecf96Smrg return (array); 19495dfecf96Smrg} 19505dfecf96Smrg 19515dfecf96Smrgstatic LispObj * 19525dfecf96SmrgLispReadFeature(int with, read_info *info) 19535dfecf96Smrg{ 19545dfecf96Smrg READ_ENTER(); 19555dfecf96Smrg LispObj *status; 19565dfecf96Smrg LispObj *feature = LispDoRead(info); 19575dfecf96Smrg 19585dfecf96Smrg /* form read */ 19595dfecf96Smrg if (info->discard) 19605dfecf96Smrg return (feature); 19615dfecf96Smrg 19625dfecf96Smrg if (INVALIDP(feature)) 19635dfecf96Smrg READ_ERROR_INVARG(); 19645dfecf96Smrg 19655dfecf96Smrg /* paranoia check, features must be a list, possibly empty */ 19665dfecf96Smrg if (!CONSP(FEATURES) && FEATURES != NIL) 19675dfecf96Smrg READ_ERROR1("%s is not a list", STROBJ(FEATURES)); 19685dfecf96Smrg 19695dfecf96Smrg status = LispEvalFeature(feature); 19705dfecf96Smrg 19715dfecf96Smrg if (with) { 19725dfecf96Smrg if (status == T) 19735dfecf96Smrg return (LispDoRead(info)); 19745dfecf96Smrg 19755dfecf96Smrg /* need to use the field discard because the following expression 19765dfecf96Smrg * may be #.FORM or #,FORM or any other form that may generate 19775dfecf96Smrg * side effects */ 19785dfecf96Smrg info->discard = 1; 19795dfecf96Smrg LispDoRead(info); 19805dfecf96Smrg info->discard = 0; 19815dfecf96Smrg 19825dfecf96Smrg return (LispDoRead(info)); 19835dfecf96Smrg } 19845dfecf96Smrg 19855dfecf96Smrg if (status == NIL) 19865dfecf96Smrg return (LispDoRead(info)); 19875dfecf96Smrg 19885dfecf96Smrg info->discard = 1; 19895dfecf96Smrg LispDoRead(info); 19905dfecf96Smrg info->discard = 0; 19915dfecf96Smrg 19925dfecf96Smrg return (LispDoRead(info)); 19935dfecf96Smrg} 19945dfecf96Smrg 19955dfecf96Smrg/* 19965dfecf96Smrg * A very simple eval loop with AND, NOT, and OR functions for testing 19975dfecf96Smrg * the available features. 19985dfecf96Smrg */ 19995dfecf96Smrgstatic LispObj * 20005dfecf96SmrgLispEvalFeature(LispObj *feature) 20015dfecf96Smrg{ 20025dfecf96Smrg READ_ENTER(); 20035dfecf96Smrg Atom_id test; 20045dfecf96Smrg LispObj *object; 20055dfecf96Smrg 20065dfecf96Smrg if (CONSP(feature)) { 20075dfecf96Smrg LispObj *function = CAR(feature), *arguments = CDR(feature); 20085dfecf96Smrg 20095dfecf96Smrg if (!SYMBOLP(function)) 20105dfecf96Smrg READ_ERROR1("bad feature test function %s", STROBJ(function)); 20115dfecf96Smrg if (!CONSP(arguments)) 20125dfecf96Smrg READ_ERROR1("bad feature test arguments %s", STROBJ(arguments)); 20135dfecf96Smrg test = ATOMID(function); 20145dfecf96Smrg if (test == Sand) { 20155dfecf96Smrg for (; CONSP(arguments); arguments = CDR(arguments)) { 20165dfecf96Smrg if (LispEvalFeature(CAR(arguments)) == NIL) 20175dfecf96Smrg return (NIL); 20185dfecf96Smrg } 20195dfecf96Smrg return (T); 20205dfecf96Smrg } 20215dfecf96Smrg else if (test == Sor) { 20225dfecf96Smrg for (; CONSP(arguments); arguments = CDR(arguments)) { 20235dfecf96Smrg if (LispEvalFeature(CAR(arguments)) == T) 20245dfecf96Smrg return (T); 20255dfecf96Smrg } 20265dfecf96Smrg return (NIL); 20275dfecf96Smrg } 20285dfecf96Smrg else if (test == Snot) { 20295dfecf96Smrg if (CONSP(CDR(arguments))) 20305dfecf96Smrg READ_ERROR0("too many arguments to NOT"); 20315dfecf96Smrg 20325dfecf96Smrg return (LispEvalFeature(CAR(arguments)) == NIL ? T : NIL); 20335dfecf96Smrg } 20345dfecf96Smrg else 20355dfecf96Smrg READ_ERROR1("unimplemented feature test function %s", test); 20365dfecf96Smrg } 20375dfecf96Smrg 20385dfecf96Smrg if (KEYWORDP(feature)) 20395dfecf96Smrg feature = feature->data.quote; 20405dfecf96Smrg else if (!SYMBOLP(feature)) 20415dfecf96Smrg READ_ERROR1("bad feature specification %s", STROBJ(feature)); 20425dfecf96Smrg 20435dfecf96Smrg test = ATOMID(feature); 20445dfecf96Smrg 20455dfecf96Smrg for (object = FEATURES; CONSP(object); object = CDR(object)) { 20465dfecf96Smrg /* paranoia check, elements in the feature list must ge keywords */ 20475dfecf96Smrg if (!KEYWORDP(CAR(object))) 20485dfecf96Smrg READ_ERROR1("%s is not a keyword", STROBJ(CAR(object))); 20495dfecf96Smrg if (ATOMID(CAR(object)) == test) 20505dfecf96Smrg return (T); 20515dfecf96Smrg } 20525dfecf96Smrg 20535dfecf96Smrg /* unknown feature */ 20545dfecf96Smrg return (NIL); 20555dfecf96Smrg} 2056