File Coverage

include/eshu.h
Criterion Covered Total %
statement 62 62 100.0
branch 29 36 80.5
condition n/a
subroutine n/a
pod n/a
total 91 98 92.8


line stmt bran cond sub pod time code
1             /*
2             * eshu.h — Core types, config, and public API for Eshu indentation fixer
3             *
4             * Pure C, no Perl dependencies.
5             */
6              
7             #ifndef ESHU_H
8             #define ESHU_H
9              
10             #include
11             #include
12             #include
13              
14             /* ══════════════════════════════════════════════════════════════════
15             * Language enum
16             * ══════════════════════════════════════════════════════════════════ */
17              
18             enum eshu_lang {
19             ESHU_LANG_C = 0,
20             ESHU_LANG_PERL = 1,
21             ESHU_LANG_XS = 2,
22             ESHU_LANG_XML = 3,
23             ESHU_LANG_HTML = 4,
24             ESHU_LANG_CSS = 5,
25             ESHU_LANG_JS = 6,
26             ESHU_LANG_POD = 7
27             };
28              
29             /* ══════════════════════════════════════════════════════════════════
30             * Scanner state
31             * ══════════════════════════════════════════════════════════════════ */
32              
33             enum eshu_state {
34             ESHU_CODE,
35             ESHU_STRING_DQ,
36             ESHU_STRING_SQ,
37             ESHU_CHAR_LIT,
38             ESHU_COMMENT_LINE,
39             ESHU_COMMENT_BLOCK,
40             ESHU_PREPROCESSOR,
41             /* Perl-specific states */
42             ESHU_HEREDOC,
43             ESHU_HEREDOC_INDENT,
44             ESHU_REGEX,
45             ESHU_QW,
46             ESHU_QQ,
47             ESHU_Q,
48             ESHU_POD,
49             /* XML/HTML-specific states */
50             ESHU_XML_TAG,
51             ESHU_XML_COMMENT,
52             ESHU_XML_CDATA,
53             ESHU_XML_PI,
54             ESHU_XML_DOCTYPE,
55             ESHU_XML_ATTR_DQ,
56             ESHU_XML_ATTR_SQ,
57             ESHU_XML_VERBATIM,
58             /* CSS-specific states */
59             ESHU_CSS_STRING_DQ,
60             ESHU_CSS_STRING_SQ,
61             ESHU_CSS_COMMENT,
62             ESHU_CSS_URL,
63             /* JS-specific states */
64             ESHU_JS_TEMPLATE,
65             ESHU_JS_REGEX,
66             ESHU_JS_REGEX_CLASS,
67             /* POD-specific states */
68             ESHU_POD_VERBATIM,
69             ESHU_POD_OVER
70             };
71              
72             /* ══════════════════════════════════════════════════════════════════
73             * Configuration
74             * ══════════════════════════════════════════════════════════════════ */
75              
76             typedef struct {
77             char indent_char; /* '\t' or ' ' */
78             int indent_width; /* spaces per level (ignored for tabs) */
79             int indent_pp; /* indent preprocessor directives? */
80             int lang; /* eshu_lang enum value */
81             int range_start; /* first line to reindent (1-based, 0=all) */
82             int range_end; /* last line to reindent (1-based, 0=all) */
83             } eshu_config_t;
84              
85 350           static eshu_config_t eshu_default_config(void) {
86             eshu_config_t c;
87 350           c.indent_char = '\t';
88 350           c.indent_width = 1;
89 350           c.indent_pp = 0;
90 350           c.lang = ESHU_LANG_C;
91 350           c.range_start = 0;
92 350           c.range_end = 0;
93 350           return c;
94             }
95              
96             /* Check if a line number is within the configured range (or range is disabled) */
97 8939           static int eshu_in_range(const eshu_config_t *cfg, int line_num) {
98 8939 100         if (cfg->range_start == 0) return 1; /* no range = all lines */
99 13 100         return line_num >= cfg->range_start && line_num <= cfg->range_end;
    100          
100             }
101              
102             /* ══════════════════════════════════════════════════════════════════
103             * Dynamic buffer
104             * ══════════════════════════════════════════════════════════════════ */
105              
106             typedef struct {
107             char *data;
108             size_t len;
109             size_t cap;
110             } eshu_buf_t;
111              
112 543           static void eshu_buf_init(eshu_buf_t *b, size_t initial) {
113 543 50         b->cap = initial > 0 ? initial : 4096;
114 543           b->data = (char *)malloc(b->cap);
115 543           b->len = 0;
116 543           }
117              
118 30499           static void eshu_buf_ensure(eshu_buf_t *b, size_t extra) {
119 30519 100         while (b->len + extra > b->cap) {
120 20           b->cap *= 2;
121 20           b->data = (char *)realloc(b->data, b->cap);
122             }
123 30499           }
124              
125 21182           static void eshu_buf_putc(eshu_buf_t *b, char c) {
126 21182           eshu_buf_ensure(b, 1);
127 21182           b->data[b->len++] = c;
128 21182           }
129              
130 9317           static void eshu_buf_write(eshu_buf_t *b, const char *s, size_t n) {
131 9317           eshu_buf_ensure(b, n);
132 9317           memcpy(b->data + b->len, s, n);
133 9317           b->len += n;
134 9317           }
135              
136 137           static void eshu_buf_free(eshu_buf_t *b) {
137 137 50         if (b->data) free(b->data);
138 137           b->data = NULL;
139 137           b->len = 0;
140 137           b->cap = 0;
141 137           }
142              
143             /* ══════════════════════════════════════════════════════════════════
144             * Line extraction helper
145             * ══════════════════════════════════════════════════════════════════ */
146              
147             /* Find end of current line. Returns pointer to '\n' or to the
148             * terminating NUL if no newline. */
149 10541           static const char * eshu_find_eol(const char *p) {
150 257285 50         while (*p && *p != '\n')
    100          
151 246744           p++;
152 10541           return p;
153             }
154              
155             /* Return pointer to first non-whitespace char in line */
156 13101           static const char * eshu_skip_leading_ws(const char *p) {
157 31365 100         while (*p == ' ' || *p == '\t')
    100          
158 18264           p++;
159 13101           return p;
160             }
161              
162             /* ══════════════════════════════════════════════════════════════════
163             * Trim trailing whitespace
164             * ══════════════════════════════════════════════════════════════════ */
165              
166             /* Return length of content with trailing whitespace removed */
167 8345           static int eshu_trimmed_len(const char *content, int len) {
168 8366 50         while (len > 0 && (content[len - 1] == ' ' || content[len - 1] == '\t'))
    100          
    50          
169 21           len--;
170 8345           return len;
171             }
172              
173             /* Write content to buffer with trailing whitespace stripped */
174 8345           static void eshu_buf_write_trimmed(eshu_buf_t *b, const char *s, int n) {
175 8345           n = eshu_trimmed_len(s, n);
176 8345 50         if (n > 0)
177 8345           eshu_buf_write(b, s, (size_t)n);
178 8345           }
179              
180             /* ══════════════════════════════════════════════════════════════════
181             * Emit indentation
182             * ══════════════════════════════════════════════════════════════════ */
183              
184 7327           static void eshu_emit_indent(eshu_buf_t *out, int depth,
185             const eshu_config_t *cfg) {
186             int i;
187 7327 50         if (depth < 0) depth = 0;
188 7327 100         if (cfg->indent_char == '\t') {
189 17190 100         for (i = 0; i < depth; i++)
190 9881           eshu_buf_putc(out, '\t');
191             } else {
192 18           int n = depth * cfg->indent_width;
193 42 100         for (i = 0; i < n; i++)
194 24           eshu_buf_putc(out, ' ');
195             }
196 7327           }
197              
198             #endif /* ESHU_H */