reflow

Преобликује пасусе у редове
git clone https://git.sr.ht/~strahinja/reflow
Дневник | Датотеке | Референце | ПРОЧИТАЈМЕ | ЛИЦЕНЦА

reflow.c (4622B)


      1 /* This program is licensed under the terms of GNU GPL v3 or (at your option)
      2  * any later version. Copyright (C) 2021-2026  Страхиња Радић.
      3  * See the file LICENSE for exact copyright and license details. */
      4 
      5 #include <assert.h>
      6 #include <errno.h>
      7 #include <stdarg.h>
      8 #include <stdio.h>
      9 #include <stdlib.h>
     10 #include <string.h>
     11 
     12 #include "defs.h"
     13 #include "version.h"
     14 
     15 #define COPYRIGHT                                                            \
     16 	("  This program is licensed under the terms of GNU GPL v3"          \
     17 	 " or (at your option)\n"                                            \
     18 	 "  any later version. Copyright (C) 2021-2026  Strahinya Radich.\n" \
     19 	 "  See the file LICENSE for exact copyright and license "           \
     20 	 "details.")
     21 
     22 char filename[MAXPATH];
     23 
     24 int
     25 usage(void)
     26 {
     27 	printf("Usage:\t%s -h | --help | -V | --full-version | -v | --version\n"
     28 	       "\t%s [file]\n",
     29 		PROGRAMNAME, PROGRAMNAME);
     30 	return 0;
     31 }
     32 
     33 int
     34 error(const int code, const char* format, ...)
     35 {
     36 	char buf[MAXBUF];
     37 	va_list args;
     38 	assert(format != NULL);
     39 	va_start(args, format);
     40 	vsnprintf(buf, sizeof(buf), format, args);
     41 	va_end(args);
     42 	fprintf(stderr, "%s:%s: %s\n", PROGRAMNAME,
     43 		*filename ? filename : "(stdin)", buf);
     44 	return code;
     45 }
     46 
     47 int
     48 version(const int full)
     49 {
     50 	printf("%s %s, built on %s\n", PROGRAMNAME, VERSION, DATE);
     51 	if (full)
     52 		puts(COPYRIGHT);
     53 	return 0;
     54 }
     55 
     56 int
     57 is_whitespace(const char ch)
     58 {
     59 	return (ch == ' ') || (ch == '\t');
     60 }
     61 
     62 int
     63 main(int argc, char** argv)
     64 {
     65 	FILE* input	    = NULL;
     66 	char* buffer	    = NULL;
     67 	char* carg	    = NULL;
     68 	char* pbuffer	    = NULL;
     69 	char* line	    = NULL;
     70 	char* pline	    = NULL;
     71 	char* eol	    = NULL;
     72 	char* tempb	    = NULL;
     73 	ssize_t buffer_size = 0;
     74 	ssize_t line_len    = 0;
     75 	ssize_t prev_size   = 0;
     76 	int argn	    = 1;
     77 	int empty_line;
     78 	int initial_whitespace;
     79 
     80 	*filename = 0;
     81 	while (argn < argc)
     82 	{
     83 		carg = *(argv + argn);
     84 		if (!strcmp(carg, "-h") || !strcmp(carg, "--help"))
     85 			return usage();
     86 		else if (!strcmp(carg, "-V") || !strcmp(carg, "--full-version"))
     87 			return version(1);
     88 		else if (!strcmp(carg, "-v") || !strcmp(carg, "--version"))
     89 			return version(0);
     90 		else if (!*filename)
     91 		{
     92 			if (!memccpy(filename, carg, 0, MAXPATH))
     93 				return error(1,
     94 					"Overflow when setting filename");
     95 		}
     96 		else
     97 			return usage();
     98 		argn++;
     99 	}
    100 
    101 	if (!*filename || (*filename == '-' && !*(filename + 1)))
    102 		input = stdin;
    103 	else
    104 		input = fopen(filename, "rt");
    105 	if (!input)
    106 		return error(errno, "Cannot open file");
    107 
    108 	line = malloc(MAXBUF);
    109 	if (!line)
    110 		exit(error(ENOMEM, "Memory allocation failed"));
    111 	prev_size = MAXBUF;
    112 
    113 	while (!feof(input))
    114 	{
    115 		if (!fgets(line, MAXBUF, input))
    116 		{
    117 			if (!feof(input))
    118 				return error(errno, "Error reading file");
    119 			else
    120 				break;
    121 		}
    122 
    123 		eol = strchr(line, '\n');
    124 		if (eol)
    125 			line_len = eol - line + 1;
    126 		else
    127 			line_len = strlen(line);
    128 
    129 		buffer_size += line_len;
    130 		if (!buffer)
    131 		{
    132 			buffer = malloc(buffer_size + 1);
    133 			if (!buffer)
    134 				exit(error(ENOMEM, "Memory allocation failed"));
    135 			pbuffer = buffer;
    136 		}
    137 		else
    138 		{
    139 			ssize_t pbuffer_start = pbuffer - buffer;
    140 			tempb = realloc(buffer, buffer_size + 1);
    141 			if (!tempb)
    142 				exit(error(ENOMEM, "Memory allocation failed"));
    143 			buffer	= tempb;
    144 			pbuffer = buffer + pbuffer_start;
    145 		}
    146 		pline		   = line;
    147 		initial_whitespace = is_whitespace(*pline);
    148 		while (*pline)
    149 		{
    150 			if (initial_whitespace)
    151 			{
    152 				if (!is_whitespace(*pline))
    153 				{
    154 					initial_whitespace = 0;
    155 					*pbuffer++	   = *pline;
    156 				}
    157 			}
    158 			else if (!((pline + 1 - line) < line_len
    159 					 && is_whitespace(*pline)
    160 					 && is_whitespace(pline[1])))
    161 				*pbuffer++ = *pline;
    162 			pline++;
    163 		}
    164 	}
    165 	if (pbuffer)
    166 		*pbuffer = 0;
    167 	else
    168 		exit(0);
    169 
    170 	empty_line = 0;
    171 	pbuffer	   = buffer;
    172 	tempb	   = NULL;
    173 	while (*pbuffer)
    174 	{
    175 		eol = strchr(pbuffer, '\n');
    176 		if (eol)
    177 			line_len = eol - pbuffer;
    178 		else
    179 			line_len = strlen(pbuffer);
    180 		if (empty_line && line_len == 0)
    181 		{
    182 			pbuffer++;
    183 			continue;
    184 		}
    185 		empty_line = line_len == 0;
    186 		if (!line || line_len + 1 > prev_size)
    187 		{
    188 			tempb = realloc(line, line_len + 1);
    189 			if (!tempb)
    190 				exit(error(ENOMEM, "Memory allocation failed"));
    191 			prev_size = line_len + 1;
    192 			line	  = tempb;
    193 		}
    194 		strncpy(line, pbuffer, line_len);
    195 		*(line + line_len) = 0;
    196 		printf("%s", line);
    197 		if (pbuffer[line_len + 1] == '\n' && !empty_line)
    198 			printf("\n\n");
    199 		else if (!empty_line && !is_whitespace(pbuffer[line_len - 1])
    200 			&& !is_whitespace(pbuffer[line_len + 1])
    201 			&& pbuffer[line_len - 1] != '\n'
    202 			&& pbuffer[line_len + 1] != '\n')
    203 			printf(" ");
    204 		pbuffer += line_len + 1;
    205 	}
    206 	puts("");
    207 	free(buffer);
    208 	free(line);
    209 
    210 	return 0;
    211 }