Annotation of 43BSD/contrib/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 Richard M. Stallman.
                      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 (XINT (ch))]);
                    151: }
                    152: 
                    153: DEFUN ("modify-syntax-entry", Fmodify_syntax_entry, Smodify_syntax_entry, 2, 3, 
                    154:   /* I really don't know why this is interactive
                    155:      help-form should at least be made useful whilst reading the second arg
                    156:    */
                    157:   "cSet syntax for character: \nsSet syntax for %s to: ",
                    158:   0 /* See auxdoc.c */)
                    159:   (c, newentry, syntax_table)
                    160:      Lisp_Object c, newentry, syntax_table;
                    161: {
                    162:   register unsigned char *p, match;
                    163:   register enum syntaxcode code;
                    164:   Lisp_Object val;
                    165: 
                    166:   CHECK_NUMBER (c, 0);
                    167:   CHECK_STRING (newentry, 1);
                    168:   if (NULL (syntax_table))
                    169:     XSET (syntax_table, Lisp_Vector, bf_cur->syntax_table_v);
                    170:   else syntax_table = check_syntax_table (syntax_table);
                    171: 
                    172:   p = XSTRING (newentry)->data;
                    173:   code = (enum syntaxcode) syntax_spec_code[*p++];
                    174:   if (((int) code & 0377) == 0377)
                    175:     error ("invalid syntax description letter: %c", c);
                    176: 
                    177:   match = *p;
                    178:   if (match) p++;
                    179:   if (match == ' ') match = 0;
                    180: 
                    181:   XFASTINT (val) = (match << 8) + (int) code;
                    182:   while (*p)
                    183:     switch (*p++)
                    184:       {
                    185:       case '1':
                    186:        XFASTINT (val) |= 1 << 16;
                    187:        break;
                    188: 
                    189:       case '2':
                    190:        XFASTINT (val) |= 1 << 17;
                    191:        break;
                    192: 
                    193:       case '3':
                    194:        XFASTINT (val) |= 1 << 18;
                    195:        break;
                    196: 
                    197:       case '4':
                    198:        XFASTINT (val) |= 1 << 19;
                    199:        break;
                    200:       }
                    201:        
                    202:   XVECTOR (syntax_table)->contents[XINT (c)] = val;
                    203: 
                    204:   return Qnil;
                    205: }
                    206: 
                    207: /* Dump syntax table to buffer in human-readable format */
                    208: 
                    209: describe_syntax (value)
                    210:     Lisp_Object value;
                    211: {
                    212:   register enum syntaxcode code;
                    213:   char desc, match, start1, start2, end1, end2;
                    214:   char str[2];
                    215: 
                    216:   if (XTYPE (value) != Lisp_Int)
                    217:     {
                    218:       InsStr ("invalid");
                    219:       return;
                    220:     }
                    221: 
                    222:   code = (enum syntaxcode) (XINT (value) & 0377);
                    223:   match = (XINT (value) >> 8) & 0377;
                    224:   start1 = (XINT (value) >> 16) & 1;
                    225:   start2 = (XINT (value) >> 17) & 1;
                    226:   end1 = (XINT (value) >> 18) & 1;
                    227:   end2 = (XINT (value) >> 19) & 1;
                    228: 
                    229:   if ((int) code < 0 || (int) code >= (int) Smax)
                    230:     {
                    231:       InsStr ("invalid");
                    232:       return;
                    233:     }
                    234:   desc = syntax_code_spec[(int) code];
                    235: 
                    236:   str[0] = desc, str[1] = 0;
                    237:   InsCStr (str, 1);
                    238: 
                    239:   str[0] = match ? match : ' ';
                    240:   InsCStr (str, 1);
                    241: 
                    242: 
                    243:   if (start1)
                    244:     InsCStr ("1", 1);
                    245:   if (start2)
                    246:     InsCStr ("2", 1);
                    247: 
                    248:   if (end1)
                    249:     InsCStr ("3", 1);
                    250:   if (end2)
                    251:     InsCStr ("4", 1);
                    252: 
                    253:   InsStr ("\twhich means: ");
                    254: 
                    255: #ifdef SWITCH_ENUM_BUG
                    256:   switch ((int) code)
                    257: #else
                    258:   switch (code)
                    259: #endif
                    260:     {
                    261:     case Swhitespace:
                    262:       InsStr ("whitespace"); break;
                    263:     case Spunct:
                    264:       InsStr ("punctuation"); break;
                    265:     case Sword:
                    266:       InsStr ("word"); break;
                    267:     case Ssymbol:
                    268:       InsStr ("symbol"); break;
                    269:     case Sopen:
                    270:       InsStr ("open"); break;
                    271:     case Sclose:
                    272:       InsStr ("close"); break;
                    273:     case Squote:
                    274:       InsStr ("quote"); break;
                    275:     case Sstring:
                    276:       InsStr ("string"); break;
                    277:     case Smath:
                    278:       InsStr ("math"); break;
                    279:     case Sescape:
                    280:       InsStr ("escape"); break;
                    281:     case Scharquote:
                    282:       InsStr ("charquote"); break;
                    283:     case Scomment:
                    284:       InsStr ("comment"); break;
                    285:     case Sendcomment:
                    286:       InsStr ("endcomment"); break;
                    287:     default:
                    288:       InsStr ("invalid");
                    289:       return;
                    290:     }
                    291: 
                    292:   if (match)
                    293:     {
                    294:       InsStr (", matches ");
                    295:       
                    296:       str[0] = match, str[1] = 0;
                    297:       InsCStr (str, 1);
                    298:     }
                    299: 
                    300:   if (start1)
                    301:     InsStr (",\n\t  is the first character of a comment-start sequence");
                    302:   if (start2)
                    303:     InsStr (",\n\t  is the second character of a comment-start sequence");
                    304: 
                    305:   if (end1)
                    306:     InsStr (",\n\t  is the first character of a comment-end sequence");
                    307:   if (end2)
                    308:     InsStr (",\n\t  is the second character of a comment-end sequence");
                    309: }
                    310: 
                    311: Lisp_Object
                    312: describe_syntax_1 (vector)
                    313:      Lisp_Object vector;
                    314: {
                    315:   struct buffer *old = bf_cur;
                    316:   SetBfp (XBUFFER (Vstandard_output));
                    317:   describe_vector (vector, Qnil, describe_syntax, 0);
                    318:   SetBfp (old);
                    319:   return Qnil;
                    320: }
                    321: 
                    322: DEFUN ("describe-syntax", Fdescribe_syntax, Sdescribe_syntax, 0, 0, "",
                    323:   "Describe the syntax specifications in the syntax table.\n\
                    324: The descriptions are inserted in a buffer, which is selected so you can see it.")
                    325:   ()
                    326: {
                    327:   register Lisp_Object vector;
                    328: 
                    329:   XSET (vector, Lisp_Vector, bf_cur->syntax_table_v);
                    330:   internal_with_output_to_temp_buffer
                    331:      ("*Help*", describe_syntax_1, vector);
                    332: 
                    333:   return Qnil;
                    334: }
                    335: 
                    336: /* Return the position across `count' words from `from'.
                    337:    If that many words cannot be found before the end of the buffer, return 0.
                    338:    `count' negative means scan backward and stop at word beginning.  */
                    339: 
                    340: scan_words (from, count)
                    341:      register int from, count;
                    342: {
                    343:   register int beg = FirstCharacter;
                    344:   register int end = NumCharacters + 1;
                    345: 
                    346:   immediate_quit = 1;
                    347:   QUIT;
                    348: 
                    349:   while (count > 0)
                    350:     {
                    351:       while (1)
                    352:        {
                    353:          if (from == end)
                    354:            {
                    355:              immediate_quit = 0;
                    356:              return 0;
                    357:            }
                    358:          if (SYNTAX(CharAt (from)) == Sword)
                    359:            break;
                    360:          from++;
                    361:        }
                    362:       while (1)
                    363:        {
                    364:          if (from == end) break;
                    365:          if (SYNTAX(CharAt (from)) != Sword)
                    366:            break;
                    367:          from++;
                    368:        }
                    369:       count--;
                    370:     }
                    371:   while (count < 0)
                    372:     {
                    373:       while (1)
                    374:        {
                    375:          if (from == beg)
                    376:            {
                    377:              immediate_quit = 0;
                    378:              return 0;
                    379:            }
                    380:          if (SYNTAX(CharAt (from - 1)) == Sword)
                    381:            break;
                    382:          from--;
                    383:        }
                    384:       while (1)
                    385:        {
                    386:          if (from == beg) break;
                    387:          if (SYNTAX(CharAt (from - 1)) != Sword)
                    388:            break;
                    389:          from--;
                    390:        }
                    391:       count++;
                    392:     }
                    393: 
                    394:   immediate_quit = 0;
                    395: 
                    396:   return from;
                    397: }
                    398: 
                    399: DEFUN ("forward-word", Fforward_word, Sforward_word, 1, 1, "p",
                    400:   "Move point forward ARG words (backward if ARG is negative).\n\
                    401: Normally returns t.\n\
                    402: If an edge of the buffer is reached, point is left there\n\
                    403: and nil is returned.")
                    404:   (count)
                    405:      Lisp_Object count;
                    406: {
                    407:   int val;
                    408:   CHECK_NUMBER (count, 0);
                    409: 
                    410:   if (!(val = scan_words (point, XINT (count))))
                    411:     {
                    412:       SetPoint (XINT (count) > 0 ? NumCharacters + 1 : FirstCharacter);
                    413:       return Qnil;
                    414:     }
                    415:   SetPoint (val);
                    416:   return Qt;
                    417: }
                    418: 
                    419: int parse_sexp_ignore_comments;
                    420: 
                    421: Lisp_Object
                    422: scan_lists (from, count, depth, sexpflag)
                    423:      register int from;
                    424:      int count, depth, sexpflag;
                    425: {
                    426:   Lisp_Object val;
                    427:   register int stop;
                    428:   register int c;
                    429:   char stringterm;
                    430:   int quoted;
                    431:   int mathexit = 0;
                    432:   register enum syntaxcode code;
                    433:   int min_depth = depth;    /* Err out if depth gets less than this. */
                    434: 
                    435:   if (depth > 0) min_depth = 0;
                    436: 
                    437:   immediate_quit = 1;
                    438:   QUIT;
                    439: 
                    440:   while (count > 0)
                    441:     {
                    442:       stop = NumCharacters + 1;
                    443:       while (from < stop)
                    444:        {
                    445:          c = CharAt (from);
                    446:          code = SYNTAX(c);
                    447:          from++;
                    448:          if (from < stop && SYNTAX_COMSTART_FIRST (c)
                    449:              && SYNTAX_COMSTART_SECOND (CharAt (from))
                    450:              && parse_sexp_ignore_comments)
                    451:            code = Scomment, from++;
                    452: 
                    453: #ifdef SWITCH_ENUM_BUG
                    454:          switch ((int) code)
                    455: #else
                    456:          switch (code)
                    457: #endif
                    458:            {
                    459:            case Sescape:
                    460:            case Scharquote:
                    461:              if (from == stop) goto lose;
                    462:              from++;
                    463:              /* treat following character as a word constituent */
                    464:            case Sword:
                    465:            case Ssymbol:
                    466:              if (depth || !sexpflag) break;
                    467:              /* This word counts as a sexp; return at end of it. */
                    468:              while (from < stop)
                    469:                {
                    470: #ifdef SWITCH_ENUM_BUG
                    471:                  switch ((int) SYNTAX(CharAt (from)))
                    472: #else
                    473:                  switch (SYNTAX(CharAt (from)))
                    474: #endif
                    475:                    {
                    476:                    case Scharquote:
                    477:                    case Sescape:
                    478:                      from++;
                    479:                      if (from == stop) goto lose;
                    480:                      break;
                    481:                    case Sword:
                    482:                    case Ssymbol:
                    483:                      break;
                    484:                    default:
                    485:                      goto done;
                    486:                    }
                    487:                  from++;
                    488:                }
                    489:              goto done;
                    490: 
                    491:            case Scomment:
                    492:              if (!parse_sexp_ignore_comments) break;
                    493:              while (1)
                    494:                {
                    495:                  if (from == stop) goto done;
                    496:                  if (SYNTAX (c = CharAt (from)) == Sendcomment)
                    497:                    break;
                    498:                  from++;
                    499:                  if (from < stop && SYNTAX_COMEND_FIRST (c)
                    500:                       && SYNTAX_COMEND_SECOND (CharAt (from)))
                    501:                    { from++; break; }
                    502:                }
                    503:              break;
                    504: 
                    505:            case Smath:
                    506:              if (!sexpflag)
                    507:                break;
                    508:              if (from != stop && c == CharAt (from))
                    509:                from++;
                    510:              if (mathexit) goto close1;
                    511:              mathexit = 1;
                    512: 
                    513:            case Sopen:
                    514:              if (!++depth) goto done;
                    515:              break;
                    516: 
                    517:            case Sclose:
                    518:            close1:
                    519:              if (!--depth) goto done;
                    520:              if (depth < min_depth)
                    521:                error ("Containing expression ends prematurely");
                    522:              break;
                    523: 
                    524:            case Sstring:
                    525:              stringterm = CharAt (from - 1);
                    526:              while (1)
                    527:                {
                    528:                  if (from >= stop) goto lose;
                    529:                  if (CharAt (from) == stringterm) break;
                    530: #ifdef SWITCH_ENUM_BUG
                    531:                  switch ((int) SYNTAX(CharAt (from)))
                    532: #else
                    533:                  switch (SYNTAX(CharAt (from)))
                    534: #endif
                    535:                    {
                    536:                    case Scharquote:
                    537:                    case Sescape:
                    538:                      from++;
                    539:                    }
                    540:                  from++;
                    541:                }
                    542:              from++;
                    543:              if (!depth && sexpflag) goto done;
                    544:              break;
                    545:            }
                    546:        }
                    547: 
                    548:       /* Reached end of buffer.  Error if within object, return nil if between */
                    549:       if (depth) goto lose;
                    550: 
                    551:       immediate_quit = 0;
                    552:       return Qnil;
                    553: 
                    554:       /* End of object reached */
                    555:     done:
                    556:       count--;
                    557:     }
                    558: 
                    559:   while (count < 0)
                    560:     {
                    561:       stop = FirstCharacter;
                    562:       while (from > stop)
                    563:        {
                    564:          from--;
                    565:          if (quoted = char_quoted (from))
                    566:            from--;
                    567:          c = CharAt (from);
                    568:          code = SYNTAX (c);
                    569:          if (from > stop && SYNTAX_COMEND_SECOND (c)
                    570:              && SYNTAX_COMEND_FIRST (CharAt (from - 1))
                    571:              && !char_quoted (from - 1)
                    572:              && parse_sexp_ignore_comments)
                    573:            code = Sendcomment, from--;
                    574: 
                    575: #ifdef SWITCH_ENUM_BUG
                    576:          switch ((int) (quoted ? Sword : code))
                    577: #else
                    578:          switch (quoted ? Sword : code)
                    579: #endif
                    580:            {
                    581:            case Sword:
                    582:            case Ssymbol:
                    583:              if (depth || !sexpflag) break;
                    584:              /* This word counts as a sexp; count object finished after passing it. */
                    585:              while (from > stop)
                    586:                {
                    587:                  if (quoted = char_quoted (from - 1))
                    588:                    from--;
                    589:                  if (! (quoted || SYNTAX(CharAt (from - 1)) == Sword ||
                    590:                         SYNTAX(CharAt (from - 1)) == Ssymbol))
                    591:                    goto done2;
                    592:                  from--;
                    593:                }
                    594:              goto done2;
                    595: 
                    596:            case Smath:
                    597:              if (!sexpflag)
                    598:                break;
                    599:              if (from != stop && c == CharAt (from - 1))
                    600:                from--;
                    601:              if (mathexit) goto open2;
                    602:              mathexit = 1;
                    603: 
                    604:            case Sclose:
                    605:              if (!++depth) goto done2;
                    606:              break;
                    607: 
                    608:            case Sopen:
                    609:            open2:
                    610:              if (!--depth) goto done2;
                    611:              if (depth < min_depth)
                    612:                error ("Containing expression ends prematurely");
                    613:              break;
                    614: 
                    615:            case Sendcomment:
                    616:              if (!parse_sexp_ignore_comments) break;
                    617:              if (from != stop) from--;
                    618:              while (1)
                    619:                {
                    620:                  if (SYNTAX (c = CharAt (from)) == Scomment)
                    621:                    break;
                    622:                  if (from == stop) goto done;
                    623:                  from--;
                    624:                  if (SYNTAX_COMSTART_SECOND (c)
                    625:                      && SYNTAX_COMSTART_FIRST (CharAt (from))
                    626:                      && !char_quoted (from))
                    627:                    break;
                    628:                }
                    629:              break;
                    630: 
                    631:            case Sstring:
                    632:              stringterm = CharAt (from);
                    633:              while (1)
                    634:                {
                    635:                  if (from == stop) goto lose;
                    636:                  if (!char_quoted (from - 1)
                    637:                      && stringterm == CharAt (from - 1))
                    638:                    break;
                    639:                  from--;
                    640:                }
                    641:              from--;
                    642:              if (!depth && sexpflag) goto done2;
                    643:              break;
                    644:            }
                    645:        }
                    646: 
                    647:       /* Reached start of buffer.  Error if within object, return nil if between */
                    648:       if (depth) goto lose;
                    649: 
                    650:       immediate_quit = 0;
                    651:       return Qnil;
                    652: 
                    653:     done2:
                    654:       count++;
                    655:     }
                    656: 
                    657: 
                    658:   immediate_quit = 0;
                    659:   XFASTINT (val) = from;
                    660:   return val;
                    661: 
                    662:  lose:
                    663:   error ("Unbalanced parentheses");
                    664:   /* NOTREACHED */
                    665: }
                    666: 
                    667: char_quoted (pos)
                    668:      register int pos;
                    669: {
                    670:   register enum syntaxcode code;
                    671:   register int beg = FirstCharacter;
                    672:   register int quoted = 0;
                    673: 
                    674:   while (pos > beg &&
                    675:         ((code = SYNTAX (CharAt (pos - 1))) == Scharquote
                    676:          || code == Sescape))
                    677:     pos--, quoted = !quoted;
                    678:   return quoted;
                    679: }
                    680: 
                    681: DEFUN ("scan-lists", Fscan_lists, Sscan_lists, 3, 3, 0,
                    682:   "Scan from character number FROM by COUNT lists.\n\
                    683: Returns the character number of the position thus found.\n\
                    684: \n\
                    685: If DEPTH is nonzero, paren depth begins counting from that value,\n\
                    686: only places where the depth in parentheses becomes zero\n\
                    687: are candidates for stopping; COUNT such places are counted.\n\
                    688: Thus, a positive value for DEPTH means go out levels.\n\
                    689: \n\
                    690: Comments are ignored if parse-sexp-ignore-comments is non-nil.\n\
                    691: \n\
                    692: If the beginning or end of (the visible part of) the buffer is reached\n\
                    693: and the depth is wrong, an error is signaled.\n\
                    694: If the depth is right but the count is not used up, nil is returned.")
                    695:   (from, count, depth)
                    696:      Lisp_Object from, count, depth;
                    697: {
                    698:   CHECK_NUMBER (from, 0);
                    699:   CHECK_NUMBER (count, 1);
                    700:   CHECK_NUMBER (depth, 2);
                    701: 
                    702:   return scan_lists (XINT (from), XINT (count), XINT (depth), 0);
                    703: }
                    704: 
                    705: DEFUN ("scan-sexps", Fscan_sexps, Sscan_sexps, 2, 2, 0,
                    706:   "Scan from character number FROM by COUNT balanced expressions.\n\
                    707: Returns the character number of the position thus found.\n\
                    708: \n\
                    709: Comments are ignored if parse-sexp-ignore-comments is non-nil.\n\
                    710: \n\
                    711: If the beginning or end of (the visible part of) the buffer is reached\n\
                    712: in the middle of a parenthetical grouping, an error is signaled.\n\
                    713: If the beginning or end is reached between groupings but before count is used up,\n\
                    714: nil is returned.")
                    715:   (from, count)
                    716:      Lisp_Object from, count;
                    717: {
                    718:   CHECK_NUMBER (from, 0);
                    719:   CHECK_NUMBER (count, 1);
                    720: 
                    721:   return scan_lists (XINT (from), XINT (count), 0, 1);
                    722: }
                    723: 
                    724: DEFUN ("backward-prefix-chars", Fbackward_prefix_chars, Sbackward_prefix_chars,
                    725:   0, 0, 0,
                    726:   "Move point backward over any number of chars with syntax \"prefix\".")
                    727:   ()
                    728: {
                    729:   int beg = FirstCharacter;
                    730:   int pos = point;
                    731: 
                    732:   while (pos > beg && !char_quoted (pos - 1) && SYNTAX (CharAt (pos - 1)) == Squote)
                    733:     pos--;
                    734: 
                    735:   SetPoint (pos);
                    736: 
                    737:   return Qnil;
                    738: }
                    739: 
                    740: struct lisp_parse_state
                    741:   {
                    742:     int depth;         /* Depth at end of parsing */
                    743:     int instring;      /* -1 if not within string, else desired terminator. */
                    744:     int incomment;     /* Nonzero if within a comment at end of parsing */
                    745:     int quoted;                /* Nonzero if just after an escape char at end of parsing */
                    746:     int thislevelstart;        /* Char number of most recent start-of-expression at current level */
                    747:     int prevlevelstart; /* Char number of start of containing expression */
                    748:     int location;      /* Char number at which parsing stopped. */
                    749:   };
                    750: 
                    751: /* Parse forward from `from' to `end', assuming that `from'
                    752: is the start of a function, and return a description of the state of the parse at `end'. */
                    753: 
                    754: struct lisp_parse_state val_scan_sexps_forward;
                    755: 
                    756: struct lisp_parse_state *
                    757: scan_sexps_forward (from, end, targetdepth, stopbefore, oldstate)
                    758:      register int from;
                    759:      int end, targetdepth, stopbefore;
                    760:      Lisp_Object oldstate;
                    761: {
                    762:   struct lisp_parse_state state;
                    763: 
                    764:   register enum syntaxcode code;
                    765:   struct level { int last, prev; };
                    766:   struct level levelstart[100];
                    767:   register struct level *curlevel = levelstart;
                    768:   struct level *endlevel = levelstart + 100;
                    769:   char prev;
                    770:   register int depth;  /* Paren depth of current scanning location.
                    771:                           level - levelstart equals this except
                    772:                           when the depth becomes negative.  */
                    773:   int start_quoted = 0;                /* Nonzero means starting after a char quote */
                    774:   Lisp_Object tem;
                    775: 
                    776:   immediate_quit = 1;
                    777:   QUIT;
                    778: 
                    779:   if (NULL (oldstate))
                    780:     {
                    781:       depth = 0;
                    782:       state.instring = -1;
                    783:       state.incomment = 0;
                    784:     }
                    785:   else
                    786:     {
                    787:       tem = Fcar (oldstate);
                    788:       if (!NULL (tem))
                    789:        depth = XINT (tem);
                    790:       else
                    791:        depth = 0;
                    792: 
                    793:       oldstate = Fcdr (oldstate);
                    794:       oldstate = Fcdr (oldstate);
                    795:       oldstate = Fcdr (oldstate);
                    796:       tem = Fcar (oldstate);
                    797:       state.instring = !NULL (tem) ? XINT (tem) : -1;
                    798: 
                    799:       oldstate = Fcdr (oldstate);
                    800:       tem = Fcar (oldstate);
                    801:       state.incomment = !NULL (tem);
                    802: 
                    803:       oldstate = Fcdr (oldstate);
                    804:       tem = Fcar (oldstate);
                    805:       start_quoted = !NULL (tem);
                    806:     }
                    807:   state.quoted = 0;
                    808: 
                    809:   curlevel->prev = -1;
                    810: 
                    811:   /* Enter the loop at a place appropriate for initial state. */
                    812: 
                    813:   if (state.incomment) goto startincomment;
                    814:   if (state.instring >= 0)
                    815:     {
                    816:       if (start_quoted) goto startquotedinstring;
                    817:       goto startinstring;
                    818:     }
                    819:   if (start_quoted) goto startquoted;
                    820: 
                    821:   while (from < end)
                    822:     {
                    823:       code = SYNTAX(CharAt (from));
                    824:       from++;
                    825:       if (from < end && SYNTAX_COMSTART_FIRST (CharAt (from - 1))
                    826:           && SYNTAX_COMSTART_SECOND (CharAt (from)))
                    827:        code = Scomment, from++;
                    828: #ifdef SWITCH_ENUM_BUG
                    829:       switch ((int) code)
                    830: #else
                    831:       switch (code)
                    832: #endif
                    833:        {
                    834:        case Sescape:
                    835:        case Scharquote:
                    836:          if (stopbefore) goto stop;  /* this arg means stop at sexp start */
                    837:          curlevel->last = from - 1;
                    838:        startquoted:
                    839:          if (from == end) goto endquoted;
                    840:          from++;
                    841:          goto symstarted;
                    842:          /* treat following character as a word constituent */
                    843:        case Sword:
                    844:        case Ssymbol:
                    845:          if (stopbefore) goto stop;  /* this arg means stop at sexp start */
                    846:          curlevel->last = from - 1;
                    847:        symstarted:
                    848:          while (from < end)
                    849:            {
                    850: #ifdef SWITCH_ENUM_BUG
                    851:              switch ((int) SYNTAX(CharAt (from)))
                    852: #else
                    853:              switch (SYNTAX(CharAt (from)))
                    854: #endif
                    855:                {
                    856:                case Scharquote:
                    857:                case Sescape:
                    858:                  from++;
                    859:                  if (from == end) goto endquoted;
                    860:                  break;
                    861:                case Sword:
                    862:                case Ssymbol:
                    863:                  break;
                    864:                default:
                    865:                  goto symdone;
                    866:                }
                    867:              from++;
                    868:            }
                    869:        symdone:
                    870:          curlevel->prev = curlevel->last;
                    871:          break;
                    872: 
                    873:        case Scomment:
                    874:          state.incomment = 1;
                    875:        startincomment:
                    876:          while (1)
                    877:            {
                    878:              if (from == end) goto done;
                    879:              if (SYNTAX (prev = CharAt (from)) == Sendcomment)
                    880:                break;
                    881:              from++;
                    882:              if (from < end && SYNTAX_COMEND_FIRST (prev)
                    883:                   && SYNTAX_COMEND_SECOND (CharAt (from)))
                    884:                { from++; break; }
                    885:            }
                    886:          state.incomment = 0;
                    887:          break;
                    888: 
                    889:        case Sopen:
                    890:          if (stopbefore) goto stop;  /* this arg means stop at sexp start */
                    891:          depth++;
                    892:          /* curlevel++->last ran into compiler bug on Apollo */
                    893:          curlevel->last = from - 1;
                    894:          if (++curlevel == endlevel)
                    895:            error ("Nesting too deep for parser");
                    896:          curlevel->prev = -1;
                    897:          curlevel->last = -1;
                    898:          if (!--targetdepth) goto done;
                    899:          break;
                    900: 
                    901:        case Sclose:
                    902:          depth--;
                    903:          if (curlevel != levelstart)
                    904:            curlevel--;
                    905:          curlevel->prev = curlevel->last;
                    906:          if (!++targetdepth) goto done;
                    907:          break;
                    908: 
                    909:        case Sstring:
                    910:          if (stopbefore) goto stop;  /* this arg means stop at sexp start */
                    911:          curlevel->last = from - 1;
                    912:          state.instring = CharAt (from - 1);
                    913:        startinstring:
                    914:          while (1)
                    915:            {
                    916:              if (from >= end) goto done;
                    917:              if (CharAt (from) == state.instring) break;
                    918: #ifdef SWITCH_ENUM_BUG
                    919:              switch ((int) SYNTAX(CharAt (from)))
                    920: #else
                    921:              switch (SYNTAX(CharAt (from)))
                    922: #endif
                    923:                {
                    924:                case Scharquote:
                    925:                case Sescape:
                    926:                  from++;
                    927:                startquotedinstring:
                    928:                  if (from >= end) goto endquoted;
                    929:                }
                    930:              from++;
                    931:            }
                    932:          state.instring = -1;
                    933:          curlevel->prev = curlevel->last;
                    934:          from++;
                    935:          break;
                    936: 
                    937:        case Smath:
                    938:          break;
                    939:        }
                    940:     }
                    941:   goto done;
                    942: 
                    943:  stop:   /* Here if stopping before start of sexp. */
                    944:   from--;    /* We have just fetched the char that starts it; */
                    945:   goto done; /* but return the position before it. */
                    946: 
                    947:  endquoted:
                    948:   state.quoted = 1;
                    949:  done:
                    950:   state.depth = depth;
                    951:   state.thislevelstart = curlevel->prev;
                    952:   state.prevlevelstart
                    953:     = (curlevel == levelstart) ? -1 : (curlevel - 1)->last;
                    954:   state.location = from;
                    955:   immediate_quit = 0;
                    956: 
                    957:   val_scan_sexps_forward = state;
                    958:   return &val_scan_sexps_forward;
                    959: }
                    960: 
                    961: DEFUN ("parse-partial-sexp", Fparse_partial_sexp, Sparse_partial_sexp, 2, 5, 0,
                    962:   0 /* See auxdoc.c */)
                    963:   (from, to, targetdepth, stopbefore, oldstate)
                    964:      Lisp_Object from, to, targetdepth, stopbefore, oldstate;
                    965: {
                    966:   struct lisp_parse_state state;
                    967:   int target;
                    968: 
                    969:   if (!NULL (targetdepth))
                    970:     {
                    971:       CHECK_NUMBER (targetdepth, 3);
                    972:       target = XINT (targetdepth);
                    973:     }
                    974:   else
                    975:     target = -100000;          /* We won't reach this depth */
                    976: 
                    977:   validate_region (&from, &to);
                    978:   state = *scan_sexps_forward (XINT (from), XINT (to),
                    979:                               target, !NULL (stopbefore), oldstate);
                    980: 
                    981:   SetPoint (state.location);
                    982:   
                    983:   return Fcons (make_number (state.depth),
                    984:           Fcons (state.prevlevelstart < 0 ? Qnil : make_number (state.prevlevelstart),
                    985:             Fcons (state.thislevelstart < 0 ? Qnil : make_number (state.thislevelstart),
                    986:               Fcons (state.instring >= 0 ? make_number (state.instring) : Qnil,
                    987:                 Fcons (state.incomment ? Qt : Qnil,
                    988:                   Fcons (state.quoted ? Qt : Qnil, Qnil))))));
                    989: }
                    990: 
                    991: init_syntax_once ()
                    992: {
                    993:   register int i;
                    994:   register struct Lisp_Vector *v;
                    995: 
                    996:   /* Set this now, so first buffer creation can refer to it. */
                    997:   /* Make it nil before calling copy-syntax-table
                    998:     so that copy-syntax-table will know not to try to copy from garbage */
                    999:   Vstandard_syntax_table = Qnil;
                   1000:   Vstandard_syntax_table = Fcopy_syntax_table (Qnil);
                   1001: 
                   1002:   v = XVECTOR (Vstandard_syntax_table);
                   1003: 
                   1004:   for (i = 'a'; i <= 'z'; i++)
                   1005:     XFASTINT (v->contents[i]) = (int) Sword;
                   1006:   for (i = 'A'; i <= 'Z'; i++)
                   1007:     XFASTINT (v->contents[i]) = (int) Sword;
                   1008:   for (i = '0'; i <= '9'; i++)
                   1009:     XFASTINT (v->contents[i]) = (int) Sword;
                   1010:   XFASTINT (v->contents['$']) = (int) Sword;
                   1011:   XFASTINT (v->contents['%']) = (int) Sword;
                   1012: 
                   1013:   XFASTINT (v->contents['(']) = (int) Sopen + (')' << 8);
                   1014:   XFASTINT (v->contents[')']) = (int) Sclose + ('(' << 8);
                   1015:   XFASTINT (v->contents['[']) = (int) Sopen + (']' << 8);
                   1016:   XFASTINT (v->contents[']']) = (int) Sclose + ('[' << 8);
                   1017:   XFASTINT (v->contents['{']) = (int) Sopen + ('}' << 8);
                   1018:   XFASTINT (v->contents['}']) = (int) Sclose + ('{' << 8);
                   1019:   XFASTINT (v->contents['"']) = (int) Sstring;
                   1020:   XFASTINT (v->contents['\\']) = (int) Sescape;
                   1021: 
                   1022:   for (i = 0; i < 10; i++)
                   1023:     XFASTINT (v->contents["_-+*/&|<>="[i]]) = (int) Ssymbol;
                   1024: 
                   1025:   for (i = 0; i < 12; i++)
                   1026:     XFASTINT (v->contents[".,;:?!#@~^'`"[i]]) = (int) Spunct;
                   1027: }
                   1028: 
                   1029: syms_of_syntax ()
                   1030: {
                   1031:   Qsyntax_table_p = intern ("syntax-table-p");
                   1032:   staticpro (&Qsyntax_table_p);
                   1033: 
                   1034: /* Mustn't let user clobber this!
                   1035:   DefLispVar ("standard-syntax-table", &Vstandard_syntax_table,
                   1036:     "The syntax table used by buffers that don't specify another.");
                   1037:  */
                   1038:   staticpro (&Vstandard_syntax_table);
                   1039: 
                   1040:   DefBoolVar ("parse-sexp-ignore-comments", &parse_sexp_ignore_comments,
                   1041:     "Non-nil means forward-sexp, etc., should treat comments as whitespace.\n\
                   1042: Non-nil works only when the comment terminator is something like *\/,\n\
                   1043: and appears only when it ends a comment.\n\
                   1044: If comments are terminated by newlines,\n\
                   1045: you must make this variable nil.");
                   1046: 
                   1047:   defsubr (&Ssyntax_table_p);
                   1048:   defsubr (&Ssyntax_table);
                   1049:   defsubr (&Sstandard_syntax_table);
                   1050:   defsubr (&Scopy_syntax_table);
                   1051:   defsubr (&Sset_syntax_table);
                   1052:   defsubr (&Schar_syntax);
                   1053:   defsubr (&Smodify_syntax_entry);
                   1054:   defsubr (&Sdescribe_syntax);
                   1055: 
                   1056:   defsubr (&Sforward_word);
                   1057: 
                   1058:   defsubr (&Sscan_lists);
                   1059:   defsubr (&Sscan_sexps);
                   1060:   defsubr (&Sbackward_prefix_chars);
                   1061:   defsubr (&Sparse_partial_sexp);
                   1062: }

unix.superglobalmegacorp.com

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