android_system_core/logcat/include/log/getopt.h
Mark Salyzyn e9ade17418 liblogcat: introduce getopt_long_r
Resolve one of the threading issues by creating a private C++ified
copy of getopt_long_r that started out its life as the bionic
getopt_long, but is reentrant.  Adds a new state context for the
stderr stream called optstderr.  Utilize this new function in logcat.
Control opterr and optstderr to match liblogcat expectations.  Correct
and fortify const.

Alternative would be to lock around _all_ getopt callers.  This has
the advantage of requiring _no_ locks that could get in the way of
using liblogcat in a signal handler.  The log reader interface does
run the risk of incurring locks and heap allocations though, so there
is more work to be done for that final goal.

Test: gTest logcat-unit-tests
Bug: 35326290
Change-Id: Ibb1b374c55d357d5d7fa5ad00bfaf07ae0bc4ba5
2017-03-06 08:40:16 -08:00

67 lines
1.8 KiB
C

/*
* Copyright (C) 2017 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef _LOG_GETOPT_H_
#define _LOG_GETOPT_H_
#ifndef __ANDROID_USE_LIBLOG_LOGCAT_INTERFACE
#ifndef __ANDROID_API__
#define __ANDROID_USE_LIBLOG_LOGCAT_INTERFACE 1
#elif __ANDROID_API__ > 24 /* > Nougat */
#define __ANDROID_USE_LIBLOG_LOGCAT_INTERFACE 1
#else
#define __ANDROID_USE_LIBLOG_LOGCAT_INTERFACE 0
#endif
#endif
#if __ANDROID_USE_LIBLOG_LOGCAT_INTERFACE
#include <getopt.h>
#include <sys/cdefs.h>
struct getopt_context {
int opterr;
int optind;
int optopt;
int optreset;
const char* optarg;
FILE* optstderr; /* NULL defaults to stderr */
/* private */
const char* place;
int nonopt_start;
int nonopt_end;
int dash_prefix;
/* expansion space */
int __extra__;
void* __stuff__;
};
#define EMSG ""
#define NO_PREFIX (-1)
#define INIT_GETOPT_CONTEXT(context) \
context = { 1, 1, '?', 0, NULL, NULL, EMSG, -1, -1, NO_PREFIX, 0, NULL }
__BEGIN_DECLS
int getopt_long_r(int nargc, char* const* nargv, const char* options,
const struct option* long_options, int* idx,
struct getopt_context* context);
__END_DECLS
#endif /* __ANDROID_USE_LIBLOG_LOGCAT_INTERFACE */
#endif /* !_LOG_GETOPT_H_ */