A project to implement a console using the Mbed using VGA for video output and a PS/2 keyboard for the input. The eventual goal is to also include tools for managing SD cards, and a semi-self-hosting programming environment.
Dependencies: PS2_MbedConsole fastlib SDFileSystem vga640x480g_mbedconsole lightvm mbed
plEarlz.cpp
00001 /* 00002 <Copyright Header> 00003 Copyright (c) 2012 Jordan "Earlz" Earls <http://lastyearswishes.com> 00004 All rights reserved. 00005 00006 Redistribution and use in source and binary forms, with or without 00007 modification, are permitted provided that the following conditions 00008 are met: 00009 00010 1. Redistributions of source code must retain the above copyright 00011 notice, this list of conditions and the following disclaimer. 00012 2. Redistributions in binary form must reproduce the above copyright 00013 notice, this list of conditions and the following disclaimer in the 00014 documentation and/or other materials provided with the distribution. 00015 3. The name of the author may not be used to endorse or promote products 00016 derived from this software without specific prior written permission. 00017 00018 THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, 00019 INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY 00020 AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL 00021 THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 00022 EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 00023 PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; 00024 OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 00025 WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR 00026 OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF 00027 ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 00028 00029 This file is part of the MbedConsole project 00030 */ 00031 00032 #include "mbedconsole.h" 00033 #include "plEarlz.h" 00034 #include <stdarg.h> 00035 #include <stdint.h> 00036 //Basically a non-conforming take on Forth, btw. 00037 00038 inline int internal_captureline(void* pBuffer, char const* pFormatString, ...) 00039 { 00040 char* pStringEnd = (char*)pBuffer + strlen((char*)pBuffer); 00041 va_list valist; 00042 00043 va_start(valist, pFormatString); 00044 00045 return vsprintf(pStringEnd, pFormatString, valist); 00046 } 00047 void printheapstats() 00048 { 00049 char buffer[256]; 00050 __heapstats(internal_captureline, buffer); 00051 vputs("Memory info: "); 00052 vputs(buffer); 00053 } 00054 00055 00056 00057 00058 00059 BranchTarget *last_target=NULL; 00060 00061 ErrorType pl_error=None; 00062 00063 00064 enum WordType 00065 { 00066 Unknown, 00067 Number, 00068 Word, 00069 Quote 00070 }; 00071 00072 uint8_t *pl_codeblock; 00073 int pl_blockpos; 00074 int pl_blocksize; 00075 00076 uint8_t* push_opcode_byte(uint8_t val) 00077 { 00078 if(pl_blockpos>=pl_blocksize) 00079 { 00080 void* tmp=realloc(pl_codeblock, pl_blocksize+CODEBLOCKSTEP); 00081 if(tmp==NULL) 00082 { 00083 vputs("Out of memory!!"); 00084 return; 00085 } 00086 pl_codeblock=(uint8_t*)tmp; 00087 pl_blocksize+=CODEBLOCKSTEP; 00088 } 00089 pl_codeblock[pl_blockpos]=val; 00090 pl_blockpos++; 00091 return &pl_codeblock[pl_blockpos-1]; 00092 } 00093 Opcode* push_opcode(Opcode val) 00094 { 00095 if(pl_blockpos>=pl_blocksize) 00096 { 00097 void* tmp=realloc(pl_codeblock, pl_blocksize+CODEBLOCKSTEP); 00098 if(tmp==NULL) 00099 { 00100 vputs("Out of memory!!"); 00101 return; 00102 } 00103 pl_codeblock=(uint8_t*)tmp; 00104 pl_blocksize+=CODEBLOCKSTEP; 00105 } 00106 pl_codeblock[pl_blockpos]=(uint8_t)val; 00107 pl_blockpos++; 00108 return (Opcode*)&pl_codeblock[pl_blockpos-1]; 00109 } 00110 uint16_t* push_opcode_word(uint16_t val) 00111 { 00112 if(pl_blockpos>=pl_blocksize) 00113 { 00114 void* tmp=realloc(pl_codeblock, pl_blocksize+CODEBLOCKSTEP); 00115 if(tmp==NULL) 00116 { 00117 vputs("Out of memory!!"); 00118 return; 00119 } 00120 pl_codeblock=(uint8_t*)tmp; 00121 pl_blocksize+=CODEBLOCKSTEP; 00122 } 00123 *(uint16_t*)&pl_codeblock[pl_blockpos]=val; 00124 pl_blockpos+=2; 00125 return (uint16_t*)(&pl_codeblock[pl_blockpos-2]); 00126 } 00127 uint32_t* push_opcode_dword(uint32_t val) 00128 { 00129 if(pl_blockpos>=pl_blocksize) 00130 { 00131 void* tmp=realloc(pl_codeblock, pl_blocksize+CODEBLOCKSTEP); 00132 if(tmp==NULL) 00133 { 00134 vputs("Out of memory!!"); 00135 return; 00136 } 00137 pl_codeblock=(uint8_t*)tmp; 00138 pl_blocksize+=CODEBLOCKSTEP; 00139 } 00140 *(uint32_t*)&pl_codeblock[pl_blockpos]=val; 00141 pl_blockpos+=4; 00142 return (uint32_t*)&pl_codeblock[pl_blockpos-4]; 00143 } 00144 void new_codeblock(bool freeit) 00145 { 00146 if(freeit) 00147 { 00148 free(pl_codeblock); 00149 } 00150 pl_codeblock=(uint8_t*)malloc(CODEBLOCKSTEP); 00151 pl_blockpos=0; 00152 pl_blocksize=CODEBLOCKSTEP; 00153 last_target=NULL; 00154 } 00155 int execute_codeblock() 00156 { 00157 return forth_execute(pl_codeblock, pl_blockpos); 00158 } 00159 00160 00161 void push_target(int address) 00162 { 00163 BranchTarget* target=(BranchTarget*)malloc(sizeof(BranchTarget)); 00164 target->previous=last_target; 00165 target->target=address; 00166 last_target=target; 00167 } 00168 void pop_target() 00169 { 00170 if(last_target==NULL) 00171 { 00172 vputs("Unmatched control statement!\n"); 00173 return; 00174 } 00175 volatile void* tmp=last_target; 00176 last_target=last_target->previous; 00177 free((void*)tmp); 00178 } 00179 inline void write_blockword(int pos,uint16_t val) 00180 { 00181 *(uint16_t*)&pl_codeblock[pos]=val; 00182 } 00183 00184 int compile_word(char *word, WordType type) //returns 0 for success, 1 for ending word found, -1 for error 00185 { 00186 if(type==Number){ 00187 push_opcode(Push); 00188 push_opcode_dword(atoi(word)); 00189 }else{ 00190 if(word[1]==0) //check the quick builtins first 00191 { 00192 if(word[0]=='.'){ 00193 push_opcode(CallInt); 00194 push_opcode_dword((uint32_t)&bi_print); 00195 }else if(word[0]==';') 00196 { 00197 push_opcode(Ret); 00198 //execute! 00199 return 1; 00200 }else if(word[0]=='+'){ 00201 push_opcode(Add); 00202 }else if(word[0]=='/'){ 00203 push_opcode(Div); 00204 }else if(word[0]=='-'){ 00205 push_opcode(Sub); 00206 }else if(word[0]=='!'){ 00207 //pl_push(pl_pop()-pl_pop()); 00208 }else if(word[0]=='%'){ 00209 push_opcode(Mod); 00210 }else if(word[0]=='*'){ 00211 push_opcode(Mul); 00212 }else if(word[0]=='!'){ 00213 //push_opcode(Store); 00214 }else if(word[0]=='?'){ 00215 pl_push(*(int*)pl_pop()); 00216 }else if(word[0]=='='){ 00217 pl_push(pl_pop() == pl_pop()); 00218 }else if(word[0]=='`'){ 00219 pl_push(pl_pop()>0); 00220 }else if(word[0]=='$'){ 00221 //print string (address on stack 00222 }else if(word[0]=='['){ 00223 //begin quotation 00224 push_opcode(Push); 00225 push_opcode_word(pl_blockpos+3); 00226 push_opcode(Branch); 00227 push_target(pl_blockpos); 00228 push_opcode_word(0); 00229 }else if(word[0] == ']'){ 00230 //end quotation 00231 push_opcode(Ret); 00232 write_blockword(last_target->target, pl_blockpos); 00233 pop_target(); 00234 } 00235 }else if(strlcmp("if", word, 3)==0){ 00236 push_opcode(BranchFalse); 00237 push_target(pl_blockpos); 00238 push_opcode_word(0); 00239 }else if(strlcmp("else", word, 5)==0){ 00240 push_opcode(Branch); 00241 int tmp=pl_blockpos; 00242 push_opcode_word(0); 00243 write_blockword(last_target->target,pl_blockpos); 00244 pop_target(); 00245 push_target(tmp); //have to do it after we pop it or we fall into an infinite loop! 00246 }else if(strlcmp("end", word, 4)==0){ 00247 write_blockword(last_target->target,(uint16_t)pl_blockpos); 00248 pop_target(); 00249 }else if(strlcmp("tif", word, 4)==0){ 00250 /** 00251 swap value 2 behind stack to front 00252 call.true 1 from stack 00253 call.false top of stack 00254 _label: 00255 **/ 00256 //alloca(10); 00257 push_opcode(Push); 00258 push_opcode_dword(3); 00259 push_opcode(Pick); 00260 push_opcode(BranchFalse); 00261 //push_opcode_word(pl_blockpos+ 00262 00263 }else{ 00264 vputs("I don't know the word '"); 00265 vputs(word); 00266 vputs("'\n"); 00267 } 00268 } 00269 return 0; 00270 } 00271 00272 00273 00274 void parse_line(char *line) 00275 { 00276 int len=strlen(line); 00277 char word[16]; 00278 word[0]=0; 00279 int wordpos=0; 00280 WordType type=Unknown; 00281 for(int i=0;i<len;i++) 00282 { 00283 char c=line[i]; 00284 if(is_whitespace(c) || c=='\\') 00285 { 00286 if(word[0]!=0) 00287 { 00288 word[wordpos]=0; 00289 00290 int tmp=compile_word(word,type); 00291 if(tmp==1) 00292 { 00293 execute_codeblock(); 00294 new_codeblock(true); 00295 } 00296 word[0]=0; 00297 } 00298 wordpos=0; 00299 type=Unknown; 00300 if(c=='\\'){ 00301 return; //rest is a comment 00302 } 00303 }else if(is_numeric(c)){ 00304 if(type==Unknown){ 00305 type=Number; 00306 } 00307 word[wordpos]=c; 00308 wordpos++; 00309 }else if(is_quote(c)){ 00310 push_opcode(LoadStr); 00311 for(;i<len;i++) 00312 { 00313 //char c=line[ 00314 } 00315 vputs("This isn't supported yet foo!"); 00316 return; 00317 }else{ 00318 if(type==Number){ 00319 vputs("Syntax Error! Unexpected symbol in the middle of a number"); 00320 return; 00321 } 00322 type=Word; 00323 word[wordpos]=c; 00324 wordpos++; 00325 } 00326 } 00327 } 00328 00329 00330 void tester() 00331 { 00332 printf("foo!"); 00333 } 00334 00335 int pl_shell() 00336 { 00337 vputs(">>plEarlz -- A forth-ish shell<<\n"); 00338 printheapstats(); 00339 vputs("\n"); 00340 char *line=(char*)malloc(MAXLINELENGTH); 00341 sprintf(line, "Stack Size: %i; Max Recursion Level %i; Loaded WORDs: %i", MAXSTACK, MAXTEMPSTACK, 0); 00342 vputs(line); 00343 sprintf(line, "Max line length: %i\n", MAXLINELENGTH); 00344 vputs(line); 00345 new_codeblock(false); 00346 char *tmp=(char*)malloc(32); //for constructing words/elements 00347 while(1) 00348 { 00349 vputs("cmd> "); 00350 vgetsl(line, MAXLINELENGTH); 00351 line[MAXLINELENGTH-1]=0; 00352 int len=strlen(line); 00353 line[len]='\n'; 00354 line[len+1]=0; 00355 parse_line(line); 00356 00357 } 00358 free(line); 00359 free(tmp); 00360 return 0; 00361 } 00362 00363
Generated on Sun Jul 17 2022 09:10:09 by 1.7.2