|
|
@@ -7,6 +7,10 @@ |
|
|
|
#define ALLOCATION_CHUNK (1024UL) |
|
|
|
#define ALLOCATION_LIMIT (1024UL * 1024UL) |
|
|
|
|
|
|
|
#ifndef PROGN |
|
|
|
# define PROGN "hl" |
|
|
|
#endif |
|
|
|
|
|
|
|
enum { NORMAL, BOLD, DARKNESS, ITALIC, UNDERLINE, BLINK, DUNNO_6, REVERSE, INVISIBLE }; |
|
|
|
enum { GREY, RED, GREEN, YELLOW, BLUE, PINK, CYAN, WHITE, CANCEL }; |
|
|
|
|
|
|
@@ -30,281 +34,356 @@ static int effect_keyword = BOLD; |
|
|
|
static int effect_preprocessor = BOLD; |
|
|
|
static int effect_default = BOLD; |
|
|
|
|
|
|
|
static char * buffer = NULL; |
|
|
|
|
|
|
|
static unsigned long int buffer_size = 0; |
|
|
|
|
|
|
|
static void render_character ( |
|
|
|
char character |
|
|
|
char character |
|
|
|
) { |
|
|
|
putchar (character); |
|
|
|
putchar (character); |
|
|
|
} |
|
|
|
|
|
|
|
static void render_string ( |
|
|
|
char * string |
|
|
|
char * string |
|
|
|
) { |
|
|
|
while (* string) render_character (* string++); |
|
|
|
while (* string) render_character (* string++); |
|
|
|
} |
|
|
|
|
|
|
|
static void render_colour ( |
|
|
|
int colour, |
|
|
|
int effect |
|
|
|
int colour, |
|
|
|
int effect |
|
|
|
) { |
|
|
|
if (colour == CANCEL) { |
|
|
|
render_string ("\033[0m"); |
|
|
|
return; |
|
|
|
} |
|
|
|
|
|
|
|
render_string ("\033["); |
|
|
|
render_character ((char) (effect % 9) + '0'); |
|
|
|
render_string (";3"); |
|
|
|
render_character ((char) (colour % 8) + '0'); |
|
|
|
render_character ('m'); |
|
|
|
if (colour == CANCEL) { |
|
|
|
render_string ("\033[0m"); |
|
|
|
return; |
|
|
|
} |
|
|
|
|
|
|
|
render_string ("\033["); |
|
|
|
render_character ((char) (effect % 9) + '0'); |
|
|
|
render_string (";3"); |
|
|
|
render_character ((char) (colour % 8) + '0'); |
|
|
|
render_character ('m'); |
|
|
|
} |
|
|
|
|
|
|
|
static int is_space ( |
|
|
|
char character |
|
|
|
char character |
|
|
|
) { |
|
|
|
if ((character == ' ') || (character == '\t') || (character == '\r') || (character == '\n')) { |
|
|
|
return (1); |
|
|
|
} else { |
|
|
|
return (0); |
|
|
|
} |
|
|
|
switch (character) |
|
|
|
{ |
|
|
|
case ' ': case '\t': case '\r': case '\n': |
|
|
|
return (1); |
|
|
|
default: |
|
|
|
return (0); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
static int is_separator ( |
|
|
|
char character |
|
|
|
char character |
|
|
|
) { |
|
|
|
if ((character == ' ') || (character == '\t') || (character == '\r') || (character == '\n') || |
|
|
|
(character == '+') || (character == '-') || (character == '*') || (character == '/') || |
|
|
|
(character == '(') || (character == ')') || (character == '[') || (character == ']') || |
|
|
|
(character == '{') || (character == '}') || (character == '<') || (character == '>') || |
|
|
|
(character == ';') || (character == ':') || (character == ',') || (character == '.') || |
|
|
|
(character == '!') || (character == '&') || (character == '|') || (character == '?') || |
|
|
|
(character == '~') || (character == '^') || (character == '%') || (character == '=')) { |
|
|
|
return (1); |
|
|
|
} else { |
|
|
|
return (0); |
|
|
|
} |
|
|
|
switch (character) |
|
|
|
{ |
|
|
|
case ' ': case '\t': case '\r': case '\n': |
|
|
|
case '+': case '-': case '*': case '/': |
|
|
|
case '(': case ')': case '[': case ']': |
|
|
|
case '{': case '}': case '<': case '>': |
|
|
|
case ';': case ':': case ',': case '.': |
|
|
|
case '!': case '&': case '|': case '?': |
|
|
|
case '~': case '^': case '%': case '=': |
|
|
|
return (1); |
|
|
|
default: |
|
|
|
return (0); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
static int compare_multiple_strings ( |
|
|
|
char * string, |
|
|
|
const char * * strings, |
|
|
|
const int count |
|
|
|
char * string, |
|
|
|
const char ** strings, |
|
|
|
const int count |
|
|
|
) { |
|
|
|
int i = 0; |
|
|
|
int i = 0; |
|
|
|
|
|
|
|
do { |
|
|
|
if (strcmp (string, strings [i]) == 0) { |
|
|
|
return (1); |
|
|
|
} |
|
|
|
++i; |
|
|
|
} while (i != count); |
|
|
|
do { |
|
|
|
if (strcmp (string, strings [i]) == 0) { |
|
|
|
return (1); |
|
|
|
} |
|
|
|
++i; |
|
|
|
} while (i != count); |
|
|
|
|
|
|
|
return (0); |
|
|
|
return (0); |
|
|
|
} |
|
|
|
|
|
|
|
static int render_short_comment ( |
|
|
|
int data_offset |
|
|
|
char * buffer, |
|
|
|
int data_offset |
|
|
|
) { |
|
|
|
render_colour (colour_short_comment, effect_short_comment); |
|
|
|
render_colour (colour_short_comment, effect_short_comment); |
|
|
|
|
|
|
|
do { |
|
|
|
render_character (buffer [data_offset]); |
|
|
|
++data_offset; |
|
|
|
} while ((buffer [data_offset] != '\n') && (buffer [data_offset] != '\0')); |
|
|
|
do { |
|
|
|
render_character (buffer [data_offset]); |
|
|
|
++data_offset; |
|
|
|
} while ((buffer [data_offset] != '\n') && (buffer [data_offset] != '\0')); |
|
|
|
|
|
|
|
render_character (buffer [data_offset]); |
|
|
|
++data_offset; |
|
|
|
render_character (buffer [data_offset]); |
|
|
|
++data_offset; |
|
|
|
|
|
|
|
return (data_offset); |
|
|
|
return (data_offset); |
|
|
|
} |
|
|
|
|
|
|
|
static int render_long_comment ( |
|
|
|
int data_offset |
|
|
|
char * buffer, |
|
|
|
int data_offset |
|
|
|
) { |
|
|
|
render_colour (colour_long_comment, effect_long_comment); |
|
|
|
render_colour (colour_long_comment, effect_long_comment); |
|
|
|
|
|
|
|
do { |
|
|
|
render_character (buffer [data_offset]); |
|
|
|
++data_offset; |
|
|
|
} while (((buffer [data_offset] != '/') || |
|
|
|
(buffer [data_offset - 1] != '*')) && |
|
|
|
(buffer [data_offset] != '\0')); |
|
|
|
do { |
|
|
|
render_character (buffer [data_offset]); |
|
|
|
++data_offset; |
|
|
|
} while (((buffer [data_offset] != '/') || |
|
|
|
(buffer [data_offset - 1] != '*')) && |
|
|
|
(buffer [data_offset] != '\0')); |
|
|
|
|
|
|
|
render_character (buffer [data_offset]); |
|
|
|
++data_offset; |
|
|
|
render_character (buffer [data_offset]); |
|
|
|
++data_offset; |
|
|
|
|
|
|
|
return (data_offset); |
|
|
|
return (data_offset); |
|
|
|
} |
|
|
|
|
|
|
|
static int render_short_string ( |
|
|
|
int data_offset |
|
|
|
char * buffer, |
|
|
|
int data_offset |
|
|
|
) { |
|
|
|
render_colour (colour_short_string, effect_short_string); |
|
|
|
render_colour (colour_short_string, effect_short_string); |
|
|
|
|
|
|
|
do { |
|
|
|
render_character (buffer [data_offset]); |
|
|
|
++data_offset; |
|
|
|
if (buffer [data_offset - 1] == '\\') { |
|
|
|
render_character (buffer [data_offset]); |
|
|
|
++data_offset; |
|
|
|
} |
|
|
|
} while ((buffer [data_offset] != '\'') && (buffer [data_offset] != '\0')); |
|
|
|
do { |
|
|
|
render_character (buffer [data_offset]); |
|
|
|
++data_offset; |
|
|
|
if (buffer [data_offset - 1] == '\\') { |
|
|
|
render_character (buffer [data_offset]); |
|
|
|
++data_offset; |
|
|
|
} |
|
|
|
} while ((buffer [data_offset] != '\'') && (buffer [data_offset] != '\0')); |
|
|
|
|
|
|
|
render_character (buffer [data_offset]); |
|
|
|
++data_offset; |
|
|
|
render_character (buffer [data_offset]); |
|
|
|
++data_offset; |
|
|
|
|
|
|
|
return (data_offset); |
|
|
|
return (data_offset); |
|
|
|
} |
|
|
|
|
|
|
|
static int render_long_string ( |
|
|
|
int data_offset |
|
|
|
char * buffer, |
|
|
|
int data_offset |
|
|
|
) { |
|
|
|
render_colour (colour_long_string, effect_long_string); |
|
|
|
render_colour (colour_long_string, effect_long_string); |
|
|
|
|
|
|
|
do { |
|
|
|
render_character (buffer [data_offset]); |
|
|
|
++data_offset; |
|
|
|
if (buffer [data_offset - 1] == '\\') { |
|
|
|
render_character (buffer [data_offset]); |
|
|
|
++data_offset; |
|
|
|
} |
|
|
|
} while ((buffer [data_offset] != '"') && (buffer [data_offset] != '\0')); |
|
|
|
do { |
|
|
|
render_character (buffer [data_offset]); |
|
|
|
++data_offset; |
|
|
|
if (buffer [data_offset - 1] == '\\') { |
|
|
|
render_character (buffer [data_offset]); |
|
|
|
++data_offset; |
|
|
|
} |
|
|
|
} while ((buffer [data_offset] != '"') && (buffer [data_offset] != '\0')); |
|
|
|
|
|
|
|
render_character (buffer [data_offset]); |
|
|
|
++data_offset; |
|
|
|
render_character (buffer [data_offset]); |
|
|
|
++data_offset; |
|
|
|
|
|
|
|
return (data_offset); |
|
|
|
return (data_offset); |
|
|
|
} |
|
|
|
|
|
|
|
static int render_separator ( |
|
|
|
int data_offset |
|
|
|
char * buffer, |
|
|
|
int data_offset |
|
|
|
) { |
|
|
|
if (is_space (buffer [data_offset]) != 0) { |
|
|
|
render_colour (WHITE, NORMAL); |
|
|
|
} else { |
|
|
|
render_colour (colour_separator, effect_separator); |
|
|
|
} |
|
|
|
if (is_space (buffer [data_offset]) != 0) { |
|
|
|
render_colour (WHITE, NORMAL); |
|
|
|
} else { |
|
|
|
render_colour (colour_separator, effect_separator); |
|
|
|
} |
|
|
|
|
|
|
|
render_character (buffer [data_offset]); |
|
|
|
++data_offset; |
|
|
|
render_character (buffer [data_offset]); |
|
|
|
++data_offset; |
|
|
|
|
|
|
|
return (data_offset); |
|
|
|
return (data_offset); |
|
|
|
} |
|
|
|
|
|
|
|
static int render_number ( |
|
|
|
int data_offset |
|
|
|
char * buffer, |
|
|
|
int data_offset |
|
|
|
) { |
|
|
|
render_colour (colour_number, effect_number); |
|
|
|
render_colour (colour_number, effect_number); |
|
|
|
|
|
|
|
do { |
|
|
|
render_character (buffer [data_offset]); |
|
|
|
++data_offset; |
|
|
|
} while ((is_separator (buffer [data_offset]) == 0) && (buffer [data_offset] != '\0')); |
|
|
|
do { |
|
|
|
render_character (buffer [data_offset]); |
|
|
|
++data_offset; |
|
|
|
} while ((is_separator (buffer [data_offset]) == 0) && (buffer [data_offset] != '\0')); |
|
|
|
|
|
|
|
return (data_offset); |
|
|
|
return (data_offset); |
|
|
|
} |
|
|
|
|
|
|
|
static int render_word ( |
|
|
|
int data_offset |
|
|
|
char * buffer, |
|
|
|
int data_offset |
|
|
|
) { |
|
|
|
const char * c_keywords [32] = { |
|
|
|
"register", "volatile", "auto", "const", "static", "extern", "if", "else", |
|
|
|
"do", "while", "for", "continue", "switch", "case", "default", "break", |
|
|
|
"enum", "union", "struct", "typedef", "goto", "void", "return", "sizeof", |
|
|
|
"char", "short", "int", "long", "signed", "unsigned", "float", "double" |
|
|
|
}; |
|
|
|
|
|
|
|
const char * preprocessor_keywords [16] = { |
|
|
|
"#include", "#pragma", "#define", "#undef", "#ifdef", "#ifndef", "#elifdef", "#elifndef", |
|
|
|
"#if", "#elif", "#else", "#endif", "#embed", "#line", "#error", "#warning" |
|
|
|
}; |
|
|
|
|
|
|
|
char * word = NULL; |
|
|
|
|
|
|
|
int i = 0; |
|
|
|
|
|
|
|
do { |
|
|
|
word = realloc (word, sizeof (* word) * (unsigned long int) (i + 1)); |
|
|
|
word [i] = buffer [data_offset + i]; |
|
|
|
++i; |
|
|
|
} while ((is_separator (buffer [data_offset + i]) == 0) && (buffer [data_offset + i] != '\0')); |
|
|
|
|
|
|
|
word = realloc (word, sizeof (* word) * (unsigned long int) (i + 1)); |
|
|
|
word [i] = '\0'; |
|
|
|
|
|
|
|
if (compare_multiple_strings (word, c_keywords, 32) != 0) { |
|
|
|
render_colour (colour_keyword, effect_keyword); |
|
|
|
} else if (compare_multiple_strings (word, preprocessor_keywords, 16) != 0) { |
|
|
|
render_colour (colour_preprocessor, effect_preprocessor); |
|
|
|
} else { |
|
|
|
render_colour (colour_default, effect_default); |
|
|
|
} |
|
|
|
|
|
|
|
do { |
|
|
|
render_character (buffer [data_offset]); |
|
|
|
++data_offset; |
|
|
|
} while ((is_separator (buffer [data_offset]) == 0) && (buffer [data_offset] != '\0')); |
|
|
|
|
|
|
|
free (word); |
|
|
|
|
|
|
|
return (data_offset); |
|
|
|
} |
|
|
|
|
|
|
|
void |
|
|
|
handle_buffer( |
|
|
|
char * buffer |
|
|
|
) { |
|
|
|
const char * c_keywords [32] = { |
|
|
|
"register", "volatile", "auto", "const", "static", "extern", "if", "else", |
|
|
|
"do", "while", "for", "continue", "switch", "case", "default", "break", |
|
|
|
"enum", "union", "struct", "typedef", "goto", "void", "return", "sizeof", |
|
|
|
"char", "short", "int", "long", "signed", "unsigned", "float", "double" |
|
|
|
}; |
|
|
|
|
|
|
|
const char * preprocessor_keywords [16] = { |
|
|
|
"#include", "#pragma", "#define", "#undef", "#ifdef", "#ifndef", "#elifdef", "#elifndef", |
|
|
|
"#if", "#elif", "#else", "#endif", "#embed", "#line", "#error", "#warning" |
|
|
|
}; |
|
|
|
|
|
|
|
char * word = NULL; |
|
|
|
|
|
|
|
int i = 0; |
|
|
|
|
|
|
|
do { |
|
|
|
word = realloc (word, sizeof (* word) * (unsigned long int) (i + 1)); |
|
|
|
word [i] = buffer [data_offset + i]; |
|
|
|
++i; |
|
|
|
} while ((is_separator (buffer [data_offset + i]) == 0) && (buffer [data_offset + i] != '\0')); |
|
|
|
|
|
|
|
word = realloc (word, sizeof (* word) * (unsigned long int) (i + 1)); |
|
|
|
word [i] = '\0'; |
|
|
|
|
|
|
|
if (compare_multiple_strings (word, c_keywords, 32) != 0) { |
|
|
|
render_colour (colour_keyword, effect_keyword); |
|
|
|
} else if (compare_multiple_strings (word, preprocessor_keywords, 16) != 0) { |
|
|
|
render_colour (colour_preprocessor, effect_preprocessor); |
|
|
|
} else { |
|
|
|
render_colour (colour_default, effect_default); |
|
|
|
} |
|
|
|
|
|
|
|
do { |
|
|
|
render_character (buffer [data_offset]); |
|
|
|
++data_offset; |
|
|
|
} while ((is_separator (buffer [data_offset]) == 0) && (buffer [data_offset] != '\0')); |
|
|
|
|
|
|
|
free (word); |
|
|
|
|
|
|
|
return (data_offset); |
|
|
|
int offset = 0; |
|
|
|
while (buffer [offset] != '\0') { |
|
|
|
if ((buffer [offset] == '/') && (buffer [offset + 1] == '/')) { |
|
|
|
offset = render_short_comment (buffer, offset); |
|
|
|
} else if ((buffer [offset] == '/') && (buffer [offset + 1] == '*')) { |
|
|
|
offset = render_long_comment (buffer, offset); |
|
|
|
} else if (buffer [offset] == '\'') { |
|
|
|
offset = render_short_string (buffer, offset); |
|
|
|
} else if (buffer [offset] == '"') { |
|
|
|
offset = render_long_string (buffer, offset); |
|
|
|
} else if (is_separator (buffer [offset]) != 0) { |
|
|
|
offset = render_separator (buffer, offset); |
|
|
|
} else if ((buffer [offset] >= '0') && (buffer [offset] <= '9')) { |
|
|
|
offset = render_number (buffer, offset); |
|
|
|
} else { |
|
|
|
offset = render_word (buffer, offset); |
|
|
|
} |
|
|
|
render_colour (CANCEL, NORMAL); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
static char * |
|
|
|
slurp(const char * fn) |
|
|
|
{ |
|
|
|
size_t len; |
|
|
|
char * b; |
|
|
|
FILE * fp = fopen(fn, "r"); |
|
|
|
if (fp) |
|
|
|
{ |
|
|
|
fseek(fp, 0, SEEK_END); |
|
|
|
len = ftell(fp); |
|
|
|
rewind(fp); |
|
|
|
b = malloc(len); |
|
|
|
if (b && |
|
|
|
len != fread(b, 1, len, fp)) |
|
|
|
{ perror(PROGN); } |
|
|
|
fclose(fp); |
|
|
|
return b; |
|
|
|
} |
|
|
|
else |
|
|
|
{ return NULL; } |
|
|
|
} |
|
|
|
|
|
|
|
#define OPT(c,s) \ |
|
|
|
if ((c == argv[0][0] && argv[0][1] == '\0') || \ |
|
|
|
0 == strncmp(argv[0], s, strlen(s))) |
|
|
|
|
|
|
|
#define SOPT(s) \ |
|
|
|
if (0 == strncmp(argv[0], s, strlen(s))) |
|
|
|
|
|
|
|
/* |
|
|
|
Valgrind: Depends on uninitialized value (buffer [0])...? |
|
|
|
280 : } while ((buffer [buffer_size - 1] != '\0') || (buffer_size != ALLOCATION_LIMIT)); |
|
|
|
285 : while (buffer [offset] != '\0') { |
|
|
|
*/ |
|
|
|
int main ( |
|
|
|
int argc, |
|
|
|
char * * argv |
|
|
|
int argc, |
|
|
|
char ** argv |
|
|
|
) { |
|
|
|
int offset = 0; |
|
|
|
|
|
|
|
if (argc != 1) { |
|
|
|
(void) argv; |
|
|
|
puts ("ARGUMENTS \"Heyo world!\""); |
|
|
|
return (-1); |
|
|
|
} |
|
|
|
|
|
|
|
buffer = realloc (buffer, ALLOCATION_CHUNK); |
|
|
|
|
|
|
|
do { |
|
|
|
if ((buffer_size + 1) % ALLOCATION_CHUNK == 0) { |
|
|
|
buffer = realloc (buffer, ((buffer_size + 1) / ALLOCATION_CHUNK + 1) * ALLOCATION_CHUNK); |
|
|
|
} |
|
|
|
buffer [buffer_size] = '\0'; /* Fixing Valgrind warnings... */ |
|
|
|
read (STDIN_FILENO, & buffer [buffer_size], sizeof (* buffer)); |
|
|
|
++buffer_size; |
|
|
|
} while ((buffer [buffer_size - 1] != '\0') /*|| (buffer_size != ALLOCATION_LIMIT)*/); |
|
|
|
|
|
|
|
buffer [buffer_size - 1] = '\0'; |
|
|
|
|
|
|
|
/* Checking if long comments work... */ |
|
|
|
// Checking if short comments work... |
|
|
|
|
|
|
|
while (buffer [offset] != '\0') { |
|
|
|
if ((buffer [offset] == '/') && (buffer [offset + 1] == '/')) { |
|
|
|
offset = render_short_comment (offset); |
|
|
|
} else if ((buffer [offset] == '/') && (buffer [offset + 1] == '*')) { |
|
|
|
offset = render_long_comment (offset); |
|
|
|
} else if (buffer [offset] == '\'') { |
|
|
|
offset = render_short_string (offset); |
|
|
|
} else if (buffer [offset] == '"') { |
|
|
|
offset = render_long_string (offset); |
|
|
|
} else if (is_separator (buffer [offset]) != 0) { |
|
|
|
offset = render_separator (offset); |
|
|
|
} else if ((buffer [offset] >= '0') && (buffer [offset] <= '9')) { |
|
|
|
offset = render_number (offset); |
|
|
|
} else { |
|
|
|
offset = render_word (offset); |
|
|
|
} |
|
|
|
render_colour (CANCEL, NORMAL); |
|
|
|
} |
|
|
|
|
|
|
|
free (buffer); |
|
|
|
|
|
|
|
return (0); |
|
|
|
char * buffer = NULL; |
|
|
|
|
|
|
|
if (argc != 1) { |
|
|
|
(void) argv; |
|
|
|
while (++argv, --argc) { |
|
|
|
if (argv[0][0] == '-') { |
|
|
|
argv[0]++; |
|
|
|
OPT ('?',"help") { |
|
|
|
fprintf (stderr, PROGN ": ... | hl [OPTIONS] FILES ...\n"); |
|
|
|
return (0); |
|
|
|
} |
|
|
|
SOPT ("version") { |
|
|
|
fprintf(stderr, PROGN ": Version 9000\n"); |
|
|
|
return (0); |
|
|
|
} |
|
|
|
else { |
|
|
|
fprintf (stderr, PROGN ": Unrecognized option '%s'\n", argv [0]); |
|
|
|
return (1); |
|
|
|
} |
|
|
|
} else { |
|
|
|
if ((buffer = slurp (argv [0]))) { |
|
|
|
handle_buffer (buffer); |
|
|
|
free (buffer); |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
buffer = realloc (buffer, ALLOCATION_CHUNK); |
|
|
|
|
|
|
|
#define MEMFAIL(v) if (v == NULL) { perror(PROGN); return (1); } |
|
|
|
MEMFAIL(buffer); |
|
|
|
|
|
|
|
do { |
|
|
|
if ((buffer_size + 1) % ALLOCATION_CHUNK == 0) { |
|
|
|
buffer = realloc (buffer, |
|
|
|
((buffer_size + 1) |
|
|
|
/ ALLOCATION_CHUNK + 1) |
|
|
|
* ALLOCATION_CHUNK); |
|
|
|
MEMFAIL(buffer); |
|
|
|
} |
|
|
|
buffer [buffer_size] = '\0'; /* Fixing Valgrind warnings... */ |
|
|
|
read (STDIN_FILENO, & buffer [buffer_size], sizeof (* buffer)); |
|
|
|
++buffer_size; |
|
|
|
} while ((buffer [buffer_size - 1] != '\0') /*|| |
|
|
|
(buffer_size != ALLOCATION_LIMIT)*/); |
|
|
|
|
|
|
|
buffer [buffer_size - 1] = '\0'; |
|
|
|
|
|
|
|
// Checking if short comments work... |
|
|
|
/* Checking if long comments work... */ |
|
|
|
|
|
|
|
handle_buffer(buffer); |
|
|
|
|
|
|
|
free (buffer); |
|
|
|
|
|
|
|
return (0); |
|
|
|
} |