|
|
1.1 ! root 1: .\" Copyright (c) 1980 Regents of the University of California. ! 2: .\" All rights reserved. The Berkeley software License Agreement ! 3: .\" specifies the terms and conditions for redistribution. ! 4: .\" ! 5: .\" @(#)sccs.me 6.3 (Berkeley) 5/30/86 ! 6: .\" ! 7: .eh '\fRPS1:14-%\fP''\fRAn Introduction to the Source Code Control System\fP' ! 8: .oh '\fRAn Introduction to the Source Code Control System\fP''\fRPS1:14-%\fP' ! 9: .ds S \s-1SCCS\s0 ! 10: .ds I \s-1SID\s0 ! 11: .nr bi 8n ! 12: .ev 1 \" only for keeps ! 13: .ss 16 ! 14: .ev ! 15: .\".he '\*S Introduction''%' ! 16: .+c ! 17: .(l C ! 18: .sz 14 ! 19: .b ! 20: An Introduction to the ! 21: Source Code Control System ! 22: .sz ! 23: .r ! 24: .sp ! 25: Eric Allman ! 26: .i "Project Ingres" ! 27: .i "University of California at Berkeley" ! 28: .)l ! 29: .sp 3 ! 30: .pp ! 31: .(f ! 32: This is version 1.21 of this document. ! 33: It was last modified on 12/5/80. ! 34: .)f ! 35: This document gives a quick introduction ! 36: to using the Source Code Control System ! 37: (\*S). ! 38: The presentation is geared to programmers ! 39: who are more concerned with ! 40: what ! 41: to do to get a task done ! 42: rather than how it works; ! 43: for this reason some of the examples ! 44: are not well explained. ! 45: For details of what the magic options do, ! 46: see the section on ! 47: .q "Further Information" . ! 48: .(l F ! 49: This is a working document. ! 50: Please send any comments or suggestions ! 51: to [email protected]. ! 52: .)l ! 53: .sh 1 "Introduction" ! 54: .pp ! 55: \*S is a source management system. ! 56: Such a system maintains a record of versions of a system; ! 57: a record is kept with each set of changes ! 58: of what the changes are, ! 59: why they were made, ! 60: and who made them and when. ! 61: Old versions can be recovered, ! 62: and different versions can be maintained simultaneously. ! 63: In projects with more than one person, ! 64: \*S will insure that two people are not ! 65: editing the same file at the same time. ! 66: .pp ! 67: All versions of your program, ! 68: plus the log and other information, ! 69: is kept in a file called the ! 70: .q "s-file" . ! 71: There are three major operations ! 72: that can be performed on the s-file: ! 73: .np ! 74: Get a file for compilation (not for editing). ! 75: This operation retrieves a version of the file ! 76: from the s-file. ! 77: By default, the latest version is retrieved. ! 78: This file is intended for compilation, printing, or whatever; ! 79: it is specifically NOT intended to be edited ! 80: or changed in any way; ! 81: any changes made to a file retrieved ! 82: in this way will probably be lost. ! 83: .np ! 84: Get a file for editing. ! 85: This operation also retrieves a version of the file ! 86: from the s-file, ! 87: but this file is intended to be edited and then ! 88: incorporated back into the s-file. ! 89: Only one person may be editing a file at one time. ! 90: .np ! 91: Merge a file back into the s-file. ! 92: This is the companion operation to (2). ! 93: A new version number is assigned, ! 94: and comments are saved explaining why this change was made. ! 95: .sh 1 "Learning the Lingo" ! 96: .pp ! 97: There are a number of terms that are worth learning ! 98: before we go any farther. ! 99: .sh 2 "S-file" ! 100: .pp ! 101: The s-file ! 102: is a single file that holds all the different versions ! 103: of your file. ! 104: The s-file is stored in ! 105: differential format; ! 106: .i i.e. , ! 107: only the differences between versions are stored, ! 108: rather than the entire text of the new version. ! 109: This saves disk space ! 110: and allows selective changes to be removed later. ! 111: Also included in the s-file ! 112: is some header information for each version, ! 113: including the comments given by the person who ! 114: created the version explaining why the changes were made. ! 115: .sh 2 "Deltas" ! 116: .pp ! 117: Each set of changes to the s-file ! 118: (which is approximately [but not exactly!] equivalent ! 119: to a version of the file) ! 120: is called a ! 121: .i delta . ! 122: Although technically a delta only includes the ! 123: .i changes ! 124: made, ! 125: in practice ! 126: it is usual for ! 127: each delta to be made with respect to ! 128: all the deltas that have occurred before\**. ! 129: .(f ! 130: \**This matches normal usage, where the previous changes are not saved ! 131: at all, ! 132: so all changes are automatically based on all other changes ! 133: that have happened through history. ! 134: .)f ! 135: However, ! 136: it is possible to get a version of the file ! 137: that has selected deltas removed out of the middle ! 138: of the list of changes \*- ! 139: equivalent to removing your changes later. ! 140: .sh 2 "\*I's (or, version numbers)" ! 141: .pp ! 142: A \*I ! 143: (\*S Id) ! 144: is a number that represents a delta. ! 145: This is normally a two-part number ! 146: consisting of a ! 147: .q release ! 148: number and a ! 149: .q level ! 150: number. ! 151: Normally the release number stays the same, ! 152: however, ! 153: it is possible to move into a new release ! 154: if some major change is being made. ! 155: .pp ! 156: Since all past deltas are normally applied, ! 157: the \*I of the final delta applied ! 158: can be used to represent a version number of the file ! 159: as a whole. ! 160: .sh 2 "Id keywords" ! 161: .pp ! 162: When you get a version of a file ! 163: with intent to compile and install it ! 164: (\c ! 165: .i i.e. , ! 166: something other than edit it), ! 167: some special keywords are expanded inline ! 168: by \*S. ! 169: These ! 170: .i "Id Keywords" ! 171: can be used to include the current version number ! 172: or other information into the file. ! 173: All id keywords are of the form ! 174: .b % \c ! 175: .i x \c ! 176: .b % , ! 177: where ! 178: .i x ! 179: is an upper case letter. ! 180: For example, ! 181: .b %\&I\&% ! 182: is the \*I of the latest delta applied, ! 183: .b %\&W\&% ! 184: includes the module name, ! 185: \*I, ! 186: and a mark that makes it findable by a program, ! 187: and ! 188: .b %\&G\&% ! 189: is the date of the latest delta applied. ! 190: There are many others, ! 191: most of which are of dubious usefulness. ! 192: .pp ! 193: When you get a file for editing, ! 194: the id keywords are not expanded; ! 195: this is so that after you put them back in to the s-file, ! 196: they will be expanded automatically on each new version. ! 197: But notice: if you were to get them ! 198: expanded accidently, ! 199: then your file would appear to be the same version ! 200: forever more, ! 201: which would of course defeat the purpose. ! 202: Also, ! 203: if you should install a version of the program ! 204: without expanding the id keywords, ! 205: it will be impossible to tell what version it is ! 206: (since all it will have is ! 207: .q %\&W\&% ! 208: or whatever). ! 209: .sh 1 "Creating \*S Files" ! 210: .pp ! 211: To put source files ! 212: into ! 213: \*S ! 214: format, run the following shell script from csh: ! 215: .(b ! 216: mkdir SCCS save ! 217: foreach i (*.[ch]) ! 218: sccs admin \-i$i $i ! 219: mv $i save/$i ! 220: end ! 221: .)b ! 222: This will put the named files ! 223: into s-files ! 224: in the subdirectory ! 225: .q SCCS ! 226: The files will be removed from the current directory ! 227: and hidden away in the directory ! 228: .q save , ! 229: so the next thing you will probably want to do ! 230: is to get all the files ! 231: (described below). ! 232: When you are convinced that ! 233: \*S has correctly created the s-files, ! 234: you should remove the directory ! 235: .q save . ! 236: .pp ! 237: If you want to have id keywords in the files, ! 238: it is best to put them in before you create the s-files. ! 239: If you do not, ! 240: .i admin ! 241: will print ! 242: .q "No Id Keywords (cm7)" , ! 243: which is a warning message only. ! 244: .sh 1 "Getting Files for Compilation" ! 245: .pp ! 246: To get a copy of the latest version ! 247: of a file, ! 248: run ! 249: .(b ! 250: sccs get prog.c ! 251: .)b ! 252: \*S will respond: ! 253: .(b ! 254: 1.1 ! 255: 87 lines ! 256: .)b ! 257: meaning that version 1.1 was retrieved\** ! 258: .(f ! 259: \**Actually, ! 260: the \*I of the final delta applied was 1.1. ! 261: .)f ! 262: and that it has 87 lines. ! 263: The file ! 264: .i prog.c ! 265: will be created ! 266: in the current directory. ! 267: The file will be read-only ! 268: to remind you that you are not ! 269: supposed to change it. ! 270: .pp ! 271: This copy of the file ! 272: should not be changed, ! 273: since \*S is unable ! 274: to merge the changes ! 275: back into the s-file. ! 276: If you do make changes, ! 277: they will be lost the next time ! 278: someone does a ! 279: .i get . ! 280: .sh 1 "Changing Files (or, Creating Deltas)" ! 281: .sh 2 "Getting a copy to edit" ! 282: .pp ! 283: To edit a source file, ! 284: you must first get it, ! 285: requesting permission to edit it\**: ! 286: .(f ! 287: \**The ! 288: .q "edit" ! 289: command is equivalent to using the \-e ! 290: flag to ! 291: .i "get" , ! 292: as: ! 293: .(l ! 294: sccs get \-e prog.c ! 295: .)l ! 296: Keep this in mind when reading other documentation. ! 297: .)f ! 298: .(b ! 299: sccs edit prog.c ! 300: .)b ! 301: The response will be the same as with ! 302: .i get ! 303: except that it will also say: ! 304: .(b ! 305: New delta 1.2 ! 306: .)b ! 307: You then edit it, ! 308: using a standard text editor: ! 309: .(b ! 310: vi prog.c ! 311: .)b ! 312: .sh 2 "Merging the changes back into the s-file" ! 313: .pp ! 314: When the desired changes are made, ! 315: you can put your changes into the ! 316: \*S ! 317: file using the ! 318: .i delta ! 319: command: ! 320: .(b ! 321: sccs delta prog.c ! 322: .)b ! 323: .pp ! 324: Delta will prompt you for ! 325: .q "comments?" ! 326: before it merges the changes in. ! 327: At this prompt you should type a one-line description ! 328: of what the changes mean ! 329: (more lines can be entered by ending each line ! 330: except the last with a backslash\**). ! 331: .(f ! 332: \**Yes, this is a stupid default. ! 333: .)f ! 334: .i Delta ! 335: will then type: ! 336: .(b ! 337: 1.2 ! 338: 5 inserted ! 339: 3 deleted ! 340: 84 unchanged ! 341: .)b ! 342: saying that delta 1.2 was created, ! 343: and it inserted five lines, ! 344: removed three lines, ! 345: and left 84 lines unchanged\**. ! 346: .(f ! 347: \**Changes to a line are counted as a line deleted ! 348: and a line inserted. ! 349: .)f ! 350: The ! 351: .i prog.c ! 352: file will be removed; ! 353: it can be retrieved ! 354: using ! 355: .i get . ! 356: .sh 2 "When to make deltas" ! 357: .pp ! 358: It is probably unwise to make a delta ! 359: before every recompilation or test; ! 360: otherwise, ! 361: you tend to get a lot of deltas with comments like ! 362: .q "fixed compilation problem in previous delta" ! 363: or ! 364: .q "fixed botch in 1.3" . ! 365: However, ! 366: it is very important to delta everything ! 367: before installing a module for general use. ! 368: A good technique is to edit the files you need, ! 369: make all necessary changes and tests, ! 370: compiling and editing as often as necessary ! 371: without making deltas. ! 372: When you are satisfied that you have a working version, ! 373: delta everything being edited, ! 374: re-get them, ! 375: and recompile everything. ! 376: .sh 2 "What's going on: the info command" ! 377: .pp ! 378: To find out what files where being edited, ! 379: you can use: ! 380: .(b ! 381: sccs info ! 382: .)b ! 383: to print out all the files being edited ! 384: and other information such as the name of the user ! 385: who did the edit. ! 386: Also, ! 387: the command: ! 388: .(b ! 389: sccs check ! 390: .)b ! 391: is nearly equivalent to the ! 392: .i info ! 393: command, ! 394: except that it is silent if nothing is being edited, ! 395: and returns non-zero exit status if anything is being edited; ! 396: it can be used in an ! 397: .q install ! 398: entry in a makefile ! 399: to abort the install ! 400: if anything has not been properly deltaed. ! 401: .pp ! 402: If you know that everything being edited should be deltaed, ! 403: you can use: ! 404: .(b ! 405: sccs delta \`sccs tell\` ! 406: .)b ! 407: The ! 408: .i tell ! 409: command is similar to ! 410: .i info ! 411: except that only the names of files being edited ! 412: are output, ! 413: one per line. ! 414: .pp ! 415: All of these commands take a ! 416: .b \-b ! 417: flag ! 418: to ignore ! 419: .q branches ! 420: (alternate versions, described later) ! 421: and the ! 422: .b \-u ! 423: flag to only give files being edited by you. ! 424: The ! 425: .b \-u ! 426: flag takes an optional ! 427: .i user ! 428: argument, ! 429: giving only files being edited by that user. ! 430: For example, ! 431: .(b ! 432: sccs info \-ujohn ! 433: .)b ! 434: gives a listing of files being edited by john. ! 435: .sh 2 "ID keywords" ! 436: .pp ! 437: Id keywords can be inserted into your file ! 438: that will be expanded automatically by ! 439: .i get . ! 440: For example, ! 441: a line such as: ! 442: .(b ! 443: static char SccsId[] = "%\&W\&%\et%\&G\&%"; ! 444: .)b ! 445: will be replaced with something like: ! 446: .(b ! 447: static char SccsId[] = "@\&(#)prog.c 1.2 08/29/80"; ! 448: .)b ! 449: This tells you ! 450: the name and version ! 451: of the source file ! 452: and the time the delta was created. ! 453: The string ! 454: .q "@\&(#)" ! 455: is a special string ! 456: which signals the beginning ! 457: of an ! 458: \*S ! 459: Id keyword. ! 460: .sh 3 "The what command" ! 461: .pp ! 462: To find out what version of a program ! 463: is being run, ! 464: use: ! 465: .(b ! 466: sccs what prog.c /usr/bin/prog ! 467: .)b ! 468: which will print all strings ! 469: it finds that ! 470: begin with ! 471: .q "@\&(#)" . ! 472: This works on all types of files, ! 473: including binaries and libraries. ! 474: For example, the above command will output something like: ! 475: .(b ! 476: prog.c: ! 477: prog.c 1.2 08/29/80 ! 478: /usr/bin/prog: ! 479: prog.c 1.1 02/05/79 ! 480: .)b ! 481: From this I can see ! 482: that the source that I have in prog.c ! 483: will not compile into the same version ! 484: as the binary in /usr/bin/prog. ! 485: .sh 3 "Where to put id keywords" ! 486: .pp ! 487: ID keywords can be inserted anywhere, ! 488: including in comments, ! 489: but ! 490: Id Keywords that are compiled into the object module ! 491: are especially useful, ! 492: since it lets you find out what version of ! 493: the object is being run, ! 494: as well as the source. ! 495: However, ! 496: there is a cost: ! 497: data space is used up to store ! 498: the keywords, ! 499: and on small address space machines ! 500: this may be prohibitive. ! 501: .pp ! 502: When you put id keywords into header files, ! 503: it is important that you assign them to different variables. ! 504: For example, you might use: ! 505: .(b ! 506: static char AccessSid[] = "%\&W\&% %\&G\&%"; ! 507: .)b ! 508: in the file ! 509: .i access.h ! 510: and: ! 511: .(b ! 512: static char OpsysSid[] = "%\&W\&% %\&G\&%"; ! 513: .)b ! 514: in the file ! 515: .i opsys.h . ! 516: Otherwise, ! 517: you will get compilation errors because ! 518: .q SccsId ! 519: is redefined. ! 520: The problem with this is that if the header file ! 521: is included by many modules that are loaded together, ! 522: the version number of that header file is included ! 523: in the object module many times; ! 524: you may find it more to your taste ! 525: to put id keywords in header files ! 526: in comments. ! 527: .sh 2 "Keeping \*I's consistent across files" ! 528: .pp ! 529: With some care, ! 530: it is possible to keep the \*I's consistent ! 531: in multi-file systems. ! 532: The trick here is to always ! 533: .i edit ! 534: all files ! 535: at once. ! 536: The changes can then be made ! 537: to whatever files are necessary ! 538: and then all files ! 539: (even those not changed) ! 540: are redeltaed. ! 541: This can be done fairly easily ! 542: by just specifying the name of the directory ! 543: that the \*S files are in: ! 544: .(b ! 545: sccs edit SCCS ! 546: .)b ! 547: which will ! 548: .i edit ! 549: all files in that directory. ! 550: To make the delta, use: ! 551: .(b ! 552: sccs delta SCCS ! 553: .)b ! 554: You will be prompted for comments only once. ! 555: .sh 2 "Creating new releases" ! 556: .pp ! 557: When you want to create a new release ! 558: of a program, ! 559: you can specify the release number you want to create ! 560: on the ! 561: .i edit ! 562: command. ! 563: For example: ! 564: .(b ! 565: sccs edit \-r2 prog.c ! 566: .)b ! 567: will cause the next delta to be in release two ! 568: (that is, ! 569: it will be numbered 2.1). ! 570: Future deltas will automatically be in release two. ! 571: To change the release number ! 572: of an entire system, ! 573: use: ! 574: .(b ! 575: sccs edit \-r2 SCCS ! 576: .)b ! 577: .sh 1 "Restoring Old Versions" ! 578: .sh 2 "Reverting to old versions" ! 579: .pp ! 580: Suppose that after delta 1.2 ! 581: was stable ! 582: you made and released a delta 1.3. ! 583: But this introduced a bug, ! 584: so you made a delta 1.4 to correct it. ! 585: But 1.4 was still buggy, ! 586: and you decided you wanted to go back ! 587: to the old version. ! 588: You could ! 589: revert to delta 1.2 ! 590: by choosing the \*I in a get: ! 591: .(b ! 592: sccs get \-r1.2 prog.c ! 593: .)b ! 594: This will produce a version of ! 595: .i prog.c ! 596: that is delta 1.2 ! 597: that can be reinstalled so that work can proceed. ! 598: .pp ! 599: In some cases you don't know ! 600: what the \*I of the delta you want is. ! 601: However, ! 602: you can revert to the version of the program ! 603: that was running as of a certain date ! 604: by using the ! 605: .b \-c ! 606: (cutoff) flag. ! 607: For example, ! 608: .(b ! 609: sccs get \-c800722120000 prog.c ! 610: .)b ! 611: will retrieve whatever version was current ! 612: as of July 22, 1980 ! 613: at 12:00 noon. ! 614: Trailing components can be stripped off ! 615: (defaulting to their highest legal value), ! 616: and punctuation can be inserted in the obvious ! 617: places; ! 618: for example, ! 619: the above line could be equivalently stated: ! 620: .(b ! 621: sccs get \-c"80/07/22 12:00:00" prog.c ! 622: .)b ! 623: .sh 2 "Selectively deleting old deltas" ! 624: .pp ! 625: Suppose that you later decided ! 626: that you liked the changes in delta 1.4, ! 627: but that delta 1.3 should be removed. ! 628: You could do this by ! 629: .i excluding ! 630: delta 1.3: ! 631: .(b ! 632: sccs edit \-x1.3 prog.c ! 633: .)b ! 634: When delta 1.5 is made, ! 635: it will include the changes made ! 636: in delta 1.4, ! 637: but will exclude the changes made ! 638: in delta 1.3. ! 639: You can exclude a range of deltas ! 640: using a dash. ! 641: For example, ! 642: if you want to get rid of 1.3 and 1.4 ! 643: you can use: ! 644: .(b ! 645: sccs edit \-x1.3\-1.4 prog.c ! 646: .)b ! 647: which will exclude all deltas from 1.3 to 1.4. ! 648: Alternatively, ! 649: .(b ! 650: sccs edit \-x1.3\-1 prog.c ! 651: .)b ! 652: will exclude a range of deltas ! 653: from 1.3 to the current highest delta in release 1. ! 654: .pp ! 655: In certain cases when using ! 656: .b \-x ! 657: (or ! 658: .b \-i ; ! 659: see below) ! 660: there will be conflicts ! 661: between versions; ! 662: for example, it may be necessary ! 663: to both include and delete ! 664: a particular line. ! 665: If this happens, ! 666: \*S always prints out a message ! 667: telling the range of lines effected; ! 668: these lines should then be examined very carefully ! 669: to see if the version \*S got ! 670: is ok. ! 671: .pp ! 672: Since each delta ! 673: (in the sense of ! 674: .q "a set of changes" ) ! 675: can be excluded at will, ! 676: that this makes it most useful ! 677: to put each semantically distinct change ! 678: into its own delta. ! 679: .sh 1 "Auditing Changes" ! 680: .sh 2 "The prt command" ! 681: .pp ! 682: When you created a delta, ! 683: you presumably gave a reason for the delta ! 684: to the ! 685: .q "comments?" ! 686: prompt. ! 687: To print out these comments later, ! 688: use: ! 689: .(b ! 690: sccs prt prog.c ! 691: .)b ! 692: This will produce ! 693: a report ! 694: for each delta ! 695: of the \*I, ! 696: time and date of creation, ! 697: user who created the delta, ! 698: number of lines inserted, deleted, and unchanged, ! 699: and the comments associated with the delta. ! 700: For example, the output of the above command might be: ! 701: .(b ! 702: D 1.2 80/08/29 12:35:31 bill 2 1 00005/00003/00084 ! 703: removed "-q" option ! 704: .sp \n(psu ! 705: D 1.1 79/02/05 00:19:31 eric 1 0 00087/00000/00000 ! 706: date and time created 80/06/10 00:19:31 by eric ! 707: .)b ! 708: .sh 2 "Finding why lines were inserted" ! 709: .pp ! 710: To find out ! 711: why you inserted lines, ! 712: you can get a copy of the file ! 713: with each line ! 714: preceded by the \*I that created it: ! 715: .(b ! 716: sccs get \-m prog.c ! 717: .)b ! 718: You can then find out ! 719: what this delta did ! 720: by printing the comments using ! 721: .i prt . ! 722: .pp ! 723: To find out what lines are associated with a particular delta ! 724: (\c ! 725: .i e.g. , ! 726: 1.3), ! 727: use: ! 728: .(b ! 729: sccs get \-m \-p prog.c \(bv grep \'^1.3\' ! 730: .)b ! 731: The ! 732: .b \-p ! 733: flag causes \*S to output the generated source ! 734: to the standard output rather than to a file. ! 735: .sh 2 "Finding what changes you have made" ! 736: .pp ! 737: When you are editing a file, ! 738: you can find out what changes you have made using: ! 739: .(b ! 740: sccs diffs prog.c ! 741: .)b ! 742: Most of the ``diff'' flags can be used. ! 743: To pass the ! 744: .b \-c ! 745: flag, ! 746: use ! 747: .b \-C . ! 748: .pp ! 749: To compare two versions that are in deltas, ! 750: use: ! 751: .(b ! 752: sccs sccsdiff -r1.3 -r1.6 prog.c ! 753: .)b ! 754: to see the differences between delta 1.3 and delta 1.6. ! 755: .sh 1 "Shorthand Notations" ! 756: .pp ! 757: There are several sequences of commands that get ! 758: executed frequently. ! 759: .i Sccs ! 760: tries to make it easy to do these. ! 761: .sh 2 "Delget" ! 762: .pp ! 763: A frequent requirement is to make a delta of some file ! 764: and then get that file. ! 765: This can be done by using: ! 766: .(b ! 767: sccs delget prog.c ! 768: .)b ! 769: which is entirely equivalent to using: ! 770: .(b ! 771: sccs delta prog.c ! 772: sccs get prog.c ! 773: .)b ! 774: The ! 775: .q deledit ! 776: command is equivalent to ! 777: .q delget ! 778: except that the ! 779: .q edit ! 780: command is used ! 781: instead of the ! 782: .q get ! 783: command. ! 784: .sh 2 "Fix" ! 785: .pp ! 786: Frequently, there are small bugs ! 787: in deltas, ! 788: e.g., compilation errors, ! 789: for which there is no reason to maintain an audit trail. ! 790: To ! 791: .i replace ! 792: a delta, use: ! 793: .(b ! 794: sccs fix \-r1.4 prog.c ! 795: .)b ! 796: This will get a copy of delta 1.4 of prog.c for you to edit ! 797: and then delete delta 1.4 from the \*S file. ! 798: When you do a delta of prog.c, ! 799: it will be delta 1.4 again. ! 800: The \-r flag must be specified, ! 801: and the delta that is specified must be a leaf delta, ! 802: i.e., no other deltas may have been made subsequent ! 803: to the creation of that delta. ! 804: .sh 2 "Unedit" ! 805: .pp ! 806: If you found you edited a file ! 807: that you did not want to edit, ! 808: you can back out by using: ! 809: .(b ! 810: sccs unedit prog.c ! 811: .)b ! 812: .sh 2 "The \-d flag" ! 813: .pp ! 814: If you are working on a project ! 815: where the \*S code is in a directory somewhere, ! 816: you may be able to simplify things ! 817: by using a shell alias. ! 818: For example, ! 819: the alias: ! 820: .(b ! 821: alias syssccs sccs \-d/usr/src ! 822: .)b ! 823: will allow you to issue commands such as: ! 824: .(b ! 825: syssccs edit cmd/who.c ! 826: .)b ! 827: which will look for the file ! 828: .q "/usr/src/cmd/SCCS/who.c" . ! 829: The file ! 830: .q who.c ! 831: will always be created in your current directory ! 832: regardless of the value of the \-d flag. ! 833: .sh 1 "Using \*S on a Project" ! 834: .pp ! 835: Working on a project with several people ! 836: has its own set of special problems. ! 837: The main problem occurs when two people ! 838: modify a file at the same time. ! 839: \*S prevents this by locking an s-file ! 840: while it is being edited. ! 841: .pp ! 842: As a result, ! 843: files should not be reserved for editing ! 844: unless they are actually being edited at the time, ! 845: since this will prevent other people on the project ! 846: from making necessary changes. ! 847: For example, ! 848: a good scenario for working might be: ! 849: .(b ! 850: sccs edit a.c g.c t.c ! 851: vi a.c g.c t.c ! 852: # do testing of the (experimental) version ! 853: sccs delget a.c g.c t.c ! 854: sccs info ! 855: # should respond "Nothing being edited" ! 856: make install ! 857: .)b ! 858: .pp ! 859: As a general rule, ! 860: all source files should be deltaed ! 861: before installing the program for general use. ! 862: This will insure that it is possible ! 863: to restore any version in use at any time. ! 864: .sh 1 "Saving Yourself" ! 865: .sh 2 "Recovering a munged edit file" ! 866: .pp ! 867: Sometimes you may find ! 868: that you have destroyed or trashed ! 869: a file that you were trying to edit\**. ! 870: .(f ! 871: \**Or given up and decided to start over. ! 872: .)f ! 873: Unfortunately, ! 874: you can't just remove it ! 875: and re-\c ! 876: .i edit ! 877: it; ! 878: \*S keeps track ! 879: of the fact ! 880: that someone is trying to edit it, ! 881: so it won't let you do it again. ! 882: Neither can you just get it using ! 883: .i get , ! 884: since that would expand the Id keywords. ! 885: Instead, ! 886: you can say: ! 887: .(b ! 888: sccs get \-k prog.c ! 889: .)b ! 890: This will not expand the Id keywords, ! 891: so it is safe to do a delta ! 892: with it. ! 893: .pp ! 894: Alternately, ! 895: you can ! 896: .i unedit ! 897: and ! 898: .i edit ! 899: the file. ! 900: .sh 2 "Restoring the s-file" ! 901: .pp ! 902: In particularly bad circumstances, ! 903: the \*S file itself ! 904: may get munged. ! 905: The most common way this happens ! 906: is that it gets edited. ! 907: Since \*S keeps a checksum, ! 908: you will get errors every time you read the file. ! 909: To fix this checksum, use: ! 910: .(b ! 911: sccs admin \-z prog.c ! 912: .)b ! 913: .sh 1 "Using the Admin Command" ! 914: .pp ! 915: There are a number of parameters that can be set ! 916: using the ! 917: .i admin ! 918: command. ! 919: The most interesting of these are flags. ! 920: Flags can be added by using the ! 921: .b \-f ! 922: flag. ! 923: For example: ! 924: .(b ! 925: sccs admin \-fd1 prog.c ! 926: .)b ! 927: sets the ! 928: .q d ! 929: flag to the value ! 930: .q 1 . ! 931: This flag can be deleted by using: ! 932: .(b ! 933: sccs admin \-dd prog.c ! 934: .)b ! 935: The most useful flags are: ! 936: .nr ii 7n ! 937: .ip "b" ! 938: Allow branches to be made using the ! 939: \-b ! 940: flag to ! 941: .i edit . ! 942: .ip "d\fISID\fP" ! 943: Default \*I to be used on a ! 944: .i get ! 945: or ! 946: .i edit . ! 947: If this is just a release number ! 948: it constrains the ! 949: version ! 950: to a particular release only. ! 951: .ip "i" ! 952: Give a fatal error ! 953: if there are no Id Keywords in a file. ! 954: This is useful to guarantee that a version of the ! 955: file does not get merged into the s-file ! 956: that has the Id Keywords inserted as constants ! 957: instead of internal forms. ! 958: .ip "y" ! 959: The ! 960: .q type ! 961: of the module. ! 962: Actually, ! 963: the value of this flag is unused by \*S ! 964: except that it replaces the ! 965: .b %\&Y\&% ! 966: keyword. ! 967: .pp ! 968: The ! 969: .b \-t\fIfile\fR ! 970: flag can be used ! 971: to store descriptive text ! 972: from ! 973: .i file . ! 974: This descriptive text might be the documentation ! 975: or a design and implementation document. ! 976: Using the ! 977: .b \-t ! 978: flag insures that if the \*S file is sent, ! 979: the documentation will be sent also. ! 980: If ! 981: .i file ! 982: is omitted, ! 983: the descriptive text is deleted. ! 984: To see the descriptive text, ! 985: use ! 986: .q "prt \-t" . ! 987: .pp ! 988: The ! 989: .i admin ! 990: command can be used safely ! 991: any number of times on files. ! 992: A file need not be gotten ! 993: for ! 994: .i admin ! 995: to work. ! 996: .sh 1 "Maintaining Different Versions (Branches)" ! 997: .pp ! 998: Sometimes it is convenient ! 999: to maintain an experimental version of a program ! 1000: for an extended period ! 1001: while normal maintenance continues ! 1002: on the version in production. ! 1003: This can be done using a ! 1004: .q branch. ! 1005: Normally deltas continue in a straight line, ! 1006: each depending on the delta before. ! 1007: Creating a branch ! 1008: .q "forks off" ! 1009: a version of the program. ! 1010: .pp ! 1011: The ability to create branches ! 1012: must be enabled in advance using: ! 1013: .(b ! 1014: sccs admin \-fb prog.c ! 1015: .)b ! 1016: The ! 1017: .b \-fb ! 1018: flag can be specified when the ! 1019: \*S file is first created. ! 1020: .sh 2 "Creating a branch" ! 1021: .pp ! 1022: To create a branch, use: ! 1023: .(b ! 1024: sccs edit \-b prog.c ! 1025: .)b ! 1026: This will create a branch ! 1027: with (for example) \*I 1.5.1.1. ! 1028: The deltas for this version ! 1029: will be numbered ! 1030: 1.5.1.\c ! 1031: .i n . ! 1032: .sh 2 "Getting from a branch" ! 1033: .pp ! 1034: Deltas in a branch are normally not included ! 1035: when you do a get. ! 1036: To get these versions, ! 1037: you will have to say: ! 1038: .(b ! 1039: sccs get \-r1.5.1 prog.c ! 1040: .)b ! 1041: .sh 2 "Merging a branch back into the main trunk" ! 1042: .pp ! 1043: At some point you will have finished the experiment, ! 1044: and if it was successful ! 1045: you will want to incorporate it into the release version. ! 1046: But in the meantime ! 1047: someone may have created a delta 1.6 ! 1048: that you don't want to lose. ! 1049: The commands: ! 1050: .(b ! 1051: sccs edit \-i1.5.1.1\-1.5.1 prog.c ! 1052: sccs delta prog.c ! 1053: .)b ! 1054: will merge all of your changes ! 1055: into the release system. ! 1056: If some of the changes conflict, ! 1057: get will print an error; ! 1058: the generated result ! 1059: should be carefully examined ! 1060: before the delta is made. ! 1061: .sh 2 "A more detailed example" ! 1062: .pp ! 1063: The following technique might be used ! 1064: to maintain a different version of a program. ! 1065: First, ! 1066: create a directory to contain the new version: ! 1067: .(b ! 1068: mkdir ../newxyz ! 1069: cd ../newxyz ! 1070: .)b ! 1071: Edit a copy of the program ! 1072: on a branch: ! 1073: .(b ! 1074: sccs \-d../xyz edit prog.c ! 1075: .)b ! 1076: When using the old version, ! 1077: be sure to use the ! 1078: .b \-b ! 1079: flag to info, check, tell, and clean ! 1080: to avoid confusion. ! 1081: For example, use: ! 1082: .(b ! 1083: sccs info \-b ! 1084: .)b ! 1085: when in the directory ! 1086: .q xyz . ! 1087: .pp ! 1088: If you want to save a copy of the program ! 1089: (still on the branch) ! 1090: back in the s-file, ! 1091: you can use: ! 1092: .(b ! 1093: sccs -d../xyz deledit prog.c ! 1094: .)b ! 1095: which will do a delta on the branch ! 1096: and reedit it for you. ! 1097: .pp ! 1098: When the experiment is complete, merge it back into the s-file ! 1099: using delta: ! 1100: .(b ! 1101: sccs -d../xyz delta prog.c ! 1102: .)b ! 1103: At this point you must decide whether this version ! 1104: should be merged back into the trunk ! 1105: (\c ! 1106: .i i.e. ! 1107: the default version), ! 1108: which may have undergone changes. ! 1109: If so, it can be merged using the ! 1110: .b \-i ! 1111: flag to ! 1112: .i edit ! 1113: as described above. ! 1114: .sh 2 "A warning" ! 1115: .pp ! 1116: Branches should be kept to a minimum. ! 1117: After the first branch from the trunk, ! 1118: \*I's are assigned rather haphazardly, ! 1119: and the structure gets complex fast. ! 1120: .sh 1 "Using \*S with Make" ! 1121: .pp ! 1122: \*S and make can be made to work together ! 1123: with a little care. ! 1124: A few sample makefiles ! 1125: for common applications are shown. ! 1126: .pp ! 1127: There are a few basic entries that every makefile ! 1128: ought to have. ! 1129: These are: ! 1130: .nr ii 1i ! 1131: .ip a.out ! 1132: (or whatever the makefile generates.) ! 1133: This entry regenerates whatever this makefile is ! 1134: supposed to regenerate. ! 1135: If the makefile regenerates many things, ! 1136: this should be called ! 1137: .q all ! 1138: and should in turn ! 1139: have dependencies on everything ! 1140: the makefile can generate. ! 1141: .ip install ! 1142: Moves the objects to the final ! 1143: resting place, ! 1144: doing any special ! 1145: .i chmod 's ! 1146: or ! 1147: .i ranlib 's ! 1148: as appropriate. ! 1149: .ip sources ! 1150: Creates all the source files from \*S files. ! 1151: .ip clean ! 1152: Removes all files from the current directory ! 1153: that can be regenerated from \*S files. ! 1154: .ip print ! 1155: Prints the contents of the directory. ! 1156: .lp ! 1157: The examples shown below are only partial examples, ! 1158: and may omit some of these entries ! 1159: when they are deemed to be obvious. ! 1160: .pp ! 1161: The ! 1162: .i clean ! 1163: entry should not remove files that can be ! 1164: regenerated from the \*S files. ! 1165: It is sufficiently important to have the ! 1166: source files around at all times ! 1167: that the only time they should be removed ! 1168: is when the directory is being mothballed. ! 1169: To do this, the command: ! 1170: .(b ! 1171: sccs clean ! 1172: .)b ! 1173: can be used. ! 1174: This will remove all files for which an s-file ! 1175: exists, ! 1176: but which is not being edited. ! 1177: .sh 2 "To maintain single programs" ! 1178: .pp ! 1179: Frequently there are directories with several ! 1180: largely unrelated programs ! 1181: (such as simple commands). ! 1182: These can be put into a single makefile: ! 1183: .(b ! 1184: LDFLAGS= \-i \-s ! 1185: .sp \n(psu ! 1186: prog: prog.o ! 1187: $(CC) $(LDFLAGS) \-o prog prog.o ! 1188: prog.o: prog.c prog.h ! 1189: .sp \n(psu ! 1190: example: example.o ! 1191: $(CC) $(LDFLAGS) \-o example example.o ! 1192: example.o: example.c ! 1193: .sp \n(psu ! 1194: \&.DEFAULT: ! 1195: sccs get $< ! 1196: .)b ! 1197: The trick here ! 1198: is that the .DEFAULT rule ! 1199: is called every time ! 1200: something is needed ! 1201: that does not exist, ! 1202: and no other rule exists to make it. ! 1203: The explicit dependency of the ! 1204: .b \&.o ! 1205: file on the ! 1206: .b \&.c ! 1207: file is important. ! 1208: Another way of doing the same thing is: ! 1209: .(b ! 1210: SRCS= prog.c prog.h example.c ! 1211: .sp \n(psu ! 1212: LDFLAGS= \-i \-s ! 1213: .sp \n(psu ! 1214: prog: prog.o ! 1215: $(CC) $(LDFLAGS) \-o prog prog.o ! 1216: prog.o: prog.h ! 1217: .sp \n(psu ! 1218: example: example.o ! 1219: $(CC) $(LDFLAGS) \-o example example.o ! 1220: .sp \n(psu ! 1221: sources: $(SRCS) ! 1222: $(SRCS): ! 1223: sccs get $@ ! 1224: .)b ! 1225: There are a couple of advantages to this approach: ! 1226: (1) the explicit dependencies of the .o on the .c files are ! 1227: not needed, ! 1228: (2) there is an entry called "sources" so if you want to get ! 1229: all the sources you can just say ! 1230: .q "make sources" , ! 1231: and ! 1232: (3) the makefile is less likely to do confusing things ! 1233: since it won't try to ! 1234: .i get ! 1235: things that do not exist. ! 1236: .sh 2 "To maintain a library" ! 1237: .pp ! 1238: Libraries that are largely static ! 1239: are best updated using explicit commands, ! 1240: since ! 1241: .i make ! 1242: doesn't know about updating them properly. ! 1243: However, ! 1244: libraries that are in the process of being developed ! 1245: can be handled quite adequately. ! 1246: The problem is that the .o files ! 1247: have to be kept out of the library ! 1248: as well as in the library. ! 1249: .(b ! 1250: # configuration information ! 1251: OBJS= a.o b.o c.o d.o ! 1252: SRCS= a.c b.c c.c d.s x.h y.h z.h ! 1253: TARG= /usr/lib ! 1254: .sp \n(psu ! 1255: # programs ! 1256: GET= sccs get ! 1257: REL= ! 1258: AR= \-ar ! 1259: RANLIB= ranlib ! 1260: .sp \n(psu ! 1261: lib.a: $(OBJS) ! 1262: $(AR) rvu lib.a $(OBJS) ! 1263: $(RANLIB) lib.a ! 1264: .sp \n(psu ! 1265: install: lib.a ! 1266: sccs check ! 1267: cp lib.a $(TARG)/lib.a ! 1268: $(RANLIB) $(TARG)/lib.a ! 1269: .sp \n(psu ! 1270: sources: $(SRCS) ! 1271: $(SRCS): ! 1272: $(GET) $(REL) $@ ! 1273: .sp \n(psu ! 1274: print: sources ! 1275: pr *.h *.[cs] ! 1276: clean: ! 1277: rm \-f *.o ! 1278: rm \-f core a.out $(LIB) ! 1279: .)b ! 1280: .pp ! 1281: The ! 1282: .q "$(REL)" ! 1283: in the get ! 1284: can be used to get old versions ! 1285: easily; for example: ! 1286: .(b ! 1287: make b.o REL=\-r1.3 ! 1288: .)b ! 1289: .pp ! 1290: The ! 1291: .i install ! 1292: entry includes the line ! 1293: .q "sccs check" ! 1294: before anything else. ! 1295: This guarantees that all the s-files ! 1296: are up to date ! 1297: (\c ! 1298: .i i.e. , ! 1299: nothing is being edited), ! 1300: and will abort the ! 1301: .i make ! 1302: if this condition is not met. ! 1303: .sh 2 "To maintain a large program" ! 1304: .(b ! 1305: OBJS= a.o b.o c.o d.o ! 1306: SRCS= a.c b.c c.y d.s x.h y.h z.h ! 1307: .sp \n(psu ! 1308: GET= sccs get ! 1309: REL= ! 1310: .sp \n(psu ! 1311: a.out: $(OBJS) ! 1312: $(CC) $(LDFLAGS) $(OBJS) $(LIBS) ! 1313: .sp \n(psu ! 1314: sources: $(SRCS) ! 1315: $(SRCS): ! 1316: $(GET) $(REL) $@ ! 1317: .)b ! 1318: (The ! 1319: .i print ! 1320: and ! 1321: .i clean ! 1322: entries are identical to the previous case.) ! 1323: This makefile requires copies of the source and object files ! 1324: to be kept during development. ! 1325: It is probably also wise to include lines of the form: ! 1326: .(b ! 1327: a.o: x.h y.h ! 1328: b.o: z.h ! 1329: c.o: x.h y.h z.h ! 1330: z.h: x.h ! 1331: .)b ! 1332: so that modules will be recompiled ! 1333: if header files change. ! 1334: .pp ! 1335: Since ! 1336: .i make ! 1337: does not do transitive closure on dependencies, ! 1338: you may find in some makefiles lines like: ! 1339: .(b ! 1340: z.h: x.h ! 1341: touch z.h ! 1342: .)b ! 1343: This would be used in cases where file z.h ! 1344: has a line: ! 1345: .(b ! 1346: #include "x.h" ! 1347: .)b ! 1348: in order to bring the mod date of z.h in line ! 1349: with the mod date of x.h. ! 1350: When you have a makefile such as above, ! 1351: the ! 1352: .i touch ! 1353: command can be removed completely; ! 1354: the equivalent effect will be achieved ! 1355: by doing an automatic ! 1356: .i get ! 1357: on z.h. ! 1358: .sh 1 "Further Information" ! 1359: .pp ! 1360: The ! 1361: .i "SCCS/PWB User's Manual" ! 1362: gives a deeper description ! 1363: of how to use \*S. ! 1364: Of particular interest ! 1365: are the numbering of branches, ! 1366: the l-file, ! 1367: which gives a description of what deltas were used on a get, ! 1368: and certain other \*S commands. ! 1369: .pp ! 1370: The \*S manual pages ! 1371: are a good last resort. ! 1372: These should be read by software managers ! 1373: and by people who want to know ! 1374: everything about everything. ! 1375: .pp ! 1376: Both of these documents were written without the ! 1377: .i sccs ! 1378: front end in mind, ! 1379: so most of the examples are slightly different from those ! 1380: in this document. ! 1381: .bp ! 1382: .sz 12 ! 1383: .ce ! 1384: .b "Quick Reference" ! 1385: .sz ! 1386: .sp 2 ! 1387: .sh 1 Commands 1 ! 1388: .pp ! 1389: The following commands should all be preceded with ! 1390: .q sccs . ! 1391: This list is not exhaustive; ! 1392: for more options see ! 1393: .i "Further Information" . ! 1394: .ip get 9n ! 1395: Gets files for compilation (not for editing). ! 1396: Id keywords are expanded. ! 1397: .ba 9n ! 1398: .nr ii 8n ! 1399: .ip \-r\fI\*I\fP ! 1400: Version to get. ! 1401: .ip \-p ! 1402: Send to standard output rather than to the actual file. ! 1403: .ip \-k ! 1404: Don't expand id keywords. ! 1405: .ip \-i\fIlist\fP ! 1406: List of deltas to include. ! 1407: .ip \-x\fIlist\fP ! 1408: List of deltas to exclude. ! 1409: .ip \-m ! 1410: Precede each line with \*I of creating delta. ! 1411: .ip \-c\fIdate\fP ! 1412: Don't apply any deltas created after ! 1413: .i date. ! 1414: .ba ! 1415: .ip edit 9n ! 1416: Gets files for editing. ! 1417: Id keywords are not expanded. ! 1418: Should be matched with a ! 1419: .i delta ! 1420: command. ! 1421: .ba 9n ! 1422: .nr ii 8n ! 1423: .ip \-r\fI\*I\fP ! 1424: Same as ! 1425: .i get . ! 1426: If ! 1427: .i \*I ! 1428: specifies a release that does not yet exist, ! 1429: the highest numbered delta is retrieved ! 1430: and the new delta is numbered with ! 1431: .i \*I . ! 1432: .ip \-b ! 1433: Create a branch. ! 1434: .ip \-i\fIlist\fP ! 1435: Same as ! 1436: .i get . ! 1437: .ip \-x\fIlist\fP ! 1438: Same as ! 1439: .i get . ! 1440: .ba ! 1441: .ip delta 9n ! 1442: Merge a file gotten using ! 1443: .i edit ! 1444: back into the s-file. ! 1445: Collect comments about why this delta was made. ! 1446: .ip unedit 9n ! 1447: Remove a file that has been edited previously ! 1448: without merging the changes into the s-file. ! 1449: .ip prt 9n ! 1450: Produce a report of changes. ! 1451: .ba 9n ! 1452: .nr ii 5n ! 1453: .ip \-t ! 1454: Print the descriptive text. ! 1455: .ip \-e ! 1456: Print (nearly) everything. ! 1457: .ba ! 1458: .ip info 9n ! 1459: Give a list of all files being edited. ! 1460: .ba 9n ! 1461: .nr ii 5n ! 1462: .ip \-b ! 1463: Ignore branches. ! 1464: .ip \-u[\fIuser\fP] ! 1465: Ignore files not being edited by ! 1466: .i user . ! 1467: .ba ! 1468: .ip check 9n ! 1469: Same as ! 1470: .i info , ! 1471: except that nothing is printed if nothing is being edited ! 1472: and exit status is returned. ! 1473: .ip tell 9n ! 1474: Same as ! 1475: .i info , ! 1476: except that one line is produced per file being edited containing ! 1477: only the file name. ! 1478: .ip clean 9n ! 1479: Remove all files that can be regenerated from the ! 1480: s-file. ! 1481: .ip what 9n ! 1482: Find and print id keywords. ! 1483: .ip admin 9n ! 1484: Create or set parameters on s-files. ! 1485: .ba 9n ! 1486: .nr ii 8n ! 1487: .ip \-i\fIfile\fP ! 1488: Create, using ! 1489: .i file ! 1490: as the initial contents. ! 1491: .ip \-z ! 1492: Rebuild the checksum in case ! 1493: the file has been trashed. ! 1494: .ip \-f\fIflag\fP ! 1495: Turn on the ! 1496: .i flag . ! 1497: .ip \-d\fIflag\fP ! 1498: Turn off (delete) the ! 1499: .i flag . ! 1500: .ip \-t\fIfile\fP ! 1501: Replace the descriptive text ! 1502: in the s-file with the contents of ! 1503: .i file . ! 1504: If ! 1505: .i file ! 1506: is omitted, ! 1507: the text is deleted. ! 1508: Useful for storing documentation ! 1509: or ! 1510: .q "design & implementation" ! 1511: documents to insure they get distributed with the ! 1512: s-file. ! 1513: .lp ! 1514: Useful flags are: ! 1515: .ip b ! 1516: Allow branches to be made using the \-b flag to ! 1517: .i edit. ! 1518: .ip d\fI\*I\fP ! 1519: Default \*I to be used ! 1520: on a ! 1521: .i get ! 1522: or ! 1523: .i edit . ! 1524: .ip i ! 1525: Cause ! 1526: .q "No Id Keywords" ! 1527: error message ! 1528: to be a fatal error rather than a warning. ! 1529: .ip t ! 1530: The module ! 1531: .q type ; ! 1532: the value of this flag replaces the ! 1533: .b %\&Y\&% ! 1534: keyword. ! 1535: .ba ! 1536: .ip fix 9n ! 1537: Remove a delta and reedit it. ! 1538: .ip delget 9n ! 1539: Do a ! 1540: .i delta ! 1541: followed by a ! 1542: .i get . ! 1543: .ip deledit 9n ! 1544: Do a ! 1545: .i delta ! 1546: followed by an ! 1547: .i edit . ! 1548: .sh 1 "Id Keywords" ! 1549: .nr ii 6n ! 1550: .ip "%\&Z\&%" ! 1551: Expands to ! 1552: .q @\&(#) ! 1553: for the ! 1554: .i what ! 1555: command to find. ! 1556: .ip "%\&M\&%" ! 1557: The current module name, ! 1558: .i e.g., ! 1559: .q prog.c . ! 1560: .ip "%\&I\&%" ! 1561: The highest \*I applied. ! 1562: .ip "%\&W\&%" ! 1563: A shorthand for ! 1564: .q "%\&Z\&%%\&M\&% <tab> %\&I\&%" . ! 1565: .ip "%\&G\&%" ! 1566: The date of the delta ! 1567: corresponding to the ! 1568: .q "%\&I\&%" ! 1569: keyword. ! 1570: .ip "%\&R\&%" ! 1571: The current release number, ! 1572: .i i.e. , ! 1573: the first component of the ! 1574: .q "%\&I\&%" ! 1575: keyword. ! 1576: .ip "%\&Y\&%" ! 1577: Replaced by the value of the ! 1578: .b t ! 1579: flag ! 1580: (set by ! 1581: .i admin ).
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.