comment.c (3078B)
1 /* This work is in the public domain. See COPYING file for details. */ 2 3 #include <stdio.h> 4 #include <stdlib.h> 5 #include <string.h> 6 7 #include "comment.h" 8 #include "utils.h" 9 10 enum { 11 HANDLE_NAME, 12 HANDLE_EMAIL, 13 HANDLE_BODY, 14 HANDLE_DELIMITER, 15 }; 16 17 struct comment_list * 18 comment_list_new(char *path) 19 { 20 struct comment_list *head, *tail; 21 FILE *file; 22 char line[512]; 23 int state, lineno, len; 24 25 /* init struct */ 26 head = tail = NULL; 27 state = HANDLE_NAME; 28 lineno = 0; 29 30 if ((file = fopen(path, "rb")) == NULL) 31 fatal("%s:", path); 32 33 while(fgets(line, sizeof(line), file) != NULL) { 34 /* if line doesn't end with newline character */ 35 if (line[strlen(line) - 1] != '\n' && state != HANDLE_BODY) { 36 fatal("%s:%d: name or email is too big", path, lineno); 37 } else { 38 lineno++; 39 if (state == HANDLE_BODY) { 40 if (strcmp(line, "---\n") == 0) { 41 tail->body[strlen(tail->body)-1] = '\0'; 42 state = HANDLE_NAME; 43 continue; 44 } 45 } else { 46 line[strlen(line) - 1] = '\0'; 47 } 48 } 49 switch (state) { 50 case HANDLE_NAME: 51 if (head == NULL) { 52 head = tail = ecalloc(1, sizeof(*tail)); 53 } else { 54 tail->next = ecalloc(1, sizeof(*tail)); 55 tail = tail->next; 56 } 57 tail->name = strlen(line) == 0 ? NULL : strdup(line); 58 state = HANDLE_EMAIL; 59 break; 60 case HANDLE_EMAIL: 61 tail->email = strlen(line) == 0 ? NULL : strdup(line); 62 state = HANDLE_BODY; 63 break; 64 case HANDLE_BODY: 65 if (tail->body == NULL) 66 len = strlen(line) + 1; 67 else 68 len = strlen(tail->body) + strlen(line) + 1; 69 tail->body = erealloc(tail->body, len * sizeof(char)); 70 strcat(tail->body, line); 71 break; 72 } 73 } 74 fclose(file); 75 if (state != HANDLE_NAME) 76 fatal("%s:%d: incomplete comment", path, lineno); 77 return head; 78 } 79 80 void 81 comment_list_free(struct comment_list *clist) 82 { 83 struct comment_list *it, *itn; 84 85 for (it = clist; it != NULL;) { 86 free(it->name); 87 free(it->email); 88 free(it->body); 89 itn = it->next; 90 free(it); 91 it = itn; 92 } 93 } 94 95 void 96 comment_list_print(struct comment_list *clist) 97 { 98 struct comment_list *it; 99 100 puts("<h2> Comments </h2>"); 101 for (it = clist; it != NULL; it = it->next) { 102 103 puts("<div class='comment'>"); 104 printf("<p>"); 105 106 if (it->name == NULL) 107 printf("<b>Anonymous</b>"); 108 else 109 printf("<b>%s</b>", it->name); 110 111 if (it->email != NULL) 112 printf(" <%s>", it->email); 113 114 printf("</p>\n"); 115 116 printf("<pre>%s</pre>\n", it->body); 117 puts("</div>"); 118 } 119 } 120 121 void 122 comment_write(struct input_list *ilist, char *path) 123 { 124 FILE *file; 125 char *name, *email, *body; 126 127 if ((file = fopen(path, "a")) == NULL) 128 fatal("%s:", path); 129 130 /* first get all the values before writing to the file */ 131 name = input_list_find(ilist, "name"); 132 email = input_list_find(ilist, "email"); 133 body = input_list_find(ilist, "body"); 134 if (body == NULL) 135 fatal("comment_write: body can't be empty"); 136 137 /* now write the values on the file */ 138 name == NULL ? fprintf(file, "\n") : fprintf(file, "%s\n", name); 139 email == NULL ? fprintf(file, "\n") : fprintf(file, "%s\n", email); 140 fprintf(file, "%s\n", body); 141 fprintf(file, "---\n"); 142 143 fclose(file); 144 }