fparseln(): * Read a line from a file parsing continuations ending in \ * and eliminating trailing newlines, or comments starting with * the comment char. */
| 78 | * the comment char. |
| 79 | */ |
| 80 | char * |
| 81 | fparseln(FILE *fp, size_t *size, size_t *lineno, const char str[3], int flags) |
| 82 | { |
| 83 | static const char dstr[3] = { '\\', '\\', '#' }; |
| 84 | |
| 85 | size_t s, len; |
| 86 | char *buf; |
| 87 | char *ptr, *cp; |
| 88 | int cnt; |
| 89 | char esc, con, nl, com; |
| 90 | #ifdef FSTACK |
| 91 | #define MAXLINELEN 4096 |
| 92 | char fbuf[MAXLINELEN]; |
| 93 | #endif |
| 94 | |
| 95 | #if 0 |
| 96 | _DIAGASSERT(fp != NULL); |
| 97 | #endif |
| 98 | |
| 99 | len = 0; |
| 100 | buf = NULL; |
| 101 | cnt = 1; |
| 102 | |
| 103 | if (str == NULL) |
| 104 | str = dstr; |
| 105 | |
| 106 | esc = str[0]; |
| 107 | con = str[1]; |
| 108 | com = str[2]; |
| 109 | /* |
| 110 | * XXX: it would be cool to be able to specify the newline character, |
| 111 | * but unfortunately, fgetln does not let us |
| 112 | */ |
| 113 | nl = '\n'; |
| 114 | |
| 115 | while (cnt) { |
| 116 | cnt = 0; |
| 117 | |
| 118 | if (lineno) |
| 119 | (*lineno)++; |
| 120 | |
| 121 | #ifndef FSTACK |
| 122 | if ((ptr = fgetln(fp, &s)) == NULL) |
| 123 | break; |
| 124 | #else |
| 125 | if (fgets(fbuf, MAXLINELEN, fp) == NULL) |
| 126 | break; |
| 127 | fbuf[strcspn(fbuf, "\n")] = '\0'; |
| 128 | ptr = fbuf; |
| 129 | #endif |
| 130 | |
| 131 | if (s && com) { /* Check and eliminate comments */ |
| 132 | for (cp = ptr; cp < ptr + s; cp++) |
| 133 | if (*cp == com && !isescaped(ptr, cp, esc)) { |
| 134 | s = cp - ptr; |
| 135 | cnt = s == 0 && buf == NULL; |
| 136 | break; |
| 137 | } |