when not providing an --input or --output, stdin and stdout are used. Also the c2html function outputs the length of the string
This commit is contained in:
@@ -46,7 +46,7 @@ You can highlight your C files by doing
|
||||
```sh
|
||||
c2html --input file.c --output file.html
|
||||
```
|
||||
which will read `file.c` and generate `file.html`. To know more, you can always run `c2html --help`.
|
||||
which will read `file.c` and generate `file.html`. To know more, you can always run `c2html --help`. If the input and/or the output aren't provided, then `stdin` and `stdout` are used.
|
||||
|
||||
### --style
|
||||
The HTML comes with no styling. If you want to apply a CSS to it, you can provide to `c2html` a style file using the `--style` option followed by the name of the file.
|
||||
@@ -67,9 +67,8 @@ in which case, identifiers will be generated with the `myprefix-identifier` clas
|
||||
## Using the library
|
||||
The library only exports one function
|
||||
```c
|
||||
char *c2html(const char *str, long len,
|
||||
const char *prefix, const char **error);
|
||||
|
||||
char *c2html(const char *str, long len, const char *prefix,
|
||||
long *output_len, const char **error)
|
||||
```
|
||||
Given a string containing C code, returns the highlighted version using HTML `<span>` tags. (You can find a complete description of what it does in `c2html.h`)
|
||||
|
||||
@@ -88,14 +87,14 @@ int main()
|
||||
" return 0;\n"
|
||||
"}\n";
|
||||
|
||||
char *html = c2html(c, strlen(c), prefix, NULL);
|
||||
char *html = c2html(c, -1, prefix, NULL, NULL);
|
||||
printf("%s\n", html);
|
||||
free(html);
|
||||
return 0;
|
||||
}
|
||||
```
|
||||
when executed, the output will be:
|
||||
```
|
||||
```html
|
||||
<div class="code">
|
||||
<div class="code-inner">
|
||||
<table>
|
||||
|
||||
@@ -487,8 +487,8 @@ static void print_escaped(buff_t *buff, const char *str, long len)
|
||||
}
|
||||
}
|
||||
|
||||
char *c2html(const char *str, long len,
|
||||
const char *prefix, const char **error)
|
||||
char *c2html(const char *str, long len, const char *prefix,
|
||||
long *output_len, const char **error)
|
||||
{
|
||||
if(str == NULL)
|
||||
str = "";
|
||||
@@ -639,6 +639,9 @@ char *c2html(const char *str, long len,
|
||||
res = NULL;
|
||||
}
|
||||
|
||||
if(output_len != NULL)
|
||||
*output_len = buff.used;
|
||||
|
||||
free(tokens);
|
||||
return res;
|
||||
}
|
||||
@@ -1,6 +1,8 @@
|
||||
/* Takes as input a string of C code [str] of length
|
||||
* [len] and returns the same C code but annotated
|
||||
* with HTML tags. The returned string must be freed
|
||||
* with HTML tags. The returned string's length is
|
||||
* returned through the [output_len] optional output
|
||||
* parameter. The returned pointer must be freed
|
||||
* using [free]. The class names of each tag are
|
||||
* prefixed with the value provided through [prefix].
|
||||
* If [prefix] is NULL, then no prefix is used.
|
||||
@@ -19,5 +21,5 @@
|
||||
* to be zero-terminated and it's length is calculated
|
||||
* using [strlen].
|
||||
*/
|
||||
char *c2html(const char *str, long len,
|
||||
const char *prefix, const char **error);
|
||||
char *c2html(const char *str, long len, const char *prefix,
|
||||
long *output_len, const char **error);
|
||||
|
||||
@@ -37,68 +37,89 @@ char *timed_c2html(const char *str, long len,
|
||||
#define c2html timed_c2html
|
||||
#endif
|
||||
|
||||
static char *load_from_stream(FILE *fp, long *out_size, const char **err)
|
||||
{
|
||||
char *data = NULL;
|
||||
long capacity = 1 << 11;
|
||||
long size = 0;
|
||||
|
||||
while(1) {
|
||||
|
||||
capacity *= 2;
|
||||
if((long) capacity < 0) {
|
||||
|
||||
if(err)
|
||||
*err = "Too big";
|
||||
|
||||
free(data);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void *temp = realloc(data, capacity);
|
||||
if(temp == NULL) {
|
||||
if(err)
|
||||
*err = "No memory";
|
||||
free(data);
|
||||
return NULL;
|
||||
}
|
||||
data = temp;
|
||||
|
||||
long unused = capacity - size - 1; // Spare one byte for NULL termination.
|
||||
long num = fread(data + size, 1, unused, fp);
|
||||
size += num;
|
||||
|
||||
if(num < unused) {
|
||||
// Either something went wrong or
|
||||
// we're done copying.
|
||||
if(ferror(fp)) {
|
||||
if(err)
|
||||
*err = "Unknown read error";
|
||||
free(data);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
data[size] = '\0';
|
||||
|
||||
if(out_size)
|
||||
*out_size = size;
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
static char *load_file(const char *file, long *size)
|
||||
{
|
||||
FILE *fp = fopen(file, "rb");
|
||||
if(fp == NULL)
|
||||
return NULL;
|
||||
|
||||
fseek(fp, 0, SEEK_END);
|
||||
long size2 = ftell(fp);
|
||||
fseek(fp, 0, SEEK_SET);
|
||||
|
||||
char *data = malloc(size2+1);
|
||||
if(data == NULL) {
|
||||
fclose(fp);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
fread(data, 1, size2, fp);
|
||||
char *data = load_from_stream(fp, size, NULL);
|
||||
fclose(fp);
|
||||
|
||||
if(size)
|
||||
*size = size2;
|
||||
|
||||
data[size2] = '\0';
|
||||
return data;
|
||||
}
|
||||
|
||||
static int fileconv(const char *input_file, const char *output_file,
|
||||
const char *style_file, const char *prefix)
|
||||
static int fileconv(FILE *in_fp, FILE *out_fp,
|
||||
const char *style_file,
|
||||
const char *prefix)
|
||||
{
|
||||
if(input_file == NULL || output_file == NULL) {
|
||||
fprintf(stderr,
|
||||
"Error: You must specify both input and output "
|
||||
"files using the --input and --output options\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if(prefix == NULL)
|
||||
prefix = "c2h-";
|
||||
|
||||
/* Load the input string */
|
||||
const char *err;
|
||||
|
||||
long input_size;
|
||||
char *input = load_file(input_file, &input_size);
|
||||
char *input = load_from_stream(in_fp, &input_size, &err);
|
||||
if(input == NULL) {
|
||||
fprintf(stderr, "Error: Failed to open file %s\n", input_file);
|
||||
fprintf(stderr, "Error: Failed to read input (%s)\n", err);
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Convert it */
|
||||
const char *error;
|
||||
char *output = c2html(input, input_size, prefix, &error);
|
||||
long output_size;
|
||||
char *output = c2html(input, input_size, prefix,
|
||||
&output_size, &err);
|
||||
if(output == NULL) {
|
||||
fprintf(stderr, "Error: %s\n", error);
|
||||
free(input);
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Open the output file */
|
||||
FILE *fp = fopen(output_file, "wb");
|
||||
if(fp == NULL) {
|
||||
fprintf(stderr, "ERROR: Failed to write to file %s\n",
|
||||
output_file);
|
||||
free(output);
|
||||
fprintf(stderr, "Error: %s\n", err);
|
||||
free(input);
|
||||
return -1;
|
||||
}
|
||||
@@ -112,15 +133,13 @@ static int fileconv(const char *input_file, const char *output_file,
|
||||
free(input);
|
||||
return -1;
|
||||
}
|
||||
fputs("<style>", fp);
|
||||
fputs(style_data, fp);
|
||||
fputs("</style>", fp);
|
||||
fputs("<style>", out_fp);
|
||||
fputs(style_data, out_fp);
|
||||
fputs("</style>", out_fp);
|
||||
free(style_data);
|
||||
}
|
||||
|
||||
/* ..and write the converted string to it */
|
||||
fwrite(output, 1, strlen(output), fp);
|
||||
fclose(fp);
|
||||
fwrite(output, 1, output_size, out_fp); // TODO: Check the return value!!
|
||||
|
||||
/* All done! :^) */
|
||||
free(output);
|
||||
@@ -139,7 +158,7 @@ static void print_help(FILE *fp, char *name) {
|
||||
" to the generated output, you get the highliting!\n"
|
||||
"\n"
|
||||
" The usage is:\n"
|
||||
" $ %s -i file.c -o file.html [--style file.css] [-p <prefix>]\n"
|
||||
" $ %s [-i file.c] [-o file.html] [--style file.css] [-p <prefix>]\n"
|
||||
"\n"
|
||||
" ..and here's a table of all available options:\n"
|
||||
"\n"
|
||||
@@ -161,11 +180,6 @@ static void print_help(FILE *fp, char *name) {
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
if(argc == 1) {
|
||||
print_help(stdout, argv[0]);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Parse command-line arguments */
|
||||
char *input_file = NULL,
|
||||
*output_file = NULL,
|
||||
@@ -212,6 +226,37 @@ int main(int argc, char **argv)
|
||||
}
|
||||
}
|
||||
|
||||
return fileconv(input_file, output_file,
|
||||
style_file, prefix);
|
||||
bool use_stdin = (input_file == NULL);
|
||||
bool use_stdout = (output_file == NULL);
|
||||
|
||||
FILE *in_fp, *out_fp;
|
||||
|
||||
if(use_stdin)
|
||||
in_fp = stdin;
|
||||
else {
|
||||
in_fp = fopen(input_file, "rb");
|
||||
if(in_fp == NULL) {
|
||||
fprintf(stderr, "Error: Couldn't open file %s\n", input_file);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
if(output_file == NULL)
|
||||
out_fp = stdout;
|
||||
else {
|
||||
out_fp = fopen(output_file, "wb");
|
||||
if(out_fp == NULL) {
|
||||
if(!use_stdin)
|
||||
fclose(in_fp);
|
||||
fprintf(stderr, "Error: Couldn't open or create file %s\n", output_file);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
int rescode = fileconv(in_fp, out_fp,
|
||||
style_file, prefix);
|
||||
|
||||
if(!use_stdin) fclose(in_fp);
|
||||
if(!use_stdout) fclose(out_fp);
|
||||
return rescode;
|
||||
}
|
||||
Reference in New Issue
Block a user