K&R Ask:
When either a tab or a single blank would suffice to reach a tab stop, which should be given preference?
I’ve chosen to leave blanks that fall short of constituting their own tab stops in place, even if they would position the next non-blank character at a tab column. This is because single spaces anywhere in the program may have this effect, even when they should not be tabs.
For example, consider the following program line:
c h a r l i n e [ M A X L I N E ] ;
- - - - - - - - - - - - - - - - - - - - - - - -
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3
The l
of line[MAXLINE]
is the 10th character of the line; it occurs at the beginning of the second tab stop and immediately following a blank. Should the program consider that a tab or a space? The answer is obvious—(“no”)—but only from the context.
#include <u.h>
#include <libc.h>
#include <bio.h>
#define STDIN 0
#define TABSTOP 5
#define MAXLINE 1000
int getline(Biobuf *buffer, char line[], int maxline);
/* replaces strings of blanks by the minimum number of tabs and blanks to achieve the same spacing */
void
main()
{
char line[MAXLINE];
int len, spaces, i, k;
Biobuf *bstdin;
bstdin = Bfdopen(STDIN, OREAD);
while((len = getline(bstdin, line, MAXLINE)) > 0){
spaces = 0;
for(i = 0; i < len; ++i){
if(line[i] == ' ')
spaces++;
else if(line[i] != ' '){
if(spaces > 0)
for(k = 0; k < spaces; ++k)
print("%c", ' ');
print("%c", line[i]);
spaces = 0;
}
if(spaces == TABSTOP){
print("%c", '\t');
spaces = 0;
}
}
}
}
int getline(Biobuf *b, char s[], int lim)
{
int c, i;
for(i = 0; i<lim-1 && (c=Bgetc(b))>= 0 && c!='\n'; ++i)
s[i] = c;
if(c == '\n'){
s[i] = c;
++i;
}
s[i] = '\0';
return i;
}
$ 9c entab.c; 9l entab.o -o entab
$ ./detab < entab.c | ./entab
#include <u.h>
#include <libc.h>
#include <bio.h>
#define STDIN 0
#define TABSTOP 5
#define MAXLINE 1000
int getline(Biobuf *buffer, char line[], int maxline);
/* replaces strings of blanks by the minimum number of tabs and blanks to achieve the same spacing */
void
main()
{
char line[MAXLINE];
int len, spaces, i, k;
Biobuf *bstdin;
bstdin = Bfdopen(STDIN, OREAD);
while((len = getline(bstdin, line, MAXLINE)) > 0){
spaces = 0;
for(i = 0; i < len; ++i){
if(line[i] == ' ')
spaces++;
else if(line[i] != ' '){
if(spaces > 0)
for(k = 0; k < spaces; ++k)
print("%c", ' ');
print("%c", line[i]);
spaces = 0;
}
if(spaces == TABSTOP){
print("%c", '\t');
spaces = 0;
}
}
}
}
int getline(Biobuf *b, char s[], int lim)
{
int c, i;
for(i = 0; i<lim-1 && (c=Bgetc(b))>= 0 && c!='\n'; ++i)
s[i] = c;
if(c == '\n'){
s[i] = c;
++i;
}
s[i] = '\0';
return i;
}