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

unix.superglobalmegacorp.com

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