/* */
This source file includes following definitions.
- settabs
- read_file_detabing
- detab_replacing
1 /*
2 * Copyright (c) 1996, 1997, 1998, 1999, 2000, 2006
3 * Tama Communications Corporation
4 *
5 * This file is part of GNU GLOBAL.
6 *
7 * This program is free software: you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation, either version 3 of the License, or
10 * (at your option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program. If not, see <http://www.gnu.org/licenses/>.
19 */
20
21 #ifdef HAVE_CONFIG_H
22 #include <config.h>
23 #endif
24 #include <stdio.h>
25
26 #include "die.h"
27 #include "tab.h"
28
29 /*
30 * Puct and getc are very slow on some platforms including GNU/Linux.
31 * Because GLOBAL does not have multi-threaded program,
32 * they can be replaced with non thread safe version.
33 */
34 #ifdef HAVE_PUTC_UNLOCKED
35 #undef putc
36 #define putc putc_unlocked
37 #endif
38 #ifdef HAVE_GETC_UNLOCKED
39 #undef getc
40 #define getc getc_unlocked
41 #endif
42
43 static int tabs = 8;
44
45 /**
46 * settabs: set default tab stop
47 *
48 * @param[in] n tab stop (1...32 only)
49 */
50 void
51 settabs(int n)
52 {
53 if (n < 1 || n > 32)
54 return;
55 tabs = n;
56 }
57 /**
58 * @fn size_t read_file_detabing(char *buf, size_t size, FILE *ip, int *dest_saved, int *spaces_saved)
59 *
60 * Read file converting tabs into spaces.
61 *
62 * @param[out] buf
63 * @param[in] size size of @a buf
64 * @param[in] ip input file
65 * @param[out] dest_saved current column in @a buf
66 * @param[out] spaces_saved left spaces
67 * @return size of data
68 *
69 * @attention
70 * @a dest_saved and @a spaces_saved are control variables. <br>
71 * You must initialize them with 0 (zero) when the input file is opened.
72 */
73 #define PUTSPACES \
74 do { \
75 int n = (spaces < size) ? spaces : size; \
76 dest += n; \
77 size -= n; \
78 spaces -= n; \
79 do { \
80 *p++ = ' '; \
81 } while (--n); \
82 } while (0)
83 size_t
84 read_file_detabing(char *buf, size_t size, FILE *ip, int *dest_saved, int *spaces_saved)
85 {
86 char *p;
87 int c, dest, spaces;
88
89 if (size == 0)
90 return 0;
91 p = buf;
92 dest = *dest_saved;
93 spaces = *spaces_saved;
94 if (spaces > 0)
95 PUTSPACES;
96 while (size > 0) {
97 c = getc(ip);
98 if (c == EOF) {
99 if (ferror(ip))
100 die("read error.");
101 break;
102 }
103 if (c == '\t') {
104 spaces = tabs - dest % tabs;
105 PUTSPACES;
106 } else {
107 *p++ = c;
108 dest++;
109 if (c == '\n')
110 dest = 0;
111 size--;
112 }
113 }
114 *dest_saved = dest;
115 *spaces_saved = spaces;
116 return p - buf;
117 }
118 /**
119 * detab_replacing: convert tabs into spaces and print with replacing.
120 *
121 * @param[in] op @CODE{FILE *}
122 * @param[in] buf string including tabs
123 * @param[in] replace replacing function
124 */
125 void
126 detab_replacing(FILE *op, const char *buf, const char *(*replace)(int c))
127 {
128 int dst, spaces;
129 int c;
130
131 dst = 0;
132 while ((c = *buf++) != '\0') {
133 if (c == '\t') {
134 spaces = tabs - dst % tabs;
135 dst += spaces;
136 do {
137 putc(' ', op);
138 } while (--spaces);
139 } else {
140 const char *s = replace(c);
141 if (s)
142 fputs(s, op);
143 else
144 putc(c, op);
145 dst++;
146 }
147 }
148 putc('\n', op);
149 }
/* */