Annotation of 43BSDReno/contrib/emacs-18.55/etc/make-docfile.c, revision 1.1.1.1

1.1       root        1: /* Generate doc-string file for GNU Emacs from source files.
                      2:    Copyright (C) 1985, 1986 Free Software Foundation, Inc.
                      3: 
                      4: This file is part of GNU Emacs.
                      5: 
                      6: GNU Emacs is distributed in the hope that it will be useful,
                      7: but without any warranty.  No author or distributor
                      8: accepts responsibility to anyone for the consequences of using it
                      9: or for whether it serves any particular purpose or works at all,
                     10: unless he says so in writing.
                     11: 
                     12: Everyone is granted permission to copy, modify and redistribute
                     13: GNU Emacs, but only under the conditions described in the
                     14: document "GNU Emacs copying permission notice".   An exact copy
                     15: of the document is supposed to have been given to you along with
                     16: GNU Emacs so that you can know how you may redistribute it all.
                     17: It should be in a file named COPYING.  Among other things, the
                     18: copyright notice and this notice must be preserved on all copies.  */
                     19: 
                     20: /* The arguments given to this program are all the C and Lisp source files
                     21:  of GNU Emacs.  .elc and .el and .c files are allowed.
                     22:  A .o file can also be specified; the .c file it was made from is used.
                     23:  This helps the makefile pass the correct list of files.
                     24: 
                     25:  The results, which go to standard output or to a file
                     26:  specified with -a or -o (-a to append, -o to start from nothing),
                     27:  are entries containing function or variable names and their documentation.
                     28:  Each entry starts with a ^_ character.
                     29:  Then comes F for a function or V for a variable.
                     30:  Then comes the function or variable name, terminated with a newline.
                     31:  Then comes the documentation for that function or variable.
                     32:  */
                     33: 
                     34: #include <stdio.h>
                     35: 
                     36: FILE *outfile;
                     37: 
                     38: main (argc, argv)
                     39:      int argc;
                     40:      char **argv;
                     41: {
                     42:   int i;
                     43:   int err_count = 0;
                     44: 
                     45:   outfile = stdout;
                     46: 
                     47:   /* If first two args are -o FILE, output to FILE.  */
                     48:   i = 1;
                     49:   if (argc > i + 1 && !strcmp (argv[i], "-o"))
                     50:     {
                     51:       outfile = fopen (argv[i + 1], "w");
                     52:       i += 2;
                     53:     }
                     54:   if (argc > i + 1 && !strcmp (argv[i], "-a"))
                     55:     {
                     56:       outfile = fopen (argv[i + 1], "a");
                     57:       i += 2;
                     58:     }
                     59: 
                     60:   for (; i < argc; i++)
                     61:     err_count += scan_file (argv[i]);  /* err_count seems to be {mis,un}used */
                     62: #ifndef VMS
                     63:   exit (err_count);                    /* see below - shane */
                     64: #endif VMS
                     65: }
                     66: 
                     67: /* Read file FILENAME and output its doc strings to stdout.  */
                     68: /* Return 1 if file is not found, 0 if it is found.  */
                     69: 
                     70: scan_file (filename)
                     71:      char *filename;
                     72: {
                     73:   int len = strlen (filename);
                     74:   if (!strcmp (filename + len - 4, ".elc"))
                     75:     return scan_lisp_file (filename);
                     76:   else if (!strcmp (filename + len - 3, ".el"))
                     77:     return scan_lisp_file (filename);
                     78:   else
                     79:     return scan_c_file (filename);
                     80: }
                     81: 
                     82: char buf[128];
                     83: 
                     84: /* Skip a C string from INFILE,
                     85:  and return the character that follows the closing ".
                     86:  If printflag is positive, output string contents to stdout.
                     87:  If it is negative, store contents in buf.
                     88:  Convert escape sequences \n and \t to newline and tab;
                     89:  discard \ followed by newline.  */
                     90: 
                     91: read_c_string (infile, printflag)
                     92:      FILE *infile;
                     93:      int printflag;
                     94: {
                     95:   register int c;
                     96:   char *p = buf;
                     97: 
                     98:   c = getc (infile);
                     99:   while (c != EOF)
                    100:     {
                    101:       while (c != '"' && c != EOF)
                    102:        {
                    103:          if (c == '\\')
                    104:            {
                    105:              c = getc (infile);
                    106:              if (c == '\n')
                    107:                {
                    108:                  c = getc (infile);
                    109:                  continue;
                    110:                }
                    111:              if (c == 'n')
                    112:                c = '\n';
                    113:              if (c == 't')
                    114:                c = '\t';
                    115:            }
                    116:          if (printflag > 0)
                    117:            putc (c, outfile);
                    118:          else if (printflag < 0)
                    119:            *p++ = c;
                    120:          c = getc (infile);
                    121:        }
                    122:       c = getc (infile);
                    123:       if (c != '"')
                    124:        break;
                    125:       if (printflag > 0)
                    126:        putc (c, outfile);
                    127:       else if (printflag < 0)
                    128:        *p++ = c;
                    129:       c = getc (infile);
                    130:     }
                    131: 
                    132:   if (printflag < 0)
                    133:     *p = 0;
                    134: 
                    135:   return c;
                    136: }
                    137: 
                    138: /* Read through a c file.  If a .o file is named,
                    139:  the corresponding .c file is read instead.
                    140:  Looks for DEFUN constructs such as are defined in ../src/lisp.h.
                    141:  Accepts any word starting DEF... so it finds DEFSIMPLE and DEFPRED.  */
                    142: 
                    143: scan_c_file (filename)
                    144:      char *filename;
                    145: {
                    146:   FILE *infile;
                    147:   register int c;
                    148:   register int commas;
                    149:   register int defunflag;
                    150:   register int defvarflag;
                    151:   
                    152:   if (filename[strlen (filename) - 1] == 'o')
                    153:     filename[strlen (filename) - 1] = 'c';
                    154: 
                    155:   infile = fopen (filename, "r");
                    156: 
                    157:   /* No error if non-ex input file */
                    158:   if (infile == NULL)
                    159:     {
                    160:       perror (filename);
                    161:       return 0;
                    162:     }
                    163: 
                    164:   c = '\n';
                    165:   while (!feof (infile))
                    166:     {
                    167:       if (c != '\n')
                    168:        {
                    169:          c = getc (infile);
                    170:          continue;
                    171:        }
                    172:       c = getc (infile);
                    173:       if (c == ' ')
                    174:        {
                    175:          while (c == ' ')
                    176:            c = getc (infile);
                    177:          if (c != 'D')
                    178:            continue;
                    179:          c = getc (infile);
                    180:          if (c != 'E')
                    181:            continue;
                    182:          c = getc (infile);
                    183:          if (c != 'F')
                    184:            continue;
                    185:          c = getc (infile);
                    186:          if (c != 'V')
                    187:            continue;
                    188:          defvarflag = 1;
                    189:          defunflag = 0;
                    190:          c = getc (infile);
                    191:        }
                    192:       else if (c == 'D')
                    193:        {
                    194:          c = getc (infile);
                    195:          if (c != 'E')
                    196:            continue;
                    197:          c = getc (infile);
                    198:          if (c != 'F')
                    199:            continue;
                    200:          c = getc (infile);
                    201:          defunflag = c == 'U';
                    202:          defvarflag = 0;
                    203:        }
                    204:       else continue;
                    205: 
                    206:       while (c != '(')
                    207:        {
                    208:          if (c < 0)
                    209:            return 0;
                    210:          c = getc (infile);
                    211:        }
                    212: 
                    213:       c = getc (infile);
                    214:       if (c != '"')
                    215:        continue;
                    216:       c = read_c_string (infile, -1);
                    217: 
                    218:       if (defunflag)
                    219:        commas = 5;
                    220:       else if (defvarflag)
                    221:        commas = 1;
                    222:       else  /* For DEFSIMPLE and DEFPRED */
                    223:        commas = 2;
                    224: 
                    225:       while (commas)
                    226:        {
                    227:          if (c == ',') commas --;
                    228:          if (c < 0)
                    229:            return 0;
                    230:          c = getc (infile);
                    231:        }
                    232:       while (c == ' ' || c == '\n' || c == '\t')
                    233:        c = getc (infile);
                    234:       if (c == '"')
                    235:        c = read_c_string (infile, 0);
                    236:       while (c != ',')
                    237:        c = getc (infile);
                    238:       c = getc (infile);
                    239:       while (c == ' ' || c == '\n' || c == '\t')
                    240:        c = getc (infile);
                    241: 
                    242:       if (c == '"')
                    243:        {
                    244:          putc (037, outfile);
                    245:          putc (defvarflag ? 'V' : 'F', outfile);
                    246:          fprintf (outfile, "%s\n", buf);
                    247:          read_c_string (infile, 1);
                    248:        }
                    249:     }
                    250:   fclose (infile);
                    251:   return 0;
                    252: }
                    253: 
                    254: /* Read a file of Lisp code, compiled or interpreted.
                    255:  Looks for
                    256:   (defun NAME ARGS DOCSTRING ...)
                    257:   (autoload 'NAME FILE DOCSTRING ...)
                    258:   (defvar NAME VALUE DOCSTRING)
                    259:   (defconst NAME VALUE DOCSTRING)
                    260:  starting in column zero.
                    261:  ARGS, FILE or VALUE is ignored.  We do not know how to parse Lisp code
                    262:  so we use a kludge to skip them:
                    263:   In a function definition, the form of ARGS of FILE is known, and we
                    264:   can skip it.
                    265:   In a variable definition, we use a formatting convention:
                    266:   the DOCSTRING, if present, must be followed by a closeparen and a newline,
                    267:   and no newline must appear between the defvar or defconst and the docstring,
                    268:   The only source file that must follow this convention is loaddefs.el;
                    269:   aside from that, it is always the .elc file that we look at, and
                    270:   they are no problem because byte-compiler output follows this convention.
                    271:  The NAME and DOCSTRING are output.
                    272:  NAME is preceded by `F' for a function or `V' for a variable.
                    273:  An entry is output only if DOCSTRING has \ newline just after the opening "
                    274:  */
                    275: 
                    276: scan_lisp_file (filename)
                    277:      char *filename;
                    278: {
                    279:   FILE *infile;
                    280:   register int c;
                    281:   register int commas;
                    282:   register char *p;
                    283:   int defvarflag;
                    284: 
                    285:   infile = fopen (filename, "r");
                    286:   if (infile == NULL)
                    287:     {
                    288:       perror (filename);
                    289:       return 0;                                /* No error */
                    290:     }
                    291: 
                    292:   c = '\n';
                    293:   while (!feof (infile))
                    294:     {
                    295:       if (c != '\n')
                    296:        {
                    297:          c = getc (infile);
                    298:          continue;
                    299:        }
                    300:       c = getc (infile);
                    301:       if (c != '(')
                    302:        continue;
                    303:       c = getc (infile);
                    304:       if (c == 'a')
                    305:        {
                    306:          c = getc (infile);
                    307:          if (c != 'u')
                    308:            continue;
                    309:          c = getc (infile);
                    310:          if (c != 't')
                    311:            continue;
                    312:          c = getc (infile);
                    313:          if (c != 'o')
                    314:            continue;
                    315:          c = getc (infile);
                    316:          if (c != 'l')
                    317:            continue;
                    318:          c = getc (infile);
                    319:          if (c != 'o')
                    320:            continue;
                    321:          c = getc (infile);
                    322:          if (c != 'a')
                    323:            continue;
                    324:          c = getc (infile);
                    325:          if (c != 'd')
                    326:            continue;
                    327: 
                    328:          c = getc (infile);
                    329:          while (c == ' ')
                    330:            c = getc (infile);
                    331: 
                    332:          if (c == '\'')
                    333:            {
                    334:              c = getc (infile);
                    335:            }
                    336:          else
                    337:            {
                    338:              if (c != '(')
                    339:                continue;
                    340:              c = getc (infile);
                    341:              if (c != 'q')
                    342:                continue;
                    343:              c = getc (infile);
                    344:              if (c != 'u')
                    345:                continue;
                    346:              c = getc (infile);
                    347:              if (c != 'o')
                    348:                continue;
                    349:              c = getc (infile);
                    350:              if (c != 't')
                    351:                continue;
                    352:              c = getc (infile);
                    353:              if (c != 'e')
                    354:                continue;
                    355:              c = getc (infile);
                    356:              if (c != ' ')
                    357:                continue;
                    358:              while (c == ' ')
                    359:                c = getc (infile);
                    360:            }
                    361: 
                    362:          p = buf;
                    363:          while (c != ' ' && c != ')')
                    364:            {
                    365:              if (c == EOF)
                    366:                return 1;
                    367:              if (c == '\\')
                    368:                c = getc (infile);
                    369:              *p++ = c;
                    370:              c = getc (infile);
                    371:            }
                    372:          *p = 0;
                    373: 
                    374:          while (c != '"')
                    375:            {
                    376:              if (c == EOF)
                    377:                return 1;
                    378:              c = getc (infile);
                    379:            }
                    380:          c = read_c_string (infile, 0);
                    381:        }
                    382:       else if (c == 'd')
                    383:        {
                    384:          c = getc (infile);
                    385:          if (c != 'e')
                    386:            continue;
                    387:          c = getc (infile);
                    388:          if (c != 'f')
                    389:            continue;
                    390:          c = getc (infile);
                    391:          if (c == 'u')
                    392:            {
                    393:              c = getc (infile);
                    394:              if (c != 'n')
                    395:                continue;
                    396:              defvarflag = 0;
                    397:            }
                    398:          else if (c == 'v')
                    399:            {
                    400:              c = getc (infile);
                    401:              if (c != 'a')
                    402:                continue;
                    403:              c = getc (infile);
                    404:              if (c != 'r')
                    405:                continue;
                    406:              defvarflag = 1;
                    407:            }
                    408:          else if (c == 'c')
                    409:            {
                    410:              c = getc (infile);
                    411:              if (c != 'o')
                    412:                continue;
                    413:              c = getc (infile);
                    414:              if (c != 'n')
                    415:                continue;
                    416:              c = getc (infile);
                    417:              if (c != 's')
                    418:                continue;
                    419:              c = getc (infile);
                    420:              if (c != 't')
                    421:                continue;
                    422:              defvarflag = 1;
                    423:            }
                    424:          else
                    425:            continue;
                    426: 
                    427:          /* Now we have seen "defun" or "defvar" or "defconst".  */
                    428: 
                    429:          while (c != ' ' && c != '\n' && c != '\t')
                    430:            c = getc (infile);
                    431: 
                    432:          while (c == ' ' || c == '\n' || c == '\t')
                    433:            c = getc (infile);
                    434: 
                    435:          /* Read and store name of function or variable being defined
                    436:             Discard backslashes that are for quoting.  */
                    437:          p = buf;
                    438:          while (c != ' ' && c != '\n' && c != '\t')
                    439:            {
                    440:              if (c == '\\')
                    441:                c = getc (infile);
                    442:              *p++ = c;
                    443:              c = getc (infile);
                    444:            }
                    445:          *p = 0;
                    446: 
                    447:          while (c == ' ' || c == '\n' || c == '\t')
                    448:            c = getc (infile);
                    449: 
                    450:          if (! defvarflag)
                    451:            {
                    452:              /* A function: */
                    453:              /* Skip the arguments: either "nil" or a list in parens */
                    454:              if (c == 'n')
                    455:                {
                    456:                  while (c != ' ' && c != '\n' && c != '\t')
                    457:                    c = getc (infile);
                    458:                }
                    459:              else
                    460:                {
                    461:                  while (c != '(')
                    462:                    c = getc (infile);
                    463:                  while (c != ')')
                    464:                    c = getc (infile);
                    465:                }
                    466:              c = getc (infile);
                    467:            }
                    468:          else
                    469:            {
                    470:              /* A variable:  */
                    471: 
                    472:              /* Skip until the first newline; remember
                    473:                 the two previous characters.  */
                    474:              char c1 = 0, c2 = 0;
                    475: 
                    476:              while (c != '\n' && c >= 0)
                    477:                {
                    478:                  c2 = c1;
                    479:                  c1 = c;
                    480:                  c = getc (infile);
                    481:                }
                    482: 
                    483:              /* If two previous characters were " and \,
                    484:                 this is a doc string.  Otherwise, there is none.  */
                    485:              if (c2 == '"' && c1 == '\\')
                    486:                {
                    487:                  putc (037, outfile);
                    488:                  putc ('V', outfile);
                    489:                  fprintf (outfile, "%s\n", buf);
                    490:                  read_c_string (infile, 1);
                    491:                }
                    492:              continue;
                    493:            }
                    494:        }
                    495:       else
                    496:        continue;
                    497: 
                    498:       /* Here for a function definition.
                    499:         We have skipped the file name or arguments
                    500:         and arrived at where the doc string is,
                    501:         if there is a doc string.  */
                    502: 
                    503:       /* Skip whitespace */
                    504: 
                    505:       while (c == ' ' || c == '\n' || c == '\t')
                    506:        c = getc (infile);
                    507: 
                    508:       /* " followed by \ and newline means a doc string we should gobble */
                    509:       if (c != '"')
                    510:        continue;
                    511:       c = getc (infile);
                    512:       if (c != '\\')
                    513:        continue;
                    514:       c = getc (infile);
                    515:       if (c != '\n')
                    516:        continue;
                    517: 
                    518:       putc (037, outfile);
                    519:       putc ('F', outfile);
                    520:       fprintf (outfile, "%s\n", buf);
                    521:       read_c_string (infile, 1);
                    522:     }
                    523:   fclose (infile);
                    524:   return 0;
                    525: }

unix.superglobalmegacorp.com

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