summaryrefslogtreecommitdiffstats
path: root/main.c
blob: 80825113d26daff66214c7d3b34849ccc36c5e8a (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
/*	Splits up questions and answers in a \LaTeX file and saves each to separate files. Questions are prefixed by "\section*{". Answers are prefixed by "\subsection*{"
	Copyright (C) 2021 Gentoo-libre Install

	This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by
	the Free Software Foundation, either version 3 of the License, or (at your option) any later version.

	This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more details.

	You should have received a copy of the GNU General Public License along with this program.  If not, see <http://www.gnu.org/licenses/>.
*/

#include <stdio.h>//basic I/O library
#include <stdlib.h>//library for malloc etc
#include <stdbool.h>//library for getting bools
#include <string.h>//We use this library just for strstr()

#define DEFAULT_SIZE 100//the default size of the buffer is 100 bytes (100 chars) to balance peformace and memory usage. Realloc is also increased by this much each time

int main(int argc, char *argv[])
{
if (!argv[1]){printf("No file given.\n"); return 1;}//return 1 if input isn't given


FILE *input = fopen(argv[1], "r");//file from where the question/answers are read
if (!input)
{
    printf("%s %s\n", "Error opening input file:", argv[1]);
    return 1;
}

FILE *questions = fopen("questions.tex", "a");//file where the questions are printed
if (!questions)
{
    printf("Error opening output file questions.");
    return 1;
}

FILE *answers = fopen("answers.tex", "a");//file where the answers are printed
if (!answers)
{
    printf("Error opening output file answers");
    return 1;
}

unsigned short size = DEFAULT_SIZE;//set size int to the DEFAULT_SIZE value. (Only an int because you can't increase the value of static symbolic values. {Muh memory wasted})
char *buffer = malloc(size*sizeof(char *));//malloc a 1D array of DEFAULT_SIZE length
if (!buffer){printf("Malloc failed!\n"); return 1;}//exit if malloc fails

char c;//buffer char
bool question_or_answer = false;//When the current line needs to be written to the questions file; bool is false. When the current line needs to be written to the answers file; bool is true;
unsigned short i = 0;//i is used to count how many chars have been written to the buffer.
char *temp;//a pointer to a char. strstr() wants this, so we use it.

c = fgetc(input);//read the first char in the file to c.
while(c != EOF)//exit if EOF is reached
{
if (c != '\n')//if read char isn't a newline, add it to the buffer.
	{
	if (i==size)//check for when the buffer is about to become larger than the memory allocated.
		{
		size+=DEFAULT_SIZE;//size = size + DEFAULT_SIZE, to add an extra 100 chars every realloc
		buffer = realloc(buffer, size);//realloc the buffer larger to fix those extra chars.
		if (!buffer){printf("Realloc failed!\n"); return 1;}//If out of memory, exit
		}

	buffer[i]=c; ++i; goto skip;//write char to buffer and skip ahead to next char reading
	}

if (c == '\n')//If the current char is newline, analyse the now made buffer for a question or answer marking and write that to the correct file
{
buffer[i]=c;//Write newline to the buffer
temp = strstr(buffer, "\\section*");//If the current line is part of a question, "\section*" will be within it, and strstr will fine such
	if (temp)//If temp isn't NULL, the string has been found
	{
	question_or_answer = false;//set the bool to question mode.
	++i; buffer[i] = '\0';//add a NULL terminator to the buffer so it can be printed.
	fprintf(questions,"%s", buffer);//output to the questions file with fprintf
	i = 0;//reset the buffer counter ready for a new read into the buffer
	goto skip;//skip ahead to reading the next char
	}
temp = strstr(buffer, "\\subsection*");//if the current line has "\\subsection*" in it, strstr will find as such.
	if (temp)//If temp isn't NULL, the string has been found
	{
	question_or_answer = true;//Set the bool to answer writing mode
	++i; buffer[i] = '\0';//Add a NULL terminator to the buffer so it can be printed
	fprintf(answers,"%s", buffer);//print the buffer to the answers file
	i = 0;//reset the buffer counter
	goto skip;//skip ahead to reading the next char
	}

switch(question_or_answer)//If above fell through, then the line in the buffer is not a section or subsection, but is still under a question or an answer. The correct file should be written to.
	{
	case 0://if question_or_answer is false, the last defermined output was a question
		++i; buffer[i] = '\0';//Add a NULL terminator so the buffer can be printed
		fprintf(questions,"%s", buffer);//print the line to the questions file with fprintf
		i = 0;//reset the buffer counter
		break;//break so that the other case doesn't waste 1< CPU cycle checking for 1
	case 1://If question_or_answer is true, the last determined output was an answer
		++i; buffer[i] = '\0';///add a NULL terminator so that the line can be printed
		fprintf(answers,"%s", buffer);//Use fprintf to write the line to the answers file
		i = 0;//reset the buffer counter
		//break; //yay, I saved a fraction of a CPU cycle by allowing a fall through instead of calling a break. (Or, I made it slower)
	}


}

skip: c = fgetc(input);//read the next char before looping up to the start of processing. If there's no more chars to read, then the while loop will determine EOF and will exit
}

fclose(input);//close the input file
fclose(questions);//close the output file
fclose(answers);//close the output file
free(buffer);//free the malloce'd buffer

return 0;
}