git.y1.nz

digest-html

Converts HTML to plaintext-with-links.
download: http://git.y1.nz/archives/digest-html.tar.gz
README | Files | Log | Refs

main.c

      1 #include <unistd.h> /* getopt */
      2 #include <sys/stat.h> /* fstat, ... */
      3 #include <stdlib.h> /* exit, EXIT_FAILURE */
      4 #include <stdio.h> /* fopen */
      5 
      6 #include "translate.h"
      7 #include "okra.h"
      8 
      9 // TODO: use more-compatible tools for this instead of fstat.
     10 static void
     11 read_file(FILE *fp, char **output, int *length)
     12 {
     13 	struct stat filestats;
     14 	int fd = fileno(fp);
     15 	fstat(fd, &filestats);
     16 	*length = filestats.st_size;
     17 	*output = malloc(*length + 1);
     18 	int start = 0;
     19 	int bytes_read;
     20 
     21 	while ((
     22 		bytes_read = fread(*output + start, 1, *length - start, fp)
     23 	)) {
     24 		start += bytes_read;
     25 	}
     26 }
     27 
     28 void
     29 print_usage(const char *name)
     30 {
     31 	printf(
     32 		"HTML-to-plaintext-with-links converter" "\n"
     33 		"Usage: %s [-d] [-b BASE_URI] [-o OUTFILE] INFILE" "\n"
     34 		" -d  show all tags that aren't explicitly handled" "\n"
     35 		" -o  write to file instead of stdout" "\n"
     36 		" -b  specify a default base uri" "\n",
     37 		name
     38 	);
     39 }
     40 
     41 void
     42 init_state(GlobalState **global, EphemeralState **state)
     43 {
     44 	*global = calloc(1, sizeof(GlobalState));
     45 	*state = calloc(1, sizeof(EphemeralState));
     46 	(*global)->out = stdout;
     47 	(*state)->global = *global;
     48 }
     49 
     50 int
     51 main(int argc, char *argv[])
     52 {
     53 	GlobalState *global;
     54 	EphemeralState *state;
     55 	char *filename = NULL, *base_uri_str = NULL;
     56 	FILE *fp;
     57 	int opt;
     58 
     59 	init_state(&global, &state);
     60 
     61 	for (;;) {
     62 		opt = getopt(argc, argv, "db:o:");
     63 		if (opt == -1) break;
     64 		switch (opt) {
     65 		case 'b': base_uri_str = optarg; break;
     66 		case 'd': global->debug++; break;
     67 		case 'o': global->out = fopen(optarg, "w"); break;
     68 		default:
     69 			printf("Invalid argument." "\n");
     70 			print_usage(argv[0]);
     71 			exit(1);
     72 		}
     73 	}
     74 	filename = argv[optind];
     75 	if (optind != argc-1) {
     76 		printf("Bad arguments." "\n");
     77 		print_usage(argv[0]);
     78 		exit(1);
     79 	}
     80 
     81 	fp = fopen(filename, "r");
     82 	if (!fp) {
     83 		printf("File %s not found!\n", filename);
     84 		exit(EXIT_FAILURE);
     85 	}
     86 
     87 	if (base_uri_str != NULL) {
     88 		global->base_uri = okra_parse(base_uri_str);
     89 		if (global->base_uri == NULL) {
     90 			printf("Invalid base URI: %s" "\n", argv[1]);
     91 			exit(1);
     92 		}
     93 	}
     94 
     95 	char *input;
     96 	int input_length;
     97 	read_file(fp, &input, &input_length);
     98 	GumboOutput *output = gumbo_parse_with_options(
     99 		&kGumboDefaultOptions, input, input_length
    100 	);
    101 	process_node(state, output->root);
    102 
    103 	if (global->base_uri != NULL) okra_free(global->base_uri);
    104 	gumbo_destroy_output(&kGumboDefaultOptions, output);
    105 	free(input);
    106 	fclose(global->out);
    107 	free(global);
    108 	free(state);
    109 }

This webpage is intended to be an accessible preview of this repository. To get a fuller picture, clone it and use the git CLI.