Groups 
Advanced Groups Search    Preferences    Groups Help 
 
Groups search result 1 for cpp predefined macros target 
 Free Unix/Linux Info • Unix/Linux tips, reviews and news free from UnixReview and Sys Admin! • www.sysadminmag.comSponsored Links 
Search Result 1
From: Thomas A. Baker (tombaker@bumetb.bu.edu)
Subject: v41i163: tbdefs - shows compilers predefined macros, Part01/01
This is the only article in this thread
View: Original Format
Newsgroups: comp.sources.misc
Date: 1994-03-07 14:26:56 PST
Submitted-by: tombaker@bumetb.bu.edu (Thomas A. Baker)
Posting-number: Volume 41, Issue 163
Archive-name: tbdefs/part01
Environment: cpp

#! /bin/sh
# This is a shell archive.  Remove anything before this line, then feed it
# into a shell via "sh file" or similar.  To overwrite existing files,
# type "sh file -c".
# Contents:  makefile showdefs tbdefsmk.c tbdefsmk.h
# Wrapped by kent@sparky on Sun Mar  6 23:34:08 1994
PATH=/bin:/usr/bin:/usr/ucb:/usr/local/bin:/usr/lbin:$PATH ; export PATH
echo If this archive is complete, you will see the following message:
echo '          "shar: End of archive 1 (of 1)."'
if test -f 'makefile' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'makefile'\"
else
  echo shar: Extracting \"'makefile'\" \(83 characters\)
  sed "s/^X//" >'makefile' <<'END_OF_FILE'
Xtbdefs.c : tbdefsmk.h tbdefsmk.c
X cc -o tbdefsmk tbdefsmk.c
X tbdefsmk
X rm tbdefsmk
END_OF_FILE
  if test 83 -ne `wc -c <'makefile'`; then
    echo shar: \"'makefile'\" unpacked with wrong size!
  fi
  # end of 'makefile'
fi
if test -f 'showdefs' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'showdefs'\"
else
  echo shar: Extracting \"'showdefs'\" \(236 characters\)
  sed "s/^X//" >'showdefs' <<'END_OF_FILE'
X#!/bin/csh -f
Xif( "$*" == "" ) then
X    echo Need compiler invocation.
X    exit 1
Xendif
Xmake tbdefs.c
Xecho $* -o tbdefs tbdefs.c
X$* -o tbdefs tbdefs.c
X# echo tbdefs and pr -a -t -l24 -2 -p -
Xecho tbdefs and more
Xtbdefs | more
Xrm tbdefs
END_OF_FILE
  if test 236 -ne `wc -c <'showdefs'`; then
    echo shar: \"'showdefs'\" unpacked with wrong size!
  fi
  chmod +x 'showdefs'
  # end of 'showdefs'
fi
if test -f 'tbdefsmk.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'tbdefsmk.c'\"
else
  echo shar: Extracting \"'tbdefsmk.c'\" \(10683 characters\)
  sed "s/^X//" >'tbdefsmk.c' <<'END_OF_FILE'
X/* tbdefsmk.c - Produce a pgm of all the defs compilers have thrown at me. */
X/*
X * Intro:
X * 
X * The question was put to me once, of how to determine just which
X * #defines are set by a given compiler.  The answer is, of course, to go read
X * the documentation.  The "Preset" #define's, or the "predefined macros",
X * (or whatever they're called), are usually listed under the "-U"
X * switch, and are in the section on the preprocessor, if there is such a
X * section.  (For Unix systems, they're usually in the "cpp(1)" man page,
X * not often in "cc(1)".)
X * 
X * You HAVE to read the documentation.  It is not enough to know that,
X * for example, symbol XYZZY will be provided.  If you are going to use
X * it, you'll have to know what it means.  (For instance, "m68000" may
X * mean that the code is for any chip in the 68000 family; but on some
X * compilers, it might mean the 68000 chip and not 68010 or later.)
X * 
X * I've found that reading the documentation once is not enough.
X * Unless I specifically write the symbols down somewhere, I am doomed to
X * searching for the list of "predefined's" again and again.  So I made
X * the list, and kept it.  And with each compiler, I added to it.
X * 
X * From there, it was inevitable that the list become a program,
X * "tbdefs.c".  (You might think "tb" stands for my name, actually it
X * officially stands for "toolbox".)  A sample chunk is given below:
X * 
X *     #ifdef SYMBOL1
X *     puts( "SYMBOL1" );
X *     #endif
X *     #ifdef SYMBOL2
X *     puts( "SYMBOL2" );
X *     #endif
X * 
X * When compiled and run, of course, it spits out a list of predefined
X * symbols.
X * 
X * That became pretty tough to maintain, so I got this package together
X * that you have now.  The list "tbdefsmk.h" is essentially the original
X * list; a sample chunk is given:
X * 
X * "BORLANDC",
X * "EOF",          /* Usually means stdio.h got included automatically */
X/* "EXIT_FAILURE",
X * 
X * There is one line per symbol, leaving enough room to put in a C-style
X * comment if you want.  Then, the file you are reading, "tbdefsmk.c",
X * includes the list and spits out the "tbdefs.c" file, with all the
X * #ifdef and #endif lines.
X * 
X * See the section "TO RUN" for info on running the program.  But,
X * basically, for any compiler (Dos/Unix/VMS/Apple):
X * 
X * 1) Read its documentation, and add any new "predefines" to tbdefsmk.h .
X * 
X * 2) Compile and run tbdefsmk.c .  This produces tbdefs.c .
X * 
X * 3) Compile and run tbdefs.c .  This produces the list.
X * 
X * Philosophy:
X * 
X * This program doesn't really subvert the documentation, and certainly
X * does not replace it.  It does provide a very useful addition to it.
X * 
X * I've run it against a new compiler, and gotten a surprise output.  My
X * response is to pour through the documentation again -- I ALWAYS find
X * the symbol listed, and had somehow missed it before.
X * 
X * I've run it against a compiler to see if it is "ansi" complient.  The
X * symbol that flags that is "__ANSI__".  It's a standard.
X * 
X * If my present project's code is to run on just a few, different
X * machines, I'll use tbdefs.c to produce lists of symbols.  Then I'll
X * use the ones that I guess the compiler writers intended, to have the
X * code check which platform is present.  I'll usually #define my own
X * symbols, derived from those, for further checks later on in the code
X * (making all platform determinations localized to the top of the file).
X * 
X * I've used this for verifying that the compilers and preprocessors do
X * set the macros they say they will.
X * 
X * Note that this can check for flags set on the command line.
X */
X/*
X * Copyright 1993, 1994 Thomas A.J.F. Baker
X *
X * I retain the rights and ownership of this code, but release this for
X * public use as long as no one makes a profit on it or alters this
X * notice in any way.  No one is liable for the correctness of this code.
X *
X * If you can make a profit with this, contact me and we'll talk.
X */
X/*
X * (If what you have is the "tbdefs.bdl" file... put it into an empty
X *  directory, then ...
X *
X * (If you have a Unix system, then enter the command: sh < tbdefs.bdl
X * and it will extract itself into separate files.
X * 
X * (Otherwise, cut this into pieces with any text editor.
X * A "file" named "makefile", for instance, starts after
X * the line 
X *             cat >makefile <<'End of makefile'
X * and ends before
X * the line 
X *             End of makefile
X * 
X * TO RUN:
X *
X * (On Unix, just type "showdefs cc" to test the "cc" compiler.)
X * (That requires that you give showdefs "x" permission.)
X *
X * Compile this somewhere and run it.  It stores the output in "tbdefs.c".
X *
X * Then, on the target platform:
X *
X * Either run 'tbdefs.c' through the preprocessor and look at the output,
X * or compile 'tbdefs.c' and run it.
X *
X * (Note: The two techniques are not redundant.  On some systems,
X *        like Borland's, preprocessor-alone and preprocessor-cum-compiler
X *        produce different lists.)
X */
X/* TO ADD CANDIDATE STRINGS:
X *
X * Add them to the file tbdefsmk.h, following it's format.
X * You might want to run it through a sorter.
X *
X * You can document, a little bit, in that file.  Add a C comment after the
X * comma, and it should not affect any sorting operations.  (However, it
X * will affect the operation of 'uniq', or any program that tries to
X * eliminate multiple entries.)
X *
X * The format is one-per-line so it can be sorted.  That's why the
X * first few lines begin with one or more spaces, and have strange
X * first characters, like underscores.  If you are compliant with
X * these conventions, then you may send me your 'tbdefsmk.h' lists (to
X * 'tombaker@world.std.com') and I'll fold them in, sorting and uniq-ing,
X * for the next release.
X */
X/*
X * Example:
X *
X * Started using GNU C on an IBM AIX system (the one at Boston University).
X * I read the documentation and found nothing got mentioned that hadn't been
X * added to the "tbdefsmk.h" file before.  I built and ran tbdefsmk.
X *
X * > gcc -o tbdefsmk tbdefsmk.c
X * > tbdefsmk
X *
X * That produced the file "tbdefs.c".  Now, I tried the different flags
X * mentioned in gcc's documentation.
X *
X * > gcc -o tbdefs tbdefs.c
X * > tbdefs
X *
X * > gcc -ansi -o tbdefs tbdefs.c
X * > tbdefs
X *
X * > gcc -traditional -o tbdefs tbdefs.c
X * > tbdefs
X *
X * And that proved to me that gcc's behaviour is markedly changed by
X * its command line options.  The three lists were very different.
X */
X/*
X * UNIX Aids:
X *            As a rule, the 'make' facilities on DOS or other
X *            machines are not as standardized as the ones on
X *            UNIX systems.  So I have been just compiling the
X *            tbdefs stuff manually there.
X *
X *            But, on Unix systems, I've had more consistent
X *            experiences.  So I've been able to put together
X *            a makefile that seems to work to build the
X *            'tbdefs.c' file if it isn't there, and the
X *            'tbdefsmk' executable if that isn't.
X *
X *            So, finally, the command 'showdefs' uses
X *            'makefile' to make the whole operation a single line.
X *
X *            $ chmod +x showdefs
X *
X *            $ showdefs cc
X *            $ showdefs c89
X *            $ showdefs gcc
X *            $ showdefs gcc -ansi
X *
X *            The above four commands should produce four lists of tokens.
X *            Notice that command line options, like "-DNODEBUG", are allowed.
X *
X/*
X * Note that, while <stdio.h> is included in this program generator,
X *                                                        ---------
X * it won't figure into the program we'll end up giving to the preprocessor.
X *
X * Note also: This ends up depending on the "puts()" function.
X *            I've found that, everywhere I've compiled it, the program
X *            worked just fine even without the definition of puts()
X *            from <stdio.h>.
X *
X *            If that turns out to be untrue, a puts() function can be
X *            put right into the output code.
X *
X * Note: As you can see from the code, this used to #undef each token as
X *       it was examined.  But first "__STDC__" resisted that, then "__ANSI__"
X *       in some compilers.  Finally, I realized that this concept should
X *       work with the "functions" like "__LINE__" and "__TIMESTAMP__".
X *       You can put it back if you need it, just #define UNDEF_THE_TOKENS.
X *
X * Note: You'll also see that from "tbdefsmk.h" that I used to have in
X *       the trivially standard __FILE__ and __TIME__ macros.  I then
X *       found that I didn't like them cluttering up every output.
X *       (I use this to verify macros I can use for #ifdef arguments, and
X *       __LINE__ is not used that way.)  So they are tucked into the
X *       file header section of "tbdefsmk.h"
X */
X/*
X * mid-1980s Version 1.0 "tbdefs.c" The end program, manually generated,
X *                       which followed me around and kept growing slowly.
X *                       I tried to sort the candidate strings intelligently,
X *                       but no scheme worked out, in the long run.
X * 30-sep-93 Version 2.0 "tbdefsmk.c" now generates tbdefs.c, and the
X *                       candidate strings in tbdefsmk.h are sorted by
X *                       machine.
X * 14-dec-93 Version 2.1 Undid all the "#undef" stuff with UNDEF_THE_TOKENS.
X */
X#include <stdio.h>
X
Xchar *strings[] = {
X#include "tbdefsmk.h"
X"~"
X};
X
Xmain()
X{
X    int i;
X    FILE *fp;
X
X    if( (fp=fopen("tbdefs.c","w")) == NULL )
X    {
X        fprintf(stderr, "Could not open tbdefs.c for writing.\n");
X        exit(1);
X    }
X    fprintf(fp,"main()\n");
X    fprintf(fp,"{\n");
X    fprintf(fp,"    puts(\"The list is:\");\n");
X
X    for( i=0; strings[i][0] != '~'; i++ )
X    {
X        fprintf(fp,"#ifdef %s\n", strings[i]);
X        fprintf(fp," puts(\"%s\");\n", strings[i]);
X
X#ifdef  UNDEF_THE_TOKENS
X/*
X * __STDC__ is the only predefined constant that can *not* be #undef'd.
X * (cf. K&R, 2nd edition, p. 233) (I would hope you wouldn't try this
X * program on things like __FILE__ or __DATE__; they're not constants.)
X */
X        if(  (strings[i][0] != '_')
X          || (strings[i][1] != '_')
X          || (strings[i][2] != 'S')
X          || (strings[i][3] != 'T')
X          || (strings[i][4] != 'D')
X          || (strings[i][5] != 'C')
X          || (strings[i][6] != '_')
X          || (strings[i][7] != '_')
X          || (strings[i][8] != '\0')
X          )
X            fprintf(fp,"#undef %s\n", strings[i]);
X#endif  /* UNDEF_THE_TOKENS */  /* Note that stuff after endif is not
X                                   ignored, say in SCO.              */
X
X        fprintf(fp,"#endif\n");
X    }
X    fprintf(fp,"}\n");
X    fclose(fp);
X    exit(0);
X}
END_OF_FILE
  if test 10683 -ne `wc -c <'tbdefsmk.c'`; then
    echo shar: \"'tbdefsmk.c'\" unpacked with wrong size!
  fi
  # end of 'tbdefsmk.c'
fi
if test -f 'tbdefsmk.h' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'tbdefsmk.h'\"
else
  echo shar: Extracting \"'tbdefsmk.h'\" \(7998 characters\)
  sed "s/^X//" >'tbdefsmk.h' <<'END_OF_FILE'
X /* @ Copyright 1993,1994 Thomas A.J.F. Baker   Dated: January 29, 1994     */
X /* @ I retain the rights, but release this for public use as long as       */
X /* @ No one makes a profit on it or alters these four lines in any way.    */
X /* @ These four lines are not affected by running them through 'sort'.     */
X /* Add constants only, or you'll have wierd results when the #undef hits.  */
X /* Mail changes to tombaker@world.std.com . */
X /* No one is liable for the accuracy of these annotations. */
X /* Some of these should be obvious. */
X /* Try to keep this "sort"-able.  That's why these lines start w/ a space. */
X /* _ I disabled these ones, as they're standard and mess up the output.    */
X /*"__DATE__",                                                            */
X /*"__FILE__",                                                            */
X /*"__LINE__",                                                            */
X /*"__TIME__",                                                            */
X"AIX",          /* *Not* added automatically by Aix. */
X"AZTEC",        /* Tom Baker flag indicates Manx System's Aztec compiler */
X"BORLANDC",
X"EOF",          /* Usually means stdio.h got included automatically */
X"EXIT_FAILURE",
X"EXIT_SUCCESS",
X"FALSE",
X"HIGH_C",
X"HPUX",         /* *Not* added automatically by hp compiler. */
X"HYPERC",       /* Tom Baker flag - not indicating Mac compiler */
X"LANG",         /* which language to use; shouldn't show */
X"LC_CTYPE",     /* pretty much 'what size is a char'; shouldn't show */
X"MIPSEL",
X"MSDOS",            /* SCO cc */
X"M_BITFIELDS",      /* SCO cc */
X"M_COFF",           /* SCO cc */
X"M_I186",           /* SCO cc */
X"M_I286",           /* SCO cc */
X"M_I386",           /* SCO cc */
X"M_I8086",          /* SCO cc */
X"M_I86",            /* SCO cc */
X"M_I86CM",          /* SCO cc */
X"M_I86HM",          /* SCO cc */
X"M_I86LM",          /* SCO cc */
X"M_I86MM",          /* SCO cc */
X"M_I86SM",          /* SCO cc */
X"M_INTERNAT",       /* SCO cc */
X"M_LDATA",          /* SCO cc */
X"M_LTEXT",          /* SCO cc */
X"M_SDATA",          /* SCO cc */
X"M_STEXT",          /* SCO cc */
X"M_SYS3",           /* SCO cc */
X"M_SYS5",           /* SCO cc */
X"M_SYSIII",         /* SCO cc */
X"M_SYSV",           /* SCO cc */
X"M_UNIX",           /* SCO cc */
X"M_WORDSWAP",       /* SCO cc */
X"M_XENIX",          /* SCO cc */
X"M_XOUT",           /* SCO cc */
X"NEVER",        /* Tom Baker's own flag, must "never" be defined */
X"NOTDEF",
X"NULL",
X"OS2",              /* SCO cc */
X"POSIX",
X"PWB",          /* HP compiler */
X"RES",          /* Found in Sun Microsystems cpp - shows Unix "variant" */
X"RPC_CLNT",     /* Sun Microsystems, its Remote Procedure Calls compiler */
X"RPC_HDR",      /* Sun Microsystems, its Remote Procedure Calls compiler */
X"RPC_SVC",      /* Sun Microsystems, its Remote Procedure Calls compiler */
X"RPC_XDR",      /* Sun Microsystems, its Remote Procedure Calls compiler */
X"RT",           /* Found in Sun Microsystems cpp - shows Unix "variant" */
X"SCO",          /* *Not* added automatically by SCO compiler. */
X"STDC",
X"TRUE",
X"UNIX",
X"X_NOT_POSIX",          /* Not from compiler, but from MIT's X installation */
X"X_NOT_STDC_ENV",       /* Not from compiler, but from MIT's X installation */
X"_AIX",
X"_ALL_SOURCE",      /* AIX compilers */
X"_ANSI_C_SOURCE",   /* AIX compilers - ANSI compatibility */
X"_D_NAME_MAX",      /* This should be in an #include file and not show up.  */
X"_HPUX_SOURCE", /* HP compiler */
X"_KR",
X"_MSC_VER",
X"_M_BITFIELDS",     /* SCO cc */
X"_M_COFF",          /* SCO cc */
X"_M_I186",          /* SCO cc */
X"_M_I286",          /* SCO cc */
X"_M_I386",          /* SCO cc */
X"_M_I8086",         /* SCO cc */
X"_M_I86",           /* SCO cc */
X"_M_I86CM",         /* SCO cc */
X"_M_I86HM",         /* SCO cc */
X"_M_I86LM",         /* SCO cc */
X"_M_I86MM",         /* SCO cc */
X"_M_I86SM",         /* SCO cc */
X"_M_INTERNAT",      /* SCO cc */
X"_M_LDATA",         /* SCO cc */
X"_M_LTEXT",         /* SCO cc */
X"_M_SDATA",         /* SCO cc */
X"_M_STEXT",         /* SCO cc */
X"_M_SYS3",          /* SCO cc */
X"_M_SYS5",          /* SCO cc */
X"_M_SYSIII",        /* SCO cc */
X"_M_SYSV",          /* SCO cc */
X"_M_UNIX",          /* SCO cc */
X"_M_WORDSWAP",      /* SCO cc */
X"_M_XENIX",         /* SCO cc */
X"_PA_RISC1_0",  /* HP compiler */
X"_PA_RISC1_1",  /* HP compiler */
X"_POSIX_SOURCE",    /* SCO cc, AIX XLC, HP, among others */
X"_PWB",         /* HP compiler */
X"_SIO",         /* HP compiler */
X"_STRICT_NAMES",    /* SCO cc */
X"_SVID",            /* SCO cc */
X"_WSIO",        /* HP compiler */
X"_XOPEN_SOURCE",    /* SCO cc, AIX XLC, HP, among others */
X"__AIX",
X"__AIX__",
X"__ANSI__",  /* Sometimes *can't* be #undef'd, as in AIX C89. Cf __STDC__. */
X"__BCPLUSPLUS__",       /* Borland Corporation */
X"__BORLANDCPP__",       /* Borland Corporation - preprocessor w/o compile*/
X"__BORLANDC__",         /* Borland Corporation */
X"__EXTENDED__", /* AIX extensions to ansi */
X"__GNUC__",     /* GNU C's gcc */
X"__MATH__",     /* AIX enables optimized math functions - see manual */
X"__MSDOS__",
X"__POSIX__",
X"__SAA_L2__",   /* AIX "system architecture" */
X"__SAA__",      /* AIX "system architecture" */
X"__STDC__",     /* Defined by K&R; they also say can't be #undef'd */
X"__STRICT_ANSI__",      /* GNU C's gcc, with -ansi option */
X"__STR__",      /* AIX enables optimized string functions - see manual */
X"__TCPLUSPLUS__",
X"__TIMESTAMP__",    /* Defined by AIX XLC - when file was last modified */
X"__TURBOC__",
X"__aix",
X"__cplusplus",
X"__hp9000s300", /* HP compiler - shows hardware */
X"__hp9000s700", /* HP compiler - shows hardware (Supplied by cc, not cpp!) */
X"__hp9000s800", /* HP compiler - shows hardware */
X"__hppa",       /* HP compiler */
X"__hpux",       /* HP compiler */
X"__i386",           /* SCO cc */
X"__lint",       /* HP Lint provides this. */
X"__unix",           /* SCO&HP cc, among others */
X"__unix__",     /* GNU C's gcc */
X"__vax__",      /* GNU C's gcc */
X"_aix",
X"aix",
X"bsd4_2",
X"false",
X"gcos",         /* Found in Sun Microsystems cpp - shows OS */
X"host_mips",
X"hp9000ipc",    /* HP compiler */
X"hp9000s200",   /* HP compiler - shows hardware */
X"hp9000s300",   /* HP compiler - shows hardware */
X"hp9000s500",   /* HP compiler - shows hardware */
X"hp9000s700",   /* HP compiler - shows hardware (Supplied by cc, not cpp!) */
X"hp9000s800",   /* HP compiler - shows hardware */
X"hppa",         /* HP compiler */
X"hpux",         /* HP compiler */
X"i386",         /* Found in SCO cc and Sun cpp   - shows hardware */
X"iAPX286",      /* Found in Sun Microsystems cpp - shows hardware */
X"ibm",          /* Found in Sun Microsystems cpp - shows OS */
X"interdata",    /* Found in Sun Microsystems cpp - shows hardware */
X"lint",         /* Predefined by the lint utility */
X"mc68000",      /* Can indicate 68000 itself, or whole 68000 chip family */
X"mc68010",      /* Can indicate 68010 in place of 68000 */
X"mc68020",      /* Can indicate 68020 in place of 68000 */
X"mips",
X"notdef",
X"ns32000",      /* Found in Sun Microsystems cpp - shows hardware */
X"os",           /* Found in Sun Microsystems cpp - shows OS=OS/2 */
X"pdp11",        /* Found in Sun Microsystems cpp - shows hardware */
X"posix",
X"sparc",        /* Found in Sun Microsystems cpp - shows hardware */
X"sun",          /* Found in Sun Microsystems cpp - shows hardware */
X"true",
X"tss",          /* Found in Sun Microsystems cpp - shows OS */
X"u370",         /* Found in Sun Microsystems cpp - shows hardware */
X"u3b",          /* Found in Sun Microsystems cpp - shows hardware */
X"u3b15",        /* Found in Sun Microsystems cpp - shows hardware */
X"u3b2",         /* Found in Sun Microsystems cpp - shows hardware */
X"u3b20d",       /* Found in Sun Microsystems cpp - shows hardware */
X"u3b5",         /* Found in Sun Microsystems cpp - shows hardware */
X"ultrix",
X"unix",         /* SCO cc and Sun cpp, HP, etc.  - shows cpp */
X"vax",          /* Found in Sun Microsystems cpp - shows hardware */
END_OF_FILE
  if test 7998 -ne `wc -c <'tbdefsmk.h'`; then
    echo shar: \"'tbdefsmk.h'\" unpacked with wrong size!
  fi
  # end of 'tbdefsmk.h'
fi
echo shar: End of archive 1 \(of 1\).
cp /dev/null ark1isdone
MISSING=""
for I in 1 ; do
    if test ! -f ark${I}isdone ; then
 MISSING="${MISSING} ${I}"
    fi
done
if test "${MISSING}" = "" ; then
    echo You have the archive.
    rm -f ark[1-9]isdone
else
    echo You still must unpack the following archives:
    echo "        " ${MISSING}
fi
exit 0
exit 0 # Just in case...


Google Home - Advertise with Us - Business Solutions - Services & Tools - Jobs, Press, & Help

©2003 Google