Testing data

This commit is contained in:
4coder 2018-03-16 11:19:11 -07:00
parent 0f0eb2f299
commit 1578631a72
466 changed files with 722445 additions and 0 deletions

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@ -0,0 +1,89 @@
/*
* Mr. 4th Dimention - Allen Webster
*
* 23.02.2016
*
* Types shared by custom and application
*
*/
// TOP
#ifndef FRED_BUFFER_TYPES_H
#define FRED_BUFFER_TYPES_H
typedef struct Full_Cursor{
int pos;
int line, character;
float unwrapped_x, unwrapped_y;
float wrapped_x, wrapped_y;
} Full_Cursor;
typedef enum{
buffer_seek_pos,
buffer_seek_wrapped_xy,
buffer_seek_unwrapped_xy,
buffer_seek_line_char
} Buffer_Seek_Type;
typedef struct Buffer_Seek{
Buffer_Seek_Type type;
union{
struct { int pos; };
struct { int round_down; float x, y; };
struct { int line, character; };
};
} Buffer_Seek;
static Buffer_Seek
seek_pos(int pos){
Buffer_Seek result;
result.type = buffer_seek_pos;
result.pos = pos;
return(result);
}
static Buffer_Seek
seek_wrapped_xy(float x, float y, int round_down){
Buffer_Seek result;
result.type = buffer_seek_wrapped_xy;
result.x = x;
result.y = y;
result.round_down = round_down;
return(result);
}
static Buffer_Seek
seek_unwrapped_xy(float x, float y, int round_down){
Buffer_Seek result;
result.type = buffer_seek_unwrapped_xy;
result.x = x;
result.y = y;
result.round_down = round_down;
return(result);
}
static Buffer_Seek
seek_xy(float x, float y, int round_down, int unwrapped){
Buffer_Seek result;
result.type = unwrapped?buffer_seek_unwrapped_xy:buffer_seek_wrapped_xy;
result.x = x;
result.y = y;
result.round_down = round_down;
return(result);
}
static Buffer_Seek
seek_line_char(int line, int character){
Buffer_Seek result;
result.type = buffer_seek_line_char;
result.line = line;
result.character = character;
return(result);
}
#endif
// BOTTOM

View File

@ -0,0 +1,87 @@
/* "4cpp" Open C++ Parser v0.1: Config
no warranty implied; use at your own risk
NOTES ON USE:
This file is used to configure 4cpp options at the begining of 4cpp files.
It is not meant to be used directly.
*/
#ifdef FCPP_NO_CRT
# ifndef FCPP_NO_MALLOC
# define FCPP_NO_MALLOC
# endif
# ifndef FCPP_NO_ASSERT
# define FCPP_NO_ASSERT
# endif
# ifndef FCPP_NO_STRING
# define FCPP_NO_STRING
# endif
#endif
#ifdef FCPP_FORBID_MALLOC
# define FCPP_NO_MALLOC
#endif
#ifndef FCPP_NO_MALLOC
# include <stdlib.h>
#endif
#ifndef FCPP_NO_ASSERT
# include <assert.h>
#endif
#ifndef FCPP_NO_STRING
# include <string.h>
#endif
#ifndef FCPP_NO_MALLOC
# ifndef FCPP_GET_MEMORY
# define FCPP_GET_MEMORY malloc
# endif
# ifndef FCPP_FREE_MEMORY
# define FCPP_FREE_MEMORY free
# endif
#else
# ifndef FCPP_FORBID_MALLOC
# ifndef FCPP_GET_MEMORY
# error Missing definition for FCPP_GET_MEMORY
# endif
# ifndef FCPP_FREE_MEMORY
# error Missing definition for FCPP_FREE_MEMORY
# endif
# endif
#endif
#ifndef FCPP_NO_ASSERT
# ifndef FCPP_ASSERT
# define FCPP_ASSERT assert
# endif
#else
# ifndef FCPP_ASSERT
# define FCPP_ASSERT(x)
# endif
#endif
#ifndef FCPP_NO_STRING
# ifndef FCPP_MEM_COPY
# define FCPP_MEM_COPY memcpy
# endif
# ifndef FCPP_MEM_MOVE
# define FCPP_MEM_MOVE memmove
# endif
#endif
#ifndef FCPP_LINK
# ifdef FCPP_EXTERN
# define FCPP_LINK extern
# else
# define FCPP_LINK static
# endif
#endif
#ifndef DrBegin
#define DrBegin() switch (s.__pc__){ case 0:;
#define DrEnd() default: Assert(!"Invalid __pc__"); }
#define DrYield(pc, n) { s.__pc__ = pc; *state = s; return(n); case pc:; }
#define DrReturn(n) { s.__pc__ = -1; return(n); }
#endif

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,587 @@
#include "4coder_version.h"
#include "4coder_keycodes.h"
#include "4coder_style.h"
#include "4coder_buffer_types.h"
#ifndef FRED_STRING_STRUCT
#define FRED_STRING_STRUCT
typedef struct String{
char *str;
int size;
int memory_size;
} String;
typedef struct Offset_String{
int offset;
int size;
} Offset_String;
#endif
typedef unsigned char Code;
typedef enum{
MDFR_SHIFT_INDEX,
MDFR_CONTROL_INDEX,
MDFR_ALT_INDEX,
MDFR_CAPS_INDEX,
// always last
MDFR_INDEX_COUNT
} Key_Control;
typedef struct Key_Event_Data{
Code keycode;
Code character;
Code character_no_caps_lock;
char modifiers[MDFR_INDEX_COUNT];
} Key_Event_Data;
typedef struct Mouse_State{
char l, r;
char press_l, press_r;
char release_l, release_r;
char wheel;
char out_of_window;
int x, y;
} Mouse_State;
typedef union Range{
struct{
int min, max;
};
struct{
int start, end;
};
} Range;
inline Range
make_range(int p1, int p2){
Range range;
if (p1 < p2){
range.min = p1;
range.max = p2;
}
else{
range.min = p2;
range.max = p1;
}
return(range);
}
typedef enum Dynamic_Type{
dynamic_type_int,
dynamic_type_string,
// never below this
dynamic_type_count
} Dynamic_Type;
typedef struct Dynamic{
int type;
union{
struct{
int str_len;
char *str_value;
};
int int_value;
};
} Dynamic;
inline Dynamic
dynamic_int(int x){
Dynamic result;
result.type = dynamic_type_int;
result.int_value = x;
return result;
}
inline Dynamic
dynamic_string(const char *string, int len){
Dynamic result;
result.type = dynamic_type_string;
result.str_len = len;
result.str_value = (char*)(string);
return result;
}
inline int
dynamic_to_int(Dynamic *dynamic){
int result = 0;
if (dynamic->type == dynamic_type_int){
result = dynamic->int_value;
}
return result;
}
inline char*
dynamic_to_string(Dynamic *dynamic, int *len){
char *result = 0;
if (dynamic->type == dynamic_type_string){
result = dynamic->str_value;
*len = dynamic->str_len;
}
return result;
}
inline int
dynamic_to_bool(Dynamic *dynamic){
int result = 0;
if (dynamic->type == dynamic_type_int){
result = (dynamic->int_value != 0);
}
else{
result = 1;
}
return result;
}
typedef struct File_Info{
String filename;
int folder;
} File_Info;
typedef struct File_List{
// Ignore this, it's for internal stuff.
void *block;
// The list of files and folders.
File_Info *infos;
int count;
// Ignore this, it's for internal stuff.
int block_size;
} File_List;
#define MDFR_NONE 0x0
#define MDFR_CTRL 0x1
#define MDFR_ALT 0x2
#define MDFR_SHIFT 0x4
enum Command_ID{
cmdid_null,
cmdid_write_character,
cmdid_seek_left,
cmdid_seek_right,
cmdid_seek_whitespace_up,
cmdid_seek_whitespace_down,
cmdid_word_complete,
cmdid_set_mark,
cmdid_copy,
cmdid_cut,
cmdid_paste,
cmdid_paste_next,
cmdid_delete_range,
cmdid_timeline_scrub,
cmdid_undo,
cmdid_redo,
cmdid_history_backward,
cmdid_history_forward,
cmdid_interactive_new,
cmdid_interactive_open,
cmdid_reopen,
cmdid_save,
cmdid_interactive_save_as,
cmdid_change_active_panel,
cmdid_interactive_switch_buffer,
cmdid_interactive_kill_buffer,
cmdid_kill_buffer,
cmdid_toggle_line_wrap,
cmdid_toggle_endline_mode,
cmdid_to_uppercase,
cmdid_to_lowercase,
cmdid_toggle_show_whitespace,
cmdid_clean_all_lines,
cmdid_eol_dosify,
cmdid_eol_nixify,
cmdid_auto_tab_range,
cmdid_open_panel_vsplit,
cmdid_open_panel_hsplit,
cmdid_close_panel,
cmdid_move_left,
cmdid_move_right,
cmdid_delete,
cmdid_backspace,
cmdid_move_up,
cmdid_move_down,
cmdid_seek_end_of_line,
cmdid_seek_beginning_of_line,
cmdid_page_up,
cmdid_page_down,
cmdid_open_color_tweaker,
cmdid_cursor_mark_swap,
cmdid_open_menu,
cmdid_set_settings,
cmdid_command_line,
//
cmdid_count
};
enum Param_ID{
par_range_start,
par_range_end,
par_name,
par_buffer_id,
par_do_in_background,
par_flags,
par_lex_as_cpp_file,
par_wrap_lines,
par_key_mapid,
par_cli_path,
par_cli_command,
par_clear_blank_lines,
// never below this
par_type_count
};
#define CLI_OverlapWithConflict 0x1
#define CLI_AlwaysBindToView 0x2
// These are regular hooks, any of them can be set to any function
// that matches the HOOK_SIG pattern.
enum Hook_ID{
hook_start,
hook_open_file,
hook_frame,
// never below this
hook_type_count
};
// These are for special hooks, each must bind to specialized signatures
// that do not necessarily have access to the app pointer.
enum Special_Hook_ID{
_hook_scroll_rule = hook_type_count,
};
// NOTE(allen): None of the members of *_Summary structs nor any of the
// data pointed to by the members should be modified, I would have made
// them all const... but that causes a lot problems for C++ reasons.
struct Buffer_Summary{
int exists;
int ready;
int buffer_id;
int size;
int file_name_len;
int buffer_name_len;
char *file_name;
char *buffer_name;
int buffer_cursor_pos;
int is_lexed;
int map_id;
};
struct View_Summary{
int exists;
int view_id;
int buffer_id;
int locked_buffer_id;
int hidden_buffer_id;
Full_Cursor cursor;
Full_Cursor mark;
float preferred_x;
int line_height;
int unwrapped_lines;
};
#define UserInputKey 0
#define UserInputMouse 1
struct User_Input{
int type;
int abort;
union{
Key_Event_Data key;
Mouse_State mouse;
};
unsigned long long command;
};
#define CommandEqual(c1,c2) ((unsigned long long)(c1) == (unsigned long long)(c2))
struct Query_Bar{
String prompt;
String string;
};
struct Theme_Color{
Style_Tag tag;
unsigned int color;
};
#define GET_BINDING_DATA(name) int name(void *data, int size)
#define CUSTOM_COMMAND_SIG(name) void name(struct Application_Links *app)
#define HOOK_SIG(name) int name(struct Application_Links *app)
#define SCROLL_RULE_SIG(name) int name(float target_x, float target_y, float *scroll_x, float *scroll_y, int view_id, int is_new_target)
extern "C"{
typedef CUSTOM_COMMAND_SIG(Custom_Command_Function);
typedef GET_BINDING_DATA(Get_Binding_Data_Function);
typedef HOOK_SIG(Hook_Function);
typedef SCROLL_RULE_SIG(Scroll_Rule_Function);
}
struct Application_Links;
// Command exectuion
#define PUSH_PARAMETER_SIG(n) void n(Application_Links *app, Dynamic param, Dynamic value)
#define PUSH_MEMORY_SIG(n) char* n(Application_Links *app, int len)
#define EXECUTE_COMMAND_SIG(n) void n(Application_Links *app, int command_id)
#define CLEAR_PARAMETERS_SIG(n) void n(Application_Links *app)
// File system navigation
#define DIRECTORY_GET_HOT_SIG(n) int n(Application_Links *app, char *out, int capacity)
#define FILE_EXISTS_SIG(n) int n(Application_Links *app, char *filename, int len)
#define DIRECTORY_CD_SIG(n) int n(Application_Links *app, char *dir, int *len, int capacity, char *rel_path, int rel_len)
#define GET_FILE_LIST_SIG(n) File_List n(Application_Links *app, char *dir, int len)
#define FREE_FILE_LIST_SIG(n) void n(Application_Links *app, File_List list)
// Direct buffer manipulation
#define GET_BUFFER_FIRST_SIG(n) Buffer_Summary n(Application_Links *app)
#define GET_BUFFER_NEXT_SIG(n) void n(Application_Links *app, Buffer_Summary *buffer)
#define GET_BUFFER_SIG(n) Buffer_Summary n(Application_Links *app, int index)
#define GET_ACTIVE_BUFFER_SIG(n) Buffer_Summary n(Application_Links *app)
#define GET_PARAMETER_BUFFER_SIG(n) Buffer_Summary n(Application_Links *app, int param_index)
#define GET_BUFFER_BY_NAME(n) Buffer_Summary n(Application_Links *app, char *filename, int len)
#define BUFFER_SEEK_DELIMITER_SIG(n) int n(Application_Links *app, Buffer_Summary *buffer, int start, char delim, int seek_forward, int *out)
#define BUFFER_SEEK_STRING_SIG(n) int n(Application_Links *app, Buffer_Summary *buffer, int start, char *str, int len, int seek_forward, int *out)
#define REFRESH_BUFFER_SIG(n) int n(Application_Links *app, Buffer_Summary *buffer)
#define BUFFER_READ_RANGE_SIG(n) int n(Application_Links *app, Buffer_Summary *buffer, int start, int end, char *out)
#define BUFFER_REPLACE_RANGE_SIG(n) int n(Application_Links *app, Buffer_Summary *buffer, int start, int end, char *str, int len)
#define BUFFER_SET_POS_SIG(n) int n(Application_Links *app, Buffer_Summary *buffer, int pos)
// File view manipulation
#define GET_VIEW_FIRST_SIG(n) View_Summary n(Application_Links *app)
#define GET_VIEW_NEXT_SIG(n) void n(Application_Links *app, View_Summary *view)
#define GET_VIEW_SIG(n) View_Summary n(Application_Links *app, int index)
#define GET_ACTIVE_VIEW_SIG(n) View_Summary n(Application_Links *app)
#define REFRESH_VIEW_SIG(n) int n(Application_Links *app, View_Summary *view)
#define VIEW_SET_CURSOR_SIG(n) int n(Application_Links *app, View_Summary *view, Buffer_Seek seek, int set_preferred_x)
#define VIEW_SET_MARK_SIG(n) int n(Application_Links *app, View_Summary *view, Buffer_Seek seek)
#define VIEW_SET_HIGHLIGHT_SIG(n) int n(Application_Links *app, View_Summary *view, int start, int end, int turn_on)
#define VIEW_SET_BUFFER_SIG(n) int n(Application_Links *app, View_Summary *view, int buffer_id)
// Directly get user input
#define GET_USER_INPUT_SIG(n) User_Input n(Application_Links *app, unsigned int get_type, unsigned int abort_type)
// Queries
#define START_QUERY_BAR_SIG(n) int n(Application_Links *app, Query_Bar *bar, unsigned int flags)
#define END_QUERY_BAR_SIG(n) void n(Application_Links *app, Query_Bar *bar, unsigned int flags)
// Color settings
#define CHANGE_THEME_SIG(n) void n(Application_Links *app, char *name, int len)
#define CHANGE_FONT_SIG(n) void n(Application_Links *app, char *name, int len)
#define SET_THEME_COLORS_SIG(n) void n(Application_Links *app, Theme_Color *colors, int count)
// Boundry type flags
#define BoundryWhitespace 0x1
#define BoundryToken 0x2
#define BoundryAlphanumeric 0x4
#define BoundryCamelCase 0x8
// Input type flags
#define EventOnAnyKey 0x1
#define EventOnEsc 0x2
#define EventOnLeftButton 0x4
#define EventOnRightButton 0x8
#define EventOnWheel 0x10
#define EventOnButton (EventOnLeftButton | EventOnRightButton | EventOnWheel)
// NOTE(allen): These don't work so much, so let's pretend they're not here for now.
#define EventOnMouseMove 0x20
#define EventOnMouse (EventOnButton | EventOnMouseMove)
extern "C"{
// Command exectuion
typedef EXECUTE_COMMAND_SIG(Exec_Command_Function);
typedef PUSH_PARAMETER_SIG(Push_Parameter_Function);
typedef PUSH_MEMORY_SIG(Push_Memory_Function);
typedef CLEAR_PARAMETERS_SIG(Clear_Parameters_Function);
// File system navigation
typedef DIRECTORY_GET_HOT_SIG(Directory_Get_Hot_Function);
typedef FILE_EXISTS_SIG(File_Exists_Function);
typedef DIRECTORY_CD_SIG(Directory_CD_Function);
typedef GET_FILE_LIST_SIG(Get_File_List_Function);
typedef FREE_FILE_LIST_SIG(Free_File_List_Function);
// Buffer manipulation
typedef GET_BUFFER_FIRST_SIG(Get_Buffer_First_Function);
typedef GET_BUFFER_NEXT_SIG(Get_Buffer_Next_Function);
typedef GET_BUFFER_SIG(Get_Buffer_Function);
typedef GET_ACTIVE_BUFFER_SIG(Get_Active_Buffer_Function);
typedef GET_PARAMETER_BUFFER_SIG(Get_Parameter_Buffer_Function);
typedef GET_BUFFER_BY_NAME(Get_Buffer_By_Name_Function);
typedef BUFFER_SEEK_DELIMITER_SIG(Buffer_Seek_Delimiter_Function);
typedef BUFFER_SEEK_STRING_SIG(Buffer_Seek_String_Function);
typedef REFRESH_BUFFER_SIG(Refresh_Buffer_Function);
typedef BUFFER_READ_RANGE_SIG(Buffer_Read_Range_Function);
typedef BUFFER_REPLACE_RANGE_SIG(Buffer_Replace_Range_Function);
typedef BUFFER_SET_POS_SIG(Buffer_Set_Pos_Function);
// View manipulation
typedef GET_VIEW_FIRST_SIG(Get_View_First_Function);
typedef GET_VIEW_NEXT_SIG(Get_View_Next_Function);
typedef GET_VIEW_SIG(Get_View_Function);
typedef GET_ACTIVE_VIEW_SIG(Get_Active_View_Function);
typedef REFRESH_VIEW_SIG(Refresh_View_Function);
typedef VIEW_SET_CURSOR_SIG(View_Set_Cursor_Function);
typedef VIEW_SET_MARK_SIG(View_Set_Mark_Function);
typedef VIEW_SET_HIGHLIGHT_SIG(View_Set_Highlight_Function);
typedef VIEW_SET_BUFFER_SIG(View_Set_Buffer_Function);
// Directly get user input
typedef GET_USER_INPUT_SIG(Get_User_Input_Function);
// Queries
typedef START_QUERY_BAR_SIG(Start_Query_Bar_Function);
typedef END_QUERY_BAR_SIG(End_Query_Bar_Function);
// Color settings
typedef CHANGE_THEME_SIG(Change_Theme_Function);
typedef CHANGE_FONT_SIG(Change_Font_Function);
typedef SET_THEME_COLORS_SIG(Set_Theme_Colors_Function);
}
struct Application_Links{
// User data
void *memory;
int memory_size;
// Command exectuion
Exec_Command_Function *exec_command_keep_stack;
Push_Parameter_Function *push_parameter;
Push_Memory_Function *push_memory;
Clear_Parameters_Function *clear_parameters;
// File system navigation
Directory_Get_Hot_Function *directory_get_hot;
File_Exists_Function *file_exists;
Directory_CD_Function *directory_cd;
Get_File_List_Function *get_file_list;
Free_File_List_Function *free_file_list;
// Buffer manipulation
Get_Buffer_First_Function *get_buffer_first;
Get_Buffer_Next_Function *get_buffer_next;
Get_Buffer_Function *get_buffer;
Get_Active_Buffer_Function *get_active_buffer;
Get_Parameter_Buffer_Function *get_parameter_buffer;
Get_Buffer_By_Name_Function *get_buffer_by_name;
Buffer_Seek_Delimiter_Function *buffer_seek_delimiter;
Buffer_Seek_String_Function *buffer_seek_string;
Refresh_Buffer_Function *refresh_buffer;
Buffer_Read_Range_Function *buffer_read_range;
Buffer_Replace_Range_Function *buffer_replace_range;
Buffer_Set_Pos_Function *buffer_set_pos;
// View manipulation
Get_View_First_Function *get_view_first;
Get_View_Next_Function *get_view_next;
Get_View_Function *get_view;
Get_Active_View_Function *get_active_view;
Refresh_View_Function *refresh_view;
View_Set_Cursor_Function *view_set_cursor;
View_Set_Mark_Function *view_set_mark;
View_Set_Highlight_Function *view_set_highlight;
View_Set_Buffer_Function *view_set_buffer;
// Directly get user input
Get_User_Input_Function *get_user_input;
// Queries
Start_Query_Bar_Function *start_query_bar;
End_Query_Bar_Function *end_query_bar;
// Theme
Change_Theme_Function *change_theme;
Change_Font_Function *change_font;
Set_Theme_Colors_Function *set_theme_colors;
// Internal
void *cmd_context;
};
#define _GET_VERSION_SIG(n) int n(int maj, int min, int patch)
typedef _GET_VERSION_SIG(_Get_Version_Function);
extern "C" _GET_VERSION_SIG(get_alpha_4coder_version){
int result = (maj == MAJOR && min == MINOR && patch == PATCH);
return(result);
}
struct Custom_API{
Get_Binding_Data_Function *get_bindings;
_Get_Version_Function *get_alpha_4coder_version;
};
// NOTE(allen): definitions for the buffer that communicates to 4ed.exe
enum Binding_Unit_Type{
unit_header,
unit_map_begin,
unit_binding,
unit_callback,
unit_inherit,
unit_hook
};
enum Map_ID{
mapid_global = (1 << 24),
mapid_file,
// NOTE(allen): mapid_nomap will remain empty even if you attempt to fill it
// it is for setting a map's parent to nothing, in cases where you don't want
// to inherit from global (which is the default).
mapid_nomap
};
struct Binding_Unit{
Binding_Unit_Type type;
union{
struct{ int total_size; int user_map_count; int error; } header;
struct{ int mapid; int bind_count; } map_begin;
struct{ int mapid; } map_inherit;
struct{
short code;
unsigned char modifiers;
int command_id;
} binding;
struct{
short code;
unsigned char modifiers;
Custom_Command_Function *func;
} callback;
struct{
int hook_id;
void *func;
} hook;
};
};

View File

@ -0,0 +1,343 @@
/*
* Bind helper struct and functions
*/
struct Bind_Helper{
Binding_Unit *cursor, *start, *end;
Binding_Unit *header, *group;
int write_total;
int error;
};
#define BH_ERR_NONE 0
#define BH_ERR_MISSING_END 1
#define BH_ERR_MISSING_BEGIN 2
#define BH_ERR_OUT_OF_MEMORY 3
inline void
copy(char *dest, const char *src, int len){
for (int i = 0; i < len; ++i){
*dest++ = *src++;
}
}
inline Binding_Unit*
write_unit(Bind_Helper *helper, Binding_Unit unit){
Binding_Unit *p = 0;
helper->write_total += sizeof(*p);
if (helper->error == 0 && helper->cursor != helper->end){
p = helper->cursor++;
*p = unit;
}
return p;
}
inline char*
write_inline_string(Bind_Helper *helper, char *value, int len){
char *dest = 0;
helper->write_total += len;
if (helper->error == 0){
dest = (char*)helper->cursor;
int cursor_advance = len + sizeof(*helper->cursor) - 1;
cursor_advance /= sizeof(*helper->cursor);
cursor_advance *= sizeof(*helper->cursor);
helper->cursor += cursor_advance;
if (helper->cursor < helper->end){
copy(dest, value, len);
}
else{
helper->error = BH_ERR_OUT_OF_MEMORY;
}
}
return dest;
}
inline Bind_Helper
begin_bind_helper(void *data, int size){
Bind_Helper result;
result.header = 0;
result.group = 0;
result.write_total = 0;
result.error = 0;
result.cursor = (Binding_Unit*)data;
result.start = result.cursor;
result.end = result.start + size / sizeof(*result.cursor);
Binding_Unit unit;
unit.type = unit_header;
unit.header.total_size = sizeof(*result.header);
result.header = write_unit(&result, unit);
result.header->header.user_map_count = 0;
return result;
}
inline void
begin_map(Bind_Helper *helper, int mapid){
if (helper->group != 0 && helper->error == 0) helper->error = BH_ERR_MISSING_END;
if (!helper->error && mapid < mapid_global) ++helper->header->header.user_map_count;
Binding_Unit unit;
unit.type = unit_map_begin;
unit.map_begin.mapid = mapid;
helper->group = write_unit(helper, unit);
helper->group->map_begin.bind_count = 0;
}
inline void
end_map(Bind_Helper *helper){
if (helper->group == 0 && helper->error == 0) helper->error = BH_ERR_MISSING_BEGIN;
helper->group = 0;
}
inline void
bind(Bind_Helper *helper, short code, unsigned char modifiers, int cmdid){
if (helper->group == 0 && helper->error == 0) helper->error = BH_ERR_MISSING_BEGIN;
if (!helper->error) ++helper->group->map_begin.bind_count;
Binding_Unit unit;
unit.type = unit_binding;
unit.binding.command_id = cmdid;
unit.binding.code = code;
unit.binding.modifiers = modifiers;
write_unit(helper, unit);
}
inline void
bind(Bind_Helper *helper, short code, unsigned char modifiers, Custom_Command_Function *func){
if (helper->group == 0 && helper->error == 0) helper->error = BH_ERR_MISSING_BEGIN;
if (!helper->error) ++helper->group->map_begin.bind_count;
Binding_Unit unit;
unit.type = unit_callback;
unit.callback.func = func;
unit.callback.code = code;
unit.callback.modifiers = modifiers;
write_unit(helper, unit);
}
inline void
bind_vanilla_keys(Bind_Helper *helper, int cmdid){
bind(helper, 0, 0, cmdid);
}
inline void
bind_vanilla_keys(Bind_Helper *helper, Custom_Command_Function *func){
bind(helper, 0, 0, func);
}
inline void
bind_vanilla_keys(Bind_Helper *helper, unsigned char modifiers, int cmdid){
bind(helper, 0, modifiers, cmdid);
}
inline void
bind_vanilla_keys(Bind_Helper *helper, unsigned char modifiers, Custom_Command_Function *func){
bind(helper, 0, modifiers, func);
}
inline void
inherit_map(Bind_Helper *helper, int mapid){
if (helper->group == 0 && helper->error == 0) helper->error = BH_ERR_MISSING_BEGIN;
if (!helper->error && mapid < mapid_global) ++helper->header->header.user_map_count;
Binding_Unit unit;
unit.type = unit_inherit;
unit.map_inherit.mapid = mapid;
write_unit(helper, unit);
}
inline void
set_hook(Bind_Helper *helper, int hook_id, Hook_Function *func){
Binding_Unit unit;
unit.type = unit_hook;
unit.hook.hook_id = hook_id;
unit.hook.func = (void*) func;
write_unit(helper, unit);
}
inline void
set_scroll_rule(Bind_Helper *helper, Scroll_Rule_Function *func){
Binding_Unit unit;
unit.type = unit_hook;
unit.hook.hook_id = _hook_scroll_rule;
unit.hook.func = (void*) func;
write_unit(helper, unit);
}
inline void
end_bind_helper(Bind_Helper *helper){
if (helper->header){
helper->header->header.total_size = (int)(helper->cursor - helper->start);
helper->header->header.error = helper->error;
}
}
// NOTE(allen): Useful functions and overloads on app links
inline void
push_parameter(Application_Links *app, int param, int value){
app->push_parameter(app, dynamic_int(param), dynamic_int(value));
}
inline void
push_parameter(Application_Links *app, int param, const char *value, int value_len){
char *value_copy = app->push_memory(app, value_len+1);
copy(value_copy, value, value_len);
value_copy[value_len] = 0;
app->push_parameter(app, dynamic_int(param), dynamic_string(value_copy, value_len));
}
inline void
push_parameter(Application_Links *app, const char *param, int param_len, int value){
char *param_copy = app->push_memory(app, param_len+1);
copy(param_copy, param, param_len);
param_copy[param_len] = 0;
app->push_parameter(app, dynamic_string(param_copy, param_len), dynamic_int(value));
}
inline void
push_parameter(Application_Links *app, const char *param, int param_len, const char *value, int value_len){
char *param_copy = app->push_memory(app, param_len+1);
char *value_copy = app->push_memory(app, value_len+1);
copy(param_copy, param, param_len);
copy(value_copy, value, value_len);
value_copy[value_len] = 0;
param_copy[param_len] = 0;
app->push_parameter(app, dynamic_string(param_copy, param_len), dynamic_string(value_copy, value_len));
}
inline Range
get_range(View_Summary *view){
Range range;
range = make_range(view->cursor.pos, view->mark.pos);
return(range);
}
inline void
exec_command(Application_Links *app, Command_ID id){
app->exec_command_keep_stack(app, id);
app->clear_parameters(app);
}
inline void
exec_command(Application_Links *app, Custom_Command_Function *func){
func(app);
app->clear_parameters(app);
}
inline void
active_view_to_line(Application_Links *app, int line_number){
View_Summary view;
view = app->get_active_view(app);
// NOTE(allen|a3.4.4): We don't have to worry about whether this is a valid line number.
// When it's not possible to place a cursor at the position for whatever reason it will set the
// cursor to a nearby valid position.
app->view_set_cursor(app, &view, seek_line_char(line_number, 0), 1);
}
inline View_Summary
get_first_view_with_buffer(Application_Links *app, int buffer_id){
View_Summary result = {};
View_Summary test = {};
for(test = app->get_view_first(app);
test.exists;
app->get_view_next(app, &test)){
if(test.locked_buffer_id == buffer_id){
result = test;
break;
}
}
return(result);
}
inline int
key_is_unmodified(Key_Event_Data *key){
char *mods = key->modifiers;
int unmodified = !mods[MDFR_CONTROL_INDEX] && !mods[MDFR_ALT_INDEX];
return(unmodified);
}
static int
query_user_general(Application_Links *app, Query_Bar *bar, int force_number){
User_Input in;
int success = 1;
int good_character = 0;
// NOTE(allen|a3.4.4): It will not cause an *error* if we continue on after failing to.
// start a query bar, but it will be unusual behavior from the point of view of the
// user, if this command starts intercepting input even though no prompt is shown.
// This will only happen if you have a lot of bars open already or if the current view
// doesn't support query bars.
if (app->start_query_bar(app, bar, 0) == 0) return 0;
while (1){
// NOTE(allen|a3.4.4): This call will block until the user does one of the input
// types specified in the flags. The first set of flags are inputs you'd like to intercept
// that you don't want to abort on. The second set are inputs that you'd like to cause
// the command to abort. If an event satisfies both flags, it is treated as an abort.
in = app->get_user_input(app, EventOnAnyKey, EventOnEsc | EventOnButton);
// NOTE(allen|a3.4.4): The responsible thing to do on abort is to end the command
// without waiting on get_user_input again.
if (in.abort){
success = 0;
break;
}
good_character = 0;
if (key_is_unmodified(&in.key)){
if (force_number){
if (in.key.character >= '0' && in.key.character <= '9'){
good_character = 1;
}
}
else{
if (in.key.character != 0){
good_character = 1;
}
}
}
// NOTE(allen|a3.4.4): All we have to do to update the query bar is edit our
// local Query_Bar struct! This is handy because it means our Query_Bar
// is always correct for typical use without extra work updating the bar.
if (in.type == UserInputKey){
if (in.key.keycode == '\n' || in.key.keycode == '\t'){
break;
}
else if (in.key.keycode == key_back){
--bar->string.size;
}
else if (good_character){
append(&bar->string, in.key.character);
}
}
}
return(success);
}
inline int
query_user_string(Application_Links *app, Query_Bar *bar){
int success = query_user_general(app, bar, 0);
return(success);
}
inline int
query_user_number(Application_Links *app, Query_Bar *bar){
int success = query_user_general(app, bar, 1);
return(success);
}
inline String empty_string() {String Result = {}; return(Result);}

View File

@ -0,0 +1,30 @@
enum Key_Code{
key_back = 1,
key_up = 2,
key_down = 3,
key_left = 4,
key_right = 5,
key_del = 6,
key_insert = 7,
key_home = 8,
key_end = 11,
key_page_up = 12,
key_page_down = 13,
key_esc = 14,
key_f1 = 127,
key_f2 = 128,
key_f3 = 129,
key_f4 = 130,
key_f5 = 131,
key_f6 = 132,
key_f7 = 133,
key_f8 = 134,
key_f9 = 135,
key_f10 = 136,
key_f11 = 137,
key_f12 = 138,
key_f13 = 139,
key_f14 = 140,
key_f15 = 141,
key_f16 = 142,
};

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,33 @@
enum Style_Tag{
Stag_Bar,
Stag_Bar_Active,
Stag_Base,
Stag_Pop1,
Stag_Pop2,
Stag_Back,
Stag_Margin,
Stag_Margin_Hover,
Stag_Margin_Active,
Stag_Cursor,
Stag_At_Cursor,
Stag_Highlight,
Stag_At_Highlight,
Stag_Mark,
Stag_Default,
Stag_Comment,
Stag_Keyword,
Stag_Str_Constant,
Stag_Char_Constant,
Stag_Int_Constant,
Stag_Float_Constant,
Stag_Bool_Constant,
Stag_Preproc,
Stag_Include,
Stag_Special_Character,
Stag_Highlight_Junk,
Stag_Highlight_White,
Stag_Paste,
Stag_Undo,
Stag_Next_Undo,
};

View File

@ -0,0 +1,15 @@
#define MAJOR 4
#define MINOR 0
#define PATCH 1
#define VN__(a,b,c) #a"."#b"."#c
#define VN_(a,b,c) VN__(a,b,c)
#define VERSION_NUMBER VN_(MAJOR,MINOR,PATCH)
#define VERSION_STRING "alpha " VERSION_NUMBER
#ifdef FRED_SUPER
#define VERSION_TYPE " super!"
#else
#define VERSION_TYPE
#endif
#define VERSION VERSION_STRING VERSION_TYPE

View File

@ -0,0 +1,54 @@
/* "4cpp" Open C++ Parser v0.1: Clear Config
no warranty implied; use at your own risk
NOTES ON USE:
This file is used to clear options. The main use for this is for cases when you want
it include different portions of the library with different settings. So that the compiler
does not complain about redifintion, and so that you do not have to undef everything yourself
this is provided to undef everything at once.
*/
#ifdef FCPP_NO_CRT
#undef FCPP_NO_CRT
#endif
#ifdef FCPP_NO_MALLOC
#undef FCPP_NO_MALLOC
#endif
#ifdef FCPP_NO_ASSERT
#undef FCPP_NO_ASSERT
#endif
#ifdef FCPP_NO_STRING
#undef FCPP_NO_STRING
#endif
#ifdef FCPP_GET_MEMORY
#undef FCPP_GET_MEMORY
#endif
#ifdef FCPP_FREE_MEMORY
#undef FCPP_FREE_MEMORY
#endif
#ifdef FCPP_ASSERT
#undef FCPP_ASSERT
#endif
#ifdef FCPP_MEM_COPY
#undef FCPP_MEM_COPY
#endif
#ifdef FCPP_MEM_MOVE
#undef FCPP_MEM_MOVE
#endif
#ifdef FCPP_LINK
#undef FCPP_LINK
#endif
#ifdef FCPP_EXTERN
#undef FCPP_EXTERN
#endif

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,19 @@
/*
* Mr. 4th Dimention - Allen Webster
*
* 30.11.2015
*
* CPP preprocessor
*
*/
// TOP
#define byte unsigned char
#undef byte
// BOTTOM

View File

@ -0,0 +1,39 @@
/* "4cpp" Open C++ Parser v0.1: Types
no warranty implied; use at your own risk
NOTES ON USE:
This file is used to declare 4cpp fixed width integer and float types.
It is not meant to be used directly.
*/
// TODO(allen):
// - create non stdint.h version in case someone wants to exclude that header
#include "4coder_config.h"
#ifndef FCPP_TYPES
#define FCPP_TYPES
#include <stdint.h>
typedef uint8_t fcpp_u8;
typedef uint64_t fcpp_u64;
typedef uint32_t fcpp_u32;
typedef uint16_t fcpp_u16;
typedef int8_t fcpp_i8;
typedef int64_t fcpp_i64;
typedef int32_t fcpp_i32;
typedef int16_t fcpp_i16;
typedef fcpp_i32 fcpp_bool32;
typedef fcpp_i8 fcpp_bool8;
typedef float fcpp_real32;
typedef double fcpp_real64;
#define FCPP_GLOBAL static
#define FCPP_COUNT(a) (sizeof(a)/sizeof(*(a)))
#endif

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,130 @@
/*
* Mr. 4th Dimention - Allen Webster
*
* 12.12.2014
*
* Application Layer for 4coder
*
*/
// TOP
#ifndef FRED_H
#define FRED_H
struct Application_Memory{
void *vars_memory;
i32 vars_memory_size;
void *target_memory;
i32 target_memory_size;
void *user_memory;
i32 user_memory_size;
};
#define KEY_INPUT_BUFFER_SIZE 4
#define KEY_INPUT_BUFFER_DSIZE (KEY_INPUT_BUFFER_SIZE << 1)
struct Key_Input_Data{
Key_Event_Data press[KEY_INPUT_BUFFER_SIZE];
Key_Event_Data hold[KEY_INPUT_BUFFER_SIZE];
i32 press_count;
i32 hold_count;
};
struct Key_Summary{
i32 count;
Key_Event_Data keys[KEY_INPUT_BUFFER_DSIZE];
};
inline Key_Event_Data
get_single_key(Key_Summary *summary, i32 index){
Assert(index >= 0 && index < summary->count);
Key_Event_Data key;
key = summary->keys[index];
return key;
}
struct Input_Summary{
Mouse_State mouse;
Key_Summary keys;
};
struct Command_Line_Parameters{
char **argv;
int argc;
};
struct Plat_Settings{
char *custom_dll;
b32 custom_dll_is_strict;
i32 window_w, window_h;
i32 window_x, window_y;
b8 set_window_pos, set_window_size;
b8 maximize_window;
};
#define App_Read_Command_Line_Sig(name) \
i32 name(System_Functions *system, \
Application_Memory *memory, \
String current_directory, \
Plat_Settings *plat_settings, \
char ***files, i32 **file_count, \
Command_Line_Parameters clparams \
)
typedef App_Read_Command_Line_Sig(App_Read_Command_Line);
#define App_Init_Sig(name) void \
name(System_Functions *system, \
Render_Target *target, \
Application_Memory *memory, \
Exchange *exchange, \
String clipboard, \
String current_directory, \
Custom_API api)
typedef App_Init_Sig(App_Init);
enum Application_Mouse_Cursor{
APP_MOUSE_CURSOR_DEFAULT,
APP_MOUSE_CURSOR_ARROW,
APP_MOUSE_CURSOR_IBEAM,
APP_MOUSE_CURSOR_LEFTRIGHT,
APP_MOUSE_CURSOR_UPDOWN,
// never below this
APP_MOUSE_CURSOR_COUNT
};
struct Application_Step_Result{
Application_Mouse_Cursor mouse_cursor_type;
b32 redraw;
b32 lctrl_lalt_is_altgr;
};
#define App_Step_Sig(name) void \
name(System_Functions *system, \
Key_Input_Data *input, \
Mouse_State *mouse, \
Render_Target *target, \
Application_Memory *memory, \
Exchange *exchange, \
String clipboard, \
b32 time_step, b32 first_step, b32 force_redraw, \
Application_Step_Result *result)
typedef App_Step_Sig(App_Step);
struct App_Functions{
App_Read_Command_Line *read_command_line;
App_Init *init;
App_Step *step;
};
#define App_Get_Functions_Sig(name) App_Functions name()
typedef App_Get_Functions_Sig(App_Get_Functions);
#endif
// BOTTOM

View File

@ -0,0 +1,67 @@
/*
* Mr. 4th Dimention - Allen Webster
*
* 27.01.2016
*
* Global app level settings definition
*
*/
// TOP
struct App_Settings{
char *user_file;
b32 user_file_is_strict;
char *init_files[8];
i32 init_files_count;
i32 init_files_max;
i32 initial_line;
b32 lctrl_lalt_is_altgr;
};
struct Models{
Mem_Options mem;
App_Settings settings;
Command_Map map_top;
Command_Map map_file;
Command_Map map_ui;
Command_Map *user_maps;
i32 *map_id_table;
i32 user_map_count;
Command_Binding prev_command;
Coroutine *command_coroutine;
u32 command_coroutine_flags[2];
Hook_Function *hooks[hook_type_count];
i32 *buffer_param_indices;
i32 buffer_param_count, buffer_param_max;
Font_Set *font_set;
Style_Font global_font;
Style style;
Style_Library styles;
u32 *palette;
i32 palette_size;
Editing_Layout layout;
Working_Set working_set;
char hot_dir_base_[256];
Hot_Directory hot_directory;
Delay delay1, delay2;
Panel *prev_mouse_panel;
Custom_API config_api;
Scroll_Rule_Function *scroll_rule;
};
// BOTTOM

View File

@ -0,0 +1,55 @@
/*
* Mr. 4th Dimention - Allen Webster
*
* 13.11.2015
*
* Application layer build target
*
*/
// TOP
#include "4ed_config.h"
#define BUFFER_EXPERIMENT_SCALPEL 0
#include "4ed_meta.h"
#include "4cpp_types.h"
#define FCPP_STRING_IMPLEMENTATION
#include "4coder_string.h"
#include "4ed_mem.cpp"
#include "4ed_math.cpp"
#include "4coder_custom.h"
#include "4ed_system.h"
#include "4ed_rendering.h"
#include "4ed.h"
#include "4ed_internal.h"
#include "4tech_table.cpp"
#define FCPP_LEXER_IMPLEMENTATION
#include "4cpp_lexer.h"
#include "4ed_template.cpp"
#include "4ed_font_set.cpp"
#include "4ed_rendering_helper.cpp"
#include "4ed_style.h"
#include "4ed_style.cpp"
#include "4ed_exchange.cpp"
#include "4ed_command.cpp"
#include "4ed_file.cpp"
#include "4ed_gui.cpp"
#include "4ed_layout.cpp"
#include "4ed_delay.cpp"
#include "4ed_app_settings.h"
#include "4ed_file_view.cpp"
#include "4ed.cpp"
// BOTTOM

View File

@ -0,0 +1,201 @@
/*
* Mr. 4th Dimention - Allen Webster
*
* 19.08.2015
*
* Command management functions for 4coder
*
*/
// TOP
#define Command_Function_Sig(name) void (name)( \
System_Functions *system, \
struct Command_Data *command, \
struct Command_Binding binding)
typedef Command_Function_Sig(*Command_Function);
struct Command_Binding{
Command_Function function;
union{
Custom_Command_Function *custom;
u64 custom_id;
};
i64 hash;
};
struct Command_Map{
Command_Map *parent;
Command_Binding vanilla_keyboard_default;
Command_Binding *commands;
i32 count, max;
};
internal void command_null(Command_Data *command);
internal i64
map_hash(u16 event_code, u8 modifiers){
i64 result = (event_code << 8) | modifiers;
return result;
}
internal b32
map_add(Command_Map *map, u16 event_code, u8 modifiers,
Command_Function function, Custom_Command_Function *custom = 0){
Assert(map->count * 8 < map->max * 7);
Command_Binding bind;
bind.function = function;
bind.custom = custom;
bind.hash = map_hash(event_code, modifiers);
i32 max = map->max;
i32 index = bind.hash % max;
Command_Binding entry;
while ((entry = map->commands[index]).function && entry.hash != -1){
if (entry.hash == bind.hash){
return 1;
}
index = (index + 1) % max;
}
map->commands[index] = bind;
++map->count;
return 0;
}
inline b32
map_add(Command_Map *map, u16 event_code, u8 modifiers,
Command_Function function, u64 custom_id){
return (map_add(map, event_code, modifiers, function, (Custom_Command_Function*)custom_id));
}
internal b32
map_find_entry(Command_Map *map, u16 event_code, u8 modifiers,
i32 *index_out){
i64 hash = map_hash(event_code, modifiers);
i32 max = map->max;
i32 index = hash % map->max;
Command_Binding entry;
while ((entry = map->commands[index]).function){
if (entry.hash == hash){
*index_out = index;
return 1;
}
index = (index + 1) % max;
}
return 0;
}
internal b32
map_find(Command_Map *map, u16 event_code, u8 modifiers,
Command_Binding *bind_out){
b32 result;
i32 index;
result = map_find_entry(map, event_code, modifiers, &index);
if (result){
*bind_out = map->commands[index];
}
return result;
}
internal b32
map_drop(Command_Map *map, u16 event_code, u8 modifiers){
b32 result;
i32 index;
result = map_find_entry(map, event_code, modifiers, &index);
if (result){
map->commands[index].function = 0;
map->commands[index].hash = -1;
}
return result;
}
internal void
map_init(Command_Map *commands, Partition *part, i32 max, Command_Map *parent){
max = ((max < 6)?(6):(max));
commands->parent = parent;
commands->commands = push_array(part, Command_Binding, max);
memset(commands->commands, 0, max*sizeof(*commands->commands));
commands->vanilla_keyboard_default = {};
commands->max = max;
commands->count = 0;
}
internal void
map_get_vanilla_keyboard_default(Command_Map *map, u8 command,
Command_Binding *bind_out){
if (command == MDFR_NONE){
*bind_out = map->vanilla_keyboard_default;
}
}
inline u8
apply_shift_to_code(u8 keycode){
return !(keycode >= 0x20 && keycode < 0x7F && keycode != ' ');
}
internal Command_Binding
map_extract(Command_Map *map, Key_Event_Data key){
Command_Binding bind = {};
b32 ctrl = key.modifiers[MDFR_CONTROL_INDEX];
b32 alt = key.modifiers[MDFR_ALT_INDEX];
b32 shift = key.modifiers[MDFR_SHIFT_INDEX];
u16 code;
u8 command = MDFR_NONE;
//if (key.character_no_caps_lock != 0 &&
// key.character_no_caps_lock != ' ') shift = 0;
if (shift) command |= MDFR_SHIFT;
if (ctrl) command |= MDFR_CTRL;
if (alt) command |= MDFR_ALT;
code = key.character_no_caps_lock;
if (code == 0){
code = key.keycode;
map_find(map, code, command, &bind);
}
else{
if (code != '\n' && code != '\t' && code != ' '){
command &= ~(MDFR_SHIFT);
}
map_find(map, code, command, &bind);
if (bind.function == 0){
map_get_vanilla_keyboard_default(map, command, &bind);
}
}
return(bind);
}
internal Command_Binding
map_extract_recursive(Command_Map *map, Key_Event_Data key){
Command_Binding cmd_bind = {};
Command_Map *visited_maps[16] = {};
i32 visited_top = 0;
while (map){
cmd_bind = map_extract(map, key);
if (cmd_bind.function == 0){
if (visited_top < ArrayCount(visited_maps)){
visited_maps[visited_top++] = map;
map = map->parent;
for (i32 i = 0; i < visited_top; ++i){
if (map == visited_maps[i]){
map = 0;
break;
}
}
}
else map = 0;
}
else map = 0;
}
return(cmd_bind);
}
// BOTTOM

View File

@ -0,0 +1,52 @@
/*
* Mr. 4th Dimention - Allen Webster
*
* 13.11.2014
*
* Application layer build target
*
*/
// TOP
#ifdef FRED_NOT_PACKAGE
#define FRED_INTERNAL 1
#define FRED_SLOW 1
#define FRED_PRINT_DEBUG 1
#define FRED_PRINT_DEBUG_FILE_LINE 0
#define FRED_PROFILING 1
#define FRED_PROFILING_OS 0
#define FRED_FULL_ERRORS 0
#else
#define FRED_SLOW 0
#define FRED_INTERNAL 0
#define FRED_PRINT_DEBUG 0
#define FRED_PRINT_DEBUG_FILE_LINE 0
#define FRED_PROFILING 0
#define FRED_PROFILING_OS 0
#define FRED_FULL_ERRORS 0
#endif
#if FRED_INTERNAL == 0
#undef FRED_PRINT_DEBUG
#define FRED_PRINT_DEBUG 0
#undef FRED_PROFILING
#define FRED_PROFILING 0
#undef FRED_PROFILING_OS
#define FRED_PROFILING_OS 0
#endif
#if FRED_PRINT_DEBUG == 0
#undef FRED_PRINT_DEBUG_FILE_LINE
#define FRED_PRINT_DEBUG_FILE_LINE 0
#undef FRED_PRINT_DEBUG_FILE_LINE
#define FRED_PROFILING_OS 0
#endif
// BOTTOM

View File

@ -0,0 +1,131 @@
enum Action_Type{
DACT_OPEN,
DACT_OPEN_BACKGROUND,
DACT_SET_LINE,
DACT_SAVE_AS,
DACT_SAVE,
DACT_NEW,
DACT_SWITCH,
DACT_TRY_KILL,
DACT_KILL,
DACT_TOUCH_FILE,
};
struct Delayed_Action{
Action_Type type;
String string;
Panel* panel;
Editing_File* file;
i32 integer;
};
struct Delay{
General_Memory* general;
Delayed_Action* acts;
i32 count;
i32 max;
};
internal String
str_alloc_copy(General_Memory *general, String str){
String result;
result.memory_size = str.memory_size + 1;
result.size = str.size;
result.str = (char*)general_memory_allocate(general, result.memory_size, 0);
memcpy(result.str, str.str, str.size);
result.str[result.size] = 0;
return(result);}
inline Delayed_Action*
delayed_action_(Delay *delay, Action_Type type){
Delayed_Action *result;
if (delay->count == delay->max){
delay->max *= 2;
delay->acts = (Delayed_Action*)general_memory_reallocate(delay->general, delay->acts, delay->count*sizeof(Delayed_Action), delay->max*sizeof(Delayed_Action), 0);
}
result = delay->acts + delay->count++;
*result = {};
result->type = type;
return(result);
}
inline Delayed_Action*
delayed_action_(Delay *delay, Action_Type type, String string){
Delayed_Action *result;
result = delayed_action_(delay, type);
result->string = str_alloc_copy(delay->general, string);
return(result);
}
inline Delayed_Action*
delayed_action_(Delay *delay, Action_Type type, Panel* panel){
Delayed_Action *result;
result = delayed_action_(delay, type);
result->panel = panel;
return(result);
}
inline Delayed_Action*
delayed_action_(Delay *delay, Action_Type type, Editing_File* file){
Delayed_Action *result;
result = delayed_action_(delay, type);
result->file = file;
return(result);
}
inline Delayed_Action*
delayed_action_(Delay *delay, Action_Type type, Editing_File* file, Panel* panel){
Delayed_Action *result;
result = delayed_action_(delay, type);
result->file = file;
result->panel = panel;
return(result);
}
inline Delayed_Action*
delayed_action_(Delay *delay, Action_Type type, String string, Panel* panel){
Delayed_Action *result;
result = delayed_action_(delay, type);
result->string = str_alloc_copy(delay->general, string);
result->panel = panel;
return(result);
}
inline Delayed_Action*
delayed_action_(Delay *delay, Action_Type type, String string, Editing_File* file){
Delayed_Action *result;
result = delayed_action_(delay, type);
result->string = str_alloc_copy(delay->general, string);
result->file = file;
return(result);
}
inline Delayed_Action*
delayed_action_(Delay *delay, Action_Type type, Panel* panel, i32 integer){
Delayed_Action *result;
result = delayed_action_(delay, type);
result->panel = panel;
result->integer = integer;
return(result);
}
inline Delayed_Action*
delayed_action_repush(Delay *delay, Delayed_Action *act){
Delayed_Action *new_act = delayed_action_(delay, (Action_Type)0);
*new_act = *act;
if (act->string.str){
new_act->string = str_alloc_copy(delay->general, act->string);
}
return(new_act);
}
#define delayed_open(delay, ...) delayed_action_(delay, DACT_OPEN, __VA_ARGS__)
#define delayed_open_background(delay, ...) delayed_action_(delay, DACT_OPEN_BACKGROUND, __VA_ARGS__)
#define delayed_set_line(delay, ...) delayed_action_(delay, DACT_SET_LINE, __VA_ARGS__)
#define delayed_save_as(delay, ...) delayed_action_(delay, DACT_SAVE_AS, __VA_ARGS__)
#define delayed_save(delay, ...) delayed_action_(delay, DACT_SAVE, __VA_ARGS__)
#define delayed_new(delay, ...) delayed_action_(delay, DACT_NEW, __VA_ARGS__)
#define delayed_switch(delay, ...) delayed_action_(delay, DACT_SWITCH, __VA_ARGS__)
#define delayed_try_kill(delay, ...) delayed_action_(delay, DACT_TRY_KILL, __VA_ARGS__)
#define delayed_kill(delay, ...) delayed_action_(delay, DACT_KILL, __VA_ARGS__)
#define delayed_touch_file(delay, ...) delayed_action_(delay, DACT_TOUCH_FILE, __VA_ARGS__)

View File

@ -0,0 +1,378 @@
/*
* Mr. 4th Dimention - Allen Webster
*
* 20.11.2015
*
* DLL loader declarations for 4coder
*
*/
// TOP
// TODO(allen):
// Check the relocation table, if it contains anything that
// is platform specific generate an error to avoid calling
// into invalid code.
i32
dll_compare(char *a, char *b, i32 len){
i32 result;
char *e;
result = 0;
e = a + len;
for (;a < e && *a == *b; ++a, ++b);
if (a < e){
if (*a < *b) result = -1;
else result = 1;
}
return(result);
}
enum DLL_Error{
dll_err_too_small_for_header = 1,
dll_err_wrong_MZ_signature,
dll_err_wrong_DOS_error,
dll_err_wrong_PE_signature,
dll_err_unrecognized_bit_signature,
};
b32
dll_parse_headers(Data file, DLL_Data *dll, i32 *error){
b32 result;
i32 pe_offset;
i32 read_pos;
result = 1;
if (file.size <= sizeof(DOS_Header) + DOS_error_size){
if (error) *error = dll_err_too_small_for_header;
result = 0;
goto dll_parse_end;
}
dll->dos_header = (DOS_Header*)file.data;
if (dll_compare(dll->dos_header->signature, "MZ", 2) != 0){
if (error) *error = dll_err_wrong_MZ_signature;
result = 0;
goto dll_parse_end;
}
if (file.size <= DOS_error_offset + DOS_error_size){
if (error) *error = dll_err_too_small_for_header;
result = 0;
goto dll_parse_end;
}
if (dll_compare((char*)(file.data + DOS_error_offset), DOS_error_message,
sizeof(DOS_error_message) - 1) != 0){
if (error) *error = dll_err_wrong_DOS_error;
result = 0;
goto dll_parse_end;
}
pe_offset = dll->dos_header->e_lfanew;
read_pos = pe_offset;
if (file.size <= read_pos + PE_header_size){
if (error) *error = dll_err_too_small_for_header;
result = 0;
goto dll_parse_end;
}
if (dll_compare((char*)(file.data + read_pos),
PE_header, PE_header_size) != 0){
if (error) *error = dll_err_wrong_PE_signature;
result = 0;
goto dll_parse_end;
}
read_pos += PE_header_size;
if (file.size <= read_pos + sizeof(COFF_Header)){
if (error) *error = dll_err_too_small_for_header;
result = 0;
goto dll_parse_end;
}
dll->coff_header = (COFF_Header*)(file.data + read_pos);
read_pos += sizeof(COFF_Header);
if (file.size <= read_pos + dll->coff_header->size_of_optional_header){
if (error) *error = dll_err_too_small_for_header;
result = 0;
goto dll_parse_end;
}
dll->opt_header_32 = (PE_Opt_Header_32Bit*)(file.data + read_pos);
dll->opt_header_64 = (PE_Opt_Header_64Bit*)(file.data + read_pos);
read_pos += dll->coff_header->size_of_optional_header;
if (dll->opt_header_32->signature != bitsig_32bit &&
dll->opt_header_32->signature != bitsig_64bit){
if (error) *error = dll_err_unrecognized_bit_signature;
result = 0;
goto dll_parse_end;
}
if (dll->opt_header_32->signature == bitsig_32bit) dll->is_64bit = 0;
else dll->is_64bit = 1;
dll->section_defs = (PE_Section_Definition*)(file.data + read_pos);
dll_parse_end:
return(result);
}
i32
dll_total_loaded_size(DLL_Data *dll){
COFF_Header *coff_header;
PE_Section_Definition *section_def;
i32 result, section_end, i;
coff_header = dll->coff_header;
section_def = dll->section_defs;
result = 0;
for (i = 0; i < coff_header->number_of_sections; ++i, ++section_def){
section_end = section_def->loaded_location + section_def->loaded_size;
if (section_end > result){
result = section_end;
}
}
return(result);
}
b32
dll_perform_reloc(DLL_Loaded *loaded){
Data img;
byte *base;
Relocation_Block_Header *header;
Relocation_Block_Entry *entry;
Data_Directory *data_directory;
u32 cursor;
u32 bytes_in_table;
u32 block_end;
u32 type;
u32 offset;
b32 result;
b32 highadj_stage;
u64 dif64;
result = 1;
img = loaded->img;
if (loaded->is_64bit){
data_directory = loaded->opt_header_64->data_directory;
dif64 = ((u64)img.data - (u64)loaded->opt_header_64->image_base);
}
else{
data_directory = loaded->opt_header_32->data_directory;
dif64 = ((u64)img.data - (u64)loaded->opt_header_32->image_base);
}
data_directory += image_dir_base_reloc_table;
base = img.data + data_directory->virtual_address;
bytes_in_table = data_directory->size;
highadj_stage = 1;
for (cursor = 0; cursor < bytes_in_table;){
header = (Relocation_Block_Header*)(base + cursor);
block_end = cursor + header->block_size;
cursor += sizeof(Relocation_Block_Header);
for (;cursor < block_end;){
entry = (Relocation_Block_Entry*)(base + cursor);
cursor += sizeof(Relocation_Block_Entry);
type = (u32)(entry->entry & reloc_entry_type_mask) >> reloc_entry_type_shift;
offset = (u32)(entry->entry & reloc_entry_offset_mask) + header->page_base_offset;
switch (type){
case image_base_absolute: break;
case image_base_high:
case image_base_low:
case image_base_highlow:
case image_base_highadj:
case image_base_arm_mov32a:
case image_base_arm_mov32t:
case image_base_mips_jmpaddr16:
result = 0;
goto dll_reloc_end;
case image_base_dir64:
*(u64*)(img.data + offset) += dif64;
break;
}
}
}
dll_reloc_end:
return(result);
}
b32
dll_load_sections(Data img, DLL_Loaded *loaded,
Data file, DLL_Data *dll){
COFF_Header *coff_header;
PE_Section_Definition *section_def;
u32 header_size;
u32 size;
u32 i;
coff_header = dll->coff_header;
section_def = dll->section_defs;
header_size =
(u32)((byte*)(section_def + coff_header->number_of_sections) - file.data);
memcpy(img.data, file.data, header_size);
memset(img.data + header_size, 0, img.size - header_size);
for (i = 0; i < coff_header->number_of_sections; ++i, ++section_def){
size = section_def->loaded_size;
if (size > section_def->disk_size)
size = section_def->disk_size;
memcpy(img.data + section_def->loaded_location,
file.data + section_def->disk_location,
size);
if (dll_compare(section_def->name, ".text", 5) == 0){
loaded->text_start = section_def->loaded_location;
loaded->text_size = section_def->loaded_size;
}
}
return(1);
}
void
dll_load(Data img, DLL_Loaded *loaded, Data file, DLL_Data *dll){
Data_Directory *export_dir;
dll_load_sections(img, loaded, file, dll);
loaded->img = img;
loaded->dos_header = (DOS_Header*)((byte*)img.data + ((byte*)dll->dos_header - file.data));
loaded->coff_header = (COFF_Header*)((byte*)img.data + ((byte*)dll->coff_header - file.data));
loaded->opt_header_32 = (PE_Opt_Header_32Bit*)
((byte*)img.data + ((byte*)dll->opt_header_32 - file.data));
loaded->opt_header_64 = (PE_Opt_Header_64Bit*)
((byte*)img.data + ((byte*)dll->opt_header_64 - file.data));
loaded->section_defs = (PE_Section_Definition*)
((byte*)img.data + ((byte*)dll->section_defs - file.data));
loaded->is_64bit = dll->is_64bit;
if (dll->is_64bit){
export_dir = dll->opt_header_64->data_directory;
}
else{
export_dir = dll->opt_header_32->data_directory;
}
export_dir += image_dir_entry_export;
loaded->export_start = export_dir->virtual_address;
dll_perform_reloc(loaded);
}
void*
dll_load_function(DLL_Loaded *dll, char *func_name, i32 size){
Data img;
DLL_Export_Directory_Table *export_dir;
DLL_Export_Address *address_ptr;
DLL_Export_Name *name_ptr;
void *result;
u32 count, i;
u32 result_offset;
u32 ordinal;
img = dll->img;
export_dir = (DLL_Export_Directory_Table*)(img.data + dll->export_start);
count = export_dir->number_of_name_pointers;
name_ptr = (DLL_Export_Name*)(img.data + export_dir->name_pointer_offset);
result = 0;
for (i = 0; i < count; ++i, ++name_ptr){
if (dll_compare((char*)img.data + name_ptr->name_offset,
func_name, size) == 0){
ordinal = ((u16*)(img.data + export_dir->ordinal_offset))[i];
#if 0
// NOTE(allen): The MS docs say to do this, but
// it appears to just be downright incorrect.
ordinal -= export_dir->ordinal_base;
#endif
address_ptr = (DLL_Export_Address*)(img.data + export_dir->address_offset);
address_ptr += ordinal;
result_offset = address_ptr->export_offset;
result = (img.data + result_offset);
break;
}
}
return(result);
}
#define MachineCase(x) case x: result = #x; *len = sizeof(#x) - 1; break
char*
dll_machine_type_str(u16 machine, i32 *len){
char *result;
i32 extra;
if (!len) len = &extra;
result = 0;
switch (machine){
MachineCase(intel_i386);
MachineCase(intel_i860);
MachineCase(mips_r3000);
MachineCase(mips_little_endian);
MachineCase(mips_r10000);
MachineCase(old_alpha_axp);
MachineCase(alpha_axp);
MachineCase(hitachi_sh3);
MachineCase(hitachi_sh3_dsp);
MachineCase(hitachi_sh4);
MachineCase(hitachi_sh5);
MachineCase(arm_little_endian);
MachineCase(thumb);
MachineCase(matsushita_am33);
MachineCase(power_pc_little_endian);
MachineCase(power_pc_with_floating);
MachineCase(intel_ia64);
MachineCase(mips16);
MachineCase(motorola_68000_series);
MachineCase(alpha_axp_64_bit);
MachineCase(mips_with_fpu);
MachineCase(mips16_with_fpu);
MachineCase(eft_byte_code);
MachineCase(amd_amd64);
MachineCase(mitsubishi_m32r_little_endian);
MachineCase(clr_pure_msil);
}
return(result);
}
#undef MachineCase
// BOTTOM

View File

@ -0,0 +1,441 @@
/*
* Mr. 4th Dimention - Allen Webster
*
* 20.11.2015
*
* DLL loader declarations for 4coder
*
*/
// TOP
struct DOS_Header {
char signature[2];
i16 lastsize;
i16 nblocks;
i16 nreloc;
i16 hdrsize;
i16 minalloc;
i16 maxalloc;
i16 ss;
i16 sp;
i16 checksum;
i16 ip;
i16 cs;
i16 relocpos;
i16 noverlay;
i16 reserved1[4];
i16 oem_id;
i16 oem_info;
i16 reserved2[10];
i32 e_lfanew;
};
enum Target_Machine_Code{
intel_i386 = 0x14C,
intel_i860 = 0x14D,
mips_r3000 = 0x162,
mips_little_endian = 0x166,
mips_r10000 = 0x168,
old_alpha_axp = 0x183,
alpha_axp = 0x184,
hitachi_sh3 = 0x1a2,
hitachi_sh3_dsp = 0x1a3,
hitachi_sh4 = 0x1a6,
hitachi_sh5 = 0x1a8,
arm_little_endian = 0x1c0,
thumb = 0x1c2,
matsushita_am33 = 0x1d3,
power_pc_little_endian = 0x1f0,
power_pc_with_floating = 0x1f1,
intel_ia64 = 0x200,
mips16 = 0x266,
motorola_68000_series = 0x268,
alpha_axp_64_bit = 0x284,
mips_with_fpu = 0x366,
mips16_with_fpu = 0x466,
eft_byte_code = 0xebc,
amd_amd64 = 0x8664,
mitsubishi_m32r_little_endian = 0x9041,
clr_pure_msil = 0xc0ee
};
#define file_is_exe 0x2
#define file_is_non_reloctable 0x200
#define file_is_dll 0x2000
struct COFF_Header{
u16 machine;
u16 number_of_sections;
u32 time_date_stamp;
u32 pointer_to_symbol_table;
u32 number_of_symbols;
u16 size_of_optional_header;
u16 characteristics;
};
struct Data_Directory{
u32 virtual_address;
u32 size;
};
// This version is untested
struct PE_Opt_Header_32Bit{
// Universal Portion
i16 signature;
i8 major_linker_version;
i8 minor_linker_version;
i32 size_of_code;
i32 size_of_initialized_data;
i32 size_of_uninitialized_data;
i32 address_of_entry_point;
i32 base_of_code;
i32 base_of_data;
// Windows Portion
i32 image_base;
i32 section_alignment;
i32 file_alignment;
i16 major_OS_version;
i16 minor_OS_version;
i16 major_image_version;
i16 minor_image_version;
i16 major_subsystem_version;
i16 minor_subsystem_version;
i32 reserved;
i32 size_of_image;
i32 size_of_headers;
i32 checksum;
i16 subsystem;
i16 DLL_characteristics;
i32 size_of_stack_reserve;
i32 size_of_stack_commit;
i32 size_of_heap_reserve;
i32 size_of_heap_commit;
i32 loader_flags;
i32 number_of_rva_and_sizes;
Data_Directory data_directory[16];
};
struct PE_Opt_Header_64Bit{
// Universal Portion
u16 signature;
u8 major_linker_version;
u8 minor_linker_version;
u32 size_of_code;
u32 size_of_initialized_data;
u32 size_of_uninitialized_data;
u32 address_of_entry_point;
u32 base_of_code;
// Windows Portion
u64 image_base;
u32 section_alignment;
u32 file_alignment;
u16 major_OS_version;
u16 minor_OS_version;
u16 major_image_version;
u16 minor_image_version;
u16 major_subsystem_version;
u16 minor_subsystem_version;
u32 reserved;
u32 size_of_image;
u32 size_of_headers;
u32 checksum;
u16 subsystem;
u16 DLL_characteristics;
u64 size_of_stack_reserve;
u64 size_of_stack_commit;
u64 size_of_heap_reserve;
u64 size_of_heap_commit;
u32 loader_flags;
u32 number_of_rva_and_sizes;
Data_Directory data_directory[16];
};
#define bitsig_32bit 267
#define bitsig_64bit 523
#define image_dir_entry_export 0
#define image_dir_entry_import 1
#define image_dir_entry_resource 2
#define image_dir_base_reloc_table 5
#define image_dir_entry_bound_import 11
struct PE_Section_Definition{
char name[8];
u32 loaded_size;
u32 loaded_location;
u32 disk_size;
u32 disk_location;
u32 disk_relocs;
u32 reserved1;
u16 number_of_relocs;
u16 reserved2;
u32 flags;
};
#define image_scn_type_no_pad 0x00000008
#define image_scn_cnt_code 0x00000020
#define image_scn_cnt_initialized_data 0x00000040
#define image_scn_cnt_uninitialized_data 0x00000080
#define image_scn_lnk_other 0x00000100
#define image_scn_lnk_info 0x00000200
#define image_scn_lnk_remove 0x00000800
#define image_scn_lnk_comdat 0x00001000
#define image_scn_no_defer_spec_exc 0x00004000
#define image_scn_gprel 0x00008000
#define image_scn_mem_fardata 0x00008000
#define image_scn_mem_purgeable 0x00020000
#define image_scn_mem_16BIT 0x00020000
#define image_scn_mem_locked 0x00040000
#define image_scn_mem_preload 0x00080000
#define image_scn_align_1bytes 0x00100000
#define image_scn_align_2bytes 0x00200000
#define image_scn_align_4bytes 0x00300000
#define image_scn_align_8bytes 0x00400000
#define image_scn_align_16bytes 0x00500000
#define image_scn_align_32bytes 0x00600000
#define image_scn_align_64bytes 0x00700000
#define image_scn_align_128bytes 0x00800000
#define image_scn_align_256bytes 0x00900000
#define image_scn_align_512bytes 0x00A00000
#define image_scn_align_1024bytes 0x00B00000
#define image_scn_align_2048bytes 0x00C00000
#define image_scn_align_4096bytes 0x00D00000
#define image_scn_align_8192bytes 0x00E00000
#define image_scn_align_mask 0x00F00000
#define image_scn_lnk_nreloc_ovfl 0x01000000
#define image_scn_mem_discardable 0x02000000
#define image_scn_mem_not_cached 0x04000000
#define image_scn_mem_not_paged 0x08000000
#define image_scn_mem_shared 0x10000000
#define image_scn_mem_execute 0x20000000
#define image_scn_mem_read 0x40000000
#define image_scn_mem_write 0x80000000
#pragma pack(push, 1)
struct COFF_Relocation{
u32 virtual_address;
u32 symbol_table_index;
u16 type;
};
#pragma pack(pop)
enum Image_Rel_Amd64{
image_rel_amd64_absolute = 0x00,
image_rel_amd64_addr64 = 0x01,
image_rel_amd64_addr32 = 0x02,
image_rel_amd64_addr32nb = 0x03,
image_rel_amd64_rel32 = 0x04,
image_rel_amd64_rel32_1 = 0x05,
image_rel_amd64_rel32_2 = 0x06,
image_rel_amd64_rel32_3 = 0x07,
image_rel_amd64_rel32_4 = 0x08,
image_rel_amd64_rel32_5 = 0x09,
image_rel_amd64_section = 0x0A,
image_rel_amd64_secrel = 0x0B,
image_rel_amd64_secrel7 = 0x0C,
image_rel_amd64_token = 0x0D,
image_rel_amd64_srel32 = 0x0E,
image_rel_amd64_pair = 0x0F,
image_rel_amd64_sspan32 = 0x10
};
enum Image_Rel_Arm{
image_rel_arm_absolute = 0x0,
image_rel_arm_addr32 = 0x1,
image_rel_arm_addr32nb = 0x2,
image_rel_arm_branch24 = 0x3,
image_rel_arm_branch11 = 0x4,
image_rel_arm_token = 0x5,
image_rel_arm_blx24 = 0x6,
image_rel_arm_blx11 = 0x7,
image_rel_arm_section = 0x8,
image_rel_arm_secrel = 0x9,
image_rel_arm_mov32a = 0xA,
image_rel_arm_mov32t = 0xB,
image_rel_arm_branch20t = 0xC,
image_rel_arm_branch24t = 0xD,
image_rel_arm_blx32t = 0xE
};
enum Image_Rel_Arm64{
image_rel_arm64_absolute = 0x0,
image_rel_arm64_addr32 = 0x1,
image_rel_arm64_addr32nb = 0x2,
image_rel_arm64_branch26 = 0x3,
image_rel_arm64_pagebase_rel21 = 0x4,
image_rel_arm64_rel21 = 0x5,
image_rel_arm64_pageoffset_12a = 0x6,
image_rel_arm64_pageoffset_12l = 0x7,
image_rel_arm64_secrel = 0x8,
image_rel_arm64_secrel_low12a = 0x9,
image_rel_arm64_secrel_high12a = 0xA,
image_rel_arm64_secrel_low12l = 0xB,
image_rel_arm64_token = 0xC,
image_rel_arm64_section = 0xD,
image_rel_arm64_addr64 = 0xE
};
// NOTE(allen):
// skipped Hitachi SuperH
// skiiped IBM PowerPC
enum Image_Rel_i386{
image_rel_i386_absolute = 0x0,
image_rel_i386_dir16 = 0x1,
image_rel_i386_rel16 = 0x2,
image_rel_i386_dir32 = 0x3,
image_rel_i386_dir32nb = 0x4,
image_rel_i386_seg12 = 0x5,
image_rel_i386_section = 0x6,
image_rel_i386_secrel = 0x7,
image_rel_i386_token = 0x8,
image_rel_i386_secrel7 = 0x9,
image_rel_i386_rel32 = 0xA
};
// NOTE(allen):
// skipped ia64
// skipped MIPS
// skiiped Mitsubishi
struct Relocation_Block_Header{
u32 page_base_offset;
u32 block_size;
};
#define reloc_entry_type_mask 0xF000
#define reloc_entry_type_shift 12
#define reloc_entry_offset_mask 0x0FFF
struct Relocation_Block_Entry{
u16 entry;
};
enum DLL_Relocation_Type{
image_base_absolute,
// nothing
image_base_high,
// add high 16 bits of diff to 16 bits at offset
image_base_low,
// add low 16 bits of diff to 16 bits at offset
image_base_highlow,
// adds all 32 bits to 32 bits at offset
image_base_highadj,
// consumes two slots: high 16 bits at location, low 16 bits at next location
image_base_arm_mov32a,
// mips: jump instruction; arm: MOVW+MOVT
image_base_reserved1,
image_base_arm_mov32t,
// MOVW+MOVT in Thumb mode
image_base_reserved2,
image_base_mips_jmpaddr16,
// mips16 jump instruction
image_base_dir64
// adds to 64 bits field
};
struct DLL_Data{
DOS_Header *dos_header;
COFF_Header *coff_header;
PE_Opt_Header_32Bit *opt_header_32;
PE_Opt_Header_64Bit *opt_header_64;
PE_Section_Definition *section_defs;
b32 is_64bit;
};
struct DLL_Loaded{
DOS_Header *dos_header;
COFF_Header *coff_header;
PE_Opt_Header_32Bit *opt_header_32;
PE_Opt_Header_64Bit *opt_header_64;
PE_Section_Definition *section_defs;
b32 is_64bit;
Data img;
u32 export_start;
u32 text_start;
u32 text_size;
};
struct DLL_Export_Directory_Table{
u32 export_flags;
u32 time_date_stamp;
u16 major_version;
u16 minor_version;
u32 name_offset;
u32 ordinal_base;
u32 number_of_addresses;
u32 number_of_name_pointers;
u32 address_offset;
u32 name_pointer_offset;
u32 ordinal_offset;
};
struct DLL_Export_Address{
u32 export_offset;
};
struct DLL_Export_Name{
u32 name_offset;
};
struct DLL_Export_Ordinal{
u16 ordinal;
};
struct DLL_Debug_Entry{
u32 characteristics;
u32 time_date_stamp;
u16 major_version;
u16 minor_version;
u32 type;
u32 size_of_data;
u32 offset_of_data;
u32 disk_offset_of_data;
} thingy;
enum DLL_Debug_Type{
img_dbg_type_unknown,
img_dbg_type_coff,
img_dbg_type_codeview,
img_dbg_type_fpo,
img_dbg_type_misc,
img_dbg_type_exception,
img_dbg_type_fixup,
img_dbg_type_omap_to_src,
img_dbg_type_omap_from_src
};
char DOS_error_message[] = "This program cannot be run in DOS mode.";
i32 DOS_error_offset = 0x4E;
i32 DOS_error_size = sizeof(DOS_error_message) - 1;
char PE_header[] = {'P', 'E', 0, 0};
i32 PE_header_size = 4;
// BOTTOM

View File

@ -0,0 +1,234 @@
/*
* Mr. 4th Dimention - Allen Webster
*
* 9.12.2015
*
* Exchange stuff
*
*/
// TOP
internal void
ex__file_insert(File_Slot *pos, File_Slot *file){
pos->next->prev = file;
file->next = pos->next;
pos->next = file;
file->prev = pos;
}
internal void
ex__file_remove(File_Slot *file){
file->next->prev = file->prev;
file->prev->next = file->next;
}
internal void
ex__check_file(File_Slot *pos){
File_Slot *file = pos;
Assert(pos == pos->next->prev);
for (pos = pos->next;
file != pos;
pos = pos->next){
Assert(pos == pos->next->prev);
}
}
internal void
ex__check(File_Exchange *file_exchange){
ex__check_file(&file_exchange->available);
ex__check_file(&file_exchange->active);
ex__check_file(&file_exchange->free_list);
}
internal void
ex__clear(File_Slot *file){
file->data = 0;
file->size = 0;
file->max = 0;
file->flags = 0;
}
internal File_Slot*
ex__get_file(Exchange *exchange){
File_Exchange *files = &exchange->file;
File_Slot *file;
++files->num_active;
file = files->available.next;
ex__file_remove(file);
ex__clear(file);
ex__file_insert(&files->active, file);
ex__check(files);
return file;
}
internal void
ex__set_filename(File_Slot *file, char *filename, int len){
memcpy(file->filename, filename, len);
file->filename[len] = 0;
file->filename_len = len;
}
internal i32
exchange_request_file(Exchange *exchange, char *filename, int len){
File_Exchange *files = &exchange->file;
i32 result = 0;
if (len+1 < FileNameMax){
if (files->num_active < files->max){
File_Slot *file = ex__get_file(exchange);
ex__set_filename(file, filename, len);
file->flags |= FEx_Request;
result = (int)(file - files->files) + 1;
}
}
return result;
}
internal b32
exchange_file_ready(Exchange *exchange, i32 file_id, byte **data, int *size, int *max){
File_Exchange *files = &exchange->file;
b32 result = 0;
if (file_id > 0 && file_id <= files->max){
File_Slot *file = files->files + file_id - 1;
if (file->flags & FEx_Ready){
*data = file->data;
*size = file->size;
*max = file->max;
result = 1;
}
if (file->flags & FEx_Not_Exist){
*data = 0;
*size = 0;
*max = 0;
result = 1;
}
}
return result;
}
internal b32
exchange_file_does_not_exist(Exchange *exchange, i32 file_id){
File_Exchange *files = &exchange->file;
b32 result = 1;
File_Slot *slot;
if (file_id > 0 && file_id <= files->max){
slot = files->files + file_id - 1;
if (!(slot->flags & FEx_Not_Exist)){
result = 0;
}
}
return result;
}
internal i32
exchange_save_file(Exchange *exchange, char *filename, int len,
byte *data, int size, int max){
File_Exchange *files = &exchange->file;
i32 result = 0;
if (len+1 < FileNameMax){
if (files->num_active < files->max){
File_Slot *file = ex__get_file(exchange);
ex__set_filename(file, filename, len);
file->flags |= FEx_Save;
file->data = data;
file->size = size;
file->max = max;
result = (int)(file - files->files) + 1;
}
}
return result;
}
internal b32
exchange_file_save_complete(Exchange *exchange, i32 file_id, byte **data, int *size, int *max, int *failed){
File_Exchange *files = &exchange->file;
b32 result = 0;
if (file_id > 0 && file_id <= files->max){
File_Slot *file = files->files + file_id - 1;
if (file->flags & FEx_Save_Complete || file->flags & FEx_Save_Failed){
*data = file->data;
*size = file->size;
*max = file->max;
result = 1;
*failed = (file->flags & FEx_Save_Complete)?(1):(0);
}
}
return result;
}
internal char*
exchange_file_filename(Exchange *exchange, i32 file_id, i32 *size = 0){
File_Exchange *files = &exchange->file;
char *result = 0;
if (file_id > 0 && file_id <= files->max){
File_Slot *file = files->files + file_id - 1;
result = file->filename;
if (size) *size = file->filename_len;
}
return result;
}
internal void
exchange_free_file(Exchange *exchange, i32 file_id){
File_Exchange *files = &exchange->file;
if (file_id > 0 && file_id <= files->max){
File_Slot *file = files->files + file_id - 1;
ex__file_remove(file);
ex__file_insert(&files->free_list, file);
ex__check(files);
}
}
internal void
exchange_clear_file(Exchange *exchange, i32 file_id){
File_Exchange *files = &exchange->file;
if (file_id > 0 && file_id <= files->max){
File_Slot *file = files->files + file_id - 1;
ex__clear(file);
}
}
internal b32
queue_job_is_pending(Work_Queue *queue, u32 job_id){
b32 result;
u32 job_index;
Full_Job_Data *full_job;
job_index = job_id % QUEUE_WRAP;
full_job = queue->jobs + job_index;
Assert(full_job->id == job_id);
result = 0;
if (full_job->running_thread != 0){
result = 1;
}
return(result);
}
// BOTTOM

View File

@ -0,0 +1,530 @@
/*
* Mr. 4th Dimention - Allen Webster
*
* 20.02.2016
*
* File editing view for 4coder
*
*/
// TOP
#include "buffer/4coder_shared.cpp"
#if BUFFER_EXPERIMENT_SCALPEL == 0
#include "buffer/4coder_golden_array.cpp"
#define Buffer_Type Buffer
#elif BUFFER_EXPERIMENT_SCALPEL == 1
#include "buffer/4coder_gap_buffer.cpp"
#define Buffer_Type Gap_Buffer
#elif BUFFER_EXPERIMENT_SCALPEL == 2
#include "buffer/4coder_multi_gap_buffer.cpp"
#define Buffer_Type Multi_Gap_Buffer
#else
#include "buffer/4coder_rope_buffer.cpp"
#define Buffer_Type Rope_Buffer
#endif
#include "buffer/4coder_buffer_abstract.cpp"
enum Edit_Type{
ED_NORMAL,
ED_REVERSE_NORMAL,
ED_UNDO,
ED_REDO,
};
struct Edit_Step{
Edit_Type type;
union{
struct{
b32 can_merge;
Buffer_Edit edit;
i32 pre_pos;
i32 post_pos;
i32 next_block, prev_block;
};
struct{
i32 first_child;
i32 inverse_first_child;
i32 inverse_child_count;
i32 special_type;
};
};
i32 child_count;
};
struct Edit_Stack{
u8 *strings;
i32 size, max;
Edit_Step *edits;
i32 edit_count, edit_max;
};
struct Small_Edit_Stack{
u8 *strings;
i32 size, max;
Buffer_Edit *edits;
i32 edit_count, edit_max;
};
struct Undo_Data{
Edit_Stack undo;
Edit_Stack redo;
Edit_Stack history;
Small_Edit_Stack children;
i32 history_block_count, history_head_block;
i32 edit_history_cursor;
b32 current_block_normal;
};
struct Text_Effect{
i32 start, end;
u32 color;
i32 tick_down, tick_max;
};
// NOTE(allen): The Editing_File struct is now divided into two
// parts. Variables in the Settings part can be set even when the
// file is still streaming in, and all operations except for the
// initial allocation of the file.
struct Editing_File_Settings{
i32 base_map_id;
i32 dos_write_mode;
b32 unwrapped_lines;
b8 tokens_exist;
b8 is_initialized;
b8 unimportant;
b8 read_only;
};
// NOTE(allen): This part of the Editing_File is cleared whenever
// the contents of the file is set.
struct Editing_File_State{
b32 is_dummy;
b32 is_loading;
i16 font_id;
Buffer_Type buffer;
i32 cursor_pos;
Undo_Data undo;
Cpp_Token_Stack token_stack;
Cpp_Token_Stack swap_stack;
u32 lex_job;
b32 tokens_complete;
b32 still_lexing;
Text_Effect paste_effect;
u64 last_4ed_write_time;
u64 last_4ed_edit_time;
u64 last_sys_write_time;
};
struct Editing_File_Preload{
i32 start_line;
};
struct Editing_File_Name{
char live_name_[256];
String live_name;
char source_path_[256];
char extension_[16];
String source_path;
String extension;
};
struct File_Node{
File_Node *next, *prev;
};
struct Editing_File{
File_Node node;
Editing_File_Settings settings;
union{
Editing_File_State state;
Editing_File_Preload preload;
};
Editing_File_Name name;
};
struct File_Table_Entry{
String name;
u32 hash;
i32 id;
};
struct File_Table{
File_Table_Entry *table;
i32 count, max;
};
internal u32
get_file_hash(String name){
u32 x = 5381;
int i = 0;
char c;
while (i < name.size){
c = name.str[i++];
x = ((x << 5) + x) + c;
}
return x;
}
internal b32
table_add(File_Table *table, String name, i32 id){
Assert(table->count * 3 < table->max * 2);
File_Table_Entry entry, e;
i32 i;
entry.name = name;
entry.id = id;
entry.hash = get_file_hash(name);
i = entry.hash % table->max;
while ((e = table->table[i]).name.str){
if (e.hash == entry.hash && match(e.name, entry.name)){
return 1;
}
i = (i + 1) % table->max;
}
table->table[i] = entry;
++table->count;
return 0;
}
internal b32
table_find_pos(File_Table *table, String name, i32 *index){
File_Table_Entry e;
i32 i;
u32 hash;
hash = get_file_hash(name);
i = hash % table->max;
while ((e = table->table[i]).name.size){
if (e.name.str && e.hash == hash && match(e.name, name)){
*index = i;
return 1;
}
i = (i + 1) % table->max;
}
return 0;
}
inline b32
table_find(File_Table *table, String name, i32 *id){
i32 pos;
b32 r = table_find_pos(table, name, &pos);
if (r) *id = table->table[pos].id;
return r;
}
inline b32
table_remove(File_Table *table, String name){
i32 pos;
b32 r = table_find_pos(table, name, &pos);
if (r){
table->table[pos].name.str = 0;
--table->count;
}
return r;
}
struct Working_Set{
Editing_File *files;
i32 file_count, file_max;
File_Node free_sentinel;
File_Node used_sentinel;
File_Table table;
String clipboards[64];
i32 clipboard_size, clipboard_max_size;
i32 clipboard_current, clipboard_rolling;
};
// Hot Directory
struct Hot_Directory{
String string;
File_List file_list;
char slash;
};
internal void
hot_directory_clean_end(Hot_Directory *hot_directory){
String *str = &hot_directory->string;
if (str->size != 0 && str->str[str->size-1] != hot_directory->slash){
str->size = reverse_seek_slash(*str) + 1;
str->str[str->size] = 0;
}
}
internal i32
hot_directory_quick_partition(File_Info *infos, i32 start, i32 pivot){
File_Info *p = infos + pivot;
File_Info *a = infos + start;
for (i32 i = start; i < pivot; ++i, ++a){
i32 comp = 0;
comp = p->folder - a->folder;
if (comp == 0) comp = compare(a->filename, p->filename);
if (comp < 0){
Swap(*a, infos[start]);
++start;
}
}
Swap(*p, infos[start]);
return start;
}
internal void
hot_directory_quick_sort(File_Info *infos, i32 start, i32 pivot){
i32 mid = hot_directory_quick_partition(infos, start, pivot);
if (start < mid-1) hot_directory_quick_sort(infos, start, mid-1);
if (mid+1 < pivot) hot_directory_quick_sort(infos, mid+1, pivot);
}
inline void
hot_directory_fixup(Hot_Directory *hot_directory, Working_Set *working_set){
File_List *files = &hot_directory->file_list;
if (files->count >= 2)
hot_directory_quick_sort(files->infos, 0, files->count - 1);
}
inline void
hot_directory_set(System_Functions *system, Hot_Directory *hot_directory,
String str, Working_Set *working_set){
b32 success = copy_checked(&hot_directory->string, str);
terminate_with_null(&hot_directory->string);
if (success){
if (str.size > 0){
system->set_file_list(&hot_directory->file_list, str);
}
else{
system->set_file_list(&hot_directory->file_list, make_string((char*)1, 0));
}
}
hot_directory_fixup(hot_directory, working_set);
}
inline void
hot_directory_reload(System_Functions *system, Hot_Directory *hot_directory, Working_Set *working_set){
system->set_file_list(&hot_directory->file_list, hot_directory->string);
hot_directory_fixup(hot_directory, working_set);
}
internal void
hot_directory_init(Hot_Directory *hot_directory, String base, String dir, char slash){
hot_directory->string = base;
hot_directory->string.str[255] = 0;
hot_directory->string.size = 0;
copy(&hot_directory->string, dir);
append(&hot_directory->string, slash);
hot_directory->slash = slash;
}
struct Hot_Directory_Match{
String filename;
b32 is_folder;
};
internal b32
filename_match(String query, Absolutes *absolutes, String filename, b32 case_sensitive){
b32 result;
result = (query.size == 0);
replace_char(query, '\\', '/');
replace_char(filename, '\\', '/');
if (!result) result = wildcard_match(absolutes, filename, case_sensitive);
return result;
}
internal Hot_Directory_Match
hot_directory_first_match(Hot_Directory *hot_directory,
String str,
b32 include_files,
b32 exact_match,
b32 case_sensitive){
Hot_Directory_Match result = {};
replace_char(str, '\\', '/');
Absolutes absolutes;
if (!exact_match)
get_absolutes(str, &absolutes, 1, 1);
File_List *files = &hot_directory->file_list;
File_Info *info, *end;
end = files->infos + files->count;
for (info = files->infos; info != end; ++info){
String filename = info->filename;
b32 is_match = 0;
if (exact_match){
if (case_sensitive){
if (match(filename, str)) is_match = 1;
}
else{
if (match_unsensitive(filename, str)) is_match = 1;
}
}
else{
if (filename_match(str, &absolutes, filename, case_sensitive)) is_match = 1;
}
if (is_match){
result.is_folder = info->folder;
result.filename = filename;
break;
}
}
return result;
}
enum File_Sync_State{
SYNC_GOOD,
SYNC_BEHIND_OS,
SYNC_UNSAVED
};
inline File_Sync_State
buffer_get_sync(Editing_File *file){
File_Sync_State result = SYNC_GOOD;
if (file->state.last_4ed_write_time != file->state.last_sys_write_time)
result = SYNC_BEHIND_OS;
else if (file->state.last_4ed_edit_time > file->state.last_sys_write_time)
result = SYNC_UNSAVED;
return result;
}
inline b32
buffer_needs_save(Editing_File *file){
b32 result = 0;
if (file->settings.unimportant == 0)
if (buffer_get_sync(file) == SYNC_UNSAVED)
result = 1;
return(result);
}
inline b32
file_is_ready(Editing_File *file){
b32 result = 0;
if (file && file->state.is_loading == 0){
result = 1;
}
return(result);
}
inline Editing_File*
working_set_contains(Working_Set *working, String filename){
Editing_File *result = 0;
i32 id;
replace_char(filename, '\\', '/');
if (table_find(&working->table, filename, &id)){
if (id >= 0 && id <= working->file_max){
result = working->files + id;
}
}
return (result);
}
// TODO(allen): Pick better first options.
internal Editing_File*
working_set_lookup_file(Working_Set *working_set, String string){
Editing_File *file = 0;
replace_char(string, '\\', '/');
{
File_Node *node, *used_nodes;
used_nodes = &working_set->used_sentinel;
for (dll_items(node, used_nodes)){
file = (Editing_File*)node;
if (string.size == 0 || match(string, file->name.live_name)){
break;
}
}
if (node == used_nodes) file = 0;
}
if (!file){
File_Node *node, *used_nodes;
used_nodes = &working_set->used_sentinel;
for (dll_items(node, used_nodes)){
file = (Editing_File*)node;
if (string.size == 0 || has_substr(file->name.live_name, string)){
break;
}
}
if (node == used_nodes) file = 0;
}
return (file);
}
struct Get_File_Result{
Editing_File *file;
i32 index;
};
internal Get_File_Result
working_set_get_available_file(Working_Set *working_set){
Get_File_Result result = {};
File_Node *node;
if (working_set->file_count < working_set->file_max){
node = working_set->free_sentinel.next;
Assert(node != &working_set->free_sentinel);
result.file = (Editing_File*)node;
result.index = (i32)(result.file - working_set->files);
++working_set->file_count;
dll_remove(node);
*result.file = {};
dll_insert(&working_set->used_sentinel, node);
}
return result;
}
inline void
working_set_free_file(Working_Set *working_set, Editing_File *file){
file->state.is_dummy = 1;
dll_remove(&file->node);
dll_insert(&working_set->free_sentinel, &file->node);
--working_set->file_count;
}
inline Get_File_Result
working_set_get_file(Working_Set *working_set, i32 id, b32 require_active){
Get_File_Result result = {};
if (id > 0 && id <= working_set->file_max){
result.file = working_set->files + id;
result.index = id;
if (result.file->state.is_dummy && require_active){
result.file = 0;
result.index = 0;
}
}
return(result);
}
inline void
file_set_to_loading(Editing_File *file){
file->state = {};
file->settings = {};
file->state.is_loading = 1;
}
// BOTTOM

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,230 @@
/*
* Mr. 4th Dimention - Allen Webster
*
* 18.12.2015
*
* Font set for 4coder
*
*/
// TOP
inline u32
font_hash(String name){
u32 x = 5381;
char *p = name.str;
for (i32 i = 0; i < name.size; ++i, ++p){
x = ((x << 5) + x) ^ (*p);
}
return(x);
}
inline void
font__insert(Font_Slot *pos, Font_Slot *slot){
Font_Slot *nex;
nex = pos->next;
slot->next = nex;
slot->prev = pos;
nex->prev = slot;
pos->next = slot;
}
inline void
font__remove(Font_Slot *slot){
Font_Slot *n, *p;
n = slot->next;
p = slot->prev;
p->next = n;
n->prev = p;
}
internal void
font_set_init(Font_Set *set, Partition *partition, i32 max, i16 live_max){
partition_align(partition, 8);
set->info = push_array(partition, Font_Info, max);
partition_align(partition, 8);
set->entries = push_array(partition, Font_Table_Entry, max);
set->count = 0;
set->max = max;
partition_align(partition, 8);
set->font_block = push_block(partition, live_max*(sizeof(Render_Font) + sizeof(Font_Slot)));
set->free_slots = {};
set->used_slots = {};
dll_init_sentinel(&set->free_slots);
dll_init_sentinel(&set->used_slots);
char *ptr = (char*)set->font_block;
for (i32 i = 0; i < live_max; ++i){
dll_insert(&set->free_slots, (Font_Slot*)ptr);
ptr += sizeof(Font_Slot) + sizeof(Render_Font);
}
set->font_used_flags = push_array(partition, b8, max);
set->live_max = live_max;
}
internal b32
font_set_can_add(Font_Set *set){
b32 result = 0;
if (set->count*8 < set->max*7) result = 1;
return(result);
}
internal void
font_set_add_hash(Font_Set *set, String name, i16 font_id){
Font_Table_Entry entry;
entry.hash = font_hash(name);
entry.name = name;
entry.font_id = font_id;
u32 i, j;
i = entry.hash % set->max;
j = i - 1;
if (i <= 1) j += set->max;
for (; i != j; ++i){
if (i == set->max) i = 0;
if (set->entries[i].font_id == 0){
set->entries[i] = entry;
break;
}
}
Assert(i != j);
}
inline b32
font_set_can_load(Font_Set *set){
b32 result = (set->free_slots.next != &set->free_slots);
return(result);
}
internal void
font_set_load(Partition *partition, Font_Set *set, i16 font_id){
Font_Info *info = get_font_info(set, font_id);
Font_Slot *slot = set->free_slots.next;
Assert(slot != &set->free_slots);
font__remove(slot);
font__insert(&set->used_slots, slot);
Render_Font *font = (Render_Font*)(slot + 1);
set->font_load(font, info->filename.str, info->pt_size, 4);
info->font = font;
slot->font_id = font_id;
}
internal void
font_set_evict_lru(Font_Set *set){
Font_Slot *slot = set->used_slots.prev;
Assert(slot != &set->used_slots);
i16 font_id = slot->font_id;
Font_Info *info = get_font_info(set, font_id);
Assert(((Font_Slot*)info->font) - 1 == slot);
set->release_font(info->font);
info->font = 0;
slot->font_id = 0;
font__remove(slot);
font__insert(&set->free_slots, slot);
}
internal void
font_set_use(Partition *partition, Font_Set *set, i16 font_id){
b8 already_used;
already_used = set->font_used_flags[font_id-1];
if (!already_used){
if (set->used_this_frame < set->live_max){
++set->used_this_frame;
set->font_used_flags[font_id-1] = 1;
already_used = 1;
}
}
if (already_used){
// TODO(allen): optimize if you don't mind!!!!
Font_Info *info = get_font_info(set, font_id);
Font_Slot *slot;
if (info->font == 0){
if (!font_set_can_load(set)){
font_set_evict_lru(set);
}
font_set_load(partition, set, font_id);
}
slot = ((Font_Slot*)info->font) - 1;
font__remove(slot);
font__insert(&set->used_slots, slot);
}
}
internal b32
font_set_add(Partition *partition, Font_Set *set,
String filename, String name, i32 pt_size){
b32 result = 0;
if (font_set_can_add(set)){
i16 font_id = (i16)(++set->count);
Font_Info *info = get_font_info(set, font_id);
info->filename = filename;
info->name = name;
info->pt_size = pt_size;
set->font_info_load(partition, filename.str, pt_size, &info->height, &info->advance);
font_set_add_hash(set, name, font_id);
if (font_set_can_load(set)){
font_set_load(partition, set, font_id);
}
result = 1;
}
return(result);
}
internal b32
font_set_find_pos(Font_Set *set, String name, u32 *position){
b32 result;
u32 hash, i, j;
hash = font_hash(name);
i = hash % set->max;
j = i - 1;
if (j <= 1) j += set->max;
result = 0;
Font_Table_Entry *entry;
for (; i != j; ++i){
if (i == set->max) i = 0;
entry = set->entries + i;
if (entry->hash == hash){
if (match(name, entry->name)){
result = 1;
*position = i;
break;
}
}
}
return(result);
}
internal b32
font_set_extract(Font_Set *set, String name, i16 *font_id){
b32 result;
u32 position;
result = font_set_find_pos(set, name, &position);
if (result){
*font_id = set->entries[position].font_id;
}
return(result);
}
// BOTTOM

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,60 @@
/*
* Mr. 4th Dimention - Allen Webster
*
* 16.05.2015
*
* Fascilities available for development but not intended for shipping.
*
*/
// TOP
#if FRED_INTERNAL == 1
#define ProfileStart_(name, start, counter, hit, thread, n, c)
#define ProfileEnd_(name, start, counter, hit, thread)
#define ProfileMoment_(name, counter, thread)
#if 0
#define ProfileStart(name) char *_pname_##name; i64 _pstart_##name; \
i32 _pcounter_##name; u32 _phit_##name; \
ProfileStart_(_pname_##name, _pstart_##name, _pcounter_##name, \
_phit_##name, system->thread_get_id(thread), \
#name, __COUNTER__)
#define ProfileEnd(name) ProfileEnd_(_pname_##name, _pstart_##name, \
_pcounter_##name, _phit_##name, \
system->thread_get_id(thread))
#define ProfileMoment(name, thread) ProfileMoment_(#name, __COUNTER__, thread)
#define ProfileMomentFunction() ProfileMoment_(__FUNCTION__, __COUNTER__, 0)
#else
#define ProfileStart(name)
#define ProfileEnd(name)
#define ProfileMoment(name)
#define ProfileMomentFunction()
#endif
struct Sys_Bubble : public Bubble{
i32 line_number;
char *file_name;
};
#else
#define ProfileStart(name)
#define ProfileEnd(name)
#define ProfileMoment(name)
#define ProfileMomentFunction()
#endif
// BOTTOM

View File

@ -0,0 +1,20 @@
/*
* Mr. 4th Dimention - Allen Webster
*
* 16.11.2014
*
* Keyboard layer for 4coder
*
*/
// TOP
globalvar u8 keycode_lookup_table[255];
inline u8
keycode_lookup(u8 system_code){
return keycode_lookup_table[system_code];
}
// BOTTOM

View File

@ -0,0 +1,30 @@
enum Key_Code{
key_back = 1,
key_up = 2,
key_down = 3,
key_left = 4,
key_right = 5,
key_del = 6,
key_insert = 7,
key_home = 8,
key_end = 11,
key_page_up = 12,
key_page_down = 13,
key_esc = 14,
key_f1 = 127,
key_f2 = 128,
key_f3 = 129,
key_f4 = 130,
key_f5 = 131,
key_f6 = 132,
key_f7 = 133,
key_f8 = 134,
key_f9 = 135,
key_f10 = 136,
key_f11 = 137,
key_f12 = 138,
key_f13 = 139,
key_f14 = 140,
key_f15 = 141,
key_f15 = 142,
}

View File

@ -0,0 +1,313 @@
/*
* Mr. 4th Dimention - Allen Webster
*
* 19.08.2015
*
* Panel layout and general view functions for 4coder
*
*/
// TOP
struct Panel_Divider{
Panel_Divider *next;
i32 parent;
i32 which_child;
i32 child1, child2;
b32 v_divider;
i32 pos;
};
struct Screen_Region{
i32_Rect full;
i32_Rect inner;
i32_Rect prev_inner;
i32 l_margin, r_margin;
i32 t_margin, b_margin;
};
struct Panel{
Panel *next;
Panel *prev;
struct View *view;
i32 parent;
i32 which_child;
int ALLOCED;
union{
struct{
i32_Rect full;
i32_Rect inner;
i32_Rect prev_inner;
i32 l_margin, r_margin;
i32 t_margin, b_margin;
};
Screen_Region screen_region;
};
};
struct Editing_Layout{
Panel *panels;
Panel free_sentinel;
Panel used_sentinel;
Panel_Divider *dividers;
Panel_Divider *free_divider;
i32 panel_count, panel_max_count;
i32 root;
i32 active_panel;
i32 full_width, full_height;
};
struct Divider_And_ID{
Panel_Divider* divider;
i32 id;
};
struct Panel_And_ID{
Panel* panel;
i32 id;
};
internal void
panel_init(Panel *panel){
panel->view = 0;
panel->parent = -1;
panel->which_child = 0;
panel->screen_region.full = {};
panel->screen_region.inner = {};
panel->screen_region.prev_inner = {};
panel->l_margin = 3;
panel->r_margin = 3;
panel->t_margin = 3;
panel->b_margin = 3;
}
internal Divider_And_ID
layout_alloc_divider(Editing_Layout *layout){
Divider_And_ID result;
Assert(layout->free_divider);
result.divider = layout->free_divider;
layout->free_divider = result.divider->next;
*result.divider = {};
result.divider->parent = -1;
result.divider->child1 = -1;
result.divider->child2 = -1;
result.id = (i32)(result.divider - layout->dividers);
if (layout->panel_count == 1){
layout->root = result.id;
}
return(result);
}
internal Divider_And_ID
layout_get_divider(Editing_Layout *layout, i32 id){
Divider_And_ID result;
Assert(id >= 0 && id < layout->panel_max_count-1);
result.id = id;
result.divider = layout->dividers + id;
return(result);
}
internal void
layout_free_divider(Editing_Layout *layout, Panel_Divider *divider){
divider->next = layout->free_divider;
layout->free_divider = divider;
}
internal Panel_And_ID
layout_alloc_panel(Editing_Layout *layout){
Panel_And_ID result = {};
Assert(layout->panel_count < layout->panel_max_count);
++layout->panel_count;
result.panel = layout->free_sentinel.next;
dll_remove(result.panel);
dll_insert(&layout->used_sentinel, result.panel);
panel_init(result.panel);
result.id = (i32)(result.panel - layout->panels);
result.panel->ALLOCED = 1;
return(result);
}
internal void
layout_free_panel(Editing_Layout *layout, Panel *panel){
dll_remove(panel);
dll_insert(&layout->free_sentinel, panel);
--layout->panel_count;
panel->ALLOCED = 0;
}
internal Divider_And_ID
layout_calc_divider_id(Editing_Layout *layout, Panel_Divider *divider){
Divider_And_ID result;
result.divider = divider;
result.id = (i32)(divider - layout->dividers);
return result;
}
struct Split_Result{
Panel_Divider *divider;
Panel *panel;
};
internal Split_Result
layout_split_panel(Editing_Layout *layout, Panel *panel, b32 vertical){
Split_Result result = {};
Divider_And_ID div = {}, parent_div = {};
Panel_And_ID new_panel = {};
div = layout_alloc_divider(layout);
if (panel->parent != -1){
parent_div = layout_get_divider(layout, panel->parent);
if (panel->which_child == -1){
parent_div.divider->child1 = div.id;
}
else{
parent_div.divider->child2 = div.id;
}
}
div.divider->parent = panel->parent;
div.divider->which_child = panel->which_child;
if (vertical){
div.divider->v_divider = 1;
div.divider->pos = (panel->full.x0 + panel->full.x1) / 2;
}
else{
div.divider->v_divider = 0;
div.divider->pos = (panel->full.y0 + panel->full.y1) / 2;
}
new_panel = layout_alloc_panel(layout);
panel->parent = div.id;
panel->which_child = -1;
new_panel.panel->parent = div.id;
new_panel.panel->which_child = 1;
result.divider = div.divider;
result.panel = new_panel.panel;
return result;
}
internal void
panel_fix_internal_area(Panel *panel){
panel->inner.x0 = panel->full.x0 + panel->l_margin;
panel->inner.x1 = panel->full.x1 - panel->r_margin;
panel->inner.y0 = panel->full.y0 + panel->t_margin;
panel->inner.y1 = panel->full.y1 - panel->b_margin;
}
internal void
layout_fix_all_panels(Editing_Layout *layout){
Panel *panel;
Panel_Divider *dividers = layout->dividers;
i32 panel_count = layout->panel_count;
i32_Rect r;
i32 pos, which_child, action;
Divider_And_ID div;
if (panel_count > 1){
for (panel = layout->used_sentinel.next;
panel != &layout->used_sentinel;
panel = panel->next){
r.x0 = 0;
r.x1 = r.x0 + layout->full_width;
r.y0 = 0;
r.y1 = r.y0 + layout->full_height;
which_child = panel->which_child;
div.id = panel->parent;
for (;;){
Assert(div.id != -1);
div.divider = dividers + div.id;
pos = div.divider->pos;
action = (div.divider->v_divider << 1) | (which_child > 0);
switch (action){
case 0: // v_divider : 0, which_child : -1
if (pos < r.y1) r.y1 = pos;
break;
case 1: // v_divider : 0, which_child : 1
if (pos > r.y0) r.y0 = pos;
break;
case 2: // v_divider : 1, which_child : -1
if (pos < r.x1) r.x1 = pos;
break;
case 3: // v_divider : 1, which_child : 1
if (pos > r.x0) r.x0 = pos;
break;
}
if (div.id != layout->root){
div.id = div.divider->parent;
which_child = div.divider->which_child;
}
else{
break;
}
}
panel->full = r;
panel_fix_internal_area(panel);
}
}
else{
panel = layout->used_sentinel.next;
panel->full.x0 = 0;
panel->full.y0 = 0;
panel->full.x1 = layout->full_width;
panel->full.y1 = layout->full_height;
panel_fix_internal_area(panel);
}
}
internal void
layout_refit(Editing_Layout *layout, i32 prev_width, i32 prev_height){
Panel_Divider *dividers = layout->dividers;
i32 max = layout->panel_max_count - 1;
f32 h_ratio, v_ratio;
Panel_Divider *divider = dividers;
i32 i;
if (layout->panel_count > 1){
Assert(prev_width != 0 && prev_height != 0);
h_ratio = ((f32)layout->full_width) / prev_width;
v_ratio = ((f32)layout->full_height) / prev_height;
for (i = 0; i < max; ++i, ++divider){
if (divider->v_divider){
divider->pos = ROUND32((divider->pos) * h_ratio);
}
else{
divider->pos = ROUND32((divider->pos) * v_ratio);
}
}
}
layout_fix_all_panels(layout);
}
// BOTTOM

View File

@ -0,0 +1,92 @@
/*
* Mr. 4th Dimention - Allen Webster
*
* 14.11.2015
*
* Linux-US Keyboard layer for 4coder
*
*/
// TOP
#include "4ed_keyboard.cpp"
internal void
keycode_init(Display* dpy){
#if 0
// NOTE(inso): these are for XInput, currently not used.
keycode_lookup_table[KEY_BACKSPACE] = codes->back;
keycode_lookup_table[KEY_DELETE] = codes->del;
keycode_lookup_table[KEY_UP] = codes->up;
keycode_lookup_table[KEY_DOWN] = codes->down;
keycode_lookup_table[KEY_LEFT] = codes->left;
keycode_lookup_table[KEY_RIGHT] = codes->right;
keycode_lookup_table[KEY_INSERT] = codes->insert;
keycode_lookup_table[KEY_HOME] = codes->home;
keycode_lookup_table[KEY_END] = codes->end;
keycode_lookup_table[KEY_PAGEUP] = codes->page_up;
keycode_lookup_table[KEY_PAGEDOWN] = codes->page_down;
keycode_lookup_table[KEY_ESC] = codes->esc;
#endif
// NOTE(inso): This looks a bit dumb, but it's the best way I can think of to do it, since:
// KeySyms are the type representing "virtual" keys, like XK_BackSpace, but they are 32-bit ints.
// KeyCodes are guaranteed to fit in 1 byte (and therefore the keycode_lookup_table) but
// have dynamic numbers assigned by the XServer.
// There is XKeysymToKeycode, but it only returns 1 KeyCode for a KeySym. I have my capslock
// rebound to esc, so there are two KeyCodes for the XK_Escape KeyCode but XKeysymToKeycode only
// gets one of them, hence the need for this crazy lookup which works correctly with rebound keys.
memset(keycode_lookup_table, 0, sizeof(keycode_lookup_table));
struct SymMapping {
KeySym sym;
Code code;
} sym_table[] = {
{ XK_BackSpace, key_back },
{ XK_Delete, key_del },
{ XK_Up, key_up },
{ XK_Down, key_down },
{ XK_Left, key_left },
{ XK_Right, key_right },
{ XK_Insert, key_insert },
{ XK_Home, key_home },
{ XK_End, key_end },
{ XK_Page_Up, key_page_up },
{ XK_Page_Down, key_page_down },
{ XK_Escape, key_esc }
};
const int table_size = sizeof(sym_table) / sizeof(struct SymMapping);
int key_min, key_max, syms_per_code;
XDisplayKeycodes(dpy, &key_min, &key_max);
int key_count = (key_max - key_min) + 1;
KeySym* syms = XGetKeyboardMapping(
dpy,
key_min,
key_count,
&syms_per_code
);
if(!syms) return;
int key = key_min;
for(int i = 0; i < key_count * syms_per_code; ++i){
for(int j = 0; j < table_size; ++j){
if(sym_table[j].sym == syms[i]){
keycode_lookup_table[key + (i/syms_per_code)] = sym_table[j].code;
break;
}
}
}
XFree(syms);
}
// BOTTOM

View File

@ -0,0 +1,774 @@
/*
* Mr. 4th Dimention - Allen Webster
*
* 15.05.2015
*
* Math functions for 4coder
*
*/
// TOP
/*
* Scalar operators
*/
#define C_MATH 1
#define DEG_TO_RAD 0.0174533f
#if C_MATH
#include <math.h>
#endif
inline f32
ABS(f32 x){
if (x < 0) x = -x;
return x;
}
inline f32
MOD(f32 x, i32 m){
#if C_MATH
f32 whole, frac;
frac = modff(x, &whole);
return ((i32)(whole) % m) + frac;
#endif
}
inline f32
SQRT(f32 x){
#if C_MATH
return sqrt(x);
#endif
}
inline f32
SIN(f32 x_degrees){
#if C_MATH
return sinf(x_degrees * DEG_TO_RAD);
#endif
}
inline f32
COS(f32 x_degrees){
#if C_MATH
return cosf(x_degrees * DEG_TO_RAD);
#endif
}
/*
* Rounding
*/
inline i32
TRUNC32(real32 x) { return (i32)x; }
inline i32
FLOOR32(real32 x) { return (i32)(x)-((x!=(i32)(x) && x<0)?1:0); }
inline i32
CEIL32(real32 x) { return (i32)(x)+((x!=(i32)(x) && x>0)?1:0); }
inline i32
ROUND32(real32 x) { return FLOOR32(x + .5f); }
inline i32
DIVCEIL32(i32 n, i32 d) {
i32 q = (n/d);
return q + (q*d < n);
}
inline real32
FRACPART32(real32 x) { return x - (i32)x; }
inline u32
ROUNDPOT32(u32 v){
v--;
v |= v >> 1;
v |= v >> 2;
v |= v >> 4;
v |= v >> 8;
v |= v >> 16;
v++;
return v;
}
/*
* Rectangles
*/
struct i32_Rect{
i32 x0, y0;
i32 x1, y1;
};
struct f32_Rect{
f32 x0, y0;
f32 x1, y1;
};
inline i32_Rect
i32R(i32 l, i32 t, i32 r, i32 b){
i32_Rect rect;
rect.x0 = l; rect.y0 = t;
rect.x1 = r; rect.y1 = b;
return rect;
}
inline i32_Rect
i32R(f32_Rect r){
i32_Rect rect;
rect.x0 = (i32)r.x0;
rect.y0 = (i32)r.y0;
rect.x1 = (i32)r.x1;
rect.y1 = (i32)r.y1;
return rect;
}
inline i32_Rect
i32XYWH(i32 x, i32 y, i32 w, i32 h){
i32_Rect rect;
rect.x0 = x; rect.y0 = y;
rect.x1 = x+w; rect.y1 = y+h;
return rect;
}
inline f32_Rect
f32R(f32 l, f32 t, f32 r, f32 b){
f32_Rect rect;
rect.x0 = l; rect.y0 = t;
rect.x1 = r; rect.y1 = b;
return rect;
}
inline f32_Rect
f32R(i32_Rect r){
f32_Rect rect;
rect.x0 = (f32)r.x0;
rect.y0 = (f32)r.y0;
rect.x1 = (f32)r.x1;
rect.y1 = (f32)r.y1;
return rect;
}
inline f32_Rect
f32XYWH(f32 x, f32 y, f32 w, f32 h){
f32_Rect rect;
rect.x0 = x; rect.y0 = y;
rect.x1 = x+w; rect.y1 = y+h;
return rect;
}
inline b32
hit_check(i32 x, i32 y, i32 x0, i32 y0, i32 x1, i32 y1){
return (x >= x0 && x < x1 && y >= y0 && y < y1);
}
inline b32
hit_check(i32 x, i32 y, i32_Rect rect){
return (hit_check(x, y, rect.x0, rect.y0, rect.x1, rect.y1));
}
inline b32
hit_check(i32 x, i32 y, f32 x0, f32 y0, f32 x1, f32 y1){
return (x >= x0 && x < x1 && y >= y0 && y < y1);
}
inline b32
hit_check(i32 x, i32 y, f32_Rect rect){
return (hit_check(x, y, rect.x0, rect.y0, rect.x1, rect.y1));
}
inline b32
positive_area(i32_Rect rect){
return (rect.x0 < rect.x1 && rect.y0 < rect.y1);
}
inline i32_Rect
get_inner_rect(i32_Rect outer, i32 margin){
i32_Rect r;
r.x0 = outer.x0 + margin;
r.y0 = outer.y0 + margin;
r.x1 = outer.x1 - margin;
r.y1 = outer.y1 - margin;
return r;
}
inline b32
fits_inside(i32_Rect rect, i32_Rect outer){
return (rect.x0 >= outer.x0 && rect.x1 <= outer.x1 &&
rect.y0 >= outer.y0 && rect.y1 <= outer.y1);
}
inline i32_Rect
rect_clamp_to_rect(i32_Rect rect, i32_Rect clamp_box){
if (rect.x0 < clamp_box.x0) rect.x0 = clamp_box.x0;
if (rect.y0 < clamp_box.y0) rect.y0 = clamp_box.y0;
if (rect.x1 > clamp_box.x1) rect.x1 = clamp_box.x1;
if (rect.y1 > clamp_box.y1) rect.y1 = clamp_box.y1;
return rect;
}
inline i32_Rect
rect_clamp_to_rect(i32 left, i32 top, i32 right, i32 bottom, i32_Rect clamp_box){
return rect_clamp_to_rect(i32R(left, top, right, bottom), clamp_box);
}
/*
* Vectors
*/
struct Vec2{
union{
struct{
real32 x, y;
};
struct{
real32 v[2];
};
};
};
struct Vec3{
union{
struct{
real32 x, y, z;
};
struct{
real32 r, g, b;
};
struct{
Vec2 xy;
real32 _z;
};
struct{
real32 _x;
Vec2 yz;
};
struct{
real32 v[3];
};
};
};
struct Vec4{
union{
struct{
real32 r, g, b, a;
};
struct{
real32 h, s, l, __a;
};
struct{
real32 x, y, z, w;
};
struct{
Vec3 rgb;
real32 _a;
};
struct{
Vec3 xyz;
real32 _w;
};
struct{
real32 _x;
Vec3 yzw;
};
struct{
real32 v[4];
};
};
};
inline internal Vec2
V2(real32 x, real32 y){
Vec2 result;
result.x = x;
result.y = y;
return result;
}
inline internal Vec3
V3(real32 x, real32 y, real32 z){
Vec3 result;
result.x = x;
result.y = y;
result.z = z;
return result;
}
inline internal Vec4
V4(real32 x, real32 y, real32 z, real32 w){
Vec4 result;
result.x = x;
result.y = y;
result.z = z;
result.w = w;
return result;
}
inline internal Vec2
operator+(Vec2 a, Vec2 b){
Vec2 result;
result.x = a.x + b.x;
result.y = a.y + b.y;
return result;
}
inline internal Vec3
operator+(Vec3 a, Vec3 b){
Vec3 result;
result.x = a.x + b.x;
result.y = a.y + b.y;
result.z = a.z + b.z;
return result;
}
inline internal Vec4
operator+(Vec4 a, Vec4 b){
Vec4 result;
result.x = a.x + b.x;
result.y = a.y + b.y;
result.z = a.z + b.z;
result.w = a.w + b.w;
return result;
}
inline internal Vec2
operator-(Vec2 a, Vec2 b){
Vec2 result;
result.x = a.x - b.x;
result.y = a.y - b.y;
return result;
}
inline internal Vec3
operator-(Vec3 a, Vec3 b){
Vec3 result;
result.x = a.x - b.x;
result.y = a.y - b.y;
result.z = a.z - b.z;
return result;
}
inline internal Vec4
operator-(Vec4 a, Vec4 b){
Vec4 result;
result.x = a.x - b.x;
result.y = a.y - b.y;
result.z = a.z - b.z;
result.w = a.w - b.w;
return result;
}
inline internal Vec2
operator*(Vec2 a, real32 k){
Vec2 result;
result.x = a.x * k;
result.y = a.y * k;
return result;
}
inline internal Vec3
operator*(Vec3 a, real32 k){
Vec3 result;
result.x = a.x * k;
result.y = a.y * k;
result.z = a.z * k;
return result;
}
inline internal Vec4
operator*(Vec4 a, real32 k){
Vec4 result;
result.x = a.x * k;
result.y = a.y * k;
result.z = a.z * k;
result.w = a.w * k;
return result;
}
inline internal Vec2
operator*(real32 k, Vec2 a){
Vec2 result;
result.x = a.x * k;
result.y = a.y * k;
return result;
}
inline internal Vec3
operator*(real32 k, Vec3 a){
Vec3 result;
result.x = a.x * k;
result.y = a.y * k;
result.z = a.z * k;
return result;
}
inline internal Vec4
operator*(real32 k, Vec4 a){
Vec4 result;
result.x = a.x * k;
result.y = a.y * k;
result.z = a.z * k;
result.w = a.w * k;
return result;
}
inline internal Vec2&
operator+=(Vec2 &a, Vec2 b){
a = (a + b);
return a;
}
inline internal Vec3&
operator+=(Vec3 &a, Vec3 b){
a = (a + b);
return a;
}
inline internal Vec4&
operator+=(Vec4 &a, Vec4 b){
a = (a + b);
return a;
}
inline internal Vec2&
operator-=(Vec2 &a, Vec2 b){
a = (a - b);
return a;
}
inline internal Vec3&
operator-=(Vec3 &a, Vec3 b){
a = (a - b);
return a;
}
inline internal Vec4&
operator-=(Vec4 &a, Vec4 b){
a = (a - b);
return a;
}
inline internal Vec2&
operator*=(Vec2 &a, real32 k){
a = (a * k);
return a;
}
inline internal Vec3&
operator*=(Vec3 &a, real32 k){
a = (a * k);
return a;
}
inline internal Vec4&
operator*=(Vec4 &a, real32 k){
a = (a * k);
return a;
}
inline internal real32
dot(Vec2 a, Vec2 b){
real32 result;
result = a.x*b.x + a.y*b.y;
return result;
}
inline internal real32
dot(Vec3 a, Vec3 b){
real32 result;
result = a.x*b.x + a.y*b.y + a.z*b.z;
return result;
}
inline internal real32
dot(Vec4 a, Vec4 b){
real32 result;
result = a.x*b.x + a.y*b.y + a.z*b.z + a.w*b.w;
return result;
}
inline internal Vec3
cross(Vec3 a, Vec3 b){
Vec3 result;
result.x = a.y*b.z - b.y*a.z;
result.y = a.z*b.x - b.z*a.x;
result.z = a.x*b.y - b.x*a.y;
return result;
}
inline internal Vec2
hadamard(Vec2 a, Vec2 b){
Vec2 result;
result.x = a.x*b.x;
result.y = a.y*b.y;
return result;
}
inline internal Vec3
hadamard(Vec3 a, Vec3 b){
Vec3 result;
result.x = a.x*b.x;
result.y = a.y*b.y;
result.z = a.z*b.z;
return result;
}
inline internal Vec4
hadamard(Vec4 a, Vec4 b){
Vec4 result;
result.x = a.x*b.x;
result.y = a.y*b.y;
result.z = a.z*b.z;
result.w = a.w*b.w;
return result;
}
inline internal Vec2
perp(Vec2 v){
Vec2 result;
result.x = -v.y;
result.y = v.x;
return result;
}
inline Vec2
polar_to_cartesian(real32 theta_degrees, real32 length){
Vec2 result;
result.x = COS(theta_degrees)*length;
result.y = SIN(theta_degrees)*length;
return result;
}
inline Vec2
rotate(Vec2 v, real32 theta_degrees){
Vec2 result;
real32 c, s;
c = COS(theta_degrees);
s = SIN(theta_degrees);
result.x = v.x*c - v.y*s;
result.y = v.x*s + v.y*c;
return result;
}
/*
* Coordinates
*/
struct Matrix2{
Vec2 x_axis;
Vec2 y_axis;
};
internal Matrix2
invert(Vec2 x_axis, Vec2 y_axis){
Matrix2 result = {};
real32 det = 1.f / (x_axis.x*y_axis.y - x_axis.y*y_axis.x);
result.x_axis.x = y_axis.y*det;
result.y_axis.x = -y_axis.x*det;
result.x_axis.y = -x_axis.y*det;
result.y_axis.y = x_axis.x*det;
return result;
}
internal Matrix2
invert(Matrix2 m){
Matrix2 result = {};
real32 det = 1.f / (m.x_axis.x*m.y_axis.y - m.x_axis.y*m.y_axis.x);
result.x_axis.x = m.y_axis.y*det;
result.y_axis.x = -m.y_axis.x*det;
result.x_axis.y = -m.x_axis.y*det;
result.y_axis.y = m.x_axis.x*det;
return result;
}
/*
* Lerps, Clamps, Thresholds, Etc
*/
inline real32
lerp(real32 a, real32 t, real32 b){
return a + (b-a)*t;
}
inline Vec2
lerp(Vec2 a, real32 t, Vec2 b){
return a + (b-a)*t;
}
inline Vec3
lerp(Vec3 a, real32 t, Vec3 b){
return a + (b-a)*t;
}
inline Vec4
lerp(Vec4 a, real32 t, Vec4 b){
return a + (b-a)*t;
}
inline real32
unlerp(real32 a, real32 x, real32 b){
return (x - a) / (b - a);
}
inline real32
clamp(real32 a, real32 n, real32 z){
return (n<a)?(a):((n>z)?(z):n);
}
/*
* Color
*/
// TODO(allen): Convert colors to Vec4
inline internal u32
color_blend(u32 a, real32 t, u32 b){
union{
u8 byte[4];
u32 comp;
} A, B, R;
A.comp = a;
B.comp = b;
R.byte[0] = (u8)lerp(A.byte[0], t, B.byte[0]);
R.byte[1] = (u8)lerp(A.byte[1], t, B.byte[1]);
R.byte[2] = (u8)lerp(A.byte[2], t, B.byte[2]);
R.byte[3] = (u8)lerp(A.byte[3], t, B.byte[3]);
return R.comp;
}
internal Vec3
unpack_color3(u32 color){
Vec3 result;
result.r = ((color >> 16) & 0xFF) / 255.f;
result.g = ((color >> 8) & 0xFF) / 255.f;
result.b = ((color >> 0) & 0xFF) / 255.f;
return result;
}
internal Vec4
unpack_color4(u32 color){
Vec4 result;
result.a = ((color >> 24) & 0xFF) / 255.f;
result.r = ((color >> 16) & 0xFF) / 255.f;
result.g = ((color >> 8) & 0xFF) / 255.f;
result.b = ((color >> 0) & 0xFF) / 255.f;
return result;
}
internal u32
pack_color4(Vec4 color){
u32 result =
((u8)(color.a * 255) << 24) |
((u8)(color.r * 255) << 16) |
((u8)(color.g * 255) << 8) |
((u8)(color.b * 255) << 0);
return result;
}
internal Vec4
rgba_to_hsla(Vec4 rgba){
Vec4 hsla = {};
real32 max, min, delta;
i32 maxc;
hsla.a = rgba.a;
max = rgba.r; min = rgba.r;
maxc = 0;
if (rgba.r < rgba.g){
max = rgba.g;
maxc = 1;
}
if (rgba.b > max){
max = rgba.b;
maxc = 2;
}
if (rgba.r > rgba.g){
min = rgba.g;
}
if (rgba.b < min){
min = rgba.b;
}
delta = max - min;
hsla.z = (max + min) * .5f;
if (delta == 0){
hsla.x = 0.f;
hsla.y = 0.f;
}
else{
switch (maxc){
case 0:
{
hsla.x = (rgba.g - rgba.b) / delta;
hsla.x += (rgba.g < rgba.b) * 6.f;
}break;
case 1:
{
hsla.x = (rgba.b - rgba.r) / delta;
hsla.x += 2.f;
}break;
case 2:
{
hsla.x = (rgba.r - rgba.g) / delta;
hsla.x += 4.f;
}break;
}
hsla.x *= (1/6.f); // * 60 / 360
hsla.y = delta / (1.f - ABS(2.f*hsla.z - 1.f));
}
return hsla;
}
internal Vec4
hsla_to_rgba(Vec4 hsla){
if (hsla.h >= 1.f) hsla.h = 0.f;
Vec4 rgba = {};
real32 C, X, m;
i32 H;
rgba.a = hsla.a;
C = (1.f - ABS(2*hsla.z - 1.f)) * hsla.y;
X = C * (1.f-ABS(MOD(hsla.x*6.f, 2)-1.f));
m = hsla.z - C*.5f;
H = FLOOR32(hsla.x * 6.f);
switch (H){
case 0:
rgba.r = C; rgba.g = X; rgba.b = 0;
break;
case 1:
rgba.r = X; rgba.g = C; rgba.b = 0;
break;
case 2:
rgba.r = 0; rgba.g = C; rgba.b = X;
break;
case 3:
rgba.r = 0; rgba.g = X; rgba.b = C;
break;
case 4:
rgba.r = X; rgba.g = 0; rgba.b = C;
break;
case 5:
rgba.r = C; rgba.g = 0; rgba.b = X;
break;
}
rgba.r += m;
rgba.g += m;
rgba.b += m;
return rgba;
}
// BOTTOM

View File

@ -0,0 +1,256 @@
/*
* Mr. 4th Dimention - Allen Webster
*
* 13.11.2015
*
* Memory utils for 4coder
*
*/
// TOP
struct Partition{
u8 *base;
i32 pos, max;
};
struct Temp_Memory{
void *handle;
int pos;
};
enum Memory_Bubble_Flag{
MEM_BUBBLE_USED = 0x1,
MEM_BUBBLE_DEBUG = 0xD3000000,
MEM_BUBBLE_SYS_DEBUG = 0x5D000000,
MEM_BUBBLE_DEBUG_MASK = 0xFF000000
};
struct Bubble{
Bubble *prev;
Bubble *next;
u32 flags;
i32 size;
u32 type;
u32 _unused_;
};
struct General_Memory{
Bubble sentinel;
};
struct Mem_Options{
Partition part;
General_Memory general;
};
inline Partition
partition_open(void *memory, i32 size){
Partition partition;
partition.base = (u8*)memory;
partition.pos = 0;
partition.max = size;
return partition;
}
inline void*
partition_allocate(Partition *data, i32 size){
void *ret = 0;
if (size > 0 && data->pos + size <= data->max){
ret = data->base + data->pos;
data->pos += size;
}
return ret;
}
inline void
partition_align(Partition *data, u32 boundary){
--boundary;
data->pos = (data->pos + boundary) & (~boundary);
}
inline void*
partition_current(Partition *data){
return data->base + data->pos;
}
inline i32
partition_remaining(Partition *data){
return data->max - data->pos;
}
inline Partition
partition_sub_part(Partition *data, i32 size){
Partition result = {};
void *d = partition_allocate(data, size);
if (d) result = partition_open(d, size);
return result;
}
#define push_struct(part, T) (T*)partition_allocate(part, sizeof(T))
#define push_array(part, T, size) (T*)partition_allocate(part, sizeof(T)*(size))
#define push_block(part, size) partition_allocate(part, size)
inline void
insert_bubble(Bubble *prev, Bubble *bubble){
bubble->prev = prev;
bubble->next = prev->next;
bubble->prev->next = bubble;
bubble->next->prev = bubble;
}
inline void
remove_bubble(Bubble *bubble){
bubble->prev->next = bubble->next;
bubble->next->prev = bubble->prev;
}
#if FRED_INTERNAL
#define MEM_BUBBLE_FLAG_INIT MEM_BUBBLE_DEBUG
#else
#define MEM_BUBBLE_FLAG_INIT 0
#endif
internal void
general_memory_open(General_Memory *general, void *memory, i32 size){
general->sentinel.prev = &general->sentinel;
general->sentinel.next = &general->sentinel;
general->sentinel.flags = MEM_BUBBLE_USED;
general->sentinel.size = 0;
Bubble *first = (Bubble*)memory;
first->flags = (u32)MEM_BUBBLE_FLAG_INIT;
first->size = size - sizeof(Bubble);
insert_bubble(&general->sentinel, first);
}
internal void
general_memory_check(General_Memory *general){
Bubble *sentinel = &general->sentinel;
for (Bubble *bubble = sentinel->next;
bubble != sentinel;
bubble = bubble->next){
Assert(bubble);
Bubble *next = bubble->next;
Assert(bubble == next->prev);
if (next != sentinel){
Assert(bubble->next > bubble);
Assert(bubble > bubble->prev);
char *end_ptr = (char*)(bubble + 1) + bubble->size;
char *next_ptr = (char*)next;
AllowLocal(end_ptr);
AllowLocal(next_ptr);
Assert(end_ptr == next_ptr);
}
}
}
#define BUBBLE_MIN_SIZE 1024
internal void
general_memory_attempt_split(Bubble *bubble, i32 wanted_size){
i32 remaining_size = bubble->size - wanted_size;
if (remaining_size >= BUBBLE_MIN_SIZE){
bubble->size = wanted_size;
Bubble *new_bubble = (Bubble*)((u8*)(bubble + 1) + wanted_size);
new_bubble->flags = (u32)MEM_BUBBLE_FLAG_INIT;
new_bubble->size = remaining_size - sizeof(Bubble);
insert_bubble(bubble, new_bubble);
}
}
internal void*
general_memory_allocate(General_Memory *general, i32 size, u32 type = 0){
void *result = 0;
for (Bubble *bubble = general->sentinel.next;
bubble != &general->sentinel;
bubble = bubble->next){
if (!(bubble->flags & MEM_BUBBLE_USED)){
if (bubble->size >= size){
result = bubble + 1;
bubble->flags |= MEM_BUBBLE_USED;
bubble->type = type;
general_memory_attempt_split(bubble, size);
break;
}
}
}
return result;
}
inline void
general_memory_do_merge(Bubble *left, Bubble *right){
Assert(left->next == right);
Assert(right->prev == left);
left->size += sizeof(Bubble) + right->size;
remove_bubble(right);
}
inline void
general_memory_attempt_merge(Bubble *left, Bubble *right){
if (!(left->flags & MEM_BUBBLE_USED) &&
!(right->flags & MEM_BUBBLE_USED)){
general_memory_do_merge(left, right);
}
}
internal void
general_memory_free(General_Memory *general, void *memory){
Bubble *bubble = ((Bubble*)memory) - 1;
Assert((!FRED_INTERNAL) || (bubble->flags & MEM_BUBBLE_DEBUG_MASK) == MEM_BUBBLE_DEBUG);
bubble->flags &= ~MEM_BUBBLE_USED;
bubble->type = 0;
Bubble *prev, *next;
prev = bubble->prev;
next = bubble->next;
general_memory_attempt_merge(bubble, next);
general_memory_attempt_merge(prev, bubble);
}
internal void*
general_memory_reallocate(General_Memory *general, void *old, i32 old_size, i32 size, u32 type = 0){
void *result = old;
Bubble *bubble = ((Bubble*)old) - 1;
bubble->type = type;
Assert((!FRED_INTERNAL) || (bubble->flags & MEM_BUBBLE_DEBUG_MASK) == MEM_BUBBLE_DEBUG);
i32 additional_space = size - bubble->size;
if (additional_space > 0){
Bubble *next = bubble->next;
if (!(next->flags & MEM_BUBBLE_USED) &&
next->size + sizeof(Bubble) >= additional_space){
general_memory_do_merge(bubble, next);
general_memory_attempt_split(bubble, size);
}
else{
result = general_memory_allocate(general, size, type);
if (old_size) memcpy(result, old, old_size);
general_memory_free(general, old);
}
}
return result;
}
inline void*
general_memory_reallocate_nocopy(General_Memory *general, void *old, i32 size, u32 type = 0){
return general_memory_reallocate(general, old, 0, size, type);
}
internal Temp_Memory
begin_temp_memory(Partition *data){
Temp_Memory result;
result.handle = data;
result.pos = data->pos;
return result;
}
internal void
end_temp_memory(Temp_Memory temp){
((Partition*)temp.handle)->pos = temp.pos;
}
#define reset_temp_memory end_temp_memory
// BOTTOM

View File

@ -0,0 +1,200 @@
/*
* Mr. 4th Dimention - Allen Webster
*
* 12.12.2014
*
* Meta setup for project codename "4ed"
*
*/
#ifndef FRED_META_H
#define FRED_META_H
#include <string.h>
#include <stdint.h>
typedef uint8_t u8;
typedef uint64_t u64;
typedef uint32_t u32;
typedef uint16_t u16;
typedef int8_t i8;
typedef int64_t i64;
typedef int32_t i32;
typedef int16_t i16;
typedef i32 bool32;
typedef i8 bool8;
typedef i32 b32;
typedef i8 b8;
typedef uint8_t byte;
typedef float real32;
typedef double real64;
typedef float f32;
typedef double f64;
struct Data{
byte *data;
i32 size;
};
#define external extern "C"
#define internal static
#define globalvar static
#define persist static
#define globalconst static const
inline i32
raw_ptr_dif(void *a, void *b) { return (i32)((u8*)a - (u8*)b); }
#define COMP_ID_(a,b,c,d) (d << 24) | (c << 16) | (b << 8) | a
#define COMPOSE_ID(a,b,c,d) (COMP_ID_((a),(b),(c),(d)))
#define S(X) #X
#define S_(X) S(X)
#define S__LINE__ S_(__LINE__)
#if FRED_PRINT_DEBUG == 1
internal void
_OutDbgStr(u8*);
# include <stdio.h>
# if FRED_PRINT_DEBUG_FILE_LINE
# define FredDbg(con, size, ...) {_OutDbgStr((u8*)("FILE:"__FILE__"LINE:"S__LINE__"\n")); char msg[size]; sprintf(msg, __VA_ARGS__); _OutDbgStr((u8*)msg);}
# else
# define FredDbg(con, size, ...) {char msg[size]; sprintf(msg, __VA_ARGS__); _OutDbgStr((u8*)msg);}
# endif
#elif FRED_PRINT_DEBUG == 2
# include <stdio.h>
# if FRED_PRINT_DEBUG_FILE_LINE
# define FredDbg(con, size, ...) {fprintf((con)->log, ("FILE:"__FILE__"LINE:"S__LINE__"\n")); fprintf(__VA_ARGS__);}
# else
# define FredDbg(con, size, ...) {fprintf((con)->log, __VA_ARGS__);}
# endif
#else
# define FredDbg(con, size, ...)
#endif
#if FRED_INTERNAL && FRED_FULL_ERRORS
# include <stdio.h>
# define FatalErrorFormat(alt, size, ...) {char msg[size]; sprintf(msg, __VA_ARGS__); FatalError(msg);}
#else
# define FatalErrorFormat(alt, size, ...) {FatalError(alt);}
#endif
#if FRED_SLOW
# define Assert(c) assert(c)
#else
# define Assert(c)
#endif
#define TentativeAssert(c) Assert(c)
#define FatalError(message) system_fatal_error((u8*)message)
#define AllowLocal(name) (void)name
#define ArrayCount(array) (sizeof(array)/sizeof(array[0]))
#define OffsetOfStruct(S,c) ((i64)(& ((S*)0)->c ))
#define OffsetOfPtr(s,c) ((i64)((char*)(&(s)->c) - (char*)(s)))
#define Swap(a,b) {auto t = a; a = b; b = t;}
#ifndef literal
#define literal(s) s, (sizeof(s)-1)
#endif
#define Min(a,b) (((a)<(b))?(a):(b))
#define Max(a,b) (((a)>(b))?(a):(b))
#define TMax(t,v) globalconst t max_##t = v
TMax(u8, 255);
TMax(u16, 65535);
TMax(u32, 4294967295);
TMax(u64, 18446744073709551615U);
TMax(i8, 127);
TMax(i16, 32767);
TMax(i32, 2147483647);
TMax(i64, 9223372036854775807);
#undef TMax
#define TMin(t) globalconst t min_##t = 0
TMin(u8);
TMin(u16);
TMin(u32);
TMin(u64);
#undef TMin
#define TMin(t,v) globalconst t min_##t = ((t)v)
TMin(i8, -0xF0);
TMin(i16, -0xF000);
TMin(i32, -0xF00000);
TMin(i64, -0xF0000000LL);
#undef TMin
internal i32
LargeRoundUp(i32 x, i32 granularity){
i32 original_x = x;
x /= granularity;
x *= granularity;
if (x < original_x){
x += granularity;
}
return x;
}
#define Bit_0 (1 << 0)
#define Bit_1 (1 << 1)
#define Bit_2 (1 << 2)
#define Bit_3 (1 << 3)
#define Bit_4 (1 << 4)
#define Bit_5 (1 << 5)
#define Bit_6 (1 << 6)
#define Bit_7 (1 << 7)
#define Bit_8 (1 << 8)
#define Bit_9 (1 << 9)
#define Bit_10 (1 << 10)
#define Bit_11 (1 << 11)
#define Bit_12 (1 << 12)
#define Bit_13 (1 << 13)
#define Bit_14 (1 << 14)
#define Bit_15 (1 << 15)
#define Bit_16 (1 << 16)
#define Bit_17 (1 << 17)
#define Bit_18 (1 << 18)
#define Bit_19 (1 << 19)
#define Bit_20 (1 << 20)
#define Bit_21 (1 << 21)
#define Bit_22 (1 << 22)
#define Bit_23 (1 << 23)
#define Bit_24 (1 << 24)
#define Bit_25 (1 << 25)
#define Bit_26 (1 << 26)
#define Bit_27 (1 << 27)
#define Bit_28 (1 << 28)
#define Bit_29 (1 << 29)
#define Bit_30 (1 << 30)
#define Bit_31 (1 << 31)
#define Byte_0 (0xFFU)
#define Byte_1 (0xFFU << 8)
#define Byte_2 (0xFFU << 16)
#define Byte_3 (0xFFU << 24)
#define Byte_4 (0xFFU << 32)
#define Byte_5 (0xFFU << 40)
#define Byte_6 (0xFFU << 48)
#define Byte_7 (0xFFU << 56)
#define bytes(n) (n)
#define Kbytes(n) ((n) << 10)
#define Mbytes(n) ((n) << 20)
#define Gbytes(n) (((u64)n) << 30)
#define Tbytes(n) (((u64)n) << 40)
#endif

View File

@ -0,0 +1,462 @@
/*
* Mr. 4th Dimention - Allen Webster
*
* 25.02.2016
*
* File editing view for 4coder
*
*/
// TOP
#define FCPP_STRING_IMPLEMENTATION
#include "4coder_string.h"
struct Struct_Field{
char *type;
char *name;
};
void to_lower(char *src, char *dst){
char *c, ch;
for (c = src; *c != 0; ++c){
ch = char_to_lower(*c);
*dst++ = ch;
}
*dst = 0;
}
void to_upper(char *src, char *dst){
char *c, ch;
for (c = src; *c != 0; ++c){
ch = char_to_upper(*c);
*dst++ = ch;
}
*dst = 0;
}
void to_camel(char *src, char *dst){
char *c, ch;
int is_first = 1;
for (c = src; *c != 0; ++c){
ch = *c;
if (char_is_alpha_numeric_true(ch)){
if (is_first){
is_first = 0;
ch = char_to_upper(ch);
}
else{
ch = char_to_lower(ch);
}
}
else{
is_first = 1;
}
*dst++ = ch;
}
*dst = 0;
}
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
void struct_begin(FILE *file, char *name){
fprintf(file, "struct %s{\n", name);
}
void struct_fields(FILE *file, Struct_Field *fields, int count){
int i;
for (i = 0; i < count; ++i){
fprintf(file, " %s %s;\n", fields[i].type, fields[i].name);
}
}
void struct_end(FILE *file){
fprintf(file, "};\n\n");
}
void enum_begin(FILE *file, char *name){
fprintf(file, "enum %s{\n", name);
}
char *keys_that_need_codes[] = {
"back",
"up",
"down",
"left",
"right",
"del",
"insert",
"home",
"end",
"page_up",
"page_down",
"esc",
"f1",
"f2",
"f3",
"f4",
"f5",
"f6",
"f7",
"f8",
"f9",
"f10",
"f11",
"f12",
"f13",
"f14",
"f15",
"f16",
};
char* generate_keycode_enum(){
FILE *file;
char *filename = "4coder_keycodes.h";
int i, count;
unsigned char code = 1;
file = fopen(filename, "wb");
fprintf(file, "enum Key_Code{\n");
count = ArrayCount(keys_that_need_codes);
for (i = 0; i < count;){
if (strcmp(keys_that_need_codes[i], "f1") == 0 && code < 0x7F){
code = 0x7F;
}
switch (code){
case '\n': code++; break;
case '\t': code++; break;
case 0x20: code = 0x7F; break;
default:
fprintf(file, " key_%s = %d,\n", keys_that_need_codes[i++], code++);
break;
}
}
fprintf(file, "};\n");
fclose(file);
return(filename);
}
//////////////////////////////////////////////////////////////////////////////////////////////////
char daction_enum_name[] = "Action_Type";
char *daction_enum[] = {
"OPEN",
"OPEN_BACKGROUND",
"SET_LINE",
"SAVE_AS",
"SAVE",
"NEW",
"SWITCH",
"TRY_KILL",
"KILL",
"TOUCH_FILE",
};
char str_alloc_copy[] =
"internal String\n"
"str_alloc_copy(General_Memory *general, String str){\n"
" String result;\n"
" result.memory_size = str.memory_size + 1;\n"
" result.size = str.size;\n"
" result.str = (char*)general_memory_allocate(general, result.memory_size, 0);\n"
" memcpy(result.str, str.str, str.size);\n"
" result.str[result.size] = 0;\n"
" return(result);"
"}\n\n";
char daction_name[] = "Delayed_Action";
Struct_Field daction_fields[] = {
{"Action_Type", "type"},
};
Struct_Field daction_fields_primary[] = {
{"String", "string"},
{"Panel*", "panel"},
{"Editing_File*", "file"},
{"i32", "integer"},
};
enum Daction_Field_Handle{
dfph_null,
dfph_string,
dfph_panel,
dfph_file,
dfph_integer,
};
Daction_Field_Handle dact_param_sets[] = {
dfph_string, dfph_null,
dfph_panel, dfph_null,
dfph_file, dfph_null,
dfph_file, dfph_panel, dfph_null,
dfph_string, dfph_panel, dfph_null,
dfph_string, dfph_file, dfph_null,
dfph_panel, dfph_integer, dfph_null,
};
char delay_name[] = "Delay";
Struct_Field delay_fields[] = {
{"General_Memory*", "general"},
{"Delayed_Action*", "acts"},
{"i32", "count"},
{"i32", "max"},
};
char delayed_action_function_top[] =
"inline Delayed_Action*\n"
"delayed_action_(Delay *delay, Action_Type type";
char delayed_action_function_bottom[] =
"){\n"
" Delayed_Action *result;\n"
" if (delay->count == delay->max){\n"
" delay->max *= 2;\n"
" delay->acts = (Delayed_Action*)general_memory_reallocate("
"delay->general, delay->acts, delay->count*sizeof(Delayed_Action), delay->max*sizeof(Delayed_Action), 0);\n"
" }\n"
" result = delay->acts + delay->count++;\n"
" *result = {};\n"
" result->type = type;\n"
" return(result);\n"
"}\n\n";
char delayed_action_special_param[] = ", %s %s";
char delayed_action_specialized_middle[] =
"){\n"
" Delayed_Action *result;\n"
" result = delayed_action_(delay, type);\n";
char delayed_action_special_line[] =
" result->%s = %s;\n";
char delayed_action_special_string_line[] =
" result->%s = str_alloc_copy(delay->general, %s);\n";
char delayed_action_specialized_bottom[] =
" return(result);\n"
"}\n\n";
char delayed_action_macro[] =
"#define delayed_%s(delay, ...) delayed_action_(delay, DACT_%s, __VA_ARGS__)\n";
char delayed_action_repush_function[] =
"inline Delayed_Action*\n"
"delayed_action_repush(Delay *delay, Delayed_Action *act){\n"
" Delayed_Action *new_act = delayed_action_(delay, (Action_Type)0);\n"
" *new_act = *act;\n"
" if (act->string.str){\n"
" new_act->string = str_alloc_copy(delay->general, act->string);\n"
" }\n"
" return(new_act);\n"
"}\n\n";
char* generate_delayed_action(){
FILE *file;
char *filename = "4ed_delay.cpp";
char scratch[256];
int i,j;
file = fopen(filename, "wb");
fprintf(file, "enum %s{\n", daction_enum_name);
for (i = 0; i < ArrayCount(daction_enum); ++i){
fprintf(file, " DACT_%s,\n", daction_enum[i]);
}
fprintf(file, "};\n\n");
struct_begin(file, daction_name);
struct_fields(file, daction_fields, ArrayCount(daction_fields));
struct_fields(file, daction_fields_primary, ArrayCount(daction_fields_primary));
struct_end(file);
struct_begin(file, delay_name);
struct_fields(file, delay_fields, ArrayCount(delay_fields));
struct_end(file);
fprintf(file, "%s", str_alloc_copy);
fprintf(file, "%s%s", delayed_action_function_top, delayed_action_function_bottom);
for (i = 0; i < ArrayCount(dact_param_sets); ++i){
j = i;
fprintf(file, "%s", delayed_action_function_top);
for (; dact_param_sets[i] != dfph_null; ++i){
Struct_Field field = daction_fields_primary[dact_param_sets[i] - 1];
fprintf(file, delayed_action_special_param, field.type, field.name);
}
fprintf(file, "%s", delayed_action_specialized_middle);
for (; dact_param_sets[j] != dfph_null; ++j){
int handle = (int)(dact_param_sets[j]);
Struct_Field field = daction_fields_primary[handle - 1];
if (handle == dfph_string){
fprintf(file, delayed_action_special_string_line, field.name, field.name);
}
else{
fprintf(file, delayed_action_special_line, field.name, field.name);
}
}
fprintf(file, "%s", delayed_action_specialized_bottom);
}
fprintf(file, "%s", delayed_action_repush_function);
for (i = 0; i < ArrayCount(daction_enum); ++i){
to_lower(daction_enum[i], scratch);
fprintf(file, delayed_action_macro, scratch, daction_enum[i]);
}
return(filename);
}
//////////////////////////////////////////////////////////////////////////////////////////////////
char* bar_style_fields[] = {
"bar",
"bar_active",
"base",
"pop1",
"pop2",
};
char* main_style_fields[] = {
"back",
"margin",
"margin_hover",
"margin_active",
"cursor",
"at_cursor",
"highlight",
"at_highlight",
"mark",
"default",
"comment",
"keyword",
"str_constant",
"char_constant",
"int_constant",
"float_constant",
"bool_constant",
"preproc",
"include",
"special_character",
"highlight_junk",
"highlight_white",
"paste",
"undo",
"next_undo",
};
static char*
make_style_tag(char *tag){
char *str;
int len;
len = (int)strlen(tag);
str = (char*)malloc(len + 1);
to_camel(tag, str);
str[len] = 0;
return(str);
}
char style_index_function_start[] =
"inline u32*\n"
"style_index_by_tag(Style_Main_Data *s, u32 tag){\n"
" u32 *result = 0;\n"
" switch (tag){\n";
char style_index_function_end[] =
" }\n"
" return(result);\n"
"}\n\n";
char style_case[] = " case Stag_%s: result = &s->%s_color; break;\n";
char style_info_case[] = " case Stag_%s: result = &s->file_info_style.%s_color; break;\n";
char* generate_style(){
char *filename = "4coder_style.h & 4ed_style.h";
char filename_4coder[] = "4coder_style.h";
char filename_4ed[] = "4ed_style.h";
FILE *file;
char *tag;
int count, i;
file = fopen(filename_4coder, "wb");
enum_begin(file, "Style_Tag");
{
count = ArrayCount(bar_style_fields);
for (i = 0; i < count; ++i){
tag = make_style_tag(bar_style_fields[i]);
fprintf(file, "Stag_%s,\n", tag);
free(tag);
}
count = ArrayCount(main_style_fields);
for (i = 0; i < count; ++i){
tag = make_style_tag(main_style_fields[i]);
fprintf(file, "Stag_%s,\n", tag);
free(tag);
}
}
struct_end(file);
fclose(file);
file = fopen(filename_4ed, "wb");
struct_begin(file, "Interactive_Style");
{
count = ArrayCount(bar_style_fields);
for (i = 0; i < count; ++i){
fprintf(file, "u32 %s_color;\n", bar_style_fields[i]);
}
}
struct_end(file);
struct_begin(file, "Style_Main_Data");
{
count = ArrayCount(main_style_fields);
for (i = 0; i < count; ++i){
fprintf(file, "u32 %s_color;\n", main_style_fields[i]);
}
fprintf(file, "Interactive_Style file_info_style;\n");
}
struct_end(file);
{
fprintf(file, "%s", style_index_function_start);
count = ArrayCount(bar_style_fields);
for (i = 0; i < count; ++i){
tag = make_style_tag(bar_style_fields[i]);
fprintf(file, style_info_case, tag, bar_style_fields[i]);
free(tag);
}
count = ArrayCount(main_style_fields);
for (i = 0; i < count; ++i){
tag = make_style_tag(main_style_fields[i]);
fprintf(file, style_case, tag, main_style_fields[i]);
free(tag);
}
fprintf(file, "%s", style_index_function_end);
}
fclose(file);
return(filename);
}
int main(){
char *filename;
filename = generate_keycode_enum();
printf("gen success: %s\n", filename);
filename = generate_delayed_action();
printf("gen success: %s\n", filename);
filename = generate_style();
printf("gen success: %s\n", filename);
}
// BOTTOM

View File

@ -0,0 +1,508 @@
/*
* Mr. 4th Dimention - Allen Webster
*
* 12.17.2014
*
* Rendering layer for project codename "4ed"
*
*/
// TOP
inline void
draw_set_clip(Render_Target *target, i32_Rect clip_box){
glScissor(clip_box.x0,
target->height - clip_box.y1,
clip_box.x1 - clip_box.x0,
clip_box.y1 - clip_box.y0);
}
inline void
draw_bind_texture(Render_Target *target, i32 texid){
if (target->bound_texture != texid){
glBindTexture(GL_TEXTURE_2D, texid);
target->bound_texture = texid;
}
}
inline void
draw_set_color(Render_Target *target, u32 color){
if (target->color != color){
target->color = color;
Vec4 c = unpack_color4(color);
glColor4f(c.r, c.g, c.b, c.a);
}
}
#define PutStruct(s,x) *(s*)(target->push_buffer + target->size) = x; target->size += sizeof(s)
internal void
draw_push_piece(Render_Target *target, Render_Piece_Combined piece){
PutStruct(Render_Piece_Header, piece.header);
switch (piece.header.type){
case piece_type_rectangle:
case piece_type_outline:
PutStruct(Render_Piece_Rectangle, piece.rectangle);
break;
case piece_type_gradient:
PutStruct(Render_Piece_Gradient, piece.gradient);
break;
case piece_type_glyph:
case piece_type_mono_glyph:
PutStruct(Render_Piece_Glyph, piece.glyph);
break;
case piece_type_mono_glyph_advance:
PutStruct(Render_Piece_Glyph_Advance, piece.glyph_advance);
break;
}
Assert(target->size <= target->max);
}
internal void
draw_push_piece_clip(Render_Target *target, i32_Rect clip_box){
// TODO(allen): optimize out if there are two clip box changes in a row
Render_Piece_Change_Clip clip;
Render_Piece_Header header;
header.type = piece_type_change_clip;
clip.box = clip_box;
PutStruct(Render_Piece_Header, header);
PutStruct(Render_Piece_Change_Clip, clip);
}
internal void
draw_push_clip(Render_Target *target, i32_Rect clip_box){
Assert(target->clip_top == -1 ||
fits_inside(clip_box, target->clip_boxes[target->clip_top]));
Assert(target->clip_top+1 < ArrayCount(target->clip_boxes));
target->clip_boxes[++target->clip_top] = clip_box;
draw_push_piece_clip(target, clip_box);
}
internal void
draw_pop_clip(Render_Target *target){
i32_Rect clip_box;
Assert(target->clip_top > 0);
--target->clip_top;
clip_box = target->clip_boxes[target->clip_top];
draw_push_piece_clip(target, clip_box);
}
#define ExtractStruct(s) ((s*)cursor); cursor += sizeof(s)
inline void
private_draw_rectangle(Render_Target *target, f32_Rect rect, u32 color){
draw_set_color(target, color);
draw_bind_texture(target, 0);
glBegin(GL_QUADS);
{
glVertex2f(rect.x0, rect.y0);
glVertex2f(rect.x0, rect.y1);
glVertex2f(rect.x1, rect.y1);
glVertex2f(rect.x1, rect.y0);
}
glEnd();
}
inline void
private_draw_rectangle_outline(Render_Target *target, f32_Rect rect, u32 color){
f32_Rect r;
r.x0 = rect.x0 + .5f;
r.y0 = rect.y0 + .5f;
r.x1 = rect.x1 - .5f;
r.y1 = rect.y1 - .5f;
draw_set_color(target, color);
draw_bind_texture(target, 0);
glBegin(GL_LINE_STRIP);
{
glVertex2f(r.x0, r.y0);
glVertex2f(r.x1, r.y0);
glVertex2f(r.x1, r.y1);
glVertex2f(r.x0, r.y1);
glVertex2f(r.x0, r.y0);
}
glEnd();
}
inline void
private_draw_gradient(Render_Target *target, f32_Rect rect,
Vec4 color_left, Vec4 color_right){
Vec4 cl = color_left;
Vec4 cr = color_right;
draw_bind_texture(target, 0);
glBegin(GL_QUADS);
{
glColor4f(cl.r, cl.g, cl.b, cl.a);
glVertex2f(rect.x0, rect.y0);
glVertex2f(rect.x0, rect.y1);
glColor4f(cr.r, cr.g, cr.b, cr.a);
glVertex2f(rect.x1, rect.y1);
glVertex2f(rect.x1, rect.y0);
}
glEnd();
}
inline void
private_draw_glyph(Render_Target *target, Render_Font *font,
u8 character, f32 x, f32 y, u32 color){
f32 x_shift, y_shift;
x_shift = 0;
y_shift = (f32)font->ascent;
x += x_shift;
y += y_shift;
stbtt_aligned_quad q;
stbtt_GetPackedQuad(font->chardata, font->tex_width, font->tex_height,
character, &x, &y, &q, 0);
draw_set_color(target, color);
draw_bind_texture(target, font->tex);
glBegin(GL_QUADS);
{
glTexCoord2f(q.s0, q.t1); glVertex2f(q.x0, q.y1);
glTexCoord2f(q.s1, q.t1); glVertex2f(q.x1, q.y1);
glTexCoord2f(q.s1, q.t0); glVertex2f(q.x1, q.y0);
glTexCoord2f(q.s0, q.t0); glVertex2f(q.x0, q.y0);
}
glEnd();
}
inline void
private_draw_glyph_mono(Render_Target *target, Render_Font *font, u8 character,
f32 x, f32 y, f32 advance, u32 color){
f32 x_shift, y_shift;
i32 left = font->chardata[character].x0;
i32 right = font->chardata[character].x1;
i32 width = (right - left);
x_shift = (f32)(advance - width) * .5f - font->chardata[character].xoff;
y_shift = (f32)font->ascent;
x += x_shift;
y += y_shift;
stbtt_aligned_quad q;
stbtt_GetPackedQuad(font->chardata, font->tex_width, font->tex_height,
character, &x, &y, &q, 0);
draw_set_color(target, color);
draw_bind_texture(target, font->tex);
glBegin(GL_QUADS);
{
glTexCoord2f(q.s0, q.t1); glVertex2f(q.x0, q.y1);
glTexCoord2f(q.s1, q.t1); glVertex2f(q.x1, q.y1);
glTexCoord2f(q.s1, q.t0); glVertex2f(q.x1, q.y0);
glTexCoord2f(q.s0, q.t0); glVertex2f(q.x0, q.y0);
}
glEnd();
}
inline void
private_draw_glyph_mono(Render_Target *target, Render_Font *font, u8 character,
real32 x, real32 y, u32 color){
private_draw_glyph_mono(target, font, character, x, y, (f32)font->advance, color);
}
internal void
launch_rendering(Render_Target *target){
byte *cursor = target->push_buffer;
byte *cursor_end = cursor + target->size;
for (; cursor < cursor_end;){
Render_Piece_Header *header = ExtractStruct(Render_Piece_Header);
i32 type = header->type;
switch (type){
case piece_type_rectangle:
{
Render_Piece_Rectangle *rectangle =
ExtractStruct(Render_Piece_Rectangle);
private_draw_rectangle(target, rectangle->rect, rectangle->color);
}break;
case piece_type_outline:
{
Render_Piece_Rectangle *rectangle =
ExtractStruct(Render_Piece_Rectangle);
private_draw_rectangle_outline(target, rectangle->rect, rectangle->color);
}break;
case piece_type_gradient:
{
Render_Piece_Gradient *gradient =
ExtractStruct(Render_Piece_Gradient);
private_draw_gradient(target, gradient->rect,
unpack_color4(gradient->left_color),
unpack_color4(gradient->right_color));
}break;
case piece_type_glyph:
{
Render_Piece_Glyph *glyph =
ExtractStruct(Render_Piece_Glyph);
Render_Font *font = get_font_info(&target->font_set, glyph->font_id)->font;
if (font)
private_draw_glyph(target, font, glyph->character,
glyph->pos.x, glyph->pos.y, glyph->color);
}break;
case piece_type_mono_glyph:
{
Render_Piece_Glyph *glyph =
ExtractStruct(Render_Piece_Glyph);
Render_Font *font = get_font_info(&target->font_set, glyph->font_id)->font;
if (font)
private_draw_glyph_mono(target, font, glyph->character,
glyph->pos.x, glyph->pos.y, glyph->color);
}break;
case piece_type_mono_glyph_advance:
{
Render_Piece_Glyph_Advance *glyph =
ExtractStruct(Render_Piece_Glyph_Advance);
Render_Font *font = get_font_info(&target->font_set, glyph->font_id)->font;
if (font)
private_draw_glyph_mono(target, font, glyph->character,
glyph->pos.x, glyph->pos.y,
glyph->advance, glyph->color);
}break;
case piece_type_change_clip:
{
Render_Piece_Change_Clip *clip =
ExtractStruct(Render_Piece_Change_Clip);
draw_set_clip(target, clip->box);
}break;
}
}
}
#undef ExtractStruct
internal i32
draw_font_info_load(Partition *partition,
char *filename_untranslated,
i32 pt_size, i32 *height, i32 *advance){
char space_[1024];
String filename = make_fixed_width_string(space_);
b32 translate_success = system_to_binary_path(&filename, filename_untranslated);
if (!translate_success) return 0;
i32 result = 1;
Data file;
file = system_load_file(filename.str);
Temp_Memory temp = begin_temp_memory(partition);
stbtt_packedchar *chardata = push_array(partition, stbtt_packedchar, 256);
i32 oversample = 2;
i32 tex_width, tex_height;
tex_width = pt_size*128*oversample;
tex_height = pt_size*2*oversample;
void *block = push_block(partition, tex_width * tex_height);
if (!file.data){
result = 0;
}
else{
stbtt_fontinfo font;
if (!stbtt_InitFont(&font, (u8*)file.data, 0)){
result = 0;
}
else{
i32 ascent, descent, line_gap;
f32 scale;
stbtt_GetFontVMetrics(&font, &ascent, &descent, &line_gap);
scale = stbtt_ScaleForPixelHeight(&font, (f32)pt_size);
f32 scaled_ascent, scaled_descent, scaled_line_gap;
scaled_ascent = scale*ascent;
scaled_descent = scale*descent;
scaled_line_gap = scale*line_gap;
i32 font_height = (i32)(scaled_ascent - scaled_descent + scaled_line_gap);
stbtt_pack_context spc;
if (stbtt_PackBegin(&spc, (u8*)block, tex_width, tex_height, tex_width, 1, partition)){
stbtt_PackSetOversampling(&spc, oversample, oversample);
if (stbtt_PackFontRange(&spc, (u8*)file.data, 0,
STBTT_POINT_SIZE((f32)pt_size), 0, 128, chardata)){
// do nothing
}
else{
result = 0;
}
stbtt_PackEnd(&spc);
}
else{
result = 0;
}
if (result){
i32 max_advance = 0;
for (u8 code_point = 0; code_point < 128; ++code_point){
if (stbtt_FindGlyphIndex(&font, code_point) != 0){
i32 adv = CEIL32(chardata[code_point].xadvance);
if (max_advance < adv){
max_advance = adv;
}
}
}
*height = font_height;
*advance = max_advance - 1;
}
}
system_free_memory(file.data);
}
end_temp_memory(temp);
return(result);
}
internal i32
draw_font_load(void *base_block, i32 size,
Render_Font *font_out,
char *filename_untranslated,
i32 pt_size,
i32 tab_width){
char space_[1024];
String filename = make_fixed_width_string(space_);
b32 translate_success = system_to_binary_path(&filename, filename_untranslated);
if (!translate_success) return 0;
i32 result = 1;
Data file;
file = system_load_file(filename.str);
Partition partition_ = partition_open(base_block, size);
Partition *partition = &partition_;
stbtt_packedchar *chardata = font_out->chardata;
i32 oversample = 2;
i32 tex_width, tex_height;
tex_width = pt_size*128*oversample;
tex_height = pt_size*2*oversample;
void *block = push_block(partition, tex_width * tex_height);
if (!file.data){
result = 0;
}
else{
stbtt_fontinfo font;
if (!stbtt_InitFont(&font, (u8*)file.data, 0)){
result = 0;
}
else{
i32 ascent, descent, line_gap;
f32 scale;
stbtt_GetFontVMetrics(&font, &ascent, &descent, &line_gap);
scale = stbtt_ScaleForPixelHeight(&font, (f32)pt_size);
f32 scaled_ascent, scaled_descent, scaled_line_gap;
scaled_ascent = scale*ascent;
scaled_descent = scale*descent;
scaled_line_gap = scale*line_gap;
font_out->height = (i32)(scaled_ascent - scaled_descent + scaled_line_gap);
font_out->ascent = (i32)(scaled_ascent);
font_out->descent = (i32)(scaled_descent);
font_out->line_skip = (i32)(scaled_line_gap);
font_out->tex_width = tex_width;
font_out->tex_height = tex_height;
stbtt_pack_context spc;
if (stbtt_PackBegin(&spc, (u8*)block, tex_width, tex_height, tex_width, 1, partition)){
stbtt_PackSetOversampling(&spc, oversample, oversample);
if (stbtt_PackFontRange(&spc, (u8*)file.data, 0,
STBTT_POINT_SIZE((f32)pt_size), 0, 128, chardata)){
// do nothing
}
else{
result = 0;
}
stbtt_PackEnd(&spc);
}
else{
result = 0;
}
if (result){
GLuint font_tex;
glGenTextures(1, &font_tex);
glBindTexture(GL_TEXTURE_2D, font_tex);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexImage2D(GL_TEXTURE_2D, 0, GL_ALPHA, tex_width, tex_height, 0, GL_ALPHA, GL_UNSIGNED_BYTE, block);
font_out->tex = font_tex;
glBindTexture(GL_TEXTURE_2D, 0);
font_out->chardata['\r'] = font_out->chardata[' '];
font_out->chardata['\n'] = font_out->chardata[' '];
font_out->chardata['\t'] = font_out->chardata[' '];
font_out->chardata['\t'].xadvance *= tab_width;
i32 max_advance = 0;
for (u8 code_point = 0; code_point < 128; ++code_point){
if (stbtt_FindGlyphIndex(&font, code_point) != 0){
font_out->glyphs[code_point].exists = 1;
i32 advance = CEIL32(font_out->chardata[code_point].xadvance);
if (max_advance < advance) max_advance = advance;
font_out->advance_data[code_point] = font_out->chardata[code_point].xadvance;
}
else if (code_point == '\r' || code_point == '\n' || code_point == '\t'){
font_out->advance_data[code_point] = font_out->chardata[code_point].xadvance;
}
}
font_out->advance = max_advance - 1;
}
}
system_free_memory(file.data);
}
return result;
}
internal
Release_Font_Sig(draw_release_font){
glDeleteTextures(1, &font->tex);
font->tex = 0;
}
// BOTTOM

View File

@ -0,0 +1,206 @@
/*
* Mr. 4th Dimention - Allen Webster
*
* 17.12.2014
*
* Rendering layer for project codename "4ed"
*
*/
// TOP
#ifndef FRED_RENDERING_H
#define FRED_RENDERING_H
internal void*
part_alloc(int size, void *context){
Partition *part = (Partition*)context;
void *result = push_block(part, size);
return(result);
}
internal void
part_free(void *ptr, void *context){
}
#define STBTT_malloc part_alloc
#define STBTT_free part_free
#define STB_TRUETYPE_IMPLEMENTATION
#include "stb_truetype.h"
struct Glyph_Data{
b32 exists;
};
struct Render_Font{
char name_[24];
String name;
b32 loaded;
Glyph_Data glyphs[256];
stbtt_packedchar chardata[256];
float advance_data[256];
i32 height, ascent, descent, line_skip;
i32 advance;
u32 tex;
i32 tex_width, tex_height;
};
enum Render_Piece_Type{
piece_type_rectangle,
piece_type_outline,
piece_type_gradient,
piece_type_glyph,
piece_type_mono_glyph,
piece_type_mono_glyph_advance,
piece_type_change_clip
};
struct Render_Piece_Header{
i32 type;
};
struct Render_Piece_Rectangle{
f32_Rect rect;
u32 color;
};
struct Render_Piece_Gradient{
f32_Rect rect;
u32 left_color, right_color;
};
struct Render_Piece_Glyph{
Vec2 pos;
u32 color;
i16 font_id;
u8 character;
};
struct Render_Piece_Glyph_Advance{
Vec2 pos;
u32 color;
f32 advance;
i16 font_id;
u8 character;
};
struct Render_Piece_Change_Clip{
i32_Rect box;
};
struct Render_Piece_Combined{
Render_Piece_Header header;
union{
Render_Piece_Rectangle rectangle;
Render_Piece_Gradient gradient;
Render_Piece_Glyph glyph;
Render_Piece_Glyph_Advance glyph_advance;
};
};
struct Render_Target;
#define Draw_Push_Clip_Sig(name) void name(Render_Target *target, i32_Rect clip_box)
typedef Draw_Push_Clip_Sig(Draw_Push_Clip);
#define Draw_Pop_Clip_Sig(name) void name(Render_Target *target)
typedef Draw_Pop_Clip_Sig(Draw_Pop_Clip);
#define Draw_Push_Piece_Sig(name) void name(Render_Target *target, Render_Piece_Combined piece)
typedef Draw_Push_Piece_Sig(Draw_Push_Piece);
#define Font_Load_Sig(name) i32 name( \
Render_Font *font_out, \
char *filename, \
i32 pt_size, \
i32 tab_width)
typedef Font_Load_Sig(Font_Load);
#define Font_Info_Load_Sig(name) i32 name( \
Partition *partition, \
char *filename, \
i32 pt_size, \
i32 *height, \
i32 *advance)
typedef Font_Info_Load_Sig(Font_Info_Load);
#define Release_Font_Sig(name) void name(Render_Font *font)
typedef Release_Font_Sig(Release_Font);
struct Font_Table_Entry{
u32 hash;
String name;
i16 font_id;
};
struct Font_Info{
Render_Font *font;
String filename;
String name;
i32 height, advance;
i32 pt_size;
};
struct Font_Slot{
Font_Slot *next, *prev;
i16 font_id;
u8 padding[14];
};
struct Font_Set{
Font_Info *info;
Font_Table_Entry *entries;
u32 count, max;
void *font_block;
Font_Slot free_slots;
Font_Slot used_slots;
Font_Info_Load *font_info_load;
Font_Load *font_load;
Release_Font *release_font;
b8 *font_used_flags;
i16 used_this_frame;
i16 live_max;
};
struct Render_Target{
void *handle;
void *context;
i32_Rect clip_boxes[5];
i32 clip_top;
i32 width, height;
i32 bound_texture;
u32 color;
// TODO(allen): change this to a Partition
byte *push_buffer;
i32 size, max;
// TODO(allen): rename this to font_partition
Font_Set font_set;
Partition *partition;
Draw_Push_Clip *push_clip;
Draw_Pop_Clip *pop_clip;
Draw_Push_Piece *push_piece;
};
inline i32_Rect
rect_from_target(Render_Target *target){
return i32R(0, 0, target->width, target->height);
}
inline Font_Info*
get_font_info(Font_Set *set, i16 font_id){
Font_Info *result = set->info + font_id - 1;
return(result);
}
#endif
// BOTTOM

View File

@ -0,0 +1,267 @@
/*
* Mr. 4th Dimention - Allen Webster
*
* 12.17.2014
*
* Rendering layer for project codename "4ed"
*
*/
// TOP
inline void
draw_push_clip(Render_Target *target, i32_Rect clip_box){
target->push_clip(target, clip_box);
}
inline void
draw_pop_clip(Render_Target *target){
target->pop_clip(target);
}
internal void
begin_render_section(Render_Target *target, System_Functions *system){
Font_Set *font_set = &target->font_set;
system->acquire_lock(RENDER_LOCK);
font_set->used_this_frame = 0;
memset(font_set->font_used_flags, 0, font_set->max);
target->size = 0;
target->clip_top = -1;
i32_Rect clip;
clip.x0 = 0;
clip.y0 = 0;
clip.x1 = target->width;
clip.y1 = target->height;
draw_push_clip(target, clip);
}
internal void
end_render_section(Render_Target *target, System_Functions *system){
Assert(target->clip_top == 0);
system->release_lock(RENDER_LOCK);
}
internal void
draw_rectangle(Render_Target *target, i32_Rect rect, u32 color){
Render_Piece_Combined piece;
piece.header.type = piece_type_rectangle;
piece.rectangle.rect = f32R(rect);
piece.rectangle.color = color;
target->push_piece(target, piece);
}
internal void
draw_rectangle(Render_Target *target, f32_Rect rect, u32 color){
Render_Piece_Combined piece;
piece.header.type = piece_type_rectangle;
piece.rectangle.rect = rect;
piece.rectangle.color = color;
target->push_piece(target, piece);
}
internal void
draw_gradient_2corner_clipped(Render_Target *target, f32_Rect rect,
Vec4 left_color, Vec4 right_color){
Render_Piece_Combined piece;
piece.header.type = piece_type_gradient;
piece.gradient.rect = rect;
piece.gradient.left_color = pack_color4(left_color);
piece.gradient.right_color = pack_color4(right_color);
target->push_piece(target, piece);
}
inline void
draw_gradient_2corner_clipped(Render_Target *target, f32 l, f32 t, f32 r, f32 b,
Vec4 color_left, Vec4 color_right){
draw_gradient_2corner_clipped(target, f32R(l,t,r,b), color_left, color_right);
}
internal void
draw_rectangle_outline(Render_Target *target, f32_Rect rect, u32 color){
Render_Piece_Combined piece;
piece.header.type = piece_type_outline;
piece.rectangle.rect = rect;
piece.rectangle.color = color;
target->push_piece(target, piece);
}
inline void
draw_rectangle_outline(Render_Target *target, i32_Rect rect, u32 color){
draw_rectangle_outline(target, f32R(rect), color);
}
internal void
draw_margin(Render_Target *target, i32_Rect outer, i32_Rect inner, u32 color){
draw_rectangle(target, i32R(outer.x0, outer.y0, outer.x1, inner.y0), color);
draw_rectangle(target, i32R(outer.x0, inner.y1, outer.x1, outer.y1), color);
draw_rectangle(target, i32R(outer.x0, inner.y0, inner.x0, inner.y1), color);
draw_rectangle(target, i32R(inner.x1, inner.y0, outer.x1, inner.y1), color);
}
inline void
draw_margin(Render_Target *target, i32_Rect outer, i32 width, u32 color){
i32_Rect inner = get_inner_rect(outer, width);
draw_margin(target, outer, inner, color);
}
inline internal i32
font_predict_size(i32 pt_size){
return pt_size*pt_size*128;
}
internal void
font_set_tabwidth(Render_Font *font, i32 tab_width){
font->chardata['\t'].xadvance *= font->chardata[' '].xadvance * tab_width;
}
internal void
font_draw_glyph_mono(Render_Target *target, i16 font_id,
u8 character, f32 x, f32 y, f32 advance, u32 color){
Render_Piece_Combined piece;
piece.header.type = piece_type_mono_glyph;
piece.glyph.pos.x = x;
piece.glyph.pos.y = y;
piece.glyph.color = color;
piece.glyph.font_id = font_id;
piece.glyph.character = character;
target->push_piece(target, piece);
font_set_use(target->partition, &target->font_set, font_id);
}
inline void
font_draw_glyph_mono(Render_Target *target, i16 font_id,
u8 character, f32 x, f32 y, u32 color){
f32 advance = (f32)get_font_info(&target->font_set, font_id)->advance;
font_draw_glyph_mono(target, font_id, character, x, y, advance, color);
}
internal void
font_draw_glyph(Render_Target *target, i16 font_id,
u8 character, f32 x, f32 y, u32 color){
Render_Piece_Combined piece;
piece.header.type = piece_type_glyph;
piece.glyph.pos.x = x;
piece.glyph.pos.y = y;
piece.glyph.color = color;
piece.glyph.font_id = font_id;
piece.glyph.character = character;
target->push_piece(target, piece);
font_set_use(target->partition, &target->font_set, font_id);
}
inline f32
font_get_glyph_width(Render_Target *target, i16 font_id, u16 character){
Render_Font *font = get_font_info(&target->font_set, font_id)->font;
f32 result = 0.f;
if (font) result = font->chardata[character].xadvance;
return (result);
}
internal f32
font_string_width(Render_Target *target, i16 font_id, char *str){
f32 x = 0;
for (i32 i = 0; str[i]; ++i){
u8 c = str[i];
// TODO(allen): Someday let's not punt on the the unicode rendering
c = c % 128;
x += font_get_glyph_width(target, font_id, c);
}
return x;
}
internal f32
font_string_width(Render_Target *target, i16 font_id, String str){
f32 x = 0;
for (i32 i = 0; i < str.size; ++i){
u8 c = str.str[i];
// TODO(allen): Someday let's not punt on the the unicode rendering
c = c % 128;
x += font_get_glyph_width(target, font_id, c);
}
return x;
}
internal i32
draw_string(Render_Target *target, i16 font_id,
char *str, i32 x_, i32 y, u32 color){
real32 x = (real32)x_;
for (i32 i = 0; str[i]; ++i){
u8 c = str[i];
// TODO(allen): Someday let's not punt on the the unicode rendering
c = c % 128;
font_draw_glyph(target, font_id, c, x, (f32)y, color);
x += font_get_glyph_width(target, font_id, c);
}
return CEIL32(x);
}
internal f32
draw_string_mono(Render_Target *target, i16 font_id,
char *str, f32 x, f32 y, f32 advance, u32 color){
for (i32 i = 0; str[i]; ++i){
u8 c = str[i];
// TODO(allen): Someday let's not punt on the the unicode rendering
c = c % 128;
font_draw_glyph_mono(target, font_id, c, x, y, advance, color);
x += advance;
}
return x;
}
internal i32
draw_string(Render_Target *target, i16 font_id,
String str, i32 x_, i32 y, u32 color){
f32 x = (f32)x_;
for (i32 i = 0; i < str.size; ++i){
u8 c = str.str[i];
// TODO(allen): Someday let's not punt on the the unicode rendering
c = c % 128;
font_draw_glyph(target, font_id, c,
x, (f32)y, color);
x += font_get_glyph_width(target, font_id, c);
}
return CEIL32(x);
}
internal f32
draw_string_mono(Render_Target *target, i16 font_id,
String str, f32 x, f32 y, f32 advance, u32 color){
for (i32 i = 0; i < str.size; ++i){
u8 c = str.str[i];
// TODO(allen): Someday let's not punt on the the unicode rendering
c = c % 128;
font_draw_glyph_mono(target, font_id, c, x, y, advance, color);
x += advance;
}
return x;
}
internal f32
font_get_max_width(Font_Set *font_set, i16 font_id, char *characters){
Render_Font *font = get_font_info(font_set, font_id)->font;
f32 cx, x = 0;
if (font){
stbtt_packedchar *chardata = font->chardata;
for (i32 i = 0; characters[i]; ++i){
cx = chardata[characters[i]].xadvance;
if (x < cx) x = cx;
}
}
return x;
}
internal f32
font_get_string_width(Render_Target *target, i16 font_id, String string){
f32 result = 0;
for (i32 i = 0; i < string.size; ++i){
u8 c = string.str[i];
// TODO(allen): Someday let's not punt on the the unicode rendering
c = c % 128;
font_get_glyph_width(target, font_id, c);
}
return result;
}
// BOTTOM

View File

@ -0,0 +1,102 @@
/*
* Mr. 4th Dimention - Allen Webster
*
* 28.08.2015
*
* Styles for 4coder
*
*/
// TOP
// TODO(allen):
// Font changing UI should be in the library menu now, it's not tied to the fonts any more
// Get the import export stuff up and running for styles again
struct Style_Font{
i16 font_id;
i16 font_changed;
};
struct Style{
char name_[24];
String name;
Style_Main_Data main;
};
internal void
style_copy(Style *dst, Style *src){
*dst = *src;
dst->name.str = dst->name_;
}
internal void
style_set_name(Style *style, String name){
i32 count = ArrayCount(style->name_);
style->name = make_string(style->name_, 0, count - 1);
copy(&style->name, name);
terminate_with_null(&style->name);
}
struct Style_Library{
Style styles[64];
i32 count, max;
};
#if 0
struct Style_File_Format{
i32 name_size;
char name[24];
i32 color_specifier_count;
};
internal b32
style_library_add(Style_Library *library, Style *style){
b32 result = 0;
i32 count = library->count;
String my_name = style->name;
Style *ostyle = library->styles;
Style *out = 0;
// TODO(allen): hashtable for name lookup?
for (i32 i = 0; i < count; ++i, ++ostyle){
if (match(my_name, ostyle->name)){
out = ostyle;
break;
}
}
if (!out && count < library->max){
out = library->styles + library->count++;
}
if (out){
style_copy(out, style);
result = 1;
}
return result;
}
internal Style_File_Format*
style_format_for_file(Font_Set *set, Style *style, Style_File_Format *out){
out->name_size = style->name.size;
memcpy(out->name, style->name.str, ArrayCount(out->name));
Style_Color_Specifier *spec = (Style_Color_Specifier*)(out + 1);
i32 count = 0;
for (u32 i = 0; i < Stag_Count; ++i){
u32 *color = style_index_by_tag(style, i);
if (color){
spec->tag = i;
spec->color = *color;
++count;
++spec;
}
}
out->color_specifier_count = count;
return (Style_File_Format*)spec;
}
#endif
// BOTTOM

View File

@ -0,0 +1,75 @@
struct Interactive_Style{
u32 bar_color;
u32 bar_active_color;
u32 base_color;
u32 pop1_color;
u32 pop2_color;
};
struct Style_Main_Data{
u32 back_color;
u32 margin_color;
u32 margin_hover_color;
u32 margin_active_color;
u32 cursor_color;
u32 at_cursor_color;
u32 highlight_color;
u32 at_highlight_color;
u32 mark_color;
u32 default_color;
u32 comment_color;
u32 keyword_color;
u32 str_constant_color;
u32 char_constant_color;
u32 int_constant_color;
u32 float_constant_color;
u32 bool_constant_color;
u32 preproc_color;
u32 include_color;
u32 special_character_color;
u32 highlight_junk_color;
u32 highlight_white_color;
u32 paste_color;
u32 undo_color;
u32 next_undo_color;
Interactive_Style file_info_style;
};
inline u32*
style_index_by_tag(Style_Main_Data *s, u32 tag){
u32 *result = 0;
switch (tag){
case Stag_Bar: result = &s->file_info_style.bar_color; break;
case Stag_Bar_Active: result = &s->file_info_style.bar_active_color; break;
case Stag_Base: result = &s->file_info_style.base_color; break;
case Stag_Pop1: result = &s->file_info_style.pop1_color; break;
case Stag_Pop2: result = &s->file_info_style.pop2_color; break;
case Stag_Back: result = &s->back_color; break;
case Stag_Margin: result = &s->margin_color; break;
case Stag_Margin_Hover: result = &s->margin_hover_color; break;
case Stag_Margin_Active: result = &s->margin_active_color; break;
case Stag_Cursor: result = &s->cursor_color; break;
case Stag_At_Cursor: result = &s->at_cursor_color; break;
case Stag_Highlight: result = &s->highlight_color; break;
case Stag_At_Highlight: result = &s->at_highlight_color; break;
case Stag_Mark: result = &s->mark_color; break;
case Stag_Default: result = &s->default_color; break;
case Stag_Comment: result = &s->comment_color; break;
case Stag_Keyword: result = &s->keyword_color; break;
case Stag_Str_Constant: result = &s->str_constant_color; break;
case Stag_Char_Constant: result = &s->char_constant_color; break;
case Stag_Int_Constant: result = &s->int_constant_color; break;
case Stag_Float_Constant: result = &s->float_constant_color; break;
case Stag_Bool_Constant: result = &s->bool_constant_color; break;
case Stag_Preproc: result = &s->preproc_color; break;
case Stag_Include: result = &s->include_color; break;
case Stag_Special_Character: result = &s->special_character_color; break;
case Stag_Highlight_Junk: result = &s->highlight_junk_color; break;
case Stag_Highlight_White: result = &s->highlight_white_color; break;
case Stag_Paste: result = &s->paste_color; break;
case Stag_Undo: result = &s->undo_color; break;
case Stag_Next_Undo: result = &s->next_undo_color; break;
}
return(result);
}

View File

@ -0,0 +1,253 @@
/*
* Mr. 4th Dimention - Allen Webster
*
* 21.01.2014
*
* System functions for project codename "4ed"
*
*/
// TOP
struct Plat_Handle{
u32 d[4];
};
struct Unique_Hash{
u32 d[4];
};
#define Sys_File_Time_Stamp_Sig(name) u64 name(char *filename)
typedef Sys_File_Time_Stamp_Sig(System_File_Time_Stamp);
// TODO(allen): make directory a char* to signal that it must be null terminated
#define Sys_Set_File_List_Sig(name) void name(File_List *file_list, String directory)
typedef Sys_Set_File_List_Sig(System_Set_File_List);
#define Sys_File_Unique_Hash_Sig(name) Unique_Hash name(char *filename)
typedef Sys_File_Unique_Hash_Sig(System_File_Unique_Hash);
#define Sys_Post_Clipboard_Sig(name) void name(String str)
typedef Sys_Post_Clipboard_Sig(System_Post_Clipboard);
#define Sys_Time_Sig(name) u64 name()
typedef Sys_Time_Sig(System_Time);
// cli
struct CLI_Handles{
Plat_Handle proc;
Plat_Handle out_read;
Plat_Handle out_write;
u32 scratch_space[4];
i32 exit;
};
#define Sys_CLI_Call_Sig(name) b32 name(char *path, char *script_name, CLI_Handles *cli_out)
typedef Sys_CLI_Call_Sig(System_CLI_Call);
#define Sys_CLI_Begin_Update_Sig(name) void name(CLI_Handles *cli)
typedef Sys_CLI_Begin_Update_Sig(System_CLI_Begin_Update);
#define Sys_CLI_Update_Step_Sig(name) b32 name(CLI_Handles *cli, char *dest, u32 max, u32 *amount)
typedef Sys_CLI_Update_Step_Sig(System_CLI_Update_Step);
#define Sys_CLI_End_Update_Sig(name) b32 name(CLI_Handles *cli)
typedef Sys_CLI_End_Update_Sig(System_CLI_End_Update);
// coroutine
#define Coroutine_Function_Sig(name) void name(struct Coroutine *coroutine)
typedef Coroutine_Function_Sig(Coroutine_Function);
struct Coroutine{
Plat_Handle plat_handle;
Coroutine_Function *func;
void *yield_handle;
void *in;
void *out;
};
#define Sys_Create_Coroutine_Sig(name) Coroutine *name(Coroutine_Function *func)
typedef Sys_Create_Coroutine_Sig(System_Create_Coroutine);
#define Sys_Launch_Coroutine_Sig(name) Coroutine *name(Coroutine *coroutine, void *in, void *out)
typedef Sys_Launch_Coroutine_Sig(System_Launch_Coroutine);
#define Sys_Resume_Coroutine_Sig(name) Coroutine *name(Coroutine *coroutine, void *in, void *out)
typedef Sys_Resume_Coroutine_Sig(System_Resume_Coroutine);
#define Sys_Yield_Coroutine_Sig(name) void name(Coroutine *coroutine)
typedef Sys_Yield_Coroutine_Sig(System_Yield_Coroutine);
// thread
struct Thread_Context;
enum Lock_ID{
FRAME_LOCK,
INPUT_LOCK,
FONT_LOCK,
RENDER_LOCK,
CANCEL_LOCK0,
CANCEL_LOCK1,
CANCEL_LOCK2,
CANCEL_LOCK3,
CANCEL_LOCK4,
CANCEL_LOCK5,
CANCEL_LOCK6,
CANCEL_LOCK7,
LOCK_COUNT
};
enum Thread_Group_ID{
BACKGROUND_THREADS,
THREAD_GROUP_COUNT
};
struct Thread_Memory{
void *data;
i32 size;
i32 id;
};
struct Thread_Exchange;
struct System_Functions;
#define Job_Callback_Sig(name) void name( \
System_Functions *system, Thread_Context *thread, Thread_Memory *memory, \
Thread_Exchange *exchange, void *data[2])
typedef Job_Callback_Sig(Job_Callback);
struct Job_Data{
Job_Callback *callback;
void *data[2];
i32 memory_request;
};
struct Full_Job_Data{
Job_Data job;
u32 job_memory_index;
u32 running_thread;
b32 finished;
u32 id;
};
struct Work_Queue{
Full_Job_Data jobs[256];
Plat_Handle semaphore;
volatile u32 write_position;
volatile u32 read_position;
};
#define THREAD_NOT_ASSIGNED 0xFFFFFFFF
#define JOB_ID_WRAP (ArrayCount(queue->jobs) * 4)
#define QUEUE_WRAP (ArrayCount(queue->jobs))
struct Thread_Exchange{
Work_Queue queues[THREAD_GROUP_COUNT];
volatile u32 force_redraw;
};
#define Sys_Post_Job_Sig(name) u32 name(Thread_Group_ID group_id, Job_Data job)
typedef Sys_Post_Job_Sig(System_Post_Job);
#define Sys_Cancel_Job_Sig(name) void name(Thread_Group_ID group_id, u32 job_id)
typedef Sys_Cancel_Job_Sig(System_Cancel_Job);
#define Sys_Grow_Thread_Memory_Sig(name) void name(Thread_Memory *memory)
typedef Sys_Grow_Thread_Memory_Sig(System_Grow_Thread_Memory);
#define Sys_Acquire_Lock_Sig(name) void name(i32 id)
typedef Sys_Acquire_Lock_Sig(System_Acquire_Lock);
#define Sys_Release_Lock_Sig(name) void name(i32 id)
typedef Sys_Release_Lock_Sig(System_Release_Lock);
// debug
#define INTERNAL_Sys_Sentinel_Sig(name) Bubble* name()
typedef INTERNAL_Sys_Sentinel_Sig(INTERNAL_System_Sentinel);
#define INTERNAL_Sys_Get_Thread_States_Sig(name) void name(Thread_Group_ID id, b8 *running, i32 *pending)
typedef INTERNAL_Sys_Get_Thread_States_Sig(INTERNAL_System_Get_Thread_States);
#define INTERNAL_Sys_Debug_Message_Sig(name) void name(char *message)
typedef INTERNAL_Sys_Debug_Message_Sig(INTERNAL_System_Debug_Message);
struct System_Functions{
// files: 3
System_File_Time_Stamp *file_time_stamp;
System_Set_File_List *set_file_list;
System_File_Unique_Hash *file_unique_hash;
// file system navigation (4coder_custom.h): 2
File_Exists_Function *file_exists;
Directory_CD_Function *directory_cd;
// clipboard: 1
System_Post_Clipboard *post_clipboard;
// time: 1
System_Time *time;
// coroutine: 4
System_Create_Coroutine *create_coroutine;
System_Launch_Coroutine *launch_coroutine;
System_Resume_Coroutine *resume_coroutine;
System_Yield_Coroutine *yield_coroutine;
// cli: 4
System_CLI_Call *cli_call;
System_CLI_Begin_Update *cli_begin_update;
System_CLI_Update_Step *cli_update_step;
System_CLI_End_Update *cli_end_update;
// threads: 5
System_Post_Job *post_job;
System_Cancel_Job *cancel_job;
System_Grow_Thread_Memory *grow_thread_memory;
System_Acquire_Lock *acquire_lock;
System_Release_Lock *release_lock;
// debug: 3
INTERNAL_System_Sentinel *internal_sentinel;
INTERNAL_System_Get_Thread_States *internal_get_thread_states;
INTERNAL_System_Debug_Message *internal_debug_message;
// non-function details
char slash;
};
#define FileNameMax (1 << 9)
struct File_Slot{
File_Slot *next, *prev;
byte *data;
i32 size, max;
char *filename;
i32 filename_len;
u32 flags;
};
enum File_Exchange_Flag{
FEx_Request = 0x1,
FEx_Ready = 0x2,
FEx_Not_Exist = 0x4,
FEx_Save = 0x8,
FEx_Save_Complete = 0x10,
FEx_Save_Failed = 0x20
};
struct File_Exchange{
File_Slot available, active, free_list;
File_Slot *files;
i32 num_active, max;
};
struct Exchange{
Thread_Exchange thread;
File_Exchange file;
};
// BOTTOM

View File

@ -0,0 +1,54 @@
/*
* Mr. 4th Dimention - Allen Webster
*
* 01.03.2016
*
* Templated code.
*
*/
// TOP
// NOTE(allen): This is an experiment, BUT remember a lot of people shit on templates.
// So if you start getting a wiff of stupidity from this back out immediately!
//
// experience 1: no badness, haven't seen any anoying template errors
// ...
template<typename T>
inline void
dll_init_sentinel(T *sentinel){
sentinel->next = sentinel;
sentinel->prev = sentinel;
}
template<typename T>
inline void
dll_insert(T *pos, T *v){
v->next = pos->next;
v->prev = pos;
pos->next = v;
v->next->prev = v;
}
template<typename T>
inline void
dll_insert_back(T *pos, T *v){
v->prev = pos->prev;
v->next = pos;
pos->prev = v;
v->prev->next = v;
}
template<typename T>
inline void
dll_remove(T *v){
v->next->prev = v->prev;
v->prev->next = v->next;
}
// for(dll_items(iterator, sentinel_ptr)){...}
#define dll_items(it, st) ((it) = (st)->next); ((it) != (st)); ((it) = (it)->next)
// BOTTOM

View File

@ -0,0 +1,360 @@
/*
* YOUR INFO HERE!
*/
// TOP
typedef unsigned int Fixed16_16;
struct Offset_Table{
Fixed16_16 version;
unsigned short num_tables;
unsigned short search_range;
unsigned short entry_selector;
unsigned short range_shift;
};
struct Table_Directory_Entry{
unsigned long tag;
unsigned long check_sum;
unsigned long offset;
unsigned long length;
};
#include <stdio.h>
#include <stdlib.h>
struct Data{
char *data;
int size;
};
Data
open_file(const char *filename){
Data result = {};
FILE *file;
file = fopen(filename, "rb");
if (file){
fseek(file, 0, SEEK_END);
result.size = ftell(file);
fseek(file, 0, SEEK_SET);
if (result.size > 0){
result.data = (char*)malloc(result.size);
fread(result.data, result.size, 1, file);
}
fclose(file);
}
return(result);
}
void
print(Offset_Table *offset){
printf("version %d\n", offset->version >> 16);
printf("number of tables %d\n", (int)(offset->num_tables));
printf("search range %d\n", (int)(offset->search_range));
printf("entry selector %d\n", (int)(offset->entry_selector));
printf("range shift %d\n", (int)(offset->range_shift));
}
void
print(Table_Directory_Entry *entry){
printf("tag %.4s\n", &entry->tag);
printf("check sum %08x\n", entry->check_sum);
printf("offset %d\n", entry->offset);
printf("length %d\n", entry->length);
}
void
byte_reverse(void *ptr, int len){
char *c;
int i,j;
char t;
c = (char*)ptr;
for (i = 0, j = len-1; i < j; ++i, --j){
t = c[i];
c[i] = c[j];
c[j] = t;
}
}
void
byte_fix(Offset_Table *offset){
byte_reverse(&offset->version, 4);
byte_reverse(&offset->num_tables, 2);
byte_reverse(&offset->search_range, 2);
byte_reverse(&offset->entry_selector, 2);
byte_reverse(&offset->range_shift, 2);
}
void
byte_fix(Table_Directory_Entry *entry){
byte_reverse(&entry->check_sum, 4);
byte_reverse(&entry->offset, 4);
byte_reverse(&entry->length, 4);
}
struct cmap_Header{
unsigned short version;
unsigned short num_subtables;
};
struct cmap_Subtable_Entry{
unsigned short plat_id;
unsigned short plat_encoding_id;
unsigned long offset_from_cmap;
};
void
byte_fix(cmap_Header *header){
byte_reverse(&header->version, 2);
byte_reverse(&header->num_subtables, 2);
}
void
print(cmap_Header *header){
printf("cmap tables:\n");
printf("\tversion %d\n", (int)(header->version));
printf("\tsubtables %d\n", (int)(header->num_subtables));
}
void
byte_fix(cmap_Subtable_Entry *entry){
byte_reverse(&entry->plat_id, 2);
byte_reverse(&entry->plat_encoding_id, 2);
byte_reverse(&entry->offset_from_cmap, 4);
}
struct cmap_Subtable_Format4_Header{
unsigned short format;
unsigned short length;
unsigned short version;
unsigned short segment_count_2;
unsigned short search_range;
unsigned short entry_selector;
unsigned short range_shift;
};
void
print(cmap_Subtable_Entry *entry){
printf("\tplatform id %d\n", (int)(entry->plat_id));
printf("\tencoding id %d\n", (int)(entry->plat_encoding_id));
printf("\toffset from cmap %d\n", (int)(entry->offset_from_cmap));
}
void
byte_fix(cmap_Subtable_Format4_Header *header){
byte_reverse(&header->length, 2);
byte_reverse(&header->version, 2);
byte_reverse(&header->segment_count_2, 2);
byte_reverse(&header->search_range, 2);
byte_reverse(&header->entry_selector, 2);
byte_reverse(&header->range_shift, 2);
}
void
print(cmap_Subtable_Format4_Header *header){
printf("\t\tlength %d\n", header->length);
printf("\t\tversion %d\n", header->version);
printf("\t\tsegment count doubled %d\n", header->segment_count_2);
printf("\t\tsearch range %d\n", header->search_range);
printf("\t\tentry selector %d\n", header->entry_selector);
printf("\t\trange shift %d\n", header->range_shift);
}
struct cmap_Subtable_Format4_Segments{
unsigned short *end_code, *start_code;
unsigned short *id_delta, *id_range_offset;
};
void
byte_fix(cmap_Subtable_Format4_Segments segs, int segment_count){
for (int i = 0; i < segment_count; ++i){
byte_reverse(segs.end_code + i, 2);
}
for (int i = 0; i < segment_count; ++i){
byte_reverse(segs.start_code + i, 2);
}
for (int i = 0; i < segment_count; ++i){
byte_reverse(segs.id_delta + i, 2);
}
for (int i = 0; i < segment_count; ++i){
byte_reverse(segs.id_range_offset + i, 2);
}
}
void
print(cmap_Subtable_Format4_Segments segs, int i){
printf("\t\tsegment %d\n", i);
printf("\t\tend code %d\n", (int)(segs.end_code[i]));
printf("\t\tstart code %d\n", (int)(segs.start_code[i]));
printf("\t\tid delta %d\n", (int)(segs.id_delta[i]));
printf("\t\tid range offset %d\n", (int)(segs.id_range_offset[i]));
}
void
parse_cmap_subtable4(char *start){
char *cursor = start;
cmap_Subtable_Format4_Header *header =
(cmap_Subtable_Format4_Header*)cursor;
cursor = (char*)(header + 1);
byte_fix(header);
print(header);
int segment_count = (header->segment_count_2 >> 1);
cmap_Subtable_Format4_Segments segs;
segs.end_code = (unsigned short*)cursor;
cursor = (char*)(segs.end_code + segment_count);
cursor = cursor + sizeof(unsigned short);
segs.start_code = (unsigned short*)cursor;
cursor = (char*)(segs.start_code + segment_count);
segs.id_delta = (unsigned short*)cursor;
cursor = (char*)(segs.id_delta + segment_count);
segs.id_range_offset = (unsigned short*)cursor;
cursor = (char*)(segs.id_range_offset + segment_count);
byte_fix(segs, segment_count);
for (int i = 0; i < segment_count; ++i){
printf("\n");
print(segs, i);
}
}
void
parse_cmap_subtable(char *start){
char *cursor = start;
short *format = (short*)cursor;
byte_reverse(format, 2);
printf("\t\tformat %d\n", (int)(*format));
switch (*format){
case 4:
parse_cmap_subtable4(start);
break;
}
}
void
parse_cmap(char *start){
char *cursor = start;
cmap_Header *header = (cmap_Header*)cursor;
cursor = (char*)(header + 1);
byte_fix(header);
print(header);
cmap_Subtable_Entry *entry = (cmap_Subtable_Entry*)cursor;
for (int i = 0; i < header->num_subtables; ++i, ++entry){
byte_fix(entry);
printf("\n");
print(entry);
if (entry->plat_id == 3 && entry->plat_encoding_id == 1){
printf("\n\tMicrosoft Unicode table:\n");
parse_cmap_subtable(start + entry->offset_from_cmap);
}
}
}
struct glyf_Glyph_Header{
short num_contours;
short x_min;
short x_max;
short y_min;
short y_max;
};
void
byte_fix(glyf_Glyph_Header *header){
byte_reverse(&header->num_contours, 2);
byte_reverse(&header->x_min, 2);
byte_reverse(&header->x_max, 2);
byte_reverse(&header->y_min, 2);
byte_reverse(&header->y_max, 2);
}
void
print(glyf_Glyph_Header *header){
printf("\tcontours %d\n", (int)(header->num_contours));
printf("\tx min %d\n", (int)(header->x_min));
printf("\tx max %d\n", (int)(header->x_max));
printf("\ty min %d\n", (int)(header->y_min));
printf("\ty max %d\n", (int)(header->y_max));
}
void
parse_glyf(char *start){
char *cursor = start;
glyf_Glyph_Header *header = (glyf_Glyph_Header*)cursor;
cursor = (char*)(header + 1);
byte_fix(header);
print(header);
}
#define TTF_Tag(a,b,c,d) ((a) + ((b) << 8) + ((c) << 16) + ((d) << 24))
#define TTF_Tag_cmap TTF_Tag('c', 'm', 'a', 'p')
#define TTF_Tag_glyf TTF_Tag('g', 'l', 'y', 'f')
#define TTF_Tag_fpgm TTF_Tag('f', 'p', 'g', 'm')
#define TTF_Tag_prep TTF_Tag('p', 'r', 'e', 'p')
#define TTF_Tag_cvt TTF_Tag('c', 'v', 't', ' ')
#define TTF_Tag_maxp TTF_Tag('m', 'a', 'x', 'p')
int
main(){
Data file;
char *filename;
filename = "test.ttf";
file = open_file(filename);
if (file.data == 0){
printf("could not open %s\n", filename);
return (1);
}
char *cursor;
Offset_Table *offset;
cursor = file.data;
offset = (Offset_Table*)cursor;
cursor = (char*)(offset + 1);
Table_Directory_Entry *directory_entries = (Table_Directory_Entry*)cursor;
byte_fix(offset);
print(offset);
int table_number = offset->num_tables;
Table_Directory_Entry *entry = directory_entries;
for (int i = 0; i < table_number; ++i, ++entry){
printf("\n");
byte_fix(entry);
print(entry);
switch (entry->tag){
case TTF_Tag_cmap:
parse_cmap(file.data + entry->offset);
break;
case TTF_Tag_glyf:
parse_glyf(file.data + entry->offset);
break;
}
}
return (0);
}
// BOTTOM

View File

@ -0,0 +1,31 @@
/*
* Mr. 4th Dimention - Allen Webster
*
* 12.17.2014
*
* Win32-US Keyboard layer for 4coder
*
*/
// TOP
#include "4ed_keyboard.cpp"
internal void
keycode_init(){
keycode_lookup_table[VK_BACK] = key_back;
keycode_lookup_table[VK_DELETE] = key_del;
keycode_lookup_table[VK_UP] = key_up;
keycode_lookup_table[VK_DOWN] = key_down;
keycode_lookup_table[VK_LEFT] = key_left;
keycode_lookup_table[VK_RIGHT] = key_right;
keycode_lookup_table[VK_INSERT] = key_insert;
keycode_lookup_table[VK_HOME] = key_home;
keycode_lookup_table[VK_END] = key_end;
keycode_lookup_table[VK_PRIOR] = key_page_up;
keycode_lookup_table[VK_NEXT] = key_page_down;
keycode_lookup_table[VK_ESCAPE] = key_esc;
}
// BOTTOM

View File

@ -0,0 +1,69 @@
enum Key_Code_Names{
key_back = 1,
key_up = 2,
key_down = 3,
key_left = 4,
key_right = 5,
key_del = 6,
key_insert = 7,
key_home = 8,
key_end = 11,
key_page_up = 12,
key_page_down = 13,
key_esc = 14,
key_mouse_left = 15,
key_mouse_right = 16,
key_f1 = 127,
key_f2 = 128,
key_f3 = 129,
key_f4 = 130,
key_f5 = 131,
key_f6 = 132,
key_f7 = 133,
key_f8 = 134,
key_f9 = 135,
key_f10 = 136,
key_f11 = 137,
key_f12 = 138,
key_f13 = 139,
key_f14 = 140,
key_f15 = 141,
key_f16 = 142,
};
static char*
global_key_name(int key_code, int *size){
char *result = 0;
switch(key_code){
case key_back: result = "back"; *size = sizeof("back")-1; break;
case key_up: result = "up"; *size = sizeof("up")-1; break;
case key_down: result = "down"; *size = sizeof("down")-1; break;
case key_left: result = "left"; *size = sizeof("left")-1; break;
case key_right: result = "right"; *size = sizeof("right")-1; break;
case key_del: result = "del"; *size = sizeof("del")-1; break;
case key_insert: result = "insert"; *size = sizeof("insert")-1; break;
case key_home: result = "home"; *size = sizeof("home")-1; break;
case key_end: result = "end"; *size = sizeof("end")-1; break;
case key_page_up: result = "page_up"; *size = sizeof("page_up")-1; break;
case key_page_down: result = "page_down"; *size = sizeof("page_down")-1; break;
case key_esc: result = "esc"; *size = sizeof("esc")-1; break;
case key_mouse_left: result = "mouse_left"; *size = sizeof("mouse_left")-1; break;
case key_mouse_right: result = "mouse_right"; *size = sizeof("mouse_right")-1; break;
case key_f1: result = "f1"; *size = sizeof("f1")-1; break;
case key_f2: result = "f2"; *size = sizeof("f2")-1; break;
case key_f3: result = "f3"; *size = sizeof("f3")-1; break;
case key_f4: result = "f4"; *size = sizeof("f4")-1; break;
case key_f5: result = "f5"; *size = sizeof("f5")-1; break;
case key_f6: result = "f6"; *size = sizeof("f6")-1; break;
case key_f7: result = "f7"; *size = sizeof("f7")-1; break;
case key_f8: result = "f8"; *size = sizeof("f8")-1; break;
case key_f9: result = "f9"; *size = sizeof("f9")-1; break;
case key_f10: result = "f10"; *size = sizeof("f10")-1; break;
case key_f11: result = "f11"; *size = sizeof("f11")-1; break;
case key_f12: result = "f12"; *size = sizeof("f12")-1; break;
case key_f13: result = "f13"; *size = sizeof("f13")-1; break;
case key_f14: result = "f14"; *size = sizeof("f14")-1; break;
case key_f15: result = "f15"; *size = sizeof("f15")-1; break;
case key_f16: result = "f16"; *size = sizeof("f16")-1; break;
}
return(result);
}

View File

@ -0,0 +1,695 @@
/*
* Mr. 4th Dimention - Allen Webster
*
* 15.05.2015
*
* Math functions for 4coder
*
*/
// TOP
/*
* Scalar operators
*/
#define C_MATH 1
#define DEG_TO_RAD 0.0174533f
#define RAD_TO_DEG 57.295780f
#if C_MATH
#include <math.h>
#endif
inline real32
ABS(real32 x){
#if C_MATH
return abs(x);
#endif
}
inline real32
MOD(real32 x, i32 m){
#if C_MATH
real32 whole, frac;
frac = modf(x, &whole);
return ((i32)(whole) % m) + frac;
#endif
}
inline real32
SQRT(real32 x){
#if C_MATH
return sqrt(x);
#endif
}
inline real32
SIN(real32 x_degrees){
#if C_MATH
return sinf(x_degrees * DEG_TO_RAD);
#endif
}
inline real32
COS(real32 x_degrees){
#if C_MATH
return cosf(x_degrees * DEG_TO_RAD);
#endif
}
inline f32
ATAN_DEG(f32 y, f32 x){
#if C_MATH
return atan2f(y, x) * RAD_TO_DEG;
#endif
}
inline f32
POW(f32 base, f32 exp){
#if C_MATH
return pow(base, exp);
#endif
}
/*
* Rounding
*/
inline i32
TRUNC32(real32 x) { return (i32)x; }
inline i32
FLOOR32(real32 x) { return (i32)(x)-((x!=(i32)(x) && x<0)?1:0); }
inline i32
CEIL32(real32 x) { return (i32)(x)+((x!=(i32)(x) && x>0)?1:0); }
inline i32
ROUND32(real32 x) { return FLOOR32(x + .5f); }
inline i32
DIVCEIL32(i32 n, i32 d) {
i32 q = (n/d);
return q + (q*d < n);
}
inline real32
FRACPART32(real32 x) { return x - (i32)x; }
/*
* Vectors
*/
struct Vec2{
union{
struct{
real32 x, y;
};
struct{
real32 v[2];
};
};
};
struct Vec3{
union{
struct{
real32 x, y, z;
};
struct{
real32 r, g, b;
};
struct{
Vec2 xy;
real32 _z;
};
struct{
real32 _x;
Vec2 yz;
};
struct{
real32 v[3];
};
};
};
struct Vec4{
union{
struct{
real32 r, g, b, a;
};
struct{
real32 h, s, l, __a;
};
struct{
real32 x, y, z, w;
};
struct{
Vec3 rgb;
real32 _a;
};
struct{
Vec3 xyz;
real32 _w;
};
struct{
real32 _x;
Vec3 yzw;
};
struct{
real32 v[4];
};
};
};
inline Vec2
V2(real32 x, real32 y){
Vec2 result;
result.x = x;
result.y = y;
return result;
}
inline Vec3
V3(real32 x, real32 y, real32 z){
Vec3 result;
result.x = x;
result.y = y;
result.z = z;
return result;
}
inline Vec4
V4(real32 x, real32 y, real32 z, real32 w){
Vec4 result;
result.x = x;
result.y = y;
result.z = z;
result.w = w;
return result;
}
inline Vec2
operator+(Vec2 a, Vec2 b){
Vec2 result;
result.x = a.x + b.x;
result.y = a.y + b.y;
return result;
}
inline Vec3
operator+(Vec3 a, Vec3 b){
Vec3 result;
result.x = a.x + b.x;
result.y = a.y + b.y;
result.z = a.z + b.z;
return result;
}
inline Vec4
operator+(Vec4 a, Vec4 b){
Vec4 result;
result.x = a.x + b.x;
result.y = a.y + b.y;
result.z = a.z + b.z;
result.w = a.w + b.w;
return result;
}
inline Vec2
operator-(Vec2 a, Vec2 b){
Vec2 result;
result.x = a.x - b.x;
result.y = a.y - b.y;
return result;
}
inline Vec3
operator-(Vec3 a, Vec3 b){
Vec3 result;
result.x = a.x - b.x;
result.y = a.y - b.y;
result.z = a.z - b.z;
return result;
}
inline Vec4
operator-(Vec4 a, Vec4 b){
Vec4 result;
result.x = a.x - b.x;
result.y = a.y - b.y;
result.z = a.z - b.z;
result.w = a.w - b.w;
return result;
}
inline Vec2
operator*(Vec2 a, real32 k){
Vec2 result;
result.x = a.x * k;
result.y = a.y * k;
return result;
}
inline Vec3
operator*(Vec3 a, real32 k){
Vec3 result;
result.x = a.x * k;
result.y = a.y * k;
result.z = a.z * k;
return result;
}
inline Vec4
operator*(Vec4 a, real32 k){
Vec4 result;
result.x = a.x * k;
result.y = a.y * k;
result.z = a.z * k;
result.w = a.w * k;
return result;
}
inline Vec2
operator*(real32 k, Vec2 a){
Vec2 result;
result.x = a.x * k;
result.y = a.y * k;
return result;
}
inline Vec3
operator*(real32 k, Vec3 a){
Vec3 result;
result.x = a.x * k;
result.y = a.y * k;
result.z = a.z * k;
return result;
}
inline Vec4
operator*(real32 k, Vec4 a){
Vec4 result;
result.x = a.x * k;
result.y = a.y * k;
result.z = a.z * k;
result.w = a.w * k;
return result;
}
inline Vec2&
operator+=(Vec2 &a, Vec2 b){
a = (a + b);
return a;
}
inline Vec3&
operator+=(Vec3 &a, Vec3 b){
a = (a + b);
return a;
}
inline Vec4&
operator+=(Vec4 &a, Vec4 b){
a = (a + b);
return a;
}
inline Vec2&
operator-=(Vec2 &a, Vec2 b){
a = (a - b);
return a;
}
inline Vec3&
operator-=(Vec3 &a, Vec3 b){
a = (a - b);
return a;
}
inline Vec4&
operator-=(Vec4 &a, Vec4 b){
a = (a - b);
return a;
}
inline Vec2&
operator*=(Vec2 &a, real32 k){
a = (a * k);
return a;
}
inline Vec3&
operator*=(Vec3 &a, real32 k){
a = (a * k);
return a;
}
inline Vec4&
operator*=(Vec4 &a, real32 k){
a = (a * k);
return a;
}
inline real32
dot(Vec2 a, Vec2 b){
real32 result;
result = a.x*b.x + a.y*b.y;
return result;
}
inline real32
dot(Vec3 a, Vec3 b){
real32 result;
result = a.x*b.x + a.y*b.y + a.z*b.z;
return result;
}
inline real32
dot(Vec4 a, Vec4 b){
real32 result;
result = a.x*b.x + a.y*b.y + a.z*b.z + a.w*b.w;
return result;
}
inline Vec3
cross(Vec3 a, Vec3 b){
Vec3 result;
result.x = a.y*b.z - b.y*a.z;
result.y = a.z*b.x - b.z*a.x;
result.z = a.x*b.y - b.x*a.y;
return result;
}
inline Vec2
hadamard(Vec2 a, Vec2 b){
Vec2 result;
result.x = a.x*b.x;
result.y = a.y*b.y;
return result;
}
inline Vec3
hadamard(Vec3 a, Vec3 b){
Vec3 result;
result.x = a.x*b.x;
result.y = a.y*b.y;
result.z = a.z*b.z;
return result;
}
inline Vec4
hadamard(Vec4 a, Vec4 b){
Vec4 result;
result.x = a.x*b.x;
result.y = a.y*b.y;
result.z = a.z*b.z;
result.w = a.w*b.w;
return result;
}
inline Vec2
perp(Vec2 v){
Vec2 result;
result.x = -v.y;
result.y = v.x;
return result;
}
inline Vec2
polar_to_cartesian(real32 theta_degrees, real32 length){
Vec2 result;
result.x = COS(theta_degrees)*length;
result.y = SIN(theta_degrees)*length;
return result;
}
inline Vec2
cis(f32 theta){
Vec2 result;
result.x = COS(theta);
result.y = SIN(theta);
return result;
}
inline Vec2
rotate(Vec2 v, real32 theta_degrees){
Vec2 result;
real32 c, s;
c = COS(theta_degrees);
s = SIN(theta_degrees);
result.x = v.x*c - v.y*s;
result.y = v.x*s + v.y*c;
return result;
}
inline real32
vector_projection(Vec2 x, Vec2 target){
real32 target_magnitude = SQRT(dot(target, target));
Vec2 unit_target = target * (1 / target_magnitude);
real32 result = dot(x, unit_target);
return(result);
}
inline Vec2
normalize(Vec2 x){
f32 d = dot(x, x);
d = SQRT(d);
x *= (1.f/d);
return(x);
}
inline Vec2
normalize_radius(Vec2 x, f32 r){
f32 d = dot(x, x);
d = SQRT(d);
r = r/d;
x *= r;
return(x);
}
inline f32
argument_degrees(Vec2 v){
f32 r = ATAN_DEG(v.y, v.x);
return(r);
}
/*
* Coordinates
*/
struct Matrix2{
Vec2 x_axis;
Vec2 y_axis;
};
internal Matrix2
invert(Vec2 x_axis, Vec2 y_axis){
Matrix2 result = {};
real32 det = 1.f / (x_axis.x*y_axis.y - x_axis.y*y_axis.x);
result.x_axis.x = y_axis.y*det;
result.y_axis.x = -y_axis.x*det;
result.x_axis.y = -x_axis.y*det;
result.y_axis.y = x_axis.x*det;
return result;
}
internal Matrix2
invert(Matrix2 m){
Matrix2 result = {};
real32 det = 1.f / (m.x_axis.x*m.y_axis.y - m.x_axis.y*m.y_axis.x);
result.x_axis.x = m.y_axis.y*det;
result.y_axis.x = -m.y_axis.x*det;
result.x_axis.y = -m.x_axis.y*det;
result.y_axis.y = m.x_axis.x*det;
return result;
}
/*
* Lerps, Clamps, Thresholds, Etc
*/
inline real32
lerp(real32 a, real32 t, real32 b){
return a + (b-a)*t;
}
inline Vec2
lerp(Vec2 a, real32 t, Vec2 b){
return a + (b-a)*t;
}
inline Vec3
lerp(Vec3 a, real32 t, Vec3 b){
return a + (b-a)*t;
}
inline Vec4
lerp(Vec4 a, real32 t, Vec4 b){
return a + (b-a)*t;
}
inline real32
unlerp(real32 a, real32 x, real32 b){
return (x - a) / (b - a);
}
inline real32
clamp(real32 a, real32 n, real32 z){
return (n<a)?(a):((n>z)?(z):n);
}
/*
* Color
*/
// TODO(allen): Convert colors to Vec4
inline internal u32
color_blend(u32 a, real32 t, u32 b){
union{
u8 byte[4];
u32 comp;
} A, B, R;
A.comp = a;
B.comp = b;
R.byte[0] = (u8)lerp(A.byte[0], t, B.byte[0]);
R.byte[1] = (u8)lerp(A.byte[1], t, B.byte[1]);
R.byte[2] = (u8)lerp(A.byte[2], t, B.byte[2]);
R.byte[3] = (u8)lerp(A.byte[3], t, B.byte[3]);
return R.comp;
}
internal Vec3
unpack_color3(u32 color){
Vec3 result;
result.r = ((color >> 16) & 0xFF) / 255.f;
result.g = ((color >> 8) & 0xFF) / 255.f;
result.b = ((color >> 0) & 0xFF) / 255.f;
return result;
}
internal Vec4
unpack_color4(u32 color){
Vec4 result;
result.a = ((color >> 24) & 0xFF) / 255.f;
result.r = ((color >> 16) & 0xFF) / 255.f;
result.g = ((color >> 8) & 0xFF) / 255.f;
result.b = ((color >> 0) & 0xFF) / 255.f;
return result;
}
internal u32
pack_color4(Vec4 color){
u32 result =
((u8)(color.a * 255) << 24) |
((u8)(color.r * 255) << 16) |
((u8)(color.g * 255) << 8) |
((u8)(color.b * 255) << 0);
return result;
}
internal Vec4
rgba_to_hsla(Vec4 rgba){
Vec4 hsla = {};
real32 max, min, delta;
i32 maxc;
hsla.a = rgba.a;
max = rgba.r; min = rgba.r;
maxc = 0;
if (rgba.r < rgba.g){
max = rgba.g;
maxc = 1;
}
if (rgba.b > max){
max = rgba.b;
maxc = 2;
}
if (rgba.r > rgba.g){
min = rgba.g;
}
if (rgba.b < min){
min = rgba.b;
}
delta = max - min;
hsla.z = (max + min) * .5f;
if (delta == 0){
hsla.x = 0.f;
hsla.y = 0.f;
}
else{
switch (maxc){
case 0:
{
hsla.x = (rgba.g - rgba.b) / delta;
hsla.x += (rgba.g < rgba.b) * 6.f;
}break;
case 1:
{
hsla.x = (rgba.b - rgba.r) / delta;
hsla.x += 2.f;
}break;
case 2:
{
hsla.x = (rgba.r - rgba.g) / delta;
hsla.x += 4.f;
}break;
}
hsla.x *= (1/6.f); // * 60 / 360
hsla.y = delta / (1.f - ABS(2.f*hsla.z - 1.f));
}
return hsla;
}
internal Vec4
hsla_to_rgba(Vec4 hsla){
Vec4 rgba = {};
real32 C, X, m;
i32 H;
rgba.a = hsla.a;
C = (1.f - ABS(2*hsla.z - 1.f)) * hsla.y;
X = C * (1.f-ABS(MOD(hsla.x*6.f, 2)-1.f));
m = hsla.z - C*.5f;
H = FLOOR32(hsla.x * 6.f);
switch (H){
case 0:
rgba.r = C; rgba.g = X; rgba.b = 0;
break;
case 1:
rgba.r = X; rgba.g = C; rgba.b = 0;
break;
case 2:
rgba.r = 0; rgba.g = C; rgba.b = X;
break;
case 3:
rgba.r = 0; rgba.g = X; rgba.b = C;
break;
case 4:
rgba.r = X; rgba.g = 0; rgba.b = C;
break;
case 5:
rgba.r = C; rgba.g = 0; rgba.b = X;
break;
}
rgba.r += m;
rgba.g += m;
rgba.b += m;
return rgba;
}
// BOTTOM

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,235 @@
/*
* Mr. 4th Dimention - Allen Webster
*
* 14.02.2016
*
* 4tech C style genereic hash table
*
*/
// TOP
#define TableHashEmpty 0
#define TableHashDeleted 1
#define TableHashMin 0x10000000
typedef u32 Hash_Function(void *item, void *arg);
typedef i32 Compare_Function(void *key, void *item, void *arg);
struct Table{
u32 *hash_array;
u8 *data_array;
i32 count, max;
i32 item_size;
};
internal b32
table_at_capacity(Table *table){
b32 result = 1;
if (table->count * 8 < table->max * 7){
result = 0;
}
return(result);
}
internal b32
table_add(Table *table, void *item, void *arg, Hash_Function *hash_func, Compare_Function *comp_func){
u32 hash, *inspect;
i32 i;
Assert(table->count * 8 < table->max * 7);
hash = (hash_func(item, arg) | TableHashMin);
i = hash % table->max;
inspect = table->hash_array + i;
while (*inspect >= TableHashMin){
if (*inspect == hash){
if (comp_func(item, table->data_array + i*table->item_size, arg) == 0){
return(1);
}
}
++i;
++inspect;
if (i == table->max){
i = 0;
inspect = table->hash_array;
}
}
*inspect = hash;
memcpy(table->data_array + i*table->item_size, item, table->item_size);
++table->count;
return(0);
}
internal b32
table_find_pos(Table *table, void *search_key, void *arg, i32 *pos, i32 *index, Hash_Function *hash_func, Compare_Function *comp_func){
u32 hash, *inspect;
i32 i;
hash = (hash_func(search_key, arg) | TableHashMin);
i = hash % table->max;
inspect = table->hash_array + i;
while (*inspect != TableHashEmpty){
if (*inspect == hash){
if (comp_func(search_key, table->data_array + i*table->item_size, arg) == 0){
if (pos) *pos = i*table->item_size;
if (index) *index = i;
return(1);
}
}
++i;
++inspect;
if (i == table->max){
i = 0;
inspect = table->hash_array;
}
}
return(0);
}
internal void*
table_find_item(Table *table, void *search_key, void *arg, Hash_Function *hash_func, Compare_Function *comp_func){
i32 pos;
void *result = 0;
if (table_find_pos(table, search_key, arg, &pos, 0, hash_func, comp_func)){
result = table->data_array + pos;
}
return(result);
}
internal void
table_remove_index(Table *table, i32 index){
table->hash_array[index] = TableHashDeleted;
--table->count;
}
internal b32
table_remove_match(Table *table, void *search_key, void *arg, Hash_Function *hash_func, Compare_Function *comp_func){
i32 index;
b32 result = 0;
if (table_find_pos(table, search_key, arg, 0, &index, hash_func, comp_func)){
table_remove_index(table, index);
result = 1;
}
return(result);
}
internal void
table_clear(Table *table){
table->count = 0;
memset(table->hash_array, 0, table->max*sizeof(*table->hash_array));
}
internal void
table_rehash(Table *src, Table *dst, void *arg, Hash_Function *hash_func, Compare_Function *comp_func){
i32 i, c, count, item_size;
u32 *hash_item;
u8 *data_item;
Assert((dst->count + src->count - 1) * 7 < dst->max * 8);
Assert(dst->item_size == src->item_size);
count = src->count;
hash_item = src->hash_array;
data_item = src->data_array;
item_size = src->item_size;
for (i = 0, c = 0; c < count; ++i, ++hash_item, data_item += item_size){
if (*hash_item >= TableHashMin){
++c;
table_add(dst, data_item, arg, hash_func, comp_func);
}
}
}
internal u32
tbl_string_hash(void *item, void *arg){
String *string = (String*)item;
char *str;
i32 i,len;
u32 x = 5381;
char c;
(void)arg;
str = string->str;
len = string->size;
i = 0;
while (i < len){
c = str[i++];
x = ((x << 5) + x) + c;
}
return(x);
}
internal i32
tbl_string_compare(void *a, void *b, void *arg){
String *stra = (String*)a;
String *strb = (String*)b;
i32 result = !match(*stra, *strb);
return(result);
}
internal u32
tbl_offset_string_hash(void *item, void *arg){
Offset_String *string = (Offset_String*)item;
char *str;
i32 i,len;
u32 x = 5381;
char c;
str = ((char*)arg) + string->offset;
len = string->size;
i = 0;
while (i < len){
c = str[i++];
x = ((x << 5) + x) + c;
}
return(x);
}
internal i32
tbl_offset_string_compare(void *a, void *b, void *arg){
Offset_String *ostra = (Offset_String*)a;
Offset_String *ostrb = (Offset_String*)b;
String stra = make_string((char*)arg + ostra->offset, ostra->size);
String strb = make_string((char*)arg + ostrb->offset, ostrb->size);
i32 result = !match(stra, strb);
return(result);
}
struct String_Space{
char *space;
i32 pos, new_pos, max;
};
internal Offset_String
strspace_append(String_Space *space, char *str, i32 len){
Offset_String result = {};
if (space->new_pos + len <= space->max){
result.offset = space->new_pos;
result.size = len;
memcpy(space->space + space->new_pos, str, len);
space->new_pos = space->pos + len;
}
return(result);
}
internal void
strspace_keep_prev(String_Space *space){
space->pos = space->new_pos;
}
internal void
strspace_discard_prev(String_Space *space){
space->new_pos = space->pos;
}
// BOTTOM

View File

@ -0,0 +1,424 @@
// ==++==
//
// Copyright (c) Microsoft Corporation. All rights reserved.
//
// ==--==
// =+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
//
// Agent.cpp
//
// Source file containing code for the agent creation APIs.
//
// =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
#include "concrtinternal.h"
#include <agents.h>
namespace Concurrency
{
// A Filter function for a filter_block to check if the Agent has completed
bool _IsDone(agent_status const &status)
{
return status == agent_done || status == agent_canceled;
}
// A Filter function for a filter_block to check if the Agent has started (or completed)
bool _IsStarted(agent_status const &status)
{
return _IsDone(status) || status == agent_started;
}
/// <summary>
/// Creates an agent within the default scheduler, and places it any schedule
/// group of the scheduler's choosing.
/// </summary>
agent::agent() :
_M_fStartable(TRUE), _M_fCancelable(TRUE), _M_pScheduler(NULL), _M_pScheduleGroup(NULL)
{
_Trace_agents(AGENTS_EVENT_CREATE,
details::_Trace_agents_get_id(this),
details::_Trace_agents_get_id(this));
send<agent_status> (_M_status, agent_created);
}
/// <summary>
/// Create an agent within the specified scheduler, in a schedule group of the
/// scheduler's choosing.
/// </summary>
agent::agent(Scheduler& pScheduler) :
_M_fStartable(TRUE), _M_fCancelable(TRUE), _M_pScheduler(&pScheduler), _M_pScheduleGroup(NULL)
{
_Trace_agents(AGENTS_EVENT_CREATE,
details::_Trace_agents_get_id(this),
details::_Trace_agents_get_id(this));
send<agent_status> (_M_status, agent_created);
}
/// <summary>
/// Create an agent within the specified schedule group. The scheduler is implied
/// by the schedule group.
/// </summary>
agent::agent(ScheduleGroup& pGroup) :
_M_fStartable(TRUE), _M_fCancelable(TRUE), _M_pScheduler(NULL), _M_pScheduleGroup(&pGroup)
{
_Trace_agents(AGENTS_EVENT_CREATE,
details::_Trace_agents_get_id(this),
details::_Trace_agents_get_id(this));
send<agent_status> (_M_status, agent_created);
}
/// <summary>
/// Cleans up any resources that may have been created by the Agent.
/// </summary>
agent::~agent()
{
_Trace_agents(AGENTS_EVENT_DESTROY, details::_Trace_agents_get_id(this));
}
/// <returns>
/// Returns a message source that can pass messages about the current state of the agent
/// </returns>
ISource<agent_status> * agent::status_port()
{
return &_M_status;
}
/// <returns>
/// Returns the current state of the agent. Note that this returned state could change
/// immediately after being returned.
/// </returns>
agent_status agent::status()
{
return receive<agent_status>(_M_status);
}
/// <summary>
/// Moves an Agent from the agent_created state to the agent_runnable state, and schedules it for execution.
/// </summary>
/// <returns>
/// true if the agent started correctly, false otherwise
/// </returns>
bool agent::start()
{
if(_M_status.value() != agent_created)
{
return false;
}
//
// Check if the agent is Startable. If the agent had already called start() or
// this variable was set to FALSE in cancel(), return false.
//
if(InterlockedCompareExchange(&_M_fStartable, FALSE, TRUE) == FALSE)
{
return false;
}
_Trace_agents(AGENTS_EVENT_SCHEDULE, details::_Trace_agents_get_id(this));
send<agent_status> (_M_status, agent_runnable);
TaskProc proc = &Concurrency::agent::_Agent_task_wrapper;
if(_M_pScheduleGroup != NULL)
{
_M_pScheduleGroup->ScheduleTask(proc, this);
}
else if(_M_pScheduler != NULL)
{
_M_pScheduler->ScheduleTask(proc, this);
}
else
{
CurrentScheduler::ScheduleTask(proc, this);
}
return true;
}
/// <summary>
/// Moves an agent into the done state, indicating the completion of the agent
/// </summary>
/// <returns>
/// true if the agent is moved to the agent_done state, false otherwise
/// </returns>
bool agent::done()
{
//
// current status
//
agent_status currentStatus = this->status();
//
// Indicate that the agent can no longer be started.
//
if (InterlockedCompareExchange(&_M_fStartable, FALSE, TRUE) != TRUE)
{
//
// agent is either canceled, started or completed run.
//
currentStatus = receive<agent_status>(_M_status, _IsStarted);
}
//
// Agent is not cancelable anymore.
//
InterlockedExchange(&_M_fCancelable, FALSE);
//
// Transition to agent_done state if it not already in one of
// the terminal states.
//
if ((currentStatus != agent_canceled) && (currentStatus != agent_done))
{
send<agent_status> (_M_status, agent_done);
return true;
}
return false;
}
/// <summary>
/// Moves an agent from the agent_created or agent_runnable to the agent_canceled state.
/// </summary>
/// <returns>
/// true if the agent was canceled correctly, false otherwise
/// </returns>
bool agent::cancel()
{
//
// In case this agent has been canceled before it was even started
// mark it as no longer Startable and send a agent_canceled message to the
// status port
//
if(InterlockedCompareExchange(&_M_fStartable, FALSE, TRUE) == TRUE)
{
send<agent_status> (_M_status, agent_canceled);
}
//
// Check to see if the agent is still Cancelable. Agents are initialized
// m_fCancelable == TRUE, and set to false either here in cancel(), so
// cancel() will not be called twice, or in the LWT, once the execution
// of the Agent task has begun.
//
if(InterlockedCompareExchange(&_M_fCancelable, FALSE, TRUE) == TRUE)
{
// Wait for the agent to reach a canceled state state
receive<agent_status>(_M_status, _IsDone);
// The above InterlockedCompareExchange marked this agent for cancelation
// When the LWT that has been spun up tries to execute the task, it will
// find it has been canceled and will propagate out the canceled state to
// the state buffer.
return true;
}
return false;
}
// Private helper class to order an input array of agents. This is used by
// wait_for_all and wait_for_one to create an array of appropriate order nodes.
// The template _OrderNode specifies an _Order_node_base that accepts agent_status.
// For example, _Reserving_node<agent_status>
template<class _OrderNode>
class _OrderBlock
{
public:
// Constructs an orderBlock which has an array of ordernodes connected to the agents.
// The ordernodes are given a filter method to filter out non-terminal agent states
_OrderBlock(size_t _Count, agent ** _PAgents, ITarget<size_t> * _PTarget) : _M_count(_Count)
{
// Create an array of order nodes
_M_ppNodes = _concrt_new _OrderNode*[_M_count];
for (size_t i = 0; i < _M_count; i++)
{
_M_ppNodes[i] = _concrt_new _OrderNode(_PAgents[i]->status_port(), i, _PTarget, _IsDone);
}
}
// Destroys the block
~_OrderBlock()
{
for (size_t i = 0; i < _M_count; i++)
{
delete _M_ppNodes[i];
}
delete [] _M_ppNodes;
}
// Retrieve the agent status for the agent at the given index
agent_status _Status(size_t _Index)
{
_CONCRT_ASSERT(_M_ppNodes[_Index]->has_value());
return _M_ppNodes[_Index]->value();
}
private:
// Number of order nodes
size_t _M_count;
// Array of order nodes
_OrderNode ** _M_ppNodes;
};
/// <summary>
/// Wait for an agent to complete its task. A task is completed when it enters the agent_canceled,
/// or agent_done states.
/// </summary>
agent_status agent::wait(agent * pAgent, unsigned int timeout)
{
if(pAgent == NULL)
{
throw std::invalid_argument("pAgent");
}
return receive<agent_status>(pAgent->status_port(), _IsDone, timeout);
}
/// <summary>
/// Wait for all agents in a given Agent array to complete their tasks. A task is completed
/// when it enters the agent_canceled or agent_done states.
/// </summary>
void agent::wait_for_all(size_t count, agent ** pAgents, agent_status * pStatus, unsigned int timeout)
{
if ( pAgents == NULL )
{
throw std::invalid_argument("pAgents");
}
for (size_t i = 0; i < count; i++)
{
if ( pAgents[i] == NULL )
{
throw std::invalid_argument("pAgents");
}
}
// Create the following network
//
// agent - orderNode -
// \
// agent - orderNode - --call ~~~ single_assignment
// /
// agent - orderNode -
single_assignment<size_t> _Sa;
volatile size_t _CompletedAgents = 0;
call<size_t> _Call([&](size_t const& _Index)
{
// Safe to access without synchronization since call blocks
// guarantee that the function is not called for multiple
// messages at the same time.
_CONCRT_ASSERT(_CompletedAgents < count);
if (++_CompletedAgents == count)
{
// All the agents have completed. Indicate the same by sending a message
// (initialize) to the single assignment.
send<size_t>(_Sa, 1);
}
});
_OrderBlock<_Greedy_node<agent_status>> _OrderedAgents(count, pAgents, &_Call);
receive(&_Sa, timeout);
// single_assignment has a message => all agents completed
// Retrieve their status messages.
if(pStatus != NULL)
{
for (size_t i = 0; i < count; i++)
{
pStatus[i] = _OrderedAgents._Status(i);
}
}
}
/// <summary>
/// Wait for any one of the agents in a given AgentTask array to complete its task. A task is completed
/// when it enters the agent_canceled or agent_done states.
/// </summary>
void agent::wait_for_one(size_t count, agent ** pAgents, agent_status &status, size_t& index, unsigned int timeout)
{
if ( pAgents == NULL )
{
throw std::invalid_argument("pAgents");
}
for (size_t i = 0; i < count; i++)
{
if ( pAgents[i] == NULL )
{
throw std::invalid_argument("pAgents");
}
}
// Create the following network
//
// agent - orderNode -
// \
// agent - orderNode - --single_assignment
// /
// agent - orderNode -
single_assignment<size_t> _Sa;
_OrderBlock<_Greedy_node<agent_status>> _OrderedAgents(count, pAgents, &_Sa);
index = receive(&_Sa, timeout);
// We were able to receive the index. Get the message (agent_status)
status = _OrderedAgents._Status(index);
}
// A static wrapper function that calls the Run() method. Used for scheduling of the task
void agent::_Agent_task_wrapper(void* data)
{
agent *pAgent = (agent *) data;
if(InterlockedCompareExchange(&pAgent->_M_fCancelable, FALSE, TRUE) == TRUE)
{
send<agent_status> (pAgent->_M_status, agent_started);
// Invoke the run() function of the agent.
_Trace_agents(AGENTS_EVENT_START, details::_Trace_agents_get_id(pAgent));
pAgent->run();
_Trace_agents(AGENTS_EVENT_END, details::_Trace_agents_get_id(pAgent), 0);
}
else
{
// This else path can be entered only if an agent was canceled before it
// ran. Send a agent_canceled message to the status.
send<agent_status> (pAgent->_M_status, agent_canceled);
}
}
// Implementation of agent APIs that should not be publicly exposed
namespace details
{
static volatile runtime_object_identity s_RuntimeObjectIdentity = 0;
_CRTIMP2 _Runtime_object::_Runtime_object()
{
// Increment the id by 2. This is done because certain blocks (like join) need to have
// a special message id to indicate a NULL id. In this case, we use -1. Incrementing by 2
// will avoid any wrap-around issues causing us to hit -1.
runtime_object_identity id = InterlockedExchangeAdd((volatile long *) &s_RuntimeObjectIdentity, 2);
_CONCRT_ASSERT(id != -1);
_M_id = id;
}
_CRTIMP2 _Runtime_object::_Runtime_object(runtime_object_identity _Id) : _M_id(_Id)
{
}
} // namespace details
} // namespace Concurrency

View File

@ -0,0 +1,219 @@
#include "Base64.h"
#include <cmath>
#include <cstring>
#include <string>
/**
* characters used for Base64 encoding
*/
const char *BASE64_CHARS = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_";
/**
* encode three bytes using base64 (RFC 3548)
*
* @param triple three bytes that should be encoded
* @param result buffer of four characters where the result is stored
*/
void _base64_encode_triple(unsigned char triple[3], char result[4])
{
int tripleValue, i;
tripleValue = triple[0];
tripleValue *= 256;
tripleValue += triple[1];
tripleValue *= 256;
tripleValue += triple[2];
for (i=0; i<4; i++)
{
result[3-i] = BASE64_CHARS[tripleValue%64];
tripleValue /= 64;
}
}
/**
* encode an array of bytes using Base64 (RFC 3548)
*
* @param source the source buffer
* @param sourcelen the length of the source buffer
* @param target the target buffer
* @param targetlen the length of the target buffer
* @return 1 on success, 0 otherwise
*/
int base64_encode(unsigned char *source, size_t sourcelen, char *target, size_t targetlen)
{
/* check if the result will fit in the target buffer */
if ((sourcelen+2)/3*4 > targetlen-1)
return 0;
/* encode all full triples */
while (sourcelen >= 3)
{
_base64_encode_triple(source, target);
sourcelen -= 3;
source += 3;
target += 4;
}
/* encode the last one or two characters */
if (sourcelen > 0)
{
unsigned char temp[3];
memset(temp, 0, sizeof(temp));
memcpy(temp, source, sourcelen);
_base64_encode_triple(temp, target);
target[3] = '=';
if (sourcelen == 1)
target[2] = '=';
target += 4;
}
/* terminate the string */
target[0] = 0;
return 1;
}
/**
* determine the value of a base64 encoding character
*
* @param base64char the character of which the value is searched
* @return the value in case of success (0-63), -1 on failure
*/
int _base64_char_value(char base64char)
{
if (base64char >= 'A' && base64char <= 'Z')
return base64char-'A';
if (base64char >= 'a' && base64char <= 'z')
return base64char-'a'+26;
if (base64char >= '0' && base64char <= '9')
return base64char-'0'+2*26;
if (base64char == '-')
return 2*26+10;
if (base64char == '_')
return 2*26+11;
return -1;
}
/**
* decode a 4 char base64 encoded byte triple
*
* @param quadruple the 4 characters that should be decoded
* @param result the decoded data
* @return length of the result (1, 2 or 3), 0 on failure
*/
int _base64_decode_triple(char quadruple[4], unsigned char *result)
{
int i, triple_value, bytes_to_decode = 3, only_equals_yet = 1;
int char_value[4];
for (i=0; i<4; i++)
char_value[i] = _base64_char_value(quadruple[i]);
/* check if the characters are valid */
for (i=3; i>=0; i--)
{
if (char_value[i]<0)
{
if (only_equals_yet && quadruple[i]=='=')
{
/* we will ignore this character anyway, make it something
* that does not break our calculations */
char_value[i]=0;
bytes_to_decode--;
continue;
}
return 0;
}
/* after we got a real character, no other '=' are allowed anymore */
only_equals_yet = 0;
}
/* if we got "====" as input, bytes_to_decode is -1 */
if (bytes_to_decode < 0)
bytes_to_decode = 0;
/* make one big value out of the partial values */
triple_value = char_value[0];
triple_value *= 64;
triple_value += char_value[1];
triple_value *= 64;
triple_value += char_value[2];
triple_value *= 64;
triple_value += char_value[3];
/* break the big value into bytes */
for (i=bytes_to_decode; i<3; i++)
triple_value /= 256;
for (i=bytes_to_decode-1; i>=0; i--)
{
result[i] = triple_value%256;
triple_value /= 256;
}
return bytes_to_decode;
}
/**
* decode base64 encoded data
*
* @param source the encoded data (zero terminated)
* @param target pointer to the target buffer
* @param targetlen length of the target buffer
* @return length of converted data on success, -1 otherwise
*/
size_t base64_decode(const char *source, unsigned char *target, size_t targetlen)
{
char *src, *tmpptr;
char quadruple[4];
unsigned char tmpresult[3];
int i;
size_t tmplen = 3;
size_t converted = 0;
/* concatenate '===' to the source to handle unpadded base64 data */
src = (char *)malloc(strlen(source)+5);
if (src == NULL)
return -1;
strcpy(src, source);
strcat(src, "====");
tmpptr = src;
/* convert as long as we get a full result */
while (tmplen == 3)
{
/* get 4 characters to convert */
for (i=0; i<4; i++)
{
/* skip invalid characters - we won't reach the end */
while (*tmpptr != '=' && _base64_char_value(*tmpptr)<0)
tmpptr++;
quadruple[i] = *(tmpptr++);
}
/* convert the characters */
tmplen = _base64_decode_triple(quadruple, tmpresult);
/* check if the fit in the result buffer */
if (targetlen < tmplen)
{
free(src);
return -1;
}
/* put the partial result in the result buffer */
memcpy(target, tmpresult, tmplen);
target += tmplen;
targetlen -= tmplen;
converted += tmplen;
}
free(src);
return converted;
}
/** get memory consumption */
size_t base64_needed(const size_t &iSize) {return 4*size_t(floorf((float(iSize)+2.0f)/3.0f))+1;}

View File

@ -0,0 +1,62 @@
#pragma once
#ifndef _BASE64_H_
#define _BASE64_H_
#define _HAS_EXCEPTIONS (0)
#define _CRT_SECURE_NO_WARNINGS
#include <cstdlib>
/**
* encode three bytes using base64 (RFC 3548)
*
* @param triple three bytes that should be encoded
* @param result buffer of four characters where the result is stored
*/
void _base64_encode_triple(unsigned char triple[3], char result[4]);
/**
* encode an array of bytes using Base64 (RFC 3548)
*
* @param source the source buffer
* @param sourcelen the length of the source buffer
* @param target the target buffer
* @param targetlen the length of the target buffer
* @return 1 on success, 0 otherwise
*/
int base64_encode(unsigned char *source, size_t sourcelen, char *target, size_t targetlen);
/**
* determine the value of a base64 encoding character
*
* @param base64char the character of which the value is searched
* @return the value in case of success (0-63), -1 on failure
*/
int _base64_char_value(char base64char);
/**
* decode a 4 char base64 encoded byte triple
*
* @param quadruple the 4 characters that should be decoded
* @param result the decoded data
* @return length of the result (1, 2 or 3), 0 on failure
*/
int _base64_decode_triple(char quadruple[4], unsigned char *result);
/**
* decode base64 encoded data
*
* @param source the encoded data (zero terminated)
* @param target pointer to the target buffer
* @param targetlen length of the target buffer
* @return length of converted data on success, -1 otherwise
*/
size_t base64_decode(const char *source, unsigned char *target, size_t targetlen);
/** get memory consumption */
size_t base64_needed(const size_t &iSize);
#endif

View File

@ -0,0 +1,104 @@
// ==++==
//
// Copyright (c) Microsoft Corporation. All rights reserved.
//
// ==--==
// =+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
//
// CacheLocalScheduleGroup.cpp
//
// Implementation file for CacheLocalScheduleGroup.
//
// =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
#include "concrtinternal.h"
namespace Concurrency
{
namespace details
{
/// <summary>
/// Puts a runnable context into the runnables collection in the schedule group.
/// </summary>
void CacheLocalScheduleGroupSegment::AddToRunnablesCollection(InternalContextBase* pContext)
{
m_runnableContexts.Enqueue(pContext);
}
/// <summary>
/// Places a chore in the mailbox associated with this schedule group segment.
/// </summary>
/// <param name="pChore">
/// The chore to mail.
/// </param>
/// <returns>
/// The mailbox slot into which the chore was placed.
/// </returns>
/// <remarks>
/// A mailed chore should also be placed on its regular work stealing queue. The mailing must come first and once mailed, the chore body
/// cannot be referenced until the slot is successfully claimed via a call to the ClaimSlot method.
/// </remarks>
Mailbox<_UnrealizedChore>::Slot CacheLocalScheduleGroupSegment::MailChore(_UnrealizedChore *pChore)
{
//
// There are two possible segments to which pChore can be accounted. One is the segment where it will appear on the WSQ -- the other is
// the segment where it will appear on the mailbox. Both are in the same group and hence we do not at present have reference counting
// issues. It will be attributed to the group it was picked up from which will further honor that affinity if the task blocks, etc...
//
ASSERT(!m_affinity._Is_system());
Mailbox<_UnrealizedChore>::Slot affinitySlot = m_mailedTasks.Enqueue(pChore);
#if _UMSTRACE && _CHORETRACK
OMTRACE(MTRACE_EVT_CHOREMAILED, this, SchedulerBase::FastCurrentContext(), NULL, pChore);
OMTRACE(MTRACE_EVT_CHOREMAILED, m_pOwningGroup, SchedulerBase::FastCurrentContext(), NULL, pChore);
#endif // _UMSTRACE && _CHORETRACK
ASSERT(!affinitySlot.IsEmpty());
return affinitySlot;
}
/// <summary>
/// Notifies virtual processors that work affinitized to them has become available in the schedule group segment.
/// </summary>
void CacheLocalScheduleGroupSegment::NotifyAffinitizedWork()
{
SchedulerBase *pScheduler = m_pOwningGroup->GetScheduler();
pScheduler->PostAffinityMessage(m_affinitySet);
//
// If this item qualifies for the quick cache, stash it.
//
if (m_affinity._GetType() == location::_ExecutionResource)
{
pScheduler->SetQuickCacheSlot(m_maskIdIf, this);
}
}
/// <summary>
/// Places a chore in a mailbox associated with the schedule group which is biased towards tasks being picked up from the specified
/// location.
/// </summary>
/// <param name="pChore">
/// The chore to mail.
/// </param>
/// <param name="pPlacement">
/// A pointer to a location where the chore will be mailed.
/// </param>
/// <returns>
/// The mailbox slot into which the chore was placed.
/// </returns>
/// <remarks>
/// A mailed chore should also be placed on its regular work stealing queue. The mailing must come first and once mailed, the chore body
/// cannot be referenced until the slot is successfully claimed via a call to the ClaimSlot method.
/// </remarks>
Mailbox<_UnrealizedChore>::Slot CacheLocalScheduleGroup::MailChore(_UnrealizedChore * pChore,
location * pPlacement,
ScheduleGroupSegmentBase ** ppDestinationSegment)
{
CacheLocalScheduleGroupSegment * pCacheLocalSegment = static_cast<CacheLocalScheduleGroupSegment *>(LocateSegment(pPlacement, true));
*ppDestinationSegment = pCacheLocalSegment;
return pCacheLocalSegment->MailChore(pChore);
}
} // namespace details
} // namespace Concurrency

View File

@ -0,0 +1,159 @@
// ==++==
//
// Copyright (c) Microsoft Corporation. All rights reserved.
//
// ==--==
// =+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
//
// CacheLocalScheduleGroup.h
//
// Header file containing CacheLocalScheduleGroup related declarations.
//
// =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
#pragma once
namespace Concurrency
{
namespace details
{
class CacheLocalScheduleGroup;
class CacheLocalScheduleGroupSegment : public ScheduleGroupSegmentBase
{
public:
//
// Public Methods
//
/// <summary>
/// Constructs a cache local schedule group segment
/// </summary>
CacheLocalScheduleGroupSegment(ScheduleGroupBase *pOwningGroup, SchedulingRing *pOwningRing, location* pSegmentAffinity) :
ScheduleGroupSegmentBase(pOwningGroup, pOwningRing, pSegmentAffinity)
{
}
/// <summary>
/// Places a chore in the mailbox associated with this schedule group segment.
/// </summary>
/// <param name="pChore">
/// The chore to mail.
/// </param>
/// <returns>
/// The mailbox slot into which the chore was placed.
/// </returns>
/// <remarks>
/// A mailed chore should also be placed on its regular work stealing queue. The mailing must come first and once mailed, the chore body
/// cannot be referenced until the slot is successfully claimed via a call to the ClaimSlot method.
/// </remarks>
Mailbox<_UnrealizedChore>::Slot MailChore(_UnrealizedChore *pChore);
/// <summary>
/// Notifies virtual processors that work affinitized to them has become available in the schedule group segment.
/// </summary>
virtual void NotifyAffinitizedWork();
protected:
private:
friend class SchedulerBase;
friend class CacheLocalScheduleGroup;
friend class ContextBase;
friend class ExternalContextBase;
friend class InternalContextBase;
friend class ThreadInternalContext;
friend class SchedulingNode;
friend class SchedulingRing;
friend class VirtualProcessor;
//
// Private data
//
// Each schedule group has three stores of work. It has a collection of runnable contexts,
// a FIFO queue of realized chores and a list of workqueues that hold unrealized chores.
// A collection of Runnable contexts.
SafeSQueue<InternalContextBase, _HyperNonReentrantLock> m_runnableContexts;
//
// Private methods
//
/// <summary>
/// Puts a runnable context into the runnables collection in the schedule group.
/// </summary>
void AddToRunnablesCollection(InternalContextBase *pContext);
InternalContextBase *GetRunnableContext()
{
if (m_runnableContexts.Empty())
return NULL;
InternalContextBase *pContext = m_runnableContexts.Dequeue();
#if defined(_DEBUG)
SetContextDebugBits(pContext, CTX_DEBUGBIT_REMOVEDFROMRUNNABLES);
#endif // _DEBUG
return pContext;
}
};
class CacheLocalScheduleGroup : public ScheduleGroupBase
{
public:
/// <summary>
/// Constructs a new cache local schedule group.
/// </summary>
CacheLocalScheduleGroup(SchedulerBase *pScheduler, location* pGroupPlacement) :
ScheduleGroupBase(pScheduler, pGroupPlacement)
{
m_kind = CacheLocalScheduling;
}
/// <summary>
/// Places a chore in a mailbox associated with the schedule group which is biased towards tasks being picked up from the specified
/// location.
/// </summary>
/// <param name="pChore">
/// The chore to mail.
/// </param>
/// <param name="pPlacement">
/// A pointer to a location where the chore will be mailed.
/// </param>
/// <returns>
/// The mailbox slot into which the chore was placed.
/// </returns>
/// <remarks>
/// A mailed chore should also be placed on its regular work stealing queue. The mailing must come first and once mailed, the chore body
/// cannot be referenced until the slot is successfully claimed via a call to the ClaimSlot method.
/// </remarks>
virtual Mailbox<_UnrealizedChore>::Slot MailChore(_UnrealizedChore * pChore,
location * pPlacement,
ScheduleGroupSegmentBase ** ppDestinationSegment);
protected:
/// <summary>
/// Allocates a new cache local schedule group segment within the specified group and ring with the specified affinity.
/// </summary>
/// <param name="pSegmentAffinity">
/// The affinity for the segment.
/// </param>
/// <param name="pOwningRing">
/// The scheduling ring to which the newly allocated segment will belong.
/// </param>
/// <returns>
/// A new cache local schedule group within the specified group and ring with the specified affinity.
/// </returns>
virtual ScheduleGroupSegmentBase* AllocateSegment(SchedulingRing *pOwningRing, location* pSegmentAffinity)
{
return _concrt_new CacheLocalScheduleGroupSegment(this, pOwningRing, pSegmentAffinity);
}
};
} // namespace details
} // namespace Concurrency

View File

@ -0,0 +1,357 @@
/***
*concurrencysal.h - markers for documenting the concurrent semantics of APIs
*
* Copyright (c) Microsoft Corporation. All rights reserved.
*
*Purpose:
* This file contains macros for Concurrency SAL annotations. Definitions
* starting with _Internal are low level macros that are subject to change.
* Users should not use those low level macros directly.
* [ANSI]
*
* [Public]
*
****/
#ifndef CONCURRENCYSAL_H
#define CONCURRENCYSAL_H
#pragma once
#ifdef __cplusplus // [
extern "C" {
#endif // ]
#if !defined(__midl) && defined(_PREFAST_) && _MSC_VER >= 1000 && !defined(_SDV_)
__ANNOTATION(SAL_guarded_by(__deferTypecheck void *));
__ANNOTATION(SAL_write_guarded_by(__deferTypecheck void *));
__ANNOTATION(SAL_requires_lock_held(__deferTypecheck void *));
__ANNOTATION(SAL_requires_exclusive_lock_held(__deferTypecheck void *));
__ANNOTATION(SAL_requires_shared_lock_held(__deferTypecheck void *));
__ANNOTATION(SAL_requires_lock_not_held(__deferTypecheck void *));
__ANNOTATION(SAL_requires_no_locks_held(void));
__ANNOTATION(SAL_set_lock_count_to_zero(__deferTypecheck void *));
__ANNOTATION(SAL_set_lock_count_to_one(__deferTypecheck void *));
__ANNOTATION(SAL_acquires_lock(__deferTypecheck void *));
__ANNOTATION(SAL_acquires_exclusive_lock(__deferTypecheck void *));
__ANNOTATION(SAL_acquires_shared_lock(__deferTypecheck void *));
__ANNOTATION(SAL_releases_lock(__deferTypecheck void *));
__ANNOTATION(SAL_releases_exclusive_lock(__deferTypecheck void *));
__ANNOTATION(SAL_releases_shared_lock(__deferTypecheck void *));
__ANNOTATION(SAL_ignore_lock_match(__deferTypecheck void *));
__ANNOTATION(SAL_has_lock_property(__AuToQuOtE __In_impl_ char *));
__ANNOTATION(SAL_has_lock_level(__AuToQuOtE __In_impl_ char *));
__ANNOTATION(SAL_lock_level_order(__deferTypecheck void *, __deferTypecheck void *));
__ANNOTATION(SAL_no_competing_thread(void));
__ANNOTATION(SAL_set_same_lock(__deferTypecheck void *, __deferTypecheck void *));
/*
* pre-defined global system locks
*/
extern int _Global_interlock_;
extern int _Global_cancel_spin_lock_;
extern int _Global_critical_region_;
/*
* Annotation identifiers
*/
#define _Internal_create_CSAL_identifier_(id) const char id##[] = "";
_Internal_create_CSAL_identifier_(_Lock_kind_mutex_)
_Internal_create_CSAL_identifier_(_Lock_kind_event_)
_Internal_create_CSAL_identifier_(_Lock_kind_semaphore_)
_Internal_create_CSAL_identifier_(_Lock_kind_spin_lock_)
_Internal_create_CSAL_identifier_(_Lock_kind_critical_section_)
/*
* data protection
*/
#define _Guarded_by_(lock) _SAL2_Source_(_Guarded_by_, (lock), _SA_annotes1(SAL_guarded_by,lock))
#define _Write_guarded_by_(lock) _SAL2_Source_(_Write_guarded_by_, (lock), _SA_annotes1(SAL_write_guarded_by,lock))
#define _Interlocked_ _Guarded_by_(_Global_interlock_)
/*
* interlocked operand used in interlocked instructions
*/
#ifndef _Interlocked_operand_
#define _Interlocked_operand_ _SAL2_Source_(_Interlocked_operand_, (), _Pre_ _SA_annotes0(SAL_interlocked))
#endif
/*
* caller/callee locking contracts
*/
#define _Requires_lock_held_(lock) _SAL2_Source_(_Requires_lock_held_, (lock), _Pre_ _SA_annotes1(SAL_requires_lock_held,lock))
#define _Requires_exclusive_lock_held_(lock) _SAL2_Source_(_Requires_exclusive_lock_held_, (lock), _Pre_ _SA_annotes1(SAL_requires_exclusive_lock_held,lock))
#define _Requires_shared_lock_held_(lock) _SAL2_Source_(_Requires_shared_lock_held_, (lock), _Pre_ _SA_annotes1(SAL_requires_shared_lock_held,lock))
#define _Requires_lock_not_held_(lock) _SAL2_Source_(_Requires_lock_not_held_, (lock), _Pre_ _SA_annotes1(SAL_requires_lock_not_held,lock))
#define _Requires_no_locks_held_ _SAL2_Source_(_Requires_no_locks_held_, (), _Pre_ _SA_annotes0(SAL_requires_no_locks_held))
/*
* acquire/release locking side effects
*/
#define _Acquires_lock_(lock) _SAL2_Source_(_Acquires_lock_, (lock), _Post_ _SA_annotes1(SAL_acquires_lock,lock))
#define _Acquires_exclusive_lock_(lock) _SAL2_Source_(_Acquires_exclusive_lock_, (lock), _Post_ _SA_annotes1(SAL_acquires_exclusive_lock,lock))
#define _Acquires_shared_lock_(lock) _SAL2_Source_(_Acquires_shared_lock_, (lock), _Post_ _SA_annotes1(SAL_acquires_shared_lock,lock))
#define _Releases_lock_(lock) _SAL2_Source_(_Releases_lock_, (lock), _Post_ _SA_annotes1(SAL_releases_lock,lock))
#define _Releases_exclusive_lock_(lock) _SAL2_Source_(_Releases_exclusive_lock_, (lock), _Post_ _SA_annotes1(SAL_releases_exclusive_lock,lock))
#define _Releases_shared_lock_(lock) _SAL2_Source_(_Releases_shared_lock_, (lock), _Post_ _SA_annotes1(SAL_releases_shared_lock,lock))
/*
* acquire/release locking side effects for non-reentrant locks
*/
#define _Acquires_nonreentrant_lock_(lock) \
_SAL2_Source_(_Acquires_nonreentrant_lock_, (lock), \
_Requires_lock_not_held_(lock) \
_Acquires_lock_(lock))
#define _Releases_nonreentrant_lock_(lock) \
_SAL2_Source_(_Releases_nonreentrant_lock_, (lock), \
_Requires_lock_held_(lock) \
_Releases_lock_(lock))
#define _Post_same_lock_(a,b) _SAL2_Source_(_Post_same_lock_, (a,b), _Post_ _SA_annotes2(SAL_set_same_lock,a,b))
/*
* lock level
*/
#define _Create_lock_level_(level) _Internal_create_CSAL_identifier_(level)
#define _Has_lock_level_(level) _SAL2_Source_(_Has_lock_level_, (level), _SA_annotes1(SAL_has_lock_level,#level))
#define _Internal_lock_level_order_(a,b) _SAL2_Source_(_Internal_lock_level_order_, (a,b), _SA_annotes2(SAL_lock_level_order,a,b))
#define _Csalcat1_(x,y) x##y
#define _Csalcat2_(x,y) _Csalcat1_(x,y)
#define _Lock_level_order_(a,b) \
extern _Internal_lock_level_order_(a,b) void _Sal_order_##a##_##b(_In_z_ char*a, _In_z_ char*b); \
static __inline void CSALCAT2(CSAL_LockOrder,__COUNTER__)(void){_Sal_order_##a##_##b(#a,#b);}
/*
* threading context
*/
#define _No_competing_thread_ _SAL2_Source_(_No_competing_thread_, (), _Pre_ _SA_annotes0(SAL_no_competing_thread))
/*
* refinement and suppression
*/
extern _Acquires_lock_(*plock) void _Internal_acquires_lock_(void* plock);
extern _Releases_lock_(*plock) void _Internal_releases_lock_(void* plock);
#define _Internal_set_lock_count_to_zero_(lock) _SAL2_Source_(Internal_set_lock_count_to_zero_, (lock), _Post_ _SA_annotes1(SAL_set_lock_count_to_zero,lock))
#define _Internal_set_lock_count_to_one_(lock) _SAL2_Source_(_Internal_set_lock_count_to_one_, (lock), _Post_ _SA_annotes1(SAL_set_lock_count_to_one,lock))
extern _Internal_set_lock_count_to_one_(*plock) void _Internal_lock_held_(void* plock);
extern _Internal_set_lock_count_to_zero_(*plock) void _Internal_lock_not_held_(void* plock);
extern _Post_same_lock_(*plock1, *plock2) void _Internal_same_lock_(void* plock1, void* plock2);
#define _Analysis_assume_lock_acquired_(lock) _Internal_acquires_lock_((void*)(&(lock)))
#define _Analysis_assume_lock_released_(lock) _Internal_releases_lock_((void*)(&(lock)))
#define _Analysis_assume_lock_held_(lock) _Internal_lock_held_((void*)(&(lock)))
#define _Analysis_assume_lock_not_held_(lock) _Internal_lock_not_held_((void*)(&(lock)))
#define _Analysis_assume_same_lock_(lock1, lock2) _Internal_same_lock_((void*)(&(lock1)), (void*)(&(lock2)))
/*
* _Function_ignore_lock_checking_ may be deprecated in future versions of SAL
*/
#define _Function_ignore_lock_checking_(lock) _SAL2_Source_(_Function_ignore_lock_checking_, (lock), _Pre_ _SA_annotes1(SAL_ignore_lock_match,lock))
extern _Function_ignore_lock_checking_(*plock) void _Internal_suppress_lock_checking_(void* plock);
/*
* _Analysis_suppress_lock_checking_ may be deprecated in future versions of SAL
*/
#define _Analysis_suppress_lock_checking_(lock) _Internal_suppress_lock_checking_((void*)(&(lock)));
#define _Benign_race_begin_ __pragma(warning(push)) __pragma(warning(disable:26100 26101 26150 26130 26180 26131 26181 28112))
#define _Benign_race_end_ __pragma(warning(pop))
#define _No_competing_thread_begin_ __pragma(warning(push)) __pragma(warning(disable:26100 26101 26150 26101 26151 26110 26160 26130 26180 26131 26181 28112))
#define _No_competing_thread_end_ __pragma(warning(pop))
/*
* lock kinds
*/
#define _Has_lock_kind_(kind) _SAL2_Source_(_Has_lock_kind_, (kind), _SA_annotes1(SAL_has_lock_property,#kind))
/*
* Old spelling
* Note: the old version may be deprecated in the future!!!
*/
extern int __system_interlock;
extern int __system_cancel_spinlock;
extern int __system_critical_region;
#define __guarded_by(lock) _SAL1_1_Source_(__guarded_by, (lock), _SA_annotes1(SAL_guarded_by,lock))
#define __write_guarded_by(lock) _SAL1_1_Source_(__write_guarded_by, (lock), _SA_annotes1(SAL_write_guarded_by,lock))
#define __interlocked __guarded_by(_Global_interlock_)
/*
* caller/callee locking contracts
*/
#define __requires_lock_held(lock) _SAL1_1_Source_(__requires_lock_held, (lock), __pre _SA_annotes1(SAL_requires_lock_held,lock))
#define __requires_exclusive_lock_held(lock) _SAL1_1_Source_(__requires_exclusive_lock_held, (lock), __pre _SA_annotes1(SAL_requires_exclusive_lock_held,lock))
#define __requires_shared_lock_held(lock) _SAL1_1_Source_(__requires_shared_lock_held, (lock), __pre _SA_annotes1(SAL_requires_shared_lock_held,lock))
#define __requires_lock_not_held(lock) _SAL1_1_Source_(__requires_lock_not_held, (lock), __pre _SA_annotes1(SAL_requires_lock_not_held,lock))
#define __requires_no_locks_held _SAL1_1_Source_(__requires_no_locks_held, (), __pre _SA_annotes0(SAL_requires_no_locks_held))
/*
* acquire/release locking side effects
*/
#define __acquires_lock(lock) _SAL1_1_Source_(__acquires_lock, (lock), __post _SA_annotes1(SAL_acquires_lock,lock))
#define __acquires_exclusive_lock(lock) _SAL1_1_Source_(__acquires_exclusive_lock, (lock), __post _SA_annotes1(SAL_acquires_exclusive_lock,lock))
#define __acquires_shared_lock(lock) _SAL1_1_Source_(__acquires_shared_lock, (lock), __post _SA_annotes1(SAL_acquires_shared_lock,lock))
#define __releases_lock(lock) _SAL1_1_Source_(__releases_lock, (lock), __post _SA_annotes1(SAL_releases_lock,lock))
#define __releases_exclusive_lock(lock) _SAL1_1_Source_(__releases_exclusive_lock, (lock),__post _SA_annotes1(SAL_releases_exclusive_lock,lock))
#define __releases_shared_lock(lock) _SAL1_1_Source_(__releases_shared_lock, (lock), __post _SA_annotes1(SAL_releases_shared_lock,lock))
/*
* lock properties
* The following kind options are supported:
* __has_lock_property(MUTEX)
* __has_lock_property(EVENT)
* __has_lock_property(SEMAPHORE)
* __has_lock_property(OTHER_HANDLE)
* __has_lock_property(REENTRANT)
* __has_lock_property(NON_REENTRANT)
*/
#define __has_lock_property(kind) _SAL1_1_Source_(__has_lock_property, (kind), _SA_annotes1(SAL_has_lock_property,#kind))
/*
* lock level
*/
#define __declare_lock_level(level) _Internal_create_CSAL_identifier_(level)
#define __has_lock_level(level) _SAL1_1_Source_(__has_lock_level, (level), _SA_annotes1(SAL_has_lock_level,#level))
#define __internal_lock_level_order(a,b) _SAL1_1_Source_(__internal_lock_level_order, (a,b), _SA_annotes2(SAL_lock_level_order,#a,#b))
#define CSALCAT1(x,y) x##y
#define CSALCAT2(x,y) CSALCAT1(x,y)
#define __lock_level_order(a,b) \
extern __internal_lock_level_order(a,b) void __sal_order_##a##_##b(__in_z char*a, __in_z char*b); \
static __inline void CSALCAT2(CSAL_LockOrder,__COUNTER__)(void){__sal_order_##a##_##b(#a,#b);}
/*
* threading context
*/
#define __no_competing_thread _SAL1_1_Source_(__no_competing_thread, (), __pre _SA_annotes0(SAL_no_competing_thread))
/*
* refinement and suppression
*/
extern __acquires_lock(*plock) void __internal_acquires_lock(void* plock);
extern __releases_lock(*plock) void __internal_releases_lock(void* plock);
#define __analysis_assume_lock_acquired(lock) __internal_acquires_lock((void*)(&(lock)))
#define __analysis_assume_lock_released(lock) __internal_releases_lock((void*)(&(lock)))
#define __function_ignore_lock_checking(lock) _SAL1_1_Source_(__function_ignore_lock_cleanup, (lock), __pre _SA_annotes1(SAL_ignore_lock_match,lock))
extern __function_ignore_lock_checking(*plock) void __internal_suppress_lock_checking(void* plock);
#define __analysis_suppress_lock_checking(lock) __internal_suppress_lock_checking((void*)(&(lock)));
#define BENIGN_RACE_BEGIN __pragma(warning(push)) __pragma(warning(disable:26100 26150 26130 26180 26131 26181))
#define BENIGN_RACE_END __pragma(warning(pop))
#define NO_COMPETING_THREAD_BEGIN __pragma(warning(push)) __pragma(warning(disable:26100 26150 26101 26151 26110 26160 26130 26180 26131 26181))
#define NO_COMPETING_THREAD_END __pragma(warning(pop))
#else
#ifndef _Interlocked_operand_
#define _Interlocked_operand_
#endif
#define _Guarded_by_(lock)
#define _Write_guarded_by_(lock)
#define _Interlocked_
#define _Requires_lock_held_(lock)
#define _Requires_exclusive_lock_held_(lock)
#define _Requires_shared_lock_held_(lock)
#define _Requires_lock_not_held_(lock)
#define _Requires_no_locks_held_
#define _Acquires_lock_(lock)
#define _Acquires_exclusive_lock_(lock)
#define _Acquires_shared_lock_(lock)
#define _Releases_lock_(lock)
#define _Releases_exclusive_lock_(lock)
#define _Releases_shared_lock_(lock)
#define _Acquires_nonreentrant_lock_(lock)
#define _Releases_nonreentrant_lock_(lock)
#define _Post_same_lock_(lock1,lock2)
#define _Internal_set_lock_count_(lock, count)
#define _Create_lock_level_(level)
#define _Has_lock_level_(level)
#define _Internal_lock_level_order_(a,b)
#define _Csalcat1_(x,y)
#define _Csalcat2_(x,y)
#define _Lock_level_order_(a,b)
#define _No_competing_thread_
#define _Analysis_assume_lock_acquired_(lock)
#define _Analysis_assume_lock_released_(lock)
#define _Analysis_assume_lock_held_(lock)
#define _Analysis_assume_lock_not_held_(lock)
#define _Analysis_assume_same_lock_(lock1, lock2)
#define _Function_ignore_lock_checking_(lock)
#define _Analysis_suppress_lock_checking_(lock)
#define _Benign_race_begin_ __pragma(warning(push))
#define _Benign_race_end_ __pragma(warning(pop))
#define _No_competing_thread_begin_ __pragma(warning(push))
#define _No_competing_thread_end_ __pragma(warning(pop))
#define _Has_lock_kind_(kind)
/*
* Old spelling: will be deprecated
*/
#define __guarded_by(lock)
#define __write_guarded_by(lock)
#define __interlocked
#define __requires_lock_held(lock)
#define __requires_exclusive_lock_held(lock)
#define __requires_shared_lock_held(lock)
#define __requires_lock_not_held(lock)
#define __requires_no_locks_held
#define __acquires_lock(lock)
#define __acquires_exclusive_lock(lock)
#define __acquires_shared_lock(lock)
#define __releases_lock(lock)
#define __releases_exclusive_lock(lock)
#define __releases_shared_lock(lock)
#define __has_lock_property(kind)
#define __declare_lock_level(level)
#define __has_lock_level(level)
#define __internal_lock_level_order(a,b)
#define CSALCAT1(x,y)
#define CSALCAT2(x,y)
#define __lock_level_order(a,b)
#define __no_competing_thread
#define __analysis_assume_lock_acquired(lock)
#define __analysis_assume_lock_released(lock)
#define __function_ignore_lock_checking(lock)
#define __analysis_suppress_lock_checking(lock)
#define BENIGN_RACE_BEGIN __pragma(warning(push))
#define BENIGN_RACE_END __pragma(warning(pop))
#define NO_COMPETING_THREAD_BEGIN __pragma(warning(push))
#define NO_COMPETING_THREAD_END __pragma(warning(pop))
#endif
#ifdef __cplusplus
}
#endif
#endif // CONCURRENCYSAL_H

View File

@ -0,0 +1,366 @@
/* MD5
converted to C++ class by Frank Thilo (thilo@unix-ag.org)
for bzflag (http://www.bzflag.org)
based on:
md5.h and md5.c
reference implementation of RFC 1321
Copyright (C) 1991-2, RSA Data Security, Inc. Created 1991. All
rights reserved.
License to copy and use this software is granted provided that it
is identified as the "RSA Data Security, Inc. MD5 Message-Digest
Algorithm" in all material mentioning or referencing this software
or this function.
License is also granted to make and use derivative works provided
that such works are identified as "derived from the RSA Data
Security, Inc. MD5 Message-Digest Algorithm" in all material
mentioning or referencing the derived work.
RSA Data Security, Inc. makes no representations concerning either
the merchantability of this software or the suitability of this
software for any particular purpose. It is provided "as is"
without express or implied warranty of any kind.
These notices must be retained in any copies of any part of this
documentation and/or software.
*/
/* interface header */
#include "MD5.h"
#include <cstdlib>
#include <cstdio>
#include <cmath>
#include <sstream>
// Constants for MD5Transform routine.
#define S11 7
#define S12 12
#define S13 17
#define S14 22
#define S21 5
#define S22 9
#define S23 14
#define S24 20
#define S31 4
#define S32 11
#define S33 16
#define S34 23
#define S41 6
#define S42 10
#define S43 15
#define S44 21
///////////////////////////////////////////////
// F, G, H and I are basic MD5 functions.
inline MD5::uint4 MD5::F(uint4 x, uint4 y, uint4 z) {
return (x&y) | (~x&z);
}
inline MD5::uint4 MD5::G(uint4 x, uint4 y, uint4 z) {
return (x&z) | (y&~z);
}
inline MD5::uint4 MD5::H(uint4 x, uint4 y, uint4 z) {
return x^y^z;
}
inline MD5::uint4 MD5::I(uint4 x, uint4 y, uint4 z) {
return y ^ (x | ~z);
}
// rotate_left rotates x left n bits.
inline MD5::uint4 MD5::rotate_left(uint4 x, int n) {
return (x << n) | (x >> (32-n));
}
// FF, GG, HH, and II transformations for rounds 1, 2, 3, and 4.
// Rotation is separate from addition to prevent recomputation.
inline void MD5::FF(uint4 &a, uint4 b, uint4 c, uint4 d, uint4 x, uint4 s, uint4 ac) {
a = rotate_left(a+ F(b,c,d) + x + ac, s) + b;
}
inline void MD5::GG(uint4 &a, uint4 b, uint4 c, uint4 d, uint4 x, uint4 s, uint4 ac) {
a = rotate_left(a + G(b,c,d) + x + ac, s) + b;
}
inline void MD5::HH(uint4 &a, uint4 b, uint4 c, uint4 d, uint4 x, uint4 s, uint4 ac) {
a = rotate_left(a + H(b,c,d) + x + ac, s) + b;
}
inline void MD5::II(uint4 &a, uint4 b, uint4 c, uint4 d, uint4 x, uint4 s, uint4 ac) {
a = rotate_left(a + I(b,c,d) + x + ac, s) + b;
}
//////////////////////////////////////////////
// default ctor, just initailize
MD5::MD5()
{
init();
}
//////////////////////////////////////////////
// nifty shortcut ctor, compute MD5 for string and finalize it right away
MD5::MD5(const std::string &text)
{
init();
update(text.c_str(), (MD5::size_type)text.length());
finalize();
}
//////////////////////////////
void MD5::init()
{
finalized=false;
for (int i = 0; i < blocksize; ++i) buffer[i] = 0;
for (int i = 0; i < 16; ++i) digest[i] = 0;
count[0] = 0;
count[1] = 0;
// load magic initialization constants.
state[0] = 0x67452301;
state[1] = 0xefcdab89;
state[2] = 0x98badcfe;
state[3] = 0x10325476;
}
//////////////////////////////
// decodes input (unsigned char) into output (uint4). Assumes len is a multiple of 4.
void MD5::decode(uint4 output[], const uint1 input[], size_type len)
{
for (unsigned int i = 0, j = 0; j < len; i++, j += 4)
output[i] = ((uint4)input[j]) | (((uint4)input[j+1]) << 8) |
(((uint4)input[j+2]) << 16) | (((uint4)input[j+3]) << 24);
}
//////////////////////////////
// encodes input (uint4) into output (unsigned char). Assumes len is
// a multiple of 4.
void MD5::encode(uint1 output[], const uint4 input[], size_type len)
{
for (size_type i = 0, j = 0; j < len; i++, j += 4) {
output[j] = input[i] & 0xff;
output[j+1] = (input[i] >> 8) & 0xff;
output[j+2] = (input[i] >> 16) & 0xff;
output[j+3] = (input[i] >> 24) & 0xff;
}
}
//////////////////////////////
// apply MD5 algo on a block
void MD5::transform(const uint1 block[blocksize])
{
uint4 a = state[0], b = state[1], c = state[2], d = state[3], x[16];
decode (x, block, blocksize);
/* Round 1 */
FF (a, b, c, d, x[ 0], S11, 0xd76aa478); /* 1 */
FF (d, a, b, c, x[ 1], S12, 0xe8c7b756); /* 2 */
FF (c, d, a, b, x[ 2], S13, 0x242070db); /* 3 */
FF (b, c, d, a, x[ 3], S14, 0xc1bdceee); /* 4 */
FF (a, b, c, d, x[ 4], S11, 0xf57c0faf); /* 5 */
FF (d, a, b, c, x[ 5], S12, 0x4787c62a); /* 6 */
FF (c, d, a, b, x[ 6], S13, 0xa8304613); /* 7 */
FF (b, c, d, a, x[ 7], S14, 0xfd469501); /* 8 */
FF (a, b, c, d, x[ 8], S11, 0x698098d8); /* 9 */
FF (d, a, b, c, x[ 9], S12, 0x8b44f7af); /* 10 */
FF (c, d, a, b, x[10], S13, 0xffff5bb1); /* 11 */
FF (b, c, d, a, x[11], S14, 0x895cd7be); /* 12 */
FF (a, b, c, d, x[12], S11, 0x6b901122); /* 13 */
FF (d, a, b, c, x[13], S12, 0xfd987193); /* 14 */
FF (c, d, a, b, x[14], S13, 0xa679438e); /* 15 */
FF (b, c, d, a, x[15], S14, 0x49b40821); /* 16 */
/* Round 2 */
GG (a, b, c, d, x[ 1], S21, 0xf61e2562); /* 17 */
GG (d, a, b, c, x[ 6], S22, 0xc040b340); /* 18 */
GG (c, d, a, b, x[11], S23, 0x265e5a51); /* 19 */
GG (b, c, d, a, x[ 0], S24, 0xe9b6c7aa); /* 20 */
GG (a, b, c, d, x[ 5], S21, 0xd62f105d); /* 21 */
GG (d, a, b, c, x[10], S22, 0x2441453); /* 22 */
GG (c, d, a, b, x[15], S23, 0xd8a1e681); /* 23 */
GG (b, c, d, a, x[ 4], S24, 0xe7d3fbc8); /* 24 */
GG (a, b, c, d, x[ 9], S21, 0x21e1cde6); /* 25 */
GG (d, a, b, c, x[14], S22, 0xc33707d6); /* 26 */
GG (c, d, a, b, x[ 3], S23, 0xf4d50d87); /* 27 */
GG (b, c, d, a, x[ 8], S24, 0x455a14ed); /* 28 */
GG (a, b, c, d, x[13], S21, 0xa9e3e905); /* 29 */
GG (d, a, b, c, x[ 2], S22, 0xfcefa3f8); /* 30 */
GG (c, d, a, b, x[ 7], S23, 0x676f02d9); /* 31 */
GG (b, c, d, a, x[12], S24, 0x8d2a4c8a); /* 32 */
/* Round 3 */
HH (a, b, c, d, x[ 5], S31, 0xfffa3942); /* 33 */
HH (d, a, b, c, x[ 8], S32, 0x8771f681); /* 34 */
HH (c, d, a, b, x[11], S33, 0x6d9d6122); /* 35 */
HH (b, c, d, a, x[14], S34, 0xfde5380c); /* 36 */
HH (a, b, c, d, x[ 1], S31, 0xa4beea44); /* 37 */
HH (d, a, b, c, x[ 4], S32, 0x4bdecfa9); /* 38 */
HH (c, d, a, b, x[ 7], S33, 0xf6bb4b60); /* 39 */
HH (b, c, d, a, x[10], S34, 0xbebfbc70); /* 40 */
HH (a, b, c, d, x[13], S31, 0x289b7ec6); /* 41 */
HH (d, a, b, c, x[ 0], S32, 0xeaa127fa); /* 42 */
HH (c, d, a, b, x[ 3], S33, 0xd4ef3085); /* 43 */
HH (b, c, d, a, x[ 6], S34, 0x4881d05); /* 44 */
HH (a, b, c, d, x[ 9], S31, 0xd9d4d039); /* 45 */
HH (d, a, b, c, x[12], S32, 0xe6db99e5); /* 46 */
HH (c, d, a, b, x[15], S33, 0x1fa27cf8); /* 47 */
HH (b, c, d, a, x[ 2], S34, 0xc4ac5665); /* 48 */
/* Round 4 */
II (a, b, c, d, x[ 0], S41, 0xf4292244); /* 49 */
II (d, a, b, c, x[ 7], S42, 0x432aff97); /* 50 */
II (c, d, a, b, x[14], S43, 0xab9423a7); /* 51 */
II (b, c, d, a, x[ 5], S44, 0xfc93a039); /* 52 */
II (a, b, c, d, x[12], S41, 0x655b59c3); /* 53 */
II (d, a, b, c, x[ 3], S42, 0x8f0ccc92); /* 54 */
II (c, d, a, b, x[10], S43, 0xffeff47d); /* 55 */
II (b, c, d, a, x[ 1], S44, 0x85845dd1); /* 56 */
II (a, b, c, d, x[ 8], S41, 0x6fa87e4f); /* 57 */
II (d, a, b, c, x[15], S42, 0xfe2ce6e0); /* 58 */
II (c, d, a, b, x[ 6], S43, 0xa3014314); /* 59 */
II (b, c, d, a, x[13], S44, 0x4e0811a1); /* 60 */
II (a, b, c, d, x[ 4], S41, 0xf7537e82); /* 61 */
II (d, a, b, c, x[11], S42, 0xbd3af235); /* 62 */
II (c, d, a, b, x[ 2], S43, 0x2ad7d2bb); /* 63 */
II (b, c, d, a, x[ 9], S44, 0xeb86d391); /* 64 */
state[0] += a;
state[1] += b;
state[2] += c;
state[3] += d;
// Zeroize sensitive information.
memset(x, 0, sizeof x);
}
//////////////////////////////
// MD5 block update operation. Continues an MD5 message-digest
// operation, processing another message block
void MD5::update(const unsigned char input[], size_type length)
{
// compute number of bytes mod 64
size_type index = count[0] / 8 % blocksize;
// Update number of bits
if ((count[0] += (length << 3)) < (length << 3))
count[1]++;
count[1] += (length >> 29);
// number of bytes we need to fill in buffer
size_type firstpart = 64 - index;
size_type i;
// transform as many times as possible.
if (length >= firstpart)
{
// fill buffer first, transform
memcpy(&buffer[index], input, firstpart);
transform(buffer);
// transform chunks of blocksize (64 bytes)
for (i = firstpart; i + blocksize <= length; i += blocksize)
transform(&input[i]);
index = 0;
}
else
i = 0;
// buffer remaining input
memcpy(&buffer[index], &input[i], length-i);
}
//////////////////////////////
// for convenience provide a verson with signed char
void MD5::update(const char input[], size_type length)
{
update((const unsigned char*)input, length);
}
//////////////////////////////
// MD5 finalization. Ends an MD5 message-digest operation, writing the
// the message digest and zeroizing the context.
MD5& MD5::finalize()
{
if (!finalized) {
static unsigned char padding[64] = {
0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
};
// Save number of bits
unsigned char bits[8];
encode(bits, count, 8);
// pad out to 56 mod 64.
size_type index = count[0] / 8 % 64;
size_type padLen = (index < 56) ? (56 - index) : (120 - index);
update(padding, padLen);
// Append length (before padding)
update(bits, 8);
// Store state in digest
encode(digest, state, 16);
// Zeroize sensitive information.
memset(buffer, 0, sizeof buffer);
memset(count, 0, sizeof count);
finalized=true;
}
return *this;
}
//////////////////////////////
// return hex representation of digest as string
std::string MD5::hexdigest() const
{
if (!finalized)
return "";
char buf[33];
for (int i=0; i<16; i++)
sprintf(buf+i*2, "%02x", digest[i]);
buf[32]=0;
return std::string(buf);
}
//////////////////////////////
std::ostream& operator<<(std::ostream& out, MD5 md5)
{
return out << md5.hexdigest();
}
//////////////////////////////
std::string md5(const std::string &str)
{
MD5 md5 = MD5(str);
return md5.hexdigest();
}

View File

@ -0,0 +1,98 @@
/* MD5
converted to C++ class by Frank Thilo (thilo@unix-ag.org)
for bzflag (http://www.bzflag.org)
based on:
md5.h and md5.c
reference implementation of RFC 1321
Copyright (C) 1991-2, RSA Data Security, Inc. Created 1991. All
rights reserved.
License to copy and use this software is granted provided that it
is identified as the "RSA Data Security, Inc. MD5 Message-Digest
Algorithm" in all material mentioning or referencing this software
or this function.
License is also granted to make and use derivative works provided
that such works are identified as "derived from the RSA Data
Security, Inc. MD5 Message-Digest Algorithm" in all material
mentioning or referencing the derived work.
RSA Data Security, Inc. makes no representations concerning either
the merchantability of this software or the suitability of this
software for any particular purpose. It is provided "as is"
without express or implied warranty of any kind.
These notices must be retained in any copies of any part of this
documentation and/or software.
*/
#pragma once
#ifndef _MD5_H_
#define _MD5_H_
#define _HAS_EXCEPTIONS (0)
#define _CRT_SECURE_NO_WARNINGS
#include <cstring>
#include <string>
// a small class for calculating MD5 hashes of strings or byte arrays
// it is not meant to be fast or secure
//
// usage: 1) feed it blocks of uchars with update()
// 2) finalize()
// 3) get hexdigest() string
// or
// MD5(std::string).hexdigest()
//
// assumes that char is 8 bit and int is 32 bit
class MD5
{
public:
typedef unsigned int size_type; // must be 32bit
MD5();
MD5(const std::string& text);
void update(const unsigned char *buf, size_type length);
void update(const char *buf, size_type length);
MD5& finalize();
std::string hexdigest() const;
friend std::ostream& operator<<(std::ostream&, MD5 md5);
private:
void init();
typedef unsigned char uint1; // 8bit
typedef unsigned int uint4; // 32bit
enum {blocksize = 64}; // VC6 won't eat a const static int here
void transform(const uint1 block[blocksize]);
static void decode(uint4 output[], const uint1 input[], size_type len);
static void encode(uint1 output[], const uint4 input[], size_type len);
bool finalized;
uint1 buffer[blocksize]; // bytes that didn't fit in last 64 byte chunk
uint4 count[2]; // 64bit counter for number of bits (lo, hi)
uint4 state[4]; // digest so far
uint1 digest[16]; // the result
// low level logic operations
static inline uint4 F(uint4 x, uint4 y, uint4 z);
static inline uint4 G(uint4 x, uint4 y, uint4 z);
static inline uint4 H(uint4 x, uint4 y, uint4 z);
static inline uint4 I(uint4 x, uint4 y, uint4 z);
static inline uint4 rotate_left(uint4 x, int n);
static inline void FF(uint4 &a, uint4 b, uint4 c, uint4 d, uint4 x, uint4 s, uint4 ac);
static inline void GG(uint4 &a, uint4 b, uint4 c, uint4 d, uint4 x, uint4 s, uint4 ac);
static inline void HH(uint4 &a, uint4 b, uint4 c, uint4 d, uint4 x, uint4 s, uint4 ac);
static inline void II(uint4 &a, uint4 b, uint4 c, uint4 d, uint4 x, uint4 s, uint4 ac);
};
std::string md5(const std::string &str);
#endif

View File

@ -0,0 +1,384 @@
/***
*_ctype.c - function versions of ctype macros
*
* Copyright (c) Microsoft Corporation. All rights reserved.
*
*Purpose:
* This files provides function versions of the character
* classification and conversion macros in ctype.h.
*
*******************************************************************************/
/***
*ctype - Function versions of ctype macros
*
*Purpose:
* Function versions of the macros in ctype.h. In order to define
* these, we use a trick -- we use parentheses so we can use the
* name in the function declaration without macro expansion, then
* we use the macro in the definition part.
*
* Functions defined:
* isalpha isupper islower
* isdigit isxdigit isspace
* ispunct isalnum isprint
* isgraph isctrl __isascii
* __toascii __iscsym __iscsymf
* isblank
*
*Entry:
* int c = character to be tested
*Exit:
* returns non-zero = character is of the requested type
* 0 = character is NOT of the requested type
*
*Exceptions:
* None.
*
*******************************************************************************/
#include <cruntime.h>
#include <ctype.h>
#include <locale.h>
#include <mtdll.h>
#include <setlocal.h>
#ifdef _DEBUG
#define __fast_ch_check(a,b) _chvalidator(a,b)
#else /* _DEBUG */
#define __fast_ch_check(a,b) (__initiallocinfo.pctype[(a)] & (b))
#endif /* _DEBUG */
extern "C"
{
extern __inline int (__cdecl _isalpha_l) (
int c,
_locale_t plocinfo
)
{
_LocaleUpdate _loc_update(plocinfo);
return _isalpha_l(c, _loc_update.GetLocaleT());
}
extern __inline int (__cdecl isalpha) (
int c
)
{
if (__locale_changed == 0)
{
return __fast_ch_check(c, _ALPHA);
}
else
{
return (_isalpha_l)(c, NULL);
}
}
extern __inline int (__cdecl _isupper_l) (
int c,
_locale_t plocinfo
)
{
_LocaleUpdate _loc_update(plocinfo);
return _isupper_l(c, _loc_update.GetLocaleT());
}
extern __inline int (__cdecl isupper) (
int c
)
{
if (__locale_changed == 0)
{
return __fast_ch_check(c, _UPPER);
}
else
{
return (_isupper_l)(c, NULL);
}
}
extern __inline int (__cdecl _islower_l) (
int c,
_locale_t plocinfo
)
{
_LocaleUpdate _loc_update(plocinfo);
return _islower_l(c, _loc_update.GetLocaleT());
}
extern __inline int (__cdecl islower) (
int c
)
{
if (__locale_changed == 0)
{
return __fast_ch_check(c, _LOWER);
}
else
{
return (_islower_l)(c, NULL);
}
}
extern __inline int (__cdecl _isdigit_l) (
int c,
_locale_t plocinfo
)
{
_LocaleUpdate _loc_update(plocinfo);
return _isdigit_l(c, _loc_update.GetLocaleT());
}
extern __inline int (__cdecl isdigit) (
int c
)
{
if (__locale_changed == 0)
{
return __fast_ch_check(c, _DIGIT);
}
else
{
return (_isdigit_l)(c, NULL);
}
}
extern __inline int (__cdecl _isxdigit_l) (
int c,
_locale_t plocinfo
)
{
_LocaleUpdate _loc_update(plocinfo);
return _isxdigit_l(c, _loc_update.GetLocaleT());
}
extern __inline int (__cdecl isxdigit) (
int c
)
{
if (__locale_changed == 0)
{
return __fast_ch_check(c, _HEX);
}
else
{
return (_isxdigit_l)(c, NULL);
}
}
extern __inline int (__cdecl _isspace_l) (
int c,
_locale_t plocinfo
)
{
_LocaleUpdate _loc_update(plocinfo);
return _isspace_l(c, _loc_update.GetLocaleT());
}
extern __inline int (__cdecl isspace) (
int c
)
{
if (__locale_changed == 0)
{
return __fast_ch_check(c, _SPACE);
}
else
{
return (_isspace_l)(c, NULL);
}
}
extern __inline int (__cdecl _ispunct_l) (
int c,
_locale_t plocinfo
)
{
_LocaleUpdate _loc_update(plocinfo);
return _ispunct_l(c, _loc_update.GetLocaleT());
}
extern __inline int (__cdecl ispunct) (
int c
)
{
if (__locale_changed == 0)
{
return __fast_ch_check(c, _PUNCT);
}
else
{
return (_ispunct_l)(c, NULL);
}
}
extern __inline int (__cdecl _isblank_l) (
int c,
_locale_t plocinfo
)
{
_LocaleUpdate _loc_update(plocinfo);
return _isblank_l(c, _loc_update.GetLocaleT());
}
extern __inline int (__cdecl isblank) (
int c
)
{
if (__locale_changed == 0)
{
return (c == '\t') ? _BLANK : __fast_ch_check(c, _BLANK);
}
else
{
return (_isblank_l)(c, NULL);
}
}
extern __inline int (__cdecl _isalnum_l) (
int c,
_locale_t plocinfo
)
{
_LocaleUpdate _loc_update(plocinfo);
return _isalnum_l(c, _loc_update.GetLocaleT());
}
extern __inline int (__cdecl isalnum) (
int c
)
{
if (__locale_changed == 0)
{
return __fast_ch_check(c, _ALPHA|_DIGIT);
}
else
{
return (_isalnum_l)(c, NULL);
}
}
extern __inline int (__cdecl _isprint_l) (
int c,
_locale_t plocinfo
)
{
_LocaleUpdate _loc_update(plocinfo);
return _isprint_l(c, _loc_update.GetLocaleT());
}
extern __inline int (__cdecl isprint) (
int c
)
{
if (__locale_changed == 0)
{
return __fast_ch_check(c, _BLANK|_PUNCT|_ALPHA|_DIGIT);
}
else
{
return (_isprint_l)(c, NULL);
}
}
extern __inline int (__cdecl _isgraph_l) (
int c,
_locale_t plocinfo
)
{
_LocaleUpdate _loc_update(plocinfo);
return _isgraph_l(c, _loc_update.GetLocaleT());
}
extern __inline int (__cdecl isgraph) (
int c
)
{
if (__locale_changed == 0)
{
return __fast_ch_check(c, _PUNCT|_ALPHA|_DIGIT);
}
else
{
return (_isgraph_l)(c, NULL);
}
}
extern __inline int (__cdecl _iscntrl_l) (
int c,
_locale_t plocinfo
)
{
_LocaleUpdate _loc_update(plocinfo);
return _iscntrl_l(c, _loc_update.GetLocaleT());
}
extern __inline int (__cdecl iscntrl) (
int c
)
{
if (__locale_changed == 0)
{
return __fast_ch_check(c, _CONTROL);
}
else
{
return (_iscntrl_l)(c, NULL);
}
}
extern __inline int (__cdecl __isascii) (
int c
)
{
return __isascii(c);
}
extern __inline int (__cdecl __toascii) (
int c
)
{
return __toascii(c);
}
extern __inline int (__cdecl _iscsymf_l) (
int c,
_locale_t plocinfo
)
{
return (_isalpha_l)(c, plocinfo) || (c) == '_';
}
extern __inline int (__cdecl __iscsymf) (
int c
)
{
return __iscsymf(c);
}
extern __inline int (__cdecl _iscsym_l) (
int c,
_locale_t plocinfo
)
{
return (_isalnum_l)(c, plocinfo) || (c) == '_';
}
extern __inline int (__cdecl __iscsym) (
int c
)
{
return __iscsym((unsigned char)(c));
}
}

View File

@ -0,0 +1,211 @@
/***
*_filbuf.c - fill buffer and get character
*
* Copyright (c) Microsoft Corporation. All rights reserved.
*
*Purpose:
* defines _filbuf() - fill buffer and read first character, allocate
* buffer if there is none. Used from getc().
* defines _filwbuf() - fill buffer and read first wide character, allocate
* buffer if there is none. Used from getwc().
*
*Note:
* this file is included in safecrt.lib build directly, plese refer
* to safecrt_filwbuf.c
*
*******************************************************************************/
#include <cruntime.h>
#include <stdio.h>
#include <file2.h>
#include <io.h>
#include <dbgint.h>
#include <malloc.h>
#include <internal.h>
#include <msdos.h>
#include <wchar.h>
#include <mtdll.h>
#include <tchar.h>
#ifndef _UNICODE
/***
*int _filbuf(stream) - fill buffer and get first character
*
*Purpose:
* get a buffer if the file doesn't have one, read into it, return first
* char. try to get a buffer, if a user buffer is not assigned. called
* only from getc; intended for use only within library. assume no input
* stream is to remain unbuffered when memory is available unless it is
* marked _IONBF. at worst, give it a single char buffer. the need for a
* buffer, no matter how small, becomes evident when we consider the
* ungetc's necessary in scanf
*
* [NOTE: Multi-thread - _filbuf() assumes that the caller has aquired
* the stream lock, if needed.]
*
*Entry:
* FILE *stream - stream to read from
*
*Exit:
* returns first character from buffer (next character to be read)
* returns EOF if the FILE is actually a string, or not open for reading,
* or if open for writing or if no more chars to read.
* all fields in FILE structure may be changed except _file.
*
*Exceptions:
*
*******************************************************************************/
int __cdecl _filbuf (
FILE *str
)
#else /* _UNICODE */
/***
*int _filwbuf(stream) - fill buffer and get first wide character
*
*Purpose:
* get a buffer if the file doesn't have one, read into it, return first
* char. try to get a buffer, if a user buffer is not assigned. called
* only from getc; intended for use only within library. assume no input
* stream is to remain unbuffered when memory is available unless it is
* marked _IONBF. at worst, give it a single char buffer. the need for a
* buffer, no matter how small, becomes evident when we consider the
* ungetc's necessary in scanf
*
* [NOTE: Multi-thread - _filwbuf() assumes that the caller has aquired
* the stream lock, if needed.]
*
*Entry:
* FILE *stream - stream to read from
*
*Exit:
* returns first wide character from buffer (next character to be read)
* returns WEOF if the FILE is actually a string, or not open for reading,
* or if open for writing or if no more chars to read.
* all fields in FILE structure may be changed except _file.
*
*Exceptions:
*
*******************************************************************************/
int __cdecl _filwbuf (
FILE *str
)
#endif /* _UNICODE */
{
FILE *stream=NULL;
#ifdef _UNICODE
int is_split_character = 0;
unsigned char leftover_low_order_byte = 0;
#endif /* _UNICODE */
/* In safecrt, we assume we always have a buffer */
_VALIDATE_RETURN(str != NULL, EINVAL, _TEOF);
/* Init pointer to _iob2 entry. */
stream = str;
if (!inuse(stream) || stream->_flag & _IOSTRG)
return(_TEOF);
if (stream->_flag & _IOWRT)
{
stream->_flag |= _IOERR;
return(_TEOF);
}
stream->_flag |= _IOREAD;
/* Get a buffer, if necessary. */
if (!anybuf(stream))
{
#ifndef _SAFECRT_IMPL
_getbuf(stream);
#else /* _SAFECRT_IMPL */
/* In safecrt, we assume we always have a buffer */
_VALIDATE_RETURN(FALSE, EINVAL, _TEOF);
#endif /* _SAFECRT_IMPL */
}
else
{
#ifdef _UNICODE
/* When reading wchar_t elements, we must handle the case where a
two-byte character straddles the buffer boundary, with the low
order byte at the end of the old buffer and the high order byte
at the start of the new buffer.
We do this here: if there is exactly one character left in the
buffer, we store that and set the is_split_character flag. After
we load the new buffer, we'll or this low order byte into the
result. */
if (stream->_cnt == 1)
{
is_split_character = 1;
leftover_low_order_byte = (unsigned char)*stream->_ptr;
}
#endif /* _UNICODE */
stream->_ptr = stream->_base;
}
stream->_cnt = _read(_fileno(stream), stream->_base, stream->_bufsiz);
#ifndef _UNICODE
if ((stream->_cnt == 0) || (stream->_cnt == -1)) {
#else /* _UNICODE */
if ((stream->_cnt == 0) || (stream->_cnt == 1) || stream->_cnt == -1) {
#endif /* _UNICODE */
stream->_flag |= stream->_cnt ? _IOERR : _IOEOF;
stream->_cnt = 0;
return(_TEOF);
}
if ( !(stream->_flag & (_IOWRT|_IORW)) &&
((_osfile_safe(_fileno(stream)) & (FTEXT|FEOFLAG)) ==
(FTEXT|FEOFLAG)) )
{
stream->_flag |= _IOCTRLZ;
}
/* Check for small _bufsiz (_SMALL_BUFSIZ). If it is small and
if it is our buffer, then this must be the first _filbuf after
an fseek on a read-access-only stream. Restore _bufsiz to its
larger value (_INTERNAL_BUFSIZ) so that the next _filbuf call,
if one is made, will fill the whole buffer. */
if ( (stream->_bufsiz == _SMALL_BUFSIZ) && (stream->_flag &
_IOMYBUF) && !(stream->_flag & _IOSETVBUF) )
{
stream->_bufsiz = _INTERNAL_BUFSIZ;
}
#ifndef _UNICODE
stream->_cnt--;
return(0xff & *stream->_ptr++);
#else /* _UNICODE */
if (is_split_character)
{
/* If the character was split across buffers, we read only one byte
from the new buffer and or it with the leftover byte from the old
buffer. */
unsigned char high_order_byte = (unsigned char)(*stream->_ptr);
wchar_t result = (high_order_byte << 8) | leftover_low_order_byte;
--stream->_cnt;
++stream->_ptr;
return (result);
}
else
{
stream->_cnt -= sizeof(wchar_t);
return (0xffff & *((wchar_t *)(stream->_ptr))++);
}
#endif /* _UNICODE */
}

View File

@ -0,0 +1,352 @@
/***
*_file.c - Definition of _iob[], initializer and terminator.
*
* Copyright (c) Microsoft Corporation. All rights reserved.
*
*Purpose:
* Defines _iob[], the array of stdio control structures, the initializer
* and terminator routines, and the multithread locking for stdio.
*
*******************************************************************************/
#include <sect_attribs.h>
#include <cruntime.h>
#include <windows.h>
#include <stdio.h>
#include <file2.h>
#include <internal.h>
#include <malloc.h>
#include <rterr.h>
#include <dbgint.h>
#include <mtdll.h>
/*
* Buffer for stdin.
*/
char _bufin[_INTERNAL_BUFSIZ];
/*
* FILE descriptors; preset for stdin/out/err (note that the __tmpnum field
* is not initialized)
*/
FILE _iob[_IOB_ENTRIES] = {
/* _ptr, _cnt, _base, _flag, _file, _charbuf, _bufsiz */
/* stdin (_iob[0]) */
{ _bufin, 0, _bufin, _IOREAD | _IOYOURBUF, 0, 0, _INTERNAL_BUFSIZ },
/* stdout (_iob[1]) */
{ NULL, 0, NULL, _IOWRT, 1, 0, 0 },
/* stderr (_iob[3]) */
{ NULL, 0, NULL, _IOWRT, 2, 0, 0 },
};
/* These functions are for enabling STATIC_CPPLIB functionality */
_CRTIMP FILE * __cdecl __iob_func(void)
{
return _iob;
}
/*
* Pointer to array of FILE * or _FILEX * structures.
*/
void ** __piob;
/*
* Number of open streams (set to _NSTREAM by default)
*/
#ifdef CRTDLL
int _nstream = _NSTREAM_;
#else /* CRTDLL */
int _nstream;
#endif /* CRTDLL */
/*
* Initializer and terminator for stdio
*/
int __cdecl __initstdio(void);
void __cdecl __endstdio(void);
_CRTALLOC(".CRT$XIC") static _PIFV pinit = __initstdio;
_CRTALLOC(".CRT$XPXA") static _PVFV pterm = __endstdio;
#ifndef CRTDLL
/*
* _cflush is a dummy variable used to pull in _endstdio() when any STDIO
* routine is included in the user program.
*/
int _cflush = 0;
#endif /* CRTDLL */
/***
* __initstdio - Initialize the stdio system
*
*Purpose:
* Create and initialize the __piob array.
*
*Entry: <void>
*
*Exit: Returns _RT_STDIOINIT if error encountered.
*
*Uses:
*
*Exceptions:
*
*******************************************************************************/
int __cdecl __initstdio(void)
{
int i;
#ifndef CRTDLL
/*
* If the user has not supplied a definition of _nstream, set it
* to _NSTREAM_. If the user has supplied a value that is too small
* set _nstream to the minimum acceptable value (_IOB_ENTRIES).
*/
if ( _nstream == 0 )
_nstream = _NSTREAM_;
else if ( _nstream < _IOB_ENTRIES )
_nstream = _IOB_ENTRIES;
#endif /* CRTDLL */
/*
* Allocate the __piob array. Try for _nstream entries first. If this
* fails then reset _nstream to _IOB_ENTRIES and try again. If it
* still fails, bail out with an RTE.
*/
if ( (__piob = (void **)_calloc_crt( _nstream, sizeof(void *) )) ==
NULL ) {
_nstream = _IOB_ENTRIES;
if ( (__piob = (void **)_calloc_crt( _nstream, sizeof(void *) ))
== NULL )
return _RT_STDIOINIT;
}
/*
* Initialize the first _IOB_ENTRIES to point to the corresponding
* entries in _iob[].
*/
for ( i = 0 ; i < _IOB_ENTRIES ; i++ )
__piob[i] = (void *)&_iob[i];
return 0;
}
/***
* __endstdio - Terminate the stdio system
*
*Purpose:
* Terminate the stdio system
*
* (1) Flush all streams. (Do this even if we're going to
* call fcloseall since that routine won't do anything to the
* std streams.)
*
* (2) If returning to caller, close all streams. This is
* not necessary if the exe is terminating because the OS will
* close the files for us (much more efficiently, too).
*
*Entry: <void>
*
*Exit: <void>
*
*Uses:
*
*Exceptions:
*
*******************************************************************************/
void __cdecl __endstdio(void)
{
/* flush all streams */
_flushall();
/* if in callable exit, close all streams */
if (_exitflag)
_fcloseall();
_free_crt(__piob);
__piob = NULL;
}
/***
* _lock_file - Lock a FILE
*
*Purpose:
* Assert the lock for a stdio-level file
*
*Entry:
* pf = __piob[] entry (pointer to a FILE or _FILEX)
*
*Exit:
*
*Exceptions:
*
*******************************************************************************/
void __cdecl _lock_file (
FILE *pf
)
{
/*
* The way the FILE (pointed to by pf) is locked depends on whether
* it is part of _iob[] or not
*/
if ( (pf >= _iob) && (pf <= (&_iob[_IOB_ENTRIES-1])) )
{
/*
* FILE lies in _iob[] so the lock lies in _locktable[].
*/
_lock( _STREAM_LOCKS + (int)(pf - _iob) );
/* We set _IOLOCKED to indicate we locked the stream */
pf->_flag |= _IOLOCKED;
}
else
/*
* Not part of _iob[]. Therefore, *pf is a _FILEX and the
* lock field of the struct is an initialized critical
* section.
*/
EnterCriticalSection( &(((_FILEX *)pf)->lock) );
}
/***
* _lock_file2(i, s) - Lock the FILE
*
*Purpose:
* Assert the lock for a stdio-level file given by s == __piob[i].
*
*Entry:
* s == __piob[i]
*
*Exit:
*
*Exceptions:
*
*******************************************************************************/
void __cdecl _lock_file2 (
int i,
void *s
)
{
/*
* The way the FILE is locked depends on whether it is part of _iob[]
* _iob[] or not
*/
if ( i < _IOB_ENTRIES )
{
/*
* FILE lies in _iob[] so the lock lies in _locktable[].
*/
_lock( _STREAM_LOCKS + i );
/* We set _IOLOCKED to indicate we locked the stream */
((FILE*)s)->_flag |= _IOLOCKED;
}
else
/*
* Not part of _iob[]. Therefore, *s is a _FILEX and the
* lock field of the struct is an initialized critical
* section.
*/
EnterCriticalSection( &(((_FILEX *)s)->lock) );
}
/***
* _unlock_file - Unlock a FILE
*
*Purpose:
* Release the lock for a stdio-level file
*
*Entry:
* pf = __piob[] entry (pointer to a FILE or _FILEX)
*
*Exit:
*
*Exceptions:
*
*******************************************************************************/
void __cdecl _unlock_file (
FILE *pf
)
{
/*
* The way the FILE (pointed to by pf) is unlocked depends on whether
* it is part of _iob[] or not
*/
if ( (pf >= _iob) && (pf <= (&_iob[_IOB_ENTRIES-1])) )
{
/*
* FILE lies in _iob[] so the lock lies in _locktable[].
* We reset _IOLOCKED to indicate we unlock the stream.
*/
pf->_flag &= ~_IOLOCKED;
_unlock( _STREAM_LOCKS + (int)(pf - _iob) );
}
else
/*
* Not part of _iob[]. Therefore, *pf is a _FILEX and the
* lock field of the struct is an initialized critical
* section.
*/
LeaveCriticalSection( &(((_FILEX *)pf)->lock) );
}
/***
* _unlock_file2(i, s) - Lock the FILE
*
*Purpose:
* Release the lock for a stdio-level file given by s == __piob[i].
*
*Entry:
* s == __piob[i]
*
*Exit:
*
*Exceptions:
*
*******************************************************************************/
void __cdecl _unlock_file2 (
int i,
void *s
)
{
/*
* The way the FILE is locked depends on whether it is part of _iob[]
* _iob[] or not
*/
if ( i < _IOB_ENTRIES )
{
/*
* FILE lies in _iob[] so the lock lies in _locktable[].
* We reset _IOLOCKED to indicate we unlock the stream.
*/
((FILE*)s)->_flag &= ~_IOLOCKED;
_unlock( _STREAM_LOCKS + i );
}
else
/*
* Not part of _iob[]. Therefore, *s is a _FILEX and the
* lock field of the struct is an initialized critical
* section.
*/
LeaveCriticalSection( &(((_FILEX *)s)->lock) );
}

View File

@ -0,0 +1,23 @@
/***
*_filwbuf.c - fill buffer and get wide character
*
* Copyright (c) Microsoft Corporation. All rights reserved.
*
*Purpose:
* defines _filwbuf() - fill buffer and read first character, allocate
* buffer if there is none. Used from getwc().
*
*******************************************************************************/
#ifndef _UNICODE
#define _UNICODE 1
#endif /* _UNICODE */
#ifndef UNICODE
#define UNICODE 1
#endif /* UNICODE */
#include "_filbuf.c"

View File

@ -0,0 +1,211 @@
/***
*_flsbuf.c - flush buffer and output character.
*
* Copyright (c) Microsoft Corporation. All rights reserved.
*
*Purpose:
* defines _flsbuf() - flush a file buffer and output a character.
* defines _flswbuf() - flush a file buffer and output a wide character.
* If no buffer, make one.
*
*******************************************************************************/
#include <cruntime.h>
#include <stdio.h>
#include <file2.h>
#include <io.h>
#include <dbgint.h>
#include <malloc.h>
#include <msdos.h>
#include <wchar.h>
#include <internal.h>
#include <mtdll.h>
#include <tchar.h>
#ifndef _UNICODE
/***
*int _flsbuf(ch, stream) - flush buffer and output character.
*
*Purpose:
* flush a buffer if this stream has one. if not, try to get one. put the
* next output char (ch) into the buffer (or output it immediately if this
* stream can't have a buffer). called only from putc. intended for use
* only within library.
*
* [NOTE: Multi-thread - It is assumed that the caller has aquired
* the stream lock.]
*
*Entry:
* FILE *stream - stream to flish and write on
* int ch - character to output.
*
*Exit:
* returns -1 if FILE is actually a string, or if can't write ch to
* unbuffered file, or if we flush a buffer but the number of chars
* written doesn't agree with buffer size. Otherwise returns ch.
* all fields in FILE struct can be affected except _file.
*
*Exceptions:
*
*******************************************************************************/
int __cdecl _flsbuf (
int ch,
FILE *str
)
#else /* _UNICODE */
/***
*int _flswbuf(ch, stream) - flush buffer and output wide character.
*
*Purpose:
* flush a buffer if this stream has one. if not, try to get one. put the
* next output wide char (ch) into the buffer (or output it immediately if this
* stream can't have a buffer). called only from putwc. intended for use
* only within library.
*
* [NOTE: Multi-thread - It is assumed that the caller has aquired
* the stream lock.]
*
*Entry:
* FILE *stream - stream to flish and write on
* int ch - wide character to output.
*
*Exit:
* returns -1 if FILE is actually a string, or if can't write ch to
* unbuffered file, or if we flush a buffer but the number of wide chars
* written doesn't agree with buffer size. Otherwise returns ch.
* all fields in FILE struct can be affected except _file.
*
*Exceptions:
*
*******************************************************************************/
int __cdecl _flswbuf (
int ch,
FILE *str
)
#endif /* _UNICODE */
{
FILE *stream;
int charcount;
int written;
int fh;
_ASSERTE(str != NULL);
stream = str;
fh = _fileno(stream);
if (!(stream->_flag & (_IOWRT|_IORW))) {
errno = EBADF;
stream->_flag |= _IOERR;
return(_TEOF);
} else if ((stream->_flag & _IOSTRG)) {
errno = ERANGE;
stream->_flag |= _IOERR;
return(_TEOF);
}
/* Check that _IOREAD is not set or, if it is, then so is _IOEOF. Note
that _IOREAD and IOEOF both being set implies switching from read to
write at end-of-file, which is allowed by ANSI. Note that resetting
the _cnt and _ptr fields amounts to doing an fflush() on the stream
in this case. Note also that the _cnt field has to be reset to 0 for
the error path as well (i.e., _IOREAD set but _IOEOF not set) as
well as the non-error path. */
if (stream->_flag & _IOREAD) {
stream->_cnt = 0;
if (stream->_flag & _IOEOF) {
stream->_ptr = stream->_base;
stream->_flag &= ~_IOREAD;
}
else {
stream->_flag |= _IOERR;
return(_TEOF);
}
}
stream->_flag |= _IOWRT;
stream->_flag &= ~_IOEOF;
written = charcount = stream->_cnt = 0;
/* Get a buffer for this stream, if necessary. */
if (!anybuf(stream)) {
/* Do NOT get a buffer if (1) stream is stdout/stderr, and
(2) stream is NOT a tty.
[If stdout/stderr is a tty, we do NOT set up single char
buffering. This is so that later temporary buffering will
not be thwarted by the _IONBF bit being set (see
_stbuf/_ftbuf usage).]
*/
if (!( ((stream==stdout) || (stream==stderr))
&& (_isatty(fh)) ))
_getbuf(stream);
} /* end !anybuf() */
/* If big buffer is assigned to stream... */
if (bigbuf(stream)) {
_ASSERTE(("inconsistent IOB fields", stream->_ptr - stream->_base >= 0));
charcount = (int)(stream->_ptr - stream->_base);
stream->_ptr = stream->_base + sizeof(TCHAR);
stream->_cnt = stream->_bufsiz - (int)sizeof(TCHAR);
if (charcount > 0)
written = _write(fh, stream->_base, charcount);
else
if (_osfile_safe(fh) & FAPPEND)
{
if( _lseeki64(fh,0L,SEEK_END)==-1)
{
stream->_flag |= _IOERR;
return(_TEOF);
}
}
#ifndef _UNICODE
*stream->_base = (char)ch;
#else /* _UNICODE */
*(wchar_t *)(stream->_base) = (wchar_t)(ch & 0xffff);
#endif /* _UNICODE */
}
/* Perform single character output (either _IONBF or no buffering) */
else {
charcount = sizeof(TCHAR);
#ifndef _UNICODE
written = _write(fh, &ch, charcount);
#else /* _UNICODE */
{
char mbc[4];
*(wchar_t *)mbc = (wchar_t)(ch & 0xffff);
written = _write(fh, mbc, charcount);
}
#endif /* _UNICODE */
}
/* See if the _write() was successful. */
if (written != charcount) {
stream->_flag |= _IOERR;
return(_TEOF);
}
#ifndef _UNICODE
return(ch & 0xff);
#else /* _UNICODE */
return(ch & 0xffff);
#endif /* _UNICODE */
}

View File

@ -0,0 +1,23 @@
/***
*_flswbuf.c - flush buffer and output wide character.
*
* Copyright (c) Microsoft Corporation. All rights reserved.
*
*Purpose:
* defines _flswbuf() - flush a file buffer and output a wide character.
* If no buffer, make one.
*
*******************************************************************************/
#ifndef _UNICODE
#define _UNICODE 1
#endif /* _UNICODE */
#ifndef UNICODE
#define UNICODE 1
#endif /* UNICODE */
#include "_flsbuf.c"

View File

@ -0,0 +1,109 @@
/***
*_fptostr.c - workhorse routine for converting floating point to string
*
* Copyright (c) Microsoft Corporation. All rights reserved.
*
*Purpose:
* Workhorse routine for fcvt, ecvt.
*
*******************************************************************************/
#include <cruntime.h>
#include <string.h>
#include <stddef.h>
#include <fltintrn.h>
#include <internal.h>
/***
*errno_t _fptostr(buf, size, digits, pflt) - workhorse floating point conversion
*
*Purpose:
* This is the workhorse routine for fcvt, ecvt. Here is where
* all the digits are put into a buffer and the rounding is
* performed and indicators of the decimal point position are set. Note,
* this must not change the mantissa field of pflt since routines which
* use this routine rely on this being unchanged.
*
*Entry:
* char *buf - the buffer in which the digits are to be put
* int digits - the number of digits which are to go into the buffer
* STRFLT pflt - a pointer to a structure containing information on the
* floating point value, including a string containing the
* non-zero significant digits of the mantissa.
*
*Exit:
* Changes the contents of the buffer and also may increment the decpt
* field of the structure pointer to by the 'pflt' parameter if overflow
* occurs during rounding (e.g. 9.999999... gets rounded to 10.000...).
*
*Exceptions:
* Input parameters are validated. Refer to the validation section of the function.
*
*******************************************************************************/
errno_t __cdecl _fptostr (
char *buf,
size_t sizeInBytes,
int digits,
STRFLT pflt
)
{
char *pbuf = buf;
char *mantissa = pflt->mantissa;
/* validation section */
_VALIDATE_RETURN_ERRCODE(buf != NULL, EINVAL);
_VALIDATE_RETURN_ERRCODE(sizeInBytes > 0, EINVAL);
buf[0] = '\0';
/* the buffer will contains ndec decimal digits plus an optional
* overflow digit for the rounding
*/
_VALIDATE_RETURN_ERRCODE(sizeInBytes > (size_t)((digits > 0 ? digits : 0) + 1), ERANGE);
_VALIDATE_RETURN_ERRCODE(pflt != NULL, EINVAL);
/* initialize the first digit in the buffer to '0' (NOTE - NOT '\0')
* and set the pointer to the second digit of the buffer. The first
* digit is used to handle overflow on rounding (e.g. 9.9999...
* becomes 10.000...) which requires a carry into the first digit.
*/
*pbuf++ = '0';
/* Copy the digits of the value into the buffer (with 0 padding)
* and insert the terminating null character.
*/
while (digits > 0) {
*pbuf++ = (*mantissa) ? *mantissa++ : (char)'0';
digits--;
}
*pbuf = '\0';
/* do any rounding which may be needed. Note - if digits < 0 don't
* do any rounding since in this case, the rounding occurs in a digit
* which will not be output beause of the precision requested
*/
if (digits >= 0 && *mantissa >= '5') {
pbuf--;
while (*pbuf == '9')
*pbuf-- = '0';
*pbuf += 1;
}
if (*buf == '1') {
/* the rounding caused overflow into the leading digit (e.g.
* 9.999.. went to 10.000...), so increment the decpt position
* by 1
*/
pflt->decpt++;
}
else {
/* move the entire string to the left one digit to remove the
* unused overflow digit.
*/
memmove(buf, buf+1, strlen(buf+1)+1);
}
return 0;
}

View File

@ -0,0 +1,56 @@
/***
*_freebuf.c - release a buffer from a stream
*
* Copyright (c) Microsoft Corporation. All rights reserved.
*
*Purpose:
* defines _freebuf() - release a buffer from a stream
*
*******************************************************************************/
#include <cruntime.h>
#include <stdio.h>
#include <file2.h>
#include <dbgint.h>
#include <internal.h>
#include <stdlib.h>
/***
*void _freebuf(stream) - release a buffer from a stream
*
*Purpose:
* free a buffer if at all possible. free() the space if malloc'd by me.
* forget about trying to free a user's buffer for him; it may be static
* memory (not from malloc), so he has to take care of it. this function
* is not intended for use outside the library.
*
* Multi-thread notes:
* _freebuf() does NOT get the stream lock; it is assumed that the
* caller has already done this.
*
*Entry:
* FILE *stream - stream to free bufer on
*
*Exit:
* Buffer may be freed.
* No return value.
*
*Exceptions:
*
*******************************************************************************/
void __cdecl _freebuf (
FILE *stream
)
{
_ASSERTE(stream != NULL);
if (inuse(stream) && mbuf(stream))
{
_free_crt(stream->_base);
stream->_flag &= ~(_IOMYBUF | _IOSETVBUF);
stream->_base = stream->_ptr = NULL;
stream->_cnt = 0;
}
}

View File

@ -0,0 +1,79 @@
/***
*_getbuf.c - Get a stream buffer
*
* Copyright (c) Microsoft Corporation. All rights reserved.
*
*Purpose:
* Allocate a buffer and init stream data bases.
*
*******************************************************************************/
#include <cruntime.h>
#include <stdio.h>
#include <file2.h>
#include <malloc.h>
#include <internal.h>
#include <dbgint.h>
/***
*_getbuf() - Allocate a buffer and init stream data bases
*
*Purpose:
* Allocates a buffer for a stream and inits the stream data bases.
*
* [NOTE 1: This routine assumes the caller has already checked to make
* sure the stream needs a buffer.
*
* [NOTE 2: Multi-thread - Assumes caller has aquired stream lock, if
* needed.]
*
*Entry:
* FILE *stream = stream to allocate a buffer for
*
*Exit:
* void
*
*Exceptions:
*
*******************************************************************************/
void __cdecl _getbuf (
FILE *str
)
{
FILE *stream;
_ASSERTE(str != NULL);
#if !defined (CRTDLL)
/* force library pre-termination procedure */
_cflush++;
#endif /* !defined (CRTDLL) */
/* Init pointers */
stream = str;
/* Try to get a big buffer */
if (stream->_base = _malloc_crt(_INTERNAL_BUFSIZ))
{
/* Got a big buffer */
stream->_flag |= _IOMYBUF;
stream->_bufsiz = _INTERNAL_BUFSIZ;
}
else {
/* Did NOT get a buffer - use single char buffering. */
stream->_flag |= _IONBF;
stream->_base = (char *)&(stream->_charbuf);
stream->_bufsiz = 2;
}
stream->_ptr = stream->_base;
stream->_cnt = 0;
return;
}

View File

@ -0,0 +1,95 @@
/***
*_mbslen.c - Return number of multibyte characters in a multibyte string
*
* Copyright (c) Microsoft Corporation. All rights reserved.
*
*Purpose:
* Return number of multibyte characters in a multibyte string
* excluding the terminal null. Locale-dependent.
*
*******************************************************************************/
#include <cruntime.h>
#include <stdlib.h>
#include <locale.h>
#include <dbgint.h>
#include <ctype.h>
#include <mbctype.h>
#include <internal.h>
#include <mtdll.h>
#include <setlocal.h>
/***
*_mbstrlen - Return number of multibyte characters in a multibyte string
*
*Purpose:
* Return number of multibyte characters in a multibyte string
* excluding the terminal null. Locale-dependent.
*
*Entry:
* char *s = string
*
*Exit:
* Returns the number of multibyte characters in the string, or
* Returns (size_t)-1 if the string contains an invalid multibyte character.
* Also, errno is set to EILSEQ.
*
*Exceptions:
* Input parameters are validated. Refer to the validation section of the function.
*
*******************************************************************************/
size_t __cdecl _mbstrlen_l(
const char *s,
_locale_t plocinfo
)
{
size_t n;
_LocaleUpdate _loc_update(plocinfo);
_ASSERTE (_loc_update.GetLocaleT()->locinfo->mb_cur_max == 1 || _loc_update.GetLocaleT()->locinfo->mb_cur_max == 2);
if ( _loc_update.GetLocaleT()->locinfo->mb_cur_max == 1 )
/* handle single byte character sets */
return strlen(s);
/* verify all valid MB chars */
if ( MultiByteToWideChar( _loc_update.GetLocaleT()->locinfo->lc_codepage,
MB_PRECOMPOSED | MB_ERR_INVALID_CHARS,
s,
-1,
NULL,
0 ) == 0 )
{
/* bad MB char */
errno = EILSEQ;
return (size_t)-1;
}
/* count MB chars */
for (n = 0; *s; n++, s++) {
if ( _isleadbyte_l((unsigned char)*s, _loc_update.GetLocaleT()) )
{
if (*++s == '\0')
break;
}
}
return(n);
}
size_t __cdecl _mbstrlen(
const char *s
)
{
if (__locale_changed == 0)
{
return strlen(s);
}
else
{
return _mbstrlen_l(s, NULL);
}
}

View File

@ -0,0 +1,111 @@
/***
*_mbslen_s.c - Return number of multibyte characters in a multibyte string
*
* Copyright (c) Microsoft Corporation. All rights reserved.
*
*Purpose:
* Return number of multibyte characters in a multibyte string
* excluding the terminal null. Locale-dependent.
*
*******************************************************************************/
#include <cruntime.h>
#include <stdlib.h>
#include <ctype.h>
#include <locale.h>
#include <dbgint.h>
#include <internal.h>
#include <mtdll.h>
#include <setlocal.h>
/***
*_mbstrnlen - Return number of multibyte characters in a multibyte string
*
*Purpose:
* Return number of multibyte characters in a multibyte string
* excluding the terminal null. Locale-dependent.
*
*Entry:
* char *s = string
* size_t maxsize
*
*Exit:
* Returns the number of multibyte characters in the string, or
* (size_t)-1 if the string contains an invalid multibyte character and errno
* is set to EILSEQ.
* Only the first sizeInBytes bytes of the string are inspected: if the null
* terminator is not found, sizeInBytes is returned.
* If the string is null terminated in sizeInBytes bytes, the return value
* will always be less than sizeInBytes.
* If something goes wrong, (size_t)-1 is returned and errno is set to EINVAL.
*
*Exceptions:
* Input parameters are validated. Refer to the validation section of the function.
*
*******************************************************************************/
size_t __cdecl _mbstrnlen_l(
const char *s,
size_t sizeInBytes,
_locale_t plocinfo
)
{
size_t n, size;
/* validation section */
_VALIDATE_RETURN(s != NULL, EINVAL, (size_t)-1);
_VALIDATE_RETURN(sizeInBytes <= INT_MAX, EINVAL, (size_t)-1);
_LocaleUpdate _loc_update(plocinfo);
_ASSERTE (_loc_update.GetLocaleT()->locinfo->mb_cur_max == 1 || _loc_update.GetLocaleT()->locinfo->mb_cur_max == 2);
if ( _loc_update.GetLocaleT()->locinfo->mb_cur_max == 1 )
/* handle single byte character sets */
return (int)strnlen(s, sizeInBytes);
/* verify all valid MB chars */
if ( MultiByteToWideChar( _loc_update.GetLocaleT()->locinfo->lc_codepage,
MB_PRECOMPOSED | MB_ERR_INVALID_CHARS,
s,
(int)sizeInBytes,
NULL,
0 ) == 0 )
{
/* bad MB char */
errno = EILSEQ;
return (size_t)-1;
}
/* count MB chars */
/* Note that sizeInBytes here is the number of bytes, not mb characters! */
for (n = 0, size = 0; size < sizeInBytes && *s; n++, s++, size++)
{
if ( _isleadbyte_l((unsigned char)*s, _loc_update.GetLocaleT()) )
{
size++;
if (size >= sizeInBytes)
{
break;
}
if (*++s == '\0')
{
break;
}
}
}
return (size >= sizeInBytes ? sizeInBytes : n);
}
size_t __cdecl _mbstrnlen(
const char *s,
size_t maxsize
)
{
return _mbstrnlen_l(s, maxsize, NULL);
}

View File

@ -0,0 +1,31 @@
/***
*_newmode.c - set new() handler mode to not handle malloc failures
*
* Copyright (c) Microsoft Corporation. All rights reserved.
*
*Purpose:
* Sets the global flag which controls whether the new() handler
* is called on malloc failures. The default behavior in Visual
* C++ v2.0 and later is not to, that malloc failures return NULL
* without calling the new handler. This object is linked in unless
* the special object NEWMODE.OBJ is manually linked.
*
* This source file is the complement of LINKOPTS/NEWMODE.C.
*
*******************************************************************************/
#ifdef CRTDLL
#undef CRTDLL
#endif /* CRTDLL */
#ifdef MRTDLL
#undef MRTDLL
#endif /* MRTDLL */
#include <internal.h>
/* enable new handler calls upon malloc failures */
int _newmode = 0; /* Malloc New Handler MODE */

View File

@ -0,0 +1,289 @@
/***
*_open.c - open a stream, with string mode
*
* Copyright (c) Microsoft Corporation. All rights reserved.
*
*Purpose:
* defines _openfile() - opens a stream, with string arguments for mode
*
*******************************************************************************/
#include <cruntime.h>
#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <file2.h>
#include <share.h>
#include <io.h>
#include <dbgint.h>
#include <internal.h>
#include <tchar.h>
#include <sys\stat.h>
#define CMASK 0644 /* rw-r--r-- */
#define P_CMASK 0666 /* different for Posix */
/***
*FILE *_openfile(filename, mode, shflag, stream) - open a file with string
* mode and file sharing flag.
*
*Purpose:
* parse the string, looking for exactly one of {rwa}, at most one '+',
* at most one of {tb}, at most one of {cn}, at most one of {SR}, at most
* one 'T', and at most one 'D'. pass the result on as an int containing
* flags of what was found. open a file with proper mode if permissions
* allow. buffer not allocated until first i/o call is issued. intended
* for use inside library only
*
*Entry:
* char *filename - file to open
* char *mode - mode to use (see above)
* int shflag - file sharing flag
* FILE *stream - stream to use for file
*
*Exit:
* set stream's fields, and causes system file management by system calls
* returns stream or NULL if fails
*
*Exceptions:
*
*******************************************************************************/
FILE * __cdecl __topenfile (
const _TSCHAR *filename,
const _TSCHAR *mode,
int shflag,
FILE *str
)
{
int modeflag = 0;
int streamflag = _commode;
int commodeset = 0;
int scanset = 0;
int whileflag;
int filedes;
FILE *stream;
BOOL encodingFlag = FALSE;
_ASSERTE(filename != NULL);
_ASSERTE(mode != NULL);
_ASSERTE(str != NULL);
/* Parse the user's specification string as set flags in
(1) modeflag - system call flags word
(2) streamflag - stream handle flags word. */
/* Skip leading spaces */
while (*mode == _T(' '))
{
++mode;
}
/* First mode character must be 'r', 'w', or 'a'. */
switch (*mode) {
case _T('r'):
modeflag = _O_RDONLY;
streamflag |= _IOREAD;
break;
case _T('w'):
modeflag = _O_WRONLY | _O_CREAT | _O_TRUNC;
streamflag |= _IOWRT;
break;
case _T('a'):
modeflag = _O_WRONLY | _O_CREAT | _O_APPEND;
streamflag |= _IOWRT;
break;
default:
_VALIDATE_RETURN(("Invalid file open mode",0), EINVAL, NULL);
}
/* There can be up to three more optional mode characters:
(1) A single '+' character,
(2) One of 't' and 'b' and
(3) One of 'c' and 'n'.
*/
whileflag=1;
while(*++mode && whileflag)
switch(*mode) {
case _T(' '):
/* skip spaces */
break;
case _T('+'):
if (modeflag & _O_RDWR)
whileflag=0;
else {
modeflag |= _O_RDWR;
modeflag &= ~(_O_RDONLY | _O_WRONLY);
streamflag |= _IORW;
streamflag &= ~(_IOREAD | _IOWRT);
}
break;
case _T('b'):
if (modeflag & (_O_TEXT | _O_BINARY))
whileflag=0;
else
modeflag |= _O_BINARY;
break;
case _T('t'):
if (modeflag & (_O_TEXT | _O_BINARY))
whileflag=0;
else
modeflag |= _O_TEXT;
break;
case _T('c'):
if (commodeset)
whileflag=0;
else {
commodeset = 1;
streamflag |= _IOCOMMIT;
}
break;
case _T('n'):
if (commodeset)
whileflag=0;
else {
commodeset = 1;
streamflag &= ~_IOCOMMIT;
}
break;
case _T('S'):
if (scanset)
whileflag=0;
else {
scanset = 1;
modeflag |= _O_SEQUENTIAL;
}
break;
case _T('R'):
if (scanset)
whileflag=0;
else {
scanset = 1;
modeflag |= _O_RANDOM;
}
break;
case _T('T'):
if (modeflag & _O_SHORT_LIVED)
whileflag=0;
else
modeflag |= _O_SHORT_LIVED;
break;
case _T('D'):
if (modeflag & _O_TEMPORARY)
whileflag=0;
else
modeflag |= _O_TEMPORARY;
break;
case _T('N'):
modeflag |= _O_NOINHERIT;
break;
case _T(','):
encodingFlag = TRUE;
whileflag = 0;
break;
default:
_VALIDATE_RETURN(("Invalid file open mode",0), EINVAL, NULL);
}
if (encodingFlag)
{
static const _TSCHAR ccsField[] = _T("ccs");
static const _TSCHAR utf8encoding[] = _T("UTF-8");
static const _TSCHAR utf16encoding[] = _T("UTF-16LE");
static const _TSCHAR unicodeencoding[] = _T("UNICODE");
/* Skip spaces */
while (*mode == _T(' '))
{
++mode;
}
/*
* The length that we want to compare is numbers of elements in
* csField -1 since this number also contains NULL terminator
*/
if (_tcsncmp(ccsField, mode, (_countof(ccsField))-1) != 0)
_VALIDATE_RETURN(("Invalid file open mode",0), EINVAL, NULL);
mode += _countof(ccsField)-1;
/* Skip spaces */
while (*mode == _T(' '))
{
++mode;
}
/* Look for '=' */
if (*mode != _T('='))
{
_VALIDATE_RETURN(("Invalid file open mode",0), EINVAL, NULL);
}
++mode;
/* Skip spaces */
while (*mode == _T(' '))
{
++mode;
}
if (_tcsnicmp(mode, utf8encoding, _countof(utf8encoding) - 1) == 0){
mode += _countof(utf8encoding)-1;
modeflag |= _O_U8TEXT;
}
else if (_tcsnicmp(mode, utf16encoding, _countof(utf16encoding) - 1) == 0) {
mode += _countof(utf16encoding)-1;
modeflag |= _O_U16TEXT;
}
else if (_tcsnicmp(mode, unicodeencoding, _countof(unicodeencoding) - 1) == 0) {
mode += _countof(unicodeencoding)-1;
modeflag |= _O_WTEXT;
}
else
_VALIDATE_RETURN(("Invalid file open mode",0), EINVAL, NULL);
}
/* Skip trailing spaces */
while (*mode == _T(' '))
{
++mode;
}
_VALIDATE_RETURN( (*mode == _T('\0')), EINVAL, NULL);
/* Try to open the file. Note that if neither 't' nor 'b' is
specified, _sopen will use the default. */
if (_tsopen_s(&filedes, filename, modeflag, shflag, _S_IREAD | _S_IWRITE) != 0)
return(NULL);
/* Set up the stream data base. */
#ifndef CRTDLL
_cflush++; /* force library pre-termination procedure */
#endif /* CRTDLL */
/* Init pointers */
stream = str;
stream->_flag = streamflag;
stream->_cnt = 0;
stream->_tmpfname = stream->_base = stream->_ptr = NULL;
stream->_file = filedes;
return(stream);
}

View File

@ -0,0 +1,15 @@
/***
*_setargv.c - Wildcard argv[] expansion
*
* Copyright (c) Microsoft Corporation. All rights reserved.
*
*Purpose:
* _setargv performs wildcard argv[] expansion
*
* NOTE: This stub module scheme is compatible with NT build
* procedure.
*
*******************************************************************************/
#define WILDCARD 1
#include "stdargv.c"

View File

@ -0,0 +1,164 @@
/***
*_sftbuf.c - temporary buffering initialization and flushing
*
* Copyright (c) Microsoft Corporation. All rights reserved.
*
*Purpose:
* temporary buffering initialization and flushing. if stdout/err is
* unbuffered, buffer it temporarily so that string is sent to kernel as
* a batch of chars, not char-at-a-time. if appropriate, make buffering
* permanent.
*
* [NOTE 1: These routines assume that the temporary buffering is only
* used for output. In particular, note that _stbuf() sets _IOWRT.]
*
* [NOTE 2: It is valid for this module to assign a value directly to
* _flag instead of simply twiddling bits since we are initializing the
* buffer data base.]
*
*******************************************************************************/
#include <cruntime.h>
#include <stdio.h>
#include <file2.h>
#include <io.h>
#include <internal.h>
#include <malloc.h>
#include <mtdll.h>
#include <dbgint.h>
/* Buffer pointers for stdout and stderr */
void *_stdbuf[2] = { NULL, NULL};
/***
*int _stbuf(stream) - set temp buffer on stdout, stdprn, stderr
*
*Purpose:
* if stdout/stderr is still unbuffered, buffer it.
* this function works intimately with _ftbuf, and accompanies it in
* bracketing normally unbuffered output. these functions intended for
* library use only.
*
* Multi-thread: It is assumed that the caller has already aquired the
* stream lock.
*
*Entry:
* FILE *stream - stream to temp buffer
*
*Exit:
* returns 1 if buffer initialized, 0 if not
* sets fields in stdout or stderr to indicate buffering
*
*Exceptions:
*
*******************************************************************************/
int __cdecl _stbuf (
FILE *str
)
{
FILE *stream;
int index;
_ASSERTE(str != NULL);
/* Init near stream pointer */
stream = str;
/* do nothing if not a tty device */
if (!_isatty(_fileno(stream)))
return(0);
/* Make sure stream is stdout/stderr and init _stdbuf index */
if (stream == stdout)
index = 0;
else if (stream == stderr)
index = 1;
else
return(0);
#ifndef CRTDLL
/* force library pre-termination procedure */
_cflush++;
#endif /* CRTDLL */
/* Make sure the stream is not already buffered. */
if (anybuf(stream))
return(0);
/* Allocate a buffer for this stream if we haven't done so yet. */
if ( (_stdbuf[index] == NULL) &&
((_stdbuf[index]=_malloc_crt(_INTERNAL_BUFSIZ)) == NULL) ) {
/* Cannot allocate buffer. Use _charbuf this time */
stream->_ptr = stream->_base = (void *)&(stream->_charbuf);
stream->_cnt = stream->_bufsiz = 2;
}
else {
/* Set up the buffer */
stream->_ptr = stream->_base = _stdbuf[index];
stream->_cnt = stream->_bufsiz = _INTERNAL_BUFSIZ;
}
stream->_flag |= (_IOWRT | _IOYOURBUF | _IOFLRTN);
return(1);
}
/***
*void _ftbuf(flag, stream) - take temp buffering off a stream
*
*Purpose:
* If stdout/stderr is being buffered and it is a device, _flush and
* dismantle the buffer. if it's not a device, leave the buffering on.
* This function works intimately with _stbuf, and accompanies it in
* bracketing normally unbuffered output. these functions intended for
* library use only
*
* Multi-thread: It is assumed that the caller has already aquired the
* stream lock.
*
*Entry:
* int flag - a flag to tell whether to dismantle temp buffering on a
* stream
* FILE *stream - the stream
*
*Exit:
* no return value
* sets fields in stdout/stderr
*
*Exceptions:
*
*******************************************************************************/
void __cdecl _ftbuf (
int flag,
FILE *str
)
{
FILE *stream;
_ASSERTE(flag == 0 || flag == 1);
/* Init near stream pointers */
stream = str;
if (flag) {
if (stream->_flag & _IOFLRTN) {
/* Flush the stream and tear down temp buffering. */
_flush(stream);
stream->_flag &= ~(_IOYOURBUF | _IOFLRTN);
stream->_bufsiz = 0;
stream->_base = stream->_ptr = NULL;
}
/* Note: If we expand the functionality of the _IOFLRTN bit to
include other streams, we may want to clear that bit here under
an 'else' clause (i.e., clear bit in the case that we leave the
buffer permanently assigned. Given our current use of the bit,
the extra code is not needed. */
} /* end flag = 1 */
}

View File

@ -0,0 +1,153 @@
/***
*_strerr.c - routine for indexing into system error list
*
* Copyright (c) Microsoft Corporation. All rights reserved.
*
*Purpose:
* Returns system error message index by errno; conforms to the
* XENIX standard, much compatibility with 1983 uniforum draft standard.
*
*******************************************************************************/
#include <cruntime.h>
#include <stdlib.h>
#include <errmsg.h>
#include <syserr.h>
#include <string.h>
#include <tchar.h>
#include <malloc.h>
#include <mtdll.h>
#include <dbgint.h>
#include <internal.h>
/* Max length of message = user_string(94)+system_string+2 */
/* [NOTE: The mthread error message buffer is shared by both strerror
and _strerror so must be the max length of both. */
#define _ERRMSGLEN_ (94+_SYS_MSGMAX+2)
#ifdef _UNICODE
#define _terrmsg _werrmsg
#else /* _UNICODE */
#define _terrmsg _errmsg
#endif /* _UNICODE */
/***
*char *_strerror(message) - get system error message
*
*Purpose:
* builds an error message consisting of the users error message
* (the message parameter), followed by ": ", followed by the system
* error message (index through errno), followed by a newline. If
* message is NULL or a null string, returns a pointer to just
* the system error message.
*
*Entry:
* char *message - user's message to prefix system error message
*
*Exit:
* returns pointer to static memory containing error message.
* returns NULL if malloc() fails in multi-thread versions.
*
*Exceptions:
*
*******************************************************************************/
#ifdef _UNICODE
wchar_t * __cdecl __wcserror(
#else /* _UNICODE */
char * __cdecl _strerror (
#endif /* _UNICODE */
const _TCHAR *message
)
{
const char *sysErrorMsg = NULL;
_TCHAR *bldmsg;
_ptiddata ptd = _getptd_noexit();
if (!ptd)
return NULL;
/* Use per thread buffer area (malloc space, if necessary) */
/* [NOTE: This buffer is shared between _strerror and streror.] */
if ( (ptd->_terrmsg == NULL) && ((ptd->_terrmsg =
_calloc_crt(_ERRMSGLEN_, sizeof(_TCHAR))) == NULL) )
return(NULL);
bldmsg = ptd->_terrmsg;
/* Build the error message */
bldmsg[0] = '\0';
if (message && *message) {
// should leave space for ": \n\0"
_ERRCHECK(_tcsncat_s( bldmsg, _ERRMSGLEN_, message, _ERRMSGLEN_-4 ));
_ERRCHECK(_tcscat_s( bldmsg, _ERRMSGLEN_, _T(": ")));
}
// We should have extra space for "\n\0"
sysErrorMsg = _get_sys_err_msg(errno);
#ifdef _UNICODE
_ERRCHECK(mbstowcs_s(NULL, bldmsg + wcslen(bldmsg), _ERRMSGLEN_ - wcslen(bldmsg), sysErrorMsg, _ERRMSGLEN_ - wcslen(bldmsg) - 2));
#else /* _UNICODE */
_ERRCHECK(strncat_s(bldmsg, _ERRMSGLEN_, sysErrorMsg, _ERRMSGLEN_ - strlen(bldmsg) - 2));
#endif /* _UNICODE */
_ERRCHECK(_tcscat_s( bldmsg, _ERRMSGLEN_, _T("\n")));
return bldmsg;
}
/***
*errno_t _strerror_s(buffer, sizeInTChars, message) - get system error message
*
*Purpose:
* builds an error message consisting of the users error message
* (the message parameter), followed by ": ", followed by the system
* error message (index through errno), followed by a newline. If
* message is NULL or a null string, returns a pointer to just
* the system error message.
*
*Entry:
* TCHAR * buffer - Destination buffer.
* size_t sizeInTChars - Size of the destination buffer.
* TCHAR * message - user's message to prefix system error message
*
*Exit:
* The error code.
*
*Exceptions:
* Input parameters are validated. Refer to the validation section of the function.
*
*******************************************************************************/
#define _MIN_MSG_LENGTH 5
#ifdef _UNICODE
errno_t __cdecl __wcserror_s(
#else /* _UNICODE */
errno_t __cdecl _strerror_s(
#endif /* _UNICODE */
TCHAR* buffer,
size_t sizeInTChars,
const _TCHAR *message
)
{
errno_t e = 0;
/* validation section */
_VALIDATE_RETURN_ERRCODE(buffer != NULL, EINVAL);
_VALIDATE_RETURN_ERRCODE(sizeInTChars > 0, EINVAL);
buffer[0] = '\0';
if (message &&
*message &&
_tcslen(message) < (sizeInTChars - 2 - _MIN_MSG_LENGTH))
{
_ERRCHECK(_tcscpy_s(buffer, sizeInTChars, message));
_ERRCHECK(_tcscat_s(buffer, sizeInTChars, _T(": ")));
}
/* append the error message at the end of the buffer */
return _tcserror_s(buffer + _tcslen(buffer), sizeInTChars - _tcslen(buffer), errno);
}

View File

@ -0,0 +1,159 @@
/***
*_tolower.c - convert character to lower case
*
* Copyright (c) Microsoft Corporation. All rights reserved.
*
*Purpose:
* Defines _Tolower().
*
*******************************************************************************/
#include <cruntime.h>
#include <ctype.h>
#include <stddef.h>
#include <xlocinfo.h>
#include <locale.h>
#include <mtdll.h>
#include <setlocal.h>
#include <awint.h>
#include <stdlib.h>
#include <dbgint.h>
#include <yvals.h>
/* remove macro definitions of _tolower() and tolower()
*/
#undef _tolower
#undef tolower
/***
*int _Tolower(c) - convert character to lower case
*
*Purpose:
* _Tolower() is a version of tolower with a locale argument.
*
*Entry:
* c - int value of character to be converted
* const _Ctypevec * = pointer to locale info
*
*Exit:
* returns int value of lower case representation of c
*
*Exceptions:
*
*******************************************************************************/
_CRTIMP2_PURE int __CLRCALL_PURE_OR_CDECL _Tolower (
int c,
const _Ctypevec *ploc
)
{
int size;
unsigned char inbuffer[3];
unsigned char outbuffer[3];
UINT codepage;
const wchar_t *locale_name;
if (ploc == 0)
{
locale_name = ___lc_locale_name_func()[LC_CTYPE];
codepage = ___lc_codepage_func();
}
else
{
locale_name = ploc->_LocaleName;
codepage = ploc->_Page;
}
if (locale_name == NULL)
{
if ( (c >= 'A') && (c <= 'Z') )
c = c + ('a' - 'A');
return c;
}
/* if checking case of c does not require API call, do it */
if ((unsigned)c < 256)
{
if (ploc == 0)
{
if (!isupper(c))
{
return c;
}
}
else
{
if (!(ploc->_Table[c] & _UPPER))
{
return c;
}
}
}
/* convert int c to multibyte string */
if (ploc == 0 ? _cpp_isleadbyte((c >> 8) & 0xff)
: (ploc->_Table[(c >> 8) & 0xff] & _LEADBYTE) != 0)
{
inbuffer[0] = (c >> 8 & 0xff);
inbuffer[1] = (unsigned char)c;
inbuffer[2] = 0;
size = 2;
} else {
inbuffer[0] = (unsigned char)c;
inbuffer[1] = 0;
size = 1;
}
/* convert wide char to lowercase */
if (0 == (size = __crtLCMapStringA(NULL, locale_name, LCMAP_LOWERCASE,
(const char *)inbuffer, size, (char *)outbuffer, 3, codepage, TRUE)))
{
return c;
}
/* construct integer return value */
if (size == 1)
return ((int)outbuffer[0]);
else
return ((int)outbuffer[1] | ((int)outbuffer[0] << 8));
}
/***
*_Ctypevec _Getctype() - get ctype info for current locale
*
*Purpose:
*
*Entry:
*
*Exit:
*
*Exceptions:
*
*******************************************************************************/
_CRTIMP2_PURE _Ctypevec __CLRCALL_PURE_OR_CDECL _Getctype()
{
/* get ctype info for current locale */
_Ctypevec ctype;
ctype._Page = ___lc_codepage_func();
ctype._Table = (const short *)_calloc_crt(256, sizeof (*__pctype_func()));
if (ctype._Table != 0)
{
memcpy((void *)ctype._Table, __pctype_func(), 256 * sizeof (*__pctype_func()));
ctype._Delfl = 1;
}
else
{
ctype._Table = (const short *)__pctype_func();
ctype._Delfl = 0;
}
ctype._LocaleName = ___lc_locale_name_func()[LC_COLLATE];
if (ctype._LocaleName)
ctype._LocaleName = _wcsdup(ctype._LocaleName);
return (ctype);
}

View File

@ -0,0 +1,119 @@
/***
*_toupper.c - convert character to uppercase
*
* Copyright (c) Microsoft Corporation. All rights reserved.
*
*Purpose:
* Defines _Toupper()
*
*******************************************************************************/
#include <cruntime.h>
#include <ctype.h>
#include <stddef.h>
#include <xlocinfo.h>
#include <locale.h>
#include <mtdll.h>
#include <setlocal.h>
#include <awint.h>
#include <yvals.h>
/* remove macro definitions of _toupper() and toupper()
*/
#undef _toupper
#undef toupper
/***
*int _Toupper(c) - convert character to uppercase
*
*Purpose:
* _Toupper() is a version of toupper with a locale argument.
*
*Entry:
* c - int value of character to be converted
* const _Ctypevec * = pointer to locale info
*
*Exit:
* returns int value of uppercase representation of c
*
*Exceptions:
*
*******************************************************************************/
_CRTIMP2_PURE int __CLRCALL_PURE_OR_CDECL _Toupper (
int c,
const _Ctypevec *ploc
)
{
int size;
unsigned char inbuffer[3];
unsigned char outbuffer[3];
const wchar_t *locale_name;
UINT codepage;
if (ploc == 0)
{
locale_name = ___lc_locale_name_func()[LC_CTYPE];
codepage = ___lc_codepage_func();
}
else
{
locale_name = ploc->_LocaleName;
codepage = ploc->_Page;
}
if (locale_name == NULL)
{
if ( (c >= 'a') && (c <= 'z') )
c = c - ('a' - 'A');
return c;
}
/* if checking case of c does not require API call, do it */
if ((unsigned)c < 256)
{
if (ploc == 0)
{
if (!islower(c))
{
return c;
}
}
else
{
if (!(ploc->_Table[c] & _LOWER))
{
return c;
}
}
}
/* convert int c to multibyte string */
if (ploc == 0 ? _cpp_isleadbyte((c >> 8) & 0xff)
: (ploc->_Table[(c >> 8) & 0xff] & _LEADBYTE) != 0)
{
inbuffer[0] = (c >> 8 & 0xff);
inbuffer[1] = (unsigned char)c;
inbuffer[2] = 0;
size = 2;
} else {
inbuffer[0] = (unsigned char)c;
inbuffer[1] = 0;
size = 1;
}
/* convert wide char to uppercase */
if (0 == (size = __crtLCMapStringA(NULL, locale_name, LCMAP_UPPERCASE,
(const char *)inbuffer, size, (char *)outbuffer, 3, codepage, TRUE)))
{
return c;
}
/* construct integer return value */
if (size == 1)
return ((int)outbuffer[0]);
else
return ((int)outbuffer[1] | ((int)outbuffer[0] << 8));
}

View File

@ -0,0 +1,26 @@
/***
*_wcserr.c - routine for indexing into system error list
*
* Copyright (c) Microsoft Corporation. All rights reserved.
*
*Purpose:
* Returns system error message index by errno; conforms to the
* XENIX standard, much compatibility with 1983 uniforum draft standard.
* (wide char version of _strerror())
*
*******************************************************************************/
#ifndef _UNICODE
#define _UNICODE 1
#endif /* _UNICODE */
#ifndef UNICODE
#define UNICODE 1
#endif /* UNICODE */
#undef _MBCS /* UNICODE not _MBCS */
#include "_strerr.c"

View File

@ -0,0 +1,284 @@
/***
*_wctype.c - function versions of wctype macros
*
* Copyright (c) Microsoft Corporation. All rights reserved.
*
*Purpose:
* This file provides function versions of the wide character
* classification and conversion macros in ctype.h.
*
*******************************************************************************/
/***
*wctype - Function versions of wctype macros
*
*Purpose:
* Function versions of the wide char macros in ctype.h,
* including isleadbyte and iswascii. In order to define
* these, we use a trick -- we undefine the macro so we can use the
* name in the function declaration, then re-include the file so
* we can use the macro in the definition part.
*
* Functions defined:
* iswalpha iswupper iswlower
* iswdigit iswxdigit iswspace
* iswpunct iswalnum iswprint
* iswgraph iswctrl iswascii
* iswblank isleadbyte
*
*Entry:
* wchar_t c = character to be tested
*Exit:
* returns non-zero = character is of the requested type
* 0 = character is NOT of the requested type
*
*Exceptions:
* None.
*
*******************************************************************************/
#include <ctype.h>
#include <cruntime.h>
#include <stdlib.h>
#include <locale.h>
#include <mbctype.h>
#include <mtdll.h>
#include <setlocal.h>
extern "C"
{
extern __inline int (__cdecl _isleadbyte_l) (
int c,
_locale_t plocinfo
)
{
_LocaleUpdate _loc_update(plocinfo);
return (_loc_update.GetLocaleT()->locinfo->pctype[(unsigned char)(c)] & _LEADBYTE);
}
extern __inline int (__cdecl isleadbyte) (
int c
)
{
return _isleadbyte_l(c, NULL);
}
extern __inline int (__cdecl _iswalpha_l) (
wint_t c,
_locale_t plocinfo
)
{
return iswalpha(c);
}
extern __inline int (__cdecl iswalpha) (
wint_t c
)
{
return iswalpha(c);
}
extern __inline int (__cdecl _iswupper_l) (
wint_t c,
_locale_t plocinfo
)
{
return iswupper(c);
}
extern __inline int (__cdecl iswupper) (
wint_t c
)
{
return iswupper(c);
}
extern __inline int (__cdecl _iswlower_l) (
wint_t c,
_locale_t plocinfo
)
{
return iswlower(c);
}
extern __inline int (__cdecl iswlower) (
wint_t c
)
{
return iswlower(c);
}
extern __inline int (__cdecl _iswdigit_l) (
wint_t c,
_locale_t plocinfo
)
{
return iswdigit(c);
}
extern __inline int (__cdecl iswdigit) (
wint_t c
)
{
return iswdigit(c);
}
extern __inline int (__cdecl _iswxdigit_l) (
wint_t c,
_locale_t plocinfo
)
{
return iswxdigit(c);
}
extern __inline int (__cdecl iswxdigit) (
wint_t c
)
{
return iswxdigit(c);
}
extern __inline int (__cdecl _iswspace_l) (
wint_t c,
_locale_t plocinfo
)
{
return iswspace(c);
}
extern __inline int (__cdecl iswspace) (
wint_t c
)
{
return iswspace(c);
}
extern __inline int (__cdecl _iswpunct_l) (
wint_t c,
_locale_t plocinfo
)
{
return iswpunct(c);
}
extern __inline int (__cdecl iswpunct) (
wint_t c
)
{
return iswpunct(c);
}
extern __inline int (__cdecl _iswblank_l) (
wint_t c,
_locale_t plocinfo
)
{
return iswblank(c);
}
extern __inline int (__cdecl iswblank) (
wint_t c
)
{
return iswblank(c);
}
extern __inline int (__cdecl _iswalnum_l) (
wint_t c,
_locale_t plocinfo
)
{
return iswalnum(c);
}
extern __inline int (__cdecl iswalnum) (
wint_t c
)
{
return iswalnum(c);
}
extern __inline int (__cdecl _iswprint_l) (
wint_t c,
_locale_t plocinfo
)
{
return iswprint(c);
}
extern __inline int (__cdecl iswprint) (
wint_t c
)
{
return iswprint(c);
}
extern __inline int (__cdecl _iswgraph_l) (
wint_t c,
_locale_t plocinfo
)
{
return iswgraph(c);
}
extern __inline int (__cdecl iswgraph) (
wint_t c
)
{
return iswgraph(c);
}
extern __inline int (__cdecl _iswcntrl_l) (
wint_t c,
_locale_t plocinfo
)
{
return iswcntrl(c);
}
extern __inline int (__cdecl iswcntrl) (
wint_t c
)
{
return iswcntrl(c);
}
extern __inline int (__cdecl iswascii) (
wint_t c
)
{
return iswascii(c);
}
extern __inline int (__cdecl _iswcsym_l) (
wint_t c,
_locale_t plocinfo
)
{
return __iswcsym(c);
}
extern __inline int (__cdecl __iswcsym) (
wint_t c
)
{
return __iswcsym(c);
}
extern __inline int (__cdecl _iswcsymf_l) (
wint_t c,
_locale_t plocinfo
)
{
return __iswcsymf(c);
}
extern __inline int (__cdecl __iswcsymf) (
wint_t c
)
{
return __iswcsymf(c);
}
}

View File

@ -0,0 +1,21 @@
/***
*_wopen.c - open a stream, with string mode (wchar_t version)
*
* Copyright (c) Microsoft Corporation. All rights reserved.
*
*Purpose:
* defines _wopenfile() - opens a stream, with string arguments for mode
*
*******************************************************************************/
#ifndef _UNICODE
#define _UNICODE 1
#endif /* _UNICODE */
#ifndef UNICODE
#define UNICODE 1
#endif /* UNICODE */
#include "_open.c"

View File

@ -0,0 +1,30 @@
/***
*_wstargv.c - Wildcard argv[] expansion (wchar_t version)
*
* Copyright (c) Microsoft Corporation. All rights reserved.
*
*Purpose:
* _wsetargv performs wildcard argv[] expansion
*
* NOTE: This stub module scheme is compatible with NT build
* procedure.
*
*******************************************************************************/
#define WPRFLAG 1
#ifndef _UNICODE
#define _UNICODE 1
#endif /* _UNICODE */
#ifndef UNICODE
#define UNICODE 1
#endif /* UNICODE */
#undef _MBCS /* UNICODE not _MBCS */
#define WILDCARD 1
#include "stdargv.c"

View File

@ -0,0 +1,279 @@
/***
*a_cmp.c - A version of CompareString.
*
* Copyright (c) Microsoft Corporation. All rights reserved.
*
*Purpose:
* Use either CompareStringA or CompareStringW depending on which is
* available
*
*******************************************************************************/
#include <cruntime.h>
#include <internal.h>
#include <dbgint.h>
#include <stdlib.h>
#include <locale.h>
#include <awint.h>
#include <dbgint.h>
#include <malloc.h>
#include <awint.h>
#include <mtdll.h>
#include <setlocal.h>
/***
*int __cdecl strncnt - count characters in a string, up to n.
*
*Purpose:
* Internal local support function. Counts characters in string before NULL.
* If NULL not found in n chars, then return n.
*
*Entry:
* const char *string - start of string
* int n - byte count
*
*Exit:
* returns number of bytes from start of string to
* NULL (exclusive), up to n.
*
*Exceptions:
*
*******************************************************************************/
static int __cdecl strncnt (
const char *string,
int cnt
)
{
int n = cnt;
char *cp = (char *)string;
while (n-- && *cp)
cp++;
return cnt - n - 1;
}
/***
*int __cdecl __crtCompareStringA - Get type information about an ANSI string.
*
*Purpose:
* Internal support function. Assumes info in ANSI string format. Tries
* to use NLS API call CompareStringA if available and uses CompareStringW
* if it must. If neither are available it fails and returns 0.
*
*Entry:
* LPCWSTR LocaleName - locale context for the comparison.
* DWORD dwCmpFlags - see NT\Chicago docs
* LPCSTR lpStringn - multibyte string to be compared
* int cchCountn - char (byte) count (NOT including NULL)
* (-1 if NULL terminated)
* int code_page - for MB/WC conversion. If 0, use __lc_codepage
*
*Exit:
* Success: 1 - if lpString1 < lpString2
* 2 - if lpString1 == lpString2
* 3 - if lpString1 > lpString2
* Failure: 0
*
*Exceptions:
*
*******************************************************************************/
static int __cdecl __crtCompareStringA_stat(
_locale_t plocinfo,
LPCWSTR LocaleName,
DWORD dwCmpFlags,
LPCSTR lpString1,
int cchCount1,
LPCSTR lpString2,
int cchCount2,
int code_page
)
{
/*
* CompareString will compare past NULL. Must find NULL if in string
* before cchCountn chars.
*/
if (cchCount1 > 0)
cchCount1 = strncnt(lpString1, cchCount1);
else if ( cchCount1 < -1 )
return FALSE;
if (cchCount2 > 0)
cchCount2 = strncnt(lpString2, cchCount2);
else if ( cchCount2 < -1 )
return FALSE;
int buff_size1;
int buff_size2;
wchar_t *wbuffer1;
wchar_t *wbuffer2;
int retcode = 0;
/*
* Use __lc_codepage for conversion if code_page not specified
*/
if (0 == code_page)
code_page = plocinfo->locinfo->lc_codepage;
/*
* Special case: at least one count is zero
*/
if (!cchCount1 || !cchCount2)
{
unsigned char *cp; // char pointer
CPINFO cpInfo; // struct for use with GetCPInfo
/* both strings zero */
if (cchCount1 == cchCount2)
return 2;
/* string 1 greater */
if (cchCount2 > 1)
return 1;
/* string 2 greater */
if (cchCount1 > 1)
return 3;
/*
* one has zero count, the other has a count of one
* - if the one count is a naked lead byte, the strings are equal
* - otherwise it is a single character and they are unequal
*/
if (GetCPInfo(code_page, &cpInfo) == FALSE)
return 0;
_ASSERTE(cchCount1==0 && cchCount2==1 || cchCount1==1 && cchCount2==0);
/* string 1 has count of 1 */
if (cchCount1 > 0)
{
if (cpInfo.MaxCharSize < 2)
return 3;
for ( cp = (unsigned char *)cpInfo.LeadByte ;
cp[0] && cp[1] ;
cp += 2 )
if ( (*(unsigned char *)lpString1 >= cp[0]) &&
(*(unsigned char *)lpString1 <= cp[1]) )
return 2;
return 3;
}
/* string 2 has count of 1 */
if (cchCount2 > 0)
{
if (cpInfo.MaxCharSize < 2)
return 1;
for ( cp = (unsigned char *)cpInfo.LeadByte ;
cp[0] && cp[1] ;
cp += 2 )
if ( (*(unsigned char *)lpString2 >= cp[0]) &&
(*(unsigned char *)lpString2 <= cp[1]) )
return 2;
return 1;
}
}
/*
* Convert strings and return the requested information.
*/
/* find out how big a buffer we need (includes NULL if any) */
if ( 0 == (buff_size1 = MultiByteToWideChar( code_page,
MB_PRECOMPOSED |
MB_ERR_INVALID_CHARS,
lpString1,
cchCount1,
NULL,
0 )) )
return 0;
/* allocate enough space for chars */
wbuffer1 = (wchar_t *)_calloca( buff_size1, sizeof(wchar_t) );
if ( wbuffer1 == NULL ) {
return 0;
}
/* do the conversion */
if ( 0 == MultiByteToWideChar( code_page,
MB_PRECOMPOSED,
lpString1,
cchCount1,
wbuffer1,
buff_size1 ) )
goto error_cleanup;
/* find out how big a buffer we need (includes NULL if any) */
if ( 0 == (buff_size2 = MultiByteToWideChar( code_page,
MB_PRECOMPOSED |
MB_ERR_INVALID_CHARS,
lpString2,
cchCount2,
NULL,
0 )) )
goto error_cleanup;
/* allocate enough space for chars */
wbuffer2 = (wchar_t *)_calloca( buff_size2, sizeof(wchar_t) );
if ( wbuffer2 == NULL ) {
goto error_cleanup;
}
/* do the conversion */
if ( 0 != MultiByteToWideChar( code_page,
MB_PRECOMPOSED,
lpString2,
cchCount2,
wbuffer2,
buff_size2 ) )
{
retcode = __crtCompareStringEx( LocaleName,
dwCmpFlags,
wbuffer1,
buff_size1,
wbuffer2,
buff_size2);
}
_freea(wbuffer2);
error_cleanup:
_freea(wbuffer1);
return retcode;
}
extern "C" int __cdecl __crtCompareStringA(
_locale_t plocinfo,
LPCWSTR LocaleName,
DWORD dwCmpFlags,
LPCSTR lpString1,
int cchCount1,
LPCSTR lpString2,
int cchCount2,
int code_page
)
{
_LocaleUpdate _loc_update(plocinfo);
return __crtCompareStringA_stat(
_loc_update.GetLocaleT(),
LocaleName,
dwCmpFlags,
lpString1,
cchCount1,
lpString2,
cchCount2,
code_page
);
}

View File

@ -0,0 +1,96 @@
/***
*a_env.c - A version of GetEnvironmentStrings.
*
* Copyright (c) Microsoft Corporation. All rights reserved.
*
*Purpose:
* Use GetEnvironmentStringsW if available, otherwise use A version.
*
*******************************************************************************/
#include <cruntime.h>
#include <internal.h>
#include <stdlib.h>
#include <setlocal.h>
#include <awint.h>
#include <dbgint.h>
/***
*LPVOID __cdecl __crtGetEnvironmentStringsA - Get normal environment block
*
*Purpose:
* Internal support function. Since GetEnvironmentStrings returns in OEM
* and we want ANSI (note that GetEnvironmentVariable returns ANSI!) and
* SetFileApistoAnsi() does not affect it, we have no choice but to
* obtain the block in wide character and convert to ANSI.
*
*Entry:
* VOID
*
*Exit:
* LPVOID - pointer to environment block
*
*Exceptions:
*
*******************************************************************************/
LPVOID __cdecl __crtGetEnvironmentStringsA(
VOID
)
{
wchar_t *wEnv;
wchar_t *wTmp;
char *aEnv = NULL;
int nSizeW;
int nSizeA;
/* obtain wide environment block */
if ( NULL == (wEnv = GetEnvironmentStringsW()) )
return NULL;
/* look for double null that indicates end of block */
wTmp = wEnv;
while ( *wTmp != L'\0' ) {
if ( *++wTmp == L'\0' )
wTmp++;
}
/* calculate total size of block, including all nulls */
nSizeW = (int)(wTmp - wEnv + 1);
/* find out how much space needed for multi-byte environment */
nSizeA = WideCharToMultiByte( CP_ACP,
0,
wEnv,
nSizeW,
NULL,
0,
NULL,
NULL );
/* allocate space for multi-byte string */
if ( (nSizeA == 0) ||
((aEnv = (char *)_malloc_crt(nSizeA)) == NULL) )
{
FreeEnvironmentStringsW( wEnv );
return NULL;
}
/* do the conversion */
if ( !WideCharToMultiByte( CP_ACP,
0,
wEnv,
nSizeW,
aEnv,
nSizeA,
NULL,
NULL ) )
{
_free_crt( aEnv );
aEnv = NULL;
}
FreeEnvironmentStringsW( wEnv );
return aEnv;
}

View File

@ -0,0 +1,130 @@
/***
*a_loc.c - A versions of GetLocaleInfo.
*
* Copyright (c) Microsoft Corporation. All rights reserved.
*
*Purpose:
* Use either GetLocaleInfoA or GetLocaleInfoW depending on which is
* available
*
*******************************************************************************/
#include <cruntime.h>
#include <internal.h>
#include <stdlib.h>
#include <awint.h>
#include <dbgint.h>
#include <malloc.h>
#include <locale.h>
#include <mtdll.h>
#include <setlocal.h>
/***
*int __cdecl __crtGetLocaleInfoA - Get locale info and return it as an ASCII
* string
*
*Purpose:
* Internal support function. Assumes info in ANSI string format. Tries
* to use NLS API call GetLocaleInfoA if available (Chicago) and uses
* GetLocaleInfoA if it must (NT). If neither are available it fails and
* returns 0.
*
*Entry:
* LPCWSTR LocaleName - locale context for the comparison.
* LCTYPE LCType - see NT\Chicago docs
* LPSTR lpLCData - pointer to memory to return data
* int cchData - char (byte) count of buffer (including NULL)
* (if 0, lpLCData is not referenced, size needed
* is returned)
* int code_page - for MB/WC conversion. If 0, use __lc_codepage
*
*Exit:
* Success: the number of characters copied (including NULL).
* Failure: 0
*
*Exceptions:
*
*******************************************************************************/
static int __cdecl __crtGetLocaleInfoA_stat(
_locale_t plocinfo,
const wchar_t* LocaleName,
LCTYPE LCType,
LPSTR lpLCData,
int cchData
)
{
int retval = 0;
int code_page;
int buff_size;
wchar_t *wbuffer;
/*
* Use __lc_codepage for conversion
*/
code_page = plocinfo->locinfo->lc_codepage;
/* find out how big buffer needs to be */
if (0 == (buff_size = __crtGetLocaleInfoEx(LocaleName, LCType, NULL, 0)))
return 0;
/* allocate buffer */
wbuffer = (wchar_t *)_calloca( buff_size, sizeof(wchar_t) );
if ( wbuffer == NULL ) {
return 0;
}
/* get the info in wide format */
if (0 == __crtGetLocaleInfoEx(LocaleName, LCType, wbuffer, buff_size))
goto error_cleanup;
/* convert from Wide Char to ANSI */
if (0 == cchData)
{
/* convert into local buffer */
retval = WideCharToMultiByte( code_page,
0,
wbuffer,
-1,
NULL,
0,
NULL,
NULL );
}
else {
/* convert into user buffer */
retval = WideCharToMultiByte( code_page,
0,
wbuffer,
-1,
lpLCData,
cchData,
NULL,
NULL );
}
error_cleanup:
_freea(wbuffer);
return retval;
}
extern "C" int __cdecl __crtGetLocaleInfoA(
_locale_t plocinfo,
const wchar_t* LocaleName,
LCTYPE LCType,
LPSTR lpLCData,
int cchData
)
{
_LocaleUpdate _loc_update(plocinfo);
return __crtGetLocaleInfoA_stat(
_loc_update.GetLocaleT(),
LocaleName,
LCType,
lpLCData,
cchData
);
}

View File

@ -0,0 +1,272 @@
/***
*a_map.c - A version of LCMapString.
*
* Copyright (c) Microsoft Corporation. All rights reserved.
*
*Purpose:
* Use either LCMapStringA or LCMapStringW depending on which is available
*
*******************************************************************************/
#include <cruntime.h>
#include <internal.h>
#include <stdlib.h>
#include <locale.h>
#include <awint.h>
#include <dbgint.h>
#include <malloc.h>
#include <locale.h>
#include <mtdll.h>
#include <setlocal.h>
/***
*int __cdecl strncnt - count characters in a string, up to n.
*
*Purpose:
* Internal local support function. Counts characters in string before
* null. If null is not found in n chars, then return n.
*
*Entry:
* const char *string - start of string
* int n - byte count
*
*Exit:
* returns number of bytes from start of string to
* null (exclusive), up to n.
*
*Exceptions:
*
*******************************************************************************/
static int __cdecl strncnt (
const char *string,
int cnt
)
{
int n = cnt;
char *cp = (char *)string;
while (n-- && *cp)
cp++;
return cnt - n - 1;
}
/***
*int __cdecl __crtLCMapStringA - Get type information about an ANSI string.
*
*Purpose:
* Internal support function. Assumes info in ANSI string format. Tries
* to use NLS API call LCMapStringA if available and uses LCMapStringW
* if it must. If neither are available it fails and returns 0.
*
*Entry:
* LPCWSTR LocaleName - locale context for the comparison.
* DWORD dwMapFlags - see NT\Chicago docs
* LPCSTR lpSrcStr - pointer to string to be mapped
* int cchSrc - wide char (word) count of input string
* (including NULL if any)
* (-1 if NULL terminated)
* LPSTR lpDestStr - pointer to memory to store mapping
* int cchDest - char (byte) count of buffer (including NULL)
* int code_page - for MB/WC conversion. If 0, use __lc_codepage
* BOOL bError - TRUE if MB_ERR_INVALID_CHARS set on call to
* MultiByteToWideChar when GetStringTypeW used.
*
*Exit:
* Success: number of chars written to lpDestStr (including NULL)
* Failure: 0
*
*Exceptions:
*
*******************************************************************************/
static int __cdecl __crtLCMapStringA_stat(
_locale_t plocinfo,
LPCWSTR LocaleName,
DWORD dwMapFlags,
LPCSTR lpSrcStr,
int cchSrc,
LPSTR lpDestStr,
int cchDest,
int code_page,
BOOL bError
)
{
/*
* LCMapString will map past NULL. Must find NULL if in string
* before cchSrc characters.
*/
if (cchSrc > 0) {
int cchSrcCnt = strncnt(lpSrcStr, cchSrc);
/*
* Include NULL in cchSrc if lpSrcStr terminated within cchSrc bytes.
*/
if (cchSrcCnt < cchSrc) {
cchSrc = cchSrcCnt + 1;
} else {
cchSrc = cchSrcCnt;
}
}
int retval = 0;
int inbuff_size;
int outbuff_size;
wchar_t *inwbuffer = NULL;
wchar_t *outwbuffer = NULL;
/*
* Convert string and return the requested information. Note that
* we are converting to a wide string so there is not a
* one-to-one correspondence between number of wide chars in the
* input string and the number of *bytes* in the buffer. However,
* there had *better be* a one-to-one correspondence between the
* number of wide characters and the number of multibyte characters
* or the resulting mapped string will be worthless to the user.
*/
/*
* Use __lc_codepage for conversion if code_page not specified
*/
if (0 == code_page)
code_page = plocinfo->locinfo->lc_codepage;
/* find out how big a buffer we need (includes NULL if any) */
if ( 0 == (inbuff_size =
MultiByteToWideChar( code_page,
bError ? MB_PRECOMPOSED |
MB_ERR_INVALID_CHARS :
MB_PRECOMPOSED,
lpSrcStr,
cchSrc,
NULL,
0 )) )
return 0;
/* allocate enough space for wide chars */
inwbuffer = (wchar_t *)_calloca( inbuff_size, sizeof(wchar_t) );
if ( inwbuffer == NULL ) {
return 0;
}
/* do the conversion */
if ( 0 == MultiByteToWideChar( code_page,
MB_PRECOMPOSED,
lpSrcStr,
cchSrc,
inwbuffer,
inbuff_size) )
goto error_cleanup;
/* get size required for string mapping */
if ( 0 == (retval = __crtLCMapStringEx( LocaleName,
dwMapFlags,
inwbuffer,
inbuff_size,
NULL,
0)) )
goto error_cleanup;
if (dwMapFlags & LCMAP_SORTKEY) {
/* retval is size in BYTES */
if (0 != cchDest) {
if (retval > cchDest)
goto error_cleanup;
/* do string mapping */
if ( 0 == __crtLCMapStringEx( LocaleName,
dwMapFlags,
inwbuffer,
inbuff_size,
(LPWSTR)lpDestStr,
cchDest) )
goto error_cleanup;
}
}
else {
/* retval is size in wide chars */
outbuff_size = retval;
/* allocate enough space for wide chars (includes NULL if any) */
outwbuffer = (wchar_t *)_calloca( outbuff_size, sizeof(wchar_t) );
if ( outwbuffer == NULL ) {
goto error_cleanup;
}
/* do string mapping */
if ( 0 == __crtLCMapStringEx( LocaleName,
dwMapFlags,
inwbuffer,
inbuff_size,
outwbuffer,
outbuff_size) )
goto error_cleanup;
if (0 == cchDest) {
/* get size required */
if ( 0 == (retval =
WideCharToMultiByte( code_page,
0,
outwbuffer,
outbuff_size,
NULL,
0,
NULL,
NULL )) )
goto error_cleanup;
}
else {
/* convert mapping */
if ( 0 == (retval =
WideCharToMultiByte( code_page,
0,
outwbuffer,
outbuff_size,
lpDestStr,
cchDest,
NULL,
NULL )) )
goto error_cleanup;
}
}
error_cleanup:
if ( outwbuffer != NULL )
_freea(outwbuffer);
_freea(inwbuffer);
return retval;
}
extern "C" int __cdecl __crtLCMapStringA(
_locale_t plocinfo,
LPCWSTR LocaleName,
DWORD dwMapFlags,
LPCSTR lpSrcStr,
int cchSrc,
LPSTR lpDestStr,
int cchDest,
int code_page,
BOOL bError
)
{
_LocaleUpdate _loc_update(plocinfo);
return __crtLCMapStringA_stat(
_loc_update.GetLocaleT(),
LocaleName,
dwMapFlags,
lpSrcStr,
cchSrc,
lpDestStr,
cchDest,
code_page,
bError
);
}

View File

@ -0,0 +1,141 @@
/***
*a_str.c - A version of GetStringType.
*
* Copyright (c) Microsoft Corporation. All rights reserved.
*
*Purpose:
* Use either GetStringTypeA or GetStringTypeW depending on which is
* unstubbed.
*
*******************************************************************************/
#include <cruntime.h>
#include <internal.h>
#include <stdlib.h>
#include <locale.h>
#include <awint.h>
#include <dbgint.h>
#include <malloc.h>
#include <awint.h>
#include <mtdll.h>
#include <setlocal.h>
/***
*int __cdecl __crtGetStringTypeA - Get type information about an ANSI string.
*
*Purpose:
* Internal support function. Assumes info in ANSI string format. Tries
* to use NLS API call GetStringTypeA if available and uses GetStringTypeW
* if it must. If neither are available it fails and returns FALSE.
*
*Entry:
* DWORD dwInfoType - see NT\Chicago docs
* LPCSTR lpSrcStr - char (byte) string for which character types
* are requested
* int cchSrc - char (byte) count of lpSrcStr (including NULL
* if any)
* LPWORD lpCharType - word array to receive character type information
* (must be twice the size of lpSrcStr)
* int code_page - for MB/WC conversion. If 0, use __lc_codepage
* BOOL bError - TRUE if MB_ERR_INVALID_CHARS set on call to
* MultiByteToWideChar when GetStringTypeW used.
*
*Exit:
* Success: TRUE
* Failure: FALSE
*
*Exceptions:
*
*******************************************************************************/
static BOOL __cdecl __crtGetStringTypeA_stat(
_locale_t plocinfo,
DWORD dwInfoType,
LPCSTR lpSrcStr,
int cchSrc,
LPWORD lpCharType,
int code_page,
BOOL bError
)
{
int retval1;
int buff_size;
wchar_t *wbuffer;
BOOL retval2 = FALSE;
/*
* Convert string and return the requested information. Note that
* we are converting to a wide character string so there is not a
* one-to-one correspondence between number of multibyte chars in the
* input string and the number of wide chars in the buffer. However,
* there had *better be* a one-to-one correspondence between the
* number of multibyte characters and the number of WORDs in the
* return buffer.
*/
/*
* Use __lc_codepage for conversion if code_page not specified
*/
if (0 == code_page)
code_page = plocinfo->locinfo->lc_codepage;
/* find out how big a buffer we need */
if ( 0 == (buff_size = MultiByteToWideChar( code_page,
bError ?
MB_PRECOMPOSED |
MB_ERR_INVALID_CHARS
: MB_PRECOMPOSED,
lpSrcStr,
cchSrc,
NULL,
0 )) )
return FALSE;
/* allocate enough space for wide chars */
wbuffer = (wchar_t *)_calloca( sizeof(wchar_t), buff_size );
if ( wbuffer == NULL ) {
return FALSE;
}
(void)memset( wbuffer, 0, sizeof(wchar_t) * buff_size );
/* do the conversion */
if ( 0 != (retval1 = MultiByteToWideChar( code_page,
MB_PRECOMPOSED,
lpSrcStr,
cchSrc,
wbuffer,
buff_size )) )
/* obtain result */
retval2 = GetStringTypeW( dwInfoType,
wbuffer,
retval1,
lpCharType );
_freea(wbuffer);
return retval2;
}
extern "C" BOOL __cdecl __crtGetStringTypeA(
_locale_t plocinfo,
DWORD dwInfoType,
LPCSTR lpSrcStr,
int cchSrc,
LPWORD lpCharType,
int code_page,
BOOL bError
)
{
_LocaleUpdate _loc_update(plocinfo);
return __crtGetStringTypeA_stat(
_loc_update.GetLocaleT(),
dwInfoType,
lpSrcStr,
cchSrc,
lpCharType,
code_page,
bError
);
}

View File

@ -0,0 +1,125 @@
/***
*abort.c - abort a program by raising SIGABRT
*
* Copyright (c) Microsoft Corporation. All rights reserved.
*
*Purpose:
* defines abort() - print a message and raise SIGABRT.
*
*******************************************************************************/
#include <cruntime.h>
#include <stdlib.h>
#include <internal.h>
#include <awint.h>
#include <rterr.h>
#include <signal.h>
#include <oscalls.h>
#include <mtdll.h>
#include <dbgint.h>
#ifdef _DEBUG
#define _INIT_ABORT_BEHAVIOR _WRITE_ABORT_MSG
#else /* _DEBUG */
#define _INIT_ABORT_BEHAVIOR _CALL_REPORTFAULT
#endif /* _DEBUG */
unsigned int __abort_behavior = _INIT_ABORT_BEHAVIOR;
/***
*void abort() - abort the current program by raising SIGABRT
*
*Purpose:
* print out an abort message and raise the SIGABRT signal. If the user
* hasn't defined an abort handler routine, terminate the program
* with exit status of 3 without cleaning up.
*
* Multi-thread version does not raise SIGABRT -- this isn't supported
* under multi-thread.
*
*Entry:
* None.
*
*Exit:
* Does not return.
*
*Uses:
*
*Exceptions:
*
*******************************************************************************/
void __cdecl abort (
void
)
{
_PHNDLR sigabrt_act = SIG_DFL;
#ifdef _DEBUG
if (__abort_behavior & _WRITE_ABORT_MSG)
{
/* write the abort message */
_NMSG_WRITE(_RT_ABORT);
}
#endif /* _DEBUG */
/* Check if the user installed a handler for SIGABRT.
* We need to read the user handler atomically in the case
* another thread is aborting while we change the signal
* handler.
*/
sigabrt_act = __get_sigabrt();
if (sigabrt_act != SIG_DFL)
{
raise(SIGABRT);
}
/* If there is no user handler for SIGABRT or if the user
* handler returns, then exit from the program anyway
*/
if (__abort_behavior & _CALL_REPORTFAULT)
{
#if defined (_M_ARM) || defined (_CRT_APP)
__fastfail(FAST_FAIL_FATAL_APP_EXIT);
#else /* defined (_M_ARM) || defined (_CRT_APP) */
if (IsProcessorFeaturePresent(PF_FASTFAIL_AVAILABLE))
__fastfail(FAST_FAIL_FATAL_APP_EXIT);
_call_reportfault(_CRT_DEBUGGER_ABORT, STATUS_FATAL_APP_EXIT, EXCEPTION_NONCONTINUABLE);
#endif /* defined (_M_ARM) || defined (_CRT_APP) */
}
/* If we don't want to call ReportFault, then we call _exit(3), which is the
* same as invoking the default handler for SIGABRT
*/
_exit(3);
}
/***
*unsigned int _set_abort_behavior(unsigned int, unsigned int) - set the behavior on abort
*
*Purpose:
*
*Entry:
* unsigned int flags - the flags we want to set
* unsigned int mask - mask the flag values
*
*Exit:
* Return the old behavior flags
*
*Exceptions:
* None
*
*******************************************************************************/
unsigned int __cdecl _set_abort_behavior(unsigned int flags, unsigned int mask)
{
unsigned int oldflags = __abort_behavior;
__abort_behavior = oldflags & (~mask) | flags & mask;
return oldflags;
}

View File

@ -0,0 +1,44 @@
/***
*abs.c - find absolute value
*
* Copyright (c) Microsoft Corporation. All rights reserved.
*
*Purpose:
* defines abs() - find the absolute value of an int.
*
*******************************************************************************/
#include <cruntime.h>
#include <stdlib.h>
#pragma function(abs, _abs64)
/***
*int abs(number) - find absolute value of number
*
*Purpose:
* Returns the absolute value of number (if number >= 0, returns number,
* else returns -number).
*
*Entry:
* int number - number to find absolute value of
*
*Exit:
* returns the aboslute value of number
*
*Exceptions:
*
*******************************************************************************/
int __cdecl abs (
int number
)
{
return( number>=0 ? number : -number );
}
__int64 __cdecl _abs64(
__int64 num
)
{
return (num >=0 ? num : -num);
}

View File

@ -0,0 +1,135 @@
/***
*access.c - access function
*
* Copyright (c) Microsoft Corporation. All rights reserved.
*
*Purpose:
* This file has the _access() function which checks on file accessability.
*
*******************************************************************************/
#include <cruntime.h>
#include <io.h>
#include <oscalls.h>
#include <stdlib.h>
#include <errno.h>
#include <msdos.h>
#include <internal.h>
#include <tchar.h>
#include <malloc.h>
#include <dbgint.h>
/***
*int _access(path, amode) - check whether file can be accessed under mode
*
*Purpose:
* Checks to see if the specified file exists and can be accessed
* in the given mode.
*
*Entry:
* _TSCHAR *path - pathname
* int amode - access mode
* (0 = exist only, 2 = write, 4 = read, 6 = read/write)
*
*Exit:
* returns 0 if file has given mode
* returns -1 and sets errno if file does not have given mode or
* does not exist
*
*Exceptions:
*
*******************************************************************************/
int __cdecl _taccess (
const _TSCHAR *path,
int amode
)
{
errno_t e;
e = _taccess_s(path,amode);
return e ? -1 : 0 ;
}
/***
*errno_t _access_s(path, amode) - check whether file can be accessed under mode
*
*Purpose:
* Checks to see if the specified file exists and can be accessed
* in the given mode.
*
*Entry:
* _TSCHAR *path - pathname
* int amode - access mode
* (0 = exist only, 2 = write, 4 = read, 6 = read/write)
*
*Exit:
* returns 0 if file has given mode
* returns errno_t for any other errors
*
*Exceptions:
*
*******************************************************************************/
#ifndef _UNICODE
errno_t __cdecl _access_s (
const char *path,
int amode
)
{
wchar_t* pathw = NULL;
errno_t retval;
if (path)
{
if (!__copy_path_to_wide_string(path, &pathw))
return errno;
}
/* call the wide-char variant */
retval = _waccess_s(pathw, amode);
_free_crt(pathw); /* _free_crt leaves errno alone if everything completes as expected */
return retval;
}
#else /* _UNICODE */
errno_t __cdecl _waccess_s (
const wchar_t *path,
int amode
)
{
WIN32_FILE_ATTRIBUTE_DATA attr_data;
_VALIDATE_CLEAR_OSSERR_RETURN_ERRCODE( (path != NULL), EINVAL);
_VALIDATE_CLEAR_OSSERR_RETURN_ERRCODE( ((amode & (~6)) == 0), EINVAL);
if (!GetFileAttributesExW(path, GetFileExInfoStandard, (void*) &attr_data)) {
/* error occured -- map error code and return */
_dosmaperr(GetLastError());
return errno;
}
if(attr_data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
{
/* All directories have read & write access */
return 0;
}
/* no error; see if returned premission settings OK */
if ( (attr_data.dwFileAttributes & FILE_ATTRIBUTE_READONLY) && (amode & 2) ) {
/* no write permission on file, return error */
_doserrno = E_access;
errno = EACCES;
return errno;
}
else
/* file exists and has requested permission setting */
return 0;
}
#endif /* _UNICODE */

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,474 @@
/***
*align.c - Aligned allocation, reallocation or freeing of memory in the heap
*
* Copyright (c) Microsoft Corporation. All rights reserved.
*
*Purpose:
* Defines the _aligned_malloc(),
* _aligned_realloc(),
* _aligned_recalloc(),
* _aligned_offset_malloc(),
* _aligned_offset_realloc(),
* _aligned_offset_recalloc(),
* _aligned_free(),
* _aligned_msize() functions.
*
*******************************************************************************/
#include <dbgint.h>
#include <crtdbg.h>
#include <errno.h>
#include <string.h>
#include <malloc.h>
#include <stddef.h>
#include <stdlib.h>
#include <internal.h>
#define IS_2_POW_N(X) (((X)&(X-1)) == 0)
#define PTR_SZ sizeof(void *)
/***
*
* |1|___6___|2|3|4|_________5__________|_6_|
*
* 1 -> Pointer to start of the block allocated by malloc.
* 2 -> Value of 1.
* 3 -> Gap used to get 1 aligned on sizeof(void *).
* 4 -> Pointer to the start of data block.
* 4+5 -> Data block.
* 6 -> Wasted memory at rear of data block.
* 6 -> Wasted memory.
*
*******************************************************************************/
/***
* void *_aligned_malloc_base(size_t size, size_t alignment)
* - Get a block of aligned memory from the heap.
*
* Purpose:
* Allocate of block of aligned memory aligned on the alignment of at least
* size bytes from the heap and return a pointer to it.
*
* Entry:
* size_t size - size of block requested
* size_t alignment - alignment of memory (needs to be a power of 2)
*
* Exit:
* Success: Pointer to memory block
* Failure: Null, errno is set
*
* Exceptions:
* Input parameters are validated. Refer to the validation section of the function.
*
*******************************************************************************/
void * __cdecl _aligned_malloc_base(
size_t size,
size_t alignment
)
{
return _aligned_offset_malloc_base(size, alignment, 0);
}
/***
* void *_aligned_offset_malloc_base(size_t size, size_t alignment, int offset)
* - Get a block of memory from the heap.
*
* Purpose:
* Allocate a block of memory which is shifted by offset from alignment of
* at least size bytes from the heap and return a pointer to it.
*
* Entry:
* size_t size - size of block of memory
* size_t alignment - alignment of memory (needs to be a power of 2)
* size_t offset - offset of memory from the alignment
*
* Exit:
* Success: Pointer to memory block
* Failure: Null, errno is set
*
* Exceptions:
* Input parameters are validated. Refer to the validation section of the function.
*
*******************************************************************************/
void * __cdecl _aligned_offset_malloc_base(
size_t size,
size_t align,
size_t offset
)
{
uintptr_t ptr, retptr, gap;
size_t nonuser_size,block_size;
/* validation section */
_VALIDATE_RETURN(IS_2_POW_N(align), EINVAL, NULL);
_VALIDATE_RETURN(offset == 0 || offset < size, EINVAL, NULL);
align = (align > PTR_SZ ? align : PTR_SZ) -1;
/* gap = number of bytes needed to round up offset to align with PTR_SZ*/
gap = (0 - offset)&(PTR_SZ -1);
nonuser_size = PTR_SZ +gap +align;
block_size = nonuser_size + size;
_VALIDATE_RETURN_NOEXC(size <= block_size, ENOMEM, NULL)
if ( (ptr =(uintptr_t)malloc(block_size)) == (uintptr_t)NULL)
return NULL;
retptr =((ptr +nonuser_size+offset)&~align)- offset;
((uintptr_t *)(retptr - gap))[-1] = ptr;
return (void *)retptr;
}
/***
*
* void *_aligned_realloc_base(void * memblock, size_t size, size_t alignment)
* - Reallocate a block of aligned memory from the heap.
*
* Purpose:
* Reallocates of block of aligned memory aligned on the alignment of at
* least size bytes from the heap and return a pointer to it. Size can be
* either greater or less than the original size of the block.
* The reallocation may result in moving the block as well as changing the
* size.
*
* Entry:
* void *memblock - pointer to block in the heap previously allocated by
* call to _aligned_malloc(), _aligned_offset_malloc(),
* _aligned_realloc() or _aligned_offset_realloc().
* size_t size - size of block requested
* size_t alignment - alignment of memory
*
* Exit:
* Success: Pointer to re-allocated memory block
* Failure: Null, errno is set
*
* Exceptions:
* Input parameters are validated. Refer to the validation section of the function.
*
*******************************************************************************/
void * __cdecl _aligned_realloc_base(
void *memblock,
size_t size,
size_t alignment
)
{
return _aligned_offset_realloc_base(memblock, size, alignment, 0);
}
/***
*
* void *_aligned_recalloc_base(void * memblock, size_t count, size_t size, size_t alignment)
* - Reallocate a block of aligned memory from the heap.
*
* Purpose:
* Reallocates of block of aligned memory aligned on the alignment of at
* least size bytes from the heap and return a pointer to it. Size can be
* either greater or less than the original size of the block.
* The reallocation may result in moving the block as well as changing the
* size.
*
* Entry:
* void *memblock - pointer to block in the heap previously allocated by
* call to _aligned_malloc(), _aligned_offset_malloc(),
* _aligned_realloc() or _aligned_offset_realloc().
* size_t count - count of items
* size_t size - size of item
* size_t alignment - alignment of memory
*
* Exit:
* Success: Pointer to re-allocated memory block
* Failure: Null, errno is set
*
* Exceptions:
* Input parameters are validated. Refer to the validation section of the function.
*
*******************************************************************************/
void * __cdecl _aligned_recalloc_base(
void *memblock,
size_t count,
size_t size,
size_t alignment
)
{
return _aligned_offset_recalloc_base(memblock, count, size, alignment, 0);
}
/***
*
* void *_aligned_offset_realloc_base (void * memblock, size_t size,
* size_t alignment, int offset)
* - Reallocate a block of memory from the heap.
*
* Purpose:
* Reallocates a block of memory which is shifted by offset from
* alignment of at least size bytes from the heap and return a pointer
* to it. Size can be either greater or less than the original size of the
* block.
*
* Entry:
* void *memblock - pointer to block in the heap previously allocated by
* call to _aligned_malloc(), _aligned_offset_malloc(),
* _aligned_realloc() or _aligned_offset_realloc().
* size_t size - size of block of memory
* size_t alignment - alignment of memory
* size_t offset - offset of memory from the alignment
*
* Exit:
* Success: Pointer to re-allocated memory block
* Failure: Null, errno is set
*
* Exceptions:
* Input parameters are validated. Refer to the validation section of the function.
*
*******************************************************************************/
void * __cdecl _aligned_offset_realloc_base(
void *memblock,
size_t size,
size_t align,
size_t offset
)
{
uintptr_t ptr, retptr, gap, stptr, diff;
uintptr_t movsz, reqsz;
int bFree = 0;
/* special cases */
if (memblock == NULL)
{
return _aligned_offset_malloc_base(size, align, offset);
}
if (size == 0)
{
_aligned_free_base(memblock);
return NULL;
}
/* validation section */
_VALIDATE_RETURN(IS_2_POW_N(align), EINVAL, NULL);
_VALIDATE_RETURN(offset == 0 || offset < size, EINVAL, NULL);
stptr = (uintptr_t)memblock;
/* ptr points to the pointer to starting of the memory block */
stptr = (stptr & ~(PTR_SZ -1)) - PTR_SZ;
/* ptr is the pointer to the start of memory block*/
stptr = *((uintptr_t *)stptr);
align = (align > PTR_SZ ? align : PTR_SZ) -1;
/* gap = number of bytes needed to round up offset to align with PTR_SZ*/
gap = (0 -offset)&(PTR_SZ -1);
diff = (uintptr_t)memblock - stptr;
/* Mov size is min of the size of data available and sizw requested.
*/
CRT_WARNING_DISABLE_PUSH(22018, "Silence prefast about overflow/underflow");
movsz = _msize((void *)stptr) - ((uintptr_t)memblock - stptr);
CRT_WARNING_POP
movsz = movsz > size? size: movsz;
reqsz = PTR_SZ +gap +align +size;
_VALIDATE_RETURN_NOEXC(size <= reqsz, ENOMEM, NULL);
/* First check if we can expand(reducing or expanding using expand) data
* safely, ie no data is lost. eg, reducing alignment and keeping size
* same might result in loss of data at the tail of data block while
* expanding.
*
* If no, use malloc to allocate the new data and move data.
*
* If yes, expand and then check if we need to move the data.
*/
if ((stptr +align +PTR_SZ +gap)<(uintptr_t)memblock)
{
if ((ptr = (uintptr_t)malloc(reqsz)) == (uintptr_t) NULL)
return NULL;
bFree = 1;
}
else
{
/* we need to save errno, which can be modified by _expand */
errno_t save_errno = errno;
if ((ptr = (uintptr_t)_expand((void *)stptr, reqsz)) == (uintptr_t)NULL)
{
errno = save_errno;
if ((ptr = (uintptr_t)malloc(reqsz)) == (uintptr_t) NULL)
return NULL;
bFree = 1;
}
else
stptr = ptr;
}
if ( ptr == ((uintptr_t)memblock - diff)
&& !( ((size_t)memblock + gap +offset) & ~(align) ))
{
return memblock;
}
retptr =((ptr +PTR_SZ +gap +align +offset)&~align)- offset;
memmove((void *)retptr, (void *)(stptr + diff), movsz);
if ( bFree)
free ((void *)stptr);
((uintptr_t *)(retptr - gap))[-1] = ptr;
return (void *)retptr;
}
/***
*
* size_t _aligned_msize_base(void *memblock, size_t align, size_t offset)
*
* Purpose:
* Computes the size of an aligned block.
*
* Entry:
* void * memblock - pointer to the aligned block of memory
*
* Exceptions:
* None. If memblock == NULL 0 is returned.
*
*******************************************************************************/
size_t __cdecl _aligned_msize_base(void *memblock, size_t align, size_t offset)
{
size_t header_size = 0; /* Size of the header block */
size_t footer_size = 0; /* Size of the footer block */
size_t total_size = 0; /* total size of the allocated block */
size_t user_size = 0; /* size of the user block*/
uintptr_t gap = 0; /* keep the alignment of the data block */
/* after the sizeof(void*) aligned pointer */
/* to the beginning of the allocated block */
uintptr_t ptr = 0; /* computes the beginning of the allocated block */
_VALIDATE_RETURN (memblock != NULL, EINVAL, -1);
/* HEADER SIZE + FOOTER SIZE = GAP + ALIGN + SIZE OF A POINTER*/
/* HEADER SIZE + USER SIZE + FOOTER SIZE = TOTAL SIZE */
ptr = (uintptr_t)memblock; /* ptr points to the start of the aligned memory block */
ptr = (ptr & ~(PTR_SZ - 1)) - PTR_SZ; /* ptr is one position behind memblock */
/* the value in ptr is the start of the real allocated block */
ptr = *((uintptr_t *)ptr); /* after dereference ptr points to the beginning of the allocated block */
total_size = _msize((void*)ptr);
header_size = (uintptr_t) memblock - ptr;
gap = (0 - offset) & (PTR_SZ - 1);
/* Alignment cannot be less than sizeof(void*) */
align = (align > PTR_SZ ? align : PTR_SZ) -1;
footer_size = gap + align + PTR_SZ - header_size;
user_size = total_size - header_size - footer_size;
return user_size;
}
/***
*
* void *_aligned_offset_recalloc_base (void * memblock, size_t size, size_t count, size_t alignment, int offset)
* - Reallocate a block of memory from the heap.
*
* Purpose:
* Reallocates a block of memory which is shifted by offset from
* alignment of at least size bytes from the heap and return a pointer
* to it. Size can be either greater or less than the original size of the
* block.
*
* Entry:
* void *memblock - pointer to block in the heap previously allocated by
* call to _aligned_malloc(), _aligned_offset_malloc(),
* _aligned_realloc() or _aligned_offset_realloc().
* size_t count - count of items
* size_t size - size of items
* size_t alignment - alignment of memory
* size_t offset - offset of memory from the alignment
*
* Exit:
* Success: Pointer to re-allocated memory block
* Failure: Null, errno is set
*
* Exceptions:
* Input parameters are validated. Refer to the validation section of the function.
*
*******************************************************************************/
void * __cdecl _aligned_offset_recalloc_base(
void * memblock,
size_t count,
size_t size,
size_t align,
size_t offset
)
{
size_t user_size = 0; /* wanted size, passed to aligned realoc */
size_t start_fill = 0; /* location where aligned recalloc starts to fill with 0 */
/* filling must start from the end of the previous user block */
void * retptr = NULL; /* result of aligned recalloc*/
uintptr_t ptr = 0; /* points to the beginning of the allocated block*/
/* ensure that (size * num) does not overflow */
if (count > 0)
{
_VALIDATE_RETURN_NOEXC((_HEAP_MAXREQ / count) >= size, ENOMEM, NULL);
}
user_size = size * count;
if (memblock != NULL)
{
start_fill = _aligned_msize(memblock, align, offset);
}
retptr = _aligned_offset_realloc_base(memblock, user_size, align, offset);
if (retptr != NULL)
{
if (start_fill < user_size)
{
memset ((char*)retptr + start_fill, 0, user_size - start_fill);
}
}
return retptr;
}
/***
*
* void *_aligned_free_base(void *memblock)
* - Free the memory which was allocated using _aligned_malloc or
* _aligned_offset_memory
*
* Purpose:
* Frees the aligned memory block which was allocated using _aligned_malloc.
*
* Entry:
* void * memblock - pointer to the block of memory
*
* Exceptions:
* None. If memblock == NULL we simply return without doing anything.
*
*******************************************************************************/
void __cdecl _aligned_free_base(void *memblock)
{
uintptr_t ptr;
if (memblock == NULL)
return;
ptr = (uintptr_t)memblock;
/* ptr points to the pointer to starting of the memory block */
ptr = (ptr & ~(PTR_SZ -1)) - PTR_SZ;
/* ptr is the pointer to the start of memory block*/
ptr = *((uintptr_t *)ptr);
free((void *)ptr);
}

View File

@ -0,0 +1,30 @@
// ==++==
//
// Copyright (c) Microsoft Corporation. All rights reserved.
//
// ==--==
// =+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
//
// align.h
//
// Alignment / Packing definitions
//
// =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
#define WORD_ALIGN 1
#define DWORD_ALIGN 3
#define QWORD_ALIGN 7
#define DQWORD_ALIGN 15
#ifdef _WIN64
#define P2_ALIGN 15
#else // !_WIN64
#define P2_ALIGN 7
#endif // _WIN64
#define ALIGNED_SIZE(size, alignment) (((size) + (alignment)) & ~(alignment))
#ifndef SIZEOF_ARRAY
#define SIZEOF_ARRAY(x) ((sizeof(x))/(sizeof(x[0])))
#endif // SIZEOF_ARRAY

View File

@ -0,0 +1,298 @@
/****
* Copyright (C) 2007-2008 Advanced Micro Devices Inc. All rights reserved.
*
* The information and source code contained herein is the exclusive
* property of Advanced Micro Devices and may not be disclosed, examined
* or reproduced in whole or in part without explicit written authorization
* from the company.
*
* ammintrin.h - Definitions for AMD-specific intrinsics
*
****/
#pragma once
#ifndef __midl
#ifndef _INCLUDED_AMM
#define _INCLUDED_AMM
#if defined (_M_CEE_PURE)
#error ERROR: This file is not supported in the pure mode!
#else /* defined (_M_CEE_PURE) */
#if defined __cplusplus
extern "C" { /* Intrinsics use C name-mangling. */
#endif /* defined __cplusplus */
/*
* Vector integer comparison control macros
*/
#define _MM_PCOMCTRL_LT 0
#define _MM_PCOMCTRL_LE 1
#define _MM_PCOMCTRL_GT 2
#define _MM_PCOMCTRL_GE 3
#define _MM_PCOMCTRL_EQ 4
#define _MM_PCOMCTRL_NEQ 5
#define _MM_PCOMCTRL_FALSE 6
#define _MM_PCOMCTRL_TRUE 7
/*
* MACRO functions for vector integer comparisons
*/
#define _mm_comlt_epu8(v1, v2) _mm_com_epu8(v1, v2, _MM_PCOMCTRL_LT)
#define _mm_comle_epu8(v1, v2) _mm_com_epu8(v1, v2, _MM_PCOMCTRL_LE)
#define _mm_comgt_epu8(v1, v2) _mm_com_epu8(v1, v2, _MM_PCOMCTRL_GT)
#define _mm_comge_epu8(v1, v2) _mm_com_epu8(v1, v2, _MM_PCOMCTRL_GE)
#define _mm_comeq_epu8(v1, v2) _mm_com_epu8(v1, v2, _MM_PCOMCTRL_EQ)
#define _mm_comneq_epu8(v1, v2) _mm_com_epu8(v1, v2, _MM_PCOMCTRL_NEQ)
#define _mm_comfalse_epu8(v1, v2) _mm_com_epu8(v1, v2, _MM_PCOMCTRL_FALSE)
#define _mm_comtrue_epu8(v1, v2) _mm_com_epu8(v1, v2, _MM_PCOMCTRL_TRUE)
#define _mm_comlt_epu16(v1, v2) _mm_com_epu16(v1, v2, _MM_PCOMCTRL_LT)
#define _mm_comle_epu16(v1, v2) _mm_com_epu16(v1, v2, _MM_PCOMCTRL_LE)
#define _mm_comgt_epu16(v1, v2) _mm_com_epu16(v1, v2, _MM_PCOMCTRL_GT)
#define _mm_comge_epu16(v1, v2) _mm_com_epu16(v1, v2, _MM_PCOMCTRL_GE)
#define _mm_comeq_epu16(v1, v2) _mm_com_epu16(v1, v2, _MM_PCOMCTRL_EQ)
#define _mm_comneq_epu16(v1, v2) _mm_com_epu16(v1, v2, _MM_PCOMCTRL_NEQ)
#define _mm_comfalse_epu16(v1, v2) _mm_com_epu16(v1, v2, _MM_PCOMCTRL_FALSE)
#define _mm_comtrue_epu16(v1, v2) _mm_com_epu16(v1, v2, _MM_PCOMCTRL_TRUE)
#define _mm_comlt_epu32(v1, v2) _mm_com_epu32(v1, v2, _MM_PCOMCTRL_LT)
#define _mm_comle_epu32(v1, v2) _mm_com_epu32(v1, v2, _MM_PCOMCTRL_LE)
#define _mm_comgt_epu32(v1, v2) _mm_com_epu32(v1, v2, _MM_PCOMCTRL_GT)
#define _mm_comge_epu32(v1, v2) _mm_com_epu32(v1, v2, _MM_PCOMCTRL_GE)
#define _mm_comeq_epu32(v1, v2) _mm_com_epu32(v1, v2, _MM_PCOMCTRL_EQ)
#define _mm_comneq_epu32(v1, v2) _mm_com_epu32(v1, v2, _MM_PCOMCTRL_NEQ)
#define _mm_comfalse_epu32(v1, v2) _mm_com_epu32(v1, v2, _MM_PCOMCTRL_FALSE)
#define _mm_comtrue_epu32(v1, v2) _mm_com_epu32(v1, v2, _MM_PCOMCTRL_TRUE)
#define _mm_comlt_epu64(v1, v2) _mm_com_epu64(v1, v2, _MM_PCOMCTRL_LT)
#define _mm_comle_epu64(v1, v2) _mm_com_epu64(v1, v2, _MM_PCOMCTRL_LE)
#define _mm_comgt_epu64(v1, v2) _mm_com_epu64(v1, v2, _MM_PCOMCTRL_GT)
#define _mm_comge_epu64(v1, v2) _mm_com_epu64(v1, v2, _MM_PCOMCTRL_GE)
#define _mm_comeq_epu64(v1, v2) _mm_com_epu64(v1, v2, _MM_PCOMCTRL_EQ)
#define _mm_comneq_epu64(v1, v2) _mm_com_epu64(v1, v2, _MM_PCOMCTRL_NEQ)
#define _mm_comfalse_epu64(v1, v2) _mm_com_epu64(v1, v2, _MM_PCOMCTRL_FALSE)
#define _mm_comtrue_epu64(v1, v2) _mm_com_epu64(v1, v2, _MM_PCOMCTRL_TRUE)
#define _mm_comlt_epi8(v1, v2) _mm_com_epi8(v1, v2, _MM_PCOMCTRL_LT)
#define _mm_comle_epi8(v1, v2) _mm_com_epi8(v1, v2, _MM_PCOMCTRL_LE)
#define _mm_comgt_epi8(v1, v2) _mm_com_epi8(v1, v2, _MM_PCOMCTRL_GT)
#define _mm_comge_epi8(v1, v2) _mm_com_epi8(v1, v2, _MM_PCOMCTRL_GE)
#define _mm_comeq_epi8(v1, v2) _mm_com_epi8(v1, v2, _MM_PCOMCTRL_EQ)
#define _mm_comneq_epi8(v1, v2) _mm_com_epi8(v1, v2, _MM_PCOMCTRL_NEQ)
#define _mm_comfalse_epi8(v1, v2) _mm_com_epi8(v1, v2, _MM_PCOMCTRL_FALSE)
#define _mm_comtrue_epi8(v1, v2) _mm_com_epi8(v1, v2, _MM_PCOMCTRL_TRUE)
#define _mm_comlt_epi16(v1, v2) _mm_com_epi16(v1, v2, _MM_PCOMCTRL_LT)
#define _mm_comle_epi16(v1, v2) _mm_com_epi16(v1, v2, _MM_PCOMCTRL_LE)
#define _mm_comgt_epi16(v1, v2) _mm_com_epi16(v1, v2, _MM_PCOMCTRL_GT)
#define _mm_comge_epi16(v1, v2) _mm_com_epi16(v1, v2, _MM_PCOMCTRL_GE)
#define _mm_comeq_epi16(v1, v2) _mm_com_epi16(v1, v2, _MM_PCOMCTRL_EQ)
#define _mm_comneq_epi16(v1, v2) _mm_com_epi16(v1, v2, _MM_PCOMCTRL_NEQ)
#define _mm_comfalse_epi16(v1, v2) _mm_com_epi16(v1, v2, _MM_PCOMCTRL_FALSE)
#define _mm_comtrue_epi16(v1, v2) _mm_com_epi16(v1, v2, _MM_PCOMCTRL_TRUE)
#define _mm_comlt_epi32(v1, v2) _mm_com_epi32(v1, v2, _MM_PCOMCTRL_LT)
#define _mm_comle_epi32(v1, v2) _mm_com_epi32(v1, v2, _MM_PCOMCTRL_LE)
#define _mm_comgt_epi32(v1, v2) _mm_com_epi32(v1, v2, _MM_PCOMCTRL_GT)
#define _mm_comge_epi32(v1, v2) _mm_com_epi32(v1, v2, _MM_PCOMCTRL_GE)
#define _mm_comeq_epi32(v1, v2) _mm_com_epi32(v1, v2, _MM_PCOMCTRL_EQ)
#define _mm_comneq_epi32(v1, v2) _mm_com_epi32(v1, v2, _MM_PCOMCTRL_NEQ)
#define _mm_comfalse_epi32(v1, v2) _mm_com_epi32(v1, v2, _MM_PCOMCTRL_FALSE)
#define _mm_comtrue_epi32(v1, v2) _mm_com_epi32(v1, v2, _MM_PCOMCTRL_TRUE)
#define _mm_comlt_epi64(v1, v2) _mm_com_epi64(v1, v2, _MM_PCOMCTRL_LT)
#define _mm_comle_epi64(v1, v2) _mm_com_epi64(v1, v2, _MM_PCOMCTRL_LE)
#define _mm_comgt_epi64(v1, v2) _mm_com_epi64(v1, v2, _MM_PCOMCTRL_GT)
#define _mm_comge_epi64(v1, v2) _mm_com_epi64(v1, v2, _MM_PCOMCTRL_GE)
#define _mm_comeq_epi64(v1, v2) _mm_com_epi64(v1, v2, _MM_PCOMCTRL_EQ)
#define _mm_comneq_epi64(v1, v2) _mm_com_epi64(v1, v2, _MM_PCOMCTRL_NEQ)
#define _mm_comfalse_epi64(v1, v2) _mm_com_epi64(v1, v2, _MM_PCOMCTRL_FALSE)
#define _mm_comtrue_epi64(v1, v2) _mm_com_epi64(v1, v2, _MM_PCOMCTRL_TRUE)
/* SSE5 intrinsics */
/* Float/double multiply-accumulate */
__m128 _mm_macc_ps(__m128, __m128, __m128);
__m128d _mm_macc_pd(__m128d, __m128d, __m128d);
__m128 _mm_macc_ss(__m128, __m128, __m128);
__m128d _mm_macc_sd(__m128d, __m128d, __m128d);
__m128 _mm_maddsub_ps(__m128, __m128, __m128);
__m128d _mm_maddsub_pd(__m128d, __m128d, __m128d);
__m128 _mm_msubadd_ps(__m128, __m128, __m128);
__m128d _mm_msubadd_pd(__m128d, __m128d, __m128d);
__m128 _mm_msub_ps(__m128, __m128, __m128);
__m128d _mm_msub_pd(__m128d, __m128d, __m128d);
__m128 _mm_msub_ss(__m128, __m128, __m128);
__m128d _mm_msub_sd(__m128d, __m128d, __m128d);
__m128 _mm_nmacc_ps(__m128, __m128, __m128);
__m128d _mm_nmacc_pd(__m128d, __m128d, __m128d);
__m128 _mm_nmacc_ss(__m128, __m128, __m128);
__m128d _mm_nmacc_sd(__m128d, __m128d, __m128d);
__m128 _mm_nmsub_ps(__m128, __m128, __m128);
__m128d _mm_nmsub_pd(__m128d, __m128d, __m128d);
__m128 _mm_nmsub_ss(__m128, __m128, __m128);
__m128d _mm_nmsub_sd(__m128d, __m128d, __m128d);
/* Integer multiply-accumulate */
__m128i _mm_maccs_epi16(__m128i, __m128i, __m128i);
__m128i _mm_macc_epi16(__m128i, __m128i, __m128i);
__m128i _mm_maccsd_epi16(__m128i, __m128i, __m128i);
__m128i _mm_maccd_epi16(__m128i, __m128i, __m128i);
__m128i _mm_maccs_epi32(__m128i, __m128i, __m128i);
__m128i _mm_macc_epi32(__m128i, __m128i, __m128i);
__m128i _mm_maccslo_epi32(__m128i, __m128i, __m128i);
__m128i _mm_macclo_epi32(__m128i, __m128i, __m128i);
__m128i _mm_maccshi_epi32(__m128i, __m128i, __m128i);
__m128i _mm_macchi_epi32(__m128i, __m128i, __m128i);
__m128i _mm_maddsd_epi16(__m128i, __m128i, __m128i);
__m128i _mm_maddd_epi16(__m128i, __m128i, __m128i);
/* Horizontal add/subtract */
__m128i _mm_haddw_epi8(__m128i);
__m128i _mm_haddd_epi8(__m128i);
__m128i _mm_haddq_epi8(__m128i);
__m128i _mm_haddd_epi16(__m128i);
__m128i _mm_haddq_epi16(__m128i);
__m128i _mm_haddq_epi32(__m128i);
__m128i _mm_haddw_epu8(__m128i);
__m128i _mm_haddd_epu8(__m128i);
__m128i _mm_haddq_epu8(__m128i);
__m128i _mm_haddd_epu16(__m128i);
__m128i _mm_haddq_epu16(__m128i);
__m128i _mm_haddq_epu32(__m128i);
__m128i _mm_hsubw_epi8(__m128i);
__m128i _mm_hsubd_epi16(__m128i);
__m128i _mm_hsubq_epi32(__m128i);
/* Vector conditional moves */
__m128i _mm_cmov_si128(__m128i, __m128i, __m128i);
__m128i _mm_perm_epi8(__m128i, __m128i, __m128i);
/* Vector shifts and rotates */
__m128i _mm_rot_epi8(__m128i, __m128i);
__m128i _mm_rot_epi16(__m128i, __m128i);
__m128i _mm_rot_epi32(__m128i, __m128i);
__m128i _mm_rot_epi64(__m128i, __m128i);
__m128i _mm_roti_epi8(__m128i, int);
__m128i _mm_roti_epi16(__m128i, int);
__m128i _mm_roti_epi32(__m128i, int);
__m128i _mm_roti_epi64(__m128i, int);
__m128i _mm_shl_epi8(__m128i, __m128i);
__m128i _mm_shl_epi16(__m128i, __m128i);
__m128i _mm_shl_epi32(__m128i, __m128i);
__m128i _mm_shl_epi64(__m128i, __m128i);
__m128i _mm_sha_epi8(__m128i, __m128i);
__m128i _mm_sha_epi16(__m128i, __m128i);
__m128i _mm_sha_epi32(__m128i, __m128i);
__m128i _mm_sha_epi64(__m128i, __m128i);
/* Vector integer comparisons */
__m128i _mm_com_epu8(__m128i, __m128i, int);
__m128i _mm_com_epu16(__m128i, __m128i, int);
__m128i _mm_com_epu32(__m128i, __m128i, int);
__m128i _mm_com_epu64(__m128i, __m128i, int);
__m128i _mm_com_epi8(__m128i, __m128i, int);
__m128i _mm_com_epi16(__m128i, __m128i, int);
__m128i _mm_com_epi32(__m128i, __m128i, int);
__m128i _mm_com_epi64(__m128i, __m128i, int);
/* Precision control */
__m128 _mm_frcz_ps(__m128);
__m128d _mm_frcz_pd(__m128d);
__m128 _mm_frcz_ss(__m128, __m128);
__m128d _mm_frcz_sd(__m128d, __m128d);
/* Control values for permute2 intrinsics */
#define _MM_PERMUTE2_COPY 0 /* just copy the selected value */
/* Note that using the constant 1 would have the same effect as 0 */
#define _MM_PERMUTE2_ZEROIF1 2 /* zero selected value if src3 bit is 1 */
#define _MM_PERMUTE2_ZEROIF0 3 /* zero selected value if src3 bit is 3 */
/* Permutation */
__m128 _mm_permute2_ps(__m128, __m128, __m128i, int);
__m128d _mm_permute2_pd(__m128d, __m128d, __m128i, int);
/* YMM versions */
__m256 _mm256_macc_ps(__m256, __m256, __m256);
__m256d _mm256_macc_pd(__m256d, __m256d, __m256d);
__m256 _mm256_maddsub_ps(__m256, __m256, __m256);
__m256d _mm256_maddsub_pd(__m256d, __m256d, __m256d);
__m256 _mm256_msubadd_ps(__m256, __m256, __m256);
__m256d _mm256_msubadd_pd(__m256d, __m256d, __m256d);
__m256 _mm256_msub_ps(__m256, __m256, __m256);
__m256d _mm256_msub_pd(__m256d, __m256d, __m256d);
__m256 _mm256_nmacc_ps(__m256, __m256, __m256);
__m256d _mm256_nmacc_pd(__m256d, __m256d, __m256d);
__m256 _mm256_nmsub_ps(__m256, __m256, __m256);
__m256d _mm256_nmsub_pd(__m256d, __m256d, __m256d);
__m256i _mm256_cmov_si256(__m256i, __m256i, __m256i);
__m256 _mm256_frcz_ps(__m256);
__m256d _mm256_frcz_pd(__m256d);
__m256 _mm256_permute2_ps(__m256, __m256, __m256i, int);
__m256d _mm256_permute2_pd(__m256d, __m256d, __m256i, int);
/* LWP intrinsics */
void __llwpcb(void *);
void *__slwpcb();
void __lwpval32(unsigned int, unsigned int, unsigned int);
unsigned char __lwpins32(unsigned int, unsigned int, unsigned int);
#if defined (_M_X64)
void __lwpval64(unsigned __int64, unsigned int, unsigned int);
unsigned char __lwpins64(unsigned __int64, unsigned int, unsigned int);
#endif /* defined (_M_X64) */
/*BMI intrinsics */
unsigned int _bextr_u32(unsigned int, unsigned int, unsigned int);
unsigned int _andn_u32(unsigned int, unsigned int);
unsigned int _tzcnt_u32(unsigned int);
unsigned int _lzcnt_u32(unsigned int);
unsigned int _blsr_u32(unsigned int);
unsigned int _blsmsk_u32(unsigned int);
unsigned int _blsi_u32(unsigned int);
#if defined (_M_X64)
unsigned __int64 _bextr_u64(unsigned __int64, unsigned int, unsigned int);
unsigned __int64 _andn_u64(unsigned __int64, unsigned __int64);
unsigned __int64 _tzcnt_u64(unsigned __int64);
unsigned __int64 _lzcnt_u64(unsigned __int64);
unsigned __int64 _blsr_u64(unsigned __int64);
unsigned __int64 _blsmsk_u64(unsigned __int64);
unsigned __int64 _blsi_u64(unsigned __int64);
#endif /* defined (_M_X64) */
/* TBM intrinsics */
unsigned int _bextri_u32(unsigned int, unsigned int);
unsigned int _blcfill_u32(unsigned int);
unsigned int _blsfill_u32(unsigned int);
unsigned int _blcs_u32(unsigned int);
unsigned int _tzmsk_u32(unsigned int);
unsigned int _blcic_u32(unsigned int);
unsigned int _blsic_u32(unsigned int);
unsigned int _t1mskc_u32(unsigned int);
unsigned int _blcmsk_u32(unsigned int);
unsigned int _blci_u32(unsigned int);
#if defined (_M_X64)
unsigned __int64 _bextri_u64(unsigned __int64, unsigned int);
unsigned __int64 _blcfill_u64(unsigned __int64);
unsigned __int64 _blsfill_u64(unsigned __int64);
unsigned __int64 _blcs_u64(unsigned __int64);
unsigned __int64 _tzmsk_u64(unsigned __int64);
unsigned __int64 _blcic_u64(unsigned __int64);
unsigned __int64 _blsic_u64(unsigned __int64);
unsigned __int64 _t1mskc_u64(unsigned __int64);
unsigned __int64 _blcmsk_u64(unsigned __int64);
unsigned __int64 _blci_u64(unsigned __int64);
#endif /* defined (_M_X64) */
#if defined __cplusplus
}; /* End "C" */
#endif /* defined __cplusplus */
#endif /* defined (_M_CEE_PURE) */
#endif /* _INCLUDED_AMM */
#endif /* __midl */

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

Some files were not shown because too many files have changed in this diff Show More