wonbe.c 42 KB

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