mirror of
git://git.code.sf.net/p/cdesktopenv/code
synced 2025-03-09 15:50:02 +00:00
This commit adds an UNREACHABLE() macro that expands to either the __builtin_unreachable() compiler builtin (for release builds) or abort(3) (for development builds). This is used to mark code paths that are never to be reached. It also adds the 'noreturn' attribute to functions that never return: path_exec(), sh_done() and sh_syntax(). The UNREACHABLE() macro is not added after calling these. The purpose of these is: * to slightly improve GCC/Clang compiler optimizations; * to fix a few compiler warnings; * to add code clarity. Changes of note: src/cmd/ksh93/sh/io.c: outexcept(): - Avoid using __builtin_unreachable() here since errormsg can return despite using ERROR_system(1), as shp->jmplist->mode is temporarily set to 0. See: https://github.com/att/ast/issues/1336 src/cmd/ksh93/tests/io.sh: - Add a regression test for the ksh2020 bug referenced above. src/lib/libast/features/common: - Detect the existence of either the C11 stdnoreturn.h header or the GCC noreturn attribute, preferring the former when available. - Test for the existence of __builtin_unreachable(). Use it for release builds. On development builds, use abort() instead, which crahses reliably for debugging when unreachable code is reached. Co-authored-by: Martijn Dekker <martijn@inlv.org>
194 lines
5.5 KiB
C
194 lines
5.5 KiB
C
/***********************************************************************
|
|
* *
|
|
* This software is part of the ast package *
|
|
* Copyright (c) 1982-2011 AT&T Intellectual Property *
|
|
* and is licensed under the *
|
|
* Eclipse Public License, Version 1.0 *
|
|
* by AT&T Intellectual Property *
|
|
* *
|
|
* A copy of the License is available at *
|
|
* http://www.eclipse.org/org/documents/epl-v10.html *
|
|
* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
|
|
* *
|
|
* Information and Software Systems Research *
|
|
* AT&T Research *
|
|
* Florham Park NJ *
|
|
* *
|
|
* David Korn <dgk@research.att.com> *
|
|
* *
|
|
***********************************************************************/
|
|
#pragma prototyped
|
|
/*
|
|
* David Korn
|
|
* AT&T Labs
|
|
*
|
|
* shell script to shell binary converter
|
|
*
|
|
*/
|
|
|
|
#include "version.h"
|
|
|
|
static const char usage[] =
|
|
"[-?\n@(#)$Id: shcomp (AT&T Research) " SH_RELEASE " $\n]"
|
|
"[-author?David Korn <dgk@research.att.com>]"
|
|
"[-copyright?(c) 1982-2012 AT&T Intellectual Property]"
|
|
"[-copyright?" SH_RELEASE_CPYR "]"
|
|
"[-license?http://www.eclipse.org/org/documents/epl-v10.html]"
|
|
"[--catalog?" SH_DICT "]"
|
|
"[+NAME?shcomp - compile a shell script]"
|
|
"[+DESCRIPTION?Unless \b-D\b is specified, \bshcomp\b takes a shell script, "
|
|
"\ainfile\a, and creates a binary format file, \aoutfile\a, that "
|
|
"\bksh\b can read and execute with the same effect as the original "
|
|
"script.]"
|
|
"[+?Since aliases are processed as the script is read, alias definitions "
|
|
"whose value requires variable expansion will not work correctly.]"
|
|
"[+?If \b-D\b is specified, all double quoted strings that are preceded by "
|
|
"\b$\b are output. These are the messages that need to be "
|
|
"translated to locale specific versions for internationalization.]"
|
|
"[+?If \aoutfile\a is omitted, then the results will be written to "
|
|
"standard output. If \ainfile\a is also omitted, the shell script "
|
|
"will be read from standard input.]"
|
|
"[D:dictionary?Generate a list of strings that need to be placed in a message "
|
|
"catalog for internationalization.]"
|
|
"[n:noexec?Displays warning messages for obsolete or non-conforming "
|
|
"constructs.] "
|
|
"[v:verbose?Displays input from \ainfile\a onto standard error as it "
|
|
"reads it.]"
|
|
"\n"
|
|
"\n[infile [outfile]]\n"
|
|
"\n"
|
|
"[+EXIT STATUS?]{"
|
|
"[+0?Successful completion.]"
|
|
"[+>0?An error occurred.]"
|
|
"}"
|
|
"[+SEE ALSO?\bksh\b(1)]"
|
|
;
|
|
|
|
#include <shell.h>
|
|
#include "defs.h"
|
|
#include "shnodes.h"
|
|
#include "sys/stat.h"
|
|
|
|
#define CNTL(x) ((x)&037)
|
|
static const char header[6] = { CNTL('k'),CNTL('s'),CNTL('h'),0,SHCOMP_HDR_VERSION,0 };
|
|
|
|
int main(int argc, char *argv[])
|
|
{
|
|
Sfio_t *in, *out;
|
|
Shell_t *shp;
|
|
Namval_t *np;
|
|
Shnode_t *t;
|
|
char *cp;
|
|
int n, nflag=0, vflag=0, dflag=0;
|
|
error_info.id = argv[0];
|
|
while(n = optget(argv, usage )) switch(n)
|
|
{
|
|
case 'D':
|
|
dflag=1;
|
|
break;
|
|
case 'v':
|
|
vflag=1;
|
|
break;
|
|
case 'n':
|
|
nflag=1;
|
|
break;
|
|
case ':':
|
|
errormsg(SH_DICT,2,"%s",opt_info.arg);
|
|
break;
|
|
case '?':
|
|
errormsg(SH_DICT,ERROR_usage(2),"%s",opt_info.arg);
|
|
UNREACHABLE();
|
|
}
|
|
shp = sh_init(argc,argv,(Shinit_f)0);
|
|
shp->shcomp = 1;
|
|
argv += opt_info.index;
|
|
argc -= opt_info.index;
|
|
if(error_info.errors || argc>2)
|
|
{
|
|
errormsg(SH_DICT,ERROR_usage(2),"%s",optusage((char*)0));
|
|
UNREACHABLE();
|
|
}
|
|
if(cp= *argv)
|
|
{
|
|
argv++;
|
|
in = sh_pathopen(cp);
|
|
}
|
|
else
|
|
in = sfstdin;
|
|
if(cp= *argv)
|
|
{
|
|
struct stat statb;
|
|
if(!(out = sfopen((Sfio_t*)0,cp,"w")))
|
|
{
|
|
errormsg(SH_DICT,ERROR_system(1),"%s: cannot create",cp);
|
|
UNREACHABLE();
|
|
}
|
|
if(fstat(sffileno(out),&statb) >=0)
|
|
chmod(cp,(statb.st_mode&~S_IFMT)|S_IXUSR|S_IXGRP|S_IXOTH);
|
|
}
|
|
else
|
|
out = sfstdout;
|
|
if(dflag)
|
|
{
|
|
sh_onoption(SH_DICTIONARY);
|
|
sh_onoption(SH_NOEXEC);
|
|
}
|
|
if(nflag)
|
|
sh_onoption(SH_NOEXEC);
|
|
if(vflag)
|
|
sh_onoption(SH_VERBOSE);
|
|
if(!dflag)
|
|
sfwrite(out,header,sizeof(header));
|
|
shp->inlineno = 1;
|
|
#if SHOPT_BRACEPAT
|
|
sh_onoption(SH_BRACEEXPAND);
|
|
#endif
|
|
while(1)
|
|
{
|
|
stakset((char*)0,0);
|
|
if(t = (Shnode_t*)sh_parse(shp,in,0))
|
|
{
|
|
if((t->tre.tretyp&(COMMSK|COMSCAN))==0 && t->com.comnamp && strcmp(nv_name((Namval_t*)t->com.comnamp),"alias")==0)
|
|
sh_exec(t,0);
|
|
if(!dflag && sh_tdump(out,t) < 0)
|
|
{
|
|
errormsg(SH_DICT,ERROR_exit(1),"dump failed");
|
|
UNREACHABLE();
|
|
}
|
|
}
|
|
else if(sfeof(in))
|
|
break;
|
|
if(sferror(in))
|
|
{
|
|
errormsg(SH_DICT,ERROR_system(1),"I/O error");
|
|
UNREACHABLE();
|
|
}
|
|
if(t && ((t->tre.tretyp&COMMSK)==TCOM) && (np=t->com.comnamp) && (cp=nv_name(np)))
|
|
{
|
|
if(strcmp(cp,"exit")==0)
|
|
break;
|
|
/* check for exec of a command */
|
|
if(strcmp(cp,"exec")==0)
|
|
{
|
|
if(t->com.comtyp&COMSCAN)
|
|
{
|
|
if(t->com.comarg->argnxt.ap)
|
|
break;
|
|
}
|
|
else
|
|
{
|
|
struct dolnod *ap = (struct dolnod*)t->com.comarg;
|
|
if(ap->dolnum>1)
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
/* copy any remaining input */
|
|
sfmove(in,out,SF_UNBOUND,-1);
|
|
if(in!=sfstdin)
|
|
sfclose(in);
|
|
if(out!=sfstdout)
|
|
sfclose(out);
|
|
return(0);
|
|
}
|