#include #include #include #include "buf.h" typedef enum { false, true } bool; FILE* getfile(int argc, char** argv){ if (argc >= 2) return fopen(argv[1], "r"); else return stdin; } char* chrmult(char c, size_t ct){ char* str = malloc(sizeof(char)*(ct+1)); str[ct] = 0; memset(str, c, ct); return str; } // file read & buffer fill helpers FILE* in; buf* inbuf; int addchr(void){ int c = fgetc(in); if (c != EOF) inschrbuf(inbuf, c); return c; } size_t fillbuf(size_t len){ // returns real len int c; size_t set; for (set = buflen(inbuf); set < len && (c = addchr()) != EOF;set++); return set; } size_t chrfill(char chr){ size_t len = buflen(inbuf); char* str = peekstrbuf(inbuf, 0, len); char* line = memchr(str,chr,len); free(str); if (line) return line-str+1; for (int c = 0; c != chr && (c = addchr()) != EOF; len++); return len; } #define min(a,b) a < b ? a : b size_t chrnfill(char chr, size_t sz){//fills to first of chr or sz size_t len = buflen(inbuf); size_t lim = min(len,sz); char* str = peekstrbuf(inbuf, 0, lim); char* line = memchr(str, chr, lim); free(str); if (line) return line-str+1; for (int c = 0; c != chr && (c = addchr()) != EOF&& len= low){ int mid = ((unsigned int)low + (unsigned int)high) >> 1; char* mval = cmds[mid]; int cmp = strncmp(dat, mval, strlen(mval)); if (cmp < 0) // dat < mval high = mid - 1; else if (cmp > 0) low = mid + 1; else{ proc = call[mid](dat+strlen(mval)); break; } } free(dat); return proc; } // 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 width){ txt[ws] = '\n'; txt += ws; len -= ws; ws = width; } } return txt; } 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;*/ } // a parser to choose when to typeset and when to run a command char* line(void){ size_t sz; 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 (twobytes[0] == '.') popchrbuf(inbuf); if (twobytes[0] == '.' && twobytes[1] != '.'){ char* data = cmd(); if (data) return data; return line(); } else { return typeset(); } } // orchestration int main(int argc, char** argv){ int c; in = getfile(argc, argv); inbuf = newbuf(256); if (in == NULL){ perror(argv[1]); return 1; } char* out; while ( (out = line())[0] != '\0'){ printf("%s",out); // free(out); } fclose(in); return 0; }