├── PyListObject对象1.doc ├── PyListObject对象2.doc ├── PyListObject对象3.doc ├── Python源码剖析-深度探索动态语言核心技术-陈儒.pdf ├── Python源码剖析1.doc ├── Python源码剖析2.doc ├── Python源码剖析3.doc ├── Python源码剖析4.doc ├── Python源码剖析5.doc ├── README.md ├── Small Python.doc ├── assets └── cover.jpg ├── pyc_parser ├── Makefile ├── Readme ├── bin │ ├── opcode.txt │ ├── pyc_generator.py │ └── to_xml.py ├── include │ ├── PycParser.h │ ├── codeObject.h │ ├── dictObject.h │ ├── intObject.h │ ├── object.h │ ├── opCode.h │ ├── reader.h │ ├── stringObject.h │ ├── tupleObject.h │ └── writer.h ├── pyc_parser.sln ├── pyc_parser.vcproj └── src │ ├── PycParser.cpp │ ├── codeObject.cpp │ ├── dictObject.cpp │ ├── intObject.cpp │ ├── object.cpp │ ├── opCode.cpp │ ├── stringObject.cpp │ └── tupleObject.cpp ├── small_python ├── .vs │ └── small_python │ │ └── v16 │ │ ├── .suo │ │ ├── Browse.VC.db │ │ └── Solution.VC.db ├── Backup │ └── small_python.sln ├── Backup1 │ └── samll_python.sln ├── Makefile ├── include │ ├── engine.h │ ├── intObject.h │ ├── object.h │ └── strObject.h ├── samll_python.ncb ├── samll_python.suo ├── samll_python.vcproj ├── samll_python.vcxproj ├── samll_python.vcxproj.filters ├── samll_python.vcxproj.user ├── small_python.sln └── src │ ├── engine.cpp │ ├── intObject.cpp │ ├── main.cpp │ ├── object.cpp │ └── strObject.cpp ├── 字典对象PyDictObject1.doc ├── 字典对象PyDictObject2.doc ├── 字典对象PyDictObject3.doc ├── 字符串对象PyStringObject1.doc ├── 字符串对象PyStringObject2.doc └── 字符串对象PyStringObject3.doc /PyListObject对象1.doc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bat67/python-source-code-analysis/b090c3d51372e31fba4270665773f07eae784ec0/PyListObject对象1.doc -------------------------------------------------------------------------------- /PyListObject对象2.doc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bat67/python-source-code-analysis/b090c3d51372e31fba4270665773f07eae784ec0/PyListObject对象2.doc -------------------------------------------------------------------------------- /PyListObject对象3.doc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bat67/python-source-code-analysis/b090c3d51372e31fba4270665773f07eae784ec0/PyListObject对象3.doc -------------------------------------------------------------------------------- /Python源码剖析-深度探索动态语言核心技术-陈儒.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bat67/python-source-code-analysis/b090c3d51372e31fba4270665773f07eae784ec0/Python源码剖析-深度探索动态语言核心技术-陈儒.pdf -------------------------------------------------------------------------------- /Python源码剖析1.doc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bat67/python-source-code-analysis/b090c3d51372e31fba4270665773f07eae784ec0/Python源码剖析1.doc -------------------------------------------------------------------------------- /Python源码剖析2.doc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bat67/python-source-code-analysis/b090c3d51372e31fba4270665773f07eae784ec0/Python源码剖析2.doc -------------------------------------------------------------------------------- /Python源码剖析3.doc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bat67/python-source-code-analysis/b090c3d51372e31fba4270665773f07eae784ec0/Python源码剖析3.doc -------------------------------------------------------------------------------- /Python源码剖析4.doc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bat67/python-source-code-analysis/b090c3d51372e31fba4270665773f07eae784ec0/Python源码剖析4.doc -------------------------------------------------------------------------------- /Python源码剖析5.doc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bat67/python-source-code-analysis/b090c3d51372e31fba4270665773f07eae784ec0/Python源码剖析5.doc -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Python源码剖析:深度探索动态语言核心技术 2 | 3 | > 前一阵终于把电子书(本仓库的pdf)、配套资源(本仓库的word)、配套代码(本仓库文件夹)找齐了! 4 | > 5 | > 虽然其Python版本已经很旧了,但不影响它为一本好书!与大家分享! 6 | 7 | 8 | ## Introduction 9 | 10 | 作为主流的动态语言,Python不仅简单易学、移植性好,而且拥有强大丰富的库的支持。此外,Python强大的可扩展性,让开发人员既可以非常容易地利用C/C++编写Python的扩展模块,还能将Python嵌入到C/C++程序中,为自己的系统添加动态扩展和动态编程的能力。 11 | 12 | 为了更好地利用Python语言,无论是使用Python语言本身,还是将Python与C/C++交互使用,深刻理解Python的运行原理都是非常重要的。本书以CPython为研究对象,在C代码一级,深入细致地剖析了Python的实现。书中不仅包括了对大量Python内置对象的剖析,更将大量的篇幅用于对Python虚拟机及Python高级特性的剖析。通过此书,读者能够透彻地理解Python中的一般表达式、控制结构、异常机制、类机制、多线程机制、模块的动态加载机制、内存管理机制等核心技术的运行原理,同时,本书所揭示的动态语言的核心技术对于理解其他动态语言,如 Javascript、Ruby等也有较大的参考价值。 13 | 14 | 本书适合于Python程序员、动态语言爱好者、C程序员阅读。 15 | 16 | 17 | 18 | 19 | 20 | ## Resources 21 | 22 | - [作者的 CSDN 博客](https://blog.csdn.net/balabalamerobert) 23 | - 可惜不再更新了 24 | 25 | - [Extending and Embedding the Python Interpreter](https://docs.python.org/3/extending/index.html) 26 | - 扩展和嵌入 Python 解析器,介绍了如何用 C/C++ 编写 Python 的扩展模块,如何在其它语言中嵌入 Python 解释器 27 | 28 | - [Python/C API Reference Manual](https://docs.python.org/3/c-api/index.html) 29 | - 详细介绍了 Python 内部的 C API 30 | 31 | - [Python Developer’s Guide](https://devguide.python.org/) 32 | - Python 开发者指南 33 | 34 | - [有没有内容类似于《Python源码剖析》,但内容更新过,针对新版本的Python书籍 - 知乎](https://www.zhihu.com/question/40787248) 35 | - 该书出版年份2008年,基于Python2.5,最新的相关内容见这个链接 36 | 37 | - [CPython-Internals - GitHub](https://github.com/zpoint/CPython-Internals) 38 | - This repository is some notes/blog for cpython source code. Trying to illustrate every detail of cpython implementation 39 | 40 | 41 | ## Chinese Version 42 | 43 | ![cover](assets/cover.jpg) 44 | 45 | 46 | ## Table of Contents 47 | 48 | * 第0章 Python源码剖析——编译Python 49 | * 0.1 Python总体架构 50 | * 0.2 Python源代码的组织 51 | * 0.3 Windows环境下编译Python 52 | * 0.4 Unix/Linux环境下编译Python 53 | * 0.5 修改Python源代码 54 | * 0.6 通往Python之路 55 | * 0.7 一些注意事项 56 | > 第1部分 Python内建对象 57 | * 第1章 Python对象初探 58 | * 1.1 Python内的对象 59 | * 1.2 类型对象 60 | * 1.3 Python对象的多态性 61 | * 1.4 引用计数 62 | * 1.5 Python对象的分类 63 | * 第2章 Python中的整数对象 64 | * 2.1 初识PyIntObject对象 65 | * 2.2 PyIntObject对象的创建和维护 66 | * 2.3 Hack PyIntObject 67 | * 第3章 Python中的字符串对象 68 | * 3.1 PyStringObject与PyString_Type 69 | * 3.2 创建PyStringObject对象 70 | * 3.3 字符串对象的intern机制 71 | * 3.4 字符缓冲池 72 | * 3.5 PyStringObject效率相关问题 73 | * 3.6 Hack PyStringObject 74 | * 第4章 Python中的List对象 75 | * 4.1 PyListObject对象 76 | * 4.2 PyListObject对象的创建与维护 77 | * 4.3 PyListObject对象缓冲池 78 | * 4.4 Hack PyListObject 79 | * 第5章 Python中的Dict对象 80 | * 5.1 散列表概述 81 | * 5.2 PyDictObject 82 | * 5.3 PyDictObject的创建和维护 83 | * 5.4 PyDictObject对象缓冲池 84 | * 5.5 Hack PyDictObject 85 | * 第6章 最简单的Python模拟——Small Python 86 | * 6.1 Small Python 87 | * 6.2 对象机制 88 | * 6.3 解释过程 89 | * 6.4 交互式环境 90 | > 第2部分 Python虚拟机 91 | * 第7章 Python的编译结果——Code对象与pyc文件 92 | * 7.1 Python程序的执行过程 93 | * 7.2 Python编译器的编译结果——PyCodeObject对象 94 | * 7.3 Pyc文件的生成 95 | * 7.4 Python的字节码 96 | * 7.5 解析pyc文件 97 | * 第8章 Python虚拟机框架 98 | * 8.1 Python虚拟机中的执行环境 99 | * 8.2 名字、作用域和名字空间 100 | * 8.3 Python虚拟机的运行框架 101 | * 8.4 Python运行时环境初探 102 | * 第9章 Python虚拟机中的一般表达式 103 | * 9.1 简单内建对象的创建 104 | * 9.2 复杂内建对象的创建 105 | * 9.3 其他一般表达式 106 | * 第10章 Python虚拟机中的控制流 107 | * 10.1 Python虚拟机中的if控制流 108 | * 10.2 Python虚拟机中的for循环控制流 109 | * 10.3 Python虚拟机中的while循环控制结构 110 | * 10.4 Python虚拟机中的异常控制流 111 | * 第11章 Python虚拟机中的函数机制 112 | * 11.1 PyFunctionObject对象 113 | * 11.2 无参函数调用 114 | * 11.3 函数执行时的名字空间 115 | * 11.4 函数参数的实现 116 | * 11.5 函数中局部变量的访问 117 | * 11.6 嵌套函数、闭包与decorator 118 | * 第12章 Python虚拟机中的类机制 119 | * 12.1 Python中的对象模型 120 | * 12.2 从type对象到class对象 121 | * 12.3 用户自定义class 122 | * 12.4 从class对象到instance对象 123 | * 12.5 访问instance对象中的属性 124 | * 12.6 千变万化的descriptor 125 | > 第3部分 Python 高级话题 126 | * 第13章 Python运行环境初始化 127 | * 13.1 线程环境初始化 128 | * 13.2 系统module初始化 129 | * 13.3 激活Python虚拟机 130 | * 第14章 Python模块的动态加载机制 131 | * 14.1 import前奏曲 132 | * 14.2 Python中import机制的黑盒探测 133 | * 14.3 import机制的实现 134 | * 14.4 Python中的import操作 135 | * 14.5 与module有关的名字空间问题 136 | * 第15章 Python多线程机制 137 | * 15.1 GIL与线程调度 138 | * 15.2 初见Python Thread 139 | * 15.3 Python线程的创建 140 | * 15.4 Python线程的调度 141 | * 15.5 Python子线程的销毁 142 | * 15.6 Python线程的用户级互斥与同步 143 | * 15.7 高级线程库——threading 144 | * 第16章 Python的内存管理机制 145 | * 16.1 内存管理架构 146 | * 16.2 小块空间的内存池 147 | * 16.3 循环引用的垃圾收集 148 | * 16.4 Python中的垃圾收集 149 | 150 | 151 | -------------------------------------------------------------------------------- /Small Python.doc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bat67/python-source-code-analysis/b090c3d51372e31fba4270665773f07eae784ec0/Small Python.doc -------------------------------------------------------------------------------- /assets/cover.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bat67/python-source-code-analysis/b090c3d51372e31fba4270665773f07eae784ec0/assets/cover.jpg -------------------------------------------------------------------------------- /pyc_parser/Makefile: -------------------------------------------------------------------------------- 1 | ##################################################### 2 | #common settings 3 | ##################################################### 4 | CC=g++ 5 | LINK=g++ 6 | INC_PREFIX=-I 7 | LIB_PREFIX=-L 8 | BUILD_PATH=./build 9 | CFLAGS=-c 10 | TARGET=pyc_parser 11 | TEST_TARGET=test_$(TARGET) 12 | CUNIT_PATH=/home/robert/CUnit 13 | 14 | ##################################################### 15 | #settings for normal compile 16 | ##################################################### 17 | SRC_PATH=./src 18 | SRCS=$(wildcard $(SRC_PATH)/*.cpp) 19 | OBJS=$(patsubst $(SRC_PATH)/%.cpp,$(BUILD_PATH)/%.o,$(SRCS)) 20 | 21 | INC_DIR=./include $(CUNIT_PATH)/include/CUnit 22 | INCS=$(addprefix $(INC_PREFIX),$(INC_DIR)) 23 | 24 | ##################################################### 25 | #settings for compiling test cases 26 | ##################################################### 27 | TEST_PATH=./test 28 | TEST_SRCS=$(wildcard $(TEST_PATH)/*.cpp) 29 | TEST_OBJS=$(patsubst $(TEST_PATH)/%.cpp,$(BUILD_PATH)/%.o,$(TEST_SRCS)) 30 | 31 | TEST_INC_DIR=$(INC_DIR) $(TEST_PATH) $(CUNIT_PATH)/include/CUnit 32 | TEST_LIB_DIR=$(CUNIT_PATH)/lib 33 | TEST_INCS=$(addprefix $(INC_PREFIX),$(TEST_INC_DIR)) 34 | TEST_LIB_PATHS=$(addprefix $(LIB_PREFIX),$(TEST_LIB_DIR)) 35 | TEST_LIBS=-lcunit 36 | 37 | ##################################################### 38 | # set path or make 39 | ##################################################### 40 | vpath %.cpp $(SRC_PATH) 41 | vpath %.o $(BUILD_PATH) 42 | vpath %.cpp $(TEST_PATH) 43 | 44 | ##################################################### 45 | # normal compile 46 | ##################################################### 47 | all : init $(TARGET) 48 | 49 | $(TARGET) : $(OBJS) 50 | @echo "generate excutable file : $@" 51 | $(LINK) -o $@ $(OBJS) 52 | 53 | $(OBJS) : $(BUILD_PATH)/%.o : $(SRC_PATH)/%.cpp 54 | $(CC) $(CFLAGS) $(INCS) -o $@ $< 55 | 56 | init: 57 | @echo "create $(BUILD_PATH) dir" 58 | mkdir $(BUILD_PATH) 59 | 60 | 61 | ##################################################### 62 | # compile for test 63 | ##################################################### 64 | test: clean init compile_test run_test 65 | 66 | compile_test: $(OBJS) $(TEST_OBJS) 67 | @echo "generate excutable file for testing : $(TEST_TARGET)" 68 | $(LINK) $(TEST_LIBS) $(TEST_LIB_PATHS) -o $(TEST_TARGET) $(TEST_OBJS) $(filter-out %main.o,$(OBJS)) 69 | 70 | $(TEST_OBJS) : $(BUILD_PATH)/%.o : $(TEST_PATH)/%.cpp 71 | $(CC) $(CFLAGS) $(TEST_INCS) -o $@ $< 72 | 73 | run_test: 74 | ./test_main 75 | 76 | ##################################################### 77 | # clean 78 | ##################################################### 79 | clean: 80 | rm -rf $(BUILD_PATH) 81 | rm -f $(TEST_TARGET) 82 | rm -f $(TARGET) 83 | 84 | ##################################################### 85 | # robert's test 86 | ##################################################### 87 | show: 88 | @echo "TEST_SRCS : $(TEST_SRCS)" 89 | @echo "TEST_INCS : $(TEST_INCS)" 90 | @echo "TEST_LIBS : $(TEST_LIBS)" 91 | @echo "TEST_OBJS : $(TEST_OBJS)" 92 | @echo "TEST_TARGET : $(TEST_TARGET)" 93 | -------------------------------------------------------------------------------- /pyc_parser/Readme: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bat67/python-source-code-analysis/b090c3d51372e31fba4270665773f07eae784ec0/pyc_parser/Readme -------------------------------------------------------------------------------- /pyc_parser/bin/opcode.txt: -------------------------------------------------------------------------------- 1 | STOP_CODE 0 2 | POP_TOP 1 3 | ROT_TWO 2 4 | ROT_THREE 3 5 | DUP_TOP 4 6 | ROT_FOUR 5 7 | NOP 9 8 | UNARY_POSITIVE 10 9 | UNARY_NEGATIVE 11 10 | UNARY_NOT 12 11 | UNARY_CONVERT 13 12 | UNARY_INVERT 15 13 | LIST_APPEND 18 14 | BINARY_POWER 19 15 | BINARY_MULTIPLY 20 16 | BINARY_DIVIDE 21 17 | BINARY_MODULO 22 18 | BINARY_ADD 23 19 | BINARY_SUBTRACT 24 20 | BINARY_SUBSCR 25 21 | BINARY_FLOOR_DIVIDE 26 22 | BINARY_TRUE_DIVIDE 27 23 | INPLACE_FLOOR_DIVIDE 28 24 | INPLACE_TRUE_DIVIDE 29 25 | SLICE 30 26 | STORE_SLICE 40 27 | DELETE_SLICE 50 28 | INPLACE_ADD 55 29 | INPLACE_SUBTRACT 56 30 | INPLACE_MULTIPLY 57 31 | INPLACE_DIVIDE 58 32 | INPLACE_MODULO 59 33 | STORE_SUBSCR 60 34 | DELETE_SUBSCR 61 35 | BINARY_LSHIFT 62 36 | BINARY_RSHIFT 63 37 | BINARY_AND 64 38 | BINARY_XOR 65 39 | BINARY_OR 66 40 | INPLACE_POWER 67 41 | GET_ITER 68 42 | PRINT_EXPR 70 43 | PRINT_ITEM 71 44 | PRINT_NEWLINE 72 45 | PRINT_ITEM_TO 73 46 | PRINT_NEWLINE_TO 74 47 | INPLACE_LSHIFT 75 48 | INPLACE_RSHIFT 76 49 | INPLACE_AND 77 50 | INPLACE_XOR 78 51 | INPLACE_OR 79 52 | BREAK_LOOP 80 53 | WITH_CLEANUP 81 54 | LOAD_LOCALS 82 55 | RETURN_VALUE 83 56 | IMPORT_STAR 84 57 | EXEC_STMT 85 58 | YIELD_VALUE 86 59 | POP_BLOCK 87 60 | END_FINALLY 88 61 | BUILD_CLASS 89 62 | STORE_NAME 90 63 | DELETE_NAME 91 64 | UNPACK_SEQUENCE 92 65 | FOR_ITER 93 66 | STORE_ATTR 95 67 | DELETE_ATTR 96 68 | STORE_GLOBAL 97 69 | DELETE_GLOBAL 98 70 | DUP_TOPX 99 71 | LOAD_CONST 100 72 | LOAD_NAME 101 73 | BUILD_TUPLE 102 74 | BUILD_LIST 103 75 | BUILD_MAP 104 76 | LOAD_ATTR 105 77 | COMPARE_OP 106 78 | IMPORT_NAME 107 79 | IMPORT_FROM 108 80 | JUMP_FORWARD 110 81 | JUMP_IF_FALSE 111 82 | JUMP_IF_TRUE 112 83 | JUMP_ABSOLUTE 113 84 | LOAD_GLOBAL 116 85 | CONTINUE_LOOP 119 86 | SETUP_LOOP 120 87 | SETUP_EXCEPT 121 88 | SETUP_FINALLY 122 89 | LOAD_FAST 124 90 | STORE_FAST 125 91 | DELETE_FAST 126 92 | RAISE_VARARGS 130 93 | CALL_FUNCTION 131 94 | MAKE_FUNCTION 132 95 | BUILD_SLICE 133 96 | MAKE_CLOSURE 134 97 | LOAD_CLOSURE 135 98 | LOAD_DEREF 136 99 | STORE_DEREF 137 100 | CALL_FUNCTION_VAR 140 101 | CALL_FUNCTION_KW 141 102 | CALL_FUNCTION_VAR_KW 142 -------------------------------------------------------------------------------- /pyc_parser/bin/pyc_generator.py: -------------------------------------------------------------------------------- 1 | import imp 2 | import sys 3 | 4 | def generate_pyc(name): 5 | fp, pathname, description = imp.find_module(name) 6 | try: 7 | imp.load_module(name, fp, pathname, description) 8 | finally: 9 | if fp: 10 | fp.close() 11 | 12 | if __name__ == '__main__': 13 | generate_pyc(sys.argv[1]) -------------------------------------------------------------------------------- /pyc_parser/bin/to_xml.py: -------------------------------------------------------------------------------- 1 | import imp 2 | import sys 3 | import os 4 | 5 | def generate_pyc(name): 6 | fp, pathname, description = imp.find_module(name) 7 | try: 8 | imp.load_module(name, fp, pathname, description) 9 | finally: 10 | if fp: 11 | fp.close() 12 | 13 | if __name__ == '__main__': 14 | py_name = sys.argv[1] 15 | module_name = py_name[:py_name.index(".")] 16 | generate_pyc(module_name) 17 | if os.path.exists('./pyc_parser.exe'): 18 | #for Win32 19 | exe = '.\\pyc_parser.exe' 20 | else: 21 | #for Linux 22 | exe = './pyc_parser' 23 | cmd = "%s %s" % (exe, module_name + ".pyc",) 24 | os.system(cmd) 25 | -------------------------------------------------------------------------------- /pyc_parser/include/PycParser.h: -------------------------------------------------------------------------------- 1 | #ifndef __SPY_PYCPARSER_H_ 2 | #define __SPY_PYCPARSER_H_ 3 | 4 | #include 5 | #include 6 | #include 7 | using namespace std; 8 | 9 | #include "reader.h" 10 | #include "writer.h" 11 | #include "codeObject.h" 12 | #include "stringObject.h" 13 | #include "intObject.h" 14 | #include "tupleObject.h" 15 | #include "opCode.h" 16 | 17 | #define TYPE_UNKNOWN '?' 18 | #define TYPE_NULL '0' 19 | #define TYPE_NONE 'N' 20 | #define TYPE_FALSE 'F' 21 | #define TYPE_TRUE 'T' 22 | #define TYPE_STOPITER 'S' 23 | #define TYPE_ELLIPSIS '.' 24 | #define TYPE_INT 'i' 25 | #define TYPE_INT64 'I' 26 | #define TYPE_FLOAT 'f' 27 | #define TYPE_BINARY_FLOAT 'g' 28 | #define TYPE_COMPLEX 'x' 29 | #define TYPE_BINARY_COMPLEX 'y' 30 | #define TYPE_LONG 'l' 31 | #define TYPE_STRING 's' 32 | #define TYPE_INTERNED 't' 33 | #define TYPE_STRINGREF 'R' 34 | #define TYPE_TUPLE '(' 35 | #define TYPE_LIST '[' 36 | #define TYPE_DICT '{' 37 | #define TYPE_CODE 'c' 38 | #define TYPE_UNICODE 'u' 39 | #define TYPE_SET '<' 40 | #define TYPE_FROZENSET '>' 41 | 42 | #define MAGIC (62131 | ((long)'\r'<<16) | ((long)'\n'<<24)) 43 | 44 | class PycParser 45 | { 46 | public: 47 | PyObject* Parse(const char* fileName) 48 | { 49 | m_StrIndexInList = 0; 50 | //open pyc file 51 | m_File = fopen(fileName, "rb"); 52 | if(m_File == NULL) 53 | { 54 | cout << "[Error] : Can't open file " << fileName << endl; 55 | return NULL; 56 | } 57 | 58 | //open xml file writer 59 | m_Writer.open(fileName); 60 | 61 | if(ReadMagicNumber() == MAGIC) 62 | { 63 | cout << "[Info] : Valid Pyc File!" << endl; 64 | } 65 | else 66 | { 67 | cout << "[Info] : Invalid Pyc File!" << endl; 68 | return NULL; 69 | } 70 | 71 | long modifiedTime = ReadModifiedTime(); 72 | cout << "[Info] : Last Modified Time : " << asctime(localtime(&modifiedTime)) << "\n\n\n"; 73 | PyObject* code = ReadObject(); 74 | 75 | //close the pyc file 76 | fclose(m_File); 77 | return code; 78 | } 79 | 80 | private: 81 | int ReadMagicNumber() 82 | { 83 | return m_Reader.ReadInt(m_File); 84 | } 85 | 86 | int ReadModifiedTime() 87 | { 88 | return m_Reader.ReadInt(m_File); 89 | } 90 | 91 | PyObject* ReadObject() 92 | { 93 | int type = m_Reader.ReadByte(m_File); 94 | switch(type) 95 | { 96 | case TYPE_UNKNOWN: 97 | break; 98 | case TYPE_NULL: 99 | break; 100 | case TYPE_NONE: 101 | { 102 | m_Writer.Write(""); 103 | return PyNone; 104 | } 105 | break; 106 | case TYPE_FALSE: 107 | cout << "False" << endl; 108 | break; 109 | case TYPE_TRUE: 110 | cout << "True" << endl; 111 | break; 112 | case TYPE_STOPITER: 113 | cout << "StopIter" << endl; 114 | break; 115 | case TYPE_ELLIPSIS: 116 | cout << "Ellipsis" << endl; 117 | break; 118 | case TYPE_INT: 119 | { 120 | int value = m_Reader.ReadInt(m_File); 121 | PyObject* object = PyInt_Create(value); 122 | sprintf(temp, "\0", value); 123 | m_Writer.Write(temp); 124 | return object; 125 | } 126 | break; 127 | case TYPE_INT64: 128 | cout << "Int64" << endl; 129 | break; 130 | case TYPE_FLOAT: 131 | cout << "Float" << endl; 132 | break; 133 | case TYPE_COMPLEX: 134 | cout << "Complex" << endl; 135 | break; 136 | case TYPE_LONG: 137 | cout << "Long" << endl; 138 | break; 139 | case TYPE_INTERNED:/*fall through*/ 140 | case TYPE_STRING: 141 | { 142 | long length = m_Reader.ReadInt(m_File); 143 | char buffer[1024]; 144 | buffer[length] = '\0'; 145 | m_Reader.ReadString(buffer, length, m_File); 146 | PyObject* strObject = PyString_Create(buffer, length); 147 | //we replace the <> by [] to let the XML cna be displayed in browser 148 | if(buffer[0] == '<') 149 | { 150 | buffer[0] = '['; 151 | } 152 | if(buffer[length-1] == '>') 153 | { 154 | buffer[length-1] = ']'; 155 | } 156 | if(type == TYPE_INTERNED) 157 | { 158 | PyString_InternInPlace(&strObject); 159 | m_vecInternedString.push_back(strObject); 160 | if(strlen(buffer) == length && IsTxtAsciiChar(buffer[0])) 161 | { 162 | cout << "string in buffer : " << buffer << endl; 163 | sprintf(temp, "\0", m_StrIndexInList++, length, buffer); 164 | } 165 | else 166 | { 167 | sprintf(temp, "\0", m_StrIndexInList++, length); 168 | } 169 | } 170 | else 171 | { 172 | if(strlen(buffer) == length && IsTxtAsciiChar(buffer[0])) 173 | { 174 | cout << "string in buffer : " << buffer << endl; 175 | sprintf(temp, "\0", length, buffer); 176 | } 177 | else 178 | { 179 | sprintf(temp, "\0", length); 180 | } 181 | } 182 | m_Writer.Write(temp); 183 | return strObject; 184 | } 185 | break; 186 | case TYPE_STRINGREF: 187 | { 188 | int index = m_Reader.ReadInt(m_File); 189 | PyObject* strObject = m_vecInternedString[index]; 190 | sprintf(temp, "\0", index, PyString_GetRawString(strObject)); 191 | m_Writer.Write(temp); 192 | return strObject; 193 | } 194 | break; 195 | case TYPE_TUPLE: 196 | { 197 | cout << "Tuple" << endl; 198 | int length = m_Reader.ReadInt(m_File); 199 | PyObject* tuple = PyTuple_Create(length); 200 | for(int i = 0; i < length; ++i) 201 | { 202 | PyObject* object = ReadObject(); 203 | PyTuple_AddItem(tuple, object); 204 | } 205 | (tuple->type)->print(tuple, stdout); 206 | return tuple; 207 | } 208 | break; 209 | case TYPE_LIST: 210 | cout << "List" << endl; 211 | break; 212 | case TYPE_DICT: 213 | cout << "Dict" << endl; 214 | break; 215 | case TYPE_CODE: 216 | { 217 | // cout << "==================== Begin Code ====================" << endl; 218 | m_Writer.Write(""); 219 | int argCount = m_Reader.ReadInt(m_File); 220 | sprintf(temp, "\0", argCount); 221 | m_Writer.Write(temp); 222 | 223 | int localCount = m_Reader.ReadInt(m_File); 224 | sprintf(temp, "\0", localCount); 225 | m_Writer.Write(temp); 226 | 227 | int stackSize = m_Reader.ReadInt(m_File); 228 | sprintf(temp, "\0", stackSize); 229 | m_Writer.Write(temp); 230 | 231 | int flags = m_Reader.ReadInt(m_File); 232 | sprintf(temp, "\0", flags); 233 | m_Writer.Write(temp); 234 | // cout << "***** Code *****" << endl; 235 | m_Writer.Write(""); 236 | PyObject* code = ReadObject(); 237 | m_Writer.Write(""); 238 | // cout << "***** Consts *****" << endl; 239 | m_Writer.Write(""); 240 | PyObject* consts = ReadObject(); 241 | m_Writer.Write(""); 242 | // cout << "***** Names *****" << endl; 243 | m_Writer.Write(""); 244 | PyObject* names = ReadObject(); 245 | m_Writer.Write(""); 246 | //cout << "***** varNames *****" << endl; 247 | m_Writer.Write(""); 248 | PyObject* varNames = ReadObject(); 249 | m_Writer.Write(""); 250 | // cout << "***** freeVars *****" << endl; 251 | m_Writer.Write(""); 252 | PyObject* freeVars = ReadObject(); 253 | m_Writer.Write(""); 254 | // cout << "***** cellVars *****" << endl; 255 | m_Writer.Write(""); 256 | PyObject* cellVars = ReadObject(); 257 | m_Writer.Write(""); 258 | // cout << "***** fileName *****" << endl; 259 | m_Writer.Write(""); 260 | PyObject* fileName = ReadObject(); 261 | m_Writer.Write(""); 262 | // cout << "***** name *****" << endl; 263 | m_Writer.Write(""); 264 | PyObject* name = ReadObject(); 265 | m_Writer.Write(""); 266 | // cout << "***** firstLineNo *****" << endl; 267 | m_Writer.Write(""); 268 | int firstLineNo = m_Reader.ReadInt(m_File); 269 | m_Writer.Write(""); 270 | // cout << "***** lnotab *****" << endl; 271 | m_Writer.Write(""); 272 | PyObject* lnotab = ReadObject(); 273 | ParseOpCode(code, lnotab, firstLineNo); 274 | m_Writer.Write(""); 275 | m_Writer.Write(""); 276 | // cout << "==================== End Code ====================\n\n\n" << endl; 277 | 278 | PyObject* codeObject = PyCode_Create( 279 | argCount, localCount, stackSize, flags, 280 | code, consts, names, varNames, 281 | freeVars, cellVars, fileName, name, 282 | firstLineNo, lnotab 283 | ); 284 | return codeObject; 285 | } 286 | break; 287 | case TYPE_UNICODE: 288 | cout << "Unicode" << endl; 289 | break; 290 | default: 291 | cout << "Can't reach this point" << endl; 292 | break; 293 | } 294 | return NULL; 295 | } 296 | 297 | void ParseOpCode(PyObject* code, PyObject* lnotab, int firstLine) 298 | { 299 | if(code->type != &PyString_Type) 300 | { 301 | cout << "[Error]ParseOpCode : code is not a PyStringObject" << endl; 302 | exit(1); 303 | } 304 | 305 | if(lnotab->type != &PyString_Type) 306 | { 307 | cout << "[Error]ParseOpCode : lnotab is not a PyStringObject" << endl; 308 | exit(1); 309 | } 310 | 311 | unsigned char* firstInstruction = (unsigned char*)PyString_GetRawString(code); 312 | unsigned char* nextInstruction = firstInstruction; 313 | int codeLength = PyString_GetLength(code); 314 | 315 | int opCode = -1; 316 | int opArg = -1; 317 | 318 | unsigned char* nextSourceLine = (unsigned char*)PyString_GetRawString(lnotab); 319 | unsigned short currentOpNo = 0; 320 | unsigned short currentLineNo = firstLine; 321 | int lnotabLength = PyString_GetLength(lnotab)/2; 322 | int lnotabIndex = 0; 323 | 324 | #define NEXT_OP() (*nextInstruction++) 325 | #define NEXT_ARG() (nextInstruction += 2, (nextInstruction[-1]<<8) + nextInstruction[-2]) 326 | 327 | while(nextInstruction-firstInstruction < codeLength) 328 | { 329 | //get source code line in .py 330 | unsigned short delta = nextInstruction-firstInstruction; 331 | nextSourceLine = (unsigned char*)PyString_GetRawString(lnotab); 332 | currentOpNo = 0; 333 | currentLineNo = firstLine; 334 | for(int i = 0; i < lnotabLength; ++i) 335 | { 336 | currentOpNo += *(nextSourceLine++); 337 | if(currentOpNo > delta) 338 | { 339 | break; 340 | } 341 | currentLineNo += *(nextSourceLine++); 342 | } 343 | 344 | //get op code and its arguments 345 | opCode = NEXT_OP(); 346 | opArg = -9999; 347 | if(HAS_ARG(opCode)) 348 | { 349 | opArg = NEXT_ARG(); 350 | } 351 | 352 | const char* codeName = m_OpCodeSet.GetStringById(opCode); 353 | 354 | if(opArg != -9999) 355 | { 356 | sprintf(temp, "\0", opCode, codeName, opArg, currentLineNo); 357 | } 358 | else 359 | { 360 | sprintf(temp, "\0", opCode, codeName, currentLineNo); 361 | } 362 | m_Writer.Write(temp); 363 | } 364 | 365 | } 366 | 367 | bool IsTxtAsciiChar(char character) 368 | { 369 | if( (character >= 33/* for ! */) && (character <= 126/* for ~ */) ) 370 | { 371 | return true; 372 | } 373 | else 374 | { 375 | return false; 376 | } 377 | } 378 | private: 379 | OpCodeSet m_OpCodeSet; 380 | Writer m_Writer; 381 | Reader m_Reader; 382 | FILE *m_File; 383 | char temp[1024]; 384 | int m_StrIndexInList; 385 | vector m_vecInternedString; /* dict on marshal, list on unmarshal */ 386 | }; 387 | #endif 388 | -------------------------------------------------------------------------------- /pyc_parser/include/codeObject.h: -------------------------------------------------------------------------------- 1 | #ifndef __SPY_CODEOBJECT_H_ 2 | #define __SPY_CODEOBJECT_H_ 3 | 4 | #include "object.h" 5 | 6 | typedef struct tagPyCodeObject 7 | { 8 | PyObject_HEAD; 9 | int argCount; /* #arguments, except *args */ 10 | int localCount; /* #local variables */ 11 | int stackSize; /* #entries needed for evaluation stack */ 12 | int flags; /* CO_..., see below */ 13 | PyObject* code; /* instruction opcodes */ 14 | PyObject* consts; /* list (constants used) */ 15 | PyObject* names; /* list of strings (names used) */ 16 | PyObject* varNames; /* tuple of strings (local variable names) */ 17 | PyObject* freeVars; /* tuple of strings (free variable names) */ 18 | PyObject* cellVars; /* tuple of strings (cell variable names) */ 19 | /* The rest doesn't count for hash/cmp */ 20 | PyObject* fileName; /* string (where it was loaded from) */ 21 | PyObject* name; /* string (name, for reference) */ 22 | int firstLineNo; /* first source line number */ 23 | PyObject* lnotab; /* string (encoding addr<->lineno mapping) */ 24 | }PyCodeObject; 25 | 26 | extern PyTypeObject PyCode_Type; 27 | 28 | PyObject* PyCode_Create(int, int, int, int, PyObject*, PyObject*, PyObject*, PyObject*, PyObject*, PyObject*, PyObject*, PyObject*, int, PyObject*); 29 | 30 | #endif 31 | -------------------------------------------------------------------------------- /pyc_parser/include/dictObject.h: -------------------------------------------------------------------------------- 1 | #ifndef __SPY_DICTOBJECT_H_ 2 | #define __SPY_DICTOBJECT_H_ 3 | 4 | #include "object.h" 5 | 6 | typedef struct tagPyDictObject 7 | { 8 | PyObject_HEAD; 9 | map dict; 10 | }PyDictObject; 11 | 12 | extern PyTypeObject PyDict_Type; 13 | 14 | PyObject* PyDict_Create(); 15 | int PyDict_SetItem(PyObject* target, PyObject* key, PyObject* value); 16 | PyObject* PyDict_GetItem(PyObject* target, PyObject* key); 17 | #endif 18 | -------------------------------------------------------------------------------- /pyc_parser/include/intObject.h: -------------------------------------------------------------------------------- 1 | #ifndef __SPY_INTOBJECT_H_ 2 | #define __SPY_INTOBJECT_H_ 3 | 4 | #include "object.h" 5 | 6 | typedef struct tagPyIntObject 7 | { 8 | PyObject_HEAD; 9 | int value; 10 | }PyIntObject; 11 | 12 | extern PyTypeObject PyInt_Type; 13 | 14 | PyObject* PyInt_Create(int value); 15 | long PyInt_GetRawValue(PyObject* object); 16 | #endif 17 | -------------------------------------------------------------------------------- /pyc_parser/include/object.h: -------------------------------------------------------------------------------- 1 | #ifndef __SPY_OBJECT_H_ 2 | #define __SPY_OBJECT_H_ 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | using namespace std; 9 | 10 | //definition of PyObject 11 | #define PyObject_HEAD \ 12 | int refCount;\ 13 | struct tagPyTypeObject *type 14 | 15 | #define PyObject_HEAD_INIT(typePtr)\ 16 | 0, typePtr 17 | 18 | typedef struct tagPyObject 19 | { 20 | PyObject_HEAD; 21 | }PyObject; 22 | 23 | //definition of PyTypeObject 24 | typedef void (*PrintFun)(PyObject* object, FILE* target); 25 | typedef PyObject* (*AddFun)(PyObject* left, PyObject* right); 26 | typedef long (*HashFun)(PyObject* object); 27 | 28 | typedef struct tagPyTypeObject 29 | { 30 | PyObject_HEAD; 31 | char* name; 32 | PrintFun print; 33 | AddFun add; 34 | HashFun hash; 35 | }PyTypeObject; 36 | 37 | extern PyTypeObject PyType_Type; 38 | extern PyObject PyNoneObject; 39 | #define PyNone (&PyNoneObject); 40 | 41 | bool CheckType(const char* caller, PyObject* object, PyTypeObject* type); 42 | 43 | #endif 44 | -------------------------------------------------------------------------------- /pyc_parser/include/opCode.h: -------------------------------------------------------------------------------- 1 | #ifndef __SPY_OPCODE_H_ 2 | #define __SPY_OPCODE_H_ 3 | 4 | #ifdef __cplusplus 5 | extern "C" { 6 | #endif 7 | 8 | 9 | /* Instruction opcodes for compiled code */ 10 | 11 | #define STOP_CODE 0 12 | #define POP_TOP 1 13 | #define ROT_TWO 2 14 | #define ROT_THREE 3 15 | #define DUP_TOP 4 16 | #define ROT_FOUR 5 17 | #define NOP 9 18 | 19 | #define UNARY_POSITIVE 10 20 | #define UNARY_NEGATIVE 11 21 | #define UNARY_NOT 12 22 | #define UNARY_CONVERT 13 23 | 24 | #define UNARY_INVERT 15 25 | 26 | #define LIST_APPEND 18 27 | #define BINARY_POWER 19 28 | 29 | #define BINARY_MULTIPLY 20 30 | #define BINARY_DIVIDE 21 31 | #define BINARY_MODULO 22 32 | #define BINARY_ADD 23 33 | #define BINARY_SUBTRACT 24 34 | #define BINARY_SUBSCR 25 35 | #define BINARY_FLOOR_DIVIDE 26 36 | #define BINARY_TRUE_DIVIDE 27 37 | #define INPLACE_FLOOR_DIVIDE 28 38 | #define INPLACE_TRUE_DIVIDE 29 39 | 40 | #define SLICE 30 41 | /* Also uses 31-33 */ 42 | 43 | #define STORE_SLICE 40 44 | /* Also uses 41-43 */ 45 | 46 | #define DELETE_SLICE 50 47 | /* Also uses 51-53 */ 48 | 49 | #define INPLACE_ADD 55 50 | #define INPLACE_SUBTRACT 56 51 | #define INPLACE_MULTIPLY 57 52 | #define INPLACE_DIVIDE 58 53 | #define INPLACE_MODULO 59 54 | #define STORE_SUBSCR 60 55 | #define DELETE_SUBSCR 61 56 | 57 | #define BINARY_LSHIFT 62 58 | #define BINARY_RSHIFT 63 59 | #define BINARY_AND 64 60 | #define BINARY_XOR 65 61 | #define BINARY_OR 66 62 | #define INPLACE_POWER 67 63 | #define GET_ITER 68 64 | 65 | #define PRINT_EXPR 70 66 | #define PRINT_ITEM 71 67 | #define PRINT_NEWLINE 72 68 | #define PRINT_ITEM_TO 73 69 | #define PRINT_NEWLINE_TO 74 70 | #define INPLACE_LSHIFT 75 71 | #define INPLACE_RSHIFT 76 72 | #define INPLACE_AND 77 73 | #define INPLACE_XOR 78 74 | #define INPLACE_OR 79 75 | #define BREAK_LOOP 80 76 | #define WITH_CLEANUP 81 77 | #define LOAD_LOCALS 82 78 | #define RETURN_VALUE 83 79 | #define IMPORT_STAR 84 80 | #define EXEC_STMT 85 81 | #define YIELD_VALUE 86 82 | #define POP_BLOCK 87 83 | #define END_FINALLY 88 84 | #define BUILD_CLASS 89 85 | 86 | #define HAVE_ARGUMENT 90 /* Opcodes from here have an argument: */ 87 | 88 | #define STORE_NAME 90 /* Index in name list */ 89 | #define DELETE_NAME 91 /* "" */ 90 | #define UNPACK_SEQUENCE 92 /* Number of sequence items */ 91 | #define FOR_ITER 93 92 | 93 | #define STORE_ATTR 95 /* Index in name list */ 94 | #define DELETE_ATTR 96 /* "" */ 95 | #define STORE_GLOBAL 97 /* "" */ 96 | #define DELETE_GLOBAL 98 /* "" */ 97 | #define DUP_TOPX 99 /* number of items to duplicate */ 98 | #define LOAD_CONST 100 /* Index in const list */ 99 | #define LOAD_NAME 101 /* Index in name list */ 100 | #define BUILD_TUPLE 102 /* Number of tuple items */ 101 | #define BUILD_LIST 103 /* Number of list items */ 102 | #define BUILD_MAP 104 /* Always zero for now */ 103 | #define LOAD_ATTR 105 /* Index in name list */ 104 | #define COMPARE_OP 106 /* Comparison operator */ 105 | #define IMPORT_NAME 107 /* Index in name list */ 106 | #define IMPORT_FROM 108 /* Index in name list */ 107 | 108 | #define JUMP_FORWARD 110 /* Number of bytes to skip */ 109 | #define JUMP_IF_FALSE 111 /* "" */ 110 | #define JUMP_IF_TRUE 112 /* "" */ 111 | #define JUMP_ABSOLUTE 113 /* Target byte offset from beginning of code */ 112 | 113 | #define LOAD_GLOBAL 116 /* Index in name list */ 114 | 115 | #define CONTINUE_LOOP 119 /* Start of loop (absolute) */ 116 | #define SETUP_LOOP 120 /* Target address (absolute) */ 117 | #define SETUP_EXCEPT 121 /* "" */ 118 | #define SETUP_FINALLY 122 /* "" */ 119 | 120 | #define LOAD_FAST 124 /* Local variable number */ 121 | #define STORE_FAST 125 /* Local variable number */ 122 | #define DELETE_FAST 126 /* Local variable number */ 123 | 124 | #define RAISE_VARARGS 130 /* Number of raise arguments (1, 2 or 3) */ 125 | /* CALL_FUNCTION_XXX opcodes defined below depend on this definition */ 126 | #define CALL_FUNCTION 131 /* #args + (#kwargs<<8) */ 127 | #define MAKE_FUNCTION 132 /* #defaults */ 128 | #define BUILD_SLICE 133 /* Number of items */ 129 | 130 | #define MAKE_CLOSURE 134 /* #free vars */ 131 | #define LOAD_CLOSURE 135 /* Load free variable from closure */ 132 | #define LOAD_DEREF 136 /* Load and dereference from closure cell */ 133 | #define STORE_DEREF 137 /* Store into cell */ 134 | 135 | /* The next 3 opcodes must be contiguous and satisfy 136 | (CALL_FUNCTION_VAR - CALL_FUNCTION) & 3 == 1 */ 137 | #define CALL_FUNCTION_VAR 140 /* #args + (#kwargs<<8) */ 138 | #define CALL_FUNCTION_KW 141 /* #args + (#kwargs<<8) */ 139 | #define CALL_FUNCTION_VAR_KW 142 /* #args + (#kwargs<<8) */ 140 | 141 | /* Support for opargs more than 16 bits long */ 142 | #define EXTENDED_ARG 143 143 | 144 | #define HAS_ARG(op) ((op) >= HAVE_ARGUMENT) 145 | 146 | #ifdef __cplusplus 147 | } 148 | #endif 149 | 150 | #include 151 | #include 152 | #include 153 | #include 154 | using namespace std; 155 | class OpCodeSet 156 | { 157 | public: 158 | OpCodeSet() 159 | { 160 | ifstream infile("opcode.txt"); 161 | int id; 162 | string code; 163 | while(infile >> code && infile >> id) 164 | { 165 | m_mapId2Str.insert(map::value_type(id, code)); 166 | } 167 | infile.close(); 168 | } 169 | public: 170 | const char* GetStringById(int id) 171 | { 172 | map::iterator it = m_mapId2Str.find(id); 173 | if(id == EXTENDED_ARG) 174 | { 175 | int i = 0; 176 | } 177 | if(it == m_mapId2Str.end()) 178 | { 179 | cout << "[Error]OpCodeSet::GetStringById : Can't find id in map" << endl; 180 | exit(1); 181 | return NULL; 182 | } 183 | 184 | return (it->second).c_str(); 185 | } 186 | private: 187 | map m_mapId2Str; 188 | }; 189 | 190 | #endif 191 | -------------------------------------------------------------------------------- /pyc_parser/include/reader.h: -------------------------------------------------------------------------------- 1 | #ifndef __SPY_READER_H_ 2 | #define __SPY_READER_H_ 3 | 4 | class Reader 5 | { 6 | public: 7 | int ReadInt(FILE* file) 8 | { 9 | unsigned char number[5]; 10 | number[4] = '\0'; 11 | number[0] = fgetc(file); 12 | number[1] = fgetc(file); 13 | number[2] = fgetc(file); 14 | number[3] = fgetc(file); 15 | return *(int*)(number); 16 | } 17 | 18 | int ReadByte(FILE* file) 19 | { 20 | return fgetc(file); 21 | } 22 | 23 | void ReadString(char* buffer, int length, FILE* file) 24 | { 25 | fread(buffer, sizeof(char), length, file); 26 | } 27 | }; 28 | 29 | #endif 30 | -------------------------------------------------------------------------------- /pyc_parser/include/stringObject.h: -------------------------------------------------------------------------------- 1 | #ifndef __SPY_STRINGOBJECT_H_ 2 | #define __SPY_STRINGOBJECT_H_ 3 | 4 | #include "object.h" 5 | 6 | typedef struct tagPyStringObject 7 | { 8 | PyObject_HEAD; 9 | long hashValue; 10 | char value[1024]; 11 | int length; 12 | }PyStringObject; 13 | 14 | extern PyTypeObject PyString_Type; 15 | 16 | PyObject* PyString_Create(char* value, int length); 17 | void PyString_InternInPlace(PyObject** object); 18 | const char* PyString_GetRawString(PyObject* object); 19 | int PyString_GetLength(PyObject* object); 20 | #endif 21 | -------------------------------------------------------------------------------- /pyc_parser/include/tupleObject.h: -------------------------------------------------------------------------------- 1 | #ifndef __SPY_TUPLEOBJECT_H_ 2 | #define __SPY_TUPLEOBJECT_H_ 3 | 4 | #include "object.h" 5 | 6 | typedef struct tagPyTupleObject 7 | { 8 | PyObject_HEAD; 9 | int size; 10 | vector tuple; 11 | }PyTupleObject; 12 | 13 | extern PyTypeObject PyTuple_Type; 14 | 15 | PyObject* PyTuple_Create(int size); 16 | void PyTuple_AddItem(PyObject* object, PyObject* item); 17 | int PyTuple_GetSize(PyObject* object); 18 | PyObject* PyTuple_GetItem(PyObject* object, int index); 19 | #endif 20 | -------------------------------------------------------------------------------- /pyc_parser/include/writer.h: -------------------------------------------------------------------------------- 1 | #ifndef __SPY_WRITER_H_ 2 | #define __SPY_WRITER_H_ 3 | 4 | #include 5 | using namespace std; 6 | 7 | class Writer 8 | { 9 | public: 10 | Writer() 11 | { 12 | 13 | } 14 | 15 | 16 | ~Writer() 17 | { 18 | if(m_OutFile) 19 | { 20 | m_OutFile << "" << endl; 21 | m_OutFile.close(); 22 | } 23 | } 24 | 25 | public: 26 | template 27 | void Write(T value, bool newLine = true) 28 | { 29 | m_OutFile << value; 30 | if(newLine) 31 | { 32 | m_OutFile << "\n"; 33 | } 34 | } 35 | 36 | void open(const char* pycFileName) { 37 | string name = pycFileName; 38 | size_t length = name.length(); 39 | name[length-3] = 'x'; 40 | name[length-2] = 'm'; 41 | name[length-1] = 'l'; 42 | m_OutFile.open(name.c_str()); 43 | m_OutFile << "" << endl; 44 | } 45 | 46 | private: 47 | ofstream m_OutFile; 48 | }; 49 | #endif 50 | -------------------------------------------------------------------------------- /pyc_parser/pyc_parser.sln: -------------------------------------------------------------------------------- 1 | Microsoft Visual Studio Solution File, Format Version 8.00 2 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "pyc_parser", "pyc_parser.vcproj", "{4719C170-FF07-4D7D-A61F-EE022B37E739}" 3 | ProjectSection(ProjectDependencies) = postProject 4 | EndProjectSection 5 | EndProject 6 | Global 7 | GlobalSection(SolutionConfiguration) = preSolution 8 | Debug = Debug 9 | Release = Release 10 | EndGlobalSection 11 | GlobalSection(ProjectConfiguration) = postSolution 12 | {4719C170-FF07-4D7D-A61F-EE022B37E739}.Debug.ActiveCfg = Debug|Win32 13 | {4719C170-FF07-4D7D-A61F-EE022B37E739}.Debug.Build.0 = Debug|Win32 14 | {4719C170-FF07-4D7D-A61F-EE022B37E739}.Release.ActiveCfg = Release|Win32 15 | {4719C170-FF07-4D7D-A61F-EE022B37E739}.Release.Build.0 = Release|Win32 16 | EndGlobalSection 17 | GlobalSection(ExtensibilityGlobals) = postSolution 18 | EndGlobalSection 19 | GlobalSection(ExtensibilityAddIns) = postSolution 20 | EndGlobalSection 21 | EndGlobal 22 | -------------------------------------------------------------------------------- /pyc_parser/pyc_parser.vcproj: -------------------------------------------------------------------------------- 1 | 2 | 8 | 9 | 11 | 12 | 13 | 19 | 31 | 33 | 41 | 43 | 45 | 47 | 49 | 51 | 53 | 55 | 57 | 59 | 61 | 62 | 68 | 76 | 78 | 87 | 89 | 91 | 93 | 95 | 97 | 99 | 101 | 103 | 105 | 107 | 108 | 109 | 110 | 111 | 112 | 116 | 118 | 119 | 121 | 122 | 124 | 125 | 127 | 128 | 130 | 131 | 133 | 134 | 136 | 137 | 139 | 140 | 141 | 145 | 147 | 148 | 150 | 151 | 153 | 154 | 156 | 157 | 159 | 160 | 162 | 163 | 165 | 166 | 168 | 169 | 171 | 172 | 174 | 175 | 176 | 180 | 181 | 182 | 183 | 184 | 185 | -------------------------------------------------------------------------------- /pyc_parser/src/PycParser.cpp: -------------------------------------------------------------------------------- 1 | #include "PycParser.h" 2 | 3 | int main(int argc, char* argv[]) 4 | { 5 | PycParser parser; 6 | if(argc != 2) 7 | { 8 | cout << "usage : PycParser " << endl; 9 | return -1; 10 | } 11 | PyObject* code = parser.Parse(argv[1]); 12 | return 0; 13 | } 14 | -------------------------------------------------------------------------------- /pyc_parser/src/codeObject.cpp: -------------------------------------------------------------------------------- 1 | #include "codeObject.h" 2 | #include "stringObject.h" 3 | 4 | PyObject* PyCode_Create(int argCount, int localCount, int stackSize, int flags, 5 | PyObject *code, PyObject *consts, PyObject *names, 6 | PyObject *varNames, PyObject *freeVars, PyObject *cellVars, 7 | PyObject *fileName, PyObject *name, int firstLineNo, 8 | PyObject *lnotab) 9 | { 10 | PyCodeObject* object = new PyCodeObject; 11 | object->refCount = 1; 12 | object->type = &PyCode_Type; 13 | 14 | object->argCount = argCount; 15 | object->localCount = localCount; 16 | object->stackSize = stackSize; 17 | object->flags = flags; 18 | object->code = code; 19 | object->consts = consts; 20 | object->names = names; 21 | object->varNames = varNames; 22 | object->freeVars = freeVars; 23 | object->cellVars = cellVars; 24 | object->fileName = fileName; 25 | object->name = name; 26 | object->firstLineNo = firstLineNo; 27 | object->lnotab = lnotab; 28 | 29 | return (PyObject*)object; 30 | } 31 | 32 | /*************************************************************************/ 33 | //functions for PyCode_Type 34 | static void code_print(PyObject* object, FILE* target=stdout) 35 | { 36 | if(object->type != &PyCode_Type) 37 | { 38 | cout << "[Error]string_print : object is not a string object"; 39 | return; 40 | } 41 | 42 | PyCodeObject* codeObject = (PyCodeObject*)object; 43 | cout << "name, target); 45 | printf(" @%p>", codeObject); 46 | } 47 | 48 | PyTypeObject PyCode_Type = 49 | { 50 | PyObject_HEAD_INIT(&PyType_Type), 51 | "code", 52 | code_print, 53 | 0 54 | }; 55 | -------------------------------------------------------------------------------- /pyc_parser/src/dictObject.cpp: -------------------------------------------------------------------------------- 1 | #include "dictObject.h" 2 | #include "intObject.h" 3 | 4 | PyObject* PyDict_Create() 5 | { 6 | //create object 7 | PyDictObject* object = new PyDictObject; 8 | object->refCount = 1; 9 | object->type = &PyDict_Type; 10 | 11 | return (PyObject*)object; 12 | } 13 | 14 | PyObject* PyDict_GetItem(PyObject* target, PyObject* key) 15 | { 16 | if(!CheckType("PyDict_GetItem", target, &PyDict_Type)) 17 | { 18 | return NULL; 19 | } 20 | 21 | long keyHashValue = (key->type)->hash(key); 22 | map& dict = ((PyDictObject*)target)->dict; 23 | map::iterator it = dict.begin(); 24 | map::iterator end = dict.end(); 25 | for( ; it != end; ++it) 26 | { 27 | PyObject* tempKey = it->first; 28 | long tempKeyHashValue = (tempKey->type)->hash(tempKey); 29 | if(keyHashValue == tempKeyHashValue) 30 | { 31 | return it->second; 32 | } 33 | } 34 | return NULL; 35 | } 36 | 37 | int PyDict_SetItem(PyObject* target, PyObject* key, PyObject* value) 38 | { 39 | if(!CheckType("PyDict_SetItem", target, &PyDict_Type)) 40 | { 41 | return -1; 42 | } 43 | 44 | long keyHashValue = (key->type)->hash(key); 45 | PyObject* intKey = PyInt_Create(keyHashValue); 46 | 47 | PyDictObject* dictObject = (PyDictObject*)target; 48 | (dictObject->dict).insert(map::value_type(intKey, value)); 49 | // cout << "Now the size of dict is : " << dictObject->dict.size() << endl; 50 | return 0; 51 | } 52 | 53 | /***********************************************************************/ 54 | //function for PyDict_Type 55 | static void dict_print(PyObject* object, FILE* target=stdout) 56 | { 57 | if(!CheckType("dict_print", object, &PyDict_Type)) 58 | return; 59 | 60 | PyDictObject* dictObject = (PyDictObject*)object; 61 | cout << "{"; 62 | map::iterator it = (dictObject->dict).begin(); 63 | map::iterator end = (dictObject->dict).end(); 64 | for( ; it != end; ++it) 65 | { 66 | PyObject* key = it->first; 67 | PyObject* value = it->second; 68 | (key->type)->print(key, target); 69 | cout << ":"; 70 | (value->type)->print(value, target); 71 | cout << ", "; 72 | } 73 | cout << "}" << endl; 74 | } 75 | 76 | PyTypeObject PyDict_Type = 77 | { 78 | PyObject_HEAD_INIT(&PyType_Type), 79 | "dict", 80 | dict_print, 81 | 0 82 | }; 83 | -------------------------------------------------------------------------------- /pyc_parser/src/intObject.cpp: -------------------------------------------------------------------------------- 1 | #include "intObject.h" 2 | 3 | PyObject* PyInt_Create(int value) 4 | { 5 | PyIntObject* object = new PyIntObject; 6 | object->refCount = 1; 7 | object->type = &PyInt_Type; 8 | object->value = value; 9 | return (PyObject*)object; 10 | } 11 | 12 | long PyInt_GetRawValue(PyObject* object) 13 | { 14 | if(!CheckType("PyInt_GetRawValue", object, &PyInt_Type)) 15 | { 16 | return 0; 17 | } 18 | 19 | PyIntObject* intObject = (PyIntObject*)object; 20 | return intObject->value; 21 | } 22 | 23 | /*************************************************************************/ 24 | //functions for PyInt_Type 25 | static void int_print(PyObject* object, FILE* target=stdout) 26 | { 27 | PyIntObject* intObject = (PyIntObject*)object; 28 | fprintf(target, "%d", intObject->value); 29 | } 30 | 31 | static long int_hash(PyObject* object) 32 | { 33 | PyIntObject* intObject = (PyIntObject*)object; 34 | return intObject->value; 35 | } 36 | 37 | static PyObject* int_add(PyObject* left, PyObject* right) 38 | { 39 | PyIntObject* leftInt = (PyIntObject*)left; 40 | PyIntObject* rightInt = (PyIntObject*)right; 41 | PyIntObject* result = (PyIntObject*)PyInt_Create(0); 42 | if(result == NULL) 43 | { 44 | printf("We have not enough memory!!"); 45 | } 46 | else 47 | { 48 | result->value = leftInt->value + rightInt->value; 49 | } 50 | return (PyObject*)result; 51 | } 52 | 53 | PyTypeObject PyInt_Type = 54 | { 55 | PyObject_HEAD_INIT(&PyType_Type), 56 | "int", 57 | int_print, 58 | int_add, 59 | int_hash 60 | }; 61 | -------------------------------------------------------------------------------- /pyc_parser/src/object.cpp: -------------------------------------------------------------------------------- 1 | #include "object.h" 2 | 3 | PyTypeObject PyType_Type = 4 | { 5 | PyObject_HEAD_INIT(&PyType_Type), 6 | "type", 7 | 0, 8 | 0 9 | }; 10 | 11 | static void nonePrint(PyObject* object, FILE* target=stdout) 12 | { 13 | fprintf(target, "none"); 14 | } 15 | 16 | static PyTypeObject PyNone_Type = 17 | { 18 | PyObject_HEAD_INIT(&PyType_Type), 19 | "none", 20 | nonePrint, 21 | 0 22 | }; 23 | 24 | PyObject PyNoneObject = 25 | { 26 | PyObject_HEAD_INIT(&PyNone_Type) 27 | }; 28 | 29 | //function 30 | bool CheckType(const char* caller, PyObject* object, PyTypeObject* type) 31 | { 32 | if(object->type != type) 33 | { 34 | cout << "[Error]" << caller << " : object is not a " << type->name << " object" << endl; 35 | return false; 36 | } 37 | return true; 38 | } 39 | -------------------------------------------------------------------------------- /pyc_parser/src/opCode.cpp: -------------------------------------------------------------------------------- 1 | #include "opCode.h" 2 | -------------------------------------------------------------------------------- /pyc_parser/src/stringObject.cpp: -------------------------------------------------------------------------------- 1 | #include "stringObject.h" 2 | #include "dictObject.h" 3 | 4 | PyDictObject* g_internDict = NULL; 5 | 6 | PyObject* PyString_Create(char* value, int length) 7 | { 8 | //create object 9 | PyStringObject* object = new PyStringObject; 10 | object->hashValue = -1; 11 | object->refCount = 1; 12 | object->type = &PyString_Type; 13 | 14 | //set value 15 | memcpy(object->value, value, length); 16 | object->value[length] = '\0'; 17 | object->length = length; 18 | return (PyObject*)object; 19 | } 20 | 21 | void PyString_InternInPlace(PyObject** object) 22 | { 23 | PyStringObject* strObject = (PyStringObject*)(*object); 24 | if(g_internDict == NULL) 25 | { 26 | g_internDict = (PyDictObject*)PyDict_Create(); 27 | } 28 | 29 | PyObject* result = PyDict_GetItem((PyObject*)g_internDict, (PyObject*)strObject); 30 | if(result != NULL) 31 | { 32 | // cout << "Already interned!!!" << endl; 33 | *object = result; 34 | return; 35 | } 36 | 37 | // cout << "Intern it!!!" << endl; 38 | PyDict_SetItem((PyObject*)g_internDict, (PyObject*)strObject, (PyObject*)strObject); 39 | } 40 | 41 | const char* PyString_GetRawString(PyObject* object) 42 | { 43 | if(!CheckType("PyString_GetRawString", object, &PyString_Type)) 44 | { 45 | return NULL; 46 | } 47 | 48 | PyStringObject* strObject = (PyStringObject*)object; 49 | return strObject->value; 50 | } 51 | 52 | int PyString_GetLength(PyObject* object) 53 | { 54 | if(!CheckType("PyString_GetLength", object, &PyString_Type)) 55 | { 56 | return NULL; 57 | } 58 | 59 | PyStringObject* strObject = (PyStringObject*)object; 60 | return strObject->length; 61 | } 62 | 63 | /************************************************************************/ 64 | //function for PyString_Type 65 | static void string_print(PyObject* object, FILE* target=stdout) 66 | { 67 | if(!CheckType("string_print", object, &PyString_Type)) 68 | { 69 | return; 70 | } 71 | PyStringObject* strObject = (PyStringObject*)object; 72 | fprintf(target, "%s", strObject->value); 73 | } 74 | 75 | static long string_hash(PyObject* object) 76 | { 77 | if(!CheckType("string_hash", object, &PyString_Type)) 78 | { 79 | return -1; 80 | } 81 | 82 | PyStringObject* strObject = (PyStringObject*)object; 83 | register int len; 84 | register unsigned char *p; 85 | register long x; 86 | 87 | if (strObject->hashValue != -1) 88 | return strObject->hashValue; 89 | len = strObject->length; 90 | p = (unsigned char *)strObject->value; 91 | x = *p << 7; 92 | while (--len >= 0) 93 | x = (1000003*x) ^ *p++; 94 | x ^= strObject->length; 95 | if (x == -1) 96 | x = -2; 97 | strObject->hashValue = x; 98 | return x; 99 | } 100 | 101 | PyTypeObject PyString_Type = 102 | { 103 | PyObject_HEAD_INIT(&PyType_Type), 104 | "string", 105 | string_print, 106 | 0, 107 | string_hash 108 | }; 109 | -------------------------------------------------------------------------------- /pyc_parser/src/tupleObject.cpp: -------------------------------------------------------------------------------- 1 | #include "tupleObject.h" 2 | 3 | PyObject* PyTuple_Create(int size) 4 | { 5 | //create object 6 | PyTupleObject* object = new PyTupleObject; 7 | object->refCount = 1; 8 | object->type = &PyTuple_Type; 9 | object->size = size; 10 | 11 | return (PyObject*)object; 12 | } 13 | 14 | void PyTuple_AddItem(PyObject* object, PyObject* item) 15 | { 16 | if(!CheckType("PyTuple_AddItem", object, &PyTuple_Type)) 17 | return; 18 | 19 | PyTupleObject* tupleObject = (PyTupleObject*)object; 20 | if((tupleObject->tuple).size() >= tupleObject->size) 21 | { 22 | cout << "[Error]PyTuple_AddItem : size over flow" << endl; 23 | return; 24 | } 25 | 26 | (tupleObject->tuple).push_back(item); 27 | } 28 | 29 | int PyTuple_GetSize(PyObject* object) 30 | { 31 | if(!CheckType("PyTuple_GetSize", object, &PyTuple_Type)) 32 | { 33 | return -1; 34 | } 35 | 36 | PyTupleObject* tupleObject = (PyTupleObject*)object; 37 | return (tupleObject->tuple).size(); 38 | } 39 | 40 | PyObject* PyTuple_GetItem(PyObject* object, int index) 41 | { 42 | if(!CheckType("PyTuple_GetItem", object, &PyTuple_Type)) 43 | { 44 | return NULL; 45 | } 46 | 47 | PyTupleObject* tupleObject = (PyTupleObject*)object; 48 | return (tupleObject->tuple)[index]; 49 | } 50 | 51 | /***********************************************************************/ 52 | //functions for PyTuple_Type 53 | static void tuple_print(PyObject* object, FILE* target=stdout) 54 | { 55 | if(object->type != &PyTuple_Type) 56 | { 57 | cout << "[Error]dict_print : object is not a dict object"; 58 | return; 59 | } 60 | 61 | PyTupleObject* tupleObject = (PyTupleObject*)object; 62 | cout << "("; 63 | vector::iterator it = (tupleObject->tuple).begin(); 64 | vector::iterator end = (tupleObject->tuple).end(); 65 | for( ; it != end; ++it) 66 | { 67 | PyObject* item = *it; 68 | (item->type)->print(item, target); 69 | cout << ", "; 70 | } 71 | cout << ")" << endl; 72 | } 73 | 74 | PyTypeObject PyTuple_Type = 75 | { 76 | PyObject_HEAD_INIT(&PyType_Type), 77 | "tuple", 78 | tuple_print, 79 | 0 80 | }; 81 | -------------------------------------------------------------------------------- /small_python/.vs/small_python/v16/.suo: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bat67/python-source-code-analysis/b090c3d51372e31fba4270665773f07eae784ec0/small_python/.vs/small_python/v16/.suo -------------------------------------------------------------------------------- /small_python/.vs/small_python/v16/Browse.VC.db: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bat67/python-source-code-analysis/b090c3d51372e31fba4270665773f07eae784ec0/small_python/.vs/small_python/v16/Browse.VC.db -------------------------------------------------------------------------------- /small_python/.vs/small_python/v16/Solution.VC.db: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bat67/python-source-code-analysis/b090c3d51372e31fba4270665773f07eae784ec0/small_python/.vs/small_python/v16/Solution.VC.db -------------------------------------------------------------------------------- /small_python/Backup/small_python.sln: -------------------------------------------------------------------------------- 1 | Microsoft Visual Studio Solution File, Format Version 8.00 2 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "samll_python", "samll_python.vcproj", "{CE93E66B-1A83-4AEB-850A-7E07AF661E62}" 3 | ProjectSection(ProjectDependencies) = postProject 4 | EndProjectSection 5 | EndProject 6 | Global 7 | GlobalSection(SolutionConfiguration) = preSolution 8 | Debug = Debug 9 | Release = Release 10 | EndGlobalSection 11 | GlobalSection(ProjectConfiguration) = postSolution 12 | {CE93E66B-1A83-4AEB-850A-7E07AF661E62}.Debug.ActiveCfg = Debug|Win32 13 | {CE93E66B-1A83-4AEB-850A-7E07AF661E62}.Debug.Build.0 = Debug|Win32 14 | {CE93E66B-1A83-4AEB-850A-7E07AF661E62}.Release.ActiveCfg = Release|Win32 15 | {CE93E66B-1A83-4AEB-850A-7E07AF661E62}.Release.Build.0 = Release|Win32 16 | EndGlobalSection 17 | GlobalSection(ExtensibilityGlobals) = postSolution 18 | EndGlobalSection 19 | GlobalSection(ExtensibilityAddIns) = postSolution 20 | EndGlobalSection 21 | EndGlobal 22 | -------------------------------------------------------------------------------- /small_python/Backup1/samll_python.sln: -------------------------------------------------------------------------------- 1 | Microsoft Visual Studio Solution File, Format Version 12.00 2 | # Visual Studio Version 16 3 | VisualStudioVersion = 16.0.30011.22 4 | MinimumVisualStudioVersion = 10.0.40219.1 5 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "samll_python", "samll_python.vcproj", "{CE93E66B-1A83-4AEB-850A-7E07AF661E62}" 6 | EndProject 7 | Global 8 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 9 | Debug|Default = Debug|Default 10 | Release|Default = Release|Default 11 | EndGlobalSection 12 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 13 | {CE93E66B-1A83-4AEB-850A-7E07AF661E62}.Debug|Default.ActiveCfg = Debug|Win32 14 | {CE93E66B-1A83-4AEB-850A-7E07AF661E62}.Debug|Default.Build.0 = Debug|Win32 15 | {CE93E66B-1A83-4AEB-850A-7E07AF661E62}.Release|Default.ActiveCfg = Release|Win32 16 | {CE93E66B-1A83-4AEB-850A-7E07AF661E62}.Release|Default.Build.0 = Release|Win32 17 | EndGlobalSection 18 | GlobalSection(SolutionProperties) = preSolution 19 | HideSolutionNode = FALSE 20 | EndGlobalSection 21 | GlobalSection(ExtensibilityGlobals) = postSolution 22 | SolutionGuid = {2246A6E8-3FFA-4624-BB70-1862954F35F8} 23 | EndGlobalSection 24 | EndGlobal 25 | -------------------------------------------------------------------------------- /small_python/Makefile: -------------------------------------------------------------------------------- 1 | ##################################################### 2 | #common settings 3 | ##################################################### 4 | CC=g++ 5 | LINK=g++ 6 | INC_PREFIX=-I 7 | LIB_PREFIX=-L 8 | BUILD_PATH=./build 9 | CFLAGS=-c 10 | TARGET=small_python 11 | TEST_TARGET=test_$(TARGET) 12 | CUNIT_PATH=/home/robert/CUnit 13 | 14 | ##################################################### 15 | #settings for normal compile 16 | ##################################################### 17 | SRC_PATH=./src 18 | SRCS=$(wildcard $(SRC_PATH)/*.cpp) 19 | OBJS=$(patsubst $(SRC_PATH)/%.cpp,$(BUILD_PATH)/%.o,$(SRCS)) 20 | 21 | INC_DIR=./include $(CUNIT_PATH)/include/CUnit 22 | INCS=$(addprefix $(INC_PREFIX),$(INC_DIR)) 23 | 24 | ##################################################### 25 | #settings for compiling test cases 26 | ##################################################### 27 | TEST_PATH=./test 28 | TEST_SRCS=$(wildcard $(TEST_PATH)/*.cpp) 29 | TEST_OBJS=$(patsubst $(TEST_PATH)/%.cpp,$(BUILD_PATH)/%.o,$(TEST_SRCS)) 30 | 31 | TEST_INC_DIR=$(INC_DIR) $(TEST_PATH) $(CUNIT_PATH)/include/CUnit 32 | TEST_LIB_DIR=$(CUNIT_PATH)/lib 33 | TEST_INCS=$(addprefix $(INC_PREFIX),$(TEST_INC_DIR)) 34 | TEST_LIB_PATHS=$(addprefix $(LIB_PREFIX),$(TEST_LIB_DIR)) 35 | TEST_LIBS=-lcunit 36 | 37 | ##################################################### 38 | # set path or make 39 | ##################################################### 40 | vpath %.cpp $(SRC_PATH) 41 | vpath %.o $(BUILD_PATH) 42 | vpath %.cpp $(TEST_PATH) 43 | 44 | ##################################################### 45 | # normal compile 46 | ##################################################### 47 | all : init $(TARGET) 48 | 49 | $(TARGET) : $(OBJS) 50 | @echo "generate excutable file : $@" 51 | $(LINK) -o $@ $(OBJS) 52 | 53 | $(OBJS) : $(BUILD_PATH)/%.o : $(SRC_PATH)/%.cpp 54 | $(CC) $(CFLAGS) $(INCS) -o $@ $< 55 | 56 | init: 57 | @echo "create $(BUILD_PATH) dir" 58 | mkdir $(BUILD_PATH) 59 | 60 | 61 | ##################################################### 62 | # compile for test 63 | ##################################################### 64 | test: clean init compile_test run_test 65 | 66 | compile_test: $(OBJS) $(TEST_OBJS) 67 | @echo "generate excutable file for testing : $(TEST_TARGET)" 68 | $(LINK) $(TEST_LIBS) $(TEST_LIB_PATHS) -o $(TEST_TARGET) $(TEST_OBJS) $(filter-out %main.o,$(OBJS)) 69 | 70 | $(TEST_OBJS) : $(BUILD_PATH)/%.o : $(TEST_PATH)/%.cpp 71 | $(CC) $(CFLAGS) $(TEST_INCS) -o $@ $< 72 | 73 | run_test: 74 | ./test_main 75 | 76 | ##################################################### 77 | # clean 78 | ##################################################### 79 | clean: 80 | rm -rf $(BUILD_PATH) 81 | rm -f $(TEST_TARGET) 82 | rm -f $(TARGET) 83 | 84 | ##################################################### 85 | # robert's test 86 | ##################################################### 87 | show: 88 | @echo "TEST_SRCS : $(TEST_SRCS)" 89 | @echo "TEST_INCS : $(TEST_INCS)" 90 | @echo "TEST_LIBS : $(TEST_LIBS)" 91 | @echo "TEST_OBJS : $(TEST_OBJS)" 92 | @echo "TEST_TARGET : $(TEST_TARGET)" 93 | -------------------------------------------------------------------------------- /small_python/include/engine.h: -------------------------------------------------------------------------------- 1 | #ifndef __PYTHONREADING_ENGINE_H_ 2 | #define __PYTHONREADING_ENGINE_H_ 3 | 4 | #include "object.h" 5 | #include "intObject.h" 6 | #include "strObject.h" 7 | 8 | #include 9 | #include 10 | #include 11 | 12 | char* info = "********** Python Research **********\nInput 'exit' to exit\n"; 13 | char* prompt = ">>> "; 14 | 15 | class ExcuteEngine 16 | { 17 | public: 18 | void Excute() 19 | { 20 | cout << info; 21 | cout << prompt; 22 | while(getline(cin, m_Command)) 23 | { 24 | if(m_Command.size() == 0) 25 | { 26 | cout << prompt; 27 | continue; 28 | } 29 | else if(m_Command == "exit") 30 | { 31 | return; 32 | } 33 | else 34 | { 35 | ExcuteCommand(m_Command); 36 | } 37 | cout << prompt; 38 | } 39 | } 40 | 41 | private: 42 | void ExcuteCommand(string& command) 43 | { 44 | string::size_type pos = 0; 45 | if((pos = command.find("print ")) != string::npos) 46 | { 47 | ExcutePrint(command.substr(6)); 48 | } 49 | else if((pos = command.find(" = ")) != string::npos) 50 | { 51 | string target = command.substr(0, pos); 52 | string source = command.substr(pos+3); 53 | ExcuteAdd(target, source); 54 | } 55 | else { 56 | cout << "[Error] : Can not recognize : " << command << endl; 57 | } 58 | } 59 | 60 | void ExcutePrint(string symbol) 61 | { 62 | PyObject* object = GetObjectFromSymbol(symbol); 63 | if(object != NULL) 64 | { 65 | PyTypeObject* type = object->type; 66 | type->print(object); 67 | } 68 | } 69 | 70 | void ExcuteAdd(string& target, string& source) 71 | { 72 | string::size_type pos; 73 | if(IsSourceAllDigit(source)) 74 | { 75 | PyObject* intObject = CreatePyIntObject(atoi(source.c_str())); 76 | if(m_Symbol2Object.find(target) == m_Symbol2Object.end()) { 77 | m_Symbol2Object.insert(map::value_type(target, intObject)); 78 | } 79 | else { 80 | m_Symbol2Object[target] = intObject; 81 | } 82 | } 83 | else if(source.find("\"") != string::npos || source.find("'") != string::npos) 84 | { 85 | PyObject* strObject = CreatePyStrObject(source.substr(1, source.size()-2).c_str()); 86 | if(m_Symbol2Object.find(target) == m_Symbol2Object.end()) { 87 | m_Symbol2Object.insert(map::value_type(target, strObject)); 88 | } 89 | else { 90 | m_Symbol2Object[target] = strObject; 91 | } 92 | } 93 | else if((pos = source.find("+")) != string::npos) 94 | { 95 | PyObject* leftObject = GetObjectFromSymbol(Trim(source.substr(0, pos))); 96 | PyObject* rightObject = GetObjectFromSymbol(Trim(source.substr(pos+1))); 97 | if(leftObject != NULL && right != NULL && leftObject->type == rightObject->type) 98 | { 99 | PyObject* result = (leftObject->type)->add(leftObject, rightObject); 100 | m_Symbol2Object.insert(map::value_type(target, result)); 101 | } 102 | } 103 | } 104 | 105 | bool IsSourceAllDigit(string& source) 106 | { 107 | string::size_type len = source.size(); 108 | for(string::size_type i = 0; i < len; ++i) 109 | { 110 | if(!isdigit(source[i])) 111 | { 112 | return false; 113 | } 114 | } 115 | return true; 116 | } 117 | 118 | PyObject* GetObjectFromSymbol(string symbol) 119 | { 120 | map::iterator it = m_Symbol2Object.find(symbol); 121 | if(it == m_Symbol2Object.end()) 122 | { 123 | cout << "[Error] : " << symbol << " is not defined!!" << endl; 124 | return NULL; 125 | } 126 | return it->second; 127 | } 128 | 129 | string Trim(string symbol) { 130 | int length = symbol.length(); 131 | 132 | int start = 0; 133 | while(symbol[start] == ' ') { 134 | ++start; 135 | } 136 | 137 | int end = length-1; 138 | while(symbol[end] == ' ') { 139 | --end; 140 | } 141 | return symbol.substr(start, end+1); 142 | } 143 | private: 144 | string m_Command; 145 | map m_Symbol2Object; 146 | }; 147 | #endif 148 | -------------------------------------------------------------------------------- /small_python/include/intObject.h: -------------------------------------------------------------------------------- 1 | #ifndef __PYTHONREADING_INTOBJECT_H_ 2 | #define __PYTHONREADING_INTOBJECT_H_ 3 | 4 | #include "object.h" 5 | 6 | typedef struct tagPyIntObject 7 | { 8 | PyObject_HEAD; 9 | int value; 10 | }PyIntObject; 11 | 12 | extern PyTypeObject PyInt_Type; 13 | 14 | PyObject* CreatePyIntObject(int value); 15 | #endif 16 | -------------------------------------------------------------------------------- /small_python/include/object.h: -------------------------------------------------------------------------------- 1 | #ifndef __PYTHONREADING_OBJECT_H_ 2 | #define __PYTHONREADING_OBJECT_H_ 3 | 4 | //definition of PyObject 5 | #define PyObject_HEAD \ 6 | int refCount;\ 7 | struct tagPyTypeObject *type 8 | 9 | #define PyObject_HEAD_INIT(typePtr)\ 10 | 0, typePtr 11 | 12 | typedef struct tagPyObject 13 | { 14 | PyObject_HEAD; 15 | }PyObject; 16 | 17 | //definition of PyTypeObject 18 | typedef void (*PrintFun)(PyObject* object); 19 | typedef PyObject* (*AddFun)(PyObject* left, PyObject* right); 20 | 21 | typedef struct tagPyTypeObject 22 | { 23 | PyObject_HEAD; 24 | char* name; 25 | PrintFun print; 26 | AddFun add; 27 | }PyTypeObject; 28 | 29 | extern PyTypeObject PyType_Type; 30 | 31 | #endif 32 | -------------------------------------------------------------------------------- /small_python/include/strObject.h: -------------------------------------------------------------------------------- 1 | #ifndef __PYTHONREADING_STROBJECT_H_ 2 | #define __PYTHONREADING_STROBJECT_H_ 3 | 4 | #include "object.h" 5 | 6 | typedef struct tagPyStrObject 7 | { 8 | PyObject_HEAD; 9 | char value[50]; 10 | }PyStrObject; 11 | 12 | extern PyTypeObject PyStr_Type; 13 | 14 | PyObject* CreatePyStrObject(const char* value); 15 | #endif 16 | -------------------------------------------------------------------------------- /small_python/samll_python.ncb: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bat67/python-source-code-analysis/b090c3d51372e31fba4270665773f07eae784ec0/small_python/samll_python.ncb -------------------------------------------------------------------------------- /small_python/samll_python.suo: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bat67/python-source-code-analysis/b090c3d51372e31fba4270665773f07eae784ec0/small_python/samll_python.suo -------------------------------------------------------------------------------- /small_python/samll_python.vcproj: -------------------------------------------------------------------------------- 1 | 2 | 8 | 9 | 11 | 12 | 13 | 19 | 31 | 33 | 41 | 43 | 45 | 47 | 49 | 51 | 53 | 55 | 57 | 59 | 61 | 62 | 68 | 76 | 78 | 87 | 89 | 91 | 93 | 95 | 97 | 99 | 101 | 103 | 105 | 107 | 108 | 109 | 110 | 111 | 112 | 116 | 118 | 119 | 121 | 122 | 124 | 125 | 127 | 128 | 130 | 131 | 132 | 136 | 138 | 139 | 141 | 142 | 144 | 145 | 147 | 148 | 149 | 153 | 154 | 155 | 156 | 157 | 158 | -------------------------------------------------------------------------------- /small_python/samll_python.vcxproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Debug 6 | Win32 7 | 8 | 9 | Release 10 | Win32 11 | 12 | 13 | 14 | {CE93E66B-1A83-4AEB-850A-7E07AF661E62} 15 | Win32Proj 16 | small_python 17 | 18 | 19 | 20 | Application 21 | v142 22 | MultiByte 23 | 24 | 25 | Application 26 | v142 27 | MultiByte 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | <_ProjectFileVersion>16.0.29911.84 41 | 42 | 43 | Debug\ 44 | Debug\ 45 | true 46 | 47 | 48 | Release\ 49 | Release\ 50 | false 51 | 52 | 53 | 54 | Disabled 55 | ./include;%(AdditionalIncludeDirectories) 56 | WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) 57 | true 58 | EnableFastChecks 59 | MultiThreadedDebug 60 | 61 | Level3 62 | EditAndContinue 63 | 64 | 65 | $(OutDir)samll_python.exe 66 | true 67 | $(OutDir)samll_python.pdb 68 | Console 69 | MachineX86 70 | 71 | 72 | 73 | 74 | WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) 75 | MultiThreaded 76 | 77 | Level3 78 | ProgramDatabase 79 | 80 | 81 | $(OutDir)samll_python.exe 82 | true 83 | Console 84 | true 85 | true 86 | MachineX86 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | -------------------------------------------------------------------------------- /small_python/samll_python.vcxproj.filters: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | {4FC737F1-C7A5-4376-A066-2A32D752A2FF} 6 | cpp;c;cxx;def;odl;idl;hpj;bat;asm;asmx 7 | 8 | 9 | {93995380-89BD-4b04-88EB-625FBE52EBFB} 10 | h;hpp;hxx;hm;inl;inc;xsd 11 | 12 | 13 | {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} 14 | rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx 15 | 16 | 17 | 18 | 19 | Source Files 20 | 21 | 22 | Source Files 23 | 24 | 25 | Source Files 26 | 27 | 28 | Source Files 29 | 30 | 31 | Source Files 32 | 33 | 34 | 35 | 36 | Header Files 37 | 38 | 39 | Header Files 40 | 41 | 42 | Header Files 43 | 44 | 45 | Header Files 46 | 47 | 48 | -------------------------------------------------------------------------------- /small_python/samll_python.vcxproj.user: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | -------------------------------------------------------------------------------- /small_python/small_python.sln: -------------------------------------------------------------------------------- 1 | Microsoft Visual Studio Solution File, Format Version 12.00 2 | # Visual Studio Version 16 3 | VisualStudioVersion = 16.0.30011.22 4 | MinimumVisualStudioVersion = 10.0.40219.1 5 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "samll_python", "samll_python.vcxproj", "{CE93E66B-1A83-4AEB-850A-7E07AF661E62}" 6 | EndProject 7 | Global 8 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 9 | Debug|Default = Debug|Default 10 | Release|Default = Release|Default 11 | EndGlobalSection 12 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 13 | {CE93E66B-1A83-4AEB-850A-7E07AF661E62}.Debug|Default.ActiveCfg = Debug|Win32 14 | {CE93E66B-1A83-4AEB-850A-7E07AF661E62}.Debug|Default.Build.0 = Debug|Win32 15 | {CE93E66B-1A83-4AEB-850A-7E07AF661E62}.Release|Default.ActiveCfg = Release|Win32 16 | {CE93E66B-1A83-4AEB-850A-7E07AF661E62}.Release|Default.Build.0 = Release|Win32 17 | EndGlobalSection 18 | GlobalSection(SolutionProperties) = preSolution 19 | HideSolutionNode = FALSE 20 | EndGlobalSection 21 | GlobalSection(ExtensibilityGlobals) = postSolution 22 | SolutionGuid = {2246A6E8-3FFA-4624-BB70-1862954F35F8} 23 | EndGlobalSection 24 | EndGlobal 25 | -------------------------------------------------------------------------------- /small_python/src/engine.cpp: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /small_python/src/intObject.cpp: -------------------------------------------------------------------------------- 1 | #include "intObject.h" 2 | #include 3 | 4 | PyObject* CreatePyIntObject(int value) 5 | { 6 | PyIntObject* object = new PyIntObject; 7 | object->refCount = 1; 8 | object->type = &PyInt_Type; 9 | object->value = value; 10 | return (PyObject*)object; 11 | } 12 | 13 | static void int_print(PyObject* object) 14 | { 15 | PyIntObject* intObject = (PyIntObject*)object; 16 | printf("%d\n", intObject->value); 17 | } 18 | 19 | static PyObject* int_add(PyObject* left, PyObject* right) 20 | { 21 | PyIntObject* leftInt = (PyIntObject*)left; 22 | PyIntObject* rightInt = (PyIntObject*)right; 23 | PyIntObject* result = (PyIntObject*)CreatePyIntObject(0); 24 | if(result == NULL) 25 | { 26 | printf("We have not enough memory!!"); 27 | } 28 | else 29 | { 30 | result->value = leftInt->value + rightInt->value; 31 | } 32 | return (PyObject*)result; 33 | } 34 | 35 | PyTypeObject PyInt_Type = 36 | { 37 | PyObject_HEAD_INIT(&PyType_Type), 38 | "int", 39 | int_print, 40 | int_add 41 | }; 42 | -------------------------------------------------------------------------------- /small_python/src/main.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | using namespace std; 3 | 4 | #include "object.h" 5 | #include "intObject.h" 6 | #include "engine.h" 7 | 8 | int main() 9 | { 10 | ExcuteEngine engine; 11 | engine.Excute(); 12 | return 0; 13 | } 14 | 15 | -------------------------------------------------------------------------------- /small_python/src/object.cpp: -------------------------------------------------------------------------------- 1 | #include "object.h" 2 | 3 | PyTypeObject PyType_Type = 4 | { 5 | PyObject_HEAD_INIT(&PyType_Type), 6 | "type", 7 | 0, 8 | 0 9 | }; 10 | -------------------------------------------------------------------------------- /small_python/src/strObject.cpp: -------------------------------------------------------------------------------- 1 | #include "strObject.h" 2 | #include 3 | #include 4 | 5 | PyObject* CreatePyStrObject(const char* value) 6 | { 7 | PyStrObject* object = new PyStrObject; 8 | object->refCount = 1; 9 | object->type = &PyStr_Type; 10 | memset(object->value, 0, 50); 11 | if(value != NULL) 12 | { 13 | strcpy(object->value, value); 14 | } 15 | return (PyObject*)object; 16 | } 17 | 18 | static void string_print(PyObject* object) 19 | { 20 | PyStrObject* strObject = (PyStrObject*)object; 21 | printf("%s\n", strObject->value); 22 | } 23 | 24 | static PyObject* string_add(PyObject* left, PyObject* right) 25 | { 26 | PyStrObject* leftStr = (PyStrObject*)left; 27 | PyStrObject* rightStr = (PyStrObject*)right; 28 | PyStrObject* result = (PyStrObject*)CreatePyStrObject(NULL); 29 | if(result == NULL) 30 | { 31 | printf("We have not enough memory!!"); 32 | } 33 | else 34 | { 35 | strcpy(result->value, leftStr->value); 36 | strcat(result->value, rightStr->value); 37 | } 38 | return (PyObject*)result; 39 | } 40 | 41 | PyTypeObject PyStr_Type = 42 | { 43 | PyObject_HEAD_INIT(&PyType_Type), 44 | "str", 45 | string_print, 46 | string_add 47 | }; 48 | -------------------------------------------------------------------------------- /字典对象PyDictObject1.doc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bat67/python-source-code-analysis/b090c3d51372e31fba4270665773f07eae784ec0/字典对象PyDictObject1.doc -------------------------------------------------------------------------------- /字典对象PyDictObject2.doc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bat67/python-source-code-analysis/b090c3d51372e31fba4270665773f07eae784ec0/字典对象PyDictObject2.doc -------------------------------------------------------------------------------- /字典对象PyDictObject3.doc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bat67/python-source-code-analysis/b090c3d51372e31fba4270665773f07eae784ec0/字典对象PyDictObject3.doc -------------------------------------------------------------------------------- /字符串对象PyStringObject1.doc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bat67/python-source-code-analysis/b090c3d51372e31fba4270665773f07eae784ec0/字符串对象PyStringObject1.doc -------------------------------------------------------------------------------- /字符串对象PyStringObject2.doc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bat67/python-source-code-analysis/b090c3d51372e31fba4270665773f07eae784ec0/字符串对象PyStringObject2.doc -------------------------------------------------------------------------------- /字符串对象PyStringObject3.doc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bat67/python-source-code-analysis/b090c3d51372e31fba4270665773f07eae784ec0/字符串对象PyStringObject3.doc --------------------------------------------------------------------------------