diff --git a/programs/develop/ktcc/trunk/libc/include/kolibrisys.h b/programs/develop/ktcc/trunk/libc/include/kolibrisys.h index aed4aed79b..66b3a26a0a 100644 --- a/programs/develop/ktcc/trunk/libc/include/kolibrisys.h +++ b/programs/develop/ktcc/trunk/libc/include/kolibrisys.h @@ -49,7 +49,7 @@ typedef struct process_table_entry{ //------------------------KolibriOS system acces to files---------------------------- //----------------------------------------------------------------------------------- extern dword stdcall _ksys_get_filesize(char *filename); -extern dword stdcall _ksys_readfile(char *filename,dword pos,dword blocksize,void *data); +extern dword stdcall _ksys_readfile(char *filename,dword pos,dword blocksize,void *data, int *preadbytes); extern dword stdcall _ksys_rewritefile(char *filename,dword blocksize,void *data); extern dword stdcall _ksys_appendtofile(char *filename,dword pos,dword blocksize,void *data); //----------------------------------------------------------------------------------- diff --git a/programs/develop/ktcc/trunk/libc/include/kos32sys0.h b/programs/develop/ktcc/trunk/libc/include/kos32sys0.h new file mode 100644 index 0000000000..55c3f9d5a4 --- /dev/null +++ b/programs/develop/ktcc/trunk/libc/include/kos32sys0.h @@ -0,0 +1,800 @@ +#ifndef __KOS_32_SYS_H__ +#define __KOS_32_SYS_H__ + +// file header taken from newlib +// added many sys functions, compatible with tcc + +//#include +//#include +#include +#include +typedef unsigned int uint32_t; +typedef int int32_t; +typedef unsigned char uint8_t; +typedef unsigned short int uint16_t; +typedef unsigned long long uint64_t; + +#ifdef __cplusplus +extern "C" { +#endif + +//#ifdef CONFIG_DEBUF +// #define DBG(format,...) printf(format,##__VA_ARGS__) +//#else +// #define DBG(format,...) +//#endif + +#define TYPE_3_BORDER_WIDTH 5 +#define WIN_STATE_MINIMIZED 0x02 +#define WIN_STATE_ROLLED 0x04 +#define POS_SCREEN 0 +#define POS_WINDOW 1 + +#define IPC_NOBUFFER 1 +#define IPC_LOCKED 2 +#define IPC_OVERFLOW 3 +#define IPC_NOPID 4 + +#define SHM_OPEN 0x00 +#define SHM_OPEN_ALWAYS 0x04 +#define SHM_CREATE 0x08 +#define SHM_READ 0x00 +#define SHM_WRITE 0x01 + + + +typedef unsigned int color_t; + + +typedef union __attribute__((packed)) pos_t +{ + uint32_t val; + struct + { + short x; + short y; + }; +} pos_t; + + +typedef union __attribute__((packed)) oskey_t +{ + uint32_t val; + struct + { + uint8_t state; + uint8_t code; + uint16_t ctrl_key; + }; +} oskey_t; + +typedef struct +{ + unsigned handle; + unsigned io_code; + void *input; + int inp_size; + void *output; + int out_size; +}ioctl_t; + +typedef union +{ + struct + { + void *data; + size_t size; + } x; + unsigned long long raw; +}ufile_t; + +struct kolibri_system_colors { + color_t frame_area; + color_t grab_bar; + color_t grab_bar_button; + color_t grab_button_text; + color_t grab_text; + color_t work_area; + color_t work_button; + color_t work_button_text; + color_t work_text; + color_t work_graph; +}; + + +struct blit_call +{ + int dstx; + int dsty; + int w; + int h; + + int srcx; + int srcy; + int srcw; + int srch; + + void *bitmap; + int stride; +}; + +struct ipc_message +{ + uint32_t pid; // PID of sending thread + uint32_t datalen; // data bytes + char data[0]; // data begin +}; + +struct ipc_buffer +{ + uint32_t lock; // nonzero is locked + uint32_t used; // used bytes in buffer + struct ipc_message data[0]; // data begin +}; + +static inline void begin_draw(void) +{ + __asm__ __volatile__( + "int $0x40" ::"a"(12),"b"(1)); +}; + +static inline +void end_draw(void) +{ + __asm__ __volatile__( + "int $0x40" ::"a"(12),"b"(2)); +}; + +static inline +void sys_create_window(int x, int y, int w, int h, const char *name, + color_t workcolor, uint32_t style) +{ + __asm__ __volatile__( + "int $0x40" + ::"a"(0), + "b"((x << 16) | ((w-1) & 0xFFFF)), + "c"((y << 16) | ((h-1) & 0xFFFF)), + "d"((style << 24) | (workcolor & 0xFFFFFF)), + "D"(name), + "S"(0) : "memory"); +}; + +static inline +void define_button(uint32_t x_w, uint32_t y_h, uint32_t id, uint32_t color) +{ + __asm__ __volatile__( + "int $0x40" + ::"a"(8), + "b"(x_w), + "c"(y_h), + "d"(id), + "S"(color)); +}; + +static inline +void draw_line(int xs, int ys, int xe, int ye, color_t color) +{ + __asm__ __volatile__( + "int $0x40" + ::"a"(38), "d"(color), + "b"((xs << 16) | xe), + "c"((ys << 16) | ye)); +} + +static inline +void draw_bar(int x, int y, int w, int h, color_t color) +{ + __asm__ __volatile__( + "int $0x40" + ::"a"(13), "d"(color), + "b"((x << 16) | w), + "c"((y << 16) | h)); +} + +static inline +void draw_bitmap(void *bitmap, int x, int y, int w, int h) +{ + __asm__ __volatile__( + "int $0x40" + ::"a"(7), "b"(bitmap), + "c"((w << 16) | h), + "d"((x << 16) | y)); +} + +static inline +void draw_text_sys(const char *text, int x, int y, int len, color_t color) +{ + __asm__ __volatile__( + "int $0x40" + ::"a"(4),"d"(text), + "b"((x << 16) | y), + "S"(len),"c"(color) + :"memory"); +} + +static inline +uint32_t get_skin_height(void) +{ + uint32_t height; + + __asm__ __volatile__( + "int $0x40 \n\t" + :"=a"(height) + :"a"(48),"b"(4)); + return height; +}; + +static inline +pos_t get_mouse_pos(int origin) +{ + pos_t val; + + __asm__ __volatile__( + "int $0x40 \n\t" + "rol $16, %%eax" + :"=a"(val) + :"a"(37),"b"(origin)); + return val; +} + +static inline +uint32_t get_mouse_buttons(void) +{ + uint32_t val; + + __asm__ __volatile__( + "int $0x40" + :"=a"(val) + :"a"(37),"b"(2)); + return val; +}; + +static inline +uint32_t get_mouse_wheels(void) +{ + uint32_t val; + + __asm__ __volatile__( + "int $0x40 \n\t" + :"=a"(val) + :"a"(37),"b"(7)); + return val; +}; + +static inline uint32_t load_cursor(void *path, uint32_t flags) +{ + uint32_t val; + __asm__ __volatile__( + "int $0x40" + :"=a"(val) + :"a"(37), "b"(4), "c"(path), "d"(flags)); + return val; +} + +static inline uint32_t set_cursor(uint32_t cursor) +{ + uint32_t old; + __asm__ __volatile__( + "int $0x40" + :"=a"(old) + :"a"(37), "b"(5), "c"(cursor)); + return old; +}; + +static inline int destroy_cursor(uint32_t cursor) +{ + int ret; + __asm__ __volatile__( + "int $0x40" + :"=a"(ret) + :"a"(37), "b"(6), "c"(cursor) + :"memory"); + return ret; +}; + + +static inline +uint32_t wait_for_event(uint32_t time) +{ + uint32_t val; + __asm__ __volatile__( + "int $0x40" + :"=a"(val) + :"a"(23), "b"(time)); + return val; +}; + +static inline uint32_t check_os_event() +{ + uint32_t val; + __asm__ __volatile__( + "int $0x40" + :"=a"(val) + :"a"(11)); + return val; +}; + +static inline uint32_t get_os_event() +{ + uint32_t val; + __asm__ __volatile__( + "int $0x40" + :"=a"(val) + :"a"(10)); + return val; +}; + +static inline +uint32_t get_tick_count(void) +{ + uint32_t val; + __asm__ __volatile__( + "int $0x40" + :"=a"(val) + :"a"(26),"b"(9)); + return val; +}; + +static inline +uint64_t get_ns_count(void) +{ + uint64_t val; + __asm__ __volatile__( + "int $0x40" + :"=A"(val) + :"a"(26), "b"(10)); + return val; +}; + +static inline +oskey_t get_key(void) +{ + oskey_t val; + __asm__ __volatile__( + "int $0x40" + :"=a"(val) + :"a"(2)); + return val; +} + +static inline +uint32_t get_os_button() +{ + uint32_t val; + __asm__ __volatile__( + "int $0x40" + :"=a"(val) + :"a"(17)); + return val>>8; +}; + +static inline uint32_t get_service(char *name) +{ + uint32_t retval = 0; + __asm__ __volatile__( + "int $0x40" + :"=a"(retval) + :"a"(68),"b"(16),"c"(name) + :"memory"); + + return retval; +}; + +static inline int call_service(ioctl_t *io) +{ + int retval; + + __asm__ __volatile__( + "int $0x40" + :"=a"(retval) + :"a"(68),"b"(17),"c"(io) + :"memory","cc"); + + return retval; +}; + + +static inline void yield(void) +{ + __asm__ __volatile__( + "int $0x40" + ::"a"(68), "b"(1)); +}; + +static inline void delay(uint32_t time) +{ + __asm__ __volatile__( + "int $0x40" + ::"a"(5), "b"(time) + :"memory"); +}; + +static inline +void *user_alloc(size_t size) +{ + void *val; + __asm__ __volatile__( + "int $0x40" + :"=a"(val) + :"a"(68),"b"(12),"c"(size)); + return val; +} + +static inline +int user_free(void *mem) +{ + int val; + __asm__ __volatile__( + "int $0x40" + :"=a"(val) + :"a"(68),"b"(13),"c"(mem)); + return val; +} + +static inline +void* user_realloc(void *mem, size_t size) +{ + void *val; + __asm__ __volatile__( + "int $0x40" + :"=a"(val) + :"a"(68),"b"(20),"c"(size),"d"(mem) + :"memory"); + + return val; +}; + +static inline +int *user_unmap(void *base, size_t offset, size_t size) +{ + int *val; + __asm__ __volatile__( + "int $0x40" + :"=a"(val) + :"a"(68),"b"(26),"c"(base),"d"(offset),"S"(size)); + return val; +}; + +static inline ufile_t load_file(const char *path) +{ + ufile_t uf; + + __asm__ __volatile__ ( + "int $0x40" + :"=A"(uf.raw) + :"a" (68), "b"(27),"c"(path)); + + return uf; +}; + +static inline int GetScreenSize() +{ + int retval; + + __asm__ __volatile__( + "int $0x40" + :"=a"(retval) + :"a"(61), "b"(1)); + return retval; +} + + +static inline void get_proc_info(char *info) +{ + __asm__ __volatile__( + "int $0x40" + : + :"a"(9), "b"(info), "c"(-1) + :"memory"); +}; + +static inline void Blit(void *bitmap, int dst_x, int dst_y, + int src_x, int src_y, int w, int h, + int src_w, int src_h, int stride) +{ + volatile struct blit_call bc; + + bc.dstx = dst_x; + bc.dsty = dst_y; + bc.w = w; + bc.h = h; + bc.srcx = src_x; + bc.srcy = src_y; + bc.srcw = src_w; + bc.srch = src_h; + bc.stride = stride; + bc.bitmap = bitmap; + + __asm__ __volatile__( + "int $0x40" + ::"a"(73),"b"(0),"c"(&bc.dstx)); +}; + + +// newlib exclusive +#ifndef __TINYC__ +int create_thread(int (*proc)(void *param), void *param, int stack_size); + +void* load_library(const char *name); + +void* get_proc_address(void *handle, const char *proc_name); + +void enumerate_libraries(int (*callback)(void *handle, const char* name, + uint32_t base, uint32_t size, void *user_data), + void *user_data); +#endif + +// May be next section need to be added in newlibc + +enum KOLIBRI_GUI_EVENTS { + KOLIBRI_EVENT_NONE = 0, /* Event queue is empty */ + KOLIBRI_EVENT_REDRAW = 1, /* Window and window elements should be redrawn */ + KOLIBRI_EVENT_KEY = 2, /* A key on the keyboard was pressed */ + KOLIBRI_EVENT_BUTTON = 3, /* A button was clicked with the mouse */ + KOLIBRI_EVENT_DESKTOP = 5, /* Desktop redraw finished */ + KOLIBRI_EVENT_MOUSE = 6, /* Mouse activity (movement, button press) was detected */ + KOLIBRI_EVENT_IPC = 7, /* Interprocess communication notify */ + KOLIBRI_EVENT_NETWORK = 8, /* Network event */ + KOLIBRI_EVENT_DEBUG = 9, /* Debug subsystem event */ + KOLIBRI_EVENT_IRQBEGIN = 16 /* 16..31 IRQ0..IRQ15 interrupt =IRQBEGIN+IRQn */ +}; + + +// copied from /programs/system/shell/system/kolibri.c +// fn's returned -1 as syserror, 1 as error, 0 as OK +static inline +int kol_clip_num() +{ + register uint32_t val; + asm volatile ("int $0x40":"=a"(val):"a"(54), "b"(0)); + return val; +} + +static inline +char* kol_clip_get(int n) +// returned buffer must be freed by user_free() +{ + register char* val; + asm volatile ("int $0x40":"=a"(val):"a"(54), "b"(1), "c"(n)); + return val; +} + +static inline +int kol_clip_set(int n, char buffer[]) +{ + register uint32_t val; + asm volatile ("int $0x40":"=a"(val):"a"(54), "b"(2), "c"(n), "d"(buffer)); + return val; +} + +static inline +int kol_clip_pop() +{ + register uint32_t val; + asm volatile ("int $0x40":"=a"(val):"a"(54), "b"(3)); + return val; +} + +static inline +int kol_clip_unlock() +{ + register uint32_t val; + asm volatile ("int $0x40":"=a"(val):"a"(54), "b"(4)); + return val; +} + +static inline void get_system_colors(struct kolibri_system_colors *color_table) +{ + __asm__ volatile ("int $0x40" + : + :"a"(48),"b"(3),"c"(color_table),"d"(40) + ); + + /* color_table should point to the system color table */ +} + +static inline void debug_board_write_byte(const char ch){ + __asm__ __volatile__( + "int $0x40" + : + :"a"(63), "b"(1), "c"(ch)); +} + + +static inline void draw_number_sys(int32_t number, int x, int y, int len, color_t color){ + register uint32_t fmt; + fmt = len << 16 | 0x80000000; // no leading zeros + width +// fmt = len << 16 | 0x00000000; // leading zeros + width + __asm__ __volatile__( + "int $0x40" + : + :"a"(47), "b"(fmt), "c"(number), "d"((x << 16) | y), "S"(color)); +} + +static inline +uint32_t get_mouse_eventstate(void) +{ + uint32_t val; + + __asm__ __volatile__( + "int $0x40" + :"=a"(val) + :"a"(37),"b"(3)); + return val; +}; + +static inline +uint32_t set_event_mask(uint32_t mask) +{ + register uint32_t val; + asm volatile ("int $0x40":"=a"(val):"a"(40), "b"(mask)); + return val; +} + +typedef void (*thread_proc)(void*); + +static inline +int start_thread(thread_proc proc, char* stack_top) +{ + register int val; + asm volatile ("int $0x40":"=a"(val):"a"(51), "b"(1), "c"(proc), "d"(stack_top)); + return val; +} + +static inline +void kos_exit() +{ + asm volatile ("int $0x40"::"a"(-1)); +} + +static inline void focus_window(int slot){ + asm volatile ("int $0x40"::"a"(18), "b"(3), "c"(slot)); +} + +static inline int get_thread_slot(int tid){ + register int val; + asm volatile ("int $0x40":"=a"(val):"a"(18), "b"(21), "c"(tid)); + return val; +} + +static inline void set_current_folder(char* dir){ + asm volatile ("int $0x40"::"a"(30), "b"(1), "c"(dir)); +} + +static inline int get_current_folder(char* buf, int bufsize){ + register int val; + asm volatile ("int $0x40":"=a"(val):"a"(30), "b"(2), "c"(buf), "d"(bufsize)); + return val; +} + +static inline +void ipc_set_area(void* buf, int bufsize){ + asm volatile ("int $0x40"::"a"(60), "b"(1), "c"(buf), "d"(bufsize)); +} + +static inline +int ipc_send_message(int pid_reciever, void *data, int datalen) { + register int val; + asm volatile ("int $0x40":"=a"(val):"a"(60), "b"(2), "c"(pid_reciever), "d"(data), "S"(datalen)); + return val; +} + +static inline +void* shm_open(char *shm_name, int msize, int flags, int *retsz){ + register int val, cod; + asm volatile ("int $0x40":"=a"(val),"=d"(cod):"a"(68), "b"(22), "c"(shm_name), "d"(msize), "S"(flags)); + + if(retsz) *retsz = cod; // errcode if NULL or memsize when open + return (void*)val; +} + +static inline +void shm_close(char *shm_name){ + asm volatile ("int $0x40"::"a"(68), "b"(23), "c"(shm_name)); +} + +static inline +int start_app(char *app_name, char *args){ + struct file_op_t + { + uint32_t fn; + uint32_t flags; + char* args; + uint32_t res1, res2; + char zero; + char* app_name __attribute__((packed)); + } file_op; + memset(&file_op, 0, sizeof(file_op)); + file_op.fn = 7; + file_op.args = args; + file_op.app_name = app_name; + + register int val; + asm volatile ("int $0x40":"=a"(val):"a"(70), "b"(&file_op)); + + return val; +} + + +/* +static inline char *getcwd(char *buf, size_t size) +{ + int rc = get_current_folder(buf, size); + if (rc > size) + { + errno = ERANGE; + return 0; + } + else + return buf; +} +*/ +// end section + + + +//added nonstatic inline because incomfortabre stepping in in debugger +void __attribute__ ((noinline)) debug_board_write_str(const char* str); +void __attribute__ ((noinline)) debug_board_printf(const char *format,...); + +/* copy body to only one project file +void __attribute__ ((noinline)) debug_board_write_str(const char* str){ + while(*str) + debug_board_write_byte(*str++); +} + +void __attribute__ ((noinline)) debug_board_printf(const char *format,...) +{ + va_list ap; + char log_board[300]; + + va_start (ap, format); + vsnprintf(log_board, sizeof log_board, format, ap); + va_end(ap); + debug_board_write_str(log_board); +} +*/ + + + +// TinyC don't support aliasing of static inline funcs +#ifndef __TINYC__ +static inline void BeginDraw(void) __attribute__ ((alias ("begin_draw"))); +static inline void EndDraw(void) __attribute__ ((alias ("end_draw"))); +static inline void DrawWindow(int x, int y, int w, int h, const char *name, + color_t workcolor, uint32_t style) + __attribute__ ((alias ("sys_create_window"))); +static inline void DefineButton(void) __attribute__ ((alias ("define_button"))); +static inline void DrawLine(int xs, int ys, int xe, int ye, color_t color) + __attribute__ ((alias ("draw_line"))); +static inline void DrawBar(int x, int y, int w, int h, color_t color) + __attribute__ ((alias ("draw_bar"))); +static inline void DrawBitmap(void *bitmap, int x, int y, int w, int h) + __attribute__ ((alias ("draw_bitmap"))); +static inline uint32_t GetSkinHeight(void) __attribute__ ((alias ("get_skin_height"))); +static inline pos_t GetMousePos(int origin) __attribute__ ((alias ("get_mouse_pos"))); +static inline uint32_t GetMouseButtons(void) __attribute__ ((alias ("get_mouse_buttons"))); +static inline uint32_t GetMouseWheels(void) __attribute__ ((alias ("get_mouse_wheels"))); +static inline uint32_t LoadCursor(void *path, uint32_t flags) __attribute__ ((alias ("load_cursor"))); +static inline uint32_t SetCursor(uint32_t cursor) __attribute__ ((alias ("set_cursor"))); +static inline int DestroyCursor(uint32_t cursor) __attribute__ ((alias ("destroy_cursor"))); +static inline uint32_t GetOsEvent(void) __attribute__ ((alias ("get_os_event"))); +static inline void *UserAlloc(size_t size) __attribute__ ((alias ("user_alloc"))); +static inline int UserFree(void *mem) __attribute__ ((alias ("user_free"))); +static inline void* UserRealloc(void *mem, size_t size) __attribute__ ((alias ("user_realloc"))); +static inline int *UserUnmap(void *base, size_t offset, size_t size) __attribute__ ((alias ("user_unmap"))); +static inline ufile_t LoadFile(const char *path) __attribute__ ((alias ("load_file"))); +static inline void GetProcInfo(char *info) __attribute__ ((alias ("get_proc_info"))); +#endif + +#ifdef __cplusplus +} +#endif + + +#endif + + + + + diff --git a/programs/develop/ktcc/trunk/libc/include/stdio.h b/programs/develop/ktcc/trunk/libc/include/stdio.h index 34da010df2..5b1bd9c41b 100644 --- a/programs/develop/ktcc/trunk/libc/include/stdio.h +++ b/programs/develop/ktcc/trunk/libc/include/stdio.h @@ -23,9 +23,12 @@ typedef struct { char* buffer; dword buffersize; dword filesize; // too small - dword filepos; // too small + int filepos; // too small, may be -1 char* filename; int mode; + int ungetc_buf; + dword buffer_start; // 1st byte position + dword buffer_end; // points after last buffered data } FILE; #define stderr ((FILE*)3) /* works only for fprintf!!! */ @@ -37,7 +40,7 @@ typedef struct { #define FILE_OPEN_TEXT 4 #define FILE_OPEN_PLUS 8 #define EOF (-1) -#define BUFSIZ (256) +#define BUFSIZ (4096) #define FILENAME_MAX (0x400) extern FILE* fopen(const char* filename, const char *mode); diff --git a/programs/develop/ktcc/trunk/libc/include/stdlib.h b/programs/develop/ktcc/trunk/libc/include/stdlib.h index 9ff9f7a93e..1d284fe662 100644 --- a/programs/develop/ktcc/trunk/libc/include/stdlib.h +++ b/programs/develop/ktcc/trunk/libc/include/stdlib.h @@ -10,6 +10,10 @@ #define abs(i) (((i)<0)?(-(i)):(i)) #define labs(li) abs(li) +#define min(a, b) ((a)<(b) ? (a) : (b)) +#define max(a, b) ((a)>(b) ? (a) : (b)) + + extern int atoib(char *s,int b); extern int atoi(char *s); extern char *itoab(unsigned int n,char* s,int b); diff --git a/programs/develop/ktcc/trunk/libc/kolibrisys/_ksys_files_acces.asm b/programs/develop/ktcc/trunk/libc/kolibrisys/_ksys_files_acces.asm index dc0a14bbf0..1c7143ba35 100644 --- a/programs/develop/ktcc/trunk/libc/kolibrisys/_ksys_files_acces.asm +++ b/programs/develop/ktcc/trunk/libc/kolibrisys/_ksys_files_acces.asm @@ -39,7 +39,7 @@ endp align 4 -proc _ksys_readfile stdcall,filename:dword,position:dword,sizeblock:dword,buffer:dword +proc _ksys_readfile stdcall,filename:dword,position:dword,sizeblock:dword,buffer:dword, preadbytes:dword xor eax,eax mov ebx,[position] @@ -58,6 +58,9 @@ proc _ksys_readfile stdcall,filename:dword,position:dword,sizeblock:dword,buffer mov ebx,fileinfo int 0x40 + mov esi, [preadbytes] + mov [esi], ebx + ret endp diff --git a/programs/develop/ktcc/trunk/libc/stdio/fgetc.c b/programs/develop/ktcc/trunk/libc/stdio/fgetc.c index 4d50cd7df3..01299755db 100644 --- a/programs/develop/ktcc/trunk/libc/stdio/fgetc.c +++ b/programs/develop/ktcc/trunk/libc/stdio/fgetc.c @@ -1,31 +1,11 @@ #include int fgetc(FILE* file) { - dword res; - if(!file) - { - errno = E_INVALIDPTR; - return EOF; - } + int c = 0, rc; + + rc = fread(&c, 1, 1, file); - if ((file->mode & 3)!=FILE_OPEN_READ && (file->mode & FILE_OPEN_PLUS)==0) return EOF; + if (rc < 1) return EOF; - if (file->filepos>=file->filesize) - { - return EOF; - } - else - { - res=_ksys_readfile(file->filename,file->filepos,1,file->buffer); - if (res==0) - { - file->filepos++; - return (int)file->buffer[0]; - } - else - { - errno = -res; - return EOF; // errors are < 0 - } - } + return c; } diff --git a/programs/develop/ktcc/trunk/libc/stdio/fgetpos.c b/programs/develop/ktcc/trunk/libc/stdio/fgetpos.c index 469fee688d..d71d203230 100644 --- a/programs/develop/ktcc/trunk/libc/stdio/fgetpos.c +++ b/programs/develop/ktcc/trunk/libc/stdio/fgetpos.c @@ -8,5 +8,6 @@ int fgetpos(FILE* file,fpos_t* pos) } *pos=file->filepos; + return 0; } diff --git a/programs/develop/ktcc/trunk/libc/stdio/fopen.c b/programs/develop/ktcc/trunk/libc/stdio/fopen.c index 180abd82b9..840056665b 100644 --- a/programs/develop/ktcc/trunk/libc/stdio/fopen.c +++ b/programs/develop/ktcc/trunk/libc/stdio/fopen.c @@ -113,6 +113,9 @@ FILE* fopen(const char* filename, const char *mode) res->filepos=0; res->mode=imode; res->filename=fullname; + res->ungetc_buf = EOF; + res->buffer_start = -1; + res->buffer_end = -1; } if(!res || !res->buffer || !res->filename) { @@ -120,7 +123,7 @@ FILE* fopen(const char* filename, const char *mode) return NULL; } - if ((imode==FILE_OPEN_READ) || (imode==FILE_OPEN_APPEND)) + if ((imode & 3) == FILE_OPEN_READ || (imode & 3) == FILE_OPEN_APPEND) { if (sz > 0) /*already got*/ res->filesize = sz; diff --git a/programs/develop/ktcc/trunk/libc/stdio/fputc.c b/programs/develop/ktcc/trunk/libc/stdio/fputc.c index d416a1734a..aba6212280 100644 --- a/programs/develop/ktcc/trunk/libc/stdio/fputc.c +++ b/programs/develop/ktcc/trunk/libc/stdio/fputc.c @@ -2,55 +2,9 @@ int fputc(int c,FILE* file) { dword res; - if(!file) - { - errno = E_INVALIDPTR; - return EOF; - } - - if ((file->mode & 3)==FILE_OPEN_READ) - { - errno = E_ACCESS; - return EOF; - } - - file->buffer[0]=c; - if ((file->mode & 3)==FILE_OPEN_APPEND) - { - file->filepos=file->filesize; - file->filesize++; - res=_ksys_appendtofile(file->filename,file->filepos,1,file->buffer); - if (res!=0) - { - errno = -res; - return EOF; - } - file->filepos++; - return c; - } - if ((file->mode & 3)==FILE_OPEN_WRITE) - { - if (file->filepos==0) - { //file not created - res=_ksys_rewritefile(file->filename,1,file->buffer); - if (res!=0) - { - errno = -res; - return EOF; - } - file->filepos++; - return c; - } - else - { //file created and need append one byte - res=_ksys_appendtofile(file->filename,file->filepos,1,file->buffer); - if (res!=0) - { - errno = -res; - return EOF; - } - file->filepos++; - return c; - } - } + + res = fwrite(&c, 1, 1, file); + if (res < 1) return EOF; + + return c; } diff --git a/programs/develop/ktcc/trunk/libc/stdio/fread.c b/programs/develop/ktcc/trunk/libc/stdio/fread.c index ddfdcdad7b..5628ed539d 100644 --- a/programs/develop/ktcc/trunk/libc/stdio/fread.c +++ b/programs/develop/ktcc/trunk/libc/stdio/fread.c @@ -1,10 +1,12 @@ #include +#include +#include #include int fread(void *buffer,int size,int count,FILE* file) { - dword res; - dword fullsize; + dword res, readbytes; + dword fullsize, read4cache, toread, readcount; if(!file || !buffer) { @@ -19,22 +21,74 @@ int fread(void *buffer,int size,int count,FILE* file) } fullsize=count*size; - if ((fullsize+file->filepos)>=(file->filesize)) + if (fullsize + file->filepos >= file->filesize) { - fullsize=file->filesize-file->filepos; - if (fullsize<=0) return(0); + fullsize=file->filesize - file->filepos; + if (fullsize <= 0) return 0; } - res=_ksys_readfile(file->filename,file->filepos,fullsize,buffer); - if (res==0) + /***** file buffering strategy, just read forward ***** + if we read small part - read full buffer, but if buffer have this data - dont read again nothing (or partial read forward 4k pages) + any writes drops buffers as ungetc_buf */ + read4cache = 0; + readcount = 0; + if (file->filepos >= file->buffer_start && file->filepos < file->buffer_end) { - file->filepos=file->filepos+fullsize; - fullsize=fullsize/size; - return(fullsize); + read4cache = min(file->buffer_end - file->filepos, fullsize); + memcpy(buffer, file->buffer + file->filepos - file->buffer_start, read4cache); + file->filepos += read4cache; + if (file->ungetc_buf != EOF) // subst ungetc byte + { + *((char*)buffer) = (char)file->ungetc_buf; + file->ungetc_buf = EOF; + } + buffer += read4cache; // ! advance + fullsize -= read4cache; + readcount = read4cache / size; } + + toread = max(fullsize, file->buffersize); + if (toread + file->filepos >= file->filesize) + { + toread = file->filesize - file->filepos; + } + + if (fullsize <= 0 || toread <= 0) + res = 0; // already read or file end else + { + file->buffer_start = file->filepos; + if (toread <= fullsize) // read to bigger buffer + { + res = _ksys_readfile(file->filename, file->filepos, toread, buffer, &readbytes); + read4cache = min(readbytes, file->buffersize); + memcpy(file->buffer, buffer, read4cache); + file->filepos += readbytes; + } else + { + res = _ksys_readfile(file->filename, file->filepos, toread, file->buffer, &readbytes); + read4cache = readbytes; + memcpy(buffer, file->buffer, min(fullsize, read4cache)); + file->filepos += min(fullsize, read4cache); + } + file->buffer_end = file->buffer_start + read4cache; + if (readbytes >= fullsize) + readcount += fullsize / size; + else + readcount += readbytes / size; + } + + if (file->ungetc_buf != EOF) // subst ungetc byte + { + *((char*)buffer) = (char)file->ungetc_buf; + file->ungetc_buf = EOF; + } + + if (res != 0) { + file->ungetc_buf = EOF; errno = -res; - return 0; } + + return readcount; // really full readed plus cached items } diff --git a/programs/develop/ktcc/trunk/libc/stdio/fsetpos.c b/programs/develop/ktcc/trunk/libc/stdio/fsetpos.c index 10f8fe875c..fcedd73430 100644 --- a/programs/develop/ktcc/trunk/libc/stdio/fsetpos.c +++ b/programs/develop/ktcc/trunk/libc/stdio/fsetpos.c @@ -10,6 +10,7 @@ int fsetpos(FILE* file,const fpos_t * pos) if (*pos>=0) { file->filepos=*pos; + file->ungetc_buf = EOF; return 0; } else diff --git a/programs/develop/ktcc/trunk/libc/stdio/fwrite.c b/programs/develop/ktcc/trunk/libc/stdio/fwrite.c index 7c366a8157..2235ddabeb 100644 --- a/programs/develop/ktcc/trunk/libc/stdio/fwrite.c +++ b/programs/develop/ktcc/trunk/libc/stdio/fwrite.c @@ -41,6 +41,13 @@ int fwrite(void *buffer,int size,int count,FILE* file) } */ + file->ungetc_buf = EOF; + if (file->filepos >= file->buffer_start && file->filepos < file->buffer_end) // drop buffer, if change his data + { + file->buffer_start = -1; + file->buffer_end = -1; + } + if ((file->mode &3)==FILE_OPEN_WRITE || (file->mode&3)==FILE_OPEN_APPEND) // always true, as read checked previous { if (file->filepos==0) diff --git a/programs/develop/ktcc/trunk/libc/stdio/rewind.c b/programs/develop/ktcc/trunk/libc/stdio/rewind.c index e35e8d6d6c..2df1a1e286 100644 --- a/programs/develop/ktcc/trunk/libc/stdio/rewind.c +++ b/programs/develop/ktcc/trunk/libc/stdio/rewind.c @@ -7,5 +7,6 @@ void rewind(FILE* file) return; } + file->ungetc_buf = EOF; file->filepos=0; } diff --git a/programs/develop/ktcc/trunk/libc/stdio/ungetc.c b/programs/develop/ktcc/trunk/libc/stdio/ungetc.c index 4a91d17e9c..2d7c295800 100644 --- a/programs/develop/ktcc/trunk/libc/stdio/ungetc.c +++ b/programs/develop/ktcc/trunk/libc/stdio/ungetc.c @@ -1,5 +1,8 @@ #include -// non standard realization - no support for virtually change char +// non standard realization - support for virtually change ONLY ONE char + + + int ungetc(int c,FILE* file) { dword res; @@ -10,17 +13,19 @@ int ungetc(int c,FILE* file) return EOF; } - if ((file->mode & 3!=FILE_OPEN_READ) && (file->mode & FILE_OPEN_PLUS==0)) + if ((file->mode & 3) != FILE_OPEN_READ && (file->mode & FILE_OPEN_PLUS) == 0) { errno = E_ACCESS; return EOF; } - if (file->filepos>file->filesize || file->filepos==0) + if (file->filepos > file->filesize || file->filepos == 0 || c == EOF || file->ungetc_buf != EOF) { errno = E_EOF; return EOF; } + + file->ungetc_buf = c; file->filepos--; return c; diff --git a/programs/develop/ktcc/trunk/libc/stdlib/exit.c b/programs/develop/ktcc/trunk/libc/stdlib/exit.c new file mode 100644 index 0000000000..15ab8864a6 --- /dev/null +++ b/programs/develop/ktcc/trunk/libc/stdlib/exit.c @@ -0,0 +1,11 @@ +#include +#include +#include + +void exit (int status) +/* close console if was initialized, also stay window [finished] when status is error < 0 */ +{ + if (__console_initdll_status) + con_exit(status > 0); + _ksys_exit(); +} \ No newline at end of file diff --git a/programs/develop/ktcc/trunk/libctest/myfile.txt b/programs/develop/ktcc/trunk/libctest/myfile.txt new file mode 100644 index 0000000000..980fb7b2a5 --- /dev/null +++ b/programs/develop/ktcc/trunk/libctest/myfile.txt @@ -0,0 +1,5 @@ +#test line 1; +-test line 2; +@test line 3; +#testline4. +# \ No newline at end of file diff --git a/programs/develop/ktcc/trunk/libctest/ungetc.c b/programs/develop/ktcc/trunk/libctest/ungetc.c index 901efb6b35..d658c199c7 100644 --- a/programs/develop/ktcc/trunk/libctest/ungetc.c +++ b/programs/develop/ktcc/trunk/libctest/ungetc.c @@ -14,6 +14,60 @@ !strcmp((s),(x)) || \ (t_error("[%s] != [%s] (%s)\n", s, x, m), 0) ) +#include +#include +#include +#include + +#define fgetc fgetc_dbg +#define ungetc ungetc_dbg + + +int fgetc_dbg(FILE* file) +{ + int c = 0, rc; + + rc = fread(&c, 1, 1, file); + + if (rc < 1) return EOF; + + return c; +} + +int ungetc_dbg(int c,FILE* file) +{ + dword res; + + if(!file) + { + errno = E_INVALIDPTR; + return EOF; + } + + if ((file->mode & 3!=FILE_OPEN_READ) && (file->mode & FILE_OPEN_PLUS==0)) + { + errno = E_ACCESS; + return EOF; + } + + if (file->filepos>file->filesize || file->filepos==0 || c == EOF || file->ungetc_buf != EOF) + { + errno = E_EOF; + return EOF; + } + + file->ungetc_buf = c; + file->filepos--; + + return c; +} + +void mark(int n) +{ + n++; +} + + int main(void) { int i; @@ -34,12 +88,15 @@ int main(void) TEST(i, ftell(f), 0, "%d != %d"); TEST(i, fscanf(f, "%[h]", a), 0, "got %d fields, expected %d"); TEST(i, ftell(f), 0, "%d != %d"); - TEST(i, fgetc(f), 'x', "'%c' != '%c'"); +mark(0x11); +printf("debug file ungetbuf=%d\n", f->ungetc_buf); + TEST(i, fgetc(f), 'x', "'%c' != '%c'"); TEST(i, ftell(f), 1, "%d != %d"); TEST(i, fseek(f, 0, SEEK_SET), 0, "%d != %d"); TEST(i, ungetc('x', f), 'x', "%d != %d"); - TEST(i, fread(a, 1, sizeof a, f), 14, "read %d, expected %d"); +mark(0x22); + TEST(i, fread(a, 1, sizeof a, f), 14, "read %d, expected %d"); a[14] = 0; TEST_S(a, "xhello, world\n", "mismatch reading ungot character"); @@ -47,6 +104,8 @@ int main(void) TEST(i, fscanf(f, "%[x]", a), 0, "got %d fields, expected %d"); TEST(i, ungetc('x', f), 'x', "unget failed after fscanf: %d != %d"); TEST(i, fgetc(f), 'x', "'%c' != '%c'"); +mark(0x33); + TEST(i, ftell(f), 1, "%d != %d"); TEST(i, fgetc(f), 'h', "'%c' != '%c'"); printf("%s finished\n", __FILE__); diff --git a/programs/develop/ktcc/trunk/libctest/ungetc2.c b/programs/develop/ktcc/trunk/libctest/ungetc2.c new file mode 100644 index 0000000000..8f4b44df81 --- /dev/null +++ b/programs/develop/ktcc/trunk/libctest/ungetc2.c @@ -0,0 +1,39 @@ +/* ungetc example */ +#include + +void trace_file(FILE* f, char* cmt); + +int main () +{ + FILE * pFile; + int c; + char buffer [256]; + + pFile = fopen ("myfile.txt","rt"); + if (pFile==NULL) perror ("Error opening file"); + else while (!feof (pFile)) { + trace_file(pFile, "1"); + + c=getc (pFile); + + trace_file(pFile, "before ungetc"); + + if (c == EOF) break; + if (c == '#') ungetc ('@',pFile); + else ungetc (c,pFile); + + trace_file(pFile, "after"); + + if (fgets (buffer,255,pFile) != NULL) + puts (buffer); + else break; + } + return 0; +} + +void trace_file(FILE* f, char* cmt) +{ + printf("%s[%s]\n", cmt, f->buffer); + printf("mode=%0X, filesize=%d, filepos=%d\n", f->mode, f->filesize, f->filepos); + printf("ungetc=%d, buffer_start=%d, buffer_end=%d\n", f->ungetc_buf, f->buffer_start, f->buffer_end); +} \ No newline at end of file diff --git a/programs/develop/ktcc/trunk/readme.txt b/programs/develop/ktcc/trunk/readme.txt index d6d120c8ea..50984d5b95 100644 --- a/programs/develop/ktcc/trunk/readme.txt +++ b/programs/develop/ktcc/trunk/readme.txt @@ -16,14 +16,13 @@ read .\source\readme_kos32.txt -add stdin, stderr, stdout emulation не хватает stdin, stdout - можно сделать как stderr!, но надо возиться заодно с ferror & feof -getchar, gets if returs errorcode (0, null) - you must exit program, because of closed console window -при нормальном выходе закрывать консоль --sstrek виснет на поиске хелпа с дискеты - just very long reading by one symbol without buffering (need to change gets, getc, ungetc etc) ------ errors ------ -not working: default search path are ./include ./lib from executable (under KOS need to use -Bpath_to_ktcc) --start.o not found using -B (kos) - put near your.c file -если проект многофайловый - .dbg генерит дублирующиеся метки данных, типа L.78 может указывать на другой сегмент ( - +-.dbg sometimes generated improperly for source code labels ----- fixed errors ------ -if static var sized more than 14096+ -> crash compiled .exe (kos) @@ -120,7 +119,7 @@ snprintf -may incorrect prints unsigned > 2147483647L ungetc --ungetc fails if filepos == 0 - no tricks +-ungetc fails if filepos == 0 - by design all file ops limited to 2Gb