Annotation of GNUtools/emacs/src/syntax.c, revision 1.1.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.