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:
cozis
2022-05-09 04:40:07 +02:00
parent df99e96361
commit e3a9c895cc
4 changed files with 117 additions and 68 deletions
+5 -6
View File
@@ -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>
+5 -2
View File
@@ -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;
}
+5 -3
View File
@@ -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);
+102 -57
View File
@@ -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;
}