wonbe.c 45 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203
  1. /* wonbe: WonderWitch Basic Environment */
  2. /* First Created: Nov.3,2000 by Nashiko */
  3. /* Copyright 2000 (c) by Pie Dey Co.,Ltd. */
  4. /* This source code is for both VC++6.0 and Turbo C 2.0 */
  5. #include <stdio.h>
  6. #include <string.h>
  7. #include <stdlib.h>
  8. #ifdef WIN32
  9. #include <assert.h>
  10. #endif
  11. #ifdef WW
  12. #include <sys/comm.h>
  13. #include <sys/process.h>
  14. #include <sys/fcntl.h>
  15. #include <sys/bios.h>
  16. #define assert(x)
  17. #endif
  18. #include "keywords.h"
  19. #ifdef WIN32
  20. #include "win32text.h"
  21. #endif
  22. char myVersion[] = "0.04";
  23. #ifdef WW
  24. #define MEMMOVE mymemmove
  25. #define FAR far
  26. #else
  27. #define MEMMOVE mymemmove
  28. #define FAR
  29. #endif
  30. #ifdef WIN32
  31. typedef unsigned char BYTE;
  32. #endif
  33. typedef unsigned short WORD;
  34. typedef signed short SHORT;
  35. #define EOL (0x0d)
  36. #ifdef WIN32
  37. typedef int BOOL;
  38. #endif
  39. #define FALSE 0
  40. #define TRUE 1
  41. typedef void (*NEARPROC)();
  42. #define WORKAREA_SIZE ((WORD)49152)
  43. #define LINE_SIZE (256)
  44. /* 実行のみのモードで動いているとき (シリアル経由で端末が居ないとき) */
  45. BOOL runtimeOnly;
  46. #ifdef WW
  47. void fatalExit( const char * msg )
  48. {
  49. text_screen_init();
  50. text_put_string( 0, 0, (char*)msg );
  51. text_put_string( 0, 3, "PUSH ANY BUTTON" );
  52. key_wait();
  53. }
  54. #endif
  55. BOOL commonPrint( FILE FAR * fp, const char * msg,... )
  56. {
  57. #ifdef WW
  58. static
  59. #endif
  60. char buf[256];
  61. vsprintf(buf, msg, (va_list)(&msg+1) );
  62. if( fp != NULL ) {
  63. int r;
  64. r = fprintf( fp, buf );
  65. return r >= 0;
  66. } else {
  67. #ifdef WW
  68. if( runtimeOnly ) {
  69. fatalExit( buf );
  70. } else {
  71. comm_send_string( buf );
  72. }
  73. #else
  74. printf( buf );
  75. #endif
  76. }
  77. return TRUE;
  78. }
  79. void consoleInput( BYTE * buf, WORD len )
  80. {
  81. #ifdef WW
  82. WORD cursor;
  83. if( runtimeOnly ) {
  84. fatalExit("consoleInput not allowed in runtime mode");
  85. } else {
  86. cursor = 0;
  87. while( TRUE ) {
  88. int ch;
  89. ch = comm_receive_char();
  90. if( ch == 0x0d ) { /* CR */
  91. buf[cursor] = '\0';
  92. return;
  93. }
  94. if( ch == 0x09 ) { /* TAB */
  95. goto inputAsChar;
  96. }
  97. if( ch == 0x08 ) { /* BS */
  98. if( cursor > 0 ) {
  99. cursor--;
  100. comm_send_char( (unsigned char)ch );
  101. continue;
  102. }
  103. }
  104. if( ch >= 0 && ch < ' ' ) {
  105. /* ignore it */
  106. continue;
  107. }
  108. if( ch >= ' ' && ch <= 0xfc ) {
  109. inputAsChar:
  110. if( cursor < len-1 ) {
  111. buf[cursor] = ch;
  112. cursor++;
  113. comm_send_char( (unsigned char)ch );
  114. }
  115. }
  116. }
  117. }
  118. #else
  119. gets(buf);
  120. #endif
  121. }
  122. typedef struct {
  123. WORD id;
  124. const BYTE * name;
  125. } KEYWORDITEM;
  126. KEYWORDITEM keywordsA[] = {
  127. { KEYWORD_AND,"and" },
  128. { KEYWORD_ABS,"abs" },
  129. { 0,NULL }
  130. };
  131. KEYWORDITEM keywordsB[] = {
  132. { KEYWORD_BREAK,"break" },
  133. { 0,NULL }
  134. };
  135. KEYWORDITEM keywordsC[] = {
  136. { KEYWORD_CHR,"chr" },
  137. { KEYWORD_CLS,"cls" },
  138. { KEYWORD_CONT,"cont" },
  139. { 0,NULL }
  140. };
  141. KEYWORDITEM keywordsD[] = {
  142. { KEYWORD_DEBUG,"debug" },
  143. { 0,NULL }
  144. };
  145. KEYWORDITEM keywordsE[] = {
  146. { KEYWORD_END,"end" },
  147. { KEYWORD_EXIT,"exit" },
  148. { 0,NULL }
  149. };
  150. KEYWORDITEM keywordsF[] = {
  151. { KEYWORD_FOR,"for" },
  152. { KEYWORD_FILES,"files" },
  153. { 0,NULL }
  154. };
  155. KEYWORDITEM keywordsG[] = {
  156. { KEYWORD_GOTO,"goto" },
  157. { KEYWORD_GOSUB,"gosub" },
  158. { 0,NULL }
  159. };
  160. KEYWORDITEM keywordsI[] = {
  161. { KEYWORD_IF,"if" },
  162. { 0,NULL }
  163. };
  164. KEYWORDITEM keywordsL[] = {
  165. { KEYWORD_LOCATE,"locate" },
  166. { KEYWORD_LIST,"list" },
  167. { KEYWORD_LOAD,"load" },
  168. { 0,NULL }
  169. };
  170. KEYWORDITEM keywordsM[] = {
  171. { KEYWORD_MERGE,"merge" },
  172. { 0,NULL }
  173. };
  174. KEYWORDITEM keywordsN[] = {
  175. { KEYWORD_NEXT,"next" },
  176. { KEYWORD_NOT,"not" },
  177. { KEYWORD_NEW,"new" },
  178. { 0,NULL }
  179. };
  180. KEYWORDITEM keywordsO[] = {
  181. { KEYWORD_OR,"or" },
  182. { 0,NULL }
  183. };
  184. KEYWORDITEM keywordsP[] = {
  185. { KEYWORD_PRINT,"print" },
  186. { 0,NULL }
  187. };
  188. KEYWORDITEM keywordsR[] = {
  189. { KEYWORD_REM,"rem" },
  190. { KEYWORD_RETURN,"return" },
  191. { KEYWORD_RND,"rnd" },
  192. { KEYWORD_RUN,"run" },
  193. { KEYWORD_RANDOMIZE,"randomize" },
  194. { 0,NULL }
  195. };
  196. KEYWORDITEM keywordsS[] = {
  197. { KEYWORD_STEP,"step" },
  198. { KEYWORD_SCAN_A,"scan_a" },
  199. { KEYWORD_SCAN_B,"scan_b" },
  200. { KEYWORD_SCAN_X1,"scan_x1" },
  201. { KEYWORD_SCAN_X2,"scan_x2" },
  202. { KEYWORD_SCAN_X3,"scan_x3" },
  203. { KEYWORD_SCAN_X4,"scan_x4" },
  204. { KEYWORD_SCAN_Y1,"scan_y1" },
  205. { KEYWORD_SCAN_Y2,"scan_y2" },
  206. { KEYWORD_SCAN_Y3,"scan_y3" },
  207. { KEYWORD_SCAN_Y4,"scan_y4" },
  208. { KEYWORD_SCAN,"scan" }, /* scanはscna_Xより後になければならない */
  209. { KEYWORD_SAVE,"save" },
  210. { 0,NULL }
  211. };
  212. KEYWORDITEM keywordsT[] = {
  213. { KEYWORD_THEN,"then" },
  214. { KEYWORD_TO,"to" },
  215. { KEYWORD_TICK,"tick" },
  216. { 0,NULL }
  217. };
  218. KEYWORDITEM keywordsW[] = {
  219. { KEYWORD_WAITVB,"waitvb" },
  220. { KEYWORD_WAIT,"wait" }, // waitはwaitvbより後になければならない
  221. { 0,NULL }
  222. };
  223. KEYWORDITEM keywordsX[] = {
  224. { KEYWORD_XOR,"xor" },
  225. { 0,NULL }
  226. };
  227. KEYWORDITEM * keywordsIndex[26] = {
  228. keywordsA, keywordsB, keywordsC, keywordsD,
  229. keywordsE, keywordsF, keywordsG, NULL,
  230. keywordsI, NULL, NULL, keywordsL,
  231. keywordsM, keywordsN, keywordsO, keywordsP,
  232. NULL, keywordsR, keywordsS, keywordsT,
  233. NULL, NULL, keywordsW, keywordsX,
  234. NULL, NULL
  235. };
  236. /* インタラクティブモード時の1行バッファ */
  237. BYTE waRawLine[LINE_SIZE];
  238. BYTE waCoockedLine[LINE_SIZE];
  239. /* コードとデータを収める領域 */
  240. WORD codeTop;
  241. WORD dataTop;
  242. /*WORD savedPointer; /* breakしたときの実行中位置 */
  243. BYTE wa[WORKAREA_SIZE];
  244. /* グローバル変数領域 */
  245. #define NUMBER_OF_SIMPLE_VARIABLES (26)
  246. SHORT globalVariables[NUMBER_OF_SIMPLE_VARIABLES];
  247. SHORT topLevelVariables[NUMBER_OF_SIMPLE_VARIABLES];
  248. SHORT * localVariables; /* あるスコープで有効なローカル変数領域を持つ */
  249. /* 現在実行中の位置に関する情報 */
  250. /* waかwaCookedLineのどちらかの中を示すかNULL */
  251. BYTE * executionPointer;
  252. /* contコマンドで実行を再開するポイント */
  253. BYTE * resumePointer;
  254. /* 現在処理中の行番号 (0ならダイレクトモード) */
  255. WORD currentLineNumber;
  256. /* gosubとforのためのスタック */
  257. #define STACK_TYPE_GOSUB 1
  258. #define STACK_TYPE_FOR 2
  259. typedef struct {
  260. WORD type; /* 1==GOSUB, 2==FOR */
  261. /* for GOSUB and FOR */
  262. BYTE * returnPointer;
  263. /* for GOSUB */
  264. SHORT * lastLocalVariables;
  265. SHORT simpleVariables[NUMBER_OF_SIMPLE_VARIABLES];
  266. /* for FOR */
  267. SHORT * pvar; /* counter variable */
  268. SHORT limit; /* limit value */
  269. SHORT step; /* step value */
  270. } STACK;
  271. #define STACK_MAX 8
  272. STACK stacks[STACK_MAX];
  273. int stackPointer;
  274. /* インタラクティブモードかインタプリタモードか */
  275. BOOL bInteractive;
  276. /* インタプリタ脱出後の振る舞いのリクエスト */
  277. BOOL bForceToReturnSuper;
  278. int requestNextAction; /* 以下のいずれか */
  279. /* 何もせず現状のまま */
  280. #define REQUEST_NO_ACTION 0
  281. /* 対話モードへ行け */
  282. #define REQUEST_INTERACTIVE 1
  283. /* runLineNumberから実行を開始せよ */
  284. #define REQUEST_RUN_LINENUMBER 2
  285. /* waRawLineに入っている文字列をファイル名としてそれを読み込んで実行せよ */
  286. #define REQUEST_RUN_FILE 3
  287. /* newせよ */
  288. #define REQUEST_NEW 4
  289. /* waRawLineに入っている文字列をファイル名としてそれをロード */
  290. #define REQUEST_LOAD_FILE 5
  291. /* WONBEを終了してOSに戻れ */
  292. #define REQUEST_EXIT_SYSTEM 6
  293. /* waRawLineに入っている文字列をファイル名としてそれをマージ */
  294. #define REQUEST_MERGE_FILE 7
  295. /* REQUEST_RUN_LINENUMBERで実行開始をリクエストする行番号 */
  296. WORD runLineNumber;
  297. // 編集機能が追加専用モードであることを示す
  298. // REQUEST_RUN_FILE or REQUEST_LOAD_FILE経由で処理するときだけTRUEとなる
  299. BOOL appendMode = FALSE;
  300. /* エラー発生 */
  301. void syntaxError()
  302. {
  303. commonPrint(NULL, "Syntax Error in %d\x07\n", currentLineNumber );
  304. bForceToReturnSuper = TRUE;
  305. requestNextAction = REQUEST_INTERACTIVE;
  306. }
  307. void divideByZero()
  308. {
  309. commonPrint(NULL, "Divide by 0 in %d\x07\n", currentLineNumber );
  310. bForceToReturnSuper = TRUE;
  311. requestNextAction = REQUEST_INTERACTIVE;
  312. }
  313. void outOfArraySubscription()
  314. {
  315. commonPrint(NULL, "Out of Array Subscription in %d\x07\n", currentLineNumber );
  316. bForceToReturnSuper = TRUE;
  317. requestNextAction = REQUEST_INTERACTIVE;
  318. }
  319. void lineNumberNotFound( WORD lineNumber )
  320. {
  321. commonPrint(NULL, "Line Number %d not Found in %d\x07\n", lineNumber, currentLineNumber );
  322. bForceToReturnSuper = TRUE;
  323. requestNextAction = REQUEST_INTERACTIVE;
  324. }
  325. void stackOverflow()
  326. {
  327. commonPrint(NULL, "Stack Overflow in %d\x07\n", currentLineNumber );
  328. bForceToReturnSuper = TRUE;
  329. requestNextAction = REQUEST_INTERACTIVE;
  330. }
  331. void stackUnderflow()
  332. {
  333. commonPrint(NULL, "Stack Underflow in %d\x07\n", currentLineNumber );
  334. bForceToReturnSuper = TRUE;
  335. requestNextAction = REQUEST_INTERACTIVE;
  336. }
  337. void nextWithoutFor()
  338. {
  339. commonPrint(NULL, "Next without For in %d\x07\n", currentLineNumber );
  340. bForceToReturnSuper = TRUE;
  341. requestNextAction = REQUEST_INTERACTIVE;
  342. }
  343. void outOfMemory()
  344. {
  345. commonPrint(NULL, "Out of memory in %d\x07\n", currentLineNumber );
  346. bForceToReturnSuper = TRUE;
  347. requestNextAction = REQUEST_INTERACTIVE;
  348. }
  349. void loadError()
  350. {
  351. commonPrint(NULL, "File Not Found or Load Error in %d\x07\n", currentLineNumber );
  352. bForceToReturnSuper = TRUE;
  353. requestNextAction = REQUEST_INTERACTIVE;
  354. }
  355. void cantContinue()
  356. {
  357. commonPrint(NULL, "Can't Continue in %d\x07\n", currentLineNumber );
  358. bForceToReturnSuper = TRUE;
  359. requestNextAction = REQUEST_INTERACTIVE;
  360. }
  361. void saveError()
  362. {
  363. commonPrint(NULL, "Save Erroor in %d\x07\n", currentLineNumber );
  364. bForceToReturnSuper = TRUE;
  365. requestNextAction = REQUEST_INTERACTIVE;
  366. }
  367. void paramError()
  368. {
  369. commonPrint(NULL, "Parameter Erroor in %d\x07\n", currentLineNumber );
  370. bForceToReturnSuper = TRUE;
  371. requestNextAction = REQUEST_INTERACTIVE;
  372. }
  373. /* ユーティリティ関数達 */
  374. void mymemmove( BYTE * dst, const BYTE * src, WORD len )
  375. {
  376. WORD i;
  377. if( dst < src ) {
  378. for( i=0; i<len; i++ ) {
  379. *dst++ = *src++;
  380. }
  381. } else {
  382. dst += len;
  383. src += len;
  384. for( i=0; i<len; i++ ) {
  385. *--dst = *--src;
  386. }
  387. }
  388. }
  389. BYTE * skipToEOL( BYTE * p )
  390. {
  391. while( TRUE ) {
  392. if( *p == EOL ) return p;
  393. switch( *p++ ) {
  394. case 0x01: /* 次にあるのは10進2バイト整数 */
  395. case 0x02: /* 次にあるのは16進2バイト整数 */
  396. p += 2;
  397. break;
  398. case 0x03: /* 次にあるのは可変長文字列 0x00でターミネート */
  399. {
  400. while( TRUE ) {
  401. if( *p++ == '\0' ) break;
  402. }
  403. }
  404. break;
  405. }
  406. }
  407. }
  408. BYTE * skipToNextLine( BYTE * p )
  409. {
  410. return skipToEOL( p+4 ); // +4は行番号2バイト行長さ2バイト
  411. }
  412. #if 1
  413. #define mytolower(ch) ((ch >= 'A' && ch <= 'Z')? ch - 'A' + 'a' : ch)
  414. #else
  415. BYTE mytolower( BYTE ch )
  416. {
  417. if( ch >= 'A' && ch <= 'Z' ) {
  418. return ch - 'A' + 'a';
  419. }
  420. return ch;
  421. }
  422. #endif
  423. /* シフトJISの1バイト目かどうか判断。マクロなので副作用に注意 */
  424. #define IsDBCSLeadByte(ch) ((ch >= 0x81 && ch <= 0x9f) || (ch >= 0xe0 && ch <= 0xfc))
  425. /* 実行時情報のクリア (contできなくなる) */
  426. void clearRuntimeInfo()
  427. {
  428. memset( globalVariables, 0, sizeof(globalVariables) );
  429. memset( topLevelVariables, 0, sizeof(topLevelVariables) );
  430. memset( stacks, 0, sizeof(globalVariables) );
  431. executionPointer = NULL;
  432. resumePointer = NULL;
  433. currentLineNumber = 0;
  434. localVariables = topLevelVariables;
  435. stackPointer = 0;
  436. srand(0);
  437. }
  438. /* 行頭の行番号の、実行時の定型処理 */
  439. void processLineHeader()
  440. {
  441. if( !bInteractive ) {
  442. currentLineNumber = *((WORD *)executionPointer);
  443. executionPointer += 4; // +4は行番号2バイト行長さ2バイト
  444. } else {
  445. currentLineNumber = 0;
  446. }
  447. }
  448. /* 行番号処理 */
  449. BYTE * getLineReferenceFromLineNumber( WORD lineNumber )
  450. {
  451. BYTE * p;
  452. WORD t;
  453. p = wa;
  454. while( TRUE ) {
  455. t = *((WORD *)p);
  456. if( t == 0 ) {
  457. return NULL;
  458. }
  459. if( lineNumber == t ) {
  460. return p;
  461. }
  462. p += *((WORD *)(p+2));
  463. }
  464. }
  465. BYTE * getInsertionPointFromLineNumber( WORD lineNumber )
  466. {
  467. BYTE * p;
  468. WORD t;
  469. p = wa;
  470. while( TRUE ) {
  471. t = *((WORD *)p);
  472. if( t == 0 ) {
  473. return p;
  474. }
  475. if( lineNumber <= t ) {
  476. return p;
  477. }
  478. p += *((WORD *)(p+2));
  479. }
  480. }
  481. /* 配列管理 */
  482. int availableArrayItems()
  483. {
  484. return (WORKAREA_SIZE-dataTop) >> 1;
  485. }
  486. SHORT * derefArrayItem( int index )
  487. {
  488. if( index < 0 || index >= availableArrayItems() ) {
  489. outOfArraySubscription();
  490. return NULL; /* そのインデックスは使えません */
  491. }
  492. return (SHORT*)(&wa[dataTop+index*2]);
  493. }
  494. /* 物理テキストの管理 */
  495. #define SCREEN_SIZE_X (224/8)
  496. #define SCREEN_SIZE_Y (144/8)
  497. WORD screen[SCREEN_SIZE_X][SCREEN_SIZE_Y];
  498. SHORT xCursor, yCursor;
  499. #define TABSTOP 8
  500. void ptextScrollUp()
  501. {
  502. int x, y;
  503. for( y=0; y<SCREEN_SIZE_Y-1; y++ ) {
  504. for( x=0; x<SCREEN_SIZE_X; x++ ) {
  505. screen[x][y] = screen[x][y+1];
  506. }
  507. }
  508. for( x=0; x<SCREEN_SIZE_X; x++ ) {
  509. screen[x][SCREEN_SIZE_Y-1] = ' ';
  510. }
  511. for( y=0; y<SCREEN_SIZE_Y; y++ ) {
  512. for( x=0; x<SCREEN_SIZE_X; x++ ) {
  513. #ifdef WIN32
  514. drawChar( x, y, screen[x][y] );
  515. #endif
  516. #ifdef WW
  517. text_put_char( x, y, screen[x][y] );
  518. #endif
  519. }
  520. }
  521. }
  522. void ptextNewline()
  523. {
  524. xCursor = 0;
  525. yCursor++;
  526. if( yCursor >= SCREEN_SIZE_Y ) {
  527. ptextScrollUp();
  528. yCursor = SCREEN_SIZE_Y-1;
  529. }
  530. }
  531. void ptextTab()
  532. {
  533. if( xCursor+TABSTOP >= SCREEN_SIZE_X ) {
  534. ptextNewline();
  535. return;
  536. }
  537. xCursor = (xCursor+TABSTOP) / TABSTOP * TABSTOP;
  538. }
  539. void ptextString( const BYTE FAR * msg )
  540. {
  541. while( TRUE ) {
  542. WORD ch;
  543. if( *msg == '\0' ) break;
  544. if( IsDBCSLeadByte(*msg) ) {
  545. ch = (msg[0] << 8) + msg[1];
  546. msg+=2;
  547. } else {
  548. ch = msg[0];
  549. msg++;
  550. }
  551. screen[xCursor][yCursor] = ch;
  552. #ifdef WIN32
  553. drawChar( xCursor, yCursor, ch );
  554. #endif
  555. #ifdef WW
  556. text_put_char( xCursor, yCursor, ch );
  557. #endif
  558. xCursor++;
  559. if( xCursor >= SCREEN_SIZE_X ) {
  560. xCursor = 0;
  561. yCursor++;
  562. if( yCursor >= SCREEN_SIZE_Y ) {
  563. ptextScrollUp();
  564. yCursor = SCREEN_SIZE_Y-1;
  565. }
  566. }
  567. }
  568. }
  569. void ptextLocate( int x, int y )
  570. {
  571. if( x < 0 ) x = 0;
  572. if( x >= SCREEN_SIZE_X ) x = SCREEN_SIZE_X-1;
  573. if( y < 0 ) y = 0;
  574. if( y >= SCREEN_SIZE_Y ) y = SCREEN_SIZE_Y-1;
  575. xCursor = x;
  576. yCursor = y;
  577. }
  578. void ptextCLS()
  579. {
  580. int x,y;
  581. xCursor = 0;
  582. yCursor = 0;
  583. #ifdef WIN32
  584. clearText();
  585. #endif
  586. #ifdef WW
  587. for( y=0; y<SCREEN_SIZE_Y; y++ ) {
  588. text_fill_char(0, y, SCREEN_SIZE_X, ' ' );
  589. }
  590. #endif
  591. for( y=0; y<SCREEN_SIZE_Y; y++ ) {
  592. for( x=0; x<SCREEN_SIZE_X; x++ ) {
  593. screen[x][y] = ' ';
  594. }
  595. }
  596. }
  597. /* 中間コードからソーステキストに戻しながら出力(listとsaveで使う) */
  598. BOOL sourceDump( FILE FAR * fp, WORD from, WORD to )
  599. {
  600. BYTE * p;
  601. BOOL b;
  602. p = getInsertionPointFromLineNumber( from );
  603. while( TRUE ) {
  604. WORD lineNumber;
  605. lineNumber = *((WORD*)p);
  606. if( lineNumber == 0 ) break;
  607. if( lineNumber > to ) break;
  608. p += 4;
  609. b = commonPrint(fp,"%d",lineNumber);
  610. if( b == FALSE ) return FALSE;
  611. while( TRUE ) {
  612. if( *p == EOL ) {
  613. p++;
  614. break;
  615. }
  616. if( *p == 0x01 ) {
  617. WORD n;
  618. p++;
  619. n = *((WORD*)p);
  620. p += 2;
  621. b = commonPrint(fp,"%d",n);
  622. if( b == FALSE ) return FALSE;
  623. } else if( *p == 0x02 ) {
  624. WORD n;
  625. p++;
  626. n = *((WORD*)p);
  627. p += 2;
  628. b = commonPrint(fp,"0x%x",n);
  629. if( b == FALSE ) return FALSE;
  630. } else if( *p == 0x03 ) {
  631. p++;
  632. b = commonPrint(fp,"\"%s\"",p);
  633. if( b == FALSE ) return FALSE;
  634. p += strlen(p)+1;
  635. } else if( *p == '\'' ) { /* コメントのあとはそのまま行末まで転送 */
  636. while( TRUE ) {
  637. if( *p == EOL ) break;
  638. b = commonPrint(fp,"%c",*p);
  639. if( b == FALSE ) return FALSE;
  640. p++;
  641. }
  642. } else if( *p >= 0x80 ) {
  643. int i;
  644. BOOL found;
  645. found = FALSE;
  646. for( i=0; i<26; i++ ) {
  647. KEYWORDITEM * k;
  648. if( found ) break;
  649. k = keywordsIndex[i];
  650. if( k == NULL ) continue;
  651. while( TRUE ) {
  652. if( k->id == 0 ) break;
  653. if( k->id == *p ) {
  654. b = commonPrint(fp, k->name );
  655. if( b == FALSE ) return FALSE;
  656. p++;
  657. if( k->id == KEYWORD_REM ) { /* コメントのあとはそのまま行末まで転送 */
  658. while( TRUE ) {
  659. if( *p == EOL ) break;
  660. b = commonPrint(fp,"%c",*p);
  661. if( b == FALSE ) return FALSE;
  662. p++;
  663. }
  664. }
  665. found = TRUE;
  666. break;
  667. }
  668. k++;
  669. }
  670. }
  671. if( !found ) {
  672. b = commonPrint(fp,"[?%x?]", *p );
  673. if( b == FALSE ) return FALSE;
  674. p++;
  675. }
  676. } else {
  677. b = commonPrint(fp,"%c",*p);
  678. if( b == FALSE ) return FALSE;
  679. p++;
  680. }
  681. }
  682. b = commonPrint(fp,"\n");
  683. if( b == FALSE ) return FALSE;
  684. }
  685. return TRUE;
  686. }
  687. /* 式計算機能 */
  688. SHORT expr(); /* forward decl */
  689. SHORT * getArrayReference()
  690. {
  691. BYTE ch;
  692. int index;
  693. SHORT * pvar;
  694. while( TRUE ) {
  695. ch = *executionPointer++;
  696. if( ch != ' ' && ch != '\t' ) break;
  697. }
  698. if( ch != '(' && ch != '[' ) {
  699. syntaxError();
  700. return NULL;
  701. }
  702. index = expr();
  703. if( bForceToReturnSuper ) return NULL;
  704. pvar = derefArrayItem( index );
  705. if( pvar == NULL ) return NULL;
  706. while( TRUE ) {
  707. ch = *executionPointer++;
  708. if( ch != ' ' && ch != '\t' ) break;
  709. }
  710. if( ch != ')' && ch != ']' ) {
  711. syntaxError();
  712. return NULL;
  713. }
  714. return pvar;
  715. }
  716. SHORT calcValue()
  717. {
  718. BYTE ch;
  719. while( TRUE ) {
  720. ch = *executionPointer++;
  721. if( ch != ' ' && ch != '\t' ) break;
  722. }
  723. if( ch >= 'A' && ch <= 'Z' ) {
  724. return globalVariables[ch-'A'];
  725. }
  726. if( ch >= 'a' && ch <= 'z' ) {
  727. return localVariables[ch-'a'];
  728. }
  729. if( ch == '@' ) {
  730. SHORT * pvar;
  731. pvar = getArrayReference();
  732. if( pvar == NULL ) return -1;
  733. return *pvar;
  734. }
  735. switch( ch ) {
  736. case 0x01: /* 次にあるのは10進2バイト整数 */
  737. case 0x02: /* 次にあるのは16進2バイト整数 */
  738. {
  739. SHORT t;
  740. t = *((SHORT *)executionPointer);
  741. executionPointer += 2;
  742. return t;
  743. }
  744. case '(':
  745. {
  746. SHORT t;
  747. t = expr();
  748. while( TRUE ) {
  749. ch = *executionPointer++;
  750. if( ch != ' ' && ch != '\t' ) break;
  751. }
  752. if( ch != ')' ) {
  753. syntaxError();
  754. return -1;
  755. }
  756. return t;
  757. }
  758. case '-':
  759. return -calcValue();
  760. case KEYWORD_NOT:
  761. return ~calcValue();
  762. case KEYWORD_SCAN:
  763. #ifdef WW
  764. return key_press_check();
  765. #else
  766. return win32_scan();
  767. #endif
  768. case KEYWORD_WAIT:
  769. #ifdef WW
  770. return key_wait();
  771. #else
  772. return win32_wait();
  773. #endif
  774. case KEYWORD_RND:
  775. {
  776. SHORT t;
  777. t = calcValue();
  778. return rand() % t;
  779. }
  780. case KEYWORD_ABS:
  781. {
  782. SHORT t;
  783. t = calcValue();
  784. if( t < 0 ) return -t;
  785. return t;
  786. }
  787. case KEYWORD_TICK:
  788. #ifdef WW
  789. return sys_get_tick_count();
  790. #else
  791. return win32_get_tick_count();
  792. #endif
  793. case KEYWORD_SCAN_A:
  794. return 4;
  795. case KEYWORD_SCAN_B:
  796. return 8;
  797. case KEYWORD_SCAN_X1:
  798. return 16;
  799. case KEYWORD_SCAN_X2:
  800. return 32;
  801. case KEYWORD_SCAN_X3:
  802. return 64;
  803. case KEYWORD_SCAN_X4:
  804. return 128;
  805. case KEYWORD_SCAN_Y1:
  806. return 256;
  807. case KEYWORD_SCAN_Y2:
  808. return 512;
  809. case KEYWORD_SCAN_Y3:
  810. return 1024;
  811. case KEYWORD_SCAN_Y4:
  812. return 2048;
  813. }
  814. syntaxError();
  815. return -1;
  816. }
  817. SHORT expr4th()
  818. {
  819. SHORT acc;
  820. acc = calcValue();
  821. if( bForceToReturnSuper ) return -1;
  822. while( TRUE ) {
  823. BYTE ch;
  824. while( TRUE ) {
  825. ch = *executionPointer++;
  826. if( ch != ' ' && ch != '\t' ) break;
  827. }
  828. switch( ch ) {
  829. case '*':
  830. acc = acc * calcValue();
  831. break;
  832. case '/':
  833. {
  834. SHORT t;
  835. t = calcValue();
  836. if( t == 0 ) {
  837. divideByZero();
  838. } else {
  839. acc = acc / t;
  840. }
  841. }
  842. break;
  843. default:
  844. executionPointer--; /* unget it */
  845. return acc;
  846. }
  847. if( bForceToReturnSuper ) return -1;
  848. }
  849. }
  850. SHORT expr3nd()
  851. {
  852. SHORT acc;
  853. acc = expr4th();
  854. if( bForceToReturnSuper ) return -1;
  855. while( TRUE ) {
  856. BYTE ch;
  857. while( TRUE ) {
  858. ch = *executionPointer++;
  859. if( ch != ' ' && ch != '\t' ) break;
  860. }
  861. switch( ch ) {
  862. case '+':
  863. acc = acc + expr4th();
  864. break;
  865. case '-':
  866. acc = acc - expr4th();
  867. break;
  868. default:
  869. executionPointer--; /* unget it */
  870. return acc;
  871. }
  872. if( bForceToReturnSuper ) return -1;
  873. }
  874. }
  875. SHORT expr2nd()
  876. {
  877. SHORT acc;
  878. acc = expr3nd();
  879. if( bForceToReturnSuper ) return -1;
  880. while( TRUE ) {
  881. BYTE ch;
  882. while( TRUE ) {
  883. ch = *executionPointer++;
  884. if( ch != ' ' && ch != '\t' ) break;
  885. }
  886. switch( ch ) {
  887. case '>':
  888. {
  889. BYTE ch2;
  890. while( TRUE ) {
  891. ch2 = *executionPointer++;
  892. if( ch2 != ' ' && ch2 != '\t' ) break;
  893. }
  894. if( ch2 == '=' ) {
  895. acc = (acc >= expr3nd());
  896. if( acc != 0 ) acc = -1;
  897. } else {
  898. executionPointer--;
  899. acc = (acc > expr3nd());
  900. if( acc != 0 ) acc = -1;
  901. }
  902. }
  903. break;
  904. case '<':
  905. {
  906. BYTE ch2;
  907. while( TRUE ) {
  908. ch2 = *executionPointer++;
  909. if( ch2 != ' ' && ch2 != '\t' ) break;
  910. }
  911. if( ch2 == '=' ) {
  912. acc = (acc <= expr3nd());
  913. if( acc != 0 ) acc = -1;
  914. } else if( ch2 == '>' ) {
  915. acc = (acc != expr3nd());
  916. if( acc != 0 ) acc = -1;
  917. } else {
  918. executionPointer--;
  919. acc = (acc < expr3nd());
  920. if( acc != 0 ) acc = -1;
  921. }
  922. }
  923. break;
  924. case '=':
  925. acc = (acc == expr3nd());
  926. if( acc != 0 ) acc = -1;
  927. break;
  928. default:
  929. executionPointer--; /* unget it */
  930. return acc;
  931. }
  932. if( bForceToReturnSuper ) return -1;
  933. }
  934. }
  935. SHORT expr()
  936. {
  937. SHORT acc;
  938. acc = expr2nd();
  939. if( bForceToReturnSuper ) return -1;
  940. while( TRUE ) {
  941. BYTE ch;
  942. while( TRUE ) {
  943. ch = *executionPointer++;
  944. if( ch != ' ' && ch != '\t' ) break;
  945. }
  946. switch( ch ) {
  947. case KEYWORD_AND:
  948. acc = acc & expr2nd();
  949. break;
  950. case KEYWORD_OR:
  951. acc = acc | expr2nd();
  952. break;
  953. case KEYWORD_XOR:
  954. acc = acc ^ expr2nd();
  955. break;
  956. default:
  957. executionPointer--; /* unget it */
  958. return acc;
  959. }
  960. if( bForceToReturnSuper ) return -1;
  961. }
  962. }
  963. /* 各ステートメント実行処理メイン */
  964. void st_assignment( SHORT * pvar ) /* 代入ステートメントだけ例外的に処理する */
  965. {
  966. BYTE ch;
  967. SHORT val;
  968. while( TRUE ) {
  969. ch = *executionPointer++;
  970. if( ch != ' ' && ch != '\t' ) break;
  971. }
  972. if( ch != '=' ) {
  973. syntaxError();
  974. return;
  975. }
  976. val = expr();
  977. if( bForceToReturnSuper ) return;
  978. *pvar = val;
  979. }
  980. void st_if()
  981. {
  982. SHORT val;
  983. BYTE ch;
  984. val = expr();
  985. if( bForceToReturnSuper ) return;
  986. while( TRUE ) {
  987. ch = *executionPointer++;
  988. if( ch != ' ' && ch != '\t' ) break;
  989. }
  990. if( ch != KEYWORD_THEN ) {
  991. syntaxError();
  992. return;
  993. }
  994. if( val != 0 ) {
  995. return; /* thenの次から継続実行する */
  996. }
  997. /* 条件不成立につき、行末まで読み飛ばす */
  998. executionPointer = skipToEOL( executionPointer );
  999. }
  1000. void printOrDebug( BOOL bPrint )
  1001. {
  1002. WORD lastChar;
  1003. BYTE ch;
  1004. lastChar = '\0';
  1005. while( TRUE ) {
  1006. while( TRUE ) {
  1007. ch = *executionPointer++;
  1008. if( ch != ' ' && ch != '\t' ) break;
  1009. }
  1010. if( ch == EOL || ch == ':' || ch == '\'' ) {
  1011. executionPointer--; /* unget it */
  1012. break;
  1013. }
  1014. lastChar = ch;
  1015. switch( ch ) {
  1016. case 0x03:
  1017. if( bPrint ) {
  1018. ptextString( executionPointer );
  1019. } else {
  1020. commonPrint( NULL, executionPointer );
  1021. }
  1022. while( TRUE ) {
  1023. ch = *executionPointer++;
  1024. if( ch == '\0' ) break;
  1025. }
  1026. break;
  1027. case ';':
  1028. break;
  1029. case ',':
  1030. if( bPrint ) {
  1031. ptextTab();
  1032. } else {
  1033. commonPrint( NULL, "\t" );
  1034. }
  1035. break;
  1036. case KEYWORD_CHR:
  1037. {
  1038. WORD val;
  1039. #ifdef WW
  1040. static
  1041. #endif
  1042. BYTE str[3];
  1043. val = expr();
  1044. if( bForceToReturnSuper ) return;
  1045. if( val >= 0x100 ) {
  1046. str[0] = (val >> 8);
  1047. str[1] = (val & 0xff);
  1048. str[2] = '\0';
  1049. } else {
  1050. str[0] = (BYTE)val;
  1051. str[1] = '\0';
  1052. }
  1053. if( bPrint ) {
  1054. ptextString( str );
  1055. } else {
  1056. commonPrint( NULL, str );
  1057. }
  1058. }
  1059. break;
  1060. default:
  1061. {
  1062. SHORT val;
  1063. #ifdef WW
  1064. static
  1065. #endif
  1066. BYTE str[10];
  1067. executionPointer--; /* unget it */
  1068. val = expr();
  1069. if( bForceToReturnSuper ) return;
  1070. sprintf( str, "%d", val );
  1071. if( bPrint ) {
  1072. ptextString( str );
  1073. } else {
  1074. commonPrint( NULL, str );
  1075. }
  1076. }
  1077. break;
  1078. }
  1079. }
  1080. if( lastChar != ';' && lastChar != ',' ) {
  1081. if( bPrint ) {
  1082. ptextNewline();
  1083. } else {
  1084. commonPrint( NULL, "\r\n" );
  1085. }
  1086. }
  1087. }
  1088. void st_print()
  1089. {
  1090. printOrDebug( TRUE );
  1091. }
  1092. void st_debug()
  1093. {
  1094. printOrDebug( FALSE );
  1095. }
  1096. void st_locate()
  1097. {
  1098. SHORT x, y;
  1099. BYTE ch;
  1100. x = expr();
  1101. if( bForceToReturnSuper ) return;
  1102. while( TRUE ) {
  1103. ch = *executionPointer++;
  1104. if( ch != ' ' && ch != '\t' ) break;
  1105. }
  1106. if( ch != ',' ) {
  1107. syntaxError();
  1108. return;
  1109. }
  1110. y = expr();
  1111. if( bForceToReturnSuper ) return;
  1112. ptextLocate( x, y );
  1113. }
  1114. void st_cls()
  1115. {
  1116. ptextCLS();
  1117. }
  1118. void st_goto()
  1119. {
  1120. SHORT val;
  1121. BYTE * t;
  1122. val = expr();
  1123. if( bForceToReturnSuper ) return;
  1124. t = getLineReferenceFromLineNumber( val );
  1125. if( t == NULL ) {
  1126. lineNumberNotFound( val );
  1127. return;
  1128. }
  1129. executionPointer = t;
  1130. bInteractive = FALSE;
  1131. processLineHeader();
  1132. }
  1133. void st_gosub()
  1134. {
  1135. SHORT val;
  1136. BYTE * t;
  1137. val = expr();
  1138. if( bForceToReturnSuper ) return;
  1139. t = getLineReferenceFromLineNumber( val );
  1140. if( t == NULL ) {
  1141. lineNumberNotFound( val );
  1142. return;
  1143. }
  1144. if( stackPointer+1 >= STACK_MAX ) {
  1145. stackOverflow();
  1146. return;
  1147. }
  1148. stacks[stackPointer].type = STACK_TYPE_GOSUB;
  1149. stacks[stackPointer].returnPointer = executionPointer;
  1150. stacks[stackPointer].lastLocalVariables = localVariables;
  1151. localVariables = stacks[stackPointer].simpleVariables;
  1152. stackPointer++;
  1153. executionPointer = t;
  1154. bInteractive = FALSE;
  1155. processLineHeader();
  1156. }
  1157. void st_return()
  1158. {
  1159. while( TRUE ) {
  1160. if( stackPointer == 0 ) {
  1161. stackUnderflow();
  1162. return;
  1163. }
  1164. stackPointer--;
  1165. if( stacks[stackPointer].type == STACK_TYPE_GOSUB ) break;
  1166. }
  1167. executionPointer = stacks[stackPointer].returnPointer;
  1168. if( executionPointer >= waCoockedLine && executionPointer < waCoockedLine+LINE_SIZE ) {
  1169. bInteractive = TRUE;
  1170. }
  1171. localVariables = stacks[stackPointer].lastLocalVariables;
  1172. }
  1173. void st_for()
  1174. {
  1175. BYTE ch;
  1176. SHORT from, to, step;
  1177. SHORT * pvar;
  1178. while( TRUE ) {
  1179. ch = *executionPointer++;
  1180. if( ch != ' ' && ch != '\t' ) break;
  1181. }
  1182. if( ch == '@' ) { /* is it l-value? */
  1183. pvar = getArrayReference();
  1184. if( pvar == NULL ) return;
  1185. } else if( ch >= 'A' && ch <= 'Z' ) {
  1186. pvar = &globalVariables[ch-'A'];
  1187. } else if( ch >= 'a' && ch <= 'z' ) {
  1188. pvar = &localVariables[ch-'a'];
  1189. } else {
  1190. syntaxError();
  1191. return;
  1192. }
  1193. while( TRUE ) {
  1194. ch = *executionPointer++;
  1195. if( ch != ' ' && ch != '\t' ) break;
  1196. }
  1197. if( ch != '=' ) {
  1198. syntaxError();
  1199. return;
  1200. }
  1201. from = expr();
  1202. if( bForceToReturnSuper ) return;
  1203. while( TRUE ) {
  1204. ch = *executionPointer++;
  1205. if( ch != ' ' && ch != '\t' ) break;
  1206. }
  1207. if( ch != KEYWORD_TO ) {
  1208. syntaxError();
  1209. return;
  1210. }
  1211. to = expr();
  1212. if( bForceToReturnSuper ) return;
  1213. while( TRUE ) {
  1214. ch = *executionPointer++;
  1215. if( ch != ' ' && ch != '\t' ) break;
  1216. }
  1217. if( ch == KEYWORD_STEP ) {
  1218. step = expr();
  1219. if( bForceToReturnSuper ) return;
  1220. } else {
  1221. step = 1;
  1222. executionPointer--; /* unget it */
  1223. }
  1224. if( stackPointer+1 >= STACK_MAX ) {
  1225. stackOverflow();
  1226. return;
  1227. }
  1228. stacks[stackPointer].type = STACK_TYPE_FOR;
  1229. stacks[stackPointer].returnPointer = executionPointer;
  1230. *pvar = from;
  1231. stacks[stackPointer].pvar = pvar;
  1232. stacks[stackPointer].limit = to;
  1233. stacks[stackPointer].step = step;
  1234. stackPointer++;
  1235. }
  1236. void st_next()
  1237. {
  1238. if( stackPointer == 0 ) {
  1239. nextWithoutFor();
  1240. return;
  1241. }
  1242. if( stacks[stackPointer-1].type != STACK_TYPE_FOR ) {
  1243. nextWithoutFor();
  1244. return;
  1245. }
  1246. if( stacks[stackPointer-1].limit == *(stacks[stackPointer-1].pvar) ) {
  1247. /* loop done */
  1248. stackPointer--;
  1249. return;
  1250. }
  1251. /* count step and loop again */
  1252. *(stacks[stackPointer-1].pvar) += stacks[stackPointer-1].step;
  1253. /* counter overflow? */
  1254. if( stacks[stackPointer-1].step > 0 ) {
  1255. if( stacks[stackPointer-1].limit < *(stacks[stackPointer-1].pvar) ) {
  1256. /* loop done */
  1257. stackPointer--;
  1258. return;
  1259. }
  1260. } else {
  1261. if( stacks[stackPointer-1].limit > *(stacks[stackPointer-1].pvar) ) {
  1262. /* loop done */
  1263. stackPointer--;
  1264. return;
  1265. }
  1266. }
  1267. executionPointer = stacks[stackPointer-1].returnPointer;
  1268. }
  1269. /* endステートメント: 正常な終了 */
  1270. void st_end()
  1271. {
  1272. bForceToReturnSuper = TRUE;
  1273. requestNextAction = REQUEST_INTERACTIVE;
  1274. }
  1275. /* breakステートメント: デバッグ用の中断 */
  1276. void st_break()
  1277. {
  1278. commonPrint(NULL, "Break in %d\x07\n", currentLineNumber);
  1279. bForceToReturnSuper = TRUE;
  1280. requestNextAction = REQUEST_INTERACTIVE;
  1281. resumePointer = executionPointer; /* contする場所はbreakの次。breakのみの例外処理 */
  1282. }
  1283. void st_rem()
  1284. {
  1285. executionPointer = skipToEOL( executionPointer );
  1286. }
  1287. void st_new()
  1288. {
  1289. bForceToReturnSuper = TRUE;
  1290. requestNextAction = REQUEST_NEW;
  1291. }
  1292. void st_list()
  1293. {
  1294. WORD from, to;
  1295. BYTE ch;
  1296. while( TRUE ) {
  1297. ch = *executionPointer++;
  1298. if( ch != ' ' && ch != '\t' ) break;
  1299. }
  1300. if( ch == ':' || ch == EOL || ch == '\'' ) {
  1301. executionPointer--; /* unget */
  1302. from = 1;
  1303. to = 32767;
  1304. } else {
  1305. if( ch == 0x01 ) {
  1306. from = *((WORD*)executionPointer);
  1307. executionPointer += 2;
  1308. while( TRUE ) {
  1309. ch = *executionPointer++;
  1310. if( ch != ' ' && ch != '\t' ) break;
  1311. }
  1312. } else {
  1313. from = 1;
  1314. }
  1315. if( ch != '-' ) {
  1316. executionPointer--; /* unget */
  1317. to = from;
  1318. } else {
  1319. while( TRUE ) {
  1320. ch = *executionPointer++;
  1321. if( ch != ' ' && ch != '\t' ) break;
  1322. }
  1323. if( ch == 0x01 ) {
  1324. to = *((WORD*)executionPointer);
  1325. executionPointer += 2;
  1326. } else {
  1327. executionPointer--; /* unget */
  1328. to = 32767;
  1329. }
  1330. }
  1331. }
  1332. sourceDump( NULL, from, to ); /* リスト出力の本体を呼ぶ */
  1333. }
  1334. void st_run()
  1335. {
  1336. BYTE ch;
  1337. while( TRUE ) {
  1338. ch = *executionPointer++;
  1339. if( ch != ' ' && ch != '\t' ) break;
  1340. }
  1341. if( ch == ':' || ch == EOL || ch == '\'' ) {
  1342. bForceToReturnSuper = TRUE;
  1343. requestNextAction = REQUEST_RUN_LINENUMBER;
  1344. runLineNumber = 0;
  1345. } else if( ch == 0x03 ) {
  1346. strcpy( waRawLine, executionPointer );
  1347. bForceToReturnSuper = TRUE;
  1348. requestNextAction = REQUEST_RUN_FILE;
  1349. } else {
  1350. SHORT val;
  1351. executionPointer--; /* unget it */
  1352. val = expr();
  1353. if( bForceToReturnSuper ) return;
  1354. bForceToReturnSuper = TRUE;
  1355. requestNextAction = REQUEST_RUN_LINENUMBER;
  1356. runLineNumber = val;
  1357. }
  1358. }
  1359. void st_cont()
  1360. {
  1361. if( resumePointer == NULL ) {
  1362. cantContinue();
  1363. return;
  1364. }
  1365. executionPointer = resumePointer;
  1366. bInteractive = FALSE;
  1367. }
  1368. void st_save()
  1369. {
  1370. BYTE ch;
  1371. BOOL b;
  1372. FILE FAR * fp;
  1373. while( TRUE ) {
  1374. ch = *executionPointer++;
  1375. if( ch != ' ' && ch != '\t' ) break;
  1376. }
  1377. if( ch != 0x03 ) {
  1378. syntaxError();
  1379. return;
  1380. }
  1381. fp = fopen( executionPointer, "w" );
  1382. if( fp == NULL ) {
  1383. saveError();
  1384. return;
  1385. }
  1386. b = sourceDump( fp, 1, 32767 );
  1387. fclose( fp );
  1388. if( b == FALSE ) {
  1389. saveError();
  1390. remove( executionPointer );
  1391. return;
  1392. }
  1393. executionPointer += strlen(executionPointer)+1;
  1394. }
  1395. void st_load()
  1396. {
  1397. BYTE ch;
  1398. while( TRUE ) {
  1399. ch = *executionPointer++;
  1400. if( ch != ' ' && ch != '\t' ) break;
  1401. }
  1402. if( ch == 0x03 ) {
  1403. strcpy( waRawLine, executionPointer );
  1404. bForceToReturnSuper = TRUE;
  1405. requestNextAction = REQUEST_LOAD_FILE;
  1406. } else {
  1407. syntaxError();
  1408. return;
  1409. }
  1410. }
  1411. void st_merge()
  1412. {
  1413. BYTE ch;
  1414. while( TRUE ) {
  1415. ch = *executionPointer++;
  1416. if( ch != ' ' && ch != '\t' ) break;
  1417. }
  1418. if( ch == 0x03 ) {
  1419. strcpy( waRawLine, executionPointer );
  1420. bForceToReturnSuper = TRUE;
  1421. requestNextAction = REQUEST_MERGE_FILE;
  1422. } else {
  1423. syntaxError();
  1424. return;
  1425. }
  1426. }
  1427. void st_randomize()
  1428. {
  1429. SHORT val;
  1430. val = expr();
  1431. srand( val );
  1432. }
  1433. void st_exit()
  1434. {
  1435. bForceToReturnSuper = TRUE;
  1436. requestNextAction = REQUEST_EXIT_SYSTEM;
  1437. }
  1438. void st_waitvb()
  1439. {
  1440. SHORT val;
  1441. val = expr();
  1442. if( bForceToReturnSuper ) return;
  1443. if( val < 0 || val > 750 ) {
  1444. paramError();
  1445. return;
  1446. }
  1447. #ifdef WW
  1448. sys_wait( val );
  1449. #endif
  1450. #ifdef WIN32
  1451. win32_sys_wait( val );
  1452. #endif
  1453. }
  1454. void st_files()
  1455. {
  1456. #ifdef WIN32
  1457. commonPrint( NULL, "files statement not implemented in Win32\x07\n" );
  1458. #endif
  1459. #ifdef WW
  1460. int i;
  1461. struct stat statbuf;
  1462. int nent;
  1463. /*chdir("/rom0");*/
  1464. nent = nument(NULL);
  1465. for (i = 0; i < nent; i++) {
  1466. int result = getent(NULL, i, &statbuf);
  1467. if (result == E_FS_SUCCESS) {
  1468. if (statbuf.count != -1) {
  1469. /* Freya OSのバグ? 回避コード */
  1470. int p, q;
  1471. p = 0;
  1472. q = 0;
  1473. waRawLine[p++] = '"';
  1474. while( TRUE ) {
  1475. if( statbuf.name[q] == '\0' ) break;
  1476. waRawLine[p++] = statbuf.name[q++];
  1477. }
  1478. waRawLine[p++] = '"';
  1479. waRawLine[p++] = ',';
  1480. q = 0;
  1481. while( TRUE ) {
  1482. if( statbuf.info[q] == '\0' ) break;
  1483. waRawLine[p++] = statbuf.info[q++];
  1484. }
  1485. waRawLine[p++] = '\0';
  1486. commonPrint( NULL, "%s,%ld,%d\n", waRawLine, statbuf.len, statbuf.count );
  1487. }
  1488. } else {
  1489. commonPrint( NULL, "*File Access Error\x07\n" );
  1490. }
  1491. }
  1492. #endif
  1493. }
  1494. /* 行エディタ */
  1495. void editLine()
  1496. {
  1497. WORD wishLineNumber;
  1498. BYTE ch, * p, * target;
  1499. WORD lineNumber;
  1500. // プログラム領域に行を格納する場合は
  1501. // 先頭に2バイトの行番号と2バイトの行長さの情報が格納される
  1502. // 一方、中間言語翻訳の結果は先頭に0x01で始まる10進整数が行番号として入っている
  1503. // このギャップを転送時に解消しなければならない
  1504. // ここに来ているということは、waCoockedLine[0]が0x01つまり10進整数である //
  1505. assert( waCoockedLine[0] == 0x01 );
  1506. wishLineNumber = *((WORD*)&waCoockedLine[1]);
  1507. p = waCoockedLine+3;
  1508. //target = getLineReferenceFromLineNumber( wishLineNumber );
  1509. target = getInsertionPointFromLineNumber( wishLineNumber );
  1510. lineNumber = *((WORD*)target);
  1511. while( TRUE ) {
  1512. ch = *p++;
  1513. if( ch != ' ' && ch != '\t' ) break;
  1514. }
  1515. if( ch == EOL ) {
  1516. WORD delta;
  1517. BYTE * from;
  1518. /* removing the line */
  1519. if( lineNumber == 0 || lineNumber != wishLineNumber ) {
  1520. lineNumberNotFound( wishLineNumber );
  1521. return;
  1522. }
  1523. from = skipToNextLine(target);
  1524. delta = from-target;
  1525. MEMMOVE( target, from, (WORD)(dataTop-(from-wa)) );
  1526. dataTop -= delta;
  1527. } else {
  1528. WORD len; // プログラム領域上に収めるときのサイズ
  1529. len = skipToEOL(p)-waCoockedLine-1+2+1; //-1は0x01の分。+2は長さ情報。+1はEOL
  1530. if( lineNumber == 0 || lineNumber != wishLineNumber ) {
  1531. /* insert new line */
  1532. if( dataTop + len >= WORKAREA_SIZE ) {
  1533. outOfMemory();
  1534. return;
  1535. }
  1536. MEMMOVE( target+len, target, (WORD)(dataTop-(target-wa)) );
  1537. dataTop += len;
  1538. } else {
  1539. /* replace line */
  1540. WORD lost;
  1541. BYTE * nextline;
  1542. int delta;
  1543. nextline = skipToNextLine(target)+1;
  1544. lost = nextline-target;
  1545. delta = len-lost;
  1546. if( dataTop + delta >= WORKAREA_SIZE ) {
  1547. outOfMemory();
  1548. return;
  1549. }
  1550. MEMMOVE( nextline+delta, nextline, (WORD)(dataTop-(nextline-wa)) );
  1551. dataTop += delta;
  1552. }
  1553. // まず行番号をコピーする
  1554. *((WORD*)target) = *((WORD*)&waCoockedLine[1]);
  1555. // 行の長さを収める
  1556. *((WORD*)(target+2)) = len;
  1557. // 残りをコピーする
  1558. MEMMOVE( target+4, waCoockedLine+3, (WORD)(len-4) );
  1559. }
  1560. }
  1561. /* 追加専門の行エディタ */
  1562. void appendLine()
  1563. {
  1564. BYTE * target;
  1565. WORD len; // プログラム領域上に収めるときのサイズ
  1566. len = skipToEOL(waCoockedLine+3)-waCoockedLine-1+2+1; //-1は0x01の分。+2は長さ情報。+1はEOL
  1567. if( dataTop + len >= WORKAREA_SIZE ) {
  1568. outOfMemory();
  1569. return;
  1570. }
  1571. target = &wa[dataTop-5]; // -5 is len of last-line-marker
  1572. // まず行番号をコピーする
  1573. *((WORD*)target) = *((WORD*)&waCoockedLine[1]);
  1574. // 行の長さを収める
  1575. *((WORD*)(target+2)) = len;
  1576. // 残りをコピーする
  1577. MEMMOVE( target+4, waCoockedLine+3, (WORD)(len-4) );
  1578. dataTop += len;
  1579. wa[dataTop-5] = 0;
  1580. wa[dataTop-4] = 0;
  1581. wa[dataTop-3] = 0;
  1582. wa[dataTop-2] = 0;
  1583. wa[dataTop-1] = EOL;
  1584. }
  1585. /* 中間言語に翻訳する */
  1586. BOOL convertInternalCode( BYTE * waCoockedLine, const BYTE * waRawLine )
  1587. {
  1588. const BYTE * src = waRawLine;
  1589. BYTE * dst = waCoockedLine;
  1590. while( TRUE ) {
  1591. if( *src == '\0' ) break;
  1592. if( *src == '\n' ) break;
  1593. if( *src == '\r' ) break;
  1594. if( *src == ' ' || *src == '\t' ) {
  1595. *dst++ = *src++;
  1596. } else if( *src < 0x20 ) {
  1597. syntaxError();
  1598. return FALSE;
  1599. } else if( *src >= '0' && *src <= '9' ) {
  1600. if( *src == '0' && *(src+1) == 'x' ) {
  1601. WORD acc;
  1602. /* 16進のとき */
  1603. *dst++ = 0x02;
  1604. acc = 0;
  1605. src += 2;
  1606. while( TRUE ) {
  1607. if( *src >= '0' && *src <= '9' ) {
  1608. acc *= 16;
  1609. acc += *src - '0';
  1610. } else if( *src >= 'a' && *src <= 'f' ) {
  1611. acc *= 16;
  1612. acc += *src - 'a' + 10;
  1613. } else if( *src >= 'A' && *src <= 'F' ) {
  1614. acc *= 16;
  1615. acc += *src - 'A' + 10;
  1616. } else {
  1617. break;
  1618. }
  1619. src++;
  1620. }
  1621. *((WORD*)dst) = acc;
  1622. dst += 2;
  1623. } else {
  1624. SHORT acc;
  1625. /* 10進のとき */
  1626. *dst++ = 0x01;
  1627. acc = *src-'0';
  1628. src++;
  1629. while( TRUE ) {
  1630. if( *src < '0' || *src > '9' ) break;
  1631. acc *= 10;
  1632. acc += *src - '0';
  1633. src++;
  1634. if( acc < 0 ) { /* overflow case */
  1635. syntaxError();
  1636. return FALSE;
  1637. }
  1638. }
  1639. *((SHORT*)dst) = acc;
  1640. dst += 2;
  1641. }
  1642. #if 0
  1643. /* 以下のコードは、2項演算子の-を負数と解釈することがあるので使えない */
  1644. } else if( *src == '-' && (*(src+1) >= '0' && *(src+1) <= '9' ) ) {
  1645. WORD acc;
  1646. /* 負数の10進のとき */
  1647. *dst++ = 0x01;
  1648. src++;
  1649. acc = *src-'0';
  1650. src++;
  1651. while( TRUE ) {
  1652. if( *src < '0' || *src > '9' ) break;
  1653. acc *= 10;
  1654. acc += *src - '0';
  1655. src++;
  1656. if( acc > 32768 ) { /* overflow case */
  1657. syntaxError();
  1658. return FALSE;
  1659. }
  1660. }
  1661. *((SHORT*)dst) = -((SHORT)acc);
  1662. dst += 2;
  1663. #endif
  1664. } else if( (*src >= 'a' && *src <= 'z') || (*src >= 'A' && *src <= 'Z') ) {
  1665. BYTE next = *(src+1);
  1666. if( (next >= 'a' && next <= 'z') || (next >= 'A' && next <= 'Z') ) {
  1667. WORD id;
  1668. KEYWORDITEM * p = keywordsIndex[mytolower(*src)-'a'];
  1669. if( p == NULL ) {
  1670. syntaxError();
  1671. return FALSE;
  1672. }
  1673. id = 0;
  1674. while( TRUE ) {
  1675. const BYTE * ps, * pd;
  1676. if( p->id == 0 ) {
  1677. syntaxError();
  1678. return FALSE;
  1679. }
  1680. ps = src;
  1681. pd = p->name;
  1682. while( TRUE ) {
  1683. if( *pd == '\0' ) {
  1684. id = p->id;
  1685. src = ps;
  1686. break;
  1687. }
  1688. if( mytolower(*ps) != mytolower(*pd) ) break;
  1689. ps++;
  1690. pd++;
  1691. }
  1692. if( id != 0 ) break;
  1693. p++;
  1694. }
  1695. *dst++ = (BYTE)id;
  1696. if( id == KEYWORD_REM ) {
  1697. /* コメント文の場合は行末まで何もかもそのままコピーする */
  1698. while( TRUE ) {
  1699. if( *src == '\0' ) break;
  1700. *dst++ = *src++;
  1701. }
  1702. }
  1703. } else {
  1704. *dst++ = *src++;
  1705. }
  1706. } else if( *src == '\'' ) {
  1707. *dst++ = *src++;
  1708. /* コメント文の場合は行末まで何もかもそのままコピーする */
  1709. while( TRUE ) {
  1710. if( *src == '\0' ) break;
  1711. *dst++ = *src++;
  1712. }
  1713. } else if( *src == '"' ) {
  1714. src++;
  1715. *dst++ = 0x03;
  1716. while( TRUE ) {
  1717. if( *src == '\0' ) {
  1718. syntaxError();
  1719. return FALSE;
  1720. }
  1721. if( *src == '"' ) break;
  1722. *dst++ = *src++;
  1723. }
  1724. *dst++ = '\0';
  1725. src++;
  1726. } else {
  1727. *dst++ = *src++;
  1728. }
  1729. }
  1730. *dst = EOL;
  1731. return TRUE;
  1732. }
  1733. /* ステートメント実行処理関数のリスト */
  1734. NEARPROC statements[KEYWORDS_STATEMENT_TO-KEYWORDS_STATEMENT_FROM+1] = {
  1735. st_if,
  1736. st_print,
  1737. st_locate,
  1738. st_cls,
  1739. st_goto,
  1740. st_gosub,
  1741. st_return,
  1742. st_for,
  1743. st_next,
  1744. st_end,
  1745. st_break,
  1746. st_rem,
  1747. st_new,
  1748. st_list,
  1749. st_run,
  1750. st_cont,
  1751. st_save,
  1752. st_load,
  1753. st_merge,
  1754. st_randomize,
  1755. st_exit,
  1756. st_debug,
  1757. st_waitvb,
  1758. st_files
  1759. };
  1760. void interpreterMain()
  1761. {
  1762. WORD keyscan;
  1763. while( TRUE ) {
  1764. /* 行の開始 */
  1765. processLineHeader();
  1766. /* 最後に達してしまった? */
  1767. if( !bInteractive && currentLineNumber == 0 ) {
  1768. bForceToReturnSuper = TRUE;
  1769. requestNextAction = REQUEST_INTERACTIVE;
  1770. return;
  1771. }
  1772. while( TRUE ) {
  1773. BYTE ch;
  1774. if( !bInteractive ) {
  1775. resumePointer = executionPointer; /* contする場所を記憶する */
  1776. }
  1777. #ifdef WW
  1778. keyscan = key_press_check();
  1779. #else
  1780. keyscan = win32_scan();
  1781. #endif
  1782. if( keyscan & 0x02 ) {
  1783. st_break();
  1784. return;
  1785. }
  1786. ch = *executionPointer++;
  1787. if( ch == EOL ) break;
  1788. if( ch == ' ' || ch == '\t' || ch == ':' ) {
  1789. /* nop */
  1790. } else if( ch == '\'' ) { /* comment */
  1791. st_rem();
  1792. } else if( ch == '@' ) { /* is it l-value? */
  1793. SHORT * pvar;
  1794. pvar = getArrayReference();
  1795. if( pvar == NULL ) return;
  1796. st_assignment( pvar );
  1797. } else if( ch >= 'A' && ch <= 'Z' ) {
  1798. st_assignment( &globalVariables[ch-'A'] );
  1799. } else if( ch >= 'a' && ch <= 'z' ) {
  1800. st_assignment( &localVariables[ch-'a'] );
  1801. } else if( ch >= KEYWORDS_STATEMENT_FROM && ch <= KEYWORDS_STATEMENT_TO ) {
  1802. (*(statements[ch-KEYWORDS_STATEMENT_FROM]))();
  1803. } else {
  1804. syntaxError();
  1805. }
  1806. if( bForceToReturnSuper ) return;
  1807. }
  1808. if( bInteractive ) return;
  1809. }
  1810. }
  1811. void interactiveMain( FILE FAR * fp )
  1812. {
  1813. if( fp == NULL ) {
  1814. commonPrint(NULL,"OK\n");
  1815. }
  1816. while( TRUE ) {
  1817. BOOL b;
  1818. if( fp == NULL ) {
  1819. consoleInput( waRawLine, LINE_SIZE );
  1820. } else {
  1821. char FAR * r;
  1822. r = fgets( waRawLine, LINE_SIZE, fp );
  1823. if( r == NULL ) break;
  1824. }
  1825. #ifdef WW
  1826. if( fp == NULL ) {
  1827. commonPrint( NULL, "\r\n" );
  1828. }
  1829. #endif
  1830. /* 中間言語に翻訳する */
  1831. b = convertInternalCode( waCoockedLine, waRawLine );
  1832. if( b == FALSE ) {
  1833. bForceToReturnSuper = FALSE;
  1834. continue;
  1835. }
  1836. /* 数値で開始されているか? */
  1837. if( waCoockedLine[0] == 0x01 ) {
  1838. /* 行エディタを呼び出す */
  1839. if( appendMode ) {
  1840. appendLine();
  1841. } else {
  1842. editLine();
  1843. }
  1844. if( fp == NULL ) {
  1845. clearRuntimeInfo();
  1846. }
  1847. } else {
  1848. /* その行を実行する */
  1849. executionPointer = waCoockedLine;
  1850. interpreterMain();
  1851. }
  1852. if( bForceToReturnSuper ) return;
  1853. }
  1854. }
  1855. /* プログラムの実行開始 */
  1856. void do_run( WORD runLineNumber )
  1857. {
  1858. BYTE * target;
  1859. if( runLineNumber == 0 ) {
  1860. target = &wa[codeTop];
  1861. } else {
  1862. target = getLineReferenceFromLineNumber( runLineNumber );
  1863. if( target == NULL ) {
  1864. lineNumberNotFound( runLineNumber );
  1865. return;
  1866. }
  1867. }
  1868. clearRuntimeInfo();
  1869. bInteractive = FALSE;
  1870. executionPointer = target;
  1871. }
  1872. void do_new()
  1873. {
  1874. clearRuntimeInfo();
  1875. bInteractive = TRUE;
  1876. codeTop = 0;
  1877. wa[0] = 0;
  1878. wa[1] = 0;
  1879. wa[2] = 0;
  1880. wa[3] = 0;
  1881. wa[4] = EOL;
  1882. dataTop = 5;
  1883. }
  1884. BOOL do_merge( const BYTE * filename )
  1885. {
  1886. FILE FAR * fp;
  1887. fp = fopen( filename, "r" );
  1888. if( fp == NULL ) {
  1889. loadError();
  1890. return FALSE;
  1891. }
  1892. interactiveMain( fp );
  1893. fclose( fp );
  1894. clearRuntimeInfo();
  1895. if( bForceToReturnSuper ) return FALSE;
  1896. return TRUE;
  1897. }
  1898. void superMain()
  1899. {
  1900. while( TRUE ) {
  1901. BOOL b;
  1902. bForceToReturnSuper = FALSE;
  1903. switch( requestNextAction ) {
  1904. case REQUEST_INTERACTIVE:
  1905. bInteractive = TRUE;
  1906. break;
  1907. case REQUEST_RUN_LINENUMBER:
  1908. do_run( runLineNumber );
  1909. break;
  1910. case REQUEST_RUN_FILE:
  1911. do_new();
  1912. appendMode=TRUE;
  1913. b = do_merge( waRawLine );
  1914. appendMode=FALSE;
  1915. if( b ) {
  1916. do_run( 0 );
  1917. }
  1918. break;
  1919. case REQUEST_LOAD_FILE:
  1920. do_new();
  1921. appendMode=TRUE;
  1922. do_merge( waRawLine );
  1923. appendMode=FALSE;
  1924. break;
  1925. case REQUEST_MERGE_FILE:
  1926. do_merge( waRawLine );
  1927. break;
  1928. case REQUEST_NEW:
  1929. do_new();
  1930. break;
  1931. case REQUEST_EXIT_SYSTEM:
  1932. return;
  1933. }
  1934. requestNextAction = REQUEST_NO_ACTION;
  1935. if( bInteractive ) {
  1936. if( runtimeOnly ) return; /* ランタイムモードのときは絶対にインタラクティブモードに行かない */
  1937. interactiveMain( NULL );
  1938. } else {
  1939. interpreterMain();
  1940. }
  1941. bForceToReturnSuper = FALSE;
  1942. }
  1943. }
  1944. #ifdef WW
  1945. BOOL entranceUI()
  1946. {
  1947. #define MAX_ENT 15
  1948. int i;
  1949. struct stat statbuf[MAX_ENT];
  1950. int nent;
  1951. int c, select;
  1952. ptextCLS();
  1953. ptextString( "ワンべぇ V" );
  1954. ptextString( myVersion );
  1955. ptextNewline();
  1956. ptextString( "↑↓Aでファイル選択 Y2で開発環境 STARTで中止" );
  1957. c = 0;
  1958. nent = nument(NULL);
  1959. for (i = 0; i < nent; i++) {
  1960. int result;
  1961. if( c >= MAX_ENT ) break;
  1962. result = getent(NULL, i, &statbuf[c]);
  1963. if (result == E_FS_SUCCESS) {
  1964. if (statbuf[c].count != -1) {
  1965. char FAR * p;
  1966. int l;
  1967. p = statbuf[c].name;
  1968. l = strlen(p);
  1969. if( l >= 3 ) {
  1970. if( p[l-3] == '.' && p[l-2] == 'w' && p[l-1] == 'b' ) {
  1971. ptextLocate(1,c+2);
  1972. ptextString( statbuf[c].info );
  1973. c++;
  1974. }
  1975. }
  1976. }
  1977. }
  1978. }
  1979. /* 選択の開始 */
  1980. select = 0;
  1981. while( TRUE ) {
  1982. int key;
  1983. for( i=0; i<c; i++ ) {
  1984. ptextLocate(0,i+2);
  1985. ptextString( " " );
  1986. }
  1987. if( c > 0 ) {
  1988. ptextLocate(0,select+2);
  1989. ptextString( "→" );
  1990. }
  1991. key = key_wait();
  1992. /* START button */
  1993. if( key & 0x02 ) return FALSE; /* 中止 */
  1994. /* B button */
  1995. if( key & 0x08 ) return FALSE; /* 中止 */
  1996. if( c > 0 ) {
  1997. /* A button */
  1998. if( key & 0x04 ) {
  1999. strcpy( waRawLine, statbuf[select].name );
  2000. requestNextAction = REQUEST_RUN_FILE;
  2001. runtimeOnly = TRUE;
  2002. return TRUE;
  2003. }
  2004. /* X1 or Y1 */
  2005. if( (key & 0x10) != 0 || (key & 0x100) != 0 ) {
  2006. select = select-1;
  2007. if( select < 0 ) {
  2008. select = c-1;
  2009. }
  2010. }
  2011. /* X3 or Y3 */
  2012. if( (key & 0x40) != 0 || (key & 0x400) != 0 ) {
  2013. select = select+1;
  2014. if( select >= c ) {
  2015. select = 0;
  2016. }
  2017. }
  2018. }
  2019. /* Y2 button */
  2020. if( (key & 0x200) != 0 ) {
  2021. return TRUE;
  2022. }
  2023. }
  2024. }
  2025. #endif
  2026. int main( int argc, char *argv[] )
  2027. {
  2028. #ifdef WW
  2029. BOOL b;
  2030. #endif
  2031. runtimeOnly = FALSE;
  2032. requestNextAction = REQUEST_NO_ACTION;
  2033. #ifdef WIN32
  2034. createText();
  2035. #endif
  2036. #ifdef WW
  2037. text_screen_init();
  2038. b = entranceUI();
  2039. if( b == FALSE ) return 0;
  2040. if( !runtimeOnly ) {
  2041. comm_set_baudrate(1);
  2042. comm_open();
  2043. }
  2044. #endif
  2045. ptextCLS();
  2046. if( requestNextAction == REQUEST_NO_ACTION ) {
  2047. do_new();
  2048. }
  2049. if( !runtimeOnly ) {
  2050. commonPrint(NULL,"ワンべぇ WonderWitch Tiny BASIC Environment Ver %s\n",myVersion);
  2051. commonPrint(NULL,"Copyright 2000 (c) by Pie Dey Co.,Ltd.\n");
  2052. }
  2053. superMain();
  2054. #ifdef WIN32
  2055. deleteText();
  2056. #endif
  2057. #ifdef WW
  2058. if( !runtimeOnly ) {
  2059. comm_close();
  2060. }
  2061. #endif
  2062. return 0;
  2063. }
  2064. /* end of wonbe.c */