1 /* RCS common definitions and data structures 2 3 Copyright (C) 2010-2020 Thien-Thi Nguyen 4 Copyright (C) 1990, 1991, 1992, 1993, 1994, 1995 Paul Eggert 5 Copyright (C) 1982, 1988, 1989 Walter Tichy 6 7 This file is part of GNU RCS. 8 9 GNU RCS is free software: you can redistribute it and/or modify it 10 under the terms of the GNU General Public License as published by 11 the Free Software Foundation, either version 3 of the License, or 12 (at your option) any later version. 13 14 GNU RCS is distributed in the hope that it will be useful, 15 but WITHOUT ANY WARRANTY; without even the implied warranty 16 of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 17 See the GNU General Public License for more details. 18 19 You should have received a copy of the GNU General Public License 20 along with this program. If not, see <http://www.gnu.org/licenses/>. 21 */ 22 23 #include "config.h" 24 #include <stdbool.h> 25 #include <stdint.h> 26 #include <stdio.h> 27 #include <sys/types.h> 28 #include <sys/stat.h> 29 #include "vla.h" 30 31 #ifdef HAVE_LIMITS_H 32 #include <limits.h> 33 #endif 34 #ifdef HAVE_MACH_MACH_H 35 #include <mach/mach.h> 36 #endif 37 #ifdef HAVE_NET_ERRNO_H 38 #include <net/errno.h> 39 #endif 40 #ifdef HAVE_VFORK_H 41 #include <vfork.h> 42 #endif 43 44 #define exiting _Noreturn 45 46 /* Some compilers, notably: 47 - IBM XL C/C++ for AIX, V11.1 (5724-X13), Version: 11.01.0000.0019 48 don't like implicitly considering non-‘NULL’ pointers as ‘true’. */ 49 #define BOOLEAN(x) ((x) ? true : false) 50 51 /* GCC attributes */ 52 53 #define ARG_NONNULL(which) _GL_ARG_NONNULL (which) 54 #define ALL_NONNULL _GL_ARG_NONNULL () 55 56 #define RCS_UNUSED _GL_UNUSED 57 58 #if __GNUC__ >= 3 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 7) 59 #define printf_string(m, n) __attribute__ ((__format__ (printf, m, n))) 60 #else 61 #define printf_string(m, n) 62 #endif 63 64 /* Keyword substitution modes. The order must agree with ‘kwsub_pool’. */ 65 enum kwsub 66 { 67 kwsub_kv, /* $Keyword: value $ */ 68 kwsub_kvl, /* $Keyword: value locker $ */ 69 kwsub_k, /* $Keyword$ */ 70 kwsub_v, /* value */ 71 kwsub_o, /* (old string) */ 72 kwsub_b /* (binary i/o old string) */ 73 }; 74 75 /* begin cruft formerly from from conf.h */ 76 77 #ifdef O_BINARY 78 /* Text and binary i/o behave differently. 79 This is incompatible with POSIX and Unix. */ 80 #define FOPEN_RB "rb" 81 #define FOPEN_R_WORK (BE (kws) == kwsub_b ? "r" : "rb") 82 #define FOPEN_WB "wb" 83 #define FOPEN_W_WORK (BE (kws) == kwsub_b ? "w" : "wb") 84 #define FOPEN_WPLUS_WORK (BE (kws) == kwsub_b ? "w+" : "w+b") 85 #define OPEN_O_BINARY O_BINARY 86 #else 87 /* Text and binary i/o behave the same. 88 Omit "b", since some nonstandard hosts reject it. */ 89 #define FOPEN_RB "r" 90 #define FOPEN_R_WORK "r" 91 #define FOPEN_WB "w" 92 #define FOPEN_W_WORK "w" 93 #define FOPEN_WPLUS_WORK "w+" 94 #define OPEN_O_BINARY 0 95 #endif 96 97 /* Lock file mode. */ 98 #define OPEN_CREAT_READONLY (S_IRUSR|S_IRGRP|S_IROTH) 99 100 /* Extra open flags for creating lock file. */ 101 #define OPEN_O_LOCK 0 102 103 /* Main open flag for creating a lock file. */ 104 #define OPEN_O_WRONLY O_WRONLY 105 106 /* Can ‘rename (A, B)’ falsely report success? */ 107 #define bad_NFS_rename 0 108 109 /* Might NFS be used? */ 110 #define has_NFS 1 111 112 /* Shell to run RCS subprograms. */ 113 #define RCS_SHELL "/bin/sh" 114 115 /* Filename component separation. 116 TMPDIR string Default directory for temporary files. 117 SLASH char Principal filename separator. 118 SLASHes ‘case SLASHes:’ Labels all filename separators. 119 ABSFNAME(p) expression Is p an absolute filename? 120 */ 121 #if !WOE 122 #define TMPDIR "/tmp" 123 #define SLASH '/' 124 #define SLASHes '/' 125 #define ABSFNAME(p) (isSLASH ((p)[0])) 126 #else /* WOE */ 127 #define TMPDIR "\\tmp" 128 #define SLASH "'\\'" 129 #define SLASHes '\\': case '/': case ':' 130 #define ABSFNAME(p) (isSLASH ((p)[0]) || (p)[0] && (p)[1] == ':') 131 #endif 132 133 /* Must TZ be set for ‘gmtime_r’ to work? */ 134 #define TZ_must_be_set 0 135 136 #if defined HAVE_WORKING_FORK && !defined HAVE_WORKING_VFORK 137 #undef vfork 138 #define vfork fork 139 #endif 140 141 /* end cruft formerly from from conf.h */ 142 143 #ifdef _POSIX_PATH_MAX 144 #define SIZEABLE_FILENAME_LEN _POSIX_PATH_MAX 145 #else 146 /* Size of a large filename; not a hard limit. */ 147 #define SIZEABLE_FILENAME_LEN 255 148 #endif 149 150 /* Backwards compatibility with old versions of RCS. */ 151 152 /* Oldest output RCS format supported. */ 153 #define VERSION_min 3 154 /* Newest output RCS format supported. */ 155 #define VERSION_max 5 156 /* Default RCS output format. */ 157 #ifndef VERSION_DEFAULT 158 #define VERSION_DEFAULT VERSION_max 159 #endif 160 /* Internally, 0 is the default. */ 161 #define VERSION(n) ((n) - VERSION_DEFAULT) 162 163 /* Locking strictness 164 false sets the default locking to non-strict; 165 used in experimental environments. 166 true sets the default locking to strict; 167 used in production environments. 168 */ 169 #ifndef STRICT_LOCKING 170 #define STRICT_LOCKING true 171 #endif 172 173 /* Delimiter for keywords. */ 174 #define KDELIM '$' 175 /* Separates keywords from values. */ 176 #define VDELIM ':' 177 /* Default state of revisions. */ 178 #define DEFAULTSTATE "Exp" 179 180 /* Minimum value for no logical expansion. */ 181 #define MIN_UNEXPAND kwsub_o 182 /* The minimum value guaranteed to yield an identical file. */ 183 #define MIN_UNCHANGED_EXPAND (OPEN_O_BINARY ? kwsub_b : kwsub_o) 184 185 /* Define to 1 to enable the "need expansion" handling 186 (support for a future rewrite of b-kwxout). */ 187 #define WITH_NEEDEXP 0 188 189 struct diffcmd 190 { 191 /* Number of first line. */ 192 long line1; 193 /* Number of lines affected. */ 194 long nlines; 195 /* Previous 'a' line1+1 or 'd' line1. */ 196 long adprev; 197 /* Sum of previous 'd' line1 and previous 'd' nlines. */ 198 long dafter; 199 }; 200 201 /* If there is no signal, better to disable mmap entirely. 202 We leave MMAP_SIGNAL as 0 to indicate this. */ 203 #if !MMAP_SIGNAL 204 #undef HAVE_MMAP 205 #undef HAVE_MADVISE 206 #endif 207 208 /* Print a char, but abort on write error. */ 209 #define aputc(c,o) do \ 210 if (putc (c, o) == EOF) \ 211 testOerror (o); \ 212 while (0) 213 214 /* Computes mode of the working file: same as ‘RCSmode’, 215 but write permission determined by ‘writable’. */ 216 #define WORKMODE(RCSmode, writable) \ 217 (((RCSmode) & (mode_t)~(S_IWUSR|S_IWGRP|S_IWOTH)) \ 218 | ((writable) ? S_IWUSR : 0)) 219 220 /* Character classes and token codes. */ 221 enum tokens 222 { 223 /* Classes. */ 224 DELIM, DIGIT, IDCHAR, NEWLN, LETTER, Letter, 225 PERIOD, SBEGIN, SPACE, UNKN, 226 /* Tokens. */ 227 COLON, ID, NUM, SEMI, STRING 228 }; 229 230 /* The actual character is needed for string handling. 231 ‘SDELIM’ must be consistent with ‘ctab’, so that ‘ctab[SDELIM] == SBEGIN’. 232 There should be no overlap among ‘SDELIM’, ‘KDELIM’ and ‘VDELIM’. */ 233 #define SDELIM '@' 234 235 /* Data structures for the symbol table. */ 236 237 struct cbuf /* immutable */ 238 { 239 char const *string; 240 size_t size; 241 }; 242 243 /* A revision. */ 244 struct delta 245 { 246 /* Pointer to revision number (ASCIZ). */ 247 char const *num; 248 249 /* Pointer to date of checkin, person checking in, the locker. */ 250 char const *date; 251 char const *author; 252 char const *lockedby; 253 254 /* State of revision (see ‘DEFAULTSTATE’). */ 255 char const *state; 256 257 /* The ‘log’ and ‘text’ fields. */ 258 struct atat *log, *text; 259 260 /* Name (if any) by which retrieved. */ 261 char const *name; 262 263 /* Log message requested at checkin. */ 264 struct cbuf pretty_log; 265 266 /* List of ‘struct delta’ (first revisions) on branches. */ 267 struct wlink *branches; 268 269 /* The ‘commitid’ added by CVS; only used for reading. */ 270 char const *commitid; 271 272 /* Another revision on same branch. 273 This used to be named ‘next’, but that's confusing to me. */ 274 struct delta *ilk; 275 276 /* True if selected, false if deleted. */ 277 bool selector; 278 279 /* Position in ‘FLOW (from)’ of the start of the delta body, 280 including the leading whitespace, starting at the ‘ATAT_TEXT_END’ 281 of the preceding description (desc) or delta body (text) atat. 282 Thus, the full backing store range of delta ‘d’ is ‘d.prologue’ 283 up to ‘ATAT_TEXT_END (d.text)’. */ 284 off_t neck; 285 }; 286 287 /* List element for locks. */ 288 struct rcslock 289 { 290 char const *login; 291 struct delta *delta; 292 }; 293 294 /* List element for symbolic names. 295 Also used for label/filename (merging) 296 and base/full (peer program names). */ 297 struct symdef 298 { 299 char const *meaningful; 300 char const *underlying; 301 }; 302 303 /* Like ‘struct symdef’, for ci(1) and rcs(1). 304 The "u_" prefix stands for user-setting. */ 305 struct u_symdef 306 { 307 struct symdef u; 308 bool override; 309 }; 310 311 /* Symbol-pool particulars. */ 312 struct tinysym 313 { 314 uint8_t len; 315 uint8_t bytes[]; 316 }; 317 struct pool_found 318 { 319 int i; 320 struct tinysym const *sym; 321 }; 322 323 #define TINY(x) (tiny_ ## x) 324 #define TINY_DECL(x) const struct tinysym (TINY (x)) 325 326 /* Max length of the (working file) keywords. */ 327 #define keylength 8 328 329 /* This must be in the same order as in ‘keyword_pool’. */ 330 enum markers 331 { 332 Author, Date, Header, Id, 333 Locker, Log, Name, RCSfile, Revision, Source, State 334 }; 335 336 /* This is used by ci and rlog. */ 337 #define EMPTYLOG "*** empty log message ***" 338 339 /* Buffer sizes for time/date funcs. 340 The six is for the year, good through AD 999,999. 341 (This was chosen so that ‘FULLDATESIZE’ + 1 = 32.) 342 The second is basically ‘(1+ (length ".MM.DD.HH.MM.SS"))’. 343 9 is max len of time zone string, e.g. "+12:34:56". */ 344 #define DATESIZE (6 + 16) 345 #define FULLDATESIZE (DATESIZE + 9) 346 347 struct maybe; 348 349 /* The function ‘pairnames’ takes to open the RCS file. */ 350 typedef struct fro * (open_rcsfile_fn) (struct maybe *m); 351 352 /* A combination of probe parameters and results for ‘pairnames’ through 353 ‘fin2open’ through ‘finopen’ through {‘rcsreadopen’, ‘rcswriteopen’} 354 (and ‘naturalize’ in the case of ‘rcswriteopen’). 355 356 The probe protocol is to set ‘open’ and ‘mustread’ once, and try various 357 permutations of basename, directory and extension (-x) in ‘tentative’, 358 finally recording ‘errno’ in ‘eno’, the "best RCS filename found" in 359 ‘bestfit’, and stat(2) info in ‘status’ (otherwise failing). */ 360 struct maybe 361 { 362 /* Input parameters, constant. */ 363 open_rcsfile_fn *open; 364 bool mustread; 365 366 /* Input parameter, varying. */ 367 struct cbuf tentative; 368 369 /* Scratch. */ 370 struct divvy *space; 371 372 /* Output parameters. */ 373 struct cbuf bestfit; 374 struct stat *status; 375 int eno; 376 }; 377 378 /* The locations of RCS programs, for internal use. */ 379 extern char const prog_diff[]; 380 extern char const prog_diff3[]; 381 382 /* Flags to make diff(1) work with RCS. These 383 should be a single argument (no internal spaces). */ 384 extern char const diff_flags[]; 385 386 /* A string of 77 '=' followed by '\n'. */ 387 extern char const equal_line[]; 388 389 /* Every program defines this. */ 390 struct program 391 { 392 /* The invocation filename, basically a copy of ‘argv[0]’. */ 393 char const *invoke; 394 /* The name of the program, for --help, --version, etc. */ 395 char const *name; 396 /* One-line description, ending with '.' (dot). */ 397 char const *desc; 398 /* Text for --help. */ 399 char const *help; 400 /* What to do when exiting errorfully (see TYAG_* below). */ 401 int const tyag; 402 }; 403 404 /* (Somewhat) fleeting files. */ 405 enum maker { notmade, real, effective }; 406 407 struct sff 408 { 409 char const *filename; 410 /* Unlink this when done. */ 411 enum maker disposition; 412 /* (But only if it is in the right mood.) */ 413 }; 414 415 /* A program controls the behavior of subsystems by setting these. 416 Subsystems also communicate via these settings. */ 417 struct behavior 418 { 419 char const *invdir; 420 /* The directory portion of ‘PROGRAM (invoke)’. 421 -- find_peer_prog */ 422 423 bool unbuffered; 424 /* Although standard error should be unbuffered by default, 425 don't rely on it. 426 -- unbuffer_standard_error */ 427 428 bool quiet; 429 /* This is set from command-line option ‘-q’. When set: 430 - disable all yn -- yesorno 431 - disable warnings -- generic_warn 432 - disable error messages -- diagnose catchsigaction 433 - don't ask about overwriting a writable workfile 434 - on missing RCS file, suppress error and init instead -- pairnames 435 - [ident] suppress no-keywords-found warning 436 - [rcs] suppress yn when outdating all revisions 437 - [rcsclean] suppress progress output */ 438 439 bool interactive_valid; /* -- ttystdin */ 440 bool interactive; 441 /* Should we act as if stdin is a tty? Set from ‘-I’. When set: 442 - enables stdin flushing and newline output -- getcstdin 443 - enables yn (masked by ‘quiet’, above) -- yesorno 444 - enables "enter FOO terminated by ." message -- getsstdin 445 - [co] when workfile writable, include name in error message */ 446 447 bool inclusive_of_Locker_in_Id_val; 448 /* If set, append locker val when expanding ‘Id’ and locking. */ 449 450 bool strictly_locking; 451 /* When set: 452 - don't inhibit error when removing self-lock -- removelock 453 - enable error if not self-lock -- addelta 454 - generate "; strict" in RCS file -- putadmin 455 - [ci] ??? 456 - [co] conspires w/ kwsub_v to make workfile readonly 457 - [rlog] display "strict" */ 458 459 bool version_set; 460 int version; 461 /* The "effective RCS version", for backward compatibility, 462 normalized via ‘VERSION’ (i.e., current 0, previous -1, etc). 463 ‘version_set’ true means the effective version was set from the 464 command-line option ‘-V’. Additional ‘-V’ results in a warning. 465 -- setRCSversion */ 466 467 bool stick_with_euid; 468 /* Ignore all calls to ‘seteid’ and ‘setrid’. 469 -- nosetid */ 470 471 int ruid, euid; 472 bool ruid_cached, euid_cached; 473 /* The real and effective user-ids, and their respective 474 "already-cached" state (to implement one-shot). 475 -- ruid euid */ 476 477 bool already_setuid; 478 /* It's not entirely clear what this bit does. 479 -- set_uid_to */ 480 481 int kws; 482 /* The keyword substitution (aka "expansion") mode, or -1 (mu). 483 FIXME: Unify with ‘enum kwsub’. 484 -- [co]main [rcs]main [rcsclean]main InitAdmin */ 485 486 char const *pe; 487 /* Possible endings, a slash-separated list of filename-end 488 fragments to consider for recognizing the name of the RCS file. 489 -- [ci]main [co]main [rcs]main [rcsclean]main [rcsdiff]main 490 -- rcssuffix 491 -- [rcsmerge]main [rlog]main */ 492 493 struct zone_offset 494 { 495 bool valid; 496 /* When set, use ‘BE (zone_offset.seconds)’ in ‘date2str’. 497 Otherwise, use UTC without timezone indication. 498 -- zone_set */ 499 500 long seconds; 501 /* Seconds east of UTC, or ‘TM_LOCAL_ZONE’. 502 -- zone_set */ 503 } zone_offset; 504 505 char *username; 506 /* The login id of the program user. 507 -- getusername */ 508 509 struct timespec now; 510 /* Cached time from ‘gettime’. 511 -- now */ 512 513 bool fixed_SIGCHLD; 514 /* True means SIGCHLD handler has been manually set to SIG_DFL. 515 (Only meaningful if ‘BAD_WAIT_IF_SIGCHLD_IGNORED’.) 516 -- runv */ 517 518 bool Oerrloop; 519 /* True means ‘Oerror’ was called already. 520 -- Oerror */ 521 522 char *cwd; 523 /* The current working directory. 524 -- getfullRCSname */ 525 526 off_t mem_limit; 527 /* If a fro is smaller than ‘mem_limit’ kilobytes, try to mmap(2) it 528 (if mmap(2)), or operate on a copy of it in core (if no mmap(2)). 529 Otherwise, use standard i/o routines as the fallback. 530 Set by env var ‘RCS_MEM_LIMIT’. 531 See also ‘MEMORY_UNLIMITED’. 532 -- gnurcs_init */ 533 534 struct sff *sff; 535 /* (Somewhat) fleeting files. */ 536 537 /* The rest of the members in ‘struct behavior’ are scratch spaces 538 managed by various subsystems. */ 539 540 struct isr_scratch *isr; 541 struct ephemstuff *ephemstuff; 542 struct maketimestuff *maketimestuff; 543 }; 544 545 /* The working file is a manifestation of a particular revision. */ 546 struct manifestation 547 { 548 /* What it's called on disk; may be relative, 549 unused if writing to stdout. 550 -- rcsreadopen */ 551 char *filename; 552 553 /* [co] Use this if writing to stdout. */ 554 FILE *standard_output; 555 556 /* Previous keywords, to accomodate ‘ci -k’. 557 -- getoldkeys */ 558 struct { 559 bool valid; 560 char *author; 561 char *date; 562 char *name; 563 char *rev; 564 char *state; 565 } prev; 566 }; 567 568 /* The repository file contains a tree of revisions, plus metadata. 569 This is represented by two structures: ‘repo’ is allocated and 570 populated by the parser, while ‘repository’ is library-wide. 571 (It remains to be seen which will swallow the other, if ever.) 572 All lists may be NULL, which means empty. */ 573 struct repo 574 { 575 char const *head; 576 /* Revision number of the tip of the default branch, or NULL. */ 577 578 char const *branch; 579 /* Default branch number, or NULL. */ 580 581 size_t access_count; 582 struct link *access; 583 /* List of usernames who may write the RCS file. */ 584 585 size_t symbols_count; 586 struct link *symbols; 587 /* List of symbolic name definitions (struct symdef). */ 588 589 size_t locks_count; 590 struct link *locks; 591 /* List of locks (struct rcslock). */ 592 593 bool strict; 594 /* True if strict locking is to be done. */ 595 596 struct atat *integrity; 597 /* Checksums and other compacted redundancies. */ 598 599 struct atat *comment; 600 /* The pre-v5 "comment leader", or NULL. */ 601 602 int expand; 603 /* The keyword substitution mode (enum kwsub), or -1. */ 604 605 size_t deltas_count; 606 struct wlink *deltas; 607 /* List of deltas (struct delta). */ 608 609 struct atat *desc; 610 /* Description of the RCS file. */ 611 612 off_t neck; 613 /* Parser internal; transitional. 614 (The previous parser design did input and output in one pass, with 615 the (input) file position an implicit state. The current design 616 does a full scan on input, remembering some key file positions 617 (in this case, the position immediately after the ‘desc’ keyword) 618 and re-synching during output. Over time we plan to make the 619 output routines not rely on file position.) */ 620 621 struct lockdef *lockdefs; 622 struct hash *ht; 623 /* Parser internal. */ 624 }; 625 626 struct repository 627 { 628 char const *filename; 629 /* What it's called on disk. 630 -- pairnames */ 631 632 int fd_lock; 633 /* The file descriptor of the RCS file lockfile. 634 -- rcswriteopen ORCSclose pairnames putadmin */ 635 636 struct stat stat; 637 /* Stat info, possibly munged. 638 -- [ci]main [rcs]main fro_open (via rcs{read,write}open) */ 639 640 struct repo *r; 641 /* The result of parsing ‘filename’. 642 -- pairnames */ 643 644 struct delta *tip; 645 /* The revision on the tip of the default branch. 646 -- addelta buildtree [rcs]main InitAdmin */ 647 648 struct cbuf log_lead; 649 /* The string to use to start lines expanded for ‘Log’. FIXME:ZONK. 650 -- [rcs]main InitAdmin */ 651 }; 652 653 /* Various data streams flow in and out of RCS programs. */ 654 struct flow 655 { 656 struct fro *from; 657 /* Input stream for the RCS file. 658 -- rcsreadopen pairnames */ 659 660 FILE *rewr; 661 /* Output stream for echoing input stream. 662 -- putadmin */ 663 664 FILE *to; 665 /* Output stream for the RCS file. 666 ``Copy of ‘rewr’, but NULL to suppress echo.'' 667 -- [ci]main scanlogtext dorewrite putdesc */ 668 669 FILE *res; 670 /* Output stream for the result file. ??? 671 -- enterstring */ 672 673 char const *result; 674 /* The result file name. 675 -- openfcopy swapeditfiles */ 676 677 bool erroneous; 678 /* True means some (parsing/merging) error was encountered. 679 The program should clean up temporary files and exit. 680 -- buildjoin syserror generic_error generic_fatal */ 681 }; 682 683 /* The top of the structure tree. */ 684 struct top 685 { 686 struct program const *program; 687 struct behavior behavior; 688 struct manifestation manifestation; 689 struct repository repository; 690 struct flow flow; 691 }; 692 693 extern struct top *top; 694 695 /* In the future we might move ‘top’ into another structure. 696 These abstractions keep the invasiveness to a minimum. */ 697 #define PROGRAM(x) (top->program-> x) 698 #define BE(quality) (top->behavior. quality) 699 #define MANI(member) (top->manifestation. member) 700 #define PREV(which) (MANI (prev). which) 701 #define REPO(member) (top->repository. member) 702 #define GROK(member) (REPO (r)-> member) 703 #define FLOW(member) (top->flow. member) 704 705 /* b-anchor */ 706 extern char const ks_revno[]; 707 extern TINY_DECL (ciklog); 708 extern TINY_DECL (access); 709 extern TINY_DECL (author); 710 extern TINY_DECL (branch); 711 extern TINY_DECL (branches); 712 extern TINY_DECL (comment); 713 extern TINY_DECL (commitid); 714 extern TINY_DECL (date); 715 extern TINY_DECL (desc); 716 extern TINY_DECL (expand); 717 extern TINY_DECL (head); 718 extern TINY_DECL (integrity); 719 extern TINY_DECL (locks); 720 extern TINY_DECL (log); 721 extern TINY_DECL (next); 722 extern TINY_DECL (state); 723 extern TINY_DECL (strict); 724 extern TINY_DECL (symbols); 725 extern TINY_DECL (text); 726 bool looking_at (struct tinysym const *sym, char const *start) 727 ALL_NONNULL; 728 int recognize_kwsub (struct cbuf const *x) 729 ALL_NONNULL; 730 int str2expmode (char const *s) 731 ALL_NONNULL; 732 char const *kwsub_string (enum kwsub i); 733 bool recognize_keyword (char const *string, struct pool_found *found) 734 ALL_NONNULL; 735 736 /* merger */ 737 int merge (bool tostdout, char const *edarg, 738 struct symdef three_manifestations[3]) 739 ARG_NONNULL ((3)); 740 741 /* rcsedit */ 742 struct editstuff *make_editstuff (void); 743 void unmake_editstuff (struct editstuff *es) 744 ALL_NONNULL; 745 int un_link (char const *s) 746 ALL_NONNULL; 747 void openfcopy (FILE *f); 748 void finishedit (struct editstuff *es, struct delta const * delta, 749 FILE *outfile, bool done); 750 void snapshotedit (struct editstuff *es, FILE *f) 751 ALL_NONNULL; 752 void copystring (struct editstuff *es, struct atat *atat) 753 ALL_NONNULL; 754 void enterstring (struct editstuff *es, struct atat *atat) 755 ALL_NONNULL; 756 void editstring (struct editstuff *es, struct atat const *script, 757 struct delta const *delta) 758 ARG_NONNULL ((1, 2)); 759 struct fro *rcswriteopen (struct maybe *m) 760 ALL_NONNULL; 761 int chnamemod (FILE **fromp, char const *from, char const *to, 762 int set_mode, mode_t mode, const struct timespec mtime) 763 ALL_NONNULL; 764 int setmtime (char const *file, const struct timespec mtime) 765 ALL_NONNULL; 766 int findlock (bool delete, struct delta **target) 767 ALL_NONNULL; 768 int addsymbol (char const *num, char const *name, bool rebind) 769 ALL_NONNULL; 770 bool checkaccesslist (void); 771 int dorewrite (bool lockflag, int changed); 772 int donerewrite (int changed, const struct timespec mtime); 773 void ORCSclose (void); 774 void ORCSerror (void); 775 exiting 776 void unexpected_EOF (void); 777 void initdiffcmd (struct diffcmd *dc) 778 ALL_NONNULL; 779 int getdiffcmd (struct fro *finfile, bool delimiter, 780 FILE *foutfile, struct diffcmd *dc) 781 ARG_NONNULL ((1, 4)); 782 783 /* rcsfcmp */ 784 int rcsfcmp (struct fro *xfp, struct stat const *xstatp, 785 char const *uname, struct delta const *delta) 786 ALL_NONNULL; 787 788 /* rcsfnms */ 789 char const *basefilename (char const *p) 790 ALL_NONNULL; 791 char const *rcssuffix (char const *name) 792 ALL_NONNULL; 793 struct fro *rcsreadopen (struct maybe *m) 794 ALL_NONNULL; 795 int pairnames (int argc, char **argv, open_rcsfile_fn *rcsopen, 796 bool mustread, bool quiet) 797 ALL_NONNULL; 798 char const *getfullRCSname (void); 799 bool isSLASH (int c); 800 801 /* rcsgen */ 802 char const *buildrevision (struct wlink const *deltas, 803 struct delta *target, 804 FILE *outfile, bool expandflag) 805 ARG_NONNULL ((1, 2)); 806 struct cbuf cleanlogmsg (char const *m, size_t s) 807 ALL_NONNULL; 808 bool ttystdin (void); 809 int getcstdin (void); 810 bool yesorno (bool default_answer, char const *question, ...) 811 ARG_NONNULL ((2)) 812 printf_string (2, 3); 813 void write_desc_maybe (FILE *to); 814 void putdesc (struct cbuf *cb, bool textflag, char *textfile) 815 ARG_NONNULL ((1)); 816 struct cbuf getsstdin (char const *option, char const *name, char const *note) 817 ALL_NONNULL; 818 void format_assocs (FILE *out, char const *fmt) 819 ALL_NONNULL; 820 void format_locks (FILE *out, char const *fmt) 821 ALL_NONNULL; 822 void putadmin (void); 823 void puttree (struct delta const *root, FILE *fout) 824 ARG_NONNULL ((2)); 825 bool putdtext (struct delta const *delta, char const *srcname, 826 FILE *fout, bool diffmt) 827 ALL_NONNULL; 828 void putstring (FILE *out, struct cbuf s, bool log) 829 ALL_NONNULL; 830 void putdftext (struct delta const *delta, struct fro *finfile, 831 FILE *foutfile, bool diffmt) 832 ALL_NONNULL; 833 834 /* rcskeep */ 835 bool getoldkeys (struct fro *fp); 836 837 /* rcsmap */ 838 extern enum tokens const ctab[]; 839 char const *checkid (char const *id, int delimiter) 840 ALL_NONNULL; 841 char const *checksym (char const *sym, int delimiter) 842 ALL_NONNULL; 843 void checksid (char const *id) 844 ALL_NONNULL; 845 void checkssym (char const *sym) 846 ALL_NONNULL; 847 848 /* rcsrev */ 849 int countnumflds (char const *s); 850 struct cbuf take (size_t count, char const *ref) 851 ALL_NONNULL; 852 int cmpnum (char const *num1, char const *num2); 853 int cmpnumfld (char const *num1, char const *num2, int fld) 854 ALL_NONNULL; 855 int cmpdate (char const *d1, char const *d2) 856 ALL_NONNULL; 857 int compartial (char const *num1, char const *num2, int length) 858 ALL_NONNULL; 859 struct delta *genrevs (char const *revno, char const *date, 860 char const *author, char const *state, 861 struct wlink **store) 862 ARG_NONNULL ((1)); 863 struct delta *gr_revno (char const *revno, struct wlink **store) 864 ALL_NONNULL; 865 struct delta *delta_from_ref (char const *ref) 866 ALL_NONNULL; 867 bool fully_numeric (struct cbuf *ans, char const *source, struct fro *fp) 868 ARG_NONNULL ((1)); 869 char const *namedrev (char const *name, struct delta *delta) 870 ARG_NONNULL ((2)); 871 char const *tiprev (void); 872 873 /* rcstime */ 874 void time2date (time_t unixtime, char date[DATESIZE]) 875 ALL_NONNULL; 876 void str2date (char const *source, char target[DATESIZE]) 877 ALL_NONNULL; 878 time_t date2time (char const source[DATESIZE]) 879 ALL_NONNULL; 880 void zone_set (char const *s) 881 ALL_NONNULL; 882 char const *date2str (char const date[DATESIZE], 883 char datebuf[FULLDATESIZE]) 884 ALL_NONNULL; 885 886 /* rcsutil */ 887 exiting 888 void thank_you_and_goodnight (int const how); 889 /* These are for ‘thank_you_and_goodnight’. */ 890 #define TYAG_ORCSERROR (1 << 3) 891 #define TYAG_DIRTMPUNLINK (1 << 2) 892 #define TYAG_TEMPUNLINK (1 << 1) 893 #define TYAG_DIFF (1 << 0) 894 #define TYAG_IMMEDIATE 0 895 896 void gnurcs_init (struct program const *program) 897 ALL_NONNULL; 898 void gnurcs_goodbye (void); 899 void bad_option (char const *option) 900 ALL_NONNULL; 901 void redefined (int c); 902 void chk_set_rev (const char **rev, char *arg) 903 ALL_NONNULL; 904 struct cbuf minus_p (char const *xrev, char const *rev) 905 ALL_NONNULL; 906 void parse_revpairs (char option, char *arg, void *data, 907 void (*put) (char const *b, char const *e, 908 bool sawsep, void *data)) 909 ALL_NONNULL; 910 void set_empty_log_message (struct cbuf *cb) 911 ALL_NONNULL; 912 void ffree (void); 913 char *str_save (char const *s) 914 ALL_NONNULL; 915 char *cgetenv (char const *name) 916 ALL_NONNULL; 917 void awrite (char const *buf, size_t chars, FILE *f) 918 ALL_NONNULL; 919 int runv (int infd, char const *outname, char const **args) 920 ARG_NONNULL ((3)); 921 int run (int infd, char const *outname, ...); 922 void setRCSversion (char const *str) 923 ALL_NONNULL; 924 int getRCSINIT (int argc, char **argv, char ***newargv) 925 ALL_NONNULL; 926 struct timespec unspecified_timespec (void); 927 struct timespec file_mtime (bool enable, struct stat const *st) 928 ALL_NONNULL; 929 930 /* Indexes into ‘BE (sff)’. */ 931 #define SFFI_LOCKDIR 0 932 #define SFFI_NEWDIR BAD_CREAT0 933 934 /* Idioms. */ 935 936 #define TIME_UNSPECIFIED ((time_t) -1) 937 #define TIME_UNSPECIFIED_P(x) ((x) == TIME_UNSPECIFIED) 938 939 /* This is for ‘ns’ (2nd) arg to ‘make_timespec’. */ 940 #define ZERO_NANOSECONDS 0 941 942 #define MEMORY_UNLIMITED -1 943 944 #define BOG_DIFF (TYAG_TEMPUNLINK | TYAG_DIFF) 945 #define BOG_ZONK (TYAG_DIRTMPUNLINK | TYAG_TEMPUNLINK) 946 #define BOG_FULL (TYAG_ORCSERROR | BOG_ZONK) 947 948 #define BOW_OUT() thank_you_and_goodnight (PROGRAM (tyag)) 949 950 /* Murphy was an optimist... */ 951 #define PROB(x) (0 > (x)) 952 953 #define clear_buf(b) (((b)->string = NULL, (b)->size = 0)) 954 955 #define STR_DIFF(a,b) (strcmp ((a), (b))) 956 #define STR_SAME(a,b) (! STR_DIFF ((a), (b))) 957 958 /* Get a character from ‘fin’, perhaps copying to a ‘frew’. */ 959 #define TEECHAR() do \ 960 { \ 961 GETCHAR (c, fin); \ 962 if (frew) \ 963 afputc (c, frew); \ 964 } \ 965 while (0) 966 967 #define TAKE(count,rev) (take (count, rev).string) 968 969 #define BRANCHNO(rev) TAKE (0, rev) 970 971 #define fully_numeric_no_k(cb,source) fully_numeric (cb, source, NULL) 972 973 #define TINYS(x) ((char const *)(x)->bytes) 974 975 #define TINYKS(x) TINYS (&TINY (x)) 976 977 #define GENERIC_COMPARE(fn,...) (cmp ## fn (__VA_ARGS__)) 978 #define GENERIC_LT(fn,...) (0 > GENERIC_COMPARE (fn, __VA_ARGS__)) 979 #define GENERIC_EQ(fn,...) (0 == GENERIC_COMPARE (fn, __VA_ARGS__)) 980 #define GENERIC_GT(fn,...) (0 < GENERIC_COMPARE (fn, __VA_ARGS__)) 981 982 #define NUM_LT(a,b) GENERIC_LT (num, a, b) 983 #define NUM_EQ(a,b) GENERIC_EQ (num, a, b) 984 #define NUM_GT(a,b) GENERIC_GT (num, a, b) 985 986 #define DATE_LT(a,b) GENERIC_LT (date, a, b) 987 #define DATE_EQ(a,b) GENERIC_EQ (date, a, b) 988 #define DATE_GT(a,b) GENERIC_GT (date, a, b) 989 990 #define NUMF_LT(nf,a,b) GENERIC_LT (numfld, a, b, nf) 991 #define NUMF_EQ(nf,a,b) GENERIC_EQ (numfld, a, b, nf) 992 993 #define MEM_SAME(n,a,b) (0 == memcmp ((a), (b), (n))) 994 #define MEM_DIFF(n,a,b) (0 != memcmp ((a), (b), (n))) 995 996 #define ODDP(n) ((n) & 1) 997 #define EVENP(n) (! ODDP (n)) 998 999 /* base.h ends here */ 1000