Annotation of GNUtools/emacs/src/syntax.c, revision 1.1

1.1     ! root        1: /* GNU Emacs routines to deal with syntax tables; also word and list parsing.
        !             2:    Copyright (C) 1985, 1987, 1990 Free Software Foundation, Inc.
        !             3: 
        !             4: This file is part of GNU Emacs.
        !             5: 
        !             6: GNU Emacs is free software; you can redistribute it and/or modify
        !             7: it under the terms of the GNU General Public License as published by
        !             8: the Free Software Foundation; either version 1, or (at your option)
        !             9: any later version.
        !            10: 
        !            11: GNU Emacs is distributed in the hope that it will be useful,
        !            12: but WITHOUT ANY WARRANTY; without even the implied warranty of
        !            13: MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
        !            14: GNU General Public License for more details.
        !            15: 
        !            16: You should have received a copy of the GNU General Public License
        !            17: along with GNU Emacs; see the file COPYING.  If not, write to
        !            18: the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
        !            19: 
        !            20: 
        !            21: #include "config.h"
        !            22: #include <ctype.h>
        !            23: #include "lisp.h"
        !            24: #include "commands.h"
        !            25: #include "buffer.h"
        !            26: #include "syntax.h"
        !            27: 
        !            28: Lisp_Object Qsyntax_table_p;
        !            29: 
        !            30: DEFUN ("syntax-table-p", Fsyntax_table_p, Ssyntax_table_p, 1, 1, 0,
        !            31:   "Return t if ARG is a syntax table.\n\
        !            32: Any vector of 256 elements will do.")
        !            33:   (obj)
        !            34:      Lisp_Object obj;
        !            35: {
        !            36:   if (XTYPE (obj) == Lisp_Vector && XVECTOR (obj)->size == 0400)
        !            37:     return Qt;
        !            38:   return Qnil;
        !            39: }
        !            40: 
        !            41: Lisp_Object
        !            42: check_syntax_table (obj)
        !            43:      Lisp_Object obj;
        !            44: {
        !            45:   register Lisp_Object tem;
        !            46:   while (tem = Fsyntax_table_p (obj),
        !            47:         NULL (tem))
        !            48:     obj = wrong_type_argument (Qsyntax_table_p, obj, 0);
        !            49:   return obj;
        !            50: }   
        !            51: 
        !            52: 
        !            53: DEFUN ("syntax-table", Fsyntax_table, Ssyntax_table, 0, 0, 0,
        !            54:   "Return the current syntax table.\n\
        !            55: This is the one specified by the current buffer.")
        !            56:   ()
        !            57: {
        !            58:   return current_buffer->syntax_table;
        !            59: }
        !            60: 
        !            61: DEFUN ("standard-syntax-table", Fstandard_syntax_table,
        !            62:    Sstandard_syntax_table, 0, 0, 0,
        !            63:   "Return the standard syntax table.\n\
        !            64: This is the one used for new buffers.")
        !            65:   ()
        !            66: {
        !            67:   return Vstandard_syntax_table;
        !            68: }
        !            69: 
        !            70: DEFUN ("copy-syntax-table", Fcopy_syntax_table, Scopy_syntax_table, 0, 1, 0,
        !            71:   "Construct a new syntax table and return it.\n\
        !            72: It is a copy of the TABLE, which defaults to the standard syntax table.")
        !            73:   (table)
        !            74:      Lisp_Object table;
        !            75: {
        !            76:   Lisp_Object size, val;
        !            77:   XFASTINT (size) = 0400;
        !            78:   XFASTINT (val) = 0;
        !            79:   val = Fmake_vector (size, val);
        !            80:   if (!NULL (table))
        !            81:     table = check_syntax_table (table);
        !            82:   else if (NULL (Vstandard_syntax_table))
        !            83:     /* Can only be null during initialization */
        !            84:     return val;
        !            85:   else table = Vstandard_syntax_table;
        !            86: 
        !            87:   bcopy (XVECTOR (table)->contents,
        !            88:         XVECTOR (val)->contents, 0400 * sizeof (Lisp_Object));
        !            89:   return val;
        !            90: }
        !            91: 
        !            92: DEFUN ("set-syntax-table", Fset_syntax_table, Sset_syntax_table, 1, 1, 0,
        !            93:   "Select a new syntax table for the current buffer.\n\
        !            94: One argument, a syntax table.")
        !            95:   (table)
        !            96:      Lisp_Object table;
        !            97: {
        !            98:   table = check_syntax_table (table);
        !            99:   current_buffer->syntax_table = table;
        !           100:   /* Indicate that this buffer now has a specified syntax table.  */
        !           101:   current_buffer->local_var_flags |= buffer_local_flags.syntax_table;
        !           102:   return table;
        !           103: }
        !           104: 
        !           105: /* Convert a letter which signifies a syntax code
        !           106:  into the code it signifies.
        !           107:  This is used by modify-syntax-entry, and other things. */
        !           108: 
        !           109: unsigned char syntax_spec_code[0400] =
        !           110:   { 0377, 0377, 0377, 0377, 0377, 0377, 0377, 0377,
        !           111:     0377, 0377, 0377, 0377, 0377, 0377, 0377, 0377,
        !           112:     0377, 0377, 0377, 0377, 0377, 0377, 0377, 0377,
        !           113:     0377, 0377, 0377, 0377, 0377, 0377, 0377, 0377,
        !           114:     (char) Swhitespace, 0377, (char) Sstring, 0377,
        !           115:         (char) Smath, 0377, 0377, (char) Squote,
        !           116:     (char) Sopen, (char) Sclose, 0377, 0377,
        !           117:        0377, (char) Swhitespace, (char) Spunct, (char) Scharquote,
        !           118:     0377, 0377, 0377, 0377, 0377, 0377, 0377, 0377,
        !           119:     0377, 0377, 0377, 0377,
        !           120:        (char) Scomment, 0377, (char) Sendcomment, 0377,
        !           121:     0377, 0377, 0377, 0377, 0377, 0377, 0377, 0377,   /* @, A, ... */
        !           122:     0377, 0377, 0377, 0377, 0377, 0377, 0377, 0377,
        !           123:     0377, 0377, 0377, 0377, 0377, 0377, 0377, (char) Sword,
        !           124:     0377, 0377, 0377, 0377, (char) Sescape, 0377, 0377, (char) Ssymbol,
        !           125:     0377, 0377, 0377, 0377, 0377, 0377, 0377, 0377,   /* `, a, ... */
        !           126:     0377, 0377, 0377, 0377, 0377, 0377, 0377, 0377,
        !           127:     0377, 0377, 0377, 0377, 0377, 0377, 0377, (char) Sword,
        !           128:     0377, 0377, 0377, 0377, 0377, 0377, 0377, 0377
        !           129:   };
        !           130: 
        !           131: /* Indexed by syntax code, give the letter that describes it. */
        !           132: 
        !           133: char syntax_code_spec[13] =
        !           134:   {
        !           135:     ' ', '.', 'w', '_', '(', ')', '\'', '\"', '$', '\\', '/', '<', '>'
        !           136:   };
        !           137: 
        !           138: DEFUN ("char-syntax", Fchar_syntax, Schar_syntax, 1, 1, 0,
        !           139:   "Return the syntax code of CHAR, described by a character.\n\
        !           140: For example, if CHAR is a word constituent, ?w is returned.\n\
        !           141: The characters that correspond to various syntax codes\n\
        !           142: are listed in the documentation of  modify-syntax-entry.")
        !           143:   (ch)
        !           144:      Lisp_Object ch;
        !           145: {
        !           146:   CHECK_NUMBER (ch, 0);
        !           147:   return make_number (syntax_code_spec[(int) SYNTAX (0xFF & XINT (ch))]);
        !           148: }
        !           149: 
        !           150: /* This comment supplies the doc string for modify-syntax-entry,
        !           151:    for make-docfile to see.  We cannot put this in the real DEFUN
        !           152:    due to limits in the Unix cpp.
        !           153: 
        !           154: DEFUN ("modify-syntax-entry", foo, bar, 0, 0, 0,
        !           155:   "Set syntax for character CHAR according to string S.\n\
        !           156: The syntax is changed only for table TABLE, which defaults to\n\
        !           157:  the current buffer's syntax table.\n\
        !           158: The first character of S should be one of the following:\n\
        !           159:   Space or -   whitespace syntax.    w   word constituent.\n\
        !           160:   _            symbol constituent.   .   punctuation.\n\
        !           161:   (            open-parenthesis.     )   close-parenthesis.\n\
        !           162:   \"            string quote.         \\   escape character.\n\
        !           163:   $            paired delimiter.     '   expression prefix operator.\n\
        !           164:   <            comment starter.      >   comment ender.\n\
        !           165:   /           character quote.\n\
        !           166: Only single-character comment start and end sequences are represented thus.\n\
        !           167: Two-character sequences are represented as described below.\n\
        !           168: The second character of S is the matching parenthesis,\n\
        !           169:  used only if the first character is ( or ).\n\
        !           170: Any additional characters are flags.\n\
        !           171: Defined flags are the characters 1, 2, 3 and 4.\n\
        !           172:  1 means C is the start of a two-char comment start sequence.\n\
        !           173:  2 means C is the second character of such a sequence.\n\
        !           174:  3 means C is the start of a two-char comment end sequence.\n\
        !           175:  4 means C is the second character of such a sequence.")
        !           176: 
        !           177: */
        !           178: 
        !           179: DEFUN ("modify-syntax-entry", Fmodify_syntax_entry, Smodify_syntax_entry, 2, 3, 
        !           180:   /* I really don't know why this is interactive
        !           181:      help-form should at least be made useful whilst reading the second arg
        !           182:    */
        !           183:   "cSet syntax for character: \nsSet syntax for %s to: ",
        !           184:   0 /* See immediately above */)
        !           185:   (c, newentry, syntax_table)
        !           186:      Lisp_Object c, newentry, syntax_table;
        !           187: {
        !           188:   register unsigned char *p, match;
        !           189:   register enum syntaxcode code;
        !           190:   Lisp_Object val;
        !           191: 
        !           192:   CHECK_NUMBER (c, 0);
        !           193:   CHECK_STRING (newentry, 1);
        !           194:   if (NULL (syntax_table))
        !           195:     syntax_table = current_buffer->syntax_table;
        !           196:   else
        !           197:     syntax_table = check_syntax_table (syntax_table);
        !           198: 
        !           199:   p = XSTRING (newentry)->data;
        !           200:   code = (enum syntaxcode) syntax_spec_code[*p++];
        !           201:   if (((int) code & 0377) == 0377)
        !           202:     error ("invalid syntax description letter: %c", c);
        !           203: 
        !           204:   match = *p;
        !           205:   if (match) p++;
        !           206:   if (match == ' ') match = 0;
        !           207: 
        !           208:   XFASTINT (val) = (match << 8) + (int) code;
        !           209:   while (*p)
        !           210:     switch (*p++)
        !           211:       {
        !           212:       case '1':
        !           213:        XFASTINT (val) |= 1 << 16;
        !           214:        break;
        !           215: 
        !           216:       case '2':
        !           217:        XFASTINT (val) |= 1 << 17;
        !           218:        break;
        !           219: 
        !           220:       case '3':
        !           221:        XFASTINT (val) |= 1 << 18;
        !           222:        break;
        !           223: 
        !           224:       case '4':
        !           225:        XFASTINT (val) |= 1 << 19;
        !           226:        break;
        !           227:       }
        !           228:        
        !           229:   XVECTOR (syntax_table)->contents[0xFF & XINT (c)] = val;
        !           230: 
        !           231:   return Qnil;
        !           232: }
        !           233: 
        !           234: /* Dump syntax table to buffer in human-readable format */
        !           235: 
        !           236: describe_syntax (value)
        !           237:     Lisp_Object value;
        !           238: {
        !           239:   register enum syntaxcode code;
        !           240:   char desc, match, start1, start2, end1, end2;
        !           241:   char str[2];
        !           242: 
        !           243:   Findent_to (make_number (16), make_number (1));
        !           244: 
        !           245:   if (XTYPE (value) != Lisp_Int)
        !           246:     {
        !           247:       InsStr ("invalid");
        !           248:       return;
        !           249:     }
        !           250: 
        !           251:   code = (enum syntaxcode) (XINT (value) & 0377);
        !           252:   match = (XINT (value) >> 8) & 0377;
        !           253:   start1 = (XINT (value) >> 16) & 1;
        !           254:   start2 = (XINT (value) >> 17) & 1;
        !           255:   end1 = (XINT (value) >> 18) & 1;
        !           256:   end2 = (XINT (value) >> 19) & 1;
        !           257: 
        !           258:   if ((int) code < 0 || (int) code >= (int) Smax)
        !           259:     {
        !           260:       InsStr ("invalid");
        !           261:       return;
        !           262:     }
        !           263:   desc = syntax_code_spec[(int) code];
        !           264: 
        !           265:   str[0] = desc, str[1] = 0;
        !           266:   insert (str, 1);
        !           267: 
        !           268:   str[0] = match ? match : ' ';
        !           269:   insert (str, 1);
        !           270: 
        !           271: 
        !           272:   if (start1)
        !           273:     insert ("1", 1);
        !           274:   if (start2)
        !           275:     insert ("2", 1);
        !           276: 
        !           277:   if (end1)
        !           278:     insert ("3", 1);
        !           279:   if (end2)
        !           280:     insert ("4", 1);
        !           281: 
        !           282:   InsStr ("\twhich means: ");
        !           283: 
        !           284: #ifdef SWITCH_ENUM_BUG
        !           285:   switch ((int) code)
        !           286: #else
        !           287:   switch (code)
        !           288: #endif
        !           289:     {
        !           290:     case Swhitespace:
        !           291:       InsStr ("whitespace"); break;
        !           292:     case Spunct:
        !           293:       InsStr ("punctuation"); break;
        !           294:     case Sword:
        !           295:       InsStr ("word"); break;
        !           296:     case Ssymbol:
        !           297:       InsStr ("symbol"); break;
        !           298:     case Sopen:
        !           299:       InsStr ("open"); break;
        !           300:     case Sclose:
        !           301:       InsStr ("close"); break;
        !           302:     case Squote:
        !           303:       InsStr ("quote"); break;
        !           304:     case Sstring:
        !           305:       InsStr ("string"); break;
        !           306:     case Smath:
        !           307:       InsStr ("math"); break;
        !           308:     case Sescape:
        !           309:       InsStr ("escape"); break;
        !           310:     case Scharquote:
        !           311:       InsStr ("charquote"); break;
        !           312:     case Scomment:
        !           313:       InsStr ("comment"); break;
        !           314:     case Sendcomment:
        !           315:       InsStr ("endcomment"); break;
        !           316:     default:
        !           317:       InsStr ("invalid");
        !           318:       return;
        !           319:     }
        !           320: 
        !           321:   if (match)
        !           322:     {
        !           323:       InsStr (", matches ");
        !           324:       
        !           325:       str[0] = match, str[1] = 0;
        !           326:       insert (str, 1);
        !           327:     }
        !           328: 
        !           329:   if (start1)
        !           330:     InsStr (",\n\t  is the first character of a comment-start sequence");
        !           331:   if (start2)
        !           332:     InsStr (",\n\t  is the second character of a comment-start sequence");
        !           333: 
        !           334:   if (end1)
        !           335:     InsStr (",\n\t  is the first character of a comment-end sequence");
        !           336:   if (end2)
        !           337:     InsStr (",\n\t  is the second character of a comment-end sequence");
        !           338: 
        !           339:   InsStr ("\n");
        !           340: }
        !           341: 
        !           342: Lisp_Object
        !           343: describe_syntax_1 (vector)
        !           344:      Lisp_Object vector;
        !           345: {
        !           346:   struct buffer *old = current_buffer;
        !           347:   set_buffer_internal (XBUFFER (Vstandard_output));
        !           348:   describe_vector (vector, Qnil, describe_syntax, 0, Qnil);
        !           349:   set_buffer_internal (old);
        !           350:   return Qnil;
        !           351: }
        !           352: 
        !           353: DEFUN ("describe-syntax", Fdescribe_syntax, Sdescribe_syntax, 0, 0, "",
        !           354:   "Describe the syntax specifications in the syntax table.\n\
        !           355: The descriptions are inserted in a buffer, which is selected so you can see it.")
        !           356:   ()
        !           357: {
        !           358:   internal_with_output_to_temp_buffer
        !           359:      ("*Help*", describe_syntax_1, current_buffer->syntax_table);
        !           360: 
        !           361:   return Qnil;
        !           362: }
        !           363: 
        !           364: /* Return the position across `count' words from `from'.
        !           365:    If that many words cannot be found before the end of the buffer, return 0.
        !           366:    `count' negative means scan backward and stop at word beginning.  */
        !           367: 
        !           368: scan_words (from, count)
        !           369:      register int from, count;
        !           370: {
        !           371:   register int beg = BEGV;
        !           372:   register int end = ZV;
        !           373: 
        !           374:   immediate_quit = 1;
        !           375:   QUIT;
        !           376: 
        !           377:   while (count > 0)
        !           378:     {
        !           379:       while (1)
        !           380:        {
        !           381:          if (from == end)
        !           382:            {
        !           383:              immediate_quit = 0;
        !           384:              return 0;
        !           385:            }
        !           386:          if (SYNTAX(FETCH_CHAR (from)) == Sword)
        !           387:            break;
        !           388:          from++;
        !           389:        }
        !           390:       while (1)
        !           391:        {
        !           392:          if (from == end) break;
        !           393:          if (SYNTAX(FETCH_CHAR (from)) != Sword)
        !           394:            break;
        !           395:          from++;
        !           396:        }
        !           397:       count--;
        !           398:     }
        !           399:   while (count < 0)
        !           400:     {
        !           401:       while (1)
        !           402:        {
        !           403:          if (from == beg)
        !           404:            {
        !           405:              immediate_quit = 0;
        !           406:              return 0;
        !           407:            }
        !           408:          if (SYNTAX(FETCH_CHAR (from - 1)) == Sword)
        !           409:            break;
        !           410:          from--;
        !           411:        }
        !           412:       while (1)
        !           413:        {
        !           414:          if (from == beg) break;
        !           415:          if (SYNTAX(FETCH_CHAR (from - 1)) != Sword)
        !           416:            break;
        !           417:          from--;
        !           418:        }
        !           419:       count++;
        !           420:     }
        !           421: 
        !           422:   immediate_quit = 0;
        !           423: 
        !           424:   return from;
        !           425: }
        !           426: 
        !           427: DEFUN ("forward-word", Fforward_word, Sforward_word, 1, 1, "p",
        !           428:   "Move point forward ARG words (backward if ARG is negative).\n\
        !           429: Normally returns t.\n\
        !           430: If an edge of the buffer is reached, point is left there\n\
        !           431: and nil is returned.")
        !           432:   (count)
        !           433:      Lisp_Object count;
        !           434: {
        !           435:   int val;
        !           436:   CHECK_NUMBER (count, 0);
        !           437: 
        !           438:   if (!(val = scan_words (point, XINT (count))))
        !           439:     {
        !           440:       SET_PT (XINT (count) > 0 ? ZV : BEGV);
        !           441:       return Qnil;
        !           442:     }
        !           443:   SET_PT (val);
        !           444:   return Qt;
        !           445: }
        !           446: 
        !           447: int parse_sexp_ignore_comments;
        !           448: 
        !           449: Lisp_Object
        !           450: scan_lists (from, count, depth, sexpflag)
        !           451:      register int from;
        !           452:      int count, depth, sexpflag;
        !           453: {
        !           454:   Lisp_Object val;
        !           455:   register int stop;
        !           456:   register int c;
        !           457:   char stringterm;
        !           458:   int quoted;
        !           459:   int mathexit = 0;
        !           460:   register enum syntaxcode code;
        !           461:   int min_depth = depth;    /* Err out if depth gets less than this. */
        !           462: 
        !           463:   if (depth > 0) min_depth = 0;
        !           464: 
        !           465:   immediate_quit = 1;
        !           466:   QUIT;
        !           467: 
        !           468:   while (count > 0)
        !           469:     {
        !           470:       stop = ZV;
        !           471:       while (from < stop)
        !           472:        {
        !           473:          c = FETCH_CHAR (from);
        !           474:          code = SYNTAX(c);
        !           475:          from++;
        !           476:          if (from < stop && SYNTAX_COMSTART_FIRST (c)
        !           477:              && SYNTAX_COMSTART_SECOND (FETCH_CHAR (from))
        !           478:              && parse_sexp_ignore_comments)
        !           479:            code = Scomment, from++;
        !           480: 
        !           481: #ifdef SWITCH_ENUM_BUG
        !           482:          switch ((int) code)
        !           483: #else
        !           484:          switch (code)
        !           485: #endif
        !           486:            {
        !           487:            case Sescape:
        !           488:            case Scharquote:
        !           489:              if (from == stop) goto lose;
        !           490:              from++;
        !           491:              /* treat following character as a word constituent */
        !           492:            case Sword:
        !           493:            case Ssymbol:
        !           494:              if (depth || !sexpflag) break;
        !           495:              /* This word counts as a sexp; return at end of it. */
        !           496:              while (from < stop)
        !           497:                {
        !           498: #ifdef SWITCH_ENUM_BUG
        !           499:                  switch ((int) SYNTAX(FETCH_CHAR (from)))
        !           500: #else
        !           501:                  switch (SYNTAX(FETCH_CHAR (from)))
        !           502: #endif
        !           503:                    {
        !           504:                    case Scharquote:
        !           505:                    case Sescape:
        !           506:                      from++;
        !           507:                      if (from == stop) goto lose;
        !           508:                      break;
        !           509:                    case Sword:
        !           510:                    case Ssymbol:
        !           511:                    case Squote:
        !           512:                      break;
        !           513:                    default:
        !           514:                      goto done;
        !           515:                    }
        !           516:                  from++;
        !           517:                }
        !           518:              goto done;
        !           519: 
        !           520:            case Scomment:
        !           521:              if (!parse_sexp_ignore_comments) break;
        !           522:              while (1)
        !           523:                {
        !           524:                  if (from == stop) goto done;
        !           525:                  if (SYNTAX (c = FETCH_CHAR (from)) == Sendcomment)
        !           526:                    break;
        !           527:                  from++;
        !           528:                  if (from < stop && SYNTAX_COMEND_FIRST (c)
        !           529:                       && SYNTAX_COMEND_SECOND (FETCH_CHAR (from)))
        !           530:                    { from++; break; }
        !           531:                }
        !           532:              break;
        !           533: 
        !           534:            case Smath:
        !           535:              if (!sexpflag)
        !           536:                break;
        !           537:              if (from != stop && c == FETCH_CHAR (from))
        !           538:                from++;
        !           539:              if (mathexit)
        !           540:                {
        !           541:                  mathexit = 0;
        !           542:                  goto close1;
        !           543:                }
        !           544:              mathexit = 1;
        !           545: 
        !           546:            case Sopen:
        !           547:              if (!++depth) goto done;
        !           548:              break;
        !           549: 
        !           550:            case Sclose:
        !           551:            close1:
        !           552:              if (!--depth) goto done;
        !           553:              if (depth < min_depth)
        !           554:                error ("Containing expression ends prematurely");
        !           555:              break;
        !           556: 
        !           557:            case Sstring:
        !           558:              stringterm = FETCH_CHAR (from - 1);
        !           559:              while (1)
        !           560:                {
        !           561:                  if (from >= stop) goto lose;
        !           562:                  if (FETCH_CHAR (from) == stringterm) break;
        !           563: #ifdef SWITCH_ENUM_BUG
        !           564:                  switch ((int) SYNTAX(FETCH_CHAR (from)))
        !           565: #else
        !           566:                  switch (SYNTAX(FETCH_CHAR (from)))
        !           567: #endif
        !           568:                    {
        !           569:                    case Scharquote:
        !           570:                    case Sescape:
        !           571:                      from++;
        !           572:                    }
        !           573:                  from++;
        !           574:                }
        !           575:              from++;
        !           576:              if (!depth && sexpflag) goto done;
        !           577:              break;
        !           578:            }
        !           579:        }
        !           580: 
        !           581:       /* Reached end of buffer.  Error if within object, return nil if between */
        !           582:       if (depth) goto lose;
        !           583: 
        !           584:       immediate_quit = 0;
        !           585:       return Qnil;
        !           586: 
        !           587:       /* End of object reached */
        !           588:     done:
        !           589:       count--;
        !           590:     }
        !           591: 
        !           592:   while (count < 0)
        !           593:     {
        !           594:       stop = BEGV;
        !           595:       while (from > stop)
        !           596:        {
        !           597:          from--;
        !           598:          if (quoted = char_quoted (from))
        !           599:            from--;
        !           600:          c = FETCH_CHAR (from);
        !           601:          code = SYNTAX (c);
        !           602:          if (from > stop && SYNTAX_COMEND_SECOND (c)
        !           603:              && SYNTAX_COMEND_FIRST (FETCH_CHAR (from - 1))
        !           604:              && !char_quoted (from - 1)
        !           605:              && parse_sexp_ignore_comments)
        !           606:            code = Sendcomment, from--;
        !           607: 
        !           608: #ifdef SWITCH_ENUM_BUG
        !           609:          switch ((int) (quoted ? Sword : code))
        !           610: #else
        !           611:          switch (quoted ? Sword : code)
        !           612: #endif
        !           613:            {
        !           614:            case Sword:
        !           615:            case Ssymbol:
        !           616:              if (depth || !sexpflag) break;
        !           617:              /* This word counts as a sexp; count object finished after passing it. */
        !           618:              while (from > stop)
        !           619:                {
        !           620:                  if (quoted = char_quoted (from - 1))
        !           621:                    from--;
        !           622:                  if (! (quoted || SYNTAX(FETCH_CHAR (from - 1)) == Sword ||
        !           623:                         SYNTAX(FETCH_CHAR (from - 1)) == Ssymbol ||
        !           624:                         SYNTAX(FETCH_CHAR (from - 1)) == Squote))
        !           625:                    goto done2;
        !           626:                  from--;
        !           627:                }
        !           628:              goto done2;
        !           629: 
        !           630:            case Smath:
        !           631:              if (!sexpflag)
        !           632:                break;
        !           633:              if (from != stop && c == FETCH_CHAR (from - 1))
        !           634:                from--;
        !           635:              if (mathexit)
        !           636:                {
        !           637:                  mathexit = 0;
        !           638:                  goto open2;
        !           639:                }
        !           640:              mathexit = 1;
        !           641: 
        !           642:            case Sclose:
        !           643:              if (!++depth) goto done2;
        !           644:              break;
        !           645: 
        !           646:            case Sopen:
        !           647:            open2:
        !           648:              if (!--depth) goto done2;
        !           649:              if (depth < min_depth)
        !           650:                error ("Containing expression ends prematurely");
        !           651:              break;
        !           652: 
        !           653:            case Sendcomment:
        !           654:              if (!parse_sexp_ignore_comments) break;
        !           655:              if (from != stop) from--;
        !           656:              while (1)
        !           657:                {
        !           658:                  if (SYNTAX (c = FETCH_CHAR (from)) == Scomment)
        !           659:                    break;
        !           660:                  if (from == stop) goto done;
        !           661:                  from--;
        !           662:                  if (SYNTAX_COMSTART_SECOND (c)
        !           663:                      && SYNTAX_COMSTART_FIRST (FETCH_CHAR (from))
        !           664:                      && !char_quoted (from))
        !           665:                    break;
        !           666:                }
        !           667:              break;
        !           668: 
        !           669:            case Sstring:
        !           670:              stringterm = FETCH_CHAR (from);
        !           671:              while (1)
        !           672:                {
        !           673:                  if (from == stop) goto lose;
        !           674:                  if (!char_quoted (from - 1)
        !           675:                      && stringterm == FETCH_CHAR (from - 1))
        !           676:                    break;
        !           677:                  from--;
        !           678:                }
        !           679:              from--;
        !           680:              if (!depth && sexpflag) goto done2;
        !           681:              break;
        !           682:            }
        !           683:        }
        !           684: 
        !           685:       /* Reached start of buffer.  Error if within object, return nil if between */
        !           686:       if (depth) goto lose;
        !           687: 
        !           688:       immediate_quit = 0;
        !           689:       return Qnil;
        !           690: 
        !           691:     done2:
        !           692:       count++;
        !           693:     }
        !           694: 
        !           695: 
        !           696:   immediate_quit = 0;
        !           697:   XFASTINT (val) = from;
        !           698:   return val;
        !           699: 
        !           700:  lose:
        !           701:   error ("Unbalanced parentheses");
        !           702:   /* NOTREACHED */
        !           703: }
        !           704: 
        !           705: char_quoted (pos)
        !           706:      register int pos;
        !           707: {
        !           708:   register enum syntaxcode code;
        !           709:   register int beg = BEGV;
        !           710:   register int quoted = 0;
        !           711: 
        !           712:   while (pos > beg &&
        !           713:         ((code = SYNTAX (FETCH_CHAR (pos - 1))) == Scharquote
        !           714:          || code == Sescape))
        !           715:     pos--, quoted = !quoted;
        !           716:   return quoted;
        !           717: }
        !           718: 
        !           719: DEFUN ("scan-lists", Fscan_lists, Sscan_lists, 3, 3, 0,
        !           720:   "Scan from character number FROM by COUNT lists.\n\
        !           721: Returns the character number of the position thus found.\n\
        !           722: \n\
        !           723: If DEPTH is nonzero, paren depth begins counting from that value,\n\
        !           724: only places where the depth in parentheses becomes zero\n\
        !           725: are candidates for stopping; COUNT such places are counted.\n\
        !           726: Thus, a positive value for DEPTH means go out levels.\n\
        !           727: \n\
        !           728: Comments are ignored if parse-sexp-ignore-comments is non-nil.\n\
        !           729: \n\
        !           730: If the beginning or end of (the visible part of) the buffer is reached\n\
        !           731: and the depth is wrong, an error is signaled.\n\
        !           732: If the depth is right but the count is not used up, nil is returned.")
        !           733:   (from, count, depth)
        !           734:      Lisp_Object from, count, depth;
        !           735: {
        !           736:   CHECK_NUMBER (from, 0);
        !           737:   CHECK_NUMBER (count, 1);
        !           738:   CHECK_NUMBER (depth, 2);
        !           739: 
        !           740:   return scan_lists (XINT (from), XINT (count), XINT (depth), 0);
        !           741: }
        !           742: 
        !           743: DEFUN ("scan-sexps", Fscan_sexps, Sscan_sexps, 2, 2, 0,
        !           744:   "Scan from character number FROM by COUNT balanced expressions.\n\
        !           745: Returns the character number of the position thus found.\n\
        !           746: \n\
        !           747: Comments are ignored if parse-sexp-ignore-comments is non-nil.\n\
        !           748: \n\
        !           749: If the beginning or end of (the visible part of) the buffer is reached\n\
        !           750: in the middle of a parenthetical grouping, an error is signaled.\n\
        !           751: If the beginning or end is reached between groupings but before count is used up,\n\
        !           752: nil is returned.")
        !           753:   (from, count)
        !           754:      Lisp_Object from, count;
        !           755: {
        !           756:   CHECK_NUMBER (from, 0);
        !           757:   CHECK_NUMBER (count, 1);
        !           758: 
        !           759:   return scan_lists (XINT (from), XINT (count), 0, 1);
        !           760: }
        !           761: 
        !           762: DEFUN ("backward-prefix-chars", Fbackward_prefix_chars, Sbackward_prefix_chars,
        !           763:   0, 0, 0,
        !           764:   "Move point backward over any number of chars with syntax \"prefix\".")
        !           765:   ()
        !           766: {
        !           767:   int beg = BEGV;
        !           768:   int pos = point;
        !           769: 
        !           770:   while (pos > beg && !char_quoted (pos - 1) && SYNTAX (FETCH_CHAR (pos - 1)) == Squote)
        !           771:     pos--;
        !           772: 
        !           773:   SET_PT (pos);
        !           774: 
        !           775:   return Qnil;
        !           776: }
        !           777: 
        !           778: struct lisp_parse_state
        !           779:   {
        !           780:     int depth;         /* Depth at end of parsing */
        !           781:     int instring;      /* -1 if not within string, else desired terminator. */
        !           782:     int incomment;     /* Nonzero if within a comment at end of parsing */
        !           783:     int quoted;                /* Nonzero if just after an escape char at end of parsing */
        !           784:     int thislevelstart;        /* Char number of most recent start-of-expression at current level */
        !           785:     int prevlevelstart; /* Char number of start of containing expression */
        !           786:     int location;      /* Char number at which parsing stopped. */
        !           787:     int mindepth;      /* Minimum depth seen while scanning.  */
        !           788:   };
        !           789: 
        !           790: /* Parse forward from FROM to END,
        !           791:    assuming that FROM is the start of a function, 
        !           792:    and return a description of the state of the parse at END. */
        !           793: 
        !           794: struct lisp_parse_state val_scan_sexps_forward;
        !           795: 
        !           796: struct lisp_parse_state *
        !           797: scan_sexps_forward (from, end, targetdepth, stopbefore, oldstate)
        !           798:      register int from;
        !           799:      int end, targetdepth, stopbefore;
        !           800:      Lisp_Object oldstate;
        !           801: {
        !           802:   struct lisp_parse_state state;
        !           803: 
        !           804:   register enum syntaxcode code;
        !           805:   struct level { int last, prev; };
        !           806:   struct level levelstart[100];
        !           807:   register struct level *curlevel = levelstart;
        !           808:   struct level *endlevel = levelstart + 100;
        !           809:   char prev;
        !           810:   register int depth;  /* Paren depth of current scanning location.
        !           811:                           level - levelstart equals this except
        !           812:                           when the depth becomes negative.  */
        !           813:   int mindepth;                /* Lowest DEPTH value seen.  */
        !           814:   int start_quoted = 0;                /* Nonzero means starting after a char quote */
        !           815:   Lisp_Object tem;
        !           816: 
        !           817:   immediate_quit = 1;
        !           818:   QUIT;
        !           819: 
        !           820:   if (NULL (oldstate))
        !           821:     {
        !           822:       depth = 0;
        !           823:       state.instring = -1;
        !           824:       state.incomment = 0;
        !           825:     }
        !           826:   else
        !           827:     {
        !           828:       tem = Fcar (oldstate);
        !           829:       if (!NULL (tem))
        !           830:        depth = XINT (tem);
        !           831:       else
        !           832:        depth = 0;
        !           833: 
        !           834:       oldstate = Fcdr (oldstate);
        !           835:       oldstate = Fcdr (oldstate);
        !           836:       oldstate = Fcdr (oldstate);
        !           837:       tem = Fcar (oldstate);
        !           838:       state.instring = !NULL (tem) ? XINT (tem) : -1;
        !           839: 
        !           840:       oldstate = Fcdr (oldstate);
        !           841:       tem = Fcar (oldstate);
        !           842:       state.incomment = !NULL (tem);
        !           843: 
        !           844:       oldstate = Fcdr (oldstate);
        !           845:       tem = Fcar (oldstate);
        !           846:       start_quoted = !NULL (tem);
        !           847:     }
        !           848:   state.quoted = 0;
        !           849:   mindepth = depth;
        !           850: 
        !           851:   curlevel->prev = -1;
        !           852:   curlevel->last = -1;
        !           853: 
        !           854:   /* Enter the loop at a place appropriate for initial state. */
        !           855: 
        !           856:   if (state.incomment) goto startincomment;
        !           857:   if (state.instring >= 0)
        !           858:     {
        !           859:       if (start_quoted) goto startquotedinstring;
        !           860:       goto startinstring;
        !           861:     }
        !           862:   if (start_quoted) goto startquoted;
        !           863: 
        !           864:   while (from < end)
        !           865:     {
        !           866:       code = SYNTAX(FETCH_CHAR (from));
        !           867:       from++;
        !           868:       if (from < end && SYNTAX_COMSTART_FIRST (FETCH_CHAR (from - 1))
        !           869:           && SYNTAX_COMSTART_SECOND (FETCH_CHAR (from)))
        !           870:        code = Scomment, from++;
        !           871: #ifdef SWITCH_ENUM_BUG
        !           872:       switch ((int) code)
        !           873: #else
        !           874:       switch (code)
        !           875: #endif
        !           876:        {
        !           877:        case Sescape:
        !           878:        case Scharquote:
        !           879:          if (stopbefore) goto stop;  /* this arg means stop at sexp start */
        !           880:          curlevel->last = from - 1;
        !           881:        startquoted:
        !           882:          if (from == end) goto endquoted;
        !           883:          from++;
        !           884:          goto symstarted;
        !           885:          /* treat following character as a word constituent */
        !           886:        case Sword:
        !           887:        case Ssymbol:
        !           888:          if (stopbefore) goto stop;  /* this arg means stop at sexp start */
        !           889:          curlevel->last = from - 1;
        !           890:        symstarted:
        !           891:          while (from < end)
        !           892:            {
        !           893: #ifdef SWITCH_ENUM_BUG
        !           894:              switch ((int) SYNTAX(FETCH_CHAR (from)))
        !           895: #else
        !           896:              switch (SYNTAX(FETCH_CHAR (from)))
        !           897: #endif
        !           898:                {
        !           899:                case Scharquote:
        !           900:                case Sescape:
        !           901:                  from++;
        !           902:                  if (from == end) goto endquoted;
        !           903:                  break;
        !           904:                case Sword:
        !           905:                case Ssymbol:
        !           906:                case Squote:
        !           907:                  break;
        !           908:                default:
        !           909:                  goto symdone;
        !           910:                }
        !           911:              from++;
        !           912:            }
        !           913:        symdone:
        !           914:          curlevel->prev = curlevel->last;
        !           915:          break;
        !           916: 
        !           917:        case Scomment:
        !           918:          state.incomment = 1;
        !           919:        startincomment:
        !           920:          while (1)
        !           921:            {
        !           922:              if (from == end) goto done;
        !           923:              if (SYNTAX (prev = FETCH_CHAR (from)) == Sendcomment)
        !           924:                break;
        !           925:              from++;
        !           926:              if (from < end && SYNTAX_COMEND_FIRST (prev)
        !           927:                   && SYNTAX_COMEND_SECOND (FETCH_CHAR (from)))
        !           928:                { from++; break; }
        !           929:            }
        !           930:          state.incomment = 0;
        !           931:          break;
        !           932: 
        !           933:        case Sopen:
        !           934:          if (stopbefore) goto stop;  /* this arg means stop at sexp start */
        !           935:          depth++;
        !           936:          /* curlevel++->last ran into compiler bug on Apollo */
        !           937:          curlevel->last = from - 1;
        !           938:          if (++curlevel == endlevel)
        !           939:            error ("Nesting too deep for parser");
        !           940:          curlevel->prev = -1;
        !           941:          curlevel->last = -1;
        !           942:          if (!--targetdepth) goto done;
        !           943:          break;
        !           944: 
        !           945:        case Sclose:
        !           946:          depth--;
        !           947:          if (depth < mindepth)
        !           948:            mindepth = depth;
        !           949:          if (curlevel != levelstart)
        !           950:            curlevel--;
        !           951:          curlevel->prev = curlevel->last;
        !           952:          if (!++targetdepth) goto done;
        !           953:          break;
        !           954: 
        !           955:        case Sstring:
        !           956:          if (stopbefore) goto stop;  /* this arg means stop at sexp start */
        !           957:          curlevel->last = from - 1;
        !           958:          state.instring = FETCH_CHAR (from - 1);
        !           959:        startinstring:
        !           960:          while (1)
        !           961:            {
        !           962:              if (from >= end) goto done;
        !           963:              if (FETCH_CHAR (from) == state.instring) break;
        !           964: #ifdef SWITCH_ENUM_BUG
        !           965:              switch ((int) SYNTAX(FETCH_CHAR (from)))
        !           966: #else
        !           967:              switch (SYNTAX(FETCH_CHAR (from)))
        !           968: #endif
        !           969:                {
        !           970:                case Scharquote:
        !           971:                case Sescape:
        !           972:                  from++;
        !           973:                startquotedinstring:
        !           974:                  if (from >= end) goto endquoted;
        !           975:                }
        !           976:              from++;
        !           977:            }
        !           978:          state.instring = -1;
        !           979:          curlevel->prev = curlevel->last;
        !           980:          from++;
        !           981:          break;
        !           982: 
        !           983:        case Smath:
        !           984:          break;
        !           985:        }
        !           986:     }
        !           987:   goto done;
        !           988: 
        !           989:  stop:   /* Here if stopping before start of sexp. */
        !           990:   from--;    /* We have just fetched the char that starts it; */
        !           991:   goto done; /* but return the position before it. */
        !           992: 
        !           993:  endquoted:
        !           994:   state.quoted = 1;
        !           995:  done:
        !           996:   state.depth = depth;
        !           997:   state.mindepth = mindepth;
        !           998:   state.thislevelstart = curlevel->prev;
        !           999:   state.prevlevelstart
        !          1000:     = (curlevel == levelstart) ? -1 : (curlevel - 1)->last;
        !          1001:   state.location = from;
        !          1002:   immediate_quit = 0;
        !          1003: 
        !          1004:   val_scan_sexps_forward = state;
        !          1005:   return &val_scan_sexps_forward;
        !          1006: }
        !          1007: 
        !          1008: /* This comment supplies the doc string for parse-partial-sexp,
        !          1009:    for make-docfile to see.  We cannot put this in the real DEFUN
        !          1010:    due to limits in the Unix cpp.
        !          1011: 
        !          1012: DEFUN ("parse-partial-sexp", Ffoo, Sfoo, 0, 0, 0,
        !          1013:   "Parse Lisp syntax starting at FROM until TO; return status of parse at TO.\n\
        !          1014: Parsing stops at TO or when certain criteria are met;\n\
        !          1015:  point is set to where parsing stops.\n\
        !          1016: If fifth arg STATE is omitted or nil,\n\
        !          1017:  parsing assumes that FROM is the beginning of a function.\n\
        !          1018: Value is a list of seven elements describing final state of parsing:\n\
        !          1019:  1. depth in parens.\n\
        !          1020:  2. character address of start of innermost containing list; nil if none.\n\
        !          1021:  3. character address of start of last complete sexp terminated.\n\
        !          1022:  4. non-nil if inside a string.\n\
        !          1023:     (it is the character that will terminate the string.)\n\
        !          1024:  5. t if inside a comment.\n\
        !          1025:  6. t if following a quote character.\n\
        !          1026:  7. the minimum paren-depth encountered during this scan.\n\
        !          1027: If third arg TARGETDEPTH is non-nil, parsing stops if the depth\n\
        !          1028: in parentheses becomes equal to TARGETDEPTH.\n\
        !          1029: Fourth arg STOPBEFORE non-nil means stop when come to\n\
        !          1030:  any character that starts a sexp.\n\
        !          1031: Fifth arg STATE is a seven-list like what this function returns.\n\
        !          1032: It is used to initialize the state of the parse.")
        !          1033: 
        !          1034: */
        !          1035: 
        !          1036: DEFUN ("parse-partial-sexp", Fparse_partial_sexp, Sparse_partial_sexp, 2, 5, 0,
        !          1037:   0 /* See immediately above */)
        !          1038:   (from, to, targetdepth, stopbefore, oldstate)
        !          1039:      Lisp_Object from, to, targetdepth, stopbefore, oldstate;
        !          1040: {
        !          1041:   struct lisp_parse_state state;
        !          1042:   int target;
        !          1043: 
        !          1044:   if (!NULL (targetdepth))
        !          1045:     {
        !          1046:       CHECK_NUMBER (targetdepth, 3);
        !          1047:       target = XINT (targetdepth);
        !          1048:     }
        !          1049:   else
        !          1050:     target = -100000;          /* We won't reach this depth */
        !          1051: 
        !          1052:   validate_region (&from, &to);
        !          1053:   state = *scan_sexps_forward (XINT (from), XINT (to),
        !          1054:                               target, !NULL (stopbefore), oldstate);
        !          1055: 
        !          1056:   SET_PT (state.location);
        !          1057:   
        !          1058:   return Fcons (make_number (state.depth),
        !          1059:           Fcons (state.prevlevelstart < 0 ? Qnil : make_number (state.prevlevelstart),
        !          1060:             Fcons (state.thislevelstart < 0 ? Qnil : make_number (state.thislevelstart),
        !          1061:               Fcons (state.instring >= 0 ? make_number (state.instring) : Qnil,
        !          1062:                 Fcons (state.incomment ? Qt : Qnil,
        !          1063:                   Fcons (state.quoted ? Qt : Qnil,
        !          1064:                          Fcons (make_number (state.mindepth), Qnil)))))));
        !          1065: }
        !          1066: 
        !          1067: init_syntax_once ()
        !          1068: {
        !          1069:   register int i;
        !          1070:   register struct Lisp_Vector *v;
        !          1071: 
        !          1072:   /* Set this now, so first buffer creation can refer to it. */
        !          1073:   /* Make it nil before calling copy-syntax-table
        !          1074:     so that copy-syntax-table will know not to try to copy from garbage */
        !          1075:   Vstandard_syntax_table = Qnil;
        !          1076:   Vstandard_syntax_table = Fcopy_syntax_table (Qnil);
        !          1077: 
        !          1078:   v = XVECTOR (Vstandard_syntax_table);
        !          1079: 
        !          1080:   for (i = 'a'; i <= 'z'; i++)
        !          1081:     XFASTINT (v->contents[i]) = (int) Sword;
        !          1082:   for (i = 'A'; i <= 'Z'; i++)
        !          1083:     XFASTINT (v->contents[i]) = (int) Sword;
        !          1084:   for (i = '0'; i <= '9'; i++)
        !          1085:     XFASTINT (v->contents[i]) = (int) Sword;
        !          1086:   XFASTINT (v->contents['$']) = (int) Sword;
        !          1087:   XFASTINT (v->contents['%']) = (int) Sword;
        !          1088: 
        !          1089:   XFASTINT (v->contents['(']) = (int) Sopen + (')' << 8);
        !          1090:   XFASTINT (v->contents[')']) = (int) Sclose + ('(' << 8);
        !          1091:   XFASTINT (v->contents['[']) = (int) Sopen + (']' << 8);
        !          1092:   XFASTINT (v->contents[']']) = (int) Sclose + ('[' << 8);
        !          1093:   XFASTINT (v->contents['{']) = (int) Sopen + ('}' << 8);
        !          1094:   XFASTINT (v->contents['}']) = (int) Sclose + ('{' << 8);
        !          1095:   XFASTINT (v->contents['"']) = (int) Sstring;
        !          1096:   XFASTINT (v->contents['\\']) = (int) Sescape;
        !          1097: 
        !          1098:   for (i = 0; i < 10; i++)
        !          1099:     XFASTINT (v->contents["_-+*/&|<>="[i]]) = (int) Ssymbol;
        !          1100: 
        !          1101:   for (i = 0; i < 12; i++)
        !          1102:     XFASTINT (v->contents[".,;:?!#@~^'`"[i]]) = (int) Spunct;
        !          1103: }
        !          1104: 
        !          1105: syms_of_syntax ()
        !          1106: {
        !          1107:   Qsyntax_table_p = intern ("syntax-table-p");
        !          1108:   staticpro (&Qsyntax_table_p);
        !          1109: 
        !          1110:   DEFVAR_BOOL ("parse-sexp-ignore-comments", &parse_sexp_ignore_comments,
        !          1111:     "Non-nil means forward-sexp, etc., should treat comments as whitespace.\n\
        !          1112: Non-nil works only when the comment terminator is something like *\/,\n\
        !          1113: and appears only when it ends a comment.\n\
        !          1114: If comments are terminated by newlines,\n\
        !          1115: you must make this variable nil.");
        !          1116: 
        !          1117:   defsubr (&Ssyntax_table_p);
        !          1118:   defsubr (&Ssyntax_table);
        !          1119:   defsubr (&Sstandard_syntax_table);
        !          1120:   defsubr (&Scopy_syntax_table);
        !          1121:   defsubr (&Sset_syntax_table);
        !          1122:   defsubr (&Schar_syntax);
        !          1123:   defsubr (&Smodify_syntax_entry);
        !          1124:   defsubr (&Sdescribe_syntax);
        !          1125: 
        !          1126:   defsubr (&Sforward_word);
        !          1127: 
        !          1128:   defsubr (&Sscan_lists);
        !          1129:   defsubr (&Sscan_sexps);
        !          1130:   defsubr (&Sbackward_prefix_chars);
        !          1131:   defsubr (&Sparse_partial_sexp);
        !          1132: }

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.