00001
00013
00014 #include <ctype.h>
00015
00016 #include "NewtPrint.h"
00017 #include "NewtCore.h"
00018 #include "NewtObj.h"
00019 #include "NewtEnv.h"
00020 #include "NewtIO.h"
00021
00022
00023
00024
00025 static int32_t NewtGetPrintLength(void);
00026 static int32_t NewtGetPrintDepth(void);
00027
00028 static bool NewtSymbolIsPrint(char * str, int len);
00029 static bool NewtStrIsPrint(char * str, int len);
00030 static char * NewtCharToEscape(int c);
00031
00032 static void NIOPrintEscapeStr(newtStream_t * f, char * str, int len);
00033 static void NIOPrintRef(newtStream_t * f, newtRefArg r);
00034 static void NIOPrintSpecial(newtStream_t * f, newtRefArg r);
00035 static void NIOPrintInteger(newtStream_t * f, newtRefArg r);
00036 static void NIOPrintReal(newtStream_t * f, newtRefArg r);
00037 static void NIOPrintObjCharacter(newtStream_t * f, newtRefArg r);
00038 static void NIOPrintObjMagicPointer(newtStream_t * f, newtRefArg r);
00039 static void NIOPrintObjBinary(newtStream_t * f, newtRefArg r);
00040 static void NIOPrintObjSymbol(newtStream_t * f, newtRefArg r);
00041 static void NIOPrintObjString(newtStream_t * f, newtRefArg r);
00042 static void NIOPrintObjArray(newtStream_t * f, newtRefArg r, int32_t depth, bool literal);
00043 static void NIOPrintFnFrame(newtStream_t * f, newtRefArg r);
00044 static void NIOPrintRegexFrame(newtStream_t * f, newtRefArg r);
00045 static void NIOPrintObjFrame(newtStream_t * f, newtRefArg r, int32_t depth, bool literal);
00046 static void NIOPrintLiteral(newtStream_t * f, newtRefArg r, bool * literalP);
00047 static void NIOPrintObj2(newtStream_t * f, newtRefArg r, int32_t depth, bool literal);
00048
00049 static void NIOPrintCharacter(newtStream_t * f, newtRefArg r);
00050 static void NIOPrintSymbol(newtStream_t * f, newtRefArg r);
00051 static void NIOPrintString(newtStream_t * f, newtRefArg r);
00052 static void NIOPrintArray(newtStream_t * f, newtRefArg r);
00053 static void NIOPrintObj(newtStream_t * f, newtRefArg r);
00054 static void NIOPrint(newtStream_t * f, newtRefArg r);
00055
00056 static void NIOInfo(newtStream_t * f, newtRefArg r);
00057
00058
00059 #pragma mark -
00060
00066 int32_t NewtGetPrintLength(void)
00067 {
00068 newtRefVar n;
00069 int32_t printLength = -1;
00070
00071 n = NcGetGlobalVar(NSSYM0(printLength));
00072
00073 if (NewtRefIsInteger(n))
00074 printLength = NewtRefToInteger(n);
00075
00076 if (printLength < 0)
00077 printLength = 0x7fffffff;
00078
00079 return printLength;
00080 }
00081
00082
00083
00089 int32_t NewtGetPrintDepth(void)
00090 {
00091 newtRefVar n;
00092 int32_t depth = 3;
00093
00094 n = NcGetGlobalVar(NSSYM0(printDepth));
00095
00096 if (NewtRefIsInteger(n))
00097 depth = NewtRefToInteger(n);
00098
00099 return depth;
00100 }
00101
00102
00103 #pragma mark -
00104
00114 bool NewtSymbolIsPrint(char * str, int len)
00115 {
00116 int c;
00117 int i;
00118
00119 if (len == 0)
00120 return false;
00121
00122 c = str[0];
00123
00124 if ('0' <= c && c <= '9')
00125 return false;
00126
00127 for (i = 0; i < len && str[i]; i++)
00128 {
00129 c = str[i];
00130
00131 if (c == '_') continue;
00132 if ('a' <= c && c <= 'z') continue;
00133 if ('A' <= c && c <= 'Z') continue;
00134 if ('0' <= c && c <= '9') continue;
00135
00136 return false;
00137 }
00138
00139 return true;
00140 }
00141
00142
00143
00153 bool NewtStrIsPrint(char * str, int len)
00154 {
00155 int i;
00156
00157 for (i = 0; i < len && str[i]; i++)
00158 {
00159 if (str[i] == '"')
00160 return false;
00161
00162 if (! isprint(str[i]))
00163 return false;
00164 }
00165
00166 return true;
00167 }
00168
00169
00170
00178 char * NewtCharToEscape(int c)
00179 {
00180 char * s = NULL;
00181
00182 switch (c)
00183 {
00184 case 'n':
00185 s = "n";
00186 break;
00187
00188 case 'r':
00189 s = "r";
00190 break;
00191
00192 case 't':
00193 s = "t";
00194 break;
00195
00196 case '"':
00197 s = """;
00198 break;
00199 }
00200
00201 return s;
00202 }
00203
00204
00205 /*------------------------------------------------------------------------*/
00217 void NIOPrintEscapeStr(newtStream_t * f, char * str, int len)
00218 {
00219 bool unicode = false;
00220 char * s;
00221 int c;
00222 int i;
00223
00224 for (i = 0; i < len; i++)
00225 {
00226 c = str[i];
00227
00228 s = NewtCharToEscape(c);
00229
00230 if (s != NULL)
00231 {
00232 if (unicode)
00233 {
00234 NIOFputs("u", f);
00235 unicode = false;
00236 }
00237
00238 NIOFputs(s, f);
00239 }
00240 else if (isprint(c))
00241 {
00242 if (unicode)
00243 {
00244 NIOFputs("u", f);
00245 unicode = false;
00246 }
00247
00248 NIOFputc(c, f);
00249 }
00250 else
00251 {
00252 if (! unicode)
00253 {
00254 NIOFputs("u", f);
00255 unicode = true;
00256 }
00257
00258 NIOFprintf(f, "%02x%02x", c, str[++i]);
00259 }
00260 }
00261 }
00262
00263
00264 #pragma mark -
00265 /*------------------------------------------------------------------------*/
00276 void NIOPrintRef(newtStream_t * f, newtRefArg r)
00277 {
00278 NIOFprintf(f, "#%08x", r);
00279 }
00280
00281
00282 /*------------------------------------------------------------------------*/
00293 void NIOPrintSpecial(newtStream_t * f, newtRefArg r)
00294 {
00295 int n;
00296
00297 n = NewtRefToSpecial(r);
00298 NIOFprintf(f, "<Special, %04x>", n);
00299 }
00300
00301
00302 /*------------------------------------------------------------------------*/
00313 void NIOPrintInteger(newtStream_t * f, newtRefArg r)
00314 {
00315 int n;
00316
00317 n = NewtRefToInteger(r);
00318 NIOFprintf(f, "%d", n);
00319 }
00320
00321
00322 /*------------------------------------------------------------------------*/
00333 void NIOPrintReal(newtStream_t * f, newtRefArg r)
00334 {
00335 double n;
00336
00337 n = NewtRefToReal(r);
00338 NIOFprintf(f, "%f", n);
00339 }
00340
00341
00342 /*------------------------------------------------------------------------*/
00353 void NIOPrintObjCharacter(newtStream_t * f, newtRefArg r)
00354 {
00355 char * s;
00356 int c;
00357
00358 c = NewtRefToCharacter(r);
00359
00360 NIOFputc('$', f);
00361
00362 s = NewtCharToEscape(c);
00363
00364 if (s != NULL)
00365 NIOFputs(s, f);
00366 else if (0xff00 & c)
00367 NIOFprintf(f, "u%04x", c);
00368 else if (isprint(c))
00369 NIOFputc(c, f);
00370 else
00371 NIOFprintf(f, "%02x", c);
00372 }
00373
00374
00375 #ifdef __NAMED_MAGIC_POINTER__
00376
00377 /*------------------------------------------------------------------------*/
00388 void NIOPrintObjMagicPointer(newtStream_t * f, newtRefArg r)
00389 {
00390 newtRefVar sym;
00391
00392 sym = NewtMPToSymbol(r);
00393
00394 NIOFputc('@', f);
00395 NIOPrintObjSymbol(f, sym);
00396 }
00397
00398 #else
00399
00400 /*------------------------------------------------------------------------*/
00411 void NIOPrintObjMagicPointer(newtStream_t * f, newtRefArg r)
00412 {
00413 int32_t table;
00414 int32_t index;
00415
00416 table = NewtMPToTable(r);
00417 index = NewtMPToIndex(r);
00418
00419 NIOFprintf(f, "@%d", index);
00420 }
00421
00422 #endif
00423
00424 /*------------------------------------------------------------------------*/
00435 void NIOPrintObjBinary(newtStream_t * f, newtRefArg r)
00436 {
00437 newtRefVar klass;
00438 int ptr;
00439 int len;
00440
00441 ptr = r;
00442 len = NewtBinaryLength(r);
00443 NIOFputs("<Binary, ", f);
00444
00445 //
00446 klass = NcClassOf(r);
00447
00448 if (NewtRefIsSymbol(klass))
00449 {
00450 NIOFputs("class "", f);
00451 NIOPrintObj2(f, klass, 0, true);
00452 NIOFputs("", ", f);
00453 }
00454
00455 NIOFprintf(f, "length %d>", len);
00456 }
00457
00458
00459 /*------------------------------------------------------------------------*/
00470 void NIOPrintObjSymbol(newtStream_t * f, newtRefArg r)
00471 {
00472 newtSymDataRef sym;
00473 int len;
00474
00475 sym = NewtRefToSymbol(r);
00476 len = NewtSymbolLength(r);
00477
00478 if (NewtSymbolIsPrint(sym->name, len))
00479 {
00480 NIOFputs(sym->name, f);
00481 }
00482 else
00483 {
00484 NIOFputc('|', f);
00485 NIOPrintEscapeStr(f, sym->name, len);
00486 NIOFputc('|', f);
00487 }
00488 }
00489
00490
00491 /*------------------------------------------------------------------------*/
00502 void NIOPrintObjString(newtStream_t * f, newtRefArg r)
00503 {
00504 char * s;
00505 int len;
00506
00507 s = NewtRefToString(r);
00508 len = NewtStringLength(r);
00509
00510 if (NewtStrIsPrint(s, len))
00511 {
00512 // NIOFprintf(f, ""%s"", s);
00513 NIOFputs(""", f);
00514 NIOFputs(s, f);
00515 NIOFputs(""", f);
00516 }
00517 else
00518 {
00519 NIOFputc('"', f);
00520 NIOPrintEscapeStr(f, s, len);
00521 NIOFputc('"', f);
00522 }
00523 }
00524
00525
00526
00539 void NIOPrintObjArray(newtStream_t * f, newtRefArg r, int32_t depth, bool literal)
00540 {
00541 newtObjRef obj;
00542 newtRef * slots;
00543 newtRefVar klass;
00544 uint32_t len;
00545 uint32_t i;
00546
00547 obj = NewtRefToPointer(r);
00548 len = NewtObjSlotsLength(obj);
00549 slots = NewtObjToSlots(obj);
00550
00551 if (literal && NcClassOf(r) == NSSYM0(pathExpr))
00552 {
00553 for (i = 0; i < len; i++)
00554 {
00555 if (0 < i)
00556 NIOFputs(".", f);
00557
00558 NIOPrintObj2(f, slots[i], 0, literal);
00559 }
00560 }
00561 else
00562 {
00563 NIOFputs("[", f);
00564
00565 klass = NcClassOf(r);
00566
00567 if (NewtRefIsNotNIL(klass) && ! NewtRefEqual(klass, NSSYM0(array)))
00568 {
00569 NIOPrintObj2(f, klass, 0, true);
00570 NIOFputs(": ", f);
00571 }
00572
00573 if (depth < 0)
00574 {
00575 NIOPrintRef(f, r);
00576 }
00577 else
00578 {
00579 int32_t printLength;
00580
00581 depth--;
00582 printLength = NewtGetPrintLength();
00583
00584 for (i = 0; i < len; i++)
00585 {
00586 if (0 < i)
00587 NIOFputs(", ", f);
00588
00589 if (printLength <= i)
00590 {
00591 NIOFputs("...", f);
00592 break;
00593 }
00594
00595 NIOPrintObj2(f, slots[i], depth, literal);
00596 }
00597 }
00598
00599 NIOFputs("]", f);
00600 }
00601 }
00602
00603
00604
00615 void NIOPrintFnFrame(newtStream_t * f, newtRefArg r)
00616 {
00617 newtRefVar indefinite;
00618 int32_t numArgs;
00619 char * indefiniteStr = "";
00620
00621 numArgs = NewtRefToInteger(NcGetSlot(r, NSSYM0(numArgs)));
00622 indefinite = NcGetSlot(r, NSSYM0(indefinite));
00623
00624 if (NewtRefIsNotNIL(indefinite))
00625 indefiniteStr = "...";
00626
00627 NIOFprintf(f, "<function, %d arg(s)%s #%08x>", numArgs, indefiniteStr, r);
00628 }
00629
00630
00631
00642 void NIOPrintRegexFrame(newtStream_t * f, newtRefArg r)
00643 {
00644 newtRefVar pattern;
00645 newtRefVar option;
00646
00647 pattern = NcGetSlot(r, NSSYM0(pattern));
00648 option = NcGetSlot(r, NSSYM0(option));
00649
00650
00651 NIOFputs("/", f);
00652 NIOFputs(NewtRefToString(pattern), f);
00653 NIOFputs("/", f);
00654
00655 if (NewtRefIsString(option))
00656 NIOFputs(NewtRefToString(option), f);
00657 }
00658
00659
00660
00673 void NIOPrintObjFrame(newtStream_t * f, newtRefArg r, int32_t depth, bool literal)
00674 {
00675 newtObjRef obj;
00676 newtRef * slots;
00677 newtRefVar slot;
00678 uint32_t index;
00679 uint32_t len;
00680 uint32_t i;
00681
00682 if (NewtRefIsFunction(r) && ! NEWT_DUMPBC)
00683 {
00684 NIOPrintFnFrame(f, r);
00685 return;
00686 }
00687
00688 if (NewtRefIsRegex(r) && ! NEWT_DUMPBC)
00689 {
00690 NIOPrintRegexFrame(f, r);
00691 return;
00692 }
00693
00694 obj = NewtRefToPointer(r);
00695 len = NewtObjSlotsLength(obj);
00696 slots = NewtObjToSlots(obj);
00697
00698 NIOFputs("{", f);
00699
00700 if (depth < 0)
00701 {
00702 NIOPrintRef(f, r);
00703 }
00704 else
00705 {
00706 int32_t printLength;
00707
00708 depth--;
00709 printLength = NewtGetPrintLength();
00710
00711 for (i = 0; i < len; i++)
00712 {
00713 if (0 < i)
00714 NIOFputs(", ", f);
00715
00716 if (printLength <= i)
00717 {
00718 NIOFputs("...", f);
00719 break;
00720 }
00721
00722 slot = NewtGetMapIndex(obj->as.map, i, &index);
00723 if (slot == kNewtRefUnbind) break;
00724
00725 NIOPrintObjSymbol(f, slot);
00726 NIOFputs(": ", f);
00727 NIOPrintObj2(f, slots[i], depth, literal);
00728 }
00729 }
00730
00731 NIOFputs("}", f);
00732 }
00733
00734
00735
00747 void NIOPrintLiteral(newtStream_t * f, newtRefArg r, bool * literalP)
00748 {
00749 if (! *literalP && NewtRefIsLiteral(r))
00750 {
00751 NIOFputc(''', f);
00752 *literalP = true;
00753 }
00754 }
00755
00756
00757
00770 void NIOPrintObj2(newtStream_t * f, newtRefArg r, int32_t depth, bool literal)
00771 {
00772 switch (NewtGetRefType(r, true))
00773 {
00774 case kNewtNil:
00775 NIOFputs("NIL", f);
00776 break;
00777
00778 case kNewtTrue:
00779 NIOFputs("TRUE", f);
00780 break;
00781
00782 case kNewtUnbind:
00783 NIOFputs("#UNBIND", f);
00784 break;
00785
00786 case kNewtSpecial:
00787 NIOPrintSpecial(f, r);
00788 break;
00789
00790 case kNewtInt30:
00791 case kNewtInt32:
00792 NIOPrintInteger(f, r);
00793 break;
00794
00795 case kNewtReal:
00796 NIOPrintReal(f, r);
00797 break;
00798
00799 case kNewtCharacter:
00800 NIOPrintObjCharacter(f, r);
00801 break;
00802
00803 case kNewtMagicPointer:
00804 if (0 <= depth)
00805 {
00806 newtRefVar r2;
00807
00808 r2 = NcResolveMagicPointer(r);
00809
00810 if (! NewtRefIsMagicPointer(r2))
00811 {
00812 NIOPrintObj2(f, r2, depth, literal);
00813 break;
00814 }
00815 }
00816
00817 NIOPrintObjMagicPointer(f, r);
00818 break;
00819
00820 case kNewtBinary:
00821 NIOPrintObjBinary(f, r);
00822 break;
00823
00824 case kNewtArray:
00825 NIOPrintLiteral(f, r, &literal);
00826 NIOPrintObjArray(f, r, depth, literal);
00827 break;
00828
00829 case kNewtFrame:
00830 NIOPrintLiteral(f, r, &literal);
00831 NIOPrintObjFrame(f, r, depth, literal);
00832 break;
00833
00834 case kNewtSymbol:
00835 NIOPrintLiteral(f, r, &literal);
00836 NIOPrintObjSymbol(f, r);
00837 break;
00838
00839 case kNewtString:
00840 NIOPrintObjString(f, r);
00841 break;
00842
00843 default:
00844 NIOFputs("###UNKNOWN###", f);
00845 break;
00846 }
00847 }
00848
00849
00850
00861 void NIOPrintObj(newtStream_t * f, newtRefArg r)
00862 {
00863 NIOPrintObj2(f, r, NewtGetPrintDepth(), false);
00864 }
00865
00866
00867
00876 void NewtPrintObj(FILE * f, newtRefArg r)
00877 {
00878 newtStream_t stream;
00879
00880 NIOSetFile(&stream, f);
00881 NIOPrintObj(&stream, r);
00882 }
00883
00884
00885
00894 void NewtPrintObject(FILE * f, newtRefArg r)
00895 {
00896 newtStream_t stream;
00897
00898 NIOSetFile(&stream, f);
00899
00900 NIOPrintObj(&stream, r);
00901 NIOFputs("n", &stream);
00902 }
00903
00904
00905
00916 void NIOPrintCharacter(newtStream_t * f, newtRefArg r)
00917 {
00918 NIOFputc(NewtRefToCharacter(r), f);
00919 }
00920
00921
00922
00933 void NIOPrintSymbol(newtStream_t * f, newtRefArg r)
00934 {
00935 newtSymDataRef sym;
00936
00937 sym = NewtRefToSymbol(r);
00938 NIOFputs(sym->name, f);
00939 }
00940
00941
00942
00953 void NIOPrintString(newtStream_t * f, newtRefArg r)
00954 {
00955 NIOFputs(NewtRefToString(r), f);
00956 }
00957
00958
00959
00970 void NIOPrintArray(newtStream_t * f, newtRefArg r)
00971 {
00972 newtRef * slots;
00973 uint32_t len;
00974 uint32_t i;
00975
00976 slots = NewtRefToSlots(r);
00977 len = NewtLength(r);
00978
00979 for (i = 0; i < len; i++)
00980 {
00981 NIOPrint(f, slots[i]);
00982 }
00983 }
00984
00985
00986
00997 void NIOPrint(newtStream_t * f, newtRefArg r)
00998 {
00999 switch (NewtGetRefType(r, true))
01000 {
01001 case kNewtNil:
01002 case kNewtTrue:
01003 case kNewtUnbind:
01004 break;
01005
01006 case kNewtSpecial:
01007 NIOPrintSpecial(f, r);
01008 break;
01009
01010 case kNewtInt30:
01011 case kNewtInt32:
01012 NIOPrintInteger(f, r);
01013 break;
01014
01015 case kNewtReal:
01016 NIOPrintReal(f, r);
01017 break;
01018
01019 case kNewtCharacter:
01020 NIOPrintCharacter(f, r);
01021 break;
01022
01023 case kNewtMagicPointer:
01024 {
01025 newtRefVar r2;
01026
01027 r2 = NcResolveMagicPointer(r);
01028
01029 if (! NewtRefIsMagicPointer(r2))
01030 {
01031 NIOPrint(f, r2);
01032 }
01033 }
01034 break;
01035
01036 case kNewtArray:
01037 NIOPrintArray(f, r);
01038 break;
01039
01040 case kNewtBinary:
01041 case kNewtFrame:
01042 break;
01043
01044 case kNewtSymbol:
01045 NIOPrintSymbol(f, r);
01046 break;
01047
01048 case kNewtString:
01049 NIOPrintString(f, r);
01050 break;
01051
01052 default:
01053 break;
01054 }
01055 }
01056
01057
01058
01067 void NewtPrint(FILE * f, newtRefArg r)
01068 {
01069 newtStream_t stream;
01070
01071 NIOSetFile(&stream, f);
01072 NIOPrint(&stream, r);
01073 }
01074
01075
01076
01086 void NIOInfo(newtStream_t * f, newtRefArg r)
01087 {
01088 newtRefVar fn = kNewtRefUnbind;
01089
01090 if (NewtRefIsSymbol(r))
01091 fn = NcGetGlobalFn(r);
01092 else
01093 fn = (newtRef)r;
01094
01095 if (NewtRefIsFunction(fn))
01096 {
01097 newtRefVar docString;
01098
01099 docString = NcGetSlot(fn, NSSYM0(docString));
01100
01101 if (NewtRefIsNotNIL(docString))
01102 {
01103 if (NewtRefIsString(docString))
01104 {
01105
01106 NIOFputs(NewtRefToString(docString), f);
01107 NIOFputs("n", f);
01108 }
01109 else
01110 {
01111 NIOPrintObj(f, docString);
01112 }
01113 }
01114 }
01115 }
01116
01117
01118
01126 void NewtInfo(newtRefArg r)
01127 {
01128 newtStream_t stream;
01129
01130 NIOSetFile(&stream, stdout);
01131 NIOInfo(&stream, r);
01132 }
01133
01134
01135
01141 void NewtInfoGlobalFns(void)
01142 {
01143 newtStream_t stream;
01144 newtRef * slots;
01145 newtRefVar fns;
01146 uint32_t len;
01147 uint32_t i;
01148
01149 NIOSetFile(&stream, stdout);
01150
01151 fns = NcGetGlobalFns();
01152 len = NewtLength(fns);
01153
01154 slots = NewtRefToSlots(fns);
01155
01156 for (i = 0; i < len; i++)
01157 {
01158 NIOInfo(&stream, slots[i]);
01159 }
01160 }
01161
01162