root/libutil/token.c

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

DEFINITIONS

This source file includes following definitions.
  1. opentoken
  2. closetoken
  3. nexttoken
  4. pushbacktoken
  5. peekc
  6. throwaway_nextchar
  7. atfirst_exceptspace
  8. pushbackchar

   1 /*
   2  * Copyright (c) 1998, 1999, 2000, 2002, 2003, 2008
   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 <ctype.h>
  25 #include <stdio.h>
  26 #ifdef HAVE_STRING_H
  27 #include <string.h>
  28 #else
  29 #include <strings.h>
  30 #endif
  31 
  32 #include "die.h"
  33 #include "gparam.h"
  34 #include "strlimcpy.h"
  35 #include "token.h"
  36 
  37 /*
  38  * File input method.
  39  */
  40 int lineno;
  41 const char *sp, *cp, *lp;
  42 int crflag;                     /**< 1: return '\\n', 0: doesn't return */
  43 int cmode;                      /**< allow token which start with '\#' */
  44 int cppmode;                    /**< allow '\::' as a token */
  45 int ymode;                      /**< allow token which start with '\%' */
  46 char token[MAXTOKEN];
  47 char curfile[MAXPATHLEN];
  48 int continued_line;             /**< previous line ends with '\\\\' */
  49 
  50 static char ptok[MAXTOKEN];
  51 static int lasttok;
  52 static FILE *ip;
  53 static STRBUF *ib;
  54 
  55 #define tlen    (p - &token[0])
  56 static void pushbackchar(void);
  57 
  58 /**
  59  * opentoken:
  60  *
  61  *      @param[in]      file
  62  */
  63 int
  64 opentoken(const char *file)
  65 {
  66         /*
  67          * b flag is needed for WIN32 environment. Almost unix ignore it.
  68          */
  69         if ((ip = fopen(file, "rb")) == NULL)
  70                 return 0;
  71         ib = strbuf_open(MAXBUFLEN);
  72         strlimcpy(curfile, file, sizeof(curfile));
  73         sp = cp = lp = NULL; ptok[0] = '\0'; lineno = 0;
  74         crflag = cmode = cppmode = ymode = 0;
  75         continued_line = 0;
  76         return 1;
  77 }
  78 /**
  79  * closetoken:
  80  */
  81 void
  82 closetoken(void)
  83 {
  84         strbuf_close(ib);
  85         fclose(ip);
  86 }
  87 
  88 /**
  89  * nexttoken: get next token
  90  *
  91  *      @param[in]      interested      interested special character <br>
  92  *                              if @VAR{NULL} then all character.
  93  *      @param[in]      reserved        converter from token to token number <br>
  94  *                              if this is specified, nexttoken() return <br>
  95  *                              word number, else return symbol.
  96  *      @return @VAR{EOF}(-1)   end of file <br>
  97  *              c ==0           symbol (#SYMBOL; #token has the value.) <br>
  98  *              c \< 256                interested special character <br>
  99  *              c \> 1000       reserved word
 100  *
 101  * @note nexttoken() doesn't return followings:
 102  * - comment
 103  * - space (@CODE{' '}, @CODE{'\\t'}, @CODE{'\\f'}, @CODE{'\\v'}, @CODE{'\\r'})
 104  * - quoted string (@CODE{\"...\"}, @CODE{'.'})
 105  * - number
 106  */
 107 
 108 int
 109 nexttoken(const char *interested, int (*reserved)(const char *, int))
 110 {
 111         int c;
 112         char *p;
 113         int sharp = 0;
 114         int percent = 0;
 115 
 116         /* check push back buffer */
 117         if (ptok[0]) {
 118                 strlimcpy(token, ptok, sizeof(token));
 119                 ptok[0] = '\0';
 120                 return lasttok;
 121         }
 122 
 123         for (;;) {
 124                 /* skip spaces */
 125                 if (!crflag)
 126                         while ((c = nextchar()) != EOF && isspace(c))
 127                                 ;
 128                 else
 129                         while ((c = nextchar()) != EOF && isspace(c) && c != '\n')
 130                                 ;
 131                 if (c == EOF || c == '\n')
 132                         break;
 133 
 134                 if (c == '"' || c == '\'') {    /* quoted string */
 135                         int quote = c;
 136 
 137                         while ((c = nextchar()) != EOF) {
 138                                 if (c == quote)
 139                                         break;
 140                                 if (quote == '\'' && c == '\n')
 141                                         break;
 142                                 if (c == '\\' && (c = nextchar()) == EOF)
 143                                         break;
 144                         }
 145                 } else if (c == '/') {                  /* comment */
 146                         if ((c = nextchar()) == '/') {
 147                                 while ((c = nextchar()) != EOF)
 148                                         if (c == '\n') {
 149                                                 pushbackchar();
 150                                                 break;
 151                                         }
 152                         } else if (c == '*') {
 153                                 while ((c = nextchar()) != EOF) {
 154                                         if (c == '*') {
 155                                                 if ((c = nextchar()) == '/')
 156                                                         break;
 157                                                 pushbackchar();
 158                                         }
 159                                 }
 160                         } else
 161                                 pushbackchar();
 162                 } else if (c == '\\') {
 163                         if (nextchar() == '\n')
 164                                 continued_line = 1;
 165                 } else if (isdigit(c)) {                /* digit */
 166                         while ((c = nextchar()) != EOF && (c == '.' || isalnum(c)))
 167                                 ;
 168                         pushbackchar();
 169                 } else if (c == '#' && cmode) {
 170                         /* recognize '##' as a token if it is reserved word. */
 171                         if (peekc(1) == '#') {
 172                                 p = token;
 173                                 *p++ = c;
 174                                 *p++ = nextchar();
 175                                 *p   = 0;
 176                                 if (reserved && (c = (*reserved)(token, tlen)) == 0)
 177                                         break;
 178                         } else if (!continued_line && atfirst_exceptspace()) {
 179                                 sharp = 1;
 180                                 continue;
 181                         }
 182                 } else if (c == ':' && cppmode) {
 183                         if (peekc(1) == ':') {
 184                                 p = token;
 185                                 *p++ = c;
 186                                 *p++ = nextchar();
 187                                 *p   = 0;
 188                                 if (reserved && (c = (*reserved)(token, tlen)) == 0)
 189                                         break;
 190                         }
 191                 } else if (c == '%' && ymode) {
 192                         /* recognize '%%' as a token if it is reserved word. */
 193                         if (atfirst) {
 194                                 p = token;
 195                                 *p++ = c;
 196                                 if ((c = peekc(1)) == '%' || c == '{' || c == '}') {
 197                                         *p++ = nextchar();
 198                                         *p   = 0;
 199                                         if (reserved && (c = (*reserved)(token, tlen)) != 0)
 200                                                 break;
 201                                 } else if (!isspace(c)) {
 202                                         percent = 1;
 203                                         continue;
 204                                 }
 205                         }
 206                 } else if (c & 0x80 || isalpha(c) || c == '_') {/* symbol */
 207                         p = token;
 208                         if (sharp) {
 209                                 sharp = 0;
 210                                 *p++ = '#';
 211                         } else if (percent) {
 212                                 percent = 0;
 213                                 *p++ = '%';
 214                         } else if (c == 'L') {
 215                                 int tmp = peekc(1);
 216 
 217                                 if (tmp == '\"' || tmp == '\'')
 218                                         continue;
 219                         }
 220                         for (*p++ = c; (c = nextchar()) != EOF && (c & 0x80 || isalnum(c) || c == '_');) {
 221                                 if (tlen < sizeof(token))
 222                                         *p++ = c;
 223                         }
 224                         if (tlen == sizeof(token)) {
 225                                 warning("symbol name is too long. (Ignored)[+%d %s]", lineno, curfile);
 226                                 continue;
 227                         }
 228                         *p = 0;
 229         
 230                         if (c != EOF)
 231                                 pushbackchar();
 232                         /* convert token string into token number */
 233                         c = SYMBOL;
 234                         if (reserved)
 235                                 c = (*reserved)(token, tlen);
 236                         break;
 237                 } else {                                /* special char */
 238                         if (interested == NULL || strchr(interested, c))
 239                                 break;
 240                         /* otherwise ignore it */
 241                 }
 242                 sharp = percent = 0;
 243         }
 244         return lasttok = c;
 245 }
 246 /**
 247  * pushbacktoken: push back token
 248  *
 249  *      following nexttoken() return same token again.
 250  */
 251 void
 252 pushbacktoken(void)
 253 {
 254         strlimcpy(ptok, token, sizeof(ptok));
 255 }
 256 /**
 257  * peekc: peek next char
 258  *
 259  *      @param[in]      immediate       0: ignore blank, 1: include blank
 260  *
 261  * peekc() read ahead following blanks but doesn't change line.
 262  */
 263 int
 264 peekc(int immediate)
 265 {
 266         int c;
 267         long pos;
 268     int comment = 0;
 269 
 270         if (cp != NULL) {
 271                 if (immediate)
 272                         c = nextchar();
 273                 else
 274             while ((c = nextchar()) != EOF && c != '\n') {
 275                 if (c == '/') {                 /* comment */
 276                     if ((c = nextchar()) == '/') {
 277                         while ((c = nextchar()) != EOF)
 278                             if (c == '\n') {
 279                                 pushbackchar();
 280                                 break;
 281                             }
 282                     } else if (c == '*') {
 283                         comment = 1;
 284                         while ((c = nextchar()) != EOF) {
 285                             if (c == '*') {
 286                                 if ((c = nextchar()) == '/')
 287                                 {
 288                                     comment = 0;
 289                                     break;
 290                                 }
 291                             }
 292                             else if (c == '\n')
 293                             {
 294                                 pushbackchar();
 295                                 break;
 296                             }
 297                         }
 298                     } else
 299                         pushbackchar();
 300                 }
 301                 else if (!isspace(c))
 302                     break;
 303             }
 304                 if (c != EOF)
 305                         pushbackchar();
 306                 if (c != '\n' || immediate)
 307                         return c;
 308         }
 309         pos = ftell(ip);
 310         if (immediate)
 311                 c = getc(ip);
 312         else
 313         while ((c = getc(ip)) != EOF) {
 314             if (comment) {
 315                 while ((c = getc(ip)) != EOF) {
 316                     if (c == '*') {
 317                         if ((c = getc(ip)) == '/')
 318                         {
 319                             comment = 0;
 320                             break;
 321                         }
 322                     }
 323                 }
 324             }
 325             else if (c == '/') {                        /* comment */
 326                 if ((c = getc(ip)) == '/') {
 327                     while ((c = getc(ip)) != EOF)
 328                         if (c == '\n') {
 329                             break;
 330                         }
 331                 } else if (c == '*') {
 332                     while ((c = getc(ip)) != EOF) {
 333                         if (c == '*') {
 334                             if ((c = getc(ip)) == '/')
 335                                 break;
 336                         }
 337                     }
 338                 } else
 339                     break;
 340             }
 341             else if (!isspace(c))
 342                 break;
 343         }
 344 
 345         (void)fseek(ip, pos, SEEK_SET);
 346 
 347         return c;
 348 }
 349 /**
 350  * throwaway_nextchar: throw away next character
 351  */
 352 void
 353 throwaway_nextchar(void)
 354 {
 355         nextchar();
 356 }
 357 /**
 358  * atfirst_exceptspace: return if current position is the first column
 359  *                      except for space.
 360  * @code
 361  *      |      1 0
 362  *      |      v v
 363  *      |      # define
 364  * @endcode
 365  */
 366 int
 367 atfirst_exceptspace(void)
 368 {
 369         const char *start = sp;
 370         const char *end = cp ? cp - 1 : lp;
 371 
 372         while (start < end && *start && isspace(*start))
 373                 start++;
 374         return (start == end) ? 1 : 0;
 375 }
 376 /**
 377  * pushbackchar: push back character.
 378  *
 379  *      following nextchar() return same character again.
 380  * 
 381  */
 382 static void
 383 pushbackchar(void)
 384 {
 385         if (sp == NULL)
 386                 return;         /* nothing to do */
 387         if (cp == NULL)
 388                 cp = lp;
 389         else
 390                 --cp;
 391 }

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