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
34 static 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 
49 static int paren_target;
50 
51 static char *lookahead_buf; /* malloc'd buffer, or NULL initially */
52 static char *lookahead_buf_end; /* end+1 of allocated space */
53 static char *lookahead_start; /* => next char for fill_buffer() to fetch */
54 static char *lookahead_ptr; /* => next char for lookahead() to fetch */
55 static char *lookahead_end; /* last+1 valid char in lookahead_buf */
56 static char *lookahead_bp_save; /* lookahead position in bp_save, if any */
57 
58 static int pad_output(int current, int target);
59 
60 void
61 dump_line(void)
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 
222 int
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
230  * (2 * continuation_indent == ps.ind_size ? 1 : ps.paren_level);
231  else if (lineup_to_parens_always)
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 
251 int
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  */
274 int
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");
304  lookahead_ptr = new_buf + (lookahead_ptr - lookahead_buf);
305  lookahead_end = new_buf + (lookahead_end - lookahead_buf);
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  */
319 void
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  */
345 void
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 */
354  buf_end = be_save;
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;
366  if (in_buffer == NULL)
367  errx(1, "input line too long");
368  p = in_buffer + offset;
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  }
387  buf_ptr = in_buffer;
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)) {
421  n_real_blanklines = 0;
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  */
467 static int
468 pad_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  */
516 int
517 count_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 
549 int
550 count_spaces(int cur, char *buffer)
551 {
552  return (count_spaces_until(cur, buffer, NULL));
553 }
554 
555 void
556 diag4(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 
572 void
573 diag3(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 
589 void
590 diag2(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 
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:69
int a
Definition: isn.c:68
int i
Definition: isn.c:72
static char * buf
Definition: pg_test_fsync.c:72
#define fprintf
Definition: port.h:242
static pg_noinline void Size size
Definition: slab.c:607
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