aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Makefile5
-rw-r--r--badroff.c119
-rw-r--r--ll.c10
-rw-r--r--ll.h12
4 files changed, 97 insertions, 49 deletions
diff --git a/Makefile b/Makefile
index b08be79..4c782b5 100644
--- a/Makefile
+++ b/Makefile
@@ -1,7 +1,8 @@
.POSIX:
-OBJS = badroff.o buf.o
+OBJS = badroff.o buf.o ll.o
badroff: $(OBJS)
-badroff.o: badroff.c buf.h
+badroff.o: badroff.c buf.h ll.h
buf.o: buf.c buf.h
+ll.o: ll.c ll.h
clean:
rm -f badroff $(OBJS)
diff --git a/badroff.c b/badroff.c
index a06fb30..c86e29f 100644
--- a/badroff.c
+++ b/badroff.c
@@ -3,6 +3,11 @@
#include <stdlib.h>
#include "buf.h"
+#include "ll.h"
+
+char* line(void);
+char* wordset(char* txt);
+void wsclean(char* txt);
typedef enum {
false,
@@ -101,11 +106,51 @@ char* leader(char* txt){
fin[i] = repeat[i % rptln];
return fin;
}
+bool endlineset = false;
+char* lineset(char* txt){
+ llnode *head, *tail; head = tail = appendll(NULL, NULL);
+ size_t ct, len; ct = len = 0;
+ while (true){
+ tail->next = appendll(tail, line());
+ if (endlineset) break;
+ tail = tail->next;
+ ct++;
+ len += strlen(tail->str);
+ }
+ free(tail->next->str); free(tail->next); //.ELS cmd
+ tail = tail->next = head->next; // loop linked list
+ free(head);
+
+ char *lines, *pos;
+ lines = malloc((sizeof(char)*(len+1)));
+ // construct lines
+ int jmp;
+ for (pos = lines; pos-lines < len; pos += jmp, tail = tail->next){
+ char* str = tail->str + tail->loc;
+ char* loc = memchr(str, '\n', strlen(str));
+ jmp = (loc == NULL) ? 0 : loc-str+1;
+ memcpy(pos, str, jmp);
+ tail->loc += jmp;
+ }
+ llnode* last = NULL;
+ /*for (size_t i = 0; i<=ct; i++, last = tail, tail = tail->next){
+ free(tail->str);
+ free(last);
+ }*/
+ endlineset = false;
+ wsclean(lines);
+ return lines;
+}
+char* finlineset(char* txt){
+ char* str = malloc(sizeof(char)); str[0] = 0;
+ endlineset = true;
+ return str;
+}
-char* cmds[] =
- {"CT ", "FIL ", "LD ", "W "}; // MUST be sorted alphabetically
+char* cmds[] = // MUST be sorted alphabetically
+ {"CT ", "ELS", "FIL ", "LD ", "LS", "W "};
char* (*call[])(char* txt) =
- {center, fillline, leader, setwidth};
+ {center, finlineset, fillline, leader, lineset, setwidth};
char* cmd(void){
char* dat = popstrbuf(inbuf, chrfill('\n'));
@@ -131,62 +176,42 @@ char* cmd(void){
// normal typesetting
-bool cont_typst = false; // communicates with line() for broken lines.
-
-size_t nextws(size_t start){//searches for \n or [^ \n]-1 in buffer
- //starts at `start` (if not whitespace, returns start-1)
- size_t len = buflen(inbuf);
- char* str = peekstrbuf(inbuf, start, len-start);
- size_t i;
- for (i = 0; i<len-start; i++){
- if (str[i] == '\n') return start+i;
- else if (str[i] != ' ') return start+i-1;
+void wsclean(char* txt){
+ size_t disp = 0;
+ int firstws;
+ for (size_t i = 0; i == 0 || txt[i-1] != 0; i++){
+ if ( (txt[i] == ' ' || txt[i] == '\n') && txt[i-1] != ' '){
+ firstws = i;
+ }
+ if (txt[i] == '\n'){
+ disp += i-firstws;
+ }
+ txt[i-disp] = txt[i];
}
- free(str);
- for (int c = 0; c != '\n' && ( c = addchr() ) != EOF && c == ' ';
- len++); // if this is a newline, exit late (len is last, !(len-1)).
- return len;
}
-char* wordtypeset(char* txt){ // always ends with \n
- size_t len = strlen(txt);
+char* wordset(char* txt){
+ char* orig = txt;
size_t ws = width;
- for (size_t i=0; i<len; i++){ // turn into a nested loop
- if (i == ' ') ws = i;
- if (i > width){
- txt[ws] = '\n';
+ for (size_t i=0; txt[i] != 0; i++){ // turn into a nested loop
+ if (txt[i] == ' ') ws = i;
+ if (i >= width && ws != i){
txt += ws;
- len -= ws;
+ txt[0] = '\n';
ws = width;
+ i = 0;
}
}
- return txt;
+ wsclean(orig);
+
+ return orig;
}
+
char* typeset(void){
size_t len = chrfill('\n');
- return wordtypeset(popstrbuf(inbuf, len));
- /*size_t len = chrnfill('\n', width+1); //+1 for \n on 81-char lines
- char* next = peekstrbuf(inbuf, 0, len);
- size_t wsend = 0;
- if (next[--len] == '\n'){
- wsend = len;
- } else if (next[len] == ' '){
- wsend = nextws(len);
- }
- else for (wsend = len; next[wsend] != ' '; wsend--);
- // wsend is last index with a piece of whitespace
- for (len = min(wsend,len-1); next[len] == ' '; len--);
- // check, within the string, behind the whitespace for a letter.
- if (next[len] == '\n') len--; // "\n" shouldn't become "\n\n"
- // len should be *index of* last letter
- if (peekchrbuf(inbuf, wsend) == '\n') cont_typst = false;
- else cont_typst = true;
- free(next);
- char* ln = popstrbuf(inbuf, wsend+1);
- ln[len+1] = '\n'; ln[len+2] = 0;
- return ln;*/
+ return wordset(popstrbuf(inbuf, len));
}
// a parser to choose when to typeset and when to run a command
@@ -196,7 +221,7 @@ char* line(void){
if ( (sz = fillbuf(2)) == 0)
return "";
char* twobytes = peekstrbuf(inbuf, 0, 2); // .., .\n, or ^.?
- if (sz == 1 || twobytes[1] == '\n' || cont_typst) return typeset();
+ if (sz == 1 || twobytes[1] == '\n') return typeset();
if (twobytes[0] == '.') popchrbuf(inbuf);
if (twobytes[0] == '.' && twobytes[1] != '.'){
char* data = cmd();
diff --git a/ll.c b/ll.c
new file mode 100644
index 0000000..d929b2f
--- /dev/null
+++ b/ll.c
@@ -0,0 +1,10 @@
+#include <stdlib.h>
+#include "ll.h"
+
+llnode* appendll(llnode* tail, char* str){
+ llnode* new = malloc(sizeof(llnode));
+ if (tail != NULL) tail->next = new;
+ new->str = str;
+ new->loc = 0;
+ return new;
+}
diff --git a/ll.h b/ll.h
new file mode 100644
index 0000000..be85ccb
--- /dev/null
+++ b/ll.h
@@ -0,0 +1,12 @@
+#ifndef _LL_INCLUDE
+#define _LL_INCLUDE
+
+typedef struct llnode {
+ char* str;
+ int loc;
+ struct llnode* next;
+} llnode;
+
+llnode* appendll(llnode* tail, char* str);
+
+#endif