darwin-xnu/osfmk/ddb/db_lex.c
<<
>>
Prefs
   1/*
   2 * Copyright (c) 2000 Apple Computer, Inc. All rights reserved.
   3 *
   4 * @APPLE_LICENSE_HEADER_START@
   5 * 
   6 * The contents of this file constitute Original Code as defined in and
   7 * are subject to the Apple Public Source License Version 1.1 (the
   8 * "License").  You may not use this file except in compliance with the
   9 * License.  Please obtain a copy of the License at
  10 * http://www.apple.com/publicsource and read it before using this file.
  11 * 
  12 * This Original Code and all software distributed under the License are
  13 * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
  14 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
  15 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
  16 * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT.  Please see the
  17 * License for the specific language governing rights and limitations
  18 * under the License.
  19 * 
  20 * @APPLE_LICENSE_HEADER_END@
  21 */
  22/*
  23 * @OSF_COPYRIGHT@
  24 */
  25/*
  26 * HISTORY
  27 * 
  28 * Revision 1.1.1.1  1998/09/22 21:05:48  wsanchez
  29 * Import of Mac OS X kernel (~semeria)
  30 *
  31 * Revision 1.1.1.1  1998/03/07 02:26:09  wsanchez
  32 * Import of OSF Mach kernel (~mburg)
  33 *
  34 * Revision 1.1.11.3  1996/01/09  19:15:49  devrcs
  35 *      Change 'register foo' to 'register int foo'.
  36 *      [1995/12/01  21:42:12  jfraser]
  37 *
  38 *      Merged '64-bit safe' changes from DEC alpha port.
  39 *      [1995/11/21  18:03:11  jfraser]
  40 *
  41 * Revision 1.1.11.2  1995/01/06  19:10:21  devrcs
  42 *      mk6 CR668 - 1.3b26 merge
  43 *      * Revision 1.1.4.6  1994/05/06  18:39:20  tmt
  44 *      Merged osc1.3dec/shared with osc1.3b19
  45 *      Merge Alpha changes into osc1.312b source code.
  46 *      String protos.
  47 *      64bit cleanup.
  48 *      Cleanup to quiet gcc warnings.
  49 *      * End1.3merge
  50 *      [1994/11/04  08:49:35  dwm]
  51 * 
  52 * Revision 1.1.11.1  1994/09/23  01:19:59  ezf
  53 *      change marker to not FREE
  54 *      [1994/09/22  21:10:14  ezf]
  55 * 
  56 * Revision 1.1.4.4  1993/08/11  20:37:55  elliston
  57 *      Add ANSI Prototypes.  CR #9523.
  58 *      [1993/08/11  03:33:26  elliston]
  59 * 
  60 * Revision 1.1.4.3  1993/07/27  18:27:38  elliston
  61 *      Add ANSI prototypes.  CR #9523.
  62 *      [1993/07/27  18:12:13  elliston]
  63 * 
  64 * Revision 1.1.4.2  1993/06/02  23:11:27  jeffc
  65 *      Added to OSF/1 R1.3 from NMK15.0.
  66 *      [1993/06/02  20:56:32  jeffc]
  67 * 
  68 * Revision 1.1  1992/09/30  02:01:10  robert
  69 *      Initial revision
  70 * 
  71 * $EndLog$
  72 */
  73/* CMU_HIST */
  74/*
  75 * Revision 2.5  91/10/09  16:00:20  af
  76 *       Revision 2.4.3.1  91/10/05  13:06:25  jeffreyh
  77 *              Added relational operator tokens and string constant etc.
  78 *              Added input switching functions for macro and conditional command.
  79 *              Moved skip_to_eol() from db_command.c and added db_last_lp to print
  80 *                skipped input data as a warning message.
  81 *              Added last input repetition support to db_read_line.
  82 *              Changed db_lex() to always set db_tok_string for error message.
  83 *              [91/08/29            tak]
  84 * 
  85 * Revision 2.4.3.1  91/10/05  13:06:25  jeffreyh
  86 *      Added relational operator tokens and string constant etc.
  87 *      Added input switching functions for macro and conditional command.
  88 *      Moved skip_to_eol() from db_command.c and added db_last_lp to print
  89 *        skipped input data as a warning message.
  90 *      Added last input repetition support to db_read_line.
  91 *      Changed db_lex() to always set db_tok_string for error message.
  92 *      [91/08/29            tak]
  93 * 
  94 * Revision 2.4  91/05/14  15:34:23  mrt
  95 *      Correcting copyright
  96 *
  97 * Revision 2.3  91/02/05  17:06:36  mrt
  98 *      Changed to new Mach copyright
  99 *      [91/01/31  16:18:20  mrt]
 100 * 
 101 * Revision 2.2  90/08/27  21:51:10  dbg
 102 *      Add 'dotdot' token.
 103 *      [90/08/22            dbg]
 104 * 
 105 *      Allow backslash to quote any character into an identifier.
 106 *      Allow colon in identifier for symbol table qualification.
 107 *      [90/08/16            dbg]
 108 *      Reduce lint.
 109 *      [90/08/07            dbg]
 110 *      Created.
 111 *      [90/07/25            dbg]
 112 * 
 113 */
 114/* CMU_ENDHIST */
 115/* 
 116 * Mach Operating System
 117 * Copyright (c) 1991,1990 Carnegie Mellon University
 118 * All Rights Reserved.
 119 * 
 120 * Permission to use, copy, modify and distribute this software and its
 121 * documentation is hereby granted, provided that both the copyright
 122 * notice and this permission notice appear in all copies of the
 123 * software, derivative works or modified versions, and any portions
 124 * thereof, and that both notices appear in supporting documentation.
 125 * 
 126 * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
 127 * CONDITION.  CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
 128 * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
 129 * 
 130 * Carnegie Mellon requests users of this software to return to
 131 * 
 132 *  Software Distribution Coordinator  or  Software.Distribution@CS.CMU.EDU
 133 *  School of Computer Science
 134 *  Carnegie Mellon University
 135 *  Pittsburgh PA 15213-3890
 136 * 
 137 * any improvements or extensions that they make and grant Carnegie Mellon
 138 * the rights to redistribute these changes.
 139 */
 140/*
 141 */
 142/*
 143 *      Author: David B. Golub, Carnegie Mellon University
 144 *      Date:   7/90
 145 */
 146/*
 147 * Lexical analyzer.
 148 */
 149#include <string.h>                     /* For strcpy(), strncmp(), strlen() */
 150#include <ddb/db_lex.h>
 151#include <ddb/db_command.h>
 152#include <ddb/db_input.h>
 153#include <ddb/db_output.h>              /* For db_printf() */
 154
 155char    db_line[DB_LEX_LINE_SIZE];
 156char    db_last_line[DB_LEX_LINE_SIZE];
 157char    *db_lp, *db_endlp;
 158char    *db_last_lp;
 159int     db_look_char = 0;
 160db_expr_t db_look_token = 0;
 161
 162
 163/* Prototypes for functions local to this file.  XXX -- should be static!
 164 */
 165void db_flush_line(void);
 166void db_unread_char(int c);
 167
 168
 169int
 170db_read_line(char *repeat_last)
 171{
 172        int     i;
 173
 174        i = db_readline(db_line, sizeof(db_line));
 175        if (i == 0)
 176            return (0); /* EOI */
 177        if (repeat_last) {
 178            if (strncmp(db_line, repeat_last, strlen(repeat_last)) == 0) {
 179                strcpy(db_line, db_last_line);
 180                db_printf("%s", db_line);
 181                i = strlen(db_line);
 182            } else if (db_line[0] != '\n' && db_line[0] != 0)
 183                strcpy(db_last_line, db_line);
 184        }
 185        db_lp = db_line;
 186        db_endlp = db_lp + i;
 187        db_last_lp = db_lp;
 188        db_look_char = 0;
 189        db_look_token = 0;
 190        return (i);
 191}
 192
 193void
 194db_flush_line(void)
 195{
 196        db_lp = db_line;
 197        db_last_lp = db_lp;
 198        db_endlp = db_line;
 199}
 200
 201void
 202db_switch_input(
 203        char    *buffer,
 204        int     size)
 205{
 206        db_lp = buffer;
 207        db_last_lp = db_lp;
 208        db_endlp = buffer + size;
 209        db_look_char = 0;
 210        db_look_token = 0;
 211}
 212
 213void
 214db_save_lex_context(register struct db_lex_context *lp)
 215{
 216        lp->l_ptr = db_lp;
 217        lp->l_eptr = db_endlp;
 218        lp->l_char = db_look_char;
 219        lp->l_token = db_look_token;
 220}
 221
 222void
 223db_restore_lex_context(register struct db_lex_context *lp)
 224{
 225        db_lp = lp->l_ptr;
 226        db_last_lp = db_lp;
 227        db_endlp = lp->l_eptr;
 228        db_look_char = lp->l_char;
 229        db_look_token = lp->l_token;
 230}
 231
 232int
 233db_read_char(void)
 234{
 235        int     c;
 236
 237        if (db_look_char != 0) {
 238            c = db_look_char;
 239            db_look_char = 0;
 240        }
 241        else if (db_lp >= db_endlp)
 242            c = -1;
 243        else 
 244            c = *db_lp++;
 245        return (c);
 246}
 247
 248void
 249db_unread_char(int c)
 250{
 251        db_look_char = c;
 252}
 253
 254void
 255db_unread_token(int t)
 256{
 257        db_look_token = t;
 258}
 259
 260int
 261db_read_token(void)
 262{
 263        int     t;
 264
 265        if (db_look_token) {
 266            t = db_look_token;
 267            db_look_token = 0;
 268        }
 269        else {
 270            db_last_lp = db_lp;
 271            if (db_look_char)
 272                db_last_lp--;
 273            t = db_lex();
 274        }
 275        return (t);
 276}
 277
 278db_expr_t db_tok_number;
 279char    db_tok_string[TOK_STRING_SIZE];
 280
 281db_expr_t db_radix = 16;
 282
 283void
 284db_flush_lex(void)
 285{
 286        db_flush_line();
 287        db_look_char = 0;
 288        db_look_token = 0;
 289}
 290
 291#define DB_DISP_SKIP    40              /* number of chars to display skip */
 292
 293void
 294db_skip_to_eol(void)
 295{
 296        register int skip;
 297        register int t;
 298        register int n;
 299        register char *p;
 300
 301        t = db_read_token();
 302        p = db_last_lp;
 303        for (skip = 0; t != tEOL && t != tSEMI_COLON && t != tEOF; skip++)
 304            t = db_read_token();
 305        if (t == tSEMI_COLON)
 306            db_unread_token(t);
 307        if (skip != 0) {
 308            while (p < db_last_lp && (*p == ' ' || *p == '\t'))
 309                p++;
 310            db_printf("Warning: Skipped input data \"");
 311            for (n = 0; n < DB_DISP_SKIP && p < db_last_lp; n++)
 312                db_printf("%c", *p++);
 313            if (n >= DB_DISP_SKIP)
 314                db_printf("....");
 315            db_printf("\"\n");
 316        }
 317}
 318
 319int
 320db_lex(void)
 321{
 322        register char *cp;
 323        register int c;
 324
 325        c = db_read_char();
 326        while (c <= ' ' || c > '~') {
 327            if (c == '\n' || c == -1)
 328                return (tEOL);
 329            c = db_read_char();
 330        }
 331
 332        cp = db_tok_string;
 333        *cp++ = c;
 334
 335        if (c >= '0' && c <= '9') {
 336            /* number */
 337            int r, digit;
 338
 339            if (c > '0')
 340                r = db_radix;
 341            else {
 342                c = db_read_char();
 343                if (c == 'O' || c == 'o')
 344                    r = 8;
 345                else if (c == 'T' || c == 't')
 346                    r = 10;
 347                else if (c == 'X' || c == 'x')
 348                    r = 16;
 349                else {
 350                    cp--;
 351                    r = db_radix;
 352                    db_unread_char(c);
 353                }
 354                c = db_read_char();
 355                *cp++ = c;
 356            }
 357            db_tok_number = 0;
 358            for (;;) {
 359                if (c >= '0' && c <= ((r == 8) ? '7' : '9'))
 360                    digit = c - '0';
 361                else if (r == 16 && ((c >= 'A' && c <= 'F') ||
 362                                     (c >= 'a' && c <= 'f'))) {
 363                    if (c >= 'a')
 364                        digit = c - 'a' + 10;
 365                    else
 366                        digit = c - 'A' + 10;
 367                }
 368                else
 369                    break;
 370                db_tok_number = db_tok_number * r + digit;
 371                c = db_read_char();
 372                if (cp < &db_tok_string[sizeof(db_tok_string)-1])
 373                        *cp++ = c;
 374            }
 375            cp[-1] = 0;
 376            if ((c >= '0' && c <= '9') ||
 377                (c >= 'A' && c <= 'Z') ||
 378                (c >= 'a' && c <= 'z') ||
 379                (c == '_'))
 380            {
 381                db_printf("Bad character '%c' after number %s\n", 
 382                                c, db_tok_string);
 383                db_error(0);
 384                db_flush_lex();
 385                return (tEOF);
 386            }
 387            db_unread_char(c);
 388            return (tNUMBER);
 389        }
 390        if ((c >= 'A' && c <= 'Z') ||
 391            (c >= 'a' && c <= 'z') ||
 392            c == '_' || c == '\\' || c == ':')
 393        {
 394            /* identifier */
 395            if (c == '\\') {
 396                c = db_read_char();
 397                if (c == '\n' || c == -1)
 398                    db_error("Bad '\\' at the end of line\n");
 399                cp[-1] = c;
 400            }
 401            while (1) {
 402                c = db_read_char();
 403                if ((c >= 'A' && c <= 'Z') ||
 404                    (c >= 'a' && c <= 'z') ||
 405                    (c >= '0' && c <= '9') ||
 406                    c == '_' || c == '\\' || c == ':' || c == '.')
 407                {
 408                    if (c == '\\') {
 409                        c = db_read_char();
 410                        if (c == '\n' || c == -1)
 411                            db_error("Bad '\\' at the end of line\n");
 412                    }
 413                    *cp++ = c;
 414                    if (cp == db_tok_string+sizeof(db_tok_string)) {
 415                        db_error("String too long\n");
 416                        db_flush_lex();
 417                        return (tEOF);
 418                    }
 419                    continue;
 420                }
 421                else {
 422                    *cp = '\0';
 423                    break;
 424                }
 425            }
 426            db_unread_char(c);
 427            return (tIDENT);
 428        }
 429
 430        *cp = 0;
 431        switch (c) {
 432            case '+':
 433                return (tPLUS);
 434            case '-':
 435                return (tMINUS);
 436            case '.':
 437                c = db_read_char();
 438                if (c == '.') {
 439                    *cp++ = c;
 440                    *cp = 0;
 441                    return (tDOTDOT);
 442                }
 443                db_unread_char(c);
 444                return (tDOT);
 445            case '*':
 446                return (tSTAR);
 447            case '/':
 448                return (tSLASH);
 449            case '=':
 450                c = db_read_char();
 451                if (c == '=') {
 452                    *cp++ = c;
 453                    *cp = 0;
 454                    return(tLOG_EQ);
 455                }
 456                db_unread_char(c);
 457                return (tEQ);
 458            case '%':
 459                return (tPCT);
 460            case '#':
 461                return (tHASH);
 462            case '(':
 463                return (tLPAREN);
 464            case ')':
 465                return (tRPAREN);
 466            case ',':
 467                return (tCOMMA);
 468            case '\'':
 469                return (tQUOTE);
 470            case '"':
 471                /* string */
 472                cp = db_tok_string;
 473                c = db_read_char();
 474                while (c != '"' && c > 0 && c != '\n') {
 475                    if (cp >= &db_tok_string[sizeof(db_tok_string)-1]) {
 476                        db_error("Too long string\n");
 477                        db_flush_lex();
 478                        return (tEOF);
 479                    }
 480                    if (c == '\\') {
 481                        c = db_read_char();
 482                        switch(c) {
 483                        case 'n':
 484                            c = '\n'; break;
 485                        case 't':
 486                            c = '\t'; break;
 487                        case '\\':
 488                        case '"':
 489                            break;
 490                        default:
 491                            db_printf("Bad escape sequence '\\%c'\n", c);
 492                            db_error(0);
 493                            db_flush_lex();
 494                            return (tEOF);
 495                        }
 496                    }
 497                    *cp++ = c;
 498                    c = db_read_char();
 499                }
 500                *cp = 0;
 501                if (c != '"') {
 502                    db_error("Non terminated string constant\n");
 503                    db_flush_lex();
 504                    return (tEOF);
 505                }
 506                return (tSTRING);
 507            case '$':
 508                return (tDOLLAR);
 509            case '!':
 510                c = db_read_char();
 511                if (c == '=') {
 512                    *cp++ = c;
 513                    *cp = 0;
 514                    return(tLOG_NOT_EQ);
 515                }
 516                db_unread_char(c);
 517                return (tEXCL);
 518            case '&':
 519                c = db_read_char();
 520                if (c == '&') {
 521                    *cp++ = c;
 522                    *cp = 0;
 523                    return(tLOG_AND);
 524                }
 525                db_unread_char(c);
 526                return(tBIT_AND);
 527            case '|':
 528                c = db_read_char();
 529                if (c == '|') {
 530                    *cp++ = c;
 531                    *cp = 0;
 532                    return(tLOG_OR);
 533                }
 534                db_unread_char(c);
 535                return(tBIT_OR);
 536            case '<':
 537                c = db_read_char();
 538                *cp++ = c;
 539                *cp = 0;
 540                if (c == '<')
 541                    return (tSHIFT_L);
 542                if (c == '=')
 543                    return (tLESS_EQ);
 544                cp[-1] = 0;
 545                db_unread_char(c);
 546                return(tLESS);
 547                break;
 548            case '>':
 549                c = db_read_char();
 550                *cp++ = c;
 551                *cp = 0;
 552                if (c == '>')
 553                    return (tSHIFT_R);
 554                if (c == '=')
 555                    return (tGREATER_EQ);
 556                cp[-1] = 0;
 557                db_unread_char(c);
 558                return (tGREATER);
 559                break;
 560            case ';':
 561                return (tSEMI_COLON);
 562            case '?':
 563                return (tQUESTION);
 564            case -1:
 565                strcpy(db_tok_string, "<EOL>");
 566                return (tEOF);
 567        }
 568        db_printf("Bad character '%c'\n", c);
 569        db_flush_lex();
 570        return (tEOF);
 571}
 572
lxr.linux.no kindly hosted by Redpill Linpro AS, provider of Linux consulting and operations services since 1995.