├── README └── src ├── Makefile ├── entry.c ├── malloc.c ├── printf.c ├── stdio.c ├── string.c ├── test.c └── tinycrt.h /README: -------------------------------------------------------------------------------- 1 | tinyCRT 2 | ================================================= 3 | This project is a summary of what i have learned a great book on linker & loader and C runtime library. I will gradually enhance it and add more functinalities in the future and make it an usable and compacted C runtime libary. 4 | 5 | build 6 | cd src/ and run make to build the code 7 | 8 | run 9 | cd src/ and run ./test 10 | -------------------------------------------------------------------------------- /src/Makefile: -------------------------------------------------------------------------------- 1 | #marco(variables) definition. here are some special marcos 2 | #$@ name of target to be made 3 | #$< name of related file that cause the action 4 | CC=gcc 5 | AR=ar 6 | LD=ld 7 | CFLAGS=-c -fno-builtin -nostdlib -fno-stack-protector 8 | LDFLAGS=-static -e tiny_crt_entry 9 | SOURCES=entry.c malloc.c stdio.c string.c printf.c test.c 10 | #special macro replace all the suffix(.c) in SOURCES with .o 11 | OBJECTS=$(SOURCES:.c=.o) 12 | AROBJS=malloc.o printf.o stdio.o string.o 13 | LIBNAME=tinycrt.a 14 | test: archive 15 | $(LD) $(LDFLAGS) entry.o test.o $(LIBNAME) -o $@ 16 | archive: $(SOURCES) $(OBJECTS) 17 | $(AR) -rs $(LIBNAME) $(AROBJS) 18 | #suffix rule in form of (.FROM.TO) 19 | .c.o: 20 | $(CC) $(CFLAGS) $< -o $@ 21 | 22 | clean: 23 | rm -rf *.o $(LIBNAME) test 24 | -------------------------------------------------------------------------------- /src/entry.c: -------------------------------------------------------------------------------- 1 | /* 2 | * ===================================================================================== 3 | * 4 | * Filename: entry.c 5 | * 6 | * Description: this is entry function of tiny CRT 7 | * 8 | * Version: 1.0 9 | * Created: 01/16/2012 12:46:37 AM 10 | * Revision: none 11 | * Compiler: gcc 12 | * 13 | * Author: Larry He 14 | * Company: 15 | * 16 | * ===================================================================================== 17 | */ 18 | #include "tinycrt.h" 19 | 20 | #ifdef WIN32 21 | #include 22 | #endif 23 | 24 | extern int main(int argc, char* argv[]); 25 | void exit(int); 26 | 27 | static void crt_fatal_error(const char* msg) 28 | { 29 | printf("fatal error: %s",msg); 30 | exit(1); 31 | } 32 | 33 | void tiny_crt_entry(void) 34 | { 35 | int ret; 36 | 37 | #ifdef WIN32 38 | int flag = 0; 39 | int argc = 0; 40 | char* argv[16];//max 16 arguments contrains 41 | char* cl = GetCommandLineA(); 42 | //parse commnad line 43 | argv[0] = cl; 44 | argc++; 45 | while(*cl){ 46 | if(*cl == '\"') 47 | if(flag == 0) flag = 1; 48 | else flag = 0; 49 | else if(*cl == ' ' && flag == 0) { 50 | if(*(cl+1)) { 51 | argv[argc] = cl + 1; 52 | argc++; 53 | } 54 | *cl = '\0'; 55 | } 56 | cl++; 57 | } 58 | #else 59 | int argc; 60 | char ** argv; 61 | 62 | char* ebp_reg = 0; 63 | //ebp_reg = %ebp 64 | asm("movl %%ebp,%0 \n":"=r"(ebp_reg)); 65 | 66 | argc = *(int*)(ebp_reg + 4); 67 | argv = (char**)(ebp_reg + 8); 68 | #endif 69 | if(!tiny_crt_heap_init()) 70 | crt_fatal_error("heap initialize failed"); 71 | 72 | if(!tiny_crt_io_init()) 73 | crt_fatal_error("IO initialize failed"); 74 | 75 | ret = main(argc, argv); 76 | exit(ret); 77 | } 78 | 79 | void exit(int exitCode) 80 | { 81 | #ifdef WIN32 82 | ExitProcess(exitCode); 83 | #else 84 | asm( "movl %0,%%ebx \n\t" 85 | "movl $1,%%eax \n\t" 86 | "int $0x80 \n\t" 87 | "hlt \n\t"::"m"(exitCode)); 88 | #endif 89 | } 90 | -------------------------------------------------------------------------------- /src/malloc.c: -------------------------------------------------------------------------------- 1 | /* 2 | * ===================================================================================== 3 | * 4 | * Filename: malloc.c 5 | * 6 | * Description: heap management malloc and free implementation 7 | * Version: 1.0 8 | * Created: 01/16/2012 01:24:37 AM 9 | * Revision: none 10 | * Compiler: gcc 11 | * 12 | * Author: YOUR NAME (), 13 | * Company: 14 | * 15 | * ===================================================================================== 16 | */ 17 | #include "tinycrt.h" 18 | 19 | typedef struct _heap_header 20 | { 21 | enum { 22 | HEAP_BLOCK_FREE = 0xABABABAB,//magic number of free block 23 | HEAP_BLOCK_USED = 0xCDCDCDCD,//magic number of used block 24 | }type;//block type (free/used) 25 | 26 | unsigned size;//block size including header 27 | struct _heap_header* next; 28 | struct _heap_header* prev; 29 | } heap_header; 30 | 31 | #define ADDR_ADD(a,o) (((char*)(a)) + o) 32 | #define HEADER_SIZE (sizeof(heap_header)) 33 | 34 | static heap_header* list_head = NULL; 35 | 36 | void free(void* ptr) 37 | { 38 | heap_header* header = (heap_header*)ADDR_ADD(ptr, -HEADER_SIZE); 39 | if(header->type != HEAP_BLOCK_USED) 40 | return; 41 | 42 | header->type = HEAP_BLOCK_FREE; 43 | //Just merge current block into previous block if it free 44 | if(header->prev != NULL && header->prev->type == HEAP_BLOCK_FREE){ 45 | header->prev->next = header->next; 46 | if(header->next != NULL) 47 | header->next->prev = header->prev; 48 | header->prev->size += header->size; 49 | 50 | header = header->prev; 51 | } 52 | //merge next block into current block if it's free 53 | if(header->next != NULL && header->next->type == HEAP_BLOCK_FREE){ 54 | header->size += header->next->size; 55 | header->next = header->next->next; 56 | } 57 | } 58 | 59 | void* malloc(unsigned size) 60 | { 61 | heap_header *header; 62 | 63 | if(size == 0) 64 | return NULL; 65 | 66 | header = list_head; 67 | while(header != 0){ 68 | if(header->type == HEAP_BLOCK_USED){ 69 | header = header->next; 70 | continue; 71 | } 72 | 73 | if(header->size > size + HEADER_SIZE && header->size <= size + HEADER_SIZE * 2){ 74 | header->type = HEAP_BLOCK_USED; 75 | } 76 | if(header->size > size + HEADER_SIZE * 2){ 77 | //split the block 78 | heap_header* next = (heap_header*)ADDR_ADD(header,size + HEADER_SIZE); 79 | next->prev = header; 80 | next->next = header->next; 81 | next->type = HEAP_BLOCK_FREE; 82 | next->size = header->size - (size - HEADER_SIZE); 83 | header->next = next; 84 | header->size = size + HEADER_SIZE; 85 | header->type = HEAP_BLOCK_USED; 86 | return ADDR_ADD(header,HEADER_SIZE); 87 | } 88 | header = header->next; 89 | } 90 | return NULL; 91 | } 92 | 93 | #ifndef WIN32 94 | //linux brk system call 95 | static int brk(void* end_data_segment){ 96 | int ret = 0; 97 | //brk system call number: 45 98 | asm( "movl $45, %%eax \n\t" 99 | "movl %1, %%ebx \n\t" 100 | "int $0x80 \n\t" 101 | "movl %%eax, %0 \n\t" 102 | : "=r"(ret): "m"(end_data_segment) ); 103 | } 104 | #endif 105 | #ifdef WIN32 106 | #include 107 | #endif 108 | 109 | int tiny_crt_heap_init() 110 | { 111 | void* base = NULL; 112 | heap_header* header = NULL; 113 | unsigned heap_size = 1024 * 1024 * 32;//init 32M heap 114 | #ifdef WIN32 115 | base = VirtualAlloc(0,heap_size,MEM_COMMIT | MEM_RESERVE,PAGE_READWRITE); 116 | if(base == NULL) 117 | return 0; 118 | #else 119 | base = (void*)brk(0); 120 | void* end = ADDR_ADD(base, heap_size); 121 | end = (void*)brk(end); 122 | if(!end) 123 | return 0; 124 | #endif 125 | header = (heap_header*)base; 126 | 127 | header->size = heap_size; 128 | header->type = HEAP_BLOCK_FREE; 129 | header->next = NULL; 130 | header->prev = NULL; 131 | 132 | list_head = header; 133 | return 1; 134 | } 135 | -------------------------------------------------------------------------------- /src/printf.c: -------------------------------------------------------------------------------- 1 | /* 2 | * ===================================================================================== 3 | * 4 | * Filename: printf.c 5 | * 6 | * Description: parameterized function implemntation in C 7 | * 8 | * Version: 1.0 9 | * Created: 01/16/2012 10:46:41 PM 10 | * Revision: none 11 | * Compiler: gcc 12 | * 13 | * Author: YOUR NAME (), 14 | * Company: 15 | * 16 | * ===================================================================================== 17 | */ 18 | #include "tinycrt.h" 19 | 20 | int fputc(int c, FILE* stream) 21 | { 22 | if(fwrite(&c, 1, 1, stream) != 1) 23 | return EOF; 24 | else 25 | return c; 26 | } 27 | 28 | int fputs(const char* str, FILE* stream) 29 | { 30 | int len = strlen(str); 31 | if(fwrite(str, 1, len, stream) != len) 32 | return EOF; 33 | else 34 | return len; 35 | } 36 | 37 | #ifndef WIN32 38 | #define va_list char* 39 | #define va_start(ap,arg) (ap=(va_list)&arg+sizeof(arg)) 40 | #define va_arg(ap,t) (*(t*)((ap+=sizeof(t))-sizeof(t))) 41 | #define va_end(ap) (ap=(va_list)0) 42 | #else 43 | #include 44 | #endif 45 | 46 | int vfprintf(FILE* stream, const char* format, va_list arglist) 47 | { 48 | int translating = 0; 49 | int ret = 0; 50 | const char* p = 0; 51 | for(p=format; *p != '\0'; ++p) 52 | { 53 | switch(*p) 54 | { 55 | case '%': 56 | if(!translating) 57 | translating = 1; 58 | else 59 | { 60 | if(fputc('%', stream) < 0) 61 | return EOF; 62 | ++ret; 63 | translating = 0; 64 | } 65 | break; 66 | case 'd': 67 | if(translating) 68 | { 69 | char buf[16]; 70 | translating = 0; 71 | itoa(va_arg(arglist, int),buf, 10); 72 | if(fputs(buf,stream) < 0) 73 | return EOF; 74 | ret += strlen(buf); 75 | }else if(fputc('d',stream) < 0) 76 | return EOF; 77 | else 78 | ++ret; 79 | break; 80 | case 's': 81 | if(translating) 82 | { 83 | const char* str = va_arg(arglist, const char*); 84 | translating = 0; 85 | if(fputs(str,stream) < 0) 86 | return EOF; 87 | ret += strlen(str); 88 | } 89 | else if(fputc('s',stream) < 0) 90 | return EOF; 91 | else 92 | ++ret; 93 | break; 94 | default: 95 | if(translating) 96 | translating = 0; 97 | if(fputc(*p, stream) < 0) 98 | return EOF; 99 | else 100 | ++ret; 101 | break; 102 | } 103 | } 104 | return ret; 105 | } 106 | 107 | int printf(const char* format, ...) 108 | { 109 | va_list(arglist); 110 | va_start(arglist,format); 111 | return vfprintf(stdout, format, arglist); 112 | } 113 | 114 | int fprintf(FILE* stream, const char* format, ...) 115 | { 116 | va_list(arglist); 117 | va_start(arglist, format); 118 | return vfprintf(stream, format, arglist); 119 | } 120 | -------------------------------------------------------------------------------- /src/stdio.c: -------------------------------------------------------------------------------- 1 | #include "tinycrt.h" 2 | 3 | int tiny_crt_io_init() 4 | { 5 | return 1; 6 | } 7 | 8 | #ifdef WIN32 9 | #include 10 | 11 | FILE* fopen(const char* filename, const char* mode) 12 | { 13 | HANDLE hFile = 0; 14 | int access = 0; 15 | int creation = 0; 16 | 17 | if(strcmp(mode, "w") == 0){ 18 | access |= GENERIC_WRITE; 19 | creation |= CREATE_ALWAYS; 20 | } 21 | 22 | if(strcmp(mode, "w+") == 0){ 23 | access |= GENERIC_WRITE | GENERIC_READ; 24 | creation |= CREATE_ALWAYS; 25 | } 26 | 27 | if(strcmp(mode, "r") == 0){ 28 | access |= GENERIC_READ; 29 | creation |= OPEN_EXISTING; 30 | } 31 | 32 | If(strcmp(mode, "r+") == 0){ 33 | access |= GENERIC_WRITE | GENERIC_READ; 34 | creation |= TRUNCATE_EXISTING; 35 | } 36 | 37 | hFile = CreateFileA(filename, access, 0, 0 , creation, 0, 0); 38 | if(hFile == INVALID_HANDLE_VALUE) 39 | return 0; 40 | 41 | return (FILE*) hFile; 42 | } 43 | 44 | int fread(void* buffer, int size, int count, FILE* stream) 45 | { 46 | int read = 0; 47 | if(!ReadFile((HANDLE)stream, buffer, size*count, &read, 0)) 48 | return 0; 49 | return read; 50 | } 51 | 52 | int fwrite(const void* buffer, int size, int count, FILE* stream) 53 | { 54 | int written = 0; 55 | if(!WriteFile((HANDLE)stream, buffer, size*count, &written, 0)) 56 | return 0; 57 | return written; 58 | } 59 | 60 | int fclose(FILE* fp) 61 | { 62 | return CloseHandle((HANDLE)fp); 63 | } 64 | 65 | int fseek(FILE* fp, int offset, int set) 66 | { 67 | return SetFilePointer((HANDLE)fp, offset, 0, set); 68 | } 69 | 70 | #else 71 | 72 | static int open(const char* pathname, int flags, int mode) 73 | { 74 | int fd = 0; 75 | //system call number 5 for open 76 | asm ("movl $5,%%eax \n\t" 77 | "movl %1, %%ebx \n\t" 78 | "movl %2, %%ecx \n\t" 79 | "movl %3, %%edx \n\t" 80 | "int $0x80 \n\t" 81 | "movl %%eax,%0 \n\t" 82 | :"=m"(fd):"m"(pathname),"m"(flags),"m"(mode)); 83 | } 84 | 85 | static int read(int fd, void* buffer, unsigned size) 86 | { 87 | int ret = 0; 88 | asm("movl $3,%%eax \n\t" 89 | "movl %1,%%ebx \n\t" 90 | "movl %2,%%ecx \n\t" 91 | "movl %3,%%edx \n\t" 92 | "int $0x80 \n\t" 93 | "movl %%eax,%0 \n\t": 94 | "=m"(ret):"m"(fd),"m"(buffer),"m"(size)); 95 | return ret; 96 | } 97 | 98 | static int write(int fd, const void* buffer, unsigned size) 99 | { 100 | int ret = 0; 101 | asm("movl $4,%%eax \n\t" 102 | "movl %1,%%ebx \n\t" 103 | "movl %2,%%ecx \n\t" 104 | "movl %3,%%edx \n\t" 105 | "int $0x80 \n\t" 106 | "movl %%eax,%0 \n\t": 107 | "=m"(ret):"m"(fd),"m"(buffer),"m"(size)); 108 | return ret; 109 | } 110 | 111 | static int close(int fd) 112 | { 113 | int ret = 0; 114 | asm("movl $6,%%eax \n\t" 115 | "movl %1,%%ebx \n\t" 116 | "int $0x80 \n\t" 117 | "movl %%eax,%0 \n\t": 118 | "=m"(ret):"m"(fd)); 119 | return ret; 120 | } 121 | 122 | static int seek(int fd, int offset, int mode) 123 | { 124 | int ret = 0; 125 | asm("movl $19,%%eax \n\t" 126 | "movl %1,%%ebx \n\t" 127 | "movl %2,%%ecx \n\t" 128 | "movl %3,%%edx \n\t" 129 | "int $0x80 \n\t" 130 | "movl %%eax,%0 \n\t": 131 | "=m"(ret):"m"(fd),"m"(offset),"m"(mode)); 132 | return ret; 133 | } 134 | 135 | FILE* fopen(const char* filename, const char* mode) 136 | { 137 | int fd = -1; 138 | int flags = 0; 139 | int access = 00700; 140 | //from /usr/include/bits/fcntl.h 141 | #define O_RDONLY 00 142 | #define O_WRONLY 01 143 | #define O_RDWR 02 144 | #define O_CREATE 0100 145 | #define O_TRUNC 01000 146 | #define O_APPEND 02000 147 | if(strcmp(mode,"w") ==0) 148 | flags |= O_WRONLY | O_CREATE | O_TRUNC; 149 | 150 | if(strcmp(mode,"w+") ==0) 151 | flags |= O_RDWR | O_CREATE | O_TRUNC; 152 | 153 | if(strcmp(mode,"r") ==0) 154 | flags |= O_RDONLY; 155 | 156 | if(strcmp(mode,"r+") == 0) 157 | flags |= O_RDWR | O_CREATE; 158 | 159 | fd = open(filename, flags, access); 160 | return (FILE*)fd; 161 | } 162 | 163 | int fread(void* buffer, int size, int count, FILE* stream) 164 | { 165 | return read((int)stream, buffer, size*count); 166 | } 167 | 168 | int fwrite(const void* buffer, int size, int count, FILE* stream) 169 | { 170 | return write((int)stream,buffer, size*count); 171 | } 172 | 173 | int fclose(FILE* fp) 174 | { 175 | return close((int)fp); 176 | } 177 | 178 | int fseek(FILE* fp, int offset, int set) 179 | { 180 | return seek((int)fp, offset,set); 181 | } 182 | 183 | #endif 184 | -------------------------------------------------------------------------------- /src/string.c: -------------------------------------------------------------------------------- 1 | /* 2 | * ===================================================================================== 3 | * 4 | * Filename: string.c 5 | * 6 | * Description: string manipulation functions including strlen, strcmp and string conversion 7 | * 8 | * Version: 1.0 9 | * Created: 01/16/2012 10:30:26 PM 10 | * Revision: none 11 | * Compiler: gcc 12 | * 13 | * Author: YOUR NAME (), 14 | * Company: 15 | * 16 | * ===================================================================================== 17 | */ 18 | char* itoa(int n, char* str, int radix) 19 | { 20 | char digit[] = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"; 21 | char* p = str; 22 | char* head = str; 23 | if(!p || radix < 2 || radix > 36) 24 | return p; 25 | if(radix != 10 && n < 0) 26 | return p; 27 | 28 | if(n == 0) 29 | { 30 | *p++ = '0'; 31 | *p = 0; 32 | return p; 33 | } 34 | if(radix == 10 && n < 0) 35 | { 36 | *p++ = '-'; 37 | n = -n; 38 | } 39 | while(n) 40 | { 41 | *p++ = digit[n%radix]; 42 | n /= radix; 43 | } 44 | *p = 0; 45 | for(--p; head < p; ++head, --p) 46 | { 47 | char temp = *head; 48 | *head = *p; 49 | *p = temp; 50 | } 51 | return str; 52 | } 53 | 54 | int strcmp(const char* src, const char* dst) 55 | { 56 | int ret = 0; 57 | unsigned char* p1 = (unsigned char*)src; 58 | unsigned char* p2 = (unsigned char*)dst; 59 | while(!(ret = *p1 - *p2) && *p2) 60 | ++p1,++p2; 61 | if(ret < 0) 62 | ret = -1; 63 | else if(ret > 0) 64 | ret = 1; 65 | return ret; 66 | } 67 | 68 | char* strcpy(char* dest, const char* src) 69 | { 70 | char* ret = dest; 71 | while(*src) 72 | *dest++ = *src++; 73 | *dest = '\0'; 74 | return ret; 75 | } 76 | 77 | unsigned strlen(const char* str) 78 | { 79 | int cnt = 0; 80 | if(!str) 81 | return 0; 82 | for(; *str != '\0'; ++str) 83 | ++cnt; 84 | return cnt; 85 | } 86 | -------------------------------------------------------------------------------- /src/test.c: -------------------------------------------------------------------------------- 1 | /* 2 | * ===================================================================================== 3 | * 4 | * Filename: test.c 5 | * 6 | * Description: test our tiny CRT library 7 | * 8 | * Version: 1.0 9 | * Created: 01/17/2012 02:54:44 AM 10 | * Revision: none 11 | * Compiler: gcc 12 | * 13 | * Author: YOUR NAME (), 14 | * Company: 15 | * 16 | * ===================================================================================== 17 | */ 18 | #include "tinycrt.h" 19 | 20 | int main(int argc, char* argv[]) 21 | { 22 | int i; 23 | FILE* fp; 24 | char** v = malloc(argc * sizeof(char*)); 25 | for(i = 0; i < argc; ++i){ 26 | v[i] = malloc(strlen(argv[i]) + 1); 27 | strcpy(v[i], argv[i]); 28 | } 29 | 30 | fp = fopen("test.txt", "w"); 31 | for(i = 0; i < argc; ++i){ 32 | int len = strlen(v[i]); 33 | fwrite(&len, 1, sizeof(int), fp); 34 | fwrite(v[i], 1, len, fp); 35 | } 36 | fclose(fp); 37 | 38 | fp = fopen("test.txt", "r"); 39 | for(i=0; i < argc; ++i){ 40 | int len; 41 | char* buf; 42 | fread(&len, 1, sizeof(int), fp); 43 | buf = malloc(len + 1); 44 | fread(buf, 1, len, fp); 45 | buf[len] = '\0'; 46 | printf("%d %s\n", len, buf); 47 | free(buf); 48 | free(v[i]); 49 | } 50 | fclose(fp); 51 | printf("size of int=%d and size of char*=%d size of unsigned=%d size of double=%d size of char=%d\n", sizeof(int), sizeof(char*), sizeof(unsigned), sizeof(double), sizeof(char)); 52 | int a[] = {2, 3}; 53 | char* str[] = {"string1 helloworld long text","string2"}; 54 | char as[] = {'a','b'}; 55 | for (i = 0; i < 2; i++) { 56 | printf("address of int=%d and addr of string=%d and char=%d\n",(a+i),(str+i),(as+i)); 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /src/tinycrt.h: -------------------------------------------------------------------------------- 1 | /* 2 | * ===================================================================================== 3 | * 4 | * Filename: tinycrt.h 5 | * 6 | * Description: header file of tiny CRT library 7 | * 8 | * Version: 1.0 9 | * Created: 01/16/2012 11:25:53 PM 10 | * Revision: none 11 | * Compiler: gcc 12 | * 13 | * Author: YOUR NAME (), 14 | * Company: 15 | * 16 | * ===================================================================================== 17 | */ 18 | #ifndef __TINY_CRT_H__ 19 | #define __TINY_CRT_H__ 20 | 21 | #ifdef __cplusplus 22 | extern "C" { 23 | #endif 24 | 25 | //malloc 26 | #ifndef NULL 27 | #define NULL (0) 28 | #endif 29 | 30 | void free(void* ptr); 31 | void* malloc(unsigned size); 32 | static int brk(void* end_data_segment); 33 | int tiny_crt_init_heap(); 34 | 35 | //string utility function 36 | char* itoa(int n, char* str, int radix); 37 | int strcmp(const char* src, const char* dst); 38 | int strcpy(char* dest, const char* src); 39 | unsigned strlen(const char* str); 40 | 41 | //file and IO 42 | typedef int FILE; 43 | #define EOF (-1) 44 | 45 | #ifdef WIN32 46 | #define stdin ((FILE*)(GetStdHandle(STD_INPUT_HANDLE))) 47 | #define stdout ((FILE*)(GetStdHandle(STD_OUTPUT_HANDLE))) 48 | #define stderr ((FILE*)(GetStdHandle(STD_ERROR_HANDLE))) 49 | #else 50 | #define stdin ((FILE*)0) 51 | #define stdout ((FILE*)1) 52 | #define stderr ((FILE*)2) 53 | #endif 54 | 55 | int tiny_crt_init_io(); 56 | FILE* fopen(const char* filename, const char* mode); 57 | int fread(void* buffer, int size, int count, FILE* stream); 58 | int fwrite(const void* buffer, int size, int count, FILE* stream); 59 | int fclose(FILE* fp); 60 | int fseek(FILE* fp, int offset, int set); 61 | 62 | //printf 63 | int fputc(int c, FILE* stream); 64 | int fputs(const char* str, FILE* stream); 65 | int printf(const char* format, ...); 66 | int fprintf(FILE* stream, const char* format, ...); 67 | 68 | //internal 69 | void do_global_ctors(); 70 | void tiny_crt_call_exit_routine(); 71 | 72 | //atexit 73 | typedef void (*atexit_func_t)(void); 74 | int atexit(atexit_func_t); 75 | 76 | #ifdef __cplusplus 77 | } 78 | #endif 79 | 80 | #endif //__TINY_CRT_H 81 | --------------------------------------------------------------------------------