PostgreSQL Source Code git master
io.c
Go to the documentation of this file.
1/*-
2 * Copyright (c) 1985 Sun Microsystems, Inc.
3 * Copyright (c) 1980, 1993
4 * The Regents of the University of California. All rights reserved.
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the University nor the names of its contributors
16 * may be used to endorse or promote products derived from this software
17 * without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 */
31
32#if 0
33#ifndef lint
34static char sccsid[] = "@(#)io.c 8.1 (Berkeley) 6/6/93";
35#endif /* not lint */
36#endif
37
38#include "c.h"
39
40#include <ctype.h>
41#include <err.h>
42#include <stdio.h>
43#include <stdlib.h>
44#include <string.h>
45#include "indent_globs.h"
46#include "indent.h"
47
49static int paren_target;
50
51static char *lookahead_buf; /* malloc'd buffer, or NULL initially */
52static char *lookahead_buf_end; /* end+1 of allocated space */
53static char *lookahead_start; /* => next char for fill_buffer() to fetch */
54static char *lookahead_ptr; /* => next char for lookahead() to fetch */
55static char *lookahead_end; /* last+1 valid char in lookahead_buf */
56static char *lookahead_bp_save; /* lookahead position in bp_save, if any */
57
58static int pad_output(int current, int target);
59
60void
62{ /* dump_line is the routine that actually
63 * effects the printing of the new source. It
64 * prints the label section, followed by the
65 * code section with the appropriate nesting
66 * level, followed by any comments */
67 int cur_col,
68 target_col = 1;
69 static int not_first_line;
70
71 if (ps.procname[0]) {
72 ps.ind_level = 0;
73 ps.procname[0] = 0;
74 }
75 if (s_code == e_code && s_lab == e_lab && s_com == e_com) {
76 if (suppress_blanklines > 0)
78 else {
79 ps.bl_line = true;
81 }
82 }
83 else if (!inhibit_formatting) {
85 ps.bl_line = false;
86 if (prefix_blankline_requested && not_first_line) {
88 if (n_real_blanklines == 1)
90 }
91 else {
92 if (n_real_blanklines == 0)
94 }
95 }
96 while (--n_real_blanklines >= 0)
97 putc('\n', output);
99 if (ps.ind_level == 0)
100 ps.ind_stmt = 0; /* this is a class A kludge. dont do
101 * additional statement indentation if we are
102 * at bracket level 0 */
103
104 if (e_lab != s_lab || e_code != s_code)
105 ++code_lines; /* keep count of lines with code */
106
107
108 if (e_lab != s_lab) { /* print lab, if any */
109 if (comment_open) {
110 comment_open = 0;
111 fprintf(output, ".*/\n");
112 }
113 while (e_lab > s_lab && (e_lab[-1] == ' ' || e_lab[-1] == '\t'))
114 e_lab--;
115 *e_lab = '\0';
116 cur_col = pad_output(1, compute_label_target());
117 if (s_lab[0] == '#' && (strncmp(s_lab, "#else", 5) == 0
118 || strncmp(s_lab, "#endif", 6) == 0)) {
119 char *s = s_lab;
120 if (e_lab[-1] == '\n') e_lab--;
121 do putc(*s++, output);
122 while (s < e_lab && 'a' <= *s && *s<='z');
123 while ((*s == ' ' || *s == '\t') && s < e_lab)
124 s++;
125 if (s < e_lab)
126 fprintf(output, s[0]=='/' && s[1]=='*' ? "\t%.*s" : "\t/* %.*s */",
127 (int)(e_lab - s), s);
128 }
129 else fprintf(output, "%.*s", (int)(e_lab - s_lab), s_lab);
130 cur_col = count_spaces(cur_col, s_lab);
131 }
132 else
133 cur_col = 1; /* there is no label section */
134
135 ps.pcase = false;
136
137 if (s_code != e_code) { /* print code section, if any */
138 char *p;
139
140 if (comment_open) {
141 comment_open = 0;
142 fprintf(output, ".*/\n");
143 }
144 target_col = compute_code_target();
145 {
146 int i;
147
148 for (i = 0; i < ps.p_l_follow; i++)
149 if (ps.paren_indents[i] >= 0)
150 ps.paren_indents[i] = -(ps.paren_indents[i] + target_col);
151 }
152 cur_col = pad_output(cur_col, target_col);
153 for (p = s_code; p < e_code; p++)
154 if (*p == (char) 0200)
155 fprintf(output, "%d", target_col * 7);
156 else
157 putc(*p, output);
158 cur_col = count_spaces(cur_col, s_code);
159 }
160 if (s_com != e_com) { /* print comment, if any */
161 int target = ps.com_col;
162 char *com_st = s_com;
163
164 target += ps.comment_delta;
165 while (*com_st == '\t') /* consider original indentation in
166 * case this is a box comment */
167 com_st++, target += tabsize;
168 while (target <= 0)
169 if (*com_st == ' ')
170 target++, com_st++;
171 else if (*com_st == '\t')
172 target = tabsize * (1 + (target - 1) / tabsize) + 1, com_st++;
173 else
174 target = 1;
175 if (cur_col > target) { /* if comment can't fit on this line,
176 * put it on next line */
177 putc('\n', output);
178 cur_col = 1;
179 ++ps.out_lines;
180 }
181 while (e_com > com_st && isspace((unsigned char)e_com[-1]))
182 e_com--;
183 (void)pad_output(cur_col, target);
184 fwrite(com_st, e_com - com_st, 1, output);
186 ++ps.com_lines; /* count lines with comments */
187 }
188 if (ps.use_ff)
189 putc('\014', output);
190 else
191 putc('\n', output);
192 ++ps.out_lines;
195 ps.just_saw_decl = 0;
196 }
197 else
200 }
201 ps.decl_on_line = ps.in_decl; /* if we are in the middle of a
202 * declaration, remember that fact for
203 * proper comment indentation */
204 /* next line should be indented if we have not completed this stmt, and
205 * either we are not in a declaration or we are in an initialization
206 * assignment; but not if we're within braces in an initialization,
207 * because that scenario is handled by other rules. */
208 ps.ind_stmt = ps.in_stmt &&
209 (!ps.in_decl || (ps.block_init && ps.block_init_level <= 0));
210 ps.use_ff = false;
212 *(e_lab = s_lab) = '\0'; /* reset buffers */
213 *(e_code = s_code) = '\0';
214 *(e_com = s_com = combuf + 1) = '\0';
217 if (ps.paren_level > 0)
219 not_first_line = 1;
220}
221
222int
224{
225 int target_col = ps.ind_size * ps.ind_level + 1;
226
227 if (ps.paren_level)
228 if (!lineup_to_parens)
229 target_col += continuation_indent
232 target_col = paren_target;
233 else {
234 int w;
235 int t = paren_target;
236
237 if ((w = count_spaces(t, s_code) - max_col) > 0
238 && count_spaces(target_col, s_code) <= max_col) {
239 t -= w + 1;
240 if (t > target_col)
241 target_col = t;
242 }
243 else
244 target_col = t;
245 }
246 else if (ps.ind_stmt)
247 target_col += continuation_indent;
248 return target_col;
249}
250
251int
253{
254 return
255 ps.pcase ? (int) (case_ind * ps.ind_size) + 1
256 : *s_lab == '#' ? 1
257 : ps.ind_size * (ps.ind_level - label_offset) + 1;
258}
259
260/*
261 * Read data ahead of what has been collected into in_buffer.
262 *
263 * Successive calls get further and further ahead, until we hit EOF.
264 * Call lookahead_reset() to rescan from just beyond in_buffer.
265 *
266 * Lookahead is automatically reset whenever fill_buffer() reads beyond
267 * the lookahead buffer, i.e., you can't use this for "look behind".
268 *
269 * The standard pattern for potentially multi-line lookahead is to call
270 * lookahead_reset(), then enter a loop that scans forward from buf_ptr
271 * to buf_end, then (if necessary) calls lookahead() to read additional
272 * characters from beyond the end of the current line.
273 */
274int
276{
277 /* First read whatever's in bp_save area */
279 return (unsigned char) *lookahead_bp_save++;
280 /* Else, we have to examine and probably fill the main lookahead buffer */
281 while (lookahead_ptr >= lookahead_end) {
282 int i = getc(input);
283
284 if (i == EOF)
285 return i;
286 if (i == '\0')
287 continue; /* fill_buffer drops nulls, and so do we */
288
290 /* Need to allocate or enlarge lookahead_buf */
291 char *new_buf;
292 size_t req;
293
294 if (lookahead_buf == NULL) {
295 req = 64;
296 new_buf = malloc(req);
297 } else {
298 req = (lookahead_buf_end - lookahead_buf) * 2;
299 new_buf = realloc(lookahead_buf, req);
300 }
301 if (new_buf == NULL)
302 errx(1, "too much lookahead required");
306 lookahead_buf = new_buf;
307 lookahead_buf_end = new_buf + req;
308 }
309
310 *lookahead_end++ = i;
311 }
312 return (unsigned char) *lookahead_ptr++;
313}
314
315/*
316 * Reset so that lookahead() will again scan from just beyond what's in
317 * in_buffer.
318 */
319void
321{
322 /* Reset the main lookahead buffer */
324 /* If bp_save isn't NULL, we need to scan that first */
326}
327
328/*
329 * Copyright (C) 1976 by the Board of Trustees of the University of Illinois
330 *
331 * All rights reserved
332 *
333 *
334 * NAME: fill_buffer
335 *
336 * FUNCTION: Reads one line of input into in_buffer,
337 * sets up buf_ptr and buf_end to point to the line's start and end+1.
338 * (Note that the buffer does not get null-terminated.)
339 *
340 * HISTORY: initial coding November 1976 D A Willcox of CAC 1/7/77 A
341 * Willcox of CAC Added check for switch back to partly full input
342 * buffer from temporary buffer
343 *
344 */
345void
347{ /* this routine reads stuff from the input */
348 char *p;
349 int i;
350 FILE *f = input;
351
352 if (bp_save != NULL) { /* there is a partly filled input buffer left */
353 buf_ptr = bp_save; /* do not read anything, just switch buffers */
355 bp_save = be_save = NULL;
356 lookahead_bp_save = NULL;
357 if (buf_ptr < buf_end)
358 return; /* only return if there is really something in
359 * this buffer */
360 }
361 for (p = in_buffer;;) {
362 if (p >= in_buffer_limit) {
363 int size = (in_buffer_limit - in_buffer) * 2 + 10;
364 int offset = p - in_buffer;
365 in_buffer = realloc(in_buffer, size);
366 if (in_buffer == NULL)
367 errx(1, "input line too long");
368 p = in_buffer + offset;
369 in_buffer_limit = in_buffer + size - 2;
370 }
372 i = (unsigned char) *lookahead_start++;
373 } else {
375 if ((i = getc(f)) == EOF) {
376 *p++ = ' ';
377 *p++ = '\n';
378 had_eof = true;
379 break;
380 }
381 }
382 if (i != '\0')
383 *p++ = i;
384 if (i == '\n')
385 break;
386 }
388 buf_end = p;
389 if (p - in_buffer > 2 && p[-2] == '/' && p[-3] == '*') {
390 if (in_buffer[3] == 'I' && strncmp(in_buffer, "/**INDENT**", 11) == 0)
391 fill_buffer(); /* flush indent error message */
392 else {
393 int com = 0;
394
395 p = in_buffer;
396 while (*p == ' ' || *p == '\t')
397 p++;
398 if (*p == '/' && p[1] == '*') {
399 p += 2;
400 while (*p == ' ' || *p == '\t')
401 p++;
402 if (p[0] == 'I' && p[1] == 'N' && p[2] == 'D' && p[3] == 'E'
403 && p[4] == 'N' && p[5] == 'T') {
404 p += 6;
405 while (*p == ' ' || *p == '\t')
406 p++;
407 if (*p == '*')
408 com = 1;
409 else if (*p == 'O') {
410 if (*++p == 'N')
411 p++, com = 1;
412 else if (*p == 'F' && *++p == 'F')
413 p++, com = 2;
414 }
415 while (*p == ' ' || *p == '\t')
416 p++;
417 if (p[0] == '*' && p[1] == '/' && p[2] == '\n' && com) {
418 if (s_com != e_com || s_lab != e_lab || s_code != e_code)
419 dump_line();
420 if (!(inhibit_formatting = com - 1)) {
425 }
426 }
427 }
428 }
429 }
430 }
431 if (inhibit_formatting) {
432 p = in_buffer;
433 do
434 putc(*p, output);
435 while (*p++ != '\n');
436 }
437}
438
439/*
440 * Copyright (C) 1976 by the Board of Trustees of the University of Illinois
441 *
442 * All rights reserved
443 *
444 *
445 * NAME: pad_output
446 *
447 * FUNCTION: Writes tabs and spaces to move the current column up to the desired
448 * position.
449 *
450 * ALGORITHM: Put tabs and/or blanks into pobuf, then write pobuf.
451 *
452 * PARAMETERS: current integer The current column
453 * target integer The desired column
454 *
455 * RETURNS: Integer value of the new column. (If current >= target, no action is
456 * taken, and current is returned.
457 *
458 * GLOBALS: None
459 *
460 * CALLS: write (sys)
461 *
462 * CALLED BY: dump_line
463 *
464 * HISTORY: initial coding November 1976 D A Willcox of CAC
465 *
466 */
467static int
468pad_output(int current, int target)
469 /* writes tabs and blanks (if necessary) to
470 * get the current output position up to the
471 * target column */
472 /* current: the current column value */
473 /* target: position we want it at */
474{
475 int curr; /* internal column pointer */
476
477 if (current >= target)
478 return (current); /* line is already long enough */
479 curr = current;
480 if (use_tabs) {
481 int tcur;
482
483 while ((tcur = tabsize * (1 + (curr - 1) / tabsize) + 1) <= target) {
484 putc((!postgres_tab_rules ||
485 tcur != curr + 1 ||
486 target >= tcur + tabsize) ? '\t' : ' ', output);
487 curr = tcur;
488 }
489 }
490 while (curr++ < target)
491 putc(' ', output); /* pad with final blanks */
492
493 return (target);
494}
495
496/*
497 * Copyright (C) 1976 by the Board of Trustees of the University of Illinois
498 *
499 * All rights reserved
500 *
501 *
502 * NAME: count_spaces
503 *
504 * FUNCTION: Find out where printing of a given string will leave the current
505 * character position on output.
506 *
507 * ALGORITHM: Run thru input string and add appropriate values to current
508 * position.
509 *
510 * RETURNS: Integer value of position after printing "buffer" starting in column
511 * "current".
512 *
513 * HISTORY: initial coding November 1976 D A Willcox of CAC
514 *
515 */
516int
517count_spaces_until(int cur, char *buffer, char *end)
518/*
519 * this routine figures out where the character position will be after
520 * printing the text in buffer starting at column "current"
521 */
522{
523 char *buf; /* used to look thru buffer */
524
525 for (buf = buffer; *buf != '\0' && buf != end; ++buf) {
526 switch (*buf) {
527
528 case '\n':
529 case 014: /* form feed */
530 cur = 1;
531 break;
532
533 case '\t':
534 cur = tabsize * (1 + (cur - 1) / tabsize) + 1;
535 break;
536
537 case 010: /* backspace */
538 --cur;
539 break;
540
541 default:
542 ++cur;
543 break;
544 } /* end of switch */
545 } /* end of for loop */
546 return (cur);
547}
548
549int
550count_spaces(int cur, char *buffer)
551{
552 return (count_spaces_until(cur, buffer, NULL));
553}
554
555void
556diag4(int level, const char *msg, int a, int b)
557{
558 if (level)
559 found_err = 1;
560 if (output == stdout) {
561 fprintf(stdout, "/**INDENT** %s@%d: ", level == 0 ? "Warning" : "Error", line_no);
562 fprintf(stdout, msg, a, b);
563 fprintf(stdout, " */\n");
564 }
565 else {
566 fprintf(stderr, "%s@%d: ", level == 0 ? "Warning" : "Error", line_no);
567 fprintf(stderr, msg, a, b);
568 fprintf(stderr, "\n");
569 }
570}
571
572void
573diag3(int level, const char *msg, int a)
574{
575 if (level)
576 found_err = 1;
577 if (output == stdout) {
578 fprintf(stdout, "/**INDENT** %s@%d: ", level == 0 ? "Warning" : "Error", line_no);
579 fprintf(stdout, msg, a);
580 fprintf(stdout, " */\n");
581 }
582 else {
583 fprintf(stderr, "%s@%d: ", level == 0 ? "Warning" : "Error", line_no);
584 fprintf(stderr, msg, a);
585 fprintf(stderr, "\n");
586 }
587}
588
589void
590diag2(int level, const char *msg)
591{
592 if (level)
593 found_err = 1;
594 if (output == stdout) {
595 fprintf(stdout, "/**INDENT** %s@%d: ", level == 0 ? "Warning" : "Error", line_no);
596 fprintf(stdout, "%s", msg);
597 fprintf(stdout, " */\n");
598 }
599 else {
600 fprintf(stderr, "%s@%d: ", level == 0 ? "Warning" : "Error", line_no);
601 fprintf(stderr, "%s", msg);
602 fprintf(stderr, "\n");
603 }
604}
605
#define fprintf(file, fmt, msg)
Definition: cubescan.l:21
struct cursor * cur
Definition: ecpg.c:29
void errx(int eval, const char *fmt,...)
Definition: err.c:58
#define realloc(a, b)
Definition: header.h:60
#define malloc(a)
Definition: header.h:50
char * e_com
int tabsize
int blanklines_after_declarations
int use_tabs
char * in_buffer
#define label_offset
Definition: indent_globs.h:38
int had_eof
int lineup_to_parens
char * s_com
int suppress_blanklines
int postfix_blankline_requested
char * buf_ptr
int prefix_blankline_requested
char * in_buffer_limit
int line_no
int postgres_tab_rules
int inhibit_formatting
int found_err
char * e_code
char * e_lab
char * buf_end
char * s_lab
char * combuf
int max_col
FILE * input
struct parser_state ps
int n_real_blanklines
char * be_save
int swallow_optional_blanklines
int continuation_indent
int code_lines
char * bp_save
float case_ind
char * s_code
FILE * output
int lineup_to_parens_always
static char * lookahead_buf_end
Definition: io.c:52
static char * lookahead_bp_save
Definition: io.c:56
int compute_code_target(void)
Definition: io.c:223
void diag3(int level, const char *msg, int a)
Definition: io.c:573
int lookahead(void)
Definition: io.c:275
int compute_label_target(void)
Definition: io.c:252
int count_spaces(int cur, char *buffer)
Definition: io.c:550
int count_spaces_until(int cur, char *buffer, char *end)
Definition: io.c:517
static char * lookahead_start
Definition: io.c:53
static char * lookahead_buf
Definition: io.c:51
void diag2(int level, const char *msg)
Definition: io.c:590
int comment_open
Definition: io.c:48
static int paren_target
Definition: io.c:49
static int pad_output(int current, int target)
Definition: io.c:468
void lookahead_reset(void)
Definition: io.c:320
void diag4(int level, const char *msg, int a, int b)
Definition: io.c:556
static char * lookahead_ptr
Definition: io.c:54
void fill_buffer(void)
Definition: io.c:346
void dump_line(void)
Definition: io.c:61
static char * lookahead_end
Definition: io.c:55
int b
Definition: isn.c:71
int a
Definition: isn.c:70
int i
Definition: isn.c:74
static char * buf
Definition: pg_test_fsync.c:72
char procname[100]
Definition: indent_globs.h:327
int block_init_level
Definition: indent_globs.h:252
int dumped_decl_indent
Definition: indent_globs.h:321
short paren_indents[20]
Definition: indent_globs.h:300