Mercurial > emacs
comparison lib-src/etags.c @ 90234:b1c1fc853d2f
Revision: miles@gnu.org--gnu-2005/emacs--unicode--0--patch-86
Merge from emacs--cvs-trunk--0
Patches applied:
* emacs--cvs-trunk--0 (patch 562-568)
- Update from CVS
- Merge from gnus--rel--5.10
* gnus--rel--5.10 (patch 125-128)
- Merge from emacs--cvs-trunk--0
- Update from CVS
author | Miles Bader <miles@gnu.org> |
---|---|
date | Fri, 30 Sep 2005 11:43:45 +0000 |
parents | 2d92f5c9d6ae fbae8bd411de |
children | 0ca0d9181b5e |
comparison
equal
deleted
inserted
replaced
90233:ee12d75eb214 | 90234:b1c1fc853d2f |
---|---|
39 * If you want to add support for a new language, start by looking at the LUA | 39 * If you want to add support for a new language, start by looking at the LUA |
40 * language, which is the simplest. Alternatively, consider shipping a | 40 * language, which is the simplest. Alternatively, consider shipping a |
41 * configuration file containing regexp definitions for etags. | 41 * configuration file containing regexp definitions for etags. |
42 */ | 42 */ |
43 | 43 |
44 char pot_etags_version[] = "@(#) pot revision number is 17.5"; | 44 char pot_etags_version[] = "@(#) pot revision number is 17.14"; |
45 | 45 |
46 #define TRUE 1 | 46 #define TRUE 1 |
47 #define FALSE 0 | 47 #define FALSE 0 |
48 | 48 |
49 #ifdef DEBUG | 49 #ifdef DEBUG |
341 static void Cjava_entries __P((FILE *)); | 341 static void Cjava_entries __P((FILE *)); |
342 static void Cobol_paragraphs __P((FILE *)); | 342 static void Cobol_paragraphs __P((FILE *)); |
343 static void Cplusplus_entries __P((FILE *)); | 343 static void Cplusplus_entries __P((FILE *)); |
344 static void Cstar_entries __P((FILE *)); | 344 static void Cstar_entries __P((FILE *)); |
345 static void Erlang_functions __P((FILE *)); | 345 static void Erlang_functions __P((FILE *)); |
346 static void Forth_words __P((FILE *)); | |
346 static void Fortran_functions __P((FILE *)); | 347 static void Fortran_functions __P((FILE *)); |
347 static void HTML_labels __P((FILE *)); | 348 static void HTML_labels __P((FILE *)); |
348 static void Lisp_functions __P((FILE *)); | 349 static void Lisp_functions __P((FILE *)); |
349 static void Lua_functions __P((FILE *)); | 350 static void Lua_functions __P((FILE *)); |
350 static void Makefile_targets __P((FILE *)); | 351 static void Makefile_targets __P((FILE *)); |
487 #endif /* ETAGS_REGEXPS */ | 488 #endif /* ETAGS_REGEXPS */ |
488 | 489 |
489 #if LONG_OPTIONS | 490 #if LONG_OPTIONS |
490 static struct option longopts[] = | 491 static struct option longopts[] = |
491 { | 492 { |
493 { "append", no_argument, NULL, 'a' }, | |
492 { "packages-only", no_argument, &packages_only, TRUE }, | 494 { "packages-only", no_argument, &packages_only, TRUE }, |
493 { "c++", no_argument, NULL, 'C' }, | 495 { "c++", no_argument, NULL, 'C' }, |
494 { "declarations", no_argument, &declarations, TRUE }, | 496 { "declarations", no_argument, &declarations, TRUE }, |
495 { "no-line-directive", no_argument, &no_line_directive, TRUE }, | 497 { "no-line-directive", no_argument, &no_line_directive, TRUE }, |
496 { "help", no_argument, NULL, 'h' }, | 498 { "help", no_argument, NULL, 'h' }, |
506 { "ignore-case-regex", required_argument, NULL, 'c' }, | 508 { "ignore-case-regex", required_argument, NULL, 'c' }, |
507 #endif /* ETAGS_REGEXPS */ | 509 #endif /* ETAGS_REGEXPS */ |
508 { "parse-stdin", required_argument, NULL, STDIN }, | 510 { "parse-stdin", required_argument, NULL, STDIN }, |
509 { "version", no_argument, NULL, 'V' }, | 511 { "version", no_argument, NULL, 'V' }, |
510 | 512 |
511 #if CTAGS /* Etags options */ | 513 #if CTAGS /* Ctags options */ |
512 { "backward-search", no_argument, NULL, 'B' }, | 514 { "backward-search", no_argument, NULL, 'B' }, |
513 { "cxref", no_argument, NULL, 'x' }, | 515 { "cxref", no_argument, NULL, 'x' }, |
514 { "defines", no_argument, NULL, 'd' }, | 516 { "defines", no_argument, NULL, 'd' }, |
515 { "globals", no_argument, &globals, TRUE }, | 517 { "globals", no_argument, &globals, TRUE }, |
516 { "typedefs", no_argument, NULL, 't' }, | 518 { "typedefs", no_argument, NULL, 't' }, |
517 { "typedefs-and-c++", no_argument, NULL, 'T' }, | 519 { "typedefs-and-c++", no_argument, NULL, 'T' }, |
518 { "update", no_argument, NULL, 'u' }, | 520 { "update", no_argument, NULL, 'u' }, |
519 { "vgrind", no_argument, NULL, 'v' }, | 521 { "vgrind", no_argument, NULL, 'v' }, |
520 { "no-warn", no_argument, NULL, 'w' }, | 522 { "no-warn", no_argument, NULL, 'w' }, |
521 | 523 |
522 #else /* Ctags options */ | 524 #else /* Etags options */ |
523 { "append", no_argument, NULL, 'a' }, | |
524 { "no-defines", no_argument, NULL, 'D' }, | 525 { "no-defines", no_argument, NULL, 'D' }, |
525 { "no-globals", no_argument, &globals, FALSE }, | 526 { "no-globals", no_argument, &globals, FALSE }, |
526 { "include", required_argument, NULL, 'i' }, | 527 { "include", required_argument, NULL, 'i' }, |
527 #endif | 528 #endif |
528 { NULL } | 529 { NULL } |
629 { "erl", "hrl", NULL }; | 630 { "erl", "hrl", NULL }; |
630 static char Erlang_help [] = | 631 static char Erlang_help [] = |
631 "In Erlang code, the tags are the functions, records and macros\n\ | 632 "In Erlang code, the tags are the functions, records and macros\n\ |
632 defined in the file."; | 633 defined in the file."; |
633 | 634 |
635 char *Forth_suffixes [] = | |
636 { "fth", "tok", NULL }; | |
637 static char Forth_help [] = | |
638 "In Forth code, tags are words defined by `:',\n\ | |
639 constant, code, create, defer, value, variable, buffer:, field."; | |
640 | |
634 static char *Fortran_suffixes [] = | 641 static char *Fortran_suffixes [] = |
635 { "F", "f", "f90", "for", NULL }; | 642 { "F", "f", "f90", "for", NULL }; |
636 static char Fortran_help [] = | 643 static char Fortran_help [] = |
637 "In Fortran code, functions, subroutines and block data are tags."; | 644 "In Fortran code, functions, subroutines and block data are tags."; |
638 | 645 |
776 { "c", default_C_help, default_C_entries, default_C_suffixes }, | 783 { "c", default_C_help, default_C_entries, default_C_suffixes }, |
777 { "c++", Cplusplus_help, Cplusplus_entries, Cplusplus_suffixes }, | 784 { "c++", Cplusplus_help, Cplusplus_entries, Cplusplus_suffixes }, |
778 { "c*", no_lang_help, Cstar_entries, Cstar_suffixes }, | 785 { "c*", no_lang_help, Cstar_entries, Cstar_suffixes }, |
779 { "cobol", Cobol_help, Cobol_paragraphs, Cobol_suffixes }, | 786 { "cobol", Cobol_help, Cobol_paragraphs, Cobol_suffixes }, |
780 { "erlang", Erlang_help, Erlang_functions, Erlang_suffixes }, | 787 { "erlang", Erlang_help, Erlang_functions, Erlang_suffixes }, |
788 { "forth", Forth_help, Forth_words, Forth_suffixes }, | |
781 { "fortran", Fortran_help, Fortran_functions, Fortran_suffixes }, | 789 { "fortran", Fortran_help, Fortran_functions, Fortran_suffixes }, |
782 { "html", HTML_help, HTML_labels, HTML_suffixes }, | 790 { "html", HTML_help, HTML_labels, HTML_suffixes }, |
783 { "java", Cjava_help, Cjava_entries, Cjava_suffixes }, | 791 { "java", Cjava_help, Cjava_entries, Cjava_suffixes }, |
784 { "lisp", Lisp_help, Lisp_functions, Lisp_suffixes }, | 792 { "lisp", Lisp_help, Lisp_functions, Lisp_suffixes }, |
785 { "lua", Lua_help, Lua_functions, Lua_suffixes }, | 793 { "lua", Lua_help, Lua_functions, Lua_suffixes }, |
879 linked with GNU getopt."); | 887 linked with GNU getopt."); |
880 puts (" A - as file name means read names from stdin (one per line).\n\ | 888 puts (" A - as file name means read names from stdin (one per line).\n\ |
881 Absolute names are stored in the output file as they are.\n\ | 889 Absolute names are stored in the output file as they are.\n\ |
882 Relative ones are stored relative to the output file's directory.\n"); | 890 Relative ones are stored relative to the output file's directory.\n"); |
883 | 891 |
884 if (!CTAGS) | 892 puts ("-a, --append\n\ |
885 puts ("-a, --append\n\ | |
886 Append tag entries to existing tags file."); | 893 Append tag entries to existing tags file."); |
887 | 894 |
888 puts ("--packages-only\n\ | 895 puts ("--packages-only\n\ |
889 For Ada files, only generate tags for packages."); | 896 For Ada files, only generate tags for packages."); |
890 | 897 |
1178 { | 1185 { |
1179 typedefs = typedefs_or_cplusplus = constantypedefs = TRUE; | 1186 typedefs = typedefs_or_cplusplus = constantypedefs = TRUE; |
1180 globals = TRUE; | 1187 globals = TRUE; |
1181 } | 1188 } |
1182 | 1189 |
1190 /* When the optstring begins with a '-' getopt_long does not rearrange the | |
1191 non-options arguments to be at the end, but leaves them alone. */ | |
1183 optstring = "-"; | 1192 optstring = "-"; |
1184 #ifdef ETAGS_REGEXPS | 1193 #ifdef ETAGS_REGEXPS |
1185 optstring = "-r:Rc:"; | 1194 optstring = "-r:Rc:"; |
1186 #endif /* ETAGS_REGEXPS */ | 1195 #endif /* ETAGS_REGEXPS */ |
1187 if (!LONG_OPTIONS) | 1196 if (!LONG_OPTIONS) |
1188 optstring += 1; | 1197 optstring += 1; /* remove the initial '-' */ |
1189 optstring = concat (optstring, | 1198 optstring = concat (optstring, |
1190 "Cf:Il:o:SVhH", | 1199 "aCf:Il:o:SVhH", |
1191 (CTAGS) ? "BxdtTuvw" : "aDi:"); | 1200 (CTAGS) ? "BxdtTuvw" : "Di:"); |
1192 | 1201 |
1193 while ((opt = getopt_long (argc, argv, optstring, longopts, 0)) != EOF) | 1202 while ((opt = getopt_long (argc, argv, optstring, longopts, NULL)) != EOF) |
1194 switch (opt) | 1203 switch (opt) |
1195 { | 1204 { |
1196 case 0: | 1205 case 0: |
1197 /* If getopt returns 0, then it has already processed a | 1206 /* If getopt returns 0, then it has already processed a |
1198 long-named option. We should do nothing. */ | 1207 long-named option. We should do nothing. */ |
1216 fatal ("cannot parse standard input more than once", (char *)NULL); | 1225 fatal ("cannot parse standard input more than once", (char *)NULL); |
1217 parsing_stdin = TRUE; | 1226 parsing_stdin = TRUE; |
1218 break; | 1227 break; |
1219 | 1228 |
1220 /* Common options. */ | 1229 /* Common options. */ |
1230 case 'a': append_to_tagfile = TRUE; break; | |
1221 case 'C': cplusplus = TRUE; break; | 1231 case 'C': cplusplus = TRUE; break; |
1222 case 'f': /* for compatibility with old makefiles */ | 1232 case 'f': /* for compatibility with old makefiles */ |
1223 case 'o': | 1233 case 'o': |
1224 if (tagfile) | 1234 if (tagfile) |
1225 { | 1235 { |
1265 case 'H': | 1275 case 'H': |
1266 help_asked = TRUE; | 1276 help_asked = TRUE; |
1267 break; | 1277 break; |
1268 | 1278 |
1269 /* Etags options */ | 1279 /* Etags options */ |
1270 case 'a': append_to_tagfile = TRUE; break; | |
1271 case 'D': constantypedefs = FALSE; break; | 1280 case 'D': constantypedefs = FALSE; break; |
1272 case 'i': included_files[nincluded_files++] = optarg; break; | 1281 case 'i': included_files[nincluded_files++] = optarg; break; |
1273 | 1282 |
1274 /* Ctags options. */ | 1283 /* Ctags options. */ |
1275 case 'B': searchar = '?'; break; | 1284 case 'B': searchar = '?'; break; |
1283 default: | 1292 default: |
1284 suggest_asking_for_help (); | 1293 suggest_asking_for_help (); |
1285 /* NOTREACHED */ | 1294 /* NOTREACHED */ |
1286 } | 1295 } |
1287 | 1296 |
1297 /* No more options. Store the rest of arguments. */ | |
1288 for (; optind < argc; optind++) | 1298 for (; optind < argc; optind++) |
1289 { | 1299 { |
1290 argbuffer[current_arg].arg_type = at_filename; | 1300 argbuffer[current_arg].arg_type = at_filename; |
1291 argbuffer[current_arg].what = argv[optind]; | 1301 argbuffer[current_arg].what = argv[optind]; |
1292 ++current_arg; | 1302 ++current_arg; |
1411 free (filebuf.buffer); | 1421 free (filebuf.buffer); |
1412 free (token_name.buffer); | 1422 free (token_name.buffer); |
1413 | 1423 |
1414 if (!CTAGS || cxref_style) | 1424 if (!CTAGS || cxref_style) |
1415 { | 1425 { |
1416 put_entries (nodehead); /* write the remainig tags (ETAGS) */ | 1426 put_entries (nodehead); /* write the remaining tags (ETAGS) */ |
1417 free_tree (nodehead); | 1427 free_tree (nodehead); |
1418 nodehead = NULL; | 1428 nodehead = NULL; |
1419 if (!CTAGS) | 1429 if (!CTAGS) |
1420 { | 1430 { |
1421 fdesc *fdp; | 1431 fdesc *fdp; |
1463 free_tree (nodehead); | 1473 free_tree (nodehead); |
1464 nodehead = NULL; | 1474 nodehead = NULL; |
1465 if (fclose (tagf) == EOF) | 1475 if (fclose (tagf) == EOF) |
1466 pfatal (tagfile); | 1476 pfatal (tagfile); |
1467 | 1477 |
1468 if (update) | 1478 if (CTAGS) |
1469 { | 1479 if (append_to_tagfile || update) |
1470 char cmd[2*BUFSIZ+10]; | 1480 { |
1471 sprintf (cmd, "sort -o %.*s %.*s", BUFSIZ, tagfile, BUFSIZ, tagfile); | 1481 char cmd[2*BUFSIZ+10]; |
1472 exit (system (cmd)); | 1482 sprintf (cmd, "sort -o %.*s %.*s", BUFSIZ, tagfile, BUFSIZ, tagfile); |
1473 } | 1483 exit (system (cmd)); |
1484 } | |
1474 return EXIT_SUCCESS; | 1485 return EXIT_SUCCESS; |
1475 } | 1486 } |
1476 | 1487 |
1477 | 1488 |
1478 /* | 1489 /* |
4073 && /* instructions at start of loop */ \ | 4084 && /* instructions at start of loop */ \ |
4074 (readline (&line_buffer, file_pointer), \ | 4085 (readline (&line_buffer, file_pointer), \ |
4075 char_pointer = line_buffer.buffer, \ | 4086 char_pointer = line_buffer.buffer, \ |
4076 TRUE); \ | 4087 TRUE); \ |
4077 ) | 4088 ) |
4078 #define LOOKING_AT(cp, keyword) /* keyword is a constant string */ \ | 4089 |
4079 (strneq ((cp), keyword, sizeof(keyword)-1) /* cp points at keyword */ \ | 4090 #define LOOKING_AT(cp, kw) /* kw is the keyword, a literal string */ \ |
4080 && notinname ((cp)[sizeof(keyword)-1]) /* end of keyword */ \ | 4091 ((assert("" kw), TRUE) /* syntax error if not a literal string */ \ |
4081 && ((cp) = skip_spaces((cp)+sizeof(keyword)-1))) /* skip spaces */ | 4092 && strneq ((cp), kw, sizeof(kw)-1) /* cp points at kw */ \ |
4093 && notinname ((cp)[sizeof(kw)-1]) /* end of kw */ \ | |
4094 && ((cp) = skip_spaces((cp)+sizeof(kw)-1))) /* skip spaces */ | |
4095 | |
4096 /* Similar to LOOKING_AT but does not use notinname, does not skip */ | |
4097 #define LOOKING_AT_NOCASE(cp, kw) /* the keyword is a literal string */ \ | |
4098 ((assert("" kw), TRUE) /* syntax error if not a literal string */ \ | |
4099 && strncaseeq ((cp), kw, sizeof(kw)-1) /* cp points at kw */ \ | |
4100 && ((cp) += sizeof(kw)-1)) /* skip spaces */ | |
4082 | 4101 |
4083 /* | 4102 /* |
4084 * Read a file, but do no processing. This is used to do regexp | 4103 * Read a file, but do no processing. This is used to do regexp |
4085 * matching on files that have no language defined. | 4104 * matching on files that have no language defined. |
4086 */ | 4105 */ |
4954 } | 4973 } |
4955 } | 4974 } |
4956 | 4975 |
4957 | 4976 |
4958 /* | 4977 /* |
4959 * Postscript tag functions | 4978 * Postscript tags |
4960 * Just look for lines where the first character is '/' | 4979 * Just look for lines where the first character is '/' |
4961 * Also look at "defineps" for PSWrap | 4980 * Also look at "defineps" for PSWrap |
4962 * Ideas by: | 4981 * Ideas by: |
4963 * Richard Mlynarik <mly@adoc.xerox.com> (1997) | 4982 * Richard Mlynarik <mly@adoc.xerox.com> (1997) |
4964 * Masatake Yamato <masata-y@is.aist-nara.ac.jp> (1999) | 4983 * Masatake Yamato <masata-y@is.aist-nara.ac.jp> (1999) |
4985 } | 5004 } |
4986 } | 5005 } |
4987 | 5006 |
4988 | 5007 |
4989 /* | 5008 /* |
5009 * Forth tags | |
5010 * Ignore anything after \ followed by space or in ( ) | |
5011 * Look for words defined by : | |
5012 * Look for constant, code, create, defer, value, and variable | |
5013 * OBP extensions: Look for buffer:, field, | |
5014 * Ideas by Eduardo Horvath <eeh@netbsd.org> (2004) | |
5015 */ | |
5016 static void | |
5017 Forth_words (inf) | |
5018 FILE *inf; | |
5019 { | |
5020 register char *bp; | |
5021 | |
5022 LOOP_ON_INPUT_LINES (inf, lb, bp) | |
5023 while ((bp = skip_spaces (bp))[0] != '\0') | |
5024 if (bp[0] == '\\' && iswhite(bp[1])) | |
5025 break; /* read next line */ | |
5026 else if (bp[0] == '(' && iswhite(bp[1])) | |
5027 do /* skip to ) or eol */ | |
5028 bp++; | |
5029 while (*bp != ')' && *bp != '\0'); | |
5030 else if ((bp[0] == ':' && iswhite(bp[1]) && bp++) | |
5031 || LOOKING_AT_NOCASE (bp, "constant") | |
5032 || LOOKING_AT_NOCASE (bp, "code") | |
5033 || LOOKING_AT_NOCASE (bp, "create") | |
5034 || LOOKING_AT_NOCASE (bp, "defer") | |
5035 || LOOKING_AT_NOCASE (bp, "value") | |
5036 || LOOKING_AT_NOCASE (bp, "variable") | |
5037 || LOOKING_AT_NOCASE (bp, "buffer:") | |
5038 || LOOKING_AT_NOCASE (bp, "field")) | |
5039 get_tag (skip_spaces (bp), NULL); /* Yay! A definition! */ | |
5040 else | |
5041 bp = skip_non_spaces (bp); | |
5042 } | |
5043 | |
5044 | |
5045 /* | |
4990 * Scheme tag functions | 5046 * Scheme tag functions |
4991 * look for (def... xyzzy | 5047 * look for (def... xyzzy |
4992 * (def... (xyzzy | 5048 * (def... (xyzzy |
4993 * (def ... ((...(xyzzy .... | 5049 * (def ... ((...(xyzzy .... |
4994 * (set! xyzzy | 5050 * (set! xyzzy |
4995 * Original code by Ken Haase (1985?) | 5051 * Original code by Ken Haase (1985?) |
4996 */ | 5052 */ |
4997 | |
4998 static void | 5053 static void |
4999 Scheme_functions (inf) | 5054 Scheme_functions (inf) |
5000 FILE *inf; | 5055 FILE *inf; |
5001 { | 5056 { |
5002 register char *bp; | 5057 register char *bp; |
5211 lb.buffer, cp - lb.buffer + 1, lineno, linecharno); | 5266 lb.buffer, cp - lb.buffer + 1, lineno, linecharno); |
5212 } | 5267 } |
5213 } | 5268 } |
5214 | 5269 |
5215 | 5270 |
5216 /* Similar to LOOKING_AT but does not use notinname, does not skip */ | |
5217 #define LOOKING_AT_NOCASE(cp, kw) /* kw is a constant string */ \ | |
5218 (strncaseeq ((cp), kw, sizeof(kw)-1) /* cp points at kw */ \ | |
5219 && ((cp) += sizeof(kw)-1)) /* skip spaces */ | |
5220 | |
5221 /* | 5271 /* |
5222 * HTML support. | 5272 * HTML support. |
5223 * Contents of <title>, <h1>, <h2>, <h3> are tags. | 5273 * Contents of <title>, <h1>, <h2>, <h3> are tags. |
5224 * Contents of <a name=xxx> are tags with name xxx. | 5274 * Contents of <a name=xxx> are tags with name xxx. |
5225 * | 5275 * |
5432 | 5482 |
5433 if ((s[pos] == '.' | 5483 if ((s[pos] == '.' |
5434 || (s[pos] == '(' && (pos += 1)) | 5484 || (s[pos] == '(' && (pos += 1)) |
5435 || (s[pos] == ':' && s[pos + 1] == '-' && (pos += 2))) | 5485 || (s[pos] == ':' && s[pos + 1] == '-' && (pos += 2))) |
5436 && (last == NULL /* save only the first clause */ | 5486 && (last == NULL /* save only the first clause */ |
5437 || len != strlen (last) | 5487 || len != (int)strlen (last) |
5438 || !strneq (s, last, len))) | 5488 || !strneq (s, last, len))) |
5439 { | 5489 { |
5440 make_tag (s, len, TRUE, s, pos, lineno, linecharno); | 5490 make_tag (s, len, TRUE, s, pos, lineno, linecharno); |
5441 return len; | 5491 return len; |
5442 } | 5492 } |
6500 return (ISALPHA (*s1) && ISALPHA (*s2) | 6550 return (ISALPHA (*s1) && ISALPHA (*s2) |
6501 ? lowcase (*s1) - lowcase (*s2) | 6551 ? lowcase (*s1) - lowcase (*s2) |
6502 : *s1 - *s2); | 6552 : *s1 - *s2); |
6503 } | 6553 } |
6504 | 6554 |
6505 /* Skip spaces, return new pointer. */ | 6555 /* Skip spaces (end of string is not space), return new pointer. */ |
6506 static char * | 6556 static char * |
6507 skip_spaces (cp) | 6557 skip_spaces (cp) |
6508 char *cp; | 6558 char *cp; |
6509 { | 6559 { |
6510 while (iswhite (*cp)) | 6560 while (iswhite (*cp)) |
6511 cp++; | 6561 cp++; |
6512 return cp; | 6562 return cp; |
6513 } | 6563 } |
6514 | 6564 |
6515 /* Skip non spaces, return new pointer. */ | 6565 /* Skip non spaces, except end of string, return new pointer. */ |
6516 static char * | 6566 static char * |
6517 skip_non_spaces (cp) | 6567 skip_non_spaces (cp) |
6518 char *cp; | 6568 char *cp; |
6519 { | 6569 { |
6520 while (*cp != '\0' && !iswhite (*cp)) | 6570 while (*cp != '\0' && !iswhite (*cp)) |