26

In the OpenBSD code here, there is a comment that ends with:

@(#)init_main.c 8.9 (Berkeley) 1/21/94

What is the purpose of @(#)? I would assume that it is to make searching easier, but why @(#) specifically and not another more meaningful pattern of characters like INFO:? I know that it is not OpenBSD specific because I remember seeing this before.

Benjily3
  • 273
  • 2
  • 7

2 Answers2

33

That's a marker for SCCS version information that the what program looks for. It will report what follows up to one of a number of end markers: null byte, newline, double quote ", greater than > and backslash \.

What is SCCS? It stands for Source Code Control System, and was developed by Marc J Rochkind at AT&T (Bell Labs) for Unix. It was the first widely used Unix-based VCS (version control system), and is standardized in POSIX with the commands admin, delta, get, prs, rmdel, unget and what. The classic (AT&T) version included commands cdc, comb, help (yes, it pre-empted that name; it's sometimes called sccshelp these days), sact, sccsdiff and val too. Some systems provided a program sccs that, like cvs or git, takes a command name as its first argument. SCCS was closed source. The Open Source community used first RCS and later CVS instead, and later there was a profusion of other alternatives, such as Git, Subversion, Mercurial, Fossil, Bazaar, … You can find at least two open source versions of SCCS: Schily-SCCS and CSSC (a GNU reimplementation of SCCS), which are both largely compatible with SCCS. SCCS is a centralized VCS, like RCS and many other systems, in contrast to distributed VCS (DVCS) such as Git. There is expected to be a master version of the SCCS-managed files stored somewhere.

As to why @(#) instead of INFO or other notations, the reason was precisely to avoid any plausible mixup with regular text. It is very unlikely that you'd ever have cause to write that sequence of characters other than as an SCCS marker.

I use it in front of RCS $Id$ strings (which can separately be tracked by ident from the RCS package). So, for example, my rmk program yields:

$ what rmk
rmk:
    RMK Version 25.92 (2017-10-09)
    *** SCCS enabled ***
    *** RCS enabled ***
    $Id: getopt.h,v 2015.3 2015/09/29 07:13:26 jleffler Exp $
    $Id: stderr.h,v 10.12 2017/04/08 03:43:34 jleffler Exp $
    $Id: sastrings.h,v 2.16 2015/07/05 06:52:05 jleffler Exp $
    $Id: list.h,v 9.6 2016/03/06 18:09:00 jleffler Exp $
    $Id: emalloc.h,v 5.10 2015/02/17 04:50:35 jleffler Exp $
    $Id: debug.h,v 3.13 2016/01/17 15:47:27 jleffler Exp $
    $Id: kludge.h,v 1.16 2016/01/17 15:48:53 jleffler Exp $
    $Id: config.h,v 9.14 2016/09/05 05:37:55 jleffler Exp $
    $Id: make.h,v 9.20 2017/03/28 21:03:36 jleffler Exp $
    $Id: main.c,v 9.20 2016/08/30 22:38:57 jleffler Exp $
    $Id: basename.c,v 2.4 2008/02/11 08:44:50 jleffler Exp $
    $Id: check.c,v 9.6 2016/03/06 07:36:35 jleffler Exp $
    $Id: cleanup.c,v 9.6 2016/08/30 22:38:57 jleffler Exp $
    *** DEBUGGING ENABLED ***
    $Id: debug.c,v 3.12 2016/07/13 00:00:35 jleffler Exp $
    $Id: emalloc.c,v 5.13 2016/01/17 16:05:58 jleffler Exp $
    $Id: errhelp.c,v 8.5 2009/03/02 19:13:51 jleffler Exp $
    $Id: estrdup.c,v 5.7 2015/06/02 03:05:40 jleffler Exp $
    $Id: getopt.c,v 2015.2 2015/09/29 07:13:58 jleffler Exp $
    $Id: input.c,v 9.24 2017/10/09 20:34:18 jleffler Exp $
    $Id: list.c,v 9.4 2015/07/16 00:13:23 jleffler Exp $
    $Id: macro.c,v 9.15 2016/08/30 22:38:57 jleffler Exp $
    $Id: make.c,v 9.12 2017/03/28 21:03:36 jleffler Exp $
    $Id: names.c,v 9.12 2016/08/30 22:38:57 jleffler Exp $
    $Id: rcs.c,v 9.9 2016/08/30 22:38:57 jleffler Exp $
    $Id: rcsfile.c,v 9.9 2016/08/30 22:38:57 jleffler Exp $
    $Id: rules.c,v 9.9 2016/03/06 03:58:52 jleffler Exp $
    $Id: sastrings.c,v 2.22 2015/07/05 06:52:05 jleffler Exp $
    $Id: sccs.c,v 9.11 2016/08/30 22:38:57 jleffler Exp $
    $Id: sccsfile.c,v 9.8 2016/08/30 22:38:57 jleffler Exp $
    $Id: stderr.c,v 10.19 2017/07/10 04:54:26 jleffler Exp $
    $Id: touch.c,v 9.7 2016/03/06 17:31:17 jleffler Exp $
    $Id: vstrcpy.c,v 1.13 2008/02/11 08:44:50 jleffler Exp $
    $Id: archive.c,v 9.11 2017/06/04 04:44:17 jleffler Exp $
    $Id: clnpath.c,v 2.19 2017/03/26 06:32:49 jleffler Exp $
    $Id: dirname.c,v 2.6 2012/02/06 01:55:16 jleffler Exp $
    $Id: tokenise.c,v 2.2 2017/03/26 06:33:37 jleffler Exp $
$

It allows me to see which versions of which files are used to build the program, plus some auxilliary information that's marked with the @(#) tag. Run on one of those source files, (stderr.c), I get:

$ what stderr.c
stderr.c:
    File:           $RCSfile: stderr.c,v $
    Version:        $Revision: 10.19 $
    Last changed:   $Date: 2017/07/10 04:54:26 $
    Purpose:        Error reporting routines
    Author:         J Leffler
    Copyright:      (C) JLSS 1988-2017
    Product:        :PRODUCT:


    $Id: stderr.c,v 10.19 2017/07/10 04:54:26 jleffler Exp $
$

The heading of the file looks like:

/*
@(#)File:           $RCSfile: stderr.c,v $
@(#)Version:        $Revision: 10.19 $
@(#)Last changed:   $Date: 2017/07/10 04:54:26 $
@(#)Purpose:        Error reporting routines
@(#)Author:         J Leffler
@(#)Copyright:      (C) JLSS 1988-2017
@(#)Product:        :PRODUCT:
*/

The other strings reported by what appear further down the file. One of the blank lines arises from:

#if defined(USE_STDERR_FILEDESC)
extern const char jlss_id_stderr_c_with_filedesc[];
const char jlss_id_stderr_c_with_filedesc[] =
        "@(#)" __FILE__ " configured with USE_STDERR_FILEDESC";
#endif /* USE_STDERR_FILEDESC */

The marker there is followed by a double quote, so the rest of the line is not reported — it looks like a blank line in the output. The last listed line is the one embedded in the object file, and hence in programs that use the object file, such as rmk.

Jonathan Leffler
  • 730,956
  • 141
  • 904
  • 1,278
5

That's a reminiscence of the old AT&T sccs code. That's an old source code revision system like rcs to maintain different versions of a file (this was superseded by systems that allowed to maintain entire directory versions, like cvs or git). Nowadays, it has been completely superseded by the new revision software in use... but these were labels to identify special strings in the object code. The source code version system used that sequence as some introductory (and rare) escape sequence that allowed it to identify the strings you see in the code. These strings allowed automatic processing of attributes in the source files, like the ones you see in the sample code that has been posted in other answers.

Luis Colorado
  • 10,974
  • 1
  • 16
  • 31