├── .travis.yml ├── Makefile ├── PropellerCompiler ├── BlockNestStackRoutines.cpp ├── CompileDatBlocks.cpp ├── CompileExpression.cpp ├── CompileInstruction.cpp ├── CompileSpin.cpp ├── CompileSpin.h ├── CompileUtilities.cpp ├── CompileUtilities.h ├── DistillObjects.cpp ├── Elementizer.cpp ├── Elementizer.h ├── ErrorStrings.cpp ├── ErrorStrings.h ├── ExpressionResolver.cpp ├── InstructionBlockCompiler.cpp ├── Makefile ├── PropellerCompiler.cpp ├── PropellerCompiler.h ├── PropellerCompilerInternal.h ├── PropellerCompiler_vs2015.vcxproj ├── PropellerCompiler_vs2017.vcxproj ├── StringConstantRoutines.cpp ├── SymbolEngine.cpp ├── SymbolEngine.h ├── UnusedMethodUtils.cpp ├── UnusedMethodUtils.h ├── Utilities.cpp ├── Utilities.h ├── flexbuf.cpp ├── flexbuf.h ├── objectheap.cpp ├── objectheap.h ├── preprocess.cpp ├── preprocess.h ├── textconvert.cpp └── textconvert.h ├── PropellerCompiler_vs2015.sln ├── PropellerCompiler_vs2017.sln ├── README.md ├── SpinSource ├── SpinSource_vs2015.vcxproj ├── SpinSource_vs2017.vcxproj ├── openspin.cpp ├── pathentry.cpp └── pathentry.h ├── openspin_vs2015.sln └── openspin_vs2017.sln /.travis.yml: -------------------------------------------------------------------------------- 1 | language: c 2 | os: 3 | - linux 4 | - osx 5 | script: make 6 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | # cross compilation scheme taken from Eric Smith's spin2cpp compiler 2 | # if CROSS is defined, we are building a cross compiler 3 | # possible targets are: win32, rpi 4 | 5 | ifeq ($(CC),) 6 | CC=gcc 7 | endif 8 | 9 | ifeq ($(CXX),) 10 | CXX=g++ 11 | endif 12 | 13 | ifeq ($(CROSS),win32) 14 | CC=i686-w64-mingw32-gcc 15 | CXX=i686-w64-mingw32-g++ 16 | EXT=.exe 17 | BUILD=./build-win32 18 | else ifeq ($(CROSS),rpi) 19 | CC=arm-linux-gnueabihf-gcc 20 | CXX=arm-linux-gnueabihf-g++ 21 | EXT= 22 | BUILD=./build-rpi 23 | else 24 | EXT= 25 | BUILD=./build 26 | endif 27 | 28 | OS:=$(shell uname) 29 | 30 | ifeq ($(OS),Darwin) 31 | CFLAGS+=-Wall -g -Wno-self-assign 32 | else 33 | CFLAGS+=-Wall -g $(MSTATIC) 34 | endif 35 | 36 | CXXFLAGS += $(CFLAGS) 37 | 38 | TARGET=$(BUILD)/openspin$(EXT) 39 | SRCDIR=SpinSource 40 | OBJ=$(BUILD)/openspin.o \ 41 | $(BUILD)/pathentry.o 42 | 43 | LIBNAME=$(BUILD)/PropellerCompiler/libopenspin.a 44 | 45 | all: $(BUILD) $(LIBNAME) $(OBJ) Makefile 46 | $(CXX) -o $(TARGET) $(CXXFLAGS) $(OBJ) $(LIBNAME) 47 | 48 | $(BUILD)/%.o: $(SRCDIR)/%.cpp 49 | $(CXX) $(CXXFLAGS) -o $@ -c $< 50 | 51 | $(LIBNAME): $(BUILD) 52 | $(MAKE) -C PropellerCompiler CROSS=$(CROSS) BUILD=$(realpath $(BUILD))/PropellerCompiler all 53 | 54 | $(BUILD): 55 | mkdir -p $(BUILD) 56 | 57 | clean: 58 | rm -rf $(BUILD) 59 | make -C PropellerCompiler BUILD=$(realpath $(BUILD))/PropellerCompiler clean 60 | -------------------------------------------------------------------------------- /PropellerCompiler/BlockNestStackRoutines.cpp: -------------------------------------------------------------------------------- 1 | ////////////////////////////////////////////////////////////// 2 | // // 3 | // Propeller Spin/PASM Compiler // 4 | // (c)2012-2016 Parallax Inc. DBA Parallax Semiconductor. // 5 | // Adapted from Chip Gracey's x86 asm code by Roy Eltham // 6 | // See end of file for terms of use. // 7 | // // 8 | ////////////////////////////////////////////////////////////// 9 | // 10 | // BlockNestStackRoutines.cpp 11 | // 12 | 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include "Utilities.h" 18 | #include "PropellerCompilerInternal.h" 19 | #include "SymbolEngine.h" 20 | #include "Elementizer.h" 21 | #include "ErrorStrings.h" 22 | #include "CompileUtilities.h" 23 | 24 | // 25 | // Block Nest Routines 26 | // 27 | 28 | bool BlockNest_New(unsigned char type, int stackSize) 29 | { 30 | if (g_pCompilerData->bnest_ptr > block_nest_limit) 31 | { 32 | g_pCompilerData->error = true; 33 | g_pCompilerData->error_msg = g_pErrorStrings[error_loxnbe]; 34 | return false; 35 | } 36 | 37 | // set blockstack base 38 | g_pCompilerData->bnest_type[g_pCompilerData->bnest_ptr] = type; 39 | g_pCompilerData->bstack_base[g_pCompilerData->bnest_ptr++] = g_pCompilerData->bstack_ptr; 40 | 41 | // init bstack values to max forward 42 | for (int i = 0; i < stackSize; i++) 43 | { 44 | g_pCompilerData->bstack[g_pCompilerData->bstack_ptr + i] = 0x0000FFC0; 45 | } 46 | g_pCompilerData->bstack_ptr += stackSize; 47 | if (g_pCompilerData->bstack_ptr >= block_stack_limit) 48 | { 49 | g_pCompilerData->error = true; 50 | g_pCompilerData->error_msg = g_pErrorStrings[error_bnso]; 51 | return false; 52 | } 53 | 54 | return true; 55 | } 56 | 57 | void BlockNest_Redo(unsigned char type) 58 | { 59 | g_pCompilerData->bnest_type[g_pCompilerData->bnest_ptr - 1] = type; 60 | } 61 | 62 | void BlockNest_End() 63 | { 64 | g_pCompilerData->bnest_ptr--; 65 | g_pCompilerData->bstack_ptr = g_pCompilerData->bstack_base[g_pCompilerData->bnest_ptr]; 66 | } 67 | 68 | // 69 | // Block Stack Routines 70 | // 71 | 72 | void BlockStack_Write(int address, int value) 73 | { 74 | int stackAddress = g_pCompilerData->bstack_base[g_pCompilerData->bnest_ptr - 1] + address; 75 | g_pCompilerData->bstack[stackAddress] = value; 76 | } 77 | 78 | int BlockStack_Read(int address) 79 | { 80 | int stackAddress = g_pCompilerData->bstack_base[g_pCompilerData->bnest_ptr - 1] + address; 81 | return g_pCompilerData->bstack[stackAddress]; 82 | } 83 | 84 | bool BlockStack_CompileAddress(int address) 85 | { 86 | return CompileAddress(BlockStack_Read(address)); 87 | } 88 | 89 | bool BlockStack_CompileConstant() 90 | { 91 | int value = BlockStack_Read(0); 92 | 93 | if (value >= 0x100) 94 | { 95 | // two byte 96 | if (!EnterObj(0x39)) // 0x39 = 00111001b 97 | { 98 | return false; 99 | } 100 | if (!EnterObj((unsigned char)((value >> 8) & 0xFF))) 101 | { 102 | return false; 103 | } 104 | } 105 | else 106 | { 107 | // one byte 108 | if (!EnterObj(0x38)) // 0x38 = 00111000b 109 | { 110 | return false; 111 | } 112 | } 113 | 114 | return EnterObj((unsigned char)(value & 0xFF)); 115 | } 116 | 117 | /////////////////////////////////////////////////////////////////////////////////////////// 118 | // TERMS OF USE: MIT License // 119 | /////////////////////////////////////////////////////////////////////////////////////////// 120 | // Permission is hereby granted, free of charge, to any person obtaining a copy of this // 121 | // software and associated documentation files (the "Software"), to deal in the Software // 122 | // without restriction, including without limitation the rights to use, copy, modify, // 123 | // merge, publish, distribute, sublicense, and/or sell copies of the Software, and to // 124 | // permit persons to whom the Software is furnished to do so, subject to the following // 125 | // conditions: // 126 | // // 127 | // The above copyright notice and this permission notice shall be included in all copies // 128 | // or substantial portions of the Software. // 129 | // // 130 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, // 131 | // INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A // 132 | // PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT // 133 | // HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION // 134 | // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE // 135 | // SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. // 136 | /////////////////////////////////////////////////////////////////////////////////////////// 137 | -------------------------------------------------------------------------------- /PropellerCompiler/CompileInstruction.cpp: -------------------------------------------------------------------------------- 1 | ////////////////////////////////////////////////////////////// 2 | // // 3 | // Propeller Spin/PASM Compiler // 4 | // (c)2012-2016 Parallax Inc. DBA Parallax Semiconductor. // 5 | // Adapted from Chip Gracey's x86 asm code by Roy Eltham // 6 | // See end of file for terms of use. // 7 | // // 8 | ////////////////////////////////////////////////////////////// 9 | // 10 | // CompileInstruction.cpp 11 | // 12 | 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include "Utilities.h" 18 | #include "PropellerCompilerInternal.h" 19 | #include "SymbolEngine.h" 20 | #include "Elementizer.h" 21 | #include "ErrorStrings.h" 22 | #include "CompileUtilities.h" 23 | 24 | // these are in CompileExpression.cpp 25 | extern bool CompileTerm_Try(unsigned char anchor); 26 | extern bool CompileTerm_Sub(unsigned char anchor, int value); 27 | extern bool CompileTerm_ObjPub(unsigned char anchor, int value); 28 | extern bool CompileTerm_CogNew(int value); 29 | extern bool CompileTerm_Inst(int value); 30 | 31 | bool CompileInst_NextQuit(int value) 32 | { 33 | int blockNestPtr = g_pCompilerData->bnest_ptr; 34 | 35 | unsigned char byteCode = 0; 36 | int caseDepth = 0; 37 | 38 | // find repeat block 39 | for (;;) 40 | { 41 | if (blockNestPtr == 0) 42 | { 43 | g_pCompilerData->error = true; 44 | g_pCompilerData->error_msg = g_pErrorStrings[error_tioawarb]; 45 | return false; 46 | } 47 | 48 | unsigned char blockNestType = g_pCompilerData->bnest_type[blockNestPtr-1]; 49 | 50 | if (blockNestType == type_repeat) 51 | { 52 | byteCode = 0x04; // jmp 'quit' 53 | break; 54 | } 55 | else if (blockNestType == type_repeat_count) 56 | { 57 | byteCode = 0x0B; // jnz 'quit' 58 | break; 59 | } 60 | else if (blockNestType == type_if) 61 | { 62 | // ignore 'if' block nest(s) 63 | } 64 | else if (blockNestType == type_case) // allow nesting within 'case' block(s) 65 | { 66 | caseDepth += 8; // pop 2 longs for each nested 'case' 67 | } 68 | else 69 | { 70 | g_pCompilerData->error = true; 71 | g_pCompilerData->error_msg = g_pErrorStrings[error_internal]; 72 | return false; 73 | } 74 | blockNestPtr--; 75 | } 76 | 77 | if (caseDepth > 0) 78 | { 79 | if (!CompileConstant(caseDepth)) // enter pop count 80 | { 81 | return false; 82 | } 83 | if (!EnterObj(0x14)) // pop 84 | { 85 | return false; 86 | } 87 | } 88 | 89 | int blockStackPtr = g_pCompilerData->bstack_base[blockNestPtr - 1]; 90 | 91 | if ((value & 0xFF) == 0) 92 | { 93 | // next 94 | if (!EnterObj(0x04)) // jmp 'next' 95 | { 96 | return false; 97 | } 98 | return CompileAddress(g_pCompilerData->bstack[blockStackPtr]); 99 | } 100 | 101 | // quit 102 | if (!EnterObj(byteCode)) // jmp/jnz 'quit' 103 | { 104 | return false; 105 | } 106 | return CompileAddress(g_pCompilerData->bstack[blockStackPtr + 1]); 107 | } 108 | 109 | bool CompileInst_AbortReturn(int value) 110 | { 111 | // preview next element 112 | bool bEof = false; 113 | if (!g_pElementizer->GetNext(bEof)) 114 | { 115 | return false; 116 | } 117 | g_pElementizer->Backup(); 118 | 119 | if (g_pElementizer->GetType() != type_end) 120 | { 121 | // there's an expression, compile it 122 | if (!CompileExpression()) 123 | { 124 | return false; 125 | } 126 | value |= 0x01; // +value 127 | } 128 | return EnterObj((unsigned char)(value & 0xFF)); 129 | } 130 | 131 | bool CompileInst_Reboot() 132 | { 133 | if (!EnterObj(0x37)) // constant 0x80 134 | { 135 | return false; 136 | } 137 | if (!EnterObj(0x06)) 138 | { 139 | return false; 140 | } 141 | 142 | if (!EnterObj(0x35)) // constant 0 143 | { 144 | return false; 145 | } 146 | 147 | return EnterObj(0x20); // clkset 148 | } 149 | 150 | bool CompileInst_CogNew(int value) 151 | { 152 | return CompileTerm_CogNew(value ^ 0x04); // no push 153 | } 154 | 155 | bool CompileInst_CogInit(int value) 156 | { 157 | int savedSourcePtr = g_pElementizer->GetSourcePtr(); 158 | 159 | if (!g_pElementizer->GetElement(type_left)) 160 | { 161 | return false; 162 | } 163 | int cogidSourcePtr = g_pElementizer->GetSourcePtr(); 164 | if (!SkipExpression()) 165 | { 166 | return false; 167 | } 168 | if (!g_pElementizer->GetElement(type_comma)) 169 | { 170 | return false; 171 | } 172 | 173 | // check for subroutine 174 | bool bEof = false; 175 | if (!g_pElementizer->GetNext(bEof)) 176 | { 177 | return false; 178 | } 179 | if (g_pElementizer->GetType() != type_sub) 180 | { 181 | // not subroutine, so backup 182 | g_pElementizer->SetSourcePtr(savedSourcePtr); 183 | 184 | return CompileTerm_Inst(value); // compile assembly 'coginit' 185 | } 186 | 187 | // compile subroutine 'cognew' (push params+index) 188 | int subConstant = g_pElementizer->GetValue(); 189 | 190 | if (!g_pCompilerData->bFinalCompile && g_pCompilerData->bUnusedMethodElimination) 191 | { 192 | AddCogNewOrInit(g_pCompilerData->current_filename, subConstant & 0x000000FF); 193 | } 194 | 195 | if (!CompileParameters((g_pElementizer->GetValue() & 0x0000FF00) >> 8)) 196 | { 197 | return false; 198 | } 199 | if (!CompileConstant(subConstant)) 200 | { 201 | return false; 202 | } 203 | if (!g_pElementizer->GetElement(type_comma)) 204 | { 205 | return false; 206 | } 207 | if (!CompileExpression()) // compile stack expression 208 | { 209 | return false; 210 | } 211 | if (!g_pElementizer->GetElement(type_right)) 212 | { 213 | return false; 214 | } 215 | if (!EnterObj(0x15)) // run 216 | { 217 | return false; 218 | } 219 | 220 | // compile 'cogid' exp 221 | if (!CompileOutOfSequenceExpression(cogidSourcePtr)) 222 | { 223 | return false; 224 | } 225 | 226 | if (!EnterObj(0x3F)) // regop 227 | { 228 | return false; 229 | } 230 | if (!EnterObj(0x8F)) // read+dcurr 231 | { 232 | return false; 233 | } 234 | if (!EnterObj(0x37)) // constant mask 235 | { 236 | return false; 237 | } 238 | if (!EnterObj(0x61)) // -4 239 | { 240 | return false; 241 | } 242 | if (!EnterObj(0xD1)) // write long[base][index] 243 | { 244 | return false; 245 | } 246 | return EnterObj(0x2C); // coginit 247 | } 248 | 249 | bool CompileInst_InstCr(int value) 250 | { 251 | return CompileTerm_Inst(value ^ 0x04); // no push 252 | } 253 | 254 | bool CompileInst_Unary(int value) 255 | { 256 | return CompileVariable_PreSignExtendOrRandom((unsigned char)(0x40 | (value & 0xFF))); 257 | } 258 | 259 | bool CompileInst_Assign(unsigned char vOperator, unsigned char type, unsigned char size, int address, int indexSourcePtr) 260 | { 261 | if (!CompileExpression()) 262 | { 263 | return false; 264 | } 265 | 266 | return CompileVariable(1, vOperator, type, size, address, indexSourcePtr); 267 | } 268 | 269 | bool CompileInstruction() 270 | { 271 | int type = g_pElementizer->GetType(); 272 | int value = g_pElementizer->GetValue(); 273 | 274 | switch(type) 275 | { 276 | case type_back: 277 | return CompileTerm_Try(0x03); 278 | case type_sub: 279 | return CompileTerm_Sub(0x01, value); 280 | case type_obj: 281 | return CompileTerm_ObjPub(0x01, value); 282 | case type_i_next_quit: 283 | return CompileInst_NextQuit(value); 284 | case type_i_abort_return: 285 | return CompileInst_AbortReturn(value); 286 | case type_i_reboot: 287 | return CompileInst_Reboot(); 288 | case type_i_cognew: 289 | return CompileInst_CogNew(value); 290 | case type_i_coginit: 291 | return CompileInst_CogInit(value); 292 | case type_i_cr: // instruction can-return 293 | return CompileInst_InstCr(value); 294 | case type_i_nr: // instruction never-return 295 | return CompileTerm_Inst(value); 296 | 297 | case type_inc: // assign pre-inc ++var 298 | return CompileVariable_PreIncOrDec(0x20); 299 | case type_dec: // assign pre-dec --var 300 | return CompileVariable_PreIncOrDec(0x30); 301 | case type_til: // assign sign-extern byte ~var 302 | return CompileVariable_PreSignExtendOrRandom(0x10); 303 | case type_tiltil: // assign sign-extern word ~~var 304 | return CompileVariable_PreSignExtendOrRandom(0x14); 305 | case type_rnd: // assign random forward ?var 306 | return CompileVariable_PreSignExtendOrRandom(0x08); 307 | } 308 | 309 | g_pElementizer->SubToNeg(); 310 | if (g_pElementizer->GetType() == type_unary) 311 | { 312 | return CompileInst_Unary(g_pElementizer->GetOpType()); 313 | } 314 | 315 | unsigned char varType = 0; 316 | unsigned char varSize = 0; 317 | int varAddress = 0; 318 | int varIndexSourcePtr = 0; 319 | bool bVariable = false; 320 | if (!CheckVariable(bVariable, varType, varSize, varAddress, varIndexSourcePtr)) 321 | { 322 | return false; 323 | } 324 | if (!bVariable) 325 | { 326 | g_pCompilerData->error = true; 327 | g_pCompilerData->error_msg = g_pErrorStrings[error_eaiov]; 328 | return false; 329 | } 330 | 331 | // check for post-var modifier 332 | bool bEof = false; 333 | if (!g_pElementizer->GetNext(bEof)) 334 | { 335 | return false; 336 | } 337 | type = g_pElementizer->GetType(); 338 | switch (type) 339 | { 340 | case type_inc: // assign post-inc 341 | return CompileVariable_IncOrDec(0x28, varType, varSize, varAddress, varIndexSourcePtr); 342 | case type_dec: // assign post-dec 343 | return CompileVariable_IncOrDec(0x38, varType, varSize, varAddress, varIndexSourcePtr); 344 | case type_rnd: // assign random reverse 345 | return CompileVariable_Assign(0x0C, varType, varSize, varAddress, varIndexSourcePtr); 346 | case type_til: // assign post-clear 347 | return CompileVariable_Assign(0x18, varType, varSize, varAddress, varIndexSourcePtr); 348 | case type_tiltil: // assign post-set 349 | return CompileVariable_Assign(0x1C, varType, varSize, varAddress, varIndexSourcePtr); 350 | case type_assign: 351 | return CompileInst_Assign(0x1C, varType, varSize, varAddress, varIndexSourcePtr); 352 | } 353 | 354 | // var binaryop? 355 | if (type == type_binary) 356 | { 357 | unsigned char varOperator = 0x40; // assign math w/swapargs 358 | varOperator |= (unsigned char)(g_pElementizer->GetOpType()); 359 | 360 | // check for '=' after binary op 361 | if (!g_pElementizer->GetNext(bEof)) 362 | { 363 | return false; 364 | } 365 | if (g_pElementizer->GetType() == type_equal) 366 | { 367 | return CompileVariable_Expression(varOperator, varType, varSize, varAddress, varIndexSourcePtr); 368 | } 369 | else 370 | { 371 | g_pElementizer->Backup(); // not '=' so backup 372 | } 373 | } 374 | g_pElementizer->Backup(); // no post-var modifier, so backup 375 | 376 | // error, so backup and reget variable for error display 377 | g_pElementizer->Backup(); 378 | g_pElementizer->GetNext(bEof); // this won't fail here, because it already succeeded above 379 | 380 | g_pCompilerData->error = true; 381 | g_pCompilerData->error_msg = g_pErrorStrings[error_vnao]; 382 | return false; 383 | } 384 | 385 | /////////////////////////////////////////////////////////////////////////////////////////// 386 | // TERMS OF USE: MIT License // 387 | /////////////////////////////////////////////////////////////////////////////////////////// 388 | // Permission is hereby granted, free of charge, to any person obtaining a copy of this // 389 | // software and associated documentation files (the "Software"), to deal in the Software // 390 | // without restriction, including without limitation the rights to use, copy, modify, // 391 | // merge, publish, distribute, sublicense, and/or sell copies of the Software, and to // 392 | // permit persons to whom the Software is furnished to do so, subject to the following // 393 | // conditions: // 394 | // // 395 | // The above copyright notice and this permission notice shall be included in all copies // 396 | // or substantial portions of the Software. // 397 | // // 398 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, // 399 | // INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A // 400 | // PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT // 401 | // HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION // 402 | // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE // 403 | // SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. // 404 | /////////////////////////////////////////////////////////////////////////////////////////// 405 | -------------------------------------------------------------------------------- /PropellerCompiler/CompileSpin.h: -------------------------------------------------------------------------------- 1 | /////////////////////////////////////////////////////////////// 2 | // // 3 | // Propeller Spin/PASM Compiler Command Line Tool 'OpenSpin' // 4 | // (c)2012-2016 Parallax Inc. DBA Parallax Semiconductor. // 5 | // See end of file for terms of use. // 6 | // // 7 | /////////////////////////////////////////////////////////////// 8 | // 9 | // CompileSpin.h 10 | // 11 | #ifndef _COMPILESPIN_H_ 12 | #define _COMPILESPIN_H_ 13 | 14 | typedef char* (*LoadFileFunc)(const char* pFilename, int* pnLength, char** ppFilePath); 15 | typedef void (*FreeFileBufferFunc)(char* pBuffer); 16 | 17 | struct CompilerConfig 18 | { 19 | CompilerConfig() 20 | : bVerbose(false) 21 | , bQuiet(false) 22 | , bFileTreeOutputOnly(false) 23 | , bFileListOutputOnly(false) 24 | , bDumpSymbols(false) 25 | , bUsePreprocessor(true) 26 | , bAlternatePreprocessorMode(false) 27 | , bUnusedMethodElimination(false) 28 | , bDocMode(false) 29 | , bDATonly(false) 30 | , bBinary(true) 31 | , eeprom_size(32768) 32 | { 33 | } 34 | 35 | bool bVerbose; 36 | bool bQuiet; 37 | bool bFileTreeOutputOnly; 38 | bool bFileListOutputOnly; 39 | bool bDumpSymbols; 40 | bool bUsePreprocessor; 41 | bool bAlternatePreprocessorMode; 42 | bool bUnusedMethodElimination; 43 | bool bDocMode; 44 | bool bDATonly; 45 | bool bBinary; 46 | unsigned int eeprom_size; 47 | }; 48 | 49 | 50 | void InitCompiler(CompilerConfig* pCompilerConfig, LoadFileFunc pLoadFileFunc, FreeFileBufferFunc pFreeFileBufferFunc); 51 | void SetDefine(const char* pName, const char* pValue); 52 | unsigned char* CompileSpin(char* pFilename, int* pnResultLength); 53 | void ShutdownCompiler(); 54 | 55 | #endif // _COMPILESPIN_H_ 56 | 57 | /////////////////////////////////////////////////////////////////////////////////////////// 58 | // TERMS OF USE: MIT License // 59 | /////////////////////////////////////////////////////////////////////////////////////////// 60 | // Permission is hereby granted, free of charge, to any person obtaining a copy of this // 61 | // software and associated documentation files (the "Software"), to deal in the Software // 62 | // without restriction, including without limitation the rights to use, copy, modify, // 63 | // merge, publish, distribute, sublicense, and/or sell copies of the Software, and to // 64 | // permit persons to whom the Software is furnished to do so, subject to the following // 65 | // conditions: // 66 | // // 67 | // The above copyright notice and this permission notice shall be included in all copies // 68 | // or substantial portions of the Software. // 69 | // // 70 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, // 71 | // INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A // 72 | // PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT // 73 | // HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION // 74 | // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE // 75 | // SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. // 76 | /////////////////////////////////////////////////////////////////////////////////////////// 77 | -------------------------------------------------------------------------------- /PropellerCompiler/CompileUtilities.cpp: -------------------------------------------------------------------------------- 1 | ////////////////////////////////////////////////////////////// 2 | // // 3 | // Propeller Spin/PASM Compiler // 4 | // (c)2012-2016 Parallax Inc. DBA Parallax Semiconductor. // 5 | // Adapted from Chip Gracey's x86 asm code by Roy Eltham // 6 | // See end of file for terms of use. // 7 | // // 8 | ////////////////////////////////////////////////////////////// 9 | // 10 | // CompileUtilities.cpp 11 | // 12 | 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include "Utilities.h" 18 | #include "PropellerCompilerInternal.h" 19 | #include "SymbolEngine.h" 20 | #include "Elementizer.h" 21 | #include "ErrorStrings.h" 22 | #include "CompileUtilities.h" 23 | 24 | bool SkipBlock(int column) 25 | { 26 | int savedObjPtr = g_pCompilerData->obj_ptr; 27 | bool savedStringPatchEnable = g_pCompilerData->str_patch_enable; 28 | g_pCompilerData->str_patch_enable = false; 29 | if (!CompileBlock(column)) 30 | { 31 | return false; 32 | } 33 | g_pCompilerData->str_patch_enable = savedStringPatchEnable; 34 | g_pCompilerData->obj_ptr = savedObjPtr; 35 | return true; 36 | } 37 | 38 | bool SkipRange() 39 | { 40 | int savedObjPtr = g_pCompilerData->obj_ptr; 41 | bool savedStringPatchEnable = g_pCompilerData->str_patch_enable; 42 | g_pCompilerData->str_patch_enable = false; 43 | bool bRange; 44 | if (!CompileRange(bRange)) 45 | { 46 | return false; 47 | } 48 | g_pCompilerData->str_patch_enable = savedStringPatchEnable; 49 | g_pCompilerData->obj_ptr = savedObjPtr; 50 | return true; 51 | } 52 | 53 | bool SkipExpression() 54 | { 55 | int savedObjPtr = g_pCompilerData->obj_ptr; 56 | bool savedStringPatchEnable = g_pCompilerData->str_patch_enable; 57 | g_pCompilerData->str_patch_enable = false; 58 | if (!CompileExpression()) 59 | { 60 | return false; 61 | } 62 | g_pCompilerData->str_patch_enable = savedStringPatchEnable; 63 | g_pCompilerData->obj_ptr = savedObjPtr; 64 | return true; 65 | } 66 | 67 | bool CheckIndex(bool& bIndex, int& expSourcePtr) 68 | { 69 | bIndex = false; 70 | if (g_pElementizer->CheckElement(type_leftb)) 71 | { 72 | expSourcePtr = g_pElementizer->GetSourcePtr(); 73 | if (!SkipExpression()) 74 | { 75 | return false; 76 | } 77 | if (!g_pElementizer->GetElement(type_rightb)) 78 | { 79 | return false; 80 | } 81 | bIndex = true; 82 | } 83 | return true; 84 | } 85 | 86 | bool CheckIndexRange(bool& bIndex, int& expSourcePtr) 87 | { 88 | bIndex = false; 89 | if (g_pElementizer->CheckElement(type_leftb)) 90 | { 91 | expSourcePtr = g_pElementizer->GetSourcePtr(); 92 | if (!SkipExpression()) 93 | { 94 | return false; 95 | } 96 | if (g_pElementizer->CheckElement(type_dotdot)) 97 | { 98 | if (!SkipExpression()) 99 | { 100 | return false; 101 | } 102 | } 103 | if (!g_pElementizer->GetElement(type_rightb)) 104 | { 105 | return false; 106 | } 107 | bIndex = true; 108 | } 109 | return true; 110 | } 111 | 112 | bool CheckVariable_AddressExpression(int& expSourcePtr) 113 | { 114 | bool bIndex = false; 115 | if (!CheckIndex(bIndex, expSourcePtr)) 116 | { 117 | return false; 118 | } 119 | if (!bIndex) 120 | { 121 | g_pCompilerData->error = true; 122 | g_pCompilerData->error_msg = g_pErrorStrings[error_eleftb]; 123 | return false; 124 | } 125 | return true; 126 | } 127 | 128 | bool CheckVariable(bool& bVariable, unsigned char& type, unsigned char& size, int& address, int& indexSourcePtr) 129 | { 130 | address = g_pElementizer->GetValue(); 131 | indexSourcePtr = 0; 132 | 133 | unsigned char varType = (unsigned char)(g_pElementizer->GetType() & 0xFF); 134 | 135 | if (varType >= type_var_byte && varType <= type_var_long) 136 | { 137 | type = type_var_byte; 138 | // adjust address base on the var size 139 | if (varType < type_var_long) 140 | { 141 | address += g_pCompilerData->var_long; 142 | } 143 | if (varType == type_var_byte) 144 | { 145 | address += g_pCompilerData->var_word; 146 | } 147 | } 148 | else if (varType >= type_dat_byte && varType <= type_dat_long) 149 | { 150 | type = type_dat_byte; 151 | } 152 | else if (varType >= type_loc_byte && varType <= type_loc_long) 153 | { 154 | type = type_loc_byte; 155 | } 156 | else 157 | { 158 | type = varType; 159 | if (varType == type_size) 160 | { 161 | size = (unsigned char)(g_pElementizer->GetValue() & 0xFF); 162 | if (!CheckVariable_AddressExpression(address)) 163 | { 164 | return false; 165 | } 166 | bool bIndex = false; 167 | if (!CheckIndex(bIndex, indexSourcePtr)) 168 | { 169 | return false; 170 | } 171 | bVariable = true; 172 | return true; 173 | } 174 | else 175 | { 176 | size = 2; 177 | if (varType == type_spr) 178 | { 179 | if (!CheckVariable_AddressExpression(address)) 180 | { 181 | return false; 182 | } 183 | bVariable = true; 184 | return true; 185 | } 186 | else if (varType == type_reg) 187 | { 188 | bool bIndex = false; 189 | if (!CheckIndexRange(bIndex, indexSourcePtr)) 190 | { 191 | return false; 192 | } 193 | if (bIndex) 194 | { 195 | size = 3; 196 | } 197 | bVariable = true; 198 | return true; 199 | } 200 | else 201 | { 202 | bVariable = false; 203 | return true; 204 | } 205 | } 206 | } 207 | // if we got here then it's a var/dat/loc type 208 | // set size 209 | size = varType; 210 | size -= type; 211 | bool bIndex = false; 212 | if (!CheckIndex(bIndex, indexSourcePtr)) 213 | { 214 | return false; 215 | } 216 | if (!bIndex) 217 | { 218 | // check for .byte/word/long{[index]} 219 | if (g_pElementizer->CheckElement(type_dot)) 220 | { 221 | bool bEof = false; 222 | if (!g_pElementizer->GetNext(bEof)) // get byte/word/long 223 | { 224 | return false; 225 | } 226 | if (g_pElementizer->GetType() != type_size) 227 | { 228 | g_pCompilerData->error = true; 229 | g_pCompilerData->error_msg = g_pErrorStrings[error_ebwol]; 230 | return false; 231 | } 232 | if (size < (g_pElementizer->GetValue() & 0xFF)) // new size must be same or smaller 233 | { 234 | g_pCompilerData->error = true; 235 | g_pCompilerData->error_msg = g_pErrorStrings[error_sombs]; 236 | return false; 237 | } 238 | size = (g_pElementizer->GetValue() & 0xFF); // update size 239 | 240 | bool bIndexCheck = false; 241 | if (!CheckIndex(bIndexCheck, indexSourcePtr)) 242 | { 243 | return false; 244 | } 245 | } 246 | } 247 | bVariable = true; 248 | return true; 249 | } 250 | 251 | bool GetVariable(unsigned char& type, unsigned char& size, int& address, int& indexSourcePtr) 252 | { 253 | bool bEof = false; 254 | if (!g_pElementizer->GetNext(bEof)) 255 | { 256 | return false; 257 | } 258 | bool bVariable = false; 259 | if (!CheckVariable(bVariable, type, size, address, indexSourcePtr)) 260 | { 261 | return false; 262 | } 263 | if (!bVariable) 264 | { 265 | g_pCompilerData->error = true; 266 | g_pCompilerData->error_msg = g_pErrorStrings[error_eav]; 267 | return false; 268 | } 269 | return true; 270 | } 271 | 272 | bool CompileVariable(unsigned char vOperation, unsigned char vOperator, unsigned char type, unsigned char size, int address, int indexSourcePtr) 273 | { 274 | // compile and index(s) 275 | if (type != type_reg) 276 | { 277 | if (type == type_spr || type == type_size) 278 | { 279 | if (!CompileOutOfSequenceExpression(address)) 280 | { 281 | return false; 282 | } 283 | } 284 | if (type != type_spr) 285 | { 286 | if (indexSourcePtr != 0) 287 | { 288 | if (!CompileOutOfSequenceExpression(indexSourcePtr)) 289 | { 290 | return false; 291 | } 292 | } 293 | } 294 | } 295 | 296 | unsigned char byteCode = 0; 297 | 298 | if (type == type_spr) 299 | { 300 | byteCode = 0x24 | vOperation; 301 | } 302 | else if (type == type_reg) 303 | { 304 | byteCode = 0x3F; 305 | if (size != 2) 306 | { 307 | bool bRange = false; 308 | if (!CompileOutOfSequenceRange(indexSourcePtr, bRange)) 309 | { 310 | return false; 311 | } 312 | if (bRange) 313 | { 314 | byteCode = 0x3E; 315 | } 316 | else 317 | { 318 | byteCode = 0x3D; 319 | } 320 | } 321 | if (!EnterObj(byteCode)) 322 | { 323 | return false; 324 | } 325 | // byteCode = 1 in high bit, bottom 2 bits of vOperation in next two bits, then bottom 5 bits of address 326 | byteCode = 0x80 | ((vOperation & 3) << 5) | (address & 0x1F); 327 | } 328 | else 329 | { 330 | if ((type != type_var_byte && type != type_loc_byte) || size != 2 || address >= 8*4 || indexSourcePtr != 0) 331 | { 332 | // not compact 333 | byteCode = 0x80 | (size << 5); 334 | if (indexSourcePtr != 0) 335 | { 336 | byteCode |= 0x10; 337 | } 338 | byteCode |= vOperation; 339 | if (type != type_size) 340 | { 341 | if (type == type_dat_byte) 342 | { 343 | byteCode += 4; 344 | } 345 | else if (type == type_var_byte) 346 | { 347 | byteCode += 8; 348 | } 349 | else if (type == type_loc_byte) 350 | { 351 | byteCode += 12; 352 | } 353 | else 354 | { 355 | g_pCompilerData->error = true; 356 | g_pCompilerData->error_msg = g_pErrorStrings[error_internal]; 357 | return false; 358 | } 359 | if (!EnterObj(byteCode)) 360 | { 361 | return false; 362 | } 363 | if (address > 0x7F) 364 | { 365 | // two byte address 366 | byteCode = (unsigned char)(address >> 8) | 0x80; 367 | if (!EnterObj(byteCode)) 368 | { 369 | return false; 370 | } 371 | } 372 | byteCode = (unsigned char)address; 373 | } 374 | } 375 | else 376 | { 377 | // compact 378 | byteCode = (type == type_var_byte) ? 0x40 : 0x60; 379 | byteCode |= (unsigned char)address; 380 | byteCode |= vOperation; 381 | } 382 | } 383 | 384 | if (!EnterObj(byteCode)) 385 | { 386 | return false; 387 | } 388 | if (vOperation == 2) // if assign 389 | { 390 | if (!EnterObj(vOperator)) 391 | { 392 | return false; 393 | } 394 | } 395 | return true; 396 | } 397 | 398 | bool CompileVariable_Assign(unsigned char vOperator, unsigned char type, unsigned char size, int address, int indexSourcePtr) 399 | { 400 | return CompileVariable(2, vOperator, type, size, address, indexSourcePtr); 401 | } 402 | 403 | bool CompileVariable_Expression(unsigned char vOperator, unsigned char type, unsigned char size, int address, int indexSourcePtr) 404 | { 405 | if (!CompileExpression()) 406 | { 407 | return false; 408 | } 409 | return CompileVariable(2, vOperator, type, size, address, indexSourcePtr); 410 | } 411 | 412 | bool CompileVariable_PreSignExtendOrRandom(unsigned char vOperator) 413 | { 414 | unsigned char varType = 0; 415 | unsigned char varSize = 0; 416 | int varAddress = 0; 417 | int varIndexSourcePtr = 0; 418 | if (!GetVariable(varType, varSize, varAddress, varIndexSourcePtr)) 419 | { 420 | return false; 421 | } 422 | 423 | return CompileVariable_Assign(vOperator, varType, varSize, varAddress, varIndexSourcePtr); 424 | } 425 | 426 | bool CompileVariable_IncOrDec(unsigned char vOperator, unsigned char type, unsigned char size, int address, int indexSourcePtr) 427 | { 428 | return CompileVariable(2, vOperator | (((size + 1) & 3) << 1), type, size, address, indexSourcePtr); 429 | } 430 | 431 | bool CompileVariable_PreIncOrDec(unsigned char vOperator) 432 | { 433 | unsigned char varType = 0; 434 | unsigned char varSize = 0; 435 | int varAddress = 0; 436 | int varIndexSourcePtr = 0; 437 | if (!GetVariable(varType, varSize, varAddress, varIndexSourcePtr)) 438 | { 439 | return false; 440 | } 441 | 442 | return CompileVariable_IncOrDec(vOperator, varType, varSize, varAddress, varIndexSourcePtr); 443 | } 444 | 445 | bool CompileParameters(int numParameters) 446 | { 447 | if (numParameters > 0) 448 | { 449 | if (!g_pElementizer->GetElement(type_left)) // ( 450 | { 451 | return false; 452 | } 453 | for (int i = 0; i < numParameters; i++) 454 | { 455 | if (!CompileExpression()) 456 | { 457 | return false; 458 | } 459 | if (i < (numParameters - 1)) 460 | { 461 | if (!g_pElementizer->GetElement(type_comma)) 462 | { 463 | return false; 464 | } 465 | } 466 | } 467 | if (!g_pElementizer->GetElement(type_right)) // ) 468 | { 469 | return false; 470 | } 471 | } 472 | return true; 473 | } 474 | 475 | bool CompileConstant(int value) 476 | { 477 | if (value >= -1 && value <= 1) 478 | { 479 | // constant is -1, 0, or 1, so compiles to a single bytecode 480 | unsigned char byteCode = (unsigned char)(value+1) | 0x34; 481 | if (!EnterObj(byteCode)) 482 | { 483 | return false; 484 | } 485 | return true; 486 | } 487 | 488 | // see if it's a mask 489 | // masks can be: only one bit on (e.g. 0x00008000), 490 | // all bits on except one (e.g. 0xFFFF7FFF), 491 | // all bits on up to a bit then all zeros (e.g. 0x0000FFFF), 492 | // or all bits off up to a bit then all ones (e.g. 0xFFFF0000) 493 | for (unsigned char i = 0; i < 128; i++) 494 | { 495 | int testVal = 2; 496 | testVal <<= (i & 0x1F); // mask i, so that we only actually shift 0 to 31 497 | 498 | if (i & 0x20) // i in range 32 to 63 or 96 to 127 499 | { 500 | testVal--; 501 | } 502 | if (i& 0x40) // i in range 64 to 127 503 | { 504 | testVal = ~testVal; 505 | } 506 | 507 | if (testVal == value) 508 | { 509 | if (!EnterObj(0x37)) // (constant mask) 510 | { 511 | return false; 512 | } 513 | if (!EnterObj(i)) 514 | { 515 | return false; 516 | } 517 | return true; 518 | } 519 | } 520 | 521 | // handle constants with upper 2 or 3 bytes being 0xFFs, using 'not' 522 | if ((value & 0xFFFFFF00) == 0xFFFFFF00) 523 | { 524 | // one byte constant using 'not' 525 | if (!EnterObj(0x38)) 526 | { 527 | return false; 528 | } 529 | unsigned char byteCode = (unsigned char)(value & 0xFF); 530 | if (!EnterObj(~byteCode)) 531 | { 532 | return false; 533 | } 534 | if (!EnterObj(0xE7)) // (bitwise bot) 535 | { 536 | return false; 537 | } 538 | return true; 539 | } 540 | else if ((value & 0xFFFF0000) == 0xFFFF0000) 541 | { 542 | // two byte constant using 'not' 543 | if (!EnterObj(0x39)) 544 | { 545 | return false; 546 | } 547 | unsigned char byteCode = (unsigned char)((value >> 8) & 0xFF); 548 | if (!EnterObj(~byteCode)) 549 | { 550 | return false; 551 | } 552 | byteCode = (unsigned char)(value & 0xFF); 553 | if (!EnterObj(~byteCode)) 554 | { 555 | return false; 556 | } 557 | if (!EnterObj(0xE7)) // (bitwise bot) 558 | { 559 | return false; 560 | } 561 | return true; 562 | } 563 | 564 | // 1 to 4 byte constant 565 | unsigned char size = 1; 566 | if (value & 0xFF000000) 567 | { 568 | size = 4; 569 | } 570 | else if (value & 0x00FF0000) 571 | { 572 | size = 3; 573 | } 574 | else if (value & 0x0000FF00) 575 | { 576 | size = 2; 577 | } 578 | unsigned char byteCode = 0x37 + size; // (constant 1..4 bytes) 579 | if (!EnterObj(byteCode)) 580 | { 581 | return false; 582 | } 583 | for (unsigned char i = size; i > 0; i--) 584 | { 585 | byteCode = (unsigned char)((value >> ((i - 1) * 8)) & 0xFF); 586 | if (!EnterObj(byteCode)) 587 | { 588 | return false; 589 | } 590 | } 591 | return true; 592 | } 593 | 594 | bool CompileOutOfSequenceExpression(int sourcePtr) 595 | { 596 | int savedSourcePtr = g_pElementizer->GetSourcePtr(); 597 | g_pElementizer->SetSourcePtr(sourcePtr); 598 | if (!CompileExpression()) 599 | { 600 | return false; 601 | } 602 | g_pElementizer->SetSourcePtr(savedSourcePtr); 603 | return true; 604 | } 605 | 606 | bool CompileOutOfSequenceRange(int sourcePtr, bool& bRange) 607 | { 608 | int savedSourcePtr = g_pElementizer->GetSourcePtr(); 609 | g_pElementizer->SetSourcePtr(sourcePtr); 610 | if (!CompileRange(bRange)) 611 | { 612 | return false; 613 | } 614 | g_pElementizer->SetSourcePtr(savedSourcePtr); 615 | return true; 616 | } 617 | 618 | // compiles either a value or a range and sets the bRange flag accordingly 619 | bool CompileRange(bool& bRange) 620 | { 621 | if (!CompileExpression()) 622 | { 623 | return false; 624 | } 625 | 626 | if (g_pElementizer->CheckElement(type_dotdot)) 627 | { 628 | if (!CompileExpression()) 629 | { 630 | return false; 631 | } 632 | bRange = true; 633 | } 634 | else 635 | { 636 | bRange = false; 637 | } 638 | 639 | return true; 640 | } 641 | 642 | // Compile relative address 643 | bool CompileAddress(int address) 644 | { 645 | address -= g_pCompilerData->obj_ptr; // make relative address 646 | address--; // compensate for single-byte 647 | 648 | if ((address < 0 && abs(address) <= 64) || (address >= 0 && address < 64)) 649 | { 650 | // single byte, enter 651 | address &= 0x007F; 652 | } 653 | else 654 | { 655 | // double byte, compensate and enter 656 | address--; 657 | if (!EnterObj((unsigned char)((address >> 8) | 0x80))) 658 | { 659 | return false; 660 | } 661 | address &= 0x00FF; 662 | } 663 | 664 | return EnterObj((unsigned char)address); 665 | } 666 | 667 | /////////////////////////////////////////////////////////////////////////////////////////// 668 | // TERMS OF USE: MIT License // 669 | /////////////////////////////////////////////////////////////////////////////////////////// 670 | // Permission is hereby granted, free of charge, to any person obtaining a copy of this // 671 | // software and associated documentation files (the "Software"), to deal in the Software // 672 | // without restriction, including without limitation the rights to use, copy, modify, // 673 | // merge, publish, distribute, sublicense, and/or sell copies of the Software, and to // 674 | // permit persons to whom the Software is furnished to do so, subject to the following // 675 | // conditions: // 676 | // // 677 | // The above copyright notice and this permission notice shall be included in all copies // 678 | // or substantial portions of the Software. // 679 | // // 680 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, // 681 | // INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A // 682 | // PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT // 683 | // HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION // 684 | // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE // 685 | // SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. // 686 | /////////////////////////////////////////////////////////////////////////////////////////// 687 | -------------------------------------------------------------------------------- /PropellerCompiler/CompileUtilities.h: -------------------------------------------------------------------------------- 1 | ////////////////////////////////////////////////////////////// 2 | // // 3 | // Propeller Spin/PASM Compiler // 4 | // (c)2012-2016 Parallax Inc. DBA Parallax Semiconductor. // 5 | // Adapted from Chip Gracey's x86 asm code by Roy Eltham // 6 | // See end of file for terms of use. // 7 | // // 8 | ////////////////////////////////////////////////////////////// 9 | // 10 | // CompileUtilities.h 11 | // 12 | 13 | #ifndef _COMPILEUTILITIES_H_ 14 | #define _COMPILEUTILITIES_H_ 15 | 16 | extern bool SkipBlock(int column); 17 | extern bool SkipRange(); 18 | extern bool SkipExpression(); 19 | extern bool CheckIndex(bool& bIndex, int& expSourcePtr); 20 | extern bool CheckIndexRange(bool& bIndex, int& expSourcePtr); 21 | extern bool CheckVariable(bool& bVariable, unsigned char& type, unsigned char& size, int& address, int& indexSourcePtr); 22 | extern bool GetVariable(unsigned char& type, unsigned char& size, int& address, int& indexSourcePtr); 23 | extern bool CompileVariable(unsigned char vOperation, unsigned char vOperator, unsigned char type, unsigned char size, int address, int indexSourcePtr); 24 | extern bool CompileVariable_Assign(unsigned char vOperator, unsigned char type, unsigned char size, int address, int indexSourcePtr); 25 | extern bool CompileVariable_Expression(unsigned char vOperator, unsigned char type, unsigned char size, int address, int indexSourcePtr); 26 | extern bool CompileVariable_PreSignExtendOrRandom(unsigned char vOperator); 27 | extern bool CompileVariable_IncOrDec(unsigned char vOperator, unsigned char type, unsigned char size, int address, int indexSourcePtr); 28 | extern bool CompileVariable_PreIncOrDec(unsigned char vOperator); 29 | extern bool CompileParameters(int numParameters); 30 | extern bool CompileConstant(int value); 31 | extern bool CompileOutOfSequenceExpression(int sourcePtr); 32 | extern bool CompileOutOfSequenceRange(int sourcePtr, bool& bRange); 33 | extern bool CompileRange(bool& bRange); 34 | extern bool CompileAddress(int address); 35 | 36 | // these are in InstructionBlockCompiler.cpp 37 | extern bool CompileBlock(int column); 38 | extern bool OptimizeBlock(int column, int param, bool (*pCompileFunction)(int, int)); 39 | 40 | extern bool CompileInstruction(); // in CompileInstruction.cpp 41 | extern bool CompileExpression(); // in CompileExpression.cpp 42 | 43 | // these are in StringConstantRoutines.cpp 44 | extern void StringConstant_PreProcess(); 45 | extern bool StringConstant_GetIndex(); 46 | extern bool StringConstant_EnterChar(unsigned char theChar); 47 | extern void StringConstant_EnterPatch(); 48 | extern bool StringConstant_PostProcess(); 49 | 50 | // these are int BlockNestStackRoutines.cpp 51 | extern bool BlockNest_New(unsigned char type, int stackSize); 52 | extern void BlockNest_Redo(unsigned char type); 53 | extern void BlockNest_End(); 54 | extern void BlockStack_Write(int address, int value); 55 | extern int BlockStack_Read(int address); 56 | extern bool BlockStack_CompileAddress(int address); 57 | extern bool BlockStack_CompileConstant(); 58 | 59 | #endif // _COMPILEUTILITIES_H_ 60 | 61 | /////////////////////////////////////////////////////////////////////////////////////////// 62 | // TERMS OF USE: MIT License // 63 | /////////////////////////////////////////////////////////////////////////////////////////// 64 | // Permission is hereby granted, free of charge, to any person obtaining a copy of this // 65 | // software and associated documentation files (the "Software"), to deal in the Software // 66 | // without restriction, including without limitation the rights to use, copy, modify, // 67 | // merge, publish, distribute, sublicense, and/or sell copies of the Software, and to // 68 | // permit persons to whom the Software is furnished to do so, subject to the following // 69 | // conditions: // 70 | // // 71 | // The above copyright notice and this permission notice shall be included in all copies // 72 | // or substantial portions of the Software. // 73 | // // 74 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, // 75 | // INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A // 76 | // PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT // 77 | // HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION // 78 | // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE // 79 | // SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. // 80 | /////////////////////////////////////////////////////////////////////////////////////////// 81 | -------------------------------------------------------------------------------- /PropellerCompiler/DistillObjects.cpp: -------------------------------------------------------------------------------- 1 | ////////////////////////////////////////////////////////////// 2 | // // 3 | // Propeller Spin/PASM Compiler // 4 | // (c)2012-2016 Parallax Inc. DBA Parallax Semiconductor. // 5 | // Adapted from Chip Gracey's x86 asm code by Roy Eltham // 6 | // See end of file for terms of use. // 7 | // // 8 | ////////////////////////////////////////////////////////////// 9 | // 10 | // DistillObjects.cpp 11 | // 12 | // called Object Distiller in the asm code 13 | // 14 | 15 | #include 16 | #include 17 | #include 18 | #include 19 | #include "Utilities.h" 20 | #include "PropellerCompilerInternal.h" 21 | #include "SymbolEngine.h" 22 | #include "Elementizer.h" 23 | #include "ErrorStrings.h" 24 | 25 | bool DistillSetup_Enter(unsigned short value) 26 | { 27 | if (g_pCompilerData->dis_ptr == distiller_limit) 28 | { 29 | g_pCompilerData->error = true; 30 | g_pCompilerData->error_msg = g_pErrorStrings[error_odo]; 31 | return false; 32 | } 33 | g_pCompilerData->dis[g_pCompilerData->dis_ptr++] = value; 34 | return true; 35 | } 36 | 37 | // create a table of all objects with their offsets and sub objects 38 | // each entry contains: 39 | // id, offset, number sub objects, [sub object ids] 40 | bool DistillSetup_Record(short id, unsigned short offset, unsigned short& subObjectId) 41 | { 42 | if (!DistillSetup_Enter(id)) 43 | { 44 | return false; 45 | } 46 | if (!DistillSetup_Enter(offset)) 47 | { 48 | return false; 49 | } 50 | unsigned short numSubObjects = (unsigned short)(g_pCompilerData->obj[offset+3]); 51 | if (!DistillSetup_Enter(numSubObjects)) 52 | { 53 | return false; 54 | } 55 | if (numSubObjects > 0) 56 | { 57 | short startingSubObjectId = subObjectId; 58 | for (short i = 0; i < numSubObjects; i++) 59 | { 60 | if (!DistillSetup_Enter(subObjectId++)) 61 | { 62 | return false; 63 | } 64 | } 65 | 66 | unsigned short nextSubObjects = (unsigned short)(g_pCompilerData->obj[offset+2]); 67 | for (short i = 0; i < numSubObjects; i++) 68 | { 69 | unsigned short offsetAdjust = *((unsigned short*)&(g_pCompilerData->obj[offset + ((nextSubObjects + i) * 4)])); 70 | if (!DistillSetup_Record(startingSubObjectId + i, offset + offsetAdjust, subObjectId)) 71 | { 72 | return false; 73 | } 74 | } 75 | } 76 | 77 | return true; 78 | } 79 | 80 | bool DistillSetup() 81 | { 82 | g_pCompilerData->dis_ptr = 0; 83 | unsigned short subObjectId = 1; 84 | if (!DistillSetup_Record(0, 0, subObjectId)) 85 | { 86 | return false; 87 | } 88 | 89 | // Clear all the objects table of offsets to their sub objects 90 | // this needs to be done so that objects will binary compare with each other properly 91 | // these offsets get replaced in the reconnect step 92 | int disPtr = 0; 93 | while (disPtr < g_pCompilerData->dis_ptr) 94 | { 95 | // do we have sub objects? 96 | unsigned short numSubObjects = g_pCompilerData->dis[disPtr + 2]; 97 | if (numSubObjects > 0) 98 | { 99 | unsigned short offset = g_pCompilerData->dis[disPtr + 1]; 100 | 101 | disPtr += numSubObjects; 102 | 103 | unsigned short offsetAdjust = (unsigned short)(g_pCompilerData->obj[offset + 2]); 104 | unsigned char* pObj = &(g_pCompilerData->obj[offset + (offsetAdjust * 4)]); 105 | for (int i = 0; i < numSubObjects; i++) 106 | { 107 | *((unsigned short*)&pObj[0]) = 0; 108 | pObj += 4; 109 | } 110 | } 111 | 112 | disPtr += 3; 113 | } 114 | 115 | return true; 116 | } 117 | 118 | // update all objects of the given id to the new id 119 | // also flags them as "distilled" with the upper bit being on 120 | void DistillEliminate_Update(unsigned short objectId, int newDisPtr) 121 | { 122 | int disPtr = 0; 123 | 124 | while (disPtr < g_pCompilerData->dis_ptr) 125 | { 126 | disPtr += 3; 127 | unsigned short numSubObjects = g_pCompilerData->dis[disPtr - 1]; 128 | if (numSubObjects > 0) 129 | { 130 | for (int i = 0; i < numSubObjects; i++) 131 | { 132 | if ((g_pCompilerData->dis[disPtr] & 0x7FFF) == objectId) 133 | { 134 | g_pCompilerData->dis[disPtr] = (g_pCompilerData->dis[newDisPtr] | 0x8000); 135 | } 136 | disPtr++; 137 | } 138 | } 139 | } 140 | } 141 | 142 | void DistillEliminate() 143 | { 144 | int disPtr = 0; 145 | 146 | while (disPtr < g_pCompilerData->dis_ptr) 147 | { 148 | unsigned short numSubObjects = g_pCompilerData->dis[disPtr + 2]; 149 | if (numSubObjects > 0) 150 | { 151 | int i; 152 | for (i = 0; i < numSubObjects; i++) 153 | { 154 | if ((g_pCompilerData->dis[disPtr + 3 + i] & 0x8000) == 0) 155 | { 156 | break; 157 | } 158 | } 159 | if (i < numSubObjects) 160 | { 161 | // point to next object record 162 | disPtr += (3 + numSubObjects); 163 | continue; 164 | } 165 | } 166 | 167 | // search for any matching objects 168 | int newDisPtr = disPtr; 169 | // point to next object record 170 | newDisPtr += (3 + numSubObjects); 171 | 172 | bool bRestart = false; 173 | while (newDisPtr < g_pCompilerData->dis_ptr) 174 | { 175 | unsigned short newNumSubObjects = g_pCompilerData->dis[newDisPtr + 2]; 176 | 177 | if (numSubObjects != newNumSubObjects) 178 | { 179 | // point to next object record 180 | newDisPtr += (3 + newNumSubObjects); 181 | continue; 182 | } 183 | if (newNumSubObjects > 0) 184 | { 185 | int i; 186 | for (i = 0; i < newNumSubObjects; i++) 187 | { 188 | if (g_pCompilerData->dis[disPtr + 3 + i] != g_pCompilerData->dis[newDisPtr + 3 + i]) 189 | { 190 | break; 191 | } 192 | } 193 | if (i < newNumSubObjects) 194 | { 195 | // point to next object record 196 | newDisPtr += (3 + newNumSubObjects); 197 | continue; 198 | } 199 | } 200 | // compare the object binaries 201 | unsigned char* pObj = &(g_pCompilerData->obj[g_pCompilerData->dis[disPtr+1]]); 202 | unsigned short objLength = *((unsigned short*)pObj); 203 | if (memcmp(pObj, &(g_pCompilerData->obj[g_pCompilerData->dis[newDisPtr+1]]), (size_t)objLength) != 0) 204 | { 205 | // point to next object record 206 | newDisPtr += (3 + newNumSubObjects); 207 | continue; 208 | } 209 | 210 | // the objects match, so update all related sub-object id's 211 | DistillEliminate_Update(g_pCompilerData->dis[disPtr], newDisPtr); 212 | DistillEliminate_Update(g_pCompilerData->dis[newDisPtr], newDisPtr); 213 | 214 | // remove redundant object record from list 215 | g_pCompilerData->dis_ptr -= (3 + numSubObjects); 216 | memmove(&g_pCompilerData->dis[disPtr], &g_pCompilerData->dis[disPtr + (3 + numSubObjects)], (g_pCompilerData->dis_ptr - disPtr) * 2); 217 | 218 | // restart elimination from beginning 219 | bRestart = true; 220 | } 221 | if (bRestart) 222 | { 223 | disPtr = 0; 224 | } 225 | else 226 | { 227 | // point to next object record 228 | disPtr += (3 + numSubObjects); 229 | continue; 230 | } 231 | } 232 | } 233 | 234 | static unsigned char s_rebuildBuffer[min_obj_limit]; 235 | void DistillRebuild() 236 | { 237 | int disPtr = 0; 238 | unsigned short rebuildPtr = 0; 239 | while (disPtr < g_pCompilerData->dis_ptr) 240 | { 241 | // copy the object from obj into the rebuild buffer 242 | unsigned char* pObj = &(g_pCompilerData->obj[g_pCompilerData->dis[disPtr + 1]]); 243 | unsigned short objLength = *((unsigned short*)pObj); 244 | memcpy(&(s_rebuildBuffer[rebuildPtr]), pObj, (size_t)objLength); 245 | 246 | // fixup the distiller record 247 | g_pCompilerData->dis[disPtr+1] = rebuildPtr; 248 | 249 | rebuildPtr += objLength; 250 | 251 | // point to the next object record 252 | disPtr += (3 + g_pCompilerData->dis[disPtr + 2]); 253 | } 254 | 255 | // copy the rebuilt data back into obj 256 | g_pCompilerData->obj_ptr = rebuildPtr; 257 | memcpy(&g_pCompilerData->obj[0], &s_rebuildBuffer[0], (size_t)rebuildPtr); 258 | } 259 | 260 | void DistillReconnect(int disPtr = 0) 261 | { 262 | unsigned short numSubObjects = g_pCompilerData->dis[disPtr + 2]; 263 | if (numSubObjects > 0) 264 | { 265 | // this objects offset in the obj 266 | unsigned short objectOffset = g_pCompilerData->dis[disPtr + 1]; 267 | // the offset (number of longs) to the sub-object offset list within this obj 268 | unsigned char subObjectOffsetListPtr = g_pCompilerData->obj[objectOffset + 2]; 269 | // pointer to the sub-object offset list for this obj 270 | unsigned short* pSubObjectOffsetList = (unsigned short*)&(g_pCompilerData->obj[objectOffset + (subObjectOffsetListPtr * 4)]); 271 | 272 | for (int i = 0; i < numSubObjects; i++) 273 | { 274 | unsigned short subObjectId = g_pCompilerData->dis[disPtr + 3 + i] & 0x7FFF; 275 | 276 | // find offset of sub-object 277 | int scanDisPtr = 0; 278 | for (;;) 279 | { 280 | if (g_pCompilerData->dis[scanDisPtr] == subObjectId) 281 | { 282 | break; 283 | } 284 | scanDisPtr += (3 + g_pCompilerData->dis[scanDisPtr + 2]); 285 | } 286 | 287 | // enter relative offset of sub-object 288 | pSubObjectOffsetList[i*2] = g_pCompilerData->dis[scanDisPtr + 1] - objectOffset; 289 | 290 | // call recursively to reconnect and sub-objects' sub-objects 291 | DistillReconnect(scanDisPtr); 292 | } 293 | } 294 | } 295 | 296 | bool DistillObjects() 297 | { 298 | int saved_obj_ptr = g_pCompilerData->obj_ptr; 299 | 300 | if (!DistillSetup()) 301 | { 302 | return false; 303 | } 304 | DistillEliminate(); 305 | DistillRebuild(); 306 | DistillReconnect(); 307 | 308 | g_pCompilerData->distilled_longs = (saved_obj_ptr - g_pCompilerData->obj_ptr) >> 2; 309 | 310 | char tempStr[64]; 311 | sprintf(tempStr, "\rDistilled longs: %d", g_pCompilerData->distilled_longs); 312 | if (!PrintString(tempStr)) 313 | { 314 | return false; 315 | } 316 | return PrintChr(13); 317 | } 318 | 319 | /////////////////////////////////////////////////////////////////////////////////////////// 320 | // TERMS OF USE: MIT License // 321 | /////////////////////////////////////////////////////////////////////////////////////////// 322 | // Permission is hereby granted, free of charge, to any person obtaining a copy of this // 323 | // software and associated documentation files (the "Software"), to deal in the Software // 324 | // without restriction, including without limitation the rights to use, copy, modify, // 325 | // merge, publish, distribute, sublicense, and/or sell copies of the Software, and to // 326 | // permit persons to whom the Software is furnished to do so, subject to the following // 327 | // conditions: // 328 | // // 329 | // The above copyright notice and this permission notice shall be included in all copies // 330 | // or substantial portions of the Software. // 331 | // // 332 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, // 333 | // INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A // 334 | // PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT // 335 | // HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION // 336 | // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE // 337 | // SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. // 338 | /////////////////////////////////////////////////////////////////////////////////////////// 339 | -------------------------------------------------------------------------------- /PropellerCompiler/Elementizer.h: -------------------------------------------------------------------------------- 1 | ////////////////////////////////////////////////////////////// 2 | // // 3 | // Propeller Spin/PASM Compiler // 4 | // (c)2012-2016 Parallax Inc. DBA Parallax Semiconductor. // 5 | // Adapted from Chip Gracey's x86 asm code by Roy Eltham // 6 | // See end of file for terms of use. // 7 | // // 8 | ////////////////////////////////////////////////////////////// 9 | // 10 | // Elementizer.h 11 | // 12 | 13 | #ifndef _ELEMENTIZER_H_ 14 | #define _ELEMENTIZER_H_ 15 | 16 | struct CompilerDataInternal; 17 | class SymbolEngine; 18 | class SymbolTableEntry; 19 | 20 | const int state_stack_limit = 32; 21 | 22 | class Elementizer 23 | { 24 | CompilerDataInternal* m_pCompilerData; 25 | SymbolEngine* m_pSymbolEngine; 26 | 27 | int m_sourceOffset; 28 | unsigned char m_sourceFlags; 29 | 30 | SymbolTableEntry* m_pSymbolEntry; 31 | int m_type; 32 | int m_value; 33 | int m_value_2; 34 | int m_opType; 35 | int m_asm; 36 | bool m_dual; 37 | 38 | unsigned char m_backIndex; 39 | int m_backOffsets[4]; 40 | unsigned char m_backFlags[4]; 41 | 42 | char m_currentSymbol[symbol_limit+2]; 43 | 44 | void SetFromSymbolEntry(); 45 | 46 | public: 47 | Elementizer(CompilerDataInternal* pCompilerData, SymbolEngine* pSymbolEngine) 48 | : m_pCompilerData(pCompilerData) 49 | , m_pSymbolEngine(pSymbolEngine) 50 | , m_sourceOffset(0) 51 | , m_sourceFlags(0) 52 | , m_backIndex(0) 53 | { 54 | for(int i = 0; i < 4; i++) 55 | { 56 | m_backOffsets[i] = 0; 57 | m_backFlags[0] = 0; 58 | } 59 | } 60 | 61 | void Reset(); // reset to start of source 62 | 63 | bool GetNext(bool& bEof); // get the next element in source, returns true no error, bEof will be set to true if eof is hit 64 | bool GetElement(int type); // if the next element is type, then return true, else false, retains value 65 | bool CheckElement(int type); // check if next element is of the given type, if so return true, if not, backup and return false 66 | bool GetNextBlock(int type, bool& bEof); // scan for the next block element of type, returns true if no error, , bEof will be set to true if eof is hit 67 | bool FindSymbol(const char* symbol); // lookup a symbol in the symbol table and set it as the current element 68 | void Backup(); // backup to the previous element 69 | 70 | void BackupSymbol(); // copy the current symbol into g_pCompilerData->symbolBackup 71 | 72 | int GetColumn(); // returns column of the element pointed to by g_pCompilerData->source_start 73 | 74 | int GetSourcePtr() // used to save the current source pointer so it can be put back 75 | { 76 | return m_sourceOffset; 77 | } 78 | void SetSourcePtr(int value) // used to set the source pointer back to a previously saved value 79 | { 80 | m_sourceOffset = value; 81 | } 82 | 83 | int GetType() { return m_type; } // symbol's type 84 | int GetValue() { return m_value; } // only valid if m_type != type_undefined 85 | int GetValue2() { return m_value_2; } // only valid if m_type != type_undefined 86 | int GetOpType() { return m_opType; } // only valid for operator symbols 87 | int GetAsm() { return m_asm; } // only valid for dual symbols + op_log_and & op_log_or 88 | bool IsDual() { return m_dual; } // true if is a dual symbol 89 | char* GetCurrentSymbol() // returns the string for the symbol 90 | { 91 | return &(m_currentSymbol[0]); 92 | } 93 | int GetCurrentLineNumber(int &offsetToStartOfLine, int& offsetToEndOfLine); 94 | 95 | bool SubToNeg(); // convert a sub to a neg 96 | void ObjConToCon(); // convert type_objcon_xx to type_con_xx 97 | void DatResToLong(); // convert type_dat_long_res to type_dat_long 98 | bool NegConToCon(); // convert -constant to constant 99 | }; 100 | 101 | #endif // _ELEMENTIZER_H_ 102 | 103 | /////////////////////////////////////////////////////////////////////////////////////////// 104 | // TERMS OF USE: MIT License // 105 | /////////////////////////////////////////////////////////////////////////////////////////// 106 | // Permission is hereby granted, free of charge, to any person obtaining a copy of this // 107 | // software and associated documentation files (the "Software"), to deal in the Software // 108 | // without restriction, including without limitation the rights to use, copy, modify, // 109 | // merge, publish, distribute, sublicense, and/or sell copies of the Software, and to // 110 | // permit persons to whom the Software is furnished to do so, subject to the following // 111 | // conditions: // 112 | // // 113 | // The above copyright notice and this permission notice shall be included in all copies // 114 | // or substantial portions of the Software. // 115 | // // 116 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, // 117 | // INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A // 118 | // PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT // 119 | // HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION // 120 | // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE // 121 | // SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. // 122 | /////////////////////////////////////////////////////////////////////////////////////////// 123 | -------------------------------------------------------------------------------- /PropellerCompiler/ErrorStrings.cpp: -------------------------------------------------------------------------------- 1 | ////////////////////////////////////////////////////////////// 2 | // // 3 | // Propeller Spin/PASM Compiler // 4 | // (c)2012-2016 Parallax Inc. DBA Parallax Semiconductor. // 5 | // Adapted from Chip Gracey's x86 asm code by Roy Eltham // 6 | // See end of file for terms of use. // 7 | // // 8 | ////////////////////////////////////////////////////////////// 9 | // 10 | // ErrorStrings.cpp 11 | // 12 | 13 | const char* g_pErrorStrings[] = 14 | { 15 | "Address is not long", 16 | "Address is out of range", 17 | "\"}\" must be preceeded by \"{\" to form a comment", 18 | "Block designator must be in first column", 19 | "Blocknest stack overflow", 20 | "Cannot compute square root of negative floating-point number", 21 | "Constant exceeds 32 bits", 22 | "_CLKFREQ or _XINFREQ must be specified", 23 | "CALL symbol must not exceed 252 characters", 24 | "_CLKFREQ/_XINFREQ not allowed with RCFAST/RCSLOW", 25 | "_CLKFREQ/_XINFREQ specified without _CLKMODE", 26 | "Divide by zero", 27 | "Destination register cannot exceed $1FF", 28 | "Expected an assembly effect or end of line", 29 | "Expected an assembly effect", 30 | "Expected an assembly instruction", 31 | "Expected a binary operator or \")\"", 32 | "Expected a constant name", 33 | "Expected a constant, unary operator, or \"(\"", 34 | "Expected a DAT symbol", 35 | "Expected an expression term", 36 | "Expected an instruction or variable", 37 | "Expected a local symbol", 38 | "Expected a memory variable after \"@\"", 39 | "Expected a subroutine name", 40 | "Expected a subroutine or object name", 41 | "Expected a terminating quote", 42 | "Expected a unique object name", 43 | "Expected a variable", 44 | "Expected a unique constant name or \"#\"", 45 | "Expected a unique name, BYTE, WORD, LONG, or assembly instruction", 46 | "Expected a unique parameter name", 47 | "Expected a unique result name", 48 | "Expected a unique subroutine name", 49 | "Expected a unique variable name", 50 | "Expected BYTE, WORD, or LONG", 51 | "Expected \",\" or end of line", 52 | "Expected \":\"", 53 | "Expected \",\"", 54 | "Expected \",\" or \")\"", 55 | "Either _CLKFREQ or _XINFREQ must be specified, but not both", 56 | "Expected \".\"", 57 | "Expected end of line", 58 | "Expected \"=\" \"[\" \",\" or end of line", 59 | "Expected FROM", 60 | "Expression is too complex", 61 | "Expected \"(\"", 62 | "Expected \"[\"", 63 | "Expected PRECOMPILE or ARCHIVE", 64 | "Expected \"|\" or end of line", 65 | "Expected \"#\"", 66 | "Expected \"}\"", 67 | "Expected \"}}\"", 68 | "Expected \")\"", 69 | "Expected \"]\"", 70 | "Empty string", 71 | "Expected STEP or end of line", 72 | "Expected TO", 73 | "Filename too long", 74 | "Floating-point constant must be within +/- 3.4e+38", 75 | "Floating-point not allowed in integer expression", 76 | "Floating-point overflow", 77 | "Invalid binary number", 78 | "Invalid _CLKMODE specified", 79 | "Invalid double-binary number", 80 | "Internal DAT file not found", 81 | "Invalid filename character", 82 | "Invalid filename, use \"FilenameInQuotes\"", 83 | "Integer not allowed in floating-point expression", 84 | "Internal", 85 | "Integer operator not allowed in floating-point expression", 86 | "Limit of 64 cases exceeded", 87 | "Limit of 8 nested blocks exceeded", 88 | "Limit of 32 unique objects exceeded", 89 | "Limit of 32 unique DAT files exceeded", 90 | "Limit of 32 unique PRECOMPILE files exceeded", 91 | "Limit of 32 unique ARCHIVE files exceeded", 92 | "List is too large", 93 | "Limit of 1,048,576 DAT symbols exceeded", 94 | "Limit of 16 ELSEIFs exceeded", 95 | "Limit of 4096 local variables exceeded", 96 | "Limit of 15 parameters exceeded", 97 | "Limit of 256 subroutines + objects exceeded", 98 | "Memory instructions cannot use WR/NR", 99 | "No cases encountered", 100 | "No PUB routines found", 101 | "Object count must be from 1 to 255", 102 | "Object distiller overflow", 103 | "Origin exceeds FIT limit", 104 | "Object exceeds 128k (before distilling)", 105 | "Origin exceeds $1F0 limit", 106 | "\"$\" is not allowed here", 107 | "OTHER must be last case", 108 | "PUB/CON list overflow", 109 | "?_RET address is not long", 110 | "?_RET address is out of range", 111 | "Register is not allowed here", 112 | "RES is not allowed in ORGX mode", 113 | "_STACK and _FREE must sum to under 8k", 114 | "Symbols _CLKMODE, _CLKFREQ, _XINFREQ can only be used as integer constants", 115 | "String characters must range from 1 to 255", 116 | "Symbol _DEBUG can only be used as an integer constant", 117 | "Symbol exceeds 256 characters", 118 | "Symbol is already defined", 119 | "STRING not allowed here", 120 | "Size override must be larger", 121 | "Size override must be smaller", 122 | "Source register/constant cannot exceed $1FF", 123 | "Symbols _STACK and _FREE can only be used as integer constants", 124 | "Symbol table is full", 125 | "This instruction is only allowed within a REPEAT block", 126 | "Too many string constants", 127 | "Too many string constant characters", 128 | "Too much variable space is declared", 129 | "Unrecognized character", 130 | "Undefined ?_RET symbol", 131 | "Undefined symbol", 132 | "Variable needs an operator" 133 | }; 134 | 135 | /////////////////////////////////////////////////////////////////////////////////////////// 136 | // TERMS OF USE: MIT License // 137 | /////////////////////////////////////////////////////////////////////////////////////////// 138 | // Permission is hereby granted, free of charge, to any person obtaining a copy of this // 139 | // software and associated documentation files (the "Software"), to deal in the Software // 140 | // without restriction, including without limitation the rights to use, copy, modify, // 141 | // merge, publish, distribute, sublicense, and/or sell copies of the Software, and to // 142 | // permit persons to whom the Software is furnished to do so, subject to the following // 143 | // conditions: // 144 | // // 145 | // The above copyright notice and this permission notice shall be included in all copies // 146 | // or substantial portions of the Software. // 147 | // // 148 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, // 149 | // INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A // 150 | // PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT // 151 | // HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION // 152 | // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE // 153 | // SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. // 154 | /////////////////////////////////////////////////////////////////////////////////////////// 155 | -------------------------------------------------------------------------------- /PropellerCompiler/ErrorStrings.h: -------------------------------------------------------------------------------- 1 | ////////////////////////////////////////////////////////////// 2 | // // 3 | // Propeller Spin/PASM Compiler // 4 | // (c)2012-2016 Parallax Inc. DBA Parallax Semiconductor. // 5 | // Adapted from Chip Gracey's x86 asm code by Roy Eltham // 6 | // See end of file for terms of use. // 7 | // // 8 | ////////////////////////////////////////////////////////////// 9 | // 10 | // ErrorStrings.h 11 | // 12 | 13 | #ifndef _ERROR_STRINGS_H_ 14 | #define _ERROR_STRINGS_H_ 15 | 16 | enum errorType 17 | { 18 | error_none = -1, 19 | error_ainl = 0, 20 | error_aioor, 21 | error_bmbpbb, 22 | error_bdmbifc, 23 | error_bnso, 24 | error_ccsronfp, 25 | error_ce32b, 26 | error_coxmbs, 27 | error_csmnexc, 28 | error_cxnawrc, 29 | error_cxswcm, 30 | error_dbz, 31 | error_drcex, 32 | error_eaaeoeol, 33 | error_eaasme, 34 | error_eaasmi, 35 | error_eaboor, 36 | error_eacn, 37 | error_eacuool, 38 | error_eads, 39 | error_eaet, 40 | error_eaiov, 41 | error_eals, 42 | error_eamvaa, 43 | error_easn, 44 | error_easoon, 45 | error_eatq, 46 | error_eauon, 47 | error_eav, 48 | error_eaucnop, 49 | error_eaunbwlo, 50 | error_eaupn, 51 | error_eaurn, 52 | error_eausn, 53 | error_eauvn, 54 | error_ebwol, 55 | error_ecoeol, 56 | error_ecolon, 57 | error_ecomma, 58 | error_ecor, 59 | error_ecoxmbs, 60 | error_edot, 61 | error_eeol, 62 | error_eelcoeol, 63 | error_efrom, 64 | error_eitc, 65 | error_eleft, 66 | error_eleftb, 67 | error_epoa, 68 | error_epoeol, 69 | error_epound, 70 | error_erb, 71 | error_erbb, 72 | error_eright, 73 | error_erightb, 74 | error_es, 75 | error_esoeol, 76 | error_eto, 77 | error_ftl, 78 | error_fpcmbw, 79 | error_fpnaiie, 80 | error_fpo, 81 | error_ibn, 82 | error_icms, 83 | error_idbn, 84 | error_idfnf, 85 | error_ifc, 86 | error_ifufiq, 87 | error_inaifpe, 88 | error_internal, 89 | error_ionaifpe, 90 | error_loxce, 91 | error_loxnbe, 92 | error_loxuoe, 93 | error_loxudfe, 94 | error_loxupfe, 95 | error_loxuafe, 96 | error_litl, 97 | error_loxdse, 98 | error_loxee, 99 | error_loxlve, 100 | error_loxpe, 101 | error_loxspoe, 102 | error_micuwn, 103 | error_nce, 104 | error_nprf, 105 | error_ocmbf1tx, 106 | error_odo, 107 | error_oefl, 108 | error_oex, 109 | error_oexl, 110 | error_oinah, 111 | error_omblc, 112 | error_pclo, 113 | error_rainl, 114 | error_raioor, 115 | error_rinah, 116 | error_rinaiom, 117 | error_safms, 118 | error_sccx, 119 | error_scmr, 120 | error_sdcobu, 121 | error_sexc, 122 | error_siad, 123 | error_snah, 124 | error_sombl, 125 | error_sombs, 126 | error_srccex, 127 | error_ssaf, 128 | error_stif, 129 | error_tioawarb, 130 | error_tmsc, 131 | error_tmscc, 132 | error_tmvsid, 133 | error_uc, 134 | error_urs, 135 | error_us, 136 | error_vnao 137 | }; 138 | 139 | extern const char* g_pErrorStrings[]; 140 | 141 | #endif // _ERROR_STRINGS_H_ 142 | 143 | /////////////////////////////////////////////////////////////////////////////////////////// 144 | // TERMS OF USE: MIT License // 145 | /////////////////////////////////////////////////////////////////////////////////////////// 146 | // Permission is hereby granted, free of charge, to any person obtaining a copy of this // 147 | // software and associated documentation files (the "Software"), to deal in the Software // 148 | // without restriction, including without limitation the rights to use, copy, modify, // 149 | // merge, publish, distribute, sublicense, and/or sell copies of the Software, and to // 150 | // permit persons to whom the Software is furnished to do so, subject to the following // 151 | // conditions: // 152 | // // 153 | // The above copyright notice and this permission notice shall be included in all copies // 154 | // or substantial portions of the Software. // 155 | // // 156 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, // 157 | // INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A // 158 | // PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT // 159 | // HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION // 160 | // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE // 161 | // SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. // 162 | /////////////////////////////////////////////////////////////////////////////////////////// 163 | -------------------------------------------------------------------------------- /PropellerCompiler/Makefile: -------------------------------------------------------------------------------- 1 | # cross compilation scheme taken from Eric Smith's spin2cpp compiler 2 | # if CROSS is defined, we are building a cross compiler 3 | # possible targets are: win32, rpi 4 | 5 | ifeq ($(CC),) 6 | CC=gcc 7 | endif 8 | 9 | ifeq ($(CXX),) 10 | CXX=g++ 11 | endif 12 | 13 | ifeq ($(CROSS),win32) 14 | CC=i686-w64-mingw32-gcc 15 | CXX=i686-w64-mingw32-g++ 16 | EXT=.exe 17 | BUILD=./build-win32 18 | else ifeq ($(CROSS),rpi) 19 | CC=arm-linux-gnueabihf-gcc 20 | CXX=arm-linux-gnueabihf-g++ 21 | EXT= 22 | BUILD=./build-rpi 23 | else 24 | EXT= 25 | BUILD=./build 26 | endif 27 | 28 | OS:=$(shell uname) 29 | 30 | ifeq ($(OS),Darwin) 31 | CFLAGS+=-Wall -g -Wno-self-assign 32 | else 33 | CFLAGS+=-Wall -g $(MSTATIC) 34 | endif 35 | CXXFLAGS += $(CFLAGS) 36 | 37 | LIBNAME=$(BUILD)/libopenspin.a 38 | SRCDIR=. 39 | OBJ=$(BUILD)/BlockNestStackRoutines.o \ 40 | $(BUILD)/CompileDatBlocks.o \ 41 | $(BUILD)/CompileExpression.o \ 42 | $(BUILD)/CompileInstruction.o \ 43 | $(BUILD)/CompileUtilities.o \ 44 | $(BUILD)/DistillObjects.o \ 45 | $(BUILD)/Elementizer.o \ 46 | $(BUILD)/ErrorStrings.o \ 47 | $(BUILD)/ExpressionResolver.o \ 48 | $(BUILD)/InstructionBlockCompiler.o \ 49 | $(BUILD)/StringConstantRoutines.o \ 50 | $(BUILD)/SymbolEngine.o \ 51 | $(BUILD)/Utilities.o \ 52 | $(BUILD)/UnusedMethodUtils.o \ 53 | $(BUILD)/PropellerCompiler.o \ 54 | $(BUILD)/CompileSpin.o \ 55 | $(BUILD)/flexbuf.o \ 56 | $(BUILD)/preprocess.o \ 57 | $(BUILD)/textconvert.o \ 58 | $(BUILD)/objectheap.o 59 | 60 | 61 | all: $(BUILD) $(LIBNAME) Makefile 62 | 63 | $(LIBNAME): $(OBJ) 64 | $(AR) rs $@ $^ 65 | 66 | $(BUILD)/%.o: $(SRCDIR)/%.cpp 67 | $(CXX) $(CXXFLAGS) -o $@ -c $< 68 | 69 | $(BUILD): 70 | mkdir -p $(BUILD) 71 | 72 | clean: 73 | rm -rf $(BUILD) 74 | -------------------------------------------------------------------------------- /PropellerCompiler/PropellerCompiler.h: -------------------------------------------------------------------------------- 1 | ////////////////////////////////////////////////////////////// 2 | // // 3 | // Propeller Spin/PASM Compiler // 4 | // (c)2012-2016 Parallax Inc. DBA Parallax Semiconductor. // 5 | // Adapted from Chip Gracey's x86 asm code by Roy Eltham // 6 | // See end of file for terms of use. // 7 | // // 8 | ////////////////////////////////////////////////////////////// 9 | // 10 | // PropellerCompiler.h 11 | // 12 | 13 | #ifndef _PROPELLER_COMPILER_H_ 14 | #define _PROPELLER_COMPILER_H_ 15 | 16 | #include "UnusedMethodUtils.h" 17 | 18 | // 19 | // OpenSpin code uses _stricmp() which is the VC++ name for the function. 20 | // this needs to be remapped to stricmp or strcasecmp depending on the compiler and OS being compiled on 21 | // GCC prior to version 4.8 have strcasecmp on both linux and windows 22 | // GCC 4.8 and newer on linux appears to still have strcasecmp, but GCC 4.8 and newer on windows does not (it has stricmp instead) 23 | // 24 | #if defined(__linux__) 25 | // we are on linux, then always use strcasecmp 26 | #define _stricmp strcasecmp 27 | #else 28 | #if __GNUC__ 29 | // if GCC version is 4.8 or greater use stricmp, else use strcasecmp 30 | #if __GNUC__ > 4 || (__GNUC__ == 4 && (__GNUC_MINOR__ >= 8 )) 31 | #define _stricmp stricmp 32 | #else 33 | #define _stricmp strcasecmp 34 | #endif 35 | #endif 36 | #endif 37 | 38 | // 39 | // no longer compatible with Prop Tool / Propellent 40 | // 41 | 42 | #define language_version '0' 43 | #define loc_limit 0x8000 44 | #define var_limit 0x8000 45 | #define min_obj_limit 0x00020000 46 | #define file_limit 32 47 | #define data_limit 0x20000 48 | #define info_limit 1000 49 | #define distiller_limit 0x4000 50 | #define symbol_limit 256 // was 32 51 | #define pubcon_list_limit 0x8000 52 | #define block_nest_limit 8 53 | #define block_stack_limit 4096 54 | #define case_limit 256 55 | #define if_limit 16 56 | #define str_limit 256 57 | #define str_buffer_limit 0x8000 58 | 59 | 60 | enum infoType 61 | { 62 | info_con = 0, // data0 = value (must be followed by info_con_float) 63 | info_con_float, // data0 = value 64 | info_dat, // data0/1 = obj start/finish 65 | info_dat_symbol, // data0 = value, data2 = offset, data1 = size 66 | info_pub, // data0/1 = obj start/finish, data2/3 = name start/finish 67 | info_pri, // data0/1 = obj start/finish, data2/3 = name start/finish 68 | info_pub_param, // data0 = pub index, data3 = param index, data2/3 = pub name start/finish 69 | info_pri_param // data0 = pri index, data3 = param index, data2/3 = pri name start/finish 70 | }; 71 | 72 | // Propeller Compiler Interface Structure 73 | struct CompilerData 74 | { 75 | bool error; // Compilation status; error if true, success if false 76 | const char* error_msg; // Pointer to error string 77 | 78 | int compile_mode; // Compile Mode; 0 = normal compile, 1 = Propeller Development compile 79 | 80 | char* source; // Pointer to source data 81 | int source_start; // Offending item start (if error) 82 | int source_finish; // Offending item end (+1) (if error) 83 | 84 | char* list; // Pointer to list data 85 | unsigned int list_limit; // Max size of list data 86 | unsigned int list_length; // Length of list data 87 | 88 | char* doc; // Pointer to document data 89 | unsigned int doc_limit; // Max size of document data 90 | unsigned int doc_length; // Length of document data 91 | 92 | unsigned char* obj; // Object binary for currently being compiled obj 93 | int obj_ptr; // Length of Object binary 94 | int obj_limit; // size of buffer allocated for obj 95 | 96 | int obj_files; // Number of object files referenced by source 97 | char obj_filenames[file_limit*256]; // Object filenames 98 | int obj_name_start[file_limit]; // Starting char of each filename 99 | int obj_name_finish[file_limit]; // Ending character (+1) of each filename 100 | int obj_offsets[file_limit]; // Offsets of final objects in ObjData 101 | int obj_lengths[file_limit]; // Lengths of final objects in ObjData 102 | unsigned char obj_data[data_limit]; // Final top-level object binary 103 | int obj_instances[file_limit]; // Instances per filename 104 | char obj_title[256]; // Object Filename (without path) 105 | 106 | int dat_files; // Number of DAT files referenced by source 107 | char dat_filenames[file_limit*256]; // DAT filenames 108 | int dat_name_start[file_limit]; // Starting char of each filename 109 | int dat_name_finish[file_limit]; // Ending character (+1) of each filename 110 | int dat_offsets[file_limit]; // Offsets of final objects in DatData 111 | int dat_lengths[file_limit]; // Lengths of final objects in DatData 112 | unsigned char dat_data[data_limit]; // Binary data 113 | 114 | int pre_files; // Number of Precompile files referenced by source 115 | char pre_filenames[file_limit*256]; // Precompile filenames 116 | int pre_name_start[file_limit]; // Starting char of each filename 117 | int pre_name_finish[file_limit]; // Ending character (+1) of each filename 118 | 119 | int arc_files; // Number of Archive files referenced by source 120 | char arc_filenames[file_limit*256]; // Archive filenames 121 | int arc_name_start[file_limit]; // Starting char of each filename 122 | int arc_name_finish[file_limit]; // Ending character (+1) of each filename 123 | 124 | int info_count; // Number of information records for object 125 | int info_start[info_limit]; // Start of source related to this info 126 | int info_finish[info_limit]; // End (+1) of source related to this info 127 | int info_type[info_limit]; // 0 = CON, 1 CON(float), 2 = DAT, 3 = DAT Symbol, 4 = PUB, 5 = PRI, 6 = PUB_PARAM, 7 = PRI_PARAM 128 | int info_data0[info_limit]; // Info field 0: if CON = Value, if DAT/PUB/PRI = Start addr in object, if DAT Symbol = value, if PARAM = pub/pri index 129 | int info_data1[info_limit]; // Info field 1: if DAT/PUB/PRI = End+1 addr in object, if DAT Symbol = size, if PARAM = param index 130 | int info_data2[info_limit]; // Info field 2: if PUB/PRI/PARAM = Start of pub/pri name in source, if DAT Symbol = offset (in cog) 131 | int info_data3[info_limit]; // Info field 3: if PUB/PRI/PARAM = End+1 of pub/pri name in source 132 | int info_data4[info_limit]; // Info field 4: if PUB/PRI = index|param count 133 | 134 | int distilled_longs; // Total longs optimized out of object 135 | unsigned char first_pub_parameters; 136 | int stack_requirement; // Stack requirement for top-level object 137 | 138 | unsigned char clkmode; 139 | int clkfreq; 140 | int debugbaud; // 0 = no debug, > 0 = debug at DebugBaud rate 141 | 142 | bool bDATonly; // only compile DAT sections (into obj) 143 | 144 | // only add new stuff below here 145 | 146 | bool bBinary; // true for binary, false for eeprom 147 | 148 | unsigned int eeprom_size; // size of eeprom 149 | unsigned int vsize; // used to hold last vsize (in case it is greater than 65536) 150 | unsigned int psize; // used to hold last psize (in case it is greater than 65536) 151 | 152 | char current_filename[256]; // name of object being compiled at the moment 153 | bool bUnusedMethodElimination; // true if unused method elimination is on 154 | bool bFinalCompile; // set to true after unused method scan complete 155 | 156 | int unused_obj_files; // number of unused object files 157 | char obj_unused[file_limit*256]; // hold filenames of unused objects 158 | 159 | int unused_methods; // number of unused methods 160 | char method_unused[32*file_limit*symbol_limit]; // hold names of unused methods 161 | 162 | char* current_file_path; // full path of the current file being compiled (points to entries in s_filesAccessed[]) 163 | }; 164 | 165 | // public functions 166 | extern CompilerData* InitStruct(); 167 | extern void Cleanup(); 168 | extern const char* Compile1(); 169 | extern const char* Compile2(); 170 | extern bool GetErrorInfo(int& lineNumber, int& column, int& offsetToStartOfLine, int& offsetToEndOfLine, int& offendingItemStart, int& offendingItemEnd); 171 | 172 | #endif // _PROPELLER_COMPILER_H_ 173 | 174 | /////////////////////////////////////////////////////////////////////////////////////////// 175 | // TERMS OF USE: MIT License // 176 | /////////////////////////////////////////////////////////////////////////////////////////// 177 | // Permission is hereby granted, free of charge, to any person obtaining a copy of this // 178 | // software and associated documentation files (the "Software"), to deal in the Software // 179 | // without restriction, including without limitation the rights to use, copy, modify, // 180 | // merge, publish, distribute, sublicense, and/or sell copies of the Software, and to // 181 | // permit persons to whom the Software is furnished to do so, subject to the following // 182 | // conditions: // 183 | // // 184 | // The above copyright notice and this permission notice shall be included in all copies // 185 | // or substantial portions of the Software. // 186 | // // 187 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, // 188 | // INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A // 189 | // PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT // 190 | // HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION // 191 | // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE // 192 | // SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. // 193 | /////////////////////////////////////////////////////////////////////////////////////////// 194 | -------------------------------------------------------------------------------- /PropellerCompiler/PropellerCompilerInternal.h: -------------------------------------------------------------------------------- 1 | ////////////////////////////////////////////////////////////// 2 | // // 3 | // Propeller Spin/PASM Compiler // 4 | // (c)2012-2016 Parallax Inc. DBA Parallax Semiconductor. // 5 | // Adapted from Chip Gracey's x86 asm code by Roy Eltham // 6 | // See end of file for terms of use. // 7 | // // 8 | ////////////////////////////////////////////////////////////// 9 | // 10 | // PropellerCompilerInternal.h 11 | // 12 | 13 | #ifndef _PROPELLER_COMPILER_INTERNAL_H_ 14 | #define _PROPELLER_COMPILER_INTERNAL_H_ 15 | 16 | #include "PropellerCompiler.h" 17 | 18 | struct CompilerDataInternal : public CompilerData 19 | { 20 | // this stuff is misc globals from around the asm code 21 | 22 | int var_byte; 23 | int var_word; 24 | int var_long; 25 | int var_ptr; 26 | 27 | int obj_start; 28 | int obj_count; 29 | 30 | int asm_local; 31 | 32 | unsigned char pubcon_list[pubcon_list_limit]; 33 | int pubcon_list_size; 34 | 35 | char symbolBackup[symbol_limit+2]; // used when entering a symbol into the symbol table 36 | 37 | bool doc_flag; 38 | bool doc_mode; 39 | 40 | int cog_org; 41 | 42 | int print_length; 43 | 44 | // these are used by EnterInfo() to fill in info_* stuff above 45 | // various code fills these in and then calls EnterInfo() 46 | // I kept it this way because at the point the code calls EnterInfo() it doesn't 47 | // always have the values available to just pass as parameters. 48 | int inf_start; // Start of source related to this info 49 | int inf_finish; // End (+1) of source related to this info 50 | int inf_type; // 0 = CON, 1 CON(float), 2 = DAT, 3 = DAT Symbol, 4 = PUB, 5 = PRI, 6 = PUB_PARAM, 7 = PRI_PARAM 51 | int inf_data0; // Info field 0: if CON = Value, if DAT/PUB/PRI = Start addr in object, if DAT Symbol = value, if PARAM = pub/pri index 52 | int inf_data1; // Info field 1: if DAT/PUB/PRI = End+1 addr in object, if DAT Symbol = size, if PARAM = param index 53 | int inf_data2; // Info field 2: if PUB/PRI/PARAM = Start of pub/pri name in source, if DAT Symbol = offset (in cog) 54 | int inf_data3; // Info field 3: if PUB/PRI/PARAM = End+1 of pub/pri name in source 55 | int inf_data4; // Info field 4: if PUB/PRI = index|param count 56 | 57 | // used by GetFileName/AddFileName 58 | char filename[255]; 59 | 60 | // these are used by the CompileConBlocks() code 61 | int enum_valid; 62 | int enum_value; 63 | int assign_flag; 64 | int assign_type; 65 | int assign_value; 66 | 67 | // used by CompileDatBlocks code 68 | int orgx; 69 | 70 | // used by ResolveExpression code 71 | int intMode; // 0 = uncommitted, 1 = int mode, 2 = float mode 72 | int precedence; // current precedence 73 | bool bMustResolve; // the expression must resolve 74 | bool bUndefined; // the expression is undefined 75 | bool bOperandMode; // when dealing with a PASM operand 76 | int mathCurrent; // index into mathStack[] 77 | int mathStack[16]; // holds the intermediate values during expression resolving 78 | int intermediateResult; // the current intermediate result 79 | int currentOp; // index into savedOp[] 80 | int savedOp[32]; // stack of operations to perform during expression resolving 81 | 82 | // used by Object Distiller (DistillObjects.cpp) 83 | int dis_ptr; 84 | unsigned short dis[distiller_limit]; 85 | 86 | // used for string constant processing (StringConstantRoutines.cpp) 87 | bool str_enable; 88 | bool str_patch_enable; 89 | int str_count; 90 | int str_buffer_ptr; 91 | unsigned char str_buffer[str_buffer_limit]; 92 | int str_source[str_limit]; 93 | int str_patch[str_limit]; 94 | int str_offset[str_limit]; 95 | int str_index; 96 | 97 | // used by InstructionBlockCompiler.cpp & BlockNestStackRoutines.cpp 98 | int bnest_ptr; 99 | unsigned char bnest_type[block_nest_limit]; 100 | int bstack_ptr; 101 | int bstack_base[block_nest_limit]; 102 | int bstack[block_stack_limit]; 103 | }; 104 | 105 | class Elementizer; 106 | class SymbolEngine; 107 | 108 | // shared globals 109 | extern Elementizer* g_pElementizer; 110 | extern CompilerDataInternal* g_pCompilerData; 111 | extern SymbolEngine* g_pSymbolEngine; 112 | 113 | #endif // _PROPELLER_COMPILER_INTERNAL_H_ 114 | 115 | /////////////////////////////////////////////////////////////////////////////////////////// 116 | // TERMS OF USE: MIT License // 117 | /////////////////////////////////////////////////////////////////////////////////////////// 118 | // Permission is hereby granted, free of charge, to any person obtaining a copy of this // 119 | // software and associated documentation files (the "Software"), to deal in the Software // 120 | // without restriction, including without limitation the rights to use, copy, modify, // 121 | // merge, publish, distribute, sublicense, and/or sell copies of the Software, and to // 122 | // permit persons to whom the Software is furnished to do so, subject to the following // 123 | // conditions: // 124 | // // 125 | // The above copyright notice and this permission notice shall be included in all copies // 126 | // or substantial portions of the Software. // 127 | // // 128 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, // 129 | // INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A // 130 | // PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT // 131 | // HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION // 132 | // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE // 133 | // SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. // 134 | /////////////////////////////////////////////////////////////////////////////////////////// 135 | -------------------------------------------------------------------------------- /PropellerCompiler/PropellerCompiler_vs2015.vcxproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | Debug 6 | Win32 7 | 8 | 9 | Release 10 | Win32 11 | 12 | 13 | 14 | {DE0E4A74-1C7F-4479-918D-9040BB599F90} 15 | PropellerCompiler 16 | Win32Proj 17 | PropellerCompiler 18 | 19 | 20 | 21 | StaticLibrary 22 | v140 23 | Unicode 24 | true 25 | 26 | 27 | StaticLibrary 28 | v140 29 | Unicode 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | <_ProjectFileVersion>12.0.30501.0 43 | 44 | 45 | $(SolutionDir)$(Configuration)\ 46 | $(Configuration)\ 47 | 48 | 49 | $(SolutionDir)$(Configuration)\ 50 | $(Configuration)\ 51 | 52 | 53 | 54 | Disabled 55 | WIN32;_DEBUG;_LIB;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions) 56 | true 57 | EnableFastChecks 58 | MultiThreadedDebug 59 | 60 | false 61 | 62 | Level4 63 | EditAndContinue 64 | true 65 | 66 | 67 | 68 | 69 | MaxSpeed 70 | true 71 | WIN32;NDEBUG;_LIB;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions) 72 | MultiThreaded 73 | true 74 | 75 | false 76 | 77 | Level3 78 | ProgramDatabase 79 | true 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | 120 | 121 | 122 | -------------------------------------------------------------------------------- /PropellerCompiler/PropellerCompiler_vs2017.vcxproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | Debug 6 | Win32 7 | 8 | 9 | Debug 10 | x64 11 | 12 | 13 | Release 14 | Win32 15 | 16 | 17 | Release 18 | x64 19 | 20 | 21 | 22 | {DE0E4A74-1C7F-4479-918D-9040BB599F90} 23 | PropellerCompiler 24 | Win32Proj 25 | PropellerCompiler 26 | 27 | 28 | 29 | StaticLibrary 30 | v141 31 | Unicode 32 | true 33 | 34 | 35 | StaticLibrary 36 | v141 37 | Unicode 38 | true 39 | 40 | 41 | StaticLibrary 42 | v141 43 | Unicode 44 | 45 | 46 | StaticLibrary 47 | v141 48 | Unicode 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | <_ProjectFileVersion>12.0.30501.0 68 | 69 | 70 | $(SolutionDir)$(Configuration)\ 71 | $(Configuration)\ 72 | 73 | 74 | 75 | $(SolutionDir)$(Configuration)\ 76 | $(Configuration)\ 77 | 78 | 79 | 80 | Disabled 81 | WIN32;_DEBUG;_LIB;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions) 82 | true 83 | EnableFastChecks 84 | MultiThreadedDebug 85 | 86 | false 87 | 88 | Level4 89 | EditAndContinue 90 | true 91 | 92 | 93 | 94 | 95 | Disabled 96 | WIN32;_DEBUG;_LIB;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions) 97 | EnableFastChecks 98 | MultiThreadedDebug 99 | 100 | 101 | false 102 | 103 | 104 | Level4 105 | ProgramDatabase 106 | true 107 | 108 | 109 | 110 | 111 | MaxSpeed 112 | true 113 | WIN32;NDEBUG;_LIB;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions) 114 | MultiThreaded 115 | true 116 | 117 | false 118 | 119 | Level3 120 | ProgramDatabase 121 | true 122 | 123 | 124 | 125 | 126 | MaxSpeed 127 | true 128 | WIN32;NDEBUG;_LIB;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions) 129 | MultiThreaded 130 | true 131 | 132 | 133 | false 134 | 135 | 136 | Level3 137 | ProgramDatabase 138 | true 139 | 140 | 141 | 142 | 143 | 144 | 145 | 146 | 147 | 148 | 149 | 150 | 151 | 152 | 153 | 154 | 155 | 156 | 157 | 158 | 159 | 160 | 161 | 162 | 163 | 164 | 165 | 166 | 167 | 168 | 169 | 170 | 171 | 172 | 173 | 174 | 175 | 176 | 177 | 178 | 179 | 180 | 181 | -------------------------------------------------------------------------------- /PropellerCompiler/StringConstantRoutines.cpp: -------------------------------------------------------------------------------- 1 | ////////////////////////////////////////////////////////////// 2 | // // 3 | // Propeller Spin/PASM Compiler // 4 | // (c)2012-2016 Parallax Inc. DBA Parallax Semiconductor. // 5 | // Adapted from Chip Gracey's x86 asm code by Roy Eltham // 6 | // See end of file for terms of use. // 7 | // // 8 | ////////////////////////////////////////////////////////////// 9 | // 10 | // StringConstantRoutines.cpp 11 | // 12 | 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include "Utilities.h" 18 | #include "PropellerCompilerInternal.h" 19 | #include "SymbolEngine.h" 20 | #include "Elementizer.h" 21 | #include "ErrorStrings.h" 22 | 23 | void StringConstant_PreProcess() 24 | { 25 | g_pCompilerData->str_enable = true; 26 | g_pCompilerData->str_patch_enable = true; 27 | g_pCompilerData->str_count = 0; 28 | g_pCompilerData->str_buffer_ptr = 0; 29 | } 30 | 31 | bool StringConstant_GetIndex() 32 | { 33 | int strIndex = 0; 34 | for (strIndex = 0; strIndex < g_pCompilerData->str_count; strIndex++) 35 | { 36 | if (g_pCompilerData->str_source[strIndex] == g_pCompilerData->source_start) 37 | { 38 | break; 39 | } 40 | } 41 | 42 | if (strIndex == g_pCompilerData->str_count) 43 | { 44 | // new string constant 45 | if (g_pCompilerData->str_count > str_limit) 46 | { 47 | g_pCompilerData->error = true; 48 | g_pCompilerData->error_msg = g_pErrorStrings[error_tmsc]; 49 | return false; 50 | } 51 | g_pCompilerData->str_count++; 52 | g_pCompilerData->str_source[strIndex] = g_pCompilerData->source_start; 53 | g_pCompilerData->str_offset[strIndex] = g_pCompilerData->str_buffer_ptr; 54 | } 55 | else 56 | { 57 | // old 58 | g_pCompilerData->str_buffer_ptr = g_pCompilerData->str_offset[strIndex]; 59 | } 60 | 61 | g_pCompilerData->str_index = strIndex; 62 | 63 | return true; 64 | } 65 | 66 | bool StringConstant_EnterChar(unsigned char theChar) 67 | { 68 | if (g_pCompilerData->str_buffer_ptr >= str_buffer_limit) 69 | { 70 | g_pCompilerData->error = true; 71 | g_pCompilerData->error_msg = g_pErrorStrings[error_tmscc]; 72 | return false; 73 | } 74 | g_pCompilerData->str_buffer[g_pCompilerData->str_buffer_ptr++] = theChar; 75 | return true; 76 | } 77 | 78 | void StringConstant_EnterPatch() 79 | { 80 | if (g_pCompilerData->str_patch_enable) 81 | { 82 | g_pCompilerData->str_patch[g_pCompilerData->str_index] = g_pCompilerData->obj_ptr; 83 | } 84 | } 85 | 86 | bool StringConstant_PostProcess() 87 | { 88 | if (g_pCompilerData->str_count > 0) 89 | { 90 | // patch string addresses 91 | int strIndex = 0; 92 | while(g_pCompilerData->str_count > 0) 93 | { 94 | int temp = g_pCompilerData->obj_ptr; 95 | temp += g_pCompilerData->str_offset[strIndex]; 96 | temp |= 0x8000; 97 | //short strAddress = ((temp & 0xFF00) >> 8) | ((temp & 0x00FF) << 8); // xchg ah,al 98 | //*((short*)&(g_pCompilerData->obj[g_pCompilerData->str_patch[strIndex]])) = strAddress; 99 | g_pCompilerData->obj[g_pCompilerData->str_patch[strIndex]] = (unsigned char)((temp >> 8) & 0xFF); 100 | g_pCompilerData->obj[g_pCompilerData->str_patch[strIndex] + 1] = (unsigned char)(temp & 0xFF); 101 | strIndex++; 102 | g_pCompilerData->str_count--; 103 | } 104 | 105 | // enter strings into obj 106 | for (int i = 0; i < g_pCompilerData->str_buffer_ptr; i++) 107 | { 108 | if (!EnterObj(g_pCompilerData->str_buffer[i])) 109 | { 110 | return false; 111 | } 112 | } 113 | } 114 | return true; 115 | } 116 | 117 | /////////////////////////////////////////////////////////////////////////////////////////// 118 | // TERMS OF USE: MIT License // 119 | /////////////////////////////////////////////////////////////////////////////////////////// 120 | // Permission is hereby granted, free of charge, to any person obtaining a copy of this // 121 | // software and associated documentation files (the "Software"), to deal in the Software // 122 | // without restriction, including without limitation the rights to use, copy, modify, // 123 | // merge, publish, distribute, sublicense, and/or sell copies of the Software, and to // 124 | // permit persons to whom the Software is furnished to do so, subject to the following // 125 | // conditions: // 126 | // // 127 | // The above copyright notice and this permission notice shall be included in all copies // 128 | // or substantial portions of the Software. // 129 | // // 130 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, // 131 | // INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A // 132 | // PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT // 133 | // HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION // 134 | // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE // 135 | // SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. // 136 | /////////////////////////////////////////////////////////////////////////////////////////// 137 | -------------------------------------------------------------------------------- /PropellerCompiler/SymbolEngine.h: -------------------------------------------------------------------------------- 1 | ////////////////////////////////////////////////////////////// 2 | // // 3 | // Propeller Spin/PASM Compiler // 4 | // (c)2012-2016 Parallax Inc. DBA Parallax Semiconductor. // 5 | // Adapted from Chip Gracey's x86 asm code by Roy Eltham // 6 | // See end of file for terms of use. // 7 | // // 8 | ////////////////////////////////////////////////////////////// 9 | // 10 | // SymbolEngine.h 11 | // 12 | 13 | #ifndef _SYMBOL_ENGINE_H_ 14 | #define _SYMBOL_ENGINE_H_ 15 | 16 | #include "Utilities.h" 17 | 18 | enum symbol_Type 19 | { 20 | type_undefined = 0, // (undefined symbol, must be 0) 21 | type_left, // ( 22 | type_right, // ) 23 | type_leftb, // [ 24 | type_rightb, // ] 25 | type_comma, // , 26 | type_equal, // = 27 | type_pound, // # 28 | type_colon, // : 29 | type_back, /* \ */ 30 | type_dot, // . 31 | type_dotdot, // .. 32 | type_at, // @ 33 | type_atat, // @@ 34 | type_til, // ~ 35 | type_tiltil, // ~~ 36 | type_rnd, // ? 37 | type_inc, // ++ 38 | type_dec, // -- 39 | type_assign, // := 40 | type_spr, // SPR 41 | type_unary, // -, !, ||, etc. 42 | type_binary, // +, -, *, /, etc. 43 | type_float, // FLOAT 44 | type_round, // ROUND 45 | type_trunc, // TRUNC 46 | type_conexp, // CONSTANT 47 | type_constr, // STRING 48 | type_block, // CON, VAR, DAT, OBJ, PUB, PRI 49 | type_size, // BYTE, WORD, LONG 50 | type_precompile, // PRECOMPILE 51 | type_archive, // ARCHIVE 52 | type_file, // FILE 53 | type_if, // IF 54 | type_ifnot, // IFNOT 55 | type_elseif, // ELSEIF 56 | type_elseifnot, // ELSEIFNOT 57 | type_else, // ELSE 58 | type_case, // CASE 59 | type_other, // OTHER 60 | type_repeat, // REPEAT 61 | type_repeat_count, // REPEAT count - different QUIT method 62 | type_while, // WHILE 63 | type_until, // UNTIL 64 | type_from, // FROM 65 | type_to, // TO 66 | type_step, // STEP 67 | type_i_next_quit, // NEXT/QUIT 68 | type_i_abort_return, // ABORT/RETURN 69 | type_i_look, // LOOKUP/LOOKDOWN 70 | type_i_clkmode, // CLKMODE 71 | type_i_clkfreq, // CLKFREQ 72 | type_i_chipver, // CHIPVER 73 | type_i_reboot, // REBOOT 74 | type_i_cogid, // COGID 75 | type_i_cognew, // COGNEW 76 | type_i_coginit, // COGINIT 77 | type_i_ar, // STRSIZE, STRCOMP - always returns value 78 | type_i_cr, // LOCKNEW, LOCKCLR, LOCKSET - can return value 79 | type_i_nr, // BYTEFILL, WORDFILL, LONGFILL, etc. - never returns value 80 | type_dual, // WAITPEQ, WAITPNE, etc. - type_asm_inst or type_i_??? 81 | type_asm_org, // $ (without a hex digit following) 82 | type_asm_dir, // ORGX, ORG, RES, FIT, NOP 83 | type_asm_cond, // IF_C, IF_Z, IF_NC, etc 84 | type_asm_inst, // RDBYTE, RDWORD, RDLONG, etc. 85 | type_asm_effect, // WZ, WC, WR, NR 86 | type_reg, // PAR, CNT, INA, etc. 87 | type_con, // user constant integer (must be followed by type_con_float) 88 | type_con_float, // user constant float 89 | type_var_byte, // V0user byte var 90 | type_var_word, // V1user word var 91 | type_var_long, // V2user long var 92 | type_dat_byte, // D0user byte dat 93 | type_dat_word, // D1user word dat 94 | type_dat_long, // D2user long dat 95 | type_dat_long_res, // (D2)user res dat (must follow type_dat_long) 96 | type_loc_byte, // L0user byte local 97 | type_loc_word, // L1user word local 98 | type_loc_long, // L2user long local 99 | type_obj, // user object 100 | type_objpub, // user object.subroutine 101 | type_objcon, // user object.constant (must be followed by type_objcon_float) 102 | type_objcon_float, // user object.constant float 103 | type_sub, // user subroutine 104 | type_end // end-of-line c=0, end-of-file c=1 105 | }; 106 | 107 | enum block_Type 108 | { 109 | block_con = 0, 110 | block_var, 111 | block_dat, 112 | block_obj, 113 | block_pub, 114 | block_pri, 115 | block_dev, 116 | }; 117 | 118 | enum operator_Type 119 | { 120 | op_ror = 0, // operator precedences (0=priority) 121 | op_rol, // 122 | op_shr, // 0= -, !, ||, >|, |<, ^^ (unary) 123 | op_shl, // 1= ->, <-, >>, << ~>, >< 124 | op_min, // 2= & 125 | op_max, // 3= |, ^ 126 | op_neg, // 4= *, **, /, // 127 | op_not, // 5= +, - 128 | op_and, // 6= #>, <# 129 | op_abs, // 7= <, >, <>, ==, =<, => 130 | op_or, // 8= NOT (unary) 131 | op_xor, // 9= AND 132 | op_add, // 10= OR 133 | op_sub, 134 | op_sar, 135 | op_rev, 136 | op_log_and, 137 | op_ncd, 138 | op_log_or, 139 | op_dcd, 140 | op_mul, 141 | op_scl, 142 | op_div, 143 | op_rem, 144 | op_sqr, 145 | op_cmp_b, 146 | op_cmp_a, 147 | op_cmp_ne, 148 | op_cmp_e, 149 | op_cmp_be, 150 | op_cmp_ae, 151 | op_log_not 152 | }; 153 | 154 | enum directives_Type 155 | { 156 | dir_orgx = 0, 157 | dir_org, 158 | dir_res, 159 | dir_fit, 160 | dir_nop 161 | }; 162 | 163 | enum if_Type 164 | { 165 | if_never = 0, 166 | if_nc_and_nz, 167 | if_nc_and_z, 168 | if_nc, 169 | if_c_and_nz, 170 | if_nz, 171 | if_c_ne_z, 172 | if_nc_or_nz, 173 | if_c_and_z, 174 | if_c_eq_z, 175 | if_z, 176 | if_nc_or_z, 177 | if_c, 178 | if_c_or_nz, 179 | if_c_or_z, 180 | if_always, 181 | }; 182 | 183 | struct SymbolTableEntryDataTable 184 | { 185 | symbol_Type type; // what type of symbol is it? 186 | int value; // value is type dependant 187 | const char* name; // the string of the symbol 188 | unsigned char operator_type_or_asm; // operator type for op symbols, or asm value for dual symbols 189 | bool dual; // indicates that this symbol is used by both PASM and spin 190 | }; 191 | 192 | struct SymbolTableEntryData 193 | { 194 | symbol_Type type; // what type of symbol is it? 195 | int value; // value is type dependant 196 | int value_2; // value 2 is type dependant 197 | char* name; // the string of the symbol 198 | unsigned char operator_type_or_asm; // operator type for op symbols, or asm value for dual symbols 199 | bool dual; // indicates that this symbol is used by both PASM and spin 200 | }; 201 | 202 | class SymbolTableEntry : public Hashable 203 | { 204 | public: 205 | SymbolTableEntry() 206 | { 207 | m_data.name = 0; 208 | } 209 | SymbolTableEntry(const SymbolTableEntryDataTable& data); 210 | ~SymbolTableEntry() 211 | { 212 | delete [] m_data.name; 213 | } 214 | SymbolTableEntryData m_data; 215 | }; 216 | 217 | class SymbolEngine 218 | { 219 | HashTable* m_pSymbols; // predefined symbols 220 | HashTable* m_pUserSymbols; // any symbols defined during compiling 221 | HashTable* m_pTempUserSymbols; // used for locals during CompileSubBlocks 222 | 223 | public: 224 | SymbolEngine(); 225 | ~SymbolEngine(); 226 | 227 | SymbolTableEntry* FindSymbol(const char* pSymbolName); 228 | 229 | void AddSymbol(const char* pSymbolName, symbol_Type type, int value, int value_2 = 0, bool bTemp = false); 230 | void Reset(bool bTempsOnly = false); 231 | }; 232 | 233 | #endif // _SYMBOL_ENGINE_H_ 234 | 235 | /////////////////////////////////////////////////////////////////////////////////////////// 236 | // TERMS OF USE: MIT License // 237 | /////////////////////////////////////////////////////////////////////////////////////////// 238 | // Permission is hereby granted, free of charge, to any person obtaining a copy of this // 239 | // software and associated documentation files (the "Software"), to deal in the Software // 240 | // without restriction, including without limitation the rights to use, copy, modify, // 241 | // merge, publish, distribute, sublicense, and/or sell copies of the Software, and to // 242 | // permit persons to whom the Software is furnished to do so, subject to the following // 243 | // conditions: // 244 | // // 245 | // The above copyright notice and this permission notice shall be included in all copies // 246 | // or substantial portions of the Software. // 247 | // // 248 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, // 249 | // INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A // 250 | // PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT // 251 | // HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION // 252 | // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE // 253 | // SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. // 254 | /////////////////////////////////////////////////////////////////////////////////////////// 255 | -------------------------------------------------------------------------------- /PropellerCompiler/UnusedMethodUtils.h: -------------------------------------------------------------------------------- 1 | /////////////////////////////////////////////////////////////// 2 | // // 3 | // Propeller Spin/PASM Compiler Command Line Tool 'OpenSpin' // 4 | // (c)2012-2016 Parallax Inc. DBA Parallax Semiconductor. // 5 | // See end of file for terms of use. // 6 | // // 7 | /////////////////////////////////////////////////////////////// 8 | // 9 | // UnusedMethodUtils.h 10 | // 11 | 12 | #ifndef _UNUSEDMETHODUTILS_H_ 13 | #define _UNUSEDMETHODUTILS_H_ 14 | 15 | struct CompilerData; 16 | 17 | void AddObjectName(char* pFilename, int nCompileIndex); 18 | void FindUnusedMethods(CompilerData* pCompilerData); 19 | void CleanUpUnusedMethodData(); 20 | void InitUnusedMethodData(); 21 | 22 | bool IsObjectUsed(char* pFilename); 23 | bool IsMethodUsed(char* pFilename, int nMethod); 24 | void AddObjectPubConList(char* pFilename, unsigned char* pPubConList, int nPubConListSize); 25 | bool GetObjectPubConList(char* pFilename, unsigned char** ppPubConList, int* pnPubConListSize); 26 | 27 | void AddCogNewOrInit(char* pFilename, int nSubConstant); 28 | 29 | #endif // _UNUSEDMETHODUTILS_H_ 30 | 31 | /////////////////////////////////////////////////////////////////////////////////////////// 32 | // TERMS OF USE: MIT License // 33 | /////////////////////////////////////////////////////////////////////////////////////////// 34 | // Permission is hereby granted, free of charge, to any person obtaining a copy of this // 35 | // software and associated documentation files (the "Software"), to deal in the Software // 36 | // without restriction, including without limitation the rights to use, copy, modify, // 37 | // merge, publish, distribute, sublicense, and/or sell copies of the Software, and to // 38 | // permit persons to whom the Software is furnished to do so, subject to the following // 39 | // conditions: // 40 | // // 41 | // The above copyright notice and this permission notice shall be included in all copies // 42 | // or substantial portions of the Software. // 43 | // // 44 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, // 45 | // INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A // 46 | // PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT // 47 | // HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION // 48 | // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE // 49 | // SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. // 50 | /////////////////////////////////////////////////////////////////////////////////////////// 51 | -------------------------------------------------------------------------------- /PropellerCompiler/Utilities.h: -------------------------------------------------------------------------------- 1 | ////////////////////////////////////////////////////////////// 2 | // // 3 | // Propeller Spin/PASM Compiler // 4 | // (c)2012-2016 Parallax Inc. DBA Parallax Semiconductor. // 5 | // Adapted from Chip Gracey's x86 asm code by Roy Eltham // 6 | // See end of file for terms of use. // 7 | // // 8 | ////////////////////////////////////////////////////////////// 9 | // 10 | // Utilities.h 11 | // 12 | 13 | #ifndef _UTILITIES_H_ 14 | #define _UTILITIES_H_ 15 | 16 | extern void SetPrint(char* pDestination, int limit); 17 | extern bool PrintChr(char theChar); 18 | extern bool PrintString(const char* theString); 19 | extern bool PrintLong(int value); 20 | extern bool PrintWord(short value); 21 | extern bool PrintByte(char value); 22 | extern bool PrintHex(char value); 23 | extern bool PrintDecimal(int value); 24 | extern bool PrintSymbol(const char* pSymbolName, unsigned char type, int value, int value_2); 25 | extern bool PrintObj(); 26 | extern bool DocPrint(char theChar); 27 | 28 | extern char Uppercase(char theChar); 29 | 30 | extern bool CheckWordChar(char theChar); 31 | extern bool CheckHex(char theChar, char& digitValue); 32 | extern bool CheckDigit(char theChar, char& digitValue, char numberBase); 33 | extern bool CheckPlus(char theChar); 34 | extern bool CheckLocal(bool& bLocal); 35 | 36 | extern bool GetFloat(char* pSource, int& sourceOffset, int& value); 37 | extern bool GetSymbol(int* length); 38 | extern bool GetObjSymbol(int type, char id); 39 | 40 | extern bool GetCommaOrEnd(bool& bComma); 41 | extern bool GetCommaOrRight(bool& bComma); 42 | extern bool GetPipeOrEnd(bool& bPipe); 43 | 44 | extern bool GetFilename(int& filenameStart, int& filenameFinish); 45 | 46 | extern void EnterInfo(); 47 | extern bool EnterObj(unsigned char value); 48 | extern bool EnterObjLong(int value); 49 | 50 | extern bool IncrementAsmLocal(); 51 | 52 | extern bool AddFileName(int& fileCount, int& fileIndex, char* pFilenames, int* pNameStart, int* pNameFinish, int error); 53 | extern bool AddPubConListByte(char value); 54 | extern bool AddSymbolToPubConList(); 55 | extern bool ConAssign(bool bFloat, int value); 56 | extern bool HandleConSymbol(int pass); 57 | 58 | extern int rol(unsigned int value, int places); 59 | extern int ror(unsigned int value, int places); 60 | 61 | // these is in ExpressionResolver.cpp 62 | extern bool GetTryValue(bool bMustResolve, bool bInteger, bool bOperandMode = false); 63 | extern int GetResult(); 64 | 65 | // 66 | // Simple Hash Table (used by the Symbol Engine) 67 | // 68 | 69 | class Hashable 70 | { 71 | public: 72 | virtual ~Hashable() 73 | { 74 | } 75 | }; 76 | 77 | struct HashNode 78 | { 79 | int key; 80 | Hashable* pValue; 81 | HashNode* pNext; 82 | HashNode* pNextList; 83 | 84 | ~HashNode() 85 | { 86 | if (pNext) 87 | { 88 | delete pNext; 89 | } 90 | delete pValue; 91 | } 92 | }; 93 | 94 | class HashTable 95 | { 96 | private: 97 | HashNode** m_pTable; 98 | int m_tableSize; 99 | HashNode* m_pListHead; 100 | HashNode* m_pListTail; 101 | 102 | public: 103 | HashTable(int tableSize) 104 | : m_tableSize(tableSize) 105 | , m_pListHead(0) 106 | , m_pListTail(0) 107 | { 108 | m_pTable = new HashNode*[tableSize]; 109 | for(int i = 0; i < m_tableSize; i++) 110 | { 111 | m_pTable[i] = 0; 112 | } 113 | } 114 | ~HashTable() 115 | { 116 | for(int i = 0; i < m_tableSize; i++) 117 | { 118 | if (m_pTable[i] != 0) 119 | { 120 | delete m_pTable[i]; 121 | m_pTable[i] = 0; 122 | } 123 | } 124 | delete [] m_pTable; 125 | m_pTable = 0; 126 | m_pListHead = m_pListTail = 0; 127 | } 128 | 129 | // insert a new node in the table with the given key and value 130 | void Insert(int key, Hashable* pValue) 131 | { 132 | unsigned int bucket = (unsigned int)key % m_tableSize; 133 | 134 | HashNode* pNode = new HashNode; 135 | pNode->key = key; 136 | pNode->pValue = pValue; 137 | pNode->pNext = m_pTable[bucket]; 138 | pNode->pNextList = 0; 139 | 140 | m_pTable[bucket] = pNode; 141 | 142 | if ( m_pListTail ) 143 | { 144 | m_pListTail->pNextList = pNode; 145 | m_pListTail = pNode; 146 | } 147 | else 148 | { 149 | m_pListHead = m_pListTail = pNode; 150 | } 151 | } 152 | 153 | HashNode* First() 154 | { 155 | return m_pListHead; 156 | } 157 | 158 | HashNode* Last() 159 | { 160 | return m_pListTail; 161 | } 162 | 163 | HashNode* Next(HashNode* pCurrent) 164 | { 165 | return (pCurrent != 0) ? pCurrent->pNextList : 0; 166 | } 167 | 168 | // find the first node with a matching key 169 | // returns 0 if not found 170 | HashNode* FindFirst(int key) 171 | { 172 | unsigned int bucket = (unsigned int)key % m_tableSize; 173 | if (m_pTable[bucket] != 0) 174 | { 175 | HashNode* pNode = m_pTable[bucket]; 176 | while (pNode != 0) 177 | { 178 | if (pNode->key == key) 179 | { 180 | return pNode; 181 | } 182 | pNode = pNode->pNext; 183 | } 184 | } 185 | 186 | return 0; 187 | } 188 | 189 | // find the next node with a matching key 190 | // returns 0 if not found 191 | HashNode* FindNext(HashNode* pCurrent) 192 | { 193 | if (pCurrent->pNext != 0 && pCurrent->pNext->key == pCurrent->key) 194 | { 195 | return pCurrent->pNext; 196 | } 197 | 198 | return 0; 199 | } 200 | 201 | // calculate a hash value of a zero terminated string (uppercased) 202 | // uses Jenkins One-at-a-time hash function 203 | int GetStringHashUppercase(const char* s) 204 | { 205 | int hash = 0; 206 | while (*s != 0) 207 | { 208 | int c = *s; 209 | c = c - (32 * (c >= 'a' && c <= 'z')); 210 | hash += c; 211 | hash += (hash << 10); 212 | hash ^= (hash >> 6); 213 | s++; 214 | } 215 | hash += (hash << 3); 216 | hash ^= (hash >> 11); 217 | hash += (hash << 15); 218 | return hash; 219 | } 220 | 221 | // calculate a hash value of a zero terminated string 222 | // uses Jenkins One-at-a-time hash function 223 | int GetStringHash(const char* s) 224 | { 225 | int hash = 0; 226 | while (*s != 0) 227 | { 228 | hash += *s; 229 | hash += (hash << 10); 230 | hash ^= (hash >> 6); 231 | s++; 232 | } 233 | hash += (hash << 3); 234 | hash ^= (hash >> 11); 235 | hash += (hash << 15); 236 | return hash; 237 | } 238 | }; 239 | 240 | 241 | class HeirarchyNode 242 | { 243 | public: 244 | HeirarchyNode* m_pNextSibling; 245 | HeirarchyNode* m_pParent; 246 | 247 | HeirarchyNode() 248 | : m_pNextSibling(0) 249 | , m_pParent(0) 250 | { 251 | } 252 | 253 | ~HeirarchyNode() 254 | { 255 | if (m_pNextSibling) 256 | { 257 | delete m_pNextSibling; 258 | } 259 | } 260 | }; 261 | 262 | class Heirarchy 263 | { 264 | public: 265 | HeirarchyNode* m_pRoot; 266 | 267 | Heirarchy() 268 | : m_pRoot(0) 269 | { 270 | } 271 | ~Heirarchy() 272 | { 273 | delete m_pRoot; 274 | } 275 | 276 | void AddNode(HeirarchyNode* pValue, HeirarchyNode* pParent) 277 | { 278 | if (m_pRoot == 0) 279 | { 280 | m_pRoot = pValue; 281 | } 282 | else 283 | { 284 | if (pParent) 285 | { 286 | pValue->m_pNextSibling = pParent->m_pNextSibling; 287 | pParent->m_pNextSibling = pValue; 288 | } 289 | else 290 | { 291 | pValue->m_pNextSibling = m_pRoot->m_pNextSibling; 292 | m_pRoot->m_pNextSibling = pValue; 293 | } 294 | } 295 | } 296 | }; 297 | 298 | #endif // _UTILITIES_H_ 299 | 300 | /////////////////////////////////////////////////////////////////////////////////////////// 301 | // TERMS OF USE: MIT License // 302 | /////////////////////////////////////////////////////////////////////////////////////////// 303 | // Permission is hereby granted, free of charge, to any person obtaining a copy of this // 304 | // software and associated documentation files (the "Software"), to deal in the Software // 305 | // without restriction, including without limitation the rights to use, copy, modify, // 306 | // merge, publish, distribute, sublicense, and/or sell copies of the Software, and to // 307 | // permit persons to whom the Software is furnished to do so, subject to the following // 308 | // conditions: // 309 | // // 310 | // The above copyright notice and this permission notice shall be included in all copies // 311 | // or substantial portions of the Software. // 312 | // // 313 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, // 314 | // INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A // 315 | // PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT // 316 | // HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION // 317 | // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE // 318 | // SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. // 319 | /////////////////////////////////////////////////////////////////////////////////////////// 320 | -------------------------------------------------------------------------------- /PropellerCompiler/flexbuf.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Functions for manipulating variable sized memory buffers. 3 | * These buffers can grow and shrink as the program progresses. 4 | * 5 | * Written by Eric R. Smith 6 | * Copyright (c) 2012 Total Spectrum Software Inc. 7 | * MIT Licensed; see terms at the end of this file. 8 | */ 9 | 10 | #include "flexbuf.h" 11 | #include 12 | #include 13 | 14 | #define DEFAULT_GROWSIZE BUFSIZ 15 | 16 | void flexbuf_init(struct flexbuf *fb, size_t growsize) 17 | { 18 | fb->data = NULL; 19 | fb->len = 0; 20 | fb->space = 0; 21 | fb->growsize = growsize ? growsize : DEFAULT_GROWSIZE; 22 | } 23 | 24 | size_t flexbuf_curlen(struct flexbuf *fb) 25 | { 26 | return fb->len; 27 | } 28 | 29 | /* add a single character to a buffer */ 30 | char *flexbuf_addchar(struct flexbuf *fb, int c) 31 | { 32 | size_t newlen = fb->len + 1; 33 | 34 | if (newlen > fb->space) { 35 | char *newdata; 36 | newdata = (char *)realloc(fb->data, fb->space + fb->growsize); 37 | if (!newdata) return newdata; 38 | fb->space += fb->growsize; 39 | fb->data = newdata; 40 | } 41 | fb->data[fb->len] = (char)c; 42 | fb->len = newlen; 43 | return fb->data; 44 | } 45 | 46 | /* add N characters to a buffer */ 47 | char *flexbuf_addmem(struct flexbuf *fb, const char *buf, size_t N) 48 | { 49 | size_t newlen = fb->len + N; 50 | 51 | if (newlen > fb->space) { 52 | char *newdata; 53 | size_t newspace; 54 | newspace = fb->space + fb->growsize; 55 | if (newspace < newlen) { 56 | newspace = newlen + fb->growsize; 57 | } 58 | newdata = (char *)realloc(fb->data, newspace); 59 | if (!newdata) return newdata; 60 | fb->space = newspace; 61 | fb->data = newdata; 62 | } 63 | memcpy(fb->data + fb->len, buf, N); 64 | fb->len = newlen; 65 | return fb->data; 66 | } 67 | 68 | /* add a string to a buffer */ 69 | char *flexbuf_addstr(struct flexbuf *fb, const char *str) 70 | { 71 | return flexbuf_addmem(fb, str, strlen(str)); 72 | } 73 | 74 | /* retrieve the pointer for a flexbuf */ 75 | /* "peek" gets it but keeps it reserved; 76 | * "get" gets it and releases it from the flexbuf 77 | */ 78 | char *flexbuf_peek(struct flexbuf *fb) 79 | { 80 | char *r = fb->data; 81 | return r; 82 | } 83 | 84 | char *flexbuf_get(struct flexbuf *fb) 85 | { 86 | char *r = fb->data; 87 | flexbuf_init(fb, fb->growsize); 88 | return r; 89 | } 90 | 91 | /* reset the buffer to empty (but do not free space) */ 92 | void flexbuf_clear(struct flexbuf *fb) 93 | { 94 | fb->len = 0; 95 | } 96 | 97 | /* free the memory associated with a buffer */ 98 | void flexbuf_delete(struct flexbuf *fb) 99 | { 100 | if (fb->data) 101 | free(fb->data); 102 | flexbuf_init(fb, 1); 103 | } 104 | 105 | /* 106 | * +-------------------------------------------------------------------- 107 | * ¦ TERMS OF USE: MIT License 108 | * +-------------------------------------------------------------------- 109 | * Permission is hereby granted, free of charge, to any person obtaining 110 | * a copy of this software and associated documentation files 111 | * (the "Software"), to deal in the Software without restriction, 112 | * including without limitation the rights to use, copy, modify, merge, 113 | * publish, distribute, sublicense, and/or sell copies of the Software, 114 | * and to permit persons to whom the Software is furnished to do so, 115 | * subject to the following conditions: 116 | * 117 | * The above copyright notice and this permission notice shall be 118 | * included in all copies or substantial portions of the Software. 119 | * 120 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 121 | * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 122 | * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 123 | * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 124 | * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 125 | * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 126 | * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 127 | * +-------------------------------------------------------------------- 128 | */ 129 | -------------------------------------------------------------------------------- /PropellerCompiler/flexbuf.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Functions for manipulating variable sized memory buffers. 3 | * These buffers can grow and shrink as the program progresses. 4 | * 5 | * Written by Eric R. Smith 6 | * Copyright (c) 2012 Total Spectrum Software Inc. 7 | * See terms of use in flexbuf.c 8 | */ 9 | 10 | #ifndef FLEXBUF_H_ 11 | #define FLEXBUF_H_ 12 | #include 13 | 14 | struct flexbuf { 15 | char * data; /* current data */ 16 | size_t len; /* current length of valid data */ 17 | size_t space; /* total space available (must be >= len) */ 18 | size_t growsize; /* how much we should grow */ 19 | }; 20 | 21 | /* initialize a buffer */ 22 | void flexbuf_init(struct flexbuf *fb, size_t growsize); 23 | 24 | /* add a single character to a buffer */ 25 | /* returns a pointer to the start of the buffer, or NULL on failure */ 26 | char *flexbuf_addchar(struct flexbuf *fb, int c); 27 | 28 | /* add N characters to a buffer */ 29 | char *flexbuf_addmem(struct flexbuf *fb, const char *buf, size_t N); 30 | 31 | /* add a string to a buffer */ 32 | char *flexbuf_addstr(struct flexbuf *fb, const char *str); 33 | 34 | /* reset the buffer to empty */ 35 | void flexbuf_clear(struct flexbuf *fb); 36 | 37 | /* harvest the flexible buffer pointer for use elsewhere */ 38 | char *flexbuf_get(struct flexbuf *fb); 39 | 40 | /* like get, but does not release the buffer */ 41 | char *flexbuf_peek(struct flexbuf *fb); 42 | 43 | /* free the space associated with a buffer */ 44 | void flexbuf_delete(struct flexbuf *fb); 45 | 46 | /* find current length of a buffer */ 47 | size_t flexbuf_curlen(struct flexbuf *fb); 48 | 49 | #endif 50 | -------------------------------------------------------------------------------- /PropellerCompiler/objectheap.cpp: -------------------------------------------------------------------------------- 1 | /////////////////////////////////////////////////////////////// 2 | // // 3 | // Propeller Spin/PASM Compiler Command Line Tool 'OpenSpin' // 4 | // (c)2012-2016 Parallax Inc. DBA Parallax Semiconductor. // 5 | // Adapted from Jeff Martin's Delphi code by Roy Eltham // 6 | // See end of file for terms of use. // 7 | // // 8 | /////////////////////////////////////////////////////////////// 9 | // 10 | // objectheap.cpp 11 | // 12 | #include 13 | 14 | #include "PropellerCompiler.h" 15 | #include "objectheap.h" 16 | 17 | // Object heap (compile-time objects) 18 | struct ObjHeap 19 | { 20 | char* ObjFilename; // Full filename of object 21 | char* Obj; // Object binary 22 | int ObjSize; // Size of object 23 | }; 24 | 25 | ObjHeap s_ObjHeap[MaxObjInHeap]; 26 | int s_nObjHeapIndex = 0; 27 | 28 | bool AddObjectToHeap(char* name, CompilerData* pCompilerData) 29 | { 30 | // see if it already exists in the heap 31 | if (IndexOfObjectInHeap(name) != -1) 32 | { 33 | return true; 34 | } 35 | 36 | // add the object to the heap 37 | if (s_nObjHeapIndex < MaxObjInHeap) 38 | { 39 | int nNameBufferLength = (int)strlen(name)+1; 40 | s_ObjHeap[s_nObjHeapIndex].ObjFilename = new char[nNameBufferLength]; 41 | strcpy(s_ObjHeap[s_nObjHeapIndex].ObjFilename, name); 42 | s_ObjHeap[s_nObjHeapIndex].ObjSize = pCompilerData->obj_ptr; 43 | s_ObjHeap[s_nObjHeapIndex].Obj = new char[pCompilerData->obj_ptr]; 44 | memcpy(s_ObjHeap[s_nObjHeapIndex].Obj, &(pCompilerData->obj[0]), pCompilerData->obj_ptr); 45 | s_nObjHeapIndex++; 46 | return true; 47 | } 48 | 49 | return false; 50 | } 51 | 52 | // Returns index of object of Name in Object Heap. Returns -1 if not found. 53 | int IndexOfObjectInHeap(char* name) 54 | { 55 | for (int i = s_nObjHeapIndex-1; i >= 0; i--) 56 | { 57 | if (_stricmp(s_ObjHeap[i].ObjFilename, name) == 0) 58 | { 59 | return i; 60 | } 61 | } 62 | return -1; 63 | } 64 | 65 | void CleanObjectHeap() 66 | { 67 | for (int i = 0; i < s_nObjHeapIndex; i++) 68 | { 69 | delete [] s_ObjHeap[i].ObjFilename; 70 | s_ObjHeap[i].ObjFilename = NULL; 71 | delete [] s_ObjHeap[i].Obj; 72 | s_ObjHeap[i].Obj = NULL; 73 | s_ObjHeap[i].ObjSize = 0; 74 | } 75 | s_nObjHeapIndex = 0; 76 | } 77 | 78 | bool CopyObjectsFromHeap(CompilerData* pCompilerData, char* filenames) 79 | { 80 | // load sub-objects from heap into obj_data for Compile2() 81 | int p = 0; 82 | for (int i = 0; i < pCompilerData->obj_files; i++) 83 | { 84 | int nObjIdx = IndexOfObjectInHeap(&filenames[i<<8]); 85 | if (p + s_ObjHeap[nObjIdx].ObjSize > data_limit) 86 | { 87 | return false; 88 | } 89 | memcpy(&pCompilerData->obj_data[p], s_ObjHeap[nObjIdx].Obj, s_ObjHeap[nObjIdx].ObjSize); 90 | pCompilerData->obj_offsets[i] = p; 91 | pCompilerData->obj_lengths[i] = s_ObjHeap[nObjIdx].ObjSize; 92 | p += s_ObjHeap[nObjIdx].ObjSize; 93 | } 94 | 95 | return true; 96 | } 97 | 98 | 99 | /////////////////////////////////////////////////////////////////////////////////////////// 100 | // TERMS OF USE: MIT License // 101 | /////////////////////////////////////////////////////////////////////////////////////////// 102 | // Permission is hereby granted, free of charge, to any person obtaining a copy of this // 103 | // software and associated documentation files (the "Software"), to deal in the Software // 104 | // without restriction, including without limitation the rights to use, copy, modify, // 105 | // merge, publish, distribute, sublicense, and/or sell copies of the Software, and to // 106 | // permit persons to whom the Software is furnished to do so, subject to the following // 107 | // conditions: // 108 | // // 109 | // The above copyright notice and this permission notice shall be included in all copies // 110 | // or substantial portions of the Software. // 111 | // // 112 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, // 113 | // INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A // 114 | // PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT // 115 | // HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION // 116 | // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE // 117 | // SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. // 118 | /////////////////////////////////////////////////////////////////////////////////////////// 119 | -------------------------------------------------------------------------------- /PropellerCompiler/objectheap.h: -------------------------------------------------------------------------------- 1 | /////////////////////////////////////////////////////////////// 2 | // // 3 | // Propeller Spin/PASM Compiler Command Line Tool 'OpenSpin' // 4 | // (c)2012-2016 Parallax Inc. DBA Parallax Semiconductor. // 5 | // Adapted from Jeff Martin's Delphi code by Roy Eltham // 6 | // See end of file for terms of use. // 7 | // // 8 | /////////////////////////////////////////////////////////////// 9 | // 10 | // objectheap.h 11 | // 12 | 13 | #ifndef _OBJECTHEAP_H_ 14 | #define _OBJECTHEAP_H_ 15 | 16 | #define MaxObjInHeap 256 17 | 18 | bool AddObjectToHeap(char* name, CompilerData* pCompilerData); 19 | int IndexOfObjectInHeap(char* name); 20 | void CleanObjectHeap(); 21 | bool CopyObjectsFromHeap(CompilerData* pCompilerData, char* filenames); 22 | 23 | #endif // _OBJECTHEAP_H_ 24 | 25 | /////////////////////////////////////////////////////////////////////////////////////////// 26 | // TERMS OF USE: MIT License // 27 | /////////////////////////////////////////////////////////////////////////////////////////// 28 | // Permission is hereby granted, free of charge, to any person obtaining a copy of this // 29 | // software and associated documentation files (the "Software"), to deal in the Software // 30 | // without restriction, including without limitation the rights to use, copy, modify, // 31 | // merge, publish, distribute, sublicense, and/or sell copies of the Software, and to // 32 | // permit persons to whom the Software is furnished to do so, subject to the following // 33 | // conditions: // 34 | // // 35 | // The above copyright notice and this permission notice shall be included in all copies // 36 | // or substantial portions of the Software. // 37 | // // 38 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, // 39 | // INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A // 40 | // PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT // 41 | // HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION // 42 | // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE // 43 | // SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. // 44 | /////////////////////////////////////////////////////////////////////////////////////////// 45 | -------------------------------------------------------------------------------- /PropellerCompiler/preprocess.h: -------------------------------------------------------------------------------- 1 | #ifndef PREPROCESS_H_ 2 | #define PREPROCESS_H_ 3 | 4 | #include 5 | #include "flexbuf.h" 6 | 7 | struct predef 8 | { 9 | struct predef *next; 10 | const char *name; 11 | const char *def; 12 | int flags; 13 | }; 14 | #define PREDEF_FLAG_FREEDEFS 0x01 /* if "name" and "def" should be freed */ 15 | 16 | 17 | #define MODE_UNKNOWN 0 18 | #define MODE_UTF8 1 19 | #define MODE_UTF16 2 20 | 21 | typedef char* (*PreprocessLoadFileFunc)(const char* pFilename, int* pnLength, char** ppFilePath); 22 | typedef void (*PreprocessFreeFileBufferFunc)(char* buffer); 23 | 24 | struct memoryfile 25 | { 26 | char* buffer; 27 | int length; 28 | int readoffset; 29 | char* filepath; 30 | }; 31 | 32 | struct filestate 33 | { 34 | struct filestate *next; 35 | memoryfile *f; 36 | const char *name; 37 | int lineno; 38 | int (*readfunc)(memoryfile *f, char *buf); 39 | int flags; 40 | }; 41 | #define FILE_FLAGS_CLOSEFILE 0x01 42 | 43 | struct ifstate 44 | { 45 | struct ifstate *next; 46 | int skip; /* if we are currently skipping code */ 47 | const char *name; /* the name of the file it started in */ 48 | int linenum; /* the line number it started on */ 49 | int skiprest; /* if we have already processed some branch */ 50 | int sawelse; /* if we have already processed a #else */ 51 | }; 52 | 53 | struct preprocess 54 | { 55 | struct filestate *fil; 56 | struct flexbuf line; 57 | struct flexbuf whole; 58 | struct predef *defs; 59 | 60 | struct ifstate *ifs; 61 | 62 | /* comment handling code */ 63 | const char *linecomment; 64 | const char *startcomment; 65 | const char *endcomment; 66 | 67 | int incomment; 68 | 69 | /* error handling code */ 70 | void (*messagefunc)(const char *level, const char *filename, int linenum, const char *msg); 71 | 72 | bool alternate; /* flag to enable alternate preprocessor rules - */ 73 | /* affects #error handling, macro substitution of */ 74 | /* symbols that are "defined" but have no value. */ 75 | }; 76 | 77 | #define pp_active(pp) (!((pp)->ifs && (pp)->ifs->skip)) 78 | 79 | void pp_setFileFunctions(PreprocessLoadFileFunc pLoadFileFunc, PreprocessFreeFileBufferFunc pFreeFileBufferFunc); 80 | 81 | /* initialize for reading */ 82 | void pp_init(struct preprocess *pp, bool alternate); 83 | 84 | /* push an opened FILE struct */ 85 | void pp_push_file_struct(struct preprocess *pp, memoryfile *f, const char *name); 86 | 87 | /* push a file by name */ 88 | void pp_push_file(struct preprocess *pp, const char *filename); 89 | 90 | /* pop a file (finish processing it) */ 91 | void pp_pop_file(struct preprocess *pp); 92 | 93 | /* set the strings that will be recognized to start line comments and start and end 94 | multi-line comments; these nest */ 95 | void pp_setcomments(struct preprocess *pp, const char *line, const char *s, const char *e); 96 | 97 | /* define symbol "name" to have "val", or undefine it if val is NULL */ 98 | void pp_define(struct preprocess *pp, const char *name, const char *val); 99 | 100 | /* get the current state of the define stack */ 101 | void *pp_get_define_state(struct preprocess *pp); 102 | 103 | /* restore the define state to the state given by a previous call to get_define_state */ 104 | void pp_restore_define_state(struct preprocess *pp, void *ptr); 105 | 106 | /* clear all the define state */ 107 | void pp_clear_define_state(struct preprocess *pp); 108 | 109 | /* actually perform the preprocessing on all files that have been pushed so far */ 110 | void pp_run(struct preprocess *pp); 111 | 112 | /* finish preprocessing and retrieve the result string */ 113 | char *pp_finish(struct preprocess *pp); 114 | 115 | #endif 116 | -------------------------------------------------------------------------------- /PropellerCompiler/textconvert.h: -------------------------------------------------------------------------------- 1 | /////////////////////////////////////////////////////////////// 2 | // // 3 | // Propeller Spin/PASM Compiler Command Line Tool 'OpenSpin' // 4 | // (c)2012-2016 Parallax Inc. DBA Parallax Semiconductor. // 5 | // See end of file for terms of use. // 6 | // // 7 | /////////////////////////////////////////////////////////////// 8 | // 9 | // textconvert.h 10 | // 11 | 12 | #ifndef _TEXTCONVERT_H_ 13 | #define _TEXTCONVERT_H_ 14 | 15 | unsigned int DecodeUtf8(const char* pBuffer, int& nCharSize); 16 | void PASCIIToUnicode16(char* pPASCIIBuffer, int nPASCIIBufferLength, unsigned short* pUnicode16Buffer); 17 | bool UnicodeToPASCII(char* pBuffer, int nBufferLength, char* pPASCIIBuffer, bool bForceUTF8); 18 | 19 | #endif // _TEXTCONVERT_H_ 20 | 21 | /////////////////////////////////////////////////////////////////////////////////////////// 22 | // TERMS OF USE: MIT License // 23 | /////////////////////////////////////////////////////////////////////////////////////////// 24 | // Permission is hereby granted, free of charge, to any person obtaining a copy of this // 25 | // software and associated documentation files (the "Software"), to deal in the Software // 26 | // without restriction, including without limitation the rights to use, copy, modify, // 27 | // merge, publish, distribute, sublicense, and/or sell copies of the Software, and to // 28 | // permit persons to whom the Software is furnished to do so, subject to the following // 29 | // conditions: // 30 | // // 31 | // The above copyright notice and this permission notice shall be included in all copies // 32 | // or substantial portions of the Software. // 33 | // // 34 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, // 35 | // INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A // 36 | // PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT // 37 | // HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION // 38 | // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE // 39 | // SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. // 40 | /////////////////////////////////////////////////////////////////////////////////////////// 41 | -------------------------------------------------------------------------------- /PropellerCompiler_vs2015.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio 2015 4 | VisualStudioVersion = 12.0.31101.0 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "PropellerCompiler", "PropellerCompiler\PropellerCompiler_vs2015.vcxproj", "{DE0E4A74-1C7F-4479-918D-9040BB599F90}" 7 | EndProject 8 | Global 9 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 10 | Debug|Win32 = Debug|Win32 11 | Release|Win32 = Release|Win32 12 | EndGlobalSection 13 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 14 | {DE0E4A74-1C7F-4479-918D-9040BB599F90}.Debug|Win32.ActiveCfg = Debug|Win32 15 | {DE0E4A74-1C7F-4479-918D-9040BB599F90}.Debug|Win32.Build.0 = Debug|Win32 16 | {DE0E4A74-1C7F-4479-918D-9040BB599F90}.Release|Win32.ActiveCfg = Release|Win32 17 | {DE0E4A74-1C7F-4479-918D-9040BB599F90}.Release|Win32.Build.0 = Release|Win32 18 | EndGlobalSection 19 | GlobalSection(SolutionProperties) = preSolution 20 | HideSolutionNode = FALSE 21 | EndGlobalSection 22 | EndGlobal 23 | -------------------------------------------------------------------------------- /PropellerCompiler_vs2017.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio 2017 4 | VisualStudioVersion = 12.0.31101.0 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "PropellerCompiler", "PropellerCompiler\PropellerCompiler_vs2017.vcxproj", "{DE0E4A74-1C7F-4479-918D-9040BB599F90}" 7 | EndProject 8 | Global 9 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 10 | Debug|Win32 = Debug|Win32 11 | Release|Win32 = Release|Win32 12 | EndGlobalSection 13 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 14 | {DE0E4A74-1C7F-4479-918D-9040BB599F90}.Debug|Win32.ActiveCfg = Debug|Win32 15 | {DE0E4A74-1C7F-4479-918D-9040BB599F90}.Debug|Win32.Build.0 = Debug|Win32 16 | {DE0E4A74-1C7F-4479-918D-9040BB599F90}.Release|Win32.ActiveCfg = Release|Win32 17 | {DE0E4A74-1C7F-4479-918D-9040BB599F90}.Release|Win32.Build.0 = Release|Win32 18 | EndGlobalSection 19 | GlobalSection(SolutionProperties) = preSolution 20 | HideSolutionNode = FALSE 21 | EndGlobalSection 22 | EndGlobal 23 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | Introduction 2 | ============ 3 | 4 | OpenSpin is an open source compiler for the Spin/PASM language of the Parallax Propeller. It was ported from Chip Gracey's original x86 assembler code. The only binary differences in the output are from the corrected handling of floating point numbers (which is now IEEE compliant). 5 | 6 | There are solution/project files for VS 2015 & VS 2017, and there are make files for use with GCC/clang/etc. Tested on MinGW, linux, and Mac OSX. They build the PropellerCompiler library and openspin.exe. 7 | 8 | The code successfully compiles all of the Library files shipped with PropTool as well as all of the files available in the OBEX as of August 2012. That's approximately 1450 spin files. 9 | 10 | OpenSpin allows symbols to be 254 characters long (instead of 31), has unused method elimination, and supports a basic [preprocessor](https://github.com/reltham/OpenSpin/wiki/Preprocessor). 11 | 12 | PropellerCompiler library 13 | ------------------------- 14 | 15 | PropellerCompiler.cpp/h contain the interface to the compiler. Look at openspin.cpp for an example of how to work with the interface. 16 | 17 | openspin.exe 18 | ------------ 19 | 20 | openspin.exe is a command line wrapper for the compiler library. You give it a spin file and it passes it through the compiler and produces a .binary (or optional .eeprom) file with the same base name as the passed in spin file. There are several [command line options](https://github.com/reltham/OpenSpin/wiki/CommandLine) available. Run openspin.exe with no arguments to get a usage description. 21 | 22 | Downloads 23 | --------- 24 | 25 | ### Builds provided by David Zemon's TeamCity service: 26 | Note: These are updated automatically whenever changes are submitted here, so they include changes between releases. 27 | * [Linux x86_64](http://david.zemon.name:8111/repository/download/OpenSpin_LinuxX8664/lastSuccessful/openspin.tar.gz?guest=1) 28 | * [Windows x86](http://david.zemon.name:8111/repository/download/OpenSpin_WindowsX86/lastSuccessful/openspin.zip?guest=1) 29 | * [Mac OS X](http://david.zemon.name:8111/repository/download/OpenSpin_MacOsX/2548:id/openspin.tar.gz?guest-1) 30 | * [Raspberry Pi](http://david.zemon.name:8111/repository/download/OpenSpin_RaspberryPi/lastSuccessful/openspin.tar.gz?guest=1) 31 | 32 | Thanks 33 | ------ 34 | 35 | * Thanks to Steve Denson, for the Makefile and testing on linux! 36 | * Thanks to David Betz for testing on Mac OSX. 37 | * Thanks to Eric Smith for providing the code and helping with integrating the preprocessor. 38 | -------------------------------------------------------------------------------- /SpinSource/SpinSource_vs2015.vcxproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | Debug 6 | Win32 7 | 8 | 9 | Release 10 | Win32 11 | 12 | 13 | 14 | openspin 15 | {A52778A6-7ABC-4FC5-B238-A6337AB2CC1F} 16 | spin 17 | Win32Proj 18 | 19 | 20 | 21 | Application 22 | v140 23 | Unicode 24 | true 25 | 26 | 27 | Application 28 | v140 29 | Unicode 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | <_ProjectFileVersion>12.0.30501.0 43 | 44 | 45 | $(SolutionDir)$(Configuration)\ 46 | $(Configuration)\ 47 | true 48 | 49 | 50 | $(SolutionDir)$(Configuration)\ 51 | $(Configuration)\ 52 | false 53 | 54 | 55 | 56 | Disabled 57 | WIN32;_DEBUG;_CONSOLE;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions) 58 | true 59 | EnableFastChecks 60 | MultiThreadedDebug 61 | 62 | Level4 63 | EditAndContinue 64 | 65 | 66 | true 67 | Console 68 | MachineX86 69 | false 70 | 71 | 72 | 73 | 74 | MaxSpeed 75 | true 76 | WIN32;NDEBUG;_CONSOLE;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions) 77 | MultiThreaded 78 | true 79 | 80 | Level4 81 | ProgramDatabase 82 | 83 | 84 | true 85 | Console 86 | true 87 | true 88 | MachineX86 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | {de0e4a74-1c7f-4479-918d-9040bb599f90} 101 | false 102 | 103 | 104 | 105 | 106 | 107 | -------------------------------------------------------------------------------- /SpinSource/SpinSource_vs2017.vcxproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | Debug 6 | Win32 7 | 8 | 9 | Release 10 | Win32 11 | 12 | 13 | 14 | openspin 15 | {A52778A6-7ABC-4FC5-B238-A6337AB2CC1F} 16 | spin 17 | Win32Proj 18 | 19 | 20 | 21 | Application 22 | v141 23 | Unicode 24 | true 25 | 26 | 27 | Application 28 | v141 29 | Unicode 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | <_ProjectFileVersion>12.0.30501.0 43 | 44 | 45 | $(SolutionDir)$(Configuration)\ 46 | $(Configuration)\ 47 | true 48 | 49 | 50 | $(SolutionDir)$(Configuration)\ 51 | $(Configuration)\ 52 | false 53 | 54 | 55 | 56 | Disabled 57 | WIN32;_DEBUG;_CONSOLE;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions) 58 | true 59 | EnableFastChecks 60 | MultiThreadedDebug 61 | 62 | Level4 63 | EditAndContinue 64 | 65 | 66 | true 67 | Console 68 | MachineX86 69 | false 70 | 71 | 72 | 73 | 74 | MaxSpeed 75 | true 76 | WIN32;NDEBUG;_CONSOLE;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions) 77 | MultiThreaded 78 | true 79 | 80 | Level4 81 | ProgramDatabase 82 | 83 | 84 | true 85 | Console 86 | true 87 | true 88 | MachineX86 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | {de0e4a74-1c7f-4479-918d-9040bb599f90} 101 | false 102 | 103 | 104 | 105 | 106 | 107 | -------------------------------------------------------------------------------- /SpinSource/openspin.cpp: -------------------------------------------------------------------------------- 1 | /////////////////////////////////////////////////////////////// 2 | // // 3 | // Propeller Spin/PASM Compiler Command Line Tool 'OpenSpin' // 4 | // (c)2012-2016 Parallax Inc. DBA Parallax Semiconductor. // 5 | // Adapted from Jeff Martin's Delphi code by Roy Eltham // 6 | // See end of file for terms of use. // 7 | // // 8 | /////////////////////////////////////////////////////////////// 9 | // 10 | // openspin.cpp 11 | // 12 | 13 | #include 14 | #include 15 | #include 16 | 17 | #include "../PropellerCompiler/CompileSpin.h" 18 | #include "pathentry.h" 19 | 20 | #define MAX_FILES 2048 21 | 22 | static int s_nFilesAccessed = 0; 23 | static char s_filesAccessed[MAX_FILES][PATH_MAX]; 24 | 25 | 26 | static void Banner(void) 27 | { 28 | fprintf(stdout, "Propeller Spin/PASM Compiler \'OpenSpin\' (c)2012-2018 Parallax Inc. DBA Parallax Semiconductor.\n"); 29 | fprintf(stdout, "Version 1.00.81 Compiled on %s %s\n",__DATE__, __TIME__); 30 | } 31 | 32 | /* Usage - display a usage message and exit */ 33 | static void Usage(void) 34 | { 35 | Banner(); 36 | fprintf(stderr, "\ 37 | usage: openspin\n\ 38 | [ -h ] display this help\n\ 39 | [ -L or -I ] add a directory to the include path\n\ 40 | [ -o ] output filename\n\ 41 | [ -b ] output binary file format\n\ 42 | [ -e ] output eeprom file format\n\ 43 | [ -c ] output only DAT sections\n\ 44 | [ -d ] dump out doc mode\n\ 45 | [ -t ] output just the object file tree\n\ 46 | [ -f ] output a list of filenames for use in archiving\n\ 47 | [ -q ] quiet mode (suppress banner and non-error text)\n\ 48 | [ -v ] verbose output\n\ 49 | [ -p ] disable the preprocessor\n\ 50 | [ -a ] use alternative preprocessor rules\n\ 51 | [ -D ] add a define\n\ 52 | [ -M ] size of eeprom (up to 16777216 bytes)\n\ 53 | [ -s ] dump PUB & CON symbol information for top object\n\ 54 | [ -u ] enable unused method elimination\n\ 55 | spin file to compile\n\ 56 | \n"); 57 | } 58 | 59 | FILE* OpenFileInPath(const char *name, const char *mode) 60 | { 61 | const char* pTryPath = NULL; 62 | 63 | FILE* file = fopen(name, mode); 64 | if (!file) 65 | { 66 | PathEntry* entry = NULL; 67 | while(!file) 68 | { 69 | pTryPath = MakeNextPath(&entry, name); 70 | if (pTryPath) 71 | { 72 | file = fopen(pTryPath, mode); 73 | if (file != NULL) 74 | { 75 | break; 76 | } 77 | } 78 | else 79 | { 80 | break; 81 | } 82 | } 83 | } 84 | 85 | if (s_nFilesAccessed < MAX_FILES) 86 | { 87 | if (!pTryPath) 88 | { 89 | #ifdef WIN32 90 | if (_fullpath(s_filesAccessed[s_nFilesAccessed], name, PATH_MAX) == NULL) 91 | #else 92 | if (realpath(name, s_filesAccessed[s_nFilesAccessed]) == NULL) 93 | #endif 94 | { 95 | strcpy(s_filesAccessed[s_nFilesAccessed], name); 96 | } 97 | s_nFilesAccessed++; 98 | } 99 | else 100 | { 101 | strcpy(s_filesAccessed[s_nFilesAccessed++], pTryPath); 102 | } 103 | } 104 | else 105 | { 106 | // should never hit this, but just in case 107 | printf("Too many files!\n"); 108 | exit(-2); 109 | } 110 | 111 | return file; 112 | } 113 | 114 | // returns NULL if the file failed to open or is 0 length 115 | char* LoadFile(const char* pFilename, int* pnLength, char** ppFilePath) 116 | { 117 | char* pBuffer = 0; 118 | FILE* pFile = OpenFileInPath(pFilename, "rb"); 119 | if (pFile != NULL) 120 | { 121 | // get the length of the file by seeking to the end and using ftell 122 | fseek(pFile, 0, SEEK_END); 123 | *pnLength = ftell(pFile); 124 | 125 | if (*pnLength > 0) 126 | { 127 | pBuffer = (char*)malloc(*pnLength+1); // allocate a buffer that is the size of the file plus one char 128 | pBuffer[*pnLength] = 0; // set the end of the buffer to 0 (null) 129 | 130 | // seek back to the beginning of the file and read it in 131 | fseek(pFile, 0, SEEK_SET); 132 | fread(pBuffer, 1, *pnLength, pFile); 133 | } 134 | 135 | fclose(pFile); 136 | 137 | *ppFilePath = &(s_filesAccessed[s_nFilesAccessed-1][0]); 138 | } 139 | else 140 | { 141 | return 0; 142 | } 143 | 144 | return pBuffer; 145 | } 146 | 147 | void FreeFileBuffer(char* pBuffer) 148 | { 149 | if (pBuffer != 0) 150 | { 151 | free(pBuffer); 152 | } 153 | } 154 | 155 | int main(int argc, char* argv[]) 156 | { 157 | CompilerConfig compilerConfig; 158 | 159 | char* infile = NULL; 160 | char* outfile = NULL; 161 | char* p = NULL; 162 | s_nFilesAccessed = 0; 163 | 164 | // go through the command line arguments, skipping over any -D 165 | for(int i = 1; i < argc; i++) 166 | { 167 | // handle switches 168 | if(argv[i][0] == '-') 169 | { 170 | switch(argv[i][1]) 171 | { 172 | case 'I': 173 | case 'L': 174 | if(argv[i][2]) 175 | { 176 | p = &argv[i][2]; 177 | } 178 | else if(++i < argc) 179 | { 180 | p = argv[i]; 181 | } 182 | else 183 | { 184 | Usage(); 185 | CleanupPathEntries(); 186 | return 1; 187 | } 188 | AddPath(p); 189 | break; 190 | 191 | case 'M': 192 | if (argv[i][2]) 193 | { 194 | p = &argv[i][2]; 195 | } 196 | else if(++i < argc) 197 | { 198 | p = argv[i]; 199 | } 200 | else 201 | { 202 | Usage(); 203 | CleanupPathEntries(); 204 | return 1; 205 | } 206 | sscanf(p, "%d", &(compilerConfig.eeprom_size)); 207 | if (compilerConfig.eeprom_size > 16777216) 208 | { 209 | Usage(); 210 | CleanupPathEntries(); 211 | return 1; 212 | } 213 | break; 214 | 215 | case 'o': 216 | if(argv[i][2]) 217 | { 218 | outfile = &argv[i][2]; 219 | } 220 | else if(++i < argc) 221 | { 222 | outfile = argv[i]; 223 | } 224 | else 225 | { 226 | Usage(); 227 | CleanupPathEntries(); 228 | return 1; 229 | } 230 | break; 231 | 232 | case 'p': 233 | compilerConfig.bUsePreprocessor = false; 234 | break; 235 | 236 | case 'a': 237 | compilerConfig.bAlternatePreprocessorMode = true; 238 | break; 239 | 240 | case 'D': 241 | if (compilerConfig.bUsePreprocessor) 242 | { 243 | if (argv[i][2]) 244 | { 245 | p = &argv[i][2]; 246 | } 247 | else if(++i < argc) 248 | { 249 | p = argv[i]; 250 | } 251 | else 252 | { 253 | Usage(); 254 | CleanupPathEntries(); 255 | return 1; 256 | } 257 | // just skipping these for now 258 | } 259 | else 260 | { 261 | Usage(); 262 | CleanupPathEntries(); 263 | return 1; 264 | } 265 | break; 266 | 267 | case 't': 268 | compilerConfig.bFileTreeOutputOnly = true; 269 | break; 270 | 271 | case 'f': 272 | compilerConfig.bFileListOutputOnly = true; 273 | break; 274 | 275 | case 'b': 276 | compilerConfig.bBinary = true; 277 | break; 278 | 279 | case 'c': 280 | compilerConfig.bDATonly = true; 281 | break; 282 | 283 | case 'd': 284 | compilerConfig.bDocMode = true; 285 | break; 286 | 287 | case 'e': 288 | compilerConfig.bBinary = false; 289 | break; 290 | 291 | case 'q': 292 | compilerConfig.bQuiet = true; 293 | break; 294 | 295 | case 'v': 296 | compilerConfig.bVerbose = true; 297 | break; 298 | 299 | case 's': 300 | compilerConfig.bDumpSymbols = true; 301 | break; 302 | 303 | case 'u': 304 | compilerConfig.bUnusedMethodElimination = true; 305 | break; 306 | 307 | case 'h': 308 | default: 309 | Usage(); 310 | CleanupPathEntries(); 311 | return 1; 312 | break; 313 | } 314 | } 315 | else // handle the input filename 316 | { 317 | if (infile) 318 | { 319 | Usage(); 320 | CleanupPathEntries(); 321 | return 1; 322 | } 323 | infile = argv[i]; 324 | } 325 | } 326 | 327 | // must have input file 328 | if (!infile) 329 | { 330 | Usage(); 331 | CleanupPathEntries(); 332 | return 1; 333 | } 334 | 335 | if (compilerConfig.bFileTreeOutputOnly || compilerConfig.bFileListOutputOnly || compilerConfig.bDumpSymbols) 336 | { 337 | compilerConfig.bQuiet = true; 338 | } 339 | 340 | // finish the include path 341 | AddFilePath(infile); 342 | 343 | char outputFilename[256]; 344 | if (!outfile) 345 | { 346 | // create *.binary filename from user passed in spin filename 347 | strcpy(&outputFilename[0], infile); 348 | const char* pTemp = strstr(&outputFilename[0], ".spin"); 349 | if (pTemp == 0) 350 | { 351 | printf("ERROR: spinfile must have .spin extension. You passed in: %s\n", infile); 352 | Usage(); 353 | CleanupPathEntries(); 354 | return 1; 355 | } 356 | else 357 | { 358 | int offset = (int)(pTemp - &outputFilename[0]); 359 | outputFilename[offset+1] = 0; 360 | if (compilerConfig.bDATonly) 361 | { 362 | strcat(&outputFilename[0], "dat"); 363 | } 364 | else if (compilerConfig.bBinary) 365 | { 366 | strcat(&outputFilename[0], "binary"); 367 | } 368 | else 369 | { 370 | strcat(&outputFilename[0], "eeprom"); 371 | } 372 | } 373 | } 374 | else // use filename specified with -o 375 | { 376 | strcpy(outputFilename, outfile); 377 | } 378 | 379 | if (!compilerConfig.bQuiet) 380 | { 381 | Banner(); 382 | printf("Compiling...\n%s\n", infile); 383 | } 384 | 385 | InitCompiler(&compilerConfig, LoadFile, FreeFileBuffer); 386 | 387 | if (compilerConfig.bUsePreprocessor) 388 | { 389 | // go through the command line arguments again, this time only processing -D 390 | for(int i = 1; i < argc; i++) 391 | { 392 | // handle switches 393 | if(argv[i][0] == '-') 394 | { 395 | if (argv[i][1] == 'D') 396 | { 397 | if (argv[i][2]) 398 | { 399 | p = &argv[i][2]; 400 | } 401 | else if(++i < argc) 402 | { 403 | p = argv[i]; 404 | } 405 | else 406 | { 407 | Usage(); 408 | ShutdownCompiler(); 409 | CleanupPathEntries(); 410 | return 1; 411 | } 412 | 413 | // add any predefined symbols here - note that when using the 414 | // "alternate" rules, these symbols have a null value - i.e. 415 | // they are just "defined", but are not used in macro substitution 416 | SetDefine(p, (compilerConfig.bAlternatePreprocessorMode ? "" : "1")); 417 | } 418 | } 419 | } 420 | 421 | // add symbols with predefined values here 422 | SetDefine("__SPIN__", "1"); 423 | SetDefine("__TARGET__", "P1"); 424 | } 425 | 426 | int nLength = 0; 427 | unsigned char* pBuffer = CompileSpin(infile, &nLength); 428 | 429 | if (pBuffer) 430 | { 431 | FILE* pFile = fopen(outputFilename, "wb"); 432 | if (pFile) 433 | { 434 | fwrite(pBuffer, nLength, 1, pFile); 435 | fclose(pFile); 436 | } 437 | } 438 | else 439 | { 440 | // compiler put out an error 441 | ShutdownCompiler(); 442 | CleanupPathEntries(); 443 | return 1; 444 | } 445 | 446 | if (compilerConfig.bFileListOutputOnly) 447 | { 448 | for (int i = 0; i < s_nFilesAccessed; i++) 449 | { 450 | for (int j = i+1; j < s_nFilesAccessed; j++) 451 | { 452 | if (strcmp(s_filesAccessed[i], s_filesAccessed[j]) == 0) 453 | { 454 | s_filesAccessed[j][0] = 0; 455 | } 456 | } 457 | } 458 | 459 | for (int i = 0; i < s_nFilesAccessed; i++) 460 | { 461 | if (s_filesAccessed[i][0] != 0) 462 | { 463 | printf("%s\n", s_filesAccessed[i]); 464 | } 465 | } 466 | } 467 | 468 | 469 | ShutdownCompiler(); 470 | CleanupPathEntries(); 471 | 472 | return 0; 473 | } 474 | 475 | /////////////////////////////////////////////////////////////////////////////////////////// 476 | // TERMS OF USE: MIT License // 477 | /////////////////////////////////////////////////////////////////////////////////////////// 478 | // Permission is hereby granted, free of charge, to any person obtaining a copy of this // 479 | // software and associated documentation files (the "Software"), to deal in the Software // 480 | // without restriction, including without limitation the rights to use, copy, modify, // 481 | // merge, publish, distribute, sublicense, and/or sell copies of the Software, and to // 482 | // permit persons to whom the Software is furnished to do so, subject to the following // 483 | // conditions: // 484 | // // 485 | // The above copyright notice and this permission notice shall be included in all copies // 486 | // or substantial portions of the Software. // 487 | // // 488 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, // 489 | // INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A // 490 | // PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT // 491 | // HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION // 492 | // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE // 493 | // SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. // 494 | /////////////////////////////////////////////////////////////////////////////////////////// 495 | -------------------------------------------------------------------------------- /SpinSource/pathentry.cpp: -------------------------------------------------------------------------------- 1 | /////////////////////////////////////////////////////////////// 2 | // // 3 | // Propeller Spin/PASM Compiler Command Line Tool 'OpenSpin' // 4 | // (c)2012-2016 Parallax Inc. DBA Parallax Semiconductor. // 5 | // See end of file for terms of use. // 6 | // // 7 | /////////////////////////////////////////////////////////////// 8 | // 9 | // pathentry.cpp 10 | // 11 | 12 | #include 13 | #include 14 | 15 | #include "pathentry.h" 16 | 17 | PathEntry *path = NULL; 18 | static PathEntry **pNextPathEntry = &path; 19 | 20 | static char lastfullpath[PATH_MAX]; 21 | 22 | const char *MakeNextPath(PathEntry **entry, const char *name) 23 | { 24 | if (!*entry) 25 | { 26 | *entry = path; 27 | } 28 | else 29 | { 30 | *entry = (*entry)->next; 31 | } 32 | if (*entry) 33 | { 34 | sprintf(lastfullpath, "%s%c%s", (*entry)->path, DIR_SEP, name); 35 | return lastfullpath; 36 | } 37 | return NULL; 38 | } 39 | 40 | bool AddPath(const char *newPath) 41 | { 42 | PathEntry* entry = (PathEntry*)new char[(sizeof(PathEntry) + strlen(newPath))]; 43 | if (!(entry)) 44 | { 45 | return false; 46 | } 47 | strcpy(entry->path, newPath); 48 | *pNextPathEntry = entry; 49 | pNextPathEntry = &entry->next; 50 | entry->next = NULL; 51 | return true; 52 | } 53 | 54 | bool AddFilePath(const char *name) 55 | { 56 | const char* end = strrchr(name, DIR_SEP); 57 | if (!end) 58 | { 59 | return false; 60 | } 61 | int len = (int)(end - name); 62 | PathEntry *entry = (PathEntry*)new char[(sizeof(PathEntry) + len)]; 63 | if (!entry) 64 | { 65 | return false; 66 | } 67 | strncpy(entry->path, name, len); 68 | entry->path[len] = '\0'; 69 | *pNextPathEntry = entry; 70 | pNextPathEntry = &entry->next; 71 | entry->next = NULL; 72 | 73 | return true; 74 | } 75 | 76 | void CleanupPathEntries() 77 | { 78 | PathEntry *entry = path; 79 | while (entry != NULL) 80 | { 81 | PathEntry *nextEntry = entry->next; 82 | delete [] entry; 83 | entry = nextEntry; 84 | } 85 | path = NULL; 86 | lastfullpath[0] = 0; 87 | } 88 | 89 | 90 | 91 | /////////////////////////////////////////////////////////////////////////////////////////// 92 | // TERMS OF USE: MIT License // 93 | /////////////////////////////////////////////////////////////////////////////////////////// 94 | // Permission is hereby granted, free of charge, to any person obtaining a copy of this // 95 | // software and associated documentation files (the "Software"), to deal in the Software // 96 | // without restriction, including without limitation the rights to use, copy, modify, // 97 | // merge, publish, distribute, sublicense, and/or sell copies of the Software, and to // 98 | // permit persons to whom the Software is furnished to do so, subject to the following // 99 | // conditions: // 100 | // // 101 | // The above copyright notice and this permission notice shall be included in all copies // 102 | // or substantial portions of the Software. // 103 | // // 104 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, // 105 | // INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A // 106 | // PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT // 107 | // HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION // 108 | // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE // 109 | // SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. // 110 | /////////////////////////////////////////////////////////////////////////////////////////// 111 | -------------------------------------------------------------------------------- /SpinSource/pathentry.h: -------------------------------------------------------------------------------- 1 | /////////////////////////////////////////////////////////////// 2 | // // 3 | // Propeller Spin/PASM Compiler Command Line Tool 'OpenSpin' // 4 | // (c)2012-2016 Parallax Inc. DBA Parallax Semiconductor. // 5 | // See end of file for terms of use. // 6 | // // 7 | /////////////////////////////////////////////////////////////// 8 | // 9 | // pathentry.h 10 | // 11 | 12 | // 13 | // code for handling directory paths (used with -I option) 14 | // 15 | 16 | #ifndef PATH_MAX 17 | #define PATH_MAX 1024 18 | #endif 19 | 20 | #if defined(WIN32) 21 | #define DIR_SEP '\\' 22 | #define DIR_SEP_STR "\\" 23 | #else 24 | #define DIR_SEP '/' 25 | #define DIR_SEP_STR "/" 26 | #endif 27 | 28 | struct PathEntry 29 | { 30 | PathEntry *next; 31 | char path[1]; 32 | }; 33 | 34 | const char *MakeNextPath(PathEntry **entry, const char *name); // pass the address of an entry that is NULL to get first path, keep calling with same entry to walk list 35 | bool AddPath(const char *path); 36 | bool AddFilePath(const char *name); 37 | void CleanupPathEntries(); 38 | 39 | /////////////////////////////////////////////////////////////////////////////////////////// 40 | // TERMS OF USE: MIT License // 41 | /////////////////////////////////////////////////////////////////////////////////////////// 42 | // Permission is hereby granted, free of charge, to any person obtaining a copy of this // 43 | // software and associated documentation files (the "Software"), to deal in the Software // 44 | // without restriction, including without limitation the rights to use, copy, modify, // 45 | // merge, publish, distribute, sublicense, and/or sell copies of the Software, and to // 46 | // permit persons to whom the Software is furnished to do so, subject to the following // 47 | // conditions: // 48 | // // 49 | // The above copyright notice and this permission notice shall be included in all copies // 50 | // or substantial portions of the Software. // 51 | // // 52 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, // 53 | // INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A // 54 | // PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT // 55 | // HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION // 56 | // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE // 57 | // SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. // 58 | /////////////////////////////////////////////////////////////////////////////////////////// 59 | -------------------------------------------------------------------------------- /openspin_vs2015.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio 2015 4 | VisualStudioVersion = 12.0.31101.0 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "openspin", "SpinSource\SpinSource_vs2015.vcxproj", "{A52778A6-7ABC-4FC5-B238-A6337AB2CC1F}" 7 | EndProject 8 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "PropellerCompiler", "PropellerCompiler\PropellerCompiler_vs2015.vcxproj", "{DE0E4A74-1C7F-4479-918D-9040BB599F90}" 9 | EndProject 10 | Global 11 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 12 | Debug|Win32 = Debug|Win32 13 | Release|Win32 = Release|Win32 14 | EndGlobalSection 15 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 16 | {A52778A6-7ABC-4FC5-B238-A6337AB2CC1F}.Debug|Win32.ActiveCfg = Debug|Win32 17 | {A52778A6-7ABC-4FC5-B238-A6337AB2CC1F}.Debug|Win32.Build.0 = Debug|Win32 18 | {A52778A6-7ABC-4FC5-B238-A6337AB2CC1F}.Release|Win32.ActiveCfg = Release|Win32 19 | {A52778A6-7ABC-4FC5-B238-A6337AB2CC1F}.Release|Win32.Build.0 = Release|Win32 20 | {DE0E4A74-1C7F-4479-918D-9040BB599F90}.Debug|Win32.ActiveCfg = Debug|Win32 21 | {DE0E4A74-1C7F-4479-918D-9040BB599F90}.Debug|Win32.Build.0 = Debug|Win32 22 | {DE0E4A74-1C7F-4479-918D-9040BB599F90}.Release|Win32.ActiveCfg = Release|Win32 23 | {DE0E4A74-1C7F-4479-918D-9040BB599F90}.Release|Win32.Build.0 = Release|Win32 24 | EndGlobalSection 25 | GlobalSection(SolutionProperties) = preSolution 26 | HideSolutionNode = FALSE 27 | EndGlobalSection 28 | EndGlobal 29 | -------------------------------------------------------------------------------- /openspin_vs2017.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio 2017 4 | VisualStudioVersion = 12.0.31101.0 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "openspin", "SpinSource\SpinSource_vs2017.vcxproj", "{A52778A6-7ABC-4FC5-B238-A6337AB2CC1F}" 7 | EndProject 8 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "PropellerCompiler", "PropellerCompiler\PropellerCompiler_vs2017.vcxproj", "{DE0E4A74-1C7F-4479-918D-9040BB599F90}" 9 | EndProject 10 | Global 11 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 12 | Debug|Win32 = Debug|Win32 13 | Release|Win32 = Release|Win32 14 | EndGlobalSection 15 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 16 | {A52778A6-7ABC-4FC5-B238-A6337AB2CC1F}.Debug|Win32.ActiveCfg = Debug|Win32 17 | {A52778A6-7ABC-4FC5-B238-A6337AB2CC1F}.Debug|Win32.Build.0 = Debug|Win32 18 | {A52778A6-7ABC-4FC5-B238-A6337AB2CC1F}.Release|Win32.ActiveCfg = Release|Win32 19 | {A52778A6-7ABC-4FC5-B238-A6337AB2CC1F}.Release|Win32.Build.0 = Release|Win32 20 | {DE0E4A74-1C7F-4479-918D-9040BB599F90}.Debug|Win32.ActiveCfg = Debug|Win32 21 | {DE0E4A74-1C7F-4479-918D-9040BB599F90}.Debug|Win32.Build.0 = Debug|Win32 22 | {DE0E4A74-1C7F-4479-918D-9040BB599F90}.Release|Win32.ActiveCfg = Release|Win32 23 | {DE0E4A74-1C7F-4479-918D-9040BB599F90}.Release|Win32.Build.0 = Release|Win32 24 | EndGlobalSection 25 | GlobalSection(SolutionProperties) = preSolution 26 | HideSolutionNode = FALSE 27 | EndGlobalSection 28 | EndGlobal 29 | --------------------------------------------------------------------------------