============================================================================== The LLVM Project is under the Apache License v2.0 with LLVM Exceptions: ============================================================================== Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 1. Definitions. "License" shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document. "Licensor" shall mean the copyright owner or entity authorized by the copyright owner that is granting the License. "Legal Entity" shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control with that entity. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity. "You" (or "Your") shall mean an individual or Legal Entity exercising permissions granted by this License. "Source" form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and configuration files. "Object" form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types. "Work" shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work (an example is provided in the Appendix below). "Derivative Works" shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof. "Contribution" shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to the Licensor or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as "Not a Contribution." "Contributor" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work. 2. Grant of Copyright License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form. 3. Grant of Patent License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is filed. 4. Redistribution. You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form, provided that You meet the following conditions: (a) You must give any other recipients of the Work or Derivative Works a copy of this License; and (b) You must cause any modified files to carry prominent notices stating that You changed the files; and (c) You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and (d) If the Work includes a "NOTICE" text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License. You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License. 5. Submission of Contributions. Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions. 6. Trademarks. This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the NOTICE file. 7. Disclaimer of Warranty. Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License. 8. Limitation of Liability. In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages. 9. Accepting Warranty or Additional Liability. While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability. END OF TERMS AND CONDITIONS APPENDIX: How to apply the Apache License to your work. To apply the Apache License to your work, attach the following boilerplate notice, with the fields enclosed by brackets "[]" replaced with your own identifying information. (Don't include the brackets!) The text should be enclosed in the appropriate comment syntax for the file format. We also recommend that a file or class name and description of purpose be included on the same "printed page" as the copyright notice for easier identification within third-party archives. Copyright [yyyy] [name of copyright owner] 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. ---- LLVM Exceptions to the Apache 2.0 License ---- As an exception, if, as a result of your compiling your source code, portions of this Software are embedded into an Object form of such source code, you may redistribute such embedded portions in such Object form without complying with the conditions of Sections 4(a), 4(b) and 4(d) of the License. In addition, if you combine or link compiled forms of this Software with software that is licensed under the GPLv2 ("Combined Software") and if a court of competent jurisdiction determines that the patent provision (Section 3), the indemnity provision (Section 9) or other Section of the License conflicts with the conditions of the GPLv2, you may retroactively and prospectively choose to deem waived or otherwise exclude such Section(s) of the License, but only in their entirety and only with respect to the Combined Software. ============================================================================== Software from third parties included in the LLVM Project: ============================================================================== The LLVM Project contains third party software which is under different license terms. All such code will be identified clearly using at least one of two mechanisms: 1) It will be in a separate directory tree with its own `LICENSE.txt` or `LICENSE` file at the top containing the specific license and restrictions which apply to that software, or 2) It will contain specific license and restriction terms at the top of every file. ============================================================================== Legacy LLVM License (https://llvm.org/docs/DeveloperPolicy.html#legacy): ============================================================================== The compiler_rt library is dual licensed under both the University of Illinois "BSD-Like" license and the MIT license. As a user of this code you may choose to use it under either license. As a contributor, you agree to allow your code to be used under both. Full text of the relevant licenses is included below. ============================================================================== University of Illinois/NCSA Open Source License Copyright (c) 2009-2019 by the contributors listed in CREDITS.TXT All rights reserved. Developed by: LLVM Team University of Illinois at Urbana-Champaign http://llvm.org Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal with the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimers. * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimers in the documentation and/or other materials provided with the distribution. * Neither the names of the LLVM Team, University of Illinois at Urbana-Champaign, nor the names of its contributors may be used to endorse or promote products derived from this Software without specific prior written permission. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE CONTRIBUTORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS WITH THE SOFTWARE. ============================================================================== Copyright (c) 2009-2015 by the contributors listed in CREDITS.TXT Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. __multi3 ============================================================================== LLVM Release License ============================================================================== University of Illinois/NCSA Open Source License Copyright (c) 2003-2012 University of Illinois at Urbana-Champaign. All rights reserved. Developed by: LLVM Team University of Illinois at Urbana-Champaign http://llvm.org Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal with the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimers. * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimers in the documentation and/or other materials provided with the distribution. * Neither the names of the LLVM Team, University of Illinois at Urbana-Champaign, nor the names of its contributors may be used to endorse or promote products derived from this Software without specific prior written permission. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE CONTRIBUTORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS WITH THE SOFTWARE. __popcountdi2 and __ctzdi2 implementation /* * CDDL HEADER START * * The contents of this file are subject to the terms of the * Common Development and Distribution License (the "License"). * You may not use this file except in compliance with the License. * * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE * or http://www.opensolaris.org/os/licensing. * See the License for the specific language governing permissions * and limitations under the License. * * When distributing Covered Code, include this CDDL HEADER in each * file and include the License file at usr/src/OPENSOLARIS.LICENSE. * If applicable, add the following below this CDDL HEADER, with the * fields enclosed by brackets "[]" replaced with your own identifying * information: Portions Copyright [yyyy] [name of copyright owner] * * CDDL HEADER END */ /* * Copyright 2008 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ /* * Copyright (c) 1983, 1984, 1985, 1986, 1987, 1988, 1989 AT&T * All Rights Reserved * * Portions of this source code were derived from Berkeley * 4.3 BSD under license from the regents of the University of * California. */ #ifndef _KMDB #include "lint.h" #endif /* !_KMDB */ #include #include #include int bcmp(const void *s1, const void *s2, size_t len) { return (memcmp(s1, s2, len) == 0 ? 0 : 1); } /* * CDDL HEADER START * * The contents of this file are subject to the terms of the * Common Development and Distribution License (the "License"). * You may not use this file except in compliance with the License. * * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE * or http://www.opensolaris.org/os/licensing. * See the License for the specific language governing permissions * and limitations under the License. * * When distributing Covered Code, include this CDDL HEADER in each * file and include the License file at usr/src/OPENSOLARIS.LICENSE. * If applicable, add the following below this CDDL HEADER, with the * fields enclosed by brackets "[]" replaced with your own identifying * information: Portions Copyright [yyyy] [name of copyright owner] * * CDDL HEADER END */ /* * Copyright 2008 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ /* * Copyright (c) 1983, 1984, 1985, 1986, 1987, 1988, 1989 AT&T * All Rights Reserved * * Portions of this source code were derived from Berkeley * 4.3 BSD under license from the regents of the University of * California. */ #if !defined(_KMDB) && !defined(_BOOT) #include "lint.h" #endif /* !_KMDB && !_BOOT */ #include #include #include /* * Copy s1 to s2, always copy n bytes. * For overlapped copies it does the right thing. */ void bcopy(const void *s1, void *s2, size_t len) { (void) memmove(s2, s1, len); } /* * CDDL HEADER START * * The contents of this file are subject to the terms of the * Common Development and Distribution License (the "License"). * You may not use this file except in compliance with the License. * * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE * or http://www.opensolaris.org/os/licensing. * See the License for the specific language governing permissions * and limitations under the License. * * When distributing Covered Code, include this CDDL HEADER in each * file and include the License file at usr/src/OPENSOLARIS.LICENSE. * If applicable, add the following below this CDDL HEADER, with the * fields enclosed by brackets "[]" replaced with your own identifying * information: Portions Copyright [yyyy] [name of copyright owner] * * CDDL HEADER END */ /* * Copyright 2008 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ /* Copyright (c) 1988 AT&T */ /* All Rights Reserved */ /* * Binary search algorithm, generalized from Knuth (6.2.1) Algorithm B. */ #if !defined(_BOOT) && !defined(_KMDB) #include "lint.h" #endif /* !_BOOT && !_KMDB */ #include #include #include void * bsearch(const void *ky, /* Key to be located */ const void *bs, /* Beginning of table */ size_t nel, /* Number of elements in the table */ size_t width, /* Width of an element (bytes) */ int (*compar)(const void *, const void *)) /* Comparison function */ { char *base; size_t two_width; char *last; /* Last element in table */ if (nel == 0) return (NULL); base = (char *)bs; two_width = width + width; last = base + width * (nel - 1); while (last >= base) { char *p = base + width * ((last - base)/two_width); int res = (*compar)(ky, (void *)p); if (res == 0) return (p); /* Key found */ if (res < 0) last = p - width; else base = p + width; } return (NULL); /* Key not found */ } /* * CDDL HEADER START * * The contents of this file are subject to the terms of the * Common Development and Distribution License (the "License"). * You may not use this file except in compliance with the License. * * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE * or http://www.opensolaris.org/os/licensing. * See the License for the specific language governing permissions * and limitations under the License. * * When distributing Covered Code, include this CDDL HEADER in each * file and include the License file at usr/src/OPENSOLARIS.LICENSE. * If applicable, add the following below this CDDL HEADER, with the * fields enclosed by brackets "[]" replaced with your own identifying * information: Portions Copyright [yyyy] [name of copyright owner] * * CDDL HEADER END */ /* * Copyright 2008 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ /* * Copyright (c) 1983, 1984, 1985, 1986, 1987, 1988, 1989 AT&T * All Rights Reserved * * Portions of this source code were derived from Berkeley * 4.3 BSD under license from the regents of the University of * California. */ #if !defined(_KMDB) && !defined(_BOOT) #include "lint.h" #endif /* !_KMDB && !_BOOT */ #include #include #include /* * Set an array of n chars starting at sp to zero. */ void bzero(void *sp, size_t len) { (void) memset(sp, 0, len); } /* * University of Illinois/NCSA Open Source License * * Copyright (c) 2003-2012 University of Illinois at Urbana-Champaign. * All rights reserved. * * Developed by: * * LLVM Team * * University of Illinois at Urbana-Champaign * * http://llvm.org * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * with the Software without restriction, including without limitation the * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or * sell copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * * Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimers. * * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimers in the * documentation and/or other materials provided with the distribution. * * * Neither the names of the LLVM Team, University of Illinois at * Urbana-Champaign, nor the names of its contributors may be used to * endorse or promote products derived from this Software without specific * prior written permission. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * CONTRIBUTORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS WITH * THE SOFTWARE. */ /* * C compiler runtime logic for __ctzdi2() related builtins taken from LLVM. */ #include #include typedef union { long long all; struct { #ifdef _LITTLE_ENDIAN unsigned low; int high; #else int high; unsigned low; #endif /* _LITTLE_ENDIAN */ } s; } dwords; int __ctzdi2(unsigned long long val) { dwords x; x.all = val; const int f = -(x.s.low == 0); return (__builtin_ctz((x.s.high & f) | (x.s.low & ~f)) + (f & ((int)(sizeof (int) * CHAR_BIT)))); } /* $OpenBSD: explicit_bzero.c,v 1.3 2014/06/21 02:34:26 matthew Exp $ */ /* * Public domain. * Written by Matthew Dempsky. */ #include #pragma weak __explicit_bzero_hook void __explicit_bzero_hook(void *buf __unused, size_t len __unused) { } void explicit_bzero(void *buf, size_t len) { (void) memset(buf, 0, len); __explicit_bzero_hook(buf, len); } /* * CDDL HEADER START * * The contents of this file are subject to the terms of the * Common Development and Distribution License (the "License"). * You may not use this file except in compliance with the License. * * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE * or http://www.opensolaris.org/os/licensing. * See the License for the specific language governing permissions * and limitations under the License. * * When distributing Covered Code, include this CDDL HEADER in each * file and include the License file at usr/src/OPENSOLARIS.LICENSE. * If applicable, add the following below this CDDL HEADER, with the * fields enclosed by brackets "[]" replaced with your own identifying * information: Portions Copyright [yyyy] [name of copyright owner] * * CDDL HEADER END */ /* * Copyright 2008 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ /* * Common implementation of ffs for kernel, mdb, and libc. Note that mdb * renames ffs into mdb_ffs to avoid user-space clashes with the signature of * ffs(3C). */ #if defined(_KERNEL) || defined(ffs) #include #define arg_t uintmax_t #else #define arg_t int #include "lint.h" #endif int ffs(arg_t bits) { int i; if (bits == 0) return (0); for (i = 1; ; i++, bits >>= 1) { if (bits & 1) break; } return (i); } /* * CDDL HEADER START * * The contents of this file are subject to the terms of the * Common Development and Distribution License, Version 1.0 only * (the "License"). You may not use this file except in compliance * with the License. * * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE * or http://www.opensolaris.org/os/licensing. * See the License for the specific language governing permissions * and limitations under the License. * * When distributing Covered Code, include this CDDL HEADER in each * file and include the License file at usr/src/OPENSOLARIS.LICENSE. * If applicable, add the following below this CDDL HEADER, with the * fields enclosed by brackets "[]" replaced with your own identifying * information: Portions Copyright [yyyy] [name of copyright owner] * * CDDL HEADER END */ /* * Copyright 1992-1996,2003 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ /* Copyright (c) 1988 AT&T */ /* All Rights Reserved */ /* * This file contains getoptstr(), which is getopt() for strings of arguments * (not arrays of strings). It is used by the bootloader ({*fs,inet}boot) and * the kernel to process argument strings. */ #include "getoptstr.h" #include /* * This routine needs to be supplied by whatever uses this file. */ char *strchr(const char *s, int c); #define ISNTWORDCH(c) ((c) == '\0' || ISSPACE(c)) /* * Prepare a gos_params structure for use by getoptstr(). */ void getoptstr_init(struct gos_params *params) { params->gos_pos = 1; } /* * Modeled after lib/libc/port/gen/getopt.c. * * With params->gos_opts set to a string of options and params->gos_strp set to * an argument string, getoptstr returns * * the next option letter, where the options are given by the * params->gos_opts string. If the option is followed by a ':' in gos_opts, * then params->gos_optargp will point to the beginning of the argument in * the string, and params->gos_optarglen will contain its length. * * -1 if "--" or a non-option argument is encountered. In the former * case, params->gos_strp is advanced to the next argument. * * '?' if an illegal option is encountered or if an argument is not * supplied for an option which requires one and ':' is not the first * character of opts. In both cases, the option letter is available in * params->gos_last_opt, and in the former case, params->gos_errp will * point to the offending character. * * ':' if an argument is not supplied for an option which requires one and * ':' is the first character of params->gos_opts. */ int getoptstr(struct gos_params *params) { char c; char *cp; /* * const because we should update params. Just make sure you don't * use this after you update params->gos_strp. */ const char * const strp = params->gos_strp; if (params->gos_opts == NULL || strp == NULL) return (-1); if (params->gos_pos == 1) { /* At beginning of new word. */ if (strp[0] == '\0' || strp[0] != '-') return (-1); if (ISNTWORDCH(strp[1])) { /* Lone dash. */ return (-1); } /* Check for "--" */ if (strp[1] == '-' && ISNTWORDCH(strp[2])) { params->gos_strp = &strp[2]; SKIP_SPC(params->gos_strp); return (-1); } } params->gos_last_opt = c = strp[params->gos_pos]; if (c == ':' || (cp = strchr(params->gos_opts, c)) == NULL) { /* Unrecognized option error. */ params->gos_errp = &strp[params->gos_pos]; ++params->gos_pos; if (ISNTWORDCH(strp[params->gos_pos])) { params->gos_strp = &strp[params->gos_pos]; SKIP_SPC(params->gos_strp); params->gos_pos = 1; } return ('?'); } if (cp[1] == ':') { /* This option expects an argument. */ params->gos_strp = &strp[params->gos_pos + 1]; if (ISNTWORDCH(*params->gos_strp)) { /* The argument is in the next word. */ SKIP_SPC(params->gos_strp); if (*params->gos_strp == '\0') { /* Not. Missing argument. */ params->gos_pos = 1; params->gos_optargp = NULL; return (params->gos_opts[0] == ':' ? ':' : '?'); } } params->gos_optargp = params->gos_strp; /* Advance to the next word. */ SKIP_WORD(params->gos_strp); params->gos_optarglen = params->gos_strp - params->gos_optargp; SKIP_SPC(params->gos_strp); params->gos_pos = 1; } else { ++params->gos_pos; if (ISNTWORDCH(strp[params->gos_pos])) { params->gos_strp = &strp[params->gos_pos]; SKIP_SPC(params->gos_strp); params->gos_pos = 1; } params->gos_optargp = NULL; } return (c); } /* * CDDL HEADER START * * The contents of this file are subject to the terms of the * Common Development and Distribution License, Version 1.0 only * (the "License"). You may not use this file except in compliance * with the License. * * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE * or http://www.opensolaris.org/os/licensing. * See the License for the specific language governing permissions * and limitations under the License. * * When distributing Covered Code, include this CDDL HEADER in each * file and include the License file at usr/src/OPENSOLARIS.LICENSE. * If applicable, add the following below this CDDL HEADER, with the * fields enclosed by brackets "[]" replaced with your own identifying * information: Portions Copyright [yyyy] [name of copyright owner] * * CDDL HEADER END */ /* * Copyright 2003 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ #ifndef _GETOPTSTR_H #define _GETOPTSTR_H /* * Declarations for getoptstr(). */ #ifdef __cplusplus extern "C" { #endif #include /* * These macros are defined here so getoptstr() callers can handle spaces and * words consistently. */ #define ISSPACE(c) ((c) == ' ' || (c) == '\t') #define SKIP_WORD(cp) while (*cp != '\0' && !ISSPACE(*cp)) ++cp; #define SKIP_SPC(cp) while (ISSPACE(*cp)) ++cp; struct gos_params { /* To be set before use. */ const char *gos_opts; /* String of acceptable options. */ const char *gos_strp; /* String of arguments to process. */ /* Publically readable. */ char gos_last_opt; /* Last option seen. */ const char *gos_optargp; /* Option argument. */ size_t gos_optarglen; /* Length of option argument. */ const char *gos_errp; /* Location of erroneous character. */ /* Private state. */ int gos_pos; /* Current position in the current */ /* word. A la _pos in getopt(). */ }; void getoptstr_init(struct gos_params *params); int getoptstr(struct gos_params *params); #ifdef __cplusplus } #endif #endif /* _GETOPTSTR_H */ /* * CDDL HEADER START * * The contents of this file are subject to the terms of the * Common Development and Distribution License (the "License"). * You may not use this file except in compliance with the License. * * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE * or http://www.opensolaris.org/os/licensing. * See the License for the specific language governing permissions * and limitations under the License. * * When distributing Covered Code, include this CDDL HEADER in each * file and include the License file at usr/src/OPENSOLARIS.LICENSE. * If applicable, add the following below this CDDL HEADER, with the * fields enclosed by brackets "[]" replaced with your own identifying * information: Portions Copyright [yyyy] [name of copyright owner] * * CDDL HEADER END */ /* * Copyright 2007 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ #include #include #include #include #include #include #include #include #include "getresponse.h" /* defaults - C locale values for yesstr, nostr, yesexpr (LC_MESSAGES) */ #define DEFAULT_YESSTR "yes" #define DEFAULT_NOSTR "no" #define DEFAULT_YESEXPR "^[yY]" #define DEFAULT_NOEXPR "^[nN]" #define FREE_MEM \ free(yesstr); \ free(nostr); \ free(yesexpr); \ free(noexpr) #define SET_DEFAULT_STRS \ yesstr = DEFAULT_YESSTR; \ nostr = DEFAULT_NOSTR; \ yesexpr = DEFAULT_YESEXPR; \ noexpr = DEFAULT_NOEXPR; /* variables used by getresponse functions */ char *yesstr = NULL; char *nostr = NULL; /* for regcomp()/regexec() yesexpr and noexpr */ static regex_t preg_yes, preg_no; /* * This function compiles a regular expression that is used to match an * affirmative response from the user, and also assigns the strings used * in the prompts that request affirmative or negative responses. The * locale's values for YESEXPR, NOEXPR, YESSTR and NOSTR are used. * * If there are any problems using the locale's YESEXPR, NOEXPR, YESSTR or NOSTR * values, default values of YESEXPR, YESSTR and NOSTR will be used * as a fallback. The default values are the same as the C locale values. */ int init_yes(void) { int fallback = 0; char *yesexpr; char *noexpr; /* get yes expression and strings for yes/no prompts */ yesstr = strdup(nl_langinfo(YESSTR)); nostr = strdup(nl_langinfo(NOSTR)); yesexpr = strdup(nl_langinfo(YESEXPR)); noexpr = strdup(nl_langinfo(NOEXPR)); if (yesstr == NULL || nostr == NULL || yesexpr == NULL || noexpr == NULL) { FREE_MEM; errno = ENOMEM; return (-1); } /* if problem with locale strings, use default values */ if (*yesstr == '\0' || *nostr == '\0' || *yesexpr == '\0' || *noexpr == '\0') { FREE_MEM; SET_DEFAULT_STRS; fallback = 1; } /* Compile the yes and no expressions */ while (regcomp(&preg_yes, yesexpr, REG_EXTENDED | REG_NOSUB) != 0 || regcomp(&preg_no, noexpr, REG_EXTENDED | REG_NOSUB) != 0) { if (fallback == 1) { /* The fallback yesexpr failed, so exit */ errno = EINVAL; return (-1); } /* The locale's yesexpr or noexpr failed so use fallback */ FREE_MEM; SET_DEFAULT_STRS; fallback = 1; } if (fallback == 0) { free(yesexpr); free(noexpr); } return (0); } void fini_yes(void) { free(yesstr); free(nostr); yesstr = DEFAULT_YESSTR; nostr = DEFAULT_NOSTR; regfree(&preg_yes); regfree(&preg_no); } static int yes_no(int (*func)(char *)) { int i, b; char ans[LINE_MAX + 1]; /* Get user's answer */ i = 0; for (;;) { b = getchar(); if (b == '\n' || b == '\0' || b == EOF) break; if (i < LINE_MAX) ans[i] = b; i++; } if (i >= LINE_MAX) ans[LINE_MAX] = '\0'; else ans[i] = '\0'; return (func(ans)); } static int yes_no_check(char *ans, regex_t *reg1, regex_t *reg2) { if (regexec(reg1, ans, 0, NULL, 0) == 0) { if (regexec(reg2, ans, 0, NULL, 0) == 0) { /* Both Expressions Match (reg2 conservative) */ return (0); } /* Match */ return (1); } return (0); } /* * yes_check() returns 1 if the input string is matched by yesexpr and is * not matched by noexpr; otherwise yes_check() returns 0. */ int yes_check(char *ans) { return (yes_no_check(ans, &preg_yes, &preg_no)); } /* * no_check() returns 1 if the input string is matched by noexpr and is * not matched by yesexpr; otherwise no_check() returns 0. */ int no_check(char *ans) { return (yes_no_check(ans, &preg_no, &preg_yes)); } int yes(void) { return (yes_no(yes_check)); } int no(void) { return (yes_no(no_check)); } /* * CDDL HEADER START * * The contents of this file are subject to the terms of the * Common Development and Distribution License (the "License"). * You may not use this file except in compliance with the License. * * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE * or http://www.opensolaris.org/os/licensing. * See the License for the specific language governing permissions * and limitations under the License. * * When distributing Covered Code, include this CDDL HEADER in each * file and include the License file at usr/src/OPENSOLARIS.LICENSE. * If applicable, add the following below this CDDL HEADER, with the * fields enclosed by brackets "[]" replaced with your own identifying * information: Portions Copyright [yyyy] [name of copyright owner] * * CDDL HEADER END */ /* * Copyright 2007 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ #ifndef _UTIL_GETRESPONSE_H #define _UTIL_GETRESPONSE_H /* * Declarations for getresponse(). */ #ifdef __cplusplus extern "C" { #endif #define ERR_MSG_INIT_YES "Error initializing international response strings: %s" extern char *yesstr; extern char *nostr; extern int init_yes(void); extern void fini_yes(void); extern int yes(void); extern int yes_check(char *); extern int no(void); extern int no_check(char *); #ifdef __cplusplus } #endif #endif /* _UTIL_GETRESPONSE_H */ /* * CDDL HEADER START * * The contents of this file are subject to the terms of the * Common Development and Distribution License, Version 1.0 only * (the "License"). You may not use this file except in compliance * with the License. * * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE * or http://www.opensolaris.org/os/licensing. * See the License for the specific language governing permissions * and limitations under the License. * * When distributing Covered Code, include this CDDL HEADER in each * file and include the License file at usr/src/OPENSOLARIS.LICENSE. * If applicable, add the following below this CDDL HEADER, with the * fields enclosed by brackets "[]" replaced with your own identifying * information: Portions Copyright [yyyy] [name of copyright owner] * * CDDL HEADER END */ /* * Copyright 2005 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ #if !defined(lint) .ident "%Z%%M% %I% %E% SMI" .file "muldiv.s" #endif #if defined(__i386) && !defined(__amd64) /* * Helper routines for 32-bit compilers to perform 64-bit math. * These are used both by the Sun and GCC compilers. */ #include #include #if defined(__lint) #include /* ARGSUSED */ int64_t __mul64(int64_t a, int64_t b) { return (0); } #else /* __lint */ / / function __mul64(A,B:Longint):Longint; / {Overflow is not checked} / / We essentially do multiply by longhand, using base 2**32 digits. / a b parameter A / x c d parameter B / --------- / ad bd / ac bc / ----------------- / ac ad+bc bd / / We can ignore ac and top 32 bits of ad+bc: if <> 0, overflow happened. / ENTRY(__mul64) push %ebp mov %esp,%ebp pushl %esi mov 12(%ebp),%eax / A.hi (a) mull 16(%ebp) / Multiply A.hi by B.lo (produces ad) xchg %ecx,%eax / ecx = bottom half of ad. movl 8(%ebp),%eax / A.Lo (b) movl %eax,%esi / Save A.lo for later mull 16(%ebp) / Multiply A.Lo by B.LO (dx:ax = bd.) addl %edx,%ecx / cx is ad xchg %eax,%esi / esi is bd, eax = A.lo (d) mull 20(%ebp) / Multiply A.lo * B.hi (producing bc) addl %ecx,%eax / Produce ad+bc movl %esi,%edx xchg %eax,%edx popl %esi movl %ebp,%esp popl %ebp ret $16 SET_SIZE(__mul64) #endif /* __lint */ /* * C support for 64-bit modulo and division. * Hand-customized compiler output - see comments for details. */ #if defined(__lint) /* ARGSUSED */ uint64_t __udiv64(uint64_t a, uint64_t b) { return (0); } /* ARGSUSED */ uint64_t __urem64(int64_t a, int64_t b) { return (0); } /* ARGSUSED */ int64_t __div64(int64_t a, int64_t b) { return (0); } /* ARGSUSED */ int64_t __rem64(int64_t a, int64_t b) { return (0); } #else /* __lint */ / /* / * Unsigned division with remainder. / * Divide two uint64_ts, and calculate remainder. / */ / uint64_t / UDivRem(uint64_t x, uint64_t y, uint64_t * pmod) / { / /* simple cases: y is a single uint32_t */ / if (HI(y) == 0) { / uint32_t div_hi, div_rem; / uint32_t q0, q1; / / /* calculate q1 */ / if (HI(x) < LO(y)) { / /* result is a single uint32_t, use one division */ / q1 = 0; / div_hi = HI(x); / } else { / /* result is a double uint32_t, use two divisions */ / A_DIV32(HI(x), 0, LO(y), q1, div_hi); / } / / /* calculate q0 and remainder */ / A_DIV32(LO(x), div_hi, LO(y), q0, div_rem); / / /* return remainder */ / *pmod = div_rem; / / /* return result */ / return (HILO(q1, q0)); / / } else if (HI(x) < HI(y)) { / /* HI(x) < HI(y) => x < y => result is 0 */ / / /* return remainder */ / *pmod = x; / / /* return result */ / return (0); / / } else { / /* / * uint64_t by uint64_t division, resulting in a one-uint32_t / * result / */ / uint32_t y0, y1; / uint32_t x1, x0; / uint32_t q0; / uint32_t normshift; / / /* normalize by shifting x and y so MSB(y) == 1 */ / HIBIT(HI(y), normshift); /* index of highest 1 bit */ / normshift = 31 - normshift; / / if (normshift == 0) { / /* no shifting needed, and x < 2*y so q <= 1 */ / y1 = HI(y); / y0 = LO(y); / x1 = HI(x); / x0 = LO(x); / / /* if x >= y then q = 1 (note x1 >= y1) */ / if (x1 > y1 || x0 >= y0) { / q0 = 1; / /* subtract y from x to get remainder */ / A_SUB2(y0, y1, x0, x1); / } else { / q0 = 0; / } / / /* return remainder */ / *pmod = HILO(x1, x0); / / /* return result */ / return (q0); / / } else { / /* / * the last case: result is one uint32_t, but we need to / * normalize / */ / uint64_t dt; / uint32_t t0, t1, x2; / / /* normalize y */ / dt = (y << normshift); / y1 = HI(dt); / y0 = LO(dt); / / /* normalize x (we need 3 uint32_ts!!!) */ / x2 = (HI(x) >> (32 - normshift)); / dt = (x << normshift); / x1 = HI(dt); / x0 = LO(dt); / / /* estimate q0, and reduce x to a two uint32_t value */ / A_DIV32(x1, x2, y1, q0, x1); / / /* adjust q0 down if too high */ / /* / * because of the limited range of x2 we can only be / * one off / */ / A_MUL32(y0, q0, t0, t1); / if (t1 > x1 || (t1 == x1 && t0 > x0)) { / q0--; / A_SUB2(y0, y1, t0, t1); / } / /* return remainder */ / /* subtract product from x to get remainder */ / A_SUB2(t0, t1, x0, x1); / *pmod = (HILO(x1, x0) >> normshift); / / /* return result */ / return (q0); / } / } / } ENTRY(UDivRem) pushl %ebp pushl %edi pushl %esi subl $48, %esp movl 68(%esp), %edi / y, testl %edi, %edi / tmp63 movl %eax, 40(%esp) / x, x movl %edx, 44(%esp) / x, x movl %edi, %esi /, tmp62 movl %edi, %ecx / tmp62, tmp63 jne .LL2 movl %edx, %eax /, tmp68 cmpl 64(%esp), %eax / y, tmp68 jae .LL21 .LL4: movl 72(%esp), %ebp / pmod, xorl %esi, %esi / movl 40(%esp), %eax / x, q0 movl %ecx, %edi / , divl 64(%esp) / y movl %edx, (%ebp) / div_rem, xorl %edx, %edx / q0 addl %eax, %esi / q0, movl $0, 4(%ebp) adcl %edx, %edi / q0, addl $48, %esp movl %esi, %eax / , popl %esi movl %edi, %edx / , popl %edi popl %ebp ret .align 16 .LL2: movl 44(%esp), %eax / x, xorl %edx, %edx cmpl %esi, %eax / tmp62, tmp5 movl %eax, 32(%esp) / tmp5, movl %edx, 36(%esp) jae .LL6 movl 72(%esp), %esi / pmod, movl 40(%esp), %ebp / x, movl 44(%esp), %ecx / x, movl %ebp, (%esi) movl %ecx, 4(%esi) xorl %edi, %edi / xorl %esi, %esi / .LL22: addl $48, %esp movl %esi, %eax / , popl %esi movl %edi, %edx / , popl %edi popl %ebp ret .align 16 .LL21: movl %edi, %edx / tmp63, div_hi divl 64(%esp) / y movl %eax, %ecx /, q1 jmp .LL4 .align 16 .LL6: movl $31, %edi /, tmp87 bsrl %esi,%edx / tmp62, normshift subl %edx, %edi / normshift, tmp87 movl %edi, 28(%esp) / tmp87, jne .LL8 movl 32(%esp), %edx /, x1 cmpl %ecx, %edx / y1, x1 movl 64(%esp), %edi / y, y0 movl 40(%esp), %esi / x, x0 ja .LL10 xorl %ebp, %ebp / q0 cmpl %edi, %esi / y0, x0 jb .LL11 .LL10: movl $1, %ebp /, q0 subl %edi,%esi / y0, x0 sbbl %ecx,%edx / tmp63, x1 .LL11: movl %edx, %ecx / x1, x1 xorl %edx, %edx / x1 xorl %edi, %edi / x0 addl %esi, %edx / x0, x1 adcl %edi, %ecx / x0, x1 movl 72(%esp), %esi / pmod, movl %edx, (%esi) / x1, movl %ecx, 4(%esi) / x1, xorl %edi, %edi / movl %ebp, %esi / q0, jmp .LL22 .align 16 .LL8: movb 28(%esp), %cl movl 64(%esp), %esi / y, dt movl 68(%esp), %edi / y, dt shldl %esi, %edi /, dt, dt sall %cl, %esi /, dt andl $32, %ecx jne .LL23 .LL17: movl $32, %ecx /, tmp102 subl 28(%esp), %ecx /, tmp102 movl %esi, %ebp / dt, y0 movl 32(%esp), %esi shrl %cl, %esi / tmp102, movl %edi, 24(%esp) / tmp99, movb 28(%esp), %cl movl %esi, 12(%esp) /, x2 movl 44(%esp), %edi / x, dt movl 40(%esp), %esi / x, dt shldl %esi, %edi /, dt, dt sall %cl, %esi /, dt andl $32, %ecx je .LL18 movl %esi, %edi / dt, dt xorl %esi, %esi / dt .LL18: movl %edi, %ecx / dt, movl %edi, %eax / tmp2, movl %ecx, (%esp) movl 12(%esp), %edx / x2, divl 24(%esp) movl %edx, %ecx /, x1 xorl %edi, %edi movl %eax, 20(%esp) movl %ebp, %eax / y0, t0 mull 20(%esp) cmpl %ecx, %edx / x1, t1 movl %edi, 4(%esp) ja .LL14 je .LL24 .LL15: movl %ecx, %edi / x1, subl %eax,%esi / t0, x0 sbbl %edx,%edi / t1, movl %edi, %eax /, x1 movl %eax, %edx / x1, x1 xorl %eax, %eax / x1 xorl %ebp, %ebp / x0 addl %esi, %eax / x0, x1 adcl %ebp, %edx / x0, x1 movb 28(%esp), %cl shrdl %edx, %eax /, x1, x1 shrl %cl, %edx /, x1 andl $32, %ecx je .LL16 movl %edx, %eax / x1, x1 xorl %edx, %edx / x1 .LL16: movl 72(%esp), %ecx / pmod, movl 20(%esp), %esi /, xorl %edi, %edi / movl %eax, (%ecx) / x1, movl %edx, 4(%ecx) / x1, jmp .LL22 .align 16 .LL24: cmpl %esi, %eax / x0, t0 jbe .LL15 .LL14: decl 20(%esp) subl %ebp,%eax / y0, t0 sbbl 24(%esp),%edx /, t1 jmp .LL15 .LL23: movl %esi, %edi / dt, dt xorl %esi, %esi / dt jmp .LL17 SET_SIZE(UDivRem) /* * Unsigned division without remainder. */ / uint64_t / UDiv(uint64_t x, uint64_t y) / { / if (HI(y) == 0) { / /* simple cases: y is a single uint32_t */ / uint32_t div_hi, div_rem; / uint32_t q0, q1; / / /* calculate q1 */ / if (HI(x) < LO(y)) { / /* result is a single uint32_t, use one division */ / q1 = 0; / div_hi = HI(x); / } else { / /* result is a double uint32_t, use two divisions */ / A_DIV32(HI(x), 0, LO(y), q1, div_hi); / } / / /* calculate q0 and remainder */ / A_DIV32(LO(x), div_hi, LO(y), q0, div_rem); / / /* return result */ / return (HILO(q1, q0)); / / } else if (HI(x) < HI(y)) { / /* HI(x) < HI(y) => x < y => result is 0 */ / / /* return result */ / return (0); / / } else { / /* / * uint64_t by uint64_t division, resulting in a one-uint32_t / * result / */ / uint32_t y0, y1; / uint32_t x1, x0; / uint32_t q0; / unsigned normshift; / / /* normalize by shifting x and y so MSB(y) == 1 */ / HIBIT(HI(y), normshift); /* index of highest 1 bit */ / normshift = 31 - normshift; / / if (normshift == 0) { / /* no shifting needed, and x < 2*y so q <= 1 */ / y1 = HI(y); / y0 = LO(y); / x1 = HI(x); / x0 = LO(x); / / /* if x >= y then q = 1 (note x1 >= y1) */ / if (x1 > y1 || x0 >= y0) { / q0 = 1; / /* subtract y from x to get remainder */ / /* A_SUB2(y0, y1, x0, x1); */ / } else { / q0 = 0; / } / / /* return result */ / return (q0); / / } else { / /* / * the last case: result is one uint32_t, but we need to / * normalize / */ / uint64_t dt; / uint32_t t0, t1, x2; / / /* normalize y */ / dt = (y << normshift); / y1 = HI(dt); / y0 = LO(dt); / / /* normalize x (we need 3 uint32_ts!!!) */ / x2 = (HI(x) >> (32 - normshift)); / dt = (x << normshift); / x1 = HI(dt); / x0 = LO(dt); / / /* estimate q0, and reduce x to a two uint32_t value */ / A_DIV32(x1, x2, y1, q0, x1); / / /* adjust q0 down if too high */ / /* / * because of the limited range of x2 we can only be / * one off / */ / A_MUL32(y0, q0, t0, t1); / if (t1 > x1 || (t1 == x1 && t0 > x0)) { / q0--; / } / /* return result */ / return (q0); / } / } / } ENTRY(UDiv) pushl %ebp pushl %edi pushl %esi subl $40, %esp movl %edx, 36(%esp) / x, x movl 60(%esp), %edx / y, testl %edx, %edx / tmp62 movl %eax, 32(%esp) / x, x movl %edx, %ecx / tmp61, tmp62 movl %edx, %eax /, tmp61 jne .LL26 movl 36(%esp), %esi / x, cmpl 56(%esp), %esi / y, tmp67 movl %esi, %eax /, tmp67 movl %esi, %edx / tmp67, div_hi jb .LL28 movl %ecx, %edx / tmp62, div_hi divl 56(%esp) / y movl %eax, %ecx /, q1 .LL28: xorl %esi, %esi / movl %ecx, %edi / , movl 32(%esp), %eax / x, q0 xorl %ecx, %ecx / q0 divl 56(%esp) / y addl %eax, %esi / q0, adcl %ecx, %edi / q0, .LL25: addl $40, %esp movl %esi, %eax / , popl %esi movl %edi, %edx / , popl %edi popl %ebp ret .align 16 .LL26: movl 36(%esp), %esi / x, xorl %edi, %edi movl %esi, 24(%esp) / tmp1, movl %edi, 28(%esp) xorl %esi, %esi / xorl %edi, %edi / cmpl %eax, 24(%esp) / tmp61, jb .LL25 bsrl %eax,%ebp / tmp61, normshift movl $31, %eax /, tmp85 subl %ebp, %eax / normshift, normshift jne .LL32 movl 24(%esp), %eax /, x1 cmpl %ecx, %eax / tmp62, x1 movl 56(%esp), %esi / y, y0 movl 32(%esp), %edx / x, x0 ja .LL34 xorl %eax, %eax / q0 cmpl %esi, %edx / y0, x0 jb .LL35 .LL34: movl $1, %eax /, q0 .LL35: movl %eax, %esi / q0, xorl %edi, %edi / .LL45: addl $40, %esp movl %esi, %eax / , popl %esi movl %edi, %edx / , popl %edi popl %ebp ret .align 16 .LL32: movb %al, %cl movl 56(%esp), %esi / y, movl 60(%esp), %edi / y, shldl %esi, %edi sall %cl, %esi andl $32, %ecx jne .LL43 .LL40: movl $32, %ecx /, tmp96 subl %eax, %ecx / normshift, tmp96 movl %edi, %edx movl %edi, 20(%esp) /, dt movl 24(%esp), %ebp /, x2 xorl %edi, %edi shrl %cl, %ebp / tmp96, x2 movl %esi, 16(%esp) /, dt movb %al, %cl movl 32(%esp), %esi / x, dt movl %edi, 12(%esp) movl 36(%esp), %edi / x, dt shldl %esi, %edi /, dt, dt sall %cl, %esi /, dt andl $32, %ecx movl %edx, 8(%esp) je .LL41 movl %esi, %edi / dt, dt xorl %esi, %esi / dt .LL41: xorl %ecx, %ecx movl %edi, %eax / tmp1, movl %ebp, %edx / x2, divl 8(%esp) movl %edx, %ebp /, x1 movl %ecx, 4(%esp) movl %eax, %ecx /, q0 movl 16(%esp), %eax / dt, mull %ecx / q0 cmpl %ebp, %edx / x1, t1 movl %edi, (%esp) movl %esi, %edi / dt, x0 ja .LL38 je .LL44 .LL39: movl %ecx, %esi / q0, .LL46: xorl %edi, %edi / jmp .LL45 .LL44: cmpl %edi, %eax / x0, t0 jbe .LL39 .LL38: decl %ecx / q0 movl %ecx, %esi / q0, jmp .LL46 .LL43: movl %esi, %edi xorl %esi, %esi jmp .LL40 SET_SIZE(UDiv) /* * __udiv64 * * Perform division of two unsigned 64-bit quantities, returning the * quotient in %edx:%eax. __udiv64 pops the arguments on return, */ ENTRY(__udiv64) movl 4(%esp), %eax / x, x movl 8(%esp), %edx / x, x pushl 16(%esp) / y pushl 16(%esp) call UDiv addl $8, %esp ret $16 SET_SIZE(__udiv64) /* * __urem64 * * Perform division of two unsigned 64-bit quantities, returning the * remainder in %edx:%eax. __urem64 pops the arguments on return */ ENTRY(__urem64) subl $12, %esp movl %esp, %ecx /, tmp65 movl 16(%esp), %eax / x, x movl 20(%esp), %edx / x, x pushl %ecx / tmp65 pushl 32(%esp) / y pushl 32(%esp) call UDivRem movl 12(%esp), %eax / rem, rem movl 16(%esp), %edx / rem, rem addl $24, %esp ret $16 SET_SIZE(__urem64) /* * __div64 * * Perform division of two signed 64-bit quantities, returning the * quotient in %edx:%eax. __div64 pops the arguments on return. */ / int64_t / __div64(int64_t x, int64_t y) / { / int negative; / uint64_t xt, yt, r; / / if (x < 0) { / xt = -(uint64_t) x; / negative = 1; / } else { / xt = x; / negative = 0; / } / if (y < 0) { / yt = -(uint64_t) y; / negative ^= 1; / } else { / yt = y; / } / r = UDiv(xt, yt); / return (negative ? (int64_t) - r : r); / } ENTRY(__div64) pushl %ebp pushl %edi pushl %esi subl $8, %esp movl 28(%esp), %edx / x, x testl %edx, %edx / x movl 24(%esp), %eax / x, x movl 32(%esp), %esi / y, y movl 36(%esp), %edi / y, y js .LL84 xorl %ebp, %ebp / negative testl %edi, %edi / y movl %eax, (%esp) / x, xt movl %edx, 4(%esp) / x, xt movl %esi, %eax / y, yt movl %edi, %edx / y, yt js .LL85 .LL82: pushl %edx / yt pushl %eax / yt movl 8(%esp), %eax / xt, xt movl 12(%esp), %edx / xt, xt call UDiv popl %ecx testl %ebp, %ebp / negative popl %esi je .LL83 negl %eax / r adcl $0, %edx /, r negl %edx / r .LL83: addl $8, %esp popl %esi popl %edi popl %ebp ret $16 .align 16 .LL84: negl %eax / x adcl $0, %edx /, x negl %edx / x testl %edi, %edi / y movl %eax, (%esp) / x, xt movl %edx, 4(%esp) / x, xt movl $1, %ebp /, negative movl %esi, %eax / y, yt movl %edi, %edx / y, yt jns .LL82 .align 16 .LL85: negl %eax / yt adcl $0, %edx /, yt negl %edx / yt xorl $1, %ebp /, negative jmp .LL82 SET_SIZE(__div64) /* * __rem64 * * Perform division of two signed 64-bit quantities, returning the * remainder in %edx:%eax. __rem64 pops the arguments on return. */ / int64_t / __rem64(int64_t x, int64_t y) / { / uint64_t xt, yt, rem; / / if (x < 0) { / xt = -(uint64_t) x; / } else { / xt = x; / } / if (y < 0) { / yt = -(uint64_t) y; / } else { / yt = y; / } / (void) UDivRem(xt, yt, &rem); / return (x < 0 ? (int64_t) - rem : rem); / } ENTRY(__rem64) pushl %edi pushl %esi subl $20, %esp movl 36(%esp), %ecx / x, movl 32(%esp), %esi / x, movl 36(%esp), %edi / x, testl %ecx, %ecx movl 40(%esp), %eax / y, y movl 44(%esp), %edx / y, y movl %esi, (%esp) /, xt movl %edi, 4(%esp) /, xt js .LL92 testl %edx, %edx / y movl %eax, %esi / y, yt movl %edx, %edi / y, yt js .LL93 .LL90: leal 8(%esp), %eax /, tmp66 pushl %eax / tmp66 pushl %edi / yt pushl %esi / yt movl 12(%esp), %eax / xt, xt movl 16(%esp), %edx / xt, xt call UDivRem addl $12, %esp movl 36(%esp), %edi / x, testl %edi, %edi movl 8(%esp), %eax / rem, rem movl 12(%esp), %edx / rem, rem js .LL94 addl $20, %esp popl %esi popl %edi ret $16 .align 16 .LL92: negl %esi adcl $0, %edi negl %edi testl %edx, %edx / y movl %esi, (%esp) /, xt movl %edi, 4(%esp) /, xt movl %eax, %esi / y, yt movl %edx, %edi / y, yt jns .LL90 .align 16 .LL93: negl %esi / yt adcl $0, %edi /, yt negl %edi / yt jmp .LL90 .align 16 .LL94: negl %eax / rem adcl $0, %edx /, rem addl $20, %esp popl %esi negl %edx / rem popl %edi ret $16 SET_SIZE(__rem64) #endif /* __lint */ #if defined(__lint) /* * C support for 64-bit modulo and division. * GNU routines callable from C (though generated by the compiler). * Hand-customized compiler output - see comments for details. */ /*ARGSUSED*/ unsigned long long __udivdi3(unsigned long long a, unsigned long long b) { return (0); } /*ARGSUSED*/ unsigned long long __umoddi3(unsigned long long a, unsigned long long b) { return (0); } /*ARGSUSED*/ long long __divdi3(long long a, long long b) { return (0); } /*ARGSUSED*/ long long __moddi3(long long a, long long b) { return (0); } /* ARGSUSED */ int64_t __divrem64(int64_t a, int64_t b) { return (0); } /* ARGSUSED */ uint64_t __udivrem64(uint64_t a, uint64_t b) { return (0); } #else /* __lint */ /* * int32_t/int64_t division/manipulation * * Hand-customized compiler output: the non-GCC entry points depart from * the SYS V ABI by requiring their arguments to be popped, and in the * [u]divrem64 cases returning the remainder in %ecx:%esi. Note the * compiler-generated use of %edx:%eax for the first argument of * internal entry points. * * Inlines for speed: * - counting the number of leading zeros in a word * - multiplying two 32-bit numbers giving a 64-bit result * - dividing a 64-bit number by a 32-bit number, giving both quotient * and remainder * - subtracting two 64-bit results */ / #define LO(X) ((uint32_t)(X) & 0xffffffff) / #define HI(X) ((uint32_t)((X) >> 32) & 0xffffffff) / #define HILO(H, L) (((uint64_t)(H) << 32) + (L)) / / /* give index of highest bit */ / #define HIBIT(a, r) \ / asm("bsrl %1,%0": "=r"((uint32_t)(r)) : "g" (a)) / / /* multiply two uint32_ts resulting in a uint64_t */ / #define A_MUL32(a, b, lo, hi) \ / asm("mull %2" \ / : "=a"((uint32_t)(lo)), "=d"((uint32_t)(hi)) : "g" (b), "0"(a)) / / /* divide a uint64_t by a uint32_t */ / #define A_DIV32(lo, hi, b, q, r) \ / asm("divl %2" \ / : "=a"((uint32_t)(q)), "=d"((uint32_t)(r)) \ / : "g" (b), "0"((uint32_t)(lo)), "1"((uint32_t)hi)) / / /* subtract two uint64_ts (with borrow) */ / #define A_SUB2(bl, bh, al, ah) \ / asm("subl %4,%0\n\tsbbl %5,%1" \ / : "=&r"((uint32_t)(al)), "=r"((uint32_t)(ah)) \ / : "0"((uint32_t)(al)), "1"((uint32_t)(ah)), "g"((uint32_t)(bl)), \ / "g"((uint32_t)(bh))) /* * __udivdi3 * * Perform division of two unsigned 64-bit quantities, returning the * quotient in %edx:%eax. */ ENTRY(__udivdi3) movl 4(%esp), %eax / x, x movl 8(%esp), %edx / x, x pushl 16(%esp) / y pushl 16(%esp) call UDiv addl $8, %esp ret SET_SIZE(__udivdi3) /* * __umoddi3 * * Perform division of two unsigned 64-bit quantities, returning the * remainder in %edx:%eax. */ ENTRY(__umoddi3) subl $12, %esp movl %esp, %ecx /, tmp65 movl 16(%esp), %eax / x, x movl 20(%esp), %edx / x, x pushl %ecx / tmp65 pushl 32(%esp) / y pushl 32(%esp) call UDivRem movl 12(%esp), %eax / rem, rem movl 16(%esp), %edx / rem, rem addl $24, %esp ret SET_SIZE(__umoddi3) /* * __divdi3 * * Perform division of two signed 64-bit quantities, returning the * quotient in %edx:%eax. */ / int64_t / __divdi3(int64_t x, int64_t y) / { / int negative; / uint64_t xt, yt, r; / / if (x < 0) { / xt = -(uint64_t) x; / negative = 1; / } else { / xt = x; / negative = 0; / } / if (y < 0) { / yt = -(uint64_t) y; / negative ^= 1; / } else { / yt = y; / } / r = UDiv(xt, yt); / return (negative ? (int64_t) - r : r); / } ENTRY(__divdi3) pushl %ebp pushl %edi pushl %esi subl $8, %esp movl 28(%esp), %edx / x, x testl %edx, %edx / x movl 24(%esp), %eax / x, x movl 32(%esp), %esi / y, y movl 36(%esp), %edi / y, y js .LL55 xorl %ebp, %ebp / negative testl %edi, %edi / y movl %eax, (%esp) / x, xt movl %edx, 4(%esp) / x, xt movl %esi, %eax / y, yt movl %edi, %edx / y, yt js .LL56 .LL53: pushl %edx / yt pushl %eax / yt movl 8(%esp), %eax / xt, xt movl 12(%esp), %edx / xt, xt call UDiv popl %ecx testl %ebp, %ebp / negative popl %esi je .LL54 negl %eax / r adcl $0, %edx /, r negl %edx / r .LL54: addl $8, %esp popl %esi popl %edi popl %ebp ret .align 16 .LL55: negl %eax / x adcl $0, %edx /, x negl %edx / x testl %edi, %edi / y movl %eax, (%esp) / x, xt movl %edx, 4(%esp) / x, xt movl $1, %ebp /, negative movl %esi, %eax / y, yt movl %edi, %edx / y, yt jns .LL53 .align 16 .LL56: negl %eax / yt adcl $0, %edx /, yt negl %edx / yt xorl $1, %ebp /, negative jmp .LL53 SET_SIZE(__divdi3) /* * __moddi3 * * Perform division of two signed 64-bit quantities, returning the * quotient in %edx:%eax. */ / int64_t / __moddi3(int64_t x, int64_t y) / { / uint64_t xt, yt, rem; / / if (x < 0) { / xt = -(uint64_t) x; / } else { / xt = x; / } / if (y < 0) { / yt = -(uint64_t) y; / } else { / yt = y; / } / (void) UDivRem(xt, yt, &rem); / return (x < 0 ? (int64_t) - rem : rem); / } ENTRY(__moddi3) pushl %edi pushl %esi subl $20, %esp movl 36(%esp), %ecx / x, movl 32(%esp), %esi / x, movl 36(%esp), %edi / x, testl %ecx, %ecx movl 40(%esp), %eax / y, y movl 44(%esp), %edx / y, y movl %esi, (%esp) /, xt movl %edi, 4(%esp) /, xt js .LL63 testl %edx, %edx / y movl %eax, %esi / y, yt movl %edx, %edi / y, yt js .LL64 .LL61: leal 8(%esp), %eax /, tmp66 pushl %eax / tmp66 pushl %edi / yt pushl %esi / yt movl 12(%esp), %eax / xt, xt movl 16(%esp), %edx / xt, xt call UDivRem addl $12, %esp movl 36(%esp), %edi / x, testl %edi, %edi movl 8(%esp), %eax / rem, rem movl 12(%esp), %edx / rem, rem js .LL65 addl $20, %esp popl %esi popl %edi ret .align 16 .LL63: negl %esi adcl $0, %edi negl %edi testl %edx, %edx / y movl %esi, (%esp) /, xt movl %edi, 4(%esp) /, xt movl %eax, %esi / y, yt movl %edx, %edi / y, yt jns .LL61 .align 16 .LL64: negl %esi / yt adcl $0, %edi /, yt negl %edi / yt jmp .LL61 .align 16 .LL65: negl %eax / rem adcl $0, %edx /, rem addl $20, %esp popl %esi negl %edx / rem popl %edi ret SET_SIZE(__moddi3) /* * __udivrem64 * * Perform division of two unsigned 64-bit quantities, returning the * quotient in %edx:%eax, and the remainder in %ecx:%esi. __udivrem64 * pops the arguments on return. */ ENTRY(__udivrem64) subl $12, %esp movl %esp, %ecx /, tmp64 movl 16(%esp), %eax / x, x movl 20(%esp), %edx / x, x pushl %ecx / tmp64 pushl 32(%esp) / y pushl 32(%esp) call UDivRem movl 16(%esp), %ecx / rem, tmp63 movl 12(%esp), %esi / rem addl $24, %esp ret $16 SET_SIZE(__udivrem64) /* * Signed division with remainder. */ / int64_t / SDivRem(int64_t x, int64_t y, int64_t * pmod) / { / int negative; / uint64_t xt, yt, r, rem; / / if (x < 0) { / xt = -(uint64_t) x; / negative = 1; / } else { / xt = x; / negative = 0; / } / if (y < 0) { / yt = -(uint64_t) y; / negative ^= 1; / } else { / yt = y; / } / r = UDivRem(xt, yt, &rem); / *pmod = (x < 0 ? (int64_t) - rem : rem); / return (negative ? (int64_t) - r : r); / } ENTRY(SDivRem) pushl %ebp pushl %edi pushl %esi subl $24, %esp testl %edx, %edx / x movl %edx, %edi / x, x js .LL73 movl 44(%esp), %esi / y, xorl %ebp, %ebp / negative testl %esi, %esi movl %edx, 12(%esp) / x, xt movl %eax, 8(%esp) / x, xt movl 40(%esp), %edx / y, yt movl 44(%esp), %ecx / y, yt js .LL74 .LL70: leal 16(%esp), %eax /, tmp70 pushl %eax / tmp70 pushl %ecx / yt pushl %edx / yt movl 20(%esp), %eax / xt, xt movl 24(%esp), %edx / xt, xt call UDivRem movl %edx, 16(%esp) /, r movl %eax, 12(%esp) /, r addl $12, %esp testl %edi, %edi / x movl 16(%esp), %edx / rem, rem movl 20(%esp), %ecx / rem, rem js .LL75 .LL71: movl 48(%esp), %edi / pmod, pmod testl %ebp, %ebp / negative movl %edx, (%edi) / rem,* pmod movl %ecx, 4(%edi) / rem, movl (%esp), %eax / r, r movl 4(%esp), %edx / r, r je .LL72 negl %eax / r adcl $0, %edx /, r negl %edx / r .LL72: addl $24, %esp popl %esi popl %edi popl %ebp ret .align 16 .LL73: negl %eax adcl $0, %edx movl 44(%esp), %esi / y, negl %edx testl %esi, %esi movl %edx, 12(%esp) /, xt movl %eax, 8(%esp) /, xt movl $1, %ebp /, negative movl 40(%esp), %edx / y, yt movl 44(%esp), %ecx / y, yt jns .LL70 .align 16 .LL74: negl %edx / yt adcl $0, %ecx /, yt negl %ecx / yt xorl $1, %ebp /, negative jmp .LL70 .align 16 .LL75: negl %edx / rem adcl $0, %ecx /, rem negl %ecx / rem jmp .LL71 SET_SIZE(SDivRem) /* * __divrem64 * * Perform division of two signed 64-bit quantities, returning the * quotient in %edx:%eax, and the remainder in %ecx:%esi. __divrem64 * pops the arguments on return. */ ENTRY(__divrem64) subl $20, %esp movl %esp, %ecx /, tmp64 movl 24(%esp), %eax / x, x movl 28(%esp), %edx / x, x pushl %ecx / tmp64 pushl 40(%esp) / y pushl 40(%esp) call SDivRem movl 16(%esp), %ecx movl 12(%esp),%esi / rem addl $32, %esp ret $16 SET_SIZE(__divrem64) #endif /* __lint */ #endif /* defined(__i386) && !defined(__amd64) */ /* * CDDL HEADER START * * The contents of this file are subject to the terms of the * Common Development and Distribution License, Version 1.0 only * (the "License"). You may not use this file except in compliance * with the License. * * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE * or http://www.opensolaris.org/os/licensing. * See the License for the specific language governing permissions * and limitations under the License. * * When distributing Covered Code, include this CDDL HEADER in each * file and include the License file at usr/src/OPENSOLARIS.LICENSE. * If applicable, add the following below this CDDL HEADER, with the * fields enclosed by brackets "[]" replaced with your own identifying * information: Portions Copyright [yyyy] [name of copyright owner] * * CDDL HEADER END */ /* * Copyright 2005 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ #ifndef _MULDIV_H #define _MULDIV_H /* * Helper routines for Sun and GCC compilers in 32-bit mode, * doing 64-bit math. These routines should not be called directly; * they are called by code generated by the compiler. Their declarations * are here for kmdb's hdr2map and map2linktest mechanisms. */ #if !defined(__amd64) #ifdef __cplusplus extern "C" { #endif extern int64_t __mul64(int64_t a, int64_t b); extern uint64_t __udiv64(uint64_t x, uint64_t y); extern uint64_t __urem64(uint64_t x, uint64_t y); extern int64_t __div64(int64_t x, int64_t y); extern int64_t __rem64(int64_t x, int64_t y); extern uint64_t __udivdi3(uint64_t a, uint64_t b); extern uint64_t __umoddi3(uint64_t a, uint64_t b); extern int64_t __divdi3(int64_t a, int64_t b); extern int64_t __moddi3(int64_t a, int64_t b); extern uint64_t __udivrem64(uint64_t x, uint64_t y); extern int64_t __divrem64(int64_t x, int64_t y); #ifdef __cplusplus } #endif #endif /* !defined(amd64) */ #endif /* _MULDIV_H */ /* * CDDL HEADER START * * The contents of this file are subject to the terms of the * Common Development and Distribution License (the "License"). * You may not use this file except in compliance with the License. * * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE * or http://www.opensolaris.org/os/licensing. * See the License for the specific language governing permissions * and limitations under the License. * * When distributing Covered Code, include this CDDL HEADER in each * file and include the License file at usr/src/OPENSOLARIS.LICENSE. * If applicable, add the following below this CDDL HEADER, with the * fields enclosed by brackets "[]" replaced with your own identifying * information: Portions Copyright [yyyy] [name of copyright owner] * * CDDL HEADER END */ /* * Copyright 2008 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ /* Copyright (c) 1988 AT&T */ /* All Rights Reserved */ #ifndef _KMDB #pragma weak _memccpy = memccpy #include "lint.h" #endif /* !_KMDB */ #include #include #include #include /* * Copy s0 to s, stopping if character c is copied. Copy no more than n bytes. * Return a pointer to the byte after character c in the copy, * or NULL if c is not found in the first n bytes. */ void * memccpy(void *s, const void *s0, int c, size_t n) { if (n != 0) { unsigned char *s1 = s; const unsigned char *s2 = s0; do { if ((*s1++ = *s2++) == (unsigned char)c) return (s1); } while (--n != 0); } return (NULL); } /* * CDDL HEADER START * * The contents of this file are subject to the terms of the * Common Development and Distribution License, Version 1.0 only * (the "License"). You may not use this file except in compliance * with the License. * * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE * or http://www.opensolaris.org/os/licensing. * See the License for the specific language governing permissions * and limitations under the License. * * When distributing Covered Code, include this CDDL HEADER in each * file and include the License file at usr/src/OPENSOLARIS.LICENSE. * If applicable, add the following below this CDDL HEADER, with the * fields enclosed by brackets "[]" replaced with your own identifying * information: Portions Copyright [yyyy] [name of copyright owner] * * CDDL HEADER END */ /* * Copyright 2004 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ /* Copyright (c) 1988 AT&T */ /* All Rights Reserved */ #include #if defined(_KERNEL) #include #else #include #include #endif /* * Return the ptr in sptr at which the character c1 appears; * or NULL if not found in n chars; don't stop at \0. */ void * memchr(const void *sptr, int c1, size_t n) { if (n != 0) { unsigned char c = (unsigned char)c1; const unsigned char *sp = sptr; do { if (*sp++ == c) return ((void *)--sp); } while (--n != 0); } return (NULL); } /* * CDDL HEADER START * * The contents of this file are subject to the terms of the * Common Development and Distribution License (the "License"). * You may not use this file except in compliance with the License. * * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE * or http://www.opensolaris.org/os/licensing. * See the License for the specific language governing permissions * and limitations under the License. * * When distributing Covered Code, include this CDDL HEADER in each * file and include the License file at usr/src/OPENSOLARIS.LICENSE. * If applicable, add the following below this CDDL HEADER, with the * fields enclosed by brackets "[]" replaced with your own identifying * information: Portions Copyright [yyyy] [name of copyright owner] * * CDDL HEADER END */ /* * Copyright 2008 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ /* Copyright (c) 1988 AT&T */ /* All Rights Reserved */ #if !defined(_KMDB) && !defined(_BOOT) && !defined(_KERNEL) #pragma weak _memcmp = memcmp #include "lint.h" #endif /* !_KMDB && !_BOOT && !_KERNEL */ #include #if defined(_KERNEL) #include #else #include #include #endif /* * Compare n bytes: s1>s2: >0 s1==s2: 0 s1 #if defined(_KERNEL) #include #elif !defined(_BOOT) #include #include #endif #include "memcpy.h" /* * Copy s0 to s, always copy n bytes. * Return s */ void * memcpy(void *s, const void *s0, size_t n) { if (n != 0) { char *s1 = s; const char *s2 = s0; do { *s1++ = *s2++; } while (--n != 0); } return (s); } /* * CDDL HEADER START * * The contents of this file are subject to the terms of the * Common Development and Distribution License (the "License"). * You may not use this file except in compliance with the License. * * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE * or http://www.opensolaris.org/os/licensing. * See the License for the specific language governing permissions * and limitations under the License. * * When distributing Covered Code, include this CDDL HEADER in each * file and include the License file at usr/src/OPENSOLARIS.LICENSE. * If applicable, add the following below this CDDL HEADER, with the * fields enclosed by brackets "[]" replaced with your own identifying * information: Portions Copyright [yyyy] [name of copyright owner] * * CDDL HEADER END */ /* * Copyright 2007 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ #ifndef _COMMON_UTIL_MEMCPY_H #define _COMMON_UTIL_MEMCPY_H #include #ifdef __cplusplus extern "C" { #endif extern void *memcpy(void *, const void *, size_t); #ifdef __cplusplus } #endif #endif /* _COMMON_UTIL_MEMCPY_H */ /* * CDDL HEADER START * * The contents of this file are subject to the terms of the * Common Development and Distribution License (the "License"). * You may not use this file except in compliance with the License. * * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE * or http://www.opensolaris.org/os/licensing. * See the License for the specific language governing permissions * and limitations under the License. * * When distributing Covered Code, include this CDDL HEADER in each * file and include the License file at usr/src/OPENSOLARIS.LICENSE. * If applicable, add the following below this CDDL HEADER, with the * fields enclosed by brackets "[]" replaced with your own identifying * information: Portions Copyright [yyyy] [name of copyright owner] * * CDDL HEADER END */ /* * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved. */ /* * Copyright (c) 2005 Pascal Gloor * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. The name of the author may not be used to endorse or promote * products derived from this software without specific prior written * permission. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ #include /* * Find the first occurrence of the byte string s in byte string l. */ void * memmem(const void *l, size_t l_len, const void *s, size_t s_len) { char *cur, *last; const char *cl = (const char *)l; const char *cs = (const char *)s; /* we need something to compare */ if (l_len == 0 || s_len == 0) return (NULL); /* "s" must be smaller or equal to "l" */ if (l_len < s_len) return (NULL); /* special case where s_len == 1 */ if (s_len == 1) return (memchr(l, (int)*cs, l_len)); /* the last position where its possible to find "s" in "l" */ last = (char *)cl + l_len - s_len; for (cur = (char *)cl; cur <= last; cur++) if (cur[0] == cs[0] && memcmp(cur, cs, s_len) == 0) return (cur); return (NULL); } /* * CDDL HEADER START * * The contents of this file are subject to the terms of the * Common Development and Distribution License (the "License"). * You may not use this file except in compliance with the License. * * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE * or http://www.opensolaris.org/os/licensing. * See the License for the specific language governing permissions * and limitations under the License. * * When distributing Covered Code, include this CDDL HEADER in each * file and include the License file at usr/src/OPENSOLARIS.LICENSE. * If applicable, add the following below this CDDL HEADER, with the * fields enclosed by brackets "[]" replaced with your own identifying * information: Portions Copyright [yyyy] [name of copyright owner] * * CDDL HEADER END */ /* * Copyright (c) 1988, 2010, Oracle and/or its affiliates. All rights reserved. */ /* Copyright (c) 1988 AT&T */ /* All Rights Reserved */ #if !defined(_KMDB) && !defined(_KERNEL) #include "lint.h" #endif /* !_KMDB && !_KERNEL */ /* * The SunStudio compiler may generate calls to _memmove; So we * need to make sure that the correct symbol exists for these calls. */ #pragma weak _memmove = memmove #include #if defined(_KERNEL) #include #else #include #include #endif /* * Copy s0 to s, always copy n bytes. * Return s * Copying between objects that overlap will take place correctly */ void * memmove(void *s, const void *s0, size_t n) { if (n != 0) { char *s1 = s; const char *s2 = s0; if (s1 <= s2) { do { *s1++ = *s2++; } while (--n != 0); } else { s2 += n; s1 += n; do { *--s1 = *--s2; } while (--n != 0); } } return (s); } /* * CDDL HEADER START * * The contents of this file are subject to the terms of the * Common Development and Distribution License (the "License"). * You may not use this file except in compliance with the License. * * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE * or http://www.opensolaris.org/os/licensing. * See the License for the specific language governing permissions * and limitations under the License. * * When distributing Covered Code, include this CDDL HEADER in each * file and include the License file at usr/src/OPENSOLARIS.LICENSE. * If applicable, add the following below this CDDL HEADER, with the * fields enclosed by brackets "[]" replaced with your own identifying * information: Portions Copyright [yyyy] [name of copyright owner] * * CDDL HEADER END */ /* * Copyright (c) 1988, 2010, Oracle and/or its affiliates. All rights reserved. */ /* Copyright (c) 1988 AT&T */ /* All Rights Reserved */ #if !defined(_KMDB) && !defined(_BOOT) && !defined(_KERNEL) #include "lint.h" #endif /* !_KMDB && !_BOOT && !_KERNEL */ /* * The SunStudio compiler may generate calls to _memset; So we * need to make sure that the correct symbol exists for these calls. */ #pragma weak _memset = memset #include #if defined(_KERNEL) #include #elif !defined(_BOOT) #include #endif #include "string.h" /* * Set an array of n chars starting at sp to the character c. * Return sp. */ void * memset(void *sp1, int c, size_t n) { if (n != 0) { unsigned char *sp = sp1; do { *sp++ = (unsigned char)c; } while (--n != 0); } return (sp1); } /* * CDDL HEADER START * * The contents of this file are subject to the terms of the * Common Development and Distribution License (the "License"). * You may not use this file except in compliance with the License. * * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE * or http://www.opensolaris.org/os/licensing. * See the License for the specific language governing permissions * and limitations under the License. * * When distributing Covered Code, include this CDDL HEADER in each * file and include the License file at usr/src/OPENSOLARIS.LICENSE. * If applicable, add the following below this CDDL HEADER, with the * fields enclosed by brackets "[]" replaced with your own identifying * information: Portions Copyright [yyyy] [name of copyright owner] * * CDDL HEADER END */ /* * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved. */ #if defined(_BOOT) #include #else #include #endif /* * Implementations of functions described in memory(3C). * These functions match the section 3C manpages. */ /* * The SunStudio compiler may generate calls to _memmove, _memset, * and _memcpy; So we need to make sure that the correct symbols * exist for these calls. We also use _memset to work around some * standards namespacing challenges. */ #pragma weak _memmove = memmove void * memmove(void *s1, const void *s2, size_t n) { #if defined(_BOOT) bcopy(s2, s1, n); #else ovbcopy(s2, s1, n); #endif return (s1); } #pragma weak _memset = memset void * memset(void *s, int c, size_t n) { unsigned char *t; if ((unsigned char)c == '\0') bzero(s, n); else { for (t = (unsigned char *)s; n > 0; n--) *t++ = (unsigned char)c; } return (s); } int memcmp(const void *s1, const void *s2, size_t n) { const uchar_t *ps1 = s1; const uchar_t *ps2 = s2; if (s1 != s2 && n != 0) { do { if (*ps1++ != *ps2++) return (ps1[-1] - ps2[-1]); } while (--n != 0); } return (0); } #pragma weak _memcpy = memcpy void * memcpy(void *s1, const void *s2, size_t n) { bcopy(s2, s1, n); return (s1); } void * memchr(const void *sptr, int c1, size_t n) { if (n != 0) { unsigned char c = (unsigned char)c1; const unsigned char *sp = sptr; do { if (*sp++ == c) return ((void *)--sp); } while (--n != 0); } return (NULL); } /* * Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. * See https://llvm.org/LICENSE.txt for license information. * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception */ #include #define CHAR_BIT 8 typedef int di_int __attribute__((mode(DI))); typedef unsigned int du_int __attribute__((mode(DI))); typedef int ti_int __attribute__((mode(TI))); typedef union { ti_int all; struct { #if _LITTLE_ENDIAN du_int low; di_int high; #else di_int high; du_int low; #endif /* _LITTLE_ENDIAN */ } s; } twords; /* Returns: a * b */ static ti_int __mulddi3(du_int a, du_int b) { twords r; const int bits_in_dword_2 = (int)(sizeof (di_int) * CHAR_BIT) / 2; const du_int lower_mask = (du_int)~0 >> bits_in_dword_2; r.s.low = (a & lower_mask) * (b & lower_mask); du_int t = r.s.low >> bits_in_dword_2; r.s.low &= lower_mask; t += (a >> bits_in_dword_2) * (b & lower_mask); r.s.low += (t & lower_mask) << bits_in_dword_2; r.s.high = t >> bits_in_dword_2; t = r.s.low >> bits_in_dword_2; r.s.low &= lower_mask; t += (b >> bits_in_dword_2) * (a & lower_mask); r.s.low += (t & lower_mask) << bits_in_dword_2; r.s.high += t >> bits_in_dword_2; r.s.high += (a >> bits_in_dword_2) * (b >> bits_in_dword_2); return (r.all); } /* Returns: a * b */ ti_int __multi3(ti_int a, ti_int b) { twords x; x.all = a; twords y; y.all = b; twords r; r.all = __mulddi3(x.s.low, y.s.low); r.s.high += x.s.high * y.s.low + x.s.low * y.s.high; return (r.all); } /* * University of Illinois/NCSA Open Source License * * Copyright (c) 2003-2012 University of Illinois at Urbana-Champaign. * All rights reserved. * * Developed by: * * LLVM Team * * University of Illinois at Urbana-Champaign * * http://llvm.org * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * with the Software without restriction, including without limitation the * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or * sell copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * * Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimers. * * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimers in the * documentation and/or other materials provided with the distribution. * * * Neither the names of the LLVM Team, University of Illinois at * Urbana-Champaign, nor the names of its contributors may be used to * endorse or promote products derived from this Software without specific * prior written permission. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * CONTRIBUTORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS WITH * THE SOFTWARE. */ /* * C compiler runtime logic for popcount() related builtins taken from LLVM. See * also the Hacker's Delight 2nd Edition. */ int __popcountdi2(unsigned long long val) { unsigned long long x2 = (unsigned long long)val; x2 = x2 - ((x2 >> 1) & 0x5555555555555555uLL); /* Every 2 bits holds the sum of every pair of bits (32) */ x2 = ((x2 >> 2) & 0x3333333333333333uLL) + (x2 & 0x3333333333333333uLL); /* * Every 4 bits holds the sum of every 4-set of bits (3 significant * bits) (16) */ x2 = (x2 + (x2 >> 4)) & 0x0F0F0F0F0F0F0F0FuLL; /* * Every 8 bits holds the sum of every 8-set of bits (4 significant * bits) (8). */ unsigned x = (unsigned)(x2 + (x2 >> 32)); /* * The lower 32 bits hold four 16 bit sums (5 significant bits). The * upper 32 bits are garbage. */ x = x + (x >> 16); /* * The lower 16 bits hold two 32 bit sums (6 significant bits). The * upper 16 bits are garbage. Extract the 7 significant bits. */ return ((x + (x >> 8)) & 0x0000007F); } int __popcountsi2(unsigned val) { unsigned x = (unsigned)val; x = x - ((x >> 1) & 0x55555555); /* Every 2 bits holds the sum of every pair of bits */ x = ((x >> 2) & 0x33333333) + (x & 0x33333333); /* * Every 4 bits holds the sum of every 4-set of bits (3 significant * bits). */ x = (x + (x >> 4)) & 0x0F0F0F0F; /* * Every 8 bits holds the sum of every 8-set of bits (4 significant * bits). */ x = (x + (x >> 16)); /* * The lower 16 bits hold two 8 bit sums (5 significant bits). The * upper 16 bits are garbage. Extract the 6 significant bits. */ return ((x + (x >> 8)) & 0x0000003F); /* (6 significant bits) */ } /* * CDDL HEADER START * * The contents of this file are subject to the terms of the * Common Development and Distribution License (the "License"). * You may not use this file except in compliance with the License. * * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE * or http://www.opensolaris.org/os/licensing. * See the License for the specific language governing permissions * and limitations under the License. * * When distributing Covered Code, include this CDDL HEADER in each * file and include the License file at usr/src/OPENSOLARIS.LICENSE. * If applicable, add the following below this CDDL HEADER, with the * fields enclosed by brackets "[]" replaced with your own identifying * information: Portions Copyright [yyyy] [name of copyright owner] * * CDDL HEADER END */ /* * Copyright 2008 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. * Copyright 2020 Oxide Computer Company */ #if !defined(_KERNEL) && !defined(_KMDB) #include "lint.h" #endif /* !_KERNEL && !_KMDB */ #include #if !defined(_KERNEL) && !defined(_KMDB) #include #include #endif /* !_KERNEL && !_KMDB */ #include "qsort.h" static void swapp32(uint32_t *r1, uint32_t *r2, size_t cnt); static void swapp64(uint64_t *r1, uint64_t *r2, size_t cnt); static void swapi(uint32_t *r1, uint32_t *r2, size_t cnt); static void swapb(char *r1, char *r2, size_t cnt); typedef int (*cmp_f)(const void *, const void *, void *); /* * choose a median of 3 values */ static __GNU_INLINE char * med3(char *a, char *b, char *c, cmp_f cmp, void *arg) { if (cmp(a, b, arg) < 0) { if (cmp(b, c, arg) < 0) { return (b); } else if (cmp(a, c, arg) < 0) { return (c); } else { return (a); } } else { if (cmp(b, c, arg) > 0) { return (b); } else if (cmp(a, c, arg) > 0) { return (c); } else { return (a); } } } #define THRESH_L 5 /* threshold for insertion sort */ #define THRESH_M3 20 /* threshold for median of 3 */ #define THRESH_M9 50 /* threshold for median of 9 */ typedef struct { char *b_lim; size_t nrec; } stk_t; /* * qsort() is a general purpose, in-place sorting routine using a * user provided call back function for comparisons. This implementation * utilizes a ternary quicksort algorithm, and cuts over to an * insertion sort for partitions involving fewer than THRESH_L records. * * Potential User Errors * There is no return value from qsort, this function has no method * of alerting the user that a sort did not work or could not work. * We do not print an error message or exit the process or thread, * Even if we can detect an error, We CANNOT silently return without * sorting the data, if we did so the user could never be sure the * sort completed successfully. * It is possible we could change the return value of sort from void * to int and return success or some error codes, but this gets into * standards and compatibility issues. * * Examples of qsort parameter errors might be * 1) record size (rsiz) equal to 0 * qsort will loop and never return. * 2) record size (rsiz) less than 0 * rsiz is unsigned, so a negative value is insanely large * 3) number of records (nrec) is 0 * This is legal - qsort will return without examining any records * 4) number of records (nrec) is less than 0 * nrec is unsigned, so a negative value is insanely large. * 5) nrec * rsiz > memory allocation for sort array * a segment violation may occur * corruption of other memory may occur * 6) The base address of the sort array is invalid * a segment violation may occur * corruption of other memory may occur * 7) The user call back function is invalid * we may get alignment errors or segment violations * we may jump into never-never land * * Some less obvious errors might be * 8) The user compare function is not comparing correctly * 9) The user compare function modifies the data records */ static int qsort_r_wrapper(const void *a, const void *b, void *arg) { int (*cmp)(const void *, const void *) = (int(*)(const void *, const void *))(uintptr_t)arg; return (cmp(a, b)); } void qsort_r(void *basep, size_t nrec, size_t rsiz, cmp_f cmp, void *arg) { size_t i; /* temporary variable */ /* variables used by swap */ void (*swapf)(char *, char *, size_t); size_t loops; /* variables used by sort */ stk_t stack[8 * sizeof (nrec) + 1]; stk_t *sp; char *b_lim; /* bottom limit */ char *b_dup; /* bottom duplicate */ char *b_par; /* bottom partition */ char *t_lim; /* top limit */ char *t_dup; /* top duplicate */ char *t_par; /* top partition */ char *m1, *m2, *m3; /* median pointers */ uintptr_t d_bytelength; /* byte length of duplicate records */ int b_nrec; int t_nrec; int cv; /* results of compare (bottom / top) */ /* * choose a swap function based on alignment and size * * The qsort function sorts an array of fixed length records. * We have very limited knowledge about the data record itself. * It may be that the data record is in the array we are sorting * or it may be that the array contains pointers or indexes to * the actual data record and all that we are sorting is the indexes. * * The following decision will choose an optimal swap function * based on the size and alignment of the data records * swapp64 will swap 64 bit pointers * swapp32 will swap 32 bit pointers * swapi will swap an array of 32 bit integers * swapb will swap an array of 8 bit characters * * swapi and swapb will also require the variable loops to be set * to control the length of the array being swapped */ if ((((uintptr_t)basep & (sizeof (uint64_t) - 1)) == 0) && (rsiz == sizeof (uint64_t))) { loops = 1; swapf = (void (*)(char *, char *, size_t))swapp64; } else if ((((uintptr_t)basep & (sizeof (uint32_t) - 1)) == 0) && (rsiz == sizeof (uint32_t))) { loops = 1; swapf = (void (*)(char *, char *, size_t))swapp32; } else if ((((uintptr_t)basep & (sizeof (uint32_t) - 1)) == 0) && ((rsiz & (sizeof (uint32_t) - 1)) == 0)) { loops = rsiz / sizeof (int); swapf = (void (*)(char *, char *, size_t))swapi; } else { loops = rsiz; swapf = swapb; } /* * qsort is a partitioning sort * * the stack is the bookkeeping mechanism to keep track of all * the partitions. * * each sort pass takes one partition and sorts it into two partitions. * at the top of the loop we simply take the partition on the top * of the stack and sort it. See the comments at the bottom * of the loop regarding which partitions to add in what order. * * initially put the whole partition on the stack */ sp = stack; sp->b_lim = (char *)basep; sp->nrec = nrec; sp++; while (sp > stack) { sp--; b_lim = sp->b_lim; nrec = sp->nrec; /* * a linear insertion sort i faster than a qsort for * very small number of records (THRESH_L) * * if number records < threshold use linear insertion sort * * this also handles the special case where the partition * 0 or 1 records length. */ if (nrec < THRESH_L) { /* * Linear insertion sort */ t_par = b_lim; for (i = 1; i < nrec; i++) { t_par += rsiz; b_par = t_par; while (b_par > b_lim) { b_par -= rsiz; if ((*cmp)(b_par, b_par + rsiz, arg) <= 0) { break; } (*swapf)(b_par, b_par + rsiz, loops); } } /* * a linear insertion sort will put all records * in their final position and will not create * subpartitions. * * therefore when the insertion sort is complete * just go to the top of the loop and get the * next partition to sort. */ continue; } /* quicksort */ /* * choose a pivot record * * Ideally the pivot record will divide the partition * into two equal parts. however we have to balance the * work involved in selecting the pivot record with the * expected benefit. * * The choice of pivot record depends on the number of * records in the partition * * for small partitions (nrec < THRESH_M3) * we just select the record in the middle of the partition * * if (nrec >= THRESH_M3 && nrec < THRESH_M9) * we select three values and choose the median of 3 * * if (nrec >= THRESH_M9) * then we use an approximate median of 9 * 9 records are selected and grouped in 3 groups of 3 * the median of each of these 3 groups is fed into another * median of 3 decision. * * Each median of 3 decision is 2 or 3 compares, * so median of 9 costs between 8 and 12 compares. * * i is byte distance between two consecutive samples * m2 will point to the pivot record */ if (nrec < THRESH_M3) { m2 = b_lim + (nrec / 2) * rsiz; } else if (nrec < THRESH_M9) { /* use median of 3 */ i = ((nrec - 1) / 2) * rsiz; m2 = med3(b_lim, b_lim + i, b_lim + 2 * i, cmp, arg); } else { /* approx median of 9 */ i = ((nrec - 1) / 8) * rsiz; m1 = med3(b_lim, b_lim + i, b_lim + 2 * i, cmp, arg); m2 = med3(b_lim + 3 * i, b_lim + 4 * i, b_lim + 5 * i, cmp, arg); m3 = med3(b_lim + 6 * i, b_lim + 7 * i, b_lim + 8 * i, cmp, arg); m2 = med3(m1, m2, m3, cmp, arg); } /* * quick sort partitioning * * The partition limits are defined by bottom and top pointers * b_lim and t_lim. * * qsort uses a fairly standard method of moving the * partitioning pointers, b_par and t_par, to the middle of * the partition and exchanging records that are in the * wrong part of the partition. * * Two enhancements have been made to the basic algorithm. * One for handling duplicate records and one to minimize * the number of swaps. * * Two duplicate records pointers are (b_dup and t_dup) are * initially set to b_lim and t_lim. Each time a record * whose sort key value is equal to the pivot record is found * it will be swapped with the record pointed to by * b_dup or t_dup and the duplicate pointer will be * incremented toward the center. * When partitioning is complete, all the duplicate records * will have been collected at the upper and lower limits of * the partition and can easily be moved adjacent to the * pivot record. * * The second optimization is to minimize the number of swaps. * The pointer m2 points to the pivot record. * During partitioning, if m2 is ever equal to the partitioning * pointers, b_par or t_par, then b_par or t_par just moves * onto the next record without doing a compare. * If as a result of duplicate record detection, * b_dup or t_dup is ever equal to m2, * then m2 is changed to point to the duplicate record and * b_dup or t_dup is incremented with out swapping records. * * When partitioning is done, we may not have the same pivot * record that we started with, but we will have one with * an equal sort key. */ b_dup = b_par = b_lim; t_dup = t_par = t_lim = b_lim + rsiz * (nrec - 1); for (;;) { /* move bottom pointer up */ for (; b_par <= t_par; b_par += rsiz) { if (b_par == m2) { continue; } cv = cmp(b_par, m2, arg); if (cv > 0) { break; } if (cv == 0) { if (b_dup == m2) { m2 = b_par; } else if (b_dup != b_par) { (*swapf)(b_dup, b_par, loops); } b_dup += rsiz; } } /* move top pointer down */ for (; b_par < t_par; t_par -= rsiz) { if (t_par == m2) { continue; } cv = cmp(t_par, m2, arg); if (cv < 0) { break; } if (cv == 0) { if (t_dup == m2) { m2 = t_par; } else if (t_dup != t_par) { (*swapf)(t_dup, t_par, loops); } t_dup -= rsiz; } } /* break if we are done partitioning */ if (b_par >= t_par) { break; } /* exchange records at upper and lower break points */ (*swapf)(b_par, t_par, loops); b_par += rsiz; t_par -= rsiz; } /* * partitioning is now complete * * there are two termination conditions from the partitioning * loop above. Either b_par or t_par have crossed or * they are equal. * * we need to swap the pivot record to its final position * m2 could be in either the upper or lower partitions * or it could already be in its final position */ /* * R[b_par] > R[m2] * R[t_par] < R[m2] */ if (t_par < b_par) { if (m2 < t_par) { (*swapf)(m2, t_par, loops); m2 = b_par = t_par; } else if (m2 > b_par) { (*swapf)(m2, b_par, loops); m2 = t_par = b_par; } else { b_par = t_par = m2; } } else { if (m2 < t_par) { t_par = b_par = t_par - rsiz; } if (m2 != b_par) { (*swapf)(m2, b_par, loops); } m2 = t_par; } /* * move bottom duplicates next to pivot * optimized to eliminate overlap */ d_bytelength = b_dup - b_lim; if (b_par - b_dup < d_bytelength) { b_dup = b_lim + (b_par - b_dup); } while (b_dup > b_lim) { b_dup -= rsiz; b_par -= rsiz; (*swapf)(b_dup, b_par, loops); } b_par = m2 - d_bytelength; /* * move top duplicates next to pivot */ d_bytelength = t_lim - t_dup; if (t_dup - t_par < d_bytelength) { t_dup = t_lim - (t_dup - t_par); } while (t_dup < t_lim) { t_dup += rsiz; t_par += rsiz; (*swapf)(t_dup, t_par, loops); } t_par = m2 + d_bytelength; /* * when a qsort pass completes there are three partitions * 1) the lower contains all records less than pivot * 2) the upper contains all records greater than pivot * 3) the pivot partition contains all record equal to pivot * * all records in the pivot partition are in their final * position and do not need to be accounted for by the stack * * when adding partitions to the stack * it is important to add the largest partition first * to prevent stack overflow. * * calculate number of unsorted records in top and bottom * push resulting partitions on stack */ b_nrec = (b_par - b_lim) / rsiz; t_nrec = (t_lim - t_par) / rsiz; if (b_nrec < t_nrec) { sp->b_lim = t_par + rsiz; sp->nrec = t_nrec; sp++; sp->b_lim = b_lim; sp->nrec = b_nrec; sp++; } else { sp->b_lim = b_lim; sp->nrec = b_nrec; sp++; sp->b_lim = t_par + rsiz; sp->nrec = t_nrec; sp++; } } } void qsort(void *basep, size_t nrec, size_t rsiz, int (*cmp)(const void *, const void *)) { return (qsort_r(basep, nrec, rsiz, qsort_r_wrapper, (void *)(uintptr_t)cmp)); } /* * The following swap functions should not create a stack frame * the SPARC call / return instruction will be executed * but the a save / restore will not be executed * which means we won't do a window turn with the spill / fill overhead * verify this by examining the assembly code */ /* ARGSUSED */ static void swapp32(uint32_t *r1, uint32_t *r2, size_t cnt) { uint32_t temp; temp = *r1; *r1++ = *r2; *r2++ = temp; } /* ARGSUSED */ static void swapp64(uint64_t *r1, uint64_t *r2, size_t cnt) { uint64_t temp; temp = *r1; *r1++ = *r2; *r2++ = temp; } static void swapi(uint32_t *r1, uint32_t *r2, size_t cnt) { uint32_t temp; /* character by character */ while (cnt--) { temp = *r1; *r1++ = *r2; *r2++ = temp; } } static void swapb(char *r1, char *r2, size_t cnt) { char temp; /* character by character */ while (cnt--) { temp = *r1; *r1++ = *r2; *r2++ = temp; } } /* * CDDL HEADER START * * The contents of this file are subject to the terms of the * Common Development and Distribution License, Version 1.0 only * (the "License"). You may not use this file except in compliance * with the License. * * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE * or http://www.opensolaris.org/os/licensing. * See the License for the specific language governing permissions * and limitations under the License. * * When distributing Covered Code, include this CDDL HEADER in each * file and include the License file at usr/src/OPENSOLARIS.LICENSE. * If applicable, add the following below this CDDL HEADER, with the * fields enclosed by brackets "[]" replaced with your own identifying * information: Portions Copyright [yyyy] [name of copyright owner] * * CDDL HEADER END */ /* * Copyright 2003 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ #ifndef _QSORT_H #define _QSORT_H /* * Declarations for qsort(). */ #ifdef __cplusplus extern "C" { #endif #include extern void qsort(void *, size_t, size_t, int (*)(const void *, const void *)); #ifdef __cplusplus } #endif #endif /* _QSORT_H */ /* * CDDL HEADER START * * The contents of this file are subject to the terms of the * Common Development and Distribution License (the "License"). * You may not use this file except in compliance with the License. * * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE * or http://www.opensolaris.org/os/licensing. * See the License for the specific language governing permissions * and limitations under the License. * * When distributing Covered Code, include this CDDL HEADER in each * file and include the License file at usr/src/OPENSOLARIS.LICENSE. * If applicable, add the following below this CDDL HEADER, with the * fields enclosed by brackets "[]" replaced with your own identifying * information: Portions Copyright [yyyy] [name of copyright owner] * * CDDL HEADER END */ /* * Copyright (c) 1990, 1993 * The Regents of the University of California. All rights reserved. * * This code is derived from software contributed to Berkeley by * Chris Torek. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 4. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * From: Id: vfscanf.c,v 1.13 1998/09/25 12:20:27 obrien Exp * From: static char sccsid[] = "@(#)strtol.c 8.1 (Berkeley) 6/4/93"; * From: static char sccsid[] = "@(#)strtoul.c 8.1 (Berkeley) 6/4/93"; */ /* * Copyright 2007 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ #include #include #include #include #include #define BUF 32 /* Maximum length of numeric string. */ /* * Flags used during conversion. */ #define LONG 0x01 /* l: long or double */ #define SHORT 0x04 /* h: short */ #define SUPPRESS 0x08 /* suppress assignment */ #define POINTER 0x10 /* weird %p pointer (`fake hex') */ #define NOSKIP 0x20 /* do not skip blanks */ /* * The following are used in numeric conversions only: * SIGNOK, NDIGITS, DPTOK, and EXPOK are for floating point; * SIGNOK, NDIGITS, PFXOK, and NZDIGITS are for integral. */ #define SIGNOK 0x40 /* +/- is (still) legal */ #define NDIGITS 0x80 /* no digits detected */ #define DPTOK 0x100 /* (float) decimal point is still legal */ #define EXPOK 0x200 /* (float) exponent (e+3, etc) still legal */ #define PFXOK 0x100 /* 0x prefix is (still) legal */ #define NZDIGITS 0x200 /* no zero digits detected */ /* * Conversion types. */ #define CT_CHAR 0 /* %c conversion */ #define CT_CCL 1 /* %[...] conversion */ #define CT_STRING 2 /* %s conversion */ #define CT_INT 3 /* integer, i.e., strtoq or strtouq */ static const uchar_t *set_ccl(char *, const uchar_t *); #define isspace(ch) (((ch) == ' ') || ((ch) == '\r') || ((ch) == '\n') || \ ((ch) == '\t') || ((ch) == '\f')) int vsscanf(const char *inp, char const *fmt0, va_list ap) { int inr; const uchar_t *fmt = (const uchar_t *)fmt0; int c; /* character from format, or conversion */ size_t width; /* field width, or 0 */ char *p; /* points into all kinds of strings */ int n; /* handy integer */ int flags; /* flags as defined above */ char *p0; /* saves original value of p when necessary */ int nassigned; /* number of fields assigned */ int nconversions; /* number of conversions */ int nread; /* number of characters consumed from fp */ int base; /* base argument to strtoq/strtouq */ int sconv; /* do signed conversion */ char ccltab[256]; /* character class table for %[...] */ char buf[BUF]; /* buffer for numeric conversions */ /* `basefix' is used to avoid `if' tests in the integer scanner */ static short basefix[17] = { 10, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16 }; inr = strlen(inp); sconv = 0; nassigned = 0; nconversions = 0; nread = 0; base = 0; for (;;) { c = *fmt++; if (c == 0) return (nassigned); if (isspace(c)) { while (inr > 0 && isspace(*inp)) nread++, inr--, inp++; continue; } if (c != '%') goto literal; width = 0; flags = 0; /* * switch on the format. continue if done; * break once format type is derived. */ again: c = *fmt++; switch (c) { case '%': literal: if (inr <= 0) goto input_failure; if (*inp != c) goto match_failure; inr--, inp++; nread++; continue; case '*': flags |= SUPPRESS; goto again; case 'l': flags |= LONG; goto again; case 'h': flags |= SHORT; goto again; case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': width = width * 10 + c - '0'; goto again; /* * Conversions. * */ case 'd': c = CT_INT; sconv = 1; base = 10; break; case 'i': c = CT_INT; sconv = 1; base = 0; break; case 'o': c = CT_INT; base = 8; break; case 'u': c = CT_INT; base = 10; break; case 'x': flags |= PFXOK; /* enable 0x prefixing */ c = CT_INT; base = 16; break; case 's': c = CT_STRING; break; case '[': fmt = set_ccl(ccltab, fmt); flags |= NOSKIP; c = CT_CCL; break; case 'c': flags |= NOSKIP; c = CT_CHAR; break; case 'p': /* pointer format is like hex */ flags |= POINTER | PFXOK; c = CT_INT; base = 16; break; case 'n': nconversions++; if (flags & SUPPRESS) /* ??? */ continue; if (flags & SHORT) *va_arg(ap, short *) = (short)nread; else if (flags & LONG) *va_arg(ap, long *) = (long)nread; else *va_arg(ap, int *) = nread; continue; } /* * We have a conversion that requires input. */ if (inr <= 0) goto input_failure; /* * Consume leading white space, except for formats * that suppress this. */ if ((flags & NOSKIP) == 0) { while (isspace(*inp)) { nread++; if (--inr > 0) inp++; else goto input_failure; } /* * Note that there is at least one character in * the buffer, so conversions that do not set NOSKIP * can no longer result in an input failure. */ } /* * Do the conversion. */ switch (c) { case CT_CHAR: /* scan arbitrary characters (sets NOSKIP) */ if (width == 0) width = 1; if (flags & SUPPRESS) { size_t sum = 0; if ((n = inr) < width) { sum += n; width -= n; inp += n; if (sum == 0) goto input_failure; } else { sum += width; inr -= width; inp += width; } nread += sum; } else { bcopy(inp, va_arg(ap, char *), width); inr -= width; inp += width; nread += width; nassigned++; } nconversions++; break; case CT_CCL: /* scan a (nonempty) character class (sets NOSKIP) */ if (width == 0) width = (size_t)~0; /* `infinity' */ /* take only those things in the class */ if (flags & SUPPRESS) { n = 0; while (ccltab[(unsigned char)*inp]) { n++, inr--, inp++; if (--width == 0) break; if (inr <= 0) { if (n == 0) goto input_failure; break; } } if (n == 0) goto match_failure; } else { p0 = p = va_arg(ap, char *); while (ccltab[(unsigned char)*inp]) { inr--; *p++ = *inp++; if (--width == 0) break; if (inr <= 0) { if (p == p0) goto input_failure; break; } } n = p - p0; if (n == 0) goto match_failure; *p = 0; nassigned++; } nread += n; nconversions++; break; case CT_STRING: /* like CCL, but zero-length string OK, & no NOSKIP */ if (width == 0) width = (size_t)~0; if (flags & SUPPRESS) { n = 0; while (!isspace(*inp)) { n++, inr--, inp++; if (--width == 0) break; if (inr <= 0) break; } nread += n; } else { p0 = p = va_arg(ap, char *); while (!isspace(*inp)) { inr--; *p++ = *inp++; if (--width == 0) break; if (inr <= 0) break; } *p = 0; nread += p - p0; nassigned++; } nconversions++; continue; case CT_INT: /* scan an integer as if by strtoq/strtouq */ /* size_t is unsigned, hence this optimisation */ if (--width > sizeof (buf) - 2) width = sizeof (buf) - 2; width++; flags |= SIGNOK | NDIGITS | NZDIGITS; for (p = buf; width; width--) { c = *inp; /* * Switch on the character; `goto ok' * if we accept it as a part of number. */ switch (c) { /* * The digit 0 is always legal, but is * special. For %i conversions, if no * digits (zero or nonzero) have been * scanned (only signs), we will have * base==0. In that case, we should set * it to 8 and enable 0x prefixing. * Also, if we have not scanned zero digits * before this, do not turn off prefixing * (someone else will turn it off if we * have scanned any nonzero digits). */ case '0': if (base == 0) { base = 8; flags |= PFXOK; } if (flags & NZDIGITS) flags &= ~(SIGNOK|NZDIGITS|NDIGITS); else flags &= ~(SIGNOK|PFXOK|NDIGITS); goto ok; /* 1 through 7 always legal */ case '1': case '2': case '3': case '4': case '5': case '6': case '7': base = basefix[base]; flags &= ~(SIGNOK | PFXOK | NDIGITS); goto ok; /* digits 8 and 9 ok iff decimal or hex */ case '8': case '9': base = basefix[base]; if (base <= 8) break; /* not legal here */ flags &= ~(SIGNOK | PFXOK | NDIGITS); goto ok; /* letters ok iff hex */ case 'A': case 'B': case 'C': case 'D': case 'E': case 'F': case 'a': case 'b': case 'c': case 'd': case 'e': case 'f': /* no need to fix base here */ if (base <= 10) break; /* not legal here */ flags &= ~(SIGNOK | PFXOK | NDIGITS); goto ok; /* sign ok only as first character */ case '+': case '-': if (flags & SIGNOK) { flags &= ~SIGNOK; goto ok; } break; /* x ok iff flag still set & 2nd char */ case 'x': case 'X': if (flags & PFXOK && p == buf + 1) { base = 16; /* if %i */ flags &= ~PFXOK; goto ok; } break; } /* * If we got here, c is not a legal character * for a number. Stop accumulating digits. */ break; ok: /* * c is legal: store it and look at the next. */ *p++ = c; if (--inr > 0) inp++; else break; /* end of input */ } /* * If we had only a sign, it is no good; push * back the sign. If the number ends in `x', * it was [sign] '0' 'x', so push back the x * and treat it as [sign] '0'. */ if (flags & NDIGITS) { if (p > buf) { inp--; inr++; } goto match_failure; } c = ((uchar_t *)p)[-1]; if (c == 'x' || c == 'X') { --p; inp--; inr++; } if ((flags & SUPPRESS) == 0) { ulong_t res; *p = 0; if (sconv) (void) ddi_strtol(buf, (char **)NULL, base, (long *)(&res)); else (void) ddi_strtoul(buf, (char **)NULL, base, &res); if (flags & POINTER) *va_arg(ap, void **) = (void *)(uintptr_t)res; else if (flags & SHORT) *va_arg(ap, short *) = (short)res; else if (flags & LONG) *va_arg(ap, long *) = (long)res; else *va_arg(ap, int *) = (int)res; nassigned++; } nread += p - buf; nconversions++; break; } } input_failure: return (nconversions != 0 ? nassigned : -1); match_failure: return (nassigned); } /* * Fill in the given table from the scanset at the given format * (just after `['). Return a pointer to the character past the * closing `]'. The table has a 1 wherever characters should be * considered part of the scanset. */ static const uchar_t * set_ccl(char *tab, const uchar_t *fmt) { int c, n, v; /* first `clear' the whole table */ c = *fmt++; /* first char hat => negated scanset */ if (c == '^') { v = 1; /* default => accept */ c = *fmt++; /* get new first char */ } else v = 0; /* default => reject */ /* XXX: Will not work if sizeof(tab*) > sizeof(char) */ for (n = 0; n < 256; n++) tab[n] = v; /* memset(tab, v, 256) */ if (c == 0) return (fmt - 1); /* format ended before closing ] */ /* * Now set the entries corresponding to the actual scanset * to the opposite of the above. * * The first character may be ']' (or '-') without being special; * the last character may be '-'. */ v = 1 - v; for (;;) { tab[c] = v; /* take character c */ doswitch: n = *fmt++; /* and examine the next */ switch (n) { case 0: /* format ended too soon */ return (fmt - 1); case '-': /* * A scanset of the form * [01+-] * is defined as `the digit 0, the digit 1, * the character +, the character -', but * the effect of a scanset such as * [a-zA-Z0-9] * is implementation defined. The V7 Unix * scanf treats `a-z' as `the letters a through * z', but treats `a-a' as `the letter a, the * character -, and the letter a'. * * For compatibility, the `-' is not considerd * to define a range if the character following * it is either a close bracket (required by ANSI) * or is not numerically greater than the character * we just stored in the table (c). */ n = *fmt; if (n == ']' || n < c) { c = '-'; break; /* resume the for(;;) */ } fmt++; /* fill in the range */ do { tab[++c] = v; } while (c < n); c = n; /* * Alas, the V7 Unix scanf also treats formats * such as [a-c-e] as `the letters a through e'. * This too is permitted by the standard.... */ goto doswitch; /* NOTREACHED */ case ']': /* end of scanset */ return (fmt); default: /* just another character */ c = n; break; } } /* NOTREACHED */ } int sscanf(const char *ibuf, const char *fmt, ...) { va_list ap; int ret; va_start(ap, fmt); ret = vsscanf(ibuf, fmt, ap); va_end(ap); return (ret); } /* * CDDL HEADER START * * The contents of this file are subject to the terms of the * Common Development and Distribution License (the "License"). * You may not use this file except in compliance with the License. * * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE * or http://www.opensolaris.org/os/licensing. * See the License for the specific language governing permissions * and limitations under the License. * * When distributing Covered Code, include this CDDL HEADER in each * file and include the License file at usr/src/OPENSOLARIS.LICENSE. * If applicable, add the following below this CDDL HEADER, with the * fields enclosed by brackets "[]" replaced with your own identifying * information: Portions Copyright [yyyy] [name of copyright owner] * * CDDL HEADER END */ /* * Copyright 2007 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ #ifndef _COMMON_UTIL_SSCANF_H #define _COMMON_UTIL_SSCANF_H #include #include #ifdef __cplusplus extern "C" { #endif /*SCANFLIKE2*/ extern int sscanf(const char *, const char *, ...); extern int vsscanf(const char *, const char *, va_list); #ifdef __cplusplus } #endif #endif /* _COMMON_UTIL_SSCANF_H */ /* * CDDL HEADER START * * The contents of this file are subject to the terms of the * Common Development and Distribution License (the "License"). * You may not use this file except in compliance with the License. * * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE * or http://www.opensolaris.org/os/licensing. * See the License for the specific language governing permissions * and limitations under the License. * * When distributing Covered Code, include this CDDL HEADER in each * file and include the License file at usr/src/OPENSOLARIS.LICENSE. * If applicable, add the following below this CDDL HEADER, with the * fields enclosed by brackets "[]" replaced with your own identifying * information: Portions Copyright [yyyy] [name of copyright owner] * * CDDL HEADER END */ /* * Copyright 2008 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. * Copyright 2014 Joyent, Inc. All rights reserved. */ /* * Copyright (c) 2016 by Delphix. All rights reserved. * Copyright 2022 Tintri by DDN, Inc. All rights reserved. */ /* * Implementations of the functions described in vsnprintf(3C) and string(3C), * for use by the kernel, the standalone, and kmdb. Unless otherwise specified, * these functions match the section 3C manpages. */ #include #include #include #include #if defined(_KERNEL) #include #include #elif !defined(_BOOT) #include #endif #include "memcpy.h" #include "string.h" /* * We don't need these for x86 boot or kmdb. */ #if !defined(_KMDB) && (!defined(_BOOT) || defined(__sparc)) #define ADDCHAR(c) if (bufp++ - buf < buflen) bufp[-1] = (c) /* * Given a buffer 'buf' of size 'buflen', render as much of the string * described by as possible. The string will always be * null-terminated, so the maximum string length is 'buflen - 1'. * Returns the number of bytes that would be necessary to render the * entire string, not including null terminator (just like vsnprintf(3C)). * To determine buffer size in advance, use vsnprintf(NULL, 0, fmt, args) + 1. * * There is no support for floating point, and the C locale is assumed. */ size_t vsnprintf(char *buf, size_t buflen, const char *fmt, va_list aargs) { uintmax_t ul, tmp; char *bufp = buf; /* current buffer pointer */ char c, pad; int width, base, sign, num; int prec, h_count, l_count, dot_count; bool zflag, jflag; int pad_count, transfer_count, left_align; char *digits, *sp, *bs; char numbuf[65]; /* sufficient for a 64-bit binary value */ int numwidth; va_list args; ul = 0; bs = NULL; /* * Make a copy so that all our callers don't have to make a copy */ va_copy(args, aargs); if ((ssize_t)buflen < 0) buflen = 0; while ((c = *fmt++) != '\0') { if (c != '%') { ADDCHAR(c); continue; } zflag = jflag = false; width = prec = numwidth = 0; left_align = base = sign = 0; h_count = l_count = dot_count = 0; pad = ' '; digits = "0123456789abcdef"; next_fmt: if ((c = *fmt++) == '\0') break; if (c >= 'A' && c <= 'Z') { c += 'a' - 'A'; digits = "0123456789ABCDEF"; } switch (c) { case '-': left_align++; goto next_fmt; case '0': if (dot_count == 0) pad = '0'; /*FALLTHROUGH*/ case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': num = 0; for (;;) { num = 10 * num + c - '0'; c = *fmt; if (c < '0' || c > '9') break; else fmt++; } if (dot_count > 0) prec = num; else width = num; goto next_fmt; case '.': dot_count++; goto next_fmt; case '*': if (dot_count > 0) prec = (int)va_arg(args, int); else width = (int)va_arg(args, int); goto next_fmt; case 'l': l_count++; goto next_fmt; case 'h': h_count++; goto next_fmt; case 'j': jflag = true; goto next_fmt; case 'd': sign = 1; /*FALLTHROUGH*/ case 'u': base = 10; break; case 'p': l_count = 1; /*FALLTHROUGH*/ case 'x': base = 16; break; case 'o': base = 8; break; case 'b': l_count = 0; base = 1; break; case 'c': c = (char)va_arg(args, int); ADDCHAR(c); break; case 's': sp = va_arg(args, char *); if (sp == NULL) { sp = ""; /* avoid truncation */ prec = strlen(sp); } /* * Handle simple case specially to avoid * performance hit of strlen() */ if (prec == 0 && width == 0) { while ((c = *sp++) != 0) ADDCHAR(c); break; } if (prec > 0) { transfer_count = strnlen(sp, prec); /* widen field if too narrow */ if (prec > width) width = prec; } else transfer_count = strlen(sp); if (width > transfer_count) pad_count = width - transfer_count; else pad_count = 0; while ((!left_align) && (pad_count-- > 0)) ADDCHAR(' '); /* ADDCHAR() evaluates arg at most once */ while (transfer_count-- > 0) ADDCHAR(*sp++); while ((left_align) && (pad_count-- > 0)) ADDCHAR(' '); break; case 'z': zflag = true; goto next_fmt; case '%': ADDCHAR('%'); break; } if (base == 0) continue; if (jflag) { if (sign) ul = va_arg(args, intmax_t); else ul = va_arg(args, uintmax_t); } else if (zflag) { if (sign) ul = va_arg(args, ssize_t); else ul = va_arg(args, size_t); } else if (h_count == 0 && l_count == 0) { if (sign) ul = va_arg(args, int); else ul = va_arg(args, unsigned int); } else if (l_count > 1) { if (sign) ul = va_arg(args, int64_t); else ul = va_arg(args, uint64_t); } else if (l_count > 0) { if (sign) ul = va_arg(args, long); else ul = va_arg(args, unsigned long); } else if (h_count > 1) { if (sign) ul = (signed char)va_arg(args, int); else ul = (unsigned char)va_arg(args, int); } else if (h_count > 0) { if (sign) ul = (short)va_arg(args, int); else ul = (unsigned short)va_arg(args, int); } if (sign && (intmax_t)ul < 0) ul = -ul; else sign = 0; if (c == 'b') { bs = va_arg(args, char *); base = *bs++; } /* * Fill in the number string buffer and calculate the * number string length. */ tmp = ul; sp = numbuf; do { *sp++ = digits[tmp % base]; numwidth++; } while ((tmp /= base) != 0); /* * Reduce the total field width by precision or the number * string length depending on which one is bigger, and sign. */ if (prec >= numwidth) width -= prec; else width -= numwidth; width -= sign; /* Add the sign if width is '0'-padded */ if (sign && pad == '0') ADDCHAR('-'); /* If not left-aligned, add the width padding */ if (!left_align) { while (width-- > 0) ADDCHAR(pad); } /* Add the sign if width is NOT '0'-padded */ if (sign && pad != '0') ADDCHAR('-'); /* Add the precision '0'-padding */ while (prec-- > numwidth) ADDCHAR('0'); /* Print out the number */ while (sp > numbuf) { sp--; ADDCHAR(*sp); } /* Add left-alignment padding */ while (width-- > 0) ADDCHAR(' '); if (c == 'b' && ul != 0) { int any = 0; c = *bs++; while (c != 0) { if (ul & (1 << (c - 1))) { if (any++ == 0) ADDCHAR('<'); while ((c = *bs++) > 32) ADDCHAR(c); ADDCHAR(','); } else { while ((c = *bs++) > 32) continue; } } if (any) { bufp--; ADDCHAR('>'); } } } if (bufp - buf < buflen) bufp[0] = c; else if (buflen != 0) buf[buflen - 1] = c; va_end(args); return (bufp - buf); } /*PRINTFLIKE3*/ size_t snprintf(char *buf, size_t buflen, const char *fmt, ...) { va_list args; va_start(args, fmt); buflen = vsnprintf(buf, buflen, fmt, args); va_end(args); return (buflen); } #if defined(_BOOT) && defined(__sparc) /* * The sprintf() and vsprintf() routines aren't shared with the kernel because * the DDI mandates that they return the buffer rather than its length. */ /*PRINTFLIKE2*/ int sprintf(char *buf, const char *fmt, ...) { va_list args; va_start(args, fmt); (void) vsnprintf(buf, INT_MAX, fmt, args); va_end(args); return (strlen(buf)); } int vsprintf(char *buf, const char *fmt, va_list args) { (void) vsnprintf(buf, INT_MAX, fmt, args); return (strlen(buf)); } #endif /* _BOOT && __sparc */ #endif /* !_KMDB && (!_BOOT || __sparc) */ char * strcat(char *s1, const char *s2) { char *os1 = s1; while (*s1++ != '\0') ; s1--; while ((*s1++ = *s2++) != '\0') ; return (os1); } char * strchr(const char *sp, int c) { do { if (*sp == (char)c) return ((char *)sp); } while (*sp++); return (NULL); } int strcmp(const char *s1, const char *s2) { while (*s1 == *s2++) if (*s1++ == '\0') return (0); return (*(unsigned char *)s1 - *(unsigned char *)--s2); } int strncmp(const char *s1, const char *s2, size_t n) { if (s1 == s2) return (0); n++; while (--n != 0 && *s1 == *s2++) if (*s1++ == '\0') return (0); return ((n == 0) ? 0 : *(unsigned char *)s1 - *(unsigned char *)--s2); } static const char charmap[] = { '\000', '\001', '\002', '\003', '\004', '\005', '\006', '\007', '\010', '\011', '\012', '\013', '\014', '\015', '\016', '\017', '\020', '\021', '\022', '\023', '\024', '\025', '\026', '\027', '\030', '\031', '\032', '\033', '\034', '\035', '\036', '\037', '\040', '\041', '\042', '\043', '\044', '\045', '\046', '\047', '\050', '\051', '\052', '\053', '\054', '\055', '\056', '\057', '\060', '\061', '\062', '\063', '\064', '\065', '\066', '\067', '\070', '\071', '\072', '\073', '\074', '\075', '\076', '\077', '\100', '\141', '\142', '\143', '\144', '\145', '\146', '\147', '\150', '\151', '\152', '\153', '\154', '\155', '\156', '\157', '\160', '\161', '\162', '\163', '\164', '\165', '\166', '\167', '\170', '\171', '\172', '\133', '\134', '\135', '\136', '\137', '\140', '\141', '\142', '\143', '\144', '\145', '\146', '\147', '\150', '\151', '\152', '\153', '\154', '\155', '\156', '\157', '\160', '\161', '\162', '\163', '\164', '\165', '\166', '\167', '\170', '\171', '\172', '\173', '\174', '\175', '\176', '\177', '\200', '\201', '\202', '\203', '\204', '\205', '\206', '\207', '\210', '\211', '\212', '\213', '\214', '\215', '\216', '\217', '\220', '\221', '\222', '\223', '\224', '\225', '\226', '\227', '\230', '\231', '\232', '\233', '\234', '\235', '\236', '\237', '\240', '\241', '\242', '\243', '\244', '\245', '\246', '\247', '\250', '\251', '\252', '\253', '\254', '\255', '\256', '\257', '\260', '\261', '\262', '\263', '\264', '\265', '\266', '\267', '\270', '\271', '\272', '\273', '\274', '\275', '\276', '\277', '\300', '\301', '\302', '\303', '\304', '\305', '\306', '\307', '\310', '\311', '\312', '\313', '\314', '\315', '\316', '\317', '\320', '\321', '\322', '\323', '\324', '\325', '\326', '\327', '\330', '\331', '\332', '\333', '\334', '\335', '\336', '\337', '\340', '\341', '\342', '\343', '\344', '\345', '\346', '\347', '\350', '\351', '\352', '\353', '\354', '\355', '\356', '\357', '\360', '\361', '\362', '\363', '\364', '\365', '\366', '\367', '\370', '\371', '\372', '\373', '\374', '\375', '\376', '\377', }; int strcasecmp(const char *s1, const char *s2) { const unsigned char *cm = (const unsigned char *)charmap; const unsigned char *us1 = (const unsigned char *)s1; const unsigned char *us2 = (const unsigned char *)s2; while (cm[*us1] == cm[*us2++]) if (*us1++ == '\0') return (0); return (cm[*us1] - cm[*(us2 - 1)]); } int strncasecmp(const char *s1, const char *s2, size_t n) { const unsigned char *cm = (const unsigned char *)charmap; const unsigned char *us1 = (const unsigned char *)s1; const unsigned char *us2 = (const unsigned char *)s2; while (n != 0 && cm[*us1] == cm[*us2++]) { if (*us1++ == '\0') return (0); n--; } return (n == 0 ? 0 : cm[*us1] - cm[*(us2 - 1)]); } char * strcpy(char *s1, const char *s2) { char *os1 = s1; while ((*s1++ = *s2++) != '\0') ; return (os1); } char * strncpy(char *s1, const char *s2, size_t n) { char *os1 = s1; n++; while (--n != 0 && (*s1++ = *s2++) != '\0') ; if (n != 0) while (--n != 0) *s1++ = '\0'; return (os1); } char * strrchr(const char *sp, int c) { char *r = NULL; do { if (*sp == (char)c) r = (char *)sp; } while (*sp++); return (r); } char * strstr(const char *as1, const char *as2) { const char *s1, *s2; const char *tptr; char c; s1 = as1; s2 = as2; if (s2 == NULL || *s2 == '\0') return ((char *)s1); c = *s2; while (*s1) if (*s1++ == c) { tptr = s1; while ((c = *++s2) == *s1++ && c) ; if (c == 0) return ((char *)tptr - 1); s1 = tptr; s2 = as2; c = *s2; } return (NULL); } char * strpbrk(const char *string, const char *brkset) { const char *p; do { for (p = brkset; *p != '\0' && *p != *string; ++p) ; if (*p != '\0') return ((char *)string); } while (*string++); return (NULL); } char * strncat(char *s1, const char *s2, size_t n) { char *os1 = s1; n++; while (*s1++ != '\0') ; --s1; while ((*s1++ = *s2++) != '\0') { if (--n == 0) { s1[-1] = '\0'; break; } } return (os1); } #if defined(_BOOT) || defined(_KMDB) #define bcopy(src, dst, n) (void) memcpy((dst), (src), (n)) #endif size_t strlcat(char *dst, const char *src, size_t dstsize) { char *df = dst; size_t left = dstsize; size_t l1; size_t l2 = strlen(src); size_t copied; while (left-- != 0 && *df != '\0') df++; /*LINTED: possible ptrdiff_t overflow*/ l1 = (size_t)(df - dst); if (dstsize == l1) return (l1 + l2); copied = l1 + l2 >= dstsize ? dstsize - l1 - 1 : l2; bcopy(src, dst + l1, copied); dst[l1+copied] = '\0'; return (l1 + l2); } size_t strlcpy(char *dst, const char *src, size_t len) { size_t slen = strlen(src); size_t copied; if (len == 0) return (slen); if (slen >= len) copied = len - 1; else copied = slen; bcopy(src, dst, copied); dst[copied] = '\0'; return (slen); } size_t strspn(const char *string, const char *charset) { const char *p, *q; for (q = string; *q != '\0'; ++q) { for (p = charset; *p != '\0' && *p != *q; ++p) ; if (*p == '\0') break; } /*LINTED: possible ptrdiff_t overflow*/ return ((size_t)(q - string)); } size_t strcspn(const char *string, const char *charset) { const char *p, *q; for (q = string; *q != '\0'; ++q) { for (p = charset; *p != '\0' && *p != *q; ++p) ; if (*p != '\0') break; } /*LINTED E_PTRDIFF_OVERFLOW*/ return ((size_t)(q - string)); } /* * strsep * * The strsep() function locates, in the string referenced by *stringp, the * first occurrence of any character in the string delim (or the terminating * `\0' character) and replaces it with a `\0'. The location of the next * character after the delimiter character (or NULL, if the end of the * string was reached) is stored in *stringp. The original value of * *stringp is returned. * * If *stringp is initially NULL, strsep() returns NULL. * * NOTE: This instance is left for in-kernel use. Libraries and programs * should use strsep from libc. */ char * strsep(char **stringp, const char *delim) { char *s; const char *spanp; int c, sc; char *tok; if ((s = *stringp) == NULL) return (NULL); for (tok = s; ; ) { c = *s++; spanp = delim; do { if ((sc = *spanp++) == c) { if (c == 0) s = NULL; else s[-1] = 0; *stringp = s; return (tok); } } while (sc != 0); } /* NOTREACHED */ } /* * strtok_r * * uses strpbrk and strspn to break string into tokens on * sequentially subsequent calls. returns NULL when no * non-separator characters remain. * `subsequent' calls are calls with first argument NULL. */ char * strtok_r(char *string, const char *sepset, char **lasts) { char *q, *r; /* first or subsequent call */ if (string == NULL) string = *lasts; if (string == NULL) /* return if no tokens remaining */ return (NULL); q = string + strspn(string, sepset); /* skip leading separators */ if (*q == '\0') /* return if no tokens remaining */ return (NULL); if ((r = strpbrk(q, sepset)) == NULL) { /* move past token */ *lasts = NULL; /* indicate this is last token */ } else { *r = '\0'; *lasts = r + 1; } return (q); } /* * Unless mentioned otherwise, all of the routines below should be added to * the Solaris DDI as necessary. For now, only provide them to standalone. */ #if defined(_BOOT) || defined(_KMDB) char * strtok(char *string, const char *sepset) { char *p, *q, *r; static char *savept; /* * Set `p' to our current location in the string. */ p = (string == NULL) ? savept : string; if (p == NULL) return (NULL); /* * Skip leading separators; bail if no tokens remain. */ q = p + strspn(p, sepset); if (*q == '\0') return (NULL); /* * Mark the end of the token and set `savept' for the next iteration. */ if ((r = strpbrk(q, sepset)) == NULL) savept = NULL; else { *r = '\0'; savept = ++r; } return (q); } /* * The strlen() routine isn't shared with the kernel because it has its own * hand-tuned assembly version. */ size_t strlen(const char *s) { size_t n = 0; while (*s++) n++; return (n); } #endif /* _BOOT || _KMDB */ /* * Returns the number of non-NULL bytes in string argument, * but not more than maxlen. Does not look past str + maxlen. */ size_t strnlen(const char *s, size_t maxlen) { size_t n = 0; while (maxlen != 0 && *s != 0) { s++; maxlen--; n++; } return (n); } #ifdef _KERNEL /* * Check for a valid C identifier: * a letter or underscore, followed by * zero or more letters, digits and underscores. */ #define IS_DIGIT(c) ((c) >= '0' && (c) <= '9') #define IS_ALPHA(c) \ (((c) >= 'a' && (c) <= 'z') || ((c) >= 'A' && (c) <= 'Z')) int strident_valid(const char *id) { int c = *id++; if (!IS_ALPHA(c) && c != '_') return (0); while ((c = *id++) != 0) { if (!IS_ALPHA(c) && !IS_DIGIT(c) && c != '_') return (0); } return (1); } /* * Convert a string into a valid C identifier by replacing invalid * characters with '_'. Also makes sure the string is nul-terminated * and takes up at most n bytes. */ void strident_canon(char *s, size_t n) { char c; char *end = s + n - 1; ASSERT(n > 0); if ((c = *s) == 0) return; if (!IS_ALPHA(c) && c != '_') *s = '_'; while (s < end && ((c = *(++s)) != 0)) { if (!IS_ALPHA(c) && !IS_DIGIT(c) && c != '_') *s = '_'; } *s = 0; } #endif /* _KERNEL */ /* * CDDL HEADER START * * The contents of this file are subject to the terms of the * Common Development and Distribution License (the "License"). * You may not use this file except in compliance with the License. * * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE * or http://www.opensolaris.org/os/licensing. * See the License for the specific language governing permissions * and limitations under the License. * * When distributing Covered Code, include this CDDL HEADER in each * file and include the License file at usr/src/OPENSOLARIS.LICENSE. * If applicable, add the following below this CDDL HEADER, with the * fields enclosed by brackets "[]" replaced with your own identifying * information: Portions Copyright [yyyy] [name of copyright owner] * * CDDL HEADER END */ /* * Copyright 2008 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ /* * Copyright (c) 2016 by Delphix. All rights reserved. */ #ifndef _COMMON_UTIL_STRING_H #define _COMMON_UTIL_STRING_H #include #ifdef __cplusplus extern "C" { #endif #if !defined(_KMDB) && (!defined(_BOOT) || defined(__sparc)) extern size_t vsnprintf(char *, size_t, const char *, va_list); /*PRINTFLIKE3*/ extern size_t snprintf(char *, size_t, const char *, ...); #if defined(_BOOT) && defined(__sparc) /*PRINTFLIKE2*/ extern int sprintf(char *, const char *, ...); extern int vsprintf(char *, const char *, va_list); #endif /* _BOOT && __sparc */ #endif /* !_KMDB && (!_BOOT || __sparc) */ extern char *strcat(char *, const char *); extern char *strchr(const char *, int); extern int strcmp(const char *, const char *); extern int strncmp(const char *, const char *, size_t); extern int strcasecmp(const char *, const char *); extern int strncasecmp(const char *, const char *, size_t); extern char *strcpy(char *, const char *); extern char *strncpy(char *, const char *, size_t); extern char *strrchr(const char *, int c); extern char *strstr(const char *, const char *); extern char *strpbrk(const char *, const char *); extern char *strsep(char **, const char *); extern char *strncat(char *, const char *, size_t); extern size_t strlcat(char *, const char *, size_t); extern size_t strlcpy(char *, const char *, size_t); extern size_t strspn(const char *, const char *); extern size_t strnlen(const char *, size_t); #if defined(_BOOT) || defined(_KMDB) extern char *strtok(char *, const char *); extern size_t strlen(const char *); #endif /* _BOOT || _KMDB */ #ifdef _KERNEL extern int strident_valid(const char *); extern void strident_canon(char *, size_t); #endif /* _KERNEL */ #ifdef __cplusplus } #endif #endif /* _COMMON_UTIL_STRING_H */ /* * CDDL HEADER START * * The contents of this file are subject to the terms of the * Common Development and Distribution License (the "License"). * You may not use this file except in compliance with the License. * * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE * or http://www.opensolaris.org/os/licensing. * See the License for the specific language governing permissions * and limitations under the License. * * When distributing Covered Code, include this CDDL HEADER in each * file and include the License file at usr/src/OPENSOLARIS.LICENSE. * If applicable, add the following below this CDDL HEADER, with the * fields enclosed by brackets "[]" replaced with your own identifying * information: Portions Copyright [yyyy] [name of copyright owner] * * CDDL HEADER END */ /* * Copyright 2011 Nexenta Systems, Inc. All rights reserved. */ /* * Copyright 2009 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ /* Copyright (c) 1988 AT&T */ /* All Rights Reserved */ #if defined(_KERNEL) #include #endif /* _KERNEL */ #if defined(_KERNEL) && !defined(_BOOT) #include #else /* _KERNEL && !_BOOT */ #if !defined(_BOOT) && !defined(_KMDB) && !defined(_STANDALONE) #include "lint.h" #endif /* !_BOOT && !_KMDB && !_STANDALONE */ #if defined(_STANDALONE) #include #include #include #else #include #include #include #include #endif /* _STANDALONE */ #endif /* _KERNEL && !_BOOT */ #include "strtolctype.h" #include #if defined(_KERNEL) && !defined(_BOOT) int ddi_strtol(const char *str, char **nptr, int base, long *result) #else /* _KERNEL && !_BOOT */ long strtol(const char *str, char **nptr, int base) #endif /* _KERNEL && !_BOOT */ { long val; int c; int xx; int neg = 0; long multmin; long limit; const char **ptr = (const char **)nptr; const unsigned char *ustr = (const unsigned char *)str; if (ptr != NULL) *ptr = (char *)ustr; /* in case no number is formed */ if (base < 0 || base > MBASE || base == 1) { /* base is invalid -- should be a fatal error */ #if defined(_KERNEL) && !defined(_BOOT) return (EINVAL); #else /* _KERNEL && !_BOOT */ errno = EINVAL; return (0); #endif /* _KERNEL && !_BOOT */ } if (!isalnum(c = *ustr)) { while (isspace(c)) c = *++ustr; switch (c) { case '-': neg++; /* FALLTHROUGH */ case '+': c = *++ustr; } } if (base == 0) { if (c != '0') base = 10; else if (ustr[1] == 'x' || ustr[1] == 'X') base = 16; else base = 8; } /* * for any base > 10, the digits incrementally following * 9 are assumed to be "abc...z" or "ABC...Z" */ if (!lisalnum(c) || (xx = DIGIT(c)) >= base) { /* no number formed */ #if defined(_KERNEL) && !defined(_BOOT) return (EINVAL); #else /* _KERNEL && !_BOOT */ errno = EINVAL; return (0); #endif /* _KERNEL && !_BOOT */ } if (base == 16 && c == '0' && (ustr[1] == 'x' || ustr[1] == 'X') && isxdigit(ustr[2])) c = *(ustr += 2); /* skip over leading "0x" or "0X" */ /* this code assumes that abs(LONG_MIN) >= abs(LONG_MAX) */ if (neg) limit = LONG_MIN; else limit = -LONG_MAX; multmin = limit / (long)base; val = -DIGIT(c); for (c = *++ustr; lisalnum(c) && (xx = DIGIT(c)) < base; ) { /* accumulate neg avoids surprises near LONG_MAX */ if (val < multmin) goto overflow; val *= base; if (val < limit + xx) goto overflow; val -= xx; c = *++ustr; } if (ptr != NULL) *ptr = (char *)ustr; #if defined(_KERNEL) && !defined(_BOOT) *result = neg ? val : -val; return (0); #else /* _KERNEL && !_BOOT */ return (neg ? val : -val); #endif /* _KERNEL && !_BOOT */ overflow: for (c = *++ustr; lisalnum(c) && (xx = DIGIT(c)) < base; (c = *++ustr)) ; if (ptr != NULL) *ptr = (char *)ustr; #if defined(_KERNEL) && !defined(_BOOT) return (ERANGE); #else /* _KERNEL && !_BOOT */ errno = ERANGE; return (neg ? LONG_MIN : LONG_MAX); #endif /* _KERNEL && !_BOOT */ } /* * CDDL HEADER START * * The contents of this file are subject to the terms of the * Common Development and Distribution License (the "License"). * You may not use this file except in compliance with the License. * * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE * or http://www.opensolaris.org/os/licensing. * See the License for the specific language governing permissions * and limitations under the License. * * When distributing Covered Code, include this CDDL HEADER in each * file and include the License file at usr/src/OPENSOLARIS.LICENSE. * If applicable, add the following below this CDDL HEADER, with the * fields enclosed by brackets "[]" replaced with your own identifying * information: Portions Copyright [yyyy] [name of copyright owner] * * CDDL HEADER END */ /* * Copyright 2016 Gary Mills * Copyright 2009 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ /* Copyright (c) 1988 AT&T */ /* All Rights Reserved */ #ifndef _COMMON_UTIL_STRTOLCTYPE_H #define _COMMON_UTIL_STRTOLCTYPE_H #ifdef __cplusplus extern "C" { #endif /* * This is a private header file containing a collection of macros that * the strtou?ll? functions in common/util use to test characters. Which * macros are defined depends on which of _KERNEL or _BOOT are defined. * New code should use the kernel version of ctype.h: . * * NOTE: These macros are used within several DTrace probe context functions. * They must not be altered to make function calls or perform actions not * safe in probe context. */ /* * Cases that define these macros: * _KERNEL && !_BOOT: Used by kernel functions * !_KERNEL && _BOOT: Used by dboot_startkern.c for x86 boot * Cases that omit these macros: * _KERNEL && _BOOT: Used by common/util/strtol.c for SPARC boot library * !_KERNEL && !_BOOT: Used by strtou?ll? functions in libc */ #if defined(_KERNEL) ^ defined(_BOOT) #define isalnum(ch) (isalpha(ch) || isdigit(ch)) #define isalpha(ch) (isupper(ch) || islower(ch)) #define isdigit(ch) ((ch) >= '0' && (ch) <= '9') #define islower(ch) ((ch) >= 'a' && (ch) <= 'z') #define isspace(ch) (((ch) == ' ') || ((ch) == '\r') || ((ch) == '\n') || \ ((ch) == '\t') || ((ch) == '\f')) #define isupper(ch) ((ch) >= 'A' && (ch) <= 'Z') #define isxdigit(ch) (isdigit(ch) || ((ch) >= 'a' && (ch) <= 'f') || \ ((ch) >= 'A' && (ch) <= 'F')) #endif /* _KERNEL ^ _BOOT */ /* * The following macros are defined unconditionally. */ #define DIGIT(x) \ (isdigit(x) ? (x) - '0' : islower(x) ? (x) + 10 - 'a' : (x) + 10 - 'A') #define MBASE ('z' - 'a' + 1 + 10) /* * The following macro is a version of isalnum() that limits alphabetic * characters to the ranges a-z and A-Z; locale dependent characters will not * return 1. The members of a-z and A-Z are assumed to be in ascending order * and contiguous. */ #define lisalnum(x) \ (isdigit(x) || ((x) >= 'a' && (x) <= 'z') || ((x) >= 'A' && (x) <= 'Z')) #ifdef __cplusplus } #endif #endif /* _COMMON_UTIL_STRTOLCTYPE_H */ /* * CDDL HEADER START * * The contents of this file are subject to the terms of the * Common Development and Distribution License (the "License"). * You may not use this file except in compliance with the License. * * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE * or http://www.opensolaris.org/os/licensing. * See the License for the specific language governing permissions * and limitations under the License. * * When distributing Covered Code, include this CDDL HEADER in each * file and include the License file at usr/src/OPENSOLARIS.LICENSE. * If applicable, add the following below this CDDL HEADER, with the * fields enclosed by brackets "[]" replaced with your own identifying * information: Portions Copyright [yyyy] [name of copyright owner] * * CDDL HEADER END */ /* * Copyright 2009 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ /* Copyright (c) 1988 AT&T */ /* All Rights Reserved */ #if defined(_KERNEL) #include #endif /* _KERNEL */ #if defined(_KERNEL) && !defined(_BOOT) #include #else /* _KERNEL && !_BOOT */ #if !defined(_BOOT) && !defined(_KMDB) && !defined(_STANDALONE) #include "lint.h" #endif /* !_BOOT && !_KMDB && !_STANDALONE */ #if defined(_STANDALONE) #include #include #include typedef long long longlong_t; #else #include #include #include #include #endif /* _STANDALONE */ #endif /* _KERNEL && !_BOOT */ #include "strtolctype.h" #include #if defined(_KERNEL) && !defined(_BOOT) int ddi_strtoll(const char *str, char **nptr, int base, longlong_t *result) #else /* _KERNEL && !_BOOT */ longlong_t strtoll(const char *str, char **nptr, int base) #endif /* _KERNEL && !_BOOT */ { longlong_t val; int c; int xx; int neg = 0; longlong_t multmin; longlong_t limit; const char **ptr = (const char **)nptr; const unsigned char *ustr = (const unsigned char *)str; if (ptr != NULL) *ptr = (char *)ustr; /* in case no number is formed */ if (base < 0 || base > MBASE || base == 1) { /* base is invalid -- should be a fatal error */ #if defined(_KERNEL) && !defined(_BOOT) return (EINVAL); #else /* _KERNEL && !_BOOT */ errno = EINVAL; return (0); #endif /* _KERNEL && !_BOOT */ } if (!isalnum(c = *ustr)) { while (isspace(c)) c = *++ustr; switch (c) { case '-': neg++; /* FALLTHROUGH */ case '+': c = *++ustr; } } if (base == 0) { if (c != '0') base = 10; else if (ustr[1] == 'x' || ustr[1] == 'X') base = 16; else base = 8; } /* * for any base > 10, the digits incrementally following * 9 are assumed to be "abc...z" or "ABC...Z" */ if (!lisalnum(c) || (xx = DIGIT(c)) >= base) { /* no number formed */ #if defined(_KERNEL) && !defined(_BOOT) return (EINVAL); #else /* _KERNEL && !_BOOT */ return (0); #endif /* _KERNEL && !_BOOT */ } if (base == 16 && c == '0' && (ustr[1] == 'x' || ustr[1] == 'X') && isxdigit(ustr[2])) c = *(ustr += 2); /* skip over leading "0x" or "0X" */ /* this code assumes that abs(LLONG_MIN) >= abs(LLONG_MAX) */ if (neg) limit = LLONG_MIN; else limit = -LLONG_MAX; multmin = limit / (longlong_t)base; val = -DIGIT(c); for (c = *++ustr; lisalnum(c) && (xx = DIGIT(c)) < base; ) { /* accumulate neg avoids surprises near LLONG_MAX */ if (val < multmin) goto overflow; val *= base; if (val < limit + xx) goto overflow; val -= xx; c = *++ustr; } if (ptr != NULL) *ptr = (char *)ustr; #if defined(_KERNEL) && !defined(_BOOT) *result = neg ? val : -val; return (0); #else /* _KERNEL && !_BOOT */ return (neg ? val : -val); #endif /* _KERNEL && !_BOOT */ overflow: for (c = *++ustr; lisalnum(c) && (xx = DIGIT(c)) < base; (c = *++ustr)) ; if (ptr != NULL) *ptr = (char *)ustr; #if defined(_KERNEL) && !defined(_BOOT) return (ERANGE); #else /* _KERNEL && !_BOOT */ errno = ERANGE; return (neg ? LLONG_MIN : LLONG_MAX); #endif /* _KERNEL && !_BOOT */ } /* * CDDL HEADER START * * The contents of this file are subject to the terms of the * Common Development and Distribution License (the "License"). * You may not use this file except in compliance with the License. * * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE * or http://www.opensolaris.org/os/licensing. * See the License for the specific language governing permissions * and limitations under the License. * * When distributing Covered Code, include this CDDL HEADER in each * file and include the License file at usr/src/OPENSOLARIS.LICENSE. * If applicable, add the following below this CDDL HEADER, with the * fields enclosed by brackets "[]" replaced with your own identifying * information: Portions Copyright [yyyy] [name of copyright owner] * * CDDL HEADER END */ /* * Copyright 2009 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ /* Copyright (c) 1988 AT&T */ /* All Rights Reserved */ #if defined(_KERNEL) #include #endif /* _KERNEL */ #if defined(_KERNEL) && !defined(_BOOT) #include #else /* _KERNEL && !_BOOT */ #if !defined(_BOOT) && !defined(_KMDB) && !defined(_STANDALONE) #include "lint.h" #endif /* !_BOOT && !_KMDB && !_STANDALONE */ #if defined(_STANDALONE) #include #include #include #else #include #include #include #include #endif /* _STANDALONE */ #endif /* _KERNEL && !_BOOT */ #include "strtolctype.h" #include #if defined(_KERNEL) && !defined(_BOOT) int ddi_strtoul(const char *str, char **nptr, int base, unsigned long *result) #else /* _KERNEL && !_BOOT */ unsigned long strtoul(const char *str, char **nptr, int base) #endif /* _KERNEL && !_BOOT */ { unsigned long val; int c; int xx; int neg = 0; unsigned long multmax; const char **ptr = (const char **)nptr; const unsigned char *ustr = (const unsigned char *)str; if (ptr != NULL) *ptr = (char *)ustr; /* in case no number is formed */ if (base < 0 || base > MBASE || base == 1) { /* base is invalid -- should be a fatal error */ #if defined(_KERNEL) && !defined(_BOOT) return (EINVAL); #else /* _KERNEL && !_BOOT */ errno = EINVAL; return (0); #endif /* _KERNEL && !_BOOT */ } if (!isalnum(c = *ustr)) { while (isspace(c)) c = *++ustr; switch (c) { case '-': neg++; /* FALLTHROUGH */ case '+': c = *++ustr; } } if (base == 0) { if (c != '0') base = 10; else if (ustr[1] == 'x' || ustr[1] == 'X') base = 16; else base = 8; } /* * for any base > 10, the digits incrementally following * 9 are assumed to be "abc...z" or "ABC...Z" */ if (!lisalnum(c) || (xx = DIGIT(c)) >= base) { /* no number formed */ #if defined(_KERNEL) && !defined(_BOOT) return (EINVAL); #else /* _KERNEL && !_BOOT */ return (0); #endif /* _KERNEL && !_BOOT */ } if (base == 16 && c == '0' && (ustr[1] == 'x' || ustr[1] == 'X') && isxdigit(ustr[2])) c = *(ustr += 2); /* skip over leading "0x" or "0X" */ multmax = ULONG_MAX / (unsigned long)base; val = DIGIT(c); for (c = *++ustr; lisalnum(c) && (xx = DIGIT(c)) < base; ) { if (val > multmax) goto overflow; val *= base; if (ULONG_MAX - val < (unsigned long)xx) goto overflow; val += xx; c = *++ustr; } if (ptr != NULL) *ptr = (char *)ustr; #if defined(_KERNEL) && !defined(_BOOT) *result = neg ? -val : val; return (0); #else /* _KERNEL && !_BOOT */ return (neg ? -val : val); #endif /* _KERNEL && !_BOOT */ overflow: for (c = *++ustr; lisalnum(c) && (xx = DIGIT(c)) < base; (c = *++ustr)) ; if (ptr != NULL) *ptr = (char *)ustr; #if defined(_KERNEL) && !defined(_BOOT) return (ERANGE); #else /* _KERNEL && !_BOOT */ errno = ERANGE; return (ULONG_MAX); #endif /* _KERNEL && !_BOOT */ } /* * CDDL HEADER START * * The contents of this file are subject to the terms of the * Common Development and Distribution License (the "License"). * You may not use this file except in compliance with the License. * * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE * or http://www.opensolaris.org/os/licensing. * See the License for the specific language governing permissions * and limitations under the License. * * When distributing Covered Code, include this CDDL HEADER in each * file and include the License file at usr/src/OPENSOLARIS.LICENSE. * If applicable, add the following below this CDDL HEADER, with the * fields enclosed by brackets "[]" replaced with your own identifying * information: Portions Copyright [yyyy] [name of copyright owner] * * CDDL HEADER END */ /* * Copyright 2009 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ /* Copyright (c) 1988 AT&T */ /* All Rights Reserved */ #if defined(_KERNEL) #include #endif /* _KERNEL */ #if defined(_KERNEL) && !defined(_BOOT) #include #else /* _KERNEL && !_BOOT */ #if !defined(_BOOT) && !defined(_KMDB) && !defined(_STANDALONE) #include "lint.h" #endif /* !_BOOT && !_KMDB && !_STANDALONE */ #if defined(_STANDALONE) #include #include #include typedef unsigned long long u_longlong_t; #else #include #include #include #include #endif /* _STANDALONE */ #endif /* _KERNEL && !_BOOT */ #include "strtolctype.h" #include #if defined(_KERNEL) && !defined(_BOOT) int ddi_strtoull(const char *str, char **nptr, int base, u_longlong_t *result) #else /* _KERNEL && !_BOOT */ u_longlong_t strtoull(const char *str, char **nptr, int base) #endif /* _KERNEL && !_BOOT */ { u_longlong_t val; int c; int xx; int neg = 0; u_longlong_t multmax; const char **ptr = (const char **)nptr; const unsigned char *ustr = (const unsigned char *)str; if (ptr != NULL) *ptr = (char *)ustr; /* in case no number is formed */ if (base < 0 || base > MBASE || base == 1) { /* base is invalid -- should be a fatal error */ #if defined(_KERNEL) && !defined(_BOOT) return (EINVAL); #else /* _KERNEL && !_BOOT */ errno = EINVAL; return (0); #endif /* _KERNEL && !_BOOT */ } if (!isalnum(c = *ustr)) { while (isspace(c)) c = *++ustr; switch (c) { case '-': neg++; /* FALLTHROUGH */ case '+': c = *++ustr; } } if (base == 0) { if (c != '0') base = 10; else if (ustr[1] == 'x' || ustr[1] == 'X') base = 16; else base = 8; } /* * for any base > 10, the digits incrementally following * 9 are assumed to be "abc...z" or "ABC...Z" */ if (!lisalnum(c) || (xx = DIGIT(c)) >= base) { /* no number formed */ #if defined(_KERNEL) && !defined(_BOOT) return (EINVAL); #else /* _KERNEL && !_BOOT */ return (0); #endif /* _KERNEL && !_BOOT */ } if (base == 16 && c == '0' && (ustr[1] == 'x' || ustr[1] == 'X') && isxdigit(ustr[2])) c = *(ustr += 2); /* skip over leading "0x" or "0X" */ multmax = ULLONG_MAX / (u_longlong_t)base; val = DIGIT(c); for (c = *++ustr; lisalnum(c) && (xx = DIGIT(c)) < base; ) { if (val > multmax) goto overflow; val *= base; if (ULLONG_MAX - val < (unsigned long long)xx) goto overflow; val += xx; c = *++ustr; } if (ptr != NULL) *ptr = (char *)ustr; #if defined(_KERNEL) && !defined(_BOOT) *result = neg ? -val : val; return (0); #else /* _KERNEL && !_BOOT */ return (neg ? -val : val); #endif /* _KERNEL && !_BOOT */ overflow: for (c = *++ustr; lisalnum(c) && (xx = DIGIT(c)) < base; (c = *++ustr)) ; if (ptr != NULL) *ptr = (char *)ustr; #if defined(_KERNEL) && !defined(_BOOT) return (ERANGE); #else /* _KERNEL && !_BOOT */ errno = ERANGE; return (ULLONG_MAX); #endif /* _KERNEL && !_BOOT */ }