/* * Retabulates files to different tab stops * * Options: * -f = Inhibit filling with spaces * -s = Convert spaces to tabs where possible * i=n,... = Specify input tab stops * o=n,... = Specify output tab stops * * Notes: * RETAB processes multiple files, and allows the tab settings to be defined * for each file. The '-f -s i= and o=' parameters must be specified BEFORE * the file name where they are to have effect. * * If more tabs are present in the input or output file than were specified * (using I= and O=), RETAB assumes that the tabs continue at the spacing of * the last two stops. Therefore, if the tabs are at regular intervals, only * the first tab stop need be given. * * Both input and output tabs default to 8 space intervals. * * If 'O=0' is specified, RETAB will convert all tabs in the input file to * the appriopriate number of spaces. * * Examples: * retab i=4 tab4.fil >tab8.fil * retab o=4 tab8.fil >tab4.fil * retab i=4 o=2 tab4.file i=8 tab8.fil >tab2.fil * retab o=0 tab8.file >space.fil * * Copyright 1988-1995 Dave Dunfied * All rights reserved. * * Permission granted for personal (non-commercial) use only. * * Compile command: cc retab -fop */ #include #define TAB_STOPS 25 /* maximum number of tab stops supported */ unsigned itabs[TAB_STOPS], otabs[TAB_STOPS]; char fill = -1, space = 0, *ptr; main(argc, argv) int argc; char *argv[]; { unsigned i, j, k, l; FILE *fp; char flag, flag1; flag = -1; flag1 = 0; /* Install default tabs at 8 space intervals */ for(i=j=0; i < TAB_STOPS; ++i) itabs[i] = otabs[i] = (j += 8); /* parse the options and parameters */ for(i=1; i < argc; ++i) { ptr = argv[i]; switch((tolower(*ptr++) << 8) | tolower(*ptr++)) { case '-f': /* disable fill */ fill = 0; goto parm; case '-s': /* enable space processing */ space = -1; goto parm; case '-i': /* specify input tabs */ j = 0; do itabs[j++] = k = l = get_dec(); while(*ptr++ == ','); if(j > 1) k -= itabs[j-2]; while(j < (sizeof(itabs)/2)) itabs[j++] = l += k; goto parm; case 'o=': /* specify output tabs */ j = 0; do otabs[j++] = k = l = get_dec(); while(*ptr++ == ','); if(j > 1) k -= otabs[j-2]; while(j < (sizeof(otabs)/2)) otabs[j++] = l += k; parm: flag1 = -1; break; default: flag = flag1 = 0; if(fp = fopen(argv[i], "r")) { do_convert(fp); fclose(fp); } else { fputs("RETAB: Cannot open: '", stderr); fputs(argv[i], stderr); fputs("'\n", stderr); } } } if(flag1) fputs("RETAB: Trailing options have no effect!!!\n", stderr); if(flag) fputs("\nUse: retab [-f -s i=n,n,n... o=n,n,n] >output_file\n\nCopyright 1988-1995 Dave Dunfield\nAll rights reserved.\n", stderr); } /* get a decimal number from the input line */ get_dec() { unsigned value; value = 0; if(isdigit(*ptr)) { /* decimal number */ while(isdigit(*ptr)) value = (value * 10) + *ptr++ - '0'; } else { fputs("RETAB: Invalid number\n", stderr); exit(-1); } return(value); } /* do the tab conversion */ do_convert(fp) FILE *fp; { unsigned ip, op, i, scount; char chr; ip = op = scount = 0; while((chr = getc(fp)) != -1) { /* read entire file */ if(chr == 0x09) { /* found a tab */ ip += scount; /* offset for any spaces */ for(i=0; ip >= itabs[i]; ++i); /* next input tab position */ ip = itabs[i]; scount = 0; } else if((chr == ' ') && space) /* convert spaces */ ++scount; else { /* std character */ /* * if more than 1 space is encountered, or a single space * is adjacent to a one or more tabs, convert it to tabs. */ if((op < ip) || (scount > 1)) { ip += scount; scount = 0; } /* * if the output pointer lags behind the input pointer * we have received tabs or multiple spaces. Generate * tabs in the output file to restore the position. */ if(op < ip) { /* we have whitespace to fill in */ for(i=0; op >= otabs[i]; ++i); /* next output tab position */ while(otabs[i] <= ip) { putc(0x09, stdout); op = otabs[i++]; } /* * Input pointer is not on an output tab stop, fill with * spaces as nessary, to restore the correct position. */ if(fill) while(op < ip) { putc(' ', stdout); ++op; } else op = ip; } ++ip; /* * Single space received, copy to output file */ if(scount) { putc(' ', stdout); ++op; ++ip; scount = 0; } /* * Copy character into output file */ putc(chr, stdout); ++op; if(chr == '\n') ip = op = 0; } } }