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 329           static eshu_config_t eshu_default_config(void) {
86             eshu_config_t c;
87 329           c.indent_char = '\t';
88 329           c.indent_width = 1;
89 329           c.indent_pp = 0;
90 329           c.lang = ESHU_LANG_C;
91 329           c.range_start = 0;
92 329           c.range_end = 0;
93 329           return c;
94             }
95              
96             /* Check if a line number is within the configured range (or range is disabled) */
97 8713           static int eshu_in_range(const eshu_config_t *cfg, int line_num) {
98 8713 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 505           static void eshu_buf_init(eshu_buf_t *b, size_t initial) {
113 505 50         b->cap = initial > 0 ? initial : 4096;
114 505           b->data = (char *)malloc(b->cap);
115 505           b->len = 0;
116 505           }
117              
118 29200           static void eshu_buf_ensure(eshu_buf_t *b, size_t extra) {
119 29220 100         while (b->len + extra > b->cap) {
120 20           b->cap *= 2;
121 20           b->data = (char *)realloc(b->data, b->cap);
122             }
123 29200           }
124              
125 20157           static void eshu_buf_putc(eshu_buf_t *b, char c) {
126 20157           eshu_buf_ensure(b, 1);
127 20157           b->data[b->len++] = c;
128 20157           }
129              
130 9043           static void eshu_buf_write(eshu_buf_t *b, const char *s, size_t n) {
131 9043           eshu_buf_ensure(b, n);
132 9043           memcpy(b->data + b->len, s, n);
133 9043           b->len += n;
134 9043           }
135              
136 122           static void eshu_buf_free(eshu_buf_t *b) {
137 122 50         if (b->data) free(b->data);
138 122           b->data = NULL;
139 122           b->len = 0;
140 122           b->cap = 0;
141 122           }
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 10237           static const char * eshu_find_eol(const char *p) {
150 251226 50         while (*p && *p != '\n')
    100          
151 240989           p++;
152 10237           return p;
153             }
154              
155             /* Return pointer to first non-whitespace char in line */
156 12797           static const char * eshu_skip_leading_ws(const char *p) {
157 30378 100         while (*p == ' ' || *p == '\t')
    100          
158 17581           p++;
159 12797           return p;
160             }
161              
162             /* ══════════════════════════════════════════════════════════════════
163             * Trim trailing whitespace
164             * ══════════════════════════════════════════════════════════════════ */
165              
166             /* Return length of content with trailing whitespace removed */
167 8086           static int eshu_trimmed_len(const char *content, int len) {
168 8107 50         while (len > 0 && (content[len - 1] == ' ' || content[len - 1] == '\t'))
    100          
    50          
169 21           len--;
170 8086           return len;
171             }
172              
173             /* Write content to buffer with trailing whitespace stripped */
174 8086           static void eshu_buf_write_trimmed(eshu_buf_t *b, const char *s, int n) {
175 8086           n = eshu_trimmed_len(s, n);
176 8086 50         if (n > 0)
177 8086           eshu_buf_write(b, s, (size_t)n);
178 8086           }
179              
180             /* ══════════════════════════════════════════════════════════════════
181             * Emit indentation
182             * ══════════════════════════════════════════════════════════════════ */
183              
184 7116           static void eshu_emit_indent(eshu_buf_t *out, int depth,
185             const eshu_config_t *cfg) {
186             int i;
187 7116 50         if (depth < 0) depth = 0;
188 7116 100         if (cfg->indent_char == '\t') {
189 16641 100         for (i = 0; i < depth; i++)
190 9543           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 7116           }
197              
198             #endif /* ESHU_H */