read.c revision f14f4646
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 655dfecf96Smrg#ifdef __UNIXOS2__ 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 1095dfecf96Smrgstatic void LispReadError(LispObj*, int, 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 */ 1435dfecf96Smrgstatic char *Char_Nul[] = {"Null", "Nul", NULL}; 1445dfecf96Smrgstatic char *Char_Soh[] = {"Soh", NULL}; 1455dfecf96Smrgstatic char *Char_Stx[] = {"Stx", NULL}; 1465dfecf96Smrgstatic char *Char_Etx[] = {"Etx", NULL}; 1475dfecf96Smrgstatic char *Char_Eot[] = {"Eot", NULL}; 1485dfecf96Smrgstatic char *Char_Enq[] = {"Enq", NULL}; 1495dfecf96Smrgstatic char *Char_Ack[] = {"Ack", NULL}; 1505dfecf96Smrgstatic char *Char_Bel[] = {"Bell", "Bel", NULL}; 1515dfecf96Smrgstatic char *Char_Bs[] = {"Backspace", "Bs", NULL}; 1525dfecf96Smrgstatic char *Char_Tab[] = {"Tab", NULL}; 1535dfecf96Smrgstatic char *Char_Nl[] = {"Newline", "Nl", "Lf", "Linefeed", NULL}; 1545dfecf96Smrgstatic char *Char_Vt[] = {"Vt", NULL}; 1555dfecf96Smrgstatic char *Char_Np[] = {"Page", "Np", NULL}; 1565dfecf96Smrgstatic char *Char_Cr[] = {"Return", "Cr", NULL}; 1575dfecf96Smrgstatic char *Char_Ff[] = {"So", "Ff", NULL}; 1585dfecf96Smrgstatic char *Char_Si[] = {"Si", NULL}; 1595dfecf96Smrgstatic char *Char_Dle[] = {"Dle", NULL}; 1605dfecf96Smrgstatic char *Char_Dc1[] = {"Dc1", NULL}; 1615dfecf96Smrgstatic char *Char_Dc2[] = {"Dc2", NULL}; 1625dfecf96Smrgstatic char *Char_Dc3[] = {"Dc3", NULL}; 1635dfecf96Smrgstatic char *Char_Dc4[] = {"Dc4", NULL}; 1645dfecf96Smrgstatic char *Char_Nak[] = {"Nak", NULL}; 1655dfecf96Smrgstatic char *Char_Syn[] = {"Syn", NULL}; 1665dfecf96Smrgstatic char *Char_Etb[] = {"Etb", NULL}; 1675dfecf96Smrgstatic char *Char_Can[] = {"Can", NULL}; 1685dfecf96Smrgstatic char *Char_Em[] = {"Em", NULL}; 1695dfecf96Smrgstatic char *Char_Sub[] = {"Sub", NULL}; 1705dfecf96Smrgstatic char *Char_Esc[] = {"Escape", "Esc", NULL}; 1715dfecf96Smrgstatic char *Char_Fs[] = {"Fs", NULL}; 1725dfecf96Smrgstatic char *Char_Gs[] = {"Gs", NULL}; 1735dfecf96Smrgstatic char *Char_Rs[] = {"Rs", NULL}; 1745dfecf96Smrgstatic char *Char_Us[] = {"Us", NULL}; 1755dfecf96Smrgstatic char *Char_Sp[] = {"Space", "Sp", NULL}; 1765dfecf96Smrgstatic char *Char_Del[] = {"Rubout", "Del", "Delete", NULL}; 1775dfecf96Smrg 1785dfecf96SmrgLispCharInfo 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 6005dfecf96SmrgLispReadError(LispObj *stream, int line, char *fmt, ...) 6015dfecf96Smrg{ 6025dfecf96Smrg char string[128], *buffer_string; 6035dfecf96Smrg LispObj *buffer = LSTRINGSTREAM("", STREAM_READ | STREAM_WRITE, 0); 6045dfecf96Smrg int length; 6055dfecf96Smrg va_list ap; 6065dfecf96Smrg 6075dfecf96Smrg va_start(ap, fmt); 6085dfecf96Smrg vsnprintf(string, sizeof(string), fmt, ap); 6095dfecf96Smrg va_end(ap); 6105dfecf96Smrg 6115dfecf96Smrg LispFwrite(Stderr, "*** Reading ", 12); 6125dfecf96Smrg LispWriteObject(buffer, stream); 6135dfecf96Smrg buffer_string = LispGetSstring(SSTREAMP(buffer), &length); 6145dfecf96Smrg LispFwrite(Stderr, buffer_string, length); 6155dfecf96Smrg LispFwrite(Stderr, " at line ", 9); 6165dfecf96Smrg if (line < 0) 6175dfecf96Smrg LispFwrite(Stderr, "?\n", 2); 6185dfecf96Smrg else { 6195dfecf96Smrg char str[32]; 6205dfecf96Smrg 6215dfecf96Smrg sprintf(str, "%d\n", line); 6225dfecf96Smrg LispFputs(Stderr, str); 6235dfecf96Smrg } 6245dfecf96Smrg 6255dfecf96Smrg LispDestroy("READ: %s", string); 6265dfecf96Smrg} 6275dfecf96Smrg 6285dfecf96Smrgstatic void 6295dfecf96SmrgLispReadFixCircle(LispObj *object, read_info *info) 6305dfecf96Smrg{ 6315dfecf96Smrg LispObj *cons; 6325dfecf96Smrg 6335dfecf96Smrgfix_again: 6345dfecf96Smrg switch (OBJECT_TYPE(object)) { 6355dfecf96Smrg case LispCons_t: 6365dfecf96Smrg for (cons = object; 6375dfecf96Smrg CONSP(object); 6385dfecf96Smrg cons = object, object = CDR(object)) { 6395dfecf96Smrg if (READLABELP(CAR(object))) 6405dfecf96Smrg CAR(object) = LispReadLabelCircle(CAR(object), info); 6415dfecf96Smrg else if (LispReadCheckCircle(object, info)) 6425dfecf96Smrg return; 6435dfecf96Smrg else 6445dfecf96Smrg LispReadFixCircle(CAR(object), info); 6455dfecf96Smrg } 6465dfecf96Smrg if (READLABELP(object)) 6475dfecf96Smrg CDR(cons) = LispReadLabelCircle(object, info); 6485dfecf96Smrg else 6495dfecf96Smrg goto fix_again; 6505dfecf96Smrg break; 6515dfecf96Smrg case LispArray_t: 6525dfecf96Smrg if (READLABELP(object->data.array.list)) 6535dfecf96Smrg object->data.array.list = 6545dfecf96Smrg LispReadLabelCircle(object->data.array.list, info); 6555dfecf96Smrg else if (!LispReadCheckCircle(object, info)) { 6565dfecf96Smrg object = object->data.array.list; 6575dfecf96Smrg goto fix_again; 6585dfecf96Smrg } 6595dfecf96Smrg break; 6605dfecf96Smrg case LispStruct_t: 6615dfecf96Smrg if (READLABELP(object->data.struc.fields)) 6625dfecf96Smrg object->data.struc.fields = 6635dfecf96Smrg LispReadLabelCircle(object->data.struc.fields, info); 6645dfecf96Smrg else if (!LispReadCheckCircle(object, info)) { 6655dfecf96Smrg object = object->data.struc.fields; 6665dfecf96Smrg goto fix_again; 6675dfecf96Smrg } 6685dfecf96Smrg break; 6695dfecf96Smrg case LispQuote_t: 6705dfecf96Smrg case LispBackquote_t: 6715dfecf96Smrg case LispFunctionQuote_t: 6725dfecf96Smrg if (READLABELP(object->data.quote)) 6735dfecf96Smrg object->data.quote = 6745dfecf96Smrg LispReadLabelCircle(object->data.quote, info); 6755dfecf96Smrg else { 6765dfecf96Smrg object = object->data.quote; 6775dfecf96Smrg goto fix_again; 6785dfecf96Smrg } 6795dfecf96Smrg break; 6805dfecf96Smrg case LispComma_t: 6815dfecf96Smrg if (READLABELP(object->data.comma.eval)) 6825dfecf96Smrg object->data.comma.eval = 6835dfecf96Smrg LispReadLabelCircle(object->data.comma.eval, info); 6845dfecf96Smrg else { 6855dfecf96Smrg object = object->data.comma.eval; 6865dfecf96Smrg goto fix_again; 6875dfecf96Smrg } 6885dfecf96Smrg break; 6895dfecf96Smrg case LispLambda_t: 6905dfecf96Smrg if (READLABELP(object->data.lambda.code)) 6915dfecf96Smrg object->data.lambda.code = 6925dfecf96Smrg LispReadLabelCircle(object->data.lambda.code, info); 6935dfecf96Smrg else if (!LispReadCheckCircle(object, info)) { 6945dfecf96Smrg object = object->data.lambda.code; 6955dfecf96Smrg goto fix_again; 6965dfecf96Smrg } 6975dfecf96Smrg break; 6985dfecf96Smrg default: 6995dfecf96Smrg break; 7005dfecf96Smrg } 7015dfecf96Smrg} 7025dfecf96Smrg 7035dfecf96Smrgstatic LispObj * 7045dfecf96SmrgLispReadLabelCircle(LispObj *label, read_info *info) 7055dfecf96Smrg{ 7065dfecf96Smrg long i, value = READLABEL_VALUE(label); 7075dfecf96Smrg 7085dfecf96Smrg for (i = 0; i < info->num_objects; i++) 7095dfecf96Smrg if (info->objects[i].label == value) 7105dfecf96Smrg return (info->objects[i].object); 7115dfecf96Smrg 7125dfecf96Smrg LispDestroy("READ: internal error"); 7135dfecf96Smrg /*NOTREACHED*/ 7145dfecf96Smrg return (label); 7155dfecf96Smrg} 7165dfecf96Smrg 7175dfecf96Smrgstatic int 7185dfecf96SmrgLispReadCheckCircle(LispObj *object, read_info *info) 7195dfecf96Smrg{ 7205dfecf96Smrg long i; 7215dfecf96Smrg 7225dfecf96Smrg for (i = 0; i < info->num_circles; i++) 7235dfecf96Smrg if (info->circles[i] == object) 7245dfecf96Smrg return (1); 7255dfecf96Smrg 7265dfecf96Smrg if ((info->num_circles % 16) == 0) 7275dfecf96Smrg info->circles = LispRealloc(info->circles, sizeof(LispObj*) * 7285dfecf96Smrg (info->num_circles + 16)); 7295dfecf96Smrg info->circles[info->num_circles++] = object; 7305dfecf96Smrg 7315dfecf96Smrg return (0); 7325dfecf96Smrg} 7335dfecf96Smrg 7345dfecf96Smrgstatic LispObj * 7355dfecf96SmrgLispDoRead(read_info *info) 7365dfecf96Smrg{ 7375dfecf96Smrg LispObj *object; 7385dfecf96Smrg int ch = LispSkipWhiteSpace(); 7395dfecf96Smrg 7405dfecf96Smrg switch (ch) { 7415dfecf96Smrg case '(': 7425dfecf96Smrg object = LispReadList(info); 7435dfecf96Smrg break; 7445dfecf96Smrg case ')': 7455dfecf96Smrg for (ch = LispGet(); ch != EOF && ch != '\n'; ch = LispGet()) { 7465dfecf96Smrg if (!isspace(ch)) { 7475dfecf96Smrg LispUnget(ch); 7485dfecf96Smrg break; 7495dfecf96Smrg } 7505dfecf96Smrg } 7515dfecf96Smrg return (EOLIST); 7525dfecf96Smrg case EOF: 7535dfecf96Smrg return (NULL); 7545dfecf96Smrg case '\'': 7555dfecf96Smrg object = LispReadQuote(info); 7565dfecf96Smrg break; 7575dfecf96Smrg case '`': 7585dfecf96Smrg object = LispReadBackquote(info); 7595dfecf96Smrg break; 7605dfecf96Smrg case ',': 7615dfecf96Smrg object = LispReadCommaquote(info); 7625dfecf96Smrg break; 7635dfecf96Smrg case '#': 7645dfecf96Smrg object = LispReadMacro(info); 7655dfecf96Smrg break; 7665dfecf96Smrg default: 7675dfecf96Smrg LispUnget(ch); 7685dfecf96Smrg object = LispReadObject(0, info); 7695dfecf96Smrg break; 7705dfecf96Smrg } 7715dfecf96Smrg 7725dfecf96Smrg return (object); 7735dfecf96Smrg} 7745dfecf96Smrg 7755dfecf96Smrgstatic LispObj * 7765dfecf96SmrgLispReadMacro(read_info *info) 7775dfecf96Smrg{ 7785dfecf96Smrg READ_ENTER(); 7795dfecf96Smrg LispObj *result = NULL; 7805dfecf96Smrg int ch = LispGet(); 7815dfecf96Smrg 7825dfecf96Smrg switch (ch) { 7835dfecf96Smrg case '(': 7845dfecf96Smrg result = LispReadVector(info); 7855dfecf96Smrg break; 7865dfecf96Smrg case '\'': 7875dfecf96Smrg result = LispReadFunction(info); 7885dfecf96Smrg break; 7895dfecf96Smrg case 'b': 7905dfecf96Smrg case 'B': 7915dfecf96Smrg result = LispReadRational(2, info); 7925dfecf96Smrg break; 7935dfecf96Smrg case 'o': 7945dfecf96Smrg case 'O': 7955dfecf96Smrg result = LispReadRational(8, info); 7965dfecf96Smrg break; 7975dfecf96Smrg case 'x': 7985dfecf96Smrg case 'X': 7995dfecf96Smrg result = LispReadRational(16, info); 8005dfecf96Smrg break; 8015dfecf96Smrg case '\\': 8025dfecf96Smrg result = LispReadCharacter(info); 8035dfecf96Smrg break; 8045dfecf96Smrg case '|': 8055dfecf96Smrg LispSkipComment(); 8065dfecf96Smrg result = LispDoRead(info); 8075dfecf96Smrg break; 8085dfecf96Smrg case '.': /* eval when compiling */ 8095dfecf96Smrg case ',': /* eval when loading */ 8105dfecf96Smrg result = LispReadEval(info); 8115dfecf96Smrg break; 8125dfecf96Smrg case 'c': 8135dfecf96Smrg case 'C': 8145dfecf96Smrg result = LispReadComplex(info); 8155dfecf96Smrg break; 8165dfecf96Smrg case 'p': 8175dfecf96Smrg case 'P': 8185dfecf96Smrg result = LispReadPathname(info); 8195dfecf96Smrg break; 8205dfecf96Smrg case 's': 8215dfecf96Smrg case 'S': 8225dfecf96Smrg result = LispReadStruct(info); 8235dfecf96Smrg break; 8245dfecf96Smrg case '+': 8255dfecf96Smrg result = LispReadFeature(1, info); 8265dfecf96Smrg break; 8275dfecf96Smrg case '-': 8285dfecf96Smrg result = LispReadFeature(0, info); 8295dfecf96Smrg break; 8305dfecf96Smrg case ':': 8315dfecf96Smrg /* Uninterned symbol */ 8325dfecf96Smrg result = LispReadObject(1, info); 8335dfecf96Smrg break; 8345dfecf96Smrg default: 8355dfecf96Smrg if (isdigit(ch)) { 8365dfecf96Smrg LispUnget(ch); 8375dfecf96Smrg result = LispReadMacroArg(info); 8385dfecf96Smrg } 8395dfecf96Smrg else if (!info->discard) 8405dfecf96Smrg READ_ERROR1("undefined dispatch macro character #%c", ch); 8415dfecf96Smrg break; 8425dfecf96Smrg } 8435dfecf96Smrg 8445dfecf96Smrg return (result); 8455dfecf96Smrg} 8465dfecf96Smrg 8475dfecf96Smrgstatic LispObj * 8485dfecf96SmrgLispReadMacroArg(read_info *info) 8495dfecf96Smrg{ 8505dfecf96Smrg READ_ENTER(); 8515dfecf96Smrg LispObj *result = NIL; 8525dfecf96Smrg long i, integer; 8535dfecf96Smrg int ch; 8545dfecf96Smrg 8555dfecf96Smrg /* skip leading zeros */ 8565dfecf96Smrg while (ch = LispGet(), ch != EOF && isdigit(ch) && ch == '0') 8575dfecf96Smrg ; 8585dfecf96Smrg 8595dfecf96Smrg if (ch == EOF) 8605dfecf96Smrg READ_ERROR_EOF(); 8615dfecf96Smrg 8625dfecf96Smrg /* if ch is not a number the argument was zero */ 8635dfecf96Smrg if (isdigit(ch)) { 8645dfecf96Smrg char stk[32], *str; 8655dfecf96Smrg int len = 1; 8665dfecf96Smrg 8675dfecf96Smrg stk[0] = ch; 8685dfecf96Smrg for (;;) { 8695dfecf96Smrg ch = LispGet(); 8705dfecf96Smrg if (!isdigit(ch)) 8715dfecf96Smrg break; 8725dfecf96Smrg if (len + 1 >= sizeof(stk)) 8735dfecf96Smrg READ_ERROR_FIXNUM(); 8745dfecf96Smrg stk[len++] = ch; 8755dfecf96Smrg } 8765dfecf96Smrg stk[len] = '\0'; 8775dfecf96Smrg errno = 0; 8785dfecf96Smrg integer = strtol(stk, &str, 10); 8795dfecf96Smrg /* number is positive because sign is not processed here */ 8805dfecf96Smrg if (*str || errno == ERANGE || integer > MOST_POSITIVE_FIXNUM) 8815dfecf96Smrg READ_ERROR_FIXNUM(); 8825dfecf96Smrg } 8835dfecf96Smrg else 8845dfecf96Smrg integer = 0; 8855dfecf96Smrg 8865dfecf96Smrg switch (ch) { 8875dfecf96Smrg case 'a': 8885dfecf96Smrg case 'A': 8895dfecf96Smrg if (integer == 1) { 8905dfecf96Smrg /* LispReadArray and LispReadList expect 8915dfecf96Smrg * the '(' being already read */ 8925dfecf96Smrg if ((ch = LispSkipWhiteSpace()) != '(') { 8935dfecf96Smrg if (info->discard) 8945dfecf96Smrg return (ch == EOF ? NULL : NIL); 8955dfecf96Smrg READ_ERROR0("bad array specification"); 8965dfecf96Smrg } 8975dfecf96Smrg result = LispReadVector(info); 8985dfecf96Smrg } 8995dfecf96Smrg else 9005dfecf96Smrg result = LispReadArray(integer, info); 9015dfecf96Smrg break; 9025dfecf96Smrg case 'r': 9035dfecf96Smrg case 'R': 9045dfecf96Smrg result = LispReadRational(integer, info); 9055dfecf96Smrg break; 9065dfecf96Smrg case '=': 9075dfecf96Smrg if (integer > MAX_LABEL_VALUE) 9085dfecf96Smrg READ_ERROR_FIXNUM(); 9095dfecf96Smrg if (!info->discard) { 9105dfecf96Smrg long num_objects = info->num_objects; 9115dfecf96Smrg 9125dfecf96Smrg /* check for duplicated label */ 9135dfecf96Smrg for (i = 0; i < info->num_objects; i++) { 9145dfecf96Smrg if (info->objects[i].label == integer) 9155dfecf96Smrg READ_ERROR1("label #%ld# defined more than once", 9165dfecf96Smrg integer); 9175dfecf96Smrg } 9185dfecf96Smrg info->objects = LispRealloc(info->objects, 9195dfecf96Smrg sizeof(object_info) * 9205dfecf96Smrg (num_objects + 1)); 9215dfecf96Smrg /* if this label is referenced it is a shared/circular object */ 9225dfecf96Smrg info->objects[num_objects].label = integer; 9235dfecf96Smrg info->objects[num_objects].object = NULL; 9245dfecf96Smrg info->objects[num_objects].num_circles = 0; 9255dfecf96Smrg ++info->num_objects; 9265dfecf96Smrg result = LispDoRead(info); 9275dfecf96Smrg if (READLABELP(result) && READLABEL_VALUE(result) == integer) 9285dfecf96Smrg READ_ERROR2("incorrect syntax #%ld= #%ld#", 9295dfecf96Smrg integer, integer); 9305dfecf96Smrg /* any reference to it now is not shared/circular */ 9315dfecf96Smrg info->objects[num_objects].object = result; 9325dfecf96Smrg } 9335dfecf96Smrg else 9345dfecf96Smrg result = LispDoRead(info); 9355dfecf96Smrg break; 9365dfecf96Smrg case '#': 9375dfecf96Smrg if (integer > MAX_LABEL_VALUE) 9385dfecf96Smrg READ_ERROR_FIXNUM(); 9395dfecf96Smrg if (!info->discard) { 9405dfecf96Smrg /* search object */ 9415dfecf96Smrg for (i = 0; i < info->num_objects; i++) { 9425dfecf96Smrg if (info->objects[i].label == integer) { 9435dfecf96Smrg result = info->objects[i].object; 9445dfecf96Smrg if (result == NULL) { 9455dfecf96Smrg ++info->objects[i].num_circles; 9465dfecf96Smrg ++info->circle_count; 9475dfecf96Smrg result = READLABEL(integer); 9485dfecf96Smrg } 9495dfecf96Smrg break; 9505dfecf96Smrg } 9515dfecf96Smrg } 9525dfecf96Smrg if (i == info->num_objects) 9535dfecf96Smrg READ_ERROR1("undefined label #%ld#", integer); 9545dfecf96Smrg } 9555dfecf96Smrg break; 9565dfecf96Smrg default: 9575dfecf96Smrg if (!info->discard) 9585dfecf96Smrg READ_ERROR1("undefined dispatch macro character #%c", ch); 9595dfecf96Smrg break; 9605dfecf96Smrg } 9615dfecf96Smrg 9625dfecf96Smrg return (result); 9635dfecf96Smrg} 9645dfecf96Smrg 9655dfecf96Smrgstatic int 9665dfecf96SmrgLispSkipWhiteSpace(void) 9675dfecf96Smrg{ 9685dfecf96Smrg int ch; 9695dfecf96Smrg 9705dfecf96Smrg for (;;) { 9715dfecf96Smrg while (ch = LispGet(), isspace(ch) && ch != EOF) 9725dfecf96Smrg ; 9735dfecf96Smrg if (ch == ';') { 9745dfecf96Smrg while (ch = LispGet(), ch != '\n' && ch != EOF) 9755dfecf96Smrg ; 9765dfecf96Smrg if (ch == EOF) 9775dfecf96Smrg return (EOF); 9785dfecf96Smrg } 9795dfecf96Smrg else 9805dfecf96Smrg break; 9815dfecf96Smrg } 9825dfecf96Smrg 9835dfecf96Smrg return (ch); 9845dfecf96Smrg} 9855dfecf96Smrg 9865dfecf96Smrg/* any data in the format '(' FORM ')' is read here */ 9875dfecf96Smrgstatic LispObj * 9885dfecf96SmrgLispReadList(read_info *info) 9895dfecf96Smrg{ 9905dfecf96Smrg READ_ENTER(); 9915dfecf96Smrg GC_ENTER(); 9925dfecf96Smrg LispObj *result, *cons, *object; 9935dfecf96Smrg int dot = 0; 9945dfecf96Smrg 9955dfecf96Smrg ++info->level; 9965dfecf96Smrg /* check for () */ 9975dfecf96Smrg object = LispDoRead(info); 9985dfecf96Smrg if (object == EOLIST) { 9995dfecf96Smrg --info->level; 10005dfecf96Smrg 10015dfecf96Smrg return (NIL); 10025dfecf96Smrg } 10035dfecf96Smrg 10045dfecf96Smrg if (object == DOT) 10055dfecf96Smrg READ_ERROR0("illegal start of dotted list"); 10065dfecf96Smrg 10075dfecf96Smrg result = cons = CONS(object, NIL); 10085dfecf96Smrg 10095dfecf96Smrg /* make sure GC will not release data being read */ 10105dfecf96Smrg GC_PROTECT(result); 10115dfecf96Smrg 10125dfecf96Smrg while ((object = LispDoRead(info)) != EOLIST) { 10135dfecf96Smrg if (object == NULL) 10145dfecf96Smrg READ_ERROR_EOF(); 10155dfecf96Smrg if (object == DOT) { 10165dfecf96Smrg if (info->nodot == info->level) 10175dfecf96Smrg READ_ERROR0("dotted list not allowed"); 10185dfecf96Smrg /* this is a dotted list */ 10195dfecf96Smrg if (dot) 10205dfecf96Smrg READ_ERROR0("more than one . in list"); 10215dfecf96Smrg dot = 1; 10225dfecf96Smrg } 10235dfecf96Smrg else { 10245dfecf96Smrg if (dot) { 10255dfecf96Smrg /* only one object after a dot */ 10265dfecf96Smrg if (++dot > 2) 10275dfecf96Smrg READ_ERROR0("more than one object after . in list"); 10285dfecf96Smrg RPLACD(cons, object); 10295dfecf96Smrg } 10305dfecf96Smrg else { 10315dfecf96Smrg RPLACD(cons, CONS(object, NIL)); 10325dfecf96Smrg cons = CDR(cons); 10335dfecf96Smrg } 10345dfecf96Smrg } 10355dfecf96Smrg } 10365dfecf96Smrg 10375dfecf96Smrg /* this will happen if last list element was a dot */ 10385dfecf96Smrg if (dot == 1) 10395dfecf96Smrg READ_ERROR0("illegal end of dotted list"); 10405dfecf96Smrg 10415dfecf96Smrg --info->level; 10425dfecf96Smrg GC_LEAVE(); 10435dfecf96Smrg 10445dfecf96Smrg return (result); 10455dfecf96Smrg} 10465dfecf96Smrg 10475dfecf96Smrgstatic LispObj * 10485dfecf96SmrgLispReadQuote(read_info *info) 10495dfecf96Smrg{ 10505dfecf96Smrg READ_ENTER(); 10515dfecf96Smrg LispObj *quote = LispDoRead(info), *result; 10525dfecf96Smrg 10535dfecf96Smrg if (INVALIDP(quote)) 10545dfecf96Smrg READ_ERROR_INVARG(); 10555dfecf96Smrg 10565dfecf96Smrg result = QUOTE(quote); 10575dfecf96Smrg 10585dfecf96Smrg return (result); 10595dfecf96Smrg} 10605dfecf96Smrg 10615dfecf96Smrgstatic LispObj * 10625dfecf96SmrgLispReadBackquote(read_info *info) 10635dfecf96Smrg{ 10645dfecf96Smrg READ_ENTER(); 10655dfecf96Smrg LispObj *backquote = LispDoRead(info), *result; 10665dfecf96Smrg 10675dfecf96Smrg if (INVALIDP(backquote)) 10685dfecf96Smrg READ_ERROR_INVARG(); 10695dfecf96Smrg 10705dfecf96Smrg result = BACKQUOTE(backquote); 10715dfecf96Smrg 10725dfecf96Smrg return (result); 10735dfecf96Smrg} 10745dfecf96Smrg 10755dfecf96Smrgstatic LispObj * 10765dfecf96SmrgLispReadCommaquote(read_info *info) 10775dfecf96Smrg{ 10785dfecf96Smrg READ_ENTER(); 10795dfecf96Smrg LispObj *comma, *result; 10805dfecf96Smrg int atlist = LispGet(); 10815dfecf96Smrg 10825dfecf96Smrg if (atlist == EOF) 10835dfecf96Smrg READ_ERROR_EOF(); 10845dfecf96Smrg else if (atlist != '@' && atlist != '.') 10855dfecf96Smrg LispUnget(atlist); 10865dfecf96Smrg 10875dfecf96Smrg comma = LispDoRead(info); 10885dfecf96Smrg if (comma == DOT) { 10895dfecf96Smrg atlist = '@'; 10905dfecf96Smrg comma = LispDoRead(info); 10915dfecf96Smrg } 10925dfecf96Smrg if (INVALIDP(comma)) 10935dfecf96Smrg READ_ERROR_INVARG(); 10945dfecf96Smrg 10955dfecf96Smrg result = COMMA(comma, atlist == '@' || atlist == '.'); 10965dfecf96Smrg 10975dfecf96Smrg return (result); 10985dfecf96Smrg} 10995dfecf96Smrg 11005dfecf96Smrg/* 11015dfecf96Smrg * Read anything that is not readily identifiable by it's first character 11025dfecf96Smrg * and also put the code for reading atoms, numbers and strings together. 11035dfecf96Smrg */ 11045dfecf96Smrgstatic LispObj * 11055dfecf96SmrgLispReadObject(int unintern, read_info *info) 11065dfecf96Smrg{ 11075dfecf96Smrg READ_ENTER(); 11085dfecf96Smrg LispObj *object; 11095dfecf96Smrg char stk[128], *string, *package, *symbol; 11105dfecf96Smrg int ch, length, backslash, size, quote, unreadable, collon; 11115dfecf96Smrg 11125dfecf96Smrg package = symbol = string = stk; 11135dfecf96Smrg size = sizeof(stk); 11145dfecf96Smrg backslash = quote = unreadable = collon = 0; 11155dfecf96Smrg length = 0; 11165dfecf96Smrg 11175dfecf96Smrg ch = LispGet(); 11185dfecf96Smrg if (unintern && (ch == ':' || ch == '"')) 11195dfecf96Smrg READ_ERROR0("syntax error after #:"); 11205dfecf96Smrg else if (ch == '"' || ch == '|') 11215dfecf96Smrg quote = ch; 11225dfecf96Smrg else if (ch == '\\') { 11235dfecf96Smrg unreadable = backslash = 1; 11245dfecf96Smrg string[length++] = ch; 11255dfecf96Smrg } 11265dfecf96Smrg else if (ch == ':') { 11275dfecf96Smrg collon = 1; 11285dfecf96Smrg string[length++] = ch; 11295dfecf96Smrg symbol = string + 1; 1130f14f4646Smrg ch = LispGet(); 1131f14f4646Smrg if (ch == '|') { 1132f14f4646Smrg quote = ch; 1133f14f4646Smrg unreadable = 1; 1134f14f4646Smrg } 1135f14f4646Smrg else if (ch != EOF) 1136f14f4646Smrg LispUnget(ch); 11375dfecf96Smrg } 11385dfecf96Smrg else if (ch) { 11395dfecf96Smrg if (islower(ch)) 11405dfecf96Smrg ch = toupper(ch); 11415dfecf96Smrg string[length++] = ch; 11425dfecf96Smrg } 11435dfecf96Smrg else 11445dfecf96Smrg unreadable = 1; 11455dfecf96Smrg 11465dfecf96Smrg /* read remaining data */ 11475dfecf96Smrg for (; ch;) { 11485dfecf96Smrg ch = LispGet(); 11495dfecf96Smrg 11505dfecf96Smrg if (ch == EOF) { 11515dfecf96Smrg if (quote) { 11525dfecf96Smrg /* if quote, file ended with an open quoted object */ 11535dfecf96Smrg if (string != stk) 11545dfecf96Smrg LispFree(string); 11555dfecf96Smrg return (NULL); 11565dfecf96Smrg } 11575dfecf96Smrg break; 11585dfecf96Smrg } 11595dfecf96Smrg else if (ch == '\0') 11605dfecf96Smrg break; 11615dfecf96Smrg 11625dfecf96Smrg if (ch == '\\') { 11635dfecf96Smrg backslash = !backslash; 11645dfecf96Smrg if (quote == '"') { 11655dfecf96Smrg /* only remove backslashs from strings */ 11665dfecf96Smrg if (backslash) 11675dfecf96Smrg continue; 11685dfecf96Smrg } 11695dfecf96Smrg else 11705dfecf96Smrg unreadable = 1; 11715dfecf96Smrg } 11725dfecf96Smrg else if (backslash) 11735dfecf96Smrg backslash = 0; 11745dfecf96Smrg else if (ch == quote) 11755dfecf96Smrg break; 11765dfecf96Smrg else if (!quote && !backslash) { 11775dfecf96Smrg if (islower(ch)) 11785dfecf96Smrg ch = toupper(ch); 11795dfecf96Smrg else if (isspace(ch)) 11805dfecf96Smrg break; 11815dfecf96Smrg else if (AtomSeparator(ch, 0, 0)) { 11825dfecf96Smrg LispUnget(ch); 11835dfecf96Smrg break; 11845dfecf96Smrg } 11855dfecf96Smrg else if (ch == ':') { 11865dfecf96Smrg if (collon == 0 || 11875dfecf96Smrg (collon == (1 - unintern) && symbol == string + length)) { 11885dfecf96Smrg ++collon; 11895dfecf96Smrg symbol = string + length + 1; 11905dfecf96Smrg } 11915dfecf96Smrg else 11925dfecf96Smrg READ_ERROR0("too many collons"); 11935dfecf96Smrg } 11945dfecf96Smrg } 11955dfecf96Smrg 11965dfecf96Smrg if (length + 2 >= size) { 11975dfecf96Smrg if (string == stk) { 11985dfecf96Smrg size = 1024; 11995dfecf96Smrg string = LispMalloc(size); 12005dfecf96Smrg strcpy(string, stk); 12015dfecf96Smrg } 12025dfecf96Smrg else { 12035dfecf96Smrg size += 1024; 12045dfecf96Smrg string = LispRealloc(string, size); 12055dfecf96Smrg } 12065dfecf96Smrg symbol = string + (symbol - package); 12075dfecf96Smrg package = string; 12085dfecf96Smrg } 12095dfecf96Smrg string[length++] = ch; 12105dfecf96Smrg } 12115dfecf96Smrg 12125dfecf96Smrg if (info->discard) { 12135dfecf96Smrg if (string != stk) 12145dfecf96Smrg LispFree(string); 12155dfecf96Smrg 12165dfecf96Smrg return (ch == EOF ? NULL : NIL); 12175dfecf96Smrg } 12185dfecf96Smrg 12195dfecf96Smrg string[length] = '\0'; 12205dfecf96Smrg 12215dfecf96Smrg if (unintern) { 12225dfecf96Smrg if (length == 0) 12235dfecf96Smrg READ_ERROR0("syntax error after #:"); 12245dfecf96Smrg object = UNINTERNED_ATOM(string); 12255dfecf96Smrg } 12265dfecf96Smrg 12275dfecf96Smrg else if (quote == '"') 12285dfecf96Smrg object = LSTRING(string, length); 12295dfecf96Smrg 12305dfecf96Smrg else if (collon) { 12315dfecf96Smrg /* Package specified in object name */ 12325dfecf96Smrg symbol[-1] = '\0'; 12335dfecf96Smrg if (collon > 1) 12345dfecf96Smrg symbol[-2] = '\0'; 12355dfecf96Smrg object = LispParseAtom(package, symbol, 12365dfecf96Smrg collon == 2, unreadable, 12375dfecf96Smrg read__stream, read__line); 12385dfecf96Smrg } 12395dfecf96Smrg 1240f14f4646Smrg else if (quote == '|' || (unreadable && !collon)) { 1241f14f4646Smrg /* Set unreadable field, this atom needs quoting to be read back */ 1242f14f4646Smrg object = ATOM(string); 1243f14f4646Smrg object->data.atom->unreadable = 1; 1244f14f4646Smrg } 1245f14f4646Smrg 12465dfecf96Smrg /* Check some common symbols */ 12475dfecf96Smrg else if (length == 1 && string[0] == 'T') 12485dfecf96Smrg /* The T */ 12495dfecf96Smrg object = T; 12505dfecf96Smrg 12515dfecf96Smrg else if (length == 1 && string[0] == '.') 12525dfecf96Smrg /* The dot */ 12535dfecf96Smrg object = DOT; 12545dfecf96Smrg 12555dfecf96Smrg else if (length == 3 && 12565dfecf96Smrg string[0] == 'N' && string[1] == 'I' && string[2] == 'L') 12575dfecf96Smrg /* The NIL */ 12585dfecf96Smrg object = NIL; 12595dfecf96Smrg 12605dfecf96Smrg else if (isdigit(string[0]) || string[0] == '.' || 12615dfecf96Smrg ((string[0] == '-' || string[0] == '+') && string[1])) 12625dfecf96Smrg /* Looks like a number */ 12635dfecf96Smrg object = LispParseNumber(string, 10, read__stream, read__line); 12645dfecf96Smrg 12655dfecf96Smrg else 12665dfecf96Smrg /* A normal atom */ 12675dfecf96Smrg object = ATOM(string); 12685dfecf96Smrg 12695dfecf96Smrg if (string != stk) 12705dfecf96Smrg LispFree(string); 12715dfecf96Smrg 12725dfecf96Smrg return (object); 12735dfecf96Smrg} 12745dfecf96Smrg 12755dfecf96Smrgstatic LispObj * 12765dfecf96SmrgLispParseAtom(char *package, char *symbol, int intern, int unreadable, 12775dfecf96Smrg LispObj *read__stream, int read__line) 12785dfecf96Smrg{ 12795dfecf96Smrg LispObj *object = NULL, *thepackage = NULL; 12805dfecf96Smrg LispPackage *pack = NULL; 12815dfecf96Smrg 12825dfecf96Smrg if (!unreadable) { 12835dfecf96Smrg /* Until NIL and T be treated as normal symbols */ 12845dfecf96Smrg if (symbol[0] == 'N' && symbol[1] == 'I' && 12855dfecf96Smrg symbol[2] == 'L' && symbol[3] == '\0') 12865dfecf96Smrg return (NIL); 12875dfecf96Smrg if (symbol[0] == 'T' && symbol[1] == '\0') 12885dfecf96Smrg return (T); 12895dfecf96Smrg unreadable = !LispCheckAtomString(symbol); 12905dfecf96Smrg } 12915dfecf96Smrg 12925dfecf96Smrg /* If package is empty, it is a keyword */ 12935dfecf96Smrg if (package[0] == '\0') { 12945dfecf96Smrg thepackage = lisp__data.keyword; 12955dfecf96Smrg pack = lisp__data.key; 12965dfecf96Smrg } 12975dfecf96Smrg 12985dfecf96Smrg else { 12995dfecf96Smrg /* Else, search it in the package list */ 13005dfecf96Smrg thepackage = LispFindPackageFromString(package); 13015dfecf96Smrg 13025dfecf96Smrg if (thepackage == NIL) 13035dfecf96Smrg READ_ERROR1("the package %s is not available", package); 13045dfecf96Smrg 13055dfecf96Smrg pack = thepackage->data.package.package; 13065dfecf96Smrg } 13075dfecf96Smrg 13085dfecf96Smrg if (pack == lisp__data.pack && intern) { 13095dfecf96Smrg /* Redundant package specification, since requesting a 13105dfecf96Smrg * intern symbol, create it if does not exist */ 13115dfecf96Smrg 13125dfecf96Smrg object = ATOM(symbol); 13135dfecf96Smrg if (unreadable) 13145dfecf96Smrg object->data.atom->unreadable = 1; 13155dfecf96Smrg } 13165dfecf96Smrg 13175dfecf96Smrg else if (intern || pack == lisp__data.key) { 13185dfecf96Smrg /* Symbol is created, or just fetched from the specified package */ 13195dfecf96Smrg 13205dfecf96Smrg LispPackage *savepack; 13215dfecf96Smrg LispObj *savepackage = PACKAGE; 13225dfecf96Smrg 13235dfecf96Smrg /* Remember curent package */ 13245dfecf96Smrg savepack = lisp__data.pack; 13255dfecf96Smrg 13265dfecf96Smrg /* Temporarily set another package */ 13275dfecf96Smrg lisp__data.pack = pack; 13285dfecf96Smrg PACKAGE = thepackage; 13295dfecf96Smrg 13305dfecf96Smrg /* Get the object pointer */ 13315dfecf96Smrg if (pack == lisp__data.key) 1332f14f4646Smrg object = KEYWORD(LispDoGetAtom(symbol, 0)->key->value); 13335dfecf96Smrg else 13345dfecf96Smrg object = ATOM(symbol); 13355dfecf96Smrg if (unreadable) 13365dfecf96Smrg object->data.atom->unreadable = 1; 13375dfecf96Smrg 13385dfecf96Smrg /* Restore current package */ 13395dfecf96Smrg lisp__data.pack = savepack; 13405dfecf96Smrg PACKAGE = savepackage; 13415dfecf96Smrg } 13425dfecf96Smrg 13435dfecf96Smrg else { 13445dfecf96Smrg /* Symbol must exist (and be extern) in the specified package */ 13455dfecf96Smrg 13465dfecf96Smrg LispAtom *atom; 13475dfecf96Smrg 1348f14f4646Smrg atom = (LispAtom *)hash_check(pack->atoms, symbol, strlen(symbol)); 1349f14f4646Smrg if (atom) 1350f14f4646Smrg object = atom->object; 13515dfecf96Smrg 13525dfecf96Smrg /* No object found */ 13535dfecf96Smrg if (object == NULL || object->data.atom->ext == 0) 13545dfecf96Smrg READ_ERROR2("no extern symbol %s in package %s", symbol, package); 13555dfecf96Smrg } 13565dfecf96Smrg 13575dfecf96Smrg return (object); 13585dfecf96Smrg} 13595dfecf96Smrg 13605dfecf96Smrgstatic LispObj * 13615dfecf96SmrgLispParseNumber(char *str, int radix, LispObj *read__stream, int read__line) 13625dfecf96Smrg{ 13635dfecf96Smrg int len; 13645dfecf96Smrg long integer; 13655dfecf96Smrg double dfloat; 13665dfecf96Smrg char *ratio, *ptr; 13675dfecf96Smrg LispObj *number; 13685dfecf96Smrg mpi *bignum; 13695dfecf96Smrg mpr *bigratio; 13705dfecf96Smrg 13715dfecf96Smrg if (radix < 2 || radix > 36) 13725dfecf96Smrg READ_ERROR1("radix %d is not in the range 2 to 36", radix); 13735dfecf96Smrg 13745dfecf96Smrg if (*str == '\0') 13755dfecf96Smrg return (NULL); 13765dfecf96Smrg 13775dfecf96Smrg ratio = strchr(str, '/'); 13785dfecf96Smrg if (ratio) { 13795dfecf96Smrg /* check if looks like a correctly specified ratio */ 13805dfecf96Smrg if (ratio[1] == '\0' || strchr(ratio + 1, '/') != NULL) 13815dfecf96Smrg return (ATOM(str)); 13825dfecf96Smrg 13835dfecf96Smrg /* ratio must point to an integer in radix base */ 13845dfecf96Smrg *ratio++ = '\0'; 13855dfecf96Smrg } 13865dfecf96Smrg else if (radix == 10) { 13875dfecf96Smrg int dot = 0; 13885dfecf96Smrg int type = 0; 13895dfecf96Smrg 13905dfecf96Smrg /* check if it is a floating point number */ 13915dfecf96Smrg ptr = str; 13925dfecf96Smrg if (*ptr == '-' || *ptr == '+') 13935dfecf96Smrg ++ptr; 13945dfecf96Smrg else if (*ptr == '.') { 13955dfecf96Smrg dot = 1; 13965dfecf96Smrg ++ptr; 13975dfecf96Smrg } 13985dfecf96Smrg while (*ptr) { 13995dfecf96Smrg if (*ptr == '.') { 14005dfecf96Smrg if (dot) 14015dfecf96Smrg return (ATOM(str)); 14025dfecf96Smrg /* ignore it if last char is a dot */ 14035dfecf96Smrg if (ptr[1] == '\0') { 14045dfecf96Smrg *ptr = '\0'; 14055dfecf96Smrg break; 14065dfecf96Smrg } 14075dfecf96Smrg dot = 1; 14085dfecf96Smrg } 14095dfecf96Smrg else if (!isdigit(*ptr)) 14105dfecf96Smrg break; 14115dfecf96Smrg ++ptr; 14125dfecf96Smrg } 14135dfecf96Smrg 14145dfecf96Smrg switch (*ptr) { 14155dfecf96Smrg case '\0': 14165dfecf96Smrg if (dot) /* if dot, it is default float */ 14175dfecf96Smrg type = 'E'; 14185dfecf96Smrg break; 14195dfecf96Smrg case 'E': case 'S': case 'F': case 'D': case 'L': 14205dfecf96Smrg type = *ptr; 14215dfecf96Smrg *ptr = 'E'; 14225dfecf96Smrg break; 14235dfecf96Smrg default: 14245dfecf96Smrg return (ATOM(str)); /* syntax error */ 14255dfecf96Smrg } 14265dfecf96Smrg 14275dfecf96Smrg /* if type set, it is not an integer specification */ 14285dfecf96Smrg if (type) { 14295dfecf96Smrg if (*ptr) { 14305dfecf96Smrg int itype = *ptr; 14315dfecf96Smrg char *ptype = ptr; 14325dfecf96Smrg 14335dfecf96Smrg ++ptr; 14345dfecf96Smrg if (*ptr == '+' || *ptr == '-') 14355dfecf96Smrg ++ptr; 14365dfecf96Smrg while (*ptr && isdigit(*ptr)) 14375dfecf96Smrg ++ptr; 14385dfecf96Smrg if (*ptr) { 14395dfecf96Smrg *ptype = itype; 14405dfecf96Smrg 14415dfecf96Smrg return (ATOM(str)); 14425dfecf96Smrg } 14435dfecf96Smrg } 14445dfecf96Smrg 14455dfecf96Smrg dfloat = strtod(str, NULL); 14465dfecf96Smrg if (!finite(dfloat)) 14475dfecf96Smrg READ_ERROR0("floating point overflow"); 14485dfecf96Smrg 14495dfecf96Smrg return (DFLOAT(dfloat)); 14505dfecf96Smrg } 14515dfecf96Smrg } 14525dfecf96Smrg 14535dfecf96Smrg /* check if correctly specified in the given radix */ 14545dfecf96Smrg len = strlen(str) - 1; 14555dfecf96Smrg if (!ratio && radix != 10 && str[len] == '.') 14565dfecf96Smrg str[len] = '\0'; 14575dfecf96Smrg 14585dfecf96Smrg if (ratio || radix != 10) { 14595dfecf96Smrg if (!StringInRadix(str, radix, 1)) { 14605dfecf96Smrg if (ratio) 14615dfecf96Smrg ratio[-1] = '/'; 14625dfecf96Smrg return (ATOM(str)); 14635dfecf96Smrg } 14645dfecf96Smrg if (ratio && !StringInRadix(ratio, radix, 0)) { 14655dfecf96Smrg ratio[-1] = '/'; 14665dfecf96Smrg return (ATOM(str)); 14675dfecf96Smrg } 14685dfecf96Smrg } 14695dfecf96Smrg 14705dfecf96Smrg bignum = NULL; 14715dfecf96Smrg bigratio = NULL; 14725dfecf96Smrg 14735dfecf96Smrg errno = 0; 14745dfecf96Smrg integer = strtol(str, NULL, radix); 14755dfecf96Smrg 14765dfecf96Smrg /* if does not fit in a long */ 14775dfecf96Smrg if (errno == ERANGE && 14785dfecf96Smrg ((*str == '-' && integer == LONG_MIN) || 14795dfecf96Smrg (*str != '-' && integer == LONG_MAX))) { 14805dfecf96Smrg bignum = LispMalloc(sizeof(mpi)); 14815dfecf96Smrg mpi_init(bignum); 14825dfecf96Smrg mpi_setstr(bignum, str, radix); 14835dfecf96Smrg } 14845dfecf96Smrg 14855dfecf96Smrg 14865dfecf96Smrg if (ratio && integer != 0) { 14875dfecf96Smrg long denominator; 14885dfecf96Smrg 14895dfecf96Smrg errno = 0; 14905dfecf96Smrg denominator = strtol(ratio, NULL, radix); 14915dfecf96Smrg if (denominator == 0) 14925dfecf96Smrg READ_ERROR0("divide by zero"); 14935dfecf96Smrg 14945dfecf96Smrg if (bignum == NULL) { 14955dfecf96Smrg if (integer == MINSLONG || 14965dfecf96Smrg (denominator == LONG_MAX && errno == ERANGE)) { 14975dfecf96Smrg bigratio = LispMalloc(sizeof(mpr)); 14985dfecf96Smrg mpr_init(bigratio); 14995dfecf96Smrg mpi_seti(mpr_num(bigratio), integer); 15005dfecf96Smrg mpi_setstr(mpr_den(bigratio), ratio, radix); 15015dfecf96Smrg } 15025dfecf96Smrg } 15035dfecf96Smrg else { 15045dfecf96Smrg bigratio = LispMalloc(sizeof(mpr)); 15055dfecf96Smrg mpr_init(bigratio); 15065dfecf96Smrg mpi_set(mpr_num(bigratio), bignum); 15075dfecf96Smrg mpi_clear(bignum); 15085dfecf96Smrg LispFree(bignum); 15095dfecf96Smrg mpi_setstr(mpr_den(bigratio), ratio, radix); 15105dfecf96Smrg } 15115dfecf96Smrg 15125dfecf96Smrg if (bigratio) { 15135dfecf96Smrg mpr_canonicalize(bigratio); 15145dfecf96Smrg if (mpi_fiti(mpr_num(bigratio)) && 15155dfecf96Smrg mpi_fiti(mpr_den(bigratio))) { 15165dfecf96Smrg integer = mpi_geti(mpr_num(bigratio)); 15175dfecf96Smrg denominator = mpi_geti(mpr_den(bigratio)); 15185dfecf96Smrg mpr_clear(bigratio); 15195dfecf96Smrg LispFree(bigratio); 15205dfecf96Smrg if (denominator == 1) 15215dfecf96Smrg number = INTEGER(integer); 15225dfecf96Smrg else 15235dfecf96Smrg number = RATIO(integer, denominator); 15245dfecf96Smrg } 15255dfecf96Smrg else 15265dfecf96Smrg number = BIGRATIO(bigratio); 15275dfecf96Smrg } 15285dfecf96Smrg else { 15295dfecf96Smrg long num = integer, den = denominator, rest; 15305dfecf96Smrg 15315dfecf96Smrg if (num < 0) 15325dfecf96Smrg num = -num; 15335dfecf96Smrg for (;;) { 15345dfecf96Smrg if ((rest = den % num) == 0) 15355dfecf96Smrg break; 15365dfecf96Smrg den = num; 15375dfecf96Smrg num = rest; 15385dfecf96Smrg } 15395dfecf96Smrg if (den != 1) { 15405dfecf96Smrg denominator /= num; 15415dfecf96Smrg integer /= num; 15425dfecf96Smrg } 15435dfecf96Smrg if (denominator < 0) { 15445dfecf96Smrg integer = -integer; 15455dfecf96Smrg denominator = -denominator; 15465dfecf96Smrg } 15475dfecf96Smrg if (denominator == 1) 15485dfecf96Smrg number = INTEGER(integer); 15495dfecf96Smrg else 15505dfecf96Smrg number = RATIO(integer, denominator); 15515dfecf96Smrg } 15525dfecf96Smrg } 15535dfecf96Smrg else if (bignum) 15545dfecf96Smrg number = BIGNUM(bignum); 15555dfecf96Smrg else 15565dfecf96Smrg number = INTEGER(integer); 15575dfecf96Smrg 15585dfecf96Smrg return (number); 15595dfecf96Smrg} 15605dfecf96Smrg 15615dfecf96Smrgstatic int 15625dfecf96SmrgStringInRadix(char *str, int radix, int skip_sign) 15635dfecf96Smrg{ 15645dfecf96Smrg if (skip_sign && (*str == '-' || *str == '+')) 15655dfecf96Smrg ++str; 15665dfecf96Smrg while (*str) { 15675dfecf96Smrg if (*str >= '0' && *str <= '9') { 15685dfecf96Smrg if (*str - '0' >= radix) 15695dfecf96Smrg return (0); 15705dfecf96Smrg } 15715dfecf96Smrg else if (*str >= 'A' && *str <= 'Z') { 15725dfecf96Smrg if (radix <= 10 || *str - 'A' + 10 >= radix) 15735dfecf96Smrg return (0); 15745dfecf96Smrg } 15755dfecf96Smrg else 15765dfecf96Smrg return (0); 15775dfecf96Smrg str++; 15785dfecf96Smrg } 15795dfecf96Smrg 15805dfecf96Smrg return (1); 15815dfecf96Smrg} 15825dfecf96Smrg 15835dfecf96Smrgstatic int 15845dfecf96SmrgAtomSeparator(int ch, int check_space, int check_backslash) 15855dfecf96Smrg{ 15865dfecf96Smrg if (check_space && isspace(ch)) 15875dfecf96Smrg return (1); 15885dfecf96Smrg if (check_backslash && ch == '\\') 15895dfecf96Smrg return (1); 15905dfecf96Smrg return (strchr("(),\";'`#|,", ch) != NULL); 15915dfecf96Smrg} 15925dfecf96Smrg 15935dfecf96Smrgstatic LispObj * 15945dfecf96SmrgLispReadVector(read_info *info) 15955dfecf96Smrg{ 15965dfecf96Smrg LispObj *objects; 15975dfecf96Smrg int nodot = info->nodot; 15985dfecf96Smrg 15995dfecf96Smrg info->nodot = info->level + 1; 16005dfecf96Smrg objects = LispReadList(info); 16015dfecf96Smrg info->nodot = nodot; 16025dfecf96Smrg 16035dfecf96Smrg if (info->discard) 16045dfecf96Smrg return (objects); 16055dfecf96Smrg 16065dfecf96Smrg return (VECTOR(objects)); 16075dfecf96Smrg} 16085dfecf96Smrg 16095dfecf96Smrgstatic LispObj * 16105dfecf96SmrgLispReadFunction(read_info *info) 16115dfecf96Smrg{ 16125dfecf96Smrg READ_ENTER(); 16135dfecf96Smrg int nodot = info->nodot; 16145dfecf96Smrg LispObj *function; 16155dfecf96Smrg 16165dfecf96Smrg info->nodot = info->level + 1; 16175dfecf96Smrg function = LispDoRead(info); 16185dfecf96Smrg info->nodot = nodot; 16195dfecf96Smrg 16205dfecf96Smrg if (info->discard) 16215dfecf96Smrg return (function); 16225dfecf96Smrg 16235dfecf96Smrg if (INVALIDP(function)) 16245dfecf96Smrg READ_ERROR_INVARG(); 16255dfecf96Smrg else if (CONSP(function)) { 16265dfecf96Smrg if (CAR(function) != Olambda) 16275dfecf96Smrg READ_ERROR_INVARG(); 16285dfecf96Smrg 16295dfecf96Smrg return (FUNCTION_QUOTE(function)); 16305dfecf96Smrg } 16315dfecf96Smrg else if (!SYMBOLP(function)) 16325dfecf96Smrg READ_ERROR_INVARG(); 16335dfecf96Smrg 16345dfecf96Smrg return (FUNCTION_QUOTE(function)); 16355dfecf96Smrg} 16365dfecf96Smrg 16375dfecf96Smrgstatic LispObj * 16385dfecf96SmrgLispReadRational(int radix, read_info *info) 16395dfecf96Smrg{ 16405dfecf96Smrg READ_ENTER(); 16415dfecf96Smrg LispObj *number; 16425dfecf96Smrg int ch, len, size; 16435dfecf96Smrg char stk[128], *str; 16445dfecf96Smrg 16455dfecf96Smrg len = 0; 16465dfecf96Smrg str = stk; 16475dfecf96Smrg size = sizeof(stk); 16485dfecf96Smrg 16495dfecf96Smrg for (;;) { 16505dfecf96Smrg ch = LispGet(); 16515dfecf96Smrg if (ch == EOF || isspace(ch)) 16525dfecf96Smrg break; 16535dfecf96Smrg else if (AtomSeparator(ch, 0, 1)) { 16545dfecf96Smrg LispUnget(ch); 16555dfecf96Smrg break; 16565dfecf96Smrg } 16575dfecf96Smrg else if (islower(ch)) 16585dfecf96Smrg ch = toupper(ch); 16595dfecf96Smrg if ((ch < '0' || ch > '9') && (ch < 'A' || ch > 'Z') && 16605dfecf96Smrg ch != '+' && ch != '-' && ch != '/') { 16615dfecf96Smrg if (str != stk) 16625dfecf96Smrg LispFree(str); 16635dfecf96Smrg if (!info->discard) 16645dfecf96Smrg READ_ERROR1("bad character %c for rational number", ch); 16655dfecf96Smrg } 16665dfecf96Smrg if (len + 1 >= size) { 16675dfecf96Smrg if (str == stk) { 16685dfecf96Smrg size = 512; 16695dfecf96Smrg str = LispMalloc(size); 16705dfecf96Smrg strcpy(str + 1, stk + 1); 16715dfecf96Smrg } 16725dfecf96Smrg else { 16735dfecf96Smrg size += 512; 16745dfecf96Smrg str = LispRealloc(str, size); 16755dfecf96Smrg } 16765dfecf96Smrg } 16775dfecf96Smrg str[len++] = ch; 16785dfecf96Smrg } 16795dfecf96Smrg 16805dfecf96Smrg if (info->discard) { 16815dfecf96Smrg if (str != stk) 16825dfecf96Smrg LispFree(str); 16835dfecf96Smrg 16845dfecf96Smrg return (ch == EOF ? NULL : NIL); 16855dfecf96Smrg } 16865dfecf96Smrg 16875dfecf96Smrg str[len] = '\0'; 16885dfecf96Smrg 16895dfecf96Smrg number = LispParseNumber(str, radix, read__stream, read__line); 16905dfecf96Smrg if (str != stk) 16915dfecf96Smrg LispFree(str); 16925dfecf96Smrg 16935dfecf96Smrg if (!RATIONALP(number)) 16945dfecf96Smrg READ_ERROR0("bad rational number specification"); 16955dfecf96Smrg 16965dfecf96Smrg return (number); 16975dfecf96Smrg} 16985dfecf96Smrg 16995dfecf96Smrgstatic LispObj * 17005dfecf96SmrgLispReadCharacter(read_info *info) 17015dfecf96Smrg{ 17025dfecf96Smrg READ_ENTER(); 17035dfecf96Smrg long c; 17045dfecf96Smrg int ch, len; 17055dfecf96Smrg char stk[64]; 17065dfecf96Smrg 17075dfecf96Smrg ch = LispGet(); 17085dfecf96Smrg if (ch == EOF) 17095dfecf96Smrg return (NULL); 17105dfecf96Smrg 17115dfecf96Smrg stk[0] = ch; 17125dfecf96Smrg len = 1; 17135dfecf96Smrg 17145dfecf96Smrg for (;;) { 17155dfecf96Smrg ch = LispGet(); 17165dfecf96Smrg if (ch == EOF) 17175dfecf96Smrg break; 17185dfecf96Smrg else if (ch != '-' && !isalnum(ch)) { 17195dfecf96Smrg LispUnget(ch); 17205dfecf96Smrg break; 17215dfecf96Smrg } 17225dfecf96Smrg if (len + 1 < sizeof(stk)) 17235dfecf96Smrg stk[len++] = ch; 17245dfecf96Smrg } 17255dfecf96Smrg if (len > 1) { 17265dfecf96Smrg char **names; 17275dfecf96Smrg int found = 0; 17285dfecf96Smrg stk[len] = '\0'; 17295dfecf96Smrg 17305dfecf96Smrg for (c = ch = 0; ch <= ' ' && !found; ch++) { 17315dfecf96Smrg for (names = LispChars[ch].names; *names; names++) 17325dfecf96Smrg if (strcasecmp(*names, stk) == 0) { 17335dfecf96Smrg c = ch; 17345dfecf96Smrg found = 1; 17355dfecf96Smrg break; 17365dfecf96Smrg } 17375dfecf96Smrg } 17385dfecf96Smrg if (!found) { 17395dfecf96Smrg for (names = LispChars[0177].names; *names; names++) 17405dfecf96Smrg if (strcasecmp(*names, stk) == 0) { 17415dfecf96Smrg c = 0177; 17425dfecf96Smrg found = 1; 17435dfecf96Smrg break; 17445dfecf96Smrg } 17455dfecf96Smrg } 17465dfecf96Smrg 17475dfecf96Smrg if (!found) { 17485dfecf96Smrg if (info->discard) 17495dfecf96Smrg return (NIL); 17505dfecf96Smrg READ_ERROR1("unkwnown character %s", stk); 17515dfecf96Smrg } 17525dfecf96Smrg } 17535dfecf96Smrg else 17545dfecf96Smrg c = stk[0]; 17555dfecf96Smrg 17565dfecf96Smrg return (SCHAR(c)); 17575dfecf96Smrg} 17585dfecf96Smrg 17595dfecf96Smrgstatic void 17605dfecf96SmrgLispSkipComment(void) 17615dfecf96Smrg{ 17625dfecf96Smrg READ_ENTER(); 17635dfecf96Smrg int ch, comm = 1; 17645dfecf96Smrg 17655dfecf96Smrg for (;;) { 17665dfecf96Smrg ch = LispGet(); 17675dfecf96Smrg if (ch == '#') { 17685dfecf96Smrg ch = LispGet(); 17695dfecf96Smrg if (ch == '|') 17705dfecf96Smrg ++comm; 17715dfecf96Smrg continue; 17725dfecf96Smrg } 17735dfecf96Smrg while (ch == '|') { 17745dfecf96Smrg ch = LispGet(); 17755dfecf96Smrg if (ch == '#' && --comm == 0) 17765dfecf96Smrg return; 17775dfecf96Smrg } 17785dfecf96Smrg if (ch == EOF) 17795dfecf96Smrg READ_ERROR_EOF(); 17805dfecf96Smrg } 17815dfecf96Smrg} 17825dfecf96Smrg 17835dfecf96Smrgstatic LispObj * 17845dfecf96SmrgLispReadEval(read_info *info) 17855dfecf96Smrg{ 17865dfecf96Smrg READ_ENTER(); 17875dfecf96Smrg int nodot = info->nodot; 17885dfecf96Smrg LispObj *code; 17895dfecf96Smrg 17905dfecf96Smrg info->nodot = info->level + 1; 17915dfecf96Smrg code = LispDoRead(info); 17925dfecf96Smrg info->nodot = nodot; 17935dfecf96Smrg 17945dfecf96Smrg if (info->discard) 17955dfecf96Smrg return (code); 17965dfecf96Smrg 17975dfecf96Smrg if (INVALIDP(code)) 17985dfecf96Smrg READ_ERROR_INVARG(); 17995dfecf96Smrg 18005dfecf96Smrg return (EVAL(code)); 18015dfecf96Smrg} 18025dfecf96Smrg 18035dfecf96Smrgstatic LispObj * 18045dfecf96SmrgLispReadComplex(read_info *info) 18055dfecf96Smrg{ 18065dfecf96Smrg READ_ENTER(); 18075dfecf96Smrg GC_ENTER(); 18085dfecf96Smrg int nodot = info->nodot; 18095dfecf96Smrg LispObj *number, *arguments; 18105dfecf96Smrg 18115dfecf96Smrg info->nodot = info->level + 1; 18125dfecf96Smrg arguments = LispDoRead(info); 18135dfecf96Smrg info->nodot = nodot; 18145dfecf96Smrg 18155dfecf96Smrg /* form read */ 18165dfecf96Smrg if (info->discard) 18175dfecf96Smrg return (arguments); 18185dfecf96Smrg 18195dfecf96Smrg if (INVALIDP(arguments) || !CONSP(arguments)) 18205dfecf96Smrg READ_ERROR_INVARG(); 18215dfecf96Smrg 18225dfecf96Smrg GC_PROTECT(arguments); 18235dfecf96Smrg number = APPLY(Ocomplex, arguments); 18245dfecf96Smrg GC_LEAVE(); 18255dfecf96Smrg 18265dfecf96Smrg return (number); 18275dfecf96Smrg} 18285dfecf96Smrg 18295dfecf96Smrgstatic LispObj * 18305dfecf96SmrgLispReadPathname(read_info *info) 18315dfecf96Smrg{ 18325dfecf96Smrg READ_ENTER(); 18335dfecf96Smrg GC_ENTER(); 18345dfecf96Smrg int nodot = info->nodot; 18355dfecf96Smrg LispObj *path, *arguments; 18365dfecf96Smrg 18375dfecf96Smrg info->nodot = info->level + 1; 18385dfecf96Smrg arguments = LispDoRead(info); 18395dfecf96Smrg info->nodot = nodot; 18405dfecf96Smrg 18415dfecf96Smrg /* form read */ 18425dfecf96Smrg if (info->discard) 18435dfecf96Smrg return (arguments); 18445dfecf96Smrg 18455dfecf96Smrg if (INVALIDP(arguments)) 18465dfecf96Smrg READ_ERROR_INVARG(); 18475dfecf96Smrg 18485dfecf96Smrg GC_PROTECT(arguments); 18495dfecf96Smrg path = APPLY1(Oparse_namestring, arguments); 18505dfecf96Smrg GC_LEAVE(); 18515dfecf96Smrg 18525dfecf96Smrg return (path); 18535dfecf96Smrg} 18545dfecf96Smrg 18555dfecf96Smrgstatic LispObj * 18565dfecf96SmrgLispReadStruct(read_info *info) 18575dfecf96Smrg{ 18585dfecf96Smrg READ_ENTER(); 18595dfecf96Smrg GC_ENTER(); 18605dfecf96Smrg int len, nodot = info->nodot; 18615dfecf96Smrg char stk[128], *str; 18625dfecf96Smrg LispObj *struc, *fields; 18635dfecf96Smrg 18645dfecf96Smrg info->nodot = info->level + 1; 18655dfecf96Smrg fields = LispDoRead(info); 18665dfecf96Smrg info->nodot = nodot; 18675dfecf96Smrg 18685dfecf96Smrg /* form read */ 18695dfecf96Smrg if (info->discard) 18705dfecf96Smrg return (fields); 18715dfecf96Smrg 18725dfecf96Smrg if (INVALIDP(fields) || !CONSP(fields) || !SYMBOLP(CAR(fields))) 18735dfecf96Smrg READ_ERROR_INVARG(); 18745dfecf96Smrg 18755dfecf96Smrg GC_PROTECT(fields); 18765dfecf96Smrg 1877f14f4646Smrg len = ATOMID(CAR(fields))->length; 18785dfecf96Smrg /* MAKE- */ 18795dfecf96Smrg if (len + 6 > sizeof(stk)) 18805dfecf96Smrg str = LispMalloc(len + 6); 18815dfecf96Smrg else 18825dfecf96Smrg str = stk; 1883f14f4646Smrg sprintf(str, "MAKE-%s", ATOMID(CAR(fields))->value); 18845dfecf96Smrg RPLACA(fields, ATOM(str)); 18855dfecf96Smrg if (str != stk) 18865dfecf96Smrg LispFree(str); 18875dfecf96Smrg struc = APPLY(Omake_struct, fields); 18885dfecf96Smrg GC_LEAVE(); 18895dfecf96Smrg 18905dfecf96Smrg return (struc); 18915dfecf96Smrg} 18925dfecf96Smrg 18935dfecf96Smrg/* XXX This is broken, needs a rewritten as soon as true vector/arrays be 18945dfecf96Smrg * implemented. */ 18955dfecf96Smrgstatic LispObj * 18965dfecf96SmrgLispReadArray(long dimensions, read_info *info) 18975dfecf96Smrg{ 18985dfecf96Smrg READ_ENTER(); 18995dfecf96Smrg GC_ENTER(); 19005dfecf96Smrg long count; 19015dfecf96Smrg int nodot = info->nodot; 19025dfecf96Smrg LispObj *arguments, *initial, *dim, *cons, *array, *data; 19035dfecf96Smrg 19045dfecf96Smrg info->nodot = info->level + 1; 19055dfecf96Smrg data = LispDoRead(info); 19065dfecf96Smrg info->nodot = nodot; 19075dfecf96Smrg 19085dfecf96Smrg /* form read */ 19095dfecf96Smrg if (info->discard) 19105dfecf96Smrg return (data); 19115dfecf96Smrg 19125dfecf96Smrg if (INVALIDP(data)) 19135dfecf96Smrg READ_ERROR_INVARG(); 19145dfecf96Smrg 19155dfecf96Smrg initial = Kinitial_contents; 19165dfecf96Smrg 19175dfecf96Smrg dim = cons = NIL; 19185dfecf96Smrg if (dimensions) { 19195dfecf96Smrg LispObj *array; 19205dfecf96Smrg 19215dfecf96Smrg for (count = 0, array = data; count < dimensions; count++) { 19225dfecf96Smrg long length; 19235dfecf96Smrg LispObj *item; 19245dfecf96Smrg 19255dfecf96Smrg if (!CONSP(array)) 19265dfecf96Smrg READ_ERROR0("bad array for given dimension"); 19275dfecf96Smrg item = array; 19285dfecf96Smrg array = CAR(array); 19295dfecf96Smrg 19305dfecf96Smrg for (length = 0; CONSP(item); item = CDR(item), length++) 19315dfecf96Smrg ; 19325dfecf96Smrg 19335dfecf96Smrg if (dim == NIL) { 19345dfecf96Smrg dim = cons = CONS(FIXNUM(length), NIL); 19355dfecf96Smrg GC_PROTECT(dim); 19365dfecf96Smrg } 19375dfecf96Smrg else { 19385dfecf96Smrg RPLACD(cons, CONS(FIXNUM(length), NIL)); 19395dfecf96Smrg cons = CDR(cons); 19405dfecf96Smrg } 19415dfecf96Smrg } 19425dfecf96Smrg } 19435dfecf96Smrg 19445dfecf96Smrg arguments = CONS(dim, CONS(initial, CONS(data, NIL))); 19455dfecf96Smrg GC_PROTECT(arguments); 19465dfecf96Smrg array = APPLY(Omake_array, arguments); 19475dfecf96Smrg GC_LEAVE(); 19485dfecf96Smrg 19495dfecf96Smrg return (array); 19505dfecf96Smrg} 19515dfecf96Smrg 19525dfecf96Smrgstatic LispObj * 19535dfecf96SmrgLispReadFeature(int with, read_info *info) 19545dfecf96Smrg{ 19555dfecf96Smrg READ_ENTER(); 19565dfecf96Smrg LispObj *status; 19575dfecf96Smrg LispObj *feature = LispDoRead(info); 19585dfecf96Smrg 19595dfecf96Smrg /* form read */ 19605dfecf96Smrg if (info->discard) 19615dfecf96Smrg return (feature); 19625dfecf96Smrg 19635dfecf96Smrg if (INVALIDP(feature)) 19645dfecf96Smrg READ_ERROR_INVARG(); 19655dfecf96Smrg 19665dfecf96Smrg /* paranoia check, features must be a list, possibly empty */ 19675dfecf96Smrg if (!CONSP(FEATURES) && FEATURES != NIL) 19685dfecf96Smrg READ_ERROR1("%s is not a list", STROBJ(FEATURES)); 19695dfecf96Smrg 19705dfecf96Smrg status = LispEvalFeature(feature); 19715dfecf96Smrg 19725dfecf96Smrg if (with) { 19735dfecf96Smrg if (status == T) 19745dfecf96Smrg return (LispDoRead(info)); 19755dfecf96Smrg 19765dfecf96Smrg /* need to use the field discard because the following expression 19775dfecf96Smrg * may be #.FORM or #,FORM or any other form that may generate 19785dfecf96Smrg * side effects */ 19795dfecf96Smrg info->discard = 1; 19805dfecf96Smrg LispDoRead(info); 19815dfecf96Smrg info->discard = 0; 19825dfecf96Smrg 19835dfecf96Smrg return (LispDoRead(info)); 19845dfecf96Smrg } 19855dfecf96Smrg 19865dfecf96Smrg if (status == NIL) 19875dfecf96Smrg return (LispDoRead(info)); 19885dfecf96Smrg 19895dfecf96Smrg info->discard = 1; 19905dfecf96Smrg LispDoRead(info); 19915dfecf96Smrg info->discard = 0; 19925dfecf96Smrg 19935dfecf96Smrg return (LispDoRead(info)); 19945dfecf96Smrg} 19955dfecf96Smrg 19965dfecf96Smrg/* 19975dfecf96Smrg * A very simple eval loop with AND, NOT, and OR functions for testing 19985dfecf96Smrg * the available features. 19995dfecf96Smrg */ 20005dfecf96Smrgstatic LispObj * 20015dfecf96SmrgLispEvalFeature(LispObj *feature) 20025dfecf96Smrg{ 20035dfecf96Smrg READ_ENTER(); 20045dfecf96Smrg Atom_id test; 20055dfecf96Smrg LispObj *object; 20065dfecf96Smrg 20075dfecf96Smrg if (CONSP(feature)) { 20085dfecf96Smrg LispObj *function = CAR(feature), *arguments = CDR(feature); 20095dfecf96Smrg 20105dfecf96Smrg if (!SYMBOLP(function)) 20115dfecf96Smrg READ_ERROR1("bad feature test function %s", STROBJ(function)); 20125dfecf96Smrg if (!CONSP(arguments)) 20135dfecf96Smrg READ_ERROR1("bad feature test arguments %s", STROBJ(arguments)); 20145dfecf96Smrg test = ATOMID(function); 20155dfecf96Smrg if (test == Sand) { 20165dfecf96Smrg for (; CONSP(arguments); arguments = CDR(arguments)) { 20175dfecf96Smrg if (LispEvalFeature(CAR(arguments)) == NIL) 20185dfecf96Smrg return (NIL); 20195dfecf96Smrg } 20205dfecf96Smrg return (T); 20215dfecf96Smrg } 20225dfecf96Smrg else if (test == Sor) { 20235dfecf96Smrg for (; CONSP(arguments); arguments = CDR(arguments)) { 20245dfecf96Smrg if (LispEvalFeature(CAR(arguments)) == T) 20255dfecf96Smrg return (T); 20265dfecf96Smrg } 20275dfecf96Smrg return (NIL); 20285dfecf96Smrg } 20295dfecf96Smrg else if (test == Snot) { 20305dfecf96Smrg if (CONSP(CDR(arguments))) 20315dfecf96Smrg READ_ERROR0("too many arguments to NOT"); 20325dfecf96Smrg 20335dfecf96Smrg return (LispEvalFeature(CAR(arguments)) == NIL ? T : NIL); 20345dfecf96Smrg } 20355dfecf96Smrg else 20365dfecf96Smrg READ_ERROR1("unimplemented feature test function %s", test); 20375dfecf96Smrg } 20385dfecf96Smrg 20395dfecf96Smrg if (KEYWORDP(feature)) 20405dfecf96Smrg feature = feature->data.quote; 20415dfecf96Smrg else if (!SYMBOLP(feature)) 20425dfecf96Smrg READ_ERROR1("bad feature specification %s", STROBJ(feature)); 20435dfecf96Smrg 20445dfecf96Smrg test = ATOMID(feature); 20455dfecf96Smrg 20465dfecf96Smrg for (object = FEATURES; CONSP(object); object = CDR(object)) { 20475dfecf96Smrg /* paranoia check, elements in the feature list must ge keywords */ 20485dfecf96Smrg if (!KEYWORDP(CAR(object))) 20495dfecf96Smrg READ_ERROR1("%s is not a keyword", STROBJ(CAR(object))); 20505dfecf96Smrg if (ATOMID(CAR(object)) == test) 20515dfecf96Smrg return (T); 20525dfecf96Smrg } 20535dfecf96Smrg 20545dfecf96Smrg /* unknown feature */ 20555dfecf96Smrg return (NIL); 20565dfecf96Smrg} 2057