root/libutil/tab.c

/* [previous][next][first][last][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. settabs
  2. read_file_detabing
  3. 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 }

/* [previous][next][first][last][top][bottom][index][help] */